ruby_clipper 5.0.3 → 6.2.1.5.2
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.
- checksums.yaml +4 -4
- data/README.md +20 -22
- data/ext/clipper/clipper.cpp +3018 -1882
- data/ext/clipper/clipper.hpp +246 -159
- data/ext/clipper/rbclipper.cpp +119 -58
- data/lib/clipper/version.rb +1 -1
- metadata +7 -6
data/ext/clipper/rbclipper.cpp
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
/*
|
1
|
+
/*
|
2
2
|
* Clipper Ruby Bindings
|
3
3
|
* Copyright 2010 Mike Owens <http://mike.filespanker.com/>
|
4
4
|
* Changed by Dag Rende for Clipper after 2.9
|
@@ -7,7 +7,7 @@
|
|
7
7
|
*
|
8
8
|
*/
|
9
9
|
|
10
|
-
#include
|
10
|
+
#include "clipper.hpp"
|
11
11
|
#include <ruby.h>
|
12
12
|
|
13
13
|
#ifndef DBL2NUM
|
@@ -26,6 +26,11 @@ static ID id_ex_polygons;
|
|
26
26
|
static ID id_jtSquare;
|
27
27
|
static ID id_jtMiter;
|
28
28
|
static ID id_jtRound;
|
29
|
+
static ID id_etClosedPolygon;
|
30
|
+
static ID id_etClosedLine;
|
31
|
+
static ID id_etOpenButt;
|
32
|
+
static ID id_etOpenSquare;
|
33
|
+
static ID id_etOpenRound;
|
29
34
|
|
30
35
|
static inline Clipper*
|
31
36
|
XCLIPPER(VALUE x)
|
@@ -35,6 +40,14 @@ XCLIPPER(VALUE x)
|
|
35
40
|
return clipper;
|
36
41
|
}
|
37
42
|
|
43
|
+
static inline ClipperOffset*
|
44
|
+
XCLIPPEROFFSET(VALUE x)
|
45
|
+
{
|
46
|
+
ClipperOffset* clipperOffset;
|
47
|
+
Data_Get_Struct(x, ClipperOffset, clipperOffset);
|
48
|
+
return clipperOffset;
|
49
|
+
}
|
50
|
+
|
38
51
|
static inline PolyFillType
|
39
52
|
sym_to_filltype(VALUE sym)
|
40
53
|
{
|
@@ -53,6 +66,26 @@ sym_to_filltype(VALUE sym)
|
|
53
66
|
rb_raise(rb_eArgError, "%s", "Expected :even_odd, :non_zero, :positive or :negative");
|
54
67
|
}
|
55
68
|
|
69
|
+
static inline EndType
|
70
|
+
sym_to_endtype(VALUE sym)
|
71
|
+
{
|
72
|
+
ID inp = rb_to_id(sym);
|
73
|
+
|
74
|
+
if (inp == id_etClosedPolygon) {
|
75
|
+
return etClosedPolygon;
|
76
|
+
} else if (inp == id_etClosedLine) {
|
77
|
+
return etClosedLine;
|
78
|
+
} else if (inp == id_etOpenButt) {
|
79
|
+
return etOpenButt;
|
80
|
+
} else if (inp == id_etOpenSquare) {
|
81
|
+
return etOpenSquare;
|
82
|
+
} else if (inp == id_etOpenRound) {
|
83
|
+
return etOpenRound;
|
84
|
+
}
|
85
|
+
|
86
|
+
rb_raise(rb_eArgError, "%s", "Expected :etClosedPolygon, :etClosedLine or :etOpenButt or :etOpenSquare or :etOpenRound");
|
87
|
+
}
|
88
|
+
|
56
89
|
static inline JoinType
|
57
90
|
sym_to_jointype(VALUE sym)
|
58
91
|
{
|
@@ -71,11 +104,16 @@ sym_to_jointype(VALUE sym)
|
|
71
104
|
|
72
105
|
extern "C" {
|
73
106
|
|
107
|
+
static inline IntPoint
|
108
|
+
xy_to_intpoint(VALUE px, VALUE py, double multiplier) {
|
109
|
+
return IntPoint((long64)(NUM2DBL(px) * multiplier), (long64)(NUM2DBL(py) * multiplier));
|
110
|
+
}
|
111
|
+
|
74
112
|
static void
|
75
|
-
ary_to_polygon(VALUE ary, ClipperLib::
|
113
|
+
ary_to_polygon(VALUE ary, ClipperLib::Path* poly, double multiplier)
|
76
114
|
{
|
77
115
|
const char* earg =
|
78
|
-
"
|
116
|
+
"Paths have format: [[p0_x, p0_y], [p1_x, p1_y], ...]";
|
79
117
|
|
80
118
|
Check_Type(ary, T_ARRAY);
|
81
119
|
|
@@ -99,6 +137,12 @@ rbclipper_free(void* ptr)
|
|
99
137
|
delete (Clipper*) ptr;
|
100
138
|
}
|
101
139
|
|
140
|
+
static void
|
141
|
+
rbclipperoffset_free(void* ptr)
|
142
|
+
{
|
143
|
+
delete (ClipperOffset*) ptr;
|
144
|
+
}
|
145
|
+
|
102
146
|
static VALUE
|
103
147
|
rbclipper_new(VALUE klass)
|
104
148
|
{
|
@@ -109,30 +153,40 @@ rbclipper_new(VALUE klass)
|
|
109
153
|
return r;
|
110
154
|
}
|
111
155
|
|
156
|
+
static VALUE
|
157
|
+
rbclipperoffset_new(VALUE klass)
|
158
|
+
{
|
159
|
+
ClipperOffset* ptr = new ClipperOffset;
|
160
|
+
VALUE r = Data_Wrap_Struct(klass, 0, rbclipperoffset_free, ptr);
|
161
|
+
rb_obj_call_init(r, 0, 0);
|
162
|
+
rb_iv_set(r, "@multiplier", INT2NUM(1048576));
|
163
|
+
return r;
|
164
|
+
}
|
165
|
+
|
112
166
|
static VALUE
|
113
167
|
rbclipper_add_polygon_internal(VALUE self, VALUE polygon,
|
114
168
|
PolyType polytype)
|
115
169
|
{
|
116
|
-
ClipperLib::
|
170
|
+
ClipperLib::Path tmp;
|
117
171
|
double multiplier = NUM2DBL(rb_iv_get(self, "@multiplier"));
|
118
172
|
ary_to_polygon(polygon, &tmp, multiplier);
|
119
|
-
XCLIPPER(self)->
|
173
|
+
XCLIPPER(self)->AddPath(tmp, polytype, true);
|
120
174
|
return Qnil;
|
121
175
|
}
|
122
176
|
|
123
177
|
static VALUE
|
124
178
|
rbclipper_add_polygons_internal(VALUE self, VALUE polygonsValue, PolyType polytype) {
|
125
179
|
double multiplier = NUM2DBL(rb_iv_get(self, "@multiplier"));
|
126
|
-
|
180
|
+
Paths polygons;
|
127
181
|
for(long i = 0; i != RARRAY_LEN(polygonsValue); i++) {
|
128
182
|
VALUE sub = rb_ary_entry(polygonsValue, i);
|
129
183
|
Check_Type(sub, T_ARRAY);
|
130
184
|
|
131
|
-
ClipperLib::
|
185
|
+
ClipperLib::Path tmp;
|
132
186
|
ary_to_polygon(sub, &tmp, multiplier);
|
133
187
|
polygons.push_back(tmp);
|
134
188
|
}
|
135
|
-
XCLIPPER(self)->
|
189
|
+
XCLIPPER(self)->AddPaths(polygons, polytype, true);
|
136
190
|
return Qnil;
|
137
191
|
}
|
138
192
|
|
@@ -167,6 +221,13 @@ rbclipper_clear(VALUE self)
|
|
167
221
|
return Qnil;
|
168
222
|
}
|
169
223
|
|
224
|
+
static VALUE
|
225
|
+
rbclipperoffset_clear(VALUE self)
|
226
|
+
{
|
227
|
+
XCLIPPEROFFSET(self)->Clear();
|
228
|
+
return Qnil;
|
229
|
+
}
|
230
|
+
|
170
231
|
static VALUE
|
171
232
|
rbclipper_multiplier(VALUE self)
|
172
233
|
{
|
@@ -184,10 +245,9 @@ static VALUE
|
|
184
245
|
rbclipper_orientation(VALUE self, VALUE polygonValue)
|
185
246
|
{
|
186
247
|
double multiplier = NUM2DBL(rb_iv_get(self, "@multiplier"));
|
187
|
-
ClipperLib::
|
248
|
+
ClipperLib::Path polygon;
|
188
249
|
ary_to_polygon(polygonValue, &polygon, multiplier);
|
189
250
|
|
190
|
-
Polygons resultPolygons;
|
191
251
|
return ClipperLib::Orientation(polygon) ? Qtrue : Qfalse;
|
192
252
|
}
|
193
253
|
|
@@ -195,44 +255,50 @@ static VALUE
|
|
195
255
|
rbclipper_area(VALUE self, VALUE polygonValue)
|
196
256
|
{
|
197
257
|
double multiplier = NUM2DBL(rb_iv_get(self, "@multiplier"));
|
198
|
-
ClipperLib::
|
258
|
+
ClipperLib::Path polygon;
|
199
259
|
ary_to_polygon(polygonValue, &polygon, multiplier);
|
200
260
|
|
201
|
-
Polygons resultPolygons;
|
202
261
|
return DBL2NUM(ClipperLib::Area(polygon) / multiplier / multiplier);
|
203
262
|
}
|
204
263
|
|
264
|
+
static VALUE
|
265
|
+
rbclipper_point_in_polygon(VALUE self, VALUE px, VALUE py, VALUE polygonValue)
|
266
|
+
{
|
267
|
+
double multiplier = NUM2DBL(rb_iv_get(self, "@multiplier"));
|
268
|
+
ClipperLib::Path polygon;
|
269
|
+
ary_to_polygon(polygonValue, &polygon, multiplier);
|
270
|
+
|
271
|
+
return abs(ClipperLib::PointInPolygon(xy_to_intpoint(px, py, multiplier), polygon)) == 1 ? Qtrue : Qfalse;
|
272
|
+
}
|
205
273
|
|
206
274
|
static VALUE
|
207
|
-
rbclipper_offset_polygons(int argc, VALUE* argv, VALUE self)
|
275
|
+
rbclipper_offset_polygons(int argc, VALUE* argv, VALUE self)
|
208
276
|
{
|
209
277
|
double multiplier = NUM2DBL(rb_iv_get(self, "@multiplier"));
|
210
278
|
double inv_multiplier = 1.0 / multiplier;
|
211
|
-
VALUE polygonsValue, deltaValue, joinTypeValue,
|
279
|
+
VALUE polygonsValue, deltaValue, joinTypeValue, endTypeValue;
|
212
280
|
|
213
|
-
rb_scan_args(argc, argv, "31", &polygonsValue, &deltaValue, &joinTypeValue, &
|
281
|
+
rb_scan_args(argc, argv, "31", &polygonsValue, &deltaValue, &joinTypeValue, &endTypeValue);
|
214
282
|
|
215
|
-
|
283
|
+
Paths polygons;
|
216
284
|
for(long i = 0; i != RARRAY_LEN(polygonsValue); i++) {
|
217
285
|
VALUE sub = rb_ary_entry(polygonsValue, i);
|
218
286
|
Check_Type(sub, T_ARRAY);
|
219
287
|
|
220
|
-
ClipperLib::
|
288
|
+
ClipperLib::Path tmp;
|
221
289
|
ary_to_polygon(sub, &tmp, multiplier);
|
222
290
|
polygons.push_back(tmp);
|
223
291
|
}
|
224
|
-
double miterLimit = 0;
|
225
|
-
if (!NIL_P(miterLimitValue)) {
|
226
|
-
miterLimit = NUM2DBL(miterLimitValue);
|
227
|
-
}
|
228
292
|
|
229
|
-
|
230
|
-
|
293
|
+
Paths resultPaths;
|
294
|
+
|
295
|
+
XCLIPPEROFFSET(self)->AddPaths(polygons, sym_to_jointype(joinTypeValue), sym_to_endtype(endTypeValue));
|
296
|
+
XCLIPPEROFFSET(self)->Execute(resultPaths, NUM2DBL(deltaValue) * multiplier);
|
231
297
|
|
232
298
|
VALUE r = rb_ary_new();
|
233
|
-
for(
|
299
|
+
for(Paths::iterator i = resultPaths.begin(); i != resultPaths.end(); ++i) {
|
234
300
|
VALUE sub = rb_ary_new();
|
235
|
-
for(
|
301
|
+
for(Path::iterator p = i->begin(); p != i->end(); ++p) {
|
236
302
|
rb_ary_push(sub, rb_ary_new3(2, DBL2NUM(p->X * inv_multiplier), DBL2NUM(p->Y * inv_multiplier)));
|
237
303
|
}
|
238
304
|
rb_ary_push(r, sub);
|
@@ -260,43 +326,18 @@ rbclipper_execute_internal(VALUE self, ClipType cliptype,
|
|
260
326
|
|
261
327
|
VALUE r = rb_ary_new();
|
262
328
|
if (resulttype == ID2SYM(id_polygons)) {
|
263
|
-
|
329
|
+
Paths solution;
|
264
330
|
XCLIPPER(self)->Execute((ClipType) cliptype,
|
265
331
|
solution,
|
266
332
|
sym_to_filltype(subjfill),
|
267
333
|
sym_to_filltype(clipfill));
|
268
|
-
for(
|
334
|
+
for(Paths::iterator i = solution.begin(); i != solution.end(); ++i) {
|
269
335
|
VALUE sub = rb_ary_new();
|
270
|
-
for(
|
336
|
+
for(Path::iterator p = i->begin(); p != i->end(); ++p) {
|
271
337
|
rb_ary_push(sub, rb_ary_new3(2, DBL2NUM(p->X * inv_multiplier), DBL2NUM(p->Y * inv_multiplier)));
|
272
338
|
}
|
273
339
|
rb_ary_push(r, sub);
|
274
340
|
}
|
275
|
-
} else {
|
276
|
-
ExPolygons solution;
|
277
|
-
XCLIPPER(self)->Execute((ClipType) cliptype,
|
278
|
-
solution,
|
279
|
-
sym_to_filltype(subjfill),
|
280
|
-
sym_to_filltype(clipfill));
|
281
|
-
for(ExPolygons::iterator i = solution.begin(); i != solution.end(); ++i) {
|
282
|
-
VALUE expolygon_arr = rb_ary_new();
|
283
|
-
|
284
|
-
VALUE outer_arr = rb_ary_new();
|
285
|
-
for(Polygon::iterator p = i->outer.begin(); p != i->outer.end(); ++p) {
|
286
|
-
rb_ary_push(outer_arr, rb_ary_new3(2, DBL2NUM(p->X * inv_multiplier), DBL2NUM(p->Y * inv_multiplier)));
|
287
|
-
}
|
288
|
-
rb_ary_push(expolygon_arr, outer_arr);
|
289
|
-
|
290
|
-
for(Polygons::iterator ps = i->holes.begin(); ps != i->holes.end(); ++ps) {
|
291
|
-
VALUE hole_arr = rb_ary_new();
|
292
|
-
for(Polygon::iterator p = ps->begin(); p != ps->end(); ++p) {
|
293
|
-
rb_ary_push(hole_arr, rb_ary_new3(2, DBL2NUM(p->X * inv_multiplier), DBL2NUM(p->Y * inv_multiplier)));
|
294
|
-
}
|
295
|
-
rb_ary_push(expolygon_arr, hole_arr);
|
296
|
-
}
|
297
|
-
|
298
|
-
rb_ary_push(r, expolygon_arr);
|
299
|
-
}
|
300
341
|
}
|
301
342
|
return r;
|
302
343
|
}
|
@@ -335,10 +376,10 @@ rbclipper_xor(int argc, VALUE* argv, VALUE self)
|
|
335
376
|
return rbclipper_execute_internal(self, ctXor, subjfill, clipfill, resulttype);
|
336
377
|
}
|
337
378
|
|
338
|
-
|
339
379
|
typedef VALUE (*ruby_method)(...);
|
340
380
|
|
341
381
|
void Init_clipper() {
|
382
|
+
|
342
383
|
id_even_odd = rb_intern("even_odd");
|
343
384
|
id_non_zero = rb_intern("non_zero");
|
344
385
|
id_positive = rb_intern("positive");
|
@@ -348,6 +389,11 @@ void Init_clipper() {
|
|
348
389
|
id_jtSquare = rb_intern("jtSquare");
|
349
390
|
id_jtMiter = rb_intern("jtMiter");
|
350
391
|
id_jtRound = rb_intern("jtRound");
|
392
|
+
id_etClosedPolygon = rb_intern("etClosedPolygon");
|
393
|
+
id_etClosedLine = rb_intern("etClosedLine");
|
394
|
+
id_etOpenButt = rb_intern("etOpenButt");
|
395
|
+
id_etOpenSquare = rb_intern("etOpenSquare");
|
396
|
+
id_etOpenRound = rb_intern("etOpenRound");
|
351
397
|
|
352
398
|
VALUE mod = rb_define_module("Clipper");
|
353
399
|
|
@@ -357,10 +403,12 @@ void Init_clipper() {
|
|
357
403
|
|
358
404
|
rb_define_method(k, "orientation",
|
359
405
|
(ruby_method) rbclipper_orientation, 1);
|
406
|
+
rb_define_method(k, "pt_in_polygon",
|
407
|
+
(ruby_method) rbclipper_point_in_polygon, 3);
|
360
408
|
rb_define_method(k, "area",
|
361
409
|
(ruby_method) rbclipper_area, 1);
|
362
|
-
rb_define_method(k, "offset_polygons",
|
363
|
-
|
410
|
+
// rb_define_method(k, "offset_polygons",
|
411
|
+
// (ruby_method) rbclipper_offset_polygons, -1);
|
364
412
|
rb_define_method(k, "add_subject_polygon",
|
365
413
|
(ruby_method) rbclipper_add_subject_polygon, 1);
|
366
414
|
rb_define_method(k, "add_clip_polygon",
|
@@ -384,6 +432,19 @@ void Init_clipper() {
|
|
384
432
|
(ruby_method) rbclipper_multiplier, 0);
|
385
433
|
rb_define_method(k, "multiplier=",
|
386
434
|
(ruby_method) rbclipper_multiplier_eq, 1);
|
387
|
-
|
435
|
+
|
436
|
+
VALUE ko = rb_define_class_under(mod, "ClipperOffset", rb_cObject);
|
437
|
+
rb_define_singleton_method(ko, "new",
|
438
|
+
(ruby_method) rbclipperoffset_new, 0);
|
439
|
+
rb_define_method(ko, "offset_polygons",
|
440
|
+
(ruby_method) rbclipper_offset_polygons, -1);
|
441
|
+
rb_define_method(ko, "clear!",
|
442
|
+
(ruby_method) rbclipperoffset_clear, 0);
|
443
|
+
|
444
|
+
rb_define_method(ko, "multiplier",
|
445
|
+
(ruby_method) rbclipper_multiplier, 0);
|
446
|
+
rb_define_method(ko, "multiplier=",
|
447
|
+
(ruby_method) rbclipper_multiplier_eq, 1);
|
448
|
+
}
|
388
449
|
|
389
450
|
} /* extern "C" */
|
data/lib/clipper/version.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ruby_clipper
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 5.
|
4
|
+
version: 6.2.1.5.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Angus Johnson
|
@@ -12,22 +12,22 @@ authors:
|
|
12
12
|
autorequire:
|
13
13
|
bindir: bin
|
14
14
|
cert_chain: []
|
15
|
-
date: 2015-
|
15
|
+
date: 2015-12-27 00:00:00.000000000 Z
|
16
16
|
dependencies:
|
17
17
|
- !ruby/object:Gem::Dependency
|
18
18
|
name: bundler
|
19
19
|
requirement: !ruby/object:Gem::Requirement
|
20
20
|
requirements:
|
21
|
-
- - "
|
21
|
+
- - ">="
|
22
22
|
- !ruby/object:Gem::Version
|
23
|
-
version:
|
23
|
+
version: 1.0.0
|
24
24
|
type: :development
|
25
25
|
prerelease: false
|
26
26
|
version_requirements: !ruby/object:Gem::Requirement
|
27
27
|
requirements:
|
28
|
-
- - "
|
28
|
+
- - ">="
|
29
29
|
- !ruby/object:Gem::Version
|
30
|
-
version:
|
30
|
+
version: 1.0.0
|
31
31
|
description: Builds a native ruby extension for Clipper
|
32
32
|
email:
|
33
33
|
- simon@sfcgeorge.co.uk
|
@@ -76,3 +76,4 @@ signing_key:
|
|
76
76
|
specification_version: 4
|
77
77
|
summary: Ruby wrapper for Clipper, Angus Johnson's excellent polygon clipping library
|
78
78
|
test_files: []
|
79
|
+
has_rdoc:
|