Skip to content

Commit e07383f

Browse files
committed
41851ca Version 1.3.0
1 parent 502dfe0 commit e07383f

File tree

3 files changed

+28
-54
lines changed

3 files changed

+28
-54
lines changed

pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
<modelVersion>4.0.0</modelVersion>
55
<groupId>micycle</groupId>
66
<artifactId>clipper2</artifactId>
7-
<version>1.2.4</version>
7+
<version>1.3.0</version>
88
<name>Clipper2</name>
99
<properties>
1010
<jmh.version>1.36</jmh.version>

src/main/java/clipper2/offset/ClipperOffset.java

Lines changed: 24 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -31,9 +31,9 @@
3131
* curves</b> that are offset a specified distance from their primary curves.
3232
* <p>
3333
* Library users will rarely need to access this class directly since it's
34-
* generally easier to use the {@link Clipper#InflatePaths(Paths64, double, JoinType, EndType)
35-
* InflatePaths()} function for polygon
36-
* offsetting.
34+
* generally easier to use the
35+
* {@link Clipper#InflatePaths(Paths64, double, JoinType, EndType)
36+
* InflatePaths()} function for polygon offsetting.
3737
* <p>
3838
* <b>Notes:</b>
3939
* <ul>
@@ -64,10 +64,9 @@
6464
* point coordinates, the <b>InflatePaths</b> function will accept paths with
6565
* floating point coordinates.</li>
6666
* <li>Redundant segments should be removed before offsetting (see
67-
* {@link Clipper#SimplifyPaths(Paths64, double)
68-
* SimplifyPaths()}), and between offsetting operations too. These redundant
69-
* segments not only slow down offsetting, but they can cause unexpected
70-
* blemishes in offset solutions.</li>
67+
* {@link Clipper#SimplifyPaths(Paths64, double) SimplifyPaths()}), and between
68+
* offsetting operations too. These redundant segments not only slow down
69+
* offsetting, but they can cause unexpected blemishes in offset solutions.</li>
7170
* </ul>
7271
*/
7372
public class ClipperOffset {
@@ -76,7 +75,6 @@ public class ClipperOffset {
7675
private static final String COORD_RANGE_ERROR = "Error: Coordinate range.";
7776

7877
private final List<Group> groupList = new ArrayList<>();
79-
private final Path64 inPath = new Path64();
8078
private Path64 pathOut = new Path64();
8179
private final PathD normals = new PathD();
8280
private final Paths64 solution = new Paths64();
@@ -283,7 +281,7 @@ public void Execute(double delta, PolyTree64 solutionTree) {
283281
c.setPreserveCollinear(preserveCollinear);
284282
// the solution should normally retain the orientation of the input
285283
c.setReverseSolution(reverseSolution != pathsReversed);
286-
c.AddSubject(solution);
284+
c.AddSubject(this.solution);
287285
c.Execute(ClipType.Union, fillRule, solutionTree);
288286
}
289287

@@ -349,31 +347,6 @@ private static PointD GetUnitNormal(Point64 pt1, Point64 pt2) {
349347
return new PointD(dy, -dx);
350348
}
351349

352-
private static void GetBoundsAndLowestPolyIdx(Paths64 paths, OutObject<Integer> index, OutObject<Rect64> recRef) {
353-
final Rect64 rec = new Rect64(false); // ie invalid rect
354-
recRef.argValue = rec;
355-
long lpX = Long.MIN_VALUE;
356-
index.argValue = -1;
357-
for (int i = 0; i < paths.size(); i++) {
358-
for (Point64 pt : paths.get(i)) {
359-
if (pt.y >= rec.bottom) {
360-
if (pt.y > rec.bottom || pt.x < lpX) {
361-
index.argValue = i;
362-
lpX = pt.x;
363-
rec.bottom = pt.y;
364-
}
365-
} else if (pt.y < rec.top) {
366-
rec.top = pt.y;
367-
}
368-
if (pt.x > rec.right) {
369-
rec.right = pt.x;
370-
} else if (pt.x < rec.left) {
371-
rec.left = pt.y;
372-
}
373-
}
374-
}
375-
}
376-
377350
private static PointD TranslatePoint(PointD pt, double dx, double dy) {
378351
return new PointD(pt.x + dx, pt.y + dy);
379352
}
@@ -499,7 +472,7 @@ private void DoRound(Path64 path, int j, int k, double angle) {
499472
// when deltaCallback is assigned, groupDelta won't be constant,
500473
// so we'll need to do the following calculations for *every* vertex.
501474
double absDelta = Math.abs(groupDelta);
502-
double arcTol = arcTolerance > TOLERANCE ? Math.min(absDelta, arcTolerance) : Math.log10(2 + absDelta) * DEFAULT_ARC_TOLERANCE;
475+
double arcTol = arcTolerance > 0.01 ? arcTolerance : Math.log10(2 + absDelta) * InternalClipper.DEFAULT_ARC_TOLERANCE;
503476
double stepsPer360 = Math.PI / Math.acos(1 - arcTol / absDelta);
504477
stepSin = Math.sin((2 * Math.PI) / stepsPer360);
505478
stepCos = Math.cos((2 * Math.PI) / stepsPer360);
@@ -568,7 +541,7 @@ private void OffsetPoint(Group group, Path64 path, int j, RefObject<Integer> k)
568541
pathOut.add(GetPerpendic(path.get(j), normals.get(j)));
569542
} else if (cosA > 0.999 && joinType != JoinType.Round) {
570543
// almost straight - less than 2.5 degree (#424, #482, #526 & #724)
571-
DoMiter(group, path, j, k.argValue, cosA);
544+
DoMiter(group, path, j, k.argValue, cosA);
572545
} else if (joinType == JoinType.Miter) {
573546
// miter unless the angle is sufficiently acute to exceed ML
574547
if (cosA > mitLimSqr - 1) {
@@ -590,7 +563,7 @@ private void OffsetPoint(Group group, Path64 path, int j, RefObject<Integer> k)
590563
private void OffsetPolygon(Group group, Path64 path) {
591564
pathOut = new Path64();
592565
int cnt = path.size();
593-
RefObject<Integer> prev = new RefObject<Integer>(cnt-1);
566+
RefObject<Integer> prev = new RefObject<Integer>(cnt - 1);
594567
for (int i = 0; i < cnt; i++) {
595568
OffsetPoint(group, path, i, prev);
596569
}
@@ -661,12 +634,17 @@ private void OffsetOpenPath(Group group, Path64 path) {
661634
solution.add(pathOut);
662635
}
663636

637+
private static boolean ToggleBoolIf(boolean val, boolean condition) {
638+
return condition ? !val : val;
639+
}
640+
664641
private void DoGroupOffset(Group group) {
665642
if (group.endType == EndType.Polygon) {
643+
// a straight path (2 points) can now also be 'polygon' offset
644+
// where the ends will be treated as (180 deg.) joins
666645
if (group.lowestPathIdx < 0) {
667-
return;
646+
delta = Math.abs(delta);
668647
}
669-
// if (area == 0) return; // probably unhelpful (#430)
670648
groupDelta = (group.pathsReversed) ? -delta : delta;
671649
} else {
672650
groupDelta = Math.abs(delta); // * 0.5
@@ -698,7 +676,9 @@ private void DoGroupOffset(Group group) {
698676

699677
int i = 0;
700678
for (Path64 p : group.inPaths) {
701-
Rect64 pathBounds = group.boundsList.get(i++);
679+
// NOTE use int i rather than 3 iterators
680+
Rect64 pathBounds = group.boundsList.get(i);
681+
boolean isHole = group.isHoleList.get(i++);
702682
if (!pathBounds.IsValid()) {
703683
continue;
704684
}
@@ -723,12 +703,12 @@ private void DoGroupOffset(Group group) {
723703
}
724704
solution.add(pathOut);
725705
continue;
726-
} // end of offsetting a single (open path) point
706+
} // end of offsetting a single point
727707

728-
// when shrinking, then make sure the path can shrink that far (#593)
729-
if (groupDelta < 0 && Math.min(pathBounds.getWidth(), pathBounds.getHeight()) < -groupDelta * 2) {
708+
// when shrinking outer paths, make sure they can shrink this far (#593)
709+
// also when shrinking holes, make sure they too can shrink this far (#715)
710+
if (((groupDelta > 0) == ToggleBoolIf(isHole, group.pathsReversed)) && (Math.min(pathBounds.getWidth(), pathBounds.getHeight()) <= -groupDelta * 2))
730711
continue;
731-
}
732712

733713
if (cnt == 2 && group.endType == EndType.Joined) {
734714
endType = (group.joinType == JoinType.Round) ? EndType.Round : EndType.Square;

src/main/java/clipper2/offset/Group.java

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ class Group {
3737

3838
// get bounds of each path --> boundsList
3939
boundsList = new ArrayList<>(inPaths.size());
40-
GetMultiBounds(inPaths, boundsList, endType);
40+
GetMultiBounds(inPaths, boundsList);
4141

4242
if (endType == EndType.Polygon) {
4343
lowestPathIdx = GetLowestPathIdx(boundsList);
@@ -63,15 +63,9 @@ class Group {
6363
}
6464
}
6565

66-
private static void GetMultiBounds(Paths64 paths, List<Rect64> boundsList, EndType endType) {
67-
int minPathLen = (endType == EndType.Polygon) ? 3 : 1;
68-
69-
// if (boundsList instanceof ArrayList) {
70-
// ((ArrayList<Rect64>) boundsList).ensureCapacity(paths.size());
71-
// }
72-
66+
private static void GetMultiBounds(Paths64 paths, List<Rect64> boundsList) {
7367
for (Path64 path : paths) {
74-
if (path.size() < minPathLen) {
68+
if (path.size() < 1) {
7569
boundsList.add(Clipper.InvalidRect64.clone());
7670
continue;
7771
}

0 commit comments

Comments
 (0)