geo 0.1.4 → 0.1.5

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