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 )
232 double dx21, dy21, dx31, dy31, h21, h31, d;
236 LWDEBUGF(2,
"lw_arc_center called (%.16f,%.16f), (%.16f,%.16f), (%.16f,%.16f).", p1->
x, p1->
y, p2->
x, p2->
y, p3->
x, p3->
y);
242 cx = p1->
x + (p2->
x - p1->
x) / 2.0;
243 cy = p1->
y + (p2->
y - p1->
y) / 2.0;
247 cr = sqrt(pow(cx - p1->
x, 2.0) + pow(cy - p1->
y, 2.0));
252 dx21 = p2->
x - p1->
x;
253 dy21 = p2->
y - p1->
y;
254 dx31 = p3->
x - p1->
x;
255 dy31 = p3->
y - p1->
y;
257 h21 = pow(dx21, 2.0) + pow(dy21, 2.0);
258 h31 = pow(dx31, 2.0) + pow(dy31, 2.0);
261 d = 2 * (dx21 * dy31 - dx31 * dy21);
268 cx = p1->
x + (h21 * dy31 - h31 * dy21) / d;
269 cy = p1->
y - (h21 * dx31 - h31 * dx21) / d;
273 cr = sqrt(pow(cx - p1->
x, 2) + pow(cy - p1->
y, 2));
275 LWDEBUGF(2,
"lw_arc_center center is (%.16f,%.16f)", result->
x, result->
y);
290 if ( memcmp(first, last,
sizeof(
POINT2D)) )
292 lwerror(
"pt_in_ring_2d: V[n] != V[0] (%g %g != %g %g)",
293 first->
x, first->
y, last->
x, last->
y);
298 LWDEBUGF(2,
"pt_in_ring_2d called with point: %g %g", p->
x, p->
y);
303 for (i=0; i<ring->
npoints-1; i++)
312 ((v1->
y <= p->
y) && (v2->
y > p->
y))
314 || ((v1->
y > p->
y) && (v2->
y <= p->
y))
318 vt = (double)(p->
y - v1->
y) / (v2->
y - v1->
y);
321 if (p->
x < v1->
x + vt * (v2->
x - v1->
x))
330 LWDEBUGF(3,
"pt_in_ring_2d returning %d", cn&1);
375 int pq1, pq2, qp1, qp2;
386 if ((pq1>0 && pq2>0) || (pq1<0 && pq2<0))
394 if ( (qp1 > 0.0 && qp2 > 0.0) || (qp1 < 0.0 && qp2 < 0.0) )
400 if ( pq1 == 0.0 && pq2 == 0.0 && qp1 == 0.0 && qp2 == 0.0 )
410 LWDEBUGF(4,
"pq1=%.15g pq2=%.15g", pq1, pq2);
411 LWDEBUGF(4,
"qp1=%.15g qp2=%.15g", qp1, qp2);
414 if ( pq2 == 0 || qp2 == 0 )
464 const POINT2D *p1, *p2, *q1, *q2;
470 #if POSTGIS_DEBUG_LEVEL >= 4
478 if ( pa1->
npoints < 2 || pa2->npoints < 2 )
481 #if POSTGIS_DEBUG_LEVEL >= 4
493 for ( i = 1; i < pa2->npoints; i++ )
502 for ( j = 1; j < pa1->
npoints; j++ )
510 LWDEBUGF(4,
"i=%d, j=%d (%.8g %.8g, %.8g %.8g)", this_cross, i, j, p1->
x, p1->
y, p2->
x, p2->
y);
514 LWDEBUG(4,
"this_cross == SEG_CROSS_LEFT");
522 LWDEBUG(4,
"this_cross == SEG_CROSS_RIGHT");
535 LWDEBUG(4,
"this_cross == SEG_COLINEAR");
541 LWDEBUG(4,
"this_cross == SEG_NO_INTERSECTION");
553 LWDEBUGF(4,
"first_cross=%d, cross_left=%d, cross_right=%d", first_cross, cross_left, cross_right);
555 if ( !cross_left && !cross_right )
558 if ( !cross_left && cross_right == 1 )
561 if ( !cross_right && cross_left == 1 )
564 if ( cross_left - cross_right == 1 )
567 if ( cross_left - cross_right == -1 )
570 if ( cross_left - cross_right == 0 && first_cross ==
SEG_CROSS_LEFT )
584 static char *
base32 =
"0123456789bcdefghjkmnpqrstuvwxyz";
594 double lat[2], lon[2], mid;
595 char bits[] = {16,8,4,2,1};
597 char *geohash = NULL;
610 mid = (lon[0] + lon[1]) / 2;
611 if (longitude >= mid)
623 mid = (lat[0] + lat[1]) / 2;
642 geohash[i++] =
base32[ch];
660 double lat[2], lon[2], mid;
664 double longitude = pt->
x;
665 double latitude = pt->
y;
676 mid = (lon[0] + lon[1]) / 2;
679 ch |= 0x0001u << bit;
689 mid = (lat[0] + lat[1]) / 2;
717 char c, cd, mask, is_even = 1;
718 static char bits[] = {16, 8, 4, 2, 1};
725 hashlen = strlen(geohash);
727 if (precision < 0 || precision > hashlen)
734 c = tolower(geohash[i]);
736 if (!(((c >=
'0') && (c <=
'9')) ||
737 ((c >=
'b') && (c <=
'z') && (c !=
'i') && (c !=
'l') && (c !=
'o'))))
739 lwerror(
"%s: Invalid character '%c'", __func__, geohash[i]);
744 for (j = 0; j < 5; j++)
749 lon[!(cd & mask)] = (lon[0] + lon[1]) / 2;
753 lat[!(cd & mask)] = (lat[0] + lat[1]) / 2;
762 double minx, miny, maxx, maxy;
763 double latmax, latmin, lonmax, lonmin;
764 double lonwidth, latwidth;
765 double latmaxadjust, lonmaxadjust, latminadjust, lonminadjust;
774 if ( minx == maxx && miny == maxy )
790 lonwidth = lonmax - lonmin;
791 latwidth = latmax - latmin;
792 latmaxadjust = lonmaxadjust = latminadjust = lonminadjust = 0.0;
794 if ( minx > lonmin + lonwidth / 2.0 )
796 lonminadjust = lonwidth / 2.0;
798 else if ( maxx < lonmax - lonwidth / 2.0 )
800 lonmaxadjust = -1 * lonwidth / 2.0;
802 if ( lonminadjust || lonmaxadjust )
804 lonmin += lonminadjust;
805 lonmax += lonmaxadjust;
815 if ( miny > latmin + latwidth / 2.0 )
817 latminadjust = latwidth / 2.0;
819 else if (maxy < latmax - latwidth / 2.0 )
821 latmaxadjust = -1 * latwidth / 2.0;
824 if ( latminadjust || latmaxadjust )
826 latmin += latminadjust;
827 latmax += latmaxadjust;
839 bounds->
xmin = lonmin;
840 bounds->
xmax = lonmax;
841 bounds->
ymin = latmin;
842 bounds->
ymax = latmax;
870 if ( gbox.
xmin < -180 || gbox.
ymin < -90 || gbox.
xmax > 180 || gbox.
ymax > 90 )
872 lwerror(
"Geohash requires inputs in decimal degrees, got (%g %g, %g %g).",
int lwgeom_calculate_gbox_cartesian(const LWGEOM *lwgeom, GBOX *gbox)
Calculate the 2-4D bounding box of a geometry.
void gbox_init(GBOX *gbox)
Zero out all the entries in the GBOX.
double distance2d_pt_pt(const POINT2D *p1, const POINT2D *p2)
char * lwgeom_to_ewkt(const LWGEOM *lwgeom)
Return an alloced string.
@ LINE_MULTICROSS_END_RIGHT
@ LINE_MULTICROSS_END_SAME_FIRST_LEFT
@ LINE_MULTICROSS_END_LEFT
@ LINE_MULTICROSS_END_SAME_FIRST_RIGHT
void * lwalloc(size_t size)
#define LW_TRUE
Return types for functions with status returns.
const POINT2D * getPoint2d_cp(const POINTARRAY *pa, uint32_t n)
Returns a POINT2D pointer into the POINTARRAY serialized_ptlist, suitable for reading from.
#define EPSILON_SQLMM
Tolerance used to determine equality.
#define SIGNUM(n)
Macro that returns: -1 if n < 0, 1 if n > 0, 0 if n == 0.
int lwgeom_geohash_precision(GBOX bbox, GBOX *bounds)
int p4d_same(const POINT4D *p1, const POINT4D *p2)
int p3d_same(const POINT3D *p1, const POINT3D *p2)
double lw_arc_length(const POINT2D *A1, const POINT2D *A2, const POINT2D *A3)
Returns the length of a circular arc segment.
unsigned int geohash_point_as_int(POINT2D *pt)
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
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...
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 pt_in_ring_2d(const POINT2D *p, const POINTARRAY *ring)
int lw_arc_side(const POINT2D *A1, const POINT2D *A2, const POINT2D *A3, const POINT2D *Q)
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.
static int lw_seg_interact(const POINT2D *p1, const POINT2D *p2, const POINT2D *q1, const POINT2D *q2)
int lw_pt_in_seg(const POINT2D *P, const POINT2D *A1, const POINT2D *A2)
Returns true if P is between A1/A2.
int lw_segment_side(const POINT2D *p1, const POINT2D *p2, const POINT2D *q)
lw_segment_side()
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) .
void decode_geohash_bbox(char *geohash, double *lat, double *lon, int precision)
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.
char * geohash_point(double longitude, double latitude, int precision)
int p2d_same(const POINT2D *p1, const POINT2D *p2)
#define LWDEBUG(level, msg)
#define LWDEBUGF(level, msg,...)
void lwerror(const char *fmt,...)
Write a notice out to the error handler.