Commit 97a65114 authored by Riegel's avatar Riegel
Browse files

Merge branch 'dev' into 'master'

Version 3.15.0

See merge request !8
parents 99c8f6a8 5950ea5f
Pipeline #10106 passed with stage
in 3 minutes and 15 seconds
......@@ -18,6 +18,7 @@
*/
package de.hft.stuttgart.citydoctor2.edge;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
......@@ -30,7 +31,7 @@ import de.hft.stuttgart.citydoctor2.math.Vector3d;
public class CDPolygonNs extends PolygonNs {
private List<List<HalfEdge>> innerHalfEdges = new ArrayList<>();
private final List<List<HalfEdge>> innerHalfEdges = new ArrayList<>();
public static CDPolygonNs of(Polygon p, Map<Vector3d, Coordinate3d> pointMap) {
List<List<Coordinate3d>> loopCoordinates = new ArrayList<>();
......
......@@ -18,6 +18,7 @@
*/
package de.hft.stuttgart.citydoctor2.edge;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
......@@ -25,7 +26,7 @@ import java.util.Set;
public class Coordinate3d extends BaseEntity {
private Point3d point;
private final Point3d point;
public Coordinate3d(Point3d point) {
this.point = point;
......
......@@ -211,6 +211,83 @@ public class DebugUtils {
return counterArr[0];
}
public static void printFPSelfIntersectionTestCaseCode(PolygonPolygonIntersection... intersectionResults){
for (PolygonPolygonIntersection intersection : intersectionResults) {
printFPSelfIntersectionTestCaseCode(intersection.getPolygon1(), intersection.getPolygon2());
}
}
public static void printFPSelfIntersectionTestCaseCode(EdgePolygon polygon1, EdgePolygon polygon2) {
Locale.setDefault(Locale.US);
System.out.println("-----------------------------------------------------");
System.out.println("");
System.out.println("@Test");
System.out.println("public void testFalsePositiveCASENAME() {");
printTabbedLine("Geometry geom = new Geometry(GeometryType.SOLID, Lod.LOD1);");
System.out.println("");
printTestCasePolygonCode(polygon1, polygon2);
printTabbedLine("CDPolygonNs edgePoly1 = CDPolygonNs.of(p1, new HashMap<>());");
printTabbedLine("CDPolygonNs edgePoly2 = CDPolygonNs.of(p2, new HashMap<>());");
printTabbedLine("List<PolygonPolygonIntersection> intersectPolygons;");
printTabbedLine("intersectPolygons = IntersectPlanarPolygons.intersectPolygons(edgePoly1, edgePoly2, 0.000001, 0.001);");
printTabbedLine("assertNotNull(intersectPolygons);");
printTabbedLine("assertTrue(intersectPolygons.isEmpty());");
System.out.println("");
printTabbedLine("intersectPolygons = IntersectPlanarPolygons.intersectPolygons(edgePoly2, edgePoly1, 0.000001, 0.001);");
printTabbedLine("assertNotNull(intersectPolygons);");
printTabbedLine("assertTrue(intersectPolygons.isEmpty());");
System.out.println("}");
}
private static void printTabbedLine(String line){
Locale.setDefault(Locale.US);
String format = "\t%s\n";
System.out.format(format, line);
}
private static void printTestCasePolygonCode(EdgePolygon polygon1, EdgePolygon polygon2) {
printTabbedLine("Polygon p1 = new ConcretePolygon();");
printTabbedLine("geom.addPolygon(p1);");
printTabbedLine("LinearRing ext = new LinearRing(LinearRingType.EXTERIOR);");
printTabbedLine("p1.setExteriorRing(ext);");
printTabbedLine("List<Vertex> vertices= new ArrayList<>();");
printTestCasePolygonVertices(polygon1);
System.out.println("");
printTabbedLine("Polygon p2 = new ConcretePolygon();");
printTabbedLine("geom.addPolygon(p2);");
printTabbedLine("ext = new LinearRing(LinearRingType.EXTERIOR);");
printTabbedLine("p2.setExteriorRing(ext);");
printTabbedLine("vertices= new ArrayList<>();");
printTestCasePolygonVertices(polygon2);
System.out.println("");
}
private static void printTestCasePolygonVertices(EdgePolygon polygon) {
List<Coordinate3d> coordList = polygon.getCoordinates();
NumberFormat nf = NumberFormat.getNumberInstance();
nf.setMaximumFractionDigits(30);
String vertexFormat = "vertices.add(new Vertex(%s,%s,%s));";
for (Coordinate3d coordinate3d : coordList) {
Point3d point = coordinate3d.getPoint();
printTabbedLine(String.format(vertexFormat,
nf.format(point.getX()), nf.format(point.getY()), nf.format(point.getZ())));
}
// close ring
Point3d point = coordList.get(0).getPoint();
printTabbedLine(String.format(vertexFormat,point.getX(),point.getY(),point.getZ()));
printTabbedLine("ext.addAllVertices(vertices);");
}
public static int printCityDoctorPolygons(Polygon... polygons) {
Locale.setDefault(Locale.US);
NumberFormat nf = NumberFormat.getNumberInstance();
......
......@@ -18,6 +18,7 @@
*/
package de.hft.stuttgart.citydoctor2.edge;
import java.util.ArrayList;
import java.util.List;
......@@ -25,8 +26,8 @@ import de.hft.stuttgart.citydoctor2.datastructure.Polygon;
public class EdgePolygon extends BaseEntity {
private Polygon original;
private List<HalfEdge> halfEdges;
private final Polygon original;
private final List<HalfEdge> halfEdges;
public EdgePolygon(List<HalfEdge> halfEdges, Polygon original) {
for (HalfEdge he : halfEdges) {
......@@ -80,12 +81,6 @@ public class EdgePolygon extends BaseEntity {
for (HalfEdge he : halfEdges) {
coords.add(he.getStart());
}
// HalfEdge firstHE = Objects.requireNonNull(getFirstHalfEdge());
// HalfEdge currHE = firstHE;
// do {
// coords.add(currHE.getStart());
// currHE = currHE.getNext();
// } while (currHE != firstHE);
return coords;
}
......@@ -97,15 +92,13 @@ public class EdgePolygon extends BaseEntity {
}
/**
* Test whether the given point is lying in- or outside of the non self
* Test whether the given point is lying inside the non-self-
* intersecting, planar polygon. It's believed, that point and polygon are lying
* in the same plane. <br>
* <br>
* It's assumed, that the polygon is non self intersecting and planar.
* Additionally it is assumed, that the point and the polygon lying in the same
* plane. The given point is projected on the plane of the polygon. If the point
* is lying on an edge of the polygon it's supposed that the point is inside of
* the polygon
* It's assumed, that the polygon is non-self-intersecting and planar, and that the point is
* lying in the same plane. The given point is projected on the plane of the polygon. If the point is lying on an edge
* of the polygon, it is considered to be inside.
*
* @param rcPoint The point that should be checked
*
......
......@@ -18,26 +18,27 @@
*/
package de.hft.stuttgart.citydoctor2.edge;
import java.util.Comparator;
public class Global {
private static final double DBL_EPSILON = 2.2204460492503131e-16;
private static double mZeroAngleCosinus = 1.0e-9;
private static double mTolVectorsParallel = 1e-9;
private static double mHighAccuracyTol = DBL_EPSILON * 5;
private static double mTolPointsEqual = 1e-3;
private static final double M_ZERO_ANGLE_COSINE = 1.0e-9;
private static final double M_TOL_VECTORS_PARALLEL = 1e-9;
private static final double M_HIGH_ACCURACY_TOL = DBL_EPSILON * 5;
private static final double M_TOL_POINTS_EQUAL = 1e-3;
private Global() {
}
public static double getTolPointsEquals() {
return mTolPointsEqual;
return M_TOL_POINTS_EQUAL;
}
public static double getHighAccuracyTolerance() {
return mHighAccuracyTol;
return M_HIGH_ACCURACY_TOL;
}
public static Comparator<Double> getDoubleTolCompare(double epsilon) {
......@@ -50,12 +51,10 @@ public class Global {
};
}
public static double getZeroAngleCosinus() {
return mZeroAngleCosinus;
}
public static double getZeroAngleCosine() { return M_ZERO_ANGLE_COSINE; }
public static double getTolVectorsParallel() {
return mTolVectorsParallel;
return M_TOL_VECTORS_PARALLEL;
}
}
......@@ -18,6 +18,7 @@
*/
package de.hft.stuttgart.citydoctor2.edge;
public class GmBoundedStraight2d extends GmStraight2d {
private double length;
......@@ -54,10 +55,7 @@ public class GmBoundedStraight2d extends GmStraight2d {
parameter = length;
}
if (0 <= parameter && parameter <= length) {
return true;
}
return false;
return 0 <= parameter && parameter <= length;
}
public double getLength() {
......
......@@ -18,29 +18,31 @@
*/
package de.hft.stuttgart.citydoctor2.edge;
import java.util.ArrayList;
import java.util.List;
public class GmPlane {
private Point3d x0;
private final Point3d x0;
private UnitVector3d r1;
private UnitVector3d r2;
private final UnitVector3d r1;
private final UnitVector3d r2;
private UnitVector3d n;
private double d;
private final UnitVector3d n;
private final double d;
public GmPlane(Point3d point, UnitVector3d normalVector) {
x0 = point;
n = normalVector;
d = new Vector3d(point).dot(n);
r1 = UnitVector3d.of(n.getZ(), n.getX(), n.getY());
r2 = n.cross(r1).toUnitVector();
UnitVector3d r = UnitVector3d.of(n.getZ(), n.getX(), n.getY());
r2 = n.cross(r).toUnitVector();
// r1 ist nicht in allen Faellen rechtwinklig zur Flaechennormalen
// daher nochmal eine neu Berechnung;
// r is not always perpendicular to the plane's normal vector,
// recalculate using r2
// ----------------------------------------------------------------
r1 = n.cross(r2).toUnitVector();
......
......@@ -18,10 +18,11 @@
*/
package de.hft.stuttgart.citydoctor2.edge;
public class GmStraight {
private Point3d org;
private UnitVector3d dir;
private final Point3d org;
private final UnitVector3d dir;
public GmStraight(Point3d org, Vector3d dir) {
this.org = org;
......@@ -54,7 +55,7 @@ public class GmStraight {
return dir;
}
public boolean isColinear(GmStraight straight2, double angleEpsilon, double epsilon) {
public boolean isCollinear(GmStraight straight2, double angleEpsilon, double epsilon) {
UnitVector3d rDir1 = getDir();
UnitVector3d rDir2 = straight2.getDir();
......@@ -74,11 +75,7 @@ public class GmStraight {
Point3d rOrigin2 = straight2.getOrigin();
Point3d foot2 = project(rOrigin2).getPoint();
if ((foot2.minus(rOrigin2)).getLength() > epsilon) {
return false;
}
return true;
return ((foot2.minus(rOrigin2)).getLength() <= epsilon);
}
public Point3d getOrigin() {
......
......@@ -18,10 +18,12 @@
*/
package de.hft.stuttgart.citydoctor2.edge;
public class GmStraight2d {
private Point2d origin;
private UnitVector2d direction;
private final Point2d origin;
private final UnitVector2d direction;
public GmStraight2d(Point2d org, UnitVector2d dir) {
this.direction = dir;
......@@ -39,14 +41,13 @@ public class GmStraight2d {
}
/**
* Just intersects two GmStraights2d.
*
* Intersects this straight with another straight.
* <br>
* <br>
* If the two straights are parallel the method will return false, so the user
* has to determine, if the straight are just parallel or identical
* If the two straights are parallel, areParallel in the returned IntersectionResult will be true.
* This method will not differentiate between parallel and identical straights.
*
* @param other First Straight
* @param other the other straight
*
* @return intersection result
*/
......@@ -60,7 +61,7 @@ public class GmStraight2d {
Vector2d r2Perpendicular = r2.getPerpendicularVector();
double diff = r1.dot(r2Perpendicular);
if (Math.abs(diff) < Global.getZeroAngleCosinus()) {
if (Math.abs(diff) < Global.getZeroAngleCosine()) {
return GmStraight2dIntersectionResult.parallel(this, other);
} else {
double invR1DotPerpR2 = 1.0 / diff;
......
......@@ -18,15 +18,9 @@
*/
package de.hft.stuttgart.citydoctor2.edge;
public class GmStraight2dIntersectionResult {
private double paramHE;
private double paramInt;
private GmStraight2d straightHE;
private GmStraight2d straightInt;
private boolean areParallel;
public record GmStraight2dIntersectionResult(double paramHE, double paramInt, GmStraight2d straightHE,
GmStraight2d straightInt, boolean areParallel) {
public static GmStraight2dIntersectionResult parallel(GmStraight2d s1, GmStraight2d s2) {
return new GmStraight2dIntersectionResult(0, 0, s1, s2, true);
......@@ -37,33 +31,5 @@ public class GmStraight2dIntersectionResult {
return new GmStraight2dIntersectionResult(paramHE, paramInt, straightHE, straightInt, false);
}
private GmStraight2dIntersectionResult(double paramHE, double paramInt, GmStraight2d straightHE,
GmStraight2d straightInt, boolean areParallel) {
this.paramHE = paramHE;
this.paramInt = paramInt;
this.straightHE = straightHE;
this.straightInt = straightInt;
this.areParallel = areParallel;
}
public double getParamHE() {
return paramHE;
}
public double getParamInt() {
return paramInt;
}
public GmStraight2d getStraightHE() {
return straightHE;
}
public GmStraight2d getStraightInt() {
return straightInt;
}
public boolean areParallel() {
return areParallel;
}
}
......@@ -108,7 +108,7 @@ public class HalfEdge extends BaseEntity {
HalfEdge pNextPartner = this.partner;
while (pNextPartner != this) {
if (pNextPartner == partner) {
logger.debug("(HalfEdge " + partner + " already exits in chain");
logger.debug(String.format("(HalfEdge %s already exits in chain", partner));
return;
}
pNextPartner = pNextPartner.partner;
......@@ -141,7 +141,7 @@ public class HalfEdge extends BaseEntity {
pPreviousPartner.partner = this;
this.partner = partner;
} else {
/**
/*
* TODO : das riecht nach einer Ringverzeigerung : 3 Polygonraender treffen auf
* einander
*/
......
......@@ -22,8 +22,8 @@ import java.util.List;
public class HalfEdge2d extends BaseEntity {
private Coordinate2d start;
private Coordinate2d end;
private final Coordinate2d start;
private final Coordinate2d end;
private HalfEdge2d partner;
......@@ -71,7 +71,7 @@ public class HalfEdge2d extends BaseEntity {
return pPartner;
}
private HalfEdge2d setPartner(HalfEdge2d pPartner) {
private void setPartner(HalfEdge2d pPartner) {
if (partner != null) {
if (pPartner != null) {
throw new IllegalStateException("cannot overwrite existing partner-connection");
......@@ -92,7 +92,6 @@ public class HalfEdge2d extends BaseEntity {
}
}
}
return pPartner;
}
public HalfEdge2d getPartner() {
......
......@@ -82,6 +82,22 @@ public class IntersectPlanarPolygons {
for (Interval in2 : intervals2) {
if (in1.isOverlapping(in2)) {
Interval overlap = in1.overlap(in2);
handleIntersectionIntervalOverlap(cpPolygon1, cpPolygon2, straight, intersections, epsilon, overlap);
} else if (Math.abs(in1.getStart() - in2.getEnd()) < Global.getHighAccuracyTolerance()) {
// check if the overlaps with a tolerance (numeric errors)
Point3d point = straight.evaluate(in1.getStart());
checkAndAddRealIntersectionPoint(cpPolygon1, cpPolygon2, point, intersections, epsilon);
} else if (Math.abs(in1.getEnd() - in2.getStart()) < Global.getHighAccuracyTolerance()) {
Point3d point = straight.evaluate(in1.getEnd());
checkAndAddRealIntersectionPoint(cpPolygon1, cpPolygon2, point, intersections, epsilon);
}
}
}
}
private static void handleIntersectionIntervalOverlap(EdgePolygon cpPolygon1, EdgePolygon cpPolygon2,
GmStraight straight, List<PolygonPolygonIntersection> intersections, double epsilon, Interval overlap) {
Point3d start = straight.evaluate(overlap.getStart());
if (overlap.getLength() < Global.getHighAccuracyTolerance() * 1e6) {
checkAndAddRealIntersectionPoint(cpPolygon1, cpPolygon2, start, intersections, epsilon);
......@@ -96,16 +112,6 @@ public class IntersectPlanarPolygons {
}
}
} else if (Math.abs(in1.getStart() - in2.getEnd()) < Global.getHighAccuracyTolerance()) {
// check if the overlaps with a tolerance (numeric errors)
Point3d point = straight.evaluate(in1.getStart());
checkAndAddRealIntersectionPoint(cpPolygon1, cpPolygon2, point, intersections, epsilon);
} else if (Math.abs(in1.getEnd() - in2.getStart()) < Global.getHighAccuracyTolerance()) {
Point3d point = straight.evaluate(in1.getEnd());
checkAndAddRealIntersectionPoint(cpPolygon1, cpPolygon2, point, intersections, epsilon);
}
}
}
}
private static boolean isPolyLineASharedEdge(EdgePolygon p1, PolyLine polyLine) {
......@@ -136,17 +142,20 @@ public class IntersectPlanarPolygons {
/**
*
* Checks if the given point is a "real" intersection point and add's it to the
* intersection segments member variable. Real means, that this point isn't
* shared by both polygons as corner point.
* Checks if the given point is a 'real' intersection point and adds it to the
* intersection segments member variable. 'Real' meaning, that this point isn't
* a shared corner point of both polygons.
*
* @param p1 First polygon
* @param p2 Second polygon
* @param point A possible intersection point
*/
private static void checkAndAddRealIntersectionPoint(EdgePolygon p1, EdgePolygon p2, Point3d point,
List<PolygonPolygonIntersection> intersections, double epsilon) {
// check if both polygons have this point in common
if (!sharingBothPolygonsThisPoint(p1, p2, point, epsilon)) {
PolyLine pPL = new PolyLine(new Coordinate3d(point), new Coordinate3d(point));
Coordinate3d realPointCoordinate = new Coordinate3d(point);
PolyLine pPL = new PolyLine(realPointCoordinate, realPointCoordinate);
PolygonPolygonIntersection pPPI = new PolygonPolygonIntersection(p1, p2, pPL);
intersections.add(pPPI);
}
......@@ -200,7 +209,6 @@ public class IntersectPlanarPolygons {
* with the exception, that the straight and the half edges of the polygon will
* be projected on the plane of the polygon, so the calculation of the
* intersection will be reduced to a 2d problem.
*
* The intersection intervals contains pairs of parameters from the intersection
* straight. If an intersection between the straight and the polygon contains
* only a point, the according interval will contain the same parameter twice
......@@ -239,7 +247,7 @@ public class IntersectPlanarPolygons {
GmBoundedStraight heStraight = e.getStraight();
// Straights are colinear; checked in the handleEmdeddedEdges method
if (heStraight.isColinear(intersectingStraight, angleEpsilon, epsilon)) {
if (heStraight.isCollinear(intersectingStraight, angleEpsilon, epsilon)) {
continue;
}
......@@ -256,7 +264,7 @@ public class IntersectPlanarPolygons {
// check if the straight of the HalfEdge is collinear to the intersection
// straight; this might result in an embedded edge intersection result
// TODO MW: really needed? this check is also made some lines above
if (heStraight.isColinear(intersectingStraight, angleEpsilon, epsilon)) {
if (heStraight.isCollinear(intersectingStraight, angleEpsilon, epsilon)) {
currHESharesAPntWithTheOtherPolygon = false;
}
......@@ -271,12 +279,22 @@ public class IntersectPlanarPolygons {
GmBoundedStraight2d heStraight2d = polyPlane.projectOn2dStraight(heStraight);
GmStraight2dIntersectionResult intersectionResult = heStraight2d.intersect(intersectingStraight2d);
analyseProjectedIntersection(intersectionResult, intersectingStraight2d, heStraight2d, intersectionValues, intersectedPolygonPoints);
}
processIntersectionIntervals(p, intersectingStraight, intersectionValues, intersectedPolygonPoints,
intersectionIntervals);
return intersectionIntervals;
}
private static void analyseProjectedIntersection(GmStraight2dIntersectionResult intersectionResult, GmStraight2d intersectingStraight2d, GmBoundedStraight2d heStraight2d, TreeSet<Double> intersectionValues, TreeSet<Double> intersectedPolygonPoints) {
if (intersectionResult.areParallel()) {
Vector2d dir = intersectingStraight2d.getDirection();
Vector2d diffVec = heStraight2d.getOrigin().minus(intersectingStraight2d.getOrigin());
double diffVecDotPerpDir = diffVec.dot(dir.getPerpendicularVector());
if (Math.abs(diffVecDotPerpDir) < Global.getZeroAngleCosinus()) {
if (Math.abs(diffVecDotPerpDir) < Global.getZeroAngleCosine()) {
// Straights are identical
Point2d p1 = heStraight2d.getOrigin();
Point2d p2 = heStraight2d.getTarget();
......@@ -299,19 +317,13 @@ public class IntersectPlanarPolygons {
assignParameterToCorrectList(params[1], intersectionValues, intersectedPolygonPoints);
}
} else {
if (heStraight2d.isWithinBoundaries(intersectionResult.getParamHE(), 1e-9)) {
assignParameterToCorrectList(intersectionResult.getParamInt(), intersectionValues,
if (heStraight2d.isWithinBoundaries(intersectionResult.paramHE(), 1e-9)) {
assignParameterToCorrectList(intersectionResult.paramInt(), intersectionValues,
intersectedPolygonPoints);
}
}
}
processIntersectionIntervals(p, intersectingStraight, intersectionValues, intersectedPolygonPoints,
intersectionIntervals);
return intersectionIntervals;
}
/**
* This methods computes the intervals of the intersection between the given
* straight and polygon. It gets only parameters where the straight hits the
......@@ -350,16 +362,35 @@ public class IntersectPlanarPolygons {
List<Double> valuesList = new ArrayList<>(intersectionValues);
for (int i = 0; i < valuesList.size(); i++) {
double i1 = valuesList.get(i);
i = i + 1;
if (i < valuesList.size()) {
double i2 = valuesList.get(i);
int j = i + 1;
if (j < valuesList.size()) {
double i2 = valuesList.get(j);
// check if the double values are corner points of the polygon
boolean gotPolygonPoint = false;
if (intersectedPolygonPoints.contains(i1) || intersectedPolygonPoints.contains(i2)) {
gotPolygonPoint = true;
}
boolean gotPolygonPoint = intersectedPolygonPoints.contains(i1) ||
intersectedPolygonPoints.contains(i2);
if (gotPolygonPoint) {
Interval newLineInt = checkIntersectionInvervalPoints(pcPolygon, intersectingStraight,
intersectionIntervals, i1, i2);
if (newLineInt != null) {
intersectionIntervals.add(newLineInt);
}
} else {
intersectionIntervals.add(new Interval(i1, i2));
}
}
// it's possible, that 'it' equals 'endIt' at the end of the loop.
// this would lead to an increment of an iterator pointing to the end
// iterator. don't ask me why, but incrementing such an iterator
// is forbidden and you get an assertion.
if (i >= valuesList.size()) {
break;
}
}
}
private static Interval checkIntersectionInvervalPoints(EdgePolygon pcPolygon, GmStraight intersectingStraight, List<Interval> intersectionIntervals, double i1, double i2) {
// maybe an interval
// check if the point between the two parameters is inside the
// polygon or outside ( i.e. i1 and i2 are both corner points of
......@@ -375,34 +406,19 @@ public class IntersectPlanarPolygons {
while (intervalIterator.hasNext() && !intersectionIntervals.isEmpty()) {
for (Interval inter = intervalIterator.next(); intervalIterator
.hasNext(); inter = intervalIterator.next()) {
if (Math.abs(inter.getLength()) < Global.getHighAccuracyTolerance()) {
if (Math.abs(inter.getStart() - i1) < 1e-9
|| Math.abs(inter.getStart() - i2) < 1e-9) {
if (Math.abs(inter.getLength()) < Global.getHighAccuracyTolerance() &&
(Math.abs(inter.getStart() - i1) < 1e-9 || Math.abs(inter.getStart() - i2) < 1e-9)) {
intervalIterator.remove();
intervalIterator = intersectionIntervals.iterator();
break;
}
}
}
}
intersectionIntervals.add(newLineInt);
} else {
i--;
}
} else {
intersectionIntervals.add(new Interval(i1, i2));
}
}
// it's possible, that 'it' equals 'endIt' at the end of the loop.
// this would lead to an increment of an iterator pointing to the end
// iterator. don't ask me why, but incrementing such an iterator
// is forbidden and you get an assertion.
if (i >= valuesList.size()) {
break;
}
return newLineInt;
}
return null;
}
/**
......@@ -444,46 +460,9 @@ public class IntersectPlanarPolygons {
List<HalfEdge> heList = new ArrayList<>(p1.getHalfEdges());
heList.addAll(p2.getHalfEdges());
List<HalfEdge> heListColinear = new ArrayList<>();
for (HalfEdge he : heList) {
List<HalfEdge> heListCollinear = getCollinearHalfEdgeList(p1, p2, straight, epsilon, angleEpsilon, heList);
if (null != he.getPartner()) {
// this half edge is shared by both polygons ==> no intersection
// NOTE: The issue of more than 2 half edges per edge is solved by
// circular pointer, so we have to cycle threw all partners
HalfEdge pStartHE = he;
HalfEdge pPartnerHE = pStartHE.getPartner();
boolean bothPolysShareThisEdge = false;
while (pStartHE != pPartnerHE && !bothPolysShareThisEdge) {
if (pPartnerHE.getPolygon() == p1 || pPartnerHE.getPolygon() == p2) {
bothPolysShareThisEdge = true;
}
pPartnerHE = pPartnerHE.getPartner();
}
if (bothPolysShareThisEdge) {
continue;
}
}
GmBoundedStraight straightHe = he.getStraight();
Point3d origin = straightHe.getOrigin();
Point3d target = straightHe.getTarget();
boolean straightsAreColinear = IntersectPlanarPolygons.areStraightsColinear(straightHe, straight, epsilon,
angleEpsilon);
ProjectedPoint3d projPoint1 = straight.project(origin);
ProjectedPoint3d projPoint2 = straight.project(target);
boolean originLiesOnIntStraight = projPoint1.getPoint().isAlmostEqual(origin,
PROJECTED_POINT_DISTANCE_EPSILON);
boolean targetLiesOnIntStraight = projPoint2.getPoint().isAlmostEqual(target,
PROJECTED_POINT_DISTANCE_EPSILON);
if (straightsAreColinear && (originLiesOnIntStraight || targetLiesOnIntStraight)) {
heListColinear.add(he);
}
}
for (HalfEdge he : heListColinear) {
for (HalfEdge he : heListCollinear) {
// 1.2) determine if fully or partially or not at all embedded
// create parameter interval of the first projected half edge
Point3d startPoint1 = he.getStraight().getOrigin();
......@@ -491,7 +470,7 @@ public class IntersectPlanarPolygons {
ProjectedPoint3d projP1 = straight.project(startPoint1);
ProjectedPoint3d projP2 = straight.project(endPoint1);
Interval int1 = new Interval(projP1.getParameter(), projP2.getParameter());
for (HalfEdge he2 : heListColinear) {
for (HalfEdge he2 : heListCollinear) {
if (he == he2) {
continue;
}
......@@ -528,7 +507,62 @@ public class IntersectPlanarPolygons {
}
}
private static boolean areStraightsColinear(GmBoundedStraight straight1, GmStraight straight2, double epsilon,
private static List<HalfEdge> getCollinearHalfEdgeList(EdgePolygon p1, EdgePolygon p2, GmStraight straight, double epsilon, double angleEpsilon, List<HalfEdge> heList) {
List<HalfEdge> heListCollinear = new ArrayList<>();
for (HalfEdge he : heList) {
if (isHalfEdgeSharedByPolygons(he, p1, p2)){
// If the HalfEdge is shared, it is not collinear.
// Ignore it and continue with next HalfEdge.
continue;
}
GmBoundedStraight straightHe = he.getStraight();
Point3d origin = straightHe.getOrigin();
Point3d target = straightHe.getTarget();
boolean straightsAreCollinear = IntersectPlanarPolygons.areStraightsCollinear(straightHe, straight, epsilon,
angleEpsilon);
ProjectedPoint3d projPoint1 = straight.project(origin);
ProjectedPoint3d projPoint2 = straight.project(target);
boolean originLiesOnIntStraight = projPoint1.getPoint().isAlmostEqual(origin,
PROJECTED_POINT_DISTANCE_EPSILON);
boolean targetLiesOnIntStraight = projPoint2.getPoint().isAlmostEqual(target,
PROJECTED_POINT_DISTANCE_EPSILON);
if (straightsAreCollinear && (originLiesOnIntStraight || targetLiesOnIntStraight)) {
heListCollinear.add(he);
}
}
return heListCollinear;
}
/**
* Checks whether a specific HalfEdge is shared by two EdgePolygons.
*
*
* @param he The HalfEdge in question
* @param p1 First Polygon
* @param p2 Second Polygon
* @return true if the HalfEdge is shared
*/
private static boolean isHalfEdgeSharedByPolygons(HalfEdge he, EdgePolygon p1, EdgePolygon p2) {
boolean bothPolysShareThisEdge = false;
if (he.getPartner() != null) {
// NOTE: The issue of more than 2 half edges per edge is solved by
// circular pointer, so we have to cycle threw all partners
HalfEdge pPartnerHE = he.getPartner();
while (he != pPartnerHE && !bothPolysShareThisEdge) {
if (pPartnerHE.getPolygon() == p1 || pPartnerHE.getPolygon() == p2) {
bothPolysShareThisEdge = true;
}
pPartnerHE = pPartnerHE.getPartner();
}
}
return bothPolysShareThisEdge;
}
private static boolean areStraightsCollinear(GmBoundedStraight straight1, GmStraight straight2, double epsilon,
double angleEpsilon) {
UnitVector3d rDir1 = straight1.getDir();
......@@ -543,11 +577,8 @@ public class IntersectPlanarPolygons {
ProjectedPoint3d foot1 = straight2.project(rOrigin);
Point3d rTarget = straight1.getTarget();
ProjectedPoint3d foot2 = straight2.project(rTarget);
if ((foot1.getPoint().minus(rOrigin)).getLength() > epsilon
|| (foot2.getPoint().minus(rTarget)).getLength() > epsilon) {
return false;
}
return true;
return !(((foot1.getPoint().minus(rOrigin)).getLength() > epsilon)
|| ((foot2.getPoint().minus(rTarget)).getLength() > epsilon));
}
private static List<PolygonPolygonIntersection> handlePolygonsInSamePlane(GmPlane plane, EdgePolygon p1,
......@@ -577,14 +608,6 @@ public class IntersectPlanarPolygons {
Polygon2d poly2d1 = new Polygon2dNs(poly2dCoords1, true);
Polygon2d poly2d2 = new Polygon2dNs(poly2dCoords2, true);
List<HalfEdge2d> halfEdges = poly2d1.getHalfEdges();
for (HalfEdge2d he : halfEdges) {
if (he.getPartner() == null) {
}
}
halfEdges = poly2d2.getHalfEdges();
List<PolygonPolygonIntersection> result = new ArrayList<>();
List<Polygon2dPolygon2dInt> ppi2ds = IntersectPolygon2d.getIntersections(poly2d1, poly2d2, epsilon);
for (Polygon2dPolygon2dInt ppi2d : ppi2ds) {
......
......@@ -100,11 +100,11 @@ public class IntersectPolygonAndStraight2d {
assignParameterToCorrectList(params[1], intersectionValues, intersectedPolygonPoints);
}
} else {
if (hEStraight.isWithinBoundaries(res.getParamHE())) {
if (hEStraight.isWithinBoundaries(res.paramHE())) {
// Point2d pnt = mIntStraight.evaluate( paramInt );
// cout << "got ( " << pnt.getU() << ", " << pnt.getV() << " ) as int point with
// param " << paramInt << endl;
assignParameterToCorrectList(res.getParamInt(), intersectionValues, intersectedPolygonPoints);
assignParameterToCorrectList(res.paramInt(), intersectionValues, intersectedPolygonPoints);
}
}
}
......@@ -164,11 +164,9 @@ public class IntersectPolygonAndStraight2d {
for (Double d : crIntersectedPolygonPoints) {
boolean pntIsPartOfExistingInterval = false;
for (Interval interval : mIntersectionIntervals) {
if (pntIsPartOfExistingInterval) {
break;
}
if (interval.getStart() == d || interval.getEnd() == d) {
pntIsPartOfExistingInterval = true;
break;
}
}
......
......@@ -18,12 +18,13 @@
*/
package de.hft.stuttgart.citydoctor2.edge;
public class Interval {
private static final Interval INVALID_INTERVAL = new Interval(1, 0);
private double start;
private double end;
private final double start;
private final double end;
public Interval(double start, double end) {
this.start = start;
......
......@@ -18,6 +18,7 @@
*/
package de.hft.stuttgart.citydoctor2.edge;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
......@@ -28,9 +29,7 @@ import de.hft.stuttgart.citydoctor2.datastructure.Polygon;
import de.hft.stuttgart.citydoctor2.math.MovedPolygon;
import de.hft.stuttgart.citydoctor2.math.Vector3d;
public class MeshSurface {
private List<CDPolygonNs> polygons;
public record MeshSurface(List<CDPolygonNs> polygons) {
public static MeshSurface of(Geometry geom) {
List<CDPolygonNs> polygonList = new ArrayList<>();
......@@ -45,12 +44,5 @@ public class MeshSurface {
return new MeshSurface(polygonList);
}
public MeshSurface(List<CDPolygonNs> polygons) {
this.polygons = polygons;
}
public List<CDPolygonNs> getPolygons() {
return polygons;
}
}
......@@ -18,6 +18,7 @@
*/
package de.hft.stuttgart.citydoctor2.edge;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
......@@ -26,7 +27,7 @@ public class MeshSurfaceUtils {
public static List<PolygonPolygonIntersection> selfIntersects(MeshSurface ms, double epsilon, double angleEpsilon) {
Objects.requireNonNull(ms);
List<CDPolygonNs> polygons = ms.getPolygons();
List<CDPolygonNs> polygons = ms.polygons();
List<PolygonPolygonIntersection> intersections = new ArrayList<>();
for (int i = 0; i < polygons.size() - 1; i++) {
EdgePolygon p1 = polygons.get(i);
......
......@@ -20,8 +20,8 @@ package de.hft.stuttgart.citydoctor2.edge;
public class Point2d {
private double x;
private double y;
private final double x;
private final double y;
public Point2d(double x, double y) {
this.x = x;
......
......@@ -18,11 +18,12 @@
*/
package de.hft.stuttgart.citydoctor2.edge;
public class Point3d {
private double x;
private double y;
private double z;
private final double x;
private final double y;
private final double z;
public Point3d(double x, double y, double z) {
this.x = x;
......
......@@ -79,7 +79,7 @@ public class PolyLine extends BaseEntity {
}
public boolean isNullLine() {
return isNullLine(0.00);
return isNullLine(0.0000001);
}
......@@ -88,6 +88,13 @@ public class PolyLine extends BaseEntity {
if (mpFirst == null || mpLast == null) {
return true;
}
// Check if same point object is start and end
if (mpFirst == mpLast){
Point3d start = mpFirst.getStart().getPoint();
Point3d end = mpLast.getEnd().getPoint();
// If start- and endpoint same object: -> not null line, intersection on a vertex
if(start == end) return false;
}
PolyLineSegment currentSegment = mpFirst;
double length = 0.00;
// Add length of all segments, starting from mpFirst
......@@ -108,7 +115,7 @@ public class PolyLine extends BaseEntity {
length += segmentLength;
}
// Check if total length is less than the set tolerance
return length <= tolerance;
return length < tolerance;
}
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment