bribera-rubyvor 0.0.2 → 0.1.1

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.
@@ -0,0 +1,35 @@
1
+ #include <ruby.h>
2
+ #include <vdefs.h>
3
+ #include <ruby_vor_c.h>
4
+ #include <math.h>
5
+
6
+ /*
7
+ * Euclidean distance between two Points
8
+ */
9
+ VALUE
10
+ RubyVor_distance_from(VALUE self, VALUE other)
11
+ {
12
+ return rb_float_new(sqrt(pow(NUM2DBL(rb_iv_get(self, "@x")) - NUM2DBL(rb_iv_get(other, "@x")), 2.0) +
13
+ pow(NUM2DBL(rb_iv_get(self, "@y")) - NUM2DBL(rb_iv_get(other, "@y")), 2.0)));
14
+ }
15
+
16
+ VALUE
17
+ RubyVor_point_hash(VALUE self)
18
+ {
19
+ double x, y;
20
+ char *c;
21
+ long i, xHash, yHash;
22
+
23
+ x = NUM2DBL(rb_iv_get(self, "@x"));
24
+ y = NUM2DBL(rb_iv_get(self, "@y"));
25
+
26
+ /* Bastardized from Ruby's numeric.c */
27
+
28
+ for (c = (char*)&x, xHash = 0, i = 0; i < sizeof(double); i++) xHash += c[i] * 971;
29
+ for (c = (char*)&y, yHash = 0, i = 0; i < sizeof(double); i++) yHash += c[i] * 971;
30
+
31
+ xHash = xHash & RB_HASH_FILTER;
32
+ yHash = yHash & RB_HASH_FILTER;
33
+
34
+ return LONG2FIX((xHash << (RB_LONG_BITS / 2)) | yHash);
35
+ }
@@ -0,0 +1,120 @@
1
+ #include <ruby.h>
2
+ #include <vdefs.h>
3
+ #include <ruby_vor_c.h>
4
+
5
+ /*
6
+ * Instance methods for RubyVor::VDDT::PriorityQueue
7
+ */
8
+
9
+
10
+ static VALUE
11
+ compare(VALUE a, VALUE b)
12
+ {
13
+ double aD, bD;
14
+ ID minDistance;
15
+ minDistance = ID2SYM(rb_intern("min_distance"));
16
+
17
+ if (rb_class_of(a) == RubyVor_rb_cQueueItem)
18
+ aD = NUM2DBL(rb_funcall(a, rb_intern("priority"), 0));
19
+ else
20
+ rb_raise(rb_eTypeError, "wrong argument type %s (expected %s)", rb_obj_classname(a), rb_class2name(RubyVor_rb_cQueueItem));
21
+
22
+ if (rb_class_of(b) == RubyVor_rb_cQueueItem)
23
+ bD = NUM2DBL(rb_funcall(b, rb_intern("priority"), 0));
24
+ else
25
+ rb_raise(rb_eTypeError, "wrong argument type %s (expected %s)", rb_obj_classname(b), rb_class2name(RubyVor_rb_cQueueItem));
26
+
27
+ return RTEST(aD < bD);
28
+ }
29
+
30
+ VALUE
31
+ RubyVor_percolate_up(VALUE self, VALUE index)
32
+ {
33
+ VALUE item, data;
34
+ long i, j, size;
35
+
36
+ Check_Type(index, T_FIXNUM);
37
+
38
+ data = rb_iv_get(self, "@data");
39
+ Check_Type(data, T_ARRAY);
40
+
41
+ size = FIX2INT(rb_iv_get(self, "@size"));
42
+ i = FIX2INT(index) + 1;
43
+
44
+ if (i < 1 || i > size)
45
+ rb_raise(rb_eIndexError, "index %i out of range", i-1);
46
+
47
+ j = i / 2;
48
+
49
+ item = RARRAY(data)->ptr[i - 1];
50
+
51
+ while(j > 0 && compare(item, RARRAY(data)->ptr[j - 1]))
52
+ {
53
+ rb_ary_store(data, i-1, RARRAY(data)->ptr[j - 1]);
54
+ rb_funcall(RARRAY(data)->ptr[i-1], rb_intern("index="), 1, INT2FIX(i-1));
55
+ i = j;
56
+ j = j / 2;
57
+ }
58
+
59
+ rb_ary_store(data, i-1, item);
60
+ rb_funcall(RARRAY(data)->ptr[i-1], rb_intern("index="), 1, INT2FIX(i-1));
61
+
62
+ return Qnil;
63
+ }
64
+
65
+
66
+ VALUE
67
+ RubyVor_percolate_down(VALUE self, VALUE index)
68
+ {
69
+ VALUE item, data;
70
+ long i, j, k, size;
71
+
72
+ Check_Type(index, T_FIXNUM);
73
+
74
+ data = rb_iv_get(self, "@data");
75
+ Check_Type(data, T_ARRAY);
76
+
77
+ size = FIX2INT(rb_iv_get(self, "@size"));
78
+ i = FIX2INT(index) + 1;
79
+
80
+ if (i < 1 || i > size)
81
+ rb_raise(rb_eIndexError, "index %i out of range", i-1);
82
+
83
+ j = size / 2;
84
+
85
+ item = RARRAY(data)->ptr[i - 1];
86
+
87
+ while (!(i > j))
88
+ {
89
+ k = i * 2;
90
+ if (k < size && compare(RARRAY(data)->ptr[k], RARRAY(data)->ptr[k - 1]))
91
+ k++;
92
+
93
+ if (compare(item, RARRAY(data)->ptr[k - 1]))
94
+ j = -1;
95
+ else
96
+ {
97
+ rb_ary_store(data, i-1, RARRAY(data)->ptr[k - 1]);
98
+ rb_funcall(RARRAY(data)->ptr[i-1], rb_intern("index="), 1, INT2FIX(i-1));
99
+ i = k;
100
+ }
101
+ }
102
+
103
+ rb_ary_store(data, i-1, item);
104
+ rb_funcall(RARRAY(data)->ptr[i-1], rb_intern("index="), 1, INT2FIX(i-1));
105
+
106
+ return Qnil;
107
+ }
108
+
109
+
110
+ VALUE
111
+ RubyVor_heapify(VALUE self)
112
+ {
113
+ long i, size;
114
+ size = FIX2INT(rb_iv_get(self, "@size"));
115
+
116
+ for(i = size / 2; i >= 1; i--)
117
+ RubyVor_percolate_down(self, INT2FIX(i-1));
118
+
119
+ return Qnil;
120
+ }
@@ -0,0 +1,106 @@
1
+ #include <ruby.h>
2
+ #include <vdefs.h>
3
+ #include <ruby_vor_c.h>
4
+
5
+ /*
6
+ * Extension initialization
7
+ */
8
+ void
9
+ Init_ruby_vor_c(void)
10
+ {
11
+ /*
12
+ * Set up our Modules and Class.
13
+ */
14
+
15
+ /*
16
+ * Main RubyVor namespace.
17
+ */
18
+ RubyVor_rb_mRubyVor = rb_define_module("RubyVor");
19
+
20
+
21
+ /*
22
+ * Voronoi Digram and Delaunay Triangulation namespace.
23
+ */
24
+ RubyVor_rb_mVDDT = rb_define_module_under(RubyVor_rb_mRubyVor, "VDDT");
25
+
26
+
27
+ /*
28
+ * Class representing a VD/DT computation based on a set of 2-dimensional points
29
+ */
30
+ RubyVor_rb_cComputation = rb_define_class_under(RubyVor_rb_mVDDT, "Computation", rb_cObject);
31
+ rb_define_singleton_method(RubyVor_rb_cComputation, "from_points", RubyVor_from_points, 1);
32
+ rb_define_method(RubyVor_rb_cComputation, "nn_graph", RubyVor_nn_graph, 0);
33
+ rb_define_method(RubyVor_rb_cComputation, "minimum_spanning_tree", RubyVor_minimum_spanning_tree, -1);
34
+
35
+
36
+ /*
37
+ * A priority queue with a customizable heap-order property.
38
+ */
39
+ RubyVor_rb_cPriorityQueue = rb_define_class_under(RubyVor_rb_mRubyVor, "PriorityQueue", rb_cObject);
40
+ RubyVor_rb_cQueueItem = rb_define_class_under(RubyVor_rb_cPriorityQueue, "QueueItem", rb_cObject);
41
+ rb_define_method(RubyVor_rb_cPriorityQueue, "percolate_up", RubyVor_percolate_up, 1);
42
+ rb_define_method(RubyVor_rb_cPriorityQueue, "percolate_down", RubyVor_percolate_down, 1);
43
+ rb_define_method(RubyVor_rb_cPriorityQueue, "heapify", RubyVor_heapify, 0);
44
+
45
+
46
+ /*
47
+ * A simple Point class
48
+ */
49
+ RubyVor_rb_cPoint = rb_define_class_under(RubyVor_rb_mRubyVor, "Point", rb_cObject);
50
+ rb_define_method(RubyVor_rb_cPoint, "distance_from", RubyVor_distance_from, 1);
51
+ rb_define_method(RubyVor_rb_cPoint, "hash", RubyVor_point_hash, 0);
52
+ }
53
+
54
+
55
+
56
+
57
+ /*
58
+ * Method declarations duplicated here for RDOC
59
+ */
60
+
61
+ /*
62
+ * Compute the voronoi diagram and delaunay triangulation from a set of points.
63
+ *
64
+ * This implementation uses Steven Fortune's sweepline algorithm, which runs in O(n log n) time and O(n) space.
65
+ * It is limited to 2-dimensional space, therefore it expects to receive an array of objects that respond to 'x' and 'y' methods.
66
+ */
67
+ VALUE RubyVor_from_points(VALUE, VALUE);
68
+
69
+ /*
70
+ * Compute the nearest-neighbor graph using the existing Delaunay triangulation.
71
+ */
72
+ VALUE RubyVor_nn_graph(VALUE);
73
+
74
+ /*
75
+ * Computes the minimum spanning tree for given points, using the Delaunay triangulation as a seed.
76
+ *
77
+ * For points on a Euclidean plane, the MST is always comprised of a subset of the edges in a Delaunay triangulation. This makes computation of the tree very efficient: simply compute the Delaunay triangulation, and then run Prim's algorithm on the resulting edges.
78
+ */
79
+ VALUE RubyVor_minimum_spanning_tree(int, VALUE*, VALUE);
80
+
81
+ /*
82
+ * Move from the given index up, restoring the heap-order property.
83
+ */
84
+ VALUE RubyVor_percolate_up(VALUE, VALUE);
85
+
86
+ /*
87
+ * Move from the index down, restoring the heap-order property.
88
+ */
89
+ VALUE RubyVor_percolate_down(VALUE, VALUE);
90
+
91
+ /*
92
+ * Restore the heap-order property for a randomly ordered array of entries.
93
+ */
94
+ VALUE RubyVor_heapify(VALUE);
95
+
96
+ /*
97
+ * Compute the Euclidean distance between two points.
98
+ */
99
+ VALUE RubyVor_distance_from(VALUE, VALUE);
100
+
101
+ /*
102
+ * Hash value for a point.
103
+ */
104
+ VALUE RubyVor_point_hash(VALUE);
105
+
106
+ /* keep comment so RDOC will find the last method definition */
@@ -0,0 +1,36 @@
1
+ #ifndef __RUBY_VOR_H
2
+ #define __RUBY_VOR_H
3
+
4
+ #ifndef RB_LONG_BITS
5
+ #define RB_LONG_BITS sizeof(long)*8
6
+ #endif
7
+
8
+ #ifndef RB_HASH_FILTER
9
+ #define RB_HASH_FILTER ((2 << (RB_LONG_BITS / 2 - 1)) - 1)
10
+ #endif
11
+
12
+ extern VoronoiState rubyvorState;
13
+
14
+ /* Base modules */
15
+ VALUE RubyVor_rb_mRubyVor;
16
+ VALUE RubyVor_rb_mVDDT;
17
+
18
+ /* Computation */
19
+ VALUE RubyVor_rb_cComputation;
20
+ VALUE RubyVor_from_points(VALUE, VALUE);
21
+ VALUE RubyVor_nn_graph(VALUE);
22
+ VALUE RubyVor_minimum_spanning_tree(int, VALUE*, VALUE);
23
+
24
+ /* PriorityQueue */
25
+ VALUE RubyVor_rb_cPriorityQueue;
26
+ VALUE RubyVor_rb_cQueueItem;
27
+ VALUE RubyVor_percolate_up(VALUE, VALUE);
28
+ VALUE RubyVor_percolate_down(VALUE, VALUE);
29
+ VALUE RubyVor_heapify(VALUE);
30
+
31
+ /* Point */
32
+ VALUE RubyVor_rb_cPoint;
33
+ VALUE RubyVor_distance_from(VALUE, VALUE);
34
+ VALUE RubyVor_point_hash(VALUE);
35
+
36
+ #endif
@@ -64,7 +64,7 @@ typedef struct tagVoronoiState
64
64
  int sorted, plot, debug, siteidx;
65
65
  float xmin, xmax, ymin, ymax;
66
66
  Site * sites;
67
- void * decomp;
67
+ void * comp;
68
68
  void (* storeT)(int, int, int);
69
69
  void (* storeL)(float, float, float);
70
70
  void (* storeE)(int, int, int);
@@ -125,6 +125,7 @@ void freeinit(Freelist *, int) ;
125
125
  char *getfree(Freelist *) ;
126
126
  void makefree(Freenode *, Freelist *) ;
127
127
  char *myalloc(unsigned) ;
128
+ char *myrealloc(void *, unsigned, unsigned);
128
129
  void free_all(void);
129
130
 
130
131
  /* output.c */
@@ -144,6 +145,6 @@ void debug_memory(void);
144
145
  /* voronoi.c */
145
146
  void voronoi(Site *(*)()) ;
146
147
  void initialize_state(int);
147
- #endif
148
+ #endif
148
149
 
149
150
 
@@ -3,9 +3,9 @@
3
3
 
4
4
  #include <ruby.h>
5
5
  #include <vdefs.h>
6
+ #include <stdio.h>
6
7
 
7
-
8
- // Static method definitions: C -> Ruby storage methods.
8
+ /* Static method definitions: C -> Ruby storage methods. */
9
9
  static void storeTriangulationTriplet(const int, const int, const int);
10
10
  static void storeLine(const float, const float, const float);
11
11
  static void storeEndpoint(const int, const int, const int);
@@ -20,7 +20,7 @@ static void storeSite(const float, const float);
20
20
 
21
21
  void initialize_state(int debug)
22
22
  {
23
- // Set up our initial state
23
+ /* Set up our initial state */
24
24
  rubyvorState.debug = debug;
25
25
  rubyvorState.plot = 0;
26
26
  rubyvorState.nsites = 0;
@@ -32,17 +32,15 @@ void initialize_state(int debug)
32
32
  rubyvorState.storeV = storeVertex;
33
33
  rubyvorState.storeS = storeSite;
34
34
 
35
- // Initialize the Site Freelist
35
+ /* Initialize the Site Freelist */
36
36
  freeinit(&(rubyvorState.sfl), sizeof(Site)) ;
37
37
 
38
- // Initialize the geometry module
38
+ /* Initialize the geometry module */
39
39
  geominit() ;
40
40
 
41
- // TODO: remove C plot references
41
+ /* TODO: remove C plot references */
42
42
  if (rubyvorState.plot)
43
43
  plotinit();
44
-
45
- debug_memory();
46
44
  }
47
45
 
48
46
  void
@@ -50,21 +48,23 @@ voronoi(Site *(*nextsite)(void))
50
48
  {
51
49
  Site * newsite, * bot, * top, * temp, * p, * v ;
52
50
  Point newintstar ;
53
- int pm ;
51
+ int pm , c;
54
52
  Halfedge * lbnd, * rbnd, * llbnd, * rrbnd, * bisector ;
55
53
  Edge * e ;
56
54
 
55
+ newintstar.x = newintstar.y = c = 0;
56
+
57
57
  PQinitialize() ;
58
58
  rubyvorState.bottomsite = (*nextsite)() ;
59
59
  out_site(rubyvorState.bottomsite) ;
60
60
  ELinitialize() ;
61
61
  newsite = (*nextsite)() ;
62
+
62
63
  while (1)
63
64
  {
64
65
  if(!PQempty())
65
- {
66
66
  newintstar = PQ_min() ;
67
- }
67
+
68
68
  if (newsite != (Site *)NULL && (PQempty()
69
69
  || newsite -> coord.y < newintstar.y
70
70
  || (newsite->coord.y == newintstar.y
@@ -150,36 +150,32 @@ voronoi(Site *(*nextsite)(void))
150
150
  e = lbnd->ELedge ;
151
151
  out_ep(e) ;
152
152
  }
153
-
154
- // After completing calculations
155
- debug_memory();
156
153
  }
157
154
 
158
155
 
159
156
 
160
157
 
161
- //
162
- // Static storage methods
163
- //
164
-
158
+ /*
159
+ * Static storage methods
160
+ */
165
161
 
166
162
  /*** stores a triplet of point indices that comprise a Delaunay triangle ***/
167
163
  static void
168
164
  storeTriangulationTriplet(const int a, const int b, const int c)
169
165
  {
170
166
  VALUE trArray, triplet;
171
-
172
- // Create a new triplet from the three incoming points
167
+
168
+ /* Create a new triplet from the three incoming points */
173
169
  triplet = rb_ary_new2(3);
174
- RARRAY(triplet)->len = 3;
175
- RARRAY(triplet)->ptr[0] = INT2FIX(a);
176
- RARRAY(triplet)->ptr[1] = INT2FIX(b);
177
- RARRAY(triplet)->ptr[2] = INT2FIX(c);
170
+
171
+ rb_ary_push(triplet, INT2FIX(a));
172
+ rb_ary_push(triplet, INT2FIX(b));
173
+ rb_ary_push(triplet, INT2FIX(c));
178
174
 
179
- // Get the existing raw triangulation
180
- trArray = rb_funcall(*(VALUE *)rubyvorState.decomp, rb_intern("delaunay_triangulation_raw"), 0);
175
+ /* Get the existing raw triangulation */
176
+ trArray = rb_funcall(*(VALUE *)rubyvorState.comp, rb_intern("delaunay_triangulation_raw"), 0);
181
177
 
182
- // Add the new triplet to it
178
+ /* Add the new triplet to it */
183
179
  rb_ary_push(trArray, triplet);
184
180
  }
185
181
 
@@ -190,19 +186,18 @@ storeLine(const float a, const float b, const float c)
190
186
  {
191
187
  VALUE lArray, line;
192
188
 
193
- // Create a new line from the three values
189
+ /* Create a new line from the three values */
194
190
  line = rb_ary_new2(4);
195
- RARRAY(line)->len = 4;
196
- RARRAY(line)->ptr[0] = ID2SYM(rb_intern("l"));
197
- RARRAY(line)->ptr[1] = rb_float_new(a);
198
- RARRAY(line)->ptr[2] = rb_float_new(b);
199
- RARRAY(line)->ptr[3] = rb_float_new(c);
191
+ rb_ary_push(line, ID2SYM(rb_intern("l")));
192
+ rb_ary_push(line, rb_float_new(a));
193
+ rb_ary_push(line, rb_float_new(b));
194
+ rb_ary_push(line, rb_float_new(c));
200
195
 
201
- // Get the existing raw voronoi diagram
202
- lArray = rb_funcall(*(VALUE *)rubyvorState.decomp, rb_intern("voronoi_diagram_raw"), 0);
196
+ /* Get the existing raw voronoi diagram */
197
+ lArray = rb_funcall(*(VALUE *)rubyvorState.comp, rb_intern("voronoi_diagram_raw"), 0);
203
198
 
204
- // Add the new line to it
205
- rb_ary_push(lArray, line);
199
+ /* Add the new line to it */
200
+ rb_ary_push(lArray, line);
206
201
  }
207
202
 
208
203
 
@@ -216,19 +211,18 @@ storeEndpoint(const int l, const int v1, const int v2)
216
211
  {
217
212
  VALUE eArray, endpoint;
218
213
 
219
- // Create a new endpoint from the three values
214
+ /* Create a new endpoint from the three values */
220
215
  endpoint = rb_ary_new2(4);
221
- RARRAY(endpoint)->len = 4;
222
- RARRAY(endpoint)->ptr[0] = ID2SYM(rb_intern("e"));
223
- RARRAY(endpoint)->ptr[1] = INT2FIX(l);
224
- RARRAY(endpoint)->ptr[2] = INT2FIX(v1);
225
- RARRAY(endpoint)->ptr[3] = INT2FIX(v2);
216
+ rb_ary_push(endpoint, ID2SYM(rb_intern("e")));
217
+ rb_ary_push(endpoint, INT2FIX(l));
218
+ rb_ary_push(endpoint, INT2FIX(v1));
219
+ rb_ary_push(endpoint, INT2FIX(v2));
226
220
 
227
- // Get the existing raw voronoi diagram
228
- eArray = rb_funcall(*(VALUE *)rubyvorState.decomp, rb_intern("voronoi_diagram_raw"), 0);
221
+ /* Get the existing raw voronoi diagram */
222
+ eArray = rb_funcall(*(VALUE *)rubyvorState.comp, rb_intern("voronoi_diagram_raw"), 0);
229
223
 
230
- // Add the new endpoint to it
231
- rb_ary_push(eArray, endpoint);
224
+ /* Add the new endpoint to it */
225
+ rb_ary_push(eArray, endpoint);
232
226
  }
233
227
 
234
228
 
@@ -238,18 +232,17 @@ storeVertex(const float a, const float b)
238
232
  {
239
233
  VALUE vArray, vertex;
240
234
 
241
- // Create a new vertex from the coordinates
235
+ /* Create a new vertex from the coordinates */
242
236
  vertex = rb_ary_new2(3);
243
- RARRAY(vertex)->len = 3;
244
- RARRAY(vertex)->ptr[0] = ID2SYM(rb_intern("v"));
245
- RARRAY(vertex)->ptr[1] = rb_float_new(a);
246
- RARRAY(vertex)->ptr[2] = rb_float_new(b);
237
+ rb_ary_push(vertex, ID2SYM(rb_intern("v")));
238
+ rb_ary_push(vertex, rb_float_new(a));
239
+ rb_ary_push(vertex, rb_float_new(b));
247
240
 
248
- // Get the existing raw voronoi diagram
249
- vArray = rb_funcall(*(VALUE *)rubyvorState.decomp, rb_intern("voronoi_diagram_raw"), 0);
241
+ /* Get the existing raw voronoi diagram */
242
+ vArray = rb_funcall(*(VALUE *)rubyvorState.comp, rb_intern("voronoi_diagram_raw"), 0);
250
243
 
251
- // Add the new vertex to it
252
- rb_ary_push(vArray, vertex);
244
+ /* Add the new vertex to it */
245
+ rb_ary_push(vArray, vertex);
253
246
  }
254
247
 
255
248
 
@@ -262,16 +255,15 @@ storeSite(const float x, const float y)
262
255
  {
263
256
  VALUE sArray, site;
264
257
 
265
- // Create a new site from the coordinates
258
+ /* Create a new site from the coordinates */
266
259
  site = rb_ary_new2(3);
267
- RARRAY(site)->len = 3;
268
- RARRAY(site)->ptr[0] = ID2SYM(rb_intern("s"));
269
- RARRAY(site)->ptr[1] = rb_float_new(x);
270
- RARRAY(site)->ptr[2] = rb_float_new(y);
260
+ rb_ary_push(site, ID2SYM(rb_intern("s")));
261
+ rb_ary_push(site, rb_float_new(x));
262
+ rb_ary_push(site, rb_float_new(y));
271
263
 
272
- // Get the existing raw voronoi diagram
273
- sArray = rb_funcall(*(VALUE *)rubyvorState.decomp, rb_intern("voronoi_diagram_raw"), 0);
264
+ /* Get the existing raw voronoi diagram */
265
+ sArray = rb_funcall(*(VALUE *)rubyvorState.comp, rb_intern("voronoi_diagram_raw"), 0);
274
266
 
275
- // Add the new site to it
276
- rb_ary_push(sArray, site);
267
+ /* Add the new site to it */
268
+ rb_ary_push(sArray, site);
277
269
  }