Skip to content

Commit

Permalink
fix polytree (and enable test)
Browse files Browse the repository at this point in the history
  • Loading branch information
micycle1 committed Oct 8, 2022
1 parent 2738567 commit 91ba7cf
Show file tree
Hide file tree
Showing 7 changed files with 23 additions and 35 deletions.
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ A Java port of _[Clipper2](https://github.com/AngusJohnson/Clipper2)_.

### Port Info
* _tangiblesoftwaresolutions_' C# to Java Converter did the heavy lifting (but then a lot of manual work was required).
* Wrapper objects are used to replicate C# `ref` (pass-by-reference) behaviour. This isn't very "Javaific" but avoids an unmanageable refactoring effort.
* Code passes all polygon and line tests.
* Wrapper objects are used to replicate C# `ref` (pass-by-reference) behaviour. This isn't very Java-esque but avoids an unmanageable refactoring effort.
* Code passes all tests: polygon, line and polytree.
* Uses lower-case (x,y) for point coordinates.
* Benchmarks can be run by appending `jmh:benchmark` to the chosen maven goal.
* `scanlineList` from `ClipperBase` uses Java `TreeSet` (variable renamed to `scanlineSet`).
12 changes: 3 additions & 9 deletions src/main/java/clipper2/Clipper.java
Original file line number Diff line number Diff line change
Expand Up @@ -650,26 +650,20 @@ private static void AddPolyNodeToPaths(PolyPath64 polyPath, Paths64 paths) {
if (!polyPath.getPolygon().isEmpty()) {
paths.add(polyPath.getPolygon());
}
for (int i = 0; i < polyPath.getCount(); i++) {
AddPolyNodeToPaths((PolyPath64) polyPath.children.get(i), paths);
}
polyPath.iterator().forEachRemaining(p -> AddPolyNodeToPaths((PolyPath64) p, paths));
}

public static Paths64 PolyTreeToPaths64(PolyTree64 polyTree) {
Paths64 result = new Paths64();
for (int i = 0; i < polyTree.getCount(); i++) {
AddPolyNodeToPaths((PolyPath64) polyTree.children.get(i), result);
}
polyTree.iterator().forEachRemaining(p -> AddPolyNodeToPaths((PolyPath64) p, result));
return result;
}

public static void AddPolyNodeToPathsD(PolyPathD polyPath, PathsD paths) {
if (!polyPath.getPolygon().isEmpty()) {
paths.add(polyPath.getPolygon());
}
for (int i = 0; i < polyPath.getCount(); i++) {
AddPolyNodeToPathsD((PolyPathD) polyPath.children.get(i), paths);
}
polyPath.iterator().forEachRemaining(p -> AddPolyNodeToPathsD((PolyPathD) p, paths));
}

public static PathsD PolyTreeToPathsD(PolyTreeD polyTree) {
Expand Down
2 changes: 1 addition & 1 deletion src/main/java/clipper2/engine/Clipper64.java
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ public final boolean Execute(ClipType clipType, FillRule fillRule, PolyTree64 po
try {
ExecuteInternal(clipType, fillRule);
BuildTree(polytree, openPaths);
} catch (java.lang.Exception e) {
} catch (Exception e) {
succeeded = false;
}

Expand Down
8 changes: 4 additions & 4 deletions src/main/java/clipper2/engine/ClipperBase.java
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@
abstract class ClipperBase {

private ClipType cliptype;
private FillRule fillrule;
private FillRule fillrule = FillRule.EvenOdd;
private Active actives = null;
private Active sel = null;
private Joiner horzJoiners = null;
Expand All @@ -43,8 +43,8 @@ abstract class ClipperBase {
private long currentBotY;
private boolean isSortedMinimaList;
private boolean hasOpenPaths;
public boolean usingPolytree;
public boolean succeeded;
boolean usingPolytree;
boolean succeeded;
private boolean preserveCollinear;
private boolean reverseSolution;

Expand Down Expand Up @@ -1230,7 +1230,7 @@ private OutPt AddLocalMaxPoly(Active ae1, Active ae2, Point64 pt) {
result = outrec.pts;

outrec.owner = GetRealOutRec(outrec.owner);
if (usingPolytree && outrec.owner.frontEdge == null) {
if (usingPolytree && outrec.owner != null && outrec.owner.frontEdge == null) {
outrec.owner = GetRealOutRec(outrec.owner.owner);
}
}
Expand Down
8 changes: 2 additions & 6 deletions src/main/java/clipper2/engine/PolyPathBase.java
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@

public abstract class PolyPathBase implements Iterable<PolyPathBase> {

public PolyPathBase parent;
public List<PolyPathBase> children = new ArrayList<>();
final PolyPathBase parent;
List<PolyPathBase> children = new ArrayList<>();

PolyPathBase(PolyPathBase parent) {
this.parent = parent;
Expand All @@ -28,10 +28,6 @@ public final PolyPathIterator iterator() {
* of a polygon.
*/
public final boolean getIsHole() {
return GetIsHole();
}

private boolean GetIsHole() {
boolean result = true;
PolyPathBase pp = parent;
while (pp != null) {
Expand Down
2 changes: 1 addition & 1 deletion src/main/java/clipper2/engine/PolyPathIterator.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
import java.util.List;
import java.util.NoSuchElementException;

class PolyPathIterator implements Iterator<PolyPathBase> {
public class PolyPathIterator implements Iterator<PolyPathBase> {

List<PolyPathBase> ppbList;
int position = 0;
Expand Down
22 changes: 10 additions & 12 deletions src/test/java/clipper2/TestPolytree.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
import java.util.List;
import java.util.stream.Stream;

import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource;
Expand All @@ -29,7 +28,6 @@ private static final Stream<Arguments> testCases() throws IOException {

@MethodSource("testCases")
@ParameterizedTest(name = "{1} {2} {3}")
@Disabled
final void RunPolytreeTestCase(TestCase test, String caption, Object o, Object o1) {
PolyTree64 solutionTree = new PolyTree64();
Paths64 solution_open = new Paths64();
Expand All @@ -44,7 +42,7 @@ final void RunPolytreeTestCase(TestCase test, String caption, Object o, Object o

for (Point64 pt : pointsOfInterestOutside) {
for (var path : subject) {
assertSame(PointInPolygonResult.IsOutside, Clipper.PointInPolygon(pt, path),
assertEquals(PointInPolygonResult.IsOutside, Clipper.PointInPolygon(pt, path),
"outside point of interest found inside subject");
}
}
Expand All @@ -59,7 +57,7 @@ final void RunPolytreeTestCase(TestCase test, String caption, Object o, Object o
poi_inside_counter++;
}
}
assertSame(1, poi_inside_counter, String.format("poi_inside_counter - expected 1 but got %1$s", poi_inside_counter));
assertEquals(1, poi_inside_counter, String.format("poi_inside_counter - expected 1 but got %1$s", poi_inside_counter));
}

clipper.AddSubject(subject);
Expand All @@ -71,10 +69,10 @@ final void RunPolytreeTestCase(TestCase test, String caption, Object o, Object o
double a1 = Clipper.Area(solutionPaths), a2 = solutionTree.Area();

assertTrue(a1 > 330000, String.format("solution has wrong area - value expected: 331,052; value returned; %1$s ", a1));
//
assertTrue(Math.abs(a1 - a2) < 0.0001,
String.format("solution tree has wrong area - value expected: %1$s; value returned; %2$s ", a1, a2));
//
assertTrue(CheckPolytreeFullyContainsChildren(solutionTree), "The polytree doesn't properly contain its children");

for (Point64 pt : pointsOfInterestOutside) {
Expand All @@ -87,7 +85,7 @@ final void RunPolytreeTestCase(TestCase test, String caption, Object o, Object o
}
}

private boolean CheckPolytreeFullyContainsChildren(PolyTree64 polytree) {
private static boolean CheckPolytreeFullyContainsChildren(PolyTree64 polytree) {
for (var p : polytree) {
PolyPath64 child = (PolyPath64) p;
if (child.getCount() > 0 && !PolyPathFullyContainsChildren(child)) {
Expand All @@ -97,7 +95,7 @@ private boolean CheckPolytreeFullyContainsChildren(PolyTree64 polytree) {
return true;
}

private boolean PolyPathFullyContainsChildren(PolyPath64 pp) {
private static boolean PolyPathFullyContainsChildren(PolyPath64 pp) {
for (var c : pp) {
var child = (PolyPath64) c;
for (Point64 pt : child.getPolygon()) {
Expand All @@ -112,7 +110,7 @@ private boolean PolyPathFullyContainsChildren(PolyPath64 pp) {
return true;
}

private boolean PolytreeContainsPoint(PolyTree64 pp, Point64 pt) {
private static boolean PolytreeContainsPoint(PolyTree64 pp, Point64 pt) {
int counter = 0;
for (int i = 0; i < pp.getCount(); i++) {
PolyPath64 child = (PolyPath64) pp.get(i);
Expand All @@ -124,12 +122,12 @@ private boolean PolytreeContainsPoint(PolyTree64 pp, Point64 pt) {
return counter != 0;
}

private void PolyPathContainsPoint(PolyPath64 pp, Point64 pt, RefObject<Integer> counter) {
private static void PolyPathContainsPoint(PolyPath64 pp, Point64 pt, RefObject<Integer> counter) {
if (Clipper.PointInPolygon(pt, pp.getPolygon()) != PointInPolygonResult.IsOutside) {
if (pp.getIsHole()) {
--counter.argValue;
counter.argValue--;
} else {
++counter.argValue;
counter.argValue++;
}
}
for (int i = 0; i < pp.getCount(); i++) {
Expand Down

0 comments on commit 91ba7cf

Please sign in to comment.