PostGIS  3.2.2dev-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 1346 of file ptarray.c.

1347 {
1348  POINTARRAY *dpa;
1349  POINT4D pt;
1350  POINT4D p1, p2;
1351  POINT4D *p1ptr=&p1; /* don't break strict-aliasing rule */
1352  POINT4D *p2ptr=&p2;
1353  int nsegs, i;
1354  double length, slength, tlength;
1355  int state = 0; /* 0=before, 1=inside */
1356 
1357  /*
1358  * Create a dynamic pointarray with an initial capacity
1359  * equal to full copy of input points
1360  */
1361  dpa = ptarray_construct_empty(FLAGS_GET_Z(ipa->flags), FLAGS_GET_M(ipa->flags), ipa->npoints);
1362 
1363  /* Compute total line length */
1364  length = ptarray_length_2d(ipa);
1365 
1366 
1367  LWDEBUGF(3, "Total length: %g", length);
1368 
1369 
1370  /* Get 'from' and 'to' lengths */
1371  from = length*from;
1372  to = length*to;
1373 
1374 
1375  LWDEBUGF(3, "From/To: %g/%g", from, to);
1376 
1377 
1378  tlength = 0;
1379  getPoint4d_p(ipa, 0, &p1);
1380  nsegs = ipa->npoints - 1;
1381  for ( i = 0; i < nsegs; i++ )
1382  {
1383  double dseg;
1384 
1385  getPoint4d_p(ipa, i+1, &p2);
1386 
1387 
1388  LWDEBUGF(3 ,"Segment %d: (%g,%g,%g,%g)-(%g,%g,%g,%g)",
1389  i, p1.x, p1.y, p1.z, p1.m, p2.x, p2.y, p2.z, p2.m);
1390 
1391 
1392  /* Find the length of this segment */
1393  slength = distance2d_pt_pt((POINT2D *)p1ptr, (POINT2D *)p2ptr);
1394 
1395  /*
1396  * We are before requested start.
1397  */
1398  if ( state == 0 ) /* before */
1399  {
1400 
1401  LWDEBUG(3, " Before start");
1402 
1403  if ( fabs ( from - ( tlength + slength ) ) <= tolerance )
1404  {
1405 
1406  LWDEBUG(3, " Second point is our start");
1407 
1408  /*
1409  * Second point is our start
1410  */
1411  ptarray_append_point(dpa, &p2, LW_FALSE);
1412  state=1; /* we're inside now */
1413  goto END;
1414  }
1415 
1416  else if ( fabs(from - tlength) <= tolerance )
1417  {
1418 
1419  LWDEBUG(3, " First point is our start");
1420 
1421  /*
1422  * First point is our start
1423  */
1424  ptarray_append_point(dpa, &p1, LW_FALSE);
1425 
1426  /*
1427  * We're inside now, but will check
1428  * 'to' point as well
1429  */
1430  state=1;
1431  }
1432 
1433  /*
1434  * Didn't reach the 'from' point,
1435  * nothing to do
1436  */
1437  else if ( from > tlength + slength ) goto END;
1438 
1439  else /* tlength < from < tlength+slength */
1440  {
1441 
1442  LWDEBUG(3, " Seg contains first point");
1443 
1444  /*
1445  * Our start is between first and
1446  * second point
1447  */
1448  dseg = (from - tlength) / slength;
1449 
1450  interpolate_point4d(&p1, &p2, &pt, dseg);
1451 
1452  ptarray_append_point(dpa, &pt, LW_FALSE);
1453 
1454  /*
1455  * We're inside now, but will check
1456  * 'to' point as well
1457  */
1458  state=1;
1459  }
1460  }
1461 
1462  if ( state == 1 ) /* inside */
1463  {
1464 
1465  LWDEBUG(3, " Inside");
1466 
1467  /*
1468  * 'to' point is our second point.
1469  */
1470  if ( fabs(to - ( tlength + slength ) ) <= tolerance )
1471  {
1472 
1473  LWDEBUG(3, " Second point is our end");
1474 
1475  ptarray_append_point(dpa, &p2, LW_FALSE);
1476  break; /* substring complete */
1477  }
1478 
1479  /*
1480  * 'to' point is our first point.
1481  * (should only happen if 'to' is 0)
1482  */
1483  else if ( fabs(to - tlength) <= tolerance )
1484  {
1485 
1486  LWDEBUG(3, " First point is our end");
1487 
1488  ptarray_append_point(dpa, &p1, LW_FALSE);
1489 
1490  break; /* substring complete */
1491  }
1492 
1493  /*
1494  * Didn't reach the 'end' point,
1495  * just copy second point
1496  */
1497  else if ( to > tlength + slength )
1498  {
1499  ptarray_append_point(dpa, &p2, LW_FALSE);
1500  goto END;
1501  }
1502 
1503  /*
1504  * 'to' point falls on this segment
1505  * Interpolate and break.
1506  */
1507  else if ( to < tlength + slength )
1508  {
1509 
1510  LWDEBUG(3, " Seg contains our end");
1511 
1512  dseg = (to - tlength) / slength;
1513  interpolate_point4d(&p1, &p2, &pt, dseg);
1514 
1515  ptarray_append_point(dpa, &pt, LW_FALSE);
1516 
1517  break;
1518  }
1519 
1520  else
1521  {
1522  LWDEBUG(3, "Unhandled case");
1523  }
1524  }
1525 
1526 
1527 END:
1528 
1529  tlength += slength;
1530  memcpy(&p1, &p2, sizeof(POINT4D));
1531  }
1532 
1533  LWDEBUGF(3, "Out of loop, ptarray has %d points", dpa->npoints);
1534 
1535  return dpa;
1536 }
#define LW_FALSE
Definition: liblwgeom.h:108
double distance2d_pt_pt(const POINT2D *p1, const POINT2D *p2)
Definition: measures.c:2306
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:650
#define FLAGS_GET_Z(flags)
Definition: liblwgeom.h:179
#define FLAGS_GET_M(flags)
Definition: liblwgeom.h:180
int getPoint4d_p(const POINTARRAY *pa, uint32_t n, POINT4D *point)
Definition: lwgeom_api.c:126
#define LWDEBUG(level, msg)
Definition: lwgeom_log.h:83
#define LWDEBUGF(level, msg,...)
Definition: lwgeom_log.h:88
double ptarray_length_2d(const POINTARRAY *pts)
Find the 2d length of the given POINTARRAY (even if it's 3d)
Definition: ptarray.c:2099
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:428
double x
Definition: liblwgeom.h:428
double z
Definition: liblwgeom.h:428
double y
Definition: liblwgeom.h:428
uint32_t npoints
Definition: liblwgeom.h:441

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: