bribera-rubyvor 0.0.3 → 0.0.4

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/History.txt CHANGED
@@ -1,3 +1,12 @@
1
+ === 0.0.5 / 2008-12-10
2
+
3
+ * Beginnings of clustering and useful graph algorithms.
4
+ * Some refactoring of C methods.
5
+
6
+ === 0.0.4 / 2008-12-04
7
+
8
+ * Fixed 64-bit segfaults due to improper definition of the myrealloc() function.
9
+
1
10
  === 0.0.3 / 2008-12-03
2
11
 
3
12
  * Fixed a segfault by using rb_ary_push instead of direct pointer manipulation. Much simpler.
data/Manifest.txt CHANGED
@@ -9,12 +9,19 @@ ext/geometry.c
9
9
  ext/heap.c
10
10
  ext/memory.c
11
11
  ext/output.c
12
+ ext/rb_cComputation.c
13
+ ext/rb_cPriorityQueue.c
14
+ ext/ruby_vor.c
15
+ ext/ruby_vor.h
12
16
  ext/vdefs.h
13
17
  ext/voronoi.c
14
18
  ext/voronoi_interface.c
15
19
  lib/ruby_vor.rb
16
20
  lib/ruby_vor/computation.rb
17
21
  lib/ruby_vor/point.rb
22
+ lib/ruby_vor/priority_queue.rb
18
23
  lib/ruby_vor/version.rb
19
24
  rubyvor.gemspec
25
+ test/test_computation.rb
26
+ test/test_priority_queue.rb
20
27
  test/test_voronoi_interface.rb
data/Rakefile CHANGED
@@ -20,7 +20,7 @@ desc "Compile extensions"
20
20
  task :compile => EXT
21
21
  task :test => :compile
22
22
 
23
- file EXT => ['ext/extconf.rb', 'ext/voronoi_interface.c'] do
23
+ file EXT => ['ext/extconf.rb', 'ext/ruby_vor.c'] do
24
24
  Dir.chdir 'ext' do
25
25
  ruby 'extconf.rb'
26
26
  sh 'make'
data/ext/extconf.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  require 'mkmf'
2
- dir_config('voronoi_interface')
3
- create_makefile('voronoi_interface')
2
+ dir_config('ruby_vor')
3
+ create_makefile('ruby_vor')
data/ext/output.c CHANGED
@@ -237,12 +237,14 @@ debug_memory(void)
237
237
  FILE* pf;
238
238
 
239
239
  unsigned size;// total program size
240
+ /*
240
241
  unsigned resident;// resident set size
241
242
  unsigned share;// shared pages
242
243
  unsigned text;// text (code)
243
244
  unsigned lib;// library
244
245
  unsigned data;// data/stack
245
246
  unsigned dt;// dirty pages (unused in Linux 2.6)
247
+ */
246
248
 
247
249
  int retVal;
248
250
 
@@ -0,0 +1,281 @@
1
+ #include <ruby.h>
2
+ #include <vdefs.h>
3
+ #include <ruby_vor.h>
4
+ #include <stdio.h>
5
+ #include <stdlib.h>
6
+
7
+ static Site * nextone(void);
8
+ static int scomp(const void *, const void *);
9
+
10
+ //
11
+ // Class methods for RubyVor::VDDT::Computation
12
+ //
13
+
14
+
15
+ /*
16
+ * Compute the voronoi diagram and delaunay triangulation from a set of points.
17
+ *
18
+ * This implementation uses Steven Fortune's sweepline algorithm, which runs in O(n log n) time and O(n) space.
19
+ * It is limited to 2-dimensional space, therefore it expects to receive an array of objects that respond to 'x' and 'y' methods.
20
+ */
21
+ VALUE
22
+ from_points(VALUE self, VALUE pointsArray)
23
+ {
24
+ //VALUE returnValue;
25
+ VALUE * inPtr, newComp;
26
+ ID x, y;
27
+
28
+ long i, inSize;
29
+
30
+ // Require T_ARRAY
31
+ Check_Type(pointsArray, T_ARRAY);
32
+
33
+ // Intern our point access methods
34
+ x = rb_intern("x");
35
+ y = rb_intern("y");
36
+
37
+ // Load up point count & points pointer.
38
+ inSize = RARRAY(pointsArray)->len;
39
+ inPtr = RARRAY(pointsArray)->ptr;
40
+
41
+ // Require nonzero size and x & y methods on each array object
42
+ if (inSize < 1)
43
+ rb_raise(rb_eRuntimeError, "points array have a nonzero length");
44
+ for (i = 0; i < inSize; i++) {
45
+ if(!rb_respond_to(inPtr[i], x) || !rb_respond_to(inPtr[i], y))
46
+ rb_raise(rb_eRuntimeError, "members of points array must respond to 'x' and 'y'");
47
+ }
48
+
49
+
50
+ // Initialize rubyvorState
51
+ initialize_state(/* debug? */ 0);
52
+ debug_memory();
53
+
54
+ // Create our return object.
55
+ newComp = rb_funcall(self, rb_intern("new"), 1, pointsArray);
56
+ // Store it in rubyvorState so we can populate its values.
57
+ rubyvorState.comp = (void *) &newComp;
58
+ //
59
+ // Read in the sites, sort, and compute xmin, xmax, ymin, ymax
60
+ //
61
+ // TODO: refactor this block into a separate method for clarity?
62
+ //
63
+ {
64
+ // Allocate memory for 4000 sites...
65
+ rubyvorState.sites = (Site *) myalloc(4000 * sizeof(Site));
66
+
67
+
68
+ // Iterate over the arrays, doubling the incoming values.
69
+ for (i=0; i<inSize; i++)
70
+ {
71
+ rubyvorState.sites[rubyvorState.nsites].coord.x = NUM2DBL(rb_funcall(inPtr[i], x, 0));
72
+ rubyvorState.sites[rubyvorState.nsites].coord.y = NUM2DBL(rb_funcall(inPtr[i], y, 0));
73
+
74
+ //
75
+ rubyvorState.sites[rubyvorState.nsites].sitenbr = rubyvorState.nsites;
76
+ rubyvorState.sites[rubyvorState.nsites++].refcnt = 0;
77
+
78
+ // Allocate for 4000 more if we just hit a multiple of 4000...
79
+ if (rubyvorState.nsites % 4000 == 0)
80
+ {
81
+ rubyvorState.sites = (Site *)myrealloc(rubyvorState.sites,(rubyvorState.nsites+4000)*sizeof(Site),rubyvorState.nsites*sizeof(Site));
82
+ }
83
+ }
84
+
85
+ // Sort the Sites
86
+ qsort((void *)rubyvorState.sites, rubyvorState.nsites, sizeof(Site), scomp) ;
87
+
88
+ // Pull the minimum values.
89
+ rubyvorState.xmin = rubyvorState.sites[0].coord.x;
90
+ rubyvorState.xmax = rubyvorState.sites[0].coord.x;
91
+ for (i=1; i < rubyvorState.nsites; ++i)
92
+ {
93
+ if (rubyvorState.sites[i].coord.x < rubyvorState.xmin)
94
+ {
95
+ rubyvorState.xmin = rubyvorState.sites[i].coord.x;
96
+ }
97
+ if (rubyvorState.sites[i].coord.x > rubyvorState.xmax)
98
+ {
99
+ rubyvorState.xmax = rubyvorState.sites[i].coord.x;
100
+ }
101
+ }
102
+ rubyvorState.ymin = rubyvorState.sites[0].coord.y;
103
+ rubyvorState.ymax = rubyvorState.sites[rubyvorState.nsites-1].coord.y;
104
+
105
+ }
106
+
107
+
108
+ // Perform the computation
109
+ voronoi(nextone);
110
+ debug_memory();
111
+
112
+ // Get rid of our comp reference
113
+ rubyvorState.comp = (void *)NULL;
114
+
115
+ // Free our allocated objects
116
+ free_all();
117
+ debug_memory();
118
+
119
+ return newComp;
120
+ }
121
+
122
+
123
+ //
124
+ // Instance methods (none)
125
+ //
126
+
127
+ VALUE
128
+ minimum_spanning_tree(int argc, VALUE *argv, VALUE self)
129
+ {
130
+ VALUE dist_proc, nodes, nnGraph, points, queue, tmpHash, tmpArray, adjList, latestAddition;
131
+ long i, j;
132
+
133
+ /* 0 mandatory, 1 optional */
134
+ rb_scan_args(argc, argv, "01", &dist_proc);
135
+
136
+ if (NIL_P(dist_proc)) {
137
+ // Use our default Proc
138
+ dist_proc = rb_eval_string("lambda{|a,b| a.distance_from(b)}");
139
+ } else if (rb_class_of(dist_proc) != rb_cProc) {
140
+ // Blow up if we have a non-nil, non-Proc
141
+ rb_raise(rb_eTypeError, "wrong argument type %s (expected %s)", rb_obj_classname(dist_proc), rb_class2name(rb_cProc));
142
+ }
143
+
144
+ points = rb_iv_get(self, "@points");
145
+ nodes = rb_ary_new2(RARRAY(points)->len);
146
+ queue = rb_eval_string("RubyVor::PriorityQueue.new(lambda{|a,b| a[:min_distance] < b[:min_distance]})");
147
+ nnGraph = nn_graph(self);
148
+
149
+ for (i=0; i < RARRAY(points)->len; i++) {
150
+ tmpHash = rb_hash_new();
151
+
152
+ // :node => n,
153
+ rb_hash_aset(tmpHash, ID2SYM(rb_intern("node")), INT2FIX(i));
154
+ // :min_distance => (n == 0) ? 0.0 : Float::MAX,
155
+ rb_hash_aset(tmpHash, ID2SYM(rb_intern("min_distance")), (i == 0) ? INT2FIX(0) : rb_const_get(rb_cFloat, rb_intern("MAX")));
156
+ // :parent => nil,
157
+ rb_hash_aset(tmpHash, ID2SYM(rb_intern("parent")), Qnil);
158
+ // :adjacency_list => nn_graph[n].clone,
159
+ rb_hash_aset(tmpHash, ID2SYM(rb_intern("adjacency_list")), rb_funcall(RARRAY(nnGraph)->ptr[i], rb_intern("clone"), 0));
160
+ // :min_adjacency_list => [],
161
+ rb_hash_aset(tmpHash, ID2SYM(rb_intern("min_adjacency_list")), rb_ary_new());
162
+ // :in_q => true
163
+ rb_hash_aset(tmpHash, ID2SYM(rb_intern("in_q")), Qtrue);
164
+
165
+ rb_funcall(queue, rb_intern("push"), 1, tmpHash);
166
+ }
167
+
168
+ tmpArray = rb_funcall(queue, rb_intern("data"), 0);
169
+ for (i = 0; i < RARRAY(tmpArray)->len; i++) {
170
+ tmpHash = RARRAY(tmpArray)->ptr[i];
171
+ adjList = rb_hash_aref(tmpHash, ID2SYM(rb_intern("adjacency_list")));
172
+
173
+ for (j = 0; j < RARRAY(adjList)->len; j++)
174
+ rb_ary_store(adjList, j, RARRAY(tmpArray)->ptr[ FIX2INT(RARRAY(adjList)->ptr[j]) ]);
175
+ }
176
+
177
+ latestAddition = rb_funcall(queue, rb_intern("pop"), 0);
178
+ while (RTEST(latestAddition)) {
179
+ rb_hash_aset(latestAddition, ID2SYM(rb_intern("in_q")), Qfalse);
180
+
181
+ if (RTEST(rb_hash_aref(latestAddition, ID2SYM(rb_intern("parent"))))) {
182
+ }
183
+ break;
184
+ }
185
+
186
+ return tmpArray;
187
+ }
188
+
189
+ VALUE
190
+ nn_graph(VALUE self)
191
+ {
192
+ long i;
193
+ VALUE dtRaw, graph, points, * dtPtr, * tripletPtr, * graphPtr;
194
+ ID has_key;
195
+ graph = rb_iv_get(self, "@nn_graph");
196
+
197
+ if (RTEST(graph))
198
+ return graph;
199
+
200
+ // Create an array of same size as points for the graph
201
+ points = rb_iv_get(self, "@points");
202
+ graph = rb_ary_new2(RARRAY(points)->len);
203
+ for (i = 0; i < RARRAY(points)->len; i++)
204
+ rb_ary_push(graph, rb_ary_new());
205
+
206
+ // Get our pointer into this array.
207
+ graphPtr = RARRAY(graph)->ptr;
208
+
209
+ // Iterate over the triangulation
210
+ dtRaw = rb_iv_get(self, "@delaunay_triangulation_raw");
211
+ dtPtr = RARRAY(dtRaw)->ptr;
212
+ for (i = 0; i < RARRAY(dtRaw)->len; i++) {
213
+ tripletPtr = RARRAY(dtPtr[i])->ptr;
214
+
215
+ rb_ary_push(graphPtr[FIX2INT(tripletPtr[0])], tripletPtr[1]);
216
+ rb_ary_push(graphPtr[FIX2INT(tripletPtr[1])], tripletPtr[0]);
217
+
218
+ rb_ary_push(graphPtr[FIX2INT(tripletPtr[0])], tripletPtr[2]);
219
+ rb_ary_push(graphPtr[FIX2INT(tripletPtr[2])], tripletPtr[0]);
220
+
221
+ rb_ary_push(graphPtr[FIX2INT(tripletPtr[1])], tripletPtr[2]);
222
+ rb_ary_push(graphPtr[FIX2INT(tripletPtr[2])], tripletPtr[1]);
223
+ }
224
+
225
+ for (i = 0; i < RARRAY(graph)->len; i++)
226
+ rb_funcall(graphPtr[i], rb_intern("uniq!"), 0);
227
+
228
+ rb_iv_set(self, "@nn_graph", graph);
229
+
230
+ return graph;
231
+ }
232
+
233
+
234
+
235
+ //
236
+ // Static C helper methods
237
+ //
238
+
239
+
240
+ /*** sort sites on y, then x, coord ***/
241
+ static int
242
+ scomp(const void * vs1, const void * vs2)
243
+ {
244
+ Point * s1 = (Point *)vs1 ;
245
+ Point * s2 = (Point *)vs2 ;
246
+
247
+ if (s1->y < s2->y)
248
+ {
249
+ return (-1) ;
250
+ }
251
+ if (s1->y > s2->y)
252
+ {
253
+ return (1) ;
254
+ }
255
+ if (s1->x < s2->x)
256
+ {
257
+ return (-1) ;
258
+ }
259
+ if (s1->x > s2->x)
260
+ {
261
+ return (1) ;
262
+ }
263
+ return (0) ;
264
+ }
265
+
266
+ /*** return a single in-storage site ***/
267
+ static Site *
268
+ nextone(void)
269
+ {
270
+ Site * s ;
271
+
272
+ if (rubyvorState.siteidx < rubyvorState.nsites)
273
+ {
274
+ s = &rubyvorState.sites[rubyvorState.siteidx++];
275
+ return (s) ;
276
+ }
277
+ else
278
+ {
279
+ return ((Site *)NULL) ;
280
+ }
281
+ }
@@ -0,0 +1,106 @@
1
+ #include <ruby.h>
2
+ #include <vdefs.h>
3
+ #include <ruby_vor.h>
4
+
5
+ VALUE
6
+ compare(VALUE a, VALUE b)
7
+ {
8
+ double aD, bD;
9
+ ID minDistance;
10
+ minDistance = ID2SYM(rb_intern("min_distance"));
11
+
12
+ if (rb_class_of(a) == rb_cQueueItem)
13
+ aD = NUM2DBL(rb_funcall(a, rb_intern("priority"), 0));
14
+ else
15
+ aD = NUM2DBL(a);
16
+
17
+ if (rb_class_of(b) == rb_cQueueItem)
18
+ bD = NUM2DBL(rb_funcall(b, rb_intern("priority"), 0));
19
+ else
20
+ bD = NUM2DBL(b);
21
+
22
+ return RTEST(aD < bD);
23
+ }
24
+
25
+ VALUE
26
+ percolate_up(VALUE self, VALUE index)
27
+ {
28
+ VALUE item, data;
29
+ long i, j;
30
+
31
+ data = rb_iv_get(self, "@data");
32
+ Check_Type(data, T_ARRAY);
33
+
34
+ i = FIX2INT(index);
35
+
36
+
37
+ j = i / 2;
38
+
39
+ item = RARRAY(data)->ptr[i - 1];
40
+
41
+ while(j > 0 && compare(item, RARRAY(data)->ptr[j - 1]))
42
+ {
43
+ rb_ary_store(data, i-1, RARRAY(data)->ptr[j - 1]);
44
+ rb_funcall(RARRAY(data)->ptr[i-1], rb_intern("index="), 1, INT2FIX(i));
45
+ i = j;
46
+ j = j / 2;
47
+ }
48
+
49
+ rb_ary_store(data, i-1, item);
50
+ rb_funcall(RARRAY(data)->ptr[i-1], rb_intern("index="), 1, INT2FIX(i));
51
+
52
+ return Qnil;
53
+ }
54
+
55
+
56
+ VALUE
57
+ percolate_down(VALUE self, VALUE index)
58
+ {
59
+ VALUE item, data;
60
+ long i, j, k, size;
61
+
62
+ data = rb_iv_get(self, "@data");
63
+ Check_Type(data, T_ARRAY);
64
+
65
+ size = FIX2INT(rb_iv_get(self, "@size"));
66
+ i = FIX2INT(index);
67
+
68
+
69
+ j = size / 2;
70
+
71
+ item = RARRAY(data)->ptr[i - 1];
72
+
73
+ while (!(i > j))
74
+ {
75
+ k = i * 2;
76
+ if (k < size && compare(RARRAY(data)->ptr[k], RARRAY(data)->ptr[k - 1]))
77
+ k++;
78
+
79
+ if (compare(item, RARRAY(data)->ptr[k - 1]))
80
+ j = -1;
81
+ else
82
+ {
83
+ rb_ary_store(data, i-1, RARRAY(data)->ptr[k - 1]);
84
+ rb_funcall(RARRAY(data)->ptr[i-1], rb_intern("index="), 1, INT2FIX(i));
85
+ i = k;
86
+ }
87
+ }
88
+
89
+ rb_ary_store(data, i-1, item);
90
+ rb_funcall(RARRAY(data)->ptr[i-1], rb_intern("index="), 1, INT2FIX(i));
91
+
92
+ return Qnil;
93
+ }
94
+
95
+
96
+ VALUE
97
+ heapify(VALUE self)
98
+ {
99
+ long i, size;
100
+ size = FIX2INT(rb_iv_get(self, "@size"));
101
+
102
+ for(i = size / 2; i >= 1; i--)
103
+ percolate_down(self, INT2FIX(i));
104
+
105
+ return Qnil;
106
+ }
data/ext/ruby_vor.c ADDED
@@ -0,0 +1,41 @@
1
+ #include <ruby.h>
2
+ #include <vdefs.h>
3
+ #include <ruby_vor.h>
4
+
5
+ void
6
+ Init_ruby_vor(void)
7
+ {
8
+ //
9
+ // Set up our Modules and Class.
10
+ //
11
+
12
+ /*
13
+ * Main RubyVor namespace.
14
+ */
15
+ rb_mRubyVor = rb_define_module("RubyVor");
16
+
17
+
18
+ /*
19
+ * Voronoi Digram and Delaunay Triangulation namespace.
20
+ */
21
+ rb_mVDDT = rb_define_module_under(rb_mRubyVor, "VDDT");
22
+
23
+
24
+ /*
25
+ * Class representing a VD/DT computation based on a set of 2-dimensional points
26
+ */
27
+ rb_cComputation = rb_define_class_under(rb_mVDDT, "Computation", rb_cObject);
28
+ rb_define_singleton_method(rb_cComputation, "from_points", from_points, 1);
29
+ rb_define_method(rb_cComputation, "nn_graph", nn_graph, 0);
30
+ //rb_define_method(rb_cComputation, "minimum_spanning_tree", minimum_spanning_tree, -1);
31
+
32
+
33
+ /*
34
+ * A priority queue with a customizable heap-order property.
35
+ */
36
+ rb_cPriorityQueue = rb_define_class_under(rb_mRubyVor, "PriorityQueue", rb_cObject);
37
+ rb_cQueueItem = rb_define_class_under(rb_cPriorityQueue, "QueueItem", rb_cObject);
38
+ rb_define_method(rb_cPriorityQueue, "percolate_up", percolate_up, 1);
39
+ rb_define_method(rb_cPriorityQueue, "percolate_down", percolate_down, 1);
40
+ rb_define_method(rb_cPriorityQueue, "heapify", heapify, 0);
41
+ }
data/ext/ruby_vor.h ADDED
@@ -0,0 +1,23 @@
1
+ #ifndef __RUBY_VOR_H
2
+ #define __RUBY_VOR_H
3
+
4
+ extern VoronoiState rubyvorState;
5
+
6
+ /* Base modules */
7
+ VALUE rb_mRubyVor;
8
+ VALUE rb_mVDDT;
9
+
10
+ /* Computation */
11
+ VALUE rb_cComputation;
12
+ VALUE from_points(VALUE, VALUE);
13
+ VALUE nn_graph(VALUE);
14
+ VALUE minimum_spanning_tree(int, VALUE*, VALUE);
15
+
16
+ /* PriorityQueue */
17
+ VALUE rb_cPriorityQueue;
18
+ VALUE rb_cQueueItem;
19
+ VALUE percolate_up(VALUE, VALUE);
20
+ VALUE percolate_down(VALUE, VALUE);
21
+ VALUE heapify(VALUE);
22
+
23
+ #endif
data/ext/vdefs.h CHANGED
@@ -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
 
data/ext/voronoi.c CHANGED
@@ -56,16 +56,12 @@ voronoi(Site *(*nextsite)(void))
56
56
 
57
57
  PQinitialize() ;
58
58
  rubyvorState.bottomsite = (*nextsite)() ;
59
- if (rubyvorState.debug) fprintf(stderr, "bnys ");
60
59
  out_site(rubyvorState.bottomsite) ;
61
60
  ELinitialize() ;
62
61
  newsite = (*nextsite)() ;
63
62
 
64
63
  while (1)
65
64
  {
66
-
67
- if (rubyvorState.debug) fprintf(stderr, "%d ", c++);
68
-
69
65
  if(!PQempty())
70
66
  newintstar = PQ_min() ;
71
67
 
@@ -74,10 +70,8 @@ voronoi(Site *(*nextsite)(void))
74
70
  || (newsite->coord.y == newintstar.y
75
71
  && newsite->coord.x < newintstar.x)))
76
72
  {
77
- if (rubyvorState.debug) fprintf(stderr, "nss ");
78
73
  /* new site is smallest */
79
74
  {
80
- if (rubyvorState.debug) fprintf(stderr, "bnys ");
81
75
  out_site(newsite) ;
82
76
  }
83
77
  lbnd = ELleftbnd(&(newsite->coord)) ;
@@ -104,14 +98,12 @@ voronoi(Site *(*nextsite)(void))
104
98
  }
105
99
  else if (!PQempty()) /* intersection is smallest */
106
100
  {
107
- if (rubyvorState.debug) fprintf(stderr, "!pqe ");
108
101
  lbnd = PQextractmin() ;
109
102
  llbnd = ELleft(lbnd) ;
110
103
  rbnd = ELright(lbnd) ;
111
104
  rrbnd = ELright(rbnd) ;
112
105
  bot = leftreg(lbnd) ;
113
106
  top = rightreg(rbnd) ;
114
- if (rubyvorState.debug) fprintf(stderr, "bnyt ");
115
107
  out_triple(bot, top, rightreg(lbnd)) ;
116
108
  v = lbnd->vertex ;
117
109
  makevertex(v) ;
@@ -156,7 +148,6 @@ voronoi(Site *(*nextsite)(void))
156
148
  lbnd = ELright(lbnd))
157
149
  {
158
150
  e = lbnd->ELedge ;
159
- if (rubyvorState.debug) fprintf(stderr, "bnye ");
160
151
  out_ep(e) ;
161
152
  }
162
153
  }
@@ -168,15 +159,15 @@ voronoi(Site *(*nextsite)(void))
168
159
  // Static storage methods
169
160
  //
170
161
 
171
-
172
162
  /*** stores a triplet of point indices that comprise a Delaunay triangle ***/
173
163
  static void
174
164
  storeTriangulationTriplet(const int a, const int b, const int c)
175
165
  {
176
166
  VALUE trArray, triplet;
177
-
167
+
178
168
  // Create a new triplet from the three incoming points
179
169
  triplet = rb_ary_new2(3);
170
+
180
171
  rb_ary_push(triplet, INT2FIX(a));
181
172
  rb_ary_push(triplet, INT2FIX(b));
182
173
  rb_ary_push(triplet, INT2FIX(c));