geo 0.1.4 → 0.1.5

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/line_set.c CHANGED
@@ -16,7 +16,7 @@
16
16
  // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17
17
 
18
18
 
19
- #include "common.h"
19
+ #include <common.h>
20
20
 
21
21
  VALUE rb_line_set;
22
22
 
@@ -70,16 +70,17 @@ rb_line_set_delete(VALUE self, VALUE line) {
70
70
  return geo_set_delete(me, (gpointer) t, line);
71
71
  }
72
72
 
73
- static void
74
- g_hash_table_yield_line(gpointer key, gpointer value, gpointer user_data) {
75
- rb_yield(( (Line *) key )->rbLine);
73
+ static gpointer
74
+ g_hash_table_yield_line(GeoSet *set, gpointer structure, gpointer user_data) {
75
+ rb_yield(( (Line *) structure )->rbLine);
76
+ return NULL;
76
77
  }
77
78
 
78
79
  VALUE
79
80
  rb_line_set_each(VALUE self) {
80
81
  GeoSet *set;
81
82
  GEO_SET(self, set);
82
- geo_set_foreach(set, g_hash_table_yield_line);
83
+ geo_set_each_structure_until(set, g_hash_table_yield_line, NULL);
83
84
  return self;
84
85
  }
85
86
 
@@ -95,9 +96,13 @@ line_set_intersection(GeoSet *set, gpointer set_line_gp, gpointer line_gp) {
95
96
 
96
97
  gboolean
97
98
  line_set_intersects(GeoSet *set, Line *line) {
98
- Intersection *intersection;
99
- LINE_SET_REINDEX(set);
100
- intersection = geo_set_each_structure_having_common_segment_id_with_line_until(set, line, line_set_intersection, line);
99
+ Intersection *intersection = NULL;
100
+ if (set->indexed) {
101
+ LINE_SET_REINDEX(set);
102
+ intersection = geo_set_each_structure_having_common_segment_id_with_line_until(set, line, line_set_intersection, line);
103
+ } else {
104
+ intersection = geo_set_each_structure_until(set, line_set_intersection, line);
105
+ }
101
106
  if (intersection != NULL)
102
107
  free_intersection(intersection);
103
108
  return GBOOL2RB(intersection != NULL);
@@ -147,127 +152,24 @@ line_set_closest_intersection(GeoSet *set, Line *line) {
147
152
  Intersection *closest = NULL;
148
153
  double closest_distance = -1;
149
154
  gpointer args[3] = { &closest_distance, &closest, line };
150
- LINE_SET_REINDEX(set);
151
- geo_set_each_structure_having_common_segment_id_with_line_until(set, line, line_set_closest_intersection_in_segments, args);
155
+ if (set->indexed) {
156
+ LINE_SET_REINDEX(set);
157
+ geo_set_each_structure_having_common_segment_id_with_line_until(set, line, line_set_closest_intersection_in_segments, args);
158
+ } else {
159
+ geo_set_each_structure_until(set, line_set_closest_intersection_in_segments, args);
160
+ }
152
161
  return closest;
153
162
  }
154
163
 
155
- static void
156
- line_set_slide(GeoSet *set, Line *line, gint ttl) {
164
+ void
165
+ line_set_slide_point(GeoSet *set, Line *line, gint ttl) {
166
+ gboolean done = FALSE;
167
+ Intersection *intersection;
157
168
  ZERO_DISTANCE_CHECK(line->p1, line->p2);
158
- Intersection *intersection = line_set_closest_intersection(set, line);
159
- if (intersection != NULL) {
160
- Point touchPoint;
161
- Point destOne;
162
- Point destTwo;
163
- gdouble distanceLeft;
164
- gdouble errorOne;
165
- gdouble errorTwo;
166
- /*
167
- * The line we want to adjust against. If the intersection is with a line of zero
168
- * length, then it is against ourselves. Otherwise with the intersecting line.
169
- */
170
- gboolean zero_intersection = intersection->type == itLINE && ZERO_DISTANCE_P(intersection->with->p1, intersection->with->p2);
171
- gdouble adjustment_length = zero_intersection ? DISTANCE(line->p1, line->p2) : DISTANCE(intersection->with->p1, intersection->with->p2);
172
- gdouble adjustment_xunit = zero_intersection ? \
173
- (line->p2->x - line->p1->x) / adjustment_length : \
174
- (intersection->with->p2->x - intersection->with->p1->x) / adjustment_length;
175
- gdouble adjustment_yunit = zero_intersection ? \
176
- (line->p2->y - line->p1->y) / adjustment_length : \
177
- (intersection->with->p2->y - intersection->with->p1->y) / adjustment_length;
178
- /*
179
- * Calculate where we actually touch the other line.
180
- */
181
- if (intersection->type == itLINE) {
182
- if (DISTANCE(intersection->line->p1, line->p1) <
183
- DISTANCE(intersection->line->p2, line->p1)) {
184
- touchPoint = *(intersection->line->p1);
185
- } else {
186
- touchPoint = *(intersection->line->p2);
187
- }
188
- } else {
189
- touchPoint = *(intersection->point);
190
- }
191
- if (intersection->type == itPOINT) {
192
- /*
193
- * If we intersected with a point, move the touch point back towards the start point to not actually touch the other line.
194
- */
195
- if (line->p1->x > touchPoint.x)
196
- touchPoint.x += MIN(1, line->p1->x - touchPoint.x);
197
- if (line->p1->x < touchPoint.x)
198
- touchPoint.x -= MIN(1, touchPoint.x - line->p1->x);
199
- if (line->p1->y > touchPoint.y)
200
- touchPoint.y += MIN(1, line->p1->y - touchPoint.y);
201
- if (line->p1->y < touchPoint.y)
202
- touchPoint.y -= MIN(1, touchPoint.y - line->p1->y);
203
- } else {
204
- /*
205
- * If we intersected with a line, move perpendicular to our adjustment-line.
206
- */
207
- if (rand() < RAND_MAX / 2) {
208
- touchPoint.x += adjustment_yunit;
209
- touchPoint.y -= adjustment_xunit;
210
- } else {
211
- touchPoint.x -= adjustment_yunit;
212
- touchPoint.y += adjustment_xunit;
213
- }
214
- }
215
- /*
216
- * Now that we wont use the intersection anymore, lets free it.
217
- */
169
+ while ((intersection = line_set_closest_intersection(set, line)) != NULL && ttl > 0 && !done) {
170
+ done = line_slide_point(intersection, line, ttl);
218
171
  free_intersection(intersection);
219
- /*
220
- * If the ttl is reached then we just set the line's p2 to the touchPoint.
221
- */
222
- if (ttl < 1) {
223
- line->p2->x = touchPoint.x;
224
- line->p2->y = touchPoint.y;
225
- } else {
226
- /*
227
- * Otherwise we calculate two alternate destinations.
228
- *
229
- * If we intersected with a zero length line, then we just go ahead in our
230
- * original direction, otherwise we follow the intersecting line.
231
- *
232
- */
233
- destOne = touchPoint;
234
- destTwo = touchPoint;
235
- distanceLeft = DISTANCE(line->p1, line->p2) - DISTANCE(&touchPoint, line->p1);
236
- if (zero_intersection) {
237
- destOne.x += adjustment_xunit * distanceLeft;
238
- destOne.y += adjustment_yunit * distanceLeft;
239
- destTwo.x += adjustment_xunit * distanceLeft;
240
- destTwo.y += adjustment_yunit * distanceLeft;
241
- } else {
242
- destOne.x += adjustment_xunit * distanceLeft;
243
- destOne.y += adjustment_yunit * distanceLeft;
244
- destTwo.x -= adjustment_xunit * distanceLeft;
245
- destTwo.y -= adjustment_yunit * distanceLeft;
246
- }
247
- /*
248
- * And select the one with the least error.
249
- */
250
- errorOne = DISTANCE(line->p2, &destOne);
251
- errorTwo = DISTANCE(line->p2, &destTwo);
252
- if (DBL_EQL(errorOne, errorTwo)) {
253
- line->p2->x = touchPoint.x;
254
- line->p2->y = touchPoint.y;
255
- } else {
256
- if (errorOne < errorTwo) {
257
- line->p2->x = destOne.x;
258
- line->p2->y = destOne.y;
259
- } else if (errorOne > errorTwo) {
260
- line->p2->x = destTwo.x;
261
- line->p2->y = destTwo.y;
262
- }
263
- line->p1->x = touchPoint.x;
264
- line->p1->y = touchPoint.y;
265
- /*
266
- * And slide along, in case something else gets in the way.
267
- */
268
- line_set_slide(set, line, ttl - 1);
269
- }
270
- }
172
+ ttl--;
271
173
  }
272
174
  }
273
175
 
@@ -278,48 +180,64 @@ rb_line_set_slide(VALUE self, VALUE l) {
278
180
  CHECK_LINE(l);
279
181
  GEO_SET(self, set);
280
182
  LINE(l, line);
281
- line_set_slide(set, line, 3);
183
+ line_set_slide_point(set, line, 3);
282
184
  return line->p2->rbPoint;
283
185
  }
284
186
 
285
187
  static void
286
- g_hash_table_intersection_free_endpoint(gpointer key, gpointer data, gpointer user_data) {
188
+ g_hash_table_each_intersection_free_endpoint(gpointer key, gpointer data, gpointer user_data) {
287
189
  gpointer *arg_wrapper = (gpointer *) user_data;
288
190
 
289
191
  gpointer *original_args = (gpointer *) arg_wrapper[0];
290
192
  gdouble *max_distance = (gdouble *) original_args[1];
291
- Line *tmpLine = (Line *) original_args[3];
292
-
193
+ Line *tmpLine = (Line *) original_args[2];
194
+ GeoSet *line_set = (GeoSet *) original_args[3];
195
+ geo_set_structure_handler handler = (geo_set_structure_handler) original_args[4];
196
+ gpointer handler_args = original_args[5];
197
+ GHashTable *seen_points = (GHashTable *) original_args[6];
198
+
293
199
  *(tmpLine->p1) = *( (Point *) arg_wrapper[1] );
294
200
  *(tmpLine->p2) = *( (Point *) key);
295
201
 
296
202
  if (*max_distance < 0 || DISTANCE(tmpLine->p1, tmpLine->p2) < *max_distance) {
297
- if (!line_set_intersects((GeoSet *) original_args[4], tmpLine)) {
298
- rb_ary_push(*( (VALUE *) original_args[2] ), ( (Point *) key )->rbPoint);
203
+ if (!line_set_intersects(line_set, tmpLine)) {
204
+ if (g_hash_table_lookup(seen_points, key) == NULL) {
205
+ handler(line_set, key, handler_args);
206
+ g_hash_table_insert(seen_points, key, GINT_TO_POINTER(1));
207
+ }
299
208
  }
300
209
  }
301
210
  }
302
211
 
212
+ static gpointer
213
+ line_set_insert_point_into_rb_ary(GeoSet *line_set, gpointer point, gpointer rval) {
214
+ rb_ary_push(*( (VALUE *) rval ), ((Point *) point)->rbPoint);
215
+ return NULL;
216
+ }
217
+
303
218
  static void
304
- g_hash_table_intersection_free_endpoints(gpointer key, gpointer data, gpointer user_data) {
219
+ g_hash_table_each_intersection_free_endpoint_for_point(gpointer key, gpointer data, gpointer user_data) {
305
220
  gpointer my_args[2];
306
221
  gpointer *given_args = (gpointer *) user_data;
307
- GeoSet *table = (GeoSet *) given_args[0];
222
+ GeoSet *endpoints = (GeoSet *) given_args[0];
308
223
  my_args[0] = user_data;
309
224
  my_args[1] = key;
310
- g_hash_table_foreach(table->table, g_hash_table_intersection_free_endpoint, (gpointer) my_args);
225
+ g_hash_table_foreach(endpoints->table, g_hash_table_each_intersection_free_endpoint, (gpointer) my_args);
311
226
  }
312
227
 
313
- static VALUE
314
- line_set_intersection_free_endpoints(GeoSet *set, GeoSet *origins, GeoSet *endpoints, gdouble max_distance) {
315
- VALUE rval = rb_ary_new();
228
+ void
229
+ line_set_each_intersection_free_endpoint(GeoSet *set,
230
+ GeoSet *origins,
231
+ GeoSet *endpoints,
232
+ gdouble max_distance,
233
+ geo_set_structure_handler handler,
234
+ gpointer user_data) {
316
235
  Line *line = new_line_with_coordinates(0,0,0,0);
317
- gpointer args[5] = { endpoints, &max_distance, &rval, line, set };
318
- g_hash_table_foreach(origins->table, g_hash_table_intersection_free_endpoints, args);
319
- free(line->p1);
320
- free(line->p2);
321
- free(line);
322
- return rval;
236
+ GHashTable *seen_points = g_hash_table_new(g_direct_hash, g_direct_equal);
237
+ gpointer args[7] = { endpoints, &max_distance, line, set, handler, user_data, seen_points };
238
+ g_hash_table_foreach(origins->table, g_hash_table_each_intersection_free_endpoint_for_point, args);
239
+ line_free(line);
240
+ g_hash_table_destroy(seen_points);
323
241
  }
324
242
 
325
243
  static gpointer
@@ -340,8 +258,12 @@ static gint
340
258
  line_set_n_intersections_with_line(GeoSet *set, Line *line) {
341
259
  gint rval = 0;
342
260
  gpointer args[2] = { &rval, line };
343
- LINE_SET_REINDEX(set);
344
- geo_set_each_structure_having_common_segment_id_with_line_until(set, line, line_set_count_intersections, args);
261
+ if (set->indexed) {
262
+ LINE_SET_REINDEX(set);
263
+ geo_set_each_structure_having_common_segment_id_with_line_until(set, line, line_set_count_intersections, args);
264
+ } else {
265
+ geo_set_each_structure_until(set, line_set_count_intersections, args);
266
+ }
345
267
  return rval;
346
268
  }
347
269
 
@@ -355,22 +277,6 @@ rb_line_set_n_intersections(VALUE self, VALUE line) {
355
277
  return INT2NUM(line_set_n_intersections_with_line(me, l));
356
278
  }
357
279
 
358
- static void
359
- g_hash_table_each_intersection(gpointer key, gpointer value, gpointer user_data) {
360
- gpointer *args = (gpointer *) user_data;
361
- Intersection *intersection = line_intersection((Line *) key, (Line *) args[0]);
362
- if (intersection != NULL) {
363
- ((GFunc) args[1])(intersection, args[2]);
364
- free_intersection(intersection);
365
- }
366
- }
367
-
368
- void
369
- line_set_each_intersection(GeoSet *set, Line *line, GFunc func, gpointer user_data) {
370
- gpointer args[3] = { line, func, user_data };
371
- g_hash_table_foreach(set->table, g_hash_table_each_intersection, args);
372
- }
373
-
374
280
  static gpointer
375
281
  line_set_collect_intersections_in_rb_ary(GeoSet *set, gpointer segment_line_gp, gpointer user_data) {
376
282
  gpointer *args = (gpointer *) user_data;
@@ -388,8 +294,12 @@ static VALUE
388
294
  line_set_intersections(GeoSet *set, Line *line) {
389
295
  VALUE rval = rb_ary_new();
390
296
  gpointer args[2] = { line, &rval };
391
- LINE_SET_REINDEX(set);
392
- geo_set_each_structure_having_common_segment_id_with_line_until(set, line, line_set_collect_intersections_in_rb_ary, args);
297
+ if (set->indexed) {
298
+ LINE_SET_REINDEX(set);
299
+ geo_set_each_structure_having_common_segment_id_with_line_until(set, line, line_set_collect_intersections_in_rb_ary, args);
300
+ } else {
301
+ geo_set_each_structure_until(set, line_set_collect_intersections_in_rb_ary, args);
302
+ }
393
303
  return rval;
394
304
  }
395
305
 
@@ -422,7 +332,7 @@ rb_line_set_intersection_free_endpoints(int argc, VALUE *argv, VALUE self) {
422
332
  endpoints = argv[1];
423
333
  max_distance = NUM2DBL(argv[2]);
424
334
  } else {
425
- rb_raise(rb_eTypeError, "Arguments to %s#intersection_free_endpoints have to be (Geo::Point | Geo::PointSet, Geo::PointSet [, Number])");
335
+ rb_raise(rb_eTypeError, "Arguments to %s#intersection_free_endpoints have to be (Geo::Point | Geo::PointSet, Geo::PointSet [, Number])", rb_obj_classname(self));
426
336
  }
427
337
  if (POINT_P(origins)) {
428
338
  ops = new_geo_set();
@@ -433,12 +343,13 @@ rb_line_set_intersection_free_endpoints(int argc, VALUE *argv, VALUE self) {
433
343
  } else if (POINT_SET_P(origins)) {
434
344
  GEO_SET(origins, ops);
435
345
  } else {
436
- rb_raise(rb_eTypeError, "Arguments to %s#intersection_free_endpoints have to be (Geo::Point | Geo::PointSet, Geo::PointSet [, Number])");
346
+ rb_raise(rb_eTypeError, "Arguments to %s#intersection_free_endpoints have to be (Geo::Point | Geo::PointSet, Geo::PointSet [, Number])", rb_obj_classname(self));
437
347
  }
438
348
  CHECK_POINT_SET(endpoints);
439
349
  GEO_SET(self, me);
440
350
  GEO_SET(endpoints, eps);
441
- rval = line_set_intersection_free_endpoints(me, ops, eps, max_distance);
351
+ rval = rb_ary_new();
352
+ line_set_each_intersection_free_endpoint(me, ops, eps, max_distance, line_set_insert_point_into_rb_ary, &rval);
442
353
  if (created_ops)
443
354
  geo_set_free(ops);
444
355
  return rval;
@@ -514,6 +425,9 @@ geo_set_each_segment_id_of_intersection_until(GeoSet *set, Line *segment_line, g
514
425
  if ((intersection = line_intersection(line, segment_line)) != NULL) {
515
426
  if (intersection->type == itPOINT) {
516
427
  rval = geo_set_each_segment_id_for_point_until(set, intersection->point, seen_segment_ids, handler, handler_args);
428
+ } else {
429
+ rval = geo_set_each_segment_id_for_point_until(set, intersection->line->p1, seen_segment_ids, handler, handler_args);
430
+ rval = geo_set_each_segment_id_for_point_until(set, intersection->line->p2, seen_segment_ids, handler, handler_args);
517
431
  }
518
432
  free_intersection(intersection);
519
433
  }
@@ -611,3 +525,7 @@ rb_line_set_reindex(VALUE self) {
611
525
  return GBOOL2RB(line_set_reindex(me));
612
526
  }
613
527
 
528
+ void
529
+ init_line_set_o() {
530
+ }
531
+
data/ext/line_set.h CHANGED
@@ -19,12 +19,13 @@
19
19
  #ifndef LINE_SET_H
20
20
  #define LINE_SET_H
21
21
 
22
- #include "common.h"
22
+ #include <common.h>
23
23
 
24
24
  extern VALUE rb_line_set;
25
25
 
26
- #define RB_LINE_SET(line_set_pointer,klass) Data_Wrap_Struct(klass, line_set_mark, geo_set_free, (line_set_pointer))
27
- #define LINE_SET_REINDEX(set) if (set->index_dirty) line_set_reindex(set)
26
+ #define RB_LINE_SET(line_set_pointer,klass) ((line_set_pointer)->rbGeoSet = Data_Wrap_Struct(klass, line_set_mark, geo_set_free, (line_set_pointer)))
27
+ #define LINE_SET_REINDEX(set) if (set->index_dirty && set->indexed) line_set_reindex(set)
28
+ #define LINE_SET_P(l) (!NIL_P((l)) && rb_is_a((l), rb_line_set))
28
29
 
29
30
  typedef gboolean
30
31
  (*line_set_line_handler)(GeoSet *set, Line *line, gpointer user_data);
@@ -77,9 +78,6 @@ g_hash_table_clone_line_value_into_rb_value(gpointer key, gpointer value, gpoint
77
78
  VALUE
78
79
  rb_line_set_segment_lines(VALUE self, VALUE line);
79
80
 
80
- void
81
- line_set_each_intersection(GeoSet *set, Line *line, GFunc func, gpointer user_data);
82
-
83
81
  VALUE
84
82
  rb_line_set_structures_in_segment(VALUE self, VALUE x, VALUE y);
85
83
 
@@ -101,4 +99,15 @@ geo_set_each_structure_having_common_segment_id_with_line_until(GeoSet *set,
101
99
  geo_set_structure_handler handler,
102
100
  gpointer user_data);
103
101
 
102
+ void
103
+ line_set_slide_point(GeoSet *set, Line *line, gint ttl);
104
+
105
+ void
106
+ line_set_each_intersection_free_endpoint(GeoSet *set,
107
+ GeoSet *origins,
108
+ GeoSet *endpoints,
109
+ gdouble max_distance,
110
+ geo_set_structure_handler handler,
111
+ gpointer user_data);
112
+
104
113
  #endif
data/ext/point.c CHANGED
@@ -16,7 +16,7 @@
16
16
  // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17
17
 
18
18
 
19
- #include "common.h"
19
+ #include <common.h>
20
20
 
21
21
  VALUE rb_point;
22
22
 
@@ -81,13 +81,23 @@ rb_point_y(VALUE self) {
81
81
  return rb_float_new(p->y);
82
82
  }
83
83
 
84
+ gchar*
85
+ point_inspect(Point *p) {
86
+ gchar *rval = calloc(1024, sizeof(gchar));
87
+ snprintf(rval, 1024, "<%s:%p x=%f y=%f>", rb_obj_classname(p->rbPoint), p, p->x, p->y);
88
+ return rval;
89
+ }
90
+
84
91
  VALUE
85
92
  rb_point_inspect(VALUE self) {
86
- gchar rval[1024];
93
+ gchar *str;
87
94
  Point *p;
95
+ VALUE rval;
88
96
  POINT(self, p);
89
- snprintf(rval, 1023, "<%s:%p x=%f y=%f>", rb_obj_classname(self), p, p->x, p->y);
90
- return rb_str_new2(rval);
97
+ str = point_inspect(p);
98
+ rval = rb_str_new2(str);
99
+ free(str);
100
+ return rval;
91
101
  }
92
102
 
93
103
 
@@ -108,6 +118,11 @@ rb_point_abs(VALUE self) {
108
118
  return rb_float_new(DISTANCE(&ORIGO, me));
109
119
  }
110
120
 
121
+ gboolean
122
+ point_equals(gconstpointer p1, gconstpointer p2) {
123
+ return POINT_EQUALS(p1, p2);
124
+ }
125
+
111
126
  VALUE
112
127
  rb_point_equals(VALUE self, VALUE o) {
113
128
  if (!POINT_P(o)) {
@@ -280,3 +295,12 @@ rb_point_minus(VALUE self, VALUE p) {
280
295
  return RB_POINT(rval, CLASS(self));
281
296
  }
282
297
 
298
+ guint
299
+ point_hash(gconstpointer p) {
300
+ Point *point = (Point *) p;
301
+ return (guint) (point->x + point->y);
302
+ }
303
+
304
+ void
305
+ init_point_o() {
306
+ }
data/ext/point.h CHANGED
@@ -19,7 +19,7 @@
19
19
  #ifndef POINT_H
20
20
  #define POINT_H
21
21
 
22
- #include "common.h"
22
+ #include <common.h>
23
23
 
24
24
  extern VALUE rb_point;
25
25
 
@@ -51,10 +51,10 @@ extern VALUE rb_point;
51
51
  : \
52
52
  M_PI)))
53
53
 
54
- #define POINT_EQUALS(p1,p2) (DBL_EQL((p1)->x, (p2)->x) && DBL_EQL((p1)->y, (p2)->y))
54
+ #define POINT_EQUALS(p1,p2) (DBL_EQL(((Point *) (p1))->x, ((Point *) (p2))->x) && DBL_EQL(((Point *) (p1))->y, ((Point *) (p2))->y))
55
55
  #define POINT_DOT(p1,p2) ((p1)->x * (p2)->x + (p1)->y * (p2)->y)
56
56
  #define POINT_P(p) (!NIL_P((p)) && rb_is_a((p), rb_point))
57
- #define CHECK_POINT(p) if (!POINT_P((p))) rb_raise(rb_eTypeError, "Expected Grueserve::Map::Point!")
57
+ #define CHECK_POINT(p) if (!POINT_P((p))) rb_raise(rb_eTypeError, "Expected Geo::Point!")
58
58
  #define ZERO_LENGTH_P(p) ((p)->x == 0 && (p)->y == 0)
59
59
  #define ZERO_LENGTH_CHECK(p) if (ZERO_LENGTH_P((p))) rb_raise(rb_eTypeError, "Expected something with length > 0!")
60
60
  #define ZERO_DISTANCE_P(p1,p2) ((p1)->x == (p2)->x && ((p1)->y == (p2)->y))
@@ -129,7 +129,14 @@ rb_point_minus(VALUE self, VALUE p);
129
129
  gint
130
130
  point_cmp(Point *me, Point *other);
131
131
 
132
+ gchar*
133
+ point_inspect(Point *p);
132
134
 
135
+ guint
136
+ point_hash(gconstpointer p);
137
+
138
+ gboolean
139
+ point_equals(gconstpointer a, gconstpointer b);
133
140
 
134
141
 
135
142
 
data/ext/point_set.c CHANGED
@@ -16,7 +16,7 @@
16
16
  // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17
17
 
18
18
 
19
- #include "common.h"
19
+ #include <common.h>
20
20
 
21
21
  VALUE rb_point_set;
22
22
 
@@ -69,16 +69,17 @@ rb_point_set_delete(VALUE self, VALUE point) {
69
69
  return geo_set_delete(me, (gpointer) t, point);
70
70
  }
71
71
 
72
- static void
73
- g_hash_table_yield_point(gpointer key, gpointer value, gpointer user_data) {
74
- rb_yield(( (Point *) key )->rbPoint);
72
+ static gpointer
73
+ g_hash_table_yield_point(GeoSet *set, gpointer structure, gpointer user_data) {
74
+ rb_yield(( (Point *) structure )->rbPoint);
75
+ return NULL;
75
76
  }
76
77
 
77
78
  VALUE
78
79
  rb_point_set_each(VALUE self) {
79
80
  GeoSet *set;
80
81
  GEO_SET(self, set);
81
- geo_set_foreach(set, g_hash_table_yield_point);
82
+ geo_set_each_structure_until(set, g_hash_table_yield_point, NULL);
82
83
  return self;
83
84
  }
84
85
 
@@ -108,3 +109,6 @@ geo_set_each_structure_having_common_segment_id_with_point_until(GeoSet *set,
108
109
  return rval;
109
110
  }
110
111
 
112
+ void
113
+ init_point_set_o() {
114
+ }
data/ext/point_set.h CHANGED
@@ -19,14 +19,14 @@
19
19
  #ifndef POINT_SET_H
20
20
  #define POINT_SET_H
21
21
 
22
- #include "common.h"
22
+ #include <common.h>
23
23
 
24
24
  extern VALUE rb_point_set;
25
25
 
26
- #define RB_POINT_SET(point_set_pointer,klass) Data_Wrap_Struct(klass, point_set_mark, geo_set_free, (point_set_pointer))
26
+ #define RB_POINT_SET(point_set_pointer,klass) ((point_set_pointer)->rbGeoSet = Data_Wrap_Struct(klass, point_set_mark, geo_set_free, (point_set_pointer)))
27
27
 
28
28
  #define POINT_SET_P(pl) (!NIL_P((pl)) && rb_is_a((pl), rb_point_set))
29
- #define CHECK_POINT_SET(pl) if (!POINT_SET_P((pl))) rb_raise(rb_eTypeError, "Expected Grueserve::Map::PointSet!")
29
+ #define CHECK_POINT_SET(pl) if (!POINT_SET_P((pl))) rb_raise(rb_eTypeError, "Expected Geo::PointSet!")
30
30
 
31
31
  void
32
32
  point_set_mark(GeoSet *set);
data/ext/triangle.c CHANGED
@@ -16,7 +16,7 @@
16
16
  // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17
17
 
18
18
 
19
- #include "common.h"
19
+ #include <common.h>
20
20
 
21
21
  VALUE rb_triangle;
22
22
 
@@ -91,17 +91,33 @@ rb_triangle_initialize(int argc, VALUE *argv, VALUE self) {
91
91
  return self;
92
92
  }
93
93
 
94
+ gchar*
95
+ triangle_inspect(Triangle *t) {
96
+ gchar *rval = calloc(1024, sizeof(gchar));
97
+ gchar *p1 = point_inspect(t->p1);
98
+ gchar *p2 = point_inspect(t->p2);
99
+ gchar *p3 = point_inspect(t->p3);
100
+ snprintf(rval, 1024, "<%s:%p p1=%s p2=%s p3=%s>",
101
+ rb_obj_classname(t->rbTriangle), t,
102
+ p1,
103
+ p2,
104
+ p3);
105
+ free(p1);
106
+ free(p2);
107
+ free(p3);
108
+ return rval;
109
+ }
110
+
94
111
  VALUE
95
112
  rb_triangle_inspect(VALUE self) {
96
- gchar rval[1024];
97
113
  Triangle *t;
114
+ gchar *str;
115
+ VALUE rval;
98
116
  TRIANGLE(self, t);
99
- 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>>",
100
- rb_obj_classname(self), t,
101
- rb_obj_classname(t->p1->rbPoint), t->p1, t->p1->x, t->p1->y,
102
- rb_obj_classname(t->p2->rbPoint), t->p2, t->p2->x, t->p2->y,
103
- rb_obj_classname(t->p3->rbPoint), t->p3, t->p3->x, t->p3->y);
104
- return rb_str_new2(rval);
117
+ str = triangle_inspect(t);
118
+ rval = rb_str_new2(str);
119
+ free(str);
120
+ return rval;
105
121
  }
106
122
 
107
123
  VALUE
@@ -181,15 +197,9 @@ triangle_contains(Triangle *triangle, Point *point) {
181
197
  Line *l13p = LINE_PARALLEL(lines[1], triangle->p2);
182
198
  Line *l23p = LINE_PARALLEL(lines[2], triangle->p1);
183
199
  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);
184
- free(l12p->p1);
185
- free(l12p->p2);
186
- free(l13p->p1);
187
- free(l13p->p2);
188
- free(l23p->p1);
189
- free(l23p->p2);
190
- free(l12p);
191
- free(l13p);
192
- free(l23p);
200
+ line_free(l12p);
201
+ line_free(l13p);
202
+ line_free(l23p);
193
203
  free_triangle_lines(lines);
194
204
  return rval;
195
205
  }
@@ -354,6 +364,23 @@ triangle_area(Triangle *me) {
354
364
  return sin(acos(LINE_DOT(l1,l2) / (length1 * length2))) * length1 * length2 / 2.0;
355
365
  }
356
366
 
367
+ static gint
368
+ triangle_cmp(Triangle *me, Triangle *other) {
369
+ gint tmp;
370
+ gdouble my_area;
371
+ gdouble other_area;
372
+ my_area = triangle_area(me);
373
+ other_area = triangle_area(other);
374
+ if (!DBL_EQL(my_area, other_area))
375
+ return CMP(my_area, other_area);
376
+ else if ((tmp = point_cmp(me->p1, other->p1)) != 0)
377
+ return tmp;
378
+ else if ((tmp = point_cmp(me->p2, other->p2)) != 0)
379
+ return tmp;
380
+ else
381
+ return point_cmp(me->p3, other->p3);
382
+ }
383
+
357
384
  VALUE
358
385
  rb_triangle_cmp(VALUE self, VALUE o) {
359
386
  if (!TRIANGLE_P(o)) {
@@ -361,18 +388,9 @@ rb_triangle_cmp(VALUE self, VALUE o) {
361
388
  } else {
362
389
  Triangle *me;
363
390
  Triangle *other;
364
- gdouble my_area;
365
- gdouble other_area;
366
391
  TRIANGLE(self, me);
367
392
  TRIANGLE(o, other);
368
- my_area = triangle_area(me);
369
- other_area = triangle_area(other);
370
- if (my_area > other_area)
371
- return INT2NUM(1);
372
- else if (my_area < other_area)
373
- return INT2NUM(-1);
374
- else
375
- return INT2NUM(0);
393
+ return INT2NUM(triangle_cmp(me, other));
376
394
  }
377
395
  }
378
396
 
@@ -427,3 +445,7 @@ VALUE
427
445
  rb_triangle_from_gpointer(gpointer l) {
428
446
  return ( (Triangle *) l)->rbTriangle;
429
447
  }
448
+
449
+ void
450
+ init_triangle_o() {
451
+ }