PostGIS  3.6.1dev-r@@SVN_REVISION@@

◆ ptarray_substring()

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

@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 1206 of file ptarray.c.

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