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