/** * @brief Diamond-shaped graph: \f$ \begin{array}{ccc} & R & \\ \diagup & & \diagdown \\ A & & B \\ \diagdown & & \diagup \\ & C \end{array} \f$ Expected output: RABCCBAR */ void traverse_simple_diamond() { Node::SPtr root = clearScene(); root->setName("R"); Node::SPtr A = root->createChild("A"); Node::SPtr B = root->createChild("B"); Node::SPtr C = A->createChild("C"); B->addChild(C); traverse_test( root, "RACCABBR", "RACCABCCBR", "RACCABCCBR", "RABC" ); }
/** * @brief More complex graph: R__ / \ | A B | \ / | C / \ / D | E Expected output: RABCDEEDCBAR */ void traverse_complex() { Node::SPtr root = clearScene(); root->setName("R"); Node::SPtr A = root->createChild("A"); Node::SPtr B = root->createChild("B"); Node::SPtr C = A->createChild("C"); B->addChild(C); Node::SPtr D = C->createChild("D"); root->addChild(D); Node::SPtr E = D->createChild("E"); traverse_test( root, "RACDEEDCABBR", "RACDEEDCABCDEEDCBDEEDR", "RACDEEDCABCCBDDR", "RABCDE" ); }
/** * @brief The root and two children: \f$ \begin{array}{ccc} & R & \\ \diagup & & \diagdown \\ A & & B \end{array} \f$ Expected output: RAABBR */ void traverse_simple_tree() { Node::SPtr root = clearScene(); root->setName("R"); root->createChild("A"); root->createChild("B"); traverse_test( root, "RAABBR", "RAABBR", "RAABBR", "RAB" ); }
/** * @brief Even more complex graph: R__ / \ | A B C \/ \| D E | | F G Expected output: RABCDEEDCBAR */ void traverse_morecomplex() { Node::SPtr root = clearScene(); root->setName("R"); Node::SPtr A = root->createChild("A"); Node::SPtr B = root->createChild("B"); Node::SPtr C = root->createChild("C"); Node::SPtr D = A->createChild("D"); B->addChild(D); Node::SPtr E = B->createChild("E"); C->addChild(E); Node::SPtr F = D->createChild("F"); Node::SPtr G = E->createChild("G"); traverse_test( root, "RADFFDABEGGEBCCR", "RADFFDABDFFDEGGEBCEGGECR", "RADFFDABDDEGGEBCEECR", "RABDFCEG" ); }
/// It is important to freeze what are the available Data field /// of a component and rise warning/errors when some one removed. /// void attributesTests(){ m_node = m_root->createChild("node") ; m_mass = New< TheUniformMass >() ; m_node->addObject(m_mass) ; EXPECT_TRUE( m_mass->findData("mass") != nullptr ) ; EXPECT_TRUE( m_mass->findData("totalmass") != nullptr ) ; EXPECT_TRUE( m_mass->findData("filename") != nullptr ) ; EXPECT_TRUE( m_mass->findData("localRange") != nullptr ) ; EXPECT_TRUE( m_mass->findData("showGravityCenter") != nullptr ) ; EXPECT_TRUE( m_mass->findData("showAxisSizeFactor") != nullptr ) ; EXPECT_TRUE( m_mass->findData("showInitialCenterOfGravity") != nullptr ) ; EXPECT_TRUE( m_mass->findData("indices") != nullptr ) ; EXPECT_TRUE( m_mass->findData("handleTopoChange") != nullptr ) ; EXPECT_TRUE( m_mass->findData("preserveTotalMass") != nullptr ) ; EXPECT_TRUE( m_mass->findData("compute_mapping_inertia") != nullptr ) ; EXPECT_TRUE( m_mass->findData("totalMass") != nullptr ) ; return ; }
/** * @brief another complex case R______ / \ \ \ \ A B C D E \/__/_/_/ F |\ G | |/ H */ void traverse_morecomplex2() { Node::SPtr root = clearScene(); root->setName("R"); Node::SPtr A = root->createChild("A"); Node::SPtr B = root->createChild("B"); Node::SPtr C = root->createChild("C"); Node::SPtr D = root->createChild("D"); Node::SPtr E = root->createChild("E"); Node::SPtr F = A->createChild("F"); B->addChild(F); C->addChild(F); D->addChild(F); E->addChild(F); Node::SPtr G = F->createChild("G"); Node::SPtr H = G->createChild("H"); F->addChild(H); traverse_test( root, "RAFGHHGFABBCCDDEER", "RAFGHHGHHFABFGHHGHHFBCFGHHGHHFCDFGHHGHHFDEFGHHGHHFER", "RAFGHHGHHFABFFBCFFCDFFDEFFER", "RABCDEFGH" ); }
Node::SPtr createChild(Node::SPtr node, BaseObjectDescription& desc) { Node::SPtr tmp = node->createChild(desc.getName()); tmp->parse(&desc); return tmp; }
/// Create an assembly of a siff hexahedral grid with other objects simulation::Node::SPtr createGridScene(Vec3 startPoint, Vec3 endPoint, unsigned numX, unsigned numY, unsigned numZ, double totalMass/*, double stiffnessValue, double dampingRatio=0.0*/ ) { using helper::vector; // The graph root node Node::SPtr root = simulation::getSimulation()->createNewGraph("root"); root->setGravity( Coord3(0,-10,0) ); root->setAnimate(false); root->setDt(0.01); addVisualStyle(root)->setShowVisual(false).setShowCollision(false).setShowMapping(true).setShowBehavior(true); Node::SPtr simulatedScene = root->createChild("simulatedScene"); EulerImplicitSolver::SPtr eulerImplicitSolver = New<EulerImplicitSolver>(); simulatedScene->addObject( eulerImplicitSolver ); CGLinearSolver::SPtr cgLinearSolver = New<CGLinearSolver>(); simulatedScene->addObject(cgLinearSolver); // The rigid object Node::SPtr rigidNode = simulatedScene->createChild("rigidNode"); MechanicalObjectRigid3::SPtr rigid_dof = addNew<MechanicalObjectRigid3>(rigidNode, "dof"); UniformMassRigid3::SPtr rigid_mass = addNew<UniformMassRigid3>(rigidNode,"mass"); FixedConstraintRigid3::SPtr rigid_fixedConstraint = addNew<FixedConstraintRigid3>(rigidNode,"fixedConstraint"); // Particles mapped to the rigid object Node::SPtr mappedParticles = rigidNode->createChild("mappedParticles"); MechanicalObject3::SPtr mappedParticles_dof = addNew< MechanicalObject3>(mappedParticles,"dof"); RigidMappingRigid3_to_3::SPtr mappedParticles_mapping = addNew<RigidMappingRigid3_to_3>(mappedParticles,"mapping"); mappedParticles_mapping->setModels( rigid_dof.get(), mappedParticles_dof.get() ); // The independent particles Node::SPtr independentParticles = simulatedScene->createChild("independentParticles"); MechanicalObject3::SPtr independentParticles_dof = addNew< MechanicalObject3>(independentParticles,"dof"); // The deformable grid, connected to its 2 parents using a MultiMapping Node::SPtr deformableGrid = independentParticles->createChild("deformableGrid"); // first parent mappedParticles->addChild(deformableGrid); // second parent RegularGridTopology::SPtr deformableGrid_grid = addNew<RegularGridTopology>( deformableGrid, "grid" ); deformableGrid_grid->setNumVertices(numX,numY,numZ); deformableGrid_grid->setPos(startPoint[0],endPoint[0],startPoint[1],endPoint[1],startPoint[2],endPoint[2]); MechanicalObject3::SPtr deformableGrid_dof = addNew< MechanicalObject3>(deformableGrid,"dof"); SubsetMultiMapping3_to_3::SPtr deformableGrid_mapping = addNew<SubsetMultiMapping3_to_3>(deformableGrid,"mapping"); deformableGrid_mapping->addInputModel(independentParticles_dof.get()); // first parent deformableGrid_mapping->addInputModel(mappedParticles_dof.get()); // second parent deformableGrid_mapping->addOutputModel(deformableGrid_dof.get()); UniformMass3::SPtr mass = addNew<UniformMass3>(deformableGrid,"mass" ); mass->mass.setValue( totalMass/(numX*numY*numZ) ); HexahedronFEMForceField3::SPtr hexaFem = addNew<HexahedronFEMForceField3>(deformableGrid, "hexaFEM"); hexaFem->f_youngModulus.setValue(1000); hexaFem->f_poissonRatio.setValue(0.4); // ====== Set up the multimapping and its parents, based on its child deformableGrid_grid->init(); // initialize the grid, so that the particles are located in space deformableGrid_dof->init(); // create the state vectors MechanicalObject3::ReadVecCoord xgrid = deformableGrid_dof->readPositions(); // cerr<<"xgrid = " << xgrid << endl; // create the rigid frames and their bounding boxes unsigned numRigid = 2; vector<BoundingBox> boxes(numRigid); vector< vector<unsigned> > indices(numRigid); // indices of the particles in each box double eps = (endPoint[0]-startPoint[0])/(numX*2); // first box, x=xmin boxes[0] = BoundingBox(Vec3d(startPoint[0]-eps, startPoint[1]-eps, startPoint[2]-eps), Vec3d(startPoint[0]+eps, endPoint[1]+eps, endPoint[2]+eps)); // second box, x=xmax boxes[1] = BoundingBox(Vec3d(endPoint[0]-eps, startPoint[1]-eps, startPoint[2]-eps), Vec3d(endPoint[0]+eps, endPoint[1]+eps, endPoint[2]+eps)); rigid_dof->resize(numRigid); MechanicalObjectRigid3::WriteVecCoord xrigid = rigid_dof->writePositions(); xrigid[0].getCenter()=Vec3d(startPoint[0], 0.5*(startPoint[1]+endPoint[1]), 0.5*(startPoint[2]+endPoint[2])); xrigid[1].getCenter()=Vec3d( endPoint[0], 0.5*(startPoint[1]+endPoint[1]), 0.5*(startPoint[2]+endPoint[2])); // find the particles in each box vector<bool> isFree(xgrid.size(),true); unsigned numMapped = 0; for(unsigned i=0; i<xgrid.size(); i++){ for(unsigned b=0; b<numRigid; b++ ) { if( isFree[i] && boxes[b].contains(xgrid[i]) ) { indices[b].push_back(i); // associate the particle with the box isFree[i] = false; numMapped++; } } } // distribution of the grid particles to the different parents (independent particle or solids. vector< pair<MechanicalObject3*,unsigned> > parentParticles(xgrid.size()); // Copy the independent particles to their parent DOF independentParticles_dof->resize( numX*numY*numZ - numMapped ); MechanicalObject3::WriteVecCoord xindependent = independentParticles_dof->writePositions(); // parent positions unsigned independentIndex=0; for( unsigned i=0; i<xgrid.size(); i++ ){ if( isFree[i] ){ parentParticles[i]=make_pair(independentParticles_dof.get(),independentIndex); xindependent[independentIndex] = xgrid[i]; independentIndex++; } } // Mapped particles. The RigidMapping requires to cluster the particles based on their parent frame. mappedParticles_dof->resize(numMapped); MechanicalObject3::WriteVecCoord xmapped = mappedParticles_dof->writePositions(); // parent positions mappedParticles_mapping->globalToLocalCoords.setValue(true); // to define the mapped positions in world coordinates vector<unsigned>* pointsPerFrame = mappedParticles_mapping->pointsPerFrame.beginEdit(); // to set how many particles are attached to each frame unsigned mappedIndex=0; for( unsigned b=0; b<numRigid; b++ ) { const vector<unsigned>& ind = indices[b]; pointsPerFrame->push_back((unsigned)ind.size()); // Tell the mapping the number of points associated with this frame. One box per frame for(unsigned i=0; i<ind.size(); i++) { parentParticles[ind[i]]=make_pair(mappedParticles_dof.get(),mappedIndex); xmapped[mappedIndex] = xgrid[ ind[i] ]; mappedIndex++; } } mappedParticles_mapping->pointsPerFrame.endEdit(); // Declare all the particles to the multimapping for( unsigned i=0; i<xgrid.size(); i++ ) { deformableGrid_mapping->addPoint( parentParticles[i].first, parentParticles[i].second ); } return root; }