PostGIS  2.1.10dev-r@@SVN_REVISION@@
static POINTARRAY* ptarray_segmentize_sphere ( const POINTARRAY pa_in,
double  max_seg_length 
)
static

Create a new point array with no segment longer than the input segment length (expressed in radians!)

Parameters
pa_in- input point array pointer
max_seg_length- maximum output segment length in radians

Definition at line 1530 of file lwgeodetic.c.

References cart2geog(), geog2cart(), geographic_point_init(), getPoint4d_p(), GEOGRAPHIC_POINT::lat, GEOGRAPHIC_POINT::lon, LW_FALSE, LW_TRUE, lwerror(), POINT4D::m, normalize(), POINTARRAY::npoints, p4d_same(), ptarray_append_point(), ptarray_construct_empty(), ptarray_has_m(), ptarray_has_z(), rad2deg, sphere_distance(), POINT3D::x, POINT4D::x, POINT3D::y, POINT4D::y, POINT3D::z, and POINT4D::z.

Referenced by lwgeom_segmentize_sphere().

1531 {
1532  POINTARRAY *pa_out;
1533  int hasz = ptarray_has_z(pa_in);
1534  int hasm = ptarray_has_m(pa_in);
1535  int pa_in_offset = 0; /* input point offset */
1536  POINT4D p1, p2, p;
1537  POINT3D q1, q2, q, qn;
1538  GEOGRAPHIC_POINT g1, g2, g;
1539  double d;
1540 
1541  /* Just crap out on crazy input */
1542  if ( ! pa_in )
1543  lwerror("ptarray_segmentize_sphere: null input pointarray");
1544  if ( max_seg_length <= 0.0 )
1545  lwerror("ptarray_segmentize_sphere: maximum segment length must be positive");
1546 
1547  /* Empty starting array */
1548  pa_out = ptarray_construct_empty(hasz, hasm, pa_in->npoints);
1549 
1550  /* Add first point */
1551  getPoint4d_p(pa_in, pa_in_offset, &p1);
1552  ptarray_append_point(pa_out, &p1, LW_FALSE);
1553  geographic_point_init(p1.x, p1.y, &g1);
1554  pa_in_offset++;
1555 
1556  while ( pa_in_offset < pa_in->npoints )
1557  {
1558  getPoint4d_p(pa_in, pa_in_offset, &p2);
1559  geographic_point_init(p2.x, p2.y, &g2);
1560 
1561  /* Skip duplicate points (except in case of 2-point lines!) */
1562  if ( (pa_in->npoints > 2) && p4d_same(&p1, &p2) )
1563  {
1564  /* Move one offset forward */
1565  p1 = p2;
1566  g1 = g2;
1567  pa_in_offset++;
1568  continue;
1569  }
1570 
1571  /* How long is this edge? */
1572  d = sphere_distance(&g1, &g2);
1573 
1574  /* We need to segmentize this edge */
1575  if ( d > max_seg_length )
1576  {
1577  int nsegs = 1 + d / max_seg_length;
1578  int i;
1579  double dx, dy, dz, dzz = 0, dmm = 0;
1580 
1581  geog2cart(&g1, &q1);
1582  geog2cart(&g2, &q2);
1583 
1584  dx = (q2.x - q1.x) / nsegs;
1585  dy = (q2.y - q1.y) / nsegs;
1586  dz = (q2.z - q1.z) / nsegs;
1587 
1588  /* The independent Z/M values on the ptarray */
1589  if ( hasz ) dzz = (p2.z - p1.z) / nsegs;
1590  if ( hasm ) dmm = (p2.m - p1.m) / nsegs;
1591 
1592  q = q1;
1593  p = p1;
1594 
1595  for ( i = 0; i < nsegs - 1; i++ )
1596  {
1597  /* Move one increment forwards */
1598  q.x += dx; q.y += dy; q.z += dz;
1599  qn = q;
1600  normalize(&qn);
1601 
1602  /* Back to spherical coordinates */
1603  cart2geog(&qn, &g);
1604  /* Back to lon/lat */
1605  p.x = rad2deg(g.lon);
1606  p.y = rad2deg(g.lat);
1607  if ( hasz )
1608  p.z += dzz;
1609  if ( hasm )
1610  p.m += dmm;
1611  ptarray_append_point(pa_out, &p, LW_FALSE);
1612  }
1613 
1614  ptarray_append_point(pa_out, &p2, LW_FALSE);
1615  }
1616  /* This edge is already short enough */
1617  else
1618  {
1619  ptarray_append_point(pa_out, &p2, (pa_in->npoints==2)?LW_TRUE:LW_FALSE);
1620  }
1621 
1622  /* Move one offset forward */
1623  p1 = p2;
1624  g1 = g2;
1625  pa_in_offset++;
1626  }
1627 
1628  return pa_out;
1629 }
double x
Definition: liblwgeom.h:308
double sphere_distance(const GEOGRAPHIC_POINT *s, const GEOGRAPHIC_POINT *e)
Given two points on a unit sphere, calculate their distance apart in radians.
Definition: lwgeodetic.c:897
double m
Definition: liblwgeom.h:308
void normalize(POINT3D *p)
Normalize to a unit vector.
Definition: lwgeodetic.c:564
double y
Definition: liblwgeom.h:296
int npoints
Definition: liblwgeom.h:327
POINTARRAY * ptarray_construct_empty(char hasz, char hasm, uint32_t maxpoints)
Create a new POINTARRAY with no points.
Definition: ptarray.c:57
void cart2geog(const POINT3D *p, GEOGRAPHIC_POINT *g)
Convert cartesion coordinates on unit sphere to spherical coordinates.
Definition: lwgeodetic.c:365
double x
Definition: liblwgeom.h:296
Point in spherical coordinates on the world.
Definition: lwgeodetic.h:33
double z
Definition: liblwgeom.h:296
void lwerror(const char *fmt,...)
Write a notice out to the error handler.
Definition: lwutil.c:67
int ptarray_append_point(POINTARRAY *pa, const POINT4D *pt, int allow_duplicates)
Append a point to the end of an existing POINTARRAY If allow_duplicate is LW_TRUE, then a duplicate point will not be added.
Definition: ptarray.c:141
#define LW_FALSE
Definition: liblwgeom.h:52
#define rad2deg(r)
Definition: lwgeodetic.h:61
#define LW_TRUE
Return types for functions with status returns.
Definition: liblwgeom.h:51
double z
Definition: liblwgeom.h:308
void geog2cart(const GEOGRAPHIC_POINT *g, POINT3D *p)
Convert spherical coordinates to cartesion coordinates on unit sphere.
Definition: lwgeodetic.c:355
int ptarray_has_m(const POINTARRAY *pa)
Definition: ptarray.c:30
void geographic_point_init(double lon, double lat, GEOGRAPHIC_POINT *g)
Initialize a geographic point.
Definition: lwgeodetic.c:157
int ptarray_has_z(const POINTARRAY *pa)
Definition: ptarray.c:23
double y
Definition: liblwgeom.h:308
int getPoint4d_p(const POINTARRAY *pa, int n, POINT4D *point)
Definition: lwgeom_api.c:217
int p4d_same(const POINT4D *p1, const POINT4D *p2)
Definition: lwalgorithm.c:29

Here is the call graph for this function:

Here is the caller graph for this function: