PostGIS  2.3.8dev-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 1241 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().

1242 {
1243 
1244  int cn = 0; /* the crossing number counter */
1245  int i;
1246  POINT3DZ v1, v2;
1247 
1248  POINT3DZ first, last;
1249 
1250  getPoint3dz_p(ring, 0, &first);
1251  getPoint3dz_p(ring, ring->npoints-1, &last);
1252  if ( memcmp(&first, &last, sizeof(POINT3DZ)) )
1253  {
1254  lwerror("pt_in_ring_3d: V[n] != V[0] (%g %g %g!= %g %g %g)",
1255  first.x, first.y, first.z, last.x, last.y, last.z);
1256  return LW_FALSE;
1257  }
1258 
1259  LWDEBUGF(2, "pt_in_ring_3d called with point: %g %g %g", p->x, p->y, p->z);
1260  /* printPA(ring); */
1261 
1262  /* loop through all edges of the polygon */
1263  getPoint3dz_p(ring, 0, &v1);
1264 
1265 
1266  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*/
1267  {
1268  for (i=0; i<ring->npoints-1; i++)
1269  {
1270  double vt;
1271  getPoint3dz_p(ring, i+1, &v2);
1272 
1273  /* edge from vertex i to vertex i+1 */
1274  if
1275  (
1276  /* an upward crossing */
1277  ((v1.y <= p->y) && (v2.y > p->y))
1278  /* a downward crossing */
1279  || ((v1.y > p->y) && (v2.y <= p->y))
1280  )
1281  {
1282 
1283  vt = (double)(p->y - v1.y) / (v2.y - v1.y);
1284 
1285  /* P.x <intersect */
1286  if (p->x < v1.x + vt * (v2.x - v1.x))
1287  {
1288  /* a valid crossing of y=p.y right of p.x */
1289  ++cn;
1290  }
1291  }
1292  v1 = v2;
1293  }
1294  }
1295  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*/
1296  {
1297  for (i=0; i<ring->npoints-1; i++)
1298  {
1299  double vt;
1300  getPoint3dz_p(ring, i+1, &v2);
1301 
1302  /* edge from vertex i to vertex i+1 */
1303  if
1304  (
1305  /* an upward crossing */
1306  ((v1.z <= p->z) && (v2.z > p->z))
1307  /* a downward crossing */
1308  || ((v1.z > p->z) && (v2.z <= p->z))
1309  )
1310  {
1311 
1312  vt = (double)(p->z - v1.z) / (v2.z - v1.z);
1313 
1314  /* P.x <intersect */
1315  if (p->x < v1.x + vt * (v2.x - v1.x))
1316  {
1317  /* a valid crossing of y=p.y right of p.x */
1318  ++cn;
1319  }
1320  }
1321  v1 = v2;
1322  }
1323  }
1324  else /*Hopefully we only have the cases where x part of the normal vector is largest left*/
1325  {
1326  for (i=0; i<ring->npoints-1; i++)
1327  {
1328  double vt;
1329  getPoint3dz_p(ring, i+1, &v2);
1330 
1331  /* edge from vertex i to vertex i+1 */
1332  if
1333  (
1334  /* an upward crossing */
1335  ((v1.z <= p->z) && (v2.z > p->z))
1336  /* a downward crossing */
1337  || ((v1.z > p->z) && (v2.z <= p->z))
1338  )
1339  {
1340 
1341  vt = (double)(p->z - v1.z) / (v2.z - v1.z);
1342 
1343  /* P.x <intersect */
1344  if (p->y < v1.y + vt * (v2.y - v1.y))
1345  {
1346  /* a valid crossing of y=p.y right of p.x */
1347  ++cn;
1348  }
1349  }
1350  v1 = v2;
1351  }
1352  }
1353  LWDEBUGF(3, "pt_in_ring_3d returning %d", cn&1);
1354 
1355  return (cn&1); /* 0 if even (out), and 1 if odd (in) */
1356 }
double z
Definition: liblwgeom.h:333
double y
Definition: liblwgeom.h:333
double x
Definition: liblwgeom.h:333
double z
Definition: measures3d.h:51
int npoints
Definition: liblwgeom.h:370
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:332
#define LW_FALSE
Definition: liblwgeom.h:76
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:102
Here is the call graph for this function:
Here is the caller graph for this function: