Commit 5d40c7b6 authored by Matthias Betz's avatar Matthias Betz
Browse files

CityDoctor2 validation open source release

parents
<?xml version="1.0" encoding="UTF-8"?>
<cd:error_report xmlns:cd="http://www.citydoctor.eu"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.citydoctor.eu ../CityDoctorValidation/errorReportSchema.xsd ">
<cd:header>
<cd:file>cd:file</cd:file>
<cd:environment>
<cd:city_doctor_validation_version>cd:city_doctor_validation_version</cd:city_doctor_validation_version>
<cd:java_vm_version>cd:java_vm_version</cd:java_vm_version>
<cd:java_vm_vendor>cd:java_vm_vendor</cd:java_vm_vendor>
<cd:java_version>cd:java_version</cd:java_version>
<cd:os_name>cd:os_name</cd:os_name>
<cd:os_arch>cd:os_arch</cd:os_arch>
</cd:environment>
<cd:date>2001-12-31T12:00:00+01:00</cd:date>
</cd:header>
<cd:validation_plan>
<cd:numberOfRoundingPlaces>8</cd:numberOfRoundingPlaces>
<cd:check activated="true" name="">
<cd:parameter name="">cd:parameter</cd:parameter>
</cd:check>
</cd:validation_plan>
<cd:global_statistics>
<cd:model_statistics>
<cd:num_buildings>0</cd:num_buildings>
<cd:num_vegetation>0</cd:num_vegetation>
<cd:num_transportation>0</cd:num_transportation>
<cd:num_land_objects>0</cd:num_land_objects>
<cd:num_bridge_objects>0</cd:num_bridge_objects>
<cd:num_water_objects>0</cd:num_water_objects>
</cd:model_statistics>
<cd:global_error_statistics>
<cd:num_error_buildings>0</cd:num_error_buildings>
<cd:num_error_vegetation>0</cd:num_error_vegetation>
<cd:num_error_transportation>0</cd:num_error_transportation>
<cd:num_error_land_objects>0</cd:num_error_land_objects>
<cd:num_error_bridge_objects>0</cd:num_error_bridge_objects>
<cd:num_error_water_objects>0</cd:num_error_water_objects>
</cd:global_error_statistics>
<cd:errors>
<cd:error name="">0</cd:error>
</cd:errors>
</cd:global_statistics>
<cd:validation_results>
<cd:building_report gml_id="">
<cd:statistics>
<cd:error_statistics>
<cd:error name="">0</cd:error>
</cd:error_statistics>
</cd:statistics>
<cd:errors>
<cd:error id="" status="ERROR">
<cd:feature feature_type="" gml_id="" />
<cd:error_details />
</cd:error>
</cd:errors>
</cd:building_report>
<cd:vegetation_report gml_id="">
<cd:statistics>
<cd:error_statistics>
<cd:error name="">0</cd:error>
</cd:error_statistics>
</cd:statistics>
<cd:errors>
<cd:error id="" status="ERROR">
<cd:feature feature_type="" gml_id="" />
<cd:error_details />
</cd:error>
</cd:errors>
</cd:vegetation_report>
<cd:transportation_object_report
gml_id="">
<cd:statistics>
<cd:error_statistics>
<cd:error name="">0</cd:error>
</cd:error_statistics>
</cd:statistics>
<cd:errors>
<cd:error id="" status="ERROR">
<cd:feature feature_type="" gml_id="" />
<cd:error_details />
</cd:error>
</cd:errors>
</cd:transportation_object_report>
<cd:land_object_report gml_id="">
<cd:statistics>
<cd:error_statistics>
<cd:error name="">0</cd:error>
</cd:error_statistics>
</cd:statistics>
<cd:errors>
<cd:error id="" status="ERROR">
<cd:feature feature_type="" gml_id="" />
<cd:error_details />
</cd:error>
</cd:errors>
</cd:land_object_report>
<cd:bridge_object_report gml_id="">
<cd:statistics>
<cd:error_statistics>
<cd:error name="">0</cd:error>
</cd:error_statistics>
</cd:statistics>
<cd:errors>
<cd:error id="" status="ERROR">
<cd:feature feature_type="" gml_id="" />
<cd:error_details />
</cd:error>
</cd:errors>
</cd:bridge_object_report>
<cd:water_object_report gml_id="">
<cd:statistics>
<cd:error_statistics>
<cd:error name="">0</cd:error>
</cd:error_statistics>
</cd:statistics>
<cd:errors>
<cd:error id="" status="ERROR">
<cd:feature feature_type="" gml_id="" />
<cd:error_details />
</cd:error>
</cd:errors>
</cd:water_object_report>
</cd:validation_results>
</cd:error_report>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>de.hft.stuttgart</groupId>
<artifactId>CityDoctorParent</artifactId>
<version>3.7.0-SNAPSHOT</version>
</parent>
<artifactId>CityDoctorEdge</artifactId>
<dependencies>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-api</artifactId>
</dependency>
<dependency>
<groupId>de.hft.stuttgart</groupId>
<artifactId>CityDoctorModel</artifactId>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<testFailureIgnore>true</testFailureIgnore>
</configuration>
</plugin>
</plugins>
</build>
</project>
\ No newline at end of file
/*-
* Copyright 2020 Beuth Hochschule für Technik Berlin, Hochschule für Technik Stuttgart
*
* This file is part of CityDoctor2.
*
* CityDoctor2 is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* CityDoctor2 is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with CityDoctor2. If not, see <https://www.gnu.org/licenses/>.
*/
package de.hft.stuttgart.citydoctor2.edge;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
public class BaseEntity {
private List<BaseEntity> parents = new ArrayList<>(2);
private List<BaseEntity> children = new ArrayList<>(2);
public void addChild(BaseEntity e) {
children.add(e);
e.parents.add(this);
}
@SuppressWarnings("unchecked")
public <T> List<T> getParents(Class<T> clazz) {
Set<T> result = new HashSet<>();
for (BaseEntity b : parents) {
if (clazz.isAssignableFrom(b.getClass())) {
result.add((T) b);
}
}
return new ArrayList<>(result);
}
@SuppressWarnings("unchecked")
public <T> List<T> getChildren(Class<T> clazz) {
List<T> result = new ArrayList<>();
for (BaseEntity b : children) {
if (b.getClass() == clazz) {
result.add((T) b);
}
}
return result;
}
public void removeChild(BaseEntity pEntity) {
children.remove(pEntity);
// check for multiple relationships
pEntity.parents.remove(this);
}
}
/*-
* Copyright 2020 Beuth Hochschule für Technik Berlin, Hochschule für Technik Stuttgart
*
* This file is part of CityDoctor2.
*
* CityDoctor2 is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* CityDoctor2 is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with CityDoctor2. If not, see <https://www.gnu.org/licenses/>.
*/
package de.hft.stuttgart.citydoctor2.edge;
public class Box2d {
private Point2d mMin;
private Point2d mMax;
public Box2d(Point2d min, Point2d max) {
mMin = min;
mMax = max;
}
public boolean isPointInside(Point2d crPoint) {
return ( ( crPoint.getX() >= mMin.getX()) &&
( crPoint.getX() <= mMax.getX()) &&
( crPoint.getY() >= mMin.getY()) &&
( crPoint.getY() <= mMax.getY()));
}
}
/*-
* Copyright 2020 Beuth Hochschule für Technik Berlin, Hochschule für Technik Stuttgart
*
* This file is part of CityDoctor2.
*
* CityDoctor2 is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* CityDoctor2 is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with CityDoctor2. If not, see <https://www.gnu.org/licenses/>.
*/
package de.hft.stuttgart.citydoctor2.edge;
import java.util.ArrayList;
import java.util.List;
public class CDPolygonNs extends PolygonNs {
private List<List<HalfEdge>> innerHalfEdges = new ArrayList<>();
public CDPolygonNs(List<List<HalfEdge>> halfEdges) {
super(halfEdges.get(0));
for (int i = 1; i < halfEdges.size(); i++) {
List<HalfEdge> loopEdges = halfEdges.get(i);
for (HalfEdge e : loopEdges) {
addChild(e);
}
innerHalfEdges.add(loopEdges);
}
}
public List<List<HalfEdge>> getInnerHalfEdges() {
return innerHalfEdges;
}
}
/*-
* Copyright 2020 Beuth Hochschule für Technik Berlin, Hochschule für Technik Stuttgart
*
* This file is part of CityDoctor2.
*
* CityDoctor2 is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* CityDoctor2 is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with CityDoctor2. If not, see <https://www.gnu.org/licenses/>.
*/
package de.hft.stuttgart.citydoctor2.edge;
public class Coordinate2d extends BaseEntity {
private Point2d point;
public Coordinate2d(Point2d point) {
this.point = point;
}
public Point2d getPoint() {
return point;
}
public void setPoint(Point2d point) {
this.point = point;
}
@Override
public String toString() {
return "Coordinate2d [point=" + point + "]";
}
}
/*-
* Copyright 2020 Beuth Hochschule für Technik Berlin, Hochschule für Technik Stuttgart
*
* This file is part of CityDoctor2.
*
* CityDoctor2 is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* CityDoctor2 is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with CityDoctor2. If not, see <https://www.gnu.org/licenses/>.
*/
package de.hft.stuttgart.citydoctor2.edge;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
public class Coordinate3d extends BaseEntity {
private Point3d point;
public Coordinate3d(Point3d point) {
this.point = point;
}
public Coordinate3d(double x, double y, double z) {
this(new Point3d(x, y, z));
}
public Point3d getPoint() {
return point;
}
public List<EdgePolygon> getPolygons() {
List<HalfEdge> halfEdges = getParents(HalfEdge.class);
Set<EdgePolygon> polygons = new HashSet<>();
for (HalfEdge he : halfEdges) {
List<EdgePolygon> localPolygons = he.getParents(EdgePolygon.class);
polygons.addAll(localPolygons);
}
return new ArrayList<>(polygons);
}
@Override
public String toString() {
return "Coordinate3d [point=" + point + "]";
}
}
/*-
* Copyright 2020 Beuth Hochschule für Technik Berlin, Hochschule für Technik Stuttgart
*
* This file is part of CityDoctor2.
*
* CityDoctor2 is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* CityDoctor2 is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with CityDoctor2. If not, see <https://www.gnu.org/licenses/>.
*/
package de.hft.stuttgart.citydoctor2.edge;
import java.text.NumberFormat;
import java.util.IdentityHashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger;
public class DebugUtils {
private static AtomicInteger polygon3dCounter = new AtomicInteger(1);
private static AtomicInteger coordListCounter = new AtomicInteger(1);
private DebugUtils() {
}
public static void printPolyLineSegment2dList(List<PolyLineSegment2d> rSegments) {
Locale.setDefault(Locale.US);
for (PolyLineSegment2d seg : rSegments) {
Point2d start = seg.getStart().getPoint();
Point2d end = seg.getEnd().getPoint();
System.out.println(String.format(
"segmentList.push_back(new PolyLineSegment2d(new Coordinate2d(%f, %f), new Coordinate2d(%f, %f)));",
start.getX(), start.getY(), end.getX(), end.getY()));
}
}
public static void printPolygon2d(Polygon2d mcpPolygon1) {
Locale.setDefault(Locale.US);
System.out.println("Coordinate2dList coords;");
HalfEdge2d firstHalfEdge = mcpPolygon1.getFirstHalfEdge();
Point2d start = firstHalfEdge.getStart().getPoint();
System.out.println(String.format("coords.push_back(new Coordinate2d(%f, %f));", start.getX(), start.getY()));
HalfEdge2d next = firstHalfEdge.getNext();
while (next != null && next != firstHalfEdge) {
start = next.getStart().getPoint();
System.out.println(String.format("coords.push_back(new Coordinate2d(%f, %f));", start.getX(), start.getY()));
next = next.getNext();
}
System.out.println("Polygon2d* mcpPolygon1 = new Polygon2dNs(coords);");
}
public static void printPolygon3d(EdgePolygon p) {
Locale.setDefault(Locale.US);
int counter = polygon3dCounter.getAndIncrement();
System.out.println("Coordinate3dList coords" + counter + ";");
HalfEdge firstHalfEdge = p.getFirstHalfEdge();
Point3d start = firstHalfEdge.getStart().getPoint();
System.out.println(String.format("coords%d.push_back(new Coordinate3d(%f, %f, %f));", counter, start.getX(), start.getY(), start.getZ()));
HalfEdge next = firstHalfEdge.getNext();
while (next != null && next != firstHalfEdge) {
start = next.getStart().getPoint();
System.out.println(String.format("coords%d.push_back(new Coordinate3d(%f, %f, %f));", counter, start.getX(), start.getY(), start.getZ()));
next = next.getNext();
}
System.out.println("PolygonNs* p" + counter + " = new PolygonNs(coords" + counter+ ");");
}
public static void printPolygon3d(CDPolygonNs edgePoly1, CDPolygonNs edgePoly2) {
Locale.setDefault(Locale.US);
Map<Point3d, String> pointMap = new IdentityHashMap<>();
int startCounter = 1;
startCounter = printPolygon3d(edgePoly1, pointMap, startCounter);
printPolygon3d(edgePoly2, pointMap, startCounter);
}
public static void printGeoknechtPolygon(CDPolygonNs... polys) {
Locale.setDefault(Locale.US);
NumberFormat nf = NumberFormat.getNumberInstance();
nf.setMaximumFractionDigits(30);
for (CDPolygonNs poly : polys) {
List<Coordinate3d> coordinates = poly.getCoordinates();
System.out.print("polygon(");
for (Coordinate3d coord : coordinates) {
Point3d point = coord.getPoint();
writeGeoknechtPoint(nf, point);
}
writeGeoknechtPoint(nf, coordinates.get(0).getPoint());
System.out.println(")");
for (List<HalfEdge> innerRing : poly.getInnerHalfEdges()) {
System.out.print("polygon(");
for (HalfEdge he : innerRing) {
Point3d point = he.getStart().getPoint();
writeGeoknechtPoint(nf, point);
}
writeGeoknechtPoint(nf, innerRing.get(innerRing.size() - 1).getEnd().getPoint());
System.out.println(")");
}
}
}
private static void writeGeoknechtPoint(NumberFormat nf, Point3d point) {
System.out.print(nf.format(point.getX()));
System.out.print("|");
System.out.print(nf.format(point.getY()));
System.out.print("|");
System.out.print(nf.format(point.getZ()));
System.out.print(" ");
}
private static int printPolygon3d(CDPolygonNs p, Map<Point3d, String> pointMap, int startCounter) {
NumberFormat nf = NumberFormat.getNumberInstance();
nf.setMaximumFractionDigits(30);
int counter = polygon3dCounter.getAndIncrement();
int listCounter = coordListCounter.getAndIncrement();
int firstListCounter = listCounter;
HalfEdge firstHalfEdge = p.getFirstHalfEdge();
int[] counterArr = new int[] {startCounter};
System.out.println("Coordinate3dList coords" + firstListCounter + ";");
writeRing(pointMap, nf, listCounter, firstHalfEdge, counterArr);
for (List<HalfEdge> innerRing : p.getInnerHalfEdges()) {
listCounter = coordListCounter.getAndIncrement();
System.out.println("Coordinate3dList coords" + listCounter + ";");
writeRing(pointMap, nf, listCounter, innerRing.get(0), counterArr);
}
int lastListCounter = coordListCounter.get();
System.out.println("std::list<Coordinate3dList> coordLists" + counter + ";");
for (int i = firstListCounter; i < lastListCounter; i++) {
System.out.println("coordLists" + counter + ".push_back(coords" + i +");");
}
System.out.println("CDPolygonNs* p" + counter + " = new CDPolygonNs(coordLists" + counter+ ");");
return counterArr[0];
}
private static void writeRing(Map<Point3d, String> pointMap, NumberFormat nf, int counter, HalfEdge firstHalfEdge,
int[] counterArr) {
final Point3d start = firstHalfEdge.getStart().getPoint();
String coordVarName = getCoordName(pointMap, nf, start, counterArr);
System.out.println(String.format("coords%d.push_back(%s);", counter, coordVarName));
HalfEdge next = firstHalfEdge.getNext();
while (next != null && next != firstHalfEdge) {
Point3d nextPoint = next.getStart().getPoint();
coordVarName = getCoordName(pointMap, nf, nextPoint, counterArr);
System.out.println(String.format("coords%d.push_back(%s);", counter, coordVarName));
next = next.getNext();
}
}
private static String getCoordName(Map<Point3d, String> pointMap, NumberFormat nf, final Point3d start,
int[] counterArr) {
String coordVarName = pointMap.computeIfAbsent(start, k -> {
System.out.println(String.format("Coordinate3d* c%d = new Coordinate3d(%s, %s, %s);", counterArr[0], nf.format(start.getX()), nf.format(start.getY()), nf.format(start.getZ())));
String name = "c" + counterArr[0];
counterArr[0]++;
return name;
});
return coordVarName;
}
}
/*-
* Copyright 2020 Beuth Hochschule für Technik Berlin, Hochschule für Technik Stuttgart
*
* This file is part of CityDoctor2.
*
* CityDoctor2 is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* CityDoctor2 is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with CityDoctor2. If not, see <https://www.gnu.org/licenses/>.
*/
package de.hft.stuttgart.citydoctor2.edge;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
public class EdgePolygon extends BaseEntity {
private List<HalfEdge> halfEdges;
public EdgePolygon(List<HalfEdge> halfEdges) {
for (HalfEdge he : halfEdges) {
addChild(he);
}
this.halfEdges = halfEdges;
}
public GmPlane getPlane() {
Point3d midPoint = getMidPoint();
List<HalfEdge> children = getChildren(HalfEdge.class);
Vector3d averageNormalVector = new Vector3d(0.0, 0.0, 0.0);
for (HalfEdge he : children) {
Point3d start = he.getStart().getPoint();
Point3d end = he.getEnd().getPoint();
Vector3d mid2Start = start.minus(midPoint);
Vector3d mid2End = end.minus(midPoint);
averageNormalVector = averageNormalVector.plus(mid2Start.cross(mid2End));
}
UnitVector3d normalVector = averageNormalVector.toUnitVector();
return new GmPlane(midPoint, normalVector);
}
private Point3d getMidPoint() {
Point3d midPoint = new Point3d(0, 0, 0);
List<HalfEdge> children = getChildren(HalfEdge.class);
for (HalfEdge he : children) {
midPoint = midPoint.plus(he.getStart().getPoint());
}
return (midPoint.div(children.size()));
}
public List<HalfEdge> getHalfEdges() {
return halfEdges;
}
public List<Coordinate3d> getCoordinates() {
List<Coordinate3d> coords = new ArrayList<>();
HalfEdge firstHE = Objects.requireNonNull(getFirstHalfEdge());
HalfEdge currHE = firstHE;
do {
coords.add(currHE.getStart());
currHE = currHE.getNext();
} while (currHE != firstHE);
return coords;
}
public HalfEdge getFirstHalfEdge() {
if (!halfEdges.isEmpty()) {
return halfEdges.get(0);
}
return null;
}
/**
* Test whether the given point is lying in- or outside of 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
*
* @param rcPoint The point that should be checked
*
* @return true, if the point is inside the polygon, false otherwise
*
*/
public boolean isPointInsidePolygon(Point3d rcPoint, double eps) {
// Project the coordinate of the point on the plane
GmPlane plane = getPlane();
Point2d projectedPoint = plane.project(rcPoint);
Polygon2d pP = plane.projectOn2dPolygon(this);
return pP.isPointInsidePolygon(projectedPoint, eps);
}
public int getNrHalfEdges() {
return halfEdges.size();
}
}
/*-
* Copyright 2020 Beuth Hochschule für Technik Berlin, Hochschule für Technik Stuttgart
*
* This file is part of CityDoctor2.
*
* CityDoctor2 is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* CityDoctor2 is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with CityDoctor2. If not, see <https://www.gnu.org/licenses/>.
*/
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 * 100;
private static double mTolPointsEqual = 1e-3;
private Global() {
}
public static double getTolPointsEquals() {
return mTolPointsEqual;
}
public static double getHighAccuracyTolerance() {
return mHighAccuracyTol;
}
public static Comparator<Double> getDoubleTolCompare(double epsilon) {
return (v1, v2) -> {
double dif = v1 - v2;
if (Math.abs(dif) < epsilon) {
return 0;
}
return Double.compare(v1, v2);
};
}
public static double getZeroAngleCosinus() {
return mZeroAngleCosinus;
}
public static double getTolVectorsParallel() {
return mTolVectorsParallel;
}
}
/*-
* Copyright 2020 Beuth Hochschule für Technik Berlin, Hochschule für Technik Stuttgart
*
* This file is part of CityDoctor2.
*
* CityDoctor2 is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* CityDoctor2 is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with CityDoctor2. If not, see <https://www.gnu.org/licenses/>.
*/
package de.hft.stuttgart.citydoctor2.edge;
public class GmBoundedStraight extends GmStraight {
private Point3d target;
private double length;
public static GmBoundedStraight of(Point3d point, Vector3d vector) {
GmBoundedStraight straight = new GmBoundedStraight(point, vector.toUnitVector());
straight.length = vector.getLength();
straight.target = point.plus(vector);
return straight;
}
public static GmBoundedStraight of(Point3d start, Point3d end) {
Vector3d vec = end.minus(start);
UnitVector3d dir = vec.toUnitVector();
GmBoundedStraight straight = new GmBoundedStraight(start, dir);
straight.target = end;
straight.length = vec.getLength();
return straight;
}
private GmBoundedStraight(Point3d start, UnitVector3d dir) {
super(start, dir);
}
public Point3d getTarget() {
return target;
}
public double getLength() {
return length;
}
}
/*-
* Copyright 2020 Beuth Hochschule für Technik Berlin, Hochschule für Technik Stuttgart
*
* This file is part of CityDoctor2.
*
* CityDoctor2 is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* CityDoctor2 is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with CityDoctor2. If not, see <https://www.gnu.org/licenses/>.
*/
package de.hft.stuttgart.citydoctor2.edge;
public class GmBoundedStraight2d extends GmStraight2d {
private double length;
private Point2d target;
public static GmBoundedStraight2d of(Point2d start, Vector2d dir) {
GmBoundedStraight2d straight = new GmBoundedStraight2d(start, dir);
straight.target = straight.getOrigin().plus(dir);
straight.length = dir.getLength();
return straight;
}
public static GmBoundedStraight2d of(Point2d from, Point2d to) {
Vector2d dir = to.minus(from);
GmBoundedStraight2d straight = new GmBoundedStraight2d(from, dir);
straight.target = to;
straight.length = dir.getLength();
return straight;
}
private GmBoundedStraight2d(Point2d start, Vector2d dir) {
super(start, dir);
}
public Point2d getTarget() {
return target;
}
public boolean isWithinBoundaries(double parameter, double eps) {
if (Math.abs(parameter) < eps) {
parameter = 0.0;
}
if (Math.abs(parameter - length) < eps) {
parameter = length;
}
if (0 <= parameter && parameter <= length) {
return true;
}
return false;
}
public double getLength() {
return length;
}
public boolean isWithinBoundaries(double parameter) {
return isWithinBoundaries(parameter, Global.getHighAccuracyTolerance());
}
}
/*-
* Copyright 2020 Beuth Hochschule für Technik Berlin, Hochschule für Technik Stuttgart
*
* This file is part of CityDoctor2.
*
* CityDoctor2 is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* CityDoctor2 is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with CityDoctor2. If not, see <https://www.gnu.org/licenses/>.
*/
package de.hft.stuttgart.citydoctor2.edge;
import java.util.ArrayList;
import java.util.List;
public class GmPlane {
private Point3d x0;
private UnitVector3d r1;
private UnitVector3d r2;
private UnitVector3d n;
private 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();
// r1 ist nicht in allen Faellen rechtwinklig zur Flaechennormalen
// daher nochmal eine neu Berechnung;
// ----------------------------------------------------------------
r1 = n.cross(r2).toUnitVector();
}
public double getDistance() {
return d;
}
public Vector3d getNormal() {
return n;
}
public Point3d evaluate(Point2d point) {
return evaluate(point.getX(), point.getY());
}
private Point3d evaluate(double x, double y) {
Vector3d vectorU = r1.mult(x);
Vector3d vectorV = r2.mult(y);
return new Point3d(x0.plus(vectorU).plus(vectorV));
}
public GmStraight2d projectOn2dStraight(GmStraight crStraight) {
Point2d start = project(crStraight.getOrigin());
Point2d end = project(crStraight.getOrigin().plus(crStraight.getDir()));
return new GmStraight2d(start, end);
}
public GmBoundedStraight2d projectOn2dStraight(GmBoundedStraight crBoundedStraight) {
Point2d start = project(crBoundedStraight.getOrigin());
Point2d end = project(crBoundedStraight.getTarget());
return GmBoundedStraight2d.of(start, end);
}
public Point2d project(Point3d crPoint) {
GmStraight firstAxis = new GmStraight(x0, r1);
GmStraight secondAxis = new GmStraight(x0, r2);
double u = firstAxis.project(crPoint).getParameter();
double v = secondAxis.project(crPoint).getParameter();
return new Point2d(u, v);
}
public GmStraight planeIntersection(GmPlane other) {
// get plane normals and distances
// -------------------------------
Vector3d normal1 = getNormal();
Vector3d normal2 = other.getNormal();
double dist1 = getDistance();
double dist2 = other.getDistance();
// planes (normal vectors) parallel? -> good bye
// ---------------------------------------------
if (Vector3d.areParallel(normal1, normal2) || Vector3d.areAntiParallel(normal1, normal2)) {
return null; // but rSuccess is false
}
// get direction and origin for straight
// -------------------------------------
Vector3d dir = normal1.cross(normal2);
Matrix3d matrix = new Matrix3d();
matrix.set(0, 0, normal1.getX());
matrix.set(0, 1, normal1.getY());
matrix.set(0, 2, normal1.getZ());
matrix.set(1, 0, normal2.getX());
matrix.set(1, 1, normal2.getY());
matrix.set(1, 2, normal2.getZ());
matrix.set(2, 0, dir.getX());
matrix.set(2, 1, dir.getY());
matrix.set(2, 2, dir.getZ());
double[] b = new double[] { dist1, dist2, 0.0 };
double[] org = new double[3];
matrix.gauss(b, org);
return new GmStraight(new Point3d(org), dir);
}
public Polygon2d projectOn2dPolygon(EdgePolygon cpPolygon) {
HalfEdge startHE = cpPolygon.getFirstHalfEdge();
HalfEdge currHE = startHE;
int numHEs = cpPolygon.getNrHalfEdges();
Coordinate2d[] coords = new Coordinate2d[numHEs];
int i = 0;
do {
Coordinate3d coord = currHE.getStart();
Point2d p = project(coord.getPoint());
coords[i++] = new Coordinate2d(p);
currHE = currHE.getNext();
} while (currHE != startHE);
List<HalfEdge2d> halfedges = new ArrayList<>();
for (i = 0; i < numHEs; ++i) {
HalfEdge2d he = new HalfEdge2d(coords[i], coords[(i + 1) % (numHEs)]);
halfedges.add(he);
}
return new Polygon2d(halfedges);
}
}
/*-
* Copyright 2020 Beuth Hochschule für Technik Berlin, Hochschule für Technik Stuttgart
*
* This file is part of CityDoctor2.
*
* CityDoctor2 is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* CityDoctor2 is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with CityDoctor2. If not, see <https://www.gnu.org/licenses/>.
*/
package de.hft.stuttgart.citydoctor2.edge;
public class GmStraight {
private Point3d org;
private UnitVector3d dir;
public GmStraight(Point3d org, Vector3d dir) {
this.org = org;
this.dir = dir.toUnitVector();
}
public GmStraight(Point3d org, UnitVector3d dir) {
this.org = org;
this.dir = dir;
}
public ProjectedPoint3d project(Point3d origin) {
Vector3d v2Origin = origin.minus(org);
double length = v2Origin.getLength();
if (length < Global.getTolPointsEquals()) {
return new ProjectedPoint3d(origin, 0.0);
}
double parameter = dir.dot(UnitVector3d.of(v2Origin)) * length;
Point3d foot = evaluate(parameter);
return new ProjectedPoint3d(foot, parameter);
}
public Point3d evaluate(double param) {
return org.plus(dir.mult(param));
}
public UnitVector3d getDir() {
return dir;
}
public boolean isColinear(GmStraight straight2, double angleEpsilon, double epsilon) {
UnitVector3d rDir1 = getDir();
UnitVector3d rDir2 = straight2.getDir();
if ((!Vector3d.areParallel(rDir1, rDir2, angleEpsilon))
&& (!Vector3d.areAntiParallel(rDir1, rDir2, angleEpsilon))) {
return false;
}
Point3d rOrigin1 = getOrigin();
Point3d foot1 = straight2.project(rOrigin1).getPoint();
if ((foot1.minus(rOrigin1)).getLength() > epsilon) {
return false;
}
Point3d rOrigin2 = straight2.getOrigin();
Point3d foot2 = project(rOrigin2).getPoint();
if ((foot2.minus(rOrigin2)).getLength() > epsilon) {
return false;
}
return true;
}
public Point3d getOrigin() {
return org;
}
}
/*-
* Copyright 2020 Beuth Hochschule für Technik Berlin, Hochschule für Technik Stuttgart
*
* This file is part of CityDoctor2.
*
* CityDoctor2 is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* CityDoctor2 is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with CityDoctor2. If not, see <https://www.gnu.org/licenses/>.
*/
package de.hft.stuttgart.citydoctor2.edge;
public class GmStraight2d {
private Point2d origin;
private UnitVector2d direction;
public GmStraight2d(Point2d org, UnitVector2d dir) {
this.direction = dir;
this.origin = org;
}
public GmStraight2d(Point2d org, Vector2d dir) {
this.origin = org;
this.direction = dir.normalize();
}
public GmStraight2d(Point2d from, Point2d to) {
origin = from;
direction = to.minus(from).normalize();
}
/**
* Just intersects two GmStraights2d.
*
* <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
*
* @param other First Straight
*
* @return intersection result
*/
public GmStraight2dIntersectionResult intersect(GmStraight2d other) {
Point2d p1 = origin;
UnitVector2d r1 = direction;
Point2d p2 = other.getOrigin();
UnitVector2d r2 = other.getDirection();
Vector2d q = p2.minus(p1);
Vector2d r2Perpendicular = r2.getPerpendicularVector();
double diff = r1.dot(r2Perpendicular);
if (Math.abs(diff) < Global.getZeroAngleCosinus()) {
return GmStraight2dIntersectionResult.parallel(this, other);
} else {
double invR1DotPerpR2 = 1.0 / diff;
double qDotPerpR1 = q.dot(r1.getPerpendicularVector());
double qDotPerpR2 = q.dot(r2Perpendicular);
double rParam1 = qDotPerpR2 * invR1DotPerpR2;
double rParam2 = qDotPerpR1 * invR1DotPerpR2;
return GmStraight2dIntersectionResult.intersecting(rParam1, rParam2, this, other);
}
}
public UnitVector2d getDirection() {
return direction;
}
public Point2d getOrigin() {
return origin;
}
public Point2d evaluate(double param) {
return origin.plus(direction.mult(param));
}
@Override
public String toString() {
return "GmStraight2d [origin=" + origin + ", direction=" + direction + "]";
}
}
/*-
* Copyright 2020 Beuth Hochschule für Technik Berlin, Hochschule für Technik Stuttgart
*
* This file is part of CityDoctor2.
*
* CityDoctor2 is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* CityDoctor2 is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with CityDoctor2. If not, see <https://www.gnu.org/licenses/>.
*/
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 static GmStraight2dIntersectionResult parallel(GmStraight2d s1, GmStraight2d s2) {
return new GmStraight2dIntersectionResult(0, 0, s1, s2, true);
}
public static GmStraight2dIntersectionResult intersecting(double rParam1, double rParam2, GmStraight2d s1,
GmStraight2d s2) {
return new GmStraight2dIntersectionResult(rParam1, rParam2, s1, s2, 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;
}
}
/*-
* Copyright 2020 Beuth Hochschule für Technik Berlin, Hochschule für Technik Stuttgart
*
* This file is part of CityDoctor2.
*
* CityDoctor2 is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* CityDoctor2 is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with CityDoctor2. If not, see <https://www.gnu.org/licenses/>.
*/
package de.hft.stuttgart.citydoctor2.edge;
import java.util.List;
public class HalfEdge extends BaseEntity {
private Coordinate3d start;
private Coordinate3d end;
private HalfEdge partner;
private HalfEdge next;
public HalfEdge(Coordinate3d start, Coordinate3d end, EdgePolygon parent) {
this.start = start;
this.end = end;
List<HalfEdge> halfEdgesToStart = start.getParents(HalfEdge.class);
List<HalfEdge> halfEdgesToEnd = end.getParents(HalfEdge.class);
HalfEdge tempPartner;
if (parent == null) {
tempPartner = findPartner(halfEdgesToStart, halfEdgesToEnd);
} else {
tempPartner = findPartner(parent, halfEdgesToStart, halfEdgesToEnd);
}
if (tempPartner != null) {
setPartner(tempPartner);
}
addChild(start);
addChild(end);
}
public HalfEdge(Coordinate3d start, Coordinate3d end) {
this(start, end, null);
}
private HalfEdge findPartner(EdgePolygon parent, List<HalfEdge> halfEdgesToStart, List<HalfEdge> halfEdgesToEnd) {
HalfEdge tempPartner = null;
for (HalfEdge heStart : halfEdgesToStart) {
for (HalfEdge heEnd : halfEdgesToEnd) {
if (heStart == heEnd) {
tempPartner = heStart;
if (tempPartner.getPartner() == null) {
EdgePolygon partnerParent = tempPartner.getPolygon();
if (partnerParent != null || partnerParent != parent) {
return tempPartner;
}
}
}
}
}
return tempPartner;
}
private HalfEdge findPartner(List<HalfEdge> halfEdgesToStart, List<HalfEdge> halfEdgesToEnd) {
HalfEdge tempPartner = null;
for (HalfEdge heStart : halfEdgesToStart) {
for (HalfEdge heEnd : halfEdgesToEnd) {
if (heStart == heEnd) {
tempPartner = heStart;
if (tempPartner.getPartner() == null) {
EdgePolygon partnerParent = tempPartner.getPolygon();
if (partnerParent != null) {
return tempPartner;
}
}
}
}
}
return tempPartner;
}
public void setPartner(HalfEdge partner) {
this.partner = partner;
partner.partner = this;
}
public HalfEdge getPartner() {
return partner;
}
public EdgePolygon getPolygon() {
List<EdgePolygon> polygons = getParents(EdgePolygon.class);
if (!polygons.isEmpty()) {
return polygons.get(0);
}
return null;
}
public GmBoundedStraight getStraight() {
return GmBoundedStraight.of(start.getPoint(), end.getPoint());
}
public Coordinate3d getStart() {
return start;
}
public Coordinate3d getEnd() {
return end;
}
public HalfEdge getNext() {
return next;
}
public void setNext(HalfEdge next) {
this.next = next;
}
@Override
public String toString() {
return "HalfEdge [start=" + start + ", end=" + end + "]";
}
}
/*-
* Copyright 2020 Beuth Hochschule für Technik Berlin, Hochschule für Technik Stuttgart
*
* This file is part of CityDoctor2.
*
* CityDoctor2 is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* CityDoctor2 is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with CityDoctor2. If not, see <https://www.gnu.org/licenses/>.
*/
package de.hft.stuttgart.citydoctor2.edge;
import java.util.List;
public class HalfEdge2d extends BaseEntity {
private Coordinate2d start;
private Coordinate2d end;
private HalfEdge2d partner;
private HalfEdge2d next;
private HalfEdge2d previous;
public HalfEdge2d(Coordinate2d c1, Coordinate2d c2) {
this(c1, c2, false);
}
public HalfEdge2d(Coordinate2d pStart, Coordinate2d pEnd, boolean setPartner) {
start = pStart;
end = pEnd;
if (setPartner) {
List<HalfEdge2d> halfEdgesToStart = pStart.getParents(HalfEdge2d.class);
List<HalfEdge2d> halfEdgesToEnd = pEnd.getParents(HalfEdge2d.class);
HalfEdge2d pPartner = findPartner(halfEdgesToStart, halfEdgesToEnd);
if (pPartner != null) {
setPartner(pPartner);
}
} else {
partner = null;
}
addChild(start);
addChild(end);
}
private HalfEdge2d findPartner(List<HalfEdge2d> halfEdgesToStart, List<HalfEdge2d> halfEdgesToEnd) {
HalfEdge2d pPartner = null;
for (HalfEdge2d heStart : halfEdgesToStart) {
for (HalfEdge2d heEnd : halfEdgesToEnd) {
if (heStart == heEnd) {
pPartner = heStart;
if (pPartner.getPartner() == null) {
return pPartner;
}
}
}
}
return pPartner;
}
private HalfEdge2d setPartner(HalfEdge2d pPartner) {
if (partner != null) {
if (pPartner != null) {
throw new IllegalStateException("cannot overwrite existing partner-connection");
} else {
// remove the existing connection
partner.partner = null;
partner = null;
}
} else {
if (pPartner != null) {
if (pPartner.partner != null) {
// TODO : das riecht nach einer Ringverzeigerung : 3 Polygonraender treffen
// aufeinander
throw new IllegalStateException("cannot overwrite existing partner-connection");
} else {
partner = pPartner;
pPartner.partner = this;
}
}
}
return pPartner;
}
public HalfEdge2d getPartner() {
return partner;
}
public void setNext(HalfEdge2d next) {
this.next = next;
}
public void setPrevious(HalfEdge2d previous) {
this.previous = previous;
}
public Polygon2d getPolygon() {
List<Polygon2d> parents = getParents(Polygon2d.class);
if (!parents.isEmpty()) {
return parents.get(0);
}
return null;
}
public GmBoundedStraight2d getStraight() {
return GmBoundedStraight2d.of(start.getPoint(), end.getPoint());
}
public Coordinate2d getStart() {
return start;
}
public HalfEdge2d getNext() {
return next;
}
public Coordinate2d getEnd() {
return end;
}
public HalfEdge2d getPrevious() {
return previous;
}
@Override
public String toString() {
return "HalfEdge2d [start=" + start + ", end=" + end + "]";
}
}
Markdown is supported
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