67 double side = ( (q->
x - p1->
x) * (p2->
y - p1->
y) - (p2->
x - p1->
x) * (q->
y - p1->
y) );
77 return sqrt((A1->
x-A2->
x)*(A1->
x-A2->
x)+(A1->
y-A2->
y)*(A1->
y-A2->
y));
98 return ((A1->
x <= P->
x && P->
x < A2->
x) || (A1->
x >= P->
x && P->
x > A2->
x)) ||
99 ((A1->
y <= P->
y && P->
y < A2->
y) || (A1->
y >= P->
y && P->
y > A2->
y));
108 if ( A1->
x == A2->
x && A2->
x == A3->
x &&
109 A1->
y == A2->
y && A2->
y == A3->
y )
122 double radius_A, circumference_A;
123 int a2_side, clockwise;
135 double dx = A1->
x - A3->
x;
136 double dy = A1->
y - A3->
y;
137 return sqrt(dx*dx + dy*dy);
141 circumference_A = M_PI * 2 * radius_A;
143 return circumference_A;
156 a1 = atan2(A1->
y - C.
y, A1->
x - C.
x);
157 a3 = atan2(A3->
y - C.
y, A3->
x - C.
x);
165 angle = 2*M_PI + a1 - a3;
172 angle = 2*M_PI + a3 - a1;
176 return circumference_A * (angle / (2*M_PI));
183 double side_Q, side_A2;
197 if ( d == radius_A && side_Q == side_A2 )
212 if ( d < radius_A && side_Q == side_A2 )
233 double dx21, dy21, dx31, dy31, h21, h31, d;
237 LWDEBUGF(2,
"lw_arc_center called (%.16f,%.16f), (%.16f,%.16f), (%.16f,%.16f).", p1->
x, p1->
y, p2->
x, p2->
y, p3->
x, p3->
y);
243 cx = p1->
x + (p2->
x - p1->
x) / 2.0;
244 cy = p1->
y + (p2->
y - p1->
y) / 2.0;
248 cr = sqrt(pow(cx - p1->
x, 2.0) + pow(cy - p1->
y, 2.0));
253 dx21 = p2->
x - p1->
x;
254 dy21 = p2->
y - p1->
y;
255 dx31 = p3->
x - p1->
x;
256 dy31 = p3->
y - p1->
y;
258 h21 = pow(dx21, 2.0) + pow(dy21, 2.0);
259 h31 = pow(dx31, 2.0) + pow(dy31, 2.0);
262 d = 2 * (dx21 * dy31 - dx31 * dy21);
269 cx = p1->
x + (h21 * dy31 - h31 * dy21) / d;
270 cy = p1->
y - (h21 * dx31 - h31 * dx21) / d;
274 cr = sqrt(pow(cx - p1->
x, 2) + pow(cy - p1->
y, 2));
276 LWDEBUGF(2,
"lw_arc_center center is (%.16f,%.16f)", result->
x, result->
y);
291 if ( memcmp(first, last,
sizeof(
POINT2D)) )
293 lwerror(
"pt_in_ring_2d: V[n] != V[0] (%g %g != %g %g)",
294 first->
x, first->
y, last->
x, last->
y);
299 LWDEBUGF(2,
"pt_in_ring_2d called with point: %g %g", p->
x, p->
y);
304 for (i=0; i<ring->
npoints-1; i++)
313 ((v1->
y <= p->
y) && (v2->
y > p->
y))
315 || ((v1->
y > p->
y) && (v2->
y <= p->
y))
319 vt = (double)(p->
y - v1->
y) / (v2->
y - v1->
y);
322 if (p->
x < v1->
x + vt * (v2->
x - v1->
x))
331 LWDEBUGF(3,
"pt_in_ring_2d returning %d", cn&1);
376 int pq1, pq2, qp1, qp2;
387 if ((pq1>0 && pq2>0) || (pq1<0 && pq2<0))
395 if ( (qp1 > 0.0 && qp2 > 0.0) || (qp1 < 0.0 && qp2 < 0.0) )
401 if ( pq1 == 0.0 && pq2 == 0.0 && qp1 == 0.0 && qp2 == 0.0 )
411 LWDEBUGF(4,
"pq1=%.15g pq2=%.15g", pq1, pq2);
412 LWDEBUGF(4,
"qp1=%.15g qp2=%.15g", qp1, qp2);
415 if ( pq2 == 0 || qp2 == 0 )
464 uint32_t i = 0, j = 0;
465 const POINT2D *p1, *p2, *q1, *q2;
471 #if POSTGIS_DEBUG_LEVEL >= 4
479 if ( pa1->
npoints < 2 || pa2->npoints < 2 )
487 #if POSTGIS_DEBUG_LEVEL >= 4
499 for ( i = 1; i < pa2->npoints; i++ )
508 for ( j = 1; j < pa1->
npoints; j++ )
516 LWDEBUGF(4,
"i=%d, j=%d (%.8g %.8g, %.8g %.8g)", this_cross, i, j, p1->
x, p1->
y, p2->
x, p2->
y);
520 LWDEBUG(4,
"this_cross == SEG_CROSS_LEFT");
528 LWDEBUG(4,
"this_cross == SEG_CROSS_RIGHT");
541 LWDEBUG(4,
"this_cross == SEG_COLINEAR");
547 LWDEBUG(4,
"this_cross == SEG_NO_INTERSECTION");
559 LWDEBUGF(4,
"first_cross=%d, cross_left=%d, cross_right=%d", first_cross, cross_left, cross_right);
561 if ( !cross_left && !cross_right )
564 if ( !cross_left && cross_right == 1 )
567 if ( !cross_right && cross_left == 1 )
570 if ( cross_left - cross_right == 1 )
573 if ( cross_left - cross_right == -1 )
576 if ( cross_left - cross_right == 0 && first_cross ==
SEG_CROSS_LEFT )
590 static char *
base32 =
"0123456789bcdefghjkmnpqrstuvwxyz";
600 double lat[2], lon[2], mid;
601 char bits[] = {16,8,4,2,1};
603 char *geohash = NULL;
616 mid = (lon[0] + lon[1]) / 2;
617 if (longitude >= mid)
629 mid = (lat[0] + lat[1]) / 2;
648 geohash[i++] =
base32[ch];
666 double lat[2], lon[2], mid;
670 double longitude = pt->
x;
671 double latitude = pt->
y;
682 mid = (lon[0] + lon[1]) / 2;
685 ch |= 0x0001u << bit;
695 mid = (lat[0] + lat[1]) / 2;
729 size_t hashlen = strlen(geohash);
737 char c = tolower(geohash[i]);
740 char *base32_pos = strchr(
base32, c);
743 lwerror(
"%s: Invalid character '%c'", __func__, geohash[i]);
746 char cd = base32_pos -
base32;
748 for (
size_t j = 0; j < 5; j++)
750 const char bits[] = {16, 8, 4, 2, 1};
754 lon[!(cd & mask)] = (lon[0] + lon[1]) / 2;
758 lat[!(cd & mask)] = (lat[0] + lat[1]) / 2;
767 double minx, miny, maxx, maxy;
768 double latmax, latmin, lonmax, lonmin;
769 double lonwidth, latwidth;
770 double latmaxadjust, lonmaxadjust, latminadjust, lonminadjust;
779 if ( minx == maxx && miny == maxy )
795 lonwidth = lonmax - lonmin;
796 latwidth = latmax - latmin;
797 latmaxadjust = lonmaxadjust = latminadjust = lonminadjust = 0.0;
799 if ( minx > lonmin + lonwidth / 2.0 )
801 lonminadjust = lonwidth / 2.0;
803 else if ( maxx < lonmax - lonwidth / 2.0 )
805 lonmaxadjust = -1 * lonwidth / 2.0;
807 if ( lonminadjust || lonmaxadjust )
809 lonmin += lonminadjust;
810 lonmax += lonmaxadjust;
820 if ( miny > latmin + latwidth / 2.0 )
822 latminadjust = latwidth / 2.0;
824 else if (maxy < latmax - latwidth / 2.0 )
826 latmaxadjust = -1 * latwidth / 2.0;
829 if ( latminadjust || latmaxadjust )
831 latmin += latminadjust;
832 latmax += latmaxadjust;
844 bounds->
xmin = lonmin;
845 bounds->
xmax = lonmax;
846 bounds->
ymin = latmin;
847 bounds->
ymax = latmax;
875 if ( gbox.
xmin < -180 || gbox.
ymin < -90 || gbox.
xmax > 180 || gbox.
ymax > 90 )
877 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)
double ptarray_length_2d(const POINTARRAY *pts)
Find the 2d length of the given POINTARRAY (even if it's 3d)
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.
#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.
static const POINT2D * getPoint2d_cp(const POINTARRAY *pa, uint32_t n)
Returns a POINT2D pointer into the POINTARRAY serialized_ptlist, suitable for reading from.