Transformations Based on Point Mapping

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!
Post Reply
inthereeds
Posts: 2
Joined: Wed May 18, 2022 3:53 pm

Transformations Based on Point Mapping

Post by inthereeds »

New to CAD so correct me if the terms I'm using aren't clear. I work in a lab and unfortunately the entire CAD model of our system got saved as STL files and then the source STEP files were lost. I have been remodeling everything using the STL files as a base. I am not only trying to reconstruct the shape geometry, but the relative positions as well. The general method was to generate a points object from the mesh, plug it into a new object using a shapebinder, and then build the solid off of that.

Many of the components are identical except for their relative placement. For those with the same orientation, it was simple enough to write a short python macro that would make a copy and transform it using the difference of the first vertex of the original mesh (the one I rebuilt) and the first vertex of the target mesh (another STL file of the same object.) However, there are some objects that are not only significantly more complicated in their geometry (thus making it time consuming to rebuild the same thing many times) but also have different orientations.

Is there a way to generate a transformation based off a point or face mapping? Say, if I have four points on the original mesh that I ultimately want to end up at four points on the target mesh, **provided these are actually congruent (no shear or stretching) and form a linearly independent basis, can I get FreeCAD to generate that transformation?

I have tried generating the matrix representation of the **affine transformation based on the four initial vectors and the four target vectors and simply plugging it in using copy.Placement.Matrix = affine_transform_matrix but this didn't work.

I'm also open to a radically different approach, I just want to understand how I can use a point mapping to generate an **affine transformation.

I attached an example file, I want to make a copy of the SilicaGasket-1 solid and map it onto the mesh labeled SilicaGasket-2.

Thank you in advance. While I would like to solve this particular example, I am very curious about how to do something like this in general. I reckon it could make for a pretty useful macro.

*NOTE: I am really talking about a subset of affine transformations, I understand that FreeCAD can not simply deform a parametric solid with stretching or shearing, I mean only angle-preserving transformations, limited to rotations and translations
Attachments
PointMapTransformationExample.FCStd
(183.24 KiB) Downloaded 18 times
User avatar
Shalmeneser
Veteran
Posts: 9475
Joined: Wed Dec 23, 2020 12:04 am
Location: Fr

Re: Transformations Based on Point Mapping

Post by Shalmeneser »

An assembly wb can position parts relatively with other parts.
Attachments
PointMapTransformationExample_SHALM.FCStd
(32.75 KiB) Downloaded 12 times
jbi
Posts: 117
Joined: Sun Apr 24, 2016 3:28 pm

Re: Transformations Based on Point Mapping

Post by jbi »

Depending how accurate the position should be you could use open3d. If you want to be compatible with freecad 0.19 the latest version you could use is 0.10 (because of numpy dependecies). You could use global registration first and afterwards fine align with ICP registration (Maybe ICP is enough for your purposes as well).
There are also good examples how to do this on the site. No need for point clicking.
This is working with point clouds only. So therefore you have to sample point clouds from the stl files, and also sample a point cloud from your newly generated CAD model. What you get is the transformation matrix which you can attach to the CAD model via placement. You can also calculate the point cloud distances to get an idea about which accuracy can be achieved.
edwilliams16
Veteran
Posts: 3112
Joined: Thu Sep 24, 2020 10:31 pm
Location: Hawaii
Contact:

Re: Transformations Based on Point Mapping

Post by edwilliams16 »

Rigid transformations are implemented in FreeCAD as Placements. If you have congruent corresponding triangles in your mesh pairs you can calculate the placement required to transform one into the other. Enclosed I've done it with two Sketcher triangles, but the math would be the same for other objects. Select (ctrl-click) the vertices of the first triangle, then the corresponding vertices of the second and run the macro.

Code: Select all

def placetriangleXY(points):
    ''' given three triangle vertices find the placement that
      Places points[0] at the origin
      Places points[1] on the x -axis 
      Puts the triangle on the XY-plane
    '''
    return App.Placement(-points[0], App.Rotation(points[1]-points[0], App.Vector(),(points[2]-points[0]).cross(points[1] - points[0])).inverted(), points[0])

def selectTriangles():
    ''' select the congruent triangle vertices in the same order
        returns the global vertex locations of the two triangles in the order selected'''
    pointslist=[]
    sels = Gui.Selection.getSelectionEx()
    for sel in sels:
        points = [v.Point for v in sel.SubObjects]
        pointslist.append(points)
    return pointslist
    

t0, t1 = selectTriangles()
p0 = placetriangleXY(t0)
p1 = placetriangleXY(t1)

#move sketch1 onto sketch0
sk1 = App.ActiveDocument.Sketch001
newPlacement = p0.inverse() * p1 * sk1.Placement
sk1.Placement = newPlacement
App.ActiveDocument.recompute() 
Attachments
maptriangles.FCStd
(5.56 KiB) Downloaded 11 times
inthereeds
Posts: 2
Joined: Wed May 18, 2022 3:53 pm

Re: Transformations Based on Point Mapping

Post by inthereeds »

Yep, that's it, thank you. The methods I was attempting to generate the placement matrix were a far cry from the elegance you've got there, I'll have to study it for a while. Cheers!
edwilliams16
Veteran
Posts: 3112
Joined: Thu Sep 24, 2020 10:31 pm
Location: Hawaii
Contact:

Re: Transformations Based on Point Mapping

Post by edwilliams16 »

inthereeds wrote: Wed May 18, 2022 10:55 pm Yep, that's it, thank you. The methods I was attempting to generate the placement matrix were a far cry from the elegance you've got there, I'll have to study it for a while. Cheers!
This, perhaps, is more robust. I forgot the optional priority argument in App.Rotation, but the default seems to work.

Code: Select all

def placetriangleXY(points):
    ''' given three triangle vertices find the placement that
      Places points[0] at the origin
      Places points[1] on the x -axis 
      Puts the triangle on the XY-plane
    '''
    return App.Placement(-points[0], App.Rotation(points[1]-points[0], App.Vector(),(points[2]-points[0]).cross(points[1] - points[0]), 'XZY').inverted(), points[0])

def selectTriangles():
    ''' select the congruent triangle vertices in the same order
        returns the global vertex locations of the two triangles in the order selected'''
    pointslist=[]
    sels = Gui.Selection.getSelectionEx()
    for sel in sels:
        points = [v.Point for v in sel.SubObjects]
        pointslist.append(points)
    return pointslist
    

t0, t1 = selectTriangles()
p0 = placetriangleXY(t0)
p1 = placetriangleXY(t1)

#move sketch1 onto sketch0
sk1 = App.ActiveDocument.Sketch001
newPlacement = p0.inverse() * p1 * sk1.Placement
sk1.Placement = newPlacement
App.ActiveDocument.recompute() 
EDIT: I should add that this only works if the two meshes/objects are referenced to the same coordinate system - eg both are at the root level or both are inside the same Part container. If they have different references, it get complicated... It gets even messier if either is a linked object, rather than being a separate object in its own right. I don't expect these caveats will affect you.
Post Reply