1 #include "ellipse.h"
2
3 /* Ellipse functions */
4
5 PG_FUNCTION_INFO_V1(sphereellipse_in);
6 PG_FUNCTION_INFO_V1(sphereellipse_infunc);
7 PG_FUNCTION_INFO_V1(sphereellipse_incl);
8 PG_FUNCTION_INFO_V1(sphereellipse_rad1);
9 PG_FUNCTION_INFO_V1(sphereellipse_rad2);
10 PG_FUNCTION_INFO_V1(sphereellipse_center);
11 PG_FUNCTION_INFO_V1(sphereellipse_trans);
12 PG_FUNCTION_INFO_V1(sphereellipse_circle);
13 PG_FUNCTION_INFO_V1(spherepoint_ellipse);
14 PG_FUNCTION_INFO_V1(spherecircle_ellipse);
15 PG_FUNCTION_INFO_V1(sphereellipse_equal);
16 PG_FUNCTION_INFO_V1(sphereellipse_equal_neg);
17 PG_FUNCTION_INFO_V1(sphereellipse_cont_point);
18 PG_FUNCTION_INFO_V1(sphereellipse_cont_point_neg);
19 PG_FUNCTION_INFO_V1(sphereellipse_cont_point_com);
20 PG_FUNCTION_INFO_V1(sphereellipse_cont_point_com_neg);
21 PG_FUNCTION_INFO_V1(sphereellipse_cont_line);
22 PG_FUNCTION_INFO_V1(sphereellipse_cont_line_neg);
23 PG_FUNCTION_INFO_V1(sphereellipse_cont_line_com);
24 PG_FUNCTION_INFO_V1(sphereellipse_cont_line_com_neg);
25 PG_FUNCTION_INFO_V1(sphereellipse_overlap_line);
26 PG_FUNCTION_INFO_V1(sphereellipse_overlap_line_neg);
27 PG_FUNCTION_INFO_V1(sphereellipse_overlap_line_com);
28 PG_FUNCTION_INFO_V1(sphereellipse_overlap_line_com_neg);
29 PG_FUNCTION_INFO_V1(sphereellipse_cont_circle);
30 PG_FUNCTION_INFO_V1(sphereellipse_cont_circle_neg);
31 PG_FUNCTION_INFO_V1(sphereellipse_cont_circle_com);
32 PG_FUNCTION_INFO_V1(sphereellipse_cont_circle_com_neg);
33 PG_FUNCTION_INFO_V1(spherecircle_cont_ellipse);
34 PG_FUNCTION_INFO_V1(spherecircle_cont_ellipse_neg);
35 PG_FUNCTION_INFO_V1(spherecircle_cont_ellipse_com);
36 PG_FUNCTION_INFO_V1(spherecircle_cont_ellipse_com_neg);
37 PG_FUNCTION_INFO_V1(sphereellipse_overlap_circle);
38 PG_FUNCTION_INFO_V1(sphereellipse_overlap_circle_neg);
39 PG_FUNCTION_INFO_V1(sphereellipse_overlap_circle_com);
40 PG_FUNCTION_INFO_V1(sphereellipse_overlap_circle_com_neg);
41 PG_FUNCTION_INFO_V1(sphereellipse_cont_ellipse);
42 PG_FUNCTION_INFO_V1(sphereellipse_cont_ellipse_neg);
43 PG_FUNCTION_INFO_V1(sphereellipse_cont_ellipse_com);
44 PG_FUNCTION_INFO_V1(sphereellipse_cont_ellipse_com_neg);
45 PG_FUNCTION_INFO_V1(sphereellipse_overlap_ellipse);
46 PG_FUNCTION_INFO_V1(sphereellipse_overlap_ellipse_neg);
47 PG_FUNCTION_INFO_V1(spheretrans_ellipse);
48 PG_FUNCTION_INFO_V1(spheretrans_ellipse_inv);
49
50
51 /*
52 * This function returns the arccos of a value. If variable 'a' is outside
53 * the range (-1.00 .. 1.00), the function returns corresponding PI/2 or 3*PI/2.
54 */
55 static float8
my_acos(float8 a)56 my_acos(float8 a)
57 {
58 if (a > 1.0)
59 a = 1.0;
60 if (a < -1.0)
61 a = -1.0;
62 return acos(a);
63 }
64
65 /*
66 * Checks the parameter of an ellipse.
67 */
68 static void
sellipse_check(SELLIPSE * e)69 sellipse_check(SELLIPSE *e)
70 {
71 SPoint sp;
72
73 sp.lng = e->phi;
74 spoint_check(&sp);
75 if (PI - sp.lng >= PI_EPS)
76 e->phi = sp.lng;
77 else
78 e->phi = sp.lng - PI;
79 sp.lng = 0.0;
80 sp.lat = e->theta;
81 spoint_check(&sp);
82 e->theta = sp.lat;
83 sp.lng = e->psi;
84 sp.lat = 0.0;
85 spoint_check(&sp);
86 e->psi = sp.lng;
87 }
88
89 /*
90 * Returns the boundary circle of an ellipse.
91 */
92 static void
sellipse_circle(SCIRCLE * sc,const SELLIPSE * e)93 sellipse_circle(SCIRCLE *sc, const SELLIPSE *e)
94 {
95 SPoint sp;
96
97 sellipse_center(&sp, e);
98 memcpy((void *) &sc->center, (void *) &sp, sizeof(SPoint));
99 sc->radius = e->rad[0];
100 }
101
102 /*
103 * Returns an ellipse from axes, center and inclination. The largest axis
104 * length is chosen for large axis.
105 */
106 static SELLIPSE *
sellipse_in(float8 r1,float8 r2,const SPoint * c,float8 inc)107 sellipse_in(float8 r1, float8 r2, const SPoint *c, float8 inc)
108 {
109 SELLIPSE *e = (SELLIPSE *) palloc(sizeof(SELLIPSE));
110
111 e->rad[0] = Max(r1, r2);
112 e->rad[1] = Min(r1, r2);
113 e->phi = inc;
114 e->theta = -c->lat;
115 e->psi = c->lng;
116 if (FPge(e->rad[0], PIH) || FPge(e->rad[1], PIH))
117 {
118 pfree(e);
119 e = NULL;
120 elog(ERROR, "sphereellipse_in: radius must be less than 90 degrees");
121 }
122 else
123 {
124 sellipse_check(e);
125 }
126 return e;
127 }
128
129 /*
130 * Returns the radius of an ellipse depending on position angle.
131 *
132 * rada - major axis length
133 * radb - minor axis length
134 * ang - position angle in radians
135 */
136 static float8
sellipse_dist(float8 rada,float8 radb,float8 ang)137 sellipse_dist(float8 rada, float8 radb, float8 ang)
138 {
139 float8 e;
140
141 e = (1 - Sqr(sin(radb)) / Sqr(sin(rada)));
142 return (asin(sin(radb) / sqrt(1 - e * Sqr(cos(ang)))));
143 }
144
145 /*
146 * Returns distance between an ellipse and a point.
147 */
148 static float8
sellipse_point_dist(const SELLIPSE * se,const SPoint * sp)149 sellipse_point_dist(const SELLIPSE *se, const SPoint *sp)
150 {
151 SEuler e;
152 SPoint p;
153 float8 dist, rad, ang;
154
155 sellipse_trans(&e, se);
156 spheretrans_inv(&e);
157 euler_spoint_trans(&p, sp, &e);
158 dist = my_acos(cos(p.lng) * cos(p.lat));
159 if (FPzero(dist))
160 {
161 return -1.0;
162 }
163 else
164 {
165 if (FPeq(dist, PIH))
166 {
167 ang = p.lat;
168 }
169 else
170 {
171 ang = my_acos(tan(p.lng) / tan(dist));
172 }
173 rad = sellipse_dist(se->rad[0], se->rad[1], ang);
174 if (FPzero((dist - rad)))
175 {
176 return 0.0;
177 }
178 else if (FPgt(dist, rad))
179 {
180 return (dist - rad);
181 }
182 else
183 {
184 return -1.0;
185 }
186 }
187 return -1.0;
188 }
189
190 /*
191 * Performs an Euler transformation of an ellipse.
192 */
193 static void
euler_sellipse_trans(SELLIPSE * out,const SELLIPSE * in,const SEuler * se)194 euler_sellipse_trans(SELLIPSE *out, const SELLIPSE *in, const SEuler *se)
195 {
196 SEuler et;
197 SLine sl[2];
198 SPoint p[2];
199
200 sellipse_trans(&et, in);
201 sl[0].length = PIH;
202 sl[0].phi = sl[0].theta = sl[0].psi = 0.0;
203 euler_sline_trans(&sl[1], &sl[0], &et);
204 euler_sline_trans(&sl[0], &sl[1], se);
205 sline_begin(&p[0], &sl[0]);
206 sline_end(&p[1], &sl[0]);
207 et.psi = p[0].lng;
208 et.theta = -p[0].lat;
209 et.phi = 0.0;
210 et.phi_a = EULER_AXIS_X;
211 et.theta_a = EULER_AXIS_Y;
212 et.psi_a = EULER_AXIS_Z;
213 out->psi = et.psi;
214 out->theta = et.theta;
215 spheretrans_inv(&et);
216 euler_sline_trans(&sl[1], &sl[0], &et);
217 sphereline_to_euler(&et, &sl[1]);
218 out->phi = et.theta;
219 out->rad[0] = in->rad[0];
220 out->rad[1] = in->rad[1];
221 }
222
223
224 /*
225 * Returns the relationship between two ellipses as PGS_ELLIPSE_ELLIPSE_REL
226 * int8 value.
227 */
228 static int8
sellipse_ellipse_pos(const SELLIPSE * se1,const SELLIPSE * se2)229 sellipse_ellipse_pos(const SELLIPSE *se1, const SELLIPSE *se2)
230 {
231 int8 r;
232
233 /* equality */
234 if (sellipse_eq(se1, se2))
235 {
236 return PGS_ELLIPSE_CONT;
237 }
238
239 /* se2 is circle or point */
240 if (FPeq(se2->rad[0], se2->rad[1]))
241 {
242
243 SCIRCLE c;
244
245 sellipse_circle(&c, se2);
246 r = sellipse_circle_pos(se1, &c);
247
248 switch (r)
249 {
250 case PGS_ELLIPSE_CIRCLE_AVOID:
251 return PGS_ELLIPSE_AVOID;
252 case PGS_CIRCLE_CONT_ELLIPSE:
253 return PGS_ELLIPSE_OVER;
254 case PGS_ELLIPSE_CONT_CIRCLE:
255 return PGS_ELLIPSE_CONT;
256 case PGS_ELLIPSE_CIRCLE_OVER:
257 return PGS_ELLIPSE_OVER;
258 default:
259 return PGS_ELLIPSE_AVOID;
260 }
261
262 }
263
264 /* se1 is circle or point */
265 if (FPeq(se1->rad[0], se1->rad[1]))
266 {
267
268 SCIRCLE c;
269
270 sellipse_circle(&c, se1);
271 r = sellipse_circle_pos(se2, &c);
272 switch (r)
273 {
274 case PGS_ELLIPSE_CIRCLE_AVOID:
275 return PGS_ELLIPSE_AVOID;
276 case PGS_CIRCLE_CONT_ELLIPSE:
277 return PGS_ELLIPSE_CONT;
278 case PGS_ELLIPSE_CONT_CIRCLE:
279 return PGS_ELLIPSE_OVER;
280 case PGS_ELLIPSE_CIRCLE_OVER:
281 return PGS_ELLIPSE_OVER;
282 default:
283 return PGS_ELLIPSE_AVOID;
284 }
285
286 }
287
288 /* se2 is line */
289 if (FPzero(se2->rad[1]))
290 {
291 SLine l;
292
293 sellipse_line(&l, se2);
294 r = sellipse_line_pos(se1, &l);
295 switch (r)
296 {
297 case PGS_ELLIPSE_LINE_AVOID:
298 return PGS_ELLIPSE_AVOID;
299 case PGS_ELLIPSE_CONT_LINE:
300 return PGS_ELLIPSE_CONT;
301 case PGS_ELLIPSE_LINE_OVER:
302 return PGS_ELLIPSE_OVER;
303 default:
304 return PGS_ELLIPSE_AVOID;
305 }
306
307 }
308
309 /* se1 is line */
310 if (FPzero(se1->rad[1]))
311 {
312 SLine l;
313
314 sellipse_line(&l, se1);
315 r = sellipse_line_pos(se2, &l);
316 switch (r)
317 {
318 case PGS_ELLIPSE_LINE_AVOID:
319 return PGS_ELLIPSE_AVOID;
320 case PGS_ELLIPSE_CONT_LINE:
321 return PGS_ELLIPSE_OVER;
322 case PGS_ELLIPSE_LINE_OVER:
323 return PGS_ELLIPSE_OVER;
324 default:
325 return PGS_ELLIPSE_AVOID;
326 }
327
328 }
329
330 /* now we have two real ellipses */
331 do
332 {
333
334 SPoint p1, p2;
335 float8 dist;
336
337 /* check inner and outer circles */
338 sellipse_center(&p1, se1);
339 sellipse_center(&p2, se2);
340 dist = spoint_dist(&p1, &p2);
341 if (FPle((se1->rad[0] + se2->rad[0]), dist))
342 {
343 return PGS_ELLIPSE_AVOID;
344 }
345 else if (FPle((dist + se1->rad[0]), se2->rad[1]))
346 {
347 return PGS_ELLIPSE_OVER;
348 }
349 else if (FPle((dist + se2->rad[0]), se1->rad[1]))
350 {
351 return PGS_ELLIPSE_CONT;
352 }
353 else
354 {
355 SEuler eul;
356 SELLIPSE etmp, e;
357 SPoint sp[3];
358 int i;
359 float8 diff[3];
360 float8 elng;
361 const int maxcntr = 100000;
362 int cntr;
363
364 /* transform se1 to north pol */
365 sellipse_trans(&eul, se1);
366 spheretrans_inv(&eul);
367 euler_sellipse_trans(&etmp, se2, &eul);
368
369 eul.phi = PIH;
370 eul.theta = PIH;
371 eul.psi = 0;
372 eul.phi_a = EULER_AXIS_Z;
373 eul.theta_a = EULER_AXIS_X;
374 eul.psi_a = EULER_AXIS_Z;
375 euler_sellipse_trans(&e, &etmp, &eul);
376
377 etmp.rad[0] = se1->rad[0];
378 etmp.rad[1] = se1->rad[1];
379 etmp.phi = 0.0;
380 etmp.theta = -PIH;
381 etmp.psi = PIH;
382
383
384 /* search for minimum distance */
385 sp[0].lat = sp[2].lat = PIH - se1->rad[0];
386 sellipse_center(&sp[1], &e);
387
388 if (FPeq(sp[1].lat, PIH))
389 {
390 elng = PIH;
391 }
392 else
393 {
394 elng = sp[1].lng;
395 }
396 if (sin(elng) < 0)
397 {
398 sp[0].lng = PI;
399 sp[1].lng = 3 * PIH;
400 sp[2].lng = PID;
401 }
402 else
403 {
404 sp[0].lng = 0.0;
405 sp[1].lng = PIH;
406 sp[2].lng = PI;
407 }
408 sp[1].lat = PIH - se1->rad[1];
409
410 cntr = 0;
411 do
412 {
413 for (i = 0; i < 3; i++)
414 {
415 diff[i] = sellipse_point_dist(&e, &sp[i]);
416
417 if (diff[i] < 0.0)
418 {
419 return PGS_ELLIPSE_OVER;
420 }
421
422 }
423 if (diff[0] <= diff[1] && diff[1] <= diff[2])
424 {
425 memcpy((void *) &sp[2], (void *) &sp[1], sizeof(SPoint));
426 }
427 else if (diff[0] <= diff[2] && diff[2] <= diff[1])
428 {
429 if (Abs(sp[0].lng - elng) < Abs(sp[2].lng - elng))
430 {
431 memcpy((void *) &sp[2], (void *) &sp[1], sizeof(SPoint));
432 }
433 else
434 {
435 memcpy((void *) &sp[0], (void *) &sp[1], sizeof(SPoint));
436 }
437 }
438 else if (diff[1] <= diff[0] && diff[0] <= diff[2])
439 {
440 memcpy((void *) &sp[2], (void *) &sp[0], sizeof(SPoint));
441 memcpy((void *) &sp[0], (void *) &sp[1], sizeof(SPoint));
442 }
443 else if (diff[1] <= diff[2] && diff[2] <= diff[0])
444 {
445 memcpy((void *) &sp[0], (void *) &sp[1], sizeof(SPoint));
446 }
447 else if (diff[2] <= diff[0] && diff[0] <= diff[1])
448 {
449 if (Abs(sp[0].lng - elng) < Abs(sp[2].lng - elng))
450 {
451 memcpy((void *) &sp[2], (void *) &sp[1], sizeof(SPoint));
452 }
453 else
454 {
455 memcpy((void *) &sp[0], (void *) &sp[1], sizeof(SPoint));
456 }
457 }
458 else if (diff[2] <= diff[1] && diff[1] <= diff[0])
459 {
460 memcpy((void *) &sp[0], (void *) &sp[2], sizeof(SPoint));
461 memcpy((void *) &sp[2], (void *) &sp[1], sizeof(SPoint));
462 }
463 if (sp[2].lng < sp[0].lng)
464 {
465 /* switch here too */
466 memcpy((void *) &sp[1], (void *) &sp[0], sizeof(SPoint));
467 memcpy((void *) &sp[0], (void *) &sp[2], sizeof(SPoint));
468 memcpy((void *) &sp[2], (void *) &sp[1], sizeof(SPoint));
469 }
470 sp[1].lng = (sp[0].lng + sp[2].lng) / 2.0;
471 sp[1].lat = PIH - sellipse_dist(etmp.rad[0], etmp.rad[1], sp[1].lng);
472 cntr++;
473 } while (cntr < maxcntr && ((sp[2].lng - sp[0].lng) > FLT_EPSILON));
474 if (cntr >= maxcntr)
475 {
476 elog(ERROR, "Bug found in pg_sphere function 'sellipse_ellipse_pos' ! \n Please report it to pg_sphere team.");
477 }
478
479 sellipse_center(&sp[1], &e);
480 if (sellipse_cont_point(&etmp, &sp[1]))
481 {
482 return PGS_ELLIPSE_CONT;
483 }
484 else
485 {
486 return PGS_ELLIPSE_AVOID;
487 }
488 }
489 } while (0);
490
491 return PGS_ELLIPSE_AVOID;
492 }
493
494 void
sellipse_trans(SEuler * se,const SELLIPSE * e)495 sellipse_trans(SEuler *se, const SELLIPSE *e)
496 {
497 se->psi = e->psi;
498 se->theta = e->theta;
499 se->phi = e->phi;
500 se->phi_a = EULER_AXIS_X;
501 se->theta_a = EULER_AXIS_Y;
502 se->psi_a = EULER_AXIS_Z;
503 }
504
505 /* Returns center of ellipse */
506 void
sellipse_center(SPoint * sp,const SELLIPSE * e)507 sellipse_center(SPoint *sp, const SELLIPSE *e)
508 {
509 sp->lng = e->psi;
510 sp->lat = -e->theta;
511 }
512
513 bool
sellipse_line(SLine * sl,const SELLIPSE * e)514 sellipse_line(SLine *sl, const SELLIPSE *e)
515 {
516 if (!FPzero(e->rad[0]))
517 {
518 SEuler se;
519 SLine slt;
520 SPoint p[2];
521
522 p[0].lat = p[1].lat = 0.0;
523 p[0].lng = -e->rad[0];
524 p[1].lng = e->rad[0];
525 sline_from_points(&slt, &p[0], &p[1]);
526 sellipse_trans(&se, e);
527 euler_sline_trans(sl, &slt, &se);
528 return true;
529 }
530 else
531 {
532 return false;
533 }
534 }
535
536 bool
sellipse_eq(const SELLIPSE * e1,const SELLIPSE * e2)537 sellipse_eq(const SELLIPSE *e1, const SELLIPSE *e2)
538 {
539 if (FPne(e1->rad[0], e2->rad[0]) || FPne(e1->rad[1], e2->rad[1]))
540 {
541 return false;
542 }
543 else if (FPzero(e1->rad[0]))
544 {
545 /* point */
546 SPoint p[2];
547
548 sellipse_center(&p[0], e1);
549 sellipse_center(&p[1], e2);
550 return spoint_eq(&p[0], &p[1]);
551 }
552 else if (FPeq(e1->rad[0], e1->rad[1]))
553 {
554 /* circle */
555 SCIRCLE c[2];
556
557 sellipse_circle(&c[0], e1);
558 sellipse_circle(&c[1], e2);
559 return scircle_eq(&c[0], &c[1]);
560 }
561 else
562 {
563 SEuler se[2];
564
565 sellipse_trans(&se[0], e1);
566 sellipse_trans(&se[1], e2);
567 return strans_eq(&se[0], &se[1]);
568 }
569 return false;
570 }
571
572 bool
sellipse_cont_point(const SELLIPSE * se,const SPoint * sp)573 sellipse_cont_point(const SELLIPSE *se, const SPoint *sp)
574 {
575 SPoint c;
576 float8 dist;
577
578 sellipse_center(&c, se);
579 dist = spoint_dist(sp, &c);
580
581 if (FPgt(dist, se->rad[0]))
582 {
583 return false;
584 }
585 if (FPle(dist, se->rad[1]))
586 {
587 return true;
588 }
589 if (FPzero(se->rad[1]))
590 {
591 SLine l;
592
593 sellipse_line(&l, se);
594 return spoint_at_sline(sp, &l);
595 }
596 else
597 {
598 SEuler et;
599 SPoint p;
600 float8 a,
601 e;
602
603 sellipse_trans(&et, se);
604 spheretrans_inv(&et);
605 euler_spoint_trans(&p, sp, &et);
606 if (FPeq(dist, PIH))
607 {
608 e = p.lat;
609 }
610 else
611 {
612 e = my_acos(tan(p.lng) / tan(dist));
613 }
614 a = sellipse_dist(se->rad[0], se->rad[1], e);
615 if (FPge(a, dist))
616 {
617 return true;
618 }
619 else
620 {
621 return false;
622 }
623 }
624 return false;
625 }
626
627
628 int8
sellipse_line_pos(const SELLIPSE * se,const SLine * sl)629 sellipse_line_pos(const SELLIPSE *se, const SLine *sl)
630 {
631 /* line is point */
632 if (FPzero(sl->length))
633 {
634 SPoint p;
635
636 sline_begin(&p, sl);
637 if (sellipse_cont_point(se, &p))
638 {
639 return PGS_ELLIPSE_CONT_LINE;
640 }
641 else
642 {
643 return PGS_ELLIPSE_LINE_AVOID;
644 }
645 }
646
647 /* ellipse is point */
648 if (FPzero(se->rad[0]))
649 {
650 SPoint p;
651
652 sellipse_center(&p, se);
653 if (spoint_at_sline(&p, sl))
654 {
655 return PGS_ELLIPSE_LINE_OVER;
656 }
657 else
658 {
659 return PGS_ELLIPSE_LINE_AVOID;
660 }
661 }
662
663 /* ellipse is line */
664 if (FPzero(se->rad[1]))
665 {
666 SLine l;
667 int8 res;
668
669 sellipse_line(&l, se);
670 res = sline_sline_pos(&l, sl);
671 if (res == PGS_LINE_AVOID)
672 {
673 return PGS_ELLIPSE_LINE_AVOID;
674 }
675 else if (res == PGS_LINE_CONT_LINE || res == PGS_LINE_EQUAL)
676 {
677 return PGS_ELLIPSE_CONT_LINE;
678 }
679 else
680 {
681 return PGS_ELLIPSE_LINE_OVER;
682 }
683 }
684
685 /* ellipse is circle */
686 if (FPeq(se->rad[0], se->rad[1]))
687 {
688 SCIRCLE c;
689 int8 res;
690
691 sellipse_circle(&c, se);
692 res = sphereline_circle_pos(sl, &c);
693 if (res == PGS_CIRCLE_LINE_AVOID)
694 {
695 return PGS_ELLIPSE_LINE_AVOID;
696 }
697 else if (res == PGS_CIRCLE_CONT_LINE)
698 {
699 return PGS_ELLIPSE_CONT_LINE;
700 }
701 else
702 {
703 return PGS_ELLIPSE_LINE_OVER;
704 }
705 }
706
707 /* begin or end of line inside ellipse */
708 {
709 bool bb,
710 be;
711 SPoint p;
712
713 sline_begin(&p, sl);
714 bb = sellipse_cont_point(se, &p);
715 sline_end(&p, sl);
716 be = sellipse_cont_point(se, &p);
717 if (bb || be)
718 {
719 if (bb && be)
720 {
721 return PGS_ELLIPSE_CONT_LINE;
722 }
723 if (!(bb && be))
724 {
725 return PGS_ELLIPSE_LINE_OVER;
726 }
727 }
728
729 }
730
731 /* compare with bounding circle */
732 {
733
734 SCIRCLE c;
735 int8 res;
736
737 sellipse_circle(&c, se);
738 res = sphereline_circle_pos(sl, &c);
739 if (res == PGS_CIRCLE_LINE_AVOID)
740 {
741 return PGS_ELLIPSE_LINE_AVOID;
742 }
743 }
744
745 /* compare in detail */
746 {
747 SEuler e;
748 SPoint c;
749 SELLIPSE set;
750
751 sphereline_to_euler(&e, sl);
752 spheretrans_inv(&e);
753 euler_sellipse_trans(&set, se, &e);
754 sellipse_center(&c, &set);
755
756 if (sin(c.lng + se->rad[0]) < 0.0)
757 {
758 return PGS_ELLIPSE_LINE_AVOID;
759 }
760 if (sin(c.lng - se->rad[0] - sl->length) < 0.0)
761 {
762 return PGS_ELLIPSE_LINE_AVOID;
763 }
764 if ((c.lat >= 0) && (se->rad[0] - c.lat) > 0.0)
765 {
766 return PGS_ELLIPSE_LINE_AVOID;
767 }
768 if ((c.lat < 0) && (se->rad[0] + c.lat) > 0.0)
769 {
770 return PGS_ELLIPSE_LINE_AVOID;
771 }
772 else
773 {
774
775 SPoint cn;
776 float8 eps,
777 dist,
778 sinr;
779 float8 d[3];
780 int i;
781 SPoint lp[3];
782 SPoint lpt[3];
783
784 sellipse_trans(&e, &set);
785 spheretrans_inv(&e);
786 lp[0].lng = 0.0;
787 lp[1].lng = sl->length / 2;
788 lp[2].lng = sl->length;
789 lp[0].lat = lp[1].lat = lp[2].lat = 0.0;
790 cn.lng = 0.0;
791 cn.lat = 0.0;
792 eps = (1 - Sqr(sin(se->rad[1])) / Sqr(sin(se->rad[0])));
793 sinr = sin(se->rad[1]);
794
795 while (FPgt(lp[2].lng, lp[0].lng))
796 {
797
798 for (i = 0; i < 3; i++)
799 {
800 euler_spoint_trans(&lpt[i], &lp[i], &e);
801 dist = spoint_dist(&lpt[i], &cn);
802 if (FPeq(dist, PIH))
803 {
804 d[i] = lpt[i].lat;
805 }
806 else
807 {
808 d[i] = tan(lpt[i].lng) / tan(dist);
809 }
810 d[i] = asin(sinr / sqrt(1 - eps * Sqr(d[i])));
811 if (FPge(d[i], dist))
812 {
813 return PGS_ELLIPSE_LINE_OVER;
814 }
815 }
816 /* get the best values */
817 for (i = 0; i < 3; i++)
818 {
819 if (d[i] <= d[(i + 1) % 3] && d[i] <= d[(i + 2) % 3])
820 {
821 lpt[0].lng = lp[i].lng;
822 if (d[(i + 1) % 3] <= d[(i + 2) % 3])
823 {
824 lpt[1].lng = lp[(i + 1) % 3].lng;
825 }
826 else
827 {
828 lpt[1].lng = lp[(i + 2) % 3].lng;
829 }
830 if (lpt[0].lng > lpt[1].lng)
831 {
832 dist = lpt[0].lng;
833 lpt[0].lng = lpt[1].lng;
834 lpt[1].lng = dist;
835 }
836 lp[0].lng = lpt[0].lng;
837 lp[1].lng = (lpt[0].lng + lpt[1].lng) / 2;
838 lp[2].lng = lpt[1].lng;
839 }
840 }
841
842 }
843
844 }
845
846 }
847 return PGS_ELLIPSE_LINE_AVOID;
848 }
849
850
851 int8
sellipse_circle_pos(const SELLIPSE * se,const SCIRCLE * sc)852 sellipse_circle_pos(const SELLIPSE *se, const SCIRCLE *sc)
853 {
854 /* circle is point */
855 if (FPzero(sc->radius))
856 {
857 if (sellipse_cont_point(se, &sc->center))
858 {
859 return PGS_ELLIPSE_CONT_CIRCLE;
860 }
861 else
862 {
863 return PGS_ELLIPSE_CIRCLE_AVOID;
864 }
865 }
866
867 /* ellipse is circle */
868 if (FPeq(se->rad[0], se->rad[1]))
869 {
870 SCIRCLE tc;
871 float8 dist;
872
873 sellipse_circle(&tc, se);
874 if (scircle_eq(&tc, sc))
875 {
876 return PGS_ELLIPSE_CIRCLE_EQUAL;
877 }
878 dist = spoint_dist(&tc.center, &sc->center);
879 if (FPle((dist + sc->radius), tc.radius))
880 {
881 return PGS_ELLIPSE_CONT_CIRCLE;
882 }
883 if (FPle((dist + tc.radius), sc->radius))
884 {
885 return PGS_CIRCLE_CONT_ELLIPSE;
886 }
887 if (FPgt((sc->radius + tc.radius), dist))
888 {
889 return PGS_ELLIPSE_CIRCLE_OVER;
890 }
891 else
892 {
893 return PGS_ELLIPSE_CIRCLE_AVOID;
894 }
895 }
896
897 /* ellipse is line */
898 if (FPzero(se->rad[1]))
899 {
900 SLine l;
901 int8 res;
902
903 sellipse_line(&l, se);
904 res = sphereline_circle_pos(&l, sc);
905 if (res == PGS_CIRCLE_LINE_AVOID)
906 {
907 return PGS_ELLIPSE_CIRCLE_AVOID;
908 }
909 else if (res == PGS_CIRCLE_CONT_LINE)
910 {
911 return PGS_CIRCLE_CONT_ELLIPSE;
912 }
913 else
914 {
915 return PGS_ELLIPSE_CIRCLE_OVER;
916 }
917
918 }
919 else
920 {
921 /*
922 * now ellipse is a real ellipse and
923 * circle is a real circle
924 */
925
926 float8 dist;
927 SPoint c;
928
929 sellipse_center(&c, se);
930 dist = spoint_dist(&sc->center, &c);
931
932 if (FPzero(dist))
933 {
934 if (FPle(sc->radius, se->rad[1]))
935 {
936 return PGS_ELLIPSE_CONT_CIRCLE;
937 }
938 else if (FPge(sc->radius, se->rad[0]))
939 {
940 return PGS_CIRCLE_CONT_ELLIPSE;
941 }
942 else
943 {
944 return PGS_ELLIPSE_CIRCLE_OVER;
945 }
946
947 }
948 else
949 {
950
951 SEuler et;
952 SPoint p;
953 float8 a, e;
954
955 sellipse_trans(&et, se);
956 spheretrans_inv(&et);
957 euler_spoint_trans(&p, &sc->center, &et);
958 if (FPeq(dist, PIH))
959 {
960 e = p.lat;
961 }
962 else
963 {
964 e = my_acos(tan(p.lng) / tan(dist));
965 }
966 a = sellipse_dist(se->rad[0], se->rad[1], e);
967 if (FPle((dist + sc->radius), a))
968 {
969 return PGS_ELLIPSE_CONT_CIRCLE;
970 }
971 else if (FPle((dist + a), sc->radius))
972 {
973 return PGS_CIRCLE_CONT_ELLIPSE;
974 }
975 else if (FPgt((a + sc->radius), dist))
976 {
977 return PGS_ELLIPSE_CIRCLE_OVER;
978 }
979 else
980 {
981 return PGS_ELLIPSE_CIRCLE_AVOID;
982 }
983 }
984 }
985 return PGS_ELLIPSE_CIRCLE_AVOID;
986 }
987
988
989 Datum
sphereellipse_in(PG_FUNCTION_ARGS)990 sphereellipse_in(PG_FUNCTION_ARGS)
991 {
992 SELLIPSE *e = NULL;
993 char *s = PG_GETARG_CSTRING(0);
994 SPoint p;
995 double r1,
996 r2,
997 inc;
998
999 void sphere_yyparse(void);
1000
1001 init_buffer(s);
1002 sphere_yyparse();
1003 if (get_ellipse(&p.lng, &p.lat, &r1, &r2, &inc))
1004 {
1005 e = sellipse_in(r1, r2, &p, inc);
1006 reset_buffer();
1007 }
1008 PG_RETURN_POINTER(e);
1009 }
1010
1011 Datum
sphereellipse_infunc(PG_FUNCTION_ARGS)1012 sphereellipse_infunc(PG_FUNCTION_ARGS)
1013 {
1014 SPoint *p = (SPoint *) PG_GETARG_POINTER(0);
1015 float8 r1 = PG_GETARG_FLOAT8(1);
1016 float8 r2 = PG_GETARG_FLOAT8(2);
1017 float8 inc = PG_GETARG_FLOAT8(3);
1018 SELLIPSE *e = sellipse_in(r1, r2, p, inc);
1019
1020 PG_RETURN_POINTER(e);
1021 }
1022
1023 Datum
sphereellipse_incl(PG_FUNCTION_ARGS)1024 sphereellipse_incl(PG_FUNCTION_ARGS)
1025 {
1026 SELLIPSE *e = (SELLIPSE *) PG_GETARG_POINTER(0);
1027
1028 PG_RETURN_FLOAT8(e->phi);
1029 }
1030
1031 Datum
sphereellipse_rad1(PG_FUNCTION_ARGS)1032 sphereellipse_rad1(PG_FUNCTION_ARGS)
1033 {
1034 SELLIPSE *e = (SELLIPSE *) PG_GETARG_POINTER(0);
1035
1036 PG_RETURN_FLOAT8(e->rad[0]);
1037 }
1038
1039 Datum
sphereellipse_rad2(PG_FUNCTION_ARGS)1040 sphereellipse_rad2(PG_FUNCTION_ARGS)
1041 {
1042 SELLIPSE *e = (SELLIPSE *) PG_GETARG_POINTER(0);
1043
1044 PG_RETURN_FLOAT8(e->rad[1]);
1045 }
1046
1047 Datum
sphereellipse_center(PG_FUNCTION_ARGS)1048 sphereellipse_center(PG_FUNCTION_ARGS)
1049 {
1050 SELLIPSE *e = (SELLIPSE *) PG_GETARG_POINTER(0);
1051 SPoint *p = (SPoint *) palloc(sizeof(SPoint));
1052
1053 sellipse_center(p, e);
1054 PG_RETURN_POINTER(p);
1055 }
1056
1057 Datum
sphereellipse_trans(PG_FUNCTION_ARGS)1058 sphereellipse_trans(PG_FUNCTION_ARGS)
1059 {
1060 SELLIPSE *e = (SELLIPSE *) PG_GETARG_POINTER(0);
1061 SEuler *t = (SEuler *) palloc(sizeof(SEuler));
1062
1063 sellipse_trans(t, e);
1064 PG_RETURN_POINTER(t);
1065 }
1066
1067 Datum
sphereellipse_circle(PG_FUNCTION_ARGS)1068 sphereellipse_circle(PG_FUNCTION_ARGS)
1069 {
1070 SELLIPSE *e = (SELLIPSE *) PG_GETARG_POINTER(0);
1071 SCIRCLE *c = (SCIRCLE *) palloc(sizeof(SCIRCLE));
1072
1073 sellipse_circle(c, e);
1074 PG_RETURN_POINTER(c);
1075 }
1076
1077 Datum
spherepoint_ellipse(PG_FUNCTION_ARGS)1078 spherepoint_ellipse(PG_FUNCTION_ARGS)
1079 {
1080 SPoint *c = (SPoint *) PG_GETARG_POINTER(0);
1081 SELLIPSE *e = sellipse_in(0.0, 0.0, c, 0.0);
1082
1083 if (e)
1084 {
1085 PG_RETURN_POINTER(e);
1086 }
1087 PG_RETURN_NULL();
1088 }
1089
1090 Datum
spherecircle_ellipse(PG_FUNCTION_ARGS)1091 spherecircle_ellipse(PG_FUNCTION_ARGS)
1092 {
1093 SCIRCLE *c = (SCIRCLE *) PG_GETARG_POINTER(0);
1094 SELLIPSE *e = sellipse_in(c->radius, c->radius, &c->center, 0.0);
1095
1096 if (e)
1097 {
1098 PG_RETURN_POINTER(e);
1099 }
1100 PG_RETURN_NULL();
1101 }
1102
1103 Datum
sphereellipse_equal(PG_FUNCTION_ARGS)1104 sphereellipse_equal(PG_FUNCTION_ARGS)
1105 {
1106 SELLIPSE *e1 = (SELLIPSE *) PG_GETARG_POINTER(0);
1107 SELLIPSE *e2 = (SELLIPSE *) PG_GETARG_POINTER(1);
1108
1109 PG_RETURN_BOOL(sellipse_eq(e1, e2));
1110 }
1111
1112 Datum
sphereellipse_equal_neg(PG_FUNCTION_ARGS)1113 sphereellipse_equal_neg(PG_FUNCTION_ARGS)
1114 {
1115 SELLIPSE *e1 = (SELLIPSE *) PG_GETARG_POINTER(0);
1116 SELLIPSE *e2 = (SELLIPSE *) PG_GETARG_POINTER(1);
1117
1118 PG_RETURN_BOOL(!sellipse_eq(e1, e2));
1119 }
1120
1121 Datum
sphereellipse_cont_point(PG_FUNCTION_ARGS)1122 sphereellipse_cont_point(PG_FUNCTION_ARGS)
1123 {
1124 SELLIPSE *e = (SELLIPSE *) PG_GETARG_POINTER(0);
1125 SPoint *p = (SPoint *) PG_GETARG_POINTER(1);
1126
1127 PG_RETURN_BOOL(sellipse_cont_point(e, p));
1128 }
1129
1130 Datum
sphereellipse_cont_point_neg(PG_FUNCTION_ARGS)1131 sphereellipse_cont_point_neg(PG_FUNCTION_ARGS)
1132 {
1133 SELLIPSE *e = (SELLIPSE *) PG_GETARG_POINTER(0);
1134 SPoint *p = (SPoint *) PG_GETARG_POINTER(1);
1135
1136 PG_RETURN_BOOL(!sellipse_cont_point(e, p));
1137 }
1138
1139 Datum
sphereellipse_cont_point_com(PG_FUNCTION_ARGS)1140 sphereellipse_cont_point_com(PG_FUNCTION_ARGS)
1141 {
1142 SELLIPSE *e = (SELLIPSE *) PG_GETARG_POINTER(1);
1143 SPoint *p = (SPoint *) PG_GETARG_POINTER(0);
1144
1145 PG_RETURN_BOOL(sellipse_cont_point(e, p));
1146 }
1147
1148 Datum
sphereellipse_cont_point_com_neg(PG_FUNCTION_ARGS)1149 sphereellipse_cont_point_com_neg(PG_FUNCTION_ARGS)
1150 {
1151 SELLIPSE *e = (SELLIPSE *) PG_GETARG_POINTER(1);
1152 SPoint *p = (SPoint *) PG_GETARG_POINTER(0);
1153
1154 PG_RETURN_BOOL(!sellipse_cont_point(e, p));
1155 }
1156
1157 Datum
sphereellipse_cont_line(PG_FUNCTION_ARGS)1158 sphereellipse_cont_line(PG_FUNCTION_ARGS)
1159 {
1160 SELLIPSE *e = (SELLIPSE *) PG_GETARG_POINTER(0);
1161 SLine *l = (SLine *) PG_GETARG_POINTER(1);
1162 int8 b = sellipse_line_pos(e, l);
1163
1164 PG_RETURN_BOOL(b == PGS_ELLIPSE_CONT_LINE);
1165 }
1166
1167 Datum
sphereellipse_cont_line_neg(PG_FUNCTION_ARGS)1168 sphereellipse_cont_line_neg(PG_FUNCTION_ARGS)
1169 {
1170 SELLIPSE *e = (SELLIPSE *) PG_GETARG_POINTER(0);
1171 SLine *l = (SLine *) PG_GETARG_POINTER(1);
1172 int8 b = sellipse_line_pos(e, l);
1173
1174 PG_RETURN_BOOL(b != PGS_ELLIPSE_CONT_LINE);
1175 }
1176
1177 Datum
sphereellipse_cont_line_com(PG_FUNCTION_ARGS)1178 sphereellipse_cont_line_com(PG_FUNCTION_ARGS)
1179 {
1180 SELLIPSE *e = (SELLIPSE *) PG_GETARG_POINTER(1);
1181 SLine *l = (SLine *) PG_GETARG_POINTER(0);
1182 int8 b = sellipse_line_pos(e, l);
1183
1184 PG_RETURN_BOOL(b == PGS_ELLIPSE_CONT_LINE);
1185 }
1186
1187 Datum
sphereellipse_cont_line_com_neg(PG_FUNCTION_ARGS)1188 sphereellipse_cont_line_com_neg(PG_FUNCTION_ARGS)
1189 {
1190 SELLIPSE *e = (SELLIPSE *) PG_GETARG_POINTER(1);
1191 SLine *l = (SLine *) PG_GETARG_POINTER(0);
1192 int8 b = sellipse_line_pos(e, l);
1193
1194 PG_RETURN_BOOL(b != PGS_ELLIPSE_CONT_LINE);
1195 }
1196
1197 Datum
sphereellipse_overlap_line(PG_FUNCTION_ARGS)1198 sphereellipse_overlap_line(PG_FUNCTION_ARGS)
1199 {
1200 SELLIPSE *e = (SELLIPSE *) PG_GETARG_POINTER(0);
1201 SLine *l = (SLine *) PG_GETARG_POINTER(1);
1202 int8 b = sellipse_line_pos(e, l);
1203
1204 PG_RETURN_BOOL(b > PGS_ELLIPSE_LINE_AVOID);
1205 }
1206
1207 Datum
sphereellipse_overlap_line_neg(PG_FUNCTION_ARGS)1208 sphereellipse_overlap_line_neg(PG_FUNCTION_ARGS)
1209 {
1210 SELLIPSE *e = (SELLIPSE *) PG_GETARG_POINTER(0);
1211 SLine *l = (SLine *) PG_GETARG_POINTER(1);
1212 int8 b = sellipse_line_pos(e, l);
1213
1214 PG_RETURN_BOOL(b == PGS_ELLIPSE_LINE_AVOID);
1215 }
1216
1217 Datum
sphereellipse_overlap_line_com(PG_FUNCTION_ARGS)1218 sphereellipse_overlap_line_com(PG_FUNCTION_ARGS)
1219 {
1220 SELLIPSE *e = (SELLIPSE *) PG_GETARG_POINTER(1);
1221 SLine *l = (SLine *) PG_GETARG_POINTER(0);
1222 int8 b = sellipse_line_pos(e, l);
1223
1224 PG_RETURN_BOOL(b > PGS_ELLIPSE_LINE_AVOID);
1225 }
1226
1227 Datum
sphereellipse_overlap_line_com_neg(PG_FUNCTION_ARGS)1228 sphereellipse_overlap_line_com_neg(PG_FUNCTION_ARGS)
1229 {
1230 SELLIPSE *e = (SELLIPSE *) PG_GETARG_POINTER(1);
1231 SLine *l = (SLine *) PG_GETARG_POINTER(0);
1232 int8 b = sellipse_line_pos(e, l);
1233
1234 PG_RETURN_BOOL(b == PGS_ELLIPSE_LINE_AVOID);
1235 }
1236
1237
1238 Datum
sphereellipse_cont_circle(PG_FUNCTION_ARGS)1239 sphereellipse_cont_circle(PG_FUNCTION_ARGS)
1240 {
1241 SELLIPSE *e = (SELLIPSE *) PG_GETARG_POINTER(0);
1242 SCIRCLE *c = (SCIRCLE *) PG_GETARG_POINTER(1);
1243 int pos = sellipse_circle_pos(e, c);
1244
1245 PG_RETURN_BOOL(pos == PGS_ELLIPSE_CONT_CIRCLE || pos == PGS_ELLIPSE_CIRCLE_EQUAL);
1246 }
1247
1248 Datum
sphereellipse_cont_circle_neg(PG_FUNCTION_ARGS)1249 sphereellipse_cont_circle_neg(PG_FUNCTION_ARGS)
1250 {
1251 SELLIPSE *e = (SELLIPSE *) PG_GETARG_POINTER(0);
1252 SCIRCLE *c = (SCIRCLE *) PG_GETARG_POINTER(1);
1253 int pos = sellipse_circle_pos(e, c);
1254
1255 PG_RETURN_BOOL(pos != PGS_ELLIPSE_CONT_CIRCLE && pos != PGS_ELLIPSE_CIRCLE_EQUAL);
1256 }
1257
1258 Datum
sphereellipse_cont_circle_com(PG_FUNCTION_ARGS)1259 sphereellipse_cont_circle_com(PG_FUNCTION_ARGS)
1260 {
1261 SELLIPSE *e = (SELLIPSE *) PG_GETARG_POINTER(1);
1262 SCIRCLE *c = (SCIRCLE *) PG_GETARG_POINTER(0);
1263 int pos = sellipse_circle_pos(e, c);
1264
1265 PG_RETURN_BOOL(pos == PGS_ELLIPSE_CONT_CIRCLE || pos == PGS_ELLIPSE_CIRCLE_EQUAL);
1266 }
1267
1268 Datum
sphereellipse_cont_circle_com_neg(PG_FUNCTION_ARGS)1269 sphereellipse_cont_circle_com_neg(PG_FUNCTION_ARGS)
1270 {
1271 SELLIPSE *e = (SELLIPSE *) PG_GETARG_POINTER(1);
1272 SCIRCLE *c = (SCIRCLE *) PG_GETARG_POINTER(0);
1273 int pos = sellipse_circle_pos(e, c);
1274
1275 PG_RETURN_BOOL(pos != PGS_ELLIPSE_CONT_CIRCLE && pos != PGS_ELLIPSE_CIRCLE_EQUAL);
1276 }
1277
1278 Datum
spherecircle_cont_ellipse(PG_FUNCTION_ARGS)1279 spherecircle_cont_ellipse(PG_FUNCTION_ARGS)
1280 {
1281 SELLIPSE *e = (SELLIPSE *) PG_GETARG_POINTER(1);
1282 SCIRCLE *c = (SCIRCLE *) PG_GETARG_POINTER(0);
1283 int pos = sellipse_circle_pos(e, c);
1284
1285 PG_RETURN_BOOL(pos == PGS_CIRCLE_CONT_ELLIPSE || pos == PGS_ELLIPSE_CIRCLE_EQUAL);
1286 }
1287
1288 Datum
spherecircle_cont_ellipse_neg(PG_FUNCTION_ARGS)1289 spherecircle_cont_ellipse_neg(PG_FUNCTION_ARGS)
1290 {
1291 SELLIPSE *e = (SELLIPSE *) PG_GETARG_POINTER(1);
1292 SCIRCLE *c = (SCIRCLE *) PG_GETARG_POINTER(0);
1293 int pos = sellipse_circle_pos(e, c);
1294
1295 PG_RETURN_BOOL(pos != PGS_CIRCLE_CONT_ELLIPSE && pos != PGS_ELLIPSE_CIRCLE_EQUAL);
1296 }
1297
1298 Datum
spherecircle_cont_ellipse_com(PG_FUNCTION_ARGS)1299 spherecircle_cont_ellipse_com(PG_FUNCTION_ARGS)
1300 {
1301 SELLIPSE *e = (SELLIPSE *) PG_GETARG_POINTER(0);
1302 SCIRCLE *c = (SCIRCLE *) PG_GETARG_POINTER(1);
1303 int pos = sellipse_circle_pos(e, c);
1304
1305 PG_RETURN_BOOL(pos == PGS_CIRCLE_CONT_ELLIPSE || pos == PGS_ELLIPSE_CIRCLE_EQUAL);
1306 }
1307
1308 Datum
spherecircle_cont_ellipse_com_neg(PG_FUNCTION_ARGS)1309 spherecircle_cont_ellipse_com_neg(PG_FUNCTION_ARGS)
1310 {
1311 SELLIPSE *e = (SELLIPSE *) PG_GETARG_POINTER(0);
1312 SCIRCLE *c = (SCIRCLE *) PG_GETARG_POINTER(1);
1313 int pos = sellipse_circle_pos(e, c);
1314
1315 PG_RETURN_BOOL(pos != PGS_CIRCLE_CONT_ELLIPSE && pos != PGS_ELLIPSE_CIRCLE_EQUAL);
1316 }
1317
1318 Datum
sphereellipse_overlap_circle(PG_FUNCTION_ARGS)1319 sphereellipse_overlap_circle(PG_FUNCTION_ARGS)
1320 {
1321 SELLIPSE *e = (SELLIPSE *) PG_GETARG_POINTER(0);
1322 SCIRCLE *c = (SCIRCLE *) PG_GETARG_POINTER(1);
1323
1324 PG_RETURN_BOOL(sellipse_circle_pos(e, c) > PGS_ELLIPSE_CIRCLE_AVOID);
1325 }
1326
1327 Datum
sphereellipse_overlap_circle_neg(PG_FUNCTION_ARGS)1328 sphereellipse_overlap_circle_neg(PG_FUNCTION_ARGS)
1329 {
1330 SELLIPSE *e = (SELLIPSE *) PG_GETARG_POINTER(0);
1331 SCIRCLE *c = (SCIRCLE *) PG_GETARG_POINTER(1);
1332
1333 PG_RETURN_BOOL(sellipse_circle_pos(e, c) == PGS_ELLIPSE_CIRCLE_AVOID);
1334 }
1335
1336 Datum
sphereellipse_overlap_circle_com(PG_FUNCTION_ARGS)1337 sphereellipse_overlap_circle_com(PG_FUNCTION_ARGS)
1338 {
1339 SELLIPSE *e = (SELLIPSE *) PG_GETARG_POINTER(1);
1340 SCIRCLE *c = (SCIRCLE *) PG_GETARG_POINTER(0);
1341
1342 PG_RETURN_BOOL(sellipse_circle_pos(e, c) > PGS_ELLIPSE_CIRCLE_AVOID);
1343 }
1344
1345 Datum
sphereellipse_overlap_circle_com_neg(PG_FUNCTION_ARGS)1346 sphereellipse_overlap_circle_com_neg(PG_FUNCTION_ARGS)
1347 {
1348 SELLIPSE *e = (SELLIPSE *) PG_GETARG_POINTER(1);
1349 SCIRCLE *c = (SCIRCLE *) PG_GETARG_POINTER(0);
1350
1351 PG_RETURN_BOOL(sellipse_circle_pos(e, c) == PGS_ELLIPSE_CIRCLE_AVOID);
1352 }
1353
1354 Datum
sphereellipse_cont_ellipse(PG_FUNCTION_ARGS)1355 sphereellipse_cont_ellipse(PG_FUNCTION_ARGS)
1356 {
1357 SELLIPSE *e1 = (SELLIPSE *) PG_GETARG_POINTER(0);
1358 SELLIPSE *e2 = (SELLIPSE *) PG_GETARG_POINTER(1);
1359
1360 PG_RETURN_BOOL(sellipse_ellipse_pos(e1, e2) == PGS_ELLIPSE_CONT);
1361 }
1362
1363 Datum
sphereellipse_cont_ellipse_neg(PG_FUNCTION_ARGS)1364 sphereellipse_cont_ellipse_neg(PG_FUNCTION_ARGS)
1365 {
1366 SELLIPSE *e1 = (SELLIPSE *) PG_GETARG_POINTER(0);
1367 SELLIPSE *e2 = (SELLIPSE *) PG_GETARG_POINTER(1);
1368
1369 PG_RETURN_BOOL(sellipse_ellipse_pos(e1, e2) != PGS_ELLIPSE_CONT);
1370 }
1371
1372 Datum
sphereellipse_cont_ellipse_com(PG_FUNCTION_ARGS)1373 sphereellipse_cont_ellipse_com(PG_FUNCTION_ARGS)
1374 {
1375 SELLIPSE *e1 = (SELLIPSE *) PG_GETARG_POINTER(1);
1376 SELLIPSE *e2 = (SELLIPSE *) PG_GETARG_POINTER(0);
1377
1378 PG_RETURN_BOOL(sellipse_ellipse_pos(e1, e2) == PGS_ELLIPSE_CONT);
1379 }
1380
1381 Datum
sphereellipse_cont_ellipse_com_neg(PG_FUNCTION_ARGS)1382 sphereellipse_cont_ellipse_com_neg(PG_FUNCTION_ARGS)
1383 {
1384 SELLIPSE *e1 = (SELLIPSE *) PG_GETARG_POINTER(1);
1385 SELLIPSE *e2 = (SELLIPSE *) PG_GETARG_POINTER(0);
1386
1387 PG_RETURN_BOOL(sellipse_ellipse_pos(e1, e2) != PGS_ELLIPSE_CONT);
1388 }
1389
1390 Datum
sphereellipse_overlap_ellipse(PG_FUNCTION_ARGS)1391 sphereellipse_overlap_ellipse(PG_FUNCTION_ARGS)
1392 {
1393 SELLIPSE *e1 = (SELLIPSE *) PG_GETARG_POINTER(0);
1394 SELLIPSE *e2 = (SELLIPSE *) PG_GETARG_POINTER(1);
1395
1396 PG_RETURN_BOOL(sellipse_ellipse_pos(e1, e2) > PGS_ELLIPSE_AVOID);
1397 }
1398
1399 Datum
sphereellipse_overlap_ellipse_neg(PG_FUNCTION_ARGS)1400 sphereellipse_overlap_ellipse_neg(PG_FUNCTION_ARGS)
1401 {
1402 SELLIPSE *e1 = (SELLIPSE *) PG_GETARG_POINTER(0);
1403 SELLIPSE *e2 = (SELLIPSE *) PG_GETARG_POINTER(1);
1404
1405 PG_RETURN_BOOL(sellipse_ellipse_pos(e1, e2) == PGS_ELLIPSE_AVOID);
1406 }
1407
1408 Datum
spheretrans_ellipse(PG_FUNCTION_ARGS)1409 spheretrans_ellipse(PG_FUNCTION_ARGS)
1410 {
1411 SELLIPSE *e = (SELLIPSE *) PG_GETARG_POINTER(0);
1412 SEuler *se = (SEuler *) PG_GETARG_POINTER(1);
1413 SELLIPSE *out = (SELLIPSE *) palloc(sizeof(SELLIPSE));
1414
1415 euler_sellipse_trans(out, e, se);
1416 sellipse_check(out);
1417 PG_RETURN_POINTER(out);
1418 }
1419
1420 Datum
spheretrans_ellipse_inv(PG_FUNCTION_ARGS)1421 spheretrans_ellipse_inv(PG_FUNCTION_ARGS)
1422 {
1423 SELLIPSE *e = (SELLIPSE *) PG_GETARG_POINTER(0);
1424 SEuler *se = (SEuler *) PG_GETARG_POINTER(1);
1425 SELLIPSE *out = (SELLIPSE *) palloc(sizeof(SELLIPSE));
1426 SEuler tmp;
1427
1428 spheretrans_inverse(&tmp, se);
1429 euler_sellipse_trans(out, e, &tmp);
1430 sellipse_check(out);
1431 PG_RETURN_POINTER(out);
1432 }
1433