64 double side = ( (q->
x - p1->
x) * (p2->
y - p1->
y) - (p2->
x - p1->
x) * (q->
y - p1->
y) );
74 return sqrt((A1->
x-A2->
x)*(A1->
x-A2->
x)+(A1->
y-A2->
y)*(A1->
y-A2->
y));
95 return ((A1->
x <= P->
x && P->
x < A2->
x) || (A1->
x >= P->
x && P->
x > A2->
x)) ||
96 ((A1->
y <= P->
y && P->
y < A2->
y) || (A1->
y >= P->
y && P->
y > A2->
y));
105 if ( A1->
x == A2->
x && A2->
x == A3->
x &&
106 A1->
y == A2->
y && A2->
y == A3->
y )
119 double radius_A, circumference_A;
120 int a2_side, clockwise;
132 double dx = A1->
x - A3->
x;
133 double dy = A1->
y - A3->
y;
134 return sqrt(dx*dx + dy*dy);
138 circumference_A = M_PI * 2 * radius_A;
140 return circumference_A;
153 a1 = atan2(A1->
y - C.
y, A1->
x - C.
x);
154 a3 = atan2(A3->
y - C.
y, A3->
x - C.
x);
162 angle = 2*M_PI + a1 - a3;
169 angle = 2*M_PI + a3 - a1;
173 return circumference_A * (angle / (2*M_PI));
180 double side_Q, side_A2;
194 if ( d == radius_A && side_Q == side_A2 )
209 if ( d < radius_A && side_Q == side_A2 )
230 double dx21, dy21, dx31, dy31, h21, h31, d;
234 LWDEBUGF(2,
"lw_arc_center called (%.16f,%.16f), (%.16f,%.16f), (%.16f,%.16f).", p1->
x, p1->
y, p2->
x, p2->
y, p3->
x, p3->
y);
240 cx = p1->
x + (p2->
x - p1->
x) / 2.0;
241 cy = p1->
y + (p2->
y - p1->
y) / 2.0;
245 cr = sqrt(pow(cx - p1->
x, 2.0) + pow(cy - p1->
y, 2.0));
250 dx21 = p2->
x - p1->
x;
251 dy21 = p2->
y - p1->
y;
252 dx31 = p3->
x - p1->
x;
253 dy31 = p3->
y - p1->
y;
255 h21 = pow(dx21, 2.0) + pow(dy21, 2.0);
256 h31 = pow(dx31, 2.0) + pow(dy31, 2.0);
259 d = 2 * (dx21 * dy31 - dx31 * dy21);
266 cx = p1->
x + (h21 * dy31 - h31 * dy21) / d;
267 cy = p1->
y - (h21 * dx31 - h31 * dx21) / d;
271 cr = sqrt(pow(cx - p1->
x, 2) + pow(cy - p1->
y, 2));
288 if ( memcmp(first, last,
sizeof(
POINT2D)) )
290 lwerror(
"pt_in_ring_2d: V[n] != V[0] (%g %g != %g %g)",
291 first->
x, first->
y, last->
x, last->
y);
296 LWDEBUGF(2,
"pt_in_ring_2d called with point: %g %g", p->
x, p->
y);
301 for (i=0; i<ring->
npoints-1; i++)
310 ((v1->
y <= p->
y) && (v2->
y > p->
y))
312 || ((v1->
y > p->
y) && (v2->
y <= p->
y))
316 vt = (double)(p->
y - v1->
y) / (v2->
y - v1->
y);
319 if (p->
x < v1->
x + vt * (v2->
x - v1->
x))
328 LWDEBUGF(3,
"pt_in_ring_2d returning %d", cn&1);
373 int pq1, pq2, qp1, qp2;
384 if ((pq1>0 && pq2>0) || (pq1<0 && pq2<0))
392 if ( (qp1 > 0.0 && qp2 > 0.0) || (qp1 < 0.0 && qp2 < 0.0) )
398 if ( pq1 == 0.0 && pq2 == 0.0 && qp1 == 0.0 && qp2 == 0.0 )
408 LWDEBUGF(4,
"pq1=%.15g pq2=%.15g", pq1, pq2);
409 LWDEBUGF(4,
"qp1=%.15g qp2=%.15g", qp1, qp2);
412 if ( pq2 == 0 || qp2 == 0 )
461 uint32_t i = 0, j = 0;
462 const POINT2D *p1, *p2, *q1, *q2;
468 #if POSTGIS_DEBUG_LEVEL >= 4
476 if ( pa1->
npoints < 2 || pa2->npoints < 2 )
484 #if POSTGIS_DEBUG_LEVEL >= 4
496 for ( i = 1; i < pa2->npoints; i++ )
505 for ( j = 1; j < pa1->
npoints; j++ )
513 LWDEBUGF(4,
"i=%d, j=%d (%.8g %.8g, %.8g %.8g)", this_cross, i, j, p1->
x, p1->
y, p2->
x, p2->
y);
517 LWDEBUG(4,
"this_cross == SEG_CROSS_LEFT");
525 LWDEBUG(4,
"this_cross == SEG_CROSS_RIGHT");
538 LWDEBUG(4,
"this_cross == SEG_COLINEAR");
544 LWDEBUG(4,
"this_cross == SEG_NO_INTERSECTION");
556 LWDEBUGF(4,
"first_cross=%d, cross_left=%d, cross_right=%d", first_cross, cross_left, cross_right);
558 if ( !cross_left && !cross_right )
561 if ( !cross_left && cross_right == 1 )
564 if ( !cross_right && cross_left == 1 )
567 if ( cross_left - cross_right == 1 )
570 if ( cross_left - cross_right == -1 )
573 if ( cross_left - cross_right == 0 && first_cross ==
SEG_CROSS_LEFT )
587 static char *
base32 =
"0123456789bcdefghjkmnpqrstuvwxyz";
598 double lat[2], lon[2], mid;
599 char bits[] = {16,8,4,2,1};
603 char *geohash = v->
data;
614 mid = (lon[0] + lon[1]) / 2;
615 if (longitude >= mid)
627 mid = (lat[0] + lat[1]) / 2;
646 geohash[i++] =
base32[ch];
664 double lat[2], lon[2], mid;
668 double longitude = pt->
x;
669 double latitude = pt->
y;
680 mid = (lon[0] + lon[1]) / 2;
683 ch |= 0x0001u << bit;
693 mid = (lat[0] + lat[1]) / 2;
727 size_t hashlen = strlen(geohash);
735 char c = tolower(geohash[i]);
738 char *base32_pos = strchr(
base32, c);
741 lwerror(
"%s: Invalid character '%c'", __func__, geohash[i]);
744 char cd = base32_pos -
base32;
746 for (
size_t j = 0; j < 5; j++)
748 const char bits[] = {16, 8, 4, 2, 1};
752 lon[!(cd & mask)] = (lon[0] + lon[1]) / 2;
756 lat[!(cd & mask)] = (lat[0] + lat[1]) / 2;
765 double minx, miny, maxx, maxy;
766 double latmax, latmin, lonmax, lonmin;
767 double lonwidth, latwidth;
768 double latmaxadjust, lonmaxadjust, latminadjust, lonminadjust;
777 if ( minx == maxx && miny == maxy )
793 lonwidth = lonmax - lonmin;
794 latwidth = latmax - latmin;
795 latmaxadjust = lonmaxadjust = latminadjust = lonminadjust = 0.0;
797 if ( minx > lonmin + lonwidth / 2.0 )
799 lonminadjust = lonwidth / 2.0;
801 else if ( maxx < lonmax - lonwidth / 2.0 )
803 lonmaxadjust = -1 * lonwidth / 2.0;
805 if ( lonminadjust || lonmaxadjust )
807 lonmin += lonminadjust;
808 lonmax += lonmaxadjust;
818 if ( miny > latmin + latwidth / 2.0 )
820 latminadjust = latwidth / 2.0;
822 else if (maxy < latmax - latwidth / 2.0 )
824 latmaxadjust = -1 * latwidth / 2.0;
827 if ( latminadjust || latmaxadjust )
829 latmin += latminadjust;
830 latmax += latmaxadjust;
842 bounds->
xmin = lonmin;
843 bounds->
xmax = lonmax;
844 bounds->
ymin = latmin;
845 bounds->
ymax = latmax;
863 GBOX gbox_bounds = {0};
874 if ( gbox.
xmin < -180 || gbox.
ymin < -90 || gbox.
xmax > 180 || gbox.
ymax > 90 )
876 lwerror(
"Geohash requires inputs in decimal degrees, got (%g %g, %g %g).",
char result[OUT_DOUBLE_BUFFER_SIZE]
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
#define LWSIZE_SET(varsize, len)
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.
lwvarlena_t * lwgeom_geohash(const LWGEOM *lwgeom, int precision)
Calculate the GeoHash (http://geohash.org) string for a geometry.
lwvarlena_t * geohash_point(double longitude, double latitude, int precision)
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)
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.
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.