static void test_geos_subdivide(void) { #if POSTGIS_GEOS_VERSION < 35 // printf("%d\n", POSTGIS_GEOS_VERSION); return; #else char *ewkt = "MULTILINESTRING((0 0, 0 100))"; char *out_ewkt; LWGEOM *geom1 = lwgeom_from_wkt(ewkt, LW_PARSER_CHECK_NONE); LWGEOM *geom2 = lwgeom_segmentize2d(geom1, 1.0); LWCOLLECTION *geom3 = lwgeom_subdivide(geom2, 80); out_ewkt = lwgeom_to_ewkt((LWGEOM*)geom3); // printf("\n--------\n%s\n--------\n", out_ewkt); CU_ASSERT_EQUAL(2, geom3->ngeoms); lwfree(out_ewkt); lwcollection_free(geom3); geom3 = lwgeom_subdivide(geom2, 20); out_ewkt = lwgeom_to_ewkt((LWGEOM*)geom3); // printf("\n--------\n%s\n--------\n", out_ewkt); CU_ASSERT_EQUAL(8, geom3->ngeoms); lwfree(out_ewkt); lwcollection_free(geom3); lwgeom_free(geom2); lwgeom_free(geom1); #endif }
static void test_lwline_clip_big(void) { POINTARRAY *pa = ptarray_construct(1, 0, 3); LWLINE *line = lwline_construct(SRID_UNKNOWN, NULL, pa); LWCOLLECTION *c; char *ewkt; POINT4D p; p.x = 0.0; p.y = 0.0; p.z = 0.0; ptarray_set_point4d(pa, 0, &p); p.x = 1.0; p.y = 1.0; p.z = 1.0; ptarray_set_point4d(pa, 1, &p); p.x = 2.0; p.y = 2.0; p.z = 2.0; ptarray_set_point4d(pa, 2, &p); c = lwline_clip_to_ordinate_range(line, 'Z', 0.5, 1.5); ewkt = lwgeom_to_ewkt((LWGEOM*)c); //printf("c = %s\n", ewkt); CU_ASSERT_STRING_EQUAL(ewkt, "MULTILINESTRING((0.5 0.5 0.5,1 1 1,1.5 1.5 1.5))" ); lwfree(ewkt); lwcollection_free(c); lwline_free(line); }
void lwgeom_free(LWGEOM *lwgeom) { /* There's nothing here to free... */ if( ! lwgeom ) return; LWDEBUGF(5,"freeing a %s",lwtype_name(lwgeom->type)); switch (lwgeom->type) { case POINTTYPE: lwpoint_free((LWPOINT *)lwgeom); break; case LINETYPE: lwline_free((LWLINE *)lwgeom); break; case POLYGONTYPE: lwpoly_free((LWPOLY *)lwgeom); break; case CIRCSTRINGTYPE: lwcircstring_free((LWCIRCSTRING *)lwgeom); break; case TRIANGLETYPE: lwtriangle_free((LWTRIANGLE *)lwgeom); break; case MULTIPOINTTYPE: lwmpoint_free((LWMPOINT *)lwgeom); break; case MULTILINETYPE: lwmline_free((LWMLINE *)lwgeom); break; case MULTIPOLYGONTYPE: lwmpoly_free((LWMPOLY *)lwgeom); break; case POLYHEDRALSURFACETYPE: lwpsurface_free((LWPSURFACE *)lwgeom); break; case TINTYPE: lwtin_free((LWTIN *)lwgeom); break; case CURVEPOLYTYPE: case COMPOUNDTYPE: case MULTICURVETYPE: case MULTISURFACETYPE: case COLLECTIONTYPE: lwcollection_free((LWCOLLECTION *)lwgeom); break; default: lwerror("lwgeom_free called with unknown type (%d) %s", lwgeom->type, lwtype_name(lwgeom->type)); } return; }
/* takes a GEOMETRY and returns an X3D representation */ extern char * lwgeom_to_x3d3(const LWGEOM *geom, char *srs, int precision, int opts, const char *defid) { int type = geom->type; switch (type) { case POINTTYPE: return asx3d3_point((LWPOINT*)geom, srs, precision, opts, defid); case LINETYPE: return asx3d3_line((LWLINE*)geom, srs, precision, opts, defid); case POLYGONTYPE: { /** We might change this later, but putting a polygon in an indexed face set * seems like the simplest way to go so treat just like a mulitpolygon */ LWCOLLECTION *tmp = (LWCOLLECTION*)lwgeom_as_multi(geom); char *ret = asx3d3_multi(tmp, srs, precision, opts, defid); lwcollection_free(tmp); return ret; } case TRIANGLETYPE: return asx3d3_triangle((LWTRIANGLE*)geom, srs, precision, opts, defid); case MULTIPOINTTYPE: case MULTILINETYPE: case MULTIPOLYGONTYPE: return asx3d3_multi((LWCOLLECTION*)geom, srs, precision, opts, defid); case POLYHEDRALSURFACETYPE: return asx3d3_psurface((LWPSURFACE*)geom, srs, precision, opts, defid); case TINTYPE: return asx3d3_tin((LWTIN*)geom, srs, precision, opts, defid); case COLLECTIONTYPE: return asx3d3_collection((LWCOLLECTION*)geom, srs, precision, opts, defid); default: lwerror("lwgeom_to_x3d3: '%s' geometry type not supported", lwtype_name(type)); return NULL; } }
Datum LWGEOM_geometryn_collection(PG_FUNCTION_ARGS) { GSERIALIZED *geom = (GSERIALIZED *)PG_DETOAST_DATUM(PG_GETARG_DATUM(0)); GSERIALIZED *result; int type = gserialized_get_type(geom); int32 idx; LWCOLLECTION *coll; LWGEOM *subgeom; POSTGIS_DEBUG(2, "LWGEOM_geometryn_collection called."); /* elog(NOTICE, "GeometryN called"); */ idx = PG_GETARG_INT32(1); idx -= 1; /* index is 1-based */ /* call is valid on multi* geoms only */ if (type==POINTTYPE || type==LINETYPE || type==CIRCSTRINGTYPE || type==COMPOUNDTYPE || type==POLYGONTYPE || type==CURVEPOLYTYPE || type==TRIANGLETYPE) { if ( idx == 0 ) PG_RETURN_POINTER(geom); PG_RETURN_NULL(); } coll = lwgeom_as_lwcollection(lwgeom_from_gserialized(geom)); if ( idx < 0 ) PG_RETURN_NULL(); if ( idx >= coll->ngeoms ) PG_RETURN_NULL(); subgeom = coll->geoms[idx]; subgeom->srid = coll->srid; /* COMPUTE_BBOX==TAINTING */ if ( coll->bbox ) lwgeom_add_bbox(subgeom); result = geometry_serialize(subgeom); lwcollection_free(coll); PG_FREE_IF_COPY(geom, 0); PG_RETURN_POINTER(result); }
static LWGEOM* lwcollection_homogenize(const LWCOLLECTION *col) { int i; int ntypes = 0; int type = 0; LWGEOM *outgeom = NULL; HomogenizeBuffer buffer; /* Sort all the parts into a buffer */ init_homogenizebuffer(&buffer); lwcollection_build_buffer(col, &buffer); /* Check for homogeneity */ for ( i = 0; i < NUMTYPES; i++ ) { if ( buffer.cnt[i] > 0 ) { ntypes++; type = i; } } /* No types? Huh. Return empty. */ if ( ntypes == 0 ) { LWCOLLECTION *outcol; outcol = lwcollection_construct_empty(COLLECTIONTYPE, col->srid, FLAGS_GET_Z(col->flags), FLAGS_GET_M(col->flags)); outgeom = lwcollection_as_lwgeom(outcol); } /* One type, return homogeneous collection */ else if ( ntypes == 1 ) { LWCOLLECTION *outcol; outcol = buffer.buf[type]; if ( outcol->ngeoms == 1 ) { outgeom = outcol->geoms[0]; outcol->ngeoms=0; lwcollection_free(outcol); } else { outgeom = lwcollection_as_lwgeom(outcol); } outgeom->srid = col->srid; } /* Bah, more than out type, return anonymous collection */ else if ( ntypes > 1 ) { int j; LWCOLLECTION *outcol; outcol = lwcollection_construct_empty(COLLECTIONTYPE, col->srid, FLAGS_GET_Z(col->flags), FLAGS_GET_M(col->flags)); for ( j = 0; j < NUMTYPES; j++ ) { if ( buffer.buf[j] ) { LWCOLLECTION *bcol = buffer.buf[j]; if ( bcol->ngeoms == 1 ) { lwcollection_add_lwgeom(outcol, bcol->geoms[0]); bcol->ngeoms=0; lwcollection_free(bcol); } else { lwcollection_add_lwgeom(outcol, lwcollection_as_lwgeom(bcol)); } } } outgeom = lwcollection_as_lwgeom(outcol); } return outgeom; }
static void test_lwline_split_by_point_to(void) { #if POSTGIS_GEOS_VERSION >= 33 LWLINE *line; LWPOINT *point; LWMLINE *coll; int ret; /* Because i don't trust that much prior tests... ;) */ cu_error_msg_reset(); coll = lwmline_construct_empty(SRID_UNKNOWN, 0, 0); CU_ASSERT_EQUAL(coll->ngeoms, 0); line = lwgeom_as_lwline(lwgeom_from_wkt("LINESTRING(0 0,5 5, 10 0)", LW_PARSER_CHECK_NONE)); CU_ASSERT(line != NULL); point = lwgeom_as_lwpoint(lwgeom_from_wkt( "POINT(0 0)", LW_PARSER_CHECK_NONE)); ret = lwline_split_by_point_to(line, point, coll); CU_ASSERT_EQUAL(ret, 1); CU_ASSERT_EQUAL(coll->ngeoms, 0); lwpoint_free(point); point = lwgeom_as_lwpoint(lwgeom_from_wkt( "POINT(10 0)", LW_PARSER_CHECK_NONE)); ret = lwline_split_by_point_to(line, point, coll); CU_ASSERT_EQUAL(ret, 1); CU_ASSERT_EQUAL(coll->ngeoms, 0); lwpoint_free(point); point = lwgeom_as_lwpoint(lwgeom_from_wkt( "POINT(5 0)", LW_PARSER_CHECK_NONE)); ret = lwline_split_by_point_to(line, point, coll); CU_ASSERT_EQUAL(ret, 0); CU_ASSERT_EQUAL(coll->ngeoms, 0); lwpoint_free(point); point = lwgeom_as_lwpoint(lwgeom_from_wkt( "POINT(5 5)", LW_PARSER_CHECK_NONE)); ret = lwline_split_by_point_to(line, point, coll); CU_ASSERT_EQUAL(ret, 2); CU_ASSERT_EQUAL(coll->ngeoms, 2); lwpoint_free(point); point = lwgeom_as_lwpoint(lwgeom_from_wkt( "POINT(2 2)", LW_PARSER_CHECK_NONE)); ret = lwline_split_by_point_to(line, point, coll); CU_ASSERT_EQUAL(ret, 2); CU_ASSERT_EQUAL(coll->ngeoms, 4); lwpoint_free(point); lwcollection_free((LWCOLLECTION*)coll); lwline_free(line); #endif /* POSTGIS_GEOS_VERSION >= 33 */ }
LWGEOM* lwgeom_node(const LWGEOM* lwgeom_in) { #if POSTGIS_GEOS_VERSION < 33 lwerror("The GEOS version this postgis binary " "was compiled against (%d) doesn't support " "'GEOSUnaryUnion' function (3.3.0+ required)", POSTGIS_GEOS_VERSION); return NULL; #else /* POSTGIS_GEOS_VERSION >= 33 */ GEOSGeometry *g1, *gu, *gm; LWGEOM *ep, *lines; LWCOLLECTION *col, *tc; int pn, ln, np, nl; if ( lwgeom_dimension(lwgeom_in) != 1 ) { lwerror("Noding geometries of dimension != 1 is unsupported"); return NULL; } initGEOS(lwgeom_geos_error, lwgeom_geos_error); g1 = LWGEOM2GEOS(lwgeom_in); if ( ! g1 ) { lwerror("LWGEOM2GEOS: %s", lwgeom_geos_errmsg); return NULL; } ep = lwgeom_extract_unique_endpoints(lwgeom_in); if ( ! ep ) { GEOSGeom_destroy(g1); lwerror("Error extracting unique endpoints from input"); return NULL; } /* Unary union input to fully node */ gu = GEOSUnaryUnion(g1); GEOSGeom_destroy(g1); if ( ! gu ) { lwgeom_free(ep); lwerror("GEOSUnaryUnion: %s", lwgeom_geos_errmsg); return NULL; } /* Linemerge (in case of overlaps) */ gm = GEOSLineMerge(gu); GEOSGeom_destroy(gu); if ( ! gm ) { lwgeom_free(ep); lwerror("GEOSLineMerge: %s", lwgeom_geos_errmsg); return NULL; } lines = GEOS2LWGEOM(gm, FLAGS_GET_Z(lwgeom_in->flags)); GEOSGeom_destroy(gm); if ( ! lines ) { lwgeom_free(ep); lwerror("Error during GEOS2LWGEOM"); return NULL; } /* * Reintroduce endpoints from input, using split-line-by-point. * Note that by now we can be sure that each point splits at * most _one_ segment as any point shared by multiple segments * would already be a node. Also we can be sure that any of * the segments endpoints won't split any other segment. * We can use the above 2 assertions to early exit the loop. */ col = lwcollection_construct_empty(MULTILINETYPE, lwgeom_in->srid, FLAGS_GET_Z(lwgeom_in->flags), FLAGS_GET_M(lwgeom_in->flags)); np = lwgeom_ngeoms(ep); for (pn=0; pn<np; ++pn) { /* for each point */ const LWPOINT* p = (LWPOINT*)lwgeom_subgeom(ep, pn); nl = lwgeom_ngeoms(lines); for (ln=0; ln<nl; ++ln) { /* for each line */ const LWLINE* l = (LWLINE*)lwgeom_subgeom(lines, ln); int s = lwline_split_by_point_to(l, p, (LWMLINE*)col); if ( ! s ) continue; /* not on this line */ if ( s == 1 ) { /* found on this line, but not splitting it */ break; } /* splits this line */ /* replace this line with the two splits */ if ( lwgeom_is_collection(lines) ) { tc = (LWCOLLECTION*)lines; lwcollection_reserve(tc, nl + 1); while (nl > ln+1) { tc->geoms[nl] = tc->geoms[nl-1]; --nl; } lwgeom_free(tc->geoms[ln]); tc->geoms[ln] = col->geoms[0]; tc->geoms[ln+1] = col->geoms[1]; tc->ngeoms++; } else { lwgeom_free(lines); /* transfer ownership rather than cloning */ lines = (LWGEOM*)lwcollection_clone_deep(col); assert(col->ngeoms == 2); lwgeom_free(col->geoms[0]); lwgeom_free(col->geoms[1]); } /* reset the vector */ assert(col->ngeoms == 2); col->ngeoms = 0; break; } } lwgeom_free(ep); lwcollection_free(col); lines->srid = lwgeom_in->srid; return (LWGEOM*)lines; #endif /* POSTGIS_GEOS_VERSION >= 33 */ }
LWGEOM* pta_unstroke(const POINTARRAY *points, int type, int srid) { int i = 0, j, k; POINT4D a1, a2, a3, b; POINT4D first, center; char *edges_in_arcs; int found_arc = LW_FALSE; int current_arc = 1; int num_edges; int edge_type; /* non-zero if edge is part of an arc */ int start, end; LWCOLLECTION *outcol; /* Minimum number of edges, per quadrant, required to define an arc */ const unsigned int min_quad_edges = 2; /* Die on null input */ if ( ! points ) lwerror("pta_unstroke called with null pointarray"); /* Null on empty input? */ if ( points->npoints == 0 ) return NULL; /* We can't desegmentize anything shorter than four points */ if ( points->npoints < 4 ) { /* Return a linestring here*/ lwerror("pta_unstroke needs implementation for npoints < 4"); } /* Allocate our result array of vertices that are part of arcs */ num_edges = points->npoints - 1; edges_in_arcs = lwalloc(num_edges + 1); memset(edges_in_arcs, 0, num_edges + 1); /* We make a candidate arc of the first two edges, */ /* And then see if the next edge follows it */ while( i < num_edges-2 ) { unsigned int arc_edges; double num_quadrants; double angle; found_arc = LW_FALSE; /* Make candidate arc */ getPoint4d_p(points, i , &a1); getPoint4d_p(points, i+1, &a2); getPoint4d_p(points, i+2, &a3); memcpy(&first, &a1, sizeof(POINT4D)); for( j = i+3; j < num_edges+1; j++ ) { LWDEBUGF(4, "i=%d, j=%d", i, j); getPoint4d_p(points, j, &b); /* Does this point fall on our candidate arc? */ if ( pt_continues_arc(&a1, &a2, &a3, &b) ) { /* Yes. Mark this edge and the two preceding it as arc components */ LWDEBUGF(4, "pt_continues_arc #%d", current_arc); found_arc = LW_TRUE; for ( k = j-1; k > j-4; k-- ) edges_in_arcs[k] = current_arc; } else { /* No. So we're done with this candidate arc */ LWDEBUG(4, "pt_continues_arc = false"); current_arc++; break; } memcpy(&a1, &a2, sizeof(POINT4D)); memcpy(&a2, &a3, sizeof(POINT4D)); memcpy(&a3, &b, sizeof(POINT4D)); } /* Jump past all the edges that were added to the arc */ if ( found_arc ) { /* Check if an arc was composed by enough edges to be * really considered an arc * See http://trac.osgeo.org/postgis/ticket/2420 */ arc_edges = j - 1 - i; LWDEBUGF(4, "arc defined by %d edges found", arc_edges); if ( first.x == b.x && first.y == b.y ) { LWDEBUG(4, "arc is a circle"); num_quadrants = 4; } else { lw_arc_center((POINT2D*)&first, (POINT2D*)&b, (POINT2D*)&a1, (POINT2D*)¢er); angle = lw_arc_angle((POINT2D*)&first, (POINT2D*)¢er, (POINT2D*)&b); int p2_side = lw_segment_side((POINT2D*)&first, (POINT2D*)&a1, (POINT2D*)&b); if ( p2_side >= 0 ) angle = -angle; if ( angle < 0 ) angle = 2 * M_PI + angle; num_quadrants = ( 4 * angle ) / ( 2 * M_PI ); LWDEBUGF(4, "arc angle (%g %g, %g %g, %g %g) is %g (side is %d), quandrants:%g", first.x, first.y, center.x, center.y, b.x, b.y, angle, p2_side, num_quadrants); } /* a1 is first point, b is last point */ if ( arc_edges < min_quad_edges * num_quadrants ) { LWDEBUGF(4, "Not enough edges for a %g quadrants arc, %g needed", num_quadrants, min_quad_edges * num_quadrants); for ( k = j-1; k >= i; k-- ) edges_in_arcs[k] = 0; } i = j-1; } else { /* Mark this edge as a linear edge */ edges_in_arcs[i] = 0; i = i+1; } } #if POSTGIS_DEBUG_LEVEL > 3 { char *edgestr = lwalloc(num_edges+1); for ( i = 0; i < num_edges; i++ ) { if ( edges_in_arcs[i] ) edgestr[i] = 48 + edges_in_arcs[i]; else edgestr[i] = '.'; } edgestr[num_edges] = 0; LWDEBUGF(3, "edge pattern %s", edgestr); lwfree(edgestr); } #endif start = 0; edge_type = edges_in_arcs[0]; outcol = lwcollection_construct_empty(COMPOUNDTYPE, srid, ptarray_has_z(points), ptarray_has_m(points)); for( i = 1; i < num_edges; i++ ) { if( edge_type != edges_in_arcs[i] ) { end = i - 1; lwcollection_add_lwgeom(outcol, geom_from_pa(points, srid, edge_type, start, end)); start = i; edge_type = edges_in_arcs[i]; } } lwfree(edges_in_arcs); /* not needed anymore */ /* Roll out last item */ end = num_edges - 1; lwcollection_add_lwgeom(outcol, geom_from_pa(points, srid, edge_type, start, end)); /* Strip down to singleton if only one entry */ if ( outcol->ngeoms == 1 ) { LWGEOM *outgeom = outcol->geoms[0]; outcol->ngeoms = 0; lwcollection_free(outcol); return outgeom; } return lwcollection_as_lwgeom(outcol); }
static void test_lwmline_clip(void) { LWCOLLECTION *c; char *ewkt; LWMLINE *mline = NULL; LWLINE *line = NULL; /* ** Set up the input line. Trivial one-member case. */ mline = (LWMLINE*)lwgeom_from_wkt("MULTILINESTRING((0 0,0 1,0 2,0 3,0 4))", LW_PARSER_CHECK_NONE); /* Clip in the middle, mid-range. */ c = lwmline_clip_to_ordinate_range(mline, 'Y', 1.5, 2.5); ewkt = lwgeom_to_ewkt((LWGEOM*)c); //printf("c = %s\n", ewkt); CU_ASSERT_STRING_EQUAL(ewkt, "MULTILINESTRING((0 1.5,0 2,0 2.5))"); lwfree(ewkt); lwcollection_free(c); lwmline_free(mline); /* ** Set up the input line. Two-member case. */ mline = (LWMLINE*)lwgeom_from_wkt("MULTILINESTRING((1 0,1 1,1 2,1 3,1 4), (0 0,0 1,0 2,0 3,0 4))", LW_PARSER_CHECK_NONE); /* Clip off the top. */ c = lwmline_clip_to_ordinate_range(mline, 'Y', 3.5, 5.5); ewkt = lwgeom_to_ewkt((LWGEOM*)c); //printf("c = %s\n", ewkt); CU_ASSERT_STRING_EQUAL(ewkt, "MULTILINESTRING((1 3.5,1 4),(0 3.5,0 4))"); lwfree(ewkt); lwcollection_free(c); lwmline_free(mline); /* ** Set up staggered input line to create multi-type output. */ mline = (LWMLINE*)lwgeom_from_wkt("MULTILINESTRING((1 0,1 -1,1 -2,1 -3,1 -4), (0 0,0 1,0 2,0 3,0 4))", LW_PARSER_CHECK_NONE); /* Clip from 0 upwards.. */ c = lwmline_clip_to_ordinate_range(mline, 'Y', 0.0, 2.5); ewkt = lwgeom_to_ewkt((LWGEOM*)c); //printf("c = %s\n", ewkt); CU_ASSERT_STRING_EQUAL(ewkt, "GEOMETRYCOLLECTION(POINT(1 0),LINESTRING(0 0,0 1,0 2,0 2.5))"); lwfree(ewkt); lwcollection_free(c); lwmline_free(mline); /* ** Set up input line from MAC */ line = (LWLINE*)lwgeom_from_wkt("LINESTRING(0 0 0 0,1 1 1 1,2 2 2 2,3 3 3 3,4 4 4 4,3 3 3 5,2 2 2 6,1 1 1 7,0 0 0 8)", LW_PARSER_CHECK_NONE); /* Clip from 3 to 3.5 */ c = lwline_clip_to_ordinate_range(line, 'Z', 3.0, 3.5); ewkt = lwgeom_to_ewkt((LWGEOM*)c); //printf("c = %s\n", ewkt); CU_ASSERT_STRING_EQUAL(ewkt, "MULTILINESTRING((3 3 3 3,3.5 3.5 3.5 3.5),(3.5 3.5 3.5 4.5,3 3 3 5))"); lwfree(ewkt); lwcollection_free(c); /* Clip from 2 to 3.5 */ c = lwline_clip_to_ordinate_range(line, 'Z', 2.0, 3.5); ewkt = lwgeom_to_ewkt((LWGEOM*)c); //printf("c = %s\n", ewkt); CU_ASSERT_STRING_EQUAL(ewkt, "MULTILINESTRING((2 2 2 2,3 3 3 3,3.5 3.5 3.5 3.5),(3.5 3.5 3.5 4.5,3 3 3 5,2 2 2 6))"); lwfree(ewkt); lwcollection_free(c); /* Clip from 3 to 4 */ c = lwline_clip_to_ordinate_range(line, 'Z', 3.0, 4.0); ewkt = lwgeom_to_ewkt((LWGEOM*)c); //printf("c = %s\n", ewkt); CU_ASSERT_STRING_EQUAL(ewkt, "MULTILINESTRING((3 3 3 3,4 4 4 4,3 3 3 5))"); lwfree(ewkt); lwcollection_free(c); /* Clip from 2 to 3 */ c = lwline_clip_to_ordinate_range(line, 'Z', 2.0, 3.0); ewkt = lwgeom_to_ewkt((LWGEOM*)c); //printf("c = %s\n", ewkt); CU_ASSERT_STRING_EQUAL(ewkt, "MULTILINESTRING((2 2 2 2,3 3 3 3),(3 3 3 5,2 2 2 6))"); lwfree(ewkt); lwcollection_free(c); lwline_free(line); }
static void test_lwline_clip(void) { LWCOLLECTION *c; LWLINE *line = NULL; LWLINE *l51 = NULL; char *ewkt; /* 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); /* Clip in the middle, mid-range. */ c = lwline_clip_to_ordinate_range(l51, 'Y', 1.5, 2.5); ewkt = lwgeom_to_ewkt((LWGEOM*)c); //printf("c = %s\n", ewkt); CU_ASSERT_STRING_EQUAL(ewkt, "MULTILINESTRING((0 1.5,0 2,0 2.5))"); lwfree(ewkt); lwcollection_free(c); /* Clip off the top. */ c = lwline_clip_to_ordinate_range(l51, 'Y', 3.5, 5.5); ewkt = lwgeom_to_ewkt((LWGEOM*)c); //printf("c = %s\n", ewkt); CU_ASSERT_STRING_EQUAL(ewkt, "MULTILINESTRING((0 3.5,0 4))"); lwfree(ewkt); lwcollection_free(c); /* Clip off the bottom. */ c = lwline_clip_to_ordinate_range(l51, 'Y', -1.5, 2.5); ewkt = lwgeom_to_ewkt((LWGEOM*)c); //printf("c = %s\n", ewkt); CU_ASSERT_STRING_EQUAL(ewkt, "MULTILINESTRING((0 0,0 1,0 2,0 2.5))" ); lwfree(ewkt); lwcollection_free(c); /* Range holds entire object. */ c = lwline_clip_to_ordinate_range(l51, 'Y', -1.5, 5.5); ewkt = lwgeom_to_ewkt((LWGEOM*)c); //printf("c = %s\n", ewkt); CU_ASSERT_STRING_EQUAL(ewkt, "MULTILINESTRING((0 0,0 1,0 2,0 3,0 4))" ); lwfree(ewkt); lwcollection_free(c); /* Clip on vertices. */ c = lwline_clip_to_ordinate_range(l51, 'Y', 1.0, 2.0); ewkt = lwgeom_to_ewkt((LWGEOM*)c); //printf("c = %s\n", ewkt); CU_ASSERT_STRING_EQUAL(ewkt, "MULTILINESTRING((0 1,0 2))" ); lwfree(ewkt); lwcollection_free(c); /* Clip on vertices off the bottom. */ c = lwline_clip_to_ordinate_range(l51, 'Y', -1.0, 2.0); ewkt = lwgeom_to_ewkt((LWGEOM*)c); //printf("c = %s\n", ewkt); CU_ASSERT_STRING_EQUAL(ewkt, "MULTILINESTRING((0 0,0 1,0 2))" ); lwfree(ewkt); lwcollection_free(c); /* Clip on top. */ c = lwline_clip_to_ordinate_range(l51, 'Y', -1.0, 0.0); ewkt = lwgeom_to_ewkt((LWGEOM*)c); //printf("c = %s\n", ewkt); CU_ASSERT_STRING_EQUAL(ewkt, "GEOMETRYCOLLECTION(POINT(0 0))" ); lwfree(ewkt); lwcollection_free(c); /* ST_LocateBetweenElevations(ST_GeomFromEWKT('LINESTRING(1 2 3, 4 5 6, 6 6 6, 1 1 1)'), 1, 2)) */ line = (LWLINE*)lwgeom_from_wkt("LINESTRING(1 2 3, 4 5 6, 6 6 6, 1 1 1)", LW_PARSER_CHECK_NONE); c = lwline_clip_to_ordinate_range(line, 'Z', 1.0, 2.0); ewkt = lwgeom_to_ewkt((LWGEOM*)c); CU_ASSERT_STRING_EQUAL(ewkt, "MULTILINESTRING((2 2 2,1 1 1))" ); lwfree(ewkt); lwcollection_free(c); lwline_free(line); /* ST_LocateBetweenElevations('LINESTRING(1 2 3, 4 5 6, 6 6 6, 1 1 1)', 1, 2)) */ line = (LWLINE*)lwgeom_from_wkt("LINESTRING(1 2 3, 4 5 6, 6 6 6, 1 1 1)", LW_PARSER_CHECK_NONE); c = lwline_clip_to_ordinate_range(line, 'Z', 1.0, 2.0); ewkt = lwgeom_to_ewkt((LWGEOM*)c); //printf("a = %s\n", ewkt); CU_ASSERT_STRING_EQUAL(ewkt, "MULTILINESTRING((2 2 2,1 1 1))" ); lwfree(ewkt); lwcollection_free(c); lwline_free(line); /* ST_LocateBetweenElevations('LINESTRING(1 2 3, 4 5 6, 6 6 6, 1 1 1)', 1, 1)) */ line = (LWLINE*)lwgeom_from_wkt("LINESTRING(1 2 3, 4 5 6, 6 6 6, 1 1 1)", LW_PARSER_CHECK_NONE); c = lwline_clip_to_ordinate_range(line, 'Z', 1.0, 1.0); ewkt = lwgeom_to_ewkt((LWGEOM*)c); //printf("b = %s\n", ewkt); CU_ASSERT_STRING_EQUAL(ewkt, "GEOMETRYCOLLECTION(POINT(1 1 1))" ); lwfree(ewkt); lwcollection_free(c); lwline_free(line); /* ST_LocateBetweenElevations('LINESTRING(1 1 1, 1 2 2)', 1,1) */ line = (LWLINE*)lwgeom_from_wkt("LINESTRING(1 1 1, 1 2 2)", LW_PARSER_CHECK_NONE); c = lwline_clip_to_ordinate_range(line, 'Z', 1.0, 1.0); ewkt = lwgeom_to_ewkt((LWGEOM*)c); //printf("c = %s\n", ewkt); CU_ASSERT_STRING_EQUAL(ewkt, "GEOMETRYCOLLECTION(POINT(1 1 1))" ); lwfree(ewkt); lwcollection_free(c); lwline_free(line); lwline_free(l51); }