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 "gts.h" 00021 00022 static void segment_destroy (GtsObject * object) 00023 { 00024 GtsSegment * segment = GTS_SEGMENT (object); 00025 GtsVertex * v1 = segment->v1; 00026 GtsVertex * v2 = segment->v2; 00027 00028 v1->segments = g_slist_remove (v1->segments, segment); 00029 if (!GTS_OBJECT_DESTROYED (v1) && 00030 !gts_allow_floating_vertices && v1->segments == NULL) 00031 gts_object_destroy (GTS_OBJECT (v1)); 00032 00033 v2->segments = g_slist_remove (v2->segments, segment); 00034 if (!GTS_OBJECT_DESTROYED (v2) && 00035 !gts_allow_floating_vertices && v2->segments == NULL) 00036 gts_object_destroy (GTS_OBJECT (v2)); 00037 00038 (* GTS_OBJECT_CLASS (gts_segment_class ())->parent_class->destroy) (object); 00039 } 00040 00041 static void segment_class_init (GtsObjectClass * klass) 00042 { 00043 klass->destroy = segment_destroy; 00044 } 00045 00046 static void segment_init (GtsSegment * segment) 00047 { 00048 segment->v1 = segment->v2 = NULL; 00049 } 00050 00056 GtsSegmentClass * gts_segment_class (void) 00057 { 00058 static GtsSegmentClass * klass = NULL; 00059 00060 if (klass == NULL) { 00061 GtsObjectClassInfo segment_info = { 00062 "GtsSegment", 00063 sizeof (GtsSegment), 00064 sizeof (GtsSegmentClass), 00065 (GtsObjectClassInitFunc) segment_class_init, 00066 (GtsObjectInitFunc) segment_init, 00067 (GtsArgSetFunc) NULL, 00068 (GtsArgGetFunc) NULL 00069 }; 00070 klass = gts_object_class_new (gts_object_class (), 00071 &segment_info); 00072 } 00073 00074 return klass; 00075 } 00076 00085 GtsSegment * gts_segment_new (GtsSegmentClass * klass, 00086 GtsVertex * v1, GtsVertex * v2) 00087 { 00088 GtsSegment * s; 00089 00090 g_return_val_if_fail (v1 != NULL, NULL); 00091 g_return_val_if_fail (v2 != NULL, NULL); 00092 g_return_val_if_fail (v1 != v2, NULL); 00093 00094 s = GTS_SEGMENT (gts_object_new (GTS_OBJECT_CLASS (klass))); 00095 s->v1 = v1; 00096 s->v2 = v2; 00097 v1->segments = g_slist_prepend (v1->segments, s); 00098 v2->segments = g_slist_prepend (v2->segments, s); 00099 00100 return s; 00101 } 00102 00110 GtsSegment * gts_segment_is_duplicate (GtsSegment * s) 00111 { 00112 GSList * i; 00113 GtsVertex * v2; 00114 00115 g_return_val_if_fail (s != NULL, NULL); 00116 00117 v2 = s->v2; 00118 i = s->v1->segments; 00119 if (s->v1 == v2) /* s is degenerate: special treatment */ 00120 while (i) { 00121 GtsSegment * s1 = i->data; 00122 if (s1 != s && s1->v1 == v2 && s1->v2 == v2) 00123 return s1; 00124 i = i->next; 00125 } 00126 else /* s is not degenerate */ 00127 while (i) { 00128 GtsSegment * s1 = i->data; 00129 if (s1 != s && (s1->v1 == v2 || s1->v2 == v2)) 00130 return s1; 00131 i = i->next; 00132 } 00133 return NULL; 00134 } 00135 00144 GtsIntersect gts_segments_are_intersecting (GtsSegment * s1, GtsSegment * s2) 00145 { 00146 GtsPoint * p1, * p2, * p3, * p4; 00147 gdouble d1, d2, d3, d4; 00148 00149 g_return_val_if_fail (s1 != NULL && s2 != NULL, FALSE); 00150 00151 p1 = GTS_POINT (s1->v1); p2 = GTS_POINT (s1->v2); 00152 p3 = GTS_POINT (s2->v1); p4 = GTS_POINT (s2->v2); 00153 d1 = gts_point_orientation (p1, p2, p3); 00154 d2 = gts_point_orientation (p1, p2, p4); 00155 if ((d1 > 0.0 && d2 > 0.0) || 00156 (d1 < 0.0 && d2 < 0.0)) 00157 return GTS_OUT; 00158 d3 = gts_point_orientation (p3, p4, p1); 00159 d4 = gts_point_orientation (p3, p4, p2); 00160 if ((d3 > 0.0 && d4 > 0.0) || 00161 (d3 < 0.0 && d4 < 0.0)) 00162 return GTS_OUT; 00163 if (d1 == 0.0 || d2 == 0.0 || d3 == 0.0 || d4 == 0.0) 00164 return GTS_ON; 00165 return GTS_IN; 00166 } 00167 00175 GtsVertex * gts_segment_midvertex (GtsSegment * s, GtsVertexClass * klass) 00176 { 00177 GtsPoint * p1, * p2; 00178 00179 g_return_val_if_fail (s != NULL, NULL); 00180 g_return_val_if_fail (klass != NULL, NULL); 00181 00182 p1 = GTS_POINT (s->v1); p2 = GTS_POINT (s->v2); 00183 return gts_vertex_new (klass, 00184 (p1->x + p2->x)/2., 00185 (p1->y + p2->y)/2., 00186 (p1->z + p2->z)/2.); 00187 } 00188 00196 GSList * gts_segments_from_vertices (GSList * vertices) 00197 { 00198 GHashTable * hash; 00199 GSList * segments = NULL, * i; 00200 00201 hash = g_hash_table_new (NULL, NULL); 00202 i = vertices; 00203 while (i) { 00204 GSList * j = GTS_VERTEX (i->data)->segments; 00205 while (j) { 00206 GtsSegment * s = j->data; 00207 if (g_hash_table_lookup (hash, s) == NULL) { 00208 segments = g_slist_prepend (segments, s); 00209 g_hash_table_insert (hash, s, i); 00210 } 00211 j = j->next; 00212 } 00213 i = i->next; 00214 } 00215 g_hash_table_destroy (hash); 00216 return segments; 00217 } 00218 00226 gboolean gts_segment_is_ok (GtsSegment * s) 00227 { 00228 g_return_val_if_fail (s != NULL, FALSE); 00229 g_return_val_if_fail (s->v1 != s->v2, FALSE); 00230 g_return_val_if_fail (!gts_segment_is_duplicate (s), FALSE); 00231 g_return_val_if_fail (GTS_OBJECT (s)->reserved == NULL, FALSE); 00232 return TRUE; 00233 }