PostGIS 3.7.0dev-r@@SVN_REVISION@@
Loading...
Searching...
No Matches

◆ lwline_crossing_direction()

int lwline_crossing_direction ( const LWLINE l1,
const LWLINE l2 
)

lwline_crossing_direction: returns the kind of CG_LINE_CROSS_TYPE behavior of 2 linestrings

Given two lines, characterize how (and if) they cross each other.

Parameters
l1first line string
l2second line string
Returns
a CG_LINE_CROSS_TYPE LINE_NO_CROSS = 0 LINE_CROSS_LEFT = -1 LINE_CROSS_RIGHT = 1 LINE_MULTICROSS_END_LEFT = -2 LINE_MULTICROSS_END_RIGHT = 2 LINE_MULTICROSS_END_SAME_FIRST_LEFT = -3 LINE_MULTICROSS_END_SAME_FIRST_RIGHT = 3

Definition at line 477 of file lwalgorithm.c.

478{
479 uint32_t i = 0, j = 0;
480 const POINT2D *p1, *p2, *q1, *q2;
481 POINTARRAY *pa1 = NULL, *pa2 = NULL;
482 int cross_left = 0;
483 int cross_right = 0;
484 int first_cross = 0;
485 int this_cross = 0;
486#if POSTGIS_DEBUG_LEVEL >= 4
487 char *geom_ewkt;
488#endif
489
490 pa1 = (POINTARRAY*)l1->points;
491 pa2 = (POINTARRAY*)l2->points;
492
493 /* One-point lines can't intersect (and shouldn't exist). */
494 if ( pa1->npoints < 2 || pa2->npoints < 2 )
495 return LINE_NO_CROSS;
496
497 /* Zero length lines don't have a side. */
498 if ( ptarray_length_2d(pa1) == 0 || ptarray_length_2d(pa2) == 0 )
499 return LINE_NO_CROSS;
500
501
502#if POSTGIS_DEBUG_LEVEL >= 4
503 geom_ewkt = lwgeom_to_ewkt((LWGEOM*)l1);
504 LWDEBUGF(4, "l1 = %s", geom_ewkt);
505 lwfree(geom_ewkt);
506 geom_ewkt = lwgeom_to_ewkt((LWGEOM*)l2);
507 LWDEBUGF(4, "l2 = %s", geom_ewkt);
508 lwfree(geom_ewkt);
509#endif
510
511 /* Initialize first point of q */
512 q1 = getPoint2d_cp(pa2, 0);
513
514 for ( i = 1; i < pa2->npoints; i++ )
515 {
516
517 /* Update second point of q to next value */
518 q2 = getPoint2d_cp(pa2, i);
519
520 /* Initialize first point of p */
521 p1 = getPoint2d_cp(pa1, 0);
522
523 for ( j = 1; j < pa1->npoints; j++ )
524 {
525
526 /* Update second point of p to next value */
527 p2 = getPoint2d_cp(pa1, j);
528
529 this_cross = lw_segment_intersects(p1, p2, q1, q2);
530
531 LWDEBUGF(4, "i=%d, j=%d (%.8g %.8g, %.8g %.8g)", i, j, p1->x, p1->y, p2->x, p2->y);
532
533 if ( this_cross == SEG_CROSS_LEFT )
534 {
535 LWDEBUG(4,"this_cross == SEG_CROSS_LEFT");
536 cross_left++;
537 if ( ! first_cross )
538 first_cross = SEG_CROSS_LEFT;
539 }
540
541 if ( this_cross == SEG_CROSS_RIGHT )
542 {
543 LWDEBUG(4,"this_cross == SEG_CROSS_RIGHT");
544 cross_right++;
545 if ( ! first_cross )
546 first_cross = SEG_CROSS_RIGHT;
547 }
548
549 /*
550 ** Crossing at a co-linearity can be turned handled by extending
551 ** segment to next vertex and seeing if the end points straddle
552 ** the co-linear segment.
553 */
554 if ( this_cross == SEG_COLINEAR )
555 {
556 LWDEBUG(4,"this_cross == SEG_COLINEAR");
557 /* TODO: Add logic here and in segment_intersects()
558 continue;
559 */
560 }
561
562 LWDEBUG(4,"this_cross == SEG_NO_INTERSECTION");
563
564 /* Turn second point of p into first point */
565 p1 = p2;
566
567 }
568
569 /* Turn second point of q into first point */
570 q1 = q2;
571
572 }
573
574 LWDEBUGF(4, "first_cross=%d, cross_left=%d, cross_right=%d", first_cross, cross_left, cross_right);
575
576 if ( !cross_left && !cross_right )
577 return LINE_NO_CROSS;
578
579 if ( !cross_left && cross_right == 1 )
580 return LINE_CROSS_RIGHT;
581
582 if ( !cross_right && cross_left == 1 )
583 return LINE_CROSS_LEFT;
584
585 if ( cross_left - cross_right == 1 )
587
588 if ( cross_left - cross_right == -1 )
590
591 if ( cross_left - cross_right == 0 && first_cross == SEG_CROSS_LEFT )
593
594 if ( cross_left - cross_right == 0 && first_cross == SEG_CROSS_RIGHT )
596
597 return LINE_NO_CROSS;
598
599}
double ptarray_length_2d(const POINTARRAY *pts)
Find the 2d length of the given POINTARRAY (even if it's 3d)
Definition ptarray.c:1975
char * lwgeom_to_ewkt(const LWGEOM *lwgeom)
Return an allocated string.
Definition lwgeom.c:593
void lwfree(void *mem)
Definition lwutil.c:248
@ LINE_MULTICROSS_END_RIGHT
Definition liblwgeom.h:1692
@ LINE_MULTICROSS_END_SAME_FIRST_LEFT
Definition liblwgeom.h:1693
@ LINE_MULTICROSS_END_LEFT
Definition liblwgeom.h:1691
@ LINE_CROSS_LEFT
Definition liblwgeom.h:1689
@ LINE_MULTICROSS_END_SAME_FIRST_RIGHT
Definition liblwgeom.h:1694
@ LINE_CROSS_RIGHT
Definition liblwgeom.h:1690
@ LINE_NO_CROSS
Definition liblwgeom.h:1688
@ SEG_COLINEAR
@ SEG_CROSS_RIGHT
@ SEG_CROSS_LEFT
int lw_segment_intersects(const POINT2D *p1, const POINT2D *p2, const POINT2D *q1, const POINT2D *q2)
returns the kind of CG_SEGMENT_INTERSECTION_TYPE behavior of lineseg 1 (constructed from p1 and p2) a...
#define LWDEBUG(level, msg)
Definition lwgeom_log.h:101
#define LWDEBUGF(level, msg,...)
Definition lwgeom_log.h:106
static const POINT2D * getPoint2d_cp(const POINTARRAY *pa, uint32_t n)
Returns a POINT2D pointer into the POINTARRAY serialized_ptlist, suitable for reading from.
Definition lwinline.h:97
POINTARRAY * points
Definition liblwgeom.h:483

References getPoint2d_cp(), LINE_CROSS_LEFT, LINE_CROSS_RIGHT, LINE_MULTICROSS_END_LEFT, LINE_MULTICROSS_END_RIGHT, LINE_MULTICROSS_END_SAME_FIRST_LEFT, LINE_MULTICROSS_END_SAME_FIRST_RIGHT, LINE_NO_CROSS, lw_segment_intersects(), LWDEBUG, LWDEBUGF, lwfree(), lwgeom_to_ewkt(), POINTARRAY::npoints, LWLINE::points, ptarray_length_2d(), SEG_COLINEAR, SEG_CROSS_LEFT, SEG_CROSS_RIGHT, POINT2D::x, and POINT2D::y.

Referenced by ST_LineCrossingDirection(), test_lwline_crossing_bugs(), test_lwline_crossing_long_lines(), and test_lwline_crossing_short_lines().

Here is the call graph for this function:
Here is the caller graph for this function: