FCInfo CG of assemblies

Need help, or want to share a macro? Post here!
Forum rules
Be nice to others! Respect the FreeCAD code of conduct!
edwilliams16
Veteran
Posts: 3112
Joined: Thu Sep 24, 2020 10:31 pm
Location: Hawaii
Contact:

FCInfo CG of assemblies

Post by edwilliams16 »

mario52 wrote:
My MoveToOrigin macro needs updating to correctly handle hierarchies of objects, where I want to move the CG of the selected assembly to the global origin. To test my own coding I thought to use FCMacro - but it produces results I can't make sense of.
The enclosed file has four cubes, one at root level, one inside 'Part' and two more inside 'Part001' which is also inside Part. I ran FCInfo on the cubes and on the Parts.

To avoid looking up all the hierarchy of Placements they are written out by:

Code: Select all

[print(f'{obj.Name} local {obj.Placement} global {obj.getGlobalPlacement()}') for obj in App.ActiveDocument.Objects if hasattr(obj, 'Shape')]
obtaining

Code: Select all

Box local Placement [Pos=(0,0,0), Yaw-Pitch-Roll=(0,0,0)] global Placement [Pos=(0,0,0), Yaw-Pitch-Roll=(0,0,0)]
Box001 local Placement [Pos=(20,0,0), Yaw-Pitch-Roll=(0,0,0)] global Placement [Pos=(20,0,20), Yaw-Pitch-Roll=(0,0,0)]
Box002 local Placement [Pos=(0,20,0), Yaw-Pitch-Roll=(0,0,0)] global Placement [Pos=(0,20,40), Yaw-Pitch-Roll=(0,0,0)]
Box003 local Placement [Pos=(0,0,0), Yaw-Pitch-Roll=(0,0,0)] global Placement [Pos=(0,0,40), Yaw-Pitch-Roll=(0,0,0)]
Part local Placement [Pos=(0,0,20), Yaw-Pitch-Roll=(0,0,0)] global Placement [Pos=(0,0,20), Yaw-Pitch-Roll=(0,0,0)]
Part001 local Placement [Pos=(0,0,20), Yaw-Pitch-Roll=(0,0,0)] global Placement [Pos=(0,0,40), Yaw-Pitch-Roll=(0,0,0)]
To keep things simple, for the moment, there are no rotations. The results for FCInfo center of mass are:
  • Cube (5,5,5)
  • Cube001 (25,5,5)
  • Cube002 (5,25,5)
  • Cube003 (5,5,5)
The CG of a 10mm cube at the origin is (5,5,5), so according to FCInfo the origins are at
  • Cube (0,0,0)
  • Cube001 (20,0,0)
  • Cube002 (0,20,0)
  • Cube003 (0,0,0)
So according to FCInfo the CG of the boxes are displaced by their local Placement - not their global one as one might have expected. Nevertheless, look at the CM of the Part objects according to FCInfo
  • Part (25,5,25)
  • Part001 (5,25,25)
The origin displacements are thus:
  • Part (20,0,20))
  • Part001 (20,0,20)
These make no sense to me at all
Part001 consists of Cube002 and Cube003. Their combined CG within Part001 is the mean of the two- displaced by ((0,20,0) +(0,0,0))/2 = (0,10,0) or at a local coordinate of (5,15,5) within Part001. FCInfo says (5,25,25). The global position of the combined CG includes the global displacement of Part001 from the document origin (0,0,20), and so is (5,15,5) +(0,0,20) = (5,15,25) - still different from FCInfo's result.

I conclude, unless I've made some mistake, FCInfo isn't computing the CG of assemblies of objects correctly. I haven't checked the moment calculations - but I would also be suspicious of them in the case of assemblies.
Attachments
testFCInfo.FCStd
(10.68 KiB) Downloaded 43 times
chrisb
Veteran
Posts: 53945
Joined: Tue Mar 17, 2015 9:14 am

Re: FCInfo CG of assemblies

Post by chrisb »

FCInfo seems to respect only the first object in a Part container. If multiple objects are selected, only the first is used. So it doesn't respect different sizes of objects at all.
A Sketcher Lecture with in-depth information is available in English, auf Deutsch, en français, en español.
edwilliams16
Veteran
Posts: 3112
Joined: Thu Sep 24, 2020 10:31 pm
Location: Hawaii
Contact:

Re: FCInfo CG of assemblies

Post by edwilliams16 »

chrisb wrote: Sun Jul 04, 2021 7:49 am FCInfo seems to respect only the first object in a Part container. If multiple objects are selected, only the first is used. So it doesn't respect different sizes of objects at all.
Yes, I think so. FCInfo is summing over the contained items for Volume, Area, Mass etc., but is not for the CG.
mario52
Veteran
Posts: 4674
Joined: Wed May 16, 2012 2:13 pm

Re: FCInfo CG of assemblies

Post by mario52 »

Hi

actual FCinfo not work with the globalplacement (then i think my macro is now outdated), i beginning the new version with globalplacement and other property Mesh, Points but ...

for the CG tray Macro_CenterOfMass Image by schupin

mario
Maybe you need a special feature, go into Macros_recipes and Code_snippets, Topological_data_scripting.
My macros on Gist.github here complete macros Wiki and forum.
edwilliams16
Veteran
Posts: 3112
Joined: Thu Sep 24, 2020 10:31 pm
Location: Hawaii
Contact:

Re: FCInfo CG of assemblies

Post by edwilliams16 »

Tried MacroCenterofMass on my test file above with mixed success


It computed the COM of Cube and Cube001 correctly. However, it didn't account for the nesting of Part001 by Part and the computed global CGs of Cube002 and Cube003 were wrong by (0,0,20), the placement of of Part. However if the intent was to compute the local CG in the objects' immediate container, the results are all correct.

When I tried to get the COM of the assemblies Part and Part001, I got an error:

Code: Select all

07:59:51  Traceback (most recent call last):
  File "/Users/ed/Library/Preferences/FreeCAD/Macro/CenterOfMass.FCMacro", line 909, in <module>
    myWidget = CenterofmassWindow()
  File "/Users/ed/Library/Preferences/FreeCAD/Macro/CenterOfMass.FCMacro", line 89, in __init__
    self.child.initUI(self)
  File "/Users/ed/Library/Preferences/FreeCAD/Macro/CenterOfMass.FCMacro", line 283, in initUI
    originColor = sel[sol].ViewObject.ShapeColor
<class 'AttributeError'>: 'Gui.ViewProviderDocumentObject' object has no attribute 'ShapeColor'
It appears that I should be multiply selecting the individual objects, not their container, so, trying that and interpreting the results as the 'local' CG in the smallest container containing all the selected objects, certain combinations worked correctly:

Cube+Cube001 - returns (15,5,15) which is both the local and global CG
Cube002+Cube003 - returns (5, 15, 25) which is the local CG in Part001

However, Cube001 + Cube002 has a global CG of (15,15,35) and a local CG (in Part) of (15,15,15). The Macro returns (15,15,25) which is neither.
Cube + Cube002 has local and global CG of (5,15,25) - the Macro returns (5, 15, 15)

I conclude this Macro doesn't handle the tricky nesting of placements correctly either.
schupin wrote:
edwilliams16
Veteran
Posts: 3112
Joined: Thu Sep 24, 2020 10:31 pm
Location: Hawaii
Contact:

Re: FCInfo CG of assemblies

Post by edwilliams16 »

Well, I have a Macro that will compute the global CG of a multiple selection of possibly nested objects correctly.
Having a "local" version would require finding the nearest common ancestor of the selected objects, so as to provide a coordinate system they can share.
I've only tried it on objects created by the Part and PartDesign workbenches. If there are pitfalls elsewhere, I'd like to know about them.
I added a test case with Placement Rotations which also works correctly.
In the case of cubes, the easiest way to verify the global CG location is to select opposite corner vertices and average the displayed coordinates.

Code: Select all

def globalCG(obj, removeLocalOffset=True):
    '''Find COM of object in global coordinates
      remove local offset per https://forum.freecadweb.org/viewtopic.php?t=27821'''
    gpl = obj.getGlobalPlacement()
    pl = obj.Placement
    rpl= gpl.multiply(pl.inverse())
    if removeLocalOffset:
        return rpl.multVec(obj.Shape.CenterOfMass)
    else:
        return gpl.multVec(obj.Shape.CenterOfMass)


def printGCM(obj):
    ''' Compute and print out global COM of an object hierarchy'''
    global volume, moment
    if hasattr(obj, 'Shape'):
        shape = obj.Shape
        if hasattr(shape, 'CenterOfMass'):
            print(f'{obj.Name}  {vectorRound(globalCG(obj, True), nDec)}')
            volume += shape.Volume
            moment += globalCG(obj, True).multiply(shape.Volume)
        else:
            for obj1 in obj.OutList:
                if hasattr(obj1, 'Shape'):
                    printGCM(obj1)

def vectorRound(v, n):
    '''Round the output of App.Vector v to n dec places'''
    return App.Vector(round(v.x, n), round(v.y, n), round(v.z, n))

volume = 0
moment = App.Vector(0., 0., 0.)
nDec = 3  #number of Decimal places in output

for sel in Gui.Selection.getSelectionEx():
        printGCM(sel.Object)

print(f'Total Volume = {round(volume,2)}  Total Moment = {vectorRound(moment, nDec)}  Global CG = {vectorRound(moment.multiply(1./volume), nDec)}')


        
    
The Macro recurses down the tree from the selections looking for objects with a CenterOfMass property and adds up their volumes and global moments. This assumes everything has the same density. Minor modification would include density effects.
Attachments
testFCInfo.FCStd
(13.54 KiB) Downloaded 41 times
mario52
Veteran
Posts: 4674
Joined: Wed May 16, 2012 2:13 pm

Re: FCInfo CG of assemblies

Post by mario52 »

hi

tray Macro_BoundingBox_Tracing Image

select Part, Part001, Part002 all is good

or cubes separately all is good only Cube004 is decaled ...

see

Code: Select all

def objectRealPlacement3D(obj, mode = 0):    # search the real Placement
(this def is include in my new FCInfo)

mario
Maybe you need a special feature, go into Macros_recipes and Code_snippets, Topological_data_scripting.
My macros on Gist.github here complete macros Wiki and forum.
edwilliams16
Veteran
Posts: 3112
Joined: Thu Sep 24, 2020 10:31 pm
Location: Hawaii
Contact:

Re: FCInfo CG of assemblies

Post by edwilliams16 »

There's a problem that your code does not account for any rotations of the container. I didn't find a fix, but the following will draw a bounding box in the right place:

Code: Select all

sel = Gui.Selection.getSelectionEx()[0]
bb = sel.Object.Shape.BoundBox
xmin = bb.XMin
xmax= bb.XMax
ymin=bb.YMin
ymax=bb.YMax
zmin=bb.ZMin
zmax=bb.ZMax
bbBox = Part.makeBox(xmax-xmin, ymax-ymin, zmax-zmin, App.Vector(xmin,ymin,zmin))
gpl =sel.Object.getGlobalPlacement()
lpl = sel.Object.Placement
pl = gpl.multiply(lpl.inverse())
bbBox.Placement = pl
Part.show(bbBox)
It's simple enough you can probably debug your own code.
Attachments
testFCInfo.FCStd
(16.38 KiB) Downloaded 35 times
mario52
Veteran
Posts: 4674
Joined: Wed May 16, 2012 2:13 pm

Re: FCInfo CG of assemblies

Post by mario52 »

Aloha

good , all object worked is good

mario
Maybe you need a special feature, go into Macros_recipes and Code_snippets, Topological_data_scripting.
My macros on Gist.github here complete macros Wiki and forum.
edwilliams16
Veteran
Posts: 3112
Joined: Thu Sep 24, 2020 10:31 pm
Location: Hawaii
Contact:

Re: FCInfo CG of assemblies

Post by edwilliams16 »

mario52 wrote: Wed Jul 07, 2021 8:57 am Aloha

mario
I did some work on your macro so it now handles objects in nested part containers. I thought it would be really easy - but of course it was more complicated than I anticipated. Placing the text correctly was convoluted...

Code: Select all

# -*- coding: utf-8 -*-
from __future__ import unicode_literals

# cette macro trace en rouge (modifiable) le tour du boundingbox avec 6 rectangles
# si "createVol" = 1 il sera cree un volume (rouge) de la dimension du BoundBox
# this macro red trace (editable) around the BoundingBox with 6 rectangles
# if "createVol" = 1 on volume (red) is created 
# Macro_BoundingBox_Tracing
#
#OS: Windows Vista     #OS: Windows 8.1                                #OS: Windows 10                                 #OS: Windows 10
#Platform: 32-bit      #Word size of OS: 64-bit                        #Word size of OS: 64-bit                        #Word size of OS: 64-bit
#Version: 0.14.3389    #Word size of FreeCAD: 64-bit                   #Word size of FreeCAD: 64-bit                   #Word size of FreeCAD: 64-bit
#Python version: 2.6.2 #Version: 0.15.4671 (Git)                       #Version: 0.16.6700 (Git)                       #Version: 0.17.13528 (Git)
#Qt version: 4.5.2     #Branch: releases/FreeCAD-0-15                  #Build type: Release                            #Build type: Release
#Coin version: 3.1.0   #Hash: 244b3aef360841646cbfe80a1b225c8b39c8380c #Branch: releases/FreeCAD-0-16                  #Branch: releases/FreeCAD-0-17
#SoQt version: 1.4.1   #Python version: 2.7.8                          #Hash: 7b925d11aa69ac405b423635adb1e2833f18a817 #Hash: 5c3f7bf8ec51e2c7187789f7edba71a7aa82a88b
#OCC version: 6.5.1    #Qt version: 4.8.6                              #Python version: 2.7.8                          #Python version: 2.7.14
#                      #Coin version: 4.0.0a                           #Qt version: 4.8.6                              #Qt version: 4.8.7
#                      #OCC version: 6.8.0.oce-0.17                    #Coin version: 4.0.0a                           #Coin version: 4.0.0a
#                                                                      #OCC version: 6.8.0.oce-0.17                    #OCC version: 7.2.0
###############################################################################################################################################
#OS: Windows 10 (10.0)
#Word size of OS: 64-bit
#Word size of FreeCAD: 64-bit
#Version: 0.19.16624 (Git)
#Build type: Release
#Branch: master
#Hash: 222ae7305fdf1097e4ef3d050f69dff47dbd8786
#Python version: 3.6.8
#Qt version: 5.12.1
#Coin version: 4.0.0a
#OCC version: 7.3.0
###############################################################################################################################################
#modified by edwilliams16 to handle objects in nested part containers

__title__   = "BoundingBox_Tracing"
__author__  = "Mario52"
__url__     = "http://www.freecadweb.org/index-fr.html"
__Wiki__    = "https://www.freecadweb.org/wiki/Macro_BoundingBox_Tracing"
__version__ = "0.12"
__date__    = "2021/07/10" #  YYYY/MM/DD


import PySide
import FreeCAD, FreeCADGui, Draft, Part
App = FreeCAD

debug = False
if debug:
    from sys import path
    sys.path.append('/Users/ed/opt/anaconda3/lib/python3.7/site-packages')
    import ptvsd
    print("Waiting for debugger attach")
    # 5678 is the default attach port in the VS Code debug configurations
    ptvsd.enable_attach(address=('localhost', 5678), redirect_output=True)
    ptvsd.wait_for_attach()

##### Section configuration begin ##################
##### for volume begin ###################
createVol         = 1           # give 1 for create Volume # mettre a 1 pour creer un volume
createDimVol      = 1           # 1 = create dimension info : 0 = not dimension info
##### for volume end   ###################

##### for dimensions info begin ##########
createDim         = 1           # 1 = create dimension info : 0 = not create dimension info

if int(FreeCAD.Version()[1]) > 17:      # Version de FreeCAD
    DisplayModeText   = str(u"3D text") # available : u"2D text" or u"3D text" 
else:
    DisplayModeText   = str(u"Screen")  # available : u"Screen" or u"World" 

JustificationText = str(u"Center")    # available : "Center" or "Left" or "Right"
FontSizeText      = 3.0        # text info dimension
TextColorText_R   = 0.0         # text color info red      1 = 255
TextColorText_G   = 0.0         # text color info green    1 = 255
TextColorText_B   = 0.0         # text color info blue     1 = 255
arondi            = 3           # round the info ex: 3 = 3 decimals

##### for dimensions info end   ##########
##### Section configuration end ####################


def adjustedGlobalPlacement(obj, locVector):
    '''find global placement to make locVector the local origin with the correct orientation'''
    try:
        objectPlacement = obj.Shape.Placement
        objectGlobalPlacement = obj.getGlobalPlacement()
        locPlacement = App.Placement(locVector, App.Rotation(App.Vector(1,0,0),0))
        return objectGlobalPlacement.multiply(objectPlacement.inverse()).multiply(locPlacement)
    except Exception:
        return locPlacement  # what should be here?


sel   = FreeCADGui.Selection.getSelection()
selEx = FreeCADGui.Selection.getSelectionEx()
objs  = [selobj.Object for selobj in selEx]
    
if len(objs) >= 1:
    if hasattr(objs[0], "Shape"):
        s = objs[0].Shape
    elif hasattr(objs[0], "Mesh"):      # upgrade with wmayer thanks #http://forum.freecadweb.org/viewtopic.php?f=13&t=22331
        s = objs[0].Mesh
    elif hasattr(objs[0], "Points"):
        s = objs[0].Points

    try:
        # LineColor
        red   = 1.0  # 1 = 255
        green = 0.0  #
        blue  = 0.0  #
    
        # boundBox
        boundBox_ = s.BoundBox
        boundBoxLX = boundBox_.XLength
        boundBoxLY = boundBox_.YLength
        boundBoxLZ = boundBox_.ZLength
        boundBoxXMin = boundBox_.XMin
        boundBoxYMin = boundBox_.YMin
        boundBoxZMin = boundBox_.ZMin
        boundBoxLocation = App.Vector(boundBox_.XMin,boundBox_.YMin,boundBox_.ZMin)
        nameLabel  = sel[0].Label

        try:
            import unicodedata    
            nameLabel = str(unicodedata.normalize('NFKD', nameLabel).encode('ascii','ignore'))[2:]
        except Exception:
            None

       
        #    if objs[0].getParentGeoFeatureGroup() == None:  Need this test somewhere?
               
    
        App.Console.PrintMessage(str(boundBox_)+"\r\n")
        App.Console.PrintMessage("Rectangle      : "+str(boundBoxLX)+" x "+str(boundBoxLY)+" x "+str(boundBoxLZ)+"\r\n")
        
        if (createVol == 1) and (boundBoxLX > 0) and (boundBoxLY > 0) and (boundBoxLZ > 0):  # Create Volume
            BDvol = App.ActiveDocument.addObject("Part::Box",nameLabel + "_BoundBoxVolume")
            #BDvol.Label = "BoundBoxVolume"
            BDvol.Length.Value = boundBoxLX
            BDvol.Width.Value  = boundBoxLY
            BDvol.Height.Value = boundBoxLZ
            BDvol.Placement = adjustedGlobalPlacement(objs[0], boundBoxLocation)
            BDPl = BDvol.Placement
            oripl_X=BDvol.Placement.Base.x
            oripl_Y=BDvol.Placement.Base.y
            oripl_Z=BDvol.Placement.Base.z
            #if debug: print(f'global {globalObjectPlacement}\n local {localObjectPlacement} BB {BBlocPlacement}')
            FreeCADGui.ActiveDocument.getObject(BDvol.Name).LineColor  = (red, green, blue)
            FreeCADGui.ActiveDocument.getObject(BDvol.Name).PointColor = (red, green, blue)
            FreeCADGui.ActiveDocument.getObject(BDvol.Name).ShapeColor = (red, green, blue)
            FreeCADGui.ActiveDocument.getObject(BDvol.Name).Transparency = 80
            App.Console.PrintMessage(nameLabel + "_BoundBoxVolume : " + str(BDvol.Shape.Volume)+"\r\n")
    
            if createDimVol == 1:    # section create dimension info for volume
                conteneurVol = []
                del conteneurVol[:]
                conteneurVol = App.activeDocument().addObject("App::DocumentObjectGroup",nameLabel + "_BoundBoxVolume_Info")
    
                #pl_0C1 = Draft.make_text([str(round(boundBoxLX,arondi))],point=FreeCAD.Vector(oripl_X + (boundBoxLX/2), oripl_Y, oripl_Z))
                pl_0C1 = Draft.make_text([str(round(boundBoxLX,arondi))],placement = BDPl.multVec(App.Vector(boundBoxLX/2,0,0)))
                pl_0C1.ViewObject.DisplayMode   = DisplayModeText
                pl_0C1.ViewObject.Justification = JustificationText
                pl_0C1.ViewObject.TextColor     = (TextColorText_R, TextColorText_G, TextColorText_B)
                pl_0C1.ViewObject.FontSize      = FontSizeText
                pl_0C1.Label      = nameLabel + "_Volume_X_" + str(round(boundBoxLX,arondi))
                conteneurVol.addObject(pl_0C1)
    
                #pl_0C2 = Draft.make_text([str(round(boundBoxLY,arondi))],point=FreeCAD.Vector(oripl_X, oripl_Y + (boundBoxLY/2), oripl_Z))
                pl_0C2 = Draft.make_text([str(round(boundBoxLY,arondi))],placement = BDPl.multVec(App.Vector(0, boundBoxLY/2, 0)))
                pl_0C2.ViewObject.DisplayMode   = DisplayModeText
                pl_0C2.ViewObject.Justification = JustificationText
                pl_0C2.ViewObject.TextColor     = (TextColorText_R, TextColorText_G, TextColorText_B)
                pl_0C2.ViewObject.FontSize      = FontSizeText
                pl_0C2.Label      = nameLabel + "_Volume_Y_" + str(round(boundBoxLY,arondi))
                conteneurVol.addObject(pl_0C2)
        
                #pl_0C3 = Draft.make_text([str(round(boundBoxLZ,arondi))],placement=FreeCAD.Vector(oripl_X, oripl_Y, oripl_Z + (boundBoxLZ/2)))
                pl_0C3 = Draft.make_text([str(round(boundBoxLZ,arondi))],placement = BDPl.multVec(App.Vector(0, 0, boundBoxLZ/2)))
                pl_0C3.ViewObject.DisplayMode   = DisplayModeText
                pl_0C3.ViewObject.Justification = JustificationText
                pl_0C3.ViewObject.TextColor     = (TextColorText_R, TextColorText_G, TextColorText_B)
                pl_0C3.ViewObject.FontSize      = FontSizeText
                pl_0C3.Label      = nameLabel + "_Volume_Z_" + str(round(boundBoxLZ,arondi))
                conteneurVol.addObject(pl_0C3)
    
    #    else:
    #        App.Console.PrintMessage("Not Volume BoundBox possible"+"\r\n")
        App.Console.PrintMessage("_____________________"+"\r\n")

    
        #####
        conteneurRectangle = []
        del conteneurRectangle[:]
        conteneurRectangle = App.activeDocument().addObject("App::DocumentObjectGroup",nameLabel + "_BoundBoxRectangle")
    
        if createDim == 1:    # conteneur dimension info
            conteneurInfo = []
            del conteneurInfo[:]
            conteneurInfo = App.activeDocument().addObject("App::DocumentObjectGroup",nameLabel + "_BoundBoxRectangle_Info")
        try:
            if (boundBoxLX and boundBoxLY) > 0.0:
                #pl_0 = App.Placement(App.Vector(oripl_X,oripl_Y,oripl_Z), App.Rotation(0.0,0.0,0.0))
                pl_0 = adjustedGlobalPlacement(objs[0], boundBoxLocation)
                double = Draft.makeRectangle(length=boundBoxLX,height=boundBoxLY,placement=pl_0,face=False,support=None) #OK
                double.Label = nameLabel + "_BoundBoxRectangle_Bo"
                FreeCADGui.activeDocument().activeObject().LineColor = (red, green, blue)
                conteneurRectangle.addObject(double)
    #        else:
    #            App.Console.PrintError("not value 0"+"\n")
    
            if createDim == 1:    # section create dimension info
                #pl_0C1 = Draft.make_text([str(round(boundBoxLX,arondi))],placement=FreeCAD.Vector(pl_0.Base.x + (boundBoxLX/2), pl_0.Base.y, pl_0.Base.z))
                # XY -> XY
                pl_0C1 = Draft.make_text([str(round(boundBoxLX,arondi))],placement=pl_0.multVec(App.Vector(boundBoxLX/2, 0, 0)))
                pl_0C1.ViewObject.DisplayMode   = DisplayModeText
                pl_0C1.ViewObject.Justification = JustificationText
                pl_0C1.ViewObject.TextColor     = (TextColorText_R, TextColorText_G, TextColorText_B)
                pl_0C1.ViewObject.FontSize      = FontSizeText
                pl_0C1.Label      = nameLabel + "_Rectangle_Bo_0X_" + str(round(boundBoxLX,arondi))
                conteneurInfo.addObject(pl_0C1)
        
                #pl_0C2 = Draft.make_text([str(round(boundBoxLY,arondi))],placement=FreeCAD.Vector(pl_0.Base.x, pl_0.Base.y + (boundBoxLY/2), pl_0.Base.z))
                pl_0C2 = Draft.make_text([str(round(boundBoxLY,arondi))],placement=pl_0.multVec(App.Vector(0., boundBoxLY/2, 0.)))
                pl_0C2.ViewObject.DisplayMode   = DisplayModeText
                pl_0C2.ViewObject.Justification = JustificationText
                pl_0C2.ViewObject.TextColor     = (TextColorText_R, TextColorText_G, TextColorText_B)
                pl_0C2.ViewObject.FontSize      = FontSizeText
                pl_0C2.Label      = nameLabel + "_Rectangle_Bo_0Y_" + str(round(boundBoxLY,arondi))
                conteneurInfo.addObject(pl_0C2)
    
        except:
            App.Console.PrintError("not done 0"+"\n")

        try:
            if (boundBoxLX and boundBoxLY) > 0.0:
                #pl_1 = App.Placement(App.Vector(oripl_X,oripl_Y,oripl_Z+boundBoxLZ), App.Rotation(0.0,0.0,0.0))
                pl_1 =adjustedGlobalPlacement(objs[0], boundBoxLocation + App.Vector(0,0,boundBoxLZ))
                double = Draft.makeRectangle(length=boundBoxLX,height=boundBoxLY,placement=pl_1,face=False,support=None) #Ok
                double.Label = nameLabel + "_BoundBoxRectangle_To"
                FreeCADGui.activeDocument().activeObject().LineColor = (red, green, blue)
                conteneurRectangle.addObject(double)
    #        else:
    #            App.Console.PrintError("not value 1"+"\n")
    
            if createDim == 1:    # section create dimension info
                #pl_0C1 = Draft.make_text([str(round(boundBoxLX,arondi))],placement=FreeCAD.Vector(pl_1.Base.x + (boundBoxLX/2), pl_1.Base.y, pl_1.Base.z))
                #XY -> XY
                pl_0C1 = Draft.make_text([str(round(boundBoxLX,arondi))],placement=pl_1.multVec(App.Vector(boundBoxLX/2, 0, 0)))
                pl_0C1.ViewObject.DisplayMode   = DisplayModeText
                pl_0C1.ViewObject.Justification = JustificationText
                pl_0C1.ViewObject.TextColor     = (TextColorText_R, TextColorText_G, TextColorText_B)
                pl_0C1.ViewObject.FontSize      = FontSizeText
                pl_0C1.Label      = nameLabel + "_Rectangle_To_1X_" + str(round(boundBoxLX,arondi))
                conteneurInfo.addObject(pl_0C1)
        
                #pl_0C2 = Draft.make_text([str(round(boundBoxLY,arondi))],placement=FreeCAD.Vector(pl_1.Base.x, pl_1.Base.y + (boundBoxLY/2), pl_1.Base.z))
                pl_0C2 = Draft.make_text([str(round(boundBoxLY,arondi))],placement=pl_1.multVec(App.Vector(0., boundBoxLY/2, 0)))

                pl_0C2.ViewObject.DisplayMode   = DisplayModeText
                pl_0C2.ViewObject.Justification = JustificationText
                pl_0C2.ViewObject.TextColor     = (TextColorText_R, TextColorText_G, TextColorText_B)
                pl_0C2.ViewObject.FontSize      = FontSizeText
                pl_0C2.Label      = nameLabel + "_Rectangle_To_1Y_" + str(round(boundBoxLY,arondi))
                conteneurInfo.addObject(pl_0C2)
    
        except:
            App.Console.PrintError("not done 1"+"\n")

        try:
            if (boundBoxLX and boundBoxLZ) > 0.0:
                #pl_2 = App.Placement(App.Vector(oripl_X,oripl_Y,oripl_Z), App.Rotation(0.0,0.0,90))
                pl_2 = pl_0.multiply(App.Placement(App.Vector(0.,0.,0.),App.Rotation(0.0,0.0,90)))
                double = Draft.makeRectangle(length=boundBoxLX,height=boundBoxLZ,placement=pl_2,face=False,support=None) #Ok
                double.Label = nameLabel + "_BoundBoxRectangle_Fr"
                FreeCADGui.activeDocument().activeObject().LineColor = (red, green, blue)
                conteneurRectangle.addObject(double)
    #        else:
    #            App.Console.PrintError("not value 2"+"\n")
    
            if createDim == 1:    # section create dimension info
                #pl_0C1 = Draft.make_text([str(round(boundBoxLX,arondi))],placement=FreeCAD.Vector(pl_2.Base.x + (boundBoxLX/2), pl_2.Base.y, pl_2.Base.z))
                #XZ -> XY
                pl_0C1 = Draft.make_text([str(round(boundBoxLX,arondi))],placement=pl_2.multVec(App.Vector(boundBoxLX/2, 0, 0)))
                pl_0C1.ViewObject.DisplayMode   = DisplayModeText
                pl_0C1.ViewObject.Justification = JustificationText
                pl_0C1.ViewObject.TextColor     = (TextColorText_R, TextColorText_G, TextColorText_B)
                pl_0C1.ViewObject.FontSize      = FontSizeText
                pl_0C1.Label      = nameLabel + "_Rectangle_Fr_2X_" + str(round(boundBoxLX,arondi))
                conteneurInfo.addObject(pl_0C1)
       
                #pl_0C2 = Draft.make_text([str(round(boundBoxLZ,arondi))],placement=FreeCAD.Vector(pl_2.Base.x, pl_2.Base.y, pl_2.Base.z + (boundBoxLZ/2)))
                pl_0C2 = Draft.make_text([str(round(boundBoxLZ,arondi))],placement=pl_2.multVec(App.Vector(0, boundBoxLZ/2, 0)))
                pl_0C2.ViewObject.DisplayMode   = DisplayModeText
                pl_0C2.ViewObject.Justification = JustificationText
                pl_0C2.ViewObject.TextColor     = (TextColorText_R, TextColorText_G, TextColorText_B)
                pl_0C2.ViewObject.FontSize      = FontSizeText
                pl_0C2.Label      = nameLabel + "_Rectangle_Fr_2Z_" + str(round(boundBoxLZ,arondi))
                conteneurInfo.addObject(pl_0C2)
    
        except:
            App.Console.PrintError("not done 2"+"\n")

        try:
            if (boundBoxLX and boundBoxLZ) > 0.0:
                #pl_3 = App.Placement(App.Vector(oripl_X,oripl_Y+boundBoxLY,oripl_Z), App.Rotation(0.0,0.0,90))
                pl_3 = adjustedGlobalPlacement(objs[0], boundBoxLocation+App.Vector(0, boundBoxLY, 0)).multiply(App.Placement(App.Vector(0.,0.,0.),App.Rotation(0.0,0.0,90)))
                double = Draft.makeRectangle(length=boundBoxLX,height=boundBoxLZ,placement=pl_3,face=False,support=None) #Ok
                double.Label = nameLabel + "_BoundBoxRectangle_Re"
                FreeCADGui.activeDocument().activeObject().LineColor = (red, green, blue)
                conteneurRectangle.addObject(double)
    #        else:
    #            App.Console.PrintError("not value 3"+"\n")
    
            if createDim == 1:    # section create dimension info
                #XZ -> XY
                pl_0C1 = Draft.make_text([str(round(boundBoxLX,arondi))],placement=pl_3.multVec(App.Vector(boundBoxLX/2, 0, 0)))
                pl_0C1.ViewObject.DisplayMode   = DisplayModeText
                pl_0C1.ViewObject.Justification = JustificationText
                pl_0C1.ViewObject.TextColor     = (TextColorText_R, TextColorText_G, TextColorText_B)
                pl_0C1.ViewObject.FontSize      = FontSizeText
                pl_0C1.Label      = nameLabel + "_Rectangle_Re_3X_" + str(round(boundBoxLX,arondi))
                conteneurInfo.addObject(pl_0C1)
        
                pl_0C2 = Draft.make_text([str(round(boundBoxLZ,arondi))],placement=pl_3.multVec(App.Vector(0, boundBoxLZ/2, 0)))
                pl_0C2.ViewObject.DisplayMode   = DisplayModeText
                pl_0C2.ViewObject.Justification = JustificationText
                pl_0C2.ViewObject.TextColor     = (TextColorText_R, TextColorText_G, TextColorText_B)
                pl_0C2.ViewObject.FontSize      = FontSizeText
                pl_0C2.Label      = nameLabel + "_Rectangle_Re_3Z_" + str(round(boundBoxLZ,arondi))
                conteneurInfo.addObject(pl_0C2)
    
        except:
            App.Console.PrintError("not done 3"+"\n")

        try:
            if (boundBoxLY and boundBoxLZ) > 0.0:
                #pl_4 = App.Placement(App.Vector(oripl_X,oripl_Y,oripl_Z), App.Rotation(90,0.0,90))
                pl_4 = pl_0.multiply(App.Placement(App.Vector(0.,0.,0.),App.Rotation(90,0,90)))
                double = Draft.makeRectangle(length=boundBoxLY,height=boundBoxLZ,placement=pl_4,face=False,support=None) #Ok
                double.Label = nameLabel + "_BoundBoxRectangle_Le"
                FreeCADGui.activeDocument().activeObject().LineColor = (red, green, blue)
                conteneurRectangle.addObject(double)
    #        else:
    #            App.Console.PrintError("not value 4"+"\n")
    
            if createDim == 1:    # section create dimension info
                #pl_0C1 = Draft.make_text([str(round(boundBoxLY,arondi))],placement=FreeCAD.Vector(pl_4.Base.x, pl_4.Base.y + (boundBoxLY/2), pl_4.Base.z))
                #YZ ->XY
                pl_0C1 = Draft.make_text([str(round(boundBoxLY,arondi))],placement=pl_4.multVec(App.Vector(boundBoxLY/2, 0., 0.)))
                pl_0C1.ViewObject.DisplayMode   = DisplayModeText
                pl_0C1.ViewObject.Justification = JustificationText
                pl_0C1.ViewObject.TextColor     = (TextColorText_R, TextColorText_G, TextColorText_B)
                pl_0C1.ViewObject.FontSize      = FontSizeText
                pl_0C1.Label      = nameLabel + "_Rectangle_Le_4Y_" + str(round(boundBoxLY,arondi))
                conteneurInfo.addObject(pl_0C1)
        
                #pl_0C2 = Draft.make_text([str(round(boundBoxLZ,arondi))],placement=FreeCAD.Vector(pl_4.Base.x, pl_4.Base.y, pl_4.Base.z + (boundBoxLZ/2)))
                pl_0C2 = Draft.make_text([str(round(boundBoxLZ,arondi))],placement=pl_4.multVec(App.Vector(0., boundBoxLZ/2, 0)))
                pl_0C2.ViewObject.DisplayMode   = DisplayModeText
                pl_0C2.ViewObject.Justification = JustificationText
                pl_0C2.ViewObject.TextColor     = (TextColorText_R, TextColorText_G, TextColorText_B)
                pl_0C2.ViewObject.FontSize      = FontSizeText
                pl_0C2.Label      = nameLabel + "_Rectangle_Le_4Z_" + str(round(boundBoxLZ,arondi))
                conteneurInfo.addObject(pl_0C2)
    
        except:
            App.Console.PrintError("not done 4"+"\n")

        try:
            if (boundBoxLY and boundBoxLZ) > 0.0:
                #pl_5 = App.Placement(App.Vector(oripl_X+boundBoxLX,oripl_Y,oripl_Z), App.Rotation(90,0.0,90))
                pl_5 = adjustedGlobalPlacement(objs[0], boundBoxLocation+App.Vector(boundBoxLX,0,0)).multiply(App.Placement(App.Vector(0.,0.,0.),App.Rotation(90,0.0,90)))
                double = Draft.makeRectangle(length=boundBoxLY,height=boundBoxLZ,placement=pl_5,face=False,support=None) #Ok
                double.Label = nameLabel + "_BoundBoxRectangle_Ri"
                FreeCADGui.activeDocument().activeObject().LineColor = (red, green, blue)
                conteneurRectangle.addObject(double)
    #            else:
    #                App.Console.PrintError("not value 5"+"\n")
    
            if createDim == 1:    # section create dimension info
                #YZ-> XY
                pl_0C1 = Draft.make_text([str(round(boundBoxLY,arondi))],placement=pl_5.multVec(App.Vector(boundBoxLY/2, 0, 0)))
                pl_0C1.ViewObject.Justification = JustificationText
                pl_0C1.ViewObject.TextColor     = (TextColorText_R, TextColorText_G, TextColorText_B)
                pl_0C1.ViewObject.FontSize      = FontSizeText
                pl_0C1.Label      = nameLabel + "_Rectangle_Ri_5Y_" + str(round(boundBoxLY,arondi))
                conteneurInfo.addObject(pl_0C1)
        
                pl_0C2 = Draft.make_text([str(round(boundBoxLZ,arondi))],placement=pl_5.multVec(App.Vector(0, boundBoxLZ/2, 0 )))
                pl_0C2.ViewObject.DisplayMode   = DisplayModeText
                pl_0C2.ViewObject.Justification = JustificationText
                pl_0C2.ViewObject.TextColor     = (TextColorText_R, TextColorText_G, TextColorText_B)
                pl_0C2.ViewObject.FontSize      = FontSizeText
                pl_0C2.Label      = nameLabel + "_Rectangle_Ri_5Z_" + str(round(boundBoxLZ,arondi))
                conteneurInfo.addObject(pl_0C2)
    
        except:
            App.Console.PrintError("not done 5"+"\n")
    
        #####
        App.ActiveDocument.recompute()
    except Exception:
        App.Console.PrintError("Bad selection"+"\n")
else:
    App.Console.PrintMessage("Select an object !"+"\n")
There was one test in your code that didn't end up in my control flow - I wasn't sure what it was for.

Code: Select all

 if objs[0].getParentGeoFeatureGroup() == None:
My test model was not complicated, so you might want to try it on yours.

It's in a git archive on my computer, I can push it to github if that is more convenient for you.

Aloha Ed
Post Reply