extern double distance2d_sqr_pt_pt(const POINT2D *p1, const POINT2D *p2);
extern double distance2d_pt_seg(const POINT2D *p, const POINT2D *A, const POINT2D *B);
extern double distance2d_sqr_pt_seg(const POINT2D *p, const POINT2D *A, const POINT2D *B);
-extern LWGEOM* lwgeom_closest_line(LWGEOM *lw1, LWGEOM *lw2);
-extern LWGEOM* lwgeom_furthest_line(LWGEOM *lw1, LWGEOM *lw2);
-extern LWGEOM* lwgeom_closest_point(LWGEOM *lw1, LWGEOM *lw2);
-extern LWGEOM* lwgeom_furthest_point(LWGEOM *lw1, LWGEOM *lw2);
-extern double lwgeom_mindistance2d(LWGEOM *lw1, LWGEOM *lw2);
-extern double lwgeom_mindistance2d_tolerance(LWGEOM *lw1, LWGEOM *lw2, double tolerance);
-extern double lwgeom_maxdistance2d(LWGEOM *lw1, LWGEOM *lw2);
-extern double lwgeom_maxdistance2d_tolerance(LWGEOM *lw1, LWGEOM *lw2, double tolerance);
+extern LWGEOM* lwgeom_closest_line(const LWGEOM *lw1, const LWGEOM *lw2);
+extern LWGEOM* lwgeom_furthest_line(const LWGEOM *lw1, const LWGEOM *lw2);
+extern LWGEOM* lwgeom_closest_point(const LWGEOM *lw1, const LWGEOM *lw2);
+extern LWGEOM* lwgeom_furthest_point(const LWGEOM *lw1, const LWGEOM *lw2);
+extern double lwgeom_mindistance2d(const LWGEOM *lw1, const LWGEOM *lw2);
+extern double lwgeom_mindistance2d_tolerance(const LWGEOM *lw1, const LWGEOM *lw2, double tolerance);
+extern double lwgeom_maxdistance2d(const LWGEOM *lw1, const LWGEOM *lw2);
+extern double lwgeom_maxdistance2d_tolerance(const LWGEOM *lw1, const LWGEOM *lw2, double tolerance);
/* 3D */
extern double distance3d_pt_pt(const POINT3D *p1, const POINT3D *p2);
--------------------------------------------------------------------------------------------------------------*/
LWGEOM *
-lwgeom_closest_line(LWGEOM *lw1, LWGEOM *lw2)
+lwgeom_closest_line(const LWGEOM *lw1, const LWGEOM *lw2)
{
return lw_dist2d_distanceline(lw1, lw2, lw1->srid, DIST_MIN);
}
LWGEOM *
-lwgeom_furthest_line(LWGEOM *lw1, LWGEOM *lw2)
+lwgeom_furthest_line(const LWGEOM *lw1, const LWGEOM *lw2)
{
return lw_dist2d_distanceline(lw1, lw2, lw1->srid, DIST_MAX);
}
LWGEOM *
-lwgeom_closest_point(LWGEOM *lw1, LWGEOM *lw2)
+lwgeom_closest_point(const LWGEOM *lw1, const LWGEOM *lw2)
{
return lw_dist2d_distancepoint(lw1, lw2, lw1->srid, DIST_MIN);
}
LWGEOM *
-lwgeom_furthest_point(LWGEOM *lw1, LWGEOM *lw2)
+lwgeom_furthest_point(const LWGEOM *lw1, const LWGEOM *lw2)
{
return lw_dist2d_distancepoint(lw1, lw2, lw1->srid, DIST_MAX);
}
Function initializing shortestline and longestline calculations.
*/
LWGEOM *
-lw_dist2d_distanceline(LWGEOM *lw1, LWGEOM *lw2, int srid, int mode)
+lw_dist2d_distanceline(const LWGEOM *lw1, const LWGEOM *lw2, int srid, int mode)
{
double x1,x2,y1,y2;
Function initializing closestpoint calculations.
*/
LWGEOM *
-lw_dist2d_distancepoint(LWGEOM *lw1, LWGEOM *lw2,int srid,int mode)
+lw_dist2d_distancepoint(const LWGEOM *lw1, const LWGEOM *lw2,int srid,int mode)
{
double x,y;
DISTPTS thedl;
Function initialazing max distance calculation
*/
double
-lwgeom_maxdistance2d(LWGEOM *lw1, LWGEOM *lw2)
+lwgeom_maxdistance2d(const LWGEOM *lw1, const LWGEOM *lw2)
{
LWDEBUG(2, "lwgeom_maxdistance2d is called");
The difference is just the tolerance.
*/
double
-lwgeom_maxdistance2d_tolerance(LWGEOM *lw1, LWGEOM *lw2, double tolerance)
+lwgeom_maxdistance2d_tolerance(const LWGEOM *lw1, const LWGEOM *lw2, double tolerance)
{
/*double thedist;*/
DISTPTS thedl;
Function initialazing min distance calculation
*/
double
-lwgeom_mindistance2d(LWGEOM *lw1, LWGEOM *lw2)
+lwgeom_mindistance2d(const LWGEOM *lw1, const LWGEOM *lw2)
{
LWDEBUG(2, "lwgeom_mindistance2d is called");
return lwgeom_mindistance2d_tolerance( lw1, lw2, 0.0 );
The difference is just the tolerance.
*/
double
-lwgeom_mindistance2d_tolerance(LWGEOM *lw1, LWGEOM *lw2, double tolerance)
+lwgeom_mindistance2d_tolerance(const LWGEOM *lw1, const LWGEOM *lw2, double tolerance)
{
DISTPTS thedl;
LWDEBUG(2, "lwgeom_mindistance2d_tolerance is called");
bboxes we will use anyway.
*/
int
-lw_dist2d_comp(LWGEOM *lw1, LWGEOM *lw2, DISTPTS *dl)
+lw_dist2d_comp(const LWGEOM *lw1,const LWGEOM *lw2, DISTPTS *dl)
{
LWDEBUG(2, "lw_dist2d_comp is called");
int
-lw_dist2d_distribute_bruteforce(LWGEOM *lwg1, LWGEOM *lwg2, DISTPTS *dl)
+lw_dist2d_distribute_bruteforce(const LWGEOM *lwg1,const LWGEOM *lwg2, DISTPTS *dl)
{
int t1 = lwg1->type;
/*
* Preprocessing functions
*/
-int lw_dist2d_comp(LWGEOM *lw1, LWGEOM *lw2, DISTPTS *dl);
-int lw_dist2d_distribute_bruteforce(LWGEOM *lwg1, LWGEOM *lwg2, DISTPTS *dl);
+int lw_dist2d_comp(const LWGEOM *lw1, const LWGEOM *lw2, DISTPTS *dl);
+int lw_dist2d_distribute_bruteforce(const LWGEOM *lwg1, const LWGEOM *lwg2, DISTPTS *dl);
int lw_dist2d_recursive(const LWGEOM *lwg1, const LWGEOM *lwg2, DISTPTS *dl);
int lw_dist2d_check_overlap(LWGEOM *lwg1, LWGEOM *lwg2);
int lw_dist2d_distribute_fast(LWGEOM *lwg1, LWGEOM *lwg2, DISTPTS *dl);
/*
* Geometry returning functions
*/
-LWGEOM* lw_dist2d_distancepoint(LWGEOM *lw1, LWGEOM *lw2, int srid, int mode);
-LWGEOM* lw_dist2d_distanceline(LWGEOM *lw1, LWGEOM *lw2, int srid, int mode);
+LWGEOM* lw_dist2d_distancepoint(const LWGEOM *lw1, const LWGEOM *lw2, int srid, int mode);
+LWGEOM* lw_dist2d_distanceline(const LWGEOM *lw1, const LWGEOM *lw2, int srid, int mode);
LWGEOM *
lw_dist3d_distanceline(const LWGEOM *lw1, const LWGEOM *lw2, int srid, int mode)
{
+ LWDEBUG(2, "lw_dist3d_distanceline is called");
double x1,x2,y1,y2, z1, z2;
double initdistance = ( mode == DIST_MIN ? FLT_MAX : -1.0);
DISTPTS3D thedl;
thedl.distance = initdistance;
thedl.tolerance = 0.0;
- LWDEBUG(2, "lw_dist3d_distanceline is called");
- if (!lw_dist3d_recursive(lw1, lw2, &thedl))
+ /*Check if we really have 3D geoemtries*/
+ /*If not, send it to 2D-calculations which will give the same result*/
+ /*as an infinite z-value at one or two of the geometries*/
+ if(!lwgeom_has_z(lw1) || !lwgeom_has_z(lw2))
{
- /*should never get here. all cases ought to be error handled earlier*/
- lwerror("Some unspecified error.");
- result = (LWGEOM *)lwcollection_construct_empty(COLLECTIONTYPE, srid, 0, 0);
+ lwnotice("One or both of the geometries is missing z-value. The unknown z-value will be regarded as 'any value'");
+
+ if(!lwgeom_has_z(lw1) && !lwgeom_has_z(lw2))
+ return lw_dist2d_distanceline(lw1, lw2, srid, mode);
+
+ DISTPTS thedl2d;
+ thedl2d.mode = mode;
+ thedl2d.distance = initdistance;
+ thedl2d.tolerance = 0.0;
+ if (!lw_dist2d_comp( lw1,lw2,&thedl2d))
+ {
+ /*should never get here. all cases ought to be error handled earlier*/
+ lwerror("Some unspecified error.");
+ result = (LWGEOM *)lwcollection_construct_empty(COLLECTIONTYPE, srid, 0, 0);
+ }
+
+ if(!lwgeom_has_z(lw1))
+ {
+ LWGEOM *new_lw1;
+ x1=thedl2d.p1.x;
+ y1=thedl2d.p1.y;
+ lwpoints[0] = lwpoint_make3dz(srid, x1, y1, FLT_MIN);
+ lwpoints[1] = lwpoint_make3dz(srid, x1, y1, FLT_MAX);
+
+ new_lw1 = (LWGEOM *)lwline_from_ptarray(srid, 2, lwpoints);
+ if (!lw_dist3d_recursive(new_lw1, lw2, &thedl))
+ {
+ /*should never get here. all cases ought to be error handled earlier*/
+ lwerror("Some unspecified error.");
+ result = (LWGEOM *)lwcollection_construct_empty(COLLECTIONTYPE, srid, 0, 0);
+ }
+ }
+ if(!lwgeom_has_z(lw2))
+ {
+ LWGEOM *new_lw2;
+ x2=thedl2d.p2.x;
+ y2=thedl2d.p2.y;
+ lwpoints[0] = lwpoint_make3dz(srid, x2, y2, FLT_MIN);
+ lwpoints[1] = lwpoint_make3dz(srid, x2, y2, FLT_MAX);
+
+ new_lw2 = (LWGEOM *)lwline_from_ptarray(srid, 2, lwpoints);
+ if (!lw_dist3d_recursive(lw1, new_lw2, &thedl))
+ {
+ /*should never get here. all cases ought to be error handled earlier*/
+ lwerror("Some unspecified error.");
+ result = (LWGEOM *)lwcollection_construct_empty(COLLECTIONTYPE, srid, 0, 0);
+ }
+ }
+
+ }
+ else
+ {
+ if (!lw_dist3d_recursive(lw1, lw2, &thedl))
+ {
+ /*should never get here. all cases ought to be error handled earlier*/
+ lwerror("Some unspecified error.");
+ result = (LWGEOM *)lwcollection_construct_empty(COLLECTIONTYPE, srid, 0, 0);
+ }
}
-
/*if thedl.distance is unchanged there where only empty geometries input*/
if (thedl.distance == initdistance)
{
y2=thedl.p2.y;
z2=thedl.p2.z;
-
lwpoints[0] = lwpoint_make3dz(srid, x1, y1, z1);
lwpoints[1] = lwpoint_make3dz(srid, x2, y2, z2);
LWGEOM *
lw_dist3d_distancepoint(const LWGEOM *lw1, const LWGEOM *lw2, int srid, int mode)
{
+
double x,y,z;
DISTPTS3D thedl;
double initdistance = FLT_MAX;
thedl.tolerance = 0;
LWDEBUG(2, "lw_dist3d_distancepoint is called");
+
+ /*Check if we really have 3D geoemtries*/
+ /*If not, send it to 2D-calculations which will give the same result*/
+ /*as an infinite z-value at one or two of the geometries*/
+ if(!lwgeom_has_z(lw1) || !lwgeom_has_z(lw2))
+ {
+ lwnotice("One or both of the geometries is missing z-value. The unknown z-value will be regarded as 'any value'");
+
+
+ if(!lwgeom_has_z(lw2))
+ return lw_dist2d_distancepoint(lw1, lw2, srid, mode);
+
+
+ DISTPTS thedl2d;
+ thedl2d.mode = mode;
+ thedl2d.distance = initdistance;
+ thedl2d.tolerance = 0.0;
+ if (!lw_dist2d_comp( lw1,lw2,&thedl2d))
+ {
+ /*should never get here. all cases ought to be error handled earlier*/
+ lwerror("Some unspecified error.");
+ result = (LWGEOM *)lwcollection_construct_empty(COLLECTIONTYPE, srid, 0, 0);
+ }
+
+ if(!lwgeom_has_z(lw1))
+ {
+ LWPOINT *lwpoints[2];
+ LWGEOM *new_lw1;
+ x=thedl2d.p1.x;
+ y=thedl2d.p1.y;
- if (!lw_dist3d_recursive(lw1, lw2, &thedl))
+ lwpoints[0] = lwpoint_make3dz(srid, x, y, FLT_MIN);
+ lwpoints[1] = lwpoint_make3dz(srid, x, y, FLT_MAX);
+
+ new_lw1 = (LWGEOM *)lwline_from_ptarray(srid, 2, lwpoints);
+ if (!lw_dist3d_recursive(new_lw1, lw2, &thedl))
+ {
+ /*should never get here. all cases ought to be error handled earlier*/
+ lwerror("Some unspecified error.");
+ result = (LWGEOM *)lwcollection_construct_empty(COLLECTIONTYPE, srid, 0, 0);
+ }
+ }
+
+ }
+ else
{
- /*should never get here. all cases ought to be error handled earlier*/
- lwerror("Some unspecified error.");
- result = (LWGEOM *)lwcollection_construct_empty(COLLECTIONTYPE, srid, 0, 0);
+ if (!lw_dist3d_recursive(lw1, lw2, &thedl))
+ {
+ /*should never get here. all cases ought to be error handled earlier*/
+ lwerror("Some unspecified error.");
+ result = (LWGEOM *)lwcollection_construct_empty(COLLECTIONTYPE, srid, 0, 0);
+ }
}
-
if (thedl.distance == initdistance)
{
LWDEBUG(3, "didn't find geometries to measure between, returning null");
double
lwgeom_maxdistance3d_tolerance(const LWGEOM *lw1, const LWGEOM *lw2, double tolerance)
{
+ if(!lwgeom_has_z(lw1) || !lwgeom_has_z(lw2))
+ {
+ lwnotice("One or both of the geometries is missing z-value. The unknown z-value will be regarded as 'any value'");
+ return lwgeom_maxdistance2d_tolerance(lw1, lw2, tolerance);
+ }
/*double thedist;*/
DISTPTS3D thedl;
LWDEBUG(2, "lwgeom_maxdistance3d_tolerance is called");
double
lwgeom_mindistance3d_tolerance(const LWGEOM *lw1, const LWGEOM *lw2, double tolerance)
{
+ if(!lwgeom_has_z(lw1) || !lwgeom_has_z(lw2))
+ {
+ lwnotice("One or both of the geometries is missing z-value. The unknown z-value will be regarded as 'any value'");
+ return lwgeom_mindistance2d_tolerance(lw1, lw2, tolerance);
+ }
DISTPTS3D thedl;
LWDEBUG(2, "lwgeom_mindistance3d_tolerance is called");
thedl.mode = DIST_MIN;
#ifndef _MEASURES3D_H
#define _MEASURES3D_H 1
-
+#include <float.h>
#include "measures.h"
#define DOT(u,v) ((u).x * (v).x + (u).y * (v).y + (u).z * (v).z)
ST_3DDistance(a,b) FROM (
SELECT 'LINESTRING(1 1 1 , 2 2 2)'::geometry as a, 'POLYGON((0 0 0, 2 2 2, 3 3 3, 0 0 0))'::geometry as b) as foo;
+
+-- 3D mixed dimmentionality #2034
+--closestpoint with 2d as first point and 3d as second
+select st_astext(st_3dclosestpoint('linestring(0 0,1 1,2 0)'::geometry, 'linestring(0 2 3, 3 2 3)'::geometry));
+
+--closestpoint with 3d as first point and 2d as second
+select st_astext(st_3dclosestpoint('linestring(0 0 1,1 1 2,2 0 3)'::geometry, 'linestring(0 2, 3 2)'::geometry));
+
+--shortestline with 2d as first point and 3d as second
+select st_astext(st_3dshortestline('linestring(0 0,1 1,2 0)'::geometry, 'linestring(0 2 3, 3 2 3)'::geometry));
+
+--shortestline with 3d as first point and 2d as second
+select st_astext(st_3dshortestline('linestring(0 0 1,1 1 2,2 0 3)'::geometry, 'linestring(0 2, 3 2)'::geometry));
+
+--distance with 2d as first point and 3d as second
+select st_3ddistance('linestring(0 0,1 1,2 0)'::geometry, 'linestring(0 2 3, 3 2 3)'::geometry);
+
+--distance with 3d as first point and 2d as second
+select st_3ddistance('linestring(0 0 1,1 1 2,2 0 3)'::geometry, 'linestring(0 2, 3 2)'::geometry);
+
+
+
+
-- Area of an empty polygon
select 'emptyPolyArea', st_area('POLYGON EMPTY');
3dDistancetest4|2|10.0498756211209|t|f|LINESTRING(1 1 3,1 1 1)|POINT(1 1 3)|LINESTRING(5 7 8,1 1 1)
3dDistancetest5|2|10|t|f|LINESTRING(5 0 5,5 2 5)|POINT(5 0 5)|LINESTRING(11 0 5,5 0 13)
3dDistancetest6|0
+NOTICE: One or both of the geometries is missing z-value. The unknown z-value will be regarded as 'any value'
+POINT Z (1 1 3)
+NOTICE: One or both of the geometries is missing z-value. The unknown z-value will be regarded as 'any value'
+POINT(1 1)
+NOTICE: One or both of the geometries is missing z-value. The unknown z-value will be regarded as 'any value'
+LINESTRING Z (1 1 3,1 2 3)
+NOTICE: One or both of the geometries is missing z-value. The unknown z-value will be regarded as 'any value'
+LINESTRING Z (1 1 2,1 2 2)
+NOTICE: One or both of the geometries is missing z-value. The unknown z-value will be regarded as 'any value'
+1
+NOTICE: One or both of the geometries is missing z-value. The unknown z-value will be regarded as 'any value'
+1
emptyPolyArea|0
emptyLineArea|0
emptyPointArea|0