Commit f6178c6a authored by Benedikt Zoennchen's avatar Benedikt Zoennchen
Browse files

software architecture improvement for the triangulation

parent eb52371f
......@@ -196,8 +196,8 @@ public abstract class DefaultModel<T extends DefaultConfig> extends Observable i
* if (scaleFactor < MAX_SCALE_FACTOR) {
* double w = getViewportBound().width / 1.2;
* double h = getViewportBound().height / 1.2;
* double x = Math.max(0, cursorWorldPosition.x - w / 2);
* double y = Math.max(0, cursorWorldPosition.y - h / 2);
* double x = Math.bound(0, cursorWorldPosition.x - w / 2);
* double y = Math.bound(0, cursorWorldPosition.y - h / 2);
* setViewportBound(new VRectangle(x, y, w, h));
* return true;
* }
......@@ -209,9 +209,9 @@ public abstract class DefaultModel<T extends DefaultConfig> extends Observable i
* double w = Math.min(getTopographyBound().getWidth(), viewportBound.width * 1.2);
* double h = Math.min(getTopographyBound().getWidth(), viewportBound.height * 1.2);
*
* double x = Math.max(0, Math.min(cursorWorldPosition.x - w / 2,
* double x = Math.bound(0, Math.min(cursorWorldPosition.x - w / 2,
* getTopographyBound().getWidth() - w));
* double y = Math.max(0, Math.min(cursorWorldPosition.y - h / 2,
* double y = Math.bound(0, Math.min(cursorWorldPosition.y - h / 2,
* getTopographyBound().getHeight() - h));
* setViewportBound(new VRectangle(x, y, w, h));
* return true;
......
......@@ -56,7 +56,7 @@ public class CLGaussianCalculator {
int maxColorValue = 255 * 255 * 255;
ColorHelper colorHelper = new ColorHelper(maxColorValue);
// double max = filter.getMaxFilteredValue();
// double bound = filter.getMaxFilteredValue();
double max = 1.00;
double factor = maxColorValue / max;
System.out.println(filterPedestrians.getMaxFilteredValue()); // 0.1259
......
......@@ -114,7 +114,7 @@ public abstract class DefaultRenderer {
double dy = topographyBound.getHeight() - viewportBound.getHeight();
graphics2D.translate(-viewportBound.getX(), Math.max((dy - viewportBound.getY()), 0));
// graphics2D.translate(+viewportBound.getX(), -Math.max((dy - viewportBound.getY()), 0));
// graphics2D.translate(+viewportBound.getX(), -Math.bound((dy - viewportBound.getY()), 0));
}
......
......@@ -332,7 +332,7 @@ public class TopographyCreatorModel extends DefaultModel implements IDrawPanelMo
@Override
public VShape translateElement(ScenarioElement element, VPoint vector) {
// double factor = Math.max(10,1/getGridResulution()); // ?? related to scaleTopography?
// double factor = Math.bound(10,1/getGridResulution()); // ?? related to scaleTopography?
return element.getShape().translatePrecise(alignToGrid(vector));
}
......
......@@ -79,8 +79,8 @@ public class TestPedestrianGaussianFilter {
for (double y = 0; y <= topographyBounds.getHeight() - 1; y += dy) {
assertTrue(maxDensity >= clFilter.getFilteredValue(x, y) - 0.1);
double exactDensity = calculateExactDensity(new VPoint(x, y), pedestriansMaxPacked, 0.7);
maxAbsErrorCL = Math.max(maxAbsErrorCL, Math.abs((clFilter.getFilteredValue(x, y) - exactDensity)));
maxRelErrorCL = Math.max(maxRelErrorCL,
maxAbsErrorCL = Math.bound(maxAbsErrorCL, Math.abs((clFilter.getFilteredValue(x, y) - exactDensity)));
maxRelErrorCL = Math.bound(maxRelErrorCL,
Math.abs((clFilter.getFilteredValue(x, y) - exactDensity)) / exactDensity);
// System.out.println("abs. cl-error:" + (clFilter.getFilteredValue(x, y) -
// exactDensity));
......
......@@ -128,7 +128,7 @@ public class Trajectory {
* }
* else {
* Optional<Step> optionalStep = sortedSteps.stream().filter(s -> s.getStepNumber() <=
* step.getStepNumber()).max((Step::compareTo));
* step.getStepNumber()).bound((Step::compareTo));
* if(optionalStep.isPresent()) {
* optionalPedestrian = Optional.of(trajectoryPoints.get(optionalStep.get()));
* }
......
......@@ -12,6 +12,7 @@ import org.vadere.util.geometry.shapes.VCircle;
import org.vadere.util.geometry.shapes.VLine;
import org.vadere.util.geometry.shapes.VPoint;
import org.vadere.util.geometry.shapes.VPolygon;
import org.vadere.util.geometry.shapes.VRectangle;
import org.vadere.util.geometry.shapes.VShape;
import org.vadere.util.geometry.shapes.VTriangle;
......@@ -265,6 +266,22 @@ public class GeometryUtils {
return (p1.getX() - p3.getX()) * (p2.getY() - p3.getY()) - (p2.getX() - p3.getX()) * (p1.getY() - p3.getY());
}
public static double sign(final double x1, final double y1, final double x2, final double y2, final double x3, final double y3) {
return (x1 - x3) * (y2 - y3) - (x2 -x3) * (y1 - y3);
}
public static <P extends IPoint> VRectangle bound(final Collection<P> points) {
if(points.isEmpty()) {
throw new IllegalArgumentException("the point collection is empty.");
}
VPoint pMax = points.stream().map(p -> new VPoint(p.getX(), p.getY())).reduce((p1, p2) -> new VPoint(Math.max(p1.getX(), p2.getX()), Math.max(p1.getY(), p2.getY()))).get();
VPoint pMin = points.stream().map(p -> new VPoint(p.getX(), p.getY())).reduce((p1, p2) -> new VPoint(Math.min(p1.getX(), p2.getX()), Math.min(p1.getY(), p2.getY()))).get();
return new VRectangle(pMin.getX(), pMin.getY(), pMax.getX() - pMin.getX(), pMax.getY() - pMin.getY());
}
/**
* This method follows the construction from
* https://proofwiki.org/wiki/Obtuse_Triangle_Divided_into_Acute_Triangles
......
......@@ -181,9 +181,9 @@ public class LinkedCellsGrid<T> implements Iterable<T> {
// create grid
/*
* this.gridSize = (int) Math.max(1,
* Math.ceil(Math.max(width, height) / sideLength));
* this.cellSize = Math.max(width, height) / gridSize;
* this.gridSize = (int) Math.bound(1,
* Math.ceil(Math.bound(width, height) / sideLength));
* this.cellSize = Math.bound(width, height) / gridSize;
* this.grid = generateGrid(gridSize, gridSize);
*/
......
......@@ -82,16 +82,6 @@ public class PMesh<P extends IPoint> implements IMesh<P, PHalfEdge<P>, PFace<P>>
return halfEdge.isBoundary();
}
@Override
public boolean isHole(@NotNull PFace<P> face) {
return false;
}
@Override
public boolean isHole(@NotNull PHalfEdge<P> halfEdge) {
return false;
}
@Override
public boolean isDestroyed(@NotNull PFace<P> face) {
return face.isDestroyed();
......@@ -152,6 +142,11 @@ public class PMesh<P extends IPoint> implements IMesh<P, PHalfEdge<P>, PFace<P>>
return vertices.size();
}
@Override
public int getNumberOfFaces() {
return faces.size();
}
@Override
public PHalfEdge<P> createEdge(@NotNull P vertex) {
PHalfEdge<P> edge = new PHalfEdge<>(vertex);
......@@ -190,6 +185,11 @@ public class PMesh<P extends IPoint> implements IMesh<P, PHalfEdge<P>, PFace<P>>
return vertex;
}
@Override
public PFace<P> getBoundary() {
return boundary;
}
@Override
public void insert(P vertex) {
vertices.add(vertex);
......
......@@ -63,9 +63,6 @@ public interface IMesh<P extends IPoint, E extends IHalfEdge<P>, F extends IFace
boolean isBoundary(@NotNull F face);
boolean isBoundary(@NotNull E halfEdge);
boolean isHole(@NotNull F face);
boolean isHole(@NotNull E halfEdge);
boolean isDestroyed(@NotNull F face);
boolean isDestroyed(@NotNull E edge);
......@@ -83,6 +80,8 @@ public interface IMesh<P extends IPoint, E extends IHalfEdge<P>, F extends IFace
F createFace();
F createFace(boolean boundary);
P createVertex(double x, double y);
F getBoundary();
void insert(P vertex);
void insertVertex(P vertex);
......@@ -299,6 +298,17 @@ public interface IMesh<P extends IPoint, E extends IHalfEdge<P>, F extends IFace
return streamIncidentEdges(edge).map(this::getVertex).collect(Collectors.toList());
}
default List<E> getEdges() {
List<E> edges = new ArrayList<>();
for(F face : this) {
for (E edge : getEdgeIt(face)) {
edges.add(edge);
}
}
return edges;
}
/**
* Returns all edges which end-point is equal to the vertex
*
......@@ -362,6 +372,8 @@ public interface IMesh<P extends IPoint, E extends IHalfEdge<P>, F extends IFace
int getNumberOfVertices();
int getNumberOfFaces();
static <P extends IPoint> IMesh<P, PHalfEdge<P>, PFace<P>> createPMesh(final IPointConstructor<P> pointConstructor) {
return new PMesh<>(pointConstructor);
}
......
package org.vadere.util.geometry.mesh.inter;
import org.vadere.util.geometry.mesh.triangulations.BasePointLocator;
import org.vadere.util.geometry.mesh.triangulations.DelaunayHierarchy;
import org.vadere.util.geometry.mesh.triangulations.DelaunayTree;
import org.vadere.util.geometry.shapes.IPoint;
import java.util.Collection;
......@@ -16,19 +13,13 @@ import java.util.Optional;
* @param <F>
*/
public interface IPointLocator<P extends IPoint, E extends IHalfEdge<P>, F extends IFace<P>> extends ITriEventListener<P, E, F> {
Collection<F> locatePoint(final IPoint point, final boolean insertion);
Collection<F> locatePoint(final P point, final boolean insertion);
Optional<F> locate(final IPoint point);
Optional<F> locate(final P point);
static <P extends IPoint, E extends IHalfEdge<P>, F extends IFace<P>> BasePointLocator<P, E, F> createBaseLocator(final ITriangulation<P, E, F> triangulation) {
return new BasePointLocator<>(triangulation);
}
static <P extends IPoint, E extends IHalfEdge<P>, F extends IFace<P>> DelaunayHierarchy<P, E, F> createDelaunayHierarchy(final ITriangulation<P, E, F> triangulation) {
return new DelaunayHierarchy<>(triangulation);
}
static <P extends IPoint, E extends IHalfEdge<P>, F extends IFace<P>> DelaunayTree<P, E, F> createDelaunayTree(final ITriangulation<P, E, F> triangulation, final F superTriangle) {
return new DelaunayTree<>(triangulation, superTriangle);
enum Type {
DELAUNAY_TREE,
DELAUNAY_HIERARCHY,
BASE
}
}
......@@ -33,7 +33,7 @@ public interface IPolyConnectivity<P extends IPoint, E extends IHalfEdge<P>, F e
return Optional.empty();
}
default Optional<F> locate(final IPoint point) {
default Optional<F> locate(final P point) {
return locate(point.getX(), point.getY());
}
......
......@@ -26,7 +26,7 @@ public interface ITriConnectivity<P extends IPoint, E extends IHalfEdge<P>, F ex
default void flipEdgeEvent(F f1, F f2) {}
default void insertEvent(P vertex) {};
default void insertEvent(E vertex) {};
boolean isIllegal(E edge);
......@@ -381,13 +381,18 @@ public interface ITriConnectivity<P extends IPoint, E extends IHalfEdge<P>, F ex
}
@Override
default Optional<F> locate(final IPoint point) {
default Optional<F> locate(final P point) {
return this.locate(point.getX(), point.getY());
}
@Override
default Optional<F> locate(final double x, final double y) {
return locate(x, y, getMesh().getFace());
if(getMesh().getNumberOfFaces() > 0) {
return locate(x, y, getMesh().getFace());
}
else {
return Optional.empty();
}
}
/*default Optional<P> locateVertex(double x, double y, F startFace) {
......
......@@ -11,7 +11,7 @@ public interface ITriEventListener<P extends IPoint, E extends IHalfEdge<P>, F e
void flipEdgeEvent(F f1, F f2);
void insertEvent(P vertex);
void insertEvent(E vertex);
//void removeEvent()
......
package org.vadere.util.geometry.mesh.inter;
import org.apache.commons.lang3.RandomUtils;
import org.vadere.util.geometry.GeometryUtils;
import org.vadere.util.geometry.mesh.impl.PFace;
import org.vadere.util.geometry.mesh.impl.PHalfEdge;
import org.vadere.util.geometry.mesh.impl.PMesh;
import org.vadere.util.geometry.mesh.triangulations.BasePointLocator;
import org.vadere.util.geometry.mesh.triangulations.DelaunayHierarchy;
import org.vadere.util.geometry.mesh.triangulations.DelaunayTree;
import org.vadere.util.geometry.mesh.triangulations.IncrementalTriangulation;
import org.vadere.util.geometry.mesh.triangulations.UniformTriangulation;
import org.vadere.util.geometry.shapes.IPoint;
import org.vadere.util.geometry.shapes.VLine;
import org.vadere.util.geometry.shapes.VPoint;
import org.vadere.util.geometry.shapes.VRectangle;
import org.vadere.util.geometry.shapes.VTriangle;
import org.vadere.util.triangulation.IPointConstructor;
import java.util.HashSet;
import java.util.Set;
import java.util.function.Supplier;
import java.util.stream.Collectors;
import java.util.stream.Stream;
public interface ITriangulation<P extends IPoint, E extends IHalfEdge<P>, F extends IFace<P>> extends Iterable<F>, ITriConnectivity<P, E, F> {
void init();
void compute();
void finalize();
Stream<F> streamFaces();
Set<F> getFaces();
E insert(final P point);
void insert(final Set<P> points);
void remove(final P point);
Stream<VTriangle> streamTriangles();
default Set<VLine> getEdges() {
IMesh<P, E, F> mesh = getMesh();
return getMesh().getEdges().stream()
.map(he -> new VLine(new VPoint(mesh.getVertex(mesh.getPrev(he))), new VPoint(mesh.getVertex(he))))
.collect(Collectors.toSet());
}
static <P extends IPoint> ITriangulation<P, PHalfEdge<P>, PFace<P>> createPTriangulation(
final IPointLocator.Type type,
final VRectangle bound,
final IPointConstructor<P> pointConstructor) {
IncrementalTriangulation<P, PHalfEdge<P>, PFace<P>> triangulation = new IncrementalTriangulation<>(bound);
IMesh<P, PHalfEdge<P>, PFace<P>> mesh = new PMesh<>(pointConstructor);
triangulation.setMesh(mesh);
IPointLocator<P, PHalfEdge<P>, PFace<P>> pointLocator;
switch (type) {
case BASE:
pointLocator = new BasePointLocator<>(triangulation);
break;
case DELAUNAY_HIERARCHY:
Supplier<ITriangulation<P, PHalfEdge<P>, PFace<P>>> supplier = () -> createPTriangulation(IPointLocator.Type.BASE, bound, pointConstructor);
pointLocator = new DelaunayHierarchy<>(triangulation, supplier);
break;
case DELAUNAY_TREE:
default:
pointLocator = new DelaunayTree<>(triangulation);
}
triangulation.setPointLocator(pointLocator);
return triangulation;
}
static <P extends IPoint> ITriangulation<P, PHalfEdge<P>, PFace<P>> createPTriangulation(
final IPointLocator.Type type,
final Set<P> points,
final IPointConstructor<P> pointConstructor) {
ITriangulation<P, PHalfEdge<P>, PFace<P>> triangulation = createPTriangulation(type, GeometryUtils.bound(points), pointConstructor);
triangulation.insert(points);
return triangulation;
}
static ITriangulation<VPoint, PHalfEdge<VPoint>, PFace<VPoint>> createPTriangulation(
final IPointLocator.Type type,
final VRectangle bound) {
return createPTriangulation(type, bound, (x, y) -> new VPoint(x, y));
}
static <P extends IPoint> UniformTriangulation<P, PHalfEdge<P>, PFace<P>> createUnifirmTriangulation(
final IPointLocator.Type type,
final VRectangle bound,
final double minTriangleSideLen,
final IPointConstructor<P> pointConstructor
) {
UniformTriangulation<P, PHalfEdge<P>, PFace<P>> triangulation = new UniformTriangulation<>(bound, minTriangleSideLen);
IMesh<P, PHalfEdge<P>, PFace<P>> mesh = new PMesh<>(pointConstructor);
triangulation.setMesh(mesh);
IPointLocator<P, PHalfEdge<P>, PFace<P>> pointLocator;
switch (type) {
case BASE:
pointLocator = new BasePointLocator<>(triangulation);
break;
case DELAUNAY_HIERARCHY:
Supplier<ITriangulation<P, PHalfEdge<P>, PFace<P>>> supplier = () -> createPTriangulation(IPointLocator.Type.BASE, bound, pointConstructor);
pointLocator = new DelaunayHierarchy<>(triangulation, supplier);
break;
case DELAUNAY_TREE:
default:
pointLocator = new DelaunayTree<>(triangulation);
}
triangulation.setPointLocator(pointLocator);
return triangulation;
}
static ITriangulation<VPoint, PHalfEdge<VPoint>, PFace<VPoint>> generateRandomTriangulation(final long numberOfPoints) {
double min = 0;
......@@ -35,6 +131,14 @@ public interface ITriangulation<P extends IPoint, E extends IHalfEdge<P>, F exte
}
IMesh<VPoint, PHalfEdge<VPoint>, PFace<VPoint>> mesh = new PMesh<>(IPointConstructor.pointConstructorVPoint);
return new IncrementalTriangulation<>(mesh, points);
IncrementalTriangulation<VPoint, PHalfEdge<VPoint>, PFace<VPoint>> triangulation = new IncrementalTriangulation<>(points);
triangulation.setMesh(mesh);
triangulation.setPointLocator(new DelaunayTree<>(triangulation));
triangulation.compute();
return triangulation;
}
}
......@@ -26,7 +26,7 @@ import java.util.Optional;
*/
public class BasePointLocator<P extends IPoint, E extends IHalfEdge<P>, F extends IFace<P>> implements IPointLocator<P, E, F> {
private final ITriConnectivity<P, E, F> triConnectivity;
private ITriConnectivity<P, E, F> triConnectivity;
public BasePointLocator(final ITriConnectivity<P, E, F> triConnectivity) {
this.triConnectivity = triConnectivity;
......@@ -39,7 +39,7 @@ public class BasePointLocator<P extends IPoint, E extends IHalfEdge<P>, F extend
public void flipEdgeEvent(final F f1, final F f2) {}
@Override
public void insertEvent(final P vertex) {}
public void insertEvent(E vertex) {}
@Override
public void deleteBoundaryFace(final F face) {}
......
......@@ -2,24 +2,50 @@ package org.vadere.util.geometry.mesh.triangulations;
import org.vadere.util.geometry.mesh.inter.IFace;
import org.vadere.util.geometry.mesh.inter.IHalfEdge;
import org.vadere.util.geometry.mesh.inter.IMesh;
import org.vadere.util.geometry.mesh.inter.IPointLocator;
import org.vadere.util.geometry.mesh.inter.ITriConnectivity;
import org.vadere.util.geometry.mesh.inter.ITriangulation;
import org.vadere.util.geometry.shapes.IPoint;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Random;
import java.util.function.Supplier;
/**
* Created by bzoennchen on 21.04.17.
* @author Benedikt Zoennchen
*
* @param <P>
* @param <E>
* @param <F>
*/
public class DelaunayHierarchy<P extends IPoint, E extends IHalfEdge<P>, F extends IFace<P>> implements IPointLocator<P, E, F> {
//private List<ITriangulation<P, E, F>>
private List<ITriangulation<P, E, F>> hierarchySets;
private ITriConnectivity<P, E, F> triConnectivity;
private List<Map<E, E>> hierarchyConnector;
public DelaunayHierarchy(final ITriConnectivity<P, E, F> triConnectivity) {
this.triConnectivity = triConnectivity;
private ITriConnectivity<P, E, F> base;
private Supplier<ITriangulation<P, E, F>> triangulationSupplier;
private double alpha;
private Random random;
public DelaunayHierarchy(final ITriangulation<P, E, F> base, final Supplier<ITriangulation<P, E, F>> triangulationSupplier) {
this.hierarchySets = new ArrayList<>();
this.hierarchyConnector = new ArrayList<>();
this.random = new Random();
this.triangulationSupplier = triangulationSupplier;
hierarchySets.add(base);
hierarchyConnector.add(new HashMap<>());
}
@Override
......@@ -29,8 +55,31 @@ public class DelaunayHierarchy<P extends IPoint, E extends IHalfEdge<P>, F exten
public void flipEdgeEvent(F f1, F f2) {}
@Override
public void insertEvent(P vertex) {
public void insertEvent(final E halfEdge) {
P vertex = base.getMesh().getVertex(halfEdge);
E lastEdge = halfEdge;
for(int i = 1; i < hierarchySets.size(); ++i) {
if(random.nextDouble() < alpha) {
if(hierarchySets.size() <= i) {
hierarchySets.add(triangulationSupplier.get());
}
E edge = hierarchySets.get(i).insert(vertex);
if(hierarchyConnector.size() < i) {
hierarchyConnector.add(new HashMap<>());
}
hierarchyConnector.get(i-1).put(lastEdge, edge);
lastEdge = edge;
}
else {
break;
}
}
}
@Override
......@@ -39,12 +88,33 @@ public class DelaunayHierarchy<P extends IPoint, E extends IHalfEdge<P>, F exten
}
@Override
public Collection<F> locatePoint(IPoint point, boolean insertion) {
public Collection<F> locatePoint(P point, boolean insertion) {
return null;
}
@Override
public Optional<F> locate(IPoint point) {
return null;
public Optional<F> locate(final P point) {
Optional<F> optStartFace = Optional.empty();
for(int i = hierarchySets.size()-1; i >= 0; --i) {
if(!optStartFace.isPresent()) {
optStartFace = hierarchySets.get(i).locate(point.getX(), point.getY());
}
else {
E edge = getNearestPoint(hierarchySets.get(i-1), optStartFace.get(), point);
E newEdge = hierarchyConnector.get(i-1).get(edge);
optStartFace = hierarchySets.get(i).locate(point.getX(), point.getY(), hierarchySets.get(i).getMesh().getFace(newEdge));
if(!optStartFace.isPresent()) {
return Optional.empty();
}
}
}
return optStartFace;
}
public E getNearestPoint(final ITriangulation<P, E, F> triangulation, final F face, final P point) {
IMesh<P, E, F> mesh = triangulation.getMesh();
return triangulation.getMesh().streamEdges(face).reduce((p1, p2) -> mesh.getVertex(p1).distance(point) > mesh.getVertex(p2).distance(point) ? p2 : p1).get();