Search in sources :

Example 21 with Vector3i

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

the class DistanceGridTester method normalCalcTest.

/**
 * This test verifies the normal calculations. For every point, we find the
 * nearest point to the triangle, subtract the points, and normalize the
 * resulting vector. There is usually quite a bit of error, especially with
 * finer resolution meshes. The error calculation is done per axis, and
 * should perhaps be represented in a better way in the future.
 */
private void normalCalcTest() {
    Vector3d normal = new Vector3d();
    double[] myPhi = g.getDistances();
    double epsilon = 1e-8;
    Point3d closestPoint = new Point3d();
    Point3d meshpnt = new Point3d();
    double errorCount = 0;
    Vector3d errorSum = new Vector3d();
    Vector3d errorAverage = new Vector3d();
    Vector3d errorMax = new Vector3d();
    Vector3d errorThis = new Vector3d();
    for (int i = 0; i < myPhi.length; i++) {
        g.getLocalVertexCoords(meshpnt, g.vertexToXyzIndices(new Vector3i(), i));
        double dist = g.getLocalDistanceAndNormal(normal, meshpnt.x, meshpnt.y, meshpnt.z);
        Face face = (Face) g.getClosestFeature(i);
        face.nearestPoint(closestPoint, meshpnt);
        // closestPoint.sub (meshpnt);
        meshpnt.sub(closestPoint);
        meshpnt.absolute();
        meshpnt.normalize();
        normal.absolute();
        // normal.scale (dist);
        double myErr = meshpnt.distance(normal);
        if (myErr > epsilon) {
            // g.setGridPointColor (i, Color.WHITE);
            errorThis.x = Math.abs(normal.x - meshpnt.x) / meshpnt.x * 100.0;
            errorThis.y = Math.abs(normal.y - meshpnt.y) / meshpnt.y * 100.0;
            errorThis.z = Math.abs(normal.z - meshpnt.z) / meshpnt.z * 100.0;
            if (errorThis.x > errorMax.x) {
                errorMax.x = errorThis.x;
            }
            if (errorThis.y > errorMax.y) {
                errorMax.y = errorThis.y;
            }
            if (errorThis.z > errorMax.z) {
                errorMax.z = errorThis.z;
            }
            errorSum.add(errorThis);
            errorCount++;
        }
    }
    if (errorCount != 0) {
        errorAverage.x = errorSum.x / errorCount;
        errorAverage.y = errorSum.y / errorCount;
        errorAverage.z = errorSum.z / errorCount;
    }
    System.out.println("Average error of normals: " + errorAverage);
    System.out.println("Max error of normals: " + errorMax);
}
Also used : Vector3d(maspack.matrix.Vector3d) Point3d(maspack.matrix.Point3d) Vector3i(maspack.matrix.Vector3i)

Example 22 with Vector3i

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

the class DistanceGridTester method checkPhiIsSet.

/**
 * This test checks that every value in phi is less than half the width of
 * the parallelpiped that is formed by the grid.
 */
private void checkPhiIsSet() {
    double[] myPhi = g.getDistances();
    Vector3i resolution = g.getResolution();
    Vector3d cellSize = g.getCellWidths();
    double maxDist = Math.sqrt(resolution.x * cellSize.x * resolution.x * cellSize.x + resolution.y * cellSize.y * resolution.y * cellSize.y + resolution.z * cellSize.z * resolution.z * cellSize.z);
    for (int i = 0; i < myPhi.length; i++) {
        if (myPhi[i] >= maxDist || myPhi[i] <= -maxDist) {
            throw new TestException("phi at index " + i + " has not been set.");
        }
    }
    System.out.println("Phi has been initialized. Test Passed.");
}
Also used : Vector3d(maspack.matrix.Vector3d) Vector3i(maspack.matrix.Vector3i)

Example 23 with Vector3i

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

the class DistanceGridTester method colourTest.

/**
 * This test changes the colour of each vertex based on
 * distance from the mesh surface. This is a visual test of the integrity
 * of the signed distance field.
 */
private void colourTest() {
    double[] myPhi = g.getDistances();
    Vector3i resolution = g.getResolution();
    Vector3d cellSize = g.getCellWidths();
    for (int i = 0; i < myPhi.length; i++) {
        // Extract out the grid coordinates.
        Vector3i gidxs = new Vector3i();
        g.vertexToXyzIndices(gidxs, i);
        double maxDist = Math.sqrt(resolution.x * cellSize.x * resolution.x * cellSize.x + resolution.y * cellSize.y * resolution.y * cellSize.y + resolution.z * cellSize.z * resolution.z * cellSize.z) / 3.0f;
        float h = (float) (Math.abs(g.getVertexDistance(gidxs)) / maxDist);
        float[] RGB = new float[3];
        float[] HSV = new float[3];
        HSV[0] = h;
        HSV[1] = 1.0f;
        HSV[2] = 1.0f;
        ColorUtils.HSVtoRGB(HSV, RGB);
        g.setVertexColor(i, new Color(RGB[0], RGB[1], RGB[2]));
    }
    System.out.println("Colour Test complete.");
}
Also used : Vector3d(maspack.matrix.Vector3d) Color(java.awt.Color) Vector3i(maspack.matrix.Vector3i)

Example 24 with Vector3i

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

the class DistanceGrid method getLocalDistanceAndNormal.

/**
 * Calculates the distance and normal at an arbitrary point in local
 * coordinates using multilinear interpolation, as described for {@link
 * #getLocalDistanceAndNormal(Vector3d,Point3d)}. If <code>Dnrm</code> is
 * non-<code>null</code>, the method also calculated the normal derivative.
 * If the point lies outside the grid volume, {@link #OUTSIDE_GRID} is
 * returned.
 *
 * @param norm returns the normal (local coordinates)
 * @param Dnrm if non-null, returns the normal derivative (local coordinates)
 * @param point point at which to calculate the normal and distance
 * (local coordinates).
 * @return interpolated distance, or <code>OUTSIDE_GRID</code>.
 */
public double getLocalDistanceAndNormal(Vector3d norm, Matrix3d Dnrm, Point3d point) {
    Vector3d coords = new Vector3d();
    Vector3i vidx = new Vector3i();
    if (!getCellCoords(vidx, coords, point)) {
        return OUTSIDE_GRID;
    }
    double dx = coords.x;
    double dy = coords.y;
    double dz = coords.z;
    // Compute weights w000, w001, w010, etc. for trilinear interpolation.
    // w001z, w011z, etc. are the derivatives of the weights
    // with respect to dz. Can use to compute weights, and also
    // to compute Dnrm if needed
    double w001z = (1 - dx) * (1 - dy);
    double w011z = (1 - dx) * dy;
    double w101z = dx * (1 - dy);
    double w111z = dx * dy;
    double w000 = w001z * (1 - dz);
    double w001 = w001z * dz;
    double w010 = w011z * (1 - dz);
    double w011 = w011z * dz;
    double w100 = w101z * (1 - dz);
    double w101 = w101z * dz;
    double w110 = w111z * (1 - dz);
    double w111 = w111z * dz;
    double d000 = getVertexDistance(vidx.x, vidx.y, vidx.z);
    double d001 = getVertexDistance(vidx.x, vidx.y, vidx.z + 1);
    double d010 = getVertexDistance(vidx.x, vidx.y + 1, vidx.z);
    double d011 = getVertexDistance(vidx.x, vidx.y + 1, vidx.z + 1);
    double d100 = getVertexDistance(vidx.x + 1, vidx.y, vidx.z);
    double d101 = getVertexDistance(vidx.x + 1, vidx.y, vidx.z + 1);
    double d110 = getVertexDistance(vidx.x + 1, vidx.y + 1, vidx.z);
    double d111 = getVertexDistance(vidx.x + 1, vidx.y + 1, vidx.z + 1);
    double d = w000 * d000 + w001 * d001 + w010 * d010 + w011 * d011 + w100 * d100 + w101 * d101 + w110 * d110 + w111 * d111;
    if (norm != null || Dnrm != null) {
        Vector3d n000 = getLocalVertexNormal(vidx.x, vidx.y, vidx.z);
        Vector3d n001 = getLocalVertexNormal(vidx.x, vidx.y, vidx.z + 1);
        Vector3d n010 = getLocalVertexNormal(vidx.x, vidx.y + 1, vidx.z);
        Vector3d n011 = getLocalVertexNormal(vidx.x, vidx.y + 1, vidx.z + 1);
        Vector3d n100 = getLocalVertexNormal(vidx.x + 1, vidx.y, vidx.z);
        Vector3d n101 = getLocalVertexNormal(vidx.x + 1, vidx.y, vidx.z + 1);
        Vector3d n110 = getLocalVertexNormal(vidx.x + 1, vidx.y + 1, vidx.z);
        Vector3d n111 = getLocalVertexNormal(vidx.x + 1, vidx.y + 1, vidx.z + 1);
        if (norm == null && Dnrm != null) {
            norm = new Vector3d();
        }
        if (norm != null) {
            norm.setZero();
            norm.scaledAdd(w000, n000);
            norm.scaledAdd(w001, n001);
            norm.scaledAdd(w010, n010);
            norm.scaledAdd(w011, n011);
            norm.scaledAdd(w100, n100);
            norm.scaledAdd(w101, n101);
            norm.scaledAdd(w110, n110);
            norm.scaledAdd(w111, n111);
        // norm.normalize();
        }
        if (Dnrm != null) {
            // compute weight derivatives with respect to dx and dy
            double w100x = (1 - dy) * (1 - dz);
            double w101x = (1 - dy) * dz;
            double w110x = dy * (1 - dz);
            double w111x = dy * dz;
            double w010y = (1 - dx) * (1 - dz);
            double w011y = (1 - dx) * dz;
            double w110y = dx * (1 - dz);
            double w111y = dx * dz;
            if (true) {
                Vector3d row = new Vector3d();
                // top row of Dnrm
                row.x = (-w100x * n000.x - w101x * n001.x - w110x * n010.x - w111x * n011.x + w100x * n100.x + w101x * n101.x + w110x * n110.x + w111x * n111.x);
                row.y = (-w010y * n000.x - w011y * n001.x + w010y * n010.x + w011y * n011.x - w110y * n100.x - w111y * n101.x + w110y * n110.x + w111y * n111.x);
                row.z = (-w001z * n000.x + w001z * n001.x - w011z * n010.x + w011z * n011.x - w101z * n100.x + w101z * n101.x - w111z * n110.x + w111z * n111.x);
                myGridToLocal.transformCovec(row, row);
                row.scale(d);
                Dnrm.m00 = row.x;
                Dnrm.m01 = row.y;
                Dnrm.m02 = row.z;
                // middle row of Dnrm
                row.x = (-w100x * n000.y - w101x * n001.y - w110x * n010.y - w111x * n011.y + w100x * n100.y + w101x * n101.y + w110x * n110.y + w111x * n111.y);
                row.y = (-w010y * n000.y - w011y * n001.y + w010y * n010.y + w011y * n011.y - w110y * n100.y - w111y * n101.y + w110y * n110.y + w111y * n111.y);
                row.z = (-w001z * n000.y + w001z * n001.y - w011z * n010.y + w011z * n011.y - w101z * n100.y + w101z * n101.y - w111z * n110.y + w111z * n111.y);
                myGridToLocal.transformCovec(row, row);
                row.scale(d);
                Dnrm.m10 = row.x;
                Dnrm.m11 = row.y;
                Dnrm.m12 = row.z;
                // bottom row of Dnrm
                row.x = (-w100x * n000.z - w101x * n001.z - w110x * n010.z - w111x * n011.z + w100x * n100.z + w101x * n101.z + w110x * n110.z + w111x * n111.z);
                row.y = (-w010y * n000.z - w011y * n001.z + w010y * n010.z + w011y * n011.z - w110y * n100.z - w111y * n101.z + w110y * n110.z + w111y * n111.z);
                row.z = (-w001z * n000.z + w001z * n001.z - w011z * n010.z + w011z * n011.z - w101z * n100.z + w101z * n101.z - w111z * n110.z + w111z * n111.z);
                myGridToLocal.transformCovec(row, row);
                row.scale(d);
                Dnrm.m20 = row.x;
                Dnrm.m21 = row.y;
                Dnrm.m22 = row.z;
            } else {
                Dnrm.setZero();
            }
            Vector3d grad = new Vector3d();
            grad.x = (-w100x * d000 - w101x * d001 - w110x * d010 - w111x * d011 + w100x * d100 + w101x * d101 + w110x * d110 + w111x * d111);
            grad.y = (-w010y * d000 - w011y * d001 + w010y * d010 + w011y * d011 - w110y * d100 - w111y * d101 + w110y * d110 + w111y * d111);
            grad.z = (-w001z * d000 + w001z * d001 - w011z * d010 + w011z * d011 - w101z * d100 + w101z * d101 - w111z * d110 + w111z * d111);
            myGridToLocal.transformCovec(grad, grad);
            Dnrm.addOuterProduct(norm, grad);
        }
    }
    return d;
}
Also used : Vector3d(maspack.matrix.Vector3d) Vector3i(maspack.matrix.Vector3i)

Example 25 with Vector3i

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

the class DistanceGrid method createDistanceSurface.

/**
 * Creates a triangular mesh approximating the surface on which the linearly
 * interpolated distance function equals <code>val</code>.
 *
 * @param val iso surface value
 * @return iso surface for linear interpolation
 */
public PolygonalMesh createDistanceSurface(double val, int res) {
    MarchingTetrahedra marcher = new MarchingTetrahedra();
    Vector3i cellRes = new Vector3i(getResolution());
    cellRes.scale(res);
    int nvx = cellRes.x + 1;
    int nvy = cellRes.y + 1;
    int nvz = cellRes.z + 1;
    double[] dists = new double[nvx * nvy * nvz];
    double invRes = 1.0 / res;
    Point3d q = new Point3d();
    for (int i = 0; i < myNx - 1; i++) {
        for (int j = 0; j < myNy - 1; j++) {
            for (int k = 0; k < myNz - 1; k++) {
                double d000 = getVertexDistance(i, j, k);
                double d001 = getVertexDistance(i, j, k + 1);
                double d010 = getVertexDistance(i, j + 1, k);
                double d011 = getVertexDistance(i, j + 1, k + 1);
                double d100 = getVertexDistance(i + 1, j, k);
                double d101 = getVertexDistance(i + 1, j, k + 1);
                double d110 = getVertexDistance(i + 1, j + 1, k);
                double d111 = getVertexDistance(i + 1, j + 1, k + 1);
                int maxci = (i < myNx - 2 ? res - 1 : res);
                int maxcj = (j < myNy - 2 ? res - 1 : res);
                int maxck = (k < myNz - 2 ? res - 1 : res);
                double cx, cy, cz;
                for (int ci = 0; ci <= maxci; ci++) {
                    cx = ci * invRes;
                    for (int cj = 0; cj <= maxcj; cj++) {
                        cy = cj * invRes;
                        for (int ck = 0; ck <= maxck; ck++) {
                            cz = ck * invRes;
                            double w001z = (1 - cx) * (1 - cy);
                            double w011z = (1 - cx) * cy;
                            double w101z = cx * (1 - cy);
                            double w111z = cx * cy;
                            double w000 = w001z * (1 - cz);
                            double w001 = w001z * cz;
                            double w010 = w011z * (1 - cz);
                            double w011 = w011z * cz;
                            double w100 = w101z * (1 - cz);
                            double w101 = w101z * cz;
                            double w110 = w111z * (1 - cz);
                            double w111 = w111z * cz;
                            dists[(i * res + ci) + (j * res + cj) * nvx + (k * res + ck) * nvx * nvy] = w000 * d000 + w001 * d001 + w010 * d010 + w011 * d011 + w100 * d100 + w101 * d101 + w110 * d110 + w111 * d111;
                        }
                    }
                }
            }
        }
    }
    PolygonalMesh mesh = marcher.createMesh(dists, Vector3d.ZERO, new Vector3d(invRes, invRes, invRes), cellRes, val);
    mesh.transform(myGridToLocal);
    return mesh;
}
Also used : Vector3d(maspack.matrix.Vector3d) Vector3i(maspack.matrix.Vector3i)

Aggregations

Vector3i (maspack.matrix.Vector3i)30 Vector3d (maspack.matrix.Vector3d)19 Point3d (maspack.matrix.Point3d)5 ArrayList (java.util.ArrayList)2 DistanceGrid (maspack.geometry.DistanceGrid)2 TetDesc (maspack.geometry.DistanceGrid.TetDesc)2 Face (maspack.geometry.Face)2 RigidTransform3d (maspack.matrix.RigidTransform3d)2 InternalErrorException (maspack.util.InternalErrorException)2 FemModel3d (artisynth.core.femmodels.FemModel3d)1 FemNode3d (artisynth.core.femmodels.FemNode3d)1 IntegrationPoint3d (artisynth.core.femmodels.IntegrationPoint3d)1 TransformableGeometry (artisynth.core.modelbase.TransformableGeometry)1 Color (java.awt.Color)1 File (java.io.File)1 IOException (java.io.IOException)1 HashMap (java.util.HashMap)1 HashSet (java.util.HashSet)1 TetID (maspack.geometry.DistanceGrid.TetID)1 OBB (maspack.geometry.OBB)1