1 /* GTS - Library for the manipulation of triangulated surfaces
2 * Copyright (C) 1999 Stéphane Popinet
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, write to the
16 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17 * Boston, MA 02111-1307, USA.
22 static void segment_destroy (GtsObject
* object
)
24 GtsSegment
* segment
= GTS_SEGMENT (object
);
25 GtsVertex
* v1
= segment
->v1
;
26 GtsVertex
* v2
= segment
->v2
;
28 v1
->segments
= g_slist_remove (v1
->segments
, segment
);
29 if (!GTS_OBJECT_DESTROYED (v1
) &&
30 !gts_allow_floating_vertices
&& v1
->segments
== NULL
)
31 gts_object_destroy (GTS_OBJECT (v1
));
33 v2
->segments
= g_slist_remove (v2
->segments
, segment
);
34 if (!GTS_OBJECT_DESTROYED (v2
) &&
35 !gts_allow_floating_vertices
&& v2
->segments
== NULL
)
36 gts_object_destroy (GTS_OBJECT (v2
));
38 (* GTS_OBJECT_CLASS (gts_segment_class ())->parent_class
->destroy
) (object
);
41 static void segment_class_init (GtsObjectClass
* klass
)
43 klass
->destroy
= segment_destroy
;
46 static void segment_init (GtsSegment
* segment
)
48 segment
->v1
= segment
->v2
= NULL
;
54 * Returns: the #GtsSegmentClass.
56 GtsSegmentClass
* gts_segment_class (void)
58 static GtsSegmentClass
* klass
= NULL
;
61 GtsObjectClassInfo segment_info
= {
64 sizeof (GtsSegmentClass
),
65 (GtsObjectClassInitFunc
) segment_class_init
,
66 (GtsObjectInitFunc
) segment_init
,
70 klass
= gts_object_class_new (gts_object_class (),
79 * @klass: a #GtsSegmentClass.
81 * @v2: another #GtsVertex different from @v1.
83 * Returns: a new #GtsSegment linking @v1 and @v2.
85 GtsSegment
* gts_segment_new (GtsSegmentClass
* klass
,
86 GtsVertex
* v1
, GtsVertex
* v2
)
90 g_return_val_if_fail (v1
!= NULL
, NULL
);
91 g_return_val_if_fail (v2
!= NULL
, NULL
);
92 g_return_val_if_fail (v1
!= v2
, NULL
);
94 s
= GTS_SEGMENT (gts_object_new (GTS_OBJECT_CLASS (klass
)));
97 v1
->segments
= g_slist_prepend (v1
->segments
, s
);
98 v2
->segments
= g_slist_prepend (v2
->segments
, s
);
104 * gts_segment_is_duplicate:
107 * Returns: the first #GtsSegment different from @s which shares the
108 * same endpoints or %NULL if there is none.
110 GtsSegment
* gts_segment_is_duplicate (GtsSegment
* s
)
115 g_return_val_if_fail (s
!= NULL
, NULL
);
119 if (s
->v1
== v2
) /* s is degenerate: special treatment */
121 GtsSegment
* s1
= i
->data
;
122 if (s1
!= s
&& s1
->v1
== v2
&& s1
->v2
== v2
)
126 else /* s is not degenerate */
128 GtsSegment
* s1
= i
->data
;
129 if (s1
!= s
&& (s1
->v1
== v2
|| s1
->v2
== v2
))
137 * gts_segments_are_intersecting:
138 * @s1: a #GtsSegment.
139 * @s2: a #GtsSegment.
141 * Returns: %GTS_IN if @s1 and @s2 are intersecting, %GTS_ON if one of the
142 * endpoints of @s1 (resp. @s2) lies on @s2 (resp. @s1), %GTS_OUT otherwise.
144 GtsIntersect
gts_segments_are_intersecting (GtsSegment
* s1
, GtsSegment
* s2
)
146 GtsPoint
* p1
, * p2
, * p3
, * p4
;
147 gdouble d1
, d2
, d3
, d4
;
149 g_return_val_if_fail (s1
!= NULL
&& s2
!= NULL
, FALSE
);
151 p1
= GTS_POINT (s1
->v1
); p2
= GTS_POINT (s1
->v2
);
152 p3
= GTS_POINT (s2
->v1
); p4
= GTS_POINT (s2
->v2
);
153 d1
= gts_point_orientation (p1
, p2
, p3
);
154 d2
= gts_point_orientation (p1
, p2
, p4
);
155 if ((d1
> 0.0 && d2
> 0.0) ||
156 (d1
< 0.0 && d2
< 0.0))
158 d3
= gts_point_orientation (p3
, p4
, p1
);
159 d4
= gts_point_orientation (p3
, p4
, p2
);
160 if ((d3
> 0.0 && d4
> 0.0) ||
161 (d3
< 0.0 && d4
< 0.0))
163 if (d1
== 0.0 || d2
== 0.0 || d3
== 0.0 || d4
== 0.0)
169 * gts_segment_midvertex:
171 * @klass: a #GtsVertexClass to be used for the new vertex.
173 * Returns: a new #GtsVertex, midvertex of @s.
175 GtsVertex
* gts_segment_midvertex (GtsSegment
* s
, GtsVertexClass
* klass
)
179 g_return_val_if_fail (s
!= NULL
, NULL
);
180 g_return_val_if_fail (klass
!= NULL
, NULL
);
182 p1
= GTS_POINT (s
->v1
); p2
= GTS_POINT (s
->v2
);
183 return gts_vertex_new (klass
,
190 * gts_segments_from_vertices:
191 * @vertices: a list of #GtsVertex.
193 * Returns: a list of unique #GtsSegment which have one of their vertices in
196 GSList
* gts_segments_from_vertices (GSList
* vertices
)
199 GSList
* segments
= NULL
, * i
;
201 hash
= g_hash_table_new (NULL
, NULL
);
204 GSList
* j
= GTS_VERTEX (i
->data
)->segments
;
206 GtsSegment
* s
= j
->data
;
207 if (g_hash_table_lookup (hash
, s
) == NULL
) {
208 segments
= g_slist_prepend (segments
, s
);
209 g_hash_table_insert (hash
, s
, i
);
215 g_hash_table_destroy (hash
);
223 * Returns: %TRUE if @s is not degenerate (i.e. @s->v1 != @s->v2) and not
224 * duplicate, %FALSE otherwise.
226 gboolean
gts_segment_is_ok (GtsSegment
* s
)
228 g_return_val_if_fail (s
!= NULL
, FALSE
);
229 g_return_val_if_fail (s
->v1
!= s
->v2
, FALSE
);
230 g_return_val_if_fail (!gts_segment_is_duplicate (s
), FALSE
);
231 g_return_val_if_fail (GTS_OBJECT (s
)->reserved
== NULL
, FALSE
);