pcb 4.1.1
An interactive printed circuit board layout editor.
|
00001 /* GTS - Library for the manipulation of triangulated surfaces 00002 * Copyright (C) 1999 Stéphane Popinet 00003 * 00004 * This library is free software; you can redistribute it and/or 00005 * modify it under the terms of the GNU Library General Public 00006 * License as published by the Free Software Foundation; either 00007 * version 2 of the License, or (at your option) any later version. 00008 * 00009 * This library is distributed in the hope that it will be useful, 00010 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00012 * Library General Public License for more details. 00013 * 00014 * You should have received a copy of the GNU Library General Public 00015 * License along with this library; if not, write to the 00016 * Free Software Foundation, Inc., 59 Temple Place - Suite 330, 00017 * Boston, MA 02111-1307, USA. 00018 */ 00019 00020 #include <math.h> 00021 #include <stdlib.h> 00022 #include "gts.h" 00023 #include "gts-private.h" 00024 #include "predicates.h" 00025 00026 static void point_read (GtsObject ** o, GtsFile * f) 00027 { 00028 GtsPoint * p = GTS_POINT (*o); 00029 00030 if (GTS_POINT_CLASS ((*o)->klass)->binary) { 00031 if (gts_file_read (f, &(p->x), sizeof (gdouble), 1) != 1) { 00032 gts_file_error (f, "expecting a binary number (x coordinate)"); 00033 return; 00034 } 00035 if (gts_file_read (f, &(p->y), sizeof (gdouble), 1) != 1) { 00036 gts_file_error (f, "expecting a binary number (y coordinate)"); 00037 return; 00038 } 00039 if (gts_file_read (f, &(p->z), sizeof (gdouble), 1) != 1) { 00040 gts_file_error (f, "expecting a binary number (z coordinate)"); 00041 return; 00042 } 00043 } 00044 else { 00045 if (f->type != GTS_INT && f->type != GTS_FLOAT) { 00046 gts_file_error (f, "expecting a number (x coordinate)"); 00047 return; 00048 } 00049 p->x = atof (f->token->str); 00050 00051 gts_file_next_token (f); 00052 if (f->type != GTS_INT && f->type != GTS_FLOAT) { 00053 gts_file_error (f, "expecting a number (y coordinate)"); 00054 return; 00055 } 00056 p->y = atof (f->token->str); 00057 00058 gts_file_next_token (f); 00059 if (f->type != GTS_INT && f->type != GTS_FLOAT) { 00060 gts_file_error (f, "expecting a number (z coordinate)"); 00061 return; 00062 } 00063 p->z = atof (f->token->str); 00064 00065 gts_file_next_token (f); 00066 } 00067 } 00068 00069 static void point_write (GtsObject * o, FILE * fptr) 00070 { 00071 GtsPoint * p = GTS_POINT (o); 00072 00073 if (GTS_POINT_CLASS ((o)->klass)->binary) { 00074 fwrite (&(p->x), sizeof (gdouble), 1, fptr); 00075 fwrite (&(p->y), sizeof (gdouble), 1, fptr); 00076 fwrite (&(p->z), sizeof (gdouble), 1, fptr); 00077 } 00078 else 00079 fprintf (fptr, "%.10g %.10g %.10g", p->x, p->y, p->z); 00080 } 00081 00082 static void point_class_init (GtsObjectClass * klass) 00083 { 00084 klass->read = point_read; 00085 klass->write = point_write; 00086 } 00087 00093 GtsPointClass * gts_point_class (void) 00094 { 00095 static GtsPointClass * klass = NULL; 00096 00097 if (klass == NULL) { 00098 GtsObjectClassInfo point_info = { 00099 "GtsPoint", 00100 sizeof (GtsPoint), 00101 sizeof (GtsPointClass), 00102 (GtsObjectClassInitFunc) point_class_init, 00103 (GtsObjectInitFunc) NULL, 00104 (GtsArgSetFunc) NULL, 00105 (GtsArgGetFunc) NULL 00106 }; 00107 klass = gts_object_class_new (gts_object_class (), 00108 &point_info); 00109 } 00110 00111 return klass; 00112 } 00113 00123 GtsPoint * gts_point_new (GtsPointClass * klass, 00124 gdouble x, gdouble y, gdouble z) 00125 { 00126 GtsPoint * p; 00127 00128 p = GTS_POINT (gts_object_new (GTS_OBJECT_CLASS (klass))); 00129 p->x = x; 00130 p->y = y; 00131 p->z = z; 00132 00133 return p; 00134 } 00135 00145 void gts_point_set (GtsPoint * p, gdouble x, gdouble y, gdouble z) 00146 { 00147 g_return_if_fail (p != NULL); 00148 00149 p->x = x; 00150 p->y = y; 00151 p->z = z; 00152 } 00153 00161 gdouble gts_point_distance (GtsPoint * p1, GtsPoint * p2) 00162 { 00163 g_return_val_if_fail (p1 != NULL && p2 != NULL, 0.0); 00164 00165 return sqrt ((p1->x - p2->x)*(p1->x - p2->x) + 00166 (p1->y - p2->y)*(p1->y - p2->y) + 00167 (p1->z - p2->z)*(p1->z - p2->z)); 00168 } 00169 00177 gdouble gts_point_distance2 (GtsPoint * p1, GtsPoint * p2) 00178 { 00179 g_return_val_if_fail (p1 != NULL && p2 != NULL, 0.0); 00180 00181 return 00182 (p1->x - p2->x)*(p1->x - p2->x) + 00183 (p1->y - p2->y)*(p1->y - p2->y) + 00184 (p1->z - p2->z)*(p1->z - p2->z); 00185 } 00186 00205 gdouble gts_point_orientation_3d (GtsPoint * p1, 00206 GtsPoint * p2, 00207 GtsPoint * p3, 00208 GtsPoint * p4) 00209 { 00210 g_return_val_if_fail (p1 != NULL && p2 != NULL && 00211 p3 != NULL && p4 != NULL, 0.0); 00212 return orient3d ((gdouble *) &p1->x, 00213 (gdouble *) &p2->x, 00214 (gdouble *) &p3->x, 00215 (gdouble *) &p4->x); 00216 } 00217 00230 GtsIntersect gts_point_is_in_triangle (GtsPoint * p, GtsTriangle * t) 00231 { 00232 GtsVertex * v1, * v2, * v3; 00233 gdouble d1, d2, d3; 00234 00235 g_return_val_if_fail (p != NULL && t != NULL, FALSE); 00236 00237 gts_triangle_vertices (t, &v1, &v2, &v3); 00238 00239 d1 = gts_point_orientation (GTS_POINT (v1), GTS_POINT (v2), p); 00240 if (d1 < 0.0) 00241 return GTS_OUT; 00242 d2 = gts_point_orientation (GTS_POINT (v2), GTS_POINT (v3), p); 00243 if (d2 < 0.0) 00244 return GTS_OUT; 00245 d3 = gts_point_orientation (GTS_POINT (v3), GTS_POINT (v1), p); 00246 if (d3 < 0.0) 00247 return GTS_OUT; 00248 if (d1 == 0.0 || d2 == 0.0 || d3 == 0.0) 00249 return GTS_ON; 00250 return GTS_IN; 00251 } 00252 00266 gdouble gts_point_in_triangle_circle (GtsPoint * p, GtsTriangle * t) 00267 { 00268 GtsPoint * p1, * p2, * p3; 00269 00270 g_return_val_if_fail (p != NULL && t != NULL, 0.0); 00271 00272 gts_triangle_vertices (t, 00273 (GtsVertex **) &p1, 00274 (GtsVertex **) &p2, 00275 (GtsVertex **) &p3); 00276 00277 return incircle ((gdouble *) &p1->x, 00278 (gdouble *) &p2->x, 00279 (gdouble *) &p3->x, 00280 (gdouble *) &p->x); 00281 } 00282 00297 gdouble gts_point_in_circle (GtsPoint * p, 00298 GtsPoint * p1, GtsPoint * p2, GtsPoint * p3) 00299 { 00300 g_return_val_if_fail (p != NULL && p1 != NULL && p2 != NULL && p3 != NULL, 00301 0.0); 00302 00303 return incircle ((gdouble *) &p1->x, 00304 (gdouble *) &p2->x, 00305 (gdouble *) &p3->x, 00306 (gdouble *) &p->x); 00307 } 00308 00324 gdouble gts_point_in_sphere (GtsPoint * p, 00325 GtsPoint * p1, GtsPoint * p2, GtsPoint * p3, GtsPoint * p4) 00326 { 00327 g_return_val_if_fail (p != NULL && p1 != NULL && p2 != NULL && p3 != NULL && p4 != NULL, 00328 0.0); 00329 00330 return insphere ((gdouble *) &p1->x, 00331 (gdouble *) &p2->x, 00332 (gdouble *) &p3->x, 00333 (gdouble *) &p4->x, 00334 (gdouble *) &p->x); 00335 } 00336 00344 gdouble gts_point_segment_distance2 (GtsPoint * p, GtsSegment * s) 00345 { 00346 gdouble t, ns2, x, y, z; 00347 GtsPoint * p1, * p2; 00348 00349 g_return_val_if_fail (p != NULL, 0.0); 00350 g_return_val_if_fail (s != NULL, 0.0); 00351 00352 p1 = GTS_POINT (s->v1); 00353 p2 = GTS_POINT (s->v2); 00354 ns2 = gts_point_distance2 (p1, p2); 00355 if (ns2 == 0.0) 00356 return gts_point_distance2 (p, p1); 00357 t = ((p2->x - p1->x)*(p->x - p1->x) + 00358 (p2->y - p1->y)*(p->y - p1->y) + 00359 (p2->z - p1->z)*(p->z - p1->z))/ns2; 00360 if (t > 1.0) 00361 return gts_point_distance2 (p, p2); 00362 if (t < 0.0) 00363 return gts_point_distance2 (p, p1); 00364 x = (1. - t)*p1->x + t*p2->x - p->x; 00365 y = (1. - t)*p1->y + t*p2->y - p->y; 00366 z = (1. - t)*p1->z + t*p2->z - p->z; 00367 return x*x + y*y + z*z; 00368 } 00369 00377 gdouble gts_point_segment_distance (GtsPoint * p, GtsSegment * s) 00378 { 00379 g_return_val_if_fail (p != NULL, 0.0); 00380 g_return_val_if_fail (s != NULL, 0.0); 00381 00382 return sqrt (gts_point_segment_distance2 (p, s)); 00383 } 00384 00394 void gts_point_segment_closest (GtsPoint * p, 00395 GtsSegment * s, 00396 GtsPoint * closest) 00397 { 00398 gdouble t, ns2; 00399 GtsPoint * p1, * p2; 00400 00401 g_return_if_fail (p != NULL); 00402 g_return_if_fail (s != NULL); 00403 g_return_if_fail (closest != NULL); 00404 00405 p1 = GTS_POINT (s->v1); 00406 p2 = GTS_POINT (s->v2); 00407 ns2 = gts_point_distance2 (p1, p2); 00408 00409 if (ns2 == 0.0) { 00410 gts_point_set (closest, p1->x, p1->y, p1->z); 00411 return; 00412 } 00413 00414 t = ((p2->x - p1->x)*(p->x - p1->x) + 00415 (p2->y - p1->y)*(p->y - p1->y) + 00416 (p2->z - p1->z)*(p->z - p1->z))/ns2; 00417 00418 if (t > 1.0) 00419 gts_point_set (closest, p2->x, p2->y, p2->z); 00420 else if (t < 0.0) 00421 gts_point_set (closest, p1->x, p1->y, p1->z); 00422 else 00423 gts_point_set (closest, 00424 (1. - t)*p1->x + t*p2->x, 00425 (1. - t)*p1->y + t*p2->y, 00426 (1. - t)*p1->z + t*p2->z); 00427 } 00428 00436 gdouble gts_point_triangle_distance2 (GtsPoint * p, GtsTriangle * t) 00437 { 00438 GtsPoint * p1, * p2, * p3; 00439 GtsEdge * e1, * e2, * e3; 00440 GtsVector p1p2, p1p3, pp1; 00441 gdouble A, B, C, D, E, det; 00442 gdouble t1, t2; 00443 gdouble x, y, z; 00444 00445 g_return_val_if_fail (p != NULL, 0.0); 00446 g_return_val_if_fail (t != NULL, 0.0); 00447 00448 gts_triangle_vertices_edges (t, NULL, 00449 (GtsVertex **) &p1, 00450 (GtsVertex **) &p2, 00451 (GtsVertex **) &p3, 00452 &e1, &e2, &e3); 00453 00454 gts_vector_init (p1p2, p1, p2); 00455 gts_vector_init (p1p3, p1, p3); 00456 gts_vector_init (pp1, p, p1); 00457 00458 B = gts_vector_scalar (p1p3, p1p2); 00459 E = gts_vector_scalar (p1p2, p1p2); 00460 C = gts_vector_scalar (p1p3, p1p3); 00461 00462 det = B*B - E*C; 00463 if (det == 0.) { /* p1p2 and p1p3 are colinear */ 00464 gdouble d1 = gts_point_segment_distance2 (p, GTS_SEGMENT (e1)); 00465 gdouble d2 = gts_point_segment_distance2 (p, GTS_SEGMENT (e3)); 00466 if (d1 < d2) 00467 return d1; 00468 return d2; 00469 } 00470 00471 A = gts_vector_scalar (p1p3, pp1); 00472 D = gts_vector_scalar (p1p2, pp1); 00473 00474 t1 = (D*C - A*B)/det; 00475 t2 = (A*E - D*B)/det; 00476 00477 if (t1 < 0.) 00478 return gts_point_segment_distance2 (p, GTS_SEGMENT (e3)); 00479 if (t2 < 0.) 00480 return gts_point_segment_distance2 (p, GTS_SEGMENT (e1)); 00481 if (t1 + t2 > 1.) 00482 return gts_point_segment_distance2 (p, GTS_SEGMENT (e2)); 00483 00484 x = pp1[0] + t1*p1p2[0] + t2*p1p3[0]; 00485 y = pp1[1] + t1*p1p2[1] + t2*p1p3[1]; 00486 z = pp1[2] + t1*p1p2[2] + t2*p1p3[2]; 00487 00488 return x*x + y*y + z*z; 00489 } 00490 00498 gdouble gts_point_triangle_distance (GtsPoint * p, GtsTriangle * t) 00499 { 00500 g_return_val_if_fail (p != NULL, 0.0); 00501 g_return_val_if_fail (t != NULL, 0.0); 00502 00503 return sqrt (gts_point_triangle_distance2 (p, t)); 00504 } 00505 00515 void gts_point_triangle_closest (GtsPoint * p, 00516 GtsTriangle * t, 00517 GtsPoint * closest) 00518 { 00519 GtsPoint * p1, * p2, * p3; 00520 GtsEdge * e1, * e2, * e3; 00521 GtsVector p1p2, p1p3, pp1; 00522 gdouble A, B, C, D, E, det; 00523 gdouble t1, t2; 00524 00525 g_return_if_fail (p != NULL); 00526 g_return_if_fail (t != NULL); 00527 g_return_if_fail (closest != NULL); 00528 00529 gts_triangle_vertices_edges (t, NULL, 00530 (GtsVertex **) &p1, 00531 (GtsVertex **) &p2, 00532 (GtsVertex **) &p3, 00533 &e1, &e2, &e3); 00534 00535 gts_vector_init (p1p2, p1, p2); 00536 gts_vector_init (p1p3, p1, p3); 00537 gts_vector_init (pp1, p, p1); 00538 00539 B = gts_vector_scalar (p1p3, p1p2); 00540 E = gts_vector_scalar (p1p2, p1p2); 00541 C = gts_vector_scalar (p1p3, p1p3); 00542 00543 det = B*B - E*C; 00544 if (det == 0.) { /* p1p2 and p1p3 are colinear */ 00545 GtsPoint * cp = 00546 GTS_POINT (gts_object_new (GTS_OBJECT_CLASS (gts_point_class ()))); 00547 gts_point_segment_closest (p, GTS_SEGMENT (e1), cp); 00548 gts_point_segment_closest (p, GTS_SEGMENT (e3), closest); 00549 00550 if (gts_point_distance2 (cp, p) < gts_point_distance2 (closest, p)) 00551 gts_point_set (closest, cp->x, cp->y, cp->z); 00552 gts_object_destroy (GTS_OBJECT (cp)); 00553 return; 00554 } 00555 00556 A = gts_vector_scalar (p1p3, pp1); 00557 D = gts_vector_scalar (p1p2, pp1); 00558 00559 t1 = (D*C - A*B)/det; 00560 t2 = (A*E - D*B)/det; 00561 00562 if (t1 < 0.) 00563 gts_point_segment_closest (p, GTS_SEGMENT (e3), closest); 00564 else if (t2 < 0.) 00565 gts_point_segment_closest (p, GTS_SEGMENT (e1), closest); 00566 else if (t1 + t2 > 1.) 00567 gts_point_segment_closest (p, GTS_SEGMENT (e2), closest); 00568 else 00569 gts_point_set (closest, 00570 p1->x + t1*p1p2[0] + t2*p1p3[0], 00571 p1->y + t1*p1p2[1] + t2*p1p3[1], 00572 p1->z + t1*p1p2[2] + t2*p1p3[2]); 00573 } 00574 00597 GtsPoint * gts_segment_triangle_intersection (GtsSegment * s, 00598 GtsTriangle * t, 00599 gboolean boundary, 00600 GtsPointClass * klass) 00601 { 00602 GtsPoint * A, * B, * C, * D, * E, * I; 00603 gdouble ABCE, ABCD, ADCE, ABDE, BCDE; 00604 gdouble c; 00605 00606 g_return_val_if_fail (s != NULL, NULL); 00607 g_return_val_if_fail (t != NULL, NULL); 00608 g_return_val_if_fail (klass != NULL, NULL); 00609 00610 A = GTS_POINT (GTS_SEGMENT (t->e1)->v1); 00611 B = GTS_POINT (GTS_SEGMENT (t->e1)->v2); 00612 C = GTS_POINT (gts_triangle_vertex (t)); 00613 D = GTS_POINT (s->v1); 00614 E = GTS_POINT (s->v2); 00615 00616 ABCE = gts_point_orientation_3d (A, B, C, E); 00617 ABCD = gts_point_orientation_3d (A, B, C, D); 00618 if (ABCE < 0.0 || ABCD > 0.0) { 00619 GtsPoint * tmpp; 00620 gdouble tmp; 00621 tmpp = E; E = D; D = tmpp; 00622 tmp = ABCE; ABCE = ABCD; ABCD = tmp; 00623 } 00624 if (ABCE < 0.0 || ABCD > 0.0) 00625 return NULL; 00626 ADCE = gts_point_orientation_3d (A, D, C, E); 00627 if ((boundary && ADCE < 0.) || (!boundary && ADCE <= 0.)) 00628 return NULL; 00629 ABDE = gts_point_orientation_3d (A, B, D, E); 00630 if ((boundary && ABDE < 0.) || (!boundary && ABDE <= 0.)) 00631 return NULL; 00632 BCDE = gts_point_orientation_3d (B, C, D, E); 00633 if ((boundary && BCDE < 0.) || (!boundary && BCDE <= 0.)) 00634 return NULL; 00635 if (ABCE == 0.0) { 00636 if (ABCD == 0.0) 00637 /* s is contained in the plane defined by t*/ 00638 return NULL; 00639 return E; 00640 } 00641 if (ABCD == 0.0) 00642 return D; 00643 if (boundary) { /* corners of @t */ 00644 if (ABDE == 0.) { 00645 if (ADCE == 0.) 00646 return A; 00647 if (BCDE == 0.) 00648 return B; 00649 } 00650 else if (BCDE == 0. && ADCE == 0.) 00651 return C; 00652 } 00653 c = ABCE/(ABCE - ABCD); 00654 I = GTS_POINT (gts_object_new (GTS_OBJECT_CLASS (klass))); 00655 gts_point_set (I, 00656 E->x + c*(D->x - E->x), 00657 E->y + c*(D->y - E->y), 00658 E->z + c*(D->z - E->z)); 00659 return I; 00660 } 00661 00670 void gts_point_transform (GtsPoint * p, GtsMatrix * m) 00671 { 00672 gdouble x, y, z; 00673 g_return_if_fail (p != NULL && m != NULL); 00674 x = m[0][0]*p->x + m[0][1]*p->y + m[0][2]*p->z + m[0][3]; 00675 y = m[1][0]*p->x + m[1][1]*p->y + m[1][2]*p->z + m[1][3]; 00676 z = m[2][0]*p->x + m[2][1]*p->y + m[2][2]*p->z + m[2][3]; 00677 p->x = x; p->y = y; p->z = z; 00678 } 00679 00696 gdouble gts_point_orientation (GtsPoint * p1, GtsPoint * p2, GtsPoint * p3) 00697 { 00698 g_return_val_if_fail (p1 != NULL && p2 != NULL && p3 != NULL, 0.0); 00699 00700 return orient2d ((gdouble *) &p1->x, 00701 (gdouble *) &p2->x, 00702 (gdouble *) &p3->x); 00703 } 00704 00705 static gboolean ray_intersects_triangle (GtsPoint * D, GtsPoint * E, 00706 GtsTriangle * t) 00707 { 00708 GtsPoint * A, * B, * C; 00709 gint ABCE, ABCD, ADCE, ABDE, BCDE; 00710 00711 gts_triangle_vertices (t, (GtsVertex **) &A, 00712 (GtsVertex **) &B, 00713 (GtsVertex **) &C); 00714 00715 ABCE = gts_point_orientation_3d_sos (A, B, C, E); 00716 ABCD = gts_point_orientation_3d_sos (A, B, C, D); 00717 if (ABCE < 0 || ABCD > 0) { 00718 GtsPoint * tmpp; 00719 gint tmp; 00720 00721 tmpp = E; E = D; D = tmpp; 00722 tmp = ABCE; ABCE = ABCD; ABCD = tmp; 00723 } 00724 if (ABCE < 0 || ABCD > 0) 00725 return FALSE; 00726 ADCE = gts_point_orientation_3d_sos (A, D, C, E); 00727 if (ADCE < 0) 00728 return FALSE; 00729 ABDE = gts_point_orientation_3d_sos (A, B, D, E); 00730 if (ABDE < 0) 00731 return FALSE; 00732 BCDE = gts_point_orientation_3d_sos (B, C, D, E); 00733 if (BCDE < 0) 00734 return FALSE; 00735 return TRUE; 00736 } 00737 00749 gboolean gts_point_is_inside_surface (GtsPoint * p, 00750 GNode * tree, 00751 gboolean is_open) 00752 { 00753 GSList * list, * i; 00754 guint nc = 0; 00755 GtsPoint * p1; 00756 GtsBBox * bb; 00757 00758 g_return_val_if_fail (p != NULL, FALSE); 00759 g_return_val_if_fail (tree != NULL, FALSE); 00760 00761 bb = tree->data; 00762 p1 = gts_point_new (gts_point_class (), bb->x2 + fabs (bb->x2)/10., p->y, p->z); 00763 i = list = gts_bb_tree_stabbed (tree, p); 00764 while (i) { 00765 GtsTriangle * t = GTS_TRIANGLE (GTS_BBOX (i->data)->bounded); 00766 00767 if (ray_intersects_triangle (p, p1, t)) 00768 nc++; 00769 i = i->next; 00770 } 00771 g_slist_free (list); 00772 gts_object_destroy (GTS_OBJECT (p1)); 00773 00774 return is_open ? (nc % 2 == 0) : (nc % 2 != 0); 00775 } 00776 00777 #define SIGN(x) ((x) > 0. ? 1 : -1) 00778 #define ORIENT1D(a,b) ((a) > (b) ? 1 : (a) < (b) ? -1 : 0) 00779 00780 static gint sortp (gpointer * p, guint n) 00781 { 00782 gint sign = 1; 00783 guint i, j; 00784 00785 for (i = 0; i < n - 1; i++) 00786 for (j = 0; j < n - 1 - i; j++) 00787 if (GPOINTER_TO_UINT (p[j+1]) < GPOINTER_TO_UINT (p[j])) { 00788 gpointer tmp = p[j]; 00789 00790 p[j] = p[j+1]; 00791 p[j+1] = tmp; 00792 sign = - sign; 00793 } 00794 return sign; 00795 } 00796 00816 gint gts_point_orientation_3d_sos (GtsPoint * p1, 00817 GtsPoint * p2, 00818 GtsPoint * p3, 00819 GtsPoint * p4) 00820 { 00821 gdouble o; 00822 00823 g_return_val_if_fail (p1 != NULL && p2 != NULL && 00824 p3 != NULL && p4 != NULL, 0); 00825 00826 o = orient3d ((gdouble *) &p1->x, 00827 (gdouble *) &p2->x, 00828 (gdouble *) &p3->x, 00829 (gdouble *) &p4->x); 00830 if (o != 0.) 00831 return SIGN (o); 00832 else { 00833 GtsPoint * p[4]; 00834 gdouble a[2], b[2], c[2]; 00835 gint sign; 00836 00837 p[0] = p1; p[1] = p2; p[2] = p3; p[3] = p4; 00838 sign = sortp ((gpointer *) p, 4); 00839 00840 /* epsilon^1/8 */ 00841 a[0] = p[1]->x; a[1] = p[1]->y; 00842 b[0] = p[2]->x; b[1] = p[2]->y; 00843 c[0] = p[3]->x; c[1] = p[3]->y; 00844 o = orient2d (a, b, c); 00845 if (o != 0.) 00846 return SIGN (o)*sign; 00847 00848 /* epsilon^1/4 */ 00849 a[0] = p[1]->x; a[1] = p[1]->z; 00850 b[0] = p[2]->x; b[1] = p[2]->z; 00851 c[0] = p[3]->x; c[1] = p[3]->z; 00852 o = orient2d (a, b, c); 00853 if (o != 0.) 00854 return - SIGN (o)*sign; 00855 00856 /* epsilon^1/2 */ 00857 a[0] = p[1]->y; a[1] = p[1]->z; 00858 b[0] = p[2]->y; b[1] = p[2]->z; 00859 c[0] = p[3]->y; c[1] = p[3]->z; 00860 o = orient2d (a, b, c); 00861 if (o != 0.) 00862 return SIGN (o)*sign; 00863 00864 /* epsilon */ 00865 a[0] = p[0]->x; a[1] = p[0]->y; 00866 b[0] = p[2]->x; b[1] = p[2]->y; 00867 c[0] = p[3]->x; c[1] = p[3]->y; 00868 o = orient2d (a, b, c); 00869 if (o != 0.) 00870 return - SIGN (o)*sign; 00871 00872 /* epsilon^5/4 */ 00873 o = ORIENT1D (p[2]->x, p[3]->x); 00874 if (o != 0.) 00875 return SIGN (o)*sign; 00876 00877 /* epsilon^3/2 */ 00878 o = ORIENT1D (p[2]->y, p[3]->y); 00879 if (o != 0.) 00880 return - SIGN (o)*sign; 00881 00882 /* epsilon^2 */ 00883 a[0] = p[0]->x; a[1] = p[0]->z; 00884 b[0] = p[2]->x; b[1] = p[2]->z; 00885 c[0] = p[3]->x; c[1] = p[3]->z; 00886 o = orient2d (a, b, c); 00887 if (o != 0.) 00888 return SIGN (o)*sign; 00889 00890 /* epsilon^5/2 */ 00891 o = ORIENT1D (p[2]->z, p[3]->z); 00892 if (o != 0.) 00893 return SIGN (o)*sign; 00894 00895 /* epsilon^4 */ 00896 a[0] = p[0]->y; a[1] = p[0]->z; 00897 b[0] = p[2]->y; b[1] = p[2]->z; 00898 c[0] = p[3]->y; c[1] = p[3]->z; 00899 o = orient2d (a, b, c); 00900 if (o != 0.) 00901 return - SIGN (o)*sign; 00902 00903 /* epsilon^8 */ 00904 a[0] = p[0]->x; a[1] = p[0]->y; 00905 b[0] = p[1]->x; b[1] = p[1]->y; 00906 c[0] = p[3]->x; c[1] = p[3]->y; 00907 o = orient2d (a, b, c); 00908 if (o != 0.) 00909 return SIGN (o)*sign; 00910 00911 /* epsilon^33/4 */ 00912 o = ORIENT1D (p[1]->x, p[3]->x); 00913 if (o != 0.) 00914 return - SIGN (o)*sign; 00915 00916 /* epsilon^17/2 */ 00917 o = ORIENT1D (p[1]->y, p[3]->y); 00918 if (o != 0.) 00919 return SIGN (o)*sign; 00920 00921 /* epsilon^10 */ 00922 o = ORIENT1D (p[0]->x, p[3]->x); 00923 if (o != 0.) 00924 return SIGN (o)*sign; 00925 00926 /* epsilon^21/2 */ 00927 return sign; 00928 } 00929 } 00930 00948 gint gts_point_orientation_sos (GtsPoint * p1, 00949 GtsPoint * p2, 00950 GtsPoint * p3) 00951 { 00952 gdouble o; 00953 00954 g_return_val_if_fail (p1 != NULL && p2 != NULL && p3 != NULL, 0); 00955 00956 o = orient2d ((gdouble *) &p1->x, 00957 (gdouble *) &p2->x, 00958 (gdouble *) &p3->x); 00959 if (o != 0.) 00960 return SIGN (o); 00961 else { 00962 GtsPoint * p[3]; 00963 gint sign; 00964 00965 p[0] = p1; p[1] = p2; p[2] = p3; 00966 sign = sortp ((gpointer *) p, 3); 00967 00968 /* epsilon^1/4 */ 00969 o = ORIENT1D (p[1]->x, p[2]->x); 00970 if (o != 0.) 00971 return - SIGN (o)*sign; 00972 00973 /* epsilon^1/2 */ 00974 o = ORIENT1D (p[1]->y, p[2]->y); 00975 if (o != 0.) 00976 return SIGN (o)*sign; 00977 00978 /* epsilon */ 00979 o = ORIENT1D (p[0]->x, p[2]->x); 00980 if (o != 0.) 00981 return SIGN (o)*sign; 00982 00983 /* epsilon^3/2 */ 00984 return sign; 00985 } 00986 }