Ticket #63: max_distance.patch

File max_distance.patch, 56.3 KB (added by nicklas, 3 years ago)
  • liblwgeom/liblwgeom.h

     
    99 * 
    1010 * This is free software; you can redistribute and/or modify it under 
    1111 * the terms of the GNU General Public Licence. See the COPYING file. 
    12  *  
     12 * 
    1313 **********************************************************************/ 
    1414 
    1515#ifndef _LIBLWGEOM_H 
     
    2121 
    2222/** 
    2323* @file liblwgeom.h 
    24 *  
     24* 
    2525* This library is the generic geometry handling section of PostGIS. The geometry 
    2626* objects, constructors, destructors, and a set of spatial processing functions, 
    27 * are implemented here.  
    28 *  
    29 * The library is designed for use in non-PostGIS applications if necessary. The  
    30 * units tests at cunit/cu_tester.c and the loader/dumper programs at  
     27* are implemented here. 
     28* 
     29* The library is designed for use in non-PostGIS applications if necessary. The 
     30* units tests at cunit/cu_tester.c and the loader/dumper programs at 
    3131* ../loader/shp2pgsql.c are examples of non-PostGIS applications using liblwgeom. 
    32 *  
     32* 
    3333* Programs using this library should set up the default memory managers and error 
    34 * handlers by implementing an lwgeom_init_allocators() function, which can be as  
     34* handlers by implementing an lwgeom_init_allocators() function, which can be as 
    3535* a wrapper around the lwgeom_install_default_allocators() function if you want 
    3636* no special handling for memory management and error reporting. 
    3737*/ 
     
    7171 
    7272#endif 
    7373 
    74 /**  
    75 * Global functions for memory/logging handlers.  
     74/** 
     75* Global functions for memory/logging handlers. 
    7676*/ 
    7777typedef void* (*lwallocator)(size_t size); 
    7878typedef void* (*lwreallocator)(void *mem, size_t size); 
     
    113113void lwerror(const char *fmt, ...); 
    114114 
    115115/** 
    116 * The default memory/logging handlers installed by lwgeom_install_default_allocators()  
     116* The default memory/logging handlers installed by lwgeom_install_default_allocators() 
    117117*/ 
    118118void *default_allocator(size_t size); 
    119119void *default_reallocator(void *mem, size_t size); 
     
    167167 
    168168typedef struct 
    169169{ 
    170         double xmin, ymin, zmin; 
    171         double xmax, ymax, zmax; 
     170        double xmin, ymin, zmin; 
     171        double xmax, ymax, zmax; 
    172172} BOX3D; 
    173173 
    174174typedef struct chiptag 
     
    241241 * NOTE: for GEOS integration, we'll probably set z=NaN 
    242242 *        so look out - z might be NaN for 2d geometries! 
    243243 */ 
    244 typedef struct { double x,y,z; } POINT3DZ; 
    245 typedef struct { double x,y,z; } POINT3D; /* alias for POINT3DZ */ 
    246 typedef struct { double x,y,m; } POINT3DM; 
     244typedef struct 
     245{ 
     246        double  x,y,z; 
     247} POINT3DZ; 
     248typedef struct 
     249{ 
     250        double  x,y,z; 
     251} POINT3D; /* alias for POINT3DZ */ 
     252typedef struct 
     253{ 
     254        double  x,y,m; 
     255} POINT3DM; 
    247256 
    248257 
    249258/* 
     
    252261 */ 
    253262typedef struct 
    254263{ 
    255          double x; 
    256          double y; 
     264        double x; 
     265        double y; 
    257266} POINT2D; 
    258267 
    259268typedef struct 
    260269{ 
    261          double x; 
    262          double y; 
    263          double z; 
    264          double m; 
     270        double x; 
     271        double y; 
     272        double z; 
     273        double m; 
    265274} POINT4D; 
    266275 
     276typedef struct 
     277{ 
     278        double d;       /*the distance between p1 and p2*/ 
     279        POINT2D p1; 
     280        POINT2D p2; 
     281        int thedir;     /*the direction of looking, if thedir = -1 then we look for maxdistance and if it is 1 then we look for mindistance*/ 
     282        int twisted; /*To preserve the order of incoming points to match the first and secon point in shortest and longest line*/ 
     283} DISTPTS; 
    267284/******************************************************************/ 
    268285 
    269286/* 
     
    274291 */ 
    275292typedef struct 
    276293{ 
    277     /* array of POINT 2D, 3D or 4D. probably missaligned. */ 
    278     uchar *serialized_pointlist; 
     294        /* array of POINT 2D, 3D or 4D. probably missaligned. */ 
     295        uchar *serialized_pointlist; 
    279296 
    280     /* use TYPE_* macros to handle */ 
    281     uchar  dims; 
     297        /* use TYPE_* macros to handle */ 
     298        uchar  dims; 
    282299 
    283     uint32 npoints; 
     300        uint32 npoints; 
    284301}  POINTARRAY; 
    285302 
    286303 
    287304/* 
    288305 * Use the following to build pointarrays 
    289  * when number of points in output is not  
     306 * when number of points in output is not 
    290307 * known in advance 
    291308 */ 
    292 typedef struct { 
     309typedef struct 
     310{ 
    293311        POINTARRAY *pa; 
    294312        size_t ptsize; 
    295313        size_t capacity; /* given in points */ 
     
    311329 * respectively. 
    312330 */ 
    313331extern int dynptarray_addPoint4d(DYNPTARRAY *dpa, POINT4D *p4d, 
    314         int allow_duplicates); 
     332                                 int allow_duplicates); 
    315333 
    316334/****************************************************************** 
    317335 * 
     
    321339 
    322340typedef struct 
    323341{ 
    324         uchar type;  
     342        uchar type; 
    325343        BOX2DFLOAT4 *bbox; 
    326344        uint32 SRID; /* -1 == unneeded */ 
    327345        void *data; 
     
    332350{ 
    333351        uchar type; /* POINTTYPE */ 
    334352        BOX2DFLOAT4 *bbox; 
    335         uint32 SRID;     
    336         POINTARRAY *point;  /* hide 2d/3d (this will be an array of 1 point) */ 
     353        uint32 SRID; 
     354        POINTARRAY *point;  /* hide 2d/3d (this will be an array of 1 point) */ 
    337355}  LWPOINT; /* "light-weight point" */ 
    338356 
    339357/* LINETYPE */ 
     
    341359{ 
    342360        uchar type; /* LINETYPE */ 
    343361        BOX2DFLOAT4 *bbox; 
    344         uint32 SRID;     
     362        uint32 SRID; 
    345363        POINTARRAY    *points; /* array of POINT3D */ 
    346364} LWLINE; /* "light-weight line" */ 
    347365 
     
    350368{ 
    351369        uchar type; /* POLYGONTYPE */ 
    352370        BOX2DFLOAT4 *bbox; 
    353         uint32 SRID;     
     371        uint32 SRID; 
    354372        int  nrings; 
    355373        POINTARRAY **rings; /* list of rings (list of points) */ 
    356374} LWPOLY; /* "light-weight polygon" */ 
     
    358376/* MULTIPOINTTYPE */ 
    359377typedef struct 
    360378{ 
    361         uchar type;   
     379        uchar type; 
    362380        BOX2DFLOAT4 *bbox; 
    363         uint32 SRID;     
     381        uint32 SRID; 
    364382        int  ngeoms; 
    365383        LWPOINT **geoms; 
    366 } LWMPOINT;  
     384} LWMPOINT; 
    367385 
    368386/* MULTILINETYPE */ 
    369387typedef struct 
    370 {   
    371         uchar type;  
     388{ 
     389        uchar type; 
    372390        BOX2DFLOAT4 *bbox; 
    373         uint32 SRID;     
     391        uint32 SRID; 
    374392        int  ngeoms; 
    375393        LWLINE **geoms; 
    376 } LWMLINE;  
     394} LWMLINE; 
    377395 
    378396/* MULTIPOLYGONTYPE */ 
    379397typedef struct 
    380 {   
    381         uchar type;  
     398{ 
     399        uchar type; 
    382400        BOX2DFLOAT4 *bbox; 
    383         uint32 SRID;     
     401        uint32 SRID; 
    384402        int  ngeoms; 
    385403        LWPOLY **geoms; 
    386 } LWMPOLY;  
     404} LWMPOLY; 
    387405 
    388406/* COLLECTIONTYPE */ 
    389407typedef struct 
    390 {    
    391         uchar type;  
     408{ 
     409        uchar type; 
    392410        BOX2DFLOAT4 *bbox; 
    393         uint32 SRID;     
     411        uint32 SRID; 
    394412        int  ngeoms; 
    395413        LWGEOM **geoms; 
    396 } LWCOLLECTION;  
     414} LWCOLLECTION; 
    397415 
    398416/* CIRCSTRINGTYPE */ 
    399417typedef struct 
    400418{ 
    401         uchar type; /* CIRCSTRINGTYPE */ 
    402         BOX2DFLOAT4 *bbox; 
    403         uint32 SRID; 
    404         POINTARRAY *points; /* array of POINT(3D/3DM) */ 
     419        uchar type; /* CIRCSTRINGTYPE */ 
     420        BOX2DFLOAT4 *bbox; 
     421        uint32 SRID; 
     422        POINTARRAY *points; /* array of POINT(3D/3DM) */ 
    405423} LWCIRCSTRING; /* "light-weight circularstring" */ 
    406424 
    407425/* COMPOUNDTYPE */ 
    408426typedef struct 
    409427{ 
    410         uchar type; /* COMPOUNDTYPE */ 
    411         BOX2DFLOAT4 *bbox; 
    412         uint32 SRID; 
    413         int ngeoms; 
    414         LWGEOM **geoms; 
     428        uchar type; /* COMPOUNDTYPE */ 
     429        BOX2DFLOAT4 *bbox; 
     430        uint32 SRID; 
     431        int ngeoms; 
     432        LWGEOM **geoms; 
    415433} LWCOMPOUND; /* "light-weight compound line" */ 
    416434 
    417435/* CURVEPOLYTYPE */ 
    418436typedef struct 
    419437{ 
    420         uchar type; /* CURVEPOLYTYPE */ 
    421         BOX2DFLOAT4 *bbox; 
    422         uint32 SRID; 
    423         int nrings; 
    424         LWGEOM **rings; /* list of rings (list of points) */ 
     438        uchar type; /* CURVEPOLYTYPE */ 
     439        BOX2DFLOAT4 *bbox; 
     440        uint32 SRID; 
     441        int nrings; 
     442        LWGEOM **rings; /* list of rings (list of points) */ 
    425443} LWCURVEPOLY; /* "light-weight polygon" */ 
    426444 
    427445/* MULTICURVE */ 
    428446typedef struct 
    429447{ 
    430         uchar type; 
    431         BOX2DFLOAT4 *bbox; 
    432         uint32 SRID; 
    433         int ngeoms; 
    434         LWGEOM **geoms; 
     448        uchar type; 
     449        BOX2DFLOAT4 *bbox; 
     450        uint32 SRID; 
     451        int ngeoms; 
     452        LWGEOM **geoms; 
    435453} LWMCURVE; 
    436454 
    437455/* MULTISURFACETYPE */ 
    438456typedef struct 
    439457{ 
    440         uchar type; 
    441         BOX2DFLOAT4 *bbox; 
    442         uint32 SRID; 
    443         int ngeoms; 
    444         LWGEOM **geoms; 
     458        uchar type; 
     459        BOX2DFLOAT4 *bbox; 
     460        uint32 SRID; 
     461        int ngeoms; 
     462        LWGEOM **geoms; 
    445463} LWMSURFACE; 
    446464 
    447465/* Casts LWGEOM->LW* (return NULL if cast is illegal) */ 
     
    466484extern LWGEOM *lwpoint_as_lwgeom(LWPOINT *obj); 
    467485 
    468486/* 
    469  * Call this function everytime LWGEOM coordinates  
     487 * Call this function everytime LWGEOM coordinates 
    470488 * change so to invalidate bounding box 
    471489 */ 
    472490extern void lwgeom_changed(LWGEOM *lwgeom); 
     
    552570 * possibly corrupt the POINTARRAY. 
    553571 * 
    554572 * WARNING: Don't cast this to a POINT ! 
    555  * it would not be reliable due to memory alignment constraints  
     573 * it would not be reliable due to memory alignment constraints 
    556574 */ 
    557575extern uchar *getPoint_internal(const POINTARRAY *pa, int n); 
    558576 
     
    568586 *       'points' points to.  No data conversion is done. 
    569587 */ 
    570588extern POINTARRAY *pointArray_construct(uchar *points, char hasz, char hasm, 
    571         uint32 npoints); 
     589                                        uint32 npoints); 
    572590 
    573 /*  
     591/* 
    574592 * Calculate the (BOX3D) bounding box of a set of points. 
    575593 * Returns an alloced BOX3D or NULL (for empty geom) in the first form. 
    576594 * Write result in user-provided BOX3D in second form (return 0 if untouched). 
     
    639657 * This is the binary representation of lwgeom compatible 
    640658 * with postgresql varlena struct 
    641659 */ 
    642 typedef struct { 
     660typedef struct 
     661{ 
    643662        uint32 size;        /* varlena header (do not touch directly!) */ 
    644663        uchar type;         /* encodes ndims, type, bbox presence, 
    645664                                srid presence */ 
     
    656675 * from the serialized form. 
    657676 */ 
    658677extern PG_LWGEOM *PG_LWGEOM_construct(uchar *serialized, int SRID, 
    659         int wantbbox); 
     678                                      int wantbbox); 
    660679 
    661680/* 
    662681 * Compute bbox of serialized geom 
     
    715734 
    716735/* 
    717736 * convert this point into its serialize form 
    718  * result's first char will be the 8bit type.  
     737 * result's first char will be the 8bit type. 
    719738 * See serialized form doc 
    720739 */ 
    721740extern uchar *lwpoint_serialize(LWPOINT *point); 
     
    724743extern void lwpoint_serialize_buf(LWPOINT *point, uchar *buf, size_t *size); 
    725744 
    726745/* 
    727  * find bounding box (standard one)  
     746 * find bounding box (standard one) 
    728747 * zmin=zmax=0 if 2d (might change to NaN) 
    729748 */ 
    730749extern BOX3D *lwpoint_compute_box3d(LWPOINT *point); 
     
    10601079 * MEMORY MANAGEMENT 
    10611080 ****************************************************************/ 
    10621081 
    1063 /*  
    1064  * The lwfree_* family of functions frees *all* memory associated  
     1082/* 
     1083 * The lwfree_* family of functions frees *all* memory associated 
    10651084 * with the pointer, including the serialized__pointlist in the 
    10661085 * point arrays. Do not use these on LWGEOMs de-serialized from 
    10671086 * PG_LWGEOMs or they will try to free an underlying structure 
    1068  * managed by PgSQL. Only use these on LWGEOMs you have  
     1087 * managed by PgSQL. Only use these on LWGEOMs you have 
    10691088 * constructed yourself. 
    10701089 */ 
    1071   
     1090 
    10721091extern void ptarray_free(POINTARRAY *pa); 
    10731092extern void lwpoint_free(LWPOINT *pt); 
    10741093extern void lwline_free(LWLINE *line); 
     
    10841103 
    10851104/* 
    10861105 * The *_release family of functions frees the LWGEOM structures 
    1087  * surrounding the POINTARRAYs but leaves the POINTARRAYs  
     1106 * surrounding the POINTARRAYs but leaves the POINTARRAYs 
    10881107 * intact. Use these on LWGEOMs that have been de-serialized 
    1089  * from PG_LWGEOMs. Do not use these on LWGEOMs you have  
     1108 * from PG_LWGEOMs. Do not use these on LWGEOMs you have 
    10901109 * constructed yourself, or you will leak lots of memory. 
    10911110 */ 
    10921111 
     
    11451164extern void lwgeom_force3dz_recursive(uchar *serialized, uchar *optr, size_t *retsize); 
    11461165extern void lwgeom_force3dm_recursive(uchar *serialized, uchar *optr, size_t *retsize); 
    11471166extern void lwgeom_force4d_recursive(uchar *serialized, uchar *optr, size_t *retsize); 
     1167 
    11481168extern double distance2d_pt_pt(POINT2D *p1, POINT2D *p2); 
     1169extern void lw_dist2d_comp_pt_pt(POINT2D *p1, POINT2D *p2, DISTPTS *dl); 
    11491170extern double distance2d_pt_seg(POINT2D *p, POINT2D *A, POINT2D *B); 
    1150 extern double distance2d_seg_seg(POINT2D *A, POINT2D *B, POINT2D *C, POINT2D *D); 
    1151 extern double distance2d_pt_ptarray(POINT2D *p, POINTARRAY *pa); 
    1152 extern double distance2d_ptarray_ptarray(POINTARRAY *l1, POINTARRAY *l2); 
     1171extern void lw_dist2d_comp_pt_seg(POINT2D *p, POINT2D *A, POINT2D *B, DISTPTS *dl); 
     1172extern void lw_dist2d_comp_seg_seg(POINT2D *A, POINT2D *B, POINT2D *C, POINT2D *D, DISTPTS *dl); 
     1173extern void lw_dist2d_comp_pt_ptarray(POINT2D *p, POINTARRAY *pa, DISTPTS *dl); 
     1174extern void lw_dist2d_comp_ptarray_ptarray(POINTARRAY *l1, POINTARRAY *l2, DISTPTS *dl); 
    11531175extern int pt_in_ring_2d(POINT2D *p, POINTARRAY *ring); 
    11541176extern int pt_in_poly_2d(POINT2D *p, LWPOLY *poly); 
    1155 extern double distance2d_ptarray_poly(POINTARRAY *pa, LWPOLY *poly); 
    1156 extern double distance2d_point_point(LWPOINT *point1, LWPOINT *point2); 
    1157 extern double distance2d_point_line(LWPOINT *point, LWLINE *line); 
    1158 extern double distance2d_line_line(LWLINE *line1, LWLINE *line2); 
    1159 extern double distance2d_point_poly(LWPOINT *point, LWPOLY *poly); 
    1160 extern double distance2d_poly_poly(LWPOLY *poly1, LWPOLY *poly2); 
    1161 extern double distance2d_line_poly(LWLINE *line, LWPOLY *poly); 
     1177extern void lw_dist2d_comp_ptarray_poly(POINTARRAY *pa, LWPOLY *poly, DISTPTS *dl); 
     1178extern void lw_dist2d_comp_point_point(LWPOINT *point1, LWPOINT *point2, DISTPTS *dl); 
     1179extern void lw_dist2d_comp_point_line(LWPOINT *point, LWLINE *line, DISTPTS *dl); 
     1180extern void lw_dist2d_comp_line_line(LWLINE *line1, LWLINE *line2, DISTPTS *dl); 
     1181extern void lw_dist2d_comp_point_poly(LWPOINT *point, LWPOLY *poly, DISTPTS *dl); 
     1182extern void lw_dist2d_comp_poly_poly(LWPOLY *poly1, LWPOLY *poly2, DISTPTS *dl); 
     1183extern void lw_dist2d_comp_line_poly(LWLINE *line, LWPOLY *poly, DISTPTS *dl); 
    11621184extern int azimuth_pt_pt(POINT2D *p1, POINT2D *p2, double *ret); 
    11631185extern double lwgeom_mindistance2d_recursive(uchar *lw1, uchar *lw2); 
    11641186extern double lwgeom_mindistance2d_recursive_tolerance(uchar *lw1, uchar *lw2, double tolerance); 
     1187extern double lwgeom_maxdistance2d_recursive(uchar *lw1, uchar *lw2); 
     1188extern double lwgeom_maxdistance2d_recursive_tolerance(uchar *lw1, uchar *lw2, double tolerance); 
     1189extern void lw_dist2d_comp(uchar *lw1, uchar *lw2, double tolerance, DISTPTS *dl); 
    11651190extern int lwgeom_pt_inside_circle(POINT2D *p, double cx, double cy, double rad); 
    11661191extern int32 lwgeom_npoints(uchar *serialized); 
    11671192extern char ptarray_isccw(const POINTARRAY *pa); 
     
    12241249/* 
    12251250 * Clone an LWGEOM 
    12261251 * pointarray are not copied. 
    1227  * BBOXes are copied  
     1252 * BBOXes are copied 
    12281253 */ 
    12291254extern LWGEOM *lwgeom_clone(const LWGEOM *lwgeom); 
    12301255extern LWPOINT *lwpoint_clone(const LWPOINT *lwgeom); 
     
    12401265 * Take ownership of arguments 
    12411266 */ 
    12421267extern LWPOINT  *lwpoint_construct(int SRID, BOX2DFLOAT4 *bbox, 
    1243         POINTARRAY *point); 
     1268                                   POINTARRAY *point); 
    12441269extern LWLINE *lwline_construct(int SRID, BOX2DFLOAT4 *bbox, 
    1245         POINTARRAY *points); 
     1270                                POINTARRAY *points); 
    12461271 
    12471272/* 
    12481273 * Construct a new LWPOLY.  arrays (points/points per ring) will NOT be copied 
    12491274 * use SRID=-1 for unknown SRID (will have 8bit type's S = 0) 
    12501275 */ 
    12511276extern LWPOLY *lwpoly_construct(int SRID, BOX2DFLOAT4 *bbox, 
    1252         unsigned int nrings, POINTARRAY **points); 
     1277                                unsigned int nrings, POINTARRAY **points); 
    12531278 
    12541279extern LWCOLLECTION *lwcollection_construct(unsigned int type, int SRID, 
    1255         BOX2DFLOAT4 *bbox, unsigned int ngeoms, LWGEOM **geoms); 
     1280        BOX2DFLOAT4 *bbox, unsigned int ngeoms, LWGEOM **geoms); 
    12561281extern LWCOLLECTION *lwcollection_construct_empty(int SRID, 
    1257         char hasZ, char hasM); 
     1282        char hasZ, char hasM); 
    12581283 
    12591284/* 
    12601285 * Construct a new LWCIRCSTRING.  arrays (points/points per ring) will NOT be copied 
     
    12881313 */ 
    12891314 
    12901315extern POINTARRAY *ptarray_addPoint(POINTARRAY *pa, uchar *p, size_t pdims, 
    1291         unsigned int where); 
     1316                                    unsigned int where); 
    12921317extern POINTARRAY *ptarray_removePoint(POINTARRAY *pa, unsigned int where); 
    12931318 
    12941319extern int ptarray_isclosed2d(const POINTARRAY *pa); 
     
    13231348#define PARSER_CHECK_ALL        (PARSER_CHECK_MINPOINTS | PARSER_CHECK_ODD | PARSER_CHECK_CLOSURE) 
    13241349 
    13251350/* 
    1326  * Parser result structure: returns the result of attempting to convert (E)WKT/(E)WKB to LWGEOM  
     1351 * Parser result structure: returns the result of attempting to convert (E)WKT/(E)WKB to LWGEOM 
    13271352 */ 
    13281353typedef struct struct_lwgeom_parser_result 
    13291354{ 
     
    13381363 * Parser error messages (these must match the message array in lwgparse.c) 
    13391364 */ 
    13401365#define PARSER_ERROR_MOREPOINTS     1 
    1341 #define PARSER_ERROR_ODDPOINTS      2    
    1342 #define PARSER_ERROR_UNCLOSED       3  
    1343 #define PARSER_ERROR_MIXDIMS        4    
     1366#define PARSER_ERROR_ODDPOINTS      2 
     1367#define PARSER_ERROR_UNCLOSED       3 
     1368#define PARSER_ERROR_MIXDIMS        4 
    13441369#define PARSER_ERROR_INVALIDGEOM    5 
    13451370#define PARSER_ERROR_INVALIDWKBTYPE 6 
    13461371#define PARSER_ERROR_INCONTINUOUS       7 
    13471372 
    13481373 
    13491374/* 
    1350  * Unparser result structure: returns the result of attempting to convert LWGEOM to (E)WKT/(E)WKB  
     1375 * Unparser result structure: returns the result of attempting to convert LWGEOM to (E)WKT/(E)WKB 
    13511376 */ 
    13521377typedef struct struct_lwgeom_unparser_result 
    13531378{ 
     
    13621387 * Unparser error messages (these must match the message array in lwgunparse.c) 
    13631388 */ 
    13641389#define UNPARSER_ERROR_MOREPOINTS       1 
    1365 #define UNPARSER_ERROR_ODDPOINTS        2        
    1366 #define UNPARSER_ERROR_UNCLOSED         3  
     1390#define UNPARSER_ERROR_ODDPOINTS        2 
     1391#define UNPARSER_ERROR_UNCLOSED         3 
    13671392 
    13681393 
    13691394/* Parser access routines */ 
  • liblwgeom/measures.c

     
    77 * 
    88 * This is free software; you can redistribute and/or modify it under 
    99 * the terms of the GNU General Public Licence. See the COPYING file. 
    10  *  
     10 * 
    1111 **********************************************************************/ 
    1212 
    1313#include <math.h> 
     
    3939        if ( memcmp(&first, &last, sizeof(POINT2D)) ) 
    4040        { 
    4141                lwerror("pt_in_ring_2d: V[n] != V[0] (%g %g != %g %g)", 
    42                         first.x, first.y, last.x, last.y); 
    43                          
     42                        first.x, first.y, last.x, last.y); 
     43 
    4444        } 
    4545#endif 
    4646 
     
    4949 
    5050        /* loop through all edges of the polygon */ 
    5151        getPoint2d_p(ring, 0, &v1); 
    52         for (i=0; i<ring->npoints-1; i++) 
    53         {    
     52        for (i=0; i<ring->npoints-1; i++) 
     53        { 
    5454                double vt; 
    5555                getPoint2d_p(ring, i+1, &v2); 
    5656 
    5757                /* edge from vertex i to vertex i+1 */ 
    58                 if 
     58                if 
    5959                ( 
    60                         /* an upward crossing */ 
    61                         ((v1.y <= p->y) && (v2.y > p->y)) 
    62                         /* a downward crossing */ 
    63                         || ((v1.y > p->y) && (v2.y <= p->y)) 
     60                    /* an upward crossing */ 
     61                    ((v1.y <= p->y) && (v2.y > p->y)) 
     62                    /* a downward crossing */ 
     63                    || ((v1.y > p->y) && (v2.y <= p->y)) 
    6464                ) 
    65                 { 
     65                { 
    6666 
    6767                        vt = (double)(p->y - v1.y) / (v2.y - v1.y); 
    6868 
     
    7070                        if (p->x < v1.x + vt * (v2.x - v1.x)) 
    7171                        { 
    7272                                /* a valid crossing of y=p.y right of p.x */ 
    73                                 ++cn; 
     73                                ++cn; 
    7474                        } 
    7575                } 
    7676                v1 = v2; 
     
    8181        return (cn&1);    /* 0 if even (out), and 1 if odd (in) */ 
    8282} 
    8383 
     84/*Compares incomming points and stores the points closest to each other or most far away from each other depending on dl->thedir (thedirection) */ 
     85void lw_dist2d_comp_pt_pt(POINT2D *thep1, POINT2D *thep2,DISTPTS *dl) 
     86{ 
     87        double hside = thep2->x - thep1->x; 
     88        double vside = thep2->y - thep1->y; 
     89        double dist = sqrt ( hside*hside + vside*vside ); 
     90        if (((dl->d - dist)*(dl->thedir))>0) 
     91        { 
     92                dl->d = dist; 
     93                /*      lwnotice("lw_dist2d_comp_pt_pt %e",dl->twisted);*/ 
     94                if (dl->twisted>0) 
     95                { 
     96                        dl->p1 = *thep1; 
     97                        dl->p2 = *thep2; 
     98                } 
     99                else 
     100                { 
     101                        dl->p1 = *thep2; 
     102                        dl->p2 = *thep1; 
     103                } 
     104        } 
     105        return; 
     106} 
     107 
     108/*The old function nessecary for ptarray_segmentize2d in ptarray.c*/ 
    84109double distance2d_pt_pt(POINT2D *p1, POINT2D *p2) 
    85110{ 
    86111        double hside = p2->x - p1->x; 
     
    94119                );  */ 
    95120} 
    96121 
    97 /*distance2d from p to line A->B */ 
     122/*lw_dist2d_comp from p to line A->B 
     123This one is now sending every occation to lw_dist2d_comp_pt_pt 
     124Berfore it was handling occations where r was between 0 and 1 internally and just returning the distance without identifying the points. 
     125To get this points it was nessecary to change and it also showed to be about 10%faster. */ 
     126void lw_dist2d_comp_pt_seg(POINT2D *p, POINT2D *A, POINT2D *B, DISTPTS *dl) 
     127{ 
     128        /*lwnotice("lw_dist2d_comp_pt_seg %e",dl->d);*/ 
     129        double  r; 
     130 
     131        /*if start==end, then use pt distance */ 
     132        if (  ( A->x == B->x) && (A->y == B->y) ) 
     133        { 
     134                lw_dist2d_comp_pt_pt(p,A,dl); 
     135                return; 
     136        } 
     137        /* 
     138         * otherwise, we use comp.graphics.algorithms 
     139         * Frequently Asked Questions method 
     140         * 
     141         *  (1)               AC dot AB 
     142             *         r = --------- 
     143             *               ||AB||^2 
     144         *      r has the following meaning: 
     145         *      r=0 P = A 
     146         *      r=1 P = B 
     147         *      r<0 P is on the backward extension of AB 
     148         *      r>1 P is on the forward extension of AB 
     149         *      0<r<1 P is interior to AB 
     150         */ 
     151 
     152        r = ( (p->x-A->x) * (B->x-A->x) + (p->y-A->y) * (B->y-A->y) )/( (B->x-A->x)*(B->x-A->x) +(B->y-A->y)*(B->y-A->y) ); 
     153 
     154        /*This is for finding the maxdistance. 
     155        the maxdistance have to be between two vertexes as I understand it, 
     156        compared to mindistance which can be ebtween some point between the vertices and a vertex.*/ 
     157        if (dl->thedir < 1) 
     158        { 
     159                if (r>=0.5) 
     160                { 
     161                        lw_dist2d_comp_pt_pt(p,A,dl); 
     162                        return; 
     163                } 
     164                if (r<0.5) 
     165                { 
     166                        lw_dist2d_comp_pt_pt(p,B,dl); 
     167                        return; 
     168                } 
     169        } 
     170 
     171        if (r<0)        /*If the first vertex A is closest to the point p*/ 
     172        { 
     173                lw_dist2d_comp_pt_pt(p,A,dl); 
     174                return; 
     175        } 
     176        if (r>1)        /*If the second vertex B is closest to the point p*/ 
     177        { 
     178         
     179                lw_dist2d_comp_pt_pt(p,B,dl); 
     180                return; 
     181        } 
     182 
     183 
     184        /*else if the point p is closer to some point between a and b then we find that point and send it to lw_dist2d_comp_pt_pt*/ 
     185        POINT2D c; 
     186        c.x=A->x + r * (B->x-A->x); 
     187        c.y=A->y + r * (B->y-A->y); 
     188 
     189        lw_dist2d_comp_pt_pt(p,&c,dl); 
     190        return; 
     191} 
     192 
     193 
     194 
     195 
     196/*The old function nessecary for ptarray_segmentize2d in ptarray.c*/ 
    98197double distance2d_pt_seg(POINT2D *p, POINT2D *A, POINT2D *B) 
    99198{ 
    100199        double  r,s; 
     
    108207         * Frequently Asked Questions method 
    109208         * 
    110209         *  (1)               AC dot AB 
    111          *         r = --------- 
    112          *               ||AB||^2 
     210             *         r = --------- 
     211             *               ||AB||^2 
    113212         *      r has the following meaning: 
    114213         *      r=0 P = A 
    115214         *      r=1 P = B 
     
    135234         */ 
    136235 
    137236        s = ( (A->y-p->y)*(B->x-A->x)- (A->x-p->x)*(B->y-A->y) ) / 
    138                 ( (B->x-A->x)*(B->x-A->x) +(B->y-A->y)*(B->y-A->y) ); 
     237            ( (B->x-A->x)*(B->x-A->x) +(B->y-A->y)*(B->y-A->y) ); 
    139238 
    140239        return LW_ABS(s) * sqrt( 
    141                 (B->x-A->x)*(B->x-A->x) + (B->y-A->y)*(B->y-A->y) 
    142                 ); 
     240                   (B->x-A->x)*(B->x-A->x) + (B->y-A->y)*(B->y-A->y) 
     241               ); 
    143242} 
    144243 
    145 /* find the minimum 2d distance from AB to CD */ 
    146 double distance2d_seg_seg(POINT2D *A, POINT2D *B, POINT2D *C, POINT2D *D) 
     244 
     245 
     246 
     247 
     248/*This function is changed so it is not doing any comparasion of distance 
     249but just sending every possible combination further to lw_dist2d_comp_pt_seg*/ 
     250void lw_dist2d_comp_seg_seg(POINT2D *A, POINT2D *B, POINT2D *C, POINT2D *D, DISTPTS *dl) 
    147251{ 
    148  
     252        /*lwnotice("lw_dist2d_comp_seg_seg %e \n",dl->d);*/ 
    149253        double  s_top, s_bot,s; 
    150254        double  r_top, r_bot,r; 
    151255 
    152         LWDEBUGF(2, "distance2d_seg_seg [%g,%g]->[%g,%g] by [%g,%g]->[%g,%g]", 
    153                 A->x,A->y,B->x,B->y, C->x,C->y, D->x, D->y); 
    154256 
     257        LWDEBUGF(2, "lw_dist2d_comp_seg_seg [%g,%g]->[%g,%g] by [%g,%g]->[%g,%g]", 
     258                 A->x,A->y,B->x,B->y, C->x,C->y, D->x, D->y); 
    155259 
    156260        /*A and B are the same point */ 
    157261        if (  ( A->x == B->x) && (A->y == B->y) ) 
    158                 return distance2d_pt_seg(A,C,D); 
     262        { 
     263                lw_dist2d_comp_pt_seg(A,C,D,dl); 
     264                return; 
     265        } 
     266        /*U and V are the same point */ 
    159267 
    160                 /*U and V are the same point */ 
    161  
    162268        if (  ( C->x == D->x) && (C->y == D->y) ) 
    163                 return distance2d_pt_seg(D,A,B); 
    164  
     269        { 
     270                dl->twisted= ((dl->twisted) * (-1)); 
     271                lw_dist2d_comp_pt_seg(D,A,B,dl); 
     272                return; 
     273        } 
    165274        /* AB and CD are line segments */ 
    166275        /* from comp.graphics.algo 
    167276 
     
    190299        s_top = (A->y-C->y)*(B->x-A->x) - (A->x-C->x)*(B->y-A->y); 
    191300        s_bot = (B->x-A->x)*(D->y-C->y) - (B->y-A->y)*(D->x-C->x); 
    192301 
    193         if  ( (r_bot==0) || (s_bot == 0) ) 
    194         { 
    195                 return ( 
    196                         LW_MIN(distance2d_pt_seg(A,C,D), 
    197                                 LW_MIN(distance2d_pt_seg(B,C,D), 
    198                                         LW_MIN(distance2d_pt_seg(C,A,B), 
    199                                                 distance2d_pt_seg(D,A,B)) 
    200                                 ) 
    201                         ) 
    202                 ); 
    203         } 
    204302        s = s_top/s_bot; 
    205303        r=  r_top/r_bot; 
    206304 
    207         if ((r<0) || (r>1) || (s<0) || (s>1) ) 
     305 
     306        if ((r<0)||(r>1)||(s<0)||(s>1)||(dl->thedir <0)) 
    208307        { 
    209                 /*no intersection */ 
    210                 return ( 
    211                         LW_MIN(distance2d_pt_seg(A,C,D), 
    212                                 LW_MIN(distance2d_pt_seg(B,C,D), 
    213                                         LW_MIN(distance2d_pt_seg(C,A,B), 
    214                                                 distance2d_pt_seg(D,A,B)) 
    215                                 ) 
    216                         ) 
    217                 ); 
    218  
     308                lw_dist2d_comp_pt_seg(A,C,D,dl); 
     309                lw_dist2d_comp_pt_seg(B,C,D,dl); 
     310                 
     311                dl->twisted= ((dl->twisted) * (-1));  /*here we change the order of inputted geometrys and that we  notice by changing sign on dl->twisted*/ 
     312                lw_dist2d_comp_pt_seg(C,A,B,dl); 
     313                lw_dist2d_comp_pt_seg(D,A,B,dl); 
     314                return; 
    219315        } 
    220316        else 
    221                 return -0; /*intersection exists */ 
     317        { 
     318                if (dl->thedir >0)      /*If there is intersection we identify the intersection point and return it but only if we are looking for mindistance*/ 
     319                {                       /*lwnotice("intersection lines: %e %e %e %e",A->x,A->y,B->x,B->y);*/ 
     320                        POINT2D theP; 
     321                         
     322                        if(((A->x==C->x)&&(A->y==C->y))||((A->x==D->x)&&(A->y==D->y))) 
     323                        { 
     324                        theP.x = A->x; 
     325                        theP.y = A->y; 
     326                        }                        
     327                        else if(((B->x==C->x)&&(B->y==C->y))||((B->x==D->x)&&(B->y==D->y))) 
     328                        { 
     329                        theP.x = B->x; 
     330                        theP.y = B->y; 
     331                        } 
     332                        else  
     333                        { 
     334                        theP.x = A->x+r*(B->x-A->x);  
     335                        theP.y = A->y+r*(B->y-A->y); 
     336                        } 
     337                        /*lwnotice("intersection: %e %e ",theP.x, theP.y);*/ 
     338                        dl->d=0; 
     339                        dl->p1=theP; 
     340                        dl->p2=theP; 
     341                }        
     342                return; 
    222343 
     344        } 
     345 
    223346} 
    224347 
    225 /* 
    226  * search all the segments of pointarray to see which one is closest to p1 
    227  * Returns minimum distance between point and pointarray 
    228  */ 
    229 double distance2d_pt_ptarray(POINT2D *p, POINTARRAY *pa) 
     348void lw_dist2d_comp_pt_ptarray(POINT2D *p, POINTARRAY *pa,DISTPTS *dl) 
    230349{ 
    231         double result = 0; 
     350 
     351 
    232352        int t; 
    233353        POINT2D start, end; 
    234  
     354        int twist = dl->twisted; 
    235355        getPoint2d_p(pa, 0, &start); 
    236356 
    237357        for (t=1; t<pa->npoints; t++) 
    238358        { 
    239                 double dist; 
     359                dl->twisted=twist; 
    240360                getPoint2d_p(pa, t, &end); 
    241                 dist = distance2d_pt_seg(p, &start, &end); 
    242                 if (t==1) result = dist; 
    243                 else result = LW_MIN(result, dist); 
     361                lw_dist2d_comp_pt_seg(p, &start, &end,dl); 
     362                start = end; 
    244363 
    245                 if ( result == 0 ) return 0; 
    246  
    247                 start = end; 
    248364        } 
    249365 
    250         return result; 
     366        return; 
    251367} 
    252368 
    253369/* test each segment of l1 against each segment of l2.  Return min */ 
    254 double distance2d_ptarray_ptarray(POINTARRAY *l1, POINTARRAY *l2) 
     370void lw_dist2d_comp_ptarray_ptarray(POINTARRAY *l1, POINTARRAY *l2,DISTPTS *dl) 
    255371{ 
    256         double  result = 99999999999.9; 
    257         char result_okay = 0; /*result is a valid min */ 
     372        /*lwnotice("lw_dist2d_comp_ptarray_ptarray");*/ 
    258373        int t,u; 
    259374        POINT2D start, end; 
    260375        POINT2D start2, end2; 
     376        int twist = dl->twisted; 
     377        LWDEBUGF(2, "lw_dist2d_comp_ptarray_ptarray called (points: %d-%d)", 
     378                 l1->npoints, l2->npoints); 
    261379 
    262         LWDEBUGF(2, "distance2d_ptarray_ptarray called (points: %d-%d)", 
    263                         l1->npoints, l2->npoints); 
    264  
    265380        getPoint2d_p(l1, 0, &start); 
    266381        for (t=1; t<l1->npoints; t++) /*for each segment in L1 */ 
    267382        { 
    268383                getPoint2d_p(l1, t, &end); 
    269  
    270384                getPoint2d_p(l2, 0, &start2); 
    271385                for (u=1; u<l2->npoints; u++) /*for each segment in L2 */ 
    272386                { 
    273                         double dist; 
    274  
    275387                        getPoint2d_p(l2, u, &end2); 
     388                        dl->twisted=twist; 
     389                        lw_dist2d_comp_seg_seg(&start, &end, &start2, &end2,dl); 
     390#if PGIS_DEBUG > 1 
     391                        printf("line_line; seg %i * seg %i, dist = %g\n",t,u,dist_this); 
     392#endif 
    276393 
    277                         dist = distance2d_seg_seg(&start, &end, &start2, &end2); 
     394#ifdef PGIS_DEBUG 
     395                        lwnotice(" seg%d-seg%d dist: %f, mindist: %f", 
     396                                 t, u, dist, result); 
     397#endif 
    278398 
    279                         LWDEBUGF(4, "line_line; seg %i * seg %i, dist = %g\n",t,u,dist); 
    280  
    281                         if (result_okay) 
    282                                 result = LW_MIN(result,dist); 
    283                         else 
    284                         { 
    285                                 result_okay = 1; 
    286                                 result = dist; 
    287                         } 
    288  
    289                         LWDEBUGF(3, " seg%d-seg%d dist: %f, mindist: %f", 
    290                                 t, u, dist, result); 
    291  
    292                         if (result <= 0) return 0; /*intersection */ 
    293  
    294399                        start2 = end2; 
    295400                } 
    296401                start = end; 
    297402        } 
    298  
    299         return result; 
     403        return ; 
    300404} 
    301405 
     406 
     407 
     408 
     409 
    302410/* true if point is in poly (and not in its holes) */ 
    303411int pt_in_poly_2d(POINT2D *p, LWPOLY *poly) 
    304412{ 
     
    327435 * otherwise return min distance to a ring (could be outside 
    328436 * polygon or inside a hole) 
    329437 */ 
    330 double distance2d_ptarray_poly(POINTARRAY *pa, LWPOLY *poly) 
     438 
     439 
     440 
     441 
     442 
     443 
     444void lw_dist2d_comp_ptarray_poly(POINTARRAY *pa, LWPOLY *poly, DISTPTS *dl) 
    331445{ 
    332446        POINT2D pt; 
    333447        int i; 
    334         double mindist = 0; 
    335448 
    336         LWDEBUGF(2, "distance2d_ptarray_poly called (%d rings)", poly->nrings); 
    337449 
     450        LWDEBUGF(2, "lw_dist2d_comp_ptarray_poly called (%d rings)", poly->nrings); 
     451 
     452 
    338453        for (i=0; i<poly->nrings; i++) 
    339454        { 
    340                 double dist = distance2d_ptarray_ptarray(pa, poly->rings[i]); 
    341                 if (i) mindist = LW_MIN(mindist, dist); 
    342                 else mindist = dist; 
     455                lw_dist2d_comp_ptarray_ptarray(pa, poly->rings[i], dl); 
    343456 
    344457                LWDEBUGF(3, " distance from ring %d: %f, mindist: %f", 
    345                         i, dist, mindist); 
     458                         i, dist, mindist); 
    346459 
    347                 if ( mindist <= 0 ) return 0.0; /* intersection */ 
    348460        } 
    349461 
    350462        /* 
     
    357469         * Outside outer ring, so min distance to a ring 
    358470         * is the actual min distance 
    359471         */ 
    360         if ( ! pt_in_ring_2d(&pt, poly->rings[0]) ) return mindist; 
     472        if ( ! pt_in_ring_2d(&pt, poly->rings[0]) ) 
     473        { 
     474                return ; 
     475        } 
    361476 
    362  
    363477        /* 
    364478         * Its in the outer ring. 
    365479         * Have to check if its inside a hole 
     
    372486                         * Its inside a hole, then the actual 
    373487                         * distance is the min ring distance 
    374488                         */ 
    375                         return mindist; 
     489                        return; 
    376490                } 
    377491        } 
     492        if (dl->thedir >0) 
     493        { 
     494                dl->d=0; 
     495                dl->p1.x=pt.x; 
     496                dl->p1.y=pt.y; 
     497                dl->p2.x=pt.x; 
     498                dl->p2.y=pt.y; 
     499        } 
     500        return ; /* Not in hole, so inside polygon */ 
    378501 
    379         return 0.0; /* Not in hole, so inside polygon */ 
    380502} 
    381503 
    382 double distance2d_point_point(LWPOINT *point1, LWPOINT *point2) 
     504 
     505 
     506 
     507 
     508void lw_dist2d_comp_point_point(LWPOINT *point1, LWPOINT *point2, DISTPTS *dl) 
    383509{ 
    384510        POINT2D p1; 
    385511        POINT2D p2; 
     
    387513        getPoint2d_p(point1->point, 0, &p1); 
    388514        getPoint2d_p(point2->point, 0, &p2); 
    389515 
    390         return distance2d_pt_pt(&p1, &p2); 
     516        lw_dist2d_comp_pt_pt(&p1, &p2,dl); 
     517        return; 
    391518} 
    392519 
    393 double distance2d_point_line(LWPOINT *point, LWLINE *line) 
     520void lw_dist2d_comp_point_line(LWPOINT *point, LWLINE *line, DISTPTS *dl) 
    394521{ 
    395522        POINT2D p; 
    396523        POINTARRAY *pa = line->points; 
    397524        getPoint2d_p(point->point, 0, &p); 
    398         return distance2d_pt_ptarray(&p, pa); 
     525        lw_dist2d_comp_pt_ptarray(&p, pa, dl); 
     526        return; 
    399527} 
    400528 
    401 double distance2d_line_line(LWLINE *line1, LWLINE *line2) 
     529void lw_dist2d_comp_line_line(LWLINE *line1, LWLINE *line2, DISTPTS *dl) 
    402530{ 
    403531        POINTARRAY *pa1 = line1->points; 
    404532        POINTARRAY *pa2 = line2->points; 
    405         return distance2d_ptarray_ptarray(pa1, pa2); 
     533        lw_dist2d_comp_ptarray_ptarray(pa1, pa2, dl); 
     534        return; 
    406535} 
    407536 
    408537/* 
     
    410539 * 2. if in the boundary, test to see if its in a hole. 
    411540 *    if so, then return dist to hole, else return 0 (point in polygon) 
    412541 */ 
    413 double distance2d_point_poly(LWPOINT *point, LWPOLY *poly) 
     542 
     543 
     544 
     545 
     546 
     547void lw_dist2d_comp_point_poly(LWPOINT *point, LWPOLY *poly, DISTPTS *dl) 
    414548{ 
    415549        POINT2D p; 
    416550        int i; 
    417551 
    418552        getPoint2d_p(point->point, 0, &p); 
    419553 
    420         LWDEBUG(2, "distance2d_point_poly called"); 
     554        LWDEBUG(2, "lw_dist2d_comp_point_poly called"); 
    421555 
     556 
    422557        /* Return distance to outer ring if not inside it */ 
    423558        if ( ! pt_in_ring_2d(&p, poly->rings[0]) ) 
    424559        { 
     560 
    425561                LWDEBUG(3, " not inside outer-ring"); 
    426562 
    427                 return distance2d_pt_ptarray(&p, poly->rings[0]); 
     563 
     564                lw_dist2d_comp_pt_ptarray(&p, poly->rings[0], dl); 
     565                return; 
    428566        } 
    429567 
     568        if (dl->thedir < 0) 
     569        { 
     570                LWDEBUG(3, "inside outer-ring but looking for maxdistance"); 
     571                lw_dist2d_comp_pt_ptarray(&p, poly->rings[0], dl); 
     572                return; 
     573        } 
    430574        /* 
    431575         * Inside the outer ring. 
    432576         * Scan though each of the inner rings looking to 
    433577         * see if its inside.  If not, distance==0. 
    434578         * Otherwise, distance = pt to ring distance 
    435579         */ 
    436         for (i=1; i<poly->nrings; i++)  
     580        for (i=1; i<poly->nrings; i++) 
    437581        { 
    438582                /* Inside a hole. Distance = pt -> ring */ 
    439583                if ( pt_in_ring_2d(&p, poly->rings[i]) ) 
    440584                { 
    441585                        LWDEBUG(3, " inside an hole"); 
    442586 
    443                         return distance2d_pt_ptarray(&p, poly->rings[i]); 
     587                        lw_dist2d_comp_pt_ptarray(&p, poly->rings[i], dl); 
     588                        return; 
    444589                } 
    445590        } 
    446591 
    447592        LWDEBUG(3, " inside the polygon"); 
    448  
    449         return 0.0; /* Is inside the polygon */ 
     593        if (dl->thedir >0) 
     594        { 
     595                dl->d=0; 
     596                dl->p1.x=p.x; 
     597                dl->p1.y=p.y; 
     598                dl->p2.x=p.x; 
     599                dl->p2.y=p.y; 
     600        } 
     601        return ; /* Is inside the polygon */ 
    450602} 
    451603 
     604 
     605 
     606 
    452607/* 
    453608 * Brute force. 
    454609 * Test to see if any rings intersect. 
     
    456611 * Test to see if one inside the other and if they are inside holes. 
    457612 * Find min distance ring-to-ring. 
    458613 */ 
    459 double distance2d_poly_poly(LWPOLY *poly1, LWPOLY *poly2) 
     614 
     615 
     616 
     617void lw_dist2d_comp_poly_poly(LWPOLY *poly1, LWPOLY *poly2, DISTPTS *dl) 
    460618{ 
    461619        POINT2D pt; 
    462         double mindist = -1; 
     620 
    463621        int i; 
    464622 
    465         LWDEBUG(2, "distance2d_poly_poly called"); 
     623        LWDEBUG(2, "lw_dist2d_comp_poly_poly called"); 
    466624 
    467625        /* if poly1 inside poly2 return 0 */ 
    468626        getPoint2d_p(poly1->rings[0], 0, &pt); 
    469         if ( pt_in_poly_2d(&pt, poly2) ) return 0.0;   
     627        if (( pt_in_poly_2d(&pt, poly2))  && (dl->thedir >0)) 
     628        { 
     629                dl->d=0; 
     630                dl->p1.x=pt.x; 
     631                dl->p1.y=pt.y; 
     632                dl->p2.x=pt.x; 
     633                dl->p2.y=pt.y; 
     634                return ; 
     635        } 
    470636 
    471637        /* if poly2 inside poly1 return 0 */ 
    472638        getPoint2d_p(poly2->rings[0], 0, &pt); 
    473         if ( pt_in_poly_2d(&pt, poly1) ) return 0.0;   
     639        if ( (pt_in_poly_2d(&pt, poly1)) && (dl->thedir >0)) 
     640        { 
     641                dl->d=0; 
     642                dl->p1.x=pt.x; 
     643                dl->p1.y=pt.y; 
     644                dl->p2.x=pt.x; 
     645                dl->p2.y=pt.y; 
     646                return ; 
     647        } 
    474648 
    475649        LWDEBUG(3, "  polys not inside each other"); 
    476650 
     
    484658                int j; 
    485659                for (j=0; j<poly2->nrings; j++) 
    486660                { 
    487                         double d = distance2d_ptarray_ptarray(poly1->rings[i], 
    488                                 poly2->rings[j]); 
    489                         if ( d <= 0 ) return 0.0; 
    490  
     661                        lw_dist2d_comp_ptarray_ptarray(poly1->rings[i], poly2->rings[j],dl); 
     662                        if ( dl->d <= 0 ) 
     663                        { 
     664                                if (dl->thedir >0) 
     665                                { 
     666                                        return; 
     667                                } 
     668                                 
     669                        } 
    491670                        /* mindist is -1 when not yet set */ 
    492                         if (mindist > -1) mindist = LW_MIN(mindist, d); 
    493                         else mindist = d; 
    494  
    495                         LWDEBUGF(3, "  ring%i-%i dist: %f, mindist: %f", i, j, d, mindist); 
     671                        LWDEBUGF(3, "  ring%i-%i dist: %f", i, j, d); 
    496672                } 
    497  
    498673        } 
    499  
    500674        /* otherwise return closest approach of rings (no intersection) */ 
    501         return mindist; 
     675        return ; 
    502676 
    503677} 
    504678 
    505 double distance2d_line_poly(LWLINE *line, LWPOLY *poly) 
     679void lw_dist2d_comp_line_poly(LWLINE *line, LWPOLY *poly, DISTPTS *dl) 
    506680{ 
    507         return distance2d_ptarray_poly(line->points, poly); 
     681        lw_dist2d_comp_ptarray_poly(line->points, poly, dl); 
     682        return; 
    508683} 
    509684 
    510  
    511685/*find the 2d length of the given POINTARRAY (even if it's 3d) */ 
    512686double lwgeom_pointarray_length2d(POINTARRAY *pts) 
    513687{ 
     
    517691        POINT2D to; 
    518692 
    519693        if ( pts->npoints < 2 ) return 0.0; 
    520         for (i=0; i<pts->npoints-1;i++) 
     694        for (i=0; i<pts->npoints-1; i++) 
    521695        { 
    522696                getPoint2d_p(pts, i, &frm); 
    523697                getPoint2d_p(pts, i+1, &to); 
    524698                dist += sqrt( ( (frm.x - to.x)*(frm.x - to.x) )  + 
    525                                 ((frm.y - to.y)*(frm.y - to.y) ) ); 
     699                              ((frm.y - to.y)*(frm.y - to.y) ) ); 
    526700        } 
    527701        return dist; 
    528702} 
     
    544718        /* compute 2d length if 3d is not available */ 
    545719        if ( ! TYPE_HASZ(pts->dims) ) return lwgeom_pointarray_length2d(pts); 
    546720 
    547         for (i=0; i<pts->npoints-1;i++) 
     721        for (i=0; i<pts->npoints-1; i++) 
    548722        { 
    549723                getPoint3dz_p(pts, i, &frm); 
    550724                getPoint3dz_p(pts, i+1, &to); 
    551725                dist += sqrt( ( (frm.x - to.x)*(frm.x - to.x) )  + 
    552                                 ((frm.y - to.y)*(frm.y - to.y) ) + 
    553                                 ((frm.z - to.z)*(frm.z - to.z) ) ); 
     726                              ((frm.y - to.y)*(frm.y - to.y) ) + 
     727                              ((frm.z - to.z)*(frm.z - to.z) ) ); 
    554728        } 
    555  
    556729        return dist; 
    557730} 
    558731 
     
    562735double 
    563736lwgeom_curvepolygon_area(LWCURVEPOLY *curvepoly) 
    564737{ 
    565         LWPOLY *poly = (LWPOLY *)lwgeom_segmentize((LWGEOM *)curvepoly, 32); 
    566         return lwgeom_polygon_area(poly); 
     738        LWPOLY *poly = (LWPOLY *)lwgeom_segmentize((LWGEOM *)curvepoly, 32); 
     739        return lwgeom_polygon_area(poly); 
    567740} 
    568741 
    569742/* 
     
    589762                LWDEBUGF(4, " rings %d has %d points", i, ring->npoints); 
    590763 
    591764                for (j=0; j<ring->npoints-1; j++) 
    592                 { 
     765                { 
    593766                        getPoint2d_p(ring, j, &p1); 
    594767                        getPoint2d_p(ring, j+1, &p2); 
    595768                        ringarea += ( p1.x * p2.y ) - ( p1.y * p2.x ); 
     
    644817} 
    645818 
    646819double 
     820lwgeom_maxdistance2d_recursive(uchar *lw1, uchar *lw2) 
     821{ 
     822        return lwgeom_maxdistance2d_recursive_tolerance( lw1, lw2, 99999999 ); 
     823} 
     824 
     825 
     826double 
     827lwgeom_maxdistance2d_recursive_tolerance(uchar *lw1, uchar *lw2, double tolerance) 
     828{ 
     829        /*double thedist;*/ 
     830        DISTPTS thedl; 
     831        thedl.thedir = (-1); 
     832        thedl.d= thedl.thedir * 99999999; 
     833        DISTPTS *dl = &thedl; 
     834        lw_dist2d_comp( lw1, lw2,tolerance, dl ); 
     835        return dl->d; 
     836        /*lwgeom_release((DISTPTS *)dl); 
     837          return thedist; 
     838          return 1212.00;*/ 
     839} 
     840 
     841double 
    647842lwgeom_mindistance2d_recursive(uchar *lw1, uchar *lw2) 
    648843{ 
    649   return lwgeom_mindistance2d_recursive_tolerance( lw1, lw2, 0.0 ); 
     844        return lwgeom_mindistance2d_recursive_tolerance( lw1, lw2, 0.0 ); 
    650845} 
    651846 
     847 
    652848double 
    653849lwgeom_mindistance2d_recursive_tolerance(uchar *lw1, uchar *lw2, double tolerance) 
    654850{ 
     851        double thedist; 
     852        DISTPTS thedl; 
     853        thedl.thedir = (1); 
     854        thedl.d= thedl.thedir * 99999999; 
     855        DISTPTS *dl = &thedl; 
     856        lw_dist2d_comp( lw1, lw2,tolerance, dl ); 
     857        thedist = dl->d; 
     858        /*lwgeom_release((DISTPTS *)dl);*/ 
     859        return thedist; 
     860} 
     861 
     862void 
     863lw_dist2d_comp(uchar *lw1, uchar *lw2, double tolerance, DISTPTS *dl) 
     864{ 
    655865        LWGEOM_INSPECTED *in1, *in2; 
    656866        int i, j; 
    657         double mindist = -1; 
    658867 
    659868        in1 = lwgeom_inspect(lw1); 
    660869        in2 = lwgeom_inspect(lw2); 
     
    663872        { 
    664873                uchar *g1 = lwgeom_getsubgeometry_inspected(in1, i); 
    665874                int t1 = lwgeom_getType(g1[0]); 
    666                 double dist=tolerance; 
    667875 
    668                 /* Argument 1 is a multitype... recurse */ 
     876                /* it's a multitype... recurse */ 
    669877                if ( lwgeom_contains_subgeoms(t1) ) 
    670878                { 
    671                         dist = lwgeom_mindistance2d_recursive_tolerance(g1, lw2, tolerance); 
    672                         if ( dist <= tolerance ) return tolerance; /* can't be closer */ 
    673                         if ( mindist == -1 ) mindist = dist; 
    674                         else mindist = LW_MIN(dist, mindist); 
     879                        lw_dist2d_comp(g1, lw2, tolerance, dl); 
     880                        if ( ((tolerance - dl->d)*dl->thedir) >0 ) 
     881                        { 
     882                                dl->d=tolerance; 
     883                                return; /* can't be closer */ 
     884                        } 
    675885                        continue; 
    676886                } 
    677887 
     
    680890                        uchar *g2 = lwgeom_getsubgeometry_inspected(in2, j); 
    681891                        int t2 = lwgeom_getType(g2[0]); 
    682892 
    683                         /* Argument 2 is a multitype... recurse */ 
    684893                        if ( lwgeom_contains_subgeoms(t2) ) 
    685894                        { 
    686                                 dist = lwgeom_mindistance2d_recursive_tolerance(g1, g2, tolerance); 
    687                                 if ( dist <= tolerance ) return tolerance; /* can't be closer */ 
    688                                 if ( mindist == -1 ) mindist = dist; 
    689                                 else mindist = LW_MIN(dist, mindist); 
     895                                lw_dist2d_comp(g1, g2, tolerance, dl); 
     896                                if ( ((tolerance - dl->d)*dl->thedir) >0 ) 
     897                                { 
     898                                        dl->d=tolerance; 
     899                                        return; /* can't be closer */ 
     900                                } 
    690901                                continue; 
    691902                        } 
    692                          
    693903                        if  ( t1 == POINTTYPE ) 
    694904                        { 
    695905                                if  ( t2 == POINTTYPE ) 
    696906                                { 
    697                                         dist = distance2d_point_point( 
    698                                                 lwpoint_deserialize(g1), 
    699                                                 lwpoint_deserialize(g2) 
    700                                         ); 
     907                                        dl->twisted=1; 
     908                                        lw_dist2d_comp_point_point( 
     909                                            lwpoint_deserialize(g1), 
     910                                            lwpoint_deserialize(g2), 
     911                                            dl); 
    701912                                } 
    702913                                else if  ( t2 == LINETYPE ) 
    703914                                { 
    704                                         dist = distance2d_point_line( 
    705                                                 lwpoint_deserialize(g1), 
    706                                                 lwline_deserialize(g2) 
    707                                         ); 
     915                                        dl->twisted=1; 
     916                                        lw_dist2d_comp_point_line( 
     917                                            lwpoint_deserialize(g1), 
     918                                            lwline_deserialize(g2), 
     919                                            dl); 
    708920                                } 
    709921                                else if  ( t2 == POLYGONTYPE ) 
    710922                                { 
    711                                         dist = distance2d_point_poly( 
    712                                                 lwpoint_deserialize(g1), 
    713                                                 lwpoly_deserialize(g2) 
    714                                         ); 
     923                                        dl->twisted=1; 
     924                                        lw_dist2d_comp_point_poly( 
     925                                            lwpoint_deserialize(g1), 
     926                                            lwpoly_deserialize(g2), 
     927                                            dl); 
    715928                                } 
    716929                                else 
    717930                                { 
    718                                         lwerror("Unsupported geometry type: %s", lwgeom_typename(t2)); 
    719                                 }        
     931                                        lwerror("Unsupported geometry type1: %s", lwgeom_typename(t2)); 
     932                                } 
    720933                        } 
    721934                        else if ( t1 == LINETYPE ) 
    722935                        { 
    723936                                if ( t2 == POINTTYPE ) 
    724937                                { 
    725                                         dist = distance2d_point_line( 
    726                                                 lwpoint_deserialize(g2), 
    727                                                 lwline_deserialize(g1) 
    728                                         ); 
     938                                        dl->twisted=(-1); 
     939                                        lw_dist2d_comp_point_line( 
     940                                            lwpoint_deserialize(g2), 
     941                                            lwline_deserialize(g1), 
     942                                            dl); 
    729943                                } 
    730944                                else if ( t2 == LINETYPE ) 
    731945                                { 
    732                                         dist = distance2d_line_line( 
    733                                                 lwline_deserialize(g1), 
    734                                                 lwline_deserialize(g2) 
    735                                         ); 
     946                                        dl->twisted=1; 
     947                                        /*lwnotice("start line");*/ 
     948                                        lw_dist2d_comp_line_line( 
     949                                            lwline_deserialize(g1), 
     950                                            lwline_deserialize(g2), 
     951                                            dl); 
    736952                                } 
    737953                                else if ( t2 == POLYGONTYPE ) 
    738954                                { 
    739                                         dist = distance2d_line_poly( 
    740                                                 lwline_deserialize(g1), 
    741                                                 lwpoly_deserialize(g2) 
    742                                         ); 
     955                                        dl->twisted=1; 
     956                                        lw_dist2d_comp_line_poly( 
     957                                            lwline_deserialize(g1), 
     958                                            lwpoly_deserialize(g2), 
     959                                            dl); 
    743960                                } 
    744961                                else 
    745962                                { 
    746                                         lwerror("Unsupported geometry type: %s", lwgeom_typename(t2)); 
    747                                 }        
     963                                        lwerror("Unsupported geometry type2: %s", lwgeom_typename(t2)); 
     964                                } 
    748965                        } 
    749966                        else if ( t1 == POLYGONTYPE ) 
    750967                        { 
    751968                                if ( t2 == POLYGONTYPE ) 
    752969                                { 
    753                                         dist = distance2d_poly_poly( 
    754                                                 lwpoly_deserialize(g2), 
    755                                                 lwpoly_deserialize(g1) 
    756                                         ); 
     970                                        dl->twisted=(-1); 
     971                                        lw_dist2d_comp_poly_poly( 
     972                                            lwpoly_deserialize(g2), 
     973                                            lwpoly_deserialize(g1), 
     974                                            dl); 
    757975                                } 
    758976                                else if ( t2 == POINTTYPE ) 
    759977                                { 
    760                                         dist = distance2d_point_poly( 
    761                                                 lwpoint_deserialize(g2), 
    762                                                 lwpoly_deserialize(g1) 
    763                                         ); 
     978                                        dl->twisted=(-1); 
     979                                        lw_dist2d_comp_point_poly( 
     980                                            lwpoint_deserialize(g2), 
     981                                            lwpoly_deserialize(g1), 
     982                                            dl); 
    764983                                } 
    765984                                else if ( t2 == LINETYPE ) 
    766985                                { 
    767                                         dist = distance2d_line_poly( 
    768                                                 lwline_deserialize(g2), 
    769                                                 lwpoly_deserialize(g1) 
    770                                         ); 
     986                                        dl->twisted=(-1); 
     987                                        lw_dist2d_comp_line_poly( 
     988                                            lwline_deserialize(g2), 
     989                                            lwpoly_deserialize(g1), 
     990                                            dl); 
    771991                                } 
    772992                                else 
    773993                                { 
    774                                         lwerror("Unsupported geometry type: %s", lwgeom_typename(t2)); 
    775                                 }        
     994                                        lwerror("Unsupported geometry type3: %s", lwgeom_typename(t2)); 
     995                                } 
    776996                        } 
    777 //                      else if (lwgeom_contains_subgeoms(t1)) /* it's a multitype... recurse */ 
    778 //                      { 
    779 //                              dist = lwgeom_mindistance2d_recursive_tolerance(g1, g2, tolerance); 
    780 //                      } 
     997                        /*                      else if (lwgeom_contains_subgeoms(t1)) 
     998                                                { 
     999                                                        lw_dist2d_comp(g1, g2, tolerance,dl); 
     1000 
     1001                                                }*/ 
    7811002                        else 
    7821003                        { 
    783                                 lwerror("Unsupported geometry type: %s", lwgeom_typename(t1)); 
     1004                                lwerror("Unsupported geometry type4: %s", lwgeom_typename(t1)); 
    7841005                        } 
    7851006 
    786                         if (mindist == -1 ) mindist = dist; 
    787                         else mindist = LW_MIN(dist, mindist); 
    7881007 
    789                         LWDEBUGF(3, "dist %d-%d: %f - mindist: %f", 
    790                                 i, j, dist, mindist); 
    7911008 
    7921009 
    793                         if (mindist <= tolerance) return tolerance; /* can't be closer */ 
     1010                        if ( ((tolerance - dl->d)*dl->thedir) >0 ) 
     1011                        { 
     1012                                dl->d=tolerance; 
     1013                                return; /* can't be closer */ 
     1014                        } 
    7941015 
    7951016                } 
    7961017 
    7971018        } 
    798  
    799         if (mindist<0) mindist = 0;  
    800  
    801         return mindist; 
     1019        return ; 
    8021020} 
    8031021 
    8041022 
  • postgis/lwgeom_functions_basic.c

     
    4343Datum LWGEOM_length_linestring(PG_FUNCTION_ARGS); 
    4444Datum LWGEOM_perimeter2d_poly(PG_FUNCTION_ARGS); 
    4545Datum LWGEOM_perimeter_poly(PG_FUNCTION_ARGS); 
     46Datum LWGEOM_maxdistance2d_linestring(PG_FUNCTION_ARGS); 
    4647Datum LWGEOM_mindistance2d(PG_FUNCTION_ARGS); 
    47 Datum LWGEOM_maxdistance2d_linestring(PG_FUNCTION_ARGS); 
     48Datum LWGEOM_shortestline2d(PG_FUNCTION_ARGS); 
     49Datum LWGEOM_longestline2d(PG_FUNCTION_ARGS); 
    4850Datum LWGEOM_inside_circle_point(PG_FUNCTION_ARGS); 
    4951Datum LWGEOM_collect(PG_FUNCTION_ARGS); 
    5052Datum LWGEOM_accum(PG_FUNCTION_ARGS); 
     
    602604                        TYPE_SETZM(nring->dims, 0, 0); 
    603605                        nring->npoints = ring->npoints; 
    604606                        nring->serialized_pointlist = 
    605                                 lwalloc(ring->npoints*sizeof(POINT2D)); 
     607                            lwalloc(ring->npoints*sizeof(POINT2D)); 
    606608                        loc = nring->serialized_pointlist; 
    607609                        for (k=0; k<ring->npoints; k++) 
    608610                        { 
     
    624626        } 
    625627 
    626628        if ( type != MULTIPOINTTYPE && type != MULTIPOLYGONTYPE && 
    627                         type != MULTILINETYPE && type != COLLECTIONTYPE && 
    628                         type != COMPOUNDTYPE && type != CURVEPOLYTYPE && 
    629                         type != MULTICURVETYPE && type != MULTISURFACETYPE) 
     629                type != MULTILINETYPE && type != COLLECTIONTYPE && 
     630                type != COMPOUNDTYPE && type != CURVEPOLYTYPE && 
     631                type != MULTICURVETYPE && type != MULTISURFACETYPE) 
    630632        { 
    631633                lwerror("lwgeom_force2d_recursive: unknown geometry: %d", 
    632634                        type); 
     
    818820                        TYPE_SETZM(nring->dims, 1, 0); 
    819821                        nring->npoints = ring->npoints; 
    820822                        nring->serialized_pointlist = 
    821                                 lwalloc(ring->npoints*sizeof(POINT3DZ)); 
     823                            lwalloc(ring->npoints*sizeof(POINT3DZ)); 
    822824                        loc = nring->serialized_pointlist; 
    823825                        for (k=0; k<ring->npoints; k++) 
    824826                        { 
     
    10121014                        TYPE_SETZM(nring->dims, 0, 1); 
    10131015                        nring->npoints = ring->npoints; 
    10141016                        nring->serialized_pointlist = 
    1015                                 lwalloc(ring->npoints*sizeof(POINT3DM)); 
     1017                            lwalloc(ring->npoints*sizeof(POINT3DM)); 
    10161018                        loc = nring->serialized_pointlist; 
    10171019                        for (k=0; k<ring->npoints; k++) 
    10181020                        { 
     
    10341036        } 
    10351037 
    10361038        if ( type != MULTIPOINTTYPE && type != MULTIPOLYGONTYPE && 
    1037                         type != MULTILINETYPE && type != COLLECTIONTYPE && 
    1038                         type != COMPOUNDTYPE && type != CURVEPOLYTYPE && 
    1039                         type != MULTICURVETYPE && type != MULTISURFACETYPE) 
     1039                type != MULTILINETYPE && type != COLLECTIONTYPE && 
     1040                type != COMPOUNDTYPE && type != CURVEPOLYTYPE && 
     1041                type != MULTICURVETYPE && type != MULTISURFACETYPE) 
    10401042        { 
    10411043                lwerror("lwgeom_force3dm_recursive: unknown geometry: %d", 
    10421044                        type); 
     
    12241226                        TYPE_SETZM(nring->dims, 1, 1); 
    12251227                        nring->npoints = ring->npoints; 
    12261228                        nring->serialized_pointlist = 
    1227                                 lwalloc(ring->npoints*sizeof(POINT4D)); 
     1229                            lwalloc(ring->npoints*sizeof(POINT4D)); 
    12281230                        loc = nring->serialized_pointlist; 
    12291231                        for (k=0; k<ring->npoints; k++) 
    12301232                        { 
     
    12521254 
    12531255        /* Add type */ 
    12541256        *optr = lwgeom_makeType_full( 
    1255                         1, 1, 
    1256                         lwgeom_hasSRID(serialized[0]), 
    1257                         type, lwgeom_hasBBOX(serialized[0])); 
     1257                    1, 1, 
     1258                    lwgeom_hasSRID(serialized[0]), 
     1259                    type, lwgeom_hasBBOX(serialized[0])); 
    12581260        optr++; 
    12591261        totsize++; 
    12601262        loc=serialized+1; 
     
    14491451         * automatic bbox addition FOR_COMPLEX_GEOMS. 
    14501452         */ 
    14511453        if ( TYPE_GETTYPE(geom->type) == COLLECTIONTYPE && 
    1452                         TYPE_HASBBOX(geom->type) ) 
     1454                TYPE_HASBBOX(geom->type) ) 
    14531455        { 
    14541456                PG_RETURN_POINTER(geom); 
    14551457        } 
     
    14731475                lwgeom->bbox = NULL; 
    14741476                lwgeoms[0] = lwgeom; 
    14751477                lwgeom = (LWGEOM *)lwcollection_construct(COLLECTIONTYPE, 
    1476                                 SRID, bbox, 1, 
    1477                                 lwgeoms); 
     1478                         SRID, bbox, 1, 
     1479                         lwgeoms); 
    14781480        } 
    14791481 
    14801482        result = pglwgeom_serialize(lwgeom); 
     
    15101512        /* deserialize into lwgeoms[0] */ 
    15111513        lwgeom = lwgeom_deserialize(SERIALIZED_FORM(geom)); 
    15121514        ogeom = lwgeom_as_multi(lwgeom); 
    1513                 printf("ogeom %p\n",ogeom); 
    1514                 printf("ogeom->type %d\n", ogeom->type); 
     1515        printf("ogeom %p\n",ogeom); 
     1516        printf("ogeom->type %d\n", ogeom->type); 
    15151517 
    15161518        result = pglwgeom_serialize(ogeom); 
    15171519 
     
    15201522        PG_RETURN_POINTER(result); 
    15211523} 
    15221524 
     1525 
     1526PG_FUNCTION_INFO_V1(LWGEOM_shortestline2d); 
     1527Datum LWGEOM_shortestline2d(PG_FUNCTION_ARGS) 
     1528{ 
     1529 
     1530        PG_LWGEOM *geom1; 
     1531        PG_LWGEOM *geom2; 
     1532        LWPOINT *point1; 
     1533        LWPOINT *point2; 
     1534        int SRID; 
     1535        double x1,x2,y1,y2; 
     1536        PG_LWGEOM *result=NULL; 
     1537        LWPOINT *lwpoints[2]; 
     1538        LWLINE *outline; 
     1539 
     1540        DISTPTS thedl; 
     1541        DISTPTS *dl = &thedl; 
     1542        dl->d=99999999; 
     1543        dl->thedir=(1); 
     1544 
     1545        geom1 = (PG_LWGEOM *)PG_DETOAST_DATUM(PG_GETARG_DATUM(0)); 
     1546        geom2 = (PG_LWGEOM *)PG_DETOAST_DATUM(PG_GETARG_DATUM(1)); 
     1547 
     1548        if (pglwgeom_getSRID(geom1) != pglwgeom_getSRID(geom2)) 
     1549        { 
     1550                elog(ERROR,"Operation on two GEOMETRIES with different SRIDs\n"); 
     1551                PG_RETURN_NULL(); 
     1552        } 
     1553 
     1554        SRID = pglwgeom_getSRID(geom1); 
     1555 
     1556        lw_dist2d_comp( SERIALIZED_FORM(geom1),SERIALIZED_FORM(geom2),0.0, dl ); 
     1557 
     1558        x1=dl->p1.x; 
     1559        y1=dl->p1.y; 
     1560        x2=dl->p2.x; 
     1561        y2=dl->p2.y; 
     1562/*       
     1563        if(x1==0) 
     1564        { 
     1565                if((x2==0)&&(y1==0)&&(y2==0)) 
     1566                { 
     1567                                PG_RETURN_NULL(); 
     1568                } 
     1569        } 
     1570        */ 
     1571        point1 = make_lwpoint2d(SRID, x1, y1); 
     1572        point2 = make_lwpoint2d(SRID, x2, y2); 
     1573 
     1574        lwpoints[0] = lwpoint_deserialize(SERIALIZED_FORM(pglwgeom_serialize((LWGEOM *)point1))); 
     1575        lwpoints[1] = lwpoint_deserialize(SERIALIZED_FORM(pglwgeom_serialize((LWGEOM *)point2))); 
     1576 
     1577        outline = lwline_from_lwpointarray(SRID, 2, lwpoints); 
     1578 
     1579        result = pglwgeom_serialize((LWGEOM *)outline); 
     1580        PG_RETURN_POINTER(result); 
     1581         
     1582} 
     1583 
     1584PG_FUNCTION_INFO_V1(LWGEOM_longestline2d); 
     1585Datum LWGEOM_longestline2d(PG_FUNCTION_ARGS) 
     1586{ 
     1587 
     1588        PG_LWGEOM *geom1; 
     1589        PG_LWGEOM *geom2; 
     1590        LWPOINT *point1; 
     1591        LWPOINT *point2; 
     1592        int SRID; 
     1593 
     1594        double x1,x2,y1,y2; 
     1595        PG_LWGEOM *result=NULL; 
     1596        LWPOINT *lwpoints[2]; 
     1597        LWLINE *outline; 
     1598        DISTPTS thedl; 
     1599        DISTPTS *dl = &thedl; 
     1600        dl->d=0; 
     1601        dl->thedir=(-1); 
     1602 
     1603        geom1 = (PG_LWGEOM *)PG_DETOAST_DATUM(PG_GETARG_DATUM(0)); 
     1604        geom2 = (PG_LWGEOM *)PG_DETOAST_DATUM(PG_GETARG_DATUM(1)); 
     1605 
     1606        if (pglwgeom_getSRID(geom1) != pglwgeom_getSRID(geom2)) 
     1607        { 
     1608                elog(ERROR,"Operation on two GEOMETRIES with different SRIDs\n"); 
     1609                PG_RETURN_NULL(); 
     1610        } 
     1611 
     1612        SRID = pglwgeom_getSRID(geom1); 
     1613 
     1614        lw_dist2d_comp( SERIALIZED_FORM(geom1),SERIALIZED_FORM(geom2),99999999, dl ); 
     1615 
     1616        x1=dl->p1.x; 
     1617        y1=dl->p1.y; 
     1618        x2=dl->p2.x; 
     1619        y2=dl->p2.y; 
     1620 
     1621        point1 = make_lwpoint2d(SRID, x1, y1); 
     1622        point2 = make_lwpoint2d(SRID, x2, y2); 
     1623 
     1624        lwpoints[0] = lwpoint_deserialize(SERIALIZED_FORM(pglwgeom_serialize((LWGEOM *)point1))); 
     1625        lwpoints[1] = lwpoint_deserialize(SERIALIZED_FORM(pglwgeom_serialize((LWGEOM *)point2))); 
     1626 
     1627        outline = lwline_from_lwpointarray(SRID, 2, lwpoints); 
     1628 
     1629        result = pglwgeom_serialize((LWGEOM *)outline); 
     1630 
     1631        PG_RETURN_POINTER(result); 
     1632} 
     1633 
    15231634/* Minimum 2d distance between objects in geom1 and geom2. */ 
    15241635PG_FUNCTION_INFO_V1(LWGEOM_mindistance2d); 
    15251636Datum LWGEOM_mindistance2d(PG_FUNCTION_ARGS) 
     
    15401651        } 
    15411652 
    15421653        mindist = lwgeom_mindistance2d_recursive(SERIALIZED_FORM(geom1), 
    1543                         SERIALIZED_FORM(geom2)); 
     1654                  SERIALIZED_FORM(geom2)); 
    15441655 
    15451656        PROFSTOP(PROF_QRUN); 
    15461657        PROFREPORT("dist",geom1, geom2, NULL); 
     
    15511662        PG_RETURN_FLOAT8(mindist); 
    15521663} 
    15531664 
    1554 /* Minimum 2d distance between objects in geom1 and geom2. */ 
    1555 PG_FUNCTION_INFO_V1(LWGEOM_dwithin); 
    1556 Datum LWGEOM_dwithin(PG_FUNCTION_ARGS) 
     1665PG_FUNCTION_INFO_V1(LWGEOM_maxdistance2d_linestring); 
     1666Datum LWGEOM_maxdistance2d_linestring(PG_FUNCTION_ARGS) 
    15571667{ 
    15581668        PG_LWGEOM *geom1; 
    15591669        PG_LWGEOM *geom2; 
    1560         double mindist, tolerance; 
     1670        double maxdist; 
    15611671 
    15621672        PROFSTART(PROF_QRUN); 
    15631673 
    15641674        geom1 = (PG_LWGEOM *)PG_DETOAST_DATUM(PG_GETARG_DATUM(0)); 
    15651675        geom2 = (PG_LWGEOM *)PG_DETOAST_DATUM(PG_GETARG_DATUM(1)); 
    1566         tolerance = PG_GETARG_FLOAT8(2); 
    15671676 
    1568         if ( tolerance < 0 ) 
    1569         { 
    1570                 elog(ERROR,"Tolerance cannot be less than zero\n"); 
    1571                 PG_RETURN_NULL(); 
    1572         } 
    1573  
    15741677        if (pglwgeom_getSRID(geom1) != pglwgeom_getSRID(geom2)) 
    15751678        { 
    15761679                elog(ERROR,"Operation on two GEOMETRIES with different SRIDs\n"); 
    15771680                PG_RETURN_NULL(); 
    15781681        } 
    15791682 
    1580         mindist = lwgeom_mindistance2d_recursive_tolerance( 
    1581                           SERIALIZED_FORM(geom1), 
    1582                           SERIALIZED_FORM(geom2), 
    1583                           tolerance 
    1584                   ); 
     1683        maxdist = lwgeom_maxdistance2d_recursive(SERIALIZED_FORM(geom1), 
     1684                  SERIALIZED_FORM(geom2)); 
    15851685 
    15861686        PROFSTOP(PROF_QRUN); 
    1587         PROFREPORT("dist",geom1, geom2, NULL); 
     1687        PROFREPORT("maxdist",geom1, geom2, NULL); 
    15881688 
    15891689        PG_FREE_IF_COPY(geom1, 0); 
    15901690        PG_FREE_IF_COPY(geom2, 1); 
    15911691 
    1592         PG_RETURN_BOOL(tolerance >= mindist); 
     1692        PG_RETURN_FLOAT8(maxdist); 
    15931693} 
    15941694 
    1595 /* 
    1596  *  Maximum 2d distance between linestrings. 
    1597  *  Returns NULL if given geoms are not linestrings. 
    1598  *  This is very bogus (or I'm missing its meaning) 
    1599  */ 
    1600 PG_FUNCTION_INFO_V1(LWGEOM_maxdistance2d_linestring); 
    1601 Datum LWGEOM_maxdistance2d_linestring(PG_FUNCTION_ARGS) 
     1695/* Minimum 2d distance between objects in geom1 and geom2. */ 
     1696PG_FUNCTION_INFO_V1(LWGEOM_dwithin); 
     1697Datum LWGEOM_dwithin(PG_FUNCTION_ARGS) 
    16021698{ 
    1603  
    16041699        PG_LWGEOM *geom1; 
    16051700        PG_LWGEOM *geom2; 
    1606         LWLINE *line1; 
    1607         LWLINE *line2; 
    1608         double maxdist = 0; 
    1609         int i; 
     1701        double mindist, tolerance; 
    16101702 
    1611         elog(ERROR, "This function is unimplemented yet"); 
    1612         PG_RETURN_NULL(); 
     1703        PROFSTART(PROF_QRUN); 
    16131704 
    16141705        geom1 = (PG_LWGEOM *)PG_DETOAST_DATUM(PG_GETARG_DATUM(0)); 
    1615         line1 = lwline_deserialize(SERIALIZED_FORM(geom1)); 
    1616         if ( line1 == NULL ) PG_RETURN_NULL(); /* not a linestring */ 
    1617  
    16181706        geom2 = (PG_LWGEOM *)PG_DETOAST_DATUM(PG_GETARG_DATUM(1)); 
    1619         line2 = lwline_deserialize(SERIALIZED_FORM(geom2)); 
    1620         if ( line2 == NULL ) PG_RETURN_NULL(); /* not a linestring */ 
     1707        tolerance = PG_GETARG_FLOAT8(2); 
    16211708 
     1709        if ( tolerance < 0 ) 
     1710        { 
     1711                elog(ERROR,"Tolerance cannot be less than zero\n"); 
     1712                PG_RETURN_NULL(); 
     1713        } 
     1714 
    16221715        if (pglwgeom_getSRID(geom1) != pglwgeom_getSRID(geom2)) 
    16231716        { 
    16241717                elog(ERROR,"Operation on two GEOMETRIES with different SRIDs\n"); 
    16251718                PG_RETURN_NULL(); 
    16261719        } 
    16271720 
    1628         for (i=0; i<line1->points->npoints; i++) 
    1629         { 
    1630                 POINT2D p; 
    1631                 double dist; 
     1721        mindist = lwgeom_mindistance2d_recursive_tolerance( 
     1722                      SERIALIZED_FORM(geom1), 
     1723                      SERIALIZED_FORM(geom2), 
     1724                      tolerance 
     1725                  ); 
    16321726 
    1633                 getPoint2d_p(line1->points, i, &p); 
    1634                 dist = distance2d_pt_ptarray(&p, line2->points); 
     1727        PROFSTOP(PROF_QRUN); 
     1728        PROFREPORT("dist",geom1, geom2, NULL); 
    16351729 
    1636                 if (dist > maxdist) maxdist = dist; 
    1637         } 
    1638  
    16391730        PG_FREE_IF_COPY(geom1, 0); 
    16401731        PG_FREE_IF_COPY(geom2, 1); 
    16411732 
    1642         PG_RETURN_FLOAT8(maxdist); 
     1733        PG_RETURN_BOOL(tolerance >= mindist); 
    16431734} 
    16441735 
    16451736/* 
     1737 *  LWGEOM_maxdistance2d_linestring is deleted and I have a new aproach to it /Nicklas Avén 
     1738 */ 
     1739/* 
    16461740 * Longitude shift: 
    16471741 *  Y remains the same 
    16481742 *  X is converted: 
     
    17881882        lwgeom_dropSRID(lwgeoms[1]); 
    17891883 
    17901884        outlwg = (LWGEOM *)lwcollection_construct( 
    1791                          outtype, SRID, 
    1792                          box, 2, lwgeoms); 
     1885                     outtype, SRID, 
     1886                     box, 2, lwgeoms); 
    17931887 
    17941888        result = pglwgeom_serialize(outlwg); 
    17951889 
     
    20622156        POSTGIS_DEBUGF(3, "LWGEOM_collect_garray: outtype = %d", outtype); 
    20632157 
    20642158        outlwg = (LWGEOM *)lwcollection_construct( 
    2065                          outtype, SRID, 
    2066                          box, nelems, lwgeoms); 
     2159                     outtype, SRID, 
     2160                     box, nelems, lwgeoms); 
    20672161 
    20682162        result = pglwgeom_serialize(outlwg); 
    20692163 
     
    21752269                if ( TYPE_GETTYPE(geom->type) != POINTTYPE ) continue; 
    21762270 
    21772271                lwpoints[npoints++] = 
    2178                         lwpoint_deserialize(SERIALIZED_FORM(geom)); 
     2272                    lwpoint_deserialize(SERIALIZED_FORM(geom)); 
    21792273 
    21802274                /* Check SRID homogeneity */ 
    21812275                if ( npoints == 1 ) 
     
    22322326        pglwg2 = (PG_LWGEOM *)PG_DETOAST_DATUM(PG_GETARG_DATUM(1)); 
    22332327 
    22342328        if ( ! TYPE_GETTYPE(pglwg1->type) == POINTTYPE || 
    2235                         ! TYPE_GETTYPE(pglwg2->type) == POINTTYPE ) 
     2329                ! TYPE_GETTYPE(pglwg2->type) == POINTTYPE ) 
    22362330        { 
    22372331                elog(ERROR, "Input geometries must be points"); 
    22382332                PG_RETURN_NULL(); 
     
    24362530 
    24372531 
    24382532        if (box.xmin == box.xmax && 
    2439                         box.ymin == box.ymax) 
     2533                box.ymin == box.ymax) 
    24402534        { 
    24412535                /* Construct and serialize point */ 
    24422536                LWPOINT *point = make_lwpoint2d(SRID, box.xmin, box.ymin); 
    24432537                ser = lwpoint_serialize(point); 
    24442538        } 
    24452539        else if (box.xmin == box.xmax || 
    2446                         box.ymin == box.ymax) 
     2540                 box.ymin == box.ymax) 
    24472541        { 
    24482542                LWLINE *line; 
    24492543                POINT2D *pts = palloc(sizeof(POINT2D)*2); 
     
    25332627 
    25342628        /* Avoid deserialize/serialize steps */ 
    25352629        if ( (TYPE_GETTYPE(ingeom->type) == POINTTYPE) || 
    2536                         (TYPE_GETTYPE(ingeom->type) == MULTIPOINTTYPE) ) 
     2630                (TYPE_GETTYPE(ingeom->type) == MULTIPOINTTYPE) ) 
    25372631                PG_RETURN_POINTER(ingeom); 
    25382632 
    25392633        inlwgeom = lwgeom_deserialize(SERIALIZED_FORM(ingeom)); 
     
    30803174        g1_bvol.ymax = g1_bvol.ymax + dist; 
    30813175 
    30823176        if (  (g1_bvol.xmin > geom2->bbox->xmax) || 
    3083                         (g1_bvol.xmax < geom2->bbox->xmin) || 
    3084                         (g1_bvol.ymin > geom2->bbox->ymax) || 
    3085                         (g1_bvol.ymax < geom2->bbox->ymin) 
     3177                (g1_bvol.xmax < geom2->bbox->xmin) || 
     3178                (g1_bvol.ymin > geom2->bbox->ymax) || 
     3179                (g1_bvol.ymax < geom2->bbox->ymin) 
    30863180           ) 
    30873181        { 
    30883182                PG_RETURN_BOOL(FALSE);  /*bbox not overlap */ 
     
    32163310                if (curve != NULL) 
    32173311                { 
    32183312                        lwgeom_affine_ptarray(curve->points, 
    3219                                 afac, bfac, cfac, 
    3220                                 dfac, efac, ffac, 
    3221                                 gfac, hfac, ifac, 
    3222                                 xoff, yoff, zoff); 
     3313                                              afac, bfac, cfac, 
     3314                                              dfac, efac, ffac, 
     3315                                              gfac, hfac, ifac, 
     3316                                              xoff, yoff, zoff); 
    32233317                        lwgeom_release((LWGEOM *)curve); 
    32243318                        continue; 
    32253319                } 
     
    32873381Datum ST_GeoHash(PG_FUNCTION_ARGS) 
    32883382{ 
    32893383 
    3290     PG_LWGEOM *geom = NULL; 
    3291     int precision = 0; 
    3292     int len = 0; 
    3293     char *geohash = NULL; 
    3294     char *result = NULL; 
     3384        PG_LWGEOM *geom = NULL; 
     3385        int precision = 0; 
     3386        int len = 0; 
     3387        char *geohash = NULL; 
     3388        char *result = NULL; 
    32953389 
    3296     if( PG_ARGISNULL(0) ) 
    3297     { 
     3390        if ( PG_ARGISNULL(0) ) 
     3391        { 
    32983392                PG_RETURN_NULL(); 
    3299     } 
     3393        } 
    33003394 
    3301     geom = (PG_LWGEOM *)PG_DETOAST_DATUM(PG_GETARG_DATUM(0)); 
     3395        geom = (PG_LWGEOM *)PG_DETOAST_DATUM(PG_GETARG_DATUM(0)); 
    33023396 
    3303     if( ! PG_ARGISNULL(1) )  
    3304     { 
    3305         precision = PG_GETARG_INT32(1); 
    3306     } 
     3397        if ( ! PG_ARGISNULL(1) ) 
     3398        { 
     3399                precision = PG_GETARG_INT32(1); 
     3400        } 
    33073401 
    3308     geohash = lwgeom_geohash((LWGEOM*)(pglwgeom_deserialize(geom)), precision); 
     3402        geohash = lwgeom_geohash((LWGEOM*)(pglwgeom_deserialize(geom)), precision); 
    33093403 
    3310     if( ! geohash )  
    3311     { 
     3404        if ( ! geohash ) 
     3405        { 
    33123406                elog(ERROR,"ST_GeoHash: lwgeom_geohash returned NULL.\n"); 
    33133407                PG_RETURN_NULL(); 
    3314     } 
     3408        } 
    33153409 
    33163410        len = strlen(geohash) + VARHDRSZ; 
    3317     result = palloc(len); 
     3411        result = palloc(len); 
    33183412        SET_VARSIZE(result, len); 
    33193413        memcpy(VARDATA(result), geohash, len-VARHDRSZ); 
    33203414        pfree(geohash); 
    33213415        PG_RETURN_POINTER(result); 
    3322      
     3416 
    33233417}