use of artisynth.core.femmodels.FemElement3d in project artisynth_core by artisynth.
the class MFreeFactory method cloneFem.
public static MFreeModel3d cloneFem(MFreeModel3d model, FemModel3d fem) {
if (model == null) {
model = new MFreeModel3d();
}
HashMap<FemNode3d, MFreeNode3d> nodeMap = new HashMap<FemNode3d, MFreeNode3d>();
HashMap<MFreeNode3d, FemNode3d> nodeMapInv = new HashMap<MFreeNode3d, FemNode3d>();
ArrayList<MFreeNode3d> nodeList = new ArrayList<MFreeNode3d>();
// duplicate nodes
for (FemNode3d node : fem.getNodes()) {
MFreeNode3d mnode = new MFreeNode3d(node.getRestPosition());
// explicit node masses
mnode.setMassExplicit(true);
mnode.setMass(node.getMass());
MFreeNode3d[] deps = new MFreeNode3d[1];
deps[0] = mnode;
VectorNd coords = new VectorNd(new double[] { 1 });
mnode.setDependentNodes(deps, coords);
nodeMap.put(node, mnode);
nodeMapInv.put(mnode, node);
nodeList.add(mnode);
}
// convert surface mesh
FemMeshComp surfaceFem = fem.getSurfaceMeshComp();
PolygonalMesh mesh = (PolygonalMesh) surfaceFem.getMesh();
// build mesh
PolygonalMesh mesh2 = mesh.copy();
// index vertices
int idx = 0;
for (Vertex3d vtx : mesh.getVertices()) {
vtx.setIndex(idx++);
}
idx = 0;
for (Vertex3d vtx : mesh2.getVertices()) {
vtx.setIndex(idx++);
}
MFreeMeshComp surfaceMFree = new MFreeMeshComp(model, "surface");
surfaceMFree.setMesh(mesh2);
// manually build surface attachments
for (Vertex3d vtx : mesh.getVertices()) {
PointAttachment pa = surfaceFem.getAttachment(vtx.getIndex());
if (pa instanceof PointFem3dAttachment) {
PointFem3dAttachment pfa = (PointFem3dAttachment) pa;
FemNode[] masters = pfa.getNodes();
MFreeNode3d[] deps = new MFreeNode3d[masters.length];
VectorNd coords = new VectorNd(masters.length);
for (int j = 0; j < masters.length; j++) {
// mlist.add (new ContactMaster (masters[j], pfa.getCoordinate(j)));
deps[j] = nodeMap.get(masters[j]);
coords.set(j, pfa.getCoordinate(j));
}
surfaceMFree.setVertexAttachment(vtx.getIndex(), coords.getBuffer(), deps);
} else {
PointParticleAttachment ppa = (PointParticleAttachment) pa;
DynamicComponent[] masters = ppa.getMasters();
MFreeNode3d[] deps = new MFreeNode3d[1];
deps[0] = nodeMap.get(masters[0]);
VectorNd coords = new VectorNd(new double[] { 1 });
surfaceMFree.setVertexAttachment(vtx.getIndex(), coords.getBuffer(), deps);
}
}
// integration regions by copying elements
ArrayList<MFreeElement3d> elemList = new ArrayList<MFreeElement3d>(fem.numElements());
HashMap<FemElement3d, MFreeElement3d> elemMap = new HashMap<FemElement3d, MFreeElement3d>(fem.numElements());
for (FemElement3d elem : fem.getElements()) {
MFreeNode3d[] elemNodes = new MFreeNode3d[elem.numNodes()];
FemNode3d[] fnodes = elem.getNodes();
for (int i = 0; i < elem.numNodes(); i++) {
elemNodes[i] = nodeMap.get(fnodes[i]);
}
MFreeElement3d region = new MFreeElement3d(null, elemNodes);
// region.setAllTermsActive(true);
MFreeIntegrationPoint3d[] mpnts = new MFreeIntegrationPoint3d[elem.numIntegrationPoints()];
IntegrationData3d[] mdata = new IntegrationData3d[elem.numIntegrationPoints()];
IntegrationPoint3d[] ipnts = elem.getIntegrationPoints();
IntegrationData3d[] idata = elem.getIntegrationData();
for (int i = 0; i < ipnts.length; i++) {
Point3d pos = new Point3d();
ipnts[i].computePosition(pos, elem.getNodes());
Vector3d[] gradU = ipnts[i].getGNs();
ArrayList<Vector3d> grads = new ArrayList<Vector3d>();
for (Vector3d g : gradU) {
grads.add(g);
}
MFreeIntegrationPoint3d mpnt = MFreeIntegrationPoint3d.create(elemNodes, ipnts[i].getShapeWeights(), grads, ipnts[i].getWeight());
IntegrationData3d mdat = new IntegrationData3d();
mdat.setRestInverseJacobian(idata[i].getInvJ0(), idata[i].getDetJ0());
mpnts[i] = mpnt;
mdata[i] = mdat;
}
// set warping point
if (region.getWarpingPoint() == null) {
IntegrationPoint3d wpnt = elem.getWarpingPoint();
IntegrationData3d wdat = elem.getWarpingData();
Point3d pos = new Point3d();
wpnt.computePosition(pos, elem.getNodes());
// Vector3d [] gradU = wpnt.updateShapeGradient(wdat.getInvJ0());
Vector3d[] gradU = wpnt.getGNs();
ArrayList<Vector3d> grads = new ArrayList<Vector3d>();
for (Vector3d g : gradU) {
grads.add(g);
}
// MFreeIntegrationPoint3d mpnt =
// MFreeIntegrationPoint3d.create(pos, deps,
// wpnt.getShapeWeights(), grads, wpnt.getWeight()*wdat.getDetJ0());
MFreeIntegrationPoint3d mpnt = MFreeIntegrationPoint3d.create(elemNodes, wpnt.getShapeWeights(), grads, wpnt.getWeight());
region.setWarpingPoint(mpnt);
IntegrationData3d wdata = new IntegrationData3d();
wdata.setRestInverseJacobian(wdat.getInvJ0(), wdat.getDetJ0());
region.setWarpingPoint(mpnt, wdata);
}
region.setIntegrationPoints(mpnts, mdata);
elemList.add(region);
elemMap.put(elem, region);
}
// add everything to model
model.addNodes(nodeList);
model.addElements(elemList);
model.setSurfaceMeshComp(surfaceMFree);
// copy properties
model.setDensity(fem.getDensity());
model.setParticleDamping(fem.getParticleDamping());
model.setStiffnessDamping(fem.getStiffnessDamping());
// copy over all masses
for (FemNode3d node : fem.getNodes()) {
nodeMap.get(node).setMass(node.getMass());
}
for (FemElement3d elem : fem.getElements()) {
elemMap.get(elem).setMass(elem.getMass());
}
model.setMaterial(fem.getMaterial());
return model;
}
use of artisynth.core.femmodels.FemElement3d in project artisynth_core by artisynth.
the class MFreeModel3d method updateSlavePos.
public void updateSlavePos() {
super.updateSlavePos();
// nodes
for (FemNode3d node : myNodes) {
((MFreeNode3d) node).updateSlavePos();
}
// integration points
for (FemElement3d elem : myElements) {
for (IntegrationPoint3d mfip : elem.getIntegrationPoints()) {
((MFreeIntegrationPoint3d) mfip).updateSlavePos();
}
MFreePoint3d warp = (MFreePoint3d) elem.getWarpingPoint();
if (warp != null) {
warp.updateSlavePos();
}
}
// meshes
myMeshList.updateSlavePos();
myBVTreeValid = false;
if (myFrameConstraint != null && !myFrameRelativeP) {
myFrameConstraint.updateFramePose(/*frameRelative=*/
false);
}
}
use of artisynth.core.femmodels.FemElement3d in project artisynth_core by artisynth.
the class MFreeModel3d method findNearestNode.
/**
* Finds the nearest node to a specified point that is within
* a specified maximum distance. If no node is within the
* specified maximum distance, <code>null</code> is returned.
*
* @param pnt Point for which the nearest node should be located
* @param maxDist Maximum distance that the node must be from the
* point. If <code>maxDist</code> < 0, then <code>null</code>
* will be returned.
* @return Nearest point within the prescribed distance, or <code>null</code>
* if there is no such point
*/
public FemNode3d findNearestNode(Point3d pnt, double maxDist) {
if (maxDist < 0) {
return null;
}
BVTree bvtree = getElementBVTree();
ArrayList<BVNode> nodes = new ArrayList<BVNode>();
bvtree.intersectSphere(nodes, pnt, maxDist);
FemNode3d nearest = null;
double dist = 1 + 2 * maxDist;
for (BVNode n : nodes) {
Boundable[] elements = n.getElements();
for (int i = 0; i < elements.length; i++) {
FemElement3d e = (FemElement3d) elements[i];
for (int k = 0; k < e.numNodes(); k++) {
double d = e.getNodes()[k].getPosition().distance(pnt);
if (d < dist && d <= maxDist) {
dist = d;
nearest = e.getNodes()[k];
}
}
}
}
return nearest;
}
use of artisynth.core.femmodels.FemElement3d in project artisynth_core by artisynth.
the class MFreeModel3d method integrate.
public double integrate(Function3x1 fun) {
double out = 0;
if (!myStiffnessesValidP) {
updateJacobians();
}
for (FemElement3d elem : myElements) {
IntegrationPoint3d[] ipnts = elem.getIntegrationPoints();
IntegrationData3d[] idata = elem.getIntegrationData();
for (int i = 0; i < elem.numIntegrationPoints(); i++) {
IntegrationPoint3d ipnt = ipnts[i];
IntegrationData3d idat = idata[i];
VectorNd shapeFunc = ipnt.getShapeWeights();
for (int j = 0; j < elem.numNodes(); j++) {
// if (elem.isTermActive(j, j)) {
double f = fun.eval(((MFreePoint3d) ipnt).getPosition()) * ipnt.getWeight() * shapeFunc.get(j);
f = f * ipnt.getDetF() * idat.getDetJ0();
out += f;
// }
}
}
}
return out;
}
use of artisynth.core.femmodels.FemElement3d in project artisynth_core by artisynth.
the class MFreeMuscleModel method prerender.
// public void setFiberMeshActive(boolean enable) {
// if (myFiberMesh == null) {
// throw new IllegalStateException(
// "Fiber mesh is null; must be set before it can be activated");
// }
// setFiberMeshActive(enable, 0, myFiberMesh);
// }
// public void setFiberMeshActive(
// boolean enable, double dist, PolylineMesh mesh) {
//
// if (enable) {
// if (dist <= 0) {
// dist = 0.05 * RenderableUtils.getRadius(mesh);
// }
// activateFiberMesh(dist, mesh);
// }
// else {
// deactivateFiberMesh();
// }
// myFiberMeshActive = enable;
// myDrawFibers = enable;
// }
// private void activateFiberMesh(double rad, PolylineMesh mesh) {
//
// Point3d pos = new Point3d();
// Vector3d dir = new Vector3d();
// Vector3d dirOld = new Vector3d();
//
// for (FemElement3d e : getElements()) {
// IntegrationPoint3d[] pnts = e.getIntegrationPoints();
// IntegrationData3d[] data = e.getIntegrationData();
// boolean elemIsActive = false;
// for (int i = 0; i < pnts.length; i++) {
// pnts[i].computePosition(pos, e.getNodes());
//
// boolean valid = false;
// valid = computeAverageFiberDirection(dir, pos, rad, mesh);
//
// // compare old and new methods
// // valid = computeAverageFiberDirection_Old(dirOld, pos, rad, mesh);
// // if (dir.dot(dirOld) < 0) {
// // dirOld.scale(-1);
// // }
// // if (dir.dot(dirOld) < Math.cos(Math.toRadians(10))
// // && dirOld.norm() != 0) { // 10 degree difference
// // System.out.println("old: " + dirOld + ", new: " + dir
// // + ", angle: " + Math.toDegrees(Math.acos(dir.dot(dirOld))));
// // }
//
// if (valid) {
// Matrix3d F = new Matrix3d();
// F.m00 = dir.x;
// F.m10 = dir.y;
// F.m20 = dir.z;
// data[i].myFrame = F;
// elemIsActive = true;
// }
// else {
// data[i].myFrame = null;
// }
// }
// if (elemIsActive) {
// e.addAuxiliaryMaterial(this);
// }
// }
// }
//
// private void deactivateFiberMesh() {
//
// for (FemElement3d e : getElements()) {
// IntegrationData3d[] data = e.getIntegrationData();
// for (int i = 0; i < data.length; i++) {
// data[i].myFrame = null;
// }
// e.removeAuxiliaryMaterial(this);
// }
// }
public void prerender(RenderList list) {
super.prerender(list);
myMuscleList.prerender(list);
// if (myFiberMeshActive) {
double dirLen = getDirectionRenderLen();
if (dirLen > 0) {
for (FemElement3d e : getElements()) {
// This is to ensure that the invJ0 in the warping data is
// updated in the current (simulation) thread:
e.getWarpingData();
}
}
// }
}
Aggregations