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.
@@ -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 <clipper.hpp>
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::Polygon* poly, double multiplier)
113
+ ary_to_polygon(VALUE ary, ClipperLib::Path* poly, double multiplier)
76
114
  {
77
115
  const char* earg =
78
- "Polygons have format: [[p0_x, p0_y], [p1_x, p1_y], ...]";
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::Polygon tmp;
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)->AddPolygon(tmp, polytype);
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
- Polygons polygons;
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::Polygon tmp;
185
+ ClipperLib::Path tmp;
132
186
  ary_to_polygon(sub, &tmp, multiplier);
133
187
  polygons.push_back(tmp);
134
188
  }
135
- XCLIPPER(self)->AddPolygons(polygons, polytype);
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::Polygon polygon;
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::Polygon polygon;
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, miterLimitValue;
279
+ VALUE polygonsValue, deltaValue, joinTypeValue, endTypeValue;
212
280
 
213
- rb_scan_args(argc, argv, "31", &polygonsValue, &deltaValue, &joinTypeValue, &miterLimitValue);
281
+ rb_scan_args(argc, argv, "31", &polygonsValue, &deltaValue, &joinTypeValue, &endTypeValue);
214
282
 
215
- Polygons polygons;
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::Polygon tmp;
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
- Polygons resultPolygons;
230
- ClipperLib::OffsetPolygons(polygons, resultPolygons, NUM2DBL(deltaValue) * multiplier, sym_to_jointype(joinTypeValue), miterLimit * multiplier);
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(Polygons::iterator i = resultPolygons.begin(); i != resultPolygons.end(); ++i) {
299
+ for(Paths::iterator i = resultPaths.begin(); i != resultPaths.end(); ++i) {
234
300
  VALUE sub = rb_ary_new();
235
- for(Polygon::iterator p = i->begin(); p != i->end(); ++p) {
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
- Polygons solution;
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(Polygons::iterator i = solution.begin(); i != solution.end(); ++i) {
334
+ for(Paths::iterator i = solution.begin(); i != solution.end(); ++i) {
269
335
  VALUE sub = rb_ary_new();
270
- for(Polygon::iterator p = i->begin(); p != i->end(); ++p) {
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
- (ruby_method) rbclipper_offset_polygons, -1);
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" */
@@ -2,5 +2,5 @@ module Clipper
2
2
  # Keep first two components sync'd to Clipper's major/minor.
3
3
  # Last is our build number based on that. Hopefully there
4
4
  # won't be too much churn re: Clipper's version vs. the bindings.
5
- VERSION = "5.0.3"
5
+ VERSION = "6.2.1.5.2"
6
6
  end
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.0.3
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-02-23 00:00:00.000000000 Z
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: '1.0'
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: '1.0'
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: