Example #1
0
/**
** @brief lwline_crossing_direction: returns the kind of #CG_LINE_CROSS_TYPE behavior  of 2 linestrings
** @param l1 first line string
** @param l2 second line string
** @return 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
**
*/
int lwline_crossing_direction(const LWLINE *l1, const LWLINE *l2)
{
    int i = 0, j = 0, rv = 0;
    POINT2D p1, p2, q1, q2;
    POINTARRAY *pa1 = NULL, *pa2 = NULL;
    int cross_left = 0;
    int cross_right = 0;
    int first_cross = 0;
    int this_cross = 0;

    pa1 = (POINTARRAY*)l1->points;
    pa2 = (POINTARRAY*)l2->points;

    /* One-point lines can't intersect (and shouldn't exist). */
    if ( pa1->npoints < 2 || pa2->npoints < 2 )
        return LINE_NO_CROSS;

    LWDEBUGF(4, "l1 = %s", lwgeom_to_ewkt((LWGEOM*)l1));
    LWDEBUGF(4, "l2 = %s", lwgeom_to_ewkt((LWGEOM*)l2));

    /* Initialize first point of q */
    rv = getPoint2d_p(pa2, 0, &q1);

    for ( i = 1; i < pa2->npoints; i++ )
    {

        /* Update second point of q to next value */
        rv = getPoint2d_p(pa2, i, &q2);

        /* Initialize first point of p */
        rv = getPoint2d_p(pa1, 0, &p1);

        for ( j = 1; j < pa1->npoints; j++ )
        {

            /* Update second point of p to next value */
            rv = getPoint2d_p(pa1, j, &p2);

            this_cross = lw_segment_intersects(&p1, &p2, &q1, &q2);

            LWDEBUGF(4, "i=%d, j=%d (%.8g %.8g, %.8g %.8g)", this_cross, i, j, p1.x, p1.y, p2.x, p2.y);

            if ( this_cross == SEG_CROSS_LEFT )
            {
                LWDEBUG(4,"this_cross == SEG_CROSS_LEFT");
                cross_left++;
                if ( ! first_cross )
                    first_cross = SEG_CROSS_LEFT;
            }

            if ( this_cross == SEG_CROSS_RIGHT )
            {
                LWDEBUG(4,"this_cross == SEG_CROSS_RIGHT");
                cross_right++;
                if ( ! first_cross )
                    first_cross = SEG_CROSS_LEFT;
            }

            /*
            ** Crossing at a co-linearity can be turned handled by extending
            ** segment to next vertext and seeing if the end points straddle
            ** the co-linear segment.
            */
            if ( this_cross == SEG_COLINEAR )
            {
                LWDEBUG(4,"this_cross == SEG_COLINEAR");
                /* TODO: Add logic here and in segment_intersects()
                continue;
                */
            }

            LWDEBUG(4,"this_cross == SEG_NO_INTERSECTION");

            /* Turn second point of p into first point */
            p1 = p2;

        }

        /* Turn second point of q into first point */
        q1 = q2;

    }

    LWDEBUGF(4, "first_cross=%d, cross_left=%d, cross_right=%d", first_cross, cross_left, cross_right);

    if ( !cross_left && !cross_right )
        return LINE_NO_CROSS;

    if ( !cross_left && cross_right == 1 )
        return LINE_CROSS_RIGHT;

    if ( !cross_right && cross_left == 1 )
        return LINE_CROSS_LEFT;

    if ( cross_left - cross_right == 1 )
        return LINE_MULTICROSS_END_LEFT;

    if ( cross_left - cross_right == -1 )
        return LINE_MULTICROSS_END_RIGHT;

    if ( cross_left - cross_right == 0 && first_cross == SEG_CROSS_LEFT )
        return LINE_MULTICROSS_END_SAME_FIRST_LEFT;

    if ( cross_left - cross_right == 0 && first_cross == SEG_CROSS_RIGHT )
        return LINE_MULTICROSS_END_SAME_FIRST_RIGHT;

    return LINE_NO_CROSS;

}
Example #2
0
/*
** Test crossings side.
*/
static void test_lw_segment_intersects(void)
{

#define setpoint(p, x1, y1) {(p).x = (x1); (p).y = (y1);}

	POINT2D p1, p2, q1, q2;

	/* P: Vertical line at x=0 */
	setpoint(p1, 0.0, 0.0);
	p1.x = 0.0;
	p1.y = 0.0;
	p2.x = 0.0;
	p2.y = 1.0;

	/* Q: Horizontal line crossing left to right */
	q1.x = -0.5;
	q1.y = 0.5;
	q2.x = 0.5;
	q2.y = 0.5;
	CU_ASSERT( lw_segment_intersects(&p1, &p2, &q1, &q2) == SEG_CROSS_RIGHT );

	/* Q: Horizontal line crossing right to left */
	q1.x = 0.5;
	q1.y = 0.5;
	q2.x = -0.5;
	q2.y = 0.5;
	CU_ASSERT( lw_segment_intersects(&p1, &p2, &q1, &q2) == SEG_CROSS_LEFT );

	/* Q: Horizontal line not crossing right to left */
	q1.x = 0.5;
	q1.y = 1.5;
	q2.x = -0.5;
	q2.y = 1.5;
	CU_ASSERT( lw_segment_intersects(&p1, &p2, &q1, &q2) == SEG_NO_INTERSECTION );

	/* Q: Horizontal line crossing at second vertex right to left */
	q1.x = 0.5;
	q1.y = 1.0;
	q2.x = -0.5;
	q2.y = 1.0;
	CU_ASSERT( lw_segment_intersects(&p1, &p2, &q1, &q2) == SEG_NO_INTERSECTION );

	/* Q: Horizontal line crossing at first vertex right to left */
	q1.x = 0.5;
	q1.y = 0.0;
	q2.x = -0.5;
	q2.y = 0.0;
	CU_ASSERT( lw_segment_intersects(&p1, &p2, &q1, &q2) == SEG_CROSS_LEFT );

	/* Q: Diagonal line with large range crossing at first vertex right to left */
	q1.x = 0.5;
	q1.y = 10.0;
	q2.x = -0.5;
	q2.y = -10.0;
	CU_ASSERT( lw_segment_intersects(&p1, &p2, &q1, &q2) == SEG_CROSS_LEFT );

	/* Q: Diagonal line with large range crossing at second vertex right to left */
	q1.x = 0.5;
	q1.y = 11.0;
	q2.x = -0.5;
	q2.y = -9.0;
	CU_ASSERT( lw_segment_intersects(&p1, &p2, &q1, &q2) == SEG_NO_INTERSECTION );

	/* Q: Horizontal touching from left at second vertex*/
	q1.x = -0.5;
	q1.y = 0.5;
	q2.x = 0.0;
	q2.y = 0.5;
	CU_ASSERT( lw_segment_intersects(&p1, &p2, &q1, &q2) == SEG_NO_INTERSECTION );

	/* Q: Horizontal touching from right at first vertex */
	q1.x = 0.0;
	q1.y = 0.5;
	q2.x = 0.5;
	q2.y = 0.5;
	CU_ASSERT( lw_segment_intersects(&p1, &p2, &q1, &q2) == SEG_CROSS_RIGHT );

	/* Q: Horizontal touching from left and far below on second vertex */
	q1.x = -0.5;
	q1.y = -10.5;
	q2.x = 0.0;
	q2.y = 0.5;
	CU_ASSERT( lw_segment_intersects(&p1, &p2, &q1, &q2) == SEG_NO_INTERSECTION );

	/* Q: Horizontal touching from right and far above on second vertex */
	q1.x = 0.5;
	q1.y = 10.5;
	q2.x = 0.0;
	q2.y = 0.5;
	CU_ASSERT( lw_segment_intersects(&p1, &p2, &q1, &q2) == SEG_NO_INTERSECTION );

	/* Q: Co-linear from top */
	q1.x = 0.0;
	q1.y = 10.0;
	q2.x = 0.0;
	q2.y = 0.5;
	CU_ASSERT( lw_segment_intersects(&p1, &p2, &q1, &q2) == SEG_COLINEAR );

	/* Q: Co-linear from bottom */
	q1.x = 0.0;
	q1.y = -10.0;
	q2.x = 0.0;
	q2.y = 0.5;
	CU_ASSERT( lw_segment_intersects(&p1, &p2, &q1, &q2) == SEG_COLINEAR );

	/* Q: Co-linear contained */
	q1.x = 0.0;
	q1.y = 0.4;
	q2.x = 0.0;
	q2.y = 0.5;
	CU_ASSERT( lw_segment_intersects(&p1, &p2, &q1, &q2) == SEG_COLINEAR );

	/* Q: Horizontal touching at end point from left */
	q1.x = -0.5;
	q1.y = 1.0;
	q2.x = 0.0;
	q2.y = 1.0;
	CU_ASSERT( lw_segment_intersects(&p1, &p2, &q1, &q2) == SEG_NO_INTERSECTION );

	/* Q: Horizontal touching at end point from right */
	q1.x = 0.0;
	q1.y = 1.0;
	q2.x = 0.0;
	q2.y = 0.5;
	CU_ASSERT( lw_segment_intersects(&p1, &p2, &q1, &q2) == SEG_COLINEAR );

	/* Q: Horizontal touching at start point from left */
	q1.x = 0.0;
	q1.y = 0.0;
	q2.x = -0.5;
	q2.y = 0.0;
	CU_ASSERT( lw_segment_intersects(&p1, &p2, &q1, &q2) == SEG_CROSS_LEFT );

	/* Q: Horizontal touching at start point from right */
	q1.x = 0.0;
	q1.y = 0.0;
	q2.x = 0.5;
	q2.y = 0.0;
	CU_ASSERT( lw_segment_intersects(&p1, &p2, &q1, &q2) == SEG_CROSS_RIGHT );

}