geo 0.1.2

Sign up to get free protection for your applications and to get access to all the features.
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