pcb 4.1.1
An interactive printed circuit board layout editor.

segment.c

Go to the documentation of this file.
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 }