Skip to content

Commit d9db7f9

Browse files
1.0.6
1 parent 70c8d18 commit d9db7f9

File tree

15 files changed

+902
-80
lines changed

15 files changed

+902
-80
lines changed

src/main/java/clipper2/Clipper.java

Lines changed: 197 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,5 @@
11
package clipper2;
22

3-
import java.util.ArrayList;
4-
import java.util.Arrays;
5-
import java.util.Collections;
6-
import java.util.List;
7-
83
import clipper2.core.ClipType;
94
import clipper2.core.FillRule;
105
import clipper2.core.InternalClipper;
@@ -18,22 +13,31 @@
1813
import clipper2.core.Rect64;
1914
import clipper2.core.RectD;
2015
import clipper2.engine.Clipper64;
16+
import clipper2.engine.ClipperBase;
2117
import clipper2.engine.ClipperD;
2218
import clipper2.engine.PointInPolygonResult;
2319
import clipper2.engine.PolyPath64;
24-
import clipper2.engine.PolyPathBase;
2520
import clipper2.engine.PolyPathD;
21+
import clipper2.engine.PolyPathNode;
2622
import clipper2.engine.PolyTree64;
2723
import clipper2.engine.PolyTreeD;
2824
import clipper2.offset.ClipperOffset;
2925
import clipper2.offset.EndType;
3026
import clipper2.offset.JoinType;
27+
import clipper2.rectclip.RectClip;
28+
import clipper2.rectclip.RectClipLines;
29+
30+
import java.util.ArrayList;
31+
import java.util.Arrays;
32+
import java.util.Collections;
33+
import java.util.List;
3134

3235
public final class Clipper {
3336

3437
public static final Rect64 MaxInvalidRect64 = new Rect64(Long.MAX_VALUE, Long.MAX_VALUE, Long.MIN_VALUE, Long.MIN_VALUE);
3538

3639
public static final RectD MaxInvalidRectD = new RectD(Double.MAX_VALUE, Double.MAX_VALUE, -Double.MAX_VALUE, -Double.MAX_VALUE);
40+
public static final String PRECISION_RANGE_ERROR = "Error: Precision is out of range.";
3741

3842
public static Paths64 Intersect(Paths64 subject, Paths64 clip, FillRule fillRule) {
3943
return BooleanOp(ClipType.Intersection, subject, clip, fillRule);
@@ -43,8 +47,8 @@ public static PathsD Intersect(PathsD subject, PathsD clip, FillRule fillRule) {
4347
return Intersect(subject, clip, fillRule, 2);
4448
}
4549

46-
public static PathsD Intersect(PathsD subject, PathsD clip, FillRule fillRule, int roundingDecimalPrecision) {
47-
return BooleanOp(ClipType.Intersection, subject, clip, fillRule, roundingDecimalPrecision);
50+
public static PathsD Intersect(PathsD subject, PathsD clip, FillRule fillRule, int precision) {
51+
return BooleanOp(ClipType.Intersection, subject, clip, fillRule, precision);
4852
}
4953

5054
public static Paths64 Union(Paths64 subject, FillRule fillRule) {
@@ -63,8 +67,8 @@ public static PathsD Union(PathsD subject, PathsD clip, FillRule fillRule) {
6367
return Union(subject, clip, fillRule, 2);
6468
}
6569

66-
public static PathsD Union(PathsD subject, PathsD clip, FillRule fillRule, int roundingDecimalPrecision) {
67-
return BooleanOp(ClipType.Union, subject, clip, fillRule, roundingDecimalPrecision);
70+
public static PathsD Union(PathsD subject, PathsD clip, FillRule fillRule, int precision) {
71+
return BooleanOp(ClipType.Union, subject, clip, fillRule, precision);
6872
}
6973

7074
public static Paths64 Difference(Paths64 subject, Paths64 clip, FillRule fillRule) {
@@ -75,8 +79,8 @@ public static PathsD Difference(PathsD subject, PathsD clip, FillRule fillRule)
7579
return Difference(subject, clip, fillRule, 2);
7680
}
7781

78-
public static PathsD Difference(PathsD subject, PathsD clip, FillRule fillRule, int roundingDecimalPrecision) {
79-
return BooleanOp(ClipType.Difference, subject, clip, fillRule, roundingDecimalPrecision);
82+
public static PathsD Difference(PathsD subject, PathsD clip, FillRule fillRule, int precision) {
83+
return BooleanOp(ClipType.Difference, subject, clip, fillRule, precision);
8084
}
8185

8286
public static Paths64 Xor(Paths64 subject, Paths64 clip, FillRule fillRule) {
@@ -87,8 +91,8 @@ public static PathsD Xor(PathsD subject, PathsD clip, FillRule fillRule) {
8791
return Xor(subject, clip, fillRule, 2);
8892
}
8993

90-
public static PathsD Xor(PathsD subject, PathsD clip, FillRule fillRule, int roundingDecimalPrecision) {
91-
return BooleanOp(ClipType.Xor, subject, clip, fillRule, roundingDecimalPrecision);
94+
public static PathsD Xor(PathsD subject, PathsD clip, FillRule fillRule, int precision) {
95+
return BooleanOp(ClipType.Xor, subject, clip, fillRule, precision);
9296
}
9397

9498
public static Paths64 BooleanOp(ClipType clipType, Paths64 subject, Paths64 clip, FillRule fillRule) {
@@ -109,10 +113,9 @@ public static PathsD BooleanOp(ClipType clipType, PathsD subject, PathsD clip, F
109113
return BooleanOp(clipType, subject, clip, fillRule, 2);
110114
}
111115

112-
public static PathsD BooleanOp(ClipType clipType, PathsD subject, @Nullable PathsD clip, FillRule fillRule,
113-
int roundingDecimalPrecision) {
116+
public static PathsD BooleanOp(ClipType clipType, PathsD subject, @Nullable PathsD clip, FillRule fillRule, int precision) {
114117
PathsD solution = new PathsD();
115-
ClipperD c = new ClipperD(roundingDecimalPrecision);
118+
ClipperD c = new ClipperD(precision);
116119
c.AddSubjectsD(subject);
117120
if (clip != null) {
118121
c.AddClipsD(clip);
@@ -184,7 +187,7 @@ public static PathsD InflatePaths(PathsD paths, double delta, JoinType joinType,
184187

185188
public static PathsD InflatePaths(PathsD paths, double delta, JoinType joinType, EndType endType, double miterLimit, int precision) {
186189
if (precision < -8 || precision > 8) {
187-
throw new IllegalArgumentException("Error: Precision is out of range.");
190+
throw new IllegalArgumentException(PRECISION_RANGE_ERROR);
188191
}
189192
double scale = Math.pow(10, precision);
190193
Paths64 tmp = ScalePaths64(paths, scale);
@@ -194,6 +197,157 @@ public static PathsD InflatePaths(PathsD paths, double delta, JoinType joinType,
194197
return ScalePathsD(tmp, 1 / scale);
195198
}
196199

200+
public static Path64 RectClip(Rect64 rect, Path64 path)
201+
{
202+
if (rect.IsEmpty() || path.isEmpty()) return new Path64();
203+
RectClip rc = new RectClip(rect);
204+
return rc.ExecuteInternal(path);
205+
}
206+
207+
public static Paths64 RectClip(Rect64 rect, Paths64 paths)
208+
{
209+
if (rect.IsEmpty() || paths.isEmpty()) return new Paths64();
210+
211+
Paths64 result = new Paths64(paths.size());
212+
RectClip rc = new RectClip(rect);
213+
for (Path64 path : paths) {
214+
Rect64 pathRec = ClipperBase.GetBounds(path);
215+
if (!rect.Intersects(pathRec))
216+
continue;
217+
else if (rect.Contains(pathRec))
218+
result.add(path);
219+
else
220+
{
221+
Path64 p = rc.ExecuteInternal(path);
222+
if (p.size() > 0) result.add(p);
223+
}
224+
}
225+
return result;
226+
}
227+
228+
public static PathD RectClip(RectD rect, PathD path){
229+
return RectClip(rect, path, 2);
230+
}
231+
232+
public static PathD RectClip(RectD rect, PathD path, int precision)
233+
{
234+
if (precision < -8 || precision > 8)
235+
throw new IllegalArgumentException(PRECISION_RANGE_ERROR);
236+
if (rect.IsEmpty() || path.size() == 0) return new PathD();
237+
double scale = Math.pow(10, precision);
238+
Rect64 r = ScaleRect(rect, scale);
239+
Path64 tmpPath = ScalePath64(path, scale);
240+
RectClip rc = new RectClip(r);
241+
tmpPath = rc.ExecuteInternal(tmpPath);
242+
return ScalePathD(tmpPath, 1 / scale);
243+
}
244+
245+
public static PathsD RectClip(RectD rect, PathsD paths)
246+
{
247+
return RectClip(rect, paths, 2);
248+
}
249+
250+
public static PathsD RectClip(RectD rect, PathsD paths, int precision)
251+
{
252+
if (precision < -8 || precision > 8)
253+
throw new IllegalArgumentException(PRECISION_RANGE_ERROR);
254+
if (rect.IsEmpty() || paths.size() == 0) return new PathsD();
255+
double scale = Math.pow(10, precision);
256+
Rect64 r = ScaleRect(rect, scale);
257+
RectClip rc = new RectClip(r);
258+
PathsD result = new PathsD(paths.size());
259+
for (PathD p : paths) {
260+
RectD pathRec = ClipperBase.GetBounds(p);
261+
if (!rect.Intersects(pathRec))
262+
continue;
263+
else if (rect.Contains(pathRec))
264+
result.add(p);
265+
else
266+
{
267+
Path64 p64 = ScalePath64(p, scale);
268+
p64 = rc.ExecuteInternal(p64);
269+
if (p64.size() > 0)
270+
result.add(ScalePathD(p64, 1 / scale));
271+
}
272+
}
273+
return result;
274+
}
275+
public static Paths64 RectClipLines(Rect64 rect, Path64 path)
276+
{
277+
if (rect.IsEmpty() || path.size() == 0) return new Paths64();
278+
RectClipLines rco = new RectClipLines(rect);
279+
return rco.NewExecuteInternal(path);
280+
}
281+
282+
public static Paths64 RectClipLines(Rect64 rect, Paths64 paths)
283+
{
284+
Paths64 result = new Paths64(paths.size());
285+
if (rect.IsEmpty() || paths.size() == 0) return result;
286+
RectClipLines rco = new RectClipLines(rect);
287+
for (Path64 path : paths) {
288+
Rect64 pathRec = ClipperBase.GetBounds(path);
289+
if (!rect.Intersects(pathRec))
290+
continue;
291+
else if (rect.Contains(pathRec))
292+
result.add(path);
293+
else
294+
{
295+
Paths64 pp = rco.NewExecuteInternal(path);
296+
if (pp.size() > 0) result.addAll(pp);
297+
}
298+
}
299+
return result;
300+
}
301+
302+
public static PathsD RectClipLines(RectD rect, PathD path)
303+
{
304+
return RectClipLines(rect, path, 2);
305+
}
306+
307+
public static PathsD RectClipLines(RectD rect, PathD path, int precision)
308+
{
309+
if (precision < -8 || precision > 8)
310+
throw new IllegalArgumentException(PRECISION_RANGE_ERROR);
311+
if (rect.IsEmpty() || path.size() == 0) return new PathsD();
312+
double scale = Math.pow(10, precision);
313+
Rect64 r = ScaleRect(rect, scale);
314+
Path64 tmpPath = ScalePath64(path, scale);
315+
RectClipLines rco = new RectClipLines(r);
316+
Paths64 tmpPaths = rco.NewExecuteInternal(tmpPath);
317+
return ScalePathsD(tmpPaths, 1 / scale);
318+
}
319+
public static PathsD RectClipLines(RectD rect, PathsD paths)
320+
{
321+
return RectClipLines(rect, paths, 2);
322+
}
323+
324+
public static PathsD RectClipLines(RectD rect, PathsD paths, int precision)
325+
{
326+
if (precision < -8 || precision > 8)
327+
throw new IllegalArgumentException(PRECISION_RANGE_ERROR);
328+
PathsD result = new PathsD(paths.size());
329+
if (rect.IsEmpty() || paths.size() == 0) return result;
330+
double scale = Math.pow(10, precision);
331+
Rect64 r = ScaleRect(rect, scale);
332+
RectClipLines rco = new RectClipLines(r);
333+
for (PathD p : paths) {
334+
RectD pathRec = ClipperBase.GetBounds(p);
335+
if (!rect.Intersects(pathRec))
336+
continue;
337+
else if (rect.Contains(pathRec))
338+
result.add(p);
339+
else
340+
{
341+
Path64 p64 = ScalePath64(p, scale);
342+
Paths64 pp64 = rco.NewExecuteInternal(p64);
343+
if (pp64.size() == 0) continue;
344+
PathsD ppd = ScalePathsD(pp64, 1 / scale);
345+
result.addAll(ppd);
346+
}
347+
}
348+
return result;
349+
}
350+
197351
public static Paths64 MinkowskiSum(Path64 pattern, Path64 path, boolean isClosed) {
198352
return Minkowski.Sum(pattern, path, isClosed);
199353
}
@@ -353,6 +507,17 @@ public static PointD ScalePointD(Point64 pt, double scale) {
353507
return result;
354508
}
355509

510+
public static Rect64 ScaleRect(RectD rec, double scale)
511+
{
512+
Rect64 result = new Rect64(
513+
(long) (rec.left * scale),
514+
(long) (rec.top * scale),
515+
(long) (rec.right * scale),
516+
(long) (rec.bottom * scale)
517+
);
518+
return result;
519+
}
520+
356521
public static Path64 ScalePath(Path64 path, double scale) {
357522
if (InternalClipper.IsAlmostZero(scale - 1)) {
358523
return path;
@@ -528,6 +693,18 @@ public static PathsD ReversePaths(PathsD paths) {
528693
return result;
529694
}
530695

696+
public static Rect64 GetBounds(Path64 path)
697+
{
698+
Rect64 result = MaxInvalidRect64;
699+
for (Point64 pt : path) {
700+
if (pt.x < result.left) result.left = pt.x;
701+
if (pt.x > result.right) result.right = pt.x;
702+
if (pt.y < result.top) result.top = pt.y;
703+
if (pt.y > result.bottom) result.bottom = pt.y;
704+
}
705+
return result.IsEmpty() ? new Rect64() : result;
706+
}
707+
531708
public static Rect64 GetBounds(Paths64 paths) {
532709
Rect64 result = MaxInvalidRect64;
533710
for (Path64 path : paths) {
@@ -669,7 +846,7 @@ public static void AddPolyNodeToPathsD(PolyPathD polyPath, PathsD paths) {
669846

670847
public static PathsD PolyTreeToPathsD(PolyTreeD polyTree) {
671848
PathsD result = new PathsD();
672-
for (PolyPathBase polyPathBase : polyTree) {
849+
for (PolyPathNode polyPathBase : polyTree) {
673850
PolyPathD p = (PolyPathD) polyPathBase;
674851
AddPolyNodeToPathsD(p, result);
675852
}
@@ -939,7 +1116,7 @@ public static PathD TrimCollinear(PathD path, int precision) {
9391116
*/
9401117
public static PathD TrimCollinear(PathD path, int precision, boolean isOpen) {
9411118
if (precision < -8 || precision > 8) {
942-
throw new IllegalArgumentException("Error: Precision is out of range.");
1119+
throw new IllegalArgumentException(PRECISION_RANGE_ERROR);
9431120
}
9441121
double scale = Math.pow(10, precision);
9451122
Path64 p = ScalePath64(path, scale);

0 commit comments

Comments
 (0)