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/point.c ADDED
@@ -0,0 +1,265 @@
1
+
2
+ #include "common.h"
3
+
4
+ VALUE rb_point;
5
+
6
+ const Point ORIGO = { 0.0, 0.0, 0 };
7
+
8
+ Point*
9
+ new_point(gdouble x, gdouble y) {
10
+ Point *rval = ALLOC(Point);
11
+ rval->x = x;
12
+ rval->y = y;
13
+ rval->rbPoint = 0;
14
+ return rval;
15
+ }
16
+
17
+
18
+ VALUE
19
+ rb_point_alloc(VALUE class) {
20
+ Point *p = ALLOC(Point);
21
+ return RB_POINT(p, class);
22
+ }
23
+
24
+ VALUE
25
+ rb_point_initialize(VALUE self, VALUE x, VALUE y) {
26
+ Point *p;
27
+ CHECK_NUMERICALITY(x);
28
+ CHECK_NUMERICALITY(y);
29
+ POINT(self, p);
30
+ p->x = NUM2DBL(x);
31
+ p->y = NUM2DBL(y);
32
+ return self;
33
+ }
34
+
35
+ VALUE
36
+ rb_point_set_x(VALUE self, VALUE new_x) {
37
+ Point *p;
38
+ CHECK_NUMERICALITY(new_x);
39
+ POINT(self, p);
40
+ p->x = NUM2DBL(new_x);
41
+ return new_x;
42
+ }
43
+
44
+ VALUE
45
+ rb_point_set_y(VALUE self, VALUE new_y) {
46
+ Point *p;
47
+ CHECK_NUMERICALITY(new_y);
48
+ POINT(self, p);
49
+ p->y = NUM2DBL(new_y);
50
+ return new_y;
51
+ }
52
+
53
+ VALUE
54
+ rb_point_x(VALUE self) {
55
+ Point *p;
56
+ POINT(self, p);
57
+ return rb_float_new(p->x);
58
+ }
59
+
60
+ VALUE
61
+ rb_point_y(VALUE self) {
62
+ Point *p;
63
+ POINT(self, p);
64
+ return rb_float_new(p->y);
65
+ }
66
+
67
+ VALUE
68
+ rb_point_inspect(VALUE self) {
69
+ gchar rval[1024];
70
+ Point *p;
71
+ POINT(self, p);
72
+ snprintf(rval, 1023, "<%s:%p x=%f y=%f>", rb_obj_classname(self), p, p->x, p->y);
73
+ return rb_str_new2(rval);
74
+ }
75
+
76
+
77
+ VALUE
78
+ rb_point_dot(VALUE self, VALUE o) {
79
+ Point *me;
80
+ Point *point;
81
+ CHECK_POINT(o);
82
+ POINT(self, me);
83
+ POINT(o, point);
84
+ return rb_float_new(POINT_DOT(me, point));
85
+ }
86
+
87
+ VALUE
88
+ rb_point_abs(VALUE self) {
89
+ Point *me;
90
+ POINT(self, me);
91
+ return rb_float_new(DISTANCE(&ORIGO, me));
92
+ }
93
+
94
+ VALUE
95
+ rb_point_equals(VALUE self, VALUE o) {
96
+ if (!POINT_P(o)) {
97
+ return Qfalse;
98
+ } else {
99
+ Point *me;
100
+ Point *other;
101
+ POINT(self, me);
102
+ POINT(o, other);
103
+ if (POINT_EQUALS(me, other)) {
104
+ return Qtrue;
105
+ } else {
106
+ return Qfalse;
107
+ }
108
+ }
109
+ }
110
+
111
+ gint
112
+ point_cmp(Point *me, Point *other) {
113
+ gdouble my_length;
114
+ gdouble other_length;
115
+ my_length = LENGTH(me->x, me->y);
116
+ other_length = LENGTH(other->x, other->y);
117
+ if (my_length != other_length)
118
+ return CMP(my_length, other_length);
119
+ else if (me->x != other->x)
120
+ return CMP(me->x, other->x);
121
+ else
122
+ return CMP(me->y, other->y);
123
+ }
124
+
125
+ VALUE
126
+ rb_point_cmp(VALUE self, VALUE o) {
127
+ if (!POINT_P(o)) {
128
+ return INT2NUM(CMP(CLASS(self), CLASS(o)));
129
+ } else {
130
+ Point *me;
131
+ Point *other;
132
+ POINT(self, me);
133
+ POINT(o, other);
134
+ return INT2NUM(point_cmp(me, other));
135
+ }
136
+ }
137
+
138
+ VALUE
139
+ rb_point_set_angle(VALUE self, VALUE new_angle) {
140
+ Point *me;
141
+ gdouble length;
142
+ gdouble angle;
143
+ CHECK_NUMERICALITY(new_angle);
144
+ POINT(self, me);
145
+ angle = NUM2DBL(new_angle);
146
+ length = LENGTH(me->x, me->y);
147
+ while (angle > M_PI * 2)
148
+ angle -= M_PI * 2;
149
+ me->x = length * cos(angle);
150
+ me->y = length * sin(angle);
151
+ return rb_float_new(angle);
152
+ }
153
+
154
+ VALUE
155
+ rb_point_angle(VALUE self) {
156
+ Point *me;
157
+ POINT(self, me);
158
+ ZERO_LENGTH_CHECK(me);
159
+ return rb_float_new(ANGLE(me->x, me->y));
160
+ }
161
+
162
+ VALUE
163
+ rb_point_set_abs(VALUE self, VALUE new_abs) {
164
+ Point *me;
165
+ gdouble ratio;
166
+ CHECK_NUMERICALITY(new_abs);
167
+ POINT(self, me);
168
+ ZERO_LENGTH_CHECK(me);
169
+ ratio = NUM2DBL(new_abs) / LENGTH(me->x, me->y);
170
+ me->x = me->x * ratio;
171
+ me->y = me->y * ratio;
172
+ return new_abs;
173
+ }
174
+
175
+ VALUE
176
+ rb_point_clone(VALUE self) {
177
+ Point *me;
178
+ Point *rval;
179
+ POINT(self, me);
180
+ rval = new_point(me->x, me->y);
181
+ return RB_POINT(rval, CLASS(self));
182
+ }
183
+
184
+ VALUE
185
+ rb_point_to(int argc, VALUE *argv, VALUE self) {
186
+ Point *me;
187
+ Point *other_end;
188
+ Line *rval;
189
+ if (argc == 1) {
190
+ CHECK_POINT(argv[0]);
191
+ POINT(self, me);
192
+ POINT(argv[0], other_end);
193
+ rval = new_line_with_points(me, other_end);
194
+ return RB_LINE(rval, rb_line);
195
+ } else if (argc == 2) {
196
+ CHECK_NUMERICALITY(argv[0]);
197
+ CHECK_NUMERICALITY(argv[1]);
198
+ POINT(self, me);
199
+ other_end = new_point(NUM2DBL(argv[0]), NUM2DBL(argv[1]));
200
+ RB_POINT(other_end, CLASS(self));
201
+ rval = new_line_with_points(me, other_end);
202
+ return RB_LINE(rval, rb_line);
203
+ } else {
204
+ rb_raise(rb_eTypeError, "Arguments to %s#to has to be either a Grueserve::Map::Point or 2 numbers.", rb_obj_classname(self));
205
+ }
206
+ }
207
+
208
+ VALUE
209
+ rb_point_on(VALUE self, VALUE l) {
210
+ Point *me;
211
+ Line *line;
212
+ gint side;
213
+ CHECK_LINE(l);
214
+ POINT(self,me);
215
+ LINE(l, line);
216
+ side = line_side(line, me);
217
+ if (side == 0) {
218
+ return Qtrue;
219
+ } else {
220
+ return Qfalse;
221
+ }
222
+ }
223
+
224
+ VALUE
225
+ rb_point_in(VALUE self, VALUE t) {
226
+ Point *me;
227
+ Triangle *triangle;
228
+ CHECK_TRIANGLE(t);
229
+ POINT(self, me);
230
+ TRIANGLE(t, triangle);
231
+ if (triangle_contains(triangle, me)) {
232
+ return Qtrue;
233
+ } else {
234
+ return Qfalse;
235
+ }
236
+ }
237
+
238
+ VALUE
239
+ rb_point_plus(VALUE self, VALUE p) {
240
+ Point *me;
241
+ Point *other;
242
+ Point *rval;
243
+ CHECK_POINT(p);
244
+ POINT(self, me);
245
+ POINT(p, other);
246
+ rval = ALLOC(Point);
247
+ rval->x = me->x + other->x;
248
+ rval->y = me->y + other->y;
249
+ return RB_POINT(rval, CLASS(self));
250
+ }
251
+
252
+ VALUE
253
+ rb_point_minus(VALUE self, VALUE p) {
254
+ Point *me;
255
+ Point *other;
256
+ Point *rval;
257
+ CHECK_POINT(p);
258
+ POINT(self, me);
259
+ POINT(p, other);
260
+ rval = ALLOC(Point);
261
+ rval->x = me->x - other->x;
262
+ rval->y = me->y - other->y;
263
+ return RB_POINT(rval, CLASS(self));
264
+ }
265
+
data/ext/point.h ADDED
@@ -0,0 +1,123 @@
1
+
2
+ #ifndef POINT_H
3
+ #define POINT_H
4
+
5
+ #include "common.h"
6
+
7
+ extern VALUE rb_point;
8
+
9
+ #define RB_POINT(point_pointer,klass) ((point_pointer)->rbPoint = Data_Wrap_Struct(klass, NULL, free, (point_pointer)))
10
+ #define POINT(rb_point,point_pointer) Data_Get_Struct((rb_point), Point, (point_pointer))
11
+
12
+ #define M_PI 3.14159265358979323846 /* pi */
13
+ #define M_PI_2 1.57079632679489661923 /* pi/2 */
14
+ #define M_PI_4 0.78539816339744830962 /* pi/4 */
15
+ #define LENGTH(dx,dy) (sqrt(pow((dx),2) + pow((dy),2)))
16
+ #define DISTANCE(p1,p2) (LENGTH((p1)->x - (p2)->x, (p1)->y - (p2)->y))
17
+ #define ANGLE(dx,dy) ((dy) > 0 ? \
18
+ ((dx) > 0 ? \
19
+ acos((dx) / LENGTH((dx),(dy))) \
20
+ : \
21
+ ((dx) < 0 ? \
22
+ acos((dx) / LENGTH((dx),(dy))) \
23
+ : \
24
+ M_PI_2)) \
25
+ : \
26
+ ((dy) < 0 ? \
27
+ ((dx) > 0 ? \
28
+ (2 * M_PI - acos((dx) / LENGTH((dx),(dy)))) \
29
+ : \
30
+ ((dx) < 0 ? \
31
+ (2 * M_PI - acos((dx) / LENGTH((dx),(dy)))) \
32
+ : \
33
+ M_PI_2 + M_PI)) \
34
+ : \
35
+ ((dx) > 0 ? \
36
+ 0.0 \
37
+ : \
38
+ M_PI)))
39
+
40
+ #define POINT_EQUALS(p1,p2) (DBL_EQL((p1)->x, (p2)->x) && DBL_EQL((p1)->y, (p2)->y))
41
+ #define POINT_DOT(p1,p2) ((p1)->x * (p2)->x + (p1)->y * (p2)->y)
42
+ #define POINT_P(p) (!NIL_P((p)) && rb_is_a((p), rb_point))
43
+ #define CHECK_POINT(p) if (!POINT_P((p))) rb_raise(rb_eTypeError, "Expected Grueserve::Map::Point!")
44
+ #define ZERO_LENGTH_P(p) ((p)->x == 0 && (p)->y == 0)
45
+ #define ZERO_LENGTH_CHECK(p) if (ZERO_LENGTH_P((p))) rb_raise(rb_eTypeError, "Expected something with length > 0!")
46
+ #define ZERO_DISTANCE_P(p1,p2) ((p1)->x == (p2)->x && ((p1)->y == (p2)->y))
47
+ #define ZERO_DISTANCE_CHECK(p1,p2) if (ZERO_DISTANCE_P((p1),(p2))) rb_raise(rb_eTypeError, "Expected something with distance > 0!")
48
+
49
+ extern const Point ORIGO;
50
+
51
+
52
+ Point*
53
+ new_point(gdouble x, gdouble y);
54
+
55
+ VALUE
56
+ rb_point_alloc(VALUE class);
57
+
58
+ VALUE
59
+ rb_point_initialize(VALUE self, VALUE x, VALUE y);
60
+
61
+ VALUE
62
+ rb_point_set_x(VALUE self, VALUE new_x);
63
+
64
+ VALUE
65
+ rb_point_set_y(VALUE self, VALUE new_y);
66
+
67
+ VALUE
68
+ rb_point_x(VALUE self);
69
+
70
+ VALUE
71
+ rb_point_y(VALUE self);
72
+
73
+ VALUE
74
+ rb_point_inspect(VALUE self);
75
+
76
+ VALUE
77
+ rb_point_dot(VALUE self, VALUE o);
78
+
79
+ VALUE
80
+ rb_point_abs(VALUE self);
81
+
82
+ VALUE
83
+ rb_point_equals(VALUE self, VALUE o);
84
+
85
+ VALUE
86
+ rb_point_cmp(VALUE self, VALUE o);
87
+
88
+ VALUE
89
+ rb_point_set_angle(VALUE self, VALUE new_angle);
90
+
91
+ VALUE
92
+ rb_point_angle(VALUE self);
93
+
94
+ VALUE
95
+ rb_point_set_abs(VALUE self, VALUE new_abs);
96
+
97
+ VALUE
98
+ rb_point_clone(VALUE self);
99
+
100
+ VALUE
101
+ rb_point_to(int argc, VALUE *argv, VALUE self);
102
+
103
+ VALUE
104
+ rb_point_on(VALUE self, VALUE l);
105
+
106
+ VALUE
107
+ rb_point_in(VALUE self, VALUE t);
108
+
109
+ VALUE
110
+ rb_point_plus(VALUE self, VALUE p);
111
+
112
+ VALUE
113
+ rb_point_minus(VALUE self, VALUE p);
114
+
115
+ gint
116
+ point_cmp(Point *me, Point *other);
117
+
118
+
119
+
120
+
121
+
122
+ #endif
123
+
data/ext/point_set.c ADDED
@@ -0,0 +1,93 @@
1
+
2
+ #include "common.h"
3
+
4
+ VALUE rb_point_set;
5
+
6
+
7
+ static void
8
+ g_hash_table_mark_point(gpointer key, gpointer value, gpointer user_data) {
9
+ rb_gc_mark( ( (Point *) key )->rbPoint);
10
+ }
11
+
12
+ void
13
+ point_set_mark(GeoSet *set) {
14
+ g_hash_table_foreach(set->table, g_hash_table_mark_point, NULL);
15
+ }
16
+
17
+
18
+ VALUE
19
+ rb_point_set_alloc(VALUE class) {
20
+ GeoSet *set = new_geo_set();
21
+ return RB_POINT_SET(set, class);
22
+ }
23
+
24
+ VALUE
25
+ rb_point_set_insert(VALUE self, VALUE p) {
26
+ Point *point;
27
+ GeoSet *me;
28
+ CHECK_POINT(p);
29
+ GEO_SET(self, me);
30
+ POINT(p, point);
31
+ geo_set_insert(me, (gpointer ) point);
32
+ return self;
33
+ }
34
+
35
+ VALUE
36
+ rb_point_set_include(VALUE self, VALUE point) {
37
+ GeoSet *me;
38
+ Point *t;
39
+ CHECK_POINT(point);
40
+ POINT(point, t);
41
+ GEO_SET(self, me);
42
+ return GBOOL2RB(g_hash_table_lookup_extended(me->table, (gpointer) t, NULL, NULL));
43
+ }
44
+
45
+ VALUE
46
+ rb_point_set_delete(VALUE self, VALUE point) {
47
+ GeoSet *me;
48
+ Point *t;
49
+ CHECK_POINT(point);
50
+ GEO_SET(self, me);
51
+ POINT(point, t);
52
+ return geo_set_delete(me, (gpointer) t, point);
53
+ }
54
+
55
+ static void
56
+ g_hash_table_yield_point(gpointer key, gpointer value, gpointer user_data) {
57
+ rb_yield(( (Point *) key )->rbPoint);
58
+ }
59
+
60
+ VALUE
61
+ rb_point_set_each(VALUE self) {
62
+ GeoSet *set;
63
+ GEO_SET(self, set);
64
+ geo_set_foreach(set, g_hash_table_yield_point);
65
+ return self;
66
+ }
67
+
68
+ VALUE
69
+ rb_point_set_clone(VALUE self) {
70
+ GeoSet *me;
71
+ GEO_SET(self, me);
72
+ return RB_POINT_SET(geo_set_clone(me), CLASS(self));
73
+ }
74
+
75
+ gpointer
76
+ geo_set_each_structure_having_common_segment_id_with_point_until(GeoSet *set,
77
+ Point *point,
78
+ geo_set_structure_handler handler,
79
+ gpointer user_data) {
80
+ GHashTable *seen_structures = g_hash_table_new(g_direct_hash, g_direct_equal);
81
+ gpointer args[3] = { seen_structures, handler, user_data };
82
+ GHashTable *seen_segment_ids = g_hash_table_new(g_direct_hash, g_direct_equal);
83
+ gpointer rval = NULL;
84
+ rval = geo_set_each_segment_id_for_point_until(set,
85
+ point,
86
+ seen_segment_ids,
87
+ geo_set_each_structure_in_segment_id_until,
88
+ args);
89
+ g_hash_table_destroy(seen_segment_ids);
90
+ g_hash_table_destroy(seen_structures);
91
+ return rval;
92
+ }
93
+
data/ext/point_set.h ADDED
@@ -0,0 +1,44 @@
1
+
2
+ #ifndef POINT_SET_H
3
+ #define POINT_SET_H
4
+
5
+ #include "common.h"
6
+
7
+ extern VALUE rb_point_set;
8
+
9
+ #define RB_POINT_SET(point_set_pointer,klass) Data_Wrap_Struct(klass, point_set_mark, geo_set_free, (point_set_pointer))
10
+
11
+ #define POINT_SET_P(pl) (!NIL_P((pl)) && rb_is_a((pl), rb_point_set))
12
+ #define CHECK_POINT_SET(pl) if (!POINT_SET_P((pl))) rb_raise(rb_eTypeError, "Expected Grueserve::Map::PointSet!")
13
+
14
+ void
15
+ point_set_mark(GeoSet *set);
16
+
17
+ VALUE
18
+ rb_point_set_alloc(VALUE class);
19
+
20
+ VALUE
21
+ rb_point_set_insert(VALUE self, VALUE p);
22
+
23
+ VALUE
24
+ rb_point_set_include(VALUE self, VALUE point);
25
+
26
+ VALUE
27
+ rb_point_set_delete(VALUE self, VALUE point);
28
+
29
+ VALUE
30
+ rb_point_set_each(VALUE self);
31
+
32
+ VALUE
33
+ rb_point_set_clone(VALUE self);
34
+
35
+ gpointer
36
+ geo_set_each_structure_having_common_segment_id_with_point_until(GeoSet *set,
37
+ Point *point,
38
+ geo_set_structure_handler handler,
39
+ gpointer user_data);
40
+
41
+
42
+
43
+
44
+ #endif