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

◆ lwgeom_node()

LWGEOM * lwgeom_node ( const LWGEOM lwgeom_in)
extern

Definition at line 130 of file lwgeom_geos_node.c.

131{
132 GEOSGeometry *g1, *gn, *gm;
133 LWGEOM *ep, *lines;
134 LWCOLLECTION *col, *tc;
135 int pn, ln, np, nl;
136
137 if ( lwgeom_dimension(lwgeom_in) != 1 ) {
138 lwerror("Noding geometries of dimension != 1 is unsupported");
139 return NULL;
140 }
141
143 g1 = LWGEOM2GEOS(lwgeom_in, 1);
144 if ( ! g1 ) {
145 lwerror("LWGEOM2GEOS: %s", lwgeom_geos_errmsg);
146 return NULL;
147 }
148
149 ep = lwgeom_extract_unique_endpoints(lwgeom_in);
150 if ( ! ep ) {
151 GEOSGeom_destroy(g1);
152 lwerror("Error extracting unique endpoints from input");
153 return NULL;
154 }
155
156 gn = GEOSNode(g1);
157 GEOSGeom_destroy(g1);
158 if ( ! gn ) {
159 lwgeom_free(ep);
160 lwerror("GEOSNode: %s", lwgeom_geos_errmsg);
161 return NULL;
162 }
163
164 gm = GEOSLineMerge(gn);
165 GEOSGeom_destroy(gn);
166 if ( ! gm ) {
167 lwgeom_free(ep);
168 lwerror("GEOSLineMerge: %s", lwgeom_geos_errmsg);
169 return NULL;
170 }
171
172 lines = GEOS2LWGEOM(gm, FLAGS_GET_Z(lwgeom_in->flags));
173 GEOSGeom_destroy(gm);
174 if ( ! lines ) {
175 lwgeom_free(ep);
176 lwerror("Error during GEOS2LWGEOM");
177 return NULL;
178 }
179
180 /*
181 * Reintroduce endpoints from input, using split-line-by-point.
182 * Note that by now we can be sure that each point splits at
183 * most _one_ segment as any point shared by multiple segments
184 * would already be a node. Also we can be sure that any of
185 * the segments endpoints won't split any other segment.
186 * We can use the above 2 assertions to early exit the loop.
187 */
188
190 FLAGS_GET_Z(lwgeom_in->flags),
191 FLAGS_GET_M(lwgeom_in->flags));
192
193 np = lwgeom_ngeoms(ep);
194 for (pn=0; pn<np; ++pn) { /* for each point */
195
196 const LWPOINT* p = (LWPOINT*)lwgeom_subgeom(ep, pn);
197
198 nl = lwgeom_ngeoms(lines);
199 for (ln=0; ln<nl; ++ln) { /* for each line */
200
201 const LWLINE* l = (LWLINE*)lwgeom_subgeom(lines, ln);
202
203 int s = lwline_split_by_point_to(l, p, (LWMLINE*)col);
204
205 if ( ! s ) continue; /* not on this line */
206
207 if ( s == 1 ) {
208 /* found on this line, but not splitting it */
209 break;
210 }
211
212 /* splits this line */
213
214 /* replace this line with the two splits */
215 if ( lwgeom_is_collection(lines) ) {
216 tc = (LWCOLLECTION*)lines;
217 lwcollection_reserve(tc, nl + 1);
218 while (nl > ln+1) {
219 tc->geoms[nl] = tc->geoms[nl-1];
220 --nl;
221 }
222 lwgeom_free(tc->geoms[ln]);
223 tc->geoms[ln] = col->geoms[0];
224 tc->geoms[ln+1] = col->geoms[1];
225 tc->ngeoms++;
226 } else {
227 lwgeom_free(lines);
228 /* transfer ownership rather than cloning */
229 lines = (LWGEOM*)lwcollection_clone_deep(col);
230 assert(col->ngeoms == 2);
231 lwgeom_free(col->geoms[0]);
232 lwgeom_free(col->geoms[1]);
233 }
234
235 /* reset the vector */
236 assert(col->ngeoms == 2);
237 col->ngeoms = 0;
238
239 break;
240 }
241
242 }
243
244 lwgeom_free(ep);
246
247 lwgeom_set_srid(lines, lwgeom_in->srid);
248 return (LWGEOM*)lines;
249}
char * s
Definition cu_in_wkt.c:23
char lwgeom_geos_errmsg[LWGEOM_GEOS_ERRMSG_MAXSIZE]
GEOSGeometry * LWGEOM2GEOS(const LWGEOM *lwgeom, uint8_t autofix)
LWGEOM * GEOS2LWGEOM(const GEOSGeometry *geom, uint8_t want3d)
void lwgeom_geos_error(const char *fmt,...)
void lwgeom_set_srid(LWGEOM *geom, int32_t srid)
Set the SRID on an LWGEOM For collections, only the parent gets an SRID, all the children get SRID_UN...
Definition lwgeom.c:1530
void lwgeom_free(LWGEOM *geom)
Definition lwgeom.c:1138
#define MULTILINETYPE
Definition liblwgeom.h:120
#define FLAGS_GET_Z(flags)
Definition liblwgeom.h:179
int lwgeom_dimension(const LWGEOM *geom)
For an LWGEOM, returns 0 for points, 1 for lines, 2 for polygons, 3 for volume, and the max dimension...
Definition lwgeom.c:1281
int lwgeom_is_collection(const LWGEOM *lwgeom)
Determine whether a LWGEOM can contain sub-geometries or not.
Definition lwgeom.c:1079
#define FLAGS_GET_M(flags)
Definition liblwgeom.h:180
void lwcollection_free(LWCOLLECTION *col)
LWCOLLECTION * lwcollection_construct_empty(uint8_t type, int32_t srid, char hasz, char hasm)
LWCOLLECTION * lwcollection_clone_deep(const LWCOLLECTION *lwgeom)
Deep clone LWCOLLECTION object.
int lwline_split_by_point_to(const LWLINE *ln, const LWPOINT *pt, LWMLINE *to)
Split a line by a point and push components to the provided multiline.
void lwcollection_reserve(LWCOLLECTION *col, uint32_t ngeoms)
Ensure the collection can hold at least up to ngeoms geometries.
static LWGEOM * lwgeom_extract_unique_endpoints(const LWGEOM *lwg)
static const LWGEOM * lwgeom_subgeom(const LWGEOM *g, int n)
static int lwgeom_ngeoms(const LWGEOM *n)
void lwerror(const char *fmt,...)
Write a notice out to the error handler.
Definition lwutil.c:190
uint32_t ngeoms
Definition liblwgeom.h:566
LWGEOM ** geoms
Definition liblwgeom.h:561
int32_t srid
Definition liblwgeom.h:446
lwflags_t flags
Definition liblwgeom.h:447

References LWGEOM::flags, FLAGS_GET_M, FLAGS_GET_Z, LWMLINE::geoms, LWCOLLECTION::geoms, GEOS2LWGEOM(), lwcollection_clone_deep(), lwcollection_construct_empty(), lwcollection_free(), lwcollection_reserve(), lwerror(), LWGEOM2GEOS(), lwgeom_dimension(), lwgeom_extract_unique_endpoints(), lwgeom_free(), lwgeom_geos_errmsg, lwgeom_geos_error(), lwgeom_is_collection(), lwgeom_ngeoms(), lwgeom_set_srid(), lwgeom_subgeom(), lwline_split_by_point_to(), MULTILINETYPE, LWMLINE::ngeoms, LWCOLLECTION::ngeoms, s, and LWGEOM::srid.

Referenced by _lwt_AddLine(), lwgeom_offsetcurve(), ST_Node(), and test_lwgeom_node().

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