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

◆ ptarray_substring()

POINTARRAY * ptarray_substring ( POINTARRAY pa,
double  d1,
double  d2,
double  tolerance 
)
extern

@d1 start location (distance from start / total distance) @d2 end location (distance from start / total distance)

Parameters
tolerancesnap to vertices at locations < tolerance away from given ones

Definition at line 1211 of file ptarray.c.

1212{
1213 POINTARRAY *dpa;
1214 POINT4D pt;
1215 POINT4D p1, p2;
1216 POINT4D *p1ptr=&p1; /* don't break strict-aliasing rule */
1217 POINT4D *p2ptr=&p2;
1218 int nsegs, i;
1219 double length, slength, tlength;
1220 int state = 0; /* 0=before, 1=inside */
1221
1222 /*
1223 * Create a dynamic pointarray with an initial capacity
1224 * equal to full copy of input points
1225 */
1226 dpa = ptarray_construct_empty(FLAGS_GET_Z(ipa->flags), FLAGS_GET_M(ipa->flags), ipa->npoints);
1227
1228 /* Compute total line length */
1229 length = ptarray_length_2d(ipa);
1230
1231
1232 LWDEBUGF(3, "Total length: %g", length);
1233
1234
1235 /* Get 'from' and 'to' lengths */
1236 from = length*from;
1237 to = length*to;
1238
1239
1240 LWDEBUGF(3, "From/To: %g/%g", from, to);
1241
1242
1243 tlength = 0;
1244 getPoint4d_p(ipa, 0, &p1);
1245 nsegs = ipa->npoints - 1;
1246 for ( i = 0; i < nsegs; i++ )
1247 {
1248 double dseg;
1249
1250 getPoint4d_p(ipa, i+1, &p2);
1251
1252
1253 LWDEBUGF(3 ,"Segment %d: (%g,%g,%g,%g)-(%g,%g,%g,%g)",
1254 i, p1.x, p1.y, p1.z, p1.m, p2.x, p2.y, p2.z, p2.m);
1255
1256
1257 /* Find the length of this segment */
1258 slength = distance2d_pt_pt((POINT2D *)p1ptr, (POINT2D *)p2ptr);
1259
1260 /*
1261 * We are before requested start.
1262 */
1263 if ( state == 0 ) /* before */
1264 {
1265
1266 LWDEBUG(3, " Before start");
1267
1268 if ( fabs ( from - ( tlength + slength ) ) <= tolerance )
1269 {
1270
1271 LWDEBUG(3, " Second point is our start");
1272
1273 /*
1274 * Second point is our start
1275 */
1276 ptarray_append_point(dpa, &p2, LW_FALSE);
1277 state=1; /* we're inside now */
1278 goto END;
1279 }
1280
1281 else if ( fabs(from - tlength) <= tolerance )
1282 {
1283
1284 LWDEBUG(3, " First point is our start");
1285
1286 /*
1287 * First point is our start
1288 */
1289 ptarray_append_point(dpa, &p1, LW_FALSE);
1290
1291 /*
1292 * We're inside now, but will check
1293 * 'to' point as well
1294 */
1295 state=1;
1296 }
1297
1298 /*
1299 * Didn't reach the 'from' point,
1300 * nothing to do
1301 */
1302 else if ( from > tlength + slength ) goto END;
1303
1304 else /* tlength < from < tlength+slength */
1305 {
1306
1307 LWDEBUG(3, " Seg contains first point");
1308
1309 /*
1310 * Our start is between first and
1311 * second point
1312 */
1313 dseg = (from - tlength) / slength;
1314
1315 interpolate_point4d(&p1, &p2, &pt, dseg);
1316
1317 ptarray_append_point(dpa, &pt, LW_FALSE);
1318
1319 /*
1320 * We're inside now, but will check
1321 * 'to' point as well
1322 */
1323 state=1;
1324 }
1325 }
1326
1327 if ( state == 1 ) /* inside */
1328 {
1329
1330 LWDEBUG(3, " Inside");
1331
1332 /*
1333 * 'to' point is our second point.
1334 */
1335 if ( fabs(to - ( tlength + slength ) ) <= tolerance )
1336 {
1337
1338 LWDEBUG(3, " Second point is our end");
1339
1340 ptarray_append_point(dpa, &p2, LW_FALSE);
1341 break; /* substring complete */
1342 }
1343
1344 /*
1345 * 'to' point is our first point.
1346 * (should only happen if 'to' is 0)
1347 */
1348 else if ( fabs(to - tlength) <= tolerance )
1349 {
1350
1351 LWDEBUG(3, " First point is our end");
1352
1353 ptarray_append_point(dpa, &p1, LW_FALSE);
1354
1355 break; /* substring complete */
1356 }
1357
1358 /*
1359 * Didn't reach the 'end' point,
1360 * just copy second point
1361 */
1362 else if ( to > tlength + slength )
1363 {
1364 ptarray_append_point(dpa, &p2, LW_FALSE);
1365 goto END;
1366 }
1367
1368 /*
1369 * 'to' point falls on this segment
1370 * Interpolate and break.
1371 */
1372 else if ( to < tlength + slength )
1373 {
1374
1375 LWDEBUG(3, " Seg contains our end");
1376
1377 dseg = (to - tlength) / slength;
1378 interpolate_point4d(&p1, &p2, &pt, dseg);
1379
1380 ptarray_append_point(dpa, &pt, LW_FALSE);
1381
1382 break;
1383 }
1384
1385 else
1386 {
1387 LWDEBUG(3, "Unhandled case");
1388 }
1389 }
1390
1391
1392END:
1393
1394 tlength += slength;
1395 memcpy(&p1, &p2, sizeof(POINT4D));
1396 }
1397
1398 LWDEBUGF(3, "Out of loop, ptarray has %d points", dpa->npoints);
1399
1400 return dpa;
1401}
#define LW_FALSE
Definition liblwgeom.h:94
double distance2d_pt_pt(const POINT2D *p1, const POINT2D *p2)
Definition measures.c:2344
void interpolate_point4d(const POINT4D *A, const POINT4D *B, POINT4D *I, double F)
Find interpolation point I between point A and point B so that the len(AI) == len(AB)*F and I falls o...
Definition lwgeom_api.c:646
#define FLAGS_GET_Z(flags)
Definition liblwgeom.h:165
#define FLAGS_GET_M(flags)
Definition liblwgeom.h:166
int getPoint4d_p(const POINTARRAY *pa, uint32_t n, POINT4D *point)
Definition lwgeom_api.c:125
#define LWDEBUG(level, msg)
Definition lwgeom_log.h:101
#define LWDEBUGF(level, msg,...)
Definition lwgeom_log.h:106
POINTARRAY * ptarray_construct_empty(char hasz, char hasm, uint32_t maxpoints)
Create a new POINTARRAY with no points.
Definition ptarray.c:59
double ptarray_length_2d(const POINTARRAY *pts)
Find the 2d length of the given POINTARRAY (even if it's 3d)
Definition ptarray.c:1975
int ptarray_append_point(POINTARRAY *pa, const POINT4D *pt, int repeated_points)
Append a point to the end of an existing POINTARRAY If allow_duplicate is LW_FALSE,...
Definition ptarray.c:147
double m
Definition liblwgeom.h:414
double x
Definition liblwgeom.h:414
double z
Definition liblwgeom.h:414
double y
Definition liblwgeom.h:414
uint32_t npoints
Definition liblwgeom.h:427

References distance2d_pt_pt(), POINTARRAY::flags, FLAGS_GET_M, FLAGS_GET_Z, getPoint4d_p(), interpolate_point4d(), LW_FALSE, LWDEBUG, LWDEBUGF, POINT4D::m, POINTARRAY::npoints, ptarray_append_point(), ptarray_construct_empty(), ptarray_length_2d(), POINT4D::x, POINT4D::y, and POINT4D::z.

Referenced by LWGEOM_line_substring().

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