Changeset 4787
- Timestamp:
- 11/11/09 11:02:49 (3 years ago)
- Location:
- branches/1.4/liblwgeom
- Files:
-
- 5 modified
-
cunit/cu_algorithm.c (modified) (18 diffs)
-
cunit/cu_algorithm.h (modified) (1 diff)
-
liblwgeom.h (modified) (1 diff)
-
lwalgorithm.c (modified) (10 diffs)
-
lwalgorithm.h (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
-
branches/1.4/liblwgeom/cunit/cu_algorithm.c
r4168 r4787 30 30 (NULL == CU_add_test(pSuite, "test_lw_segment_intersects()", test_lw_segment_intersects)) || 31 31 (NULL == CU_add_test(pSuite, "test_lwline_crossing_short_lines()", test_lwline_crossing_short_lines)) || 32 (NULL == CU_add_test(pSuite, "test_lwline_crossing_long_lines()", test_lwline_crossing_long_lines)) || 32 (NULL == CU_add_test(pSuite, "test_lwline_crossing_long_lines()", test_lwline_crossing_long_lines)) || 33 (NULL == CU_add_test(pSuite, "test_lwline_crossing_bugs()", test_lwline_crossing_bugs)) || 33 34 (NULL == CU_add_test(pSuite, "test_lwpoint_set_ordinate()", test_lwpoint_set_ordinate)) || 34 35 (NULL == CU_add_test(pSuite, "test_lwpoint_get_ordinate()", test_lwpoint_get_ordinate)) || … … 39 40 (NULL == CU_add_test(pSuite, "test_geohash_point()", test_geohash_point)) || 40 41 (NULL == CU_add_test(pSuite, "test_geohash_precision()", test_geohash_precision)) || 41 (NULL == CU_add_test(pSuite, "test_geohash()", test_geohash)) 42 (NULL == CU_add_test(pSuite, "test_geohash()", test_geohash)) 42 43 ) 43 44 { … … 52 53 ** Global variables used by tests below 53 54 */ 54 POINT2D *p1 = NULL; 55 POINT2D *p2 = NULL; 56 POINT2D *q1 = NULL; 57 POINT2D *q2 = NULL; 58 POINT4D *p = NULL; 59 POINT4D *q = NULL; 55 60 56 /* Two-point objects */ 61 57 POINTARRAY *pa21 = NULL; … … 63 59 LWLINE *l21 = NULL; 64 60 LWLINE *l22 = NULL; 65 /* Five-point objects */66 LWLINE *l51 = NULL;67 LWLINE *l52 = NULL;68 61 /* Parsing support */ 69 62 LWGEOM_PARSER_RESULT parse_result; … … 76 69 int init_cg_suite(void) 77 70 { 78 p = lwalloc(sizeof(POINT4D));79 q = lwalloc(sizeof(POINT4D));80 p1 = lwalloc(sizeof(POINT2D));81 p2 = lwalloc(sizeof(POINT2D));82 q1 = lwalloc(sizeof(POINT2D));83 q2 = lwalloc(sizeof(POINT2D));84 71 pa21 = ptarray_construct(0, 0, 2); 85 72 pa22 = ptarray_construct(0, 0, 2); … … 96 83 int clean_cg_suite(void) 97 84 { 98 if ( p ) lwfree(p);99 if ( p1 )lwfree(p1);100 if ( p2 ) lwfree(p2);101 if ( q1 ) lwfree(q1);102 if ( q2 ) lwfree(q2);103 85 if ( l21 ) lwline_free(l21); 104 86 if ( l22 ) lwline_free(l22); … … 112 94 { 113 95 double rv = 0.0; 114 POINT2D *q = NULL; 115 q = lwalloc(sizeof(POINT2D)); 96 POINT2D p1, p2, q; 116 97 117 98 /* Vertical line at x=0 */ 118 p1 ->x = 0.0;119 p1 ->y = 0.0;120 p2 ->x = 0.0;121 p2 ->y = 1.0;99 p1.x = 0.0; 100 p1.y = 0.0; 101 p2.x = 0.0; 102 p2.y = 1.0; 122 103 123 104 /* On the left */ 124 q ->x = -2.0;125 q ->y = 1.5;105 q.x = -2.0; 106 q.y = 1.5; 126 107 rv = lw_segment_side(p1, p2, q); 127 108 //printf("left %g\n",rv); … … 129 110 130 111 /* On the right */ 131 q ->x = 2.0;112 q.x = 2.0; 132 113 rv = lw_segment_side(p1, p2, q); 133 114 //printf("right %g\n",rv); … … 135 116 136 117 /* On the line */ 137 q ->x = 0.0;118 q.x = 0.0; 138 119 rv = lw_segment_side(p1, p2, q); 139 120 //printf("on line %g\n",rv); 140 121 CU_ASSERT_EQUAL(rv, 0.0); 141 142 lwfree(q);143 122 144 123 } … … 150 129 { 151 130 131 #define setpoint(p, x1, y1) {(p).x = (x1); (p).y = (y1);} 132 133 POINT2D p1, p2, q1, q2; 134 152 135 /* P: Vertical line at x=0 */ 153 p1->x = 0.0; 154 p1->y = 0.0; 155 p2->x = 0.0; 156 p2->y = 1.0; 136 setpoint(p1, 0.0, 0.0); 137 p1.x = 0.0; 138 p1.y = 0.0; 139 p2.x = 0.0; 140 p2.y = 1.0; 157 141 158 142 /* Q: Horizontal line crossing left to right */ 159 q1 ->x = -0.5;160 q1 ->y = 0.5;161 q2 ->x = 0.5;162 q2 ->y = 0.5;143 q1.x = -0.5; 144 q1.y = 0.5; 145 q2.x = 0.5; 146 q2.y = 0.5; 163 147 CU_ASSERT( lw_segment_intersects(p1, p2, q1, q2) == SEG_CROSS_RIGHT ); 164 148 165 149 /* Q: Horizontal line crossing right to left */ 166 q1 ->x = 0.5;167 q1 ->y = 0.5;168 q2 ->x = -0.5;169 q2 ->y = 0.5;150 q1.x = 0.5; 151 q1.y = 0.5; 152 q2.x = -0.5; 153 q2.y = 0.5; 170 154 CU_ASSERT( lw_segment_intersects(p1, p2, q1, q2) == SEG_CROSS_LEFT ); 171 155 172 156 /* Q: Horizontal line not crossing right to left */ 173 q1 ->x = 0.5;174 q1 ->y = 1.5;175 q2 ->x = -0.5;176 q2 ->y = 1.5;157 q1.x = 0.5; 158 q1.y = 1.5; 159 q2.x = -0.5; 160 q2.y = 1.5; 177 161 CU_ASSERT( lw_segment_intersects(p1, p2, q1, q2) == SEG_NO_INTERSECTION ); 178 162 179 /* Q: Horizontal line crossing at vertex right to left */ 180 q1->x = 0.5; 181 q1->y = 1.0; 182 q2->x = -0.5; 183 q2->y = 1.0; 163 /* Q: Horizontal line crossing at second vertex right to left */ 164 q1.x = 0.5; 165 q1.y = 1.0; 166 q2.x = -0.5; 167 q2.y = 1.0; 168 CU_ASSERT( lw_segment_intersects(p1, p2, q1, q2) == SEG_NO_INTERSECTION ); 169 170 /* Q: Horizontal line crossing at first vertex right to left */ 171 q1.x = 0.5; 172 q1.y = 0.0; 173 q2.x = -0.5; 174 q2.y = 0.0; 184 175 CU_ASSERT( lw_segment_intersects(p1, p2, q1, q2) == SEG_CROSS_LEFT ); 185 176 186 /* Q: Diagonal line with large range crossing at vertex right to left */187 q1 ->x = 0.5;188 q1 ->y = 10.0;189 q2 ->x = -0.5;190 q2 ->y = -10.0;177 /* Q: Diagonal line with large range crossing at first vertex right to left */ 178 q1.x = 0.5; 179 q1.y = 10.0; 180 q2.x = -0.5; 181 q2.y = -10.0; 191 182 CU_ASSERT( lw_segment_intersects(p1, p2, q1, q2) == SEG_CROSS_LEFT ); 192 183 193 /* Q: Diagonal line with large range crossing at vertex right to left */ 194 q1->x = 0.5; 195 q1->y = 11.0; 196 q2->x = -0.5; 197 q2->y = -9.0; 184 /* Q: Diagonal line with large range crossing at second vertex right to left */ 185 q1.x = 0.5; 186 q1.y = 11.0; 187 q2.x = -0.5; 188 q2.y = -9.0; 189 CU_ASSERT( lw_segment_intersects(p1, p2, q1, q2) == SEG_NO_INTERSECTION ); 190 191 /* Q: Horizontal touching from left at second vertex*/ 192 q1.x = -0.5; 193 q1.y = 0.5; 194 q2.x = 0.0; 195 q2.y = 0.5; 196 CU_ASSERT( lw_segment_intersects(p1, p2, q1, q2) == SEG_NO_INTERSECTION ); 197 198 /* Q: Horizontal touching from right at first vertex */ 199 q1.x = 0.0; 200 q1.y = 0.5; 201 q2.x = 0.5; 202 q2.y = 0.5; 203 CU_ASSERT( lw_segment_intersects(p1, p2, q1, q2) == SEG_CROSS_RIGHT ); 204 205 /* Q: Horizontal touching from left and far below on second vertex */ 206 q1.x = -0.5; 207 q1.y = -10.5; 208 q2.x = 0.0; 209 q2.y = 0.5; 210 CU_ASSERT( lw_segment_intersects(p1, p2, q1, q2) == SEG_NO_INTERSECTION ); 211 212 /* Q: Horizontal touching from right and far above on second vertex */ 213 q1.x = 0.5; 214 q1.y = 10.5; 215 q2.x = 0.0; 216 q2.y = 0.5; 217 CU_ASSERT( lw_segment_intersects(p1, p2, q1, q2) == SEG_NO_INTERSECTION ); 218 219 /* Q: Co-linear from top */ 220 q1.x = 0.0; 221 q1.y = 10.0; 222 q2.x = 0.0; 223 q2.y = 0.5; 224 CU_ASSERT( lw_segment_intersects(p1, p2, q1, q2) == SEG_COLINEAR ); 225 226 /* Q: Co-linear from bottom */ 227 q1.x = 0.0; 228 q1.y = -10.0; 229 q2.x = 0.0; 230 q2.y = 0.5; 231 CU_ASSERT( lw_segment_intersects(p1, p2, q1, q2) == SEG_COLINEAR ); 232 233 /* Q: Co-linear contained */ 234 q1.x = 0.0; 235 q1.y = 0.4; 236 q2.x = 0.0; 237 q2.y = 0.5; 238 CU_ASSERT( lw_segment_intersects(p1, p2, q1, q2) == SEG_COLINEAR ); 239 240 /* Q: Horizontal touching at end point from left */ 241 q1.x = -0.5; 242 q1.y = 1.0; 243 q2.x = 0.0; 244 q2.y = 1.0; 245 CU_ASSERT( lw_segment_intersects(p1, p2, q1, q2) == SEG_NO_INTERSECTION ); 246 247 /* Q: Horizontal touching at end point from right */ 248 q1.x = 0.0; 249 q1.y = 1.0; 250 q2.x = 0.0; 251 q2.y = 0.5; 252 CU_ASSERT( lw_segment_intersects(p1, p2, q1, q2) == SEG_COLINEAR ); 253 254 /* Q: Horizontal touching at start point from left */ 255 q1.x = 0.0; 256 q1.y = 0.0; 257 q2.x = -0.5; 258 q2.y = 0.0; 198 259 CU_ASSERT( lw_segment_intersects(p1, p2, q1, q2) == SEG_CROSS_LEFT ); 199 260 200 /* Q: Horizontal touching from left */201 q1->x = -0.5;202 q1->y = 0.5;203 q2->x = 0.0;204 q2->y = 0.5;205 CU_ASSERT( lw_segment_intersects(p1, p2, q1, q2) == SEG_TOUCH_LEFT );206 207 /* Q: Horizontal touching from right */208 q1->x = 0.5;209 q1->y = 0.5;210 q2->x = 0.0;211 q2->y = 0.5;212 CU_ASSERT( lw_segment_intersects(p1, p2, q1, q2) == SEG_TOUCH_RIGHT );213 214 /* Q: Horizontal touching from left and far below*/215 q1->x = -0.5;216 q1->y = -10.5;217 q2->x = 0.0;218 q2->y = 0.5;219 CU_ASSERT( lw_segment_intersects(p1, p2, q1, q2) == SEG_TOUCH_LEFT );220 221 /* Q: Horizontal touching from right and far above */222 q1->x = 0.5;223 q1->y = 10.5;224 q2->x = 0.0;225 q2->y = 0.5;226 CU_ASSERT( lw_segment_intersects(p1, p2, q1, q2) == SEG_TOUCH_RIGHT );227 228 /* Q: Co-linear from top */229 q1->x = 0.0;230 q1->y = 10.0;231 q2->x = 0.0;232 q2->y = 0.5;233 CU_ASSERT( lw_segment_intersects(p1, p2, q1, q2) == SEG_COLINEAR );234 235 /* Q: Co-linear from bottom */236 q1->x = 0.0;237 q1->y = -10.0;238 q2->x = 0.0;239 q2->y = 0.5;240 CU_ASSERT( lw_segment_intersects(p1, p2, q1, q2) == SEG_COLINEAR );241 242 /* Q: Co-linear contained */243 q1->x = 0.0;244 q1->y = 0.4;245 q2->x = 0.0;246 q2->y = 0.5;247 CU_ASSERT( lw_segment_intersects(p1, p2, q1, q2) == SEG_COLINEAR );248 249 /* Q: Horizontal touching at end point from left */250 q1->x = -0.5;251 q1->y = 1.0;252 q2->x = 0.0;253 q2->y = 1.0;254 CU_ASSERT( lw_segment_intersects(p1, p2, q1, q2) == SEG_TOUCH_LEFT );255 256 /* Q: Horizontal touching at end point from right */257 q1->x = 0.5;258 q1->y = 1.0;259 q2->x = 0.0;260 q2->y = 1.0;261 CU_ASSERT( lw_segment_intersects(p1, p2, q1, q2) == SEG_TOUCH_RIGHT );262 263 /* Q: Horizontal touching at start point from left */264 q1->x = -0.5;265 q1->y = 0.0;266 q2->x = 0.0;267 q2->y = 0.0;268 CU_ASSERT( lw_segment_intersects(p1, p2, q1, q2) == SEG_TOUCH_LEFT );269 270 261 /* Q: Horizontal touching at start point from right */ 271 q1 ->x = 0.5;272 q1 ->y = 0.0;273 q2 ->x = 0.0;274 q2 ->y = 0.0;275 CU_ASSERT( lw_segment_intersects(p1, p2, q1, q2) == SEG_ TOUCH_RIGHT );262 q1.x = 0.0; 263 q1.y = 0.0; 264 q2.x = 0.5; 265 q2.y = 0.0; 266 CU_ASSERT( lw_segment_intersects(p1, p2, q1, q2) == SEG_CROSS_RIGHT ); 276 267 277 268 } … … 280 271 { 281 272 273 POINT4D p; 274 282 275 /* 283 276 ** Simple test, two two-point lines … … 285 278 286 279 /* Vertical line from 0,0 to 1,1 */ 287 p ->x = 0.0;288 p ->y = 0.0;289 setPoint4d(pa21, 0, p);290 p ->y = 1.0;291 setPoint4d(pa21, 1, p);280 p.x = 0.0; 281 p.y = 0.0; 282 setPoint4d(pa21, 0, &p); 283 p.y = 1.0; 284 setPoint4d(pa21, 1, &p); 292 285 293 286 /* Horizontal, crossing mid-segment */ 294 p ->x = -0.5;295 p ->y = 0.5;296 setPoint4d(pa22, 0, p);297 p ->x = 0.5;298 setPoint4d(pa22, 1, p);287 p.x = -0.5; 288 p.y = 0.5; 289 setPoint4d(pa22, 0, &p); 290 p.x = 0.5; 291 setPoint4d(pa22, 1, &p); 299 292 300 293 CU_ASSERT( lwline_crossing_direction(l21, l22) == LINE_CROSS_RIGHT ); 301 294 302 /* Horizontal, crossing at top end vertex */ 303 p->x = -0.5; 304 p->y = 1.0; 305 setPoint4d(pa22, 0, p); 306 p->x = 0.5; 307 setPoint4d(pa22, 1, p); 295 /* Horizontal, crossing at top end vertex (end crossings don't count) */ 296 p.x = -0.5; 297 p.y = 1.0; 298 setPoint4d(pa22, 0, &p); 299 p.x = 0.5; 300 setPoint4d(pa22, 1, &p); 301 302 CU_ASSERT( lwline_crossing_direction(l21, l22) == LINE_NO_CROSS ); 303 304 /* Horizontal, crossing at bottom end vertex */ 305 p.x = -0.5; 306 p.y = 0.0; 307 setPoint4d(pa22, 0, &p); 308 p.x = 0.5; 309 setPoint4d(pa22, 1, &p); 308 310 309 311 CU_ASSERT( lwline_crossing_direction(l21, l22) == LINE_CROSS_RIGHT ); 310 312 311 /* Horizontal, crossing at bottom end vertex */312 p->x = -0.5;313 p->y = 0.0;314 setPoint4d(pa22, 0, p);315 p->x = 0.5;316 setPoint4d(pa22, 1, p);317 318 CU_ASSERT( lwline_crossing_direction(l21, l22) == LINE_CROSS_RIGHT );319 320 313 /* Horizontal, no crossing */ 321 p ->x = -0.5;322 p ->y = 2.0;323 setPoint4d(pa22, 0, p);324 p ->x = 0.5;325 setPoint4d(pa22, 1, p);314 p.x = -0.5; 315 p.y = 2.0; 316 setPoint4d(pa22, 0, &p); 317 p.x = 0.5; 318 setPoint4d(pa22, 1, &p); 326 319 327 320 CU_ASSERT( lwline_crossing_direction(l21, l22) == LINE_NO_CROSS ); 328 321 329 322 /* Vertical, no crossing */ 330 p ->x = -0.5;331 p ->y = 0.0;332 setPoint4d(pa22, 0, p);333 p ->y = 1.0;334 setPoint4d(pa22, 1, p);323 p.x = -0.5; 324 p.y = 0.0; 325 setPoint4d(pa22, 0, &p); 326 p.y = 1.0; 327 setPoint4d(pa22, 1, &p); 335 328 336 329 CU_ASSERT( lwline_crossing_direction(l21, l22) == LINE_NO_CROSS ); … … 345 338 ** More complex test, longer lines and multiple crossings 346 339 */ 347 348 340 /* Vertical line with vertices at y integers */ 349 341 l51 = (LWLINE*)lwgeom_from_ewkt("LINESTRING(0 0, 0 1, 0 2, 0 3, 0 4)", PARSER_CHECK_NONE); … … 374 366 lwline_free(l52); 375 367 376 /* Two crossings, one at the last vertex on the next interior vertex */377 l52 = (LWLINE*)lwgeom_from_ewkt("LINESTRING(1 4, 0 4, -1 3, 0 3, 1 3)", PARSER_CHECK_NONE);378 CU_ASSERT( lwline_crossing_direction(l51, l52) == LINE_MULTICROSS_END_SAME_FIRST_LEFT );379 lwline_free(l52);380 381 368 /* Three crossings, two at midpoints, one at vertex */ 382 369 l52 = (LWLINE*)lwgeom_from_ewkt("LINESTRING(0.5 1, -1 0.5, 1 2, -1 2, -1 3)", PARSER_CHECK_NONE); … … 403 390 } 404 391 392 393 void test_lwline_crossing_bugs(void) 394 { 395 LWLINE *l1; 396 LWLINE *l2; 397 398 l1 = (LWLINE*)lwgeom_from_ewkt("LINESTRING(2.99 90.16,71 74,20 140,171 154)", PARSER_CHECK_NONE); 399 l2 = (LWLINE*)lwgeom_from_ewkt("LINESTRING(25 169,89 114,40 70,86 43)", PARSER_CHECK_NONE); 400 401 CU_ASSERT( lwline_crossing_direction(l1, l2) == LINE_MULTICROSS_END_RIGHT ); 402 lwline_free(l1); 403 lwline_free(l2); 404 405 } 406 405 407 void test_lwpoint_set_ordinate(void) 406 408 { 407 p->x = 0.0; 408 p->y = 0.0; 409 p->z = 0.0; 410 p->m = 0.0; 411 412 lwpoint_set_ordinate(p, 0, 1.5); 413 CU_ASSERT_EQUAL( p->x, 1.5 ); 414 415 lwpoint_set_ordinate(p, 3, 2.5); 416 CU_ASSERT_EQUAL( p->m, 2.5 ); 417 418 lwpoint_set_ordinate(p, 2, 3.5); 419 CU_ASSERT_EQUAL( p->z, 3.5 ); 409 POINT4D p; 410 411 p.x = 0.0; 412 p.y = 0.0; 413 p.z = 0.0; 414 p.m = 0.0; 415 416 lwpoint_set_ordinate(&p, 0, 1.5); 417 CU_ASSERT_EQUAL( p.x, 1.5 ); 418 419 lwpoint_set_ordinate(&p, 3, 2.5); 420 CU_ASSERT_EQUAL( p.m, 2.5 ); 421 422 lwpoint_set_ordinate(&p, 2, 3.5); 423 CU_ASSERT_EQUAL( p.z, 3.5 ); 420 424 421 425 } … … 423 427 void test_lwpoint_get_ordinate(void) 424 428 { 425 426 p->x = 10.0; 427 p->y = 20.0; 428 p->z = 30.0; 429 p->m = 40.0; 430 431 CU_ASSERT_EQUAL( lwpoint_get_ordinate(p, 0), 10.0 ); 432 CU_ASSERT_EQUAL( lwpoint_get_ordinate(p, 1), 20.0 ); 433 CU_ASSERT_EQUAL( lwpoint_get_ordinate(p, 2), 30.0 ); 434 CU_ASSERT_EQUAL( lwpoint_get_ordinate(p, 3), 40.0 ); 429 POINT4D p; 430 431 p.x = 10.0; 432 p.y = 20.0; 433 p.z = 30.0; 434 p.m = 40.0; 435 436 CU_ASSERT_EQUAL( lwpoint_get_ordinate(&p, 0), 10.0 ); 437 CU_ASSERT_EQUAL( lwpoint_get_ordinate(&p, 1), 20.0 ); 438 CU_ASSERT_EQUAL( lwpoint_get_ordinate(&p, 2), 30.0 ); 439 CU_ASSERT_EQUAL( lwpoint_get_ordinate(&p, 3), 40.0 ); 435 440 436 441 } … … 438 443 void test_lwpoint_interpolate(void) 439 444 { 440 POINT4D *r = NULL; 441 r = lwalloc(sizeof(POINT4D)); 445 POINT4D p, q, r; 442 446 int rv = 0; 443 447 444 p->x = 10.0; 445 p->y = 20.0; 446 p->z = 30.0; 447 p->m = 40.0; 448 q->x = 20.0; 449 q->y = 30.0; 450 q->z = 40.0; 451 q->m = 50.0; 452 453 rv = lwpoint_interpolate(p, q, r, 4, 2, 35.0); 454 CU_ASSERT_EQUAL( r->x, 15.0); 455 456 rv = lwpoint_interpolate(p, q, r, 4, 3, 41.0); 457 CU_ASSERT_EQUAL( r->y, 21.0); 458 459 rv = lwpoint_interpolate(p, q, r, 4, 3, 50.0); 460 CU_ASSERT_EQUAL( r->y, 30.0); 461 462 rv = lwpoint_interpolate(p, q, r, 4, 3, 40.0); 463 CU_ASSERT_EQUAL( r->y, 20.0); 464 465 lwfree(r); 448 p.x = 10.0; 449 p.y = 20.0; 450 p.z = 30.0; 451 p.m = 40.0; 452 453 q.x = 20.0; 454 q.y = 30.0; 455 q.z = 40.0; 456 q.m = 50.0; 457 458 rv = lwpoint_interpolate(&p, &q, &r, 4, 2, 35.0); 459 CU_ASSERT_EQUAL( r.x, 15.0); 460 461 rv = lwpoint_interpolate(&p, &q, &r, 4, 3, 41.0); 462 CU_ASSERT_EQUAL( r.y, 21.0); 463 464 rv = lwpoint_interpolate(&p, &q, &r, 4, 3, 50.0); 465 CU_ASSERT_EQUAL( r.y, 30.0); 466 467 rv = lwpoint_interpolate(&p, &q, &r, 4, 3, 40.0); 468 CU_ASSERT_EQUAL( r.y, 20.0); 466 469 467 470 } … … 679 682 LWCOLLECTION *c; 680 683 char *ewkt; 681 682 p->x = 0.0; 683 p->y = 0.0; 684 p->z = 0.0; 685 setPoint4d(pa, 0, p); 686 687 p->x = 1.0; 688 p->y = 1.0; 689 p->z = 1.0; 690 setPoint4d(pa, 1, p); 691 692 p->x = 2.0; 693 p->y = 2.0; 694 p->z = 2.0; 695 setPoint4d(pa, 2, p); 684 POINT4D p; 685 686 p.x = 0.0; 687 p.y = 0.0; 688 p.z = 0.0; 689 setPoint4d(pa, 0, &p); 690 691 p.x = 1.0; 692 p.y = 1.0; 693 p.z = 1.0; 694 setPoint4d(pa, 1, &p); 695 696 p.x = 2.0; 697 p.y = 2.0; 698 p.z = 2.0; 699 setPoint4d(pa, 2, &p); 696 700 697 701 c = lwline_clip_to_ordinate_range(line, 2, 0.5, 1.5); -
branches/1.4/liblwgeom/cunit/cu_algorithm.h
r4168 r4787 41 41 void test_geohash_point(void); 42 42 void test_geohash(void); 43 void test_lwline_crossing_bugs(void); -
branches/1.4/liblwgeom/liblwgeom.h
r4309 r4787 54 54 #define FP_CONTAINS_EXCL(A, X, B) (FP_LT(A, X) && FP_LT(X, B)) 55 55 #define FP_CONTAINS(A, X, B) FP_CONTAINS_EXCL(A, X, B) 56 #define FP_IS_ZERO(A) (fabs(A) <= PGIS_EPSILON) 56 57 #define LW_TRUE 1 57 58 #define LW_FALSE 0 -
branches/1.4/liblwgeom/lwalgorithm.c
r4168 r4787 21 21 ** Return = 0.0 if point Q in on segment P 22 22 */ 23 double lw_segment_side(POINT2D *p1, POINT2D *p2, POINT2D *q)24 { 25 return ( (q ->x - p1->x) * (p2->y - p1->y) - (p2->x - p1->x) * (q->y - p1->y) );23 double lw_segment_side(POINT2D p1, POINT2D p2, POINT2D q) 24 { 25 return ( (q.x - p1.x) * (p2.y - p1.y) - (p2.x - p1.x) * (q.y - p1.y) ); 26 26 } 27 27 … … 33 33 double maxp=LW_MAX(p1.x,p2.x); 34 34 35 if ( minp>maxq || maxp<minq)35 if (FP_GT(minp,maxq) || FP_LT(maxp,minq)) 36 36 return LW_FALSE; 37 37 … … 41 41 maxp=LW_MAX(p1.y,p2.y); 42 42 43 if ( minp>maxq || maxp<minq)43 if (FP_GT(minp,maxq) || FP_LT(maxp,minq)) 44 44 return LW_FALSE; 45 45 46 46 return LW_TRUE; 47 47 } 48 48 49 49 50 /** … … 60 61 ** SEG_CROSS_LEFT = 2, 61 62 ** SEG_CROSS_RIGHT = 3, 62 ** SEG_TOUCH_LEFT = 4,63 ** SEG_TOUCH_RIGHT = 564 63 */ 65 int lw_segment_intersects(POINT2D *p1, POINT2D *p2, POINT2D *q1, POINT2D *q2)64 int lw_segment_intersects(POINT2D p1, POINT2D p2, POINT2D q1, POINT2D q2) 66 65 { 67 66 … … 69 68 70 69 /* No envelope interaction => we are done. */ 71 if (!lw_segment_envelope_intersects( *p1, *p2, *q1, *p2))70 if (!lw_segment_envelope_intersects(p1, p2, q1, p2)) 72 71 { 73 72 return SEG_NO_INTERSECTION; … … 91 90 92 91 /* Nobody is on one side or another? Must be colinear. */ 93 if ( pq1 == 0.0 && pq2 == 0.0 && qp1 == 0.0 && qp2 == 0.0)92 if (FP_IS_ZERO(pq1) && FP_IS_ZERO(pq2) && FP_IS_ZERO(qp1) && FP_IS_ZERO(qp2)) 94 93 { 95 94 return SEG_COLINEAR; … … 98 97 /* 99 98 ** When one end-point touches, the sidedness is determined by the 100 ** location of the other end-point. 99 ** location of the other end-point. Only touches by the first point 100 ** will be considered "real" to avoid double counting. 101 101 */ 102 if ( pq2 == 0.0 ) 103 { 104 if ( pq1 < 0.0 ) 105 return SEG_TOUCH_LEFT; 102 LWDEBUGF(4, "pq1=%.15g pq2=%.15g", pq1, pq2); 103 LWDEBUGF(4, "qp1=%.15g qp2=%.15g", qp1, qp2); 104 105 /* Second point of p or q touches, it's not a crossing. */ 106 if ( FP_IS_ZERO(pq2) || FP_IS_ZERO(qp2) ) 107 { 108 return SEG_NO_INTERSECTION; 109 } 110 111 /* First point of p touches, it's a "crossing". */ 112 if ( FP_IS_ZERO(pq1) ) 113 { 114 if ( FP_GT(pq2,0.0) ) 115 return SEG_CROSS_RIGHT; 106 116 else 107 return SEG_TOUCH_RIGHT; 108 } 109 if ( pq1 == 0.0 ) 110 { 111 if ( pq2 < 0.0 ) 112 return SEG_TOUCH_LEFT; 117 return SEG_CROSS_LEFT; 118 } 119 120 /* First point of q touches, it's a crossing. */ 121 if ( FP_IS_ZERO(qp1) ) 122 { 123 if ( FP_LT(pq1,pq2) ) 124 return SEG_CROSS_RIGHT; 113 125 else 114 return SEG_ TOUCH_RIGHT;115 } 116 126 return SEG_CROSS_LEFT; 127 } 128 117 129 /* The segments cross, what direction is the crossing? */ 118 if ( pq1 < pq2)130 if ( FP_LT(pq1,pq2) ) 119 131 return SEG_CROSS_RIGHT; 120 132 else … … 142 154 int lwline_crossing_direction(LWLINE *l1, LWLINE *l2) 143 155 { 144 145 156 int i = 0, j = 0, rv = 0; 146 POINT2D *p1; 147 POINT2D *p2; 148 POINT2D *q1; 149 POINT2D *q2; 150 POINTARRAY *pa1; 151 POINTARRAY *pa2; 157 POINT2D p1, p2, q1, q2; 158 POINTARRAY *pa1 = NULL, *pa2 = NULL; 152 159 int cross_left = 0; 153 160 int cross_right = 0; 154 161 int first_cross = 0; 155 int final_cross = 0;156 162 int this_cross = 0; 157 int vertex_touch = -1;158 int vertex_touch_type = 0;159 163 160 164 pa1 = (POINTARRAY*)l1->points; 161 165 pa2 = (POINTARRAY*)l2->points; 162 163 p1 = lwalloc(sizeof(POINT2D));164 p2 = lwalloc(sizeof(POINT2D));165 q1 = lwalloc(sizeof(POINT2D));166 q2 = lwalloc(sizeof(POINT2D));167 166 168 167 /* One-point lines can't intersect (and shouldn't exist). */ … … 170 169 return LINE_NO_CROSS; 171 170 172 LWDEBUGF(4, "lineCrossingDirection: l1 = %s", lwgeom_to_ewkt((LWGEOM*)l1,0)); 173 LWDEBUGF(4, "lineCrossingDirection: l2 = %s", lwgeom_to_ewkt((LWGEOM*)l2,0)); 171 LWDEBUGF(4, "l1 = %s", lwgeom_to_ewkt((LWGEOM*)l1,0)); 172 LWDEBUGF(4, "l2 = %s", lwgeom_to_ewkt((LWGEOM*)l2,0)); 173 174 /* Initialize first point of q */ 175 rv = getPoint2d_p(pa2, 0, &q1); 174 176 175 177 for ( i = 1; i < pa2->npoints; i++ ) 176 178 { 177 179 178 rv = getPoint2d_p(pa2, i-1, q1); 179 rv = getPoint2d_p(pa2, i, q2); 180 180 /* Update second point of q to next value */ 181 rv = getPoint2d_p(pa2, i, &q2); 182 183 /* Initialize first point of p */ 184 rv = getPoint2d_p(pa1, 0, &p1); 185 181 186 for ( j = 1; j < pa1->npoints; j++ ) 182 187 { 183 188 184 rv = getPoint2d_p(pa1, j-1, p1); 185 rv = getPoint2d_p(pa1, j, p2); 186 187 LWDEBUGF(4, "lineCrossingDirection: i=%d, j=%d", i, j); 188 189 /* Update second point of p to next value */ 190 rv = getPoint2d_p(pa1, j, &p2); 191 189 192 this_cross = lw_segment_intersects(p1, p2, q1, q2); 190 193 191 if ( ! first_cross && this_cross ) 192 first_cross = this_cross; 193 if ( this_cross ) 194 final_cross = this_cross; 194 LWDEBUGF(4, "i=%d, j=%d (%.8g %.8g, %.8g %.8g)", this_cross, i, j, p1.x, p1.y, p2.x, p2.y); 195 195 196 196 if ( this_cross == SEG_CROSS_LEFT ) 197 197 { 198 LWDEBUG(4,"this_cross == SEG_CROSS_LEFT"); 198 199 cross_left++; 199 break; 200 if ( ! first_cross ) 201 first_cross = SEG_CROSS_LEFT; 200 202 } 201 203 202 204 if ( this_cross == SEG_CROSS_RIGHT ) 203 205 { 206 LWDEBUG(4,"this_cross == SEG_CROSS_RIGHT"); 204 207 cross_right++; 205 break; 208 if ( ! first_cross ) 209 first_cross = SEG_CROSS_LEFT; 206 210 } 207 211 208 212 /* 209 ** Crossing at a co-linearity can be turned into crossing at210 ** a vertex by pulling the original touch point forward along211 ** the co-linear ity.213 ** Crossing at a co-linearity can be turned handled by extending 214 ** segment to next vertext and seeing if the end points straddle 215 ** the co-linear segment. 212 216 */ 213 if ( this_cross == SEG_COLINEAR && vertex_touch == (i-1) ) 214 { 215 vertex_touch = i; 216 break; 217 } 218 219 /* 220 ** Crossing-at-vertex will cause four segment touch interactions, two at 221 ** j-1 and two at j. We avoid incrementing our cross count by ignoring the 222 ** second pair. 223 */ 224 if ( this_cross == SEG_TOUCH_LEFT ) 225 { 226 if ( vertex_touch == (i-1) && vertex_touch_type == SEG_TOUCH_RIGHT ) 227 { 228 cross_left++; 229 vertex_touch = -1; 230 vertex_touch_type = 0; 231 } 232 else 233 { 234 vertex_touch = i; 235 vertex_touch_type = this_cross; 236 } 237 break; 238 } 239 if ( this_cross == SEG_TOUCH_RIGHT ) 240 { 241 if ( vertex_touch == (i-1) && vertex_touch_type == SEG_TOUCH_LEFT ) 242 { 243 cross_right++; 244 vertex_touch = -1; 245 vertex_touch_type = 0; 246 } 247 else 248 { 249 vertex_touch = i; 250 vertex_touch_type = this_cross; 251 } 252 break; 253 } 254 255 /* 256 ** TODO Handle co-linear cases. 257 */ 258 259 LWDEBUGF(4, "lineCrossingDirection: this_cross=%d, vertex_touch=%d, vertex_touch_type=%d", this_cross, vertex_touch, vertex_touch_type); 260 261 } 262 263 } 264 265 LWDEBUGF(4, "first_cross=%d, final_cross=%d, cross_left=%d, cross_right=%d", first_cross, final_cross, cross_left, cross_right); 266 267 lwfree(p1); 268 lwfree(p2); 269 lwfree(q1); 270 lwfree(q2); 217 if ( this_cross == SEG_COLINEAR ) 218 { 219 LWDEBUG(4,"this_cross == SEG_COLINEAR"); 220 /* TODO: Add logic here and in segment_intersects() 221 continue; 222 */ 223 } 224 225 LWDEBUG(4,"this_cross == SEG_NO_INTERSECTION"); 226 227 /* Turn second point of p into first point */ 228 p1 = p2; 229 230 } 231 232 /* Turn second point of q into first point */ 233 q1 = q2; 234 235 } 236 237 LWDEBUGF(4, "first_cross=%d, cross_left=%d, cross_right=%d", first_cross, cross_left, cross_right); 271 238 272 239 if ( !cross_left && !cross_right ) … … 291 258 return LINE_MULTICROSS_END_SAME_FIRST_RIGHT; 292 259 293 if ( cross_left - cross_right == 0 && first_cross == SEG_TOUCH_LEFT )294 return LINE_MULTICROSS_END_SAME_FIRST_RIGHT;295 296 if ( cross_left - cross_right == 0 && first_cross == SEG_TOUCH_RIGHT )297 return LINE_MULTICROSS_END_SAME_FIRST_LEFT;298 299 260 return LINE_NO_CROSS; 300 261 301 262 } 263 264 302 265 303 266 /* -
branches/1.4/liblwgeom/lwalgorithm.h
r4168 r4787 24 24 }; 25 25 26 double lw_segment_side(POINT2D *p1, POINT2D *p2, POINT2D *q);27 int lw_segment_intersects(POINT2D *p1, POINT2D *p2, POINT2D *q1, POINT2D *q2);26 double lw_segment_side(POINT2D p1, POINT2D p2, POINT2D q); 27 int lw_segment_intersects(POINT2D p1, POINT2D p2, POINT2D q1, POINT2D q2); 28 28 int lw_segment_envelope_intersects(POINT2D p1, POINT2D p2, POINT2D q1, POINT2D q2); 29 29
