/*-
* 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 .
*/
package de.hft.stuttgart.citydoctor2.edge;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import de.hft.stuttgart.citydoctor2.datastructure.Polygon;
public class EdgePolygon extends BaseEntity {
private Polygon original;
private List halfEdges;
public EdgePolygon(List halfEdges, Polygon original) {
for (HalfEdge he : halfEdges) {
addChild(he);
}
this.halfEdges = halfEdges;
this.original = original;
}
public Polygon getOriginal() {
return original;
}
public GmPlane getPlane() {
Point3d midPoint = getMidPoint();
List 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 children = getChildren(HalfEdge.class);
for (HalfEdge he : children) {
midPoint = midPoint.plus(he.getStart().getPoint());
}
return (midPoint.div(children.size()));
}
public List getHalfEdges() {
return halfEdges;
}
public List getCoordinates() {
List 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.
*
* 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();
}
}