Пример #1
0
Datum BOX3D_construct(PG_FUNCTION_ARGS)
{
	GSERIALIZED *min = (GSERIALIZED *)PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
	GSERIALIZED *max = (GSERIALIZED *)PG_DETOAST_DATUM(PG_GETARG_DATUM(1));
	BOX3D *result = palloc(sizeof(BOX3D));
	LWGEOM *minpoint, *maxpoint;
	POINT3DZ minp, maxp;

	minpoint = lwgeom_from_gserialized(min);
	maxpoint = lwgeom_from_gserialized(max);

	if ( minpoint->type != POINTTYPE ||
	     maxpoint->type != POINTTYPE )
	{
		elog(ERROR, "BOX3D_construct: args must be points");
		PG_RETURN_NULL();
	}

	error_if_srid_mismatch(minpoint->srid, maxpoint->srid);

	getPoint3dz_p(((LWPOINT *)minpoint)->point, 0, &minp);
	getPoint3dz_p(((LWPOINT *)maxpoint)->point, 0, &maxp);

	result->xmax = maxp.x;
	result->ymax = maxp.y;
	result->zmax = maxp.z;

	result->xmin = minp.x;
	result->ymin = minp.y;
	result->zmin = minp.z;

	result->srid = minpoint->srid;

	PG_RETURN_POINTER(result);
}
Пример #2
0
char compound_is_closed(LWCOMPOUND *compound)
{
	POINT3DZ sp, ep;
	LWGEOM *tmp;

	LWDEBUG(2, "compound_is_closed called.");

	tmp = compound->geoms[0];
	if (lwgeom_getType(tmp->type) == LINETYPE)
	{
		getPoint3dz_p(((LWLINE *)tmp)->points, 0, &sp);
	}
	else
	{
		getPoint3dz_p(((LWCIRCSTRING *)tmp)->points, 0, &sp);
	}

	tmp = compound->geoms[compound->ngeoms - 1];
	if (lwgeom_getType(tmp->type) == LINETYPE)
	{
		getPoint3dz_p(((LWLINE *)tmp)->points, ((LWLINE *)tmp)->points->npoints - 1, &ep);
	}
	else
	{
		getPoint3dz_p(((LWCIRCSTRING *)tmp)->points, ((LWCIRCSTRING *)tmp)->points->npoints - 1, &ep);
	}

	if (sp.x != ep.x) return 0;
	if (sp.y != ep.y) return 0;
	if (TYPE_HASZ(compound->type))
	{
		if (sp.z != ep.z) return 0;
	}
	return 1;
}
Пример #3
0
/**
* Re-write the measure ordinate (or add one, if it isn't already there) interpolating
* the measure between the supplied start and end values.
*/
LWLINE*
lwline_measured_from_lwline(const LWLINE *lwline, double m_start, double m_end)
{
	int i = 0;
	int hasm = 0, hasz = 0;
	int npoints = 0;
	double length = 0.0;
	double length_so_far = 0.0;
	double m_range = m_end - m_start;
	double m;
	POINTARRAY *pa = NULL;
	POINT3DZ p1, p2;

	if ( TYPE_GETTYPE(lwline->type) != LINETYPE )
	{
		lwerror("lwline_construct_from_lwline: only line types supported");
		return NULL;
	}

	hasz = TYPE_HASZ(lwline->type);
	hasm = 1;

	/* Null points or npoints == 0 will result in empty return geometry */
	if ( lwline->points )
	{
		npoints = lwline->points->npoints;
		length = lwgeom_pointarray_length2d(lwline->points);
		getPoint3dz_p(lwline->points, 0, &p1);
	}

	pa = ptarray_construct(hasz, hasm, npoints);

	for ( i = 0; i < npoints; i++ )
	{
		POINT4D q;
		POINT2D a, b;
		getPoint3dz_p(lwline->points, i, &p2);
		a.x = p1.x;
		a.y = p1.y;
		b.x = p2.x;
		b.y = p2.y;
		length_so_far += distance2d_pt_pt(&a, &b);
		if ( length > 0.0 )
			m = m_start + m_range * length_so_far / length;
		else
			m = 0.0;
		q.x = p2.x;
		q.y = p2.y;
		q.z = p2.z;
		q.m = m;
		setPoint4d(pa, i, &q);
		p1 = p2;
	}

	return lwline_construct(lwline->SRID, NULL, pa);
}
Пример #4
0
/**

point to point calculation
*/
int
lw_dist3d_point_point(LWPOINT *point1, LWPOINT *point2, DISTPTS3D *dl)
{
	POINT3DZ p1;
	POINT3DZ p2;
	LWDEBUG(2, "lw_dist3d_point_point is called");

	getPoint3dz_p(point1->point, 0, &p1);
	getPoint3dz_p(point2->point, 0, &p2);

	return lw_dist3d_pt_pt(&p1, &p2,dl);
}
Пример #5
0
Datum LWGEOM_z_point(PG_FUNCTION_ARGS)
{
	GSERIALIZED *geom;
	LWPOINT *point = NULL;
	LWGEOM *lwgeom;
	POINT3DZ p;

	geom = (GSERIALIZED *)PG_DETOAST_DATUM(PG_GETARG_DATUM(0));

	if ( gserialized_get_type(geom) != POINTTYPE )
		lwerror("Argument to Z() must be a point");

	lwgeom = lwgeom_from_gserialized(geom);
	point = lwgeom_as_lwpoint(lwgeom);
	
	if ( lwgeom_is_empty(lwgeom) )
		PG_RETURN_NULL();

	/* no Z in input */
	if ( ! gserialized_has_z(geom) ) PG_RETURN_NULL();

	getPoint3dz_p(point->point, 0, &p);

	PG_FREE_IF_COPY(geom, 0);

	PG_RETURN_FLOAT8(p.z);
}
Пример #6
0
GEOSCoordSeq
ptarray_to_GEOSCoordSeq(const POINTARRAY *pa)
{
	uint32_t dims = 2;
	uint32_t size, i;
	POINT3DZ p;
	GEOSCoordSeq sq;

	if ( FLAGS_GET_Z(pa->flags) ) dims = 3;
	size = pa->npoints;

	sq = GEOSCoordSeq_create(size, dims);
	if ( ! sq ) lwerror("Error creating GEOS Coordinate Sequence");

	for (i=0; i<size; i++)
	{
		getPoint3dz_p(pa, i, &p);

		LWDEBUGF(4, "Point: %g,%g,%g", p.x, p.y, p.z);

#if POSTGIS_GEOS_VERSION < 33
		/* Make sure we don't pass any infinite values down into GEOS */
		/* GEOS 3.3+ is supposed to  handle this stuff OK */
		if ( isinf(p.x) || isinf(p.y) || (dims == 3 && isinf(p.z)) )
			lwerror("Infinite coordinate value found in geometry.");
		if ( isnan(p.x) || isnan(p.y) || (dims == 3 && isnan(p.z)) )
			lwerror("NaN coordinate value found in geometry.");
#endif

		GEOSCoordSeq_setX(sq, i, p.x);
		GEOSCoordSeq_setY(sq, i, p.y);
		if ( dims == 3 ) GEOSCoordSeq_setZ(sq, i, p.z);
	}
	return sq;
}
Пример #7
0
char circstring_is_closed(LWCIRCSTRING *curve)
{
	POINT3DZ sp, ep;

	LWDEBUG(2, "circstring_is_closed called.");

	getPoint3dz_p(curve->points, 0, &sp);
	getPoint3dz_p(curve->points, curve->points->npoints-1, &ep);

	if (sp.x != ep.x) return 0;
	if (sp.y != ep.y) return 0;
	if (TYPE_HASZ(curve->type))
	{
		if (sp.z != ep.z) return 0;
	}
	return 1;
}
Пример #8
0
char line_is_closed(LWLINE *line)
{
	POINT3DZ sp, ep;

	LWDEBUG(2, "line_is_closed called.");

	getPoint3dz_p(line->points, 0, &sp);
	getPoint3dz_p(line->points, line->points->npoints-1, &ep);

	if ( sp.x != ep.x ) return 0;
	if ( sp.y != ep.y ) return 0;
	if ( TYPE_HASZ(line->type) )
	{
		if ( sp.z != ep.z ) return 0;
	}

	return 1;
}
Пример #9
0
/**

point to line calculation
*/
int
lw_dist3d_point_line(LWPOINT *point, LWLINE *line, DISTPTS3D *dl)
{
	POINT3DZ p;
	POINTARRAY *pa = line->points;
	LWDEBUG(2, "lw_dist3d_point_line is called");

	getPoint3dz_p(point->point, 0, &p);
	return lw_dist3d_pt_ptarray(&p, pa, dl);
}
Пример #10
0
/**

 * search all the segments of pointarray to see which one is closest to p
 * Returns distance between point and pointarray
 */
int
lw_dist3d_pt_ptarray(POINT3DZ *p, POINTARRAY *pa,DISTPTS3D *dl)
{
	int t;
	POINT3DZ	start, end;
	int twist = dl->twisted;

	LWDEBUG(2, "lw_dist3d_pt_ptarray is called");

	getPoint3dz_p(pa, 0, &start);

	for (t=1; t<pa->npoints; t++)
	{
		dl->twisted=twist;
		getPoint3dz_p(pa, t, &end);
		if (!lw_dist3d_pt_seg(p, &start, &end,dl)) return LW_FALSE;

		if (dl->distance<=dl->tolerance && dl->mode == DIST_MIN) return LW_TRUE; /*just a check if  the answer is already given*/
		start = end;
	}

	return LW_TRUE;
}
Пример #11
0
/**
* Find the 3d/2d length of the given #POINTARRAY
* (depending on its dimensionality)
*/
double
ptarray_length(const POINTARRAY *pts)
{
	double dist = 0.0;
	int i;
	POINT3DZ frm;
	POINT3DZ to;

	if ( pts->npoints < 2 ) return 0.0;

	/* compute 2d length if 3d is not available */
	if ( ! FLAGS_GET_Z(pts->flags) ) return ptarray_length_2d(pts);

	for (i=0; i<pts->npoints-1; i++)
	{
		getPoint3dz_p(pts, i, &frm);
		getPoint3dz_p(pts, i+1, &to);
		dist += sqrt( ( (frm.x - to.x)*(frm.x - to.x) )  +
		              ((frm.y - to.y)*(frm.y - to.y) ) +
		              ((frm.z - to.z)*(frm.z - to.z) ) );
	}
	return dist;
}
Пример #12
0
/**

Finds all combinationes of segments between two pointarrays
*/
int
lw_dist3d_ptarray_ptarray(POINTARRAY *l1, POINTARRAY *l2,DISTPTS3D *dl)
{
	int t,u;
	POINT3DZ	start, end;
	POINT3DZ	start2, end2;
	int twist = dl->twisted;
	LWDEBUGF(2, "lw_dist3d_ptarray_ptarray called (points: %d-%d)",l1->npoints, l2->npoints);



	if (dl->mode == DIST_MAX)/*If we are searching for maxdistance we go straight to point-point calculation since the maxdistance have to be between two vertexes*/
	{
		for (t=0; t<l1->npoints; t++) /*for each segment in L1 */
		{
			getPoint3dz_p(l1, t, &start);
			for (u=0; u<l2->npoints; u++) /*for each segment in L2 */
			{
				getPoint3dz_p(l2, u, &start2);
				lw_dist3d_pt_pt(&start,&start2,dl);
				LWDEBUGF(4, "maxdist_ptarray_ptarray; seg %i * seg %i, dist = %g\n",t,u,dl->distance);
				LWDEBUGF(3, " seg%d-seg%d dist: %f, mindist: %f",
				         t, u, dl->distance, dl->tolerance);
			}
		}
	}
	else
	{
		getPoint3dz_p(l1, 0, &start);
		for (t=1; t<l1->npoints; t++) /*for each segment in L1 */
		{
			getPoint3dz_p(l1, t, &end);
			getPoint3dz_p(l2, 0, &start2);
			for (u=1; u<l2->npoints; u++) /*for each segment in L2 */
			{
				getPoint3dz_p(l2, u, &end2);
				dl->twisted=twist;
				lw_dist3d_seg_seg(&start, &end, &start2, &end2,dl);
				LWDEBUGF(4, "mindist_ptarray_ptarray; seg %i * seg %i, dist = %g\n",t,u,dl->distance);
				LWDEBUGF(3, " seg%d-seg%d dist: %f, mindist: %f",
				         t, u, dl->distance, dl->tolerance);
				if (dl->distance<=dl->tolerance && dl->mode == DIST_MIN) return LW_TRUE; /*just a check if  the answer is already given*/
				start2 = end2;
			}
			start = end;
		}
	}
	return LW_TRUE;
}
Пример #13
0
Datum LWGEOM_z_point(PG_FUNCTION_ARGS)
{
	PG_LWGEOM *geom;
	LWPOINT *point = NULL;
	POINT3DZ p;

	geom = (PG_LWGEOM *)PG_DETOAST_DATUM(PG_GETARG_DATUM(0));

	if ( TYPE_GETTYPE(geom->type) != POINTTYPE )
		lwerror("Argument to Z() must be a point");

	point = lwgeom_getpoint(SERIALIZED_FORM(geom), 0);

	/* no Z in input */
	if ( ! TYPE_HASZ(geom->type) ) PG_RETURN_NULL();

	getPoint3dz_p(point->point, 0, &p);

	PG_FREE_IF_COPY(geom, 0);

	PG_RETURN_FLOAT8(p.z);
}
Пример #14
0
/**

Computes point to polygon distance
For mindistance that means:
1)find the plane of the polygon 
2)projecting the point to the plane of the polygon 
3)finding if that projected point is inside the polygon, if so the distance is measured to that projected point
4) if not in polygon above, check the distance against the boundary of the polygon
for max distance it is always point against boundary

*/
int
lw_dist3d_point_poly(LWPOINT *point, LWPOLY *poly, DISTPTS3D *dl)
{
	POINT3DZ p, projp;/*projp is "point projected on plane"*/
	PLANE3D plane;
	LWDEBUG(2, "lw_dist3d_point_poly is called");
	getPoint3dz_p(point->point, 0, &p);
	
	/*If we are lookig for max distance, longestline or dfullywithin*/
	if (dl->mode == DIST_MAX)
	{
		LWDEBUG(3, "looking for maxdistance");
		return lw_dist3d_pt_ptarray(&p, poly->rings[0], dl);
	}
	
	/*Find the plane of the polygon, the "holes" have to be on the same plane. so we only care about the boudary*/
	if(!define_plane(poly->rings[0], &plane))
		return LW_FALSE;
	
	/*get our point projected on the plane of the polygon*/
	project_point_on_plane(&p, &plane, &projp);
	
	return lw_dist3d_pt_poly(&p, poly,&plane, &projp, dl);
}
Пример #15
0
/**

Computes pointarray to polygon distance
*/
int lw_dist3d_ptarray_poly(POINTARRAY *pa, LWPOLY *poly,PLANE3D *plane, DISTPTS3D *dl)
{
	

	int i,j,k;
	double f, s1, s2;
	VECTOR3D projp1_projp2;
	POINT3DZ p1, p2,projp1, projp2, intersectionp;
	
	getPoint3dz_p(pa, 0, &p1);
	
	s1=project_point_on_plane(&p1, plane, &projp1); /*the sign of s1 tells us on which side of the plane the point is. */
	lw_dist3d_pt_poly(&p1, poly, plane,&projp1, dl);	
	
	for (i=1;i<pa->npoints;i++)
	{		
		int intersects;
		getPoint3dz_p(pa, i, &p2);
		s2=project_point_on_plane(&p2, plane, &projp2);	
		lw_dist3d_pt_poly(&p2, poly, plane,&projp2, dl);
		
		/*If s1and s2 has different signs that means they are on different sides of the plane of the polygon.
		That means that the edge between the points crosses the plane and might intersect with the polygon*/
		if((s1*s2)<=0) 
		{
			f=fabs(s1)/(fabs(s1)+fabs(s2)); /*The size of s1 and s2 is the distance from the point to the plane.*/
			get_3dvector_from_points(&projp1, &projp2,&projp1_projp2);
			
			/*get the point where the line segment crosses the plane*/
			intersectionp.x=projp1.x+f*projp1_projp2.x;
			intersectionp.y=projp1.y+f*projp1_projp2.y;
			intersectionp.z=projp1.z+f*projp1_projp2.z;
			
			intersects = LW_TRUE; /*We set intersects to true until the opposite is proved*/
			
			if(pt_in_ring_3d(&intersectionp, poly->rings[0], plane)) /*Inside outer ring*/
			{
				for (k=1;k<poly->nrings; k++)
				{
					/* Inside a hole, so no intersection with the polygon*/
					if ( pt_in_ring_3d(&intersectionp, poly->rings[k], plane ))
					{
						intersects=LW_FALSE;
						break;
					}
				}		
				if(intersects) 
				{
					dl->distance=0.0;
					dl->p1.x=intersectionp.x;
					dl->p1.y=intersectionp.y;
					dl->p1.z=intersectionp.z;
					
					dl->p2.x=intersectionp.x;
					dl->p2.y=intersectionp.y;
					dl->p2.z=intersectionp.z;
					return LW_TRUE;
					
				}					
			}			
		}
		
		projp1=projp2;
		s1=s2;
		p1=p2;
	}	
	
	/*check or pointarray against boundary and inner boundaries of the polygon*/
	for (j=0;j<poly->nrings;j++)
	{
		lw_dist3d_ptarray_ptarray(pa, poly->rings[j], dl);
	}
	
return LW_TRUE;
}	
Пример #16
0
/**
 * 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
 */
int
pt_in_ring_3d(const POINT3DZ *p, const POINTARRAY *ring,PLANE3D *plane)
{
	
	int cn = 0;    /* the crossing number counter */
	int i;
	POINT3DZ v1, v2;

	POINT3DZ	first, last;

	getPoint3dz_p(ring, 0, &first);
	getPoint3dz_p(ring, ring->npoints-1, &last);
	if ( memcmp(&first, &last, sizeof(POINT3DZ)) )
	{
		lwerror("pt_in_ring_3d: V[n] != V[0] (%g %g %g!= %g %g %g)",
		        first.x, first.y, first.z, last.x, last.y, last.z);
		return LW_FALSE;
	}

	LWDEBUGF(2, "pt_in_ring_3d called with point: %g %g %g", p->x, p->y, p->z);
	/* printPA(ring); */

	/* loop through all edges of the polygon */
	getPoint3dz_p(ring, 0, &v1);
	
	
	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*/
	{
		for (i=0; i<ring->npoints-1; i++)
		{
			double vt;
			getPoint3dz_p(ring, i+1, &v2);

			/* edge from vertex i to vertex i+1 */
			if
			(
			    /* an upward crossing */
			    ((v1.y <= p->y) && (v2.y > p->y))
			    /* a downward crossing */
			    || ((v1.y > p->y) && (v2.y <= p->y))
			)
			{

				vt = (double)(p->y - v1.y) / (v2.y - v1.y);

				/* P.x <intersect */
				if (p->x < v1.x + vt * (v2.x - v1.x))
				{
					/* a valid crossing of y=p.y right of p.x */
					++cn;
				}
			}
			v1 = v2;
		}
	}
	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*/
	{
		for (i=0; i<ring->npoints-1; i++)
			{
				double vt;
				getPoint3dz_p(ring, i+1, &v2);

				/* edge from vertex i to vertex i+1 */
				if
				(
				    /* an upward crossing */
				    ((v1.z <= p->z) && (v2.z > p->z))
				    /* a downward crossing */
				    || ((v1.z > p->z) && (v2.z <= p->z))
				)
				{

					vt = (double)(p->z - v1.z) / (v2.z - v1.z);

					/* P.x <intersect */
					if (p->x < v1.x + vt * (v2.x - v1.x))
					{
						/* a valid crossing of y=p.y right of p.x */
						++cn;
					}
				}
				v1 = v2;
			}
	}
	else	/*Hopefully we only have the cases where x part of the normal vector is largest left*/
	{
		for (i=0; i<ring->npoints-1; i++)
			{
				double vt;
				getPoint3dz_p(ring, i+1, &v2);

				/* edge from vertex i to vertex i+1 */
				if
				(
				    /* an upward crossing */
				    ((v1.z <= p->z) && (v2.z > p->z))
				    /* a downward crossing */
				    || ((v1.z > p->z) && (v2.z <= p->z))
				)
				{

					vt = (double)(p->z - v1.z) / (v2.z - v1.z);

					/* P.x <intersect */
					if (p->y < v1.y + vt * (v2.y - v1.y))
					{
						/* a valid crossing of y=p.y right of p.x */
						++cn;
					}
				}
				v1 = v2;
			}
	}
	LWDEBUGF(3, "pt_in_ring_3d returning %d", cn&1);

	return (cn&1);    /* 0 if even (out), and 1 if odd (in) */
}
Пример #17
0
/**

Here we define the plane of a polygon (boundary pointarray of a polygon)
the plane is stored as a pont in plane (plane.pop) and a normal vector (plane.pv)
*/
int
define_plane(POINTARRAY *pa, PLANE3D *pl)
{
	int i,j, numberofvectors, pointsinslice;
	POINT3DZ p, p1, p2;

	double sumx=0;
	double sumy=0;
	double sumz=0;
	double vl; /*vector length*/

	VECTOR3D v1, v2, v;
	
	if((pa->npoints-1)==3) /*Triangle is special case*/
	{
		pointsinslice=1;		
	}
	else
	{
		pointsinslice=(int) floor((pa->npoints-1)/4); /*divide the pointarray into 4 slices*/
	}
	
	/*find the avg point*/
	for (i=0;i<(pa->npoints-1);i++)
	{
		getPoint3dz_p(pa, i, &p);
		sumx+=p.x;
		sumy+=p.y;
		sumz+=p.z;		
	}	
	pl->pop.x=(sumx/(pa->npoints-1));
	pl->pop.y=(sumy/(pa->npoints-1));
	pl->pop.z=(sumz/(pa->npoints-1));
	
	sumx=0;
	sumy=0;
	sumz=0;
	numberofvectors= floor((pa->npoints-1)/pointsinslice); /*the number of vectors we try can be 3, 4 or 5*/
	
	getPoint3dz_p(pa, 0, &p1);
	for (j=pointsinslice;j<pa->npoints;j+=pointsinslice)
	{
		getPoint3dz_p(pa, j, &p2);	
		
		if (!get_3dvector_from_points(&(pl->pop), &p1, &v1) || !get_3dvector_from_points(&(pl->pop), &p2, &v2))
			return LW_FALSE;	
		/*perpendicular vector is cross product of v1 and v2*/
		if (!get_3dcross_product(&v1,&v2, &v))
			return LW_FALSE;		
		vl=VECTORLENGTH(v);
		sumx+=(v.x/vl);
		sumy+=(v.y/vl);
		sumz+=(v.z/vl);	
		p1=p2;
	}
	pl->pv.x=(sumx/numberofvectors);
	pl->pv.y=(sumy/numberofvectors);
	pl->pv.z=(sumz/numberofvectors);
	
	return 1;
}
Пример #18
0
/* convenience functions to hide the POINTARRAY */
int
lwpoint_getPoint3dz_p(const LWPOINT *point, POINT3DZ *out)
{
	return getPoint3dz_p(point->point,0,out);
}