rubyvor 0.1.3

Sign up to get free protection for your applications and to get access to all the features.
@@ -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 (CLASS_OF(a) == rb_path2class("RubyVor::PriorityQueue::QueueItem"))
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_obj_classname(rb_path2class("RubyVor::PriorityQueue::QueueItem")));
21
+
22
+ if (CLASS_OF(a) == rb_path2class("RubyVor::PriorityQueue::QueueItem"))
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(a), rb_obj_classname(rb_path2class("RubyVor::PriorityQueue::QueueItem")));
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 %li out of range", i-1);
46
+
47
+ j = i / 2;
48
+
49
+ item = RARRAY_PTR(data)[i - 1];
50
+
51
+ while(j > 0 && compare(item, RARRAY_PTR(data)[j - 1]))
52
+ {
53
+ rb_ary_store(data, i-1, RARRAY_PTR(data)[j - 1]);
54
+ rb_funcall(RARRAY_PTR(data)[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_PTR(data)[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 %li out of range", i-1);
82
+
83
+ j = size / 2;
84
+
85
+ item = RARRAY_PTR(data)[i - 1];
86
+
87
+ while (!(i > j))
88
+ {
89
+ k = i * 2;
90
+ if (k < size && compare(RARRAY_PTR(data)[k], RARRAY_PTR(data)[k - 1]))
91
+ k++;
92
+
93
+ if (compare(item, RARRAY_PTR(data)[k - 1]))
94
+ j = -1;
95
+ else
96
+ {
97
+ rb_ary_store(data, i-1, RARRAY_PTR(data)[k - 1]);
98
+ rb_funcall(RARRAY_PTR(data)[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_PTR(data)[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,115 @@
1
+ #include <ruby.h>
2
+ #include <vdefs.h>
3
+ #include <ruby_vor_c.h>
4
+
5
+ /* Classes & Modules */
6
+ static VALUE RubyVor_rb_mRubyVor;
7
+ static VALUE RubyVor_rb_mVDDT;
8
+
9
+ static VALUE RubyVor_rb_cComputation;
10
+ static VALUE RubyVor_rb_cPriorityQueue;
11
+ static VALUE RubyVor_rb_cQueueItem;
12
+ static VALUE RubyVor_rb_cPoint;
13
+
14
+ /*
15
+ * Extension initialization
16
+ */
17
+ void
18
+ Init_ruby_vor_c(void)
19
+ {
20
+ /*
21
+ * Set up our Modules and Class.
22
+ */
23
+
24
+ /*
25
+ * Main RubyVor namespace.
26
+ */
27
+ RubyVor_rb_mRubyVor = rb_define_module("RubyVor");
28
+
29
+
30
+ /*
31
+ * Voronoi Digram and Delaunay Triangulation namespace.
32
+ */
33
+ RubyVor_rb_mVDDT = rb_define_module_under(RubyVor_rb_mRubyVor, "VDDT");
34
+
35
+
36
+ /*
37
+ * Class representing a VD/DT computation based on a set of 2-dimensional points
38
+ */
39
+ RubyVor_rb_cComputation = rb_define_class_under(RubyVor_rb_mVDDT, "Computation", rb_cObject);
40
+ rb_define_singleton_method(RubyVor_rb_cComputation, "from_points", RubyVor_from_points, 1);
41
+ rb_define_method(RubyVor_rb_cComputation, "nn_graph", RubyVor_nn_graph, 0);
42
+ rb_define_method(RubyVor_rb_cComputation, "minimum_spanning_tree", RubyVor_minimum_spanning_tree, -1);
43
+
44
+
45
+ /*
46
+ * A priority queue with a customizable heap-order property.
47
+ */
48
+ RubyVor_rb_cPriorityQueue = rb_define_class_under(RubyVor_rb_mRubyVor, "PriorityQueue", rb_cObject);
49
+ RubyVor_rb_cQueueItem = rb_define_class_under(RubyVor_rb_cPriorityQueue, "QueueItem", rb_cObject);
50
+ rb_define_method(RubyVor_rb_cPriorityQueue, "percolate_up", RubyVor_percolate_up, 1);
51
+ rb_define_method(RubyVor_rb_cPriorityQueue, "percolate_down", RubyVor_percolate_down, 1);
52
+ rb_define_method(RubyVor_rb_cPriorityQueue, "heapify", RubyVor_heapify, 0);
53
+
54
+
55
+ /*
56
+ * A simple Point class
57
+ */
58
+ RubyVor_rb_cPoint = rb_define_class_under(RubyVor_rb_mRubyVor, "Point", rb_cObject);
59
+ rb_define_method(RubyVor_rb_cPoint, "distance_from", RubyVor_distance_from, 1);
60
+ rb_define_method(RubyVor_rb_cPoint, "hash", RubyVor_point_hash, 0);
61
+ }
62
+
63
+
64
+
65
+
66
+ /*
67
+ * Method declarations duplicated here for RDOC
68
+ */
69
+
70
+ /*
71
+ * Compute the voronoi diagram and delaunay triangulation from a set of points.
72
+ *
73
+ * This implementation uses Steven Fortune's sweepline algorithm, which runs in O(n log n) time and O(n) space.
74
+ * It is limited to 2-dimensional space, therefore it expects to receive an array of objects that respond to 'x' and 'y' methods.
75
+ */
76
+ VALUE RubyVor_from_points(VALUE, VALUE);
77
+
78
+ /*
79
+ * Compute the nearest-neighbor graph using the existing Delaunay triangulation.
80
+ */
81
+ VALUE RubyVor_nn_graph(VALUE);
82
+
83
+ /*
84
+ * Computes the minimum spanning tree for given points, using the Delaunay triangulation as a seed.
85
+ *
86
+ * 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.
87
+ */
88
+ VALUE RubyVor_minimum_spanning_tree(int, VALUE*, VALUE);
89
+
90
+ /*
91
+ * Move from the given index up, restoring the heap-order property.
92
+ */
93
+ VALUE RubyVor_percolate_up(VALUE, VALUE);
94
+
95
+ /*
96
+ * Move from the index down, restoring the heap-order property.
97
+ */
98
+ VALUE RubyVor_percolate_down(VALUE, VALUE);
99
+
100
+ /*
101
+ * Restore the heap-order property for a randomly ordered array of entries.
102
+ */
103
+ VALUE RubyVor_heapify(VALUE);
104
+
105
+ /*
106
+ * Compute the Euclidean distance between two points.
107
+ */
108
+ VALUE RubyVor_distance_from(VALUE, VALUE);
109
+
110
+ /*
111
+ * Hash value for a point.
112
+ */
113
+ VALUE RubyVor_point_hash(VALUE);
114
+
115
+ /* keep comment so RDOC will find the last method definition */
@@ -0,0 +1,40 @@
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
+ #ifndef RUBY_19
13
+ #ifndef RFLOAT_VALUE
14
+ #define RFLOAT_VALUE(v) (RFLOAT(v)->value)
15
+ #endif
16
+ #ifndef RARRAY_LEN
17
+ #define RARRAY_LEN(v) (RARRAY(v)->len)
18
+ #endif
19
+ #ifndef RARRAY_PTR
20
+ #define RARRAY_PTR(v) (RARRAY(v)->ptr)
21
+ #endif
22
+ #endif
23
+
24
+ extern VoronoiState rubyvorState;
25
+
26
+ /* Computation */
27
+ VALUE RubyVor_from_points(VALUE, VALUE);
28
+ VALUE RubyVor_nn_graph(VALUE);
29
+ VALUE RubyVor_minimum_spanning_tree(int, VALUE*, VALUE);
30
+
31
+ /* PriorityQueue */
32
+ VALUE RubyVor_percolate_up(VALUE, VALUE);
33
+ VALUE RubyVor_percolate_down(VALUE, VALUE);
34
+ VALUE RubyVor_heapify(VALUE);
35
+
36
+ /* Point */
37
+ VALUE RubyVor_distance_from(VALUE, VALUE);
38
+ VALUE RubyVor_point_hash(VALUE);
39
+
40
+ #endif
@@ -0,0 +1,150 @@
1
+ #ifndef __VDEFS_H
2
+ #define __VDEFS_H
3
+
4
+ #ifndef NULL
5
+ #define NULL 0
6
+ #endif
7
+
8
+ #define DELETED -2
9
+
10
+ typedef struct tagFreenode
11
+ {
12
+ struct tagFreenode * nextfree;
13
+ } Freenode ;
14
+
15
+
16
+ typedef struct tagFreelist
17
+ {
18
+ Freenode * head;
19
+ int nodesize;
20
+ } Freelist ;
21
+
22
+ typedef struct tagPoint
23
+ {
24
+ float x ;
25
+ float y ;
26
+ } Point ;
27
+
28
+ /* structure used both for sites and for vertices */
29
+
30
+ typedef struct tagSite
31
+ {
32
+ Point coord ;
33
+ int sitenbr ;
34
+ int refcnt ;
35
+ } Site ;
36
+
37
+
38
+ typedef struct tagEdge
39
+ {
40
+ float a, b, c ;
41
+ Site * ep[2] ;
42
+ Site * reg[2] ;
43
+ int edgenbr ;
44
+ } Edge ;
45
+
46
+ #define le 0
47
+ #define re 1
48
+
49
+ typedef struct tagHalfedge
50
+ {
51
+ struct tagHalfedge * ELleft ;
52
+ struct tagHalfedge * ELright ;
53
+ Edge * ELedge ;
54
+ int ELrefcnt ;
55
+ char ELpm ;
56
+ Site * vertex ;
57
+ float ystar ;
58
+ struct tagHalfedge * PQnext ;
59
+ } Halfedge ;
60
+
61
+ typedef struct tagVoronoiState
62
+ {
63
+ /* voronoi.c */
64
+ int sorted, plot, debug, siteidx;
65
+ float xmin, xmax, ymin, ymax;
66
+ Site * sites;
67
+ void * comp;
68
+ void (* storeT)(int, int, int);
69
+ void (* storeL)(float, float, float);
70
+ void (* storeE)(int, int, int);
71
+ void (* storeV)(float, float);
72
+ void (* storeS)(float, float);
73
+
74
+ /* geometry.c */
75
+ float deltax, deltay;
76
+ int nsites, nedges, sqrt_nsites, nvertices;
77
+ Freelist sfl;
78
+
79
+ /* edgelist.c */
80
+ int ELhashsize;
81
+ Site * bottomsite;
82
+ } VoronoiState;
83
+
84
+ extern VoronoiState rubyvorState;
85
+
86
+ /* edgelist.c */
87
+ void ELinitialize(void) ;
88
+ Halfedge * HEcreate(Edge *, int) ;
89
+ void ELinsert(Halfedge *, Halfedge *) ;
90
+ Halfedge * ELgethash(int) ;
91
+ Halfedge * ELleftbnd(Point *) ;
92
+ void ELdelete(Halfedge *) ;
93
+ Halfedge * ELright(Halfedge *) ;
94
+ Halfedge * ELleft(Halfedge *) ;
95
+ Site * leftreg(Halfedge *) ;
96
+ Site * rightreg(Halfedge *) ;
97
+ Halfedge * getELleftend(void) ;
98
+ Halfedge * getELrightend(void) ;
99
+
100
+ /* geometry.c */
101
+ void geominit(void) ;
102
+ Edge * bisect(Site *, Site *) ;
103
+ Site * intersect(Halfedge *, Halfedge *) ;
104
+ int right_of(Halfedge *, Point *) ;
105
+ void endpoint(Edge *, int, Site *) ;
106
+ float dist(Site *, Site *) ;
107
+ void makevertex(Site *) ;
108
+ void deref(Site *) ;
109
+ void ref(Site *) ;
110
+
111
+ /* heap.c */
112
+ void PQinsert(Halfedge *, Site *, float) ;
113
+ void PQdelete(Halfedge *) ;
114
+ int PQbucket(Halfedge *) ;
115
+ int PQempty(void) ;
116
+ Point PQ_min(void) ;
117
+ Halfedge * PQextractmin(void) ;
118
+ void PQinitialize(void) ;
119
+
120
+ /* getopt.c */
121
+ extern int getopt(int, char *const *, const char *);
122
+
123
+ /* memory.c */
124
+ void freeinit(Freelist *, int) ;
125
+ char *getfree(Freelist *) ;
126
+ void makefree(Freenode *, Freelist *) ;
127
+ char *myalloc(unsigned) ;
128
+ char *myrealloc(void *, unsigned, unsigned);
129
+ void free_all(void);
130
+
131
+ /* output.c */
132
+ void openpl(void) ;
133
+ void line(float, float, float, float) ;
134
+ void circle(float, float, float) ;
135
+ void range(float, float, float, float) ;
136
+ void out_bisector(Edge *) ;
137
+ void out_ep(Edge *) ;
138
+ void out_vertex(Site *) ;
139
+ void out_site(Site *) ;
140
+ void out_triple(Site *, Site *, Site *) ;
141
+ void plotinit(void) ;
142
+ void clip_line(Edge *) ;
143
+ void debug_memory(void);
144
+
145
+ /* voronoi.c */
146
+ void voronoi(Site *(*)()) ;
147
+ void initialize_state(int);
148
+ #endif
149
+
150
+