PostGIS  2.4.9dev-r@@SVN_REVISION@@

◆ pt_in_ring_3d()

int pt_in_ring_3d ( const POINT3DZ p,
const POINTARRAY ring,
PLANE3D plane 
)

pt_in_ring_3d(): crossing number test for a point in a polygon input: p = a point, pa = vertex points of a ring V[n+1] with V[n]=V[0] plane=the plane that the vertex points are lying on returns: 0 = outside, 1 = inside

Our polygons have first and last point the same,

The difference in 3D variant is that we exclude the dimension that faces the plane least. That is the dimension with the highest number in pv

Definition at line 1283 of file measures3d.c.

References getPoint3dz_p(), LW_FALSE, LWDEBUGF, lwerror(), POINTARRAY::npoints, PLANE3D::pv, VECTOR3D::x, POINT3DZ::x, VECTOR3D::y, POINT3DZ::y, VECTOR3D::z, and POINT3DZ::z.

Referenced by lw_dist3d_pt_poly(), and lw_dist3d_ptarray_poly().

1284 {
1285 
1286  int cn = 0; /* the crossing number counter */
1287  int i;
1288  POINT3DZ v1, v2;
1289 
1290  POINT3DZ first, last;
1291 
1292  getPoint3dz_p(ring, 0, &first);
1293  getPoint3dz_p(ring, ring->npoints-1, &last);
1294  if ( memcmp(&first, &last, sizeof(POINT3DZ)) )
1295  {
1296  lwerror("pt_in_ring_3d: V[n] != V[0] (%g %g %g!= %g %g %g)",
1297  first.x, first.y, first.z, last.x, last.y, last.z);
1298  return LW_FALSE;
1299  }
1300 
1301  LWDEBUGF(2, "pt_in_ring_3d called with point: %g %g %g", p->x, p->y, p->z);
1302  /* printPA(ring); */
1303 
1304  /* loop through all edges of the polygon */
1305  getPoint3dz_p(ring, 0, &v1);
1306 
1307 
1308  if(fabs(plane->pv.z)>=fabs(plane->pv.x)&&fabs(plane->pv.z)>=fabs(plane->pv.y)) /*If the z vector of the normal vector to the plane is larger than x and y vector we project the ring to the xy-plane*/
1309  {
1310  for (i=0; i<ring->npoints-1; i++)
1311  {
1312  double vt;
1313  getPoint3dz_p(ring, i+1, &v2);
1314 
1315  /* edge from vertex i to vertex i+1 */
1316  if
1317  (
1318  /* an upward crossing */
1319  ((v1.y <= p->y) && (v2.y > p->y))
1320  /* a downward crossing */
1321  || ((v1.y > p->y) && (v2.y <= p->y))
1322  )
1323  {
1324 
1325  vt = (double)(p->y - v1.y) / (v2.y - v1.y);
1326 
1327  /* P.x <intersect */
1328  if (p->x < v1.x + vt * (v2.x - v1.x))
1329  {
1330  /* a valid crossing of y=p.y right of p.x */
1331  ++cn;
1332  }
1333  }
1334  v1 = v2;
1335  }
1336  }
1337  else if(fabs(plane->pv.y)>=fabs(plane->pv.x)&&fabs(plane->pv.y)>=fabs(plane->pv.z)) /*If the y vector of the normal vector to the plane is larger than x and z vector we project the ring to the xz-plane*/
1338  {
1339  for (i=0; i<ring->npoints-1; i++)
1340  {
1341  double vt;
1342  getPoint3dz_p(ring, i+1, &v2);
1343 
1344  /* edge from vertex i to vertex i+1 */
1345  if
1346  (
1347  /* an upward crossing */
1348  ((v1.z <= p->z) && (v2.z > p->z))
1349  /* a downward crossing */
1350  || ((v1.z > p->z) && (v2.z <= p->z))
1351  )
1352  {
1353 
1354  vt = (double)(p->z - v1.z) / (v2.z - v1.z);
1355 
1356  /* P.x <intersect */
1357  if (p->x < v1.x + vt * (v2.x - v1.x))
1358  {
1359  /* a valid crossing of y=p.y right of p.x */
1360  ++cn;
1361  }
1362  }
1363  v1 = v2;
1364  }
1365  }
1366  else /*Hopefully we only have the cases where x part of the normal vector is largest left*/
1367  {
1368  for (i=0; i<ring->npoints-1; i++)
1369  {
1370  double vt;
1371  getPoint3dz_p(ring, i+1, &v2);
1372 
1373  /* edge from vertex i to vertex i+1 */
1374  if
1375  (
1376  /* an upward crossing */
1377  ((v1.z <= p->z) && (v2.z > p->z))
1378  /* a downward crossing */
1379  || ((v1.z > p->z) && (v2.z <= p->z))
1380  )
1381  {
1382 
1383  vt = (double)(p->z - v1.z) / (v2.z - v1.z);
1384 
1385  /* P.x <intersect */
1386  if (p->y < v1.y + vt * (v2.y - v1.y))
1387  {
1388  /* a valid crossing of y=p.y right of p.x */
1389  ++cn;
1390  }
1391  }
1392  v1 = v2;
1393  }
1394  }
1395  LWDEBUGF(3, "pt_in_ring_3d returning %d", cn&1);
1396 
1397  return (cn&1); /* 0 if even (out), and 1 if odd (in) */
1398 }
double z
Definition: liblwgeom.h:334
double y
Definition: liblwgeom.h:334
double x
Definition: liblwgeom.h:334
double z
Definition: measures3d.h:51
int npoints
Definition: liblwgeom.h:371
VECTOR3D pv
Definition: measures3d.h:58
double y
Definition: measures3d.h:51
int getPoint3dz_p(const POINTARRAY *pa, int n, POINT3DZ *point)
Definition: lwgeom_api.c:214
#define LW_FALSE
Definition: liblwgeom.h:77
double x
Definition: measures3d.h:51
#define LWDEBUGF(level, msg,...)
Definition: lwgeom_log.h:88
void lwerror(const char *fmt,...)
Write a notice out to the error handler.
Definition: lwutil.c:190
Here is the call graph for this function:
Here is the caller graph for this function: