rbpoly2tri 0.0.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.
- data/ext/poly2tri/common/shapes.cc +334 -0
- data/ext/poly2tri/common/shapes.h +320 -0
- data/ext/poly2tri/common/utils.h +102 -0
- data/ext/poly2tri/poly2tri.h +39 -0
- data/ext/poly2tri/sweep/advancing_front.cc +108 -0
- data/ext/poly2tri/sweep/advancing_front.h +119 -0
- data/ext/poly2tri/sweep/cdt.cc +72 -0
- data/ext/poly2tri/sweep/cdt.h +69 -0
- data/ext/poly2tri/sweep/sweep.cc +820 -0
- data/ext/poly2tri/sweep/sweep.h +126 -0
- data/ext/poly2tri/sweep/sweep_context.cc +201 -0
- data/ext/poly2tri/sweep/sweep_context.h +185 -0
- data/ext/rbpoly2tri/extconf.rb +16 -0
- data/ext/rbpoly2tri/rbpoly2tri.cc +198 -0
- data/ext/throw_assert/assert.h +19 -0
- data/lib/rbpoly2tri.rb +1 -0
- metadata +62 -0
@@ -0,0 +1,16 @@
|
|
1
|
+
require 'mkmf'
|
2
|
+
|
3
|
+
abs_root = File.expand_path(File.dirname(__FILE__))
|
4
|
+
|
5
|
+
$defs.push "-DNDEBUG -I#{abs_root}/throw_assert -isystem #{abs_root}/throw_assert"
|
6
|
+
|
7
|
+
# Collect all the poly2tri sources
|
8
|
+
$srcs = %w(rbpoly2tri.cc)
|
9
|
+
$srcs += Dir["../poly2tri/common/*.cc"]
|
10
|
+
$srcs += Dir["../poly2tri/sweep/*.cc"]
|
11
|
+
|
12
|
+
$objs = $srcs.map{|src| src.gsub(/\.cc$/, '.o')}
|
13
|
+
|
14
|
+
$cleanfiles = $objs
|
15
|
+
|
16
|
+
create_makefile('rbpoly2tri/rbpoly2tri')
|
@@ -0,0 +1,198 @@
|
|
1
|
+
#include "../poly2tri/poly2tri.h"
|
2
|
+
#include <ruby.h>
|
3
|
+
|
4
|
+
using namespace p2t;
|
5
|
+
|
6
|
+
extern "C" {
|
7
|
+
|
8
|
+
/* Converts a ruby [x,y] to a Point */
|
9
|
+
static Point
|
10
|
+
value_to_point(VALUE ptval)
|
11
|
+
{
|
12
|
+
Check_Type(ptval, T_ARRAY);
|
13
|
+
if (RARRAY_LEN(ptval) != 2) {
|
14
|
+
rb_raise(rb_eArgError, "%s", "Points are in format [x,y]");
|
15
|
+
}
|
16
|
+
return Point(NUM2DBL(rb_ary_entry(ptval, 0)),
|
17
|
+
NUM2DBL(rb_ary_entry(ptval, 1)));
|
18
|
+
}
|
19
|
+
|
20
|
+
/* converts ruby point-arrays to vector<Point*> and return it.
|
21
|
+
* if mem_track is given, each item returned is also appended
|
22
|
+
* to it. This allows the big-sweep delete finish. */
|
23
|
+
static std::vector<Point*>
|
24
|
+
ptary_to_vector(VALUE ary,
|
25
|
+
std::vector<Point*> *mem_track = 0)
|
26
|
+
{
|
27
|
+
/* We don't want to leave v in an inconsistent state if we
|
28
|
+
find an error half-way through ary, so we copy to tmp,
|
29
|
+
and then push into v if everything worked. */
|
30
|
+
std::vector<Point> tmp;
|
31
|
+
|
32
|
+
Check_Type(ary, T_ARRAY);
|
33
|
+
for (long i = 0; i != RARRAY_LEN(ary); i++) {
|
34
|
+
VALUE item = rb_ary_entry(ary, i);
|
35
|
+
tmp.push_back(value_to_point(item));
|
36
|
+
}
|
37
|
+
|
38
|
+
std::vector<Point*> result;
|
39
|
+
for (size_t i = 0; i != tmp.size(); i++) {
|
40
|
+
/* sigh, copy-ctor */
|
41
|
+
Point* heaped = new Point(tmp[i].x, tmp[i].y);
|
42
|
+
result.push_back(heaped);
|
43
|
+
if (mem_track) {
|
44
|
+
mem_track->push_back(heaped);
|
45
|
+
}
|
46
|
+
}
|
47
|
+
return result;
|
48
|
+
}
|
49
|
+
|
50
|
+
/* Uh, for some reason, we own the points given to Poly2tri */
|
51
|
+
typedef struct {
|
52
|
+
CDT *cdt;
|
53
|
+
std::vector<Point*> mem_track;
|
54
|
+
} CDTWrap;
|
55
|
+
|
56
|
+
/* Return the underlying CDTWrap* of a value, type safe */
|
57
|
+
static inline CDTWrap*
|
58
|
+
XWRAP(VALUE x)
|
59
|
+
{
|
60
|
+
CDTWrap *result;
|
61
|
+
Data_Get_Struct(x, CDTWrap, result);
|
62
|
+
return result;
|
63
|
+
}
|
64
|
+
|
65
|
+
|
66
|
+
static void
|
67
|
+
rb_cdt_free(void* ptr)
|
68
|
+
{
|
69
|
+
CDTWrap *wrap = (CDTWrap*)(ptr);
|
70
|
+
if (wrap->cdt) {
|
71
|
+
delete wrap->cdt;
|
72
|
+
wrap->cdt = 0;
|
73
|
+
}
|
74
|
+
|
75
|
+
/* every point given to the cdt should've ended up here */
|
76
|
+
for (size_t i = 0; i != wrap->mem_track.size(); ++i) {
|
77
|
+
delete wrap->mem_track[i];
|
78
|
+
}
|
79
|
+
}
|
80
|
+
|
81
|
+
static VALUE
|
82
|
+
rb_cdt_new(VALUE klass, VALUE polyline)
|
83
|
+
{
|
84
|
+
CDTWrap* ptr = new CDTWrap;
|
85
|
+
ptr->cdt = 0;
|
86
|
+
|
87
|
+
VALUE r = Data_Wrap_Struct(klass, 0, rb_cdt_free, ptr);
|
88
|
+
rb_obj_call_init(r, 1, &polyline);
|
89
|
+
return r;
|
90
|
+
}
|
91
|
+
|
92
|
+
static VALUE
|
93
|
+
rb_cdt_initialize(VALUE self, VALUE polyline)
|
94
|
+
{
|
95
|
+
CDTWrap *ptr = XWRAP(self);
|
96
|
+
|
97
|
+
if (! ptr->cdt) {
|
98
|
+
ptr->cdt = new CDT(ptary_to_vector(polyline, &ptr->mem_track));
|
99
|
+
}
|
100
|
+
|
101
|
+
return Qnil;
|
102
|
+
}
|
103
|
+
|
104
|
+
static VALUE
|
105
|
+
rb_cdt_add_hole(VALUE self, VALUE polyline)
|
106
|
+
{
|
107
|
+
CDTWrap *ptr = XWRAP(self);
|
108
|
+
ptr->cdt->AddHole(ptary_to_vector(polyline, &ptr->mem_track));
|
109
|
+
return Qnil;
|
110
|
+
}
|
111
|
+
|
112
|
+
static VALUE
|
113
|
+
rb_cdt_add_point(VALUE self, VALUE rp)
|
114
|
+
{
|
115
|
+
/* Make sure it can be constructed from the ruby value before we go
|
116
|
+
* off allocating memory */
|
117
|
+
Point p = value_to_point(rp);
|
118
|
+
Point* heaped = new Point(p);
|
119
|
+
|
120
|
+
/* Add it, and log so it can be free'd */
|
121
|
+
CDTWrap* ptr = XWRAP(self);
|
122
|
+
ptr->mem_track.push_back(heaped);
|
123
|
+
ptr->cdt->AddPoint(heaped);
|
124
|
+
|
125
|
+
return Qnil;
|
126
|
+
}
|
127
|
+
|
128
|
+
static VALUE
|
129
|
+
rb_cdt_triangulate(VALUE self)
|
130
|
+
{
|
131
|
+
CDTWrap *ptr = XWRAP(self);
|
132
|
+
|
133
|
+
/* I have never closely considered what would happen to the stack if I were
|
134
|
+
* to rb_raise (longjmp) while the C++ stack is unwinding. I'd prefer to
|
135
|
+
* keep that a mystery.
|
136
|
+
*/
|
137
|
+
|
138
|
+
bool err = false;
|
139
|
+
|
140
|
+
try {
|
141
|
+
ptr->cdt->Triangulate();
|
142
|
+
} catch (...) {
|
143
|
+
err = true;
|
144
|
+
}
|
145
|
+
|
146
|
+
if (err) {
|
147
|
+
rb_raise(rb_eRuntimeError, "Couldnt triangulate (duplicate vertices?)");
|
148
|
+
}
|
149
|
+
|
150
|
+
return Qnil;
|
151
|
+
}
|
152
|
+
|
153
|
+
static VALUE
|
154
|
+
rb_cdt_get_triangles(VALUE self)
|
155
|
+
{
|
156
|
+
CDTWrap *ptr = XWRAP(self);
|
157
|
+
CDT *cdt = ptr->cdt;
|
158
|
+
|
159
|
+
/* Notice I patched this in poly2tri to return a const-ref,
|
160
|
+
* as this is a totally needless copy */
|
161
|
+
const std::vector<Triangle*>& tris = cdt->GetTriangles();
|
162
|
+
|
163
|
+
/* Result is a list of polys... */
|
164
|
+
VALUE result = rb_ary_new();
|
165
|
+
for(size_t i = 0; i != tris.size(); i++) {
|
166
|
+
Triangle* tri = tris[i];
|
167
|
+
/* rb_tri is the current triangle... */
|
168
|
+
VALUE rb_tri = rb_ary_new2(3);
|
169
|
+
for(size_t ptidx = 0; ptidx != 3; ptidx++) {
|
170
|
+
Point *pt = tri->GetPoint(ptidx);
|
171
|
+
/* And we push each point as an [x,y] coordinate */
|
172
|
+
rb_ary_push(rb_tri, rb_ary_new3(2, DBL2NUM(pt->x), DBL2NUM(pt->y)));
|
173
|
+
}
|
174
|
+
|
175
|
+
rb_ary_push(result, rb_tri);
|
176
|
+
}
|
177
|
+
|
178
|
+
return result;
|
179
|
+
}
|
180
|
+
|
181
|
+
typedef VALUE(*rubymethod)(...);
|
182
|
+
|
183
|
+
void Init_rbpoly2tri()
|
184
|
+
{
|
185
|
+
VALUE m = rb_define_module("Poly2Tri");
|
186
|
+
|
187
|
+
VALUE k = rb_define_class_under(m, "CDT", rb_cObject);
|
188
|
+
rb_define_singleton_method(k, "new", (rubymethod) rb_cdt_new, 1);
|
189
|
+
rb_define_method(k, "initialize", (rubymethod) rb_cdt_initialize, 1);
|
190
|
+
rb_define_method(k, "add_hole", (rubymethod) rb_cdt_add_hole, 1);
|
191
|
+
rb_define_method(k, "add_point", (rubymethod) rb_cdt_add_point, 1);
|
192
|
+
rb_define_method(k, "triangulate!", (rubymethod) rb_cdt_triangulate, 0);
|
193
|
+
rb_define_method(k, "triangles", (rubymethod) rb_cdt_get_triangles, 0);
|
194
|
+
// rb_define_method(k, "map", (rubymethod) rb_cdt_get_map, 0);
|
195
|
+
|
196
|
+
}
|
197
|
+
|
198
|
+
} /* extern "C" */
|
@@ -0,0 +1,19 @@
|
|
1
|
+
/*
|
2
|
+
* poly2tri handles input errors with assert(). Some CPP trickery
|
3
|
+
* (extconf.rb) puts this directory ahead of the system directories, so
|
4
|
+
* we can intercept <assert.h> and <cassert> and give this definition,
|
5
|
+
* which throws.
|
6
|
+
*
|
7
|
+
* Note, since poly2tri expects the program to terminate on a bad
|
8
|
+
* assert(), I wouldn't be surprised to learn if it leaves resources
|
9
|
+
* dangling in certain code paths.
|
10
|
+
*
|
11
|
+
*/
|
12
|
+
|
13
|
+
#undef assert
|
14
|
+
inline void assert(bool x) {
|
15
|
+
if (! x) {
|
16
|
+
throw false;
|
17
|
+
}
|
18
|
+
}
|
19
|
+
|
data/lib/rbpoly2tri.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require 'rbpoly2tri/rbpoly2tri'
|
metadata
ADDED
@@ -0,0 +1,62 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: rbpoly2tri
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Mike Owens
|
9
|
+
- Dimitri Roche
|
10
|
+
autorequire:
|
11
|
+
bindir: bin
|
12
|
+
cert_chain: []
|
13
|
+
date: 2012-11-15 00:00:00.000000000 Z
|
14
|
+
dependencies: []
|
15
|
+
description: ! 'Ruby Bindings to poly2tri: Constrained Delaunay Triangulation'
|
16
|
+
email: dimroc@gmail.com
|
17
|
+
executables: []
|
18
|
+
extensions:
|
19
|
+
- ext/rbpoly2tri/extconf.rb
|
20
|
+
extra_rdoc_files: []
|
21
|
+
files:
|
22
|
+
- lib/rbpoly2tri.rb
|
23
|
+
- ext/poly2tri/common/shapes.cc
|
24
|
+
- ext/poly2tri/sweep/advancing_front.cc
|
25
|
+
- ext/poly2tri/sweep/cdt.cc
|
26
|
+
- ext/poly2tri/sweep/sweep.cc
|
27
|
+
- ext/poly2tri/sweep/sweep_context.cc
|
28
|
+
- ext/rbpoly2tri/rbpoly2tri.cc
|
29
|
+
- ext/poly2tri/common/shapes.h
|
30
|
+
- ext/poly2tri/common/utils.h
|
31
|
+
- ext/poly2tri/poly2tri.h
|
32
|
+
- ext/poly2tri/sweep/advancing_front.h
|
33
|
+
- ext/poly2tri/sweep/cdt.h
|
34
|
+
- ext/poly2tri/sweep/sweep.h
|
35
|
+
- ext/poly2tri/sweep/sweep_context.h
|
36
|
+
- ext/throw_assert/assert.h
|
37
|
+
- ext/rbpoly2tri/extconf.rb
|
38
|
+
homepage: https://github.com/dimroc/rbpoly2tri
|
39
|
+
licenses: []
|
40
|
+
post_install_message:
|
41
|
+
rdoc_options: []
|
42
|
+
require_paths:
|
43
|
+
- lib
|
44
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
45
|
+
none: false
|
46
|
+
requirements:
|
47
|
+
- - ! '>='
|
48
|
+
- !ruby/object:Gem::Version
|
49
|
+
version: '0'
|
50
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
51
|
+
none: false
|
52
|
+
requirements:
|
53
|
+
- - ! '>='
|
54
|
+
- !ruby/object:Gem::Version
|
55
|
+
version: '0'
|
56
|
+
requirements: []
|
57
|
+
rubyforge_project:
|
58
|
+
rubygems_version: 1.8.24
|
59
|
+
signing_key:
|
60
|
+
specification_version: 3
|
61
|
+
summary: Ruby Bindings to poly2tri
|
62
|
+
test_files: []
|