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.
data/ext/triangle.c ADDED
@@ -0,0 +1,412 @@
1
+
2
+ #include "common.h"
3
+
4
+ VALUE rb_triangle;
5
+
6
+ static void
7
+ triangle_mark(Triangle *triangle) {
8
+ if (triangle->p1 != NULL)
9
+ rb_gc_mark(triangle->p1->rbPoint);
10
+ if (triangle->p2 != NULL)
11
+ rb_gc_mark(triangle->p2->rbPoint);
12
+ if (triangle->p3 != NULL)
13
+ rb_gc_mark(triangle->p3->rbPoint);
14
+ }
15
+
16
+ static Triangle*
17
+ new_triangle_with_coordinates(gdouble x1, gdouble y1, gdouble x2, gdouble y2, gdouble x3, gdouble y3) {
18
+ Triangle *rval = ALLOC(Triangle);
19
+ rval->p1 = new_point(x1,y1);
20
+ rval->p2 = new_point(x2,y2);
21
+ rval->p3 = new_point(x3,y3);
22
+ rval->rbTriangle = 0;
23
+ return rval;
24
+ }
25
+
26
+ VALUE
27
+ rb_triangle_alloc(VALUE class) {
28
+ Triangle *t = ALLOC(Triangle);
29
+ t->p1 = NULL;
30
+ t->p2 = NULL;
31
+ t->p3 = NULL;
32
+ return RB_TRIANGLE(t, class);
33
+ }
34
+
35
+ VALUE
36
+ rb_triangle_initialize(int argc, VALUE *argv, VALUE self) {
37
+ Triangle *t;
38
+ Point *p1;
39
+ Point *p2;
40
+ Point *p3;
41
+ if (argc == 3) {
42
+ CHECK_POINT(argv[0]);
43
+ CHECK_POINT(argv[1]);
44
+ CHECK_POINT(argv[2]);
45
+ POINT(argv[0], p1);
46
+ POINT(argv[1], p2);
47
+ POINT(argv[2], p3);
48
+ } else if (argc == 6) {
49
+ CHECK_NUMERICALITY(argv[0]);
50
+ CHECK_NUMERICALITY(argv[1]);
51
+ CHECK_NUMERICALITY(argv[2]);
52
+ CHECK_NUMERICALITY(argv[3]);
53
+ CHECK_NUMERICALITY(argv[4]);
54
+ CHECK_NUMERICALITY(argv[5]);
55
+ p1 = ALLOC(Point);
56
+ p1->x = NUM2DBL(argv[0]);
57
+ p1->y = NUM2DBL(argv[1]);
58
+ p2 = ALLOC(Point);
59
+ p2->x = NUM2DBL(argv[2]);
60
+ p2->y = NUM2DBL(argv[3]);
61
+ p3 = ALLOC(Point);
62
+ p3->x = NUM2DBL(argv[4]);
63
+ p3->y = NUM2DBL(argv[5]);
64
+ RB_POINT(p1, rb_point);
65
+ RB_POINT(p2, rb_point);
66
+ RB_POINT(p3, rb_point);
67
+ } else {
68
+ rb_raise(rb_eTypeError, "Arguments to %s#new have to be 3 Grueserve::Map::Points or 6 numbers.", rb_obj_classname(self));
69
+ }
70
+ TRIANGLE(self, t);
71
+ t->p1 = p1;
72
+ t->p2 = p2;
73
+ t->p3 = p3;
74
+ return self;
75
+ }
76
+
77
+ VALUE
78
+ rb_triangle_inspect(VALUE self) {
79
+ gchar rval[1024];
80
+ Triangle *t;
81
+ TRIANGLE(self, t);
82
+ snprintf(rval, 1024, "<%s:%p p1=<%s:%p x=%f y=%f> p2=<%s:%p x=%f y=%f> p3=<%s:%p x=%f y=%f>>",
83
+ rb_obj_classname(self), t,
84
+ rb_obj_classname(t->p1->rbPoint), t->p1, t->p1->x, t->p1->y,
85
+ rb_obj_classname(t->p2->rbPoint), t->p2, t->p2->x, t->p2->y,
86
+ rb_obj_classname(t->p3->rbPoint), t->p3, t->p3->x, t->p3->y);
87
+ return rb_str_new2(rval);
88
+ }
89
+
90
+ VALUE
91
+ rb_triangle_set_p1(VALUE self, VALUE new_point) {
92
+ Triangle *t;
93
+ Point *p;
94
+ CHECK_POINT(new_point);
95
+ TRIANGLE(self, t);
96
+ POINT(new_point, p);
97
+ t->p1 = p;
98
+ return new_point;
99
+ }
100
+
101
+ VALUE
102
+ rb_triangle_set_p2(VALUE self, VALUE new_point) {
103
+ Triangle *t;
104
+ Point *p;
105
+ CHECK_POINT(new_point);
106
+ TRIANGLE(self, t);
107
+ POINT(new_point, p);
108
+ t->p2 = p;
109
+ return new_point;
110
+ }
111
+
112
+ VALUE
113
+ rb_triangle_set_p3(VALUE self, VALUE new_point) {
114
+ Triangle *t;
115
+ Point *p;
116
+ CHECK_POINT(new_point);
117
+ TRIANGLE(self, t);
118
+ POINT(new_point, p);
119
+ t->p3 = p;
120
+ return new_point;
121
+ }
122
+
123
+ VALUE
124
+ rb_triangle_p1(VALUE self) {
125
+ Triangle *t;
126
+ TRIANGLE(self, t);
127
+ return t->p1->rbPoint;
128
+ }
129
+
130
+ VALUE
131
+ rb_triangle_p2(VALUE self) {
132
+ Triangle *t;
133
+ TRIANGLE(self, t);
134
+ return t->p2->rbPoint;
135
+ }
136
+
137
+ VALUE
138
+ rb_triangle_p3(VALUE self) {
139
+ Triangle *t;
140
+ TRIANGLE(self, t);
141
+ return t->p3->rbPoint;
142
+ }
143
+
144
+ static Line**
145
+ triangle_lines(Triangle *triangle) {
146
+ Line **rval = malloc(sizeof(Line) * 3);
147
+ rval[0] = new_line_with_points(triangle->p1, triangle->p2);
148
+ rval[1] = new_line_with_points(triangle->p1, triangle->p3);
149
+ rval[2] = new_line_with_points(triangle->p2, triangle->p3);
150
+ return rval;
151
+ }
152
+
153
+ static void
154
+ free_triangle_lines(Line **lines) {
155
+ free(lines[0]);
156
+ free(lines[1]);
157
+ free(lines[2]);
158
+ }
159
+
160
+ gboolean
161
+ triangle_contains(Triangle *triangle, Point *point) {
162
+ Line **lines = triangle_lines(triangle);
163
+ Line *l12p = LINE_PARALLEL(lines[0], triangle->p3);
164
+ Line *l13p = LINE_PARALLEL(lines[1], triangle->p2);
165
+ Line *l23p = LINE_PARALLEL(lines[2], triangle->p1);
166
+ gint rval = POINT_BETWEEN_PARALLEL_LINES(lines[0], l12p, point) && POINT_BETWEEN_PARALLEL_LINES(lines[1], l13p, point) && POINT_BETWEEN_PARALLEL_LINES(lines[2], l23p, point);
167
+ free(l12p->p1);
168
+ free(l12p->p2);
169
+ free(l13p->p1);
170
+ free(l13p->p2);
171
+ free(l23p->p1);
172
+ free(l23p->p2);
173
+ free(l12p);
174
+ free(l13p);
175
+ free(l23p);
176
+ free_triangle_lines(lines);
177
+ return rval;
178
+ }
179
+
180
+ static Intersection**
181
+ triangle_intersections(Triangle *triangle, Line *line) {
182
+ Intersection **rval = malloc(sizeof(Intersection) * 3);
183
+ Line **lines = triangle_lines(triangle);
184
+ rval[0] = line_intersection(lines[0], line);
185
+ rval[1] = line_intersection(lines[1], line);
186
+ rval[2] = line_intersection(lines[2], line);
187
+ free_triangle_lines(lines);
188
+ return rval;
189
+ }
190
+
191
+ static Intersection*
192
+ triangle_closest_intersection(Triangle *triangle, Line *line, Point *point) {
193
+ Intersection *rval;
194
+ Intersection **intersections = triangle_intersections(triangle, line);
195
+ gdouble distance12 = intersections[0] == NULL ? -1 : INTERSECTION_DISTANCE(intersections[0], point);
196
+ gdouble distance13 = intersections[1] == NULL ? -1 : INTERSECTION_DISTANCE(intersections[1], point);
197
+ gdouble distance23 = intersections[2] == NULL ? -1 : INTERSECTION_DISTANCE(intersections[2], point);
198
+ if (intersections[0] != NULL &&
199
+ (intersections[1] == NULL || distance12 <= distance13) &&
200
+ (intersections[2] == NULL || distance12 <= distance23)) {
201
+ if (intersections[1] != NULL)
202
+ free_intersection(intersections[1]);
203
+ if (intersections[2] != NULL)
204
+ free_intersection(intersections[2]);
205
+ rval = intersections[0];
206
+ } else if (intersections[1] != NULL &&
207
+ (intersections[0] == NULL || distance13 <= distance12) &&
208
+ (intersections[2] == NULL || distance13 <= distance23)) {
209
+ if (intersections[0] != NULL)
210
+ free_intersection(intersections[0]);
211
+ if (intersections[2] != NULL)
212
+ free_intersection(intersections[2]);
213
+ rval = intersections[1];
214
+ } else if (intersections[2] != NULL &&
215
+ (intersections[0] == NULL || distance23 <= distance12) &&
216
+ (intersections[1] == NULL || distance23 <= distance13)) {
217
+ if (intersections[0] != NULL)
218
+ free_intersection(intersections[0]);
219
+ if (intersections[1] != NULL)
220
+ free_intersection(intersections[1]);
221
+ rval = intersections[2];
222
+ } else {
223
+ if (intersections[0] != NULL)
224
+ free_intersection(intersections[0]);
225
+ if (intersections[1] != NULL)
226
+ free_intersection(intersections[1]);
227
+ if (intersections[2] != NULL)
228
+ free_intersection(intersections[2]);
229
+ rval = NULL;
230
+ }
231
+ return rval;
232
+ }
233
+
234
+ static Line*
235
+ triangle_overlap(Triangle *triangle, Line *line) {
236
+ if (triangle_contains(triangle, line->p1)) {
237
+ if (triangle_contains(triangle, line->p2)) {
238
+ return new_line_with_coordinates(line->p1->x, line->p1->y, line->p2->x, line->p2->y);
239
+ } else {
240
+ Intersection *closest_to_p2 = triangle_closest_intersection(triangle, line, line->p2);
241
+ if (closest_to_p2 != NULL) {
242
+ Point *closest_of_intersection = INTERSECTION_CLOSEST_POINT(closest_to_p2, line->p2);
243
+ Line *rval = new_line_with_coordinates(line->p1->x, line->p1->y, closest_of_intersection->x, closest_of_intersection->y);
244
+ free_intersection(closest_to_p2);
245
+ return rval;
246
+ } else {
247
+ return NULL;
248
+ }
249
+ }
250
+ } else if (triangle_contains(triangle, line->p2)) {
251
+ Intersection *closest_to_p1 = triangle_closest_intersection(triangle, line, line->p1);
252
+ if (closest_to_p1 != NULL) {
253
+ Point *closest_of_intersection = INTERSECTION_CLOSEST_POINT(closest_to_p1, line->p1);
254
+ Line *rval = new_line_with_coordinates(closest_of_intersection->x, closest_of_intersection->y, line->p2->x, line->p2->y);
255
+ free_intersection(closest_to_p1);
256
+ return rval;
257
+ } else {
258
+ return NULL;
259
+ }
260
+ }
261
+ Intersection *closest_to_p1 = triangle_closest_intersection(triangle, line, line->p1);
262
+ if (closest_to_p1 != NULL) {
263
+ Intersection *closest_to_p2 = triangle_closest_intersection(triangle, line, line->p2);
264
+ Point *closest_of_closest_to_p1 = INTERSECTION_CLOSEST_POINT(closest_to_p1, line->p1);
265
+ Point *closest_of_closest_to_p2 = INTERSECTION_CLOSEST_POINT(closest_to_p2, line->p2);
266
+ Line *rval = new_line_with_coordinates(closest_of_closest_to_p1->x, closest_of_closest_to_p1->y, closest_of_closest_to_p2->x, closest_of_closest_to_p2->y);
267
+ free_intersection(closest_to_p2);
268
+ free_intersection(closest_to_p1);
269
+ return rval;
270
+ }
271
+ return NULL;
272
+ }
273
+
274
+ VALUE
275
+ rb_triangle_overlap(VALUE self, VALUE line) {
276
+ Triangle *me;
277
+ Line *l;
278
+ Line *rval;
279
+ CHECK_LINE(line);
280
+ TRIANGLE(self, me);
281
+ LINE(line, l);
282
+ rval = triangle_overlap(me, l);
283
+ if (rval != NULL) {
284
+ RB_POINT(rval->p1, CLASS(l->p1->rbPoint));
285
+ RB_POINT(rval->p2, CLASS(l->p2->rbPoint));
286
+ return RB_LINE(rval, CLASS(line));
287
+ }
288
+ return Qnil;
289
+ }
290
+
291
+ gboolean
292
+ triangle_intersects(Triangle *triangle, Line *line) {
293
+ Line **lines = triangle_lines(triangle);
294
+ Intersection *intersection;
295
+ gint rval = 0;
296
+ if ((intersection = line_intersection(lines[0], line)) != NULL) {
297
+ free_intersection(intersection);
298
+ rval = 1;
299
+ } else if ((intersection = line_intersection(lines[1], line)) != NULL) {
300
+ free_intersection(intersection);
301
+ rval = 1;
302
+ } else if ((intersection = line_intersection(lines[2], line)) != NULL) {
303
+ free_intersection(intersection);
304
+ rval = 1;
305
+ }
306
+ free_triangle_lines(lines);
307
+ return rval;
308
+ }
309
+
310
+ VALUE
311
+ rb_triangle_equals(VALUE self, VALUE o) {
312
+ if (!TRIANGLE_P(o)) {
313
+ return Qfalse;
314
+ } else {
315
+ Triangle *me;
316
+ Triangle *other;
317
+ TRIANGLE(self, me);
318
+ TRIANGLE(o, other);
319
+ if (TRIANGLE_EQUALS(me, other)) {
320
+ return Qtrue;
321
+ } else {
322
+ return Qfalse;
323
+ }
324
+ }
325
+ }
326
+
327
+ static gdouble
328
+ triangle_area(Triangle *me) {
329
+ Line *l1;
330
+ Line *l2;
331
+ gdouble length1;
332
+ gdouble length2;
333
+ l1 = new_line_with_points(me->p1, me->p2);
334
+ l2 = new_line_with_points(me->p1, me->p3);
335
+ length1 = DISTANCE(l1->p1, l1->p2);
336
+ length2 = DISTANCE(l2->p1, l2->p2);
337
+ return sin(acos(LINE_DOT(l1,l2) / (length1 * length2))) * length1 * length2 / 2.0;
338
+ }
339
+
340
+ VALUE
341
+ rb_triangle_cmp(VALUE self, VALUE o) {
342
+ if (!TRIANGLE_P(o)) {
343
+ return INT2NUM(0);
344
+ } else {
345
+ Triangle *me;
346
+ Triangle *other;
347
+ gdouble my_area;
348
+ gdouble other_area;
349
+ TRIANGLE(self, me);
350
+ TRIANGLE(o, other);
351
+ my_area = triangle_area(me);
352
+ other_area = triangle_area(other);
353
+ if (my_area > other_area)
354
+ return INT2NUM(1);
355
+ else if (my_area < other_area)
356
+ return INT2NUM(-1);
357
+ else
358
+ return INT2NUM(0);
359
+ }
360
+ }
361
+
362
+ VALUE
363
+ rb_triangle_clone(VALUE self) {
364
+ Triangle *me;
365
+ Triangle *rval;
366
+ TRIANGLE(self, me);
367
+ rval = new_triangle_with_coordinates(me->p1->x, me->p1->y, me->p2->x, me->p2->y, me->p3->x, me->p3->y);
368
+ RB_POINT(rval->p1, CLASS(me->p1->rbPoint));
369
+ RB_POINT(rval->p2, CLASS(me->p2->rbPoint));
370
+ RB_POINT(rval->p3, CLASS(me->p3->rbPoint));
371
+ return RB_TRIANGLE(rval, CLASS(self));
372
+ }
373
+
374
+ VALUE
375
+ rb_triangle_area(VALUE self) {
376
+ Triangle *me;
377
+ TRIANGLE(self, me);
378
+ return rb_float_new(triangle_area(me));
379
+ }
380
+
381
+ VALUE
382
+ rb_triangle_contains(VALUE self, VALUE p) {
383
+ Triangle *me;
384
+ Point *point;
385
+ CHECK_POINT(p);
386
+ TRIANGLE(self, me);
387
+ POINT(p, point);
388
+ if (triangle_contains(me, point)) {
389
+ return Qtrue;
390
+ } else {
391
+ return Qfalse;
392
+ }
393
+ }
394
+
395
+ VALUE
396
+ rb_triangle_intersects(VALUE self, VALUE line) {
397
+ Triangle *me;
398
+ Line *l;
399
+ CHECK_LINE(line);
400
+ TRIANGLE(self, me);
401
+ LINE(line, l);
402
+ if (triangle_intersects(me, l)) {
403
+ return Qtrue;
404
+ } else {
405
+ return Qfalse;
406
+ }
407
+ }
408
+
409
+ VALUE
410
+ rb_triangle_from_gpointer(gpointer l) {
411
+ return ( (Triangle *) l)->rbTriangle;
412
+ }
data/ext/triangle.h ADDED
@@ -0,0 +1,83 @@
1
+
2
+ #ifndef TRIANGLE_H
3
+ #define TRIANGLE_H
4
+
5
+ #include "common.h"
6
+
7
+
8
+ extern VALUE rb_triangle;
9
+
10
+ #define RB_TRIANGLE(triangle_pointer,klass) ((triangle_pointer)->rbTriangle = Data_Wrap_Struct(klass, triangle_mark, free, (triangle_pointer)))
11
+ #define TRIANGLE(rb_triangle,triangle_pointer) Data_Get_Struct((rb_triangle), Triangle, (triangle_pointer))
12
+ #define TRIANGLE_EQUALS(t1,t2) (POINT_EQUALS((t1)->p1, (t2)->p1) && POINT_EQUALS((t1)->p2, (t2)->p2) && POINT_EQUALS((t1)->p3, (t2)->p3))
13
+ #define TRIANGLE_P(t) (!NIL_P((t)) && rb_is_a((t), rb_triangle))
14
+ #define CHECK_TRIANGLE(t) if (!TRIANGLE_P((t))) rb_raise(rb_eTypeError, "Expected Grueserve::Map::Triangle!")
15
+ #define TRIANGLE_BOUNDS(t,bottom_left,top_right) (bottom_left)->x = MIN(t->p1->x, MIN(t->p2->x, t->p3->x)); \
16
+ (bottom_left)->y = MIN(t->p1->y, MIN(t->p2->y, t->p3->y)); \
17
+ (top_right)->x = MAX(t->p1->x, MAX(t->p2->x, t->p3->x)); \
18
+ (top_right)->y = MAX(t->p1->y, MAX(t->p2->y, t->p3->y))
19
+
20
+ VALUE
21
+ rb_triangle_alloc(VALUE class);
22
+
23
+ VALUE
24
+ rb_triangle_initialize(int argc, VALUE *argv, VALUE self);
25
+
26
+ VALUE
27
+ rb_triangle_inspect(VALUE self);
28
+
29
+ VALUE
30
+ rb_triangle_set_p1(VALUE self, VALUE new_point);
31
+
32
+ VALUE
33
+ rb_triangle_set_p2(VALUE self, VALUE new_point);
34
+
35
+ VALUE
36
+ rb_triangle_set_p3(VALUE self, VALUE new_point);
37
+
38
+ VALUE
39
+ rb_triangle_p1(VALUE self);
40
+
41
+ VALUE
42
+ rb_triangle_p2(VALUE self);
43
+
44
+ VALUE
45
+ rb_triangle_p3(VALUE self);
46
+
47
+ VALUE
48
+ rb_triangle_overlap(VALUE self, VALUE line);
49
+
50
+ VALUE
51
+ rb_triangle_equals(VALUE self, VALUE o);
52
+
53
+ VALUE
54
+ rb_triangle_cmp(VALUE self, VALUE o);
55
+
56
+ VALUE
57
+ rb_triangle_clone(VALUE self);
58
+
59
+ VALUE
60
+ rb_triangle_area(VALUE self);
61
+
62
+ gboolean
63
+ triangle_contains(Triangle *triangle, Point *point);
64
+
65
+ VALUE
66
+ rb_triangle_contains(VALUE self, VALUE p);
67
+
68
+ gboolean
69
+ triangle_intersects(Triangle *triangle, Line *line);
70
+
71
+ VALUE
72
+ rb_triangle_intersects(VALUE self, VALUE line);
73
+
74
+ VALUE
75
+ rb_triangle_from_gpointer(gpointer l);
76
+
77
+
78
+
79
+
80
+
81
+
82
+
83
+ #endif