geo 0.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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
+