Home › Forum › SOFA › Using SOFA › [SOLVED] Putting an object inside another one
Tagged: attach, constraints, python
- This topic has 16 replies, 4 voices, and was last updated 5 years, 7 months ago by Hugo.
-
AuthorPosts
-
25 August 2017 at 18:26 #9932Wendy María ArangoBlocked
Hi!
Now, I have to make a scene that simulates an ovary with a tumor. What I was told to do is to put a little ball inside a big one. I already have .obj files, what I don’t know to do is to let one .obj file inside the other.
Any ideas of how to do it?
I’d be grateful if you could help me. Thanks a lot!Cheers.
28 August 2017 at 13:56 #9935NouraBlockedHi @wendyarch,
Here is a minimal scene example how to load two obj spheres (a small sphere for the tumor and a big one for the ovary).
<?xml version="1.0"?> <Node name="root" gravity="0 0 0" dt="0.01" > <VisualStyle name="visualStyle1" displayFlags="showWireframe " /> <Node name="Big_Sphere" activated="1"> <MeshObjLoader name="loader" filename="big_sphere_05.obj"/> <Mesh src="@loader"/> <MechanicalObject template="Vec3d" name="MO_BigSphere" src="@loader" /> <UniformMass totalmass="1" /> <OglModel name="Visual" fileMesh="big_sphere_05.obj" color="green" /> </Node> <Node name="Small_Sphere" activated="1"> <MeshObjLoader name="loader" filename="small_sphere_05.obj"/> <Mesh src="@loader" /> <MechanicalObject template="Vec3d" name="MO_smallSphere" src="@loader" /> <UniformMass totalmass="0.1" /> <OglModel name="Visual_2" fileMesh="small_sphere_05.obj" color="red"/> </Node> </Node>
You can get the spheres obj files at this link
I’m not sure what do you mean by placing a ball inside the other. You say that you have the obj files of the two meshes, so I suppose that the initial configuration of the 2 meshes are already be in such a way that the small object is inside the bigger one.
Hope this helps!
Noura
28 August 2017 at 14:05 #9936HugoKeymasterHi Wendy,
Since the tumor and the ovary are the same organ (ovary), just with different properties, an easy way to go is to run a simulation with heterogeneous properties of your object. A topic talks about it: https://www.sofa-framework.org/community/forum/topic/composite_objects/
To do so, you can use mesher (like CGAL) to take into account the two regions while meshing (create a clear frontier). Then, give specific parameter to each element/region.
Is it clear? Does it help?
Cheers,Hugo
29 August 2017 at 19:05 #9952Wendy María ArangoBlockedHi! Thanks a lot for replying.
What I meant is, what do I have to do to put the tumor inside the ovary? The thing is: the ‘ball’ (.obj) I created for the ovary is bigger than the one I created for the tumor.
In the scene, what I have to do is like ‘chain them’.
<?xml version="1.0" ?> <Node name="lroot" gravity="0 -9.81 0" dt="0.02"> <DefaultPipeline name="CollisionPipeline" verbose="0" /> <BruteForceDetection name="N2" /> <DefaultContactManager name="collision response" response="default" /> <DiscreteIntersection/> <Node name="Ovary"> <RequiredPlugin name="LeapMotion Driver" pluginName="LeapMotion" /> <EulerImplicitSolver name="cg_odesolver" /> <CGLinearSolver name="linear solver" iterations="25" tolerance="1e-09" threshold="1e-09" /> <MeshGmshLoader name="meshLoader" filename="./ovary_mesh.msh" /> <!-- <MeshLoader name="meshLoader" filename="mesh/TetrasCreado.msh" /> --> <TetrahedronSetTopologyContainer name="topo" src="@meshLoader" /> <MechanicalObject name="dofs" src="@meshLoader" /> <!-- <TetrahedronSetTopologyContainer name="topo"/> <MechanicalObject name="dofs" /> --> <TetrahedronSetGeometryAlgorithms template="Vec3d" name="GeomAlgo" /> <DiagonalMass name="computed using mass density" massDensity="1" /> <TetrahedralCorotationalFEMForceField template="Vec3d" name="FEM" method="large" poissonRatio="0.3" youngModulus="3000" computeGlobalMatrix="0" /> <FixedConstraint name="FixedConstraint" indices="3 39 64" /> <LeapMotionDriver name="leapMotionDriver" displayHand="true"/> <Node name="Visu" tags="Visual"> <OglModel name="VisualModel" fileMesh="./ovario_externo.obj" /> <blockquote>--- Here maybe it'd go the tumor, that's what I don't know ---</blockquote> <BarycentricMapping name="visual mapping" input="@../dofs" output="@VisualModel" /> </Node> <Node name="Surf"> <MeshObjLoader name="loader" filename="./ovario_externo.obj" /> <Mesh src="@loader" /> <MechanicalObject src="@loader" name="CollisModel" /> <Triangle selfCollision="0" /> <Line selfCollision="0" /> <Point selfCollision="0" /> <BarycentricMapping input="@.." output="@." /> </Node> </Node> </Node>
It’s like if the big one contained the small one…
Is it enough clear?29 August 2017 at 19:32 #9953HugoKeymasterAs I said, I would model the tumor and the ovary as two regions of one single object.
The CGAL library allows you to mesh different regions with different sizes: https://www.sofa-framework.org/community/doc/using-sofa/optional-features/cgal-library/Each region can be meshed with a different level of refinement.
Each region would have each own physical/mechanical properties.HTH,
Hugo
2 September 2017 at 01:00 #9956Wendy María ArangoBlockedHi!
Thanks a lot for your answer, again.Besides using the CGAL library, I found another solution:
What I did was modelling both objects in Fusion 360. That way, I ‘dug’ a hole in the biggest one, that’s in my case the tumor or cyst. In the hole, I put the smallest one, the ovary, and then I turned them into mesh and then I exported .obj files.
In the scene, SOFA takes the original position they were exported with so it puts them like if the ovary was inside the cyst.
This is a little example. It’s not finished yet, but it can help.
<?xml version="1.0" ?> <Node name="lroot" gravity="0 -9.81 0" dt="0.02"> <DefaultPipeline name="CollisionPipeline" verbose="0" /> <BruteForceDetection name="N2" /> <DefaultContactManager name="collision response" response="default" /> <DiscreteIntersection/> <Node name="Intern"> <!--<RequiredPlugin name="LeapMotion Driver" pluginName="LeapMotion" /> --> <EulerImplicitSolver name="cg_odesolver" /> <CGLinearSolver name="linear solver" iterations="25" tolerance="1e-09" threshold="1e-09" /> <MeshGmshLoader name="meshIntern" filename="./intern.msh" /> <!-- <MeshLoader name="meshLoader" filename="mesh/TetrasCreado.msh" /> --> <TetrahedronSetTopologyContainer name="topo" src="@meshIntern" /> <MechanicalObject name="dofs" src="@meshIntern" /> <!-- <TetrahedronSetTopologyContainer name="topo"/> <MechanicalObject name="dofs" /> --> <TetrahedronSetGeometryAlgorithms template="Vec3d" name="GeomAlgo" /> <DiagonalMass name="computed using mass density" massDensity="1" /> <TetrahedralCorotationalFEMForceField template="Vec3d" name="FEM" method="large" poissonRatio="0.3" youngModulus="3000" computeGlobalMatrix="0" /> <FixedConstraint name="FixedConstraint" indices="3 39 64" /> <!--<LeapMotionDriver name="leapMotionDriver" displayHand="true"/> --> <Node name="Visu" tags="Visual"> <OglModel name="VisualModel" fileMesh="./intern.obj" /> <BarycentricMapping name="visual mapping" input="@../dofs" output="@VisualModel" /> </Node> <Node name="Surf"> <MeshObjLoader name="loader" filename="./intern.obj" /> <Mesh src="@loader" /> <MechanicalObject src="@loader" name="CollisModel" /> <Triangle selfCollision="0" /> <Line selfCollision="0" /> <Point selfCollision="0" /> <BarycentricMapping input="@.." output="@." /> </Node> </Node> <Node name="Extern"> <!--<RequiredPlugin name="LeapMotion Driver" pluginName="LeapMotion" /> --> <EulerImplicitSolver name="cg_odesolver" /> <CGLinearSolver name="linear solver" iterations="25" tolerance="1e-09" threshold="1e-09" /> <MeshGmshLoader name="meshExtern" filename="./extern.msh" /> <!-- <MeshLoader name="meshLoader" filename="mesh/TetrasCreado.msh" /> --> <TetrahedronSetTopologyContainer name="topo" src="@meshExtern" /> <MechanicalObject name="dofs" src="@meshExtern" /> <!-- <TetrahedronSetTopologyContainer name="topo"/> <MechanicalObject name="dofs" /> --> <TetrahedronSetGeometryAlgorithms template="Vec3d" name="GeomAlgo" /> <DiagonalMass name="computed using mass density" massDensity="1" /> <TetrahedralCorotationalFEMForceField template="Vec3d" name="FEM" method="large" poissonRatio="0.3" youngModulus="3000" computeGlobalMatrix="0" /> <FixedConstraint name="FixedConstraint" indices="3 39 64" /> <!--<LeapMotionDriver name="leapMotionDriver" displayHand="true"/> --> <Node name="Visu" tags="Visual"> <OglModel name="VisualModel" fileMesh="./extern.obj" /> <BarycentricMapping name="visual mapping" input="@../dofs" output="@VisualModel" /> </Node> <Node name="Surf"> <MeshObjLoader name="loader" filename="./extern.obj" /> <Mesh src="@loader" /> <MechanicalObject src="@loader" name="CollisModel" /> <Triangle selfCollision="0" /> <Line selfCollision="0" /> <Point selfCollision="0" /> <BarycentricMapping input="@.." output="@." /> </Node> </Node> </Node>
I’m not sure how to give you the .obj files and .msh files here in the forum… But, if anyone needs it to see how it works, they can write me and I’ll send them.
Thanks a lot 🙂4 September 2017 at 10:58 #9958HugoKeymasterYou can either share them on wetransfer (temporary), but I guess updloaing a picture of it (http://imgur.com/) would be good as well. Especially if you can provide a cropped view.
Keep us updated 😉
Best,
Hugo
11 September 2017 at 18:31 #9966Wendy María ArangoBlockedHi Hugo,
While I was seeing the scene that you’ve got for CGAL Plugin, I realized there’s an .inr file. How do you create that file?
Besides, I have another question: what kind of constraints do you have in SOFA?
For example, I need a constraint that you can break, like a kind of spring, I don’t know if I make understand myself.Thanks for your help,
Wendy.
12 September 2017 at 11:28 #9971HugoKeymasterHey Wendy,
The .inr format is proper to CGAL. It corresponds to a medical image format.
There is different constraints in SOFA (Fixed, Partial, Attach, Bilateral, AffineMovement…). To better answer you, I would need to better understand what you want to do. But to change the physics during the simulation (“break the constraint”), you will need to code a bit (using Python it would be pretty straightforward).
Best regards,
Hugo
13 September 2017 at 21:56 #9983Wendy María ArangoBlockedHey Hugo, I’m gonna try to explain myself as well as possible, OK?
I was a little bit confused but my boss already explained me.
There are two objects in the scene, right? One of them is a cyst and the other one is an ovary. What I have to do is simulate the cyst inside the ovary. The doctor that’s leading us need it for a prove.
Well, the thing’s that anyone has to be able to cut it, and that’s what we’re trying to do with the Phantom.
Besides, both have to be different objects, that way, if someone’s simulating and he/she stretches enough the cyst, it’s supposed to go out of the ovary, do I explain myself good enough?
That’s why I’m asking you for the constraints you have in SOFA, maybe one of them could be helpful. That’s what I meant when I said that perhaps you could “break it”, so to speak.
I don’t know if the explanation’s OK.
Thanks,
Wendy.
27 September 2017 at 03:24 #10011HugoKeymasterHi Wendy,
I think I got it.
Then, the best way to simulate this wouldn’t it be to have springs that would have a stiffness that would be set to zero when its elongation exceeds a threshold? This could be done in C++ (inheriting from SpringForceField) or maybe in a simpler way using Python.Best,
15 April 2019 at 07:10 #13408amitBlockedHi,
We are trying to something similar. In our case, We need two objects, liver and gallbladder, attached to each other and we need to stretch the gallbladder and it breaks of the liver. We were going through the python scripting tutorial and pdf file provided in the tutorial page but still confused on how we can do this?
Any help will be highly appreciated.
Thank you
amit28 April 2019 at 18:35 #13436HugoKeymasterHi @amit
Indeed a simplistic tearing could be done as described above for Wendy’s project.
To do so, a SpringForceField could be setup between the two meshes (liver and gallblader). Using Python, if the elongation of springs exceeds a threshold, you could access and modify (set to zero) the stiffness of these springs. This would mimic a tearing effect.
If you don’t feel able to to this yourself, let me know we can assist you in this. A short training session could make it possible.Otherwise, some developers of the community (Erik) are currently working on the implementation of a robust volumetric cutting in SOFA.
Best wishes,
2 May 2019 at 12:04 #13447amitBlockedHi Hugo,
Thank you for the suggestion.As you suggested, first we were trying to create spring force field between two objects then create the component if it functions well.We were looking at the StiffSpringField.scn and the indices to spring parameter are given manually in the scene. Is there any way I can use NearestPointROI to get the indices between the two mesh and give that to the spring data? Or is providing the spring indices manually the only way?
Also, We are doing this in order to model connective tissue between the liver and gallbladder. So we would have to visualize the connective tissue too after setting up the springforcefield so we could break/burn it. Any suggestions on how we do so?
Thank you again. Looking forward for your guidance.
4 May 2019 at 07:42 #13454HugoKeymasterDear @amit
Thank you for your feedback.
Unfortunately, for now, it is required to do it manually: first compute the pairing, save it and provide the full spring information.
But your remark is correct, it should be made simpler and more easy to set for the user.For visualization, you can activate the visual option for forcefields:
<VisualStyle displayFlags="showForceFields" />
Best wishes,
Hugo
7 May 2019 at 07:16 #13462amitBlockedHi Hugo,
Thank you for the answer.Is there any example of creating component inheriting from other components in SOFA? I am having tough time figuring a way to create custom component and use them in SOFA scene.
Any help would be highly appreciated.
8 May 2019 at 18:52 #13465HugoKeymasterHi @amit
Please find documentation about creation of plugins, and components online.
You can also have a look to our template plugin: MyAwesomeComponents
Let me know if it helps.
BestHugo
-
AuthorPosts
- You must be logged in to reply to this topic.