geo 0.1.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,347 @@
1
+
2
+ #include "common.h"
3
+
4
+ VALUE rb_triangle_set;
5
+
6
+ static gboolean
7
+ triangle_set_reindex(GeoSet *triangle_set);
8
+
9
+ static void
10
+ g_hash_table_mark_triangle(gpointer key, gpointer value, gpointer user_data) {
11
+ rb_gc_mark( ( (Triangle *) key )->rbTriangle);
12
+ }
13
+
14
+ static void
15
+ triangle_set_mark(GeoSet *set) {
16
+ g_hash_table_foreach(set->table, g_hash_table_mark_triangle, NULL);
17
+ }
18
+
19
+ VALUE
20
+ rb_triangle_set_alloc(VALUE class) {
21
+ GeoSet *set = new_geo_set();
22
+ return RB_TRIANGLE_SET(set, class);
23
+ }
24
+
25
+ VALUE
26
+ rb_triangle_set_insert(VALUE self, VALUE t) {
27
+ Triangle *triangle;
28
+ GeoSet *me;
29
+ CHECK_TRIANGLE(t);
30
+ GEO_SET(self, me);
31
+ TRIANGLE(t, triangle);
32
+ geo_set_insert(me, (gpointer ) triangle);
33
+ return self;
34
+ }
35
+
36
+ VALUE
37
+ rb_triangle_set_include(VALUE self, VALUE triangle) {
38
+ GeoSet *me;
39
+ Triangle *t;
40
+ CHECK_TRIANGLE(triangle);
41
+ TRIANGLE(triangle, t);
42
+ GEO_SET(self, me);
43
+ return GBOOL2RB(g_hash_table_lookup_extended(me->table, (gpointer) t, NULL, NULL));
44
+ }
45
+
46
+ VALUE
47
+ rb_triangle_set_delete(VALUE self, VALUE triangle) {
48
+ GeoSet *me;
49
+ Triangle *t;
50
+ CHECK_TRIANGLE(triangle);
51
+ GEO_SET(self, me);
52
+ TRIANGLE(triangle, t);
53
+ return geo_set_delete(me, (gpointer) t, triangle);
54
+ }
55
+
56
+ static void
57
+ g_hash_table_yield_triangle(gpointer key, gpointer value, gpointer user_data) {
58
+ rb_yield(( (Triangle *) key )->rbTriangle);
59
+ }
60
+
61
+ VALUE
62
+ rb_triangle_set_each(VALUE self) {
63
+ GeoSet *set;
64
+ GEO_SET(self, set);
65
+ geo_set_foreach(set, g_hash_table_yield_triangle);
66
+ return self;
67
+ }
68
+
69
+ static gpointer
70
+ triangle_set_collect_triangle_intersectors_in_rb_ary(GeoSet *set, gpointer structure, gpointer user_data) {
71
+ gpointer *args = (gpointer *) user_data;
72
+ Triangle *triangle = (Triangle *) structure;
73
+ Line *line = (Line *) args[0];
74
+ VALUE *rval = (VALUE *) args[1];
75
+ if (triangle_intersects(triangle, line)) {
76
+ rb_ary_push(*rval, triangle->rbTriangle);
77
+ }
78
+ return NULL;
79
+ }
80
+
81
+ static VALUE
82
+ triangle_set_intersectors(GeoSet *set, Line *line) {
83
+ VALUE rval = rb_ary_new();
84
+ gpointer args[2] = { line, &rval };
85
+ TRIANGLE_SET_REINDEX(set);
86
+ geo_set_each_structure_having_common_segment_id_with_line_until(set, line, triangle_set_collect_triangle_intersectors_in_rb_ary, args);
87
+ return rval;
88
+ }
89
+
90
+ VALUE
91
+ rb_triangle_set_intersectors(VALUE self, VALUE line) {
92
+ GeoSet *me;
93
+ Line *l;
94
+ CHECK_LINE(line);
95
+ GEO_SET(self, me);
96
+ LINE(line, l);
97
+ return triangle_set_intersectors(me, l);
98
+ }
99
+
100
+ static gpointer
101
+ triangle_set_intersecting(GeoSet *set, gpointer triangle_gp, gpointer line_gp) {
102
+ Line *line = (Line *) line_gp;
103
+ Triangle *triangle = (Triangle *) triangle_gp;
104
+ if (triangle_intersects(triangle, line))
105
+ return triangle;
106
+ return NULL;
107
+ }
108
+
109
+ static gboolean
110
+ triangle_set_intersects(GeoSet *set, Line *line) {
111
+ TRIANGLE_SET_REINDEX(set);
112
+ return GBOOL2RB(geo_set_each_structure_having_common_segment_id_with_line_until(set,
113
+ line,
114
+ triangle_set_intersecting,
115
+ line) != NULL);
116
+ }
117
+
118
+ VALUE
119
+ rb_triangle_set_intersects(VALUE self, VALUE line) {
120
+ GeoSet *me;
121
+ Line *l;
122
+ CHECK_LINE(line);
123
+ GEO_SET(self, me);
124
+ LINE(line, l);
125
+ return GBOOL2RB(triangle_set_intersects(me, l));
126
+ }
127
+
128
+ static gpointer
129
+ triangle_set_find_container(GeoSet *Set, gpointer triangle_gp, gpointer point_gp) {
130
+ Point *point = (Point *) point_gp;
131
+ Triangle *triangle = (Triangle *) triangle_gp;
132
+ if (triangle_contains(triangle, point))
133
+ return triangle;
134
+ return NULL;
135
+ }
136
+
137
+ static Triangle*
138
+ triangle_set_first_container(GeoSet *set, Point *point) {
139
+ TRIANGLE_SET_REINDEX(set);
140
+ return ( (Triangle *) geo_set_each_structure_having_common_segment_id_with_point_until(set,
141
+ point,
142
+ triangle_set_find_container,
143
+ point));
144
+ }
145
+
146
+ VALUE
147
+ rb_triangle_set_first_container(VALUE self, VALUE p) {
148
+ GeoSet *set;
149
+ Point *point;
150
+ Triangle *rval;
151
+ CHECK_POINT(p);
152
+ GEO_SET(self, set);
153
+ POINT(p, point);
154
+ if ((rval = triangle_set_first_container(set, point)) != NULL)
155
+ return rval->rbTriangle;
156
+ return Qnil;
157
+ }
158
+
159
+ VALUE
160
+ rb_triangle_set_contains(VALUE self, VALUE p) {
161
+ GeoSet *set;
162
+ Point *point;
163
+ CHECK_POINT(p);
164
+ GEO_SET(self, set);
165
+ POINT(p, point);
166
+ return GBOOL2RB(triangle_set_first_container(set, point) != NULL);
167
+ }
168
+
169
+ VALUE
170
+ rb_triangle_set_clone(VALUE self) {
171
+ GeoSet *me;
172
+ GEO_SET(self, me);
173
+ return RB_TRIANGLE_SET(geo_set_clone(me), CLASS(self));
174
+ }
175
+
176
+ VALUE
177
+ rb_triangle_set_structures_in_segment(VALUE self, VALUE x, VALUE y) {
178
+ return rb_geo_set_structures_in_segment(self, x, y, rb_triangle_from_gpointer);
179
+ }
180
+
181
+ /*
182
+ * Segment indexing.
183
+ */
184
+
185
+ static void
186
+ g_hash_table_call_handle_bounds(gpointer key, gpointer value, gpointer user_data) {
187
+ Point bottom_left;
188
+ Point top_right;
189
+ Triangle *t = (Triangle *) key;
190
+ TRIANGLE_BOUNDS(t, &bottom_left, &top_right);
191
+ geo_set_handle_bounds((GeoSet *) user_data, &bottom_left, &top_right);
192
+ }
193
+
194
+ static void
195
+ triangle_set_bound_finder(GeoSet *set) {
196
+ g_hash_table_foreach(set->table, g_hash_table_call_handle_bounds, set);
197
+ }
198
+
199
+ static gpointer
200
+ triangle_set_insert_segment_id_into_gtree(GeoSet *set, guint32 segment_id, gpointer tree) {
201
+ g_tree_insert((GTree *) tree, GUINT_TO_POINTER(segment_id), GUINT_TO_POINTER(segment_id));
202
+ return NULL;
203
+ }
204
+
205
+ static gboolean
206
+ triangle_set_each_segment_id_and_contained(gpointer key, gpointer value, gpointer user_data) {
207
+ gpointer *args = (gpointer *) user_data;
208
+ guint32 segment_id = GPOINTER_TO_UINT(key);
209
+ guint32 tmp_segment_id;
210
+ guint16 i;
211
+ guint16 x = segment_id >> 16;
212
+ guint16 y = (segment_id << 16) >> 16;
213
+ guint16 *last_x = (guint16 *) args[0];
214
+ guint16 *last_y = (guint16 *) args[1];
215
+ geo_set_segment_id_handler handler = (geo_set_segment_id_handler) args[2];
216
+ GeoSet *set = (GeoSet *) args[3];
217
+ gpointer *rval = args[4];
218
+ gpointer handler_args = args[5];
219
+ if (*last_x == x && y - *last_y > 1) {
220
+ for (i = *last_y + 1; i < y; i++) {
221
+ tmp_segment_id = (x << 16) + i;
222
+ if ((*rval = handler(set, tmp_segment_id, handler_args)) != NULL) {
223
+ return TRUE;
224
+ }
225
+ }
226
+ }
227
+ if ((*rval = handler(set, segment_id, handler_args)) != NULL) {
228
+ return TRUE;
229
+ }
230
+ *last_x = x;
231
+ *last_y = y;
232
+ return FALSE;
233
+ }
234
+
235
+ gpointer
236
+ geo_set_each_segment_id_of_triangle_until(GeoSet *set,
237
+ Triangle *triangle,
238
+ geo_set_segment_id_handler handler,
239
+ gpointer user_data) {
240
+ Point bottom_left;
241
+ Point top_right;
242
+ GHashTable *seen_segment_ids = g_hash_table_new(g_direct_hash, g_direct_equal);
243
+ gpointer rval = NULL;
244
+ GTree *tree = g_tree_new(gpointer_compare_as_uint);
245
+ gpointer filler_args[4] = { NULL, triangle_set_insert_segment_id_into_gtree, tree, seen_segment_ids };
246
+ Line tmp;
247
+ guint16 last_x = -1;
248
+ guint16 last_y = -1;
249
+ gpointer tree_args[6] = { &last_x, &last_y, handler, set, &rval, user_data };
250
+ TRIANGLE_BOUNDS(triangle, &bottom_left, &top_right);
251
+ /*
252
+ * Put the segment ids of each line in the tree.
253
+ */
254
+ tmp.p1 = triangle->p1;
255
+ tmp.p2 = triangle->p2;
256
+ filler_args[0] = &tmp;
257
+ geo_set_each_segment_line_until(set, &bottom_left, &top_right, geo_set_each_segment_id_of_intersection_until, filler_args);
258
+ tmp.p2 = triangle->p3;
259
+ geo_set_each_segment_line_until(set, &bottom_left, &top_right, geo_set_each_segment_id_of_intersection_until, filler_args);
260
+ tmp.p1 = triangle->p2;
261
+ geo_set_each_segment_line_until(set, &bottom_left, &top_right, geo_set_each_segment_id_of_intersection_until, filler_args);
262
+ /*
263
+ * Put the segment ids of each point in the tree.
264
+ */
265
+ geo_set_each_segment_id_for_point_until(set, triangle->p1, seen_segment_ids, triangle_set_insert_segment_id_into_gtree, tree);
266
+ geo_set_each_segment_id_for_point_until(set, triangle->p2, seen_segment_ids, triangle_set_insert_segment_id_into_gtree, tree);
267
+ geo_set_each_segment_id_for_point_until(set, triangle->p3, seen_segment_ids, triangle_set_insert_segment_id_into_gtree, tree);
268
+ /*
269
+ * Go through the found segment ids (and all contained in them) and call the handler for each one.
270
+ */
271
+ g_tree_foreach(tree, triangle_set_each_segment_id_and_contained, tree_args);
272
+ g_tree_destroy(tree);
273
+ g_hash_table_destroy(seen_segment_ids);
274
+ return rval;
275
+ }
276
+
277
+ gpointer
278
+ geo_set_each_structure_having_common_segment_id_with_triangle_until(GeoSet *set,
279
+ Triangle *line,
280
+ geo_set_structure_handler handler,
281
+ gpointer user_data) {
282
+ gpointer rval = NULL;
283
+ GHashTable *seen_structures = g_hash_table_new(g_direct_hash, g_direct_equal);
284
+ gpointer args[3] = { seen_structures, handler, user_data };
285
+ rval = geo_set_each_segment_id_of_triangle_until(set, line, geo_set_each_structure_in_segment_id_until, args);
286
+ g_hash_table_destroy(seen_structures);
287
+ return rval;
288
+ }
289
+
290
+ VALUE
291
+ rb_triangle_set_triangles_with_common_segment_id(VALUE self, VALUE l) {
292
+ GeoSet *me;
293
+ Triangle *triangle;
294
+ VALUE rval;
295
+ gpointer args[2];
296
+ CHECK_TRIANGLE(l);
297
+ GEO_SET(self, me);
298
+ TRIANGLE(l, triangle);
299
+ TRIANGLE_SET_REINDEX(me);
300
+ rval = rb_ary_new();
301
+ args[0] = &rval;
302
+ args[1] = rb_triangle_from_gpointer;
303
+ geo_set_each_structure_having_common_segment_id_with_triangle_until(me, triangle, geo_set_insert_structure_into_rb_ary, args);
304
+ return rval;
305
+ }
306
+
307
+ static void
308
+ g_hash_table_each_segment_id_for_triangle(gpointer key, gpointer value, gpointer user_data) {
309
+ gpointer *args = (gpointer *) user_data;
310
+ geo_set_each_segment_id_of_triangle_until((GeoSet *) args[0],
311
+ (Triangle *) key,
312
+ (geo_set_segment_id_handler) args[1],
313
+ (Triangle *) key);
314
+ }
315
+
316
+ static void
317
+ triangle_set_segment_finder(GeoSet *set) {
318
+ gpointer args[2] = { set, geo_set_insert_into_segment };
319
+ g_hash_table_foreach(set->table, g_hash_table_each_segment_id_for_triangle, args);
320
+ }
321
+
322
+ static gboolean
323
+ triangle_set_reindex(GeoSet *set) {
324
+ return geo_set_reindex(set, triangle_set_bound_finder, triangle_set_segment_finder);
325
+ }
326
+
327
+ VALUE
328
+ rb_triangle_set_reindex(VALUE self) {
329
+ GeoSet *me;
330
+ GEO_SET(self, me);
331
+ return GBOOL2RB(triangle_set_reindex(me));
332
+ }
333
+
334
+ VALUE
335
+ rb_triangle_set_segment_ids_for_triangle(VALUE self, VALUE t) {
336
+ GeoSet *me;
337
+ Triangle *triangle;
338
+ VALUE rval;
339
+ CHECK_TRIANGLE(t);
340
+ GEO_SET(self, me);
341
+ TRIANGLE(t, triangle);
342
+ TRIANGLE_SET_REINDEX(me);
343
+ rval = rb_ary_new();
344
+ geo_set_each_segment_id_of_triangle_until(me, triangle, geo_set_insert_segment_id_into_rb_ary, &rval);
345
+ return rval;
346
+ }
347
+
@@ -0,0 +1,68 @@
1
+
2
+ #ifndef TRIANGLE_SET_H
3
+ #define TRIANGLE_SET_H
4
+
5
+ #include "common.h"
6
+
7
+ extern VALUE rb_triangle_set;
8
+
9
+
10
+ #define RB_TRIANGLE_SET(triangle_set_pointer,klass) Data_Wrap_Struct(klass, triangle_set_mark, geo_set_free, (triangle_set_pointer))
11
+ #define TRIANGLE_SET_REINDEX(set) if (set->index_dirty) triangle_set_reindex(set)
12
+
13
+ VALUE
14
+ rb_triangle_set_alloc(VALUE class);
15
+
16
+ VALUE
17
+ rb_triangle_set_insert(VALUE self, VALUE t);
18
+
19
+ VALUE
20
+ rb_triangle_set_include(VALUE self, VALUE triangle);
21
+
22
+ VALUE
23
+ rb_triangle_set_delete(VALUE self, VALUE triangle);
24
+
25
+ VALUE
26
+ rb_triangle_set_each(VALUE self);
27
+
28
+ VALUE
29
+ rb_triangle_set_intersectors(VALUE self, VALUE line);
30
+
31
+ VALUE
32
+ rb_triangle_set_intersects(VALUE self, VALUE line);
33
+
34
+ VALUE
35
+ rb_triangle_set_first_container(VALUE self, VALUE p);
36
+
37
+ VALUE
38
+ rb_triangle_set_contains(VALUE self, VALUE p);
39
+
40
+ VALUE
41
+ rb_triangle_set_clone(VALUE self);
42
+
43
+ VALUE
44
+ rb_triangle_set_reindex(VALUE self);
45
+
46
+ VALUE
47
+ rb_triangle_set_segment_ids_for_triangle(VALUE self, VALUE t);
48
+
49
+ VALUE
50
+ rb_triangle_set_triangles_with_common_segment_id(VALUE self, VALUE l);
51
+
52
+ VALUE
53
+ rb_triangle_set_structures_in_segment(VALUE self, VALUE x, VALUE y);
54
+
55
+ gpointer
56
+ geo_set_each_segment_id_of_triangle_until(GeoSet *set,
57
+ Triangle *triangle,
58
+ geo_set_segment_id_handler handler,
59
+ gpointer user_data);
60
+
61
+ gpointer
62
+ geo_set_each_structure_having_common_segment_id_with_triangle_until(GeoSet *set,
63
+ Triangle *line,
64
+ geo_set_structure_handler handler,
65
+ gpointer user_data);
66
+
67
+
68
+ #endif
data/ext/types.h ADDED
@@ -0,0 +1,48 @@
1
+
2
+ #ifndef TYPES_H
3
+ #define TYPES_H
4
+
5
+ typedef struct {
6
+ gdouble x;
7
+ gdouble y;
8
+ VALUE rbPoint;
9
+ } Point;
10
+
11
+ typedef struct {
12
+ Point *p1;
13
+ Point *p2;
14
+ VALUE rbLine;
15
+ } Line;
16
+
17
+ typedef enum {
18
+ itPOINT,
19
+ itLINE,
20
+ } IntersectionType;
21
+
22
+ typedef struct {
23
+ Point *point;
24
+ Line *line;
25
+ Line *with;
26
+ IntersectionType type;
27
+ } Intersection;
28
+
29
+ typedef struct {
30
+ Point *p1;
31
+ Point *p2;
32
+ Point *p3;
33
+ VALUE rbTriangle;
34
+ } Triangle;
35
+
36
+ typedef struct {
37
+ GHashTable *table; // key and value are the content of this GeoSet
38
+ gboolean iterating; // TRUE if iterating right now
39
+ Point *bottom_left;
40
+ Point *top_right;
41
+ gdouble segment_side;
42
+ GHashTable *segments; // x-index_from_left(0) << 16 + y-index_from_top(ymax)
43
+ GHashTable *segment_lines; // x-index_from_left(0) << 16 + y-index_from_top(ymax)
44
+ gboolean index_dirty;
45
+ } GeoSet;
46
+
47
+
48
+ #endif
metadata ADDED
@@ -0,0 +1,69 @@
1
+ --- !ruby/object:Gem::Specification
2
+ rubygems_version: 0.9.4
3
+ specification_version: 1
4
+ name: geo
5
+ version: !ruby/object:Gem::Version
6
+ version: 0.1.2
7
+ date: 2007-12-17 00:00:00 +01:00
8
+ summary: A 2D geometry engine.
9
+ require_paths:
10
+ - lib
11
+ email: geo at troja dot ath dot cx
12
+ homepage:
13
+ rubyforge_project:
14
+ description:
15
+ autorequire: geo
16
+ default_executable:
17
+ bindir: bin
18
+ has_rdoc: true
19
+ required_ruby_version: !ruby/object:Gem::Version::Requirement
20
+ requirements:
21
+ - - ">"
22
+ - !ruby/object:Gem::Version
23
+ version: 0.0.0
24
+ version:
25
+ platform: ruby
26
+ signing_key:
27
+ cert_chain:
28
+ post_install_message:
29
+ authors:
30
+ - Martin Kihlgren
31
+ files:
32
+ - ext/geo_set.h
33
+ - ext/geo_set.c
34
+ - ext/point.c
35
+ - ext/intersection.h
36
+ - ext/intersection.c
37
+ - ext/triangle.h
38
+ - ext/triangle.c
39
+ - ext/line_set.c
40
+ - ext/line.h
41
+ - ext/line.c
42
+ - ext/point_set.c
43
+ - ext/triangle_set.c
44
+ - ext/common.h
45
+ - ext/point.h
46
+ - ext/triangle_set.h
47
+ - ext/point_set.h
48
+ - ext/line_set.h
49
+ - ext/common.c
50
+ - ext/types.h
51
+ - ext/extconf.rb
52
+ - ext/geo.c
53
+ - examples/intersects.rb
54
+ - README
55
+ test_files: []
56
+
57
+ rdoc_options:
58
+ - --line-numbers
59
+ - --inline-source
60
+ extra_rdoc_files:
61
+ - README
62
+ executables: []
63
+
64
+ extensions:
65
+ - ext/extconf.rb
66
+ requirements: []
67
+
68
+ dependencies: []
69
+