Search in sources :

Example 1 with BVFeatureQuery

use of maspack.geometry.BVFeatureQuery in project artisynth_core by artisynth.

the class MeshCollider method getContactPlaneInfo.

/**
 * Get information about a specific region of intersections.
 */
static void getContactPlaneInfo(ContactPlane region, PolygonalMesh mesh0, PolygonalMesh mesh1, double pointTol) {
    Vector3d sectnormal = new Vector3d(), tmpnormal = new Vector3d();
    BVFeatureQuery query = new BVFeatureQuery();
    RigidTransform3d trans0 = mesh0.getMeshToWorld();
    RigidTransform3d trans1 = mesh1.getMeshToWorld();
    // calculate a weighted average of the face normals
    for (TriTriIntersection isect : region.intersections) {
        region.points = new ArrayList<Point3d>();
        region.points.add(isect.points[0]);
        region.points.add(isect.points[1]);
        double length = isect.points[0].distance(isect.points[1]);
        tmpnormal.transform(trans0, isect.face0.getNormal());
        tmpnormal.negate();
        sectnormal.scaledAdd(length, tmpnormal, sectnormal);
        tmpnormal.transform(trans1, isect.face1.getNormal());
        sectnormal.scaledAdd(length, tmpnormal, sectnormal);
    }
    // calculate the weighted intersection center
    Point3d center = new Point3d();
    double weight = 0;
    for (TriTriIntersection isect : region.intersections) {
        double length = isect.points[0].distance(isect.points[1]);
        center.scaledAdd(length, isect.points[0], center);
        center.scaledAdd(length, isect.points[1], center);
        weight += 2 * length;
    }
    center.scale(1.0 / weight);
    region.centroid = center;
    // calculate the weighted normal
    Vector3d cp0 = new Vector3d(), cp1 = new Vector3d();
    region.normal.setZero();
    for (TriTriIntersection isect : region.intersections) {
        cp0.sub(isect.points[0], center);
        cp1.sub(isect.points[1], center);
        tmpnormal.cross(cp0, cp1);
        if (tmpnormal.dot(sectnormal) < 0)
            tmpnormal.negate();
        region.normal.add(tmpnormal);
    }
    if (region.normal.dot(sectnormal) < 0)
        region.normal.negate();
    // handle degenerate cases
    if (region.normal.containsNaN() || region.normal.norm() < EPS) {
        region.normal.setZero();
        Point3d p0 = new Point3d();
        Point3d p1 = new Point3d();
        Vector3d c0 = new Vector3d();
        Vector3d c1 = new Vector3d();
        for (TriTriIntersection isect : region.intersections) {
            for (Point3d p : isect.points) {
                p0.inverseTransform(trans0, p);
                p1.inverseTransform(trans1, p);
                Vertex3d u0 = isect.face0.getVertex(0);
                Vertex3d u1 = isect.face0.getVertex(1);
                Vertex3d u2 = isect.face0.getVertex(2);
                Vertex3d v0 = isect.face1.getVertex(0);
                Vertex3d v1 = isect.face1.getVertex(1);
                Vertex3d v2 = isect.face1.getVertex(2);
                getCoordinates(c0, u0.pnt, u1.pnt, u2.pnt, p0);
                getCoordinates(c1, v0.pnt, v1.pnt, v2.pnt, p1);
                int[] type0 = classifyPoint(c0);
                int[] type1 = classifyPoint(c1);
                if (type0[0] == 2) {
                    if (type1[0] == 2) {
                        // vertex,vertex
                        region.normal.add(vertexVertexNormal(trans0, trans1, isect.face0, isect.face1, type0[1], type1[1]));
                    } else if (type1[0] == 1) {
                        // vertex,edge
                        region.normal.add(vertexEdgeNormal(trans0, trans1, isect.face0, isect.face1, type0[1], type1[1]));
                    } else {
                        // vertex,face
                        region.normal.add(vertexFaceNormal(trans0, trans1, isect.face0, isect.face1, type0[1]));
                    }
                } else if (type0[0] == 1) {
                    if (type1[0] == 2) {
                        // edge,vertex
                        region.normal.sub(vertexEdgeNormal(trans1, trans0, isect.face1, isect.face0, type1[1], type0[1]));
                    } else if (type1[0] == 1) {
                        // edge,edge
                        region.normal.add(edgeEdgeNormal(trans0, trans1, isect.face0, isect.face1, type0[1], type1[1]));
                    } else {
                        // edge,face
                        region.normal.add(edgeFaceNormal(trans0, trans1, isect.face0, isect.face1, type0[1]));
                    }
                } else {
                    if (type1[0] == 2) {
                        // face,vertex
                        region.normal.sub(vertexFaceNormal(trans1, trans0, isect.face1, isect.face0, type1[1]));
                    } else if (type1[0] == 1) {
                        // face,edge
                        region.normal.sub(edgeFaceNormal(trans1, trans0, isect.face1, isect.face0, type1[1]));
                    } else {
                        // face,face
                        region.normal.add(faceFaceNormal(trans0, trans1, isect.face0, isect.face1));
                    }
                }
            }
        }
    }
    region.normal.normalize();
    // calculate the contact depth for the region
    boolean foundPenetratingVertice = false;
    Point3d p = new Point3d();
    Point3d nearest = new Point3d();
    Vector3d diff = new Vector3d();
    Vector2d coords = new Vector2d();
    Vertex3d v;
    Face nf;
    Point3d plocal = new Point3d();
    LinkedHashSet<Vertex3d> regionvertices0 = new LinkedHashSet<Vertex3d>();
    LinkedHashSet<Vertex3d> regionvertices1 = new LinkedHashSet<Vertex3d>();
    region.depth = 0;
    for (TriTriIntersection isect : region.intersections) {
        for (int i = 0; i < 3; i++) {
            // face0 vertex depths
            v = isect.face0.getVertex(i);
            p.transform(trans0, v.pnt);
            plocal.inverseTransform(trans1, p);
            plocal.sub(isect.face1.getVertex(0).pnt);
            if (plocal.dot(isect.face1.getNormal()) <= 0) {
                regionvertices0.add(v);
            }
            // face1 vertex depths
            v = isect.face1.getVertex(i);
            p.transform(trans1, v.pnt);
            plocal.inverseTransform(trans0, p);
            plocal.sub(isect.face0.getVertex(0).pnt);
            if (plocal.dot(isect.face0.getNormal()) <= 0) {
                regionvertices1.add(v);
            }
        }
    }
    for (Vertex3d v0 : regionvertices0) {
        p.transform(trans0, v0.pnt);
        // XXX Sanchez, Jun 22, 2014
        // Changed to isInside.  Sometimes a vertex is outside
        // the mesh but determined to be "penetrating" due to
        // normal (e.g. when nearest to an edge)
        // nf = myQuery.nearestFaceToPoint (nearest, coords, mesh1, p);
        boolean inside = query.isInsideOrientedMesh(mesh1, p, 0);
        if (inside) {
            query.getFaceForInsideOrientedTest(nearest, coords);
            nearest.transform(trans1);
            diff.sub(p, nearest);
            diff.inverseTransform(trans1);
            foundPenetratingVertice = true;
            // -diff.dot (nf.getNormal());
            double dist = diff.norm();
            if (dist > region.depth)
                region.depth = dist;
        }
    }
    for (Vertex3d v1 : regionvertices1) {
        p.transform(trans1, v1.pnt);
        // nf = myQuery.nearestFaceToPoint (nearest, coords, mesh0, p);
        boolean inside = query.isInsideOrientedMesh(mesh0, p, 0);
        if (inside) {
            query.getFaceForInsideOrientedTest(nearest, coords);
            nearest.transform(trans0);
            diff.sub(p, nearest);
            diff.inverseTransform(trans0);
            foundPenetratingVertice = true;
            // -diff.dot (nf.getNormal());
            double dist = diff.norm();
            if (dist > region.depth)
                region.depth = dist;
        }
    }
    if (!foundPenetratingVertice) {
        double min = Double.POSITIVE_INFINITY, max = Double.NEGATIVE_INFINITY;
        for (int i = 0; i < region.points.size(); i++) {
            double d = region.points.get(i).dot(region.normal);
            if (d < min)
                min = d;
            if (d > max)
                max = d;
        }
        region.depth = max - min;
    }
    // eliminate redundant points
    // use point tolerance
    region.points.clear();
    for (TriTriIntersection isect : region.intersections) {
        for (Point3d pcandidate : isect.points) {
            boolean add = true;
            for (Point3d other : region.points) if (pcandidate.epsilonEquals(other, pointTol)) {
                add = false;
                break;
            }
            if (add) {
                region.points.add(pcandidate);
            }
        }
    }
    // take extrema along n axes
    if (numextremaaxes > 0) {
        // final ArrayList<Vector3d> axes = new ArrayList<Vector3d>();
        Vector3d crosszup = new Vector3d(0, 0, 1);
        crosszup.cross(region.normal, crosszup);
        double crosszupnorm = crosszup.norm();
        RigidTransform3d normtoworld;
        if (crosszup.norm() > EPS) {
            normtoworld = new RigidTransform3d(new Vector3d(), new AxisAngle(crosszup, Math.asin(crosszupnorm)));
        } else {
            normtoworld = new RigidTransform3d();
        }
        boolean[] keep = new boolean[region.points.size()];
        for (int j = 0; j < region.points.size(); j++) keep[j] = false;
        Vector3d offset = new Vector3d();
        Vector3d axis = new Vector3d();
        for (int i = 0; i < numextremaaxes; i++) {
            double min = Double.POSITIVE_INFINITY, max = Double.NEGATIVE_INFINITY;
            int mini = 0, maxi = 0;
            double angle = Math.PI * i / numextremaaxes;
            axis.set(Math.cos(angle), Math.sin(angle), 0);
            axis.transform(normtoworld);
            for (int j = 0; j < region.points.size(); j++) {
                offset.sub(region.points.get(j), center);
                double dot = offset.dot(axis);
                if (dot < min) {
                    min = dot;
                    mini = j;
                }
                if (dot > max) {
                    max = dot;
                    maxi = j;
                }
            }
            keep[mini] = true;
            keep[maxi] = true;
        }
        for (int j = (region.points.size() - 1); j >= 0; j--) {
            if (!keep[j])
                region.points.remove(j);
        }
    }
}
Also used : Vertex3d(maspack.geometry.Vertex3d) LinkedHashSet(java.util.LinkedHashSet) RigidTransform3d(maspack.matrix.RigidTransform3d) TriTriIntersection(maspack.geometry.TriTriIntersection) BVFeatureQuery(maspack.geometry.BVFeatureQuery) AxisAngle(maspack.matrix.AxisAngle) Vector2d(maspack.matrix.Vector2d) Vector3d(maspack.matrix.Vector3d) Point3d(maspack.matrix.Point3d) Face(maspack.geometry.Face)

Example 2 with BVFeatureQuery

use of maspack.geometry.BVFeatureQuery in project artisynth_core by artisynth.

the class NagataDistanceTest method computeNearestPoint.

public void computeNearestPoint(Point3d near, Vector3d normal, Point3d pos, boolean debug) {
    // //TriangleIntersector ti = new TriangleIntersector();
    BVFeatureQuery query = new BVFeatureQuery();
    // //OBBTree obbTree = myBaseMesh.getObbtree();
    // Vector2d svec = new Vector2d();
    // query.nearestFaceToPoint (near, svec, myBaseMesh, pos);
    // //obbTree.nearestFace (pos, normal, near, svec, ti);
    // svec.x = svec.x + svec.y; // convert to eta, zeta
    // svec.y = svec.y;
    // myInterp.nearestPointOnFace (
    // near, normal, face, myBaseMesh, svec, pos, 1e-8);
    myInterp.debug = debug;
    myInterp.nearestPointOnMesh(near, normal, myBaseMesh, pos, 1e-8, query);
// //myInterp.distanceToCurve (near, myCurvePos, myCurveDir, pos, 1e-8);
// myInterp.nearestPoint (near, normal, pos, eta, zeta, 1e-8);
}
Also used : BVFeatureQuery(maspack.geometry.BVFeatureQuery)

Example 3 with BVFeatureQuery

use of maspack.geometry.BVFeatureQuery in project artisynth_core by artisynth.

the class SkinMeshBody method createPointAttachment.

public PointSkinAttachment createPointAttachment(Point pnt) {
    if (!(getMesh() instanceof PolygonalMesh)) {
        return null;
    }
    PolygonalMesh mesh = (PolygonalMesh) getMesh();
    if (!mesh.isTriangular()) {
        return null;
    }
    // Find nearest face to the point; we'll need this to
    // estimate a basePosition for the attachments from the
    // start by find
    BVFeatureQuery query = new BVFeatureQuery();
    Point3d near = new Point3d();
    Vector2d uv = new Vector2d();
    Face face = query.nearestFaceToPoint(near, uv, mesh, pnt.getPosition());
    // Create a new PointSkinAttachment
    MeshDistCalc dcalc = new MeshDistCalc();
    dcalc.computeDistancesAndWeights(pnt.getPosition(), myLastSigma);
    PointSkinAttachment a = dcalc.computeDisplacementAttachment();
    a.setSkinMesh(this);
    // Now estimate the basePosition from the face vertices
    Point3d basePos = new Point3d();
    Vertex3d[] vtxs = face.getTriVertices();
    double[] wgts = new double[] { 1 - uv.x - uv.y, uv.x, uv.y };
    for (int i = 0; i < vtxs.length; i++) {
        PointSkinAttachment va = (PointSkinAttachment) myVertexAttachments.get(vtxs[i].getIndex());
        basePos.scaledAdd(wgts[i], va.getBasePosition());
    }
    a.setBasePosition(basePos);
    a.setPoint(pnt);
    return a;
}
Also used : Vertex3d(maspack.geometry.Vertex3d) Vector2d(maspack.matrix.Vector2d) Point3d(maspack.matrix.Point3d) Face(maspack.geometry.Face) PolygonalMesh(maspack.geometry.PolygonalMesh) BVFeatureQuery(maspack.geometry.BVFeatureQuery) ContactPoint(artisynth.core.mechmodels.ContactPoint) Point(artisynth.core.mechmodels.Point)

Example 4 with BVFeatureQuery

use of maspack.geometry.BVFeatureQuery in project artisynth_core by artisynth.

the class FemMeshComp method createPointAttachment.

public PointFem3dAttachment createPointAttachment(Point pnt) {
    if (!(getMesh() instanceof PolygonalMesh)) {
        return null;
    }
    PolygonalMesh mesh = (PolygonalMesh) getMesh();
    if (!mesh.isTriangular()) {
        return null;
    }
    // Find nearest face to the point. The vertices of this face will be used
    // to find the nodes and weight for the attachment.
    BVFeatureQuery query = new BVFeatureQuery();
    Point3d near = new Point3d();
    Vector2d uv = new Vector2d();
    Face face = query.nearestFaceToPoint(near, uv, mesh, pnt.getPosition());
    Vertex3d[] vtxs = face.getTriVertices();
    double[] wgts = new double[] { 1 - uv.x - uv.y, uv.x, uv.y };
    HashMap<FemNode, Double> nodeWeights = new HashMap<FemNode, Double>();
    for (int i = 0; i < vtxs.length; i++) {
        PointAttachment va = myVertexAttachments.get(vtxs[i].getIndex());
        if (va instanceof PointParticleAttachment) {
            PointParticleAttachment ppa = (PointParticleAttachment) va;
            FemNode node = (FemNode) ppa.getParticle();
            accumulateNodeWeights(node, wgts[i], nodeWeights);
        } else if (va instanceof PointFem3dAttachment) {
            PointFem3dAttachment pfa = (PointFem3dAttachment) va;
            for (int k = 0; k < pfa.numMasters(); k++) {
                FemNode node = pfa.getNodes()[k];
                double w = pfa.getCoordinate(k);
                accumulateNodeWeights(node, w * wgts[i], nodeWeights);
            }
        }
    }
    // Create a new PointFem3dAttachment
    PointFem3dAttachment ax = new PointFem3dAttachment(pnt);
    VectorNd weightVec = new VectorNd();
    for (Double d : nodeWeights.values()) {
        weightVec.append(d);
    }
    ax.setFromNodes(nodeWeights.keySet(), weightVec);
    return ax;
}
Also used : Vertex3d(maspack.geometry.Vertex3d) HashMap(java.util.HashMap) PointAttachment(artisynth.core.mechmodels.PointAttachment) PolygonalMesh(maspack.geometry.PolygonalMesh) BVFeatureQuery(maspack.geometry.BVFeatureQuery) ContactPoint(artisynth.core.mechmodels.ContactPoint) Point(artisynth.core.mechmodels.Point) Vector2d(maspack.matrix.Vector2d) Point3d(maspack.matrix.Point3d) VectorNd(maspack.matrix.VectorNd) Face(maspack.geometry.Face) PointParticleAttachment(artisynth.core.mechmodels.PointParticleAttachment)

Example 5 with BVFeatureQuery

use of maspack.geometry.BVFeatureQuery in project artisynth_core by artisynth.

the class IntersectionFactory method buildIntersectionChart.

public static boolean[][] buildIntersectionChart(PolygonalMesh[] meshList, double tol) {
    int n = meshList.length;
    boolean[][] out = new boolean[n][n];
    ArrayList<TriTriIntersection> intersections = new ArrayList<TriTriIntersection>();
    // TriangleIntersector ti = new TriangleIntersector();
    BVFeatureQuery query = new BVFeatureQuery();
    BVIntersector intersector = new BVIntersector();
    for (int i = 0; i < n; i++) {
        PolygonalMesh mesh1 = meshList[i];
        out[i][i] = true;
        for (int j = i + 1; j < n; j++) {
            PolygonalMesh mesh2 = meshList[j];
            boolean intersects = false;
            // }
            if (intersector.intersectMeshMesh(intersections, mesh1, mesh2)) {
                intersects = true;
                intersections.clear();
            } else if (query.isInsideOrientedMesh(mesh1, mesh2.getVertex(0).getPosition(), tol) || query.isInsideOrientedMesh(mesh2, mesh1.getVertex(0).getPosition(), tol)) {
                intersects = true;
            }
            out[i][j] = intersects;
            out[j][i] = intersects;
        }
    }
    return out;
}
Also used : ArrayList(java.util.ArrayList) TriTriIntersection(maspack.geometry.TriTriIntersection) BVIntersector(maspack.geometry.BVIntersector) BVFeatureQuery(maspack.geometry.BVFeatureQuery) PolygonalMesh(maspack.geometry.PolygonalMesh)

Aggregations

BVFeatureQuery (maspack.geometry.BVFeatureQuery)14 Point3d (maspack.matrix.Point3d)9 Vertex3d (maspack.geometry.Vertex3d)7 Vector2d (maspack.matrix.Vector2d)7 Face (maspack.geometry.Face)6 PolygonalMesh (maspack.geometry.PolygonalMesh)6 Vector3d (maspack.matrix.Vector3d)5 Point (artisynth.core.mechmodels.Point)4 ArrayList (java.util.ArrayList)4 ContactPoint (artisynth.core.mechmodels.ContactPoint)3 TriTriIntersection (maspack.geometry.TriTriIntersection)3 RigidTransform3d (maspack.matrix.RigidTransform3d)3 FemElement3d (artisynth.core.femmodels.FemElement3d)2 PointAttachment (artisynth.core.mechmodels.PointAttachment)2 PointParticleAttachment (artisynth.core.mechmodels.PointParticleAttachment)2 HashMap (java.util.HashMap)2 BVTree (maspack.geometry.BVTree)2 VectorNd (maspack.matrix.VectorNd)2 FemNode (artisynth.core.femmodels.FemNode)1 PointFem3dAttachment (artisynth.core.femmodels.PointFem3dAttachment)1