static LWGEOM* parse_geojson_multilinestring(json_object *geojson, int *hasz, int root_srid) { LWGEOM *geom = NULL; int i, j; json_object* poObjLines = NULL; if (!root_srid) { geom = (LWGEOM *)lwcollection_construct_empty(MULTILINETYPE, root_srid, 1, 0); } else { geom = (LWGEOM *)lwcollection_construct_empty(MULTILINETYPE, -1, 1, 0); } poObjLines = findMemberByName( geojson, "coordinates" ); if ( ! poObjLines ) { geojson_lwerror("Unable to find 'coordinates' in GeoJSON string", 4); return NULL; } if( json_type_array == json_object_get_type( poObjLines ) ) { const int nLines = json_object_array_length( poObjLines ); for( i = 0; i < nLines; ++i) { POINTARRAY *pa = NULL; json_object* poObjLine = NULL; poObjLine = json_object_array_get_idx( poObjLines, i ); pa = ptarray_construct_empty(1, 0, 1); if( json_type_array == json_object_get_type( poObjLine ) ) { const int nPoints = json_object_array_length( poObjLine ); for(j = 0; j < nPoints; ++j) { json_object* coords = NULL; coords = json_object_array_get_idx( poObjLine, j ); parse_geojson_coord(coords, hasz, pa); } geom = (LWGEOM*)lwmline_add_lwline((LWMLINE*)geom, (LWLINE*)lwline_construct(root_srid, NULL, pa)); } } } return geom; }
static LWGEOM* lwline_split_by_point(const LWLINE* lwline_in, const LWPOINT* blade_in) { LWMLINE* out; out = lwmline_construct_empty(lwline_in->srid, FLAGS_GET_Z(lwline_in->flags), FLAGS_GET_M(lwline_in->flags)); if ( lwline_split_by_point_to(lwline_in, blade_in, out) < 2 ) { lwmline_add_lwline(out, lwline_clone_deep(lwline_in)); } /* Turn multiline into collection */ out->type = COLLECTIONTYPE; return (LWGEOM*)out; }
static LWGEOM* lwline_split_by_mpoint(const LWLINE* lwline_in, const LWMPOINT* mp) { LWMLINE* out; int i, j; out = lwmline_construct_empty(lwline_in->srid, FLAGS_GET_Z(lwline_in->flags), FLAGS_GET_M(lwline_in->flags)); lwmline_add_lwline(out, lwline_clone_deep(lwline_in)); for (i=0; i<mp->ngeoms; ++i) { for (j=0; j<out->ngeoms; ++j) { lwline_in = out->geoms[j]; LWPOINT *blade_in = mp->geoms[i]; int ret = lwline_split_by_point_to(lwline_in, blade_in, out); if ( 2 == ret ) { /* the point splits this line, * 2 splits were added to collection. * We'll move the latest added into * the slot of the current one. */ lwline_free(out->geoms[j]); out->geoms[j] = out->geoms[--out->ngeoms]; } } } /* Turn multiline into collection */ out->type = COLLECTIONTYPE; return (LWGEOM*)out; }
int lwline_split_by_point_to(const LWLINE* lwline_in, const LWPOINT* blade_in, LWMLINE* v) { double mindist = -1; POINT4D pt, pt_projected; POINT4D p1, p2; POINTARRAY *ipa = lwline_in->points; POINTARRAY* pa1; POINTARRAY* pa2; int i, nsegs, seg = -1; /* Possible outcomes: * * 1. The point is not on the line or on the boundary * -> Leave collection untouched, return 0 * 2. The point is on the boundary * -> Leave collection untouched, return 1 * 3. The point is in the line * -> Push 2 elements on the collection: * o start_point - cut_point * o cut_point - last_point * -> Return 2 */ getPoint4d_p(blade_in->point, 0, &pt); /* Find closest segment */ getPoint4d_p(ipa, 0, &p1); nsegs = ipa->npoints - 1; for ( i = 0; i < nsegs; i++ ) { getPoint4d_p(ipa, i+1, &p2); double dist; dist = distance2d_pt_seg((POINT2D*)&pt, (POINT2D*)&p1, (POINT2D*)&p2); LWDEBUGF(4, " Distance of point %g %g to segment %g %g, %g %g: %g", pt.x, pt.y, p1.x, p1.y, p2.x, p2.y, dist); if (i==0 || dist < mindist ) { mindist = dist; seg=i; if ( mindist == 0.0 ) break; /* can't be closer than ON line */ } p1 = p2; } LWDEBUGF(3, "Closest segment: %d", seg); LWDEBUGF(3, "mindist: %g", mindist); /* No intersection */ if ( mindist > 0 ) return 0; /* empty or single-point line, intersection on boundary */ if ( seg < 0 ) return 1; /* * We need to project the * point on the closest segment, * to interpolate Z and M if needed */ getPoint4d_p(ipa, seg, &p1); getPoint4d_p(ipa, seg+1, &p2); closest_point_on_segment(&pt, &p1, &p2, &pt_projected); /* But X and Y we want the ones of the input point, * as on some architectures the interpolation math moves the * coordinates (see #3422) */ pt_projected.x = pt.x; pt_projected.y = pt.y; LWDEBUGF(3, "Projected point:(%g %g), seg:%d, p1:(%g %g), p2:(%g %g)", pt_projected.x, pt_projected.y, seg, p1.x, p1.y, p2.x, p2.y); /* When closest point == an endpoint, this is a boundary intersection */ if ( ( (seg == nsegs-1) && p4d_same(&pt_projected, &p2) ) || ( (seg == 0) && p4d_same(&pt_projected, &p1) ) ) { return 1; } /* This is an internal intersection, let's build the two new pointarrays */ pa1 = ptarray_construct_empty(FLAGS_GET_Z(ipa->flags), FLAGS_GET_M(ipa->flags), seg+2); /* TODO: replace with a memcpy ? */ for (i=0; i<=seg; ++i) { getPoint4d_p(ipa, i, &p1); ptarray_append_point(pa1, &p1, LW_FALSE); } ptarray_append_point(pa1, &pt_projected, LW_FALSE); pa2 = ptarray_construct_empty(FLAGS_GET_Z(ipa->flags), FLAGS_GET_M(ipa->flags), ipa->npoints-seg); ptarray_append_point(pa2, &pt_projected, LW_FALSE); /* TODO: replace with a memcpy (if so need to check for duplicated point) ? */ for (i=seg+1; i<ipa->npoints; ++i) { getPoint4d_p(ipa, i, &p1); ptarray_append_point(pa2, &p1, LW_FALSE); } /* NOTE: I've seen empty pointarrays with loc != 0 and loc != 1 */ if ( pa1->npoints == 0 || pa2->npoints == 0 ) { ptarray_free(pa1); ptarray_free(pa2); /* Intersection is on the boundary */ return 1; } lwmline_add_lwline(v, lwline_construct(SRID_UNKNOWN, NULL, pa1)); lwmline_add_lwline(v, lwline_construct(SRID_UNKNOWN, NULL, pa2)); return 2; }
int lwline_split_by_point_to(const LWLINE* lwline_in, const LWPOINT* blade_in, LWMLINE* v) { double loc, dist; POINT4D pt, pt_projected; POINTARRAY* pa1; POINTARRAY* pa2; double vstol; /* vertex snap tolerance */ /* Possible outcomes: * * 1. The point is not on the line or on the boundary * -> Leave collection untouched, return 0 * 2. The point is on the boundary * -> Push 1 element on the collection: * o the original line * -> Return 1 * 3. The point is in the line * -> Push 2 elements on the collection: * o start_point - cut_point * o cut_point - last_point * -> Return 2 */ getPoint4d_p(blade_in->point, 0, &pt); loc = ptarray_locate_point(lwline_in->points, &pt, &dist, &pt_projected); /* lwnotice("Location: %g -- Distance: %g", loc, dist); */ if ( dist > 0 ) /* TODO: accept a tolerance ? */ { /* No intersection */ return 0; } if ( loc == 0 || loc == 1 ) { /* Intersection is on the boundary */ return 1; } /* There is a real intersection, let's get two substrings */ /* Compute vertex snap tolerance based on line length * TODO: take as parameter ? */ vstol = ptarray_length_2d(lwline_in->points) / 1e14; pa1 = ptarray_substring(lwline_in->points, 0, loc, vstol); pa2 = ptarray_substring(lwline_in->points, loc, 1, vstol); /* NOTE: I've seen empty pointarrays with loc != 0 and loc != 1 */ if ( pa1->npoints == 0 || pa2->npoints == 0 ) { ptarray_free(pa1); ptarray_free(pa2); /* Intersection is on the boundary */ return 1; } lwmline_add_lwline(v, lwline_construct(SRID_UNKNOWN, NULL, pa1)); lwmline_add_lwline(v, lwline_construct(SRID_UNKNOWN, NULL, pa2)); return 2; }