package org.osm2world.core.world.data; import static java.util.Collections.emptyList; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import org.osm2world.core.map_data.data.MapNode; import org.osm2world.core.map_elevation.creation.EleConstraintEnforcer; import org.osm2world.core.map_elevation.data.EleConnectorGroup; import org.osm2world.core.math.AxisAlignedBoundingBoxXZ; import org.osm2world.core.math.PolygonXYZ; import org.osm2world.core.math.SimplePolygonXZ; import org.osm2world.core.math.TriangleXYZ; import org.osm2world.core.math.TriangleXZ; import org.osm2world.core.math.VectorXYZ; import org.osm2world.core.math.algorithms.TriangulationUtil; import org.osm2world.core.math.datastructures.IntersectionTestObject; /** * superclass for {@link NodeWorldObject}s that do have an outline * and are not just treated as an infinitely small point. * * @see NoOutlineNodeWorldObject */ public abstract class OutlineNodeWorldObject implements NodeWorldObject, IntersectionTestObject, WorldObjectWithOutline { protected final MapNode node; private EleConnectorGroup connectors = null; protected OutlineNodeWorldObject(MapNode node) { this.node = node; } @Override public abstract SimplePolygonXZ getOutlinePolygonXZ(); @Override public final MapNode getPrimaryMapElement() { return node; } @Override public EleConnectorGroup getEleConnectors() { if (connectors == null) { SimplePolygonXZ outlinePolygonXZ = getOutlinePolygonXZ(); if (outlinePolygonXZ == null) { connectors = EleConnectorGroup.EMPTY; } else { connectors = new EleConnectorGroup(); connectors.addConnectorsFor(outlinePolygonXZ.getVertices(), node, getGroundState()); } } return connectors; } @Override public void defineEleConstraints(EleConstraintEnforcer enforcer) {} @Override public AxisAlignedBoundingBoxXZ getAxisAlignedBoundingBoxXZ() { if (getOutlinePolygonXZ() != null) { return new AxisAlignedBoundingBoxXZ( getOutlinePolygonXZ().getVertexCollection()); } else { return new AxisAlignedBoundingBoxXZ( node.getPos().x, node.getPos().z, node.getPos().x, node.getPos().z); } } @Override public PolygonXYZ getOutlinePolygon() { return connectors.getPosXYZ(getOutlinePolygonXZ()); } @Override public String toString() { return this.getClass().getSimpleName() + "(" + node + ")"; } /** * @return a triangulation of the area covered by this junction */ protected Collection<TriangleXYZ> getTriangulation() { if (getOutlinePolygonXZ() == null) return emptyList(); Collection<TriangleXZ> trianglesXZ = TriangulationUtil.triangulate( getOutlinePolygonXZ(), Collections.<SimplePolygonXZ>emptyList()); Collection<TriangleXYZ> trianglesXYZ = new ArrayList<TriangleXYZ>(trianglesXZ.size()); for (TriangleXZ triangleXZ : trianglesXZ) { VectorXYZ v1 = connectors.getPosXYZ(triangleXZ.v1); VectorXYZ v2 = connectors.getPosXYZ(triangleXZ.v2); VectorXYZ v3 = connectors.getPosXYZ(triangleXZ.v3); if (triangleXZ.isClockwise()) { trianglesXYZ.add(new TriangleXYZ(v3, v2, v1)); } else { trianglesXYZ.add(new TriangleXYZ(v1, v2, v3)); } } return trianglesXYZ; } }