Search in sources :

Example 1 with TPoint

use of org.poly2tri.triangulation.point.TPoint in project energy3d by concord-consortium.

the class MeshLib method applyHoles.

public static void applyHoles(final Node root, final List<Window> windows) {
    final Map<Window, List<ReadOnlyVector3>> holes = new HashMap<Window, List<ReadOnlyVector3>>();
    for (final Window window : windows) {
        final ArrayList<ReadOnlyVector3> hole = new ArrayList<ReadOnlyVector3>();
        hole.add(window.getAbsPoint(0).multiplyLocal(1, 1, 0));
        hole.add(window.getAbsPoint(2).multiplyLocal(1, 1, 0));
        hole.add(window.getAbsPoint(3).multiplyLocal(1, 1, 0));
        hole.add(window.getAbsPoint(1).multiplyLocal(1, 1, 0));
        holes.put(window, hole);
    }
    for (int roofIndex = 0; roofIndex < root.getChildren().size(); roofIndex++) {
        final Spatial roofPart = root.getChildren().get(roofIndex);
        if (roofPart.getSceneHints().getCullHint() != CullHint.Always) {
            final ReadOnlyVector3 normal = (ReadOnlyVector3) roofPart.getUserData();
            final AnyToXYTransform toXY = new AnyToXYTransform(normal.getX(), normal.getY(), normal.getZ());
            final XYToAnyTransform fromXY = new XYToAnyTransform(normal.getX(), normal.getY(), normal.getZ());
            final Mesh mesh = (Mesh) ((Node) roofPart).getChild(0);
            final ArrayList<ReadOnlyVector3> points3D = computeOutline(mesh.getMeshData().getVertexBuffer());
            final List<PolygonPoint> points2D = new ArrayList<PolygonPoint>();
            final ReadOnlyVector3 firstPoint = points3D.get(0);
            final double scale = Scene.getInstance().getTextureMode() == TextureMode.Simple ? 0.5 : 0.1;
            final TPoint o;
            final TPoint u;
            final TPoint v;
            if (normal.dot(Vector3.UNIT_Z) == 1) {
                o = new TPoint(firstPoint.getX(), firstPoint.getY(), firstPoint.getZ());
                u = new TPoint(1 / scale, 0, 0);
                v = new TPoint(0, 1 / scale, 0);
            } else {
                final ReadOnlyVector3 u3 = Vector3.UNIT_Z.cross(normal, null).normalizeLocal();
                final ReadOnlyVector3 ou3 = u3.divide(scale, null).add(firstPoint, null);
                final ReadOnlyVector3 ov3 = normal.cross(u3, null).divideLocal(scale).addLocal(firstPoint);
                o = new TPoint(firstPoint.getX(), firstPoint.getY(), firstPoint.getZ());
                u = new TPoint(ou3.getX(), ou3.getY(), ou3.getZ());
                v = new TPoint(ov3.getX(), ov3.getY(), ov3.getZ());
                toXY.transform(o);
                toXY.transform(u);
                toXY.transform(v);
                u.set(u.getX() - o.getX(), u.getY() - o.getY(), 0);
                v.set(v.getX() - o.getX(), v.getY() - o.getY(), 0);
            }
            final Vector2 o2 = new Vector2(firstPoint.getX(), firstPoint.getY());
            final Vector2 ou2 = o2.add(new Vector2(u.getX(), u.getY()), null);
            final Vector2 ov2 = o2.add(new Vector2(v.getX(), v.getY()), null);
            double minLineScaleU = Double.MAX_VALUE;
            double minLineScaleV = Double.MAX_VALUE;
            for (final ReadOnlyVector3 p : points3D) {
                final PolygonPoint polygonPoint = new PolygonPoint(p.getX(), p.getY(), p.getZ());
                toXY.transform(polygonPoint);
                points2D.add(polygonPoint);
                final Vector2 p2 = new Vector2(polygonPoint.getX(), polygonPoint.getY());
                final double lineScaleU = Util.projectPointOnLineScale(p2, o2, ou2);
                final double lineScaleV = Util.projectPointOnLineScale(p2, o2, ov2);
                if (lineScaleU < minLineScaleU) {
                    minLineScaleU = lineScaleU;
                }
                if (lineScaleV < minLineScaleV) {
                    minLineScaleV = lineScaleV;
                }
            }
            o2.addLocal(new Vector2(u.getX(), u.getY()).multiplyLocal(minLineScaleU));
            o2.addLocal(new Vector2(v.getX(), v.getY()).multiplyLocal(minLineScaleV));
            final PolygonWithHoles polygon = new PolygonWithHoles(points2D);
            o.set(o2.getX(), o2.getY(), 0);
            roofPart.updateWorldBound(true);
            for (final Window window : windows) {
                if (holes.get(window) == null) {
                    continue;
                }
                final List<PolygonPoint> holePolygon = new ArrayList<PolygonPoint>();
                boolean outside = false;
                for (final ReadOnlyVector3 holePoint : holes.get(window)) {
                    final PickResults pickResults = new PrimitivePickResults();
                    PickingUtil.findPick(((Node) roofPart).getChild(0), new Ray3(holePoint, Vector3.UNIT_Z), pickResults, false);
                    if (pickResults.getNumber() > 0) {
                        final ReadOnlyVector3 intersectionPoint = pickResults.getPickData(0).getIntersectionRecord().getIntersectionPoint(0);
                        final PolygonPoint polygonPoint = new PolygonPoint(intersectionPoint.getX(), intersectionPoint.getY(), intersectionPoint.getZ());
                        toXY.transform(polygonPoint);
                        holePolygon.add(polygonPoint);
                    } else {
                        outside = true;
                        break;
                    }
                }
                if (!outside) {
                    polygon.addHole(new PolygonWithHoles(holePolygon));
                    holes.remove(window);
                    window.setRoofIndex(roofIndex);
                }
            }
            final Mesh meshWithHoles = (Mesh) ((Node) roofPart).getChild(6);
            try {
                fillMeshWithPolygon(meshWithHoles, polygon, fromXY, true, o, v, u, false);
            } catch (final RuntimeException e) {
                e.printStackTrace();
                final Mesh meshWithoutHoles = (Mesh) ((Node) roofPart).getChild(0);
                meshWithHoles.setMeshData(meshWithoutHoles.getMeshData());
            }
        }
    }
}
Also used : Window(org.concord.energy3d.model.Window) AnyToXYTransform(org.poly2tri.transform.coordinate.AnyToXYTransform) HashMap(java.util.HashMap) Node(com.ardor3d.scenegraph.Node) ArrayList(java.util.ArrayList) PolygonPoint(org.poly2tri.geometry.polygon.PolygonPoint) Mesh(com.ardor3d.scenegraph.Mesh) CullHint(com.ardor3d.scenegraph.hint.CullHint) PolygonPoint(org.poly2tri.geometry.polygon.PolygonPoint) TPoint(org.poly2tri.triangulation.point.TPoint) Point(org.poly2tri.geometry.primitives.Point) TPoint(org.poly2tri.triangulation.point.TPoint) Ray3(com.ardor3d.math.Ray3) PrimitivePickResults(com.ardor3d.intersection.PrimitivePickResults) ReadOnlyVector3(com.ardor3d.math.type.ReadOnlyVector3) XYToAnyTransform(org.poly2tri.transform.coordinate.XYToAnyTransform) Spatial(com.ardor3d.scenegraph.Spatial) ReadOnlyVector2(com.ardor3d.math.type.ReadOnlyVector2) Vector2(com.ardor3d.math.Vector2) ArrayList(java.util.ArrayList) List(java.util.List) PrimitivePickResults(com.ardor3d.intersection.PrimitivePickResults) PickResults(com.ardor3d.intersection.PickResults)

Example 2 with TPoint

use of org.poly2tri.triangulation.point.TPoint in project energy3d by concord-consortium.

the class MeshLib method fillMeshWithPolygon.

// private static boolean isAlmost180(final ReadOnlyVector3 p1, final ReadOnlyVector3 p2, final ReadOnlyVector3 p3) {
// return Math.abs(p1.subtract(p2, null).normalizeLocal().smallestAngleBetween(p3.subtract(p1, null).normalizeLocal())) > Math.PI - Math.PI / 180.0;
// }
public static void fillMeshWithPolygon(final Mesh mesh, final PolygonWithHoles polygon, final CoordinateTransform fromXY, final boolean generateNormals, final TPoint o, final TPoint u, final TPoint v, final boolean isWall) {
    /* round all points */
    for (final Point p : polygon.getPoints()) {
        p.set(Util.round(p.getX()), Util.round(p.getY()), Util.round(p.getZ()));
    }
    if (polygon.getHoles() != null) {
        for (final Polygon hole : polygon.getHoles()) {
            for (final Point p : hole.getPoints()) {
                p.set(Util.round(p.getX()), Util.round(p.getY()), Util.round(p.getZ()));
            }
        }
    }
    /* remove holes that collide with polygon or other holes */
    if (polygon.getHoles() != null) {
        // ensure polygon doesn't collide with holes
        final Path2D polygonPath = Util.makePath2D(polygon.getPoints());
        final Map<Polygon, Object> skipHoles = new HashMap<Polygon, Object>();
        for (final Polygon hole : polygon.getHoles()) {
            for (final Point p : hole.getPoints()) {
                if (!polygonPath.contains(new Point2D.Double(p.getX(), p.getY()))) {
                    skipHoles.put(hole, null);
                    break;
                }
            }
        }
        // ensure holes don't collide with each other
        for (int i = 0; i < polygon.getHoles().size(); i++) {
            final Polygon hole1 = polygon.getHoles().get(i);
            if (skipHoles.containsKey(hole1)) {
                continue;
            }
            for (int j = i + 1; j < polygon.getHoles().size(); j++) {
                final Polygon hole2 = polygon.getHoles().get(j);
                if (skipHoles.containsKey(hole2)) {
                    continue;
                }
                boolean found = false;
                for (final Point p : hole2.getPoints()) {
                    if (Util.insidePolygon(p, hole1.getPoints())) {
                        skipHoles.put(hole2, null);
                        found = true;
                        break;
                    }
                }
                if (!found) {
                    final int n1 = hole1.getPoints().size();
                    for (int i1 = 0; i1 < n1; i1++) {
                        final Point l1p1 = hole1.getPoints().get(i1);
                        final Point l1p2 = hole1.getPoints().get((i1 + 1) % n1);
                        final Line2D line1 = new Line2D.Double(l1p1.getX(), l1p1.getY(), l1p2.getX(), l1p2.getY());
                        found = false;
                        final int n2 = hole2.getPoints().size();
                        for (int i2 = 0; i2 < n2; i2++) {
                            final Point l2p1 = hole2.getPoints().get(i2);
                            final Point l2p2 = hole2.getPoints().get((i2 + 1) % n2);
                            final Line2D line2 = new Line2D.Double(l2p1.getX(), l2p1.getY(), l2p2.getX(), l2p2.getY());
                            if (line2.intersectsLine(line1)) {
                                skipHoles.put(hole2, null);
                                found = true;
                                break;
                            }
                        }
                        if (found) {
                            break;
                        }
                    }
                }
            }
        }
        for (final Polygon hole : skipHoles.keySet()) {
            polygon.getHoles().remove(hole);
        }
    }
    try {
        Poly2Tri.triangulate(polygon);
        if (fromXY == null) {
            ArdorMeshMapper.updateTriangleMesh(mesh, polygon);
        } else {
            ArdorMeshMapper.updateTriangleMesh(mesh, polygon, fromXY);
        }
        if (generateNormals) {
            if (fromXY == null) {
                ArdorMeshMapper.updateFaceNormals(mesh, polygon.getTriangles());
            } else {
                ArdorMeshMapper.updateFaceNormals(mesh, polygon.getTriangles(), fromXY);
            }
        }
        if (o != null) {
            ArdorMeshMapper.updateTextureCoordinates(mesh, polygon.getTriangles(), 1.0, o, u, v);
        }
        mesh.getMeshData().updateVertexCount();
        mesh.updateModelBound();
    } catch (final RuntimeException e) {
        System.err.println("Points:");
        for (final Point p : polygon.getPoints()) {
            System.err.println(p);
        }
        System.err.println("Holes:");
        if (polygon.getHoles() != null) {
            for (final Polygon hole : polygon.getHoles()) {
                for (final Point p : hole.getPoints()) {
                    System.err.println(p);
                }
            }
        }
        throw e;
    }
}
Also used : HashMap(java.util.HashMap) Path2D(java.awt.geom.Path2D) PolygonPoint(org.poly2tri.geometry.polygon.PolygonPoint) TPoint(org.poly2tri.triangulation.point.TPoint) Point(org.poly2tri.geometry.primitives.Point) Polygon(org.poly2tri.geometry.polygon.Polygon) Line2D(java.awt.geom.Line2D) CullHint(com.ardor3d.scenegraph.hint.CullHint) PolygonPoint(org.poly2tri.geometry.polygon.PolygonPoint) TPoint(org.poly2tri.triangulation.point.TPoint) Point(org.poly2tri.geometry.primitives.Point)

Example 3 with TPoint

use of org.poly2tri.triangulation.point.TPoint in project energy3d by concord-consortium.

the class SolarRadiation method initMeshTextureData.

private MeshDataStore initMeshTextureData(final Mesh drawMesh, final Mesh collisionMesh, final ReadOnlyVector3 normal, final boolean updateTexture) {
    final MeshDataStore data = new MeshDataStore();
    if (normal != null) {
        final AnyToXYTransform toXY = new AnyToXYTransform(normal.getX(), normal.getY(), normal.getZ());
        final XYToAnyTransform fromXY = new XYToAnyTransform(normal.getX(), normal.getY(), normal.getZ());
        final FloatBuffer vertexBuffer = collisionMesh.getMeshData().getVertexBuffer();
        vertexBuffer.rewind();
        double minX, minY, maxX, maxY;
        minX = minY = Double.POSITIVE_INFINITY;
        maxX = maxY = Double.NEGATIVE_INFINITY;
        double z = Double.NaN;
        final List<ReadOnlyVector2> points = new ArrayList<ReadOnlyVector2>(vertexBuffer.limit() / 3);
        while (vertexBuffer.hasRemaining()) {
            final Vector3 pWorld = drawMesh.localToWorld(new Vector3(vertexBuffer.get(), vertexBuffer.get(), vertexBuffer.get()), null);
            final Point p = new TPoint(pWorld.getX(), pWorld.getY(), pWorld.getZ());
            toXY.transform(p);
            if (p.getX() < minX) {
                minX = p.getX();
            }
            if (p.getX() > maxX) {
                maxX = p.getX();
            }
            if (p.getY() < minY) {
                minY = p.getY();
            }
            if (p.getY() > maxY) {
                maxY = p.getY();
            }
            if (Double.isNaN(z)) {
                z = p.getZ();
            }
            points.add(new Vector2(p.getX(), p.getY()));
        }
        final Point tmp = new TPoint(minX, minY, z);
        fromXY.transform(tmp);
        data.p0 = new Vector3(tmp.getX(), tmp.getY(), tmp.getZ());
        tmp.set(minX, maxY, z);
        fromXY.transform(tmp);
        data.p1 = new Vector3(tmp.getX(), tmp.getY(), tmp.getZ());
        tmp.set(maxX, minY, z);
        fromXY.transform(tmp);
        data.p2 = new Vector3(tmp.getX(), tmp.getY(), tmp.getZ());
        final double solarStep = Scene.getInstance().getSolarStep();
        data.rows = Math.max(1, (int) Math.ceil(data.p1.subtract(data.p0, null).length() / solarStep));
        data.cols = Math.max(1, (int) Math.ceil(data.p2.subtract(data.p0, null).length() / solarStep));
        data.dailySolarIntensity = new double[Util.roundToPowerOfTwo(data.rows)][Util.roundToPowerOfTwo(data.cols)];
        final ReadOnlyVector2 originXY = new Vector2(minX, minY);
        final ReadOnlyVector2 uXY = new Vector2(maxX - minX, 0).normalizeLocal();
        final ReadOnlyVector2 vXY = new Vector2(0, maxY - minY).normalizeLocal();
        final int nrow = data.dailySolarIntensity.length;
        final int ncol = data.dailySolarIntensity[0].length;
        for (int row = 0; row < nrow; row++) {
            for (int col = 0; col < ncol; col++) {
                if (row >= data.rows || col >= data.cols) {
                    // overshot cells
                    data.dailySolarIntensity[row][col] = -1;
                } else {
                    final ReadOnlyVector2 p = originXY.add(uXY.multiply(col * solarStep, null), null).add(vXY.multiply(row * solarStep, null), null);
                    boolean isInside = false;
                    final int numberOfPoints = points.size();
                    if (numberOfPoints >= 3) {
                        // FIXME: sometimes we can end up with less than three points
                        for (int i = 0; i < numberOfPoints; i += 3) {
                            if (i + 2 < points.size()) {
                                if (Util.isPointInsideTriangle(p, points.get(i), points.get(i + 1), points.get(i + 2))) {
                                    isInside = true;
                                    break;
                                }
                            }
                        }
                    }
                    if (!isInside && col > 0 && row > 0) {
                        // must at least include one column or row
                        data.dailySolarIntensity[row][col] = -1;
                    }
                }
            }
        }
        data.u = data.p2.subtract(data.p0, null).normalizeLocal();
        data.v = data.p1.subtract(data.p0, null).normalizeLocal();
        onMesh.put(drawMesh, data);
        if (updateTexture) {
            updateTextureCoords(drawMesh);
        }
    }
    return data;
}
Also used : AnyToXYTransform(org.poly2tri.transform.coordinate.AnyToXYTransform) ArrayList(java.util.ArrayList) FloatBuffer(java.nio.FloatBuffer) ReadOnlyVector3(com.ardor3d.math.type.ReadOnlyVector3) Vector3(com.ardor3d.math.Vector3) TPoint(org.poly2tri.triangulation.point.TPoint) Point(org.poly2tri.geometry.primitives.Point) TPoint(org.poly2tri.triangulation.point.TPoint) CullHint(com.ardor3d.scenegraph.hint.CullHint) TPoint(org.poly2tri.triangulation.point.TPoint) Point(org.poly2tri.geometry.primitives.Point) ReadOnlyVector2(com.ardor3d.math.type.ReadOnlyVector2) XYToAnyTransform(org.poly2tri.transform.coordinate.XYToAnyTransform) ReadOnlyVector2(com.ardor3d.math.type.ReadOnlyVector2) Vector2(com.ardor3d.math.Vector2)

Example 4 with TPoint

use of org.poly2tri.triangulation.point.TPoint in project energy3d by concord-consortium.

the class Wall method drawPolygon.

private void drawPolygon(final List<List<Vector3>> wallAndWindowsPoints, final Mesh mesh, final boolean drawHoles, final boolean normal, final boolean texture) {
    final List<PolygonPoint> polygonPoints = new ArrayList<PolygonPoint>(wallAndWindowsPoints.get(0).size());
    for (final Vector3 p : wallAndWindowsPoints.get(0)) {
        final PolygonPoint tp = new PolygonPoint(p.getX(), p.getY(), p.getZ());
        toXY.transform(tp);
        polygonPoints.add(tp);
    }
    final PolygonWithHoles polygon = new PolygonWithHoles(polygonPoints);
    if (drawHoles) {
        for (int i = 1; i < wallAndWindowsPoints.size(); i++) {
            final List<PolygonPoint> holePoints = new ArrayList<PolygonPoint>(wallAndWindowsPoints.get(i).size());
            for (final Vector3 p : wallAndWindowsPoints.get(i)) {
                final PolygonPoint tp = new PolygonPoint(p.getX(), p.getY(), p.getZ());
                toXY.transform(tp);
                holePoints.add(tp);
            }
            polygon.addHole(new Polygon(holePoints));
        }
    }
    if (texture) {
        final double scale = Scene.getInstance().getTextureMode() == TextureMode.Simple ? 1.0 : 8.0;
        final boolean fullTexture = Scene.getInstance().getTextureMode() == TextureMode.Full;
        final ReadOnlyVector3 p0 = getAbsPoint(0);
        final ReadOnlyVector3 p01 = getAbsPoint(1).subtractLocal(p0).normalizeLocal().multiplyLocal(scale * (fullTexture ? 1.5 : 1.0));
        final ReadOnlyVector3 p02 = getAbsPoint(2).subtractLocal(p0).normalizeLocal().multiplyLocal(scale * (fullTexture ? 2.0 : 1.0));
        final TPoint o = new TPoint(p0.getX(), p0.getY(), p0.getZ());
        final TPoint u = new TPoint(p01.getX(), p01.getY(), p01.getZ());
        final TPoint v = new TPoint(p02.getX(), p02.getY(), p02.getZ());
        toXY.transform(o);
        toXY.transform(u);
        MeshLib.fillMeshWithPolygon(mesh, polygon, fromXY, normal, o, u, v, true);
    } else {
        MeshLib.fillMeshWithPolygon(mesh, polygon, fromXY, normal, null, null, null, true);
    }
}
Also used : ReadOnlyVector3(com.ardor3d.math.type.ReadOnlyVector3) PolygonPoint(org.poly2tri.geometry.polygon.PolygonPoint) ArrayList(java.util.ArrayList) PolygonWithHoles(org.concord.energy3d.util.PolygonWithHoles) ReadOnlyVector3(com.ardor3d.math.type.ReadOnlyVector3) Vector3(com.ardor3d.math.Vector3) Polygon(org.poly2tri.geometry.polygon.Polygon) CullHint(com.ardor3d.scenegraph.hint.CullHint) PolygonPoint(org.poly2tri.geometry.polygon.PolygonPoint) ArdorVector3Point(org.poly2tri.triangulation.point.ardor3d.ArdorVector3Point) PickingHint(com.ardor3d.scenegraph.hint.PickingHint) TPoint(org.poly2tri.triangulation.point.TPoint) Point(org.poly2tri.geometry.primitives.Point) TPoint(org.poly2tri.triangulation.point.TPoint)

Example 5 with TPoint

use of org.poly2tri.triangulation.point.TPoint in project energy3d by concord-consortium.

the class Roof method fillMeshWithPolygon.

protected void fillMeshWithPolygon(final Mesh mesh, final Polygon polygon) {
    try {
        Poly2Tri.triangulate(polygon);
    } catch (final RuntimeException e) {
        e.printStackTrace();
        System.out.println("Triangulate exception received with the following polygon:");
        for (final TriangulationPoint p : polygon.getPoints()) {
            System.out.println("new PolygonPoint(" + p.getX() + ", " + p.getY() + ", " + p.getZ() + ")");
        }
        throw e;
    }
    ArdorMeshMapper.updateTriangleMesh(mesh, polygon);
    ArdorMeshMapper.updateVertexNormals(mesh, polygon.getTriangles());
    ArdorMeshMapper.updateFaceNormals(mesh, polygon.getTriangles());
    ArdorMeshMapper.updateTextureCoordinates(mesh, polygon.getTriangles(), 200, new TPoint(0, 0, 0), new TPoint(10, 0, 0), new TPoint(0, 10, 0));
    mesh.getMeshData().updateVertexCount();
    mesh.updateModelBound();
}
Also used : TriangulationPoint(org.poly2tri.triangulation.TriangulationPoint) TPoint(org.poly2tri.triangulation.point.TPoint)

Aggregations

TPoint (org.poly2tri.triangulation.point.TPoint)6 ReadOnlyVector3 (com.ardor3d.math.type.ReadOnlyVector3)4 CullHint (com.ardor3d.scenegraph.hint.CullHint)4 Point (org.poly2tri.geometry.primitives.Point)4 ArrayList (java.util.ArrayList)3 PolygonPoint (org.poly2tri.geometry.polygon.PolygonPoint)3 Vector2 (com.ardor3d.math.Vector2)2 Vector3 (com.ardor3d.math.Vector3)2 ReadOnlyVector2 (com.ardor3d.math.type.ReadOnlyVector2)2 HashMap (java.util.HashMap)2 Polygon (org.poly2tri.geometry.polygon.Polygon)2 AnyToXYTransform (org.poly2tri.transform.coordinate.AnyToXYTransform)2 XYToAnyTransform (org.poly2tri.transform.coordinate.XYToAnyTransform)2 PickResults (com.ardor3d.intersection.PickResults)1 PrimitivePickResults (com.ardor3d.intersection.PrimitivePickResults)1 Ray3 (com.ardor3d.math.Ray3)1 Mesh (com.ardor3d.scenegraph.Mesh)1 Node (com.ardor3d.scenegraph.Node)1 Spatial (com.ardor3d.scenegraph.Spatial)1 PickingHint (com.ardor3d.scenegraph.hint.PickingHint)1