use of maspack.matrix.Vector3i in project artisynth_core by artisynth.
the class DistanceGrid method scan.
public void scan(ReaderTokenizer rtok, Object ref) throws IOException {
rtok.scanToken('[');
RigidTransform3d TCL = new RigidTransform3d();
RigidTransform3d TLW = null;
Vector3d widths = new Vector3d();
Vector3i resolution = null;
myTLocalToWorld = null;
while (rtok.nextToken() != ']') {
if (rtok.ttype != ReaderTokenizer.TT_WORD) {
throw new IOException("Expected attribute name, " + rtok);
}
if (rtok.sval.equals("resolution")) {
rtok.scanToken('=');
resolution = new Vector3i();
resolution.scan(rtok);
setResolution(resolution);
} else if (rtok.sval.equals("widths")) {
rtok.scanToken('=');
widths.scan(rtok);
setWidths(widths);
} else if (rtok.sval.equals("center")) {
rtok.scanToken('=');
TCL.p.scan(rtok);
} else if (rtok.sval.equals("orientation")) {
rtok.scanToken('=');
TCL.R.scan(rtok);
} else if (rtok.sval.equals("LocalToWorld")) {
rtok.scanToken('=');
TLW = new RigidTransform3d();
TLW.scan(rtok);
} else if (rtok.sval.equals("distances")) {
if (resolution == null) {
throw new IOException("distances must be specified after resolution, line " + rtok.lineno());
}
rtok.scanToken('=');
rtok.scanToken('[');
int k = 0;
while (rtok.nextToken() != ']') {
rtok.pushBack();
myPhi[k++] = rtok.scanNumber();
}
} else {
throw new IOException("Unexpected attribute name: " + rtok);
}
}
setCenterAndOrientation(TCL);
if (TLW != null) {
setLocalToWorld(TLW);
}
// clear normals and quad coefs; shouldn't be necessary if resolution
// was set
myQuadCoefs = null;
clearNormals();
}
use of maspack.matrix.Vector3i in project artisynth_core by artisynth.
the class DistanceGrid method doGetQuadDistanceAndGradient.
protected double doGetQuadDistanceAndGradient(Vector3d grad, Matrix3d dgrad, Point3d point, VectorTransformer3d quadGridToX) {
Vector3d coords = new Vector3d();
double[] a;
double dx, dy, dz;
if (storeQuadCoefs) {
updateQuadCoefsIfNecessary();
int voff = getQuadCellCoords(coords, null, point, quadGridToX);
if (voff == -1) {
return OUTSIDE_GRID;
}
dx = coords.x;
dy = coords.y;
dz = coords.z;
a = myQuadCoefs[6 * voff + TetID.findSubTetIdx(dx, dy, dz)];
} else {
// Change to grid coordinates
Vector3i vidx = new Vector3i();
if (getQuadCellCoords(coords, vidx, point, quadGridToX) == -1) {
return OUTSIDE_GRID;
}
dx = coords.x;
dy = coords.y;
dz = coords.z;
a = new double[10];
TetDesc tdesc = new TetDesc(vidx, TetID.findSubTet(dx, dy, dz));
computeQuadCoefs(a, tdesc);
}
if (grad != null) {
computeQuadGradient(grad, a, dx, dy, dz, quadGridToX);
}
if (dgrad != null) {
computeQuadHessian(dgrad, a, quadGridToX);
}
return computeQuadDistance(a, dx, dy, dz);
}
use of maspack.matrix.Vector3i in project artisynth_core by artisynth.
the class DistanceGrid method createQuadDistanceSurface.
/**
* Creates a triangular mesh approximating the surface on which the
* quadratically interpolated distance function equals <code>val</code>.
*
* @param val iso surface value
* @param res multiplies the resolution of this grid to obtain the
* resolution of the grid used to create the mesh.
* @return iso surface for quadratic interpolation
*/
public PolygonalMesh createQuadDistanceSurface(double val, int res) {
MarchingTetrahedra marcher = new MarchingTetrahedra();
// sample at a res X higher resolution so we can get
// a better sense of the smooth surface
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();
// build a high res distance map by iterating through all the quad grid
// cells:
double[] a = new double[10];
for (int i = 0; i < myQx; i++) {
for (int j = 0; j < myQy; j++) {
for (int k = 0; k < myQz; k++) {
Vector3i vidx = new Vector3i(i, j, k);
double cx, cy, cz;
int maxci = ((i < myQx - 1) ? 2 * res - 1 : 2 * res);
int maxcj = ((j < myQy - 1) ? 2 * res - 1 : 2 * res);
int maxck = ((k < myQz - 1) ? 2 * res - 1 : 2 * res);
for (int ci = 0; ci <= maxci; ci++) {
cx = ci * invRes / 2;
for (int cj = 0; cj <= maxcj; cj++) {
cy = cj * invRes / 2;
for (int ck = 0; ck <= maxck; ck++) {
cz = ck * invRes / 2;
TetDesc tdesc = new TetDesc(vidx, TetID.findSubTet(cx, cy, cz));
computeQuadCoefs(a, tdesc);
dists[(2 * i * res + ci) + (2 * j * res + cj) * nvx + (2 * k * res + ck) * nvx * nvy] = computeQuadDistance(a, cx, cy, cz);
}
}
}
}
}
}
PolygonalMesh mesh = marcher.createMesh(dists, Vector3d.ZERO, new Vector3d(invRes, invRes, invRes), cellRes, val);
mesh.transform(myGridToLocal);
return mesh;
}
use of maspack.matrix.Vector3i in project artisynth_core by artisynth.
the class DistanceGrid method doGetQuadDistance.
protected double doGetQuadDistance(Point3d point, VectorTransformer3d quadGridToX) {
Vector3d coords = new Vector3d();
double[] a;
double dx, dy, dz;
if (storeQuadCoefs) {
updateQuadCoefsIfNecessary();
int voff = getQuadCellCoords(coords, null, point, quadGridToX);
if (voff == -1) {
return OUTSIDE_GRID;
}
dx = coords.x;
dy = coords.y;
dz = coords.z;
a = myQuadCoefs[6 * voff + TetID.findSubTetIdx(dx, dy, dz)];
} else {
// Change to grid coordinates
Vector3i vidx = new Vector3i();
if (getQuadCellCoords(coords, vidx, point, quadGridToX) == -1) {
return OUTSIDE_GRID;
}
dx = coords.x;
dy = coords.y;
dz = coords.z;
a = new double[10];
TetDesc tdesc = new TetDesc(vidx, TetID.findSubTet(dx, dy, dz));
computeQuadCoefs(a, tdesc);
}
return computeQuadDistance(a, dx, dy, dz);
}
use of maspack.matrix.Vector3i in project artisynth_core by artisynth.
the class DistanceGrid method calculatePhi.
/**
* Calculates the distance field.
*/
void calculatePhi(double[] phi, int[] closestFeatureIdxs, Feature[] features, boolean signed) {
// Logger logger = Logger.getSystemLogger();
// logger.info ("Calculating Distance Field...");
double maxDist = 2 * getRadius();
int numv = myNx * myNy * myNz;
if (phi.length != numv || (closestFeatureIdxs != null && closestFeatureIdxs.length != numv)) {
throw new InternalErrorException("length of phi and/or closestFeatureIdxs != numVertices()");
}
for (int k = 0; k < numv; k++) {
phi[k] = maxDist;
}
// Feature to the grid vertex.
if (closestFeatureIdxs != null) {
for (int i = 0; i < numv; i++) {
closestFeatureIdxs[i] = -1;
}
}
int[] zIntersectCount = null;
if (signed) {
zIntersectCount = new int[numv];
for (int i = 0; i < numv; i++) {
zIntersectCount[i] = 0;
}
}
Point3d featPnt = new Point3d();
Point3d gridPnt = new Point3d();
Vector3i gridMinOld = new Vector3i();
Vector3i gridMaxOld = new Vector3i();
Vector3i gridMin = new Vector3i();
Vector3i gridMax = new Vector3i();
Point3d featMin = new Point3d();
Point3d featMax = new Point3d();
Point3d nearPntLoc = new Point3d();
Point3d featPntLoc = new Point3d();
Vector3i hi = new Vector3i();
Vector3i lo = new Vector3i();
// For every feature ...
for (int t = 0; t < features.length; ++t) {
// Find the vertex-aligned parallelpiped containing the feature's
// bounding box.
Feature feature = features[t];
gridMin.set(myNx + 1, myNy + 1, myNz + 1);
gridMax.set(-1, -1, -1);
// max, minz of the feature in grid coords
double maxz = -INF;
double minz = INF;
for (int i = 0; i < feature.numPoints(); i++) {
featPnt = feature.getPoint(i);
myGridToLocal.inverseTransformPnt(gridPnt, featPnt);
lo.x = clip((int) gridPnt.x, 0, myNx - 1);
lo.y = clip((int) gridPnt.y, 0, myNy - 1);
lo.z = clip((int) gridPnt.z, 0, myNz - 1);
hi.x = clip((int) (gridPnt.x + 1), 0, myNx - 1);
hi.y = clip((int) (gridPnt.y + 1), 0, myNy - 1);
hi.z = clip((int) (gridPnt.z + 1), 0, myNz - 1);
if (gridPnt.z < minz) {
minz = gridPnt.z;
}
if (gridPnt.z > maxz) {
maxz = gridPnt.z;
}
lo.updateBounds(gridMin, gridMax);
hi.updateBounds(gridMin, gridMax);
}
// closestFeature.
for (int zk = gridMin.z; zk <= gridMax.z; zk++) {
for (int yj = gridMin.y; yj <= gridMax.y; yj++) {
for (int xi = gridMin.x; xi <= gridMax.x; xi++) {
// Get features coordinates
featPntLoc.set(xi, yj, zk);
myGridToLocal.transformPnt(featPntLoc, featPntLoc);
// Get the distance from this point to the Feature.
feature.nearestPoint(nearPntLoc, featPntLoc);
double distance = featPntLoc.distance(nearPntLoc);
int index = xyzIndicesToVertex(xi, yj, zk);
if (index >= numv) {
System.out.println("coords = " + xi + " " + yj + " " + zk);
}
if (distance < phi[index]) {
phi[index] = distance;
if (closestFeatureIdxs != null) {
closestFeatureIdxs[index] = t;
}
}
}
}
}
if (signed) {
if (!(feature instanceof Face)) {
throw new IllegalArgumentException("Signed grid can only be created if all features are Faces");
}
Face face = (Face) feature;
Point3d bot = new Point3d();
Point3d top = new Point3d();
// We're building intersectionCount[] to use in ray casting below.
for (int yj = gridMin.y; yj <= gridMax.y; yj++) {
for (int xi = gridMin.x; xi <= gridMax.x; xi++) {
Point3d ipnt = new Point3d();
int res = 0;
if (maxz >= 0) {
myGridToLocal.transformPnt(bot, new Point3d(xi, yj, minz - 1));
myGridToLocal.transformPnt(top, new Point3d(xi, yj, maxz + 1));
res = RobustPreds.intersectSegmentTriangle(ipnt, bot, top, face, maxDist, /*worldCoords=*/
false);
}
if (res > 0) {
myGridToLocal.inverseTransformPnt(gridPnt, ipnt);
int zInterval = clip((int) Math.ceil(gridPnt.z), 0, myNz - 1);
++zIntersectCount[xyzIndicesToVertex(xi, yj, zInterval)];
}
// point in triangle
}
// x
}
// y
}
}
// Sweep, propagating values throughout the grid volume.
for (int pass = 0; pass < 2; pass++) {
sweep(phi, +1, +1, +1, closestFeatureIdxs, features);
sweep(phi, -1, -1, -1, closestFeatureIdxs, features);
sweep(phi, +1, +1, -1, closestFeatureIdxs, features);
sweep(phi, -1, -1, +1, closestFeatureIdxs, features);
sweep(phi, +1, -1, +1, closestFeatureIdxs, features);
sweep(phi, -1, +1, -1, closestFeatureIdxs, features);
sweep(phi, +1, -1, -1, closestFeatureIdxs, features);
sweep(phi, -1, +1, +1, closestFeatureIdxs, features);
}
if (signed) {
// vertex in the grid.
for (int xi = 0; xi < myNx; xi++) {
for (int yj = 0; yj < myNy; yj++) {
int total_count = 0;
// Count the intersections of the x axis
for (int zk = 0; zk < myNz; zk++) {
int index = xyzIndicesToVertex(xi, yj, zk);
total_count += zIntersectCount[index];
// mesh.
if (total_count % 2 == 1) {
phi[index] = -phi[index];
}
}
}
}
}
}
Aggregations