/** This function is used to create a vertical line used for cases where one if the geometries lacks z-values. The vertical line crosses the 2d point that is closest and the z-range is from maxz to minz in the geoemtrie that has z values. */ static LWGEOM* create_v_line(const LWGEOM *lwgeom,double x, double y, int srid) { LWPOINT *lwpoints[2]; GBOX gbox; int rv = lwgeom_calculate_gbox(lwgeom, &gbox); if ( rv == LW_FAILURE ) return NULL; lwpoints[0] = lwpoint_make3dz(srid, x, y, gbox.zmin); lwpoints[1] = lwpoint_make3dz(srid, x, y, gbox.zmax); return (LWGEOM *)lwline_from_ptarray(srid, 2, lwpoints); }
/** Function initializing 3dshortestline and 3dlongestline calculations. */ LWGEOM * lw_dist3d_distanceline(LWGEOM *lw1, LWGEOM *lw2,int srid,int mode) { double x1,x2,y1,y2, z1, z2; double initdistance = ( mode == DIST_MIN ? MAXFLOAT : -1.0); DISTPTS3D thedl; LWPOINT *lwpoints[2]; LWGEOM *result; thedl.mode = mode; thedl.distance = initdistance; thedl.tolerance = 0.0; LWDEBUG(2, "lw_dist3d_distanceline is called"); 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) { LWDEBUG(3, "didn't find geometries to measure between, returning null"); result = (LWGEOM *)lwcollection_construct_empty(COLLECTIONTYPE, srid, 0, 0); } else { x1=thedl.p1.x; y1=thedl.p1.y; z1=thedl.p1.z; x2=thedl.p2.x; y2=thedl.p2.y; z2=thedl.p2.z; lwpoints[0] = lwpoint_make3dz(srid, x1, y1, z1); lwpoints[1] = lwpoint_make3dz(srid, x2, y2, z2); result = (LWGEOM *)lwline_from_lwpointarray(srid, 2, lwpoints); } return result; }
/** Function initializing 3dclosestpoint calculations. */ LWGEOM * lw_dist3d_distancepoint(LWGEOM *lw1, LWGEOM *lw2,int srid,int mode) { double x,y,z; DISTPTS3D thedl; double initdistance = MAXFLOAT; LWGEOM *result; thedl.mode = mode; thedl.distance= initdistance; thedl.tolerance = 0; LWDEBUG(2, "lw_dist3d_distancepoint is called"); 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"); result = (LWGEOM *)lwcollection_construct_empty(COLLECTIONTYPE, srid, 0, 0); } else { x=thedl.p1.x; y=thedl.p1.y; z=thedl.p1.z; result = (LWGEOM *)lwpoint_make3dz(srid, x, y, z); } return result; }
/** Function initializing 3dshortestline and 3dlongestline calculations. */ 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, x, y; double initdistance = ( mode == DIST_MIN ? FLT_MAX : -1.0); DISTPTS3D thedl; LWPOINT *lwpoints[2]; LWGEOM *result; thedl.mode = mode; thedl.distance = initdistance; thedl.tolerance = 0.0; /*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(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); } LWGEOM *vertical_line; if(!lwgeom_has_z(lw1)) { x=thedl2d.p1.x; y=thedl2d.p1.y; vertical_line = create_v_line(lw2,x,y,srid); if (!lw_dist3d_recursive(vertical_line, lw2, &thedl)) { /*should never get here. all cases ought to be error handled earlier*/ lwfree(vertical_line); lwerror("Some unspecified error."); result = (LWGEOM *)lwcollection_construct_empty(COLLECTIONTYPE, srid, 0, 0); } lwfree(vertical_line); } if(!lwgeom_has_z(lw2)) { x=thedl2d.p2.x; y=thedl2d.p2.y; vertical_line = create_v_line(lw1,x,y,srid); if (!lw_dist3d_recursive(lw1, vertical_line, &thedl)) { /*should never get here. all cases ought to be error handled earlier*/ lwfree(vertical_line); lwerror("Some unspecified error."); return (LWGEOM *)lwcollection_construct_empty(COLLECTIONTYPE, srid, 0, 0); } lwfree(vertical_line); } } 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) { LWDEBUG(3, "didn't find geometries to measure between, returning null"); result = (LWGEOM *)lwcollection_construct_empty(COLLECTIONTYPE, srid, 0, 0); } else { x1=thedl.p1.x; y1=thedl.p1.y; z1=thedl.p1.z; x2=thedl.p2.x; y2=thedl.p2.y; z2=thedl.p2.z; lwpoints[0] = lwpoint_make3dz(srid, x1, y1, z1); lwpoints[1] = lwpoint_make3dz(srid, x2, y2, z2); result = (LWGEOM *)lwline_from_ptarray(srid, 2, lwpoints); } return result; }