Macro SketchUnmap

From FreeCAD Documentation
Revision as of 11:02, 10 June 2019 by OpenBrain (talk | contribs) (Page creation)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)

SketchUnmap

Description
This macro resets a sketch placement to an absolute one, eventually creating a datum plane

Macro version: 0.6
Last modified: 2019-06-10
FreeCAD version: 0.17+
Author: OpenBrain
Author
OpenBrain
Download
None
Links
Macro Version
0.6
Date last modified
2019-06-10
FreeCAD Version(s)
0.17+
Default shortcut
None
See also
None

This page is under construction

Description

Context

This macro has been written mainly to circumvent Topological Naming Issue that can break a model when a sketch has been directly or indirectly attached to a face or any other topological item. To prevent breakage, macro shall be applied when the model is still right. It can't "repair" a broken model. If you just break your model, undo the last change(s) back to a good situation, apply the macro to the unstable sketch(es) then redo the previous operation.

Usage

Functionally, the macro will remove the current mapping of the sketch on which it is applied, then apply to it an absolute placement so it is immune to mapping support change.

To do so, the macro will basically propose 3 options (if your sketch isn't in a PartDesign Body, only first option is available and will be applied automatically) :

  • "Raw" mode => the sketch placement is made absolute in the body referential, nothing more
  • "DP@Face mode" => a datum plane is created where the mapping face is, then the sketch is attached to it respecting its attachment offset
  • "DP@Sketch" mode => a datum place is created where the sketch is (including attachment offset), then the sketch is attached to its origin

To use the macro, just select the target sketch (eg. in the tree view) then run the macro. That's it !

Details

For better understanding, below is an example : Let's suppose a simple cube whose top (yellow) face has been drafted. A cylinder is created with a padded circle whose sketch has been mapped (Flat face) to the drafted face and offset to match needs (Attachment offset) :


Now for some reason, you need to revert the pull direction of the draft (of course without the cylinder to move). Here is what basically happen :

The treeview shows an error, the 3D view isn't updated, and the circle sketch is floating in the middle of nowhere...

Now comes the job of the macro (that you need to run before changing the reference face, when the sketch is still at its right place). Select the sketch and run it. If your sketch is in a body, a message box will ask to choose among the 3 different options (if your sketch is out of a body, it will automatically apply the 1st one) :

  • "Raw" mode
  • "DP@Face mode"
  • "DP@Sketch" mode

Which in term of picture gives the following :

Script

Limitations

  • Only process one sketch at a time
  • Only work on sketch objects

Forum discussion

For any feedback (bug, feature request, comments, ...), please use this forum thread : https://forum.freecadweb.org/viewtopic.php?f=22&t=36078

Code

#!/usr/bin/python
#####################################
# Copyright (c) openBrain 2019
# Licensed under LGPL v2
#
# This macro will unmap a sketch from eg. a face and makes its placement absolute in the body. It proposes 3 options (forcely the first if sketch not in a body) :
# * "Raw" mode => the sketch placement is made absolute in the body referential, nothing more
# * "DP@Face mode" => a datum plane is created where the mapping face is, then the sketch is attached to it respecting its attachment offset
# * "DP@Sketch" mode => a datum place is created where the sketch is (including attachment offset), then the sketch is attached to its origin
#
# Main use of the macro is to make design more robust to taopological naming issue
#
# Version history :
# *0.5 : beta release
#
#####################################

__title__   = "Unmap a sketch & makes its placement absolute"
__author__  = "openBrain"
__license__ = "LGPL v2"
__version__ = "0.5" # Ready for beta test
__date__    = "2019.05"

__dbg__ = False  #True for debugging

from PySide import QtGui

def cslM(msg):
    FreeCAD.Console.PrintMessage('\n')
    FreeCAD.Console.PrintMessage(msg)

def cslW(msg):
    FreeCAD.Console.PrintMessage('\n')
    FreeCAD.Console.PrintWarning(msg)

def cslE(msg):
    FreeCAD.Console.PrintMessage('\n')
    FreeCAD.Console.PrintError(msg)

def cslD(msg):
    if __dbg__:
        FreeCAD.Console.PrintMessage('\n')
        FreeCAD.Console.PrintMessage("Debug : " + str(msg))

_0Vec_ = FreeCAD.Vector(0, 0, 0)
_ZVec_ = FreeCAD.Vector(0, 0, 1)

if __dbg__:  ##Clear report view in debug mode
    FreeCADGui.getMainWindow().findChild(QtGui.QTextEdit, "Report view").clear()

cslM("Starting Unmap Sketch macro")
cslD("Checking selection")

if (len(Gui.Selection.getSelection()) != 1 or str(Gui.Selection.getSelection()[0]) != '<Sketcher::SketchObject>'):
    cslE("You must select a sketch that you want to unmap (and only one) ... Exiting")
else:
    cslD("Selection OK")
    App.ActiveDocument.openTransaction("Unmap sketch")
    sk = Gui.Selection.getSelection()[0]
    skNatPl = sk.Placement
    skNatAO = sk.AttachmentOffset
    skInBody = False
    for obj in sk.InList:
        if obj.TypeId == 'PartDesign::Body':
            skInBody = True
            skBody = obj
    cslD("Sketch in a body : " + str(skInBody))
    msgb = QtGui.QMessageBox()
    msgb.setWindowTitle("Unmap Sketch : Mode selection")
    msgb.setText("""Choose which unmapping mode you want to apply :
    Raw => the sketch placement is made absolute in the body referential, nothing more
    DP@Face => a datum plane is created where the mapping face is, then the sketch is attached to it respecting its attachment offset
    DP@Sketch => a datum place is created where the sketch is (including attachment offset), then the sketch is attached to its origin
        Click 'Cancel' to cancel operation""")
    msgb.setIcon(QtGui.QMessageBox.Question)
    rbut = msgb.addButton("Raw", QtGui.QMessageBox.AcceptRole)
    fbut = msgb.addButton("DP@Face", QtGui.QMessageBox.AcceptRole)
    sbut = msgb.addButton("DP@Sketch", QtGui.QMessageBox.AcceptRole)
    cbut = msgb.addButton("Cancel", QtGui.QMessageBox.RejectRole)
    if skInBody:
        msgb.exec_()
        msgbRep = msgb.clickedButton()
    else:
        msgbRep = rbut
    if msgbRep == rbut:
        sk.Support = None
        sk.MapMode = 'Deactivated'
    elif msgbRep == fbut:
        newDP = skBody.newObject('PartDesign::Plane','DP' + sk.Name)
        if sk.Label != sk.Name:
            newDP.Label = 'DP' + sk.Label
        newDP.Support = None
        newDP.MapMode = 'Deactivated'
        newDP.Placement = skNatPl.multiply(skNatAO.inverse())
        sk.Support = [(newDP,'')]
    elif  msgbRep == sbut:
        newDP = skBody.newObject('PartDesign::Plane','DP' + sk.Name)
        if sk.Label != sk.Name:
            newDP.Label = 'DP' + sk.Label
        newDP.Support = None
        newDP.MapMode = 'Deactivated'
        newDP.Placement = skNatPl
        sk.Support = [(newDP,'')]
        sk.AttachmentOffset = App.Placement(_0Vec_, App.Rotation(_ZVec_, 0))
    App.ActiveDocument.commitTransaction()
    cslM("Unmap Sketch Macro ended correctly")