[SOLVED] How to reconstruct mesh from the faces?

Need help, or want to share a macro? Post here!
Forum rules
Be nice to others! Respect the FreeCAD code of conduct!
stefankorisnik3
Posts: 101
Joined: Sun Jul 24, 2022 12:49 pm

Re: How to reconstruct mesh from the faces?

Post by stefankorisnik3 »

Thank you for your time.
Can you make clear for me how can i
given n faces in the python code in the simple list
construct the solid object or some object that i construct mesh and then to export as stl
User avatar
onekk
Veteran
Posts: 6222
Joined: Sat Jan 17, 2015 7:48 am
Contact:

Re: How to reconstruct mesh from the faces?

Post by onekk »

stefankorisnik3 wrote: Mon Aug 01, 2022 3:15 pm Thank you for your time.
...
With some code we can do some works, as faces are made of wires and wires are made of edges, and edges have underlying curves (I'm trying to generalize).

So if your edges are derived from an interpolation like a BSPline or they are "a bunch of segments" something could be different when trying to make "faces" and the shell and then a solid.

See maybe:

https://forum.freecadweb.org/viewtopic. ... 99#p613599

And more generally the whole post.

https://forum.freecadweb.org/viewtopic.php?f=22&t=70606


Regards

Carlo D.
GitHub page: https://github.com/onekk/freecad-doc.
- In deep articles on FreeCAD.
- Learning how to model with scripting.
- Various other stuffs.

Blog: https://okkmkblog.wordpress.com/
stefankorisnik3
Posts: 101
Joined: Sun Jul 24, 2022 12:49 pm

Re: How to reconstruct mesh from the faces?

Post by stefankorisnik3 »

Thanks again i will read the posts soon.
To make it easier to imagine the faces. The faces are simple triangles: three vertices, three edges
I have formed the face. How can i display the face (triangle)
User avatar
onekk
Veteran
Posts: 6222
Joined: Sat Jan 17, 2015 7:48 am
Contact:

Re: How to reconstruct mesh from the faces?

Post by onekk »

stefankorisnik3 wrote: Mon Aug 01, 2022 3:39 pm Thanks again i will read the posts soon.
To make it easier to imagine the faces. The faces are simple triangles: three vertices, three edges
I have formed the face. How can i display the face (triangle)
Put here some code if it is not reserved:

Some more articulated code, there is some overehead due to some helper methods, to simplify the launch, modify and realunch work to develop code.

Code: Select all

"""Problematic Loft

This code was written as an sample code

Name: 20220729-loft_coinc.py

Author: Carlo Dormeletti
Copyright: 2022
Licence: CC BY-NC-ND 4.0 IT
"""

import os
import sys  # noqa
import FreeCAD
import FreeCADGui
from FreeCAD import Placement, Rotation, Vector # noqa
import Part # noqa
import Draft
from math import pi, sin, cos # noqa

V2d = FreeCAD.Base.Vector2d

DOC_NAME = "Loft"


def activate_doc():
    """Activate document."""
    FreeCAD.setActiveDocument(DOC_NAME)
    FreeCAD.ActiveDocument = FreeCAD.getDocument(DOC_NAME)
    FreeCADGui.ActiveDocument = FreeCADGui.getDocument(DOC_NAME)
    print("{0} activated".format(DOC_NAME))


def setview():
    """Rearrange View."""
    DOC.recompute()
    VIEW.viewAxometric()
    VIEW.setAxisCross(True)
    VIEW.fitAll()


def deleteObject(obj):
    """Delete documentObject."""
    if hasattr(obj, "InList") and len(obj.InList) > 0:
        for o in obj.InList:
            deleteObject(o)
            try:
                DOC.removeObject(o.Name)
            except RuntimeError as rte:
                errorMsg = str(rte)
                if errorMsg != "This object is currently not part of a document":
                    FreeCAD.Console.PrintError(errorMsg)
                    return False
    return True


def clear_DOC():
    """Clear ActiveDocument deleting all the objects."""
    while DOC.Objects:
        obj = DOC.Objects[0]
        name = obj.Name

        if not hasattr(DOC, name):
            continue

        if not deleteObject(obj):
            FreeCAD.Console.PrintError("Exiting on error")
            os.sys.exit()

        DOC.removeObject(obj.Name)

        DOC.recompute()


if FreeCAD.ActiveDocument is None:
    FreeCAD.newDocument(DOC_NAME)
    print("Document: {0} Created".format(DOC_NAME))

# test if there is an active document with a "proper" name
if FreeCAD.ActiveDocument.Name == DOC_NAME:
    print("DOC_NAME exist")
else:
    print("DOC_NAME is not active")
    # test if there is a document with a "proper" name
    try:
        FreeCAD.getDocument(DOC_NAME)
    except NameError:
        print("No Document: {0}".format(DOC_NAME))
        FreeCAD.newDocument(DOC_NAME)
        print("Document {} Created".format(DOC_NAME))

DOC = FreeCAD.getDocument(DOC_NAME)
GUI = FreeCADGui.getDocument(DOC_NAME)
VIEW = GUI.ActiveView
# print("DOC : {0} GUI : {1}".format(DOC, GUI))
activate_doc()
# print(FreeCAD.ActiveDocument.Name)
clear_DOC()

# Handy abbreviations

VZOR = Vector(0, 0, 0)
ROT0 = Rotation(0, 0, 0)

# Tolerances
EPS = 0.01

# it permit to apply half of the above tolerance, useful when cutting
# pipes using a length and EPS as quantity to add to inner cylinder

EPS_C = EPS * -0.5

# CODE START HERE

# First loft try. Returns "Recompute failed! Please check report view." --> Failed to create loft face
p11 = Vector(0, 0, 0)
p12 = Vector(1000, 0, 0)
p13 = Vector(0, 1000, 0)
p14 = Vector(0, 0, 1000)

wire11 = Part.makePolygon([p11, p12, p14, p11])
# Part.show(wire11, "wire11")

wire12 = Part.makePolygon([p11, p13, p14, p11])
# Part.show(wire12, "wire12")

face11 = Part.Face(wire11)
face12 = Part.Face(wire12)

edge11 = Part.LineSegment(p11, p12).toShape()
edge12 = Part.LineSegment(p11, p13).toShape()
edge13 = Part.LineSegment(p13, p12).toShape()

surf1 = Part.makeFilledFace([edge11, edge12,edge13])
# Part.show(surf1, "surface1")

edge14 = Part.LineSegment(p13, p14).toShape()
edge15 = Part.LineSegment(p12, p14).toShape()

surf2 = Part.makeFilledFace([edge13, edge14, edge15])
# Part.show(surf2, "surface2")

shell1 = Part.Shell([face11, face12, surf1, surf2])
Part.show(shell1, "shell1")


solid1 = Part.Solid(shell1)
Part.show(solid1, "solid1")

DOC.recompute()

setview()
This will create two triangles:

Code: Select all

p11 = Vector(0, 0, 0)
p12 = Vector(1000, 0, 0)
p13 = Vector(0, 1000, 0)
p14 = Vector(0, 0, 1000)

wire11 = Part.makePolygon([p11, p12, p14, p11])
Part.show(wire11, "wire11")

wire12 = Part.makePolygon([p11, p13, p14, p11])
Part.show(wire12, "wire12")
This will transform a wire in a face:

Code: Select all

face11 = Part.Face(wire11)
face12 = Part.Face(wire12)
to show faces add as example:

Code: Select all

Part.show(face12, "face12")

Hope it help.

Regards

Carlo D.
GitHub page: https://github.com/onekk/freecad-doc.
- In deep articles on FreeCAD.
- Learning how to model with scripting.
- Various other stuffs.

Blog: https://okkmkblog.wordpress.com/
heda
Veteran
Posts: 1348
Joined: Sat Dec 12, 2015 5:49 pm

Re: How to reconstruct mesh from the faces?

Post by heda »

if you decide not to go the route of making solids (too little info shared to know what you have and what you aim for)

there is always Reverse_Engineering_Workbench, not very well documented, but it will make a pointcloud to a mesh... (surface reconstruction/poisson, possible to script as well - search the forum)

making a pointcloud in fc is easiest done by importing a textfile with coordinates.
or do it by scripting, there are examples on the wiki (or search the forum with term "addPoints").

meshlab will do points to mesh as well, just search the web...

both for fc and ml, i would do things in gui first to see if it can do what one wants, and then worry about scripting.

btw, any algo will sooner or later choke on complexity of hull, so trial and error / subdivision is part of the game unless one is lucky on the first shoot.
stefankorisnik3
Posts: 101
Joined: Sun Jul 24, 2022 12:49 pm

Re: How to reconstruct mesh from the faces?

Post by stefankorisnik3 »

Thanks you all.

One more question if i may

For the

Code: Select all

face11 = Part.Face(wire11)
face12 = Part.Face(wire12)
How do i make the final object that contains both faces?

Me trying the code:

Code: Select all

def mediumway():
    firstTriangle = [
        App.Vector(0,0,0),
        App.Vector(0,0,1),
        App.Vector(1,0,0),
        App.Vector(0,0,0)
    ]

    wire11 = Part.makePolygon(firstTriangle)
    firstWire = wire11
    firstFace = Part.Face(firstWire)

    Part.show(wire11, "wire11")

    secondTriangle = [
        App.Vector(1,0,0),
        App.Vector(1,0,1),
        App.Vector(0,0,1),
        App.Vector(1,0,0)
    ]

    wire22 = Part.makePolygon(secondTriangle)
    secondWire = wire22
    secondFace = Part.Face(secondWire)
    
    Part.show(wire22, "wire22")

    
    shell1 = Part.Shell([firstFace, secondFace])
    Part.show(firstFace, "shell1")

mediumway()
and get: https://imgur.com/aVLWSj9
heda
Veteran
Posts: 1348
Joined: Sat Dec 12, 2015 5:49 pm

Re: How to reconstruct mesh from the faces?

Post by heda »

if you have not discovered by yourself by now...

you get what you ask for... (last line)

Code: Select all

Part.show(firstFace, "shell1")
vs

Code: Select all

Part.show(shell1, "shell1")
stefankorisnik3
Posts: 101
Joined: Sun Jul 24, 2022 12:49 pm

Re: How to reconstruct mesh from the faces?

Post by stefankorisnik3 »

Thank you. It was small but big help :)
heda
Veteran
Posts: 1348
Joined: Sat Dec 12, 2015 5:49 pm

Re: [SOLVED] How to reconstruct mesh from the faces?

Post by heda »

not easy to understand where you get your data from,
in any case making wires, faces to then make meshes seems like it is going over the bridge to get water.
if you really have defined triangles to start with, using mesh wb is more straight forward,
or if it truly is a point-cloud, unless you want to hand-assemble all triangles - find a pc 2 mesh routine, there are plenty of sw/libs that will do this

anyhow, here is how to deal with mesh wb.
the docs is far better than people think, also for scripting... the link is in the left toc under "python scripting" Mesh_Scripting

Code: Select all


import Mesh

tris = [
        ((0, 0, 0), (0, 0, 1), (1, 0, 0)), #1
        ((1, 0, 0), (1, 0, 1), (0, 0, 1)) #2
       ]


mesh = Mesh.Mesh(tris)
mobj = Mesh.show(mesh, 'mymesh')
# mobj is None since .show does not return (in v0.20)
# workaround is to use active object
doc = App.ActiveDocument
mobj = doc.ActiveObject
mobj.Label2 = 'the basic mesh'

# picking up mobj everytime is cumbersome...
def setLabel2(txt):
    doc.ActiveObject.Label2 = txt

# now this gives 2 tris with opposite normals,
# let's fix that...

mesh.harmonizeNormals()
mobj = Mesh.show(mesh, 'mymesh')
setLabel2('normal repair of basic mesh')

# further tris can be added to an existing mesh
# used console as emergency help...
#>>> dir(mesh) # always useful
#>>> mesh.addFacet()
#Traceback (most recent call last):
#  File "<input>", line 1, in <module>
#TypeError: set 9 floats or three vectors or a facet
V = App.Vector
mesh.addFacet(V(0, 0, 0), V(0, 1, 0), V(0, 0, 1))
mesh.addFacet(V(0, 0, 1), V(0, 1, 1), V(0, 1, 0))
mesh.harmonizeNormals()
mobj = Mesh.show(mesh, 'mymesh')
setLabel2('adding with addFacet')

# this time harmonize normals alone did not do the trick...
mesh.fixIndices()
mesh.harmonizeNormals()
mobj = Mesh.show(mesh, 'mymesh')
setLabel2('repair after addFacet')

# and finally merging 2 meshes...
mesh2 = Mesh.Mesh([((0, 0, 0), (0, 1, 0), (1, 1, 0)),
                   ((0, 0, 0), (1, 0, 0), (1, 1, 0))
                   ])
mesh.addMesh(mesh2)
mobj = Mesh.show(mesh, 'mymesh')
setLabel2('merging 2 meshes')

mesh.fixIndices()
mesh.harmonizeNormals()
mobj = Mesh.show(mesh, 'mymesh')
setLabel2('first repair, nok')

# once again the fixing is not enough for a wellformed mesh..
mesh.removeDuplicatedPoints()
mesh.harmonizeNormals()
mobj = Mesh.show(mesh, 'mymesh')
setLabel2('second repair, ok')

Post Reply