use of maspack.geometry.Face 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;
}
use of maspack.geometry.Face in project artisynth_core by artisynth.
the class FemMeshComp method createSurface.
// Throwable throwable = null;
public void createSurface(Collection<FemElement3d> elems) {
initializeSurfaceBuild();
// nodeVertexMap is used during the construction of this surface,
// so we build it during the construction rather then letting
// it be built in finalizeSurfaceBuild()
myNodeVertexMap = new HashMap<FemNode3d, Vertex3d>();
myNumSingleAttachments = 0;
LinkedList<FaceNodes3d> allFaces = new LinkedList<FaceNodes3d>();
// faces adjacent to each node
ArrayList<LinkedList<FaceNodes3d>> nodeFaces = new ArrayList<LinkedList<FaceNodes3d>>(myFem.numNodes());
for (int i = 0; i < myFem.numNodes(); i++) {
nodeFaces.add(new LinkedList<FaceNodes3d>());
}
PointList<FemNode3d> femNodes = myFem.getNodes();
// each node, create a list of all the faces it is associated with
for (FemElement3d e : elems) {
FaceNodes3d[] faces = e.getFaces();
for (FaceNodes3d f : faces) {
addEdgeNodesToFace(f, myFem);
for (FemNode3d n : f.getAllNodes()) {
int idx = femNodes.indexOf(n);
if (idx == -1) {
throw new InternalErrorException("Element " + e.getNumber() + ": bad node " + n.getNumber());
}
nodeFaces.get(femNodes.indexOf(n)).add(f);
}
allFaces.add(f);
}
}
// now for each face, check to see if it is overlapping with other faces
HashSet<FaceNodes3d> adjacentFaces = new HashSet<FaceNodes3d>();
for (FaceNodes3d f : allFaces) {
if (!f.isHidden()) {
adjacentFaces.clear();
for (FemNode3d n : f.getAllNodes()) {
Iterator<FaceNodes3d> it = nodeFaces.get(femNodes.indexOf(n)).iterator();
while (it.hasNext()) {
FaceNodes3d g = it.next();
if (g.isHidden()) {
it.remove();
} else if (g.getElement() != f.getElement()) {
adjacentFaces.add(g);
}
}
}
for (FaceNodes3d g : adjacentFaces) {
if (f.isContained(g)) {
f.setHidden(true);
g.setOverlapping(true);
}
if (g.isContained(f)) {
g.setHidden(true);
f.setOverlapping(true);
}
}
}
}
int num = 0;
for (FaceNodes3d f : allFaces) {
if (!f.isOverlapping() && !f.isSelfAttachedToFace()) {
num++;
}
}
// form the surface mesh from the non-overlapping faces
PolygonalMesh mesh = (PolygonalMesh) getMesh();
for (FaceNodes3d f : allFaces) {
if (!f.isOverlapping() && !f.hasSelfAttachedNode() && !f.isSelfAttachedToFace()) {
FemNode3d[][] triangles = f.triangulate();
boolean triangulatedQuad = (triangles.length == 2 && triangles[0][0] == triangles[1][0]);
for (int i = 0; i < triangles.length; i++) {
FemNode3d[] tri = triangles[i];
Vertex3d[] vtxs = new Vertex3d[3];
for (int j = 0; j < 3; j++) {
FemNode3d node = tri[j];
if ((vtxs[j] = myNodeVertexMap.get(node)) == null) {
Vertex3d vtx = new Vertex3d(new Point3d(node.getPosition()));
mesh.addVertex(vtx);
myVertexAttachments.add(new PointParticleAttachment(node, null));
myNumSingleAttachments++;
myNodeVertexMap.put(node, vtx);
vtxs[j] = vtx;
}
}
Face face = mesh.addFace(vtxs);
if (triangulatedQuad && i == 0) {
face.setFirstQuadTriangle(true);
}
}
}
}
finalizeSurfaceBuild();
// throwable = null;
}
use of maspack.geometry.Face in project artisynth_core by artisynth.
the class FemIntersector method makeConvexFace.
// ear splitting technique
protected static void makeConvexFace(PolygonalMesh mesh, Face face, Vector3d normal, double tol) {
if (face.isTriangle()) {
return;
}
Vector3d v1 = new Vector3d();
Vector3d v2 = new Vector3d();
Vertex3d[] vtxs = face.getVertices();
for (int i = 0; i < vtxs.length; i++) {
Vertex3d vm1 = vtxs[(i + vtxs.length - 1) % vtxs.length];
Vertex3d v0 = vtxs[i];
Vertex3d vp1 = vtxs[(i + 1) % vtxs.length];
v1.sub(v0.getWorldPoint(), vm1.getWorldPoint());
v2.sub(vp1.getWorldPoint(), v0.getWorldPoint());
double ang = getAngle(1, v1, 1, v2, normal);
if (ang > -tol) {
for (int j = 1; j < vtxs.length - 1; j++) {
vp1 = vtxs[(i + j + 1) % vtxs.length];
v2.sub(vp1.getWorldPoint(), v0.getWorldPoint());
ang = getAngle(1, v1, 1, v2, normal);
if (ang < -tol) {
// XXX check that doesn't intersect any edges?
Vertex3d[] f1 = new Vertex3d[j + 2];
Vertex3d[] f2 = new Vertex3d[vtxs.length - j];
for (int k = 0; k < f1.length; k++) {
f1[k] = vtxs[(i + k) % vtxs.length];
}
for (int k = 0; k < f2.length - 2; k++) {
f2[k] = vtxs[(i + k + f1.length) % vtxs.length];
}
f2[f2.length - 2] = v0;
f2[f2.length - 1] = f1[f1.length - 1];
mesh.removeFace(face);
Face face1 = mesh.addFace(f1);
Face face2 = mesh.addFace(f2);
makeConvexFace(mesh, face1, normal, tol);
makeConvexFace(mesh, face2, normal, tol);
return;
}
}
}
}
}
use of maspack.geometry.Face in project artisynth_core by artisynth.
the class Cell method writeVTK.
public static void writeVTK(String filename, PolygonalMesh mesh, ArrayList<String> pointData_scalar_names, ArrayList<double[]> pointData_scalar_data, ArrayList<String> pointData_vector_names, ArrayList<ArrayList<double[]>> pointData_vector_data, ArrayList<String> cellData_scalar_names, ArrayList<double[]> cellData_scalar_data, ArrayList<String> cellData_vector_names, ArrayList<ArrayList<double[]>> cellData_vector_data) {
// this writes a surface geometry
int nPoints = mesh.numVertices();
int nCells = mesh.numFaces();
try {
PrintWriter file = new PrintWriter(new BufferedWriter(new FileWriter(filename, false)));
// header
file.println("# vtk DataFile Version 3.0");
// title
file.println("SurfaceMesh");
// data type: ASCII or BINARY
file.println("ASCII");
// dataset type: STRUCTURED_POINTS, STRUCTURED_GRID, UNSTRUCTURED_GRID, POLYDATA, RECTILINEAR_GRID, FIELD
file.println("DATASET POLYDATA");
// write points
file.println();
file.printf("POINTS %d float\n", nPoints);
for (Vertex3d v : mesh.getVertices()) {
Point3d p = v.getPosition();
file.printf("%f %f %f\n", p.x, p.y, p.z);
}
// write cells
int nCellPoints = 0;
for (Face f : mesh.getFaces()) nCellPoints = nCellPoints + f.getVertexIndices().length;
file.println();
file.printf("POLYGONS %d %d\n", nCells, nCellPoints + nCells);
for (Face f : mesh.getFaces()) {
int[] indices = f.getVertexIndices();
int nInd = indices.length;
file.printf("%d", nInd);
for (int a = 0; a < nInd; a++) file.printf(" %d", indices[a]);
file.println();
}
// write point data
writePointData(file, nPoints, pointData_scalar_names, pointData_scalar_data, pointData_vector_names, pointData_vector_data);
// write cell data
writeCellData(file, nCells, cellData_scalar_names, cellData_scalar_data, cellData_vector_names, cellData_vector_data);
// file.flush();
file.close();
} catch (Exception e) {
}
}
use of maspack.geometry.Face in project artisynth_core by artisynth.
the class CollisionRenderer method createPenetrationRenderObject.
RenderObject createPenetrationRenderObject(CollisionHandler handler, ArrayList<PenetratingPoint> points, ArrayList<PenetrationRegion> regions) {
RenderObject rd = new RenderObject();
HashMap<Vertex3d, Double> depthMap = new HashMap<Vertex3d, Double>();
double maxd = 0;
for (PenetratingPoint pp : points) {
depthMap.put(pp.vertex, pp.distance);
if (pp.distance > maxd) {
maxd = pp.distance;
}
}
ScalarRange range = handler.myBehavior.myPenetrationDepthRange;
range.updateInterval(0, maxd);
float[] rgb = new float[3];
for (int i = 0; i < 256; i++) {
handler.myManager.myColorMap.getRGB(i / 255.0, rgb);
rd.addColor(rgb);
}
Point3d wpnt = new Point3d();
Vector3d wnrm = new Vector3d();
for (PenetrationRegion region : regions) {
for (Face face : region.getFaces()) {
HalfEdge he = face.firstHalfEdge();
Vertex3d v0 = he.getHead();
Vertex3d v1 = he.getNext().getHead();
Vertex3d v2 = he.getTail();
v0.getWorldPoint(wpnt);
int pi0 = rd.addPosition(wpnt);
v1.getWorldPoint(wpnt);
int pi1 = rd.addPosition(wpnt);
v2.getWorldPoint(wpnt);
int pi2 = rd.addPosition(wpnt);
int ci0 = getColorIndex(range, v0, depthMap);
int ci1 = getColorIndex(range, v1, depthMap);
int ci2 = getColorIndex(range, v2, depthMap);
face.getWorldNormal(wnrm);
int ni = rd.addNormal(wnrm);
int v0idx = rd.addVertex(pi0, ni, ci0, -1);
int v1idx = rd.addVertex(pi1, ni, ci1, -1);
int v2idx = rd.addVertex(pi2, ni, ci2, -1);
rd.addTriangle(v0idx, v1idx, v2idx);
}
}
return rd;
}
Aggregations