66 double side = ( (q->
x - p1->
x) * (p2->
y - p1->
y) - (p2->
x - p1->
x) * (q->
y - p1->
y) );
76 return sqrt((A1->
x-A2->
x)*(A1->
x-A2->
x)+(A1->
y-A2->
y)*(A1->
y-A2->
y));
97 return ((A1->
x <= P->
x && P->
x < A2->
x) || (A1->
x >= P->
x && P->
x > A2->
x)) ||
98 ((A1->
y <= P->
y && P->
y < A2->
y) || (A1->
y >= P->
y && P->
y > A2->
y));
107 if ( A1->
x == A2->
x && A2->
x == A3->
x &&
108 A1->
y == A2->
y && A2->
y == A3->
y )
121 double radius_A, circumference_A;
122 int a2_side, clockwise;
134 double dx = A1->
x - A3->
x;
135 double dy = A1->
y - A3->
y;
136 return sqrt(dx*dx + dy*dy);
140 circumference_A = M_PI * 2 * radius_A;
142 return circumference_A;
155 a1 = atan2(A1->
y - C.
y, A1->
x - C.
x);
156 a3 = atan2(A3->
y - C.
y, A3->
x - C.
x);
164 angle = 2*M_PI + a1 - a3;
171 angle = 2*M_PI + a3 - a1;
175 return circumference_A * (angle / (2*M_PI));
182 double side_Q, side_A2;
196 if ( d == radius_A && side_Q == side_A2 )
211 if ( d < radius_A && side_Q == side_A2 )
231 double dx21, dy21, dx31, dy31, h21, h31, d;
235 LWDEBUGF(2,
"lw_arc_center called (%.16f,%.16f), (%.16f,%.16f), (%.16f,%.16f).", p1->
x, p1->
y, p2->
x, p2->
y, p3->
x, p3->
y);
241 cx = p1->
x + (p2->
x - p1->
x) / 2.0;
242 cy = p1->
y + (p2->
y - p1->
y) / 2.0;
246 cr = sqrt(pow(cx - p1->
x, 2.0) + pow(cy - p1->
y, 2.0));
251 dx21 = p2->
x - p1->
x;
252 dy21 = p2->
y - p1->
y;
253 dx31 = p3->
x - p1->
x;
254 dy31 = p3->
y - p1->
y;
256 h21 = pow(dx21, 2.0) + pow(dy21, 2.0);
257 h31 = pow(dx31, 2.0) + pow(dy31, 2.0);
260 d = 2 * (dx21 * dy31 - dx31 * dy21);
267 cx = p1->
x + (h21 * dy31 - h31 * dy21) / d;
268 cy = p1->
y - (h21 * dx31 - h31 * dx21) / d;
272 cr = sqrt(pow(cx - p1->
x, 2) + pow(cy - p1->
y, 2));
274 LWDEBUGF(2,
"lw_arc_center center is (%.16f,%.16f)", result->
x, result->
y);
289 if ( memcmp(first, last,
sizeof(
POINT2D)) )
291 lwerror(
"pt_in_ring_2d: V[n] != V[0] (%g %g != %g %g)",
292 first->
x, first->
y, last->
x, last->
y);
297 LWDEBUGF(2,
"pt_in_ring_2d called with point: %g %g", p->
x, p->
y);
302 for (i=0; i<ring->
npoints-1; i++)
311 ((v1->
y <= p->
y) && (v2->
y > p->
y))
313 || ((v1->
y > p->
y) && (v2->
y <= p->
y))
317 vt = (double)(p->
y - v1->
y) / (v2->
y - v1->
y);
320 if (p->
x < v1->
x + vt * (v2->
x - v1->
x))
329 LWDEBUGF(3,
"pt_in_ring_2d returning %d", cn&1);
374 int pq1, pq2, qp1, qp2;
385 if ((pq1>0 && pq2>0) || (pq1<0 && pq2<0))
393 if ( (qp1 > 0.0 && qp2 > 0.0) || (qp1 < 0.0 && qp2 < 0.0) )
399 if ( pq1 == 0.0 && pq2 == 0.0 && qp1 == 0.0 && qp2 == 0.0 )
409 LWDEBUGF(4,
"pq1=%.15g pq2=%.15g", pq1, pq2);
410 LWDEBUGF(4,
"qp1=%.15g qp2=%.15g", qp1, qp2);
413 if ( pq2 == 0 || qp2 == 0 )
463 const POINT2D *p1, *p2, *q1, *q2;
474 if ( pa1->
npoints < 2 || pa2->npoints < 2 )
483 for ( i = 1; i < pa2->npoints; i++ )
492 for ( j = 1; j < pa1->
npoints; j++ )
500 LWDEBUGF(4,
"i=%d, j=%d (%.8g %.8g, %.8g %.8g)", this_cross, i, j, p1->
x, p1->
y, p2->
x, p2->
y);
504 LWDEBUG(4,
"this_cross == SEG_CROSS_LEFT");
512 LWDEBUG(4,
"this_cross == SEG_CROSS_RIGHT");
525 LWDEBUG(4,
"this_cross == SEG_COLINEAR");
531 LWDEBUG(4,
"this_cross == SEG_NO_INTERSECTION");
543 LWDEBUGF(4,
"first_cross=%d, cross_left=%d, cross_right=%d", first_cross, cross_left, cross_right);
545 if ( !cross_left && !cross_right )
548 if ( !cross_left && cross_right == 1 )
551 if ( !cross_right && cross_left == 1 )
554 if ( cross_left - cross_right == 1 )
557 if ( cross_left - cross_right == -1 )
560 if ( cross_left - cross_right == 0 && first_cross ==
SEG_CROSS_LEFT )
574 static char *
base32 =
"0123456789bcdefghjkmnpqrstuvwxyz";
584 double lat[2], lon[2], mid;
585 char bits[] = {16,8,4,2,1};
587 char *geohash = NULL;
589 geohash =
lwalloc(precision + 1);
596 while (i < precision)
600 mid = (lon[0] + lon[1]) / 2;
601 if (longitude >= mid)
613 mid = (lat[0] + lat[1]) / 2;
632 geohash[i++] =
base32[ch];
650 double lat[2], lon[2], mid;
654 double longitude = pt->
x;
655 double latitude = pt->
y;
666 mid = (lon[0] + lon[1]) / 2;
669 ch |= 0x0001u << bit;
679 mid = (lat[0] + lat[1]) / 2;
707 char c, cd, mask, is_even = 1;
708 static char bits[] = {16, 8, 4, 2, 1};
715 hashlen = strlen(geohash);
717 if (precision < 0 || precision > hashlen)
724 c = tolower(geohash[i]);
726 if (!(((c >=
'0') && (c <=
'9')) ||
727 ((c >=
'b') && (c <=
'z') && (c !=
'i') && (c !=
'l') && (c !=
'o'))))
729 lwerror(
"%s: Invalid character '%c'", __func__, geohash[i]);
734 for (j = 0; j < 5; j++)
739 lon[!(cd & mask)] = (lon[0] + lon[1]) / 2;
743 lat[!(cd & mask)] = (lat[0] + lat[1]) / 2;
752 double minx, miny, maxx, maxy;
753 double latmax, latmin, lonmax, lonmin;
754 double lonwidth, latwidth;
755 double latmaxadjust, lonmaxadjust, latminadjust, lonminadjust;
764 if ( minx == maxx && miny == maxy )
780 lonwidth = lonmax - lonmin;
781 latwidth = latmax - latmin;
782 latmaxadjust = lonmaxadjust = latminadjust = lonminadjust = 0.0;
784 if ( minx > lonmin + lonwidth / 2.0 )
786 lonminadjust = lonwidth / 2.0;
788 else if ( maxx < lonmax - lonwidth / 2.0 )
790 lonmaxadjust = -1 * lonwidth / 2.0;
792 if ( lonminadjust || lonmaxadjust )
794 lonmin += lonminadjust;
795 lonmax += lonmaxadjust;
805 if ( miny > latmin + latwidth / 2.0 )
807 latminadjust = latwidth / 2.0;
809 else if (maxy < latmax - latwidth / 2.0 )
811 latmaxadjust = -1 * latwidth / 2.0;
814 if ( latminadjust || latmaxadjust )
816 latmin += latminadjust;
817 latmax += latmaxadjust;
829 bounds->
xmin = lonmin;
830 bounds->
xmax = lonmax;
831 bounds->
ymin = latmin;
832 bounds->
ymax = latmax;
836 return precision / 5;
860 if ( gbox.
xmin < -180 || gbox.
ymin < -90 || gbox.
xmax > 180 || gbox.
ymax > 90 )
862 lwerror(
"Geohash requires inputs in decimal degrees, got (%g %g, %g %g).",
873 if ( precision <= 0 )
char * lwgeom_to_ewkt(const LWGEOM *lwgeom)
Return an alloced string.
int lwgeom_geohash_precision(GBOX bbox, GBOX *bounds)
int lw_arc_is_pt(const POINT2D *A1, const POINT2D *A2, const POINT2D *A3)
Returns true if arc A is actually a point (all vertices are the same) .
#define LWDEBUG(level, msg)
int lw_pt_in_arc(const POINT2D *P, const POINT2D *A1, const POINT2D *A2, const POINT2D *A3)
Returns true if P is on the same side of the plane partition defined by A1/A3 as A2 is...
double distance2d_pt_pt(const POINT2D *p1, const POINT2D *p2)
The old function nessecary for ptarray_segmentize2d in ptarray.c.
int lw_segment_intersects(const POINT2D *p1, const POINT2D *p2, const POINT2D *q1, const POINT2D *q2)
returns the kind of CG_SEGMENT_INTERSECTION_TYPE behavior of lineseg 1 (constructed from p1 and p2) a...
char * geohash_point(double longitude, double latitude, int precision)
int pt_in_ring_2d(const POINT2D *p, const POINTARRAY *ring)
void gbox_init(GBOX *gbox)
Zero out all the entries in the GBOX.
const POINT2D * getPoint2d_cp(const POINTARRAY *pa, int n)
Returns a POINT2D pointer into the POINTARRAY serialized_ptlist, suitable for reading from...
#define EPSILON_SQLMM
Tolerance used to determine equality.
#define LW_TRUE
Return types for functions with status returns.
double lw_arc_length(const POINT2D *A1, const POINT2D *A2, const POINT2D *A3)
Returns the length of a circular arc segment.
int lw_pt_in_seg(const POINT2D *P, const POINT2D *A1, const POINT2D *A2)
Returns true if P is between A1/A2.
int lwline_crossing_direction(const LWLINE *l1, const LWLINE *l2)
lwline_crossing_direction: returns the kind of CG_LINE_CROSS_TYPE behavior of 2 linestrings ...
double lw_arc_center(const POINT2D *p1, const POINT2D *p2, const POINT2D *p3, POINT2D *result)
Determines the center of the circle defined by the three given points.
int lw_arc_side(const POINT2D *A1, const POINT2D *A2, const POINT2D *A3, const POINT2D *Q)
static int lw_seg_interact(const POINT2D *p1, const POINT2D *p2, const POINT2D *q1, const POINT2D *q2)
int p4d_same(const POINT4D *p1, const POINT4D *p2)
unsigned int geohash_point_as_int(POINT2D *pt)
int p2d_same(const POINT2D *p1, const POINT2D *p2)
char * lwgeom_geohash(const LWGEOM *lwgeom, int precision)
Calculate the GeoHash (http://geohash.org) string for a geometry.
double lw_seg_length(const POINT2D *A1, const POINT2D *A2)
Returns the length of a linear segment.
int lw_segment_side(const POINT2D *p1, const POINT2D *p2, const POINT2D *q)
lw_segment_side()
void decode_geohash_bbox(char *geohash, double *lat, double *lon, int precision)
void * lwalloc(size_t size)
int p3d_same(const POINT3D *p1, const POINT3D *p2)
#define LWDEBUGF(level, msg,...)
void lwerror(const char *fmt,...)
Write a notice out to the error handler.
#define SIGNUM(n)
Macro that returns: -1 if n < 0, 1 if n > 0, 0 if n == 0.
int lwgeom_calculate_gbox_cartesian(const LWGEOM *lwgeom, GBOX *gbox)
Calculate the 2-4D bounding box of a geometry.