Search in sources :

Example 1 with Vector2d

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

the class MeshThicken method applyThickening.

public void applyThickening(Region region, MeshBase mesh, double thickening) {
    double margin = region.myMargin;
    Point3d pnt = new Point3d();
    Vector3d nrm = new Vector3d();
    Vector2d p2d = new Vector2d();
    ArrayList<Vertex3d> verts = myMesh.getVertices();
    ArrayList<Vector3d> nrmls = mesh.getNormals();
    if (nrmls == null) {
        System.out.println("Mesh does not have normals; thickening ignored");
    }
    int cnt = 0;
    Vector3d regionNrm = new Vector3d();
    // region normal in mesh coordinates
    region.myFrame.R.getColumn(2, regionNrm);
    for (int i = 0; i < verts.size(); i++) {
        Vertex3d v = verts.get(i);
        pnt.inverseTransform(region.myFrame, v.pnt);
        nrm.inverseTransform(region.myFrame, nrmls.get(i));
        if (pnt.z <= region.myHeight && pnt.z >= -region.myBackHeight) {
            // if (Math.abs(pnt.z) <= region.myHeight) {
            p2d.set(pnt.x, pnt.y);
            double d = region.myDist.computeInteriorDistance(/*near=*/
            null, p2d);
            if (d <= 0) {
                double dz = computeDeltaZ(-d, margin, thickening);
                if (region.myUseNormalZScalingP) {
                    if (adjacentFacesCrossNormal(v, regionNrm)) {
                        dz = 0;
                    } else {
                        dz *= nrm.z;
                    }
                } else {
                    dz = (nrm.z >= 0 ? dz : -dz);
                }
                if (nrm.z >= 0) {
                    pnt.z += dz;
                } else {
                    if (region.getThickenBackSide()) {
                        pnt.z += dz;
                    }
                }
                v.pnt.transform(region.myFrame, pnt);
                cnt++;
            }
        }
    }
    System.out.println("count=" + cnt);
    myMesh.notifyVertexPositionsModified();
    viewer.rerender();
}
Also used : Vertex3d(maspack.geometry.Vertex3d) Vector2d(maspack.matrix.Vector2d) Vector3d(maspack.matrix.Vector3d) Point3d(maspack.matrix.Point3d)

Example 2 with Vector2d

use of maspack.matrix.Vector2d 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 3 with Vector2d

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

the class BVFeatureQueryTest method nearestFaceTiming.

private void nearestFaceTiming(PolygonalMesh mesh) {
    RigidTransform3d X = new RigidTransform3d();
    OBBTree obbTree = new OBBTree(mesh, 2);
    AABBTree aabbTree = new AABBTree(mesh);
    Point3d center = new Point3d();
    double diameter = 2 * aabbTree.getRadius();
    aabbTree.getCenter(center);
    X.setRandom();
    BVFeatureQuery query = new BVFeatureQuery();
    mesh.setMeshToWorld(X);
    obbTree.setBvhToWorld(X);
    aabbTree.setBvhToWorld(X);
    int numcases = 100;
    int timingcnt = 1000;
    Point3d pnt = new Point3d();
    Vector3d dir = new Vector3d();
    Point3d near = new Point3d();
    Vector2d coords = new Vector2d();
    Vector3d duv = new Vector3d();
    FunctionTimer obbFaceTimer = new FunctionTimer();
    FunctionTimer aabbFaceTimer = new FunctionTimer();
    // FunctionTimer oldFaceTimer = new FunctionTimer();
    FunctionTimer obbRayTimer = new FunctionTimer();
    FunctionTimer aabbRayTimer = new FunctionTimer();
    // FunctionTimer oldRayTimer = new FunctionTimer();
    TriangleIntersector ti = new TriangleIntersector();
    for (int i = 0; i < numcases; i++) {
        pnt.setRandom();
        pnt.scale(2 * diameter);
        pnt.add(center);
        pnt.transform(X, pnt);
        dir.setRandom();
        dir.normalize();
        obbFaceTimer.restart();
        for (int j = 0; j < timingcnt; j++) {
            query.nearestFaceToPoint(near, coords, obbTree, pnt);
        }
        obbFaceTimer.stop();
        aabbFaceTimer.restart();
        for (int j = 0; j < timingcnt; j++) {
            query.nearestFaceToPoint(near, coords, aabbTree, pnt);
        }
        aabbFaceTimer.stop();
        // oldFaceTimer.restart();
        // for (int j=0; j<timingcnt; j++) {
        // obbTree.nearestFace (pnt, null, near, coords, ti);
        // }
        // oldFaceTimer.stop();
        obbRayTimer.restart();
        for (int j = 0; j < timingcnt; j++) {
            query.nearestFaceAlongRay(near, duv, obbTree, center, dir);
        }
        obbRayTimer.stop();
        aabbRayTimer.restart();
        for (int j = 0; j < timingcnt; j++) {
            query.nearestFaceAlongRay(near, duv, aabbTree, center, dir);
        }
        aabbRayTimer.stop();
    // oldRayTimer.restart();
    // for (int j=0; j<timingcnt; j++) {
    // obbTree.intersect (center, dir, duv, ti);
    // }
    // oldRayTimer.stop();
    }
    int cnt = numcases * timingcnt;
    System.out.println("nearestFace with OBB: " + obbFaceTimer.result(cnt));
    System.out.println("nearestFace with AABB: " + aabbFaceTimer.result(cnt));
    // System.out.println (
    // "nearestFace with old OBB: " + oldFaceTimer.result(cnt));
    System.out.println("nearestRay with OBB: " + obbRayTimer.result(cnt));
    System.out.println("nearestRay with AABB: " + aabbRayTimer.result(cnt));
// System.out.println (
// "nearestRay with old OBB: " + oldRayTimer.result(cnt));
}
Also used : RigidTransform3d(maspack.matrix.RigidTransform3d) Vector2d(maspack.matrix.Vector2d) Vector3d(maspack.matrix.Vector3d) Point3d(maspack.matrix.Point3d) FunctionTimer(maspack.util.FunctionTimer)

Example 4 with Vector2d

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

the class Intersector2d method intersectLineLine.

public int intersectLineLine(Point2d c1, Vector2d v1, Point2d c2, Vector2d v2, ArrayList<Point2d> points) {
    int nAdded = 0;
    Vector2d n1 = new Vector2d(-v1.y, v1.x);
    Vector2d n2 = new Vector2d(-v2.y, v2.x);
    n1.normalize();
    n2.normalize();
    double b1 = c1.dot(n1);
    double b2 = c2.dot(n2);
    // denominator, if zero lines are parallel
    double d = n1.x * n2.y - n1.y * n2.x;
    if (Math.abs(d) < epsilon) {
        d = n1.dot(c2) - b1;
        // distance of c2 to line 1
        d = d / n1.norm();
        if (Math.abs(d) < epsilon) {
            // lines are colinear, so add both
            // add both points
            points.add(c1);
            points.add(c2);
            nAdded = 2;
        } else {
            nAdded = 0;
        }
    } else {
        double x = (n2.y * b1 - n1.y * b2) / d;
        double y = (-n2.x * b1 + n1.x * b2) / d;
        points.add(new Point2d(x, y));
        nAdded++;
    }
    return nAdded;
}
Also used : Vector2d(maspack.matrix.Vector2d) Point2d(maspack.matrix.Point2d)

Example 5 with Vector2d

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

the class GLSupport method transformToGLMatrix.

/**
 * Converts a 2D affine transform to a 4D matrix expected by opengl
 */
public static void transformToGLMatrix(double[] mat, AffineTransform2dBase T) {
    Matrix2dBase M = T.getMatrix();
    Vector2d p = T.getOffset();
    mat[0] = M.m00;
    mat[1] = M.m10;
    mat[2] = 0;
    mat[3] = 0;
    mat[4] = M.m01;
    mat[5] = M.m11;
    mat[6] = 01;
    mat[7] = 0;
    mat[8] = 0;
    mat[9] = 0;
    mat[10] = 0;
    mat[11] = 0;
    mat[12] = p.x;
    mat[13] = p.y;
    mat[14] = 0;
    mat[15] = 1;
}
Also used : Vector2d(maspack.matrix.Vector2d) Matrix2dBase(maspack.matrix.Matrix2dBase)

Aggregations

Vector2d (maspack.matrix.Vector2d)35 Point3d (maspack.matrix.Point3d)16 Vector3d (maspack.matrix.Vector3d)11 Face (maspack.geometry.Face)9 Vertex3d (maspack.geometry.Vertex3d)8 ArrayList (java.util.ArrayList)7 BVFeatureQuery (maspack.geometry.BVFeatureQuery)7 RigidTransform3d (maspack.matrix.RigidTransform3d)6 Point2d (maspack.matrix.Point2d)5 PolygonalMesh (maspack.geometry.PolygonalMesh)4 ContactPoint (artisynth.core.mechmodels.ContactPoint)3 Point (artisynth.core.mechmodels.Point)3 Point (java.awt.Point)3 VectorNd (maspack.matrix.VectorNd)3 PointAttachment (artisynth.core.mechmodels.PointAttachment)2 PointParticleAttachment (artisynth.core.mechmodels.PointParticleAttachment)2 Rectangle (java.awt.Rectangle)2 HashMap (java.util.HashMap)2 BVTree (maspack.geometry.BVTree)2 Matrix2dBase (maspack.matrix.Matrix2dBase)2