static void test_lwline_crossing_long_lines(void) { LWLINE *l51; LWLINE *l52; /* ** More complex test, longer lines and multiple crossings */ /* Vertical line with vertices at y integers */ l51 = (LWLINE*)lwgeom_from_wkt("LINESTRING(0 0, 0 1, 0 2, 0 3, 0 4)", LW_PARSER_CHECK_NONE); /* Two crossings at segment midpoints */ l52 = (LWLINE*)lwgeom_from_wkt("LINESTRING(1 1, -1 1.5, 1 3, 1 4, 1 5)", LW_PARSER_CHECK_NONE); CU_ASSERT( lwline_crossing_direction(l51, l52) == LINE_MULTICROSS_END_SAME_FIRST_LEFT ); lwline_free(l52); /* One crossing at interior vertex */ l52 = (LWLINE*)lwgeom_from_wkt("LINESTRING(1 1, 0 1, -1 1, -1 2, -1 3)", LW_PARSER_CHECK_NONE); CU_ASSERT( lwline_crossing_direction(l51, l52) == LINE_CROSS_LEFT ); lwline_free(l52); /* Two crossings at interior vertices */ l52 = (LWLINE*)lwgeom_from_wkt("LINESTRING(1 1, 0 1, -1 1, 0 3, 1 3)", LW_PARSER_CHECK_NONE); CU_ASSERT( lwline_crossing_direction(l51, l52) == LINE_MULTICROSS_END_SAME_FIRST_LEFT ); lwline_free(l52); /* Two crossings, one at the first vertex on at interior vertex */ l52 = (LWLINE*)lwgeom_from_wkt("LINESTRING(1 0, 0 0, -1 1, 0 3, 1 3)", LW_PARSER_CHECK_NONE); CU_ASSERT( lwline_crossing_direction(l51, l52) == LINE_MULTICROSS_END_SAME_FIRST_LEFT ); lwline_free(l52); /* Two crossings, one at the first vertex on the next interior vertex */ l52 = (LWLINE*)lwgeom_from_wkt("LINESTRING(1 0, 0 0, -1 1, 0 1, 1 2)", LW_PARSER_CHECK_NONE); CU_ASSERT( lwline_crossing_direction(l51, l52) == LINE_MULTICROSS_END_SAME_FIRST_LEFT ); lwline_free(l52); /* Three crossings, two at midpoints, one at vertex */ l52 = (LWLINE*)lwgeom_from_wkt("LINESTRING(0.5 1, -1 0.5, 1 2, -1 2, -1 3)", LW_PARSER_CHECK_NONE); CU_ASSERT( lwline_crossing_direction(l51, l52) == LINE_MULTICROSS_END_LEFT ); lwline_free(l52); /* One mid-point co-linear crossing */ l52 = (LWLINE*)lwgeom_from_wkt("LINESTRING(1 1, 0 1.5, 0 2.5, -1 3, -1 4)", LW_PARSER_CHECK_NONE); CU_ASSERT( lwline_crossing_direction(l51, l52) == LINE_CROSS_LEFT ); lwline_free(l52); /* One on-vertices co-linear crossing */ l52 = (LWLINE*)lwgeom_from_wkt("LINESTRING(1 1, 0 1, 0 2, -1 4, -1 4)", LW_PARSER_CHECK_NONE); CU_ASSERT( lwline_crossing_direction(l51, l52) == LINE_CROSS_LEFT ); lwline_free(l52); /* No crossing, but end on a co-linearity. */ l52 = (LWLINE*)lwgeom_from_wkt("LINESTRING(1 1, 1 2, 1 3, 0 3, 0 4)", LW_PARSER_CHECK_NONE); CU_ASSERT( lwline_crossing_direction(l51, l52) == LINE_NO_CROSS ); lwline_free(l52); lwline_free(l51); }
Datum ST_LineCrossingDirection(PG_FUNCTION_ARGS) { int type1, type2, rv; LWLINE *l1 = NULL; LWLINE *l2 = NULL; GSERIALIZED *geom1 = (GSERIALIZED *)PG_DETOAST_DATUM(PG_GETARG_DATUM(0)); GSERIALIZED *geom2 = (GSERIALIZED *)PG_DETOAST_DATUM(PG_GETARG_DATUM(1)); error_if_srid_mismatch(gserialized_get_srid(geom1), gserialized_get_srid(geom2)); type1 = gserialized_get_type(geom1); type2 = gserialized_get_type(geom2); if ( type1 != LINETYPE || type2 != LINETYPE ) { elog(ERROR,"This function only accepts LINESTRING as arguments."); PG_RETURN_NULL(); } l1 = lwgeom_as_lwline(lwgeom_from_gserialized(geom1)); l2 = lwgeom_as_lwline(lwgeom_from_gserialized(geom2)); rv = lwline_crossing_direction(l1, l2); PG_FREE_IF_COPY(geom1, 0); PG_FREE_IF_COPY(geom2, 1); PG_RETURN_INT32(rv); }
static void test_lwline_crossing_bugs(void) { LWLINE *l1; LWLINE *l2; l1 = (LWLINE*)lwgeom_from_wkt("LINESTRING(2.99 90.16,71 74,20 140,171 154)", LW_PARSER_CHECK_NONE); l2 = (LWLINE*)lwgeom_from_wkt("LINESTRING(25 169,89 114,40 70,86 43)", LW_PARSER_CHECK_NONE); CU_ASSERT( lwline_crossing_direction(l1, l2) == LINE_MULTICROSS_END_RIGHT ); lwline_free(l1); lwline_free(l2); }
static void test_lwline_crossing_short_lines(void) { POINT4D p; /* ** Simple test, two two-point lines */ /* Vertical line from 0,0 to 1,1 */ p.x = 0.0; p.y = 0.0; ptarray_set_point4d(pa21, 0, &p); p.y = 1.0; ptarray_set_point4d(pa21, 1, &p); /* Horizontal, crossing mid-segment */ p.x = -0.5; p.y = 0.5; ptarray_set_point4d(pa22, 0, &p); p.x = 0.5; ptarray_set_point4d(pa22, 1, &p); CU_ASSERT( lwline_crossing_direction(l21, l22) == LINE_CROSS_RIGHT ); /* Horizontal, crossing at top end vertex (end crossings don't count) */ p.x = -0.5; p.y = 1.0; ptarray_set_point4d(pa22, 0, &p); p.x = 0.5; ptarray_set_point4d(pa22, 1, &p); CU_ASSERT( lwline_crossing_direction(l21, l22) == LINE_NO_CROSS ); /* Horizontal, crossing at bottom end vertex */ p.x = -0.5; p.y = 0.0; ptarray_set_point4d(pa22, 0, &p); p.x = 0.5; ptarray_set_point4d(pa22, 1, &p); CU_ASSERT( lwline_crossing_direction(l21, l22) == LINE_CROSS_RIGHT ); /* Horizontal, no crossing */ p.x = -0.5; p.y = 2.0; ptarray_set_point4d(pa22, 0, &p); p.x = 0.5; ptarray_set_point4d(pa22, 1, &p); CU_ASSERT( lwline_crossing_direction(l21, l22) == LINE_NO_CROSS ); /* Vertical, no crossing */ p.x = -0.5; p.y = 0.0; ptarray_set_point4d(pa22, 0, &p); p.y = 1.0; ptarray_set_point4d(pa22, 1, &p); CU_ASSERT( lwline_crossing_direction(l21, l22) == LINE_NO_CROSS ); }