Skip to content

Commit 6956c15

Browse files
authored
Merge pull request #4 from elara-leitstellentechnik/v1.0.6
Port of v1.0.6
2 parents 70c8d18 + 8d03e7f commit 6956c15

File tree

15 files changed

+898
-80
lines changed

15 files changed

+898
-80
lines changed

src/main/java/clipper2/Clipper.java

Lines changed: 208 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;
@@ -21,19 +16,27 @@
2116
import clipper2.engine.ClipperD;
2217
import clipper2.engine.PointInPolygonResult;
2318
import clipper2.engine.PolyPath64;
24-
import clipper2.engine.PolyPathBase;
2519
import clipper2.engine.PolyPathD;
20+
import clipper2.engine.PolyPathNode;
2621
import clipper2.engine.PolyTree64;
2722
import clipper2.engine.PolyTreeD;
2823
import clipper2.offset.ClipperOffset;
2924
import clipper2.offset.EndType;
3025
import clipper2.offset.JoinType;
26+
import clipper2.rectclip.RectClip;
27+
import clipper2.rectclip.RectClipLines;
28+
29+
import java.util.ArrayList;
30+
import java.util.Arrays;
31+
import java.util.Collections;
32+
import java.util.List;
3133

3234
public final class Clipper {
3335

3436
public static final Rect64 MaxInvalidRect64 = new Rect64(Long.MAX_VALUE, Long.MAX_VALUE, Long.MIN_VALUE, Long.MIN_VALUE);
3537

3638
public static final RectD MaxInvalidRectD = new RectD(Double.MAX_VALUE, Double.MAX_VALUE, -Double.MAX_VALUE, -Double.MAX_VALUE);
39+
private static final String PRECISION_RANGE_ERROR = "Error: Precision is out of range.";
3740

3841
public static Paths64 Intersect(Paths64 subject, Paths64 clip, FillRule fillRule) {
3942
return BooleanOp(ClipType.Intersection, subject, clip, fillRule);
@@ -43,8 +46,8 @@ public static PathsD Intersect(PathsD subject, PathsD clip, FillRule fillRule) {
4346
return Intersect(subject, clip, fillRule, 2);
4447
}
4548

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

5053
public static Paths64 Union(Paths64 subject, FillRule fillRule) {
@@ -63,8 +66,8 @@ public static PathsD Union(PathsD subject, PathsD clip, FillRule fillRule) {
6366
return Union(subject, clip, fillRule, 2);
6467
}
6568

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

7073
public static Paths64 Difference(Paths64 subject, Paths64 clip, FillRule fillRule) {
@@ -75,8 +78,8 @@ public static PathsD Difference(PathsD subject, PathsD clip, FillRule fillRule)
7578
return Difference(subject, clip, fillRule, 2);
7679
}
7780

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

8285
public static Paths64 Xor(Paths64 subject, Paths64 clip, FillRule fillRule) {
@@ -87,8 +90,8 @@ public static PathsD Xor(PathsD subject, PathsD clip, FillRule fillRule) {
8790
return Xor(subject, clip, fillRule, 2);
8891
}
8992

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

9497
public static Paths64 BooleanOp(ClipType clipType, Paths64 subject, Paths64 clip, FillRule fillRule) {
@@ -109,10 +112,9 @@ public static PathsD BooleanOp(ClipType clipType, PathsD subject, PathsD clip, F
109112
return BooleanOp(clipType, subject, clip, fillRule, 2);
110113
}
111114

112-
public static PathsD BooleanOp(ClipType clipType, PathsD subject, @Nullable PathsD clip, FillRule fillRule,
113-
int roundingDecimalPrecision) {
115+
public static PathsD BooleanOp(ClipType clipType, PathsD subject, @Nullable PathsD clip, FillRule fillRule, int precision) {
114116
PathsD solution = new PathsD();
115-
ClipperD c = new ClipperD(roundingDecimalPrecision);
117+
ClipperD c = new ClipperD(precision);
116118
c.AddSubjectsD(subject);
117119
if (clip != null) {
118120
c.AddClipsD(clip);
@@ -184,7 +186,7 @@ public static PathsD InflatePaths(PathsD paths, double delta, JoinType joinType,
184186

185187
public static PathsD InflatePaths(PathsD paths, double delta, JoinType joinType, EndType endType, double miterLimit, int precision) {
186188
if (precision < -8 || precision > 8) {
187-
throw new IllegalArgumentException("Error: Precision is out of range.");
189+
throw new IllegalArgumentException(PRECISION_RANGE_ERROR);
188190
}
189191
double scale = Math.pow(10, precision);
190192
Paths64 tmp = ScalePaths64(paths, scale);
@@ -194,6 +196,157 @@ public static PathsD InflatePaths(PathsD paths, double delta, JoinType joinType,
194196
return ScalePathsD(tmp, 1 / scale);
195197
}
196198

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

509+
public static Rect64 ScaleRect(RectD rec, double scale)
510+
{
511+
Rect64 result = new Rect64(
512+
(long) (rec.left * scale),
513+
(long) (rec.top * scale),
514+
(long) (rec.right * scale),
515+
(long) (rec.bottom * scale)
516+
);
517+
return result;
518+
}
519+
356520
public static Path64 ScalePath(Path64 path, double scale) {
357521
if (InternalClipper.IsAlmostZero(scale - 1)) {
358522
return path;
@@ -528,6 +692,30 @@ public static PathsD ReversePaths(PathsD paths) {
528692
return result;
529693
}
530694

695+
public static Rect64 GetBounds(Path64 path)
696+
{
697+
Rect64 result = MaxInvalidRect64;
698+
for (Point64 pt : path) {
699+
if (pt.x < result.left) result.left = pt.x;
700+
if (pt.x > result.right) result.right = pt.x;
701+
if (pt.y < result.top) result.top = pt.y;
702+
if (pt.y > result.bottom) result.bottom = pt.y;
703+
}
704+
return result.IsEmpty() ? new Rect64() : result;
705+
}
706+
707+
public static RectD GetBounds(PathD path)
708+
{
709+
RectD result = MaxInvalidRectD;
710+
for (PointD pt : path) {
711+
if (pt.x < result.left) result.left = pt.x;
712+
if (pt.x > result.right) result.right = pt.x;
713+
if (pt.y < result.top) result.top = pt.y;
714+
if (pt.y > result.bottom) result.bottom = pt.y;
715+
}
716+
return result.IsEmpty() ? new RectD() : result;
717+
}
718+
531719
public static Rect64 GetBounds(Paths64 paths) {
532720
Rect64 result = MaxInvalidRect64;
533721
for (Path64 path : paths) {
@@ -669,7 +857,7 @@ public static void AddPolyNodeToPathsD(PolyPathD polyPath, PathsD paths) {
669857

670858
public static PathsD PolyTreeToPathsD(PolyTreeD polyTree) {
671859
PathsD result = new PathsD();
672-
for (PolyPathBase polyPathBase : polyTree) {
860+
for (PolyPathNode polyPathBase : polyTree) {
673861
PolyPathD p = (PolyPathD) polyPathBase;
674862
AddPolyNodeToPathsD(p, result);
675863
}
@@ -939,7 +1127,7 @@ public static PathD TrimCollinear(PathD path, int precision) {
9391127
*/
9401128
public static PathD TrimCollinear(PathD path, int precision, boolean isOpen) {
9411129
if (precision < -8 || precision > 8) {
942-
throw new IllegalArgumentException("Error: Precision is out of range.");
1130+
throw new IllegalArgumentException(PRECISION_RANGE_ERROR);
9431131
}
9441132
double scale = Math.pow(10, precision);
9451133
Path64 p = ScalePath64(path, scale);

0 commit comments

Comments
 (0)