Macro clone explicit/de

Makro Expliziter Klon

Beschreibung
Erstellt eine Kopie jedes ausgewählten Objekts und legt dessen Eigenschaften auf einen Ausdruck fest, der mit dem Originalobjekt verknüpft ist, wodurch es zu einem expliziten und bearbeitbaren Klon wird.

Versionsmakro : 0.1
Datum der letzten Änderung : 2018-12-15
FreeCAD version : 18 und später
Herunterladen : Werkzeugleisten-Symbol
Autor: Raph82
Autor
Raph82
Herunterladen
Werkzeugleisten-Symbol
Links
Macro-Version
0.1
Datum der letzten Änderung
2018-12-15
FreeCAD-Version(s)
18 und später
Standardverknüpfung
None
Siehe auch
Ausdrücke

Beschreibung

Dieses Makro erstellt eine Kopie jedes ausgewählten Objekts und setzt dessen Eigenschaften auf einen Ausdruck, der mit dem Originalobjekt verknüpft ist, wodurch es zu einem expliziten und bearbeitbaren Klon wird.

Dieser Klon ist eine Kopie des Originalobjekts, wie im Befehl Bearbeiten → Auswahl duplizieren, aber seine Eigenschaften werden durch Ausdrücke definiert.

Wie unterscheidet sich dieser „explizite und bearbeitbare Klon” von einem Klonobjekt?

„Explizit“, weil alle ursprünglichen Objekteigenschaften sichtbar sind. Kannst du beispielsweise in einem Klonobjekt eines Würfels dessen Höhe sehen? Wenn du einen Ausdruck für ein Klonobjekt verwendest, kannst du dann einfach auf dessen übergeordnete Eigenschaften zugreifen?

„Bearbeitbar“, weil Sie im Gegensatz zu einem Klonobjekt den Ausdruck jeder Eigenschaft bearbeiten können. So ist es möglich, dass das Objekt nur bestimmte Eigenschaften seines übergeordneten Objekts klont, während man die anderen ändert.

Anwendung

  1. Wähle mindestens ein Objekt.
  2. Makro → Makros...
  3. Aus der Liste clone_explicit.FCMacro auswählen.
  4. Die Schaltfläche Ausführen drücken.

Skript

Werkzeugleistensymbol

Macro_clone_explicit.FCMacro

__Title__ = "clone_explicit"
__Author__ = "Raph82"
__URL__     = "https://freecad.org/index-fr.html"
__Version__ = "0.1"
__Date__    = "2018-12-15" #YYYY-MM-DD
__Comment__ = "This macro creates a copy of the selected objects and sets their properties to an expression linking to the original object, making it an explicit and editable clone"
__Web__ = "https://freecad.org/"
__Wiki__ = "https://wiki.freecad.org/index.php?title=Macro_clone_explicit"
__Icon__  = "https://wiki.freecad.org/images/a/ab/Macro_clone_explicit.png"
__IconW__  = "C:/Users/User Name/AppData/Roaming/FreeCAD/Macro_clone_explicit.png"
__Help__ = "Select at least one object and run the macro to make explicit and editable clone(s)"
__Status__ = "dev"
__Requires__ = "All FreeCAD"
__Communication__ = "https://wiki.freecad.org/index.php?title=User:raph82"

#IMPORTS:
import sys

##################################################
def set_expression(obj, property_to_set, expression):
    """"""
    try:
        print type(obj)
        obj.setExpression(property_to_set, expression)
#    except 'Base.FreeCADError':
    except Exception as detail:
        print detail
        print type(detail)
        if detail['swhat'] == 'Property not found':
            App.Console.PrintMessage('Object "{obj}" has no property "{prop}"\r\n'.format(obj=obj.Name, prop=property_to_set))
        else:
            raise

##################################################
def clone_explicit(mode):
    """Copy the selected objects and sets their properties to an expression, making it an explicit and editable clone.

     This clone is called "explicit and editable" because the link with its parent is visible and can be changed in the object properties.

     The link to the original object can be either "direct" or "transient", depending on the mode argument:
     - a direct clone has expressions pointing to its parent: clone.Length = parent.Length
     - a transient clone has expressions pointing to its ancestor. Say parent.Length = Box001.Length. With a transient clone, clone.Length = Box001.Length, whereas with a direct clone, clone.Length = parent.Length.
       This indirect link to Box001 (via the parent object) could be severed, accidentally or not, depending on what relationship you're looking for.

     If you're lost, try with a direct clone first."""

    App.Console.PrintMessage("Start of clone_explicit macro"+"\r\n")

    #Current selection check:
    sel = FreeCADGui.Selection.getSelection()

    App.Console.PrintMessage(str(len(sel))+" object(s) selected\r\n")
    if len(sel) != 0:
        for i in range(len(sel)):
            obj=sel[i]

            #copying current object:
            App.Console.PrintMessage('Copying "'+obj.Label+'" ('+obj.Name+')\r\n')
            obj_copy=App.ActiveDocument.copyObject(obj, False) #https://freecad.org/api/d8/d3e/classApp_1_1Document.html#a08f1d7d90f4a7276a02918fb6445a04a
            App.Console.PrintMessage('"'+obj_copy.Label+'" ('+obj_copy.Name+') created\r\n')

            if mode == 'direct':
                #defining expressions pointing to the original object:
                set_expression(obj_copy, 'Placement.Base.x',          obj.Name+u'.Placement.Base.x')
                set_expression(obj_copy, 'Placement.Base.y',          obj.Name+u'.Placement.Base.y')
                set_expression(obj_copy, 'Placement.Base.z',          obj.Name+u'.Placement.Base.z')
                set_expression(obj_copy, 'Placement.Rotation.Angle',  obj.Name+u'.Placement.Rotation.Angle')
                set_expression(obj_copy, 'Placement.Rotation.Axis.x', obj.Name+u'.Placement.Rotation.Axis.x')
                set_expression(obj_copy, 'Placement.Rotation.Axis.y', obj.Name+u'.Placement.Rotation.Axis.y')
                set_expression(obj_copy, 'Placement.Rotation.Axis.z', obj.Name+u'.Placement.Rotation.Axis.z')
                set_expression(obj_copy, 'Length',                    obj.Name+u'.Length')
                set_expression(obj_copy, 'Width',                     obj.Name+u'.Width')
                set_expression(obj_copy, 'Height',                    obj.Name+u'.Height')

            elif mode == 'transient':
                #defining expressions pointing to the utmost original object:
                define_transient_expression(obj, obj_copy, 'Placement.Base.x')
                define_transient_expression(obj, obj_copy, 'Placement.Base.y')
                define_transient_expression(obj, obj_copy, 'Placement.Base.z')
                define_transient_expression(obj, obj_copy, 'Placement.Rotation.Angle')
                define_transient_expression(obj, obj_copy, 'Placement.Rotation.Axis.x')
                define_transient_expression(obj, obj_copy, 'Placement.Rotation.Axis.y')
                define_transient_expression(obj, obj_copy, 'Placement.Rotation.Axis.z')
                define_transient_expression(obj, obj_copy, 'Length')
                define_transient_expression(obj, obj_copy, 'Width')
                define_transient_expression(obj, obj_copy, 'Height')
            else:
                App.Console.PrintError('Programming error: mode value not recognized.\r\n')

            App.Console.PrintMessage('('+obj_copy.Label+'" ('+obj_copy.Name+') expressions set\r\n')

        FreeCAD.ActiveDocument.recompute()
        App.Console.PrintMessage('End of clone_explicit macro\r\n')

    else:
        App.Console.PrintError('Select at least one object first\r\n')

    sel = ""
    obj = ""
    obj_copy = ""

##################################################
def find_expression(source_object, property_to_define):
    """"""

    for var_tuple in source_object.ExpressionEngine: #https://forum.freecad.org/viewtopic.php?f=22&t=21950
        # .ExpressionEngine returns tuple like [('Placement.Base.z', 'Length')], see https://docs.python.org/2.7/tutorial/datastructures.html#tuples-and-sequences
        App.Console.PrintMessage('var_tuple[0]='+var_tuple[0]+'\r\n')
        if var_tuple[0] == property_to_define:
           return var_tuple[1]

##################################################
def define_transient_expression(source_object, target_object, property_to_define):
    """"""
    expressions = source_object.ExpressionEngine #https://forum.freecad.org/viewtopic.php?f=22&t=21950
    # returns tuple like [('Placement.Base.z', 'Length')], see https://docs.python.org/2.7/tutorial/datastructures.html#tuples-and-sequences

    expression = find_expression(source_object, property_to_define)
    if expression != None:
#        App.Console.PrintMessage("target_object.Name="+target_object.Name+"\r\n")
#        App.Console.PrintMessage("property_to_define="+property_to_define+"\r\n")
#        App.Console.PrintMessage("expressions[property_to_define]="+expressions[property_to_define]+"\r\n")

        set_expression(target_object, property_to_define, expression)
    else:
        set_expression(target_object, property_to_define, source_object.Name+'.'+property_to_define)

    expressions = ""

##################################################
clone_explicit('direct')
#clone_explicit('transient')

Optionen

Eine Modus-Option war geplant. Ist aber noch nicht implementiert. Es scheint nun viel komplexer zu sein als ursprünglich angenommen, vielleicht zu komplex, als dass ich es umsetzen könnte.

Die Idee dahinter ist, dass man eines von zwei Verhaltensweisen bevorzugen könnte:

Beachten Sie die Betonung des Wortes „Ausdrücke”. Ein Ausdruck ist eine Abstraktionsebene über einem Wert.

Hier ein Beispiel: Man Stelle sich vor, das übergeordnete Objekt (das vor dem Ausführen des Makros auswählt wird) hat seine Eigenschaft Height auf den Ausdruck Object3.Height * 2 gesetzt.

Derzeit wird das Makro mit dem Modusparameter direct ausgeführt, und dem Benutzer wird keine Auswahlmöglichkeit angeboten.

Einschränkungen

Versionsverlauf