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/common.c CHANGED
@@ -16,12 +16,10 @@
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
- #ifdef GEO_DEBUG
22
- // The indentation of DBEUG messages.
21
+ // The indentation of DEBUG messages.
23
22
  gint DEBUG_indentation = 0;
24
- #endif
25
23
 
26
24
  gboolean
27
25
  rb_is_a(VALUE obj, VALUE c) {
@@ -50,3 +48,6 @@ gpointer_compare_as_uint(gconstpointer p1, gconstpointer p2) {
50
48
  return GPOINTER_TO_UINT(p1) - GPOINTER_TO_UINT(p2);
51
49
  }
52
50
 
51
+ void
52
+ init_common_o() {
53
+ }
data/ext/common.h CHANGED
@@ -23,15 +23,15 @@
23
23
  #include <stdlib.h>
24
24
  #include <math.h>
25
25
  #include <glib.h>
26
- #include "types.h"
27
- #include "point.h"
28
- #include "line.h"
29
- #include "intersection.h"
30
- #include "triangle.h"
31
- #include "geo_set.h"
32
- #include "line_set.h"
33
- #include "point_set.h"
34
- #include "triangle_set.h"
26
+ #include <types.h>
27
+ #include <point.h>
28
+ #include <line.h>
29
+ #include <intersection.h>
30
+ #include <triangle.h>
31
+ #include <geo_set.h>
32
+ #include <line_set.h>
33
+ #include <point_set.h>
34
+ #include <triangle_set.h>
35
35
 
36
36
  #ifndef M_PI
37
37
  #define M_PI 3.14159265358979323846 /* pi */
data/ext/extconf.rb CHANGED
@@ -28,12 +28,13 @@ unless find_executable("pkg-config")
28
28
  crash("pkg-config needed")
29
29
  end
30
30
 
31
+ $CFLAGS += " -std=c99 -Wall -I. " + `pkg-config --cflags glib-2.0`.strip
32
+ $LIBS += " " + `pkg-config --libs glib-2.0`
33
+
31
34
  unless have_library('glib-2.0')
32
35
  crash "libglib-2.0 needed"
33
36
  end
34
37
 
35
- $CFLAGS += " -std=c99 -Wall " + `pkg-config --cflags glib-2.0`.strip
36
-
37
38
  if ARGV.include?("-d")
38
39
  $CFLAGS += " -D GEO_DEBUG"
39
40
  end
data/ext/geo.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
22
22
  rb_float_intlike(VALUE self) {
@@ -30,12 +30,10 @@ rb_float_intlike(VALUE self) {
30
30
  extern "C" {
31
31
  #endif
32
32
  void Init_geo() {
33
- rb_funcall(rb_cObject, rb_intern("require"), 1, rb_str_new2("set"));
34
-
35
33
  rb_define_method(rb_cFloat, "intlike?", rb_float_intlike, 0);
36
34
 
37
35
  VALUE rb_geo = rb_define_module("Geo");
38
- rb_define_const(rb_geo, "VERSION", rb_str_new2("0.1.4"));
36
+ rb_define_const(rb_geo, "VERSION", rb_str_new2("0.1.5"));
39
37
 
40
38
  rb_triangle_set = rb_define_class_under(rb_geo,
41
39
  "TriangleSet",
@@ -78,6 +76,8 @@ extern "C" {
78
76
  rb_define_method(rb_triangle_set, "_segments_for", rb_triangle_set_segment_ids_for_triangle, 1);
79
77
  rb_define_method(rb_triangle_set, "_with_common_segment", rb_triangle_set_triangles_with_common_segment_id, 1);
80
78
  rb_define_method(rb_triangle_set, "_in_segment", rb_triangle_set_structures_in_segment, 2);
79
+ rb_define_method(rb_triangle_set, "indexed", rb_geo_set_get_indexed, 0);
80
+ rb_define_method(rb_triangle_set, "indexed=", rb_geo_set_set_indexed, 1);
81
81
 
82
82
  rb_define_alloc_func(rb_point_set, rb_point_set_alloc);
83
83
  rb_define_method(rb_point_set, "<<", rb_point_set_insert, 1);
@@ -112,6 +112,8 @@ extern "C" {
112
112
  rb_define_method(rb_line_set, "_width", rb_geo_set_width, 0);
113
113
  rb_define_method(rb_line_set, "_height", rb_geo_set_height, 0);
114
114
  rb_define_method(rb_line_set, "_with_common_segment", rb_line_set_lines_with_common_segment_id, 1);
115
+ rb_define_method(rb_line_set, "indexed", rb_geo_set_get_indexed, 0);
116
+ rb_define_method(rb_line_set, "indexed=", rb_geo_set_set_indexed, 1);
115
117
 
116
118
  rb_define_alloc_func(rb_triangle, rb_triangle_alloc);
117
119
  rb_define_method(rb_triangle, "initialize", rb_triangle_initialize, -1);
@@ -178,3 +180,7 @@ extern "C" {
178
180
  }
179
181
  #endif
180
182
 
183
+ void
184
+ init_geo_o() {
185
+ }
186
+
data/ext/geo_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
22
22
  rb_geo_set_inspect(VALUE self) {
@@ -39,19 +39,6 @@ g_hash_table_destroy_notify(gpointer p) {
39
39
  g_hash_table_destroy((GHashTable *) p);
40
40
  }
41
41
 
42
- static GeoSet*
43
- new_geo_set_without_table() {
44
- GeoSet *rval = ALLOC(GeoSet);
45
- rval->iterating = FALSE;
46
- rval->bottom_left = new_point(0,0);
47
- rval->top_right = new_point(0,0);
48
- rval->segment_side = 0;
49
- rval->segments = g_hash_table_new_full(g_direct_hash, g_direct_equal, NULL, g_hash_table_destroy_notify);
50
- rval->segment_lines = g_hash_table_new_full(g_direct_hash, g_direct_equal, NULL, line_destroy_notify);
51
- rval->index_dirty = TRUE;
52
- return rval;
53
- }
54
-
55
42
  void
56
43
  geo_set_free(GeoSet *t) {
57
44
  free(t->bottom_left);
@@ -62,17 +49,19 @@ geo_set_free(GeoSet *t) {
62
49
  free(t);
63
50
  }
64
51
 
65
- GeoSet*
66
- new_geo_set_with_destroy_notifier(GDestroyNotify destroy_notify) {
67
- GeoSet *rval = new_geo_set_without_table();
68
- rval->table = g_hash_table_new_full(g_direct_hash, g_direct_equal, destroy_notify, NULL);
69
- return rval;
70
- }
71
-
72
52
  GeoSet*
73
53
  new_geo_set() {
74
- GeoSet *rval = new_geo_set_without_table();
54
+ GeoSet *rval = ALLOC(GeoSet);
55
+ rval->iterating = FALSE;
56
+ rval->bottom_left = new_point(0,0);
57
+ rval->top_right = new_point(0,0);
58
+ rval->segment_side = 0;
59
+ rval->segments = g_hash_table_new_full(g_direct_hash, g_direct_equal, NULL, g_hash_table_destroy_notify);
60
+ rval->segment_lines = g_hash_table_new_full(g_direct_hash, g_direct_equal, NULL, line_destroy_notify);
61
+ rval->index_dirty = TRUE;
62
+ rval->indexed = TRUE;
75
63
  rval->table = g_hash_table_new(g_direct_hash, g_direct_equal);
64
+ rval->rbGeoSet = 0;
76
65
  return rval;
77
66
  }
78
67
 
@@ -141,11 +130,11 @@ geo_set_find_bounds(GeoSet *set, geo_set_bound_finder bound_finder) {
141
130
  set->bottom_left = NULL;
142
131
  set->top_right = NULL;
143
132
  bound_finder(set);
144
- set->segment_side = sqrt(GEO_SET_WIDTH(set) * GEO_SET_HEIGHT(set) / g_hash_table_size(set->table));
133
+ set->segment_side = sqrt(MAX(1, GEO_SET_WIDTH(set)) * MAX(1, GEO_SET_HEIGHT(set)) / g_hash_table_size(set->table));
145
134
  if (GEO_SET_HORIZONTAL_SEGMENTS(set) > MAX_GEO_SET_SEGMENTS)
146
- set->segment_side = GEO_SET_WIDTH(set) / MAX_GEO_SET_SEGMENTS;
135
+ set->segment_side = MAX(1, GEO_SET_WIDTH(set)) / MAX_GEO_SET_SEGMENTS;
147
136
  if (GEO_SET_VERTICAL_SEGMENTS(set) > MAX_GEO_SET_SEGMENTS)
148
- set->segment_side = GEO_SET_HEIGHT(set) / MAX_GEO_SET_SEGMENTS;
137
+ set->segment_side = MAX(1, GEO_SET_HEIGHT(set)) / MAX_GEO_SET_SEGMENTS;
149
138
  }
150
139
 
151
140
  static void
@@ -199,7 +188,7 @@ rb_geo_set_structures_in_segment(VALUE self, VALUE xV, VALUE yV, geo_structure_t
199
188
  }
200
189
 
201
190
  static gboolean
202
- g_hash_table_call_handler_for_structure_in_id_until(gpointer key, gpointer value, gpointer user_data) {
191
+ g_hash_table_call_handler_for_unique_structure_until(gpointer key, gpointer value, gpointer user_data) {
203
192
  gpointer *args = (gpointer *) user_data;
204
193
  GeoSet *set = (GeoSet *) args[0];
205
194
  geo_set_structure_handler handler = (geo_set_structure_handler) args[1];
@@ -232,7 +221,7 @@ geo_set_each_structure_in_segment_id_until(GeoSet *set, guint32 segment_id, gpoi
232
221
  if (structures_in_id != NULL) {
233
222
  gpointer rval = NULL;
234
223
  gpointer args[5] = { set, handler, seen_structures, &rval, handler_args };
235
- g_hash_table_find(structures_in_id, g_hash_table_call_handler_for_structure_in_id_until, args);
224
+ g_hash_table_find(structures_in_id, g_hash_table_call_handler_for_unique_structure_until, args);
236
225
  return rval;
237
226
  } else {
238
227
  return NULL;
@@ -427,7 +416,7 @@ geo_set_find_segments(GeoSet *set, geo_set_segment_finder segment_finder) {
427
416
 
428
417
  gboolean
429
418
  geo_set_reindex(GeoSet *set, geo_set_bound_finder bound_finder, geo_set_segment_finder segment_finder) {
430
- if (set->index_dirty && g_hash_table_size(set->table) > 0) {
419
+ if (set->indexed && set->index_dirty && g_hash_table_size(set->table) > 0) {
431
420
  set->index_dirty = FALSE;
432
421
  geo_set_find_bounds(set, bound_finder);
433
422
  if (set->segment_side > 0) {
@@ -442,13 +431,46 @@ geo_set_reindex(GeoSet *set, geo_set_bound_finder bound_finder, geo_set_segment_
442
431
  }
443
432
  }
444
433
 
445
- void
446
- geo_set_foreach(GeoSet *set, GHFunc func) {
447
- set->iterating = TRUE;
448
- g_hash_table_foreach(set->table, func, NULL);
449
- set->iterating = FALSE;
434
+ VALUE
435
+ rb_geo_set_set_indexed(VALUE self, VALUE new_indexed) {
436
+ GeoSet *set;
437
+ GEO_SET(self, set);
438
+ if (new_indexed == Qtrue)
439
+ set->indexed = TRUE;
440
+ else
441
+ set->indexed = FALSE;
442
+ return GBOOL2RB(set->indexed);
443
+ }
444
+
445
+ VALUE
446
+ rb_geo_set_get_indexed(VALUE self) {
447
+ GeoSet *set;
448
+ GEO_SET(self, set);
449
+ return GBOOL2RB(set->indexed);
450
+ }
451
+
452
+ static gboolean
453
+ g_hash_table_call_handler_for_structure_until(gpointer key, gpointer value, gpointer user_data) {
454
+ gpointer *args = (gpointer *) user_data;
455
+ GeoSet *set = (GeoSet *) args[0];
456
+ geo_set_structure_handler handler = (geo_set_structure_handler) args[1];
457
+ gpointer *rval = (gpointer *) args[2];
458
+ if ((*rval = handler(set, key, args[3])) != NULL) {
459
+ return TRUE;
460
+ } else {
461
+ return FALSE;
462
+ }
463
+ return FALSE;
450
464
  }
451
465
 
466
+ gpointer
467
+ geo_set_each_structure_until(GeoSet *set, geo_set_structure_handler handler, gpointer handler_args) {
468
+ gpointer rval;
469
+ gpointer args[5] = { set, handler, &rval, handler_args };
470
+ g_hash_table_find(set->table, g_hash_table_call_handler_for_structure_until, args);
471
+ return rval;
472
+ }
473
+
452
474
  VALUE
453
475
  geo_set_delete(GeoSet *set, gpointer p, VALUE rval) {
454
476
  CHECK_ITERATING(set);
@@ -479,15 +501,19 @@ rb_geo_set_segment_lines(VALUE self) {
479
501
  VALUE
480
502
  rb_geo_set_bottom_left(VALUE self) {
481
503
  GeoSet *set;
504
+ Point *point;
482
505
  GEO_SET(self, set);
483
- return RB_POINT(new_point(set->bottom_left->x, set->bottom_left->y), rb_point);
506
+ point = new_point(set->bottom_left->x, set->bottom_left->y);
507
+ return RB_POINT(point, rb_point);
484
508
  }
485
509
 
486
510
  VALUE
487
511
  rb_geo_set_top_right(VALUE self) {
488
512
  GeoSet *set;
513
+ Point *point;
489
514
  GEO_SET(self, set);
490
- return RB_POINT(new_point(set->top_right->x, set->top_right->y), rb_point);
515
+ point = new_point(set->top_right->x, set->top_right->y);
516
+ return RB_POINT(point, rb_point);
491
517
  }
492
518
 
493
519
  VALUE
@@ -503,3 +529,8 @@ rb_geo_set_height(VALUE self) {
503
529
  GEO_SET(self, set);
504
530
  return rb_float_new(GEO_SET_HEIGHT(set));
505
531
  }
532
+
533
+ void
534
+ init_geo_set_o() {
535
+ }
536
+
data/ext/geo_set.h CHANGED
@@ -19,7 +19,7 @@
19
19
  #ifndef GEO_SET_H
20
20
  #define GEO_SET_H
21
21
 
22
- #include "common.h"
22
+ #include <common.h>
23
23
 
24
24
  struct IntersectionStruct;
25
25
  enum IntersectionTypeEnum;
@@ -75,9 +75,6 @@ rb_geo_set_inspect(VALUE self);
75
75
  VALUE
76
76
  rb_geo_set_size(VALUE self);
77
77
 
78
- GeoSet*
79
- new_geo_set_with_destroy_notifier(GDestroyNotify destroy_notify);
80
-
81
78
  GeoSet*
82
79
  new_geo_set();
83
80
 
@@ -90,9 +87,6 @@ geo_set_clone(GeoSet *set);
90
87
  gboolean
91
88
  geo_set_reindex(GeoSet *set, geo_set_bound_finder bound_finder, geo_set_segment_finder segment_finder);
92
89
 
93
- void
94
- geo_set_foreach(GeoSet *set, GHFunc func);
95
-
96
90
  VALUE
97
91
  geo_set_delete(GeoSet *set, gpointer p, VALUE rval);
98
92
 
@@ -169,5 +163,13 @@ geo_set_each_structure_in_segment_id_until(GeoSet *set, guint32 segment_id, gpoi
169
163
  gpointer
170
164
  geo_set_insert_structure_into_rb_ary(GeoSet *set, gpointer structure, gpointer user_data);
171
165
 
166
+ VALUE
167
+ rb_geo_set_set_indexed(VALUE self, VALUE new_indexed);
168
+
169
+ VALUE
170
+ rb_geo_set_get_indexed(VALUE self);
171
+
172
+ gpointer
173
+ geo_set_each_structure_until(GeoSet *set, geo_set_structure_handler handler, gpointer handler_args);
172
174
 
173
175
  #endif
data/ext/intersection.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
 
22
22
  void
@@ -24,7 +24,7 @@ free_intersection(Intersection *intersection) {
24
24
  if (intersection->type == itPOINT)
25
25
  free(intersection->point);
26
26
  else if (intersection->type == itLINE)
27
- free(intersection->line);
27
+ line_free(intersection->line);
28
28
  free(intersection);
29
29
  }
30
30
 
@@ -73,3 +73,7 @@ rb_intersection(Intersection *intersection, Point *from) {
73
73
  }
74
74
  }
75
75
 
76
+ void
77
+ init_intersection_o() {
78
+ }
79
+
data/ext/intersection.h CHANGED
@@ -19,7 +19,7 @@
19
19
  #ifndef INTERSECTION_H
20
20
  #define INTERSECTION_H
21
21
 
22
- #include "common.h"
22
+ #include <common.h>
23
23
 
24
24
 
25
25
  #define INTERSECTION_CLOSEST_POINT(intersection_pointer,point_pointer) ((intersection_pointer)->type == itPOINT ? \
data/ext/line.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;
22
22
 
@@ -25,7 +25,7 @@ VALUE rb_line;
25
25
  * since they will be freed by ruby. Make sure that they have
26
26
  * rubified points (RB_POINT) as well though!
27
27
  */
28
- static void
28
+ void
29
29
  line_free(Line *l) {
30
30
  free(l->p1);
31
31
  free(l->p2);
@@ -103,16 +103,30 @@ rb_line_initialize(int argc, VALUE *argv, VALUE self) {
103
103
  return self;
104
104
  }
105
105
 
106
+ gchar *
107
+ line_inspect(Line *l) {
108
+ gchar *rval = calloc(1024, sizeof(gchar));
109
+ gchar *p1 = point_inspect(l->p1);
110
+ gchar *p2 = point_inspect(l->p2);
111
+ snprintf(rval, 1024, "<%s:%p p1=%s p2=%s>",
112
+ rb_obj_classname(l->rbLine), l,
113
+ p1,
114
+ p2);
115
+ free(p1);
116
+ free(p2);
117
+ return rval;
118
+ }
119
+
106
120
  VALUE
107
121
  rb_line_inspect(VALUE self) {
108
- gchar rval[1024];
122
+ gchar *str;
109
123
  Line *l;
124
+ VALUE rval;
110
125
  LINE(self, l);
111
- snprintf(rval, 1024, "<%s:%p p1=<%s:%p x=%f y=%f> p2=<%s:%p x=%f y=%f>>",
112
- rb_obj_classname(self), l,
113
- rb_obj_classname(l->p1->rbPoint), l->p1, l->p1->x, l->p1->y,
114
- rb_obj_classname(l->p2->rbPoint), l->p2, l->p2->x, l->p2->y);
115
- return rb_str_new2(rval);
126
+ str = line_inspect(l);
127
+ rval = rb_str_new2(str);
128
+ free(str);
129
+ return rval;
116
130
  }
117
131
 
118
132
  VALUE
@@ -319,6 +333,11 @@ rb_line_abs(VALUE self) {
319
333
  return rb_float_new(DISTANCE(me->p1, me->p2));
320
334
  }
321
335
 
336
+ gboolean
337
+ line_equals(gconstpointer l1, gconstpointer l2) {
338
+ return LINE_EQUALS(l1, l2);
339
+ }
340
+
322
341
  VALUE
323
342
  rb_line_equals(VALUE self, VALUE o) {
324
343
  if (!LINE_P(o)) {
@@ -336,14 +355,14 @@ rb_line_equals(VALUE self, VALUE o) {
336
355
  }
337
356
  }
338
357
 
339
- gint
358
+ static gint
340
359
  line_cmp(Line *me, Line *other) {
341
360
  gint tmp;
342
361
  gdouble my_length;
343
362
  gdouble other_length;
344
363
  my_length = DISTANCE(me->p1, me->p2);
345
364
  other_length = DISTANCE(other->p1, other->p2);
346
- if (my_length != other_length)
365
+ if (!DBL_EQL(my_length, other_length))
347
366
  return CMP(my_length, other_length);
348
367
  else if ((tmp = point_cmp(me->p1, other->p1)) != 0)
349
368
  return tmp;
@@ -395,16 +414,20 @@ rb_line_angle(VALUE self) {
395
414
  return rb_float_new(LINE_ANGLE(me));
396
415
  }
397
416
 
417
+ void
418
+ line_set_abs(Line *me, double new_abs) {
419
+ double ratio = new_abs / DISTANCE(me->p1, me->p2);
420
+ me->p2->x = me->p2->x * ratio;
421
+ me->p2->y = me->p2->y * ratio;
422
+ }
423
+
398
424
  VALUE
399
425
  rb_line_set_abs(VALUE self, VALUE new_abs) {
400
426
  Line *me;
401
- gdouble ratio;
402
427
  CHECK_NUMERICALITY(new_abs);
403
428
  LINE(self, me);
404
429
  ZERO_DISTANCE_CHECK(me->p1, me->p2);
405
- ratio = NUM2DBL(new_abs) / DISTANCE(me->p1, me->p2);
406
- me->p2->x = me->p2->x * ratio;
407
- me->p2->y = me->p2->y * ratio;
430
+ line_set_abs(me, NUM2DBL(new_abs));
408
431
  return new_abs;
409
432
  }
410
433
 
@@ -450,4 +473,131 @@ rb_line_from_gpointer(gpointer l) {
450
473
  return ( (Line *) l)->rbLine;
451
474
  }
452
475
 
476
+ gboolean
477
+ line_slide_point(Intersection *intersection, Line *line, gint ttl) {
478
+ Point touchPoint;
479
+ Point destOne;
480
+ Point destTwo;
481
+ gdouble distanceLeft;
482
+ gdouble errorOne;
483
+ gdouble errorTwo;
484
+ /*
485
+ * The line we want to adjust against. If the intersection is with a line of zero
486
+ * length, then it is against ourselves. Otherwise with the intersecting line.
487
+ */
488
+ gboolean zero_intersection = intersection->type == itLINE && ZERO_DISTANCE_P(intersection->with->p1, intersection->with->p2);
489
+ gdouble adjustment_length = zero_intersection ? DISTANCE(line->p1, line->p2) : DISTANCE(intersection->with->p1, intersection->with->p2);
490
+ gdouble adjustment_xunit = zero_intersection ? \
491
+ (line->p2->x - line->p1->x) / adjustment_length : \
492
+ (intersection->with->p2->x - intersection->with->p1->x) / adjustment_length;
493
+ gdouble adjustment_yunit = zero_intersection ? \
494
+ (line->p2->y - line->p1->y) / adjustment_length : \
495
+ (intersection->with->p2->y - intersection->with->p1->y) / adjustment_length;
496
+ /*
497
+ * Calculate where we actually touch the other line.
498
+ */
499
+ if (intersection->type == itLINE) {
500
+ if (DISTANCE(intersection->line->p1, line->p1) <
501
+ DISTANCE(intersection->line->p2, line->p1)) {
502
+ touchPoint = *(intersection->line->p1);
503
+ } else {
504
+ touchPoint = *(intersection->line->p2);
505
+ }
506
+ } else {
507
+ touchPoint = *(intersection->point);
508
+ }
509
+ if (intersection->type == itPOINT) {
510
+ /*
511
+ * If we intersected with a point, move the touch point back towards the start point to not actually touch the other line.
512
+ */
513
+ if (line->p1->x > touchPoint.x)
514
+ touchPoint.x += MIN(1, line->p1->x - touchPoint.x);
515
+ if (line->p1->x < touchPoint.x)
516
+ touchPoint.x -= MIN(1, touchPoint.x - line->p1->x);
517
+ if (line->p1->y > touchPoint.y)
518
+ touchPoint.y += MIN(1, line->p1->y - touchPoint.y);
519
+ if (line->p1->y < touchPoint.y)
520
+ touchPoint.y -= MIN(1, touchPoint.y - line->p1->y);
521
+ } else {
522
+ /*
523
+ * If we intersected with a line, move perpendicular to our adjustment-line.
524
+ */
525
+ if (rand() < RAND_MAX / 2) {
526
+ touchPoint.x += adjustment_yunit;
527
+ touchPoint.y -= adjustment_xunit;
528
+ } else {
529
+ touchPoint.x -= adjustment_yunit;
530
+ touchPoint.y += adjustment_xunit;
531
+ }
532
+ }
533
+ /*
534
+ * If the ttl is reached then we just set the line's p2 to the touchPoint.
535
+ */
536
+ if (ttl < 1) {
537
+ line->p2->x = touchPoint.x;
538
+ line->p2->y = touchPoint.y;
539
+ /*
540
+ * We are done here, no more sliding.
541
+ */
542
+ return TRUE;
543
+ } else {
544
+ /*
545
+ * Otherwise we calculate two alternate destinations.
546
+ *
547
+ * If we intersected with a zero length line, then we just go ahead in our
548
+ * original direction, otherwise we follow the intersecting line.
549
+ *
550
+ */
551
+ destOne = touchPoint;
552
+ destTwo = touchPoint;
553
+ distanceLeft = DISTANCE(line->p1, line->p2) - DISTANCE(&touchPoint, line->p1);
554
+ if (zero_intersection) {
555
+ destOne.x += adjustment_xunit * distanceLeft;
556
+ destOne.y += adjustment_yunit * distanceLeft;
557
+ destTwo.x += adjustment_xunit * distanceLeft;
558
+ destTwo.y += adjustment_yunit * distanceLeft;
559
+ } else {
560
+ destOne.x += adjustment_xunit * distanceLeft;
561
+ destOne.y += adjustment_yunit * distanceLeft;
562
+ destTwo.x -= adjustment_xunit * distanceLeft;
563
+ destTwo.y -= adjustment_yunit * distanceLeft;
564
+ }
565
+ /*
566
+ * And select the one with the least error.
567
+ */
568
+ errorOne = DISTANCE(line->p2, &destOne);
569
+ errorTwo = DISTANCE(line->p2, &destTwo);
570
+ if (DBL_EQL(errorOne, errorTwo)) {
571
+ line->p2->x = touchPoint.x;
572
+ line->p2->y = touchPoint.y;
573
+ /*
574
+ * We are done here, no more sliding.
575
+ */
576
+ return TRUE;
577
+ } else {
578
+ if (errorOne < errorTwo) {
579
+ line->p2->x = destOne.x;
580
+ line->p2->y = destOne.y;
581
+ } else if (errorOne > errorTwo) {
582
+ line->p2->x = destTwo.x;
583
+ line->p2->y = destTwo.y;
584
+ }
585
+ line->p1->x = touchPoint.x;
586
+ line->p1->y = touchPoint.y;
587
+ /*
588
+ * We are possibly not done, return FALSE.
589
+ */
590
+ return FALSE;
591
+ }
592
+ }
593
+ }
453
594
 
595
+ guint
596
+ line_hash(gconstpointer l) {
597
+ Line *line = (Line *) l;
598
+ return (guint) (line->p1->x + line->p1->y + line->p2->x + line->p2->y);
599
+ }
600
+
601
+ void
602
+ init_line_o() {
603
+ }
data/ext/line.h CHANGED
@@ -19,7 +19,7 @@
19
19
  #ifndef LINE_H
20
20
  #define LINE_H
21
21
 
22
- #include "common.h"
22
+ #include <common.h>
23
23
 
24
24
  extern VALUE rb_line;
25
25
 
@@ -30,7 +30,7 @@ extern VALUE rb_line;
30
30
  #define LINE_Y(line,v) (LINE_VERTICAL((line)) ? \
31
31
  (line)->p1->y : \
32
32
  (line)->p1->y + ((line)->p2->y - (line)->p1->y) * ((v - (line)->p1->x) / ((line)->p2->x - (line)->p1->x)))
33
- #define LINE_EQUALS(l1,l2) (POINT_EQUALS((l1)->p1, (l2)->p1) && POINT_EQUALS((l1)->p2, (l2)->p2))
33
+ #define LINE_EQUALS(l1,l2) (POINT_EQUALS(((Line *) (l1))->p1, ((Line *) (l2))->p1) && POINT_EQUALS(((Line *) (l1))->p2, ((Line *) (l2))->p2))
34
34
  /*
35
35
  * Is the point outside the rectangle described by the endpoints of the line?
36
36
  */
@@ -74,7 +74,7 @@ extern VALUE rb_line;
74
74
  #define POINT_BETWEEN_PARALLEL_LINES(l1,l2,p) ((line_side((l1),(p)) >= 0 && line_side((l2),(p)) <= 0) || \
75
75
  (line_side((l1),(p)) <= 0 && line_side((l2),(p)) >= 0))
76
76
  #define LINE_P(l) (!NIL_P((l)) && rb_is_a((l), rb_line))
77
- #define CHECK_LINE(l) if (!LINE_P((l))) rb_raise(rb_eTypeError, "Expected Grueserve::Map::Line!")
77
+ #define CHECK_LINE(l) if (!LINE_P((l))) rb_raise(rb_eTypeError, "Expected Geo::Line!")
78
78
  #define LINE_PARALLEL(l,p) (new_line_with_coordinates((p)->x, (p)->y, (p)->x + (l)->p2->x - (l)->p1->x, (p)->y + (l)->p2->y - (l)->p1->y))
79
79
  #define LINE_BOUNDS(line,bottom_left,top_right) (bottom_left)->x = MIN(line->p1->x, line->p2->x); \
80
80
  (bottom_left)->y = MIN(line->p1->y, line->p2->y); \
@@ -178,10 +178,25 @@ rb_line_side(VALUE self, VALUE p);
178
178
  VALUE
179
179
  rb_line_contains(VALUE self, VALUE p);
180
180
 
181
- gint
182
- line_cmp(Line *me, Line *other);
183
-
184
181
  VALUE
185
182
  rb_line_from_gpointer(gpointer l);
186
183
 
184
+ void
185
+ line_set_abs(Line *me, double new_abs);
186
+
187
+ gboolean
188
+ line_slide_point(Intersection *intersection, Line *line, gint ttl);
189
+
190
+ gchar *
191
+ line_inspect(Line *l);
192
+
193
+ guint
194
+ line_hash(gconstpointer l);
195
+
196
+ gboolean
197
+ line_equals(gconstpointer a, gconstpointer b);
198
+
199
+ void
200
+ line_free(Line *l);
201
+
187
202
  #endif