Convert mesh to solid?

Post here for help on using FreeCAD's graphical user interface (GUI).
Forum rules
and Helpful information
IMPORTANT: Please click here and read this first, before asking for help

Also, be nice to others! Read the FreeCAD code of conduct!
wmayer
Founder
Posts: 20319
Joined: Thu Feb 19, 2009 10:32 am
Contact:

Re: Convert mesh to solid?

Post by wmayer »

Your idea 1 has the advantage that it can be implemented progressively, and that since many algorithms can be written, there is an infinite quantity of optimization methods possible...
All the basics are already implemented. What we need is a special visitor class (derived from MeshFacetVisitor, Mod/Mesh/App/Core/Visitor.h) and reimplement its virtual method Visit().

The visiting of the triangles is done in the method MeshKernel::VisitNeighbourFacets() which accepts a visitor object and a start index of a triangle.
That's pretty easy. In a sphere, would there be only one curvature value? I'm not sure...
Of course, on every point on a sphere the maximum and minimum curvature are equal -- btw. these points are called umbillic points.
And specially that some "facets" of the sphere can be made of several triangles (small squares for example), so you would also have curvature values of zero, and then it's hard to decide if it's a sphere or a cylinder.
When creating a mesh sphere in FreeCAD and running the curvature plot function then even for the tiny triangles around the poles the curvatures are not zero. But of course you always will have rounding errors there.
Would those mesh approximation software you guys use be of any help for such cases?
:?:
User avatar
yorik
Founder
Posts: 13665
Joined: Tue Feb 17, 2009 9:16 pm
Location: Brussels
Contact:

Re: Convert mesh to solid?

Post by yorik »

Cool! Thanks for the explanations. I'll see if I can try to do something.
So the idea would be to make a new class derived on the Visitor class for each "optimization" (for ex: finding coplanar faces, finding cylinders, etc)
And then you would simply invoke VisitNeighbourFacets with the Visitor you want... Looks perfect (and reachable by me ;) ! What is the eigenvectors method you mentioned? Is there something implemented in freecad already?

Just one more question: the Visitor will return the number of facets visited, but the cool thing would be to get several mesh segments, so you can create a separate mesh from each one and feed the ShapeFromMesh stuff... I don't see well how to do that... Can you give me some starting point?

Ah, about the "mesh approximation software" I talked about, I was referring to FEM software, but looking better at it I see it's actually completely different...
wmayer
Founder
Posts: 20319
Joined: Thu Feb 19, 2009 10:32 am
Contact:

Re: Convert mesh to solid?

Post by wmayer »

So the idea would be to make a new class derived on the Visitor class for each "optimization" (for ex: finding coplanar faces, finding cylinders, etc)
Yes, we can have for each geometry type an own visitor class.
And then you would simply invoke VisitNeighbourFacets
Yes, but some prerequisites must be met. The mesh facets (class MeshFacet) have a flag "VISIT" which must be reset first,

Code: Select all

    // reset VISIT flag
    MeshKernel kernel = ...
    MeshAlgorithm cAlg(kernel);
    cAlg.ResetFacetFlag(MeshFacet::VISIT);
And the algorithm inside which we call VisitNeighbourFacets should look like this:

Code: Select all

    // reset VISIT flag
    MeshKernel kernel = ...
    const MeshFacetArray& rFAry = kernel.GetFacets();
    MeshFacetArray::_TConstIterator iTri = rFAry.begin();
    MeshFacetArray::_TConstIterator iBeg = rFAry.begin();
    MeshFacetArray::_TConstIterator iEnd = rFAry.end();

    MeshAlgorithm cAlg(kernel);
    cAlg.ResetFacetFlag(MeshFacet::VISIT);

    unsigned long ulStartFacet=0, ulVisited=0;
    while (ulStartFacet !=  ULONG_MAX) {
        ulVisited = kernel.VisitNeighbourFacets(ourVisitor, ulStartFacet) + 1;
        // get the next unvisited facet
        iTri = std::find_if(iTri, iEnd, std::bind2nd(MeshIsNotFlag<MeshFacet>(), MeshFacet::VISIT));
        if (iTri < iEnd)
            ulStartFacet = iTri - iBeg; // this is the new index
        else
            ulStartFacet = ULONG_MAX; // OK, we reached the end
    }
What is the eigenvectors method you mentioned?
This is a method to compute a best-fit-plane in a list of 3d points. The approach is to find a plane which minimizes the sum of squared distances to the points. This problem leads to a symmetric 3x3 matrix (the so called co-variance matrix) where the eigenvector to the smallest eigenvalue is the normal of the plane. The plane always lies in the gravity center of the points.

We have an implementation in Mesh/App/Core/Approximation -- the class PlaneFit.

The same idea could be also applied to cylinders, spheres, ... as done by the WildMagic library. But these algorithms are quite unreliable.
Just one more question: the Visitor will return the number of facets visited, but the cool thing would be to get several mesh segments, so you can create a separate mesh from each one and feed the ShapeFromMesh stuff... I don't see well how to do that... Can you give me some starting point?
Yes, the visitor must decide if the current facet belongs to this type of geometry or not. If none of the neighbours of the inspected "good"facets pass the test the visitor must return false to stop the algorithm. Now we have one segment that describes the geometry.
The best would be to store the indexes of the facets in an array (std::vector).

I think the best would be to store the segments in the MeshObject class. This is a higher-level object and owns a MeshKernel. There we can hold the segment information as I did it with the improved OBJ reader.
Ah, about the "mesh approximation software" I talked about, I was referring to FEM software, but looking better at it I see it's actually completely different...
I don't have much experience with FEM. So, I cannot say what kind of approximation algorithms are used in this field.
User avatar
yorik
Founder
Posts: 13665
Joined: Tue Feb 17, 2009 9:16 pm
Location: Brussels
Contact:

Re: Convert mesh to solid?

Post by yorik »

Wow! That's a complete lesson ;)
Thanks Werner, I think there is everything I needed to know...
I'll try to implement that, I come back here if I have big problems.
separent
Posts: 4
Joined: Thu Jun 03, 2010 1:49 am

Re: Convert mesh to solid?

Post by separent »

wmayer wrote:

Code: Select all

import Mesh,Part
mesh=Mesh.createTorus()
shape=Part.Shape()
shape.makeShapeFromMesh(mesh.Topology,0.05) # the second arg is the tolerance for sewing
solid=Part.makeSolid(shape)
Part.show(solid)
The geomplate faces produced for stratigraphic modelling (viewtopic.php?f=3&t=291) are often quite irregular so that boolean operations makes FreeCAD freeze or crash. I thought simplifying the planes by meshing them, then turn them back to faces may solve the issue. The upper code makes solids out of meshes. I tried to explode the solid (downgrade button via GUI) to about 1300 faces, and join the faces to a single face. But joining faces in batch using the GUI (upgrade button) outputs sometimes nothing, sometimes a Pyhton error. Is there a better way to make a face out of a mesh? By the way, is my strategy a good idea?

King regards,

Serge-Étienne
User avatar
yorik
Founder
Posts: 13665
Joined: Tue Feb 17, 2009 9:16 pm
Location: Brussels
Contact:

Re: Convert mesh to solid?

Post by yorik »

Actually the upgrade tool was primarily made for 2D. It actually works like this: takes all selected faces, detects which edges are not shared by 2 faces (means: they are "border" edges), constructs a wire from all the border edges, then a face out of it. Of course, as you will have guessed, if the faces are not coplanar, the wire won't be plane and the face won't be created.

I should really add a test to see if faces are coplanar, and if not, defaut to the Part Fuse operation... Then the upgrade tool will behave correctly in 3D too.
But in this particular case I'm afraid the upgrade tool will be of little use to you...
Simplifying that kind of surfaces is not so easy, I had a couple of tries already without having time to go very far...
I think Werner's approach above in this thread is the best path, having an algorithm that "scans" neighbour faces to find out faces that are coplanar (or "almost" coplanar) so you can group them and consider them one face.
wmayer
Founder
Posts: 20319
Joined: Thu Feb 19, 2009 10:32 am
Contact:

Re: Convert mesh to solid?

Post by wmayer »

With the very last revision I have checked-in some algorithms to detect at least all adjacent co-planar triangles of a mesh to group them as one face. Here is a short example of how to use it:

Code: Select all

import Mesh,Part,MeshPart

faces = []
mesh = App.ActiveDocument.ActiveObject.Mesh
segments = mesh.getPlanes(0.00001) # use rather strict tolerance here

for i in segments:
	if len(i) > 0:
		# a segment can have inner holes
		wires = MeshPart.wireFromSegment(mesh, i)
		# we assume that the exterior boundary is that one with the biggest bounding box
		if len(wires) > 0:
			ext=None
			max_length=0
			for i in wires:
				if i.BoundBox.DiagonalLength > max_length:
					max_length = i.BoundBox.DiagonalLength
					ext = i

			wires.remove(ext)
			# all interior wires mark a hole and must reverse their orientation, otherwise Part.Face fails
			for i in wires:
				i.reverse()

			# make sure that the exterior wires comes as first in the lsit
			wires.insert(0, ext)
			faces.append(Part.Face(wires))


shell=Part.Compound(faces)
Part.show(shell)
#solid = Part.Solid(Part.Shell(faces))
#Part.show(solid)
User avatar
yorik
Founder
Posts: 13665
Joined: Tue Feb 17, 2009 9:16 pm
Location: Brussels
Contact:

Re: Convert mesh to solid?

Post by yorik »

Werner, one more time I must say it, you are a genius!!!!
I've been trying to do that for MONTHS! I've been so ashamed of my weak pieces of C++ code that I didn't even dare to commit them ;)
It seems to work just perfectly! Thanks a LOT for that commit!
easyw
Posts: 16
Joined: Tue Feb 05, 2013 10:12 am

Re: Convert mesh to solid?

Post by easyw »

Hi to all,
I'm a very newbie with freecad and I'm trying to convert some simple model of kicad from wrl or stl to solid (step or iges)...
I'm using the Version: 0.13.1828, in OS: Windows Platform: 32-bit, Python version: 2.6.2, Qt version: 4.5.2, Coin version: 3.1.0, SoQt version: 1.4.1, OCC version: 6.3.0 (FreeCad 0.13 latest 28.01.2013)

I tried importing a simple 'stl' cube in freecad and exporting it in 'step' but without success
(error message: it is not a shape, export will be ignored)...
I tried also to use the python console and digit the following commands (as in Wermer example):

Code: Select all

import Mesh,Part,MeshPart
faces = []
mesh = App.ActiveDocument.ActiveObject.Mesh
segments = mesh.getPlanes(0.00001) # use rather strict tolerance here
but after the 4th command I get this error:
Traceback (most recent call last):
File "<input>", line 1, in <module>
AttributeError: 'Mesh.MeshObject' object has no attribute 'getPlanes'


Any suggestion would be usefull...
Is there a howto or a simple tutorial for this topic?
Thank you :)
Maurice
jmaustpc
Veteran
Posts: 11207
Joined: Tue Jul 26, 2011 6:28 am
Location: Australia

Re: Convert mesh to solid?

Post by jmaustpc »

Hi Maurice

You have to convert the STL file to a shape before you try to convert it to IGES etc.. First open the mesh (stl) file, you then have to "create a shape from mesh" (Part Workbench, Part menu, 6th item down).

Once you have a "shape" you then select that shape, and go to the Part Workbench, Part menu, "export CAD". Note that with Part WB import and export CAD, you can select different formats STEP, IGES or BREP. If you import from the file menu, you will find a few more choices.

Note also that converting STL to shape has its limitations. You often get a lot of unwanted edges, circles will be polygons etc.. Some times Part WB... Part menu ... refine shape, can help a small amount.

Generally STL format has a lot of limitations, and often is best to avoid, if possible. It is probably not very likely that you IGES or STEP will be much good unless you manually tidy up the "shape from mesh" in FreeCAD first. This is often not simple, and mostly can not be done automatically, due to the limitations of the STL format.

I hope this helps.

Jim
Post Reply