Search in sources :

Example 56 with Vector3d

use of maspack.matrix.Vector3d in project artisynth_core by artisynth.

the class PolygonalMesh method extendOpenEdges.

/**
 * Extends the first open edge loop found.
 *
 * @param amount
 * The amount to extend it by.
 */
public void extendOpenEdges(double amount) {
    // Vertex3d v0;
    HalfEdge he0 = null;
    boolean found = false;
    for (Object fo : myFaces) {
        Face f = (Face) fo;
        he0 = f.he0;
        do {
            if (isOpen(he0)) {
                found = true;
                break;
            }
            he0 = he0.next;
        } while (he0 != f.he0);
        if (found)
            break;
    }
    Vector3d i = new Vector3d(), j = new Vector3d();
    HalfEdge he = he0;
    ArrayList<Vertex3d> iverts = new ArrayList<Vertex3d>(), overts = new ArrayList<Vertex3d>();
    do {
        HalfEdgeNode hen = he.tail.getIncidentHedges();
        while (hen != null) {
            if (isOpen(hen.he)) {
                break;
            }
            hen = hen.next;
        }
        he.computeUnitVec(i);
        hen.he.computeUnitVec(j);
        double angleFactor = 1.0 - i.angle(j) / Math.PI;
        i.add(j);
        i.cross(he.face.getNormal());
        i.normalize();
        Point3d p = new Point3d();
        p.scaledAdd(amount * angleFactor, i, he.tail.pnt);
        iverts.add(he.tail);
        overts.add(addVertex(p));
        he = hen.he;
    } while (he != he0);
    Vertex3d lastiv = iverts.get(iverts.size() - 1), lastov = overts.get(overts.size() - 1);
    for (int v = 0; v < iverts.size(); v++) {
        Vertex3d iv = iverts.get(v), ov = overts.get(v);
        addFace(new int[] { lastiv.idx, iv.idx, ov.idx });
        addFace(new int[] { ov.idx, lastov.idx, lastiv.idx });
        lastiv = iv;
        lastov = ov;
    }
}
Also used : Vector3d(maspack.matrix.Vector3d) Point3d(maspack.matrix.Point3d) ArrayList(java.util.ArrayList)

Example 57 with Vector3d

use of maspack.matrix.Vector3d in project artisynth_core by artisynth.

the class PolygonalMesh method computePrincipalAxes.

public static RigidTransform3d computePrincipalAxes(PolygonalMesh mesh) {
    Vector3d mov1 = new Vector3d();
    Vector3d mov2 = new Vector3d();
    Vector3d pov = new Vector3d();
    double vol = mesh.computeVolumeIntegrals(mov1, mov2, pov);
    double mass = vol;
    Point3d cov = new Point3d();
    // center of volume
    cov.scale(1.0 / vol, mov1);
    // [c], skew symmetric
    Matrix3d covMatrix = new Matrix3d(0, -cov.z, cov.y, cov.z, 0, -cov.x, -cov.y, cov.x, 0);
    // J
    Matrix3d J = new Matrix3d((mov2.y + mov2.z), -pov.z, -pov.y, -pov.z, (mov2.x + mov2.z), -pov.x, -pov.y, -pov.x, (mov2.x + mov2.y));
    // Jc = J + m[c][c]
    Matrix3d Jc = new Matrix3d();
    Jc.mul(covMatrix, covMatrix);
    Jc.scale(mass);
    Jc.add(J);
    // Compute eigenvectors and eigenvlaues of Jc
    SymmetricMatrix3d JcSymmetric = new SymmetricMatrix3d(Jc);
    Vector3d lambda = new Vector3d();
    Matrix3d U = new Matrix3d();
    JcSymmetric.getEigenValues(lambda, U);
    // Construct the rotation matrix
    RotationMatrix3d R = new RotationMatrix3d();
    R.set(U);
    lambda.absolute();
    if (lambda.x > lambda.y && lambda.z > lambda.y) {
        R.rotateZDirection(new Vector3d(R.m01, R.m11, R.m21));
    } else if (lambda.x > lambda.z && lambda.y > lambda.z) {
        R.rotateZDirection(new Vector3d(R.m00, R.m10, R.m20));
    }
    return (new RigidTransform3d(cov, R));
}
Also used : RigidTransform3d(maspack.matrix.RigidTransform3d) SymmetricMatrix3d(maspack.matrix.SymmetricMatrix3d) RotationMatrix3d(maspack.matrix.RotationMatrix3d) Matrix3d(maspack.matrix.Matrix3d) Vector3d(maspack.matrix.Vector3d) Point3d(maspack.matrix.Point3d) SymmetricMatrix3d(maspack.matrix.SymmetricMatrix3d) RotationMatrix3d(maspack.matrix.RotationMatrix3d)

Example 58 with Vector3d

use of maspack.matrix.Vector3d in project artisynth_core by artisynth.

the class PolygonalMesh method computeCentreOfVolume.

/**
 * Computes the centre of volume of the mesh
 */
public double computeCentreOfVolume(Vector3d c) {
    Vector3d mov1 = new Vector3d();
    Vector3d mov2 = new Vector3d();
    Vector3d pov = new Vector3d();
    double vol = computeVolumeIntegrals(mov1, mov2, pov);
    // center of volume
    c.scale(1.0 / vol, mov1);
    return vol;
}
Also used : Vector3d(maspack.matrix.Vector3d)

Example 59 with Vector3d

use of maspack.matrix.Vector3d in project artisynth_core by artisynth.

the class PolygonalMesh method interpolate.

/**
 * Smoothly interpolate a face using barycentric coordinates.
 *
 * @param f
 * The face to interpolate.
 * @param u
 * The weighting of the first vertice.
 * @param v
 * The weighting of the second vertice.
 */
public void interpolate(Point3d p, Face f, double u, double v) {
    HalfEdge he = f.he0;
    Vertex3d v0 = he.head;
    he = he.next;
    Vertex3d v1 = he.head;
    Vertex3d v2 = he.next.head;
    Vector3d n0tmp = new Vector3d(), n1tmp = new Vector3d(), n2tmp = new Vector3d();
    v0.computeNormal(n0tmp);
    v1.computeNormal(n1tmp);
    v2.computeNormal(n2tmp);
    TrianglePatch patch = new TrianglePatch(v0.pnt, n0tmp, v1.pnt, n1tmp, v2.pnt, n2tmp);
    patch.interpolate(p, u, v, (1.0 - u - v));
}
Also used : Vector3d(maspack.matrix.Vector3d)

Example 60 with Vector3d

use of maspack.matrix.Vector3d in project artisynth_core by artisynth.

the class PolygonalMesh method mergeCoplanarFaces.

/**
 * Merges adjacent faces whose normals satisfy n1.dot(n2) {@code >} cosLimit
 *
 * @param cosLimit limit above which faces should be merged
 * @return true if modified, false otherwise
 */
public boolean mergeCoplanarFaces(double cosLimit) {
    HashSet<HalfEdge> toMerge = new HashSet<>();
    for (Face f : myFaces) {
        HalfEdge he0 = f.he0;
        HalfEdge he = he0;
        do {
            if (he.isPrimary() && he.opposite != null) {
                if (he.getFace().getNormal().dot(he.opposite.getFace().getNormal()) > cosLimit) {
                    toMerge.add(he);
                }
            }
            he = he.next;
        } while (he != he0);
    }
    // go through and merge faces
    boolean modified = false;
    HashSet<Face> toUpdateFace = new HashSet<>();
    HashSet<Face> toRemoveFace = new HashSet<>();
    HashSet<Vertex3d> toRemoveVertex = new HashSet<>();
    if (toMerge.size() > 0) {
        for (HalfEdge he : toMerge) {
            Face f1 = he.getFace();
            Face f2 = he.getOppositeFace();
            if (f1 == f2) {
                // edge jutting out into nowhere
                if (he.next == he.opposite) {
                    HalfEdge heopp = he.opposite;
                    he.head.removeIncidentHalfEdge(he);
                    heopp.head.removeIncidentHalfEdge(heopp);
                    // replace first half-edge on face
                    if (f1.he0 == he || f1.he0 == heopp) {
                        f1.he0 = heopp.next;
                    }
                    // find previous half-edge
                    HalfEdge hprev = heopp.next;
                    while (hprev.next != he) {
                        hprev = hprev.next;
                    }
                    hprev.next = heopp.next;
                    // form a loop
                    heopp.next = he;
                    // remove if vertex no longer attached to anything
                    if (he.head.numIncidentHalfEdges() == 0) {
                        toRemoveVertex.add(he.head);
                    }
                } else if (he.opposite.next == he) {
                    HalfEdge heopp = he.opposite;
                    he.head.removeIncidentHalfEdge(he);
                    heopp.head.removeIncidentHalfEdge(heopp);
                    // replace first half-edge on face
                    if (f1.he0 == he || f1.he0 == heopp) {
                        f1.he0 = he.next;
                    }
                    // find previous half-edge
                    HalfEdge hprev = he.next;
                    while (hprev.next != heopp) {
                        hprev = hprev.next;
                    }
                    hprev.next = he.next;
                    // form a loop
                    he.next = heopp;
                    // remove if vertex no longer attached to anything
                    if (heopp.head.numIncidentHalfEdges() == 0) {
                        toRemoveVertex.add(heopp.head);
                    }
                }
            } else {
                // replace first half-edge on face
                if (f1.he0 == he) {
                    f1.he0 = he.next;
                }
                if (f2.he0 == he.opposite) {
                    f2.he0 = he.opposite.next;
                }
                // find previous half-edges
                HalfEdge hprev = he.next;
                while (hprev.next != he) {
                    hprev = hprev.next;
                }
                HalfEdge ohprev = he.opposite.next;
                while (ohprev.next != he.opposite) {
                    ohprev = ohprev.next;
                }
                // adjust face on half-edges
                HalfEdge hh = he.opposite.next;
                do {
                    hh.face = f1;
                    hh = hh.next;
                } while (hh != he.opposite);
                // remove half-edge by connecting around it
                he.head.removeIncidentHalfEdge(he);
                he.opposite.head.removeIncidentHalfEdge(he.opposite);
                hprev.next = he.opposite.next;
                ohprev.next = he.next;
                he.face = f2;
                he.next = he.opposite;
                he.opposite.face = f2;
                he.opposite.next = he;
                f2.he0 = he;
                toRemoveFace.add(f2);
                toUpdateFace.add(f1);
            }
        }
        modified = true;
    }
    // remove vertices from straight lines
    if (modified) {
        for (Vertex3d vtx : myVertices) {
            Vector3d v1 = new Vector3d();
            Vector3d v2 = new Vector3d();
            int nhe = vtx.numIncidentHalfEdges();
            if (nhe == 0) {
                toRemoveVertex.add(vtx);
            } else if (nhe == 1) {
                // check if straight boundary edge
                HalfEdge he = vtx.firstIncidentHalfEdge();
                v1.sub(he.head.pnt, he.tail.pnt);
                v1.normalize();
                v2.sub(he.next.head.pnt, he.next.tail.pnt);
                v2.normalize();
                if (v1.dot(v2) > cosLimit) {
                    // remove vtx and he
                    vtx.removeIncidentHalfEdge(he);
                    HalfEdge hprev = he.next;
                    while (hprev.next != he) {
                        hprev = hprev.next;
                    }
                    // connect he.next to hprev
                    hprev.next = he.next;
                    he.next.tail = hprev.head;
                    // maybe replace first half-edge on face
                    Face f = he.getFace();
                    if (f.he0 == he) {
                        f.he0 = he.next;
                    }
                    // create loop of one for removed half-edge
                    he.next = he;
                    toRemoveVertex.add(vtx);
                }
            } else if (nhe == 2) {
                HalfEdge he = vtx.firstIncidentHalfEdge();
                // check of consistent line on both sides of vertex
                if (he.next.opposite != null && he.next.opposite.next == he.opposite) {
                    // check if closed straight edge
                    v1.sub(he.head.pnt, he.tail.pnt);
                    v1.normalize();
                    v2.sub(he.next.head.pnt, he.next.tail.pnt);
                    v2.normalize();
                    if (v1.dot(v2) > cosLimit) {
                        HalfEdge he2 = he.next.opposite;
                        // remove vtx and he
                        vtx.removeIncidentHalfEdge(he);
                        vtx.removeIncidentHalfEdge(he2);
                        HalfEdge hprev = he.next;
                        while (hprev.next != he) {
                            hprev = hprev.next;
                        }
                        // connect he.next to hprev
                        hprev.next = he.next;
                        he.next.tail = hprev.head;
                        HalfEdge hprev2 = he2.next;
                        while (hprev2.next != he2) {
                            hprev2 = hprev2.next;
                        }
                        // connect he2.next to hprev2
                        hprev2.next = he2.next;
                        he2.next.tail = hprev2.head;
                        // align new opposites
                        he.next.opposite = he2.next;
                        he2.next.opposite = he.next;
                        // maybe replace first half-edge on face
                        Face f = he.getFace();
                        if (f.he0 == he) {
                            f.he0 = he.next;
                        }
                        Face f2 = he2.getFace();
                        if (f2.he0 == he2) {
                            f2.he0 = he2.next;
                        }
                        // create loop of one for removed half-edge
                        he.next = he;
                        he2.next = he2;
                        toRemoveVertex.add(vtx);
                    }
                }
            }
        }
    }
    if (modified) {
        // remove faces and vertices
        removeVertices(toRemoveVertex);
        removeFaces(toRemoveFace);
        // XXX for now just clear attributes.  If we were diligent, we could re-adjust.
        clearAttributes();
        myTriQuadCountsValid = false;
        notifyStructureChanged();
    }
    return modified;
}
Also used : Vector3d(maspack.matrix.Vector3d) HashSet(java.util.HashSet)

Aggregations

Vector3d (maspack.matrix.Vector3d)441 Point3d (maspack.matrix.Point3d)128 RigidTransform3d (maspack.matrix.RigidTransform3d)56 ArrayList (java.util.ArrayList)38 Matrix3d (maspack.matrix.Matrix3d)32 RotationMatrix3d (maspack.matrix.RotationMatrix3d)30 SymmetricMatrix3d (maspack.matrix.SymmetricMatrix3d)24 PolygonalMesh (maspack.geometry.PolygonalMesh)23 Vertex3d (maspack.geometry.Vertex3d)23 Face (maspack.geometry.Face)20 AxisAngle (maspack.matrix.AxisAngle)19 Vector3i (maspack.matrix.Vector3i)19 Point (artisynth.core.mechmodels.Point)18 RenderProps (maspack.render.RenderProps)17 VectorNd (maspack.matrix.VectorNd)15 AffineTransform3d (maspack.matrix.AffineTransform3d)14 IOException (java.io.IOException)13 Vector2d (maspack.matrix.Vector2d)11 Plane (maspack.matrix.Plane)10 GLViewer (maspack.render.GL.GLViewer)9