From ac6cf98c9873866d27f1997de4de28033ac3c8e3 Mon Sep 17 00:00:00 2001 From: yorikvanhavre Date: Mon, 17 Oct 2011 17:29:18 +0000 Subject: [PATCH] + standardized indentation inside Draft files to 4 git-svn-id: https://free-cad.svn.sourceforge.net/svnroot/free-cad/trunk@5034 e8eeb9e2-ec13-0410-a4a9-efa5cf37419d --- src/Mod/Draft/Draft.py | 3595 ++++++++-------- src/Mod/Draft/InitGui.py | 372 +- src/Mod/Draft/draftGui.py | 1775 ++++---- src/Mod/Draft/draftTools.py | 7981 ++++++++++++++++++----------------- 4 files changed, 6910 insertions(+), 6813 deletions(-) diff --git a/src/Mod/Draft/Draft.py b/src/Mod/Draft/Draft.py index 1d9b9ac59..ceb67df1d 100644 --- a/src/Mod/Draft/Draft.py +++ b/src/Mod/Draft/Draft.py @@ -30,45 +30,45 @@ __url__ = "http://free-cad.sourceforge.net" ''' General description: - The Draft module is a FreeCAD module for drawing/editing 2D entities. - The aim is to give FreeCAD basic 2D-CAD capabilities (similar - to Autocad and other similar software). This modules is made to be run - inside FreeCAD and needs the PyQt4 and pivy modules available. + The Draft module is a FreeCAD module for drawing/editing 2D entities. + The aim is to give FreeCAD basic 2D-CAD capabilities (similar + to Autocad and other similar software). This modules is made to be run + inside FreeCAD and needs the PyQt4 and pivy modules available. User manual: - http://sourceforge.net/apps/mediawiki/free-cad/index.php?title=2d_Drafting_Module + http://sourceforge.net/apps/mediawiki/free-cad/index.php?title=2d_Drafting_Module How it works / how to extend: - This module is written entirely in python. If you know a bit of python - language, you are welcome to modify this module or to help us to improve it. - Suggestions are also welcome on the FreeCAD discussion forum. + This module is written entirely in python. If you know a bit of python + language, you are welcome to modify this module or to help us to improve it. + Suggestions are also welcome on the FreeCAD discussion forum. + + If you want to have a look at the code, here is a general explanation. The + Draft module is divided in several files: - If you want to have a look at the code, here is a general explanation. The - Draft module is divided in several files: - - - Draft.py: Hosts the functions that are useful for scripting outside of - the Draft module, it is the "Draft API" - - draftGui.py: Creates and manages the special Draft toolbar - - draftTools.py: Contains the user tools of the Draft module (the commands - from the Draft menu), and a couple of helpers such as the "Trackers" - (temporary geometry used while drawing) - - draftlibs/fcvec.py: a vector math library, contains functions that are not - implemented in the standard FreeCAD vector - - draftlibs/fcgeo.py: a library of misc functions to manipulate shapes. + - Draft.py: Hosts the functions that are useful for scripting outside of + the Draft module, it is the "Draft API" + - draftGui.py: Creates and manages the special Draft toolbar + - draftTools.py: Contains the user tools of the Draft module (the commands + from the Draft menu), and a couple of helpers such as the "Trackers" + (temporary geometry used while drawing) + - draftlibs/fcvec.py: a vector math library, contains functions that are not + implemented in the standard FreeCAD vector + - draftlibs/fcgeo.py: a library of misc functions to manipulate shapes. - The Draft.py contains everything to create geometry in the scene. You - should start there if you intend to modify something. Then, the draftTools - are where the FreeCAD commands are defined, while in draftGui.py - you have the ui part, ie. the draft command bar. Both draftTools and - draftGui are loaded at module init by InitGui.py, which is called directly by FreeCAD. - The tools all have an Activated() function, which is called by FreeCAD when the - corresponding FreeCAD command is invoked. Most tools then create the trackers they - will need during operation, then place a callback mechanism, which will detect - user input and do the necessary cad operations. They also send commands to the - command bar, which will display the appropriate controls. While the scene event - callback watches mouse events, the keyboard is being watched by the command bar. + The Draft.py contains everything to create geometry in the scene. You + should start there if you intend to modify something. Then, the draftTools + are where the FreeCAD commands are defined, while in draftGui.py + you have the ui part, ie. the draft command bar. Both draftTools and + draftGui are loaded at module init by InitGui.py, which is called directly by FreeCAD. + The tools all have an Activated() function, which is called by FreeCAD when the + corresponding FreeCAD command is invoked. Most tools then create the trackers they + will need during operation, then place a callback mechanism, which will detect + user input and do the necessary cad operations. They also send commands to the + command bar, which will display the appropriate controls. While the scene event + callback watches mouse events, the keyboard is being watched by the command bar. ''' # import FreeCAD modules @@ -83,1573 +83,1572 @@ from pivy import coin #--------------------------------------------------------------------------- def typecheck (args_and_types, name="?"): - "typecheck([arg1,type),(arg2,type),...]): checks arguments types" - for v,t in args_and_types: - if not isinstance (v,t): - w = "typecheck[" + str(name) + "]: " - w += str(v) + " is not " + str(t) + "\n" - FreeCAD.Console.PrintWarning(w) - raise TypeError("Draft." + str(name)) + "typecheck([arg1,type),(arg2,type),...]): checks arguments types" + for v,t in args_and_types: + if not isinstance (v,t): + w = "typecheck[" + str(name) + "]: " + w += str(v) + " is not " + str(t) + "\n" + FreeCAD.Console.PrintWarning(w) + raise TypeError("Draft." + str(name)) def getParamType(param): - if param in ["dimsymbol","dimPrecision","dimorientation","precision","defaultWP", - "snapRange","gridEvery","linewidth","UiMode","modconstrain","modsnap", - "modalt"]: - return "int" - elif param in ["constructiongroupname","textfont","patternFile","template"]: - return "string" - elif param in ["textheight","tolerance","gridSpacing"]: - return "float" - elif param in ["selectBaseObjects","alwaysSnap","grid","fillmode","saveonexit"]: - return "bool" - elif param in ["color","constructioncolor","snapcolor"]: - return "unsigned" - else: - return None + if param in ["dimsymbol","dimPrecision","dimorientation","precision","defaultWP", + "snapRange","gridEvery","linewidth","UiMode","modconstrain","modsnap", + "modalt"]: + return "int" + elif param in ["constructiongroupname","textfont","patternFile","template"]: + return "string" + elif param in ["textheight","tolerance","gridSpacing"]: + return "float" + elif param in ["selectBaseObjects","alwaysSnap","grid","fillmode","saveonexit"]: + return "bool" + elif param in ["color","constructioncolor","snapcolor"]: + return "unsigned" + else: + return None def getParam(param): - "getParam(parameterName): returns a Draft parameter value from the current config" - p = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Draft") - t = getParamType(param) - if t == "int": return p.GetInt(param) - elif t == "string": return p.GetString(param) - elif t == "float": return p.GetFloat(param) - elif t == "bool": return p.GetBool(param) - elif t == "unsigned": return p.GetUnsigned(param) - else: return None + "getParam(parameterName): returns a Draft parameter value from the current config" + p = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Draft") + t = getParamType(param) + if t == "int": return p.GetInt(param) + elif t == "string": return p.GetString(param) + elif t == "float": return p.GetFloat(param) + elif t == "bool": return p.GetBool(param) + elif t == "unsigned": return p.GetUnsigned(param) + else: return None def setParam(param,value): - "setParam(parameterName,value): sets a Draft parameter with the given value" - p = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Draft") - t = getParamType(param) - if t == "int": p.SetInt(param,value) - elif t == "string": p.SetString(param,value) - elif t == "float": p.SetFloat(param,value) - elif t == "bool": p.SetBool(param,value) - elif t == "unsigned": p.SetUnsigned(param,value) + "setParam(parameterName,value): sets a Draft parameter with the given value" + p = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Draft") + t = getParamType(param) + if t == "int": p.SetInt(param,value) + elif t == "string": p.SetString(param,value) + elif t == "float": p.SetFloat(param,value) + elif t == "bool": p.SetBool(param,value) + elif t == "unsigned": p.SetUnsigned(param,value) def precision(): - "precision(): returns the precision value from Draft user settings" - return getParam("precision") + "precision(): returns the precision value from Draft user settings" + return getParam("precision") def tolerance(): - "tolerance(): returns the tolerance value from Draft user settings" - return getParam("tolerance") + "tolerance(): returns the tolerance value from Draft user settings" + return getParam("tolerance") def getRealName(name): - "getRealName(string): strips the trailing numbers from a string name" - for i in range(1,len(name)): - if not name[-i] in '1234567890': - return name[:len(name)-(i-1)] - return name + "getRealName(string): strips the trailing numbers from a string name" + for i in range(1,len(name)): + if not name[-i] in '1234567890': + return name[:len(name)-(i-1)] + return name def getType(obj): - "getType(object): returns the Draft type of the given object" - if "Proxy" in obj.PropertiesList: - if hasattr(obj.Proxy,"Type"): - return obj.Proxy.Type - if obj.isDerivedFrom("Part::Feature"): - return "Part" - if (obj.Type == "App::Annotation"): - return "Annotation" - if obj.isDerivedFrom("Mesh::Feature"): - return "Mesh" - if (obj.Type == "App::DocumentObjectGroup"): - return "Group" - return "Unknown" + "getType(object): returns the Draft type of the given object" + if "Proxy" in obj.PropertiesList: + if hasattr(obj.Proxy,"Type"): + return obj.Proxy.Type + if obj.isDerivedFrom("Part::Feature"): + return "Part" + if (obj.Type == "App::Annotation"): + return "Annotation" + if obj.isDerivedFrom("Mesh::Feature"): + return "Mesh" + if (obj.Type == "App::DocumentObjectGroup"): + return "Group" + return "Unknown" def getGroupNames(): - "returns a list of existing groups in the document" - glist = [] - doc = FreeCAD.ActiveDocument - for obj in doc.Objects: - if obj.Type == "App::DocumentObjectGroup": - glist.append(obj.Name) - return glist + "returns a list of existing groups in the document" + glist = [] + doc = FreeCAD.ActiveDocument + for obj in doc.Objects: + if obj.Type == "App::DocumentObjectGroup": + glist.append(obj.Name) + return glist def ungroup(obj): - "removes the current object from any group it belongs to" - for g in getGroupNames(): - grp = FreeCAD.ActiveDocument.getObject(g) - if grp.hasObject(obj): - grp.removeObject(obj) + "removes the current object from any group it belongs to" + for g in getGroupNames(): + grp = FreeCAD.ActiveDocument.getObject(g) + if grp.hasObject(obj): + grp.removeObject(obj) def dimSymbol(): - "returns the current dim symbol from the preferences as a pivy SoMarkerSet" - s = getParam("dimsymbol") - marker = coin.SoMarkerSet() - if s == 0: marker.markerIndex = coin.SoMarkerSet.CIRCLE_FILLED_5_5 - elif s == 1: marker.markerIndex = coin.SoMarkerSet.CIRCLE_FILLED_7_7 - elif s == 2: marker.markerIndex = coin.SoMarkerSet.CIRCLE_FILLED_9_9 - elif s == 3: marker.markerIndex = coin.SoMarkerSet.CIRCLE_LINE_5_5 - elif s == 4: marker.markerIndex = coin.SoMarkerSet.CIRCLE_LINE_7_7 - elif s == 5: marker.markerIndex = coin.SoMarkerSet.CIRCLE_LINE_9_9 - elif s == 6: marker.markerIndex = coin.SoMarkerSet.SLASH_5_5 - elif s == 7: marker.markerIndex = coin.SoMarkerSet.SLASH_7_7 - elif s == 8: marker.markerIndex = coin.SoMarkerSet.SLASH_9_9 - elif s == 9: marker.markerIndex = coin.SoMarkerSet.BACKSLASH_5_5 - elif s == 10: marker.markerIndex = coin.SoMarkerSet.BACKSLASH_7_7 - elif s == 11: marker.markerIndex = coin.SoMarkerSet.BACKSLASH_9_9 - return marker + "returns the current dim symbol from the preferences as a pivy SoMarkerSet" + s = getParam("dimsymbol") + marker = coin.SoMarkerSet() + if s == 0: marker.markerIndex = coin.SoMarkerSet.CIRCLE_FILLED_5_5 + elif s == 1: marker.markerIndex = coin.SoMarkerSet.CIRCLE_FILLED_7_7 + elif s == 2: marker.markerIndex = coin.SoMarkerSet.CIRCLE_FILLED_9_9 + elif s == 3: marker.markerIndex = coin.SoMarkerSet.CIRCLE_LINE_5_5 + elif s == 4: marker.markerIndex = coin.SoMarkerSet.CIRCLE_LINE_7_7 + elif s == 5: marker.markerIndex = coin.SoMarkerSet.CIRCLE_LINE_9_9 + elif s == 6: marker.markerIndex = coin.SoMarkerSet.SLASH_5_5 + elif s == 7: marker.markerIndex = coin.SoMarkerSet.SLASH_7_7 + elif s == 8: marker.markerIndex = coin.SoMarkerSet.SLASH_9_9 + elif s == 9: marker.markerIndex = coin.SoMarkerSet.BACKSLASH_5_5 + elif s == 10: marker.markerIndex = coin.SoMarkerSet.BACKSLASH_7_7 + elif s == 11: marker.markerIndex = coin.SoMarkerSet.BACKSLASH_9_9 + return marker def shapify(obj): - '''shapify(object): transforms a parametric shape object into - non-parametric and returns the new object''' - if not (obj.isDerivedFrom("Part::Feature")): return None - if not "Shape" in obj.PropertiesList: return None - if obj.Type == "Part::Feature": return obj - shape = obj.Shape - name = getRealName(obj.Name) - FreeCAD.ActiveDocument.removeObject(obj.Name) - newobj = FreeCAD.ActiveDocument.addObject("Part::Feature",name) - newobj.Shape = shape - FreeCAD.ActiveDocument.recompute() - return newobj + '''shapify(object): transforms a parametric shape object into + non-parametric and returns the new object''' + if not (obj.isDerivedFrom("Part::Feature")): return None + if not "Shape" in obj.PropertiesList: return None + if obj.Type == "Part::Feature": return obj + shape = obj.Shape + name = getRealName(obj.Name) + FreeCAD.ActiveDocument.removeObject(obj.Name) + newobj = FreeCAD.ActiveDocument.addObject("Part::Feature",name) + newobj.Shape = shape + FreeCAD.ActiveDocument.recompute() + return newobj def getGroupContents(objectslist): - '''getGroupContents(objectlist): if any object of the given list - is a group, its content is appened to the list, which is returned''' - newlist = [] - for obj in objectslist: - if obj.Type == "App::DocumentObjectGroup": - newlist.extend(getGroupContents(obj.Group)) - else: - newlist.append(obj) - return newlist + '''getGroupContents(objectlist): if any object of the given list + is a group, its content is appened to the list, which is returned''' + newlist = [] + for obj in objectslist: + if obj.Type == "App::DocumentObjectGroup": + newlist.extend(getGroupContents(obj.Group)) + else: + newlist.append(obj) + return newlist def formatObject(target,origin=None): - ''' - formatObject(targetObject,[originObject]): This function applies - to the given target object the current properties - set on the toolbar (line color and line width), - or copies the properties of another object if given as origin. - It also places the object in construction group if needed. - ''' - obrep = target.ViewObject - ui = FreeCADGui.draftToolBar - doc = FreeCAD.ActiveDocument - if ui.isConstructionMode(): - col = fcol = ui.getDefaultColor("constr") - gname = getParam("constructiongroupname") - if gname: - grp = doc.getObject(gname) - if not grp: grp = doc.addObject("App::DocumentObjectGroup",gname) - grp.addObject(target) - obrep.Transparency = 80 - else: - col = ui.getDefaultColor("ui") - fcol = ui.getDefaultColor("face") - col = (float(col[0]),float(col[1]),float(col[2]),0.0) - fcol = (float(fcol[0]),float(fcol[1]),float(fcol[2]),0.0) - lw = ui.linewidth - fs = ui.fontsize - if not origin: - if "FontSize" in obrep.PropertiesList: obrep.FontSize = fs - if "TextColor" in obrep.PropertiesList: obrep.TextColor = col - if "LineWidth" in obrep.PropertiesList: obrep.LineWidth = lw - if "PointColor" in obrep.PropertiesList: obrep.PointColor = col - if "LineColor" in obrep.PropertiesList: obrep.LineColor = col - if "ShapeColor" in obrep.PropertiesList: obrep.ShapeColor = fcol - else: - matchrep = origin.ViewObject - if ("LineWidth" in obrep.PropertiesList) and \ - ("LineWidth" in matchrep.PropertiesList): - obrep.LineWidth = matchrep.LineWidth - if ("PointColor" in obrep.PropertiesList) and \ - ("PointColor" in matchrep.PropertiesList): - obrep.PointColor = matchrep.PointColor - if ("LineColor" in obrep.PropertiesList) and \ - ("LineColor" in matchrep.PropertiesList): - obrep.LineColor = matchrep.LineColor - if ("ShapeColor" in obrep.PropertiesList) and \ - ("ShapeColor" in matchrep.PropertiesList): - obrep.ShapeColor = matchrep.ShapeColor - if matchrep.DisplayMode in obrep.listDisplayModes(): - obrep.DisplayMode = matchrep.DisplayMode + ''' + formatObject(targetObject,[originObject]): This function applies + to the given target object the current properties + set on the toolbar (line color and line width), + or copies the properties of another object if given as origin. + It also places the object in construction group if needed. + ''' + obrep = target.ViewObject + ui = FreeCADGui.draftToolBar + doc = FreeCAD.ActiveDocument + if ui.isConstructionMode(): + col = fcol = ui.getDefaultColor("constr") + gname = getParam("constructiongroupname") + if gname: + grp = doc.getObject(gname) + if not grp: grp = doc.addObject("App::DocumentObjectGroup",gname) + grp.addObject(target) + obrep.Transparency = 80 + else: + col = ui.getDefaultColor("ui") + fcol = ui.getDefaultColor("face") + col = (float(col[0]),float(col[1]),float(col[2]),0.0) + fcol = (float(fcol[0]),float(fcol[1]),float(fcol[2]),0.0) + lw = ui.linewidth + fs = ui.fontsize + if not origin: + if "FontSize" in obrep.PropertiesList: obrep.FontSize = fs + if "TextColor" in obrep.PropertiesList: obrep.TextColor = col + if "LineWidth" in obrep.PropertiesList: obrep.LineWidth = lw + if "PointColor" in obrep.PropertiesList: obrep.PointColor = col + if "LineColor" in obrep.PropertiesList: obrep.LineColor = col + if "ShapeColor" in obrep.PropertiesList: obrep.ShapeColor = fcol + else: + matchrep = origin.ViewObject + if ("LineWidth" in obrep.PropertiesList) and \ + ("LineWidth" in matchrep.PropertiesList): + obrep.LineWidth = matchrep.LineWidth + if ("PointColor" in obrep.PropertiesList) and \ + ("PointColor" in matchrep.PropertiesList): + obrep.PointColor = matchrep.PointColor + if ("LineColor" in obrep.PropertiesList) and \ + ("LineColor" in matchrep.PropertiesList): + obrep.LineColor = matchrep.LineColor + if ("ShapeColor" in obrep.PropertiesList) and \ + ("ShapeColor" in matchrep.PropertiesList): + obrep.ShapeColor = matchrep.ShapeColor + if matchrep.DisplayMode in obrep.listDisplayModes(): + obrep.DisplayMode = matchrep.DisplayMode def getSelection(): - "getSelection(): returns the current FreeCAD selection" - return FreeCADGui.Selection.getSelection() + "getSelection(): returns the current FreeCAD selection" + return FreeCADGui.Selection.getSelection() def select(objs): - "select(object): deselects everything and selects only the passed object or list" - FreeCADGui.Selection.clearSelection() - if not isinstance(objs,list): - objs = [objs] - for obj in objs: - FreeCADGui.Selection.addSelection(obj) + "select(object): deselects everything and selects only the passed object or list" + FreeCADGui.Selection.clearSelection() + if not isinstance(objs,list): + objs = [objs] + for obj in objs: + FreeCADGui.Selection.addSelection(obj) def makeCircle(radius, placement=None, face=True, startangle=None, endangle=None, support=None): - '''makeCircle(radius,[placement,face,startangle,endangle]): Creates a circle - object with given radius. If placement is given, it is - used. If face is False, the circle is shown as a - wireframe, otherwise as a face. If startangle AND endangle are given - (in degrees), they are used and the object appears as an arc.''' - if placement: typecheck([(placement,FreeCAD.Placement)], "makeCircle") - obj = FreeCAD.ActiveDocument.addObject("Part::Part2DObjectPython","Circle") - Circle(obj) - ViewProviderDraft(obj.ViewObject) - obj.Radius = radius - if not face: obj.ViewObject.DisplayMode = "Wireframe" - if (startangle != None) and (endangle != None): - if startangle == -0: startangle = 0 - obj.FirstAngle = startangle - obj.LastAngle = endangle - obj.Support = support - if placement: obj.Placement = placement - formatObject(obj) - select(obj) - FreeCAD.ActiveDocument.recompute() - return obj - + '''makeCircle(radius,[placement,face,startangle,endangle]): Creates a circle + object with given radius. If placement is given, it is + used. If face is False, the circle is shown as a + wireframe, otherwise as a face. If startangle AND endangle are given + (in degrees), they are used and the object appears as an arc.''' + if placement: typecheck([(placement,FreeCAD.Placement)], "makeCircle") + obj = FreeCAD.ActiveDocument.addObject("Part::Part2DObjectPython","Circle") + Circle(obj) + ViewProviderDraft(obj.ViewObject) + obj.Radius = radius + if not face: obj.ViewObject.DisplayMode = "Wireframe" + if (startangle != None) and (endangle != None): + if startangle == -0: startangle = 0 + obj.FirstAngle = startangle + obj.LastAngle = endangle + obj.Support = support + if placement: obj.Placement = placement + formatObject(obj) + select(obj) + FreeCAD.ActiveDocument.recompute() + return obj + def makeRectangle(length, height, placement=None, face=True, support=None): - '''makeRectangle(length,width,[placement],[face]): Creates a Rectangle - object with length in X direction and height in Y direction. - If a placement is given, it is used. If face is False, the - rectangle is shown as a wireframe, otherwise as a face.''' - if placement: typecheck([(placement,FreeCAD.Placement)], "makeRectangle") - obj = FreeCAD.ActiveDocument.addObject("Part::Part2DObjectPython","Rectangle") - Rectangle(obj) - ViewProviderRectangle(obj.ViewObject) - obj.Length = length - obj.Height = height - obj.Support = support - if not face: obj.ViewObject.DisplayMode = "Wireframe" - if placement: obj.Placement = placement - formatObject(obj) - select(obj) - FreeCAD.ActiveDocument.recompute() - return obj + '''makeRectangle(length,width,[placement],[face]): Creates a Rectangle + object with length in X direction and height in Y direction. + If a placement is given, it is used. If face is False, the + rectangle is shown as a wireframe, otherwise as a face.''' + if placement: typecheck([(placement,FreeCAD.Placement)], "makeRectangle") + obj = FreeCAD.ActiveDocument.addObject("Part::Part2DObjectPython","Rectangle") + Rectangle(obj) + ViewProviderRectangle(obj.ViewObject) + obj.Length = length + obj.Height = height + obj.Support = support + if not face: obj.ViewObject.DisplayMode = "Wireframe" + if placement: obj.Placement = placement + formatObject(obj) + select(obj) + FreeCAD.ActiveDocument.recompute() + return obj def makeDimension(p1,p2,p3=None,p4=None): - '''makeDimension(p1,p2,[p3]) or makeDimension(object,i1,i2,p3) - or makeDimension(objlist,indices,p3): Creates a Dimension object with - the dimension line passign through p3.The current line width and color - will be used. There are multiple ways to create a dimension, depending on - the arguments you pass to it: - - (p1,p2,p3): creates a standard dimension from p1 to p2 - - (object,i1,i2,p3): creates a linked dimension to the given object, - measuring the distance between its vertices indexed i1 and i2 - - (object,i1,mode,p3): creates a linked dimension - to the given object, i1 is the index of the (curved) edge to measure, - and mode is either "radius" or "diameter". - ''' - obj = FreeCAD.ActiveDocument.addObject("App::FeaturePython","Dimension") - Dimension(obj) - ViewProviderDimension(obj.ViewObject) - if isinstance(p1,Vector) and isinstance(p2,Vector): - obj.Start = p1 - obj.End = p2 - elif isinstance(p2,int) and isinstance(p3,int): - obj.Base = p1 - obj.LinkedVertices = [p2,p3] - p3 = p4 - elif isinstance(p3,str): - obj.Base = p1 - if p3 == "radius": - obj.LinkedVertices = [p2,1,1] - obj.ViewObject.Override = "rdim" - elif p3 == "diameter": - obj.LinkedVertices = [p2,2,1] - obj.ViewObject.Override = "ddim" - p3 = p4 - if not p3: - p3 = p2.sub(p1) - p3.multiply(0.5) - p3 = p1.add(p3) - obj.Dimline = p3 - formatObject(obj) - select(obj) - FreeCAD.ActiveDocument.recompute() - return obj + '''makeDimension(p1,p2,[p3]) or makeDimension(object,i1,i2,p3) + or makeDimension(objlist,indices,p3): Creates a Dimension object with + the dimension line passign through p3.The current line width and color + will be used. There are multiple ways to create a dimension, depending on + the arguments you pass to it: + - (p1,p2,p3): creates a standard dimension from p1 to p2 + - (object,i1,i2,p3): creates a linked dimension to the given object, + measuring the distance between its vertices indexed i1 and i2 + - (object,i1,mode,p3): creates a linked dimension + to the given object, i1 is the index of the (curved) edge to measure, + and mode is either "radius" or "diameter". + ''' + obj = FreeCAD.ActiveDocument.addObject("App::FeaturePython","Dimension") + Dimension(obj) + ViewProviderDimension(obj.ViewObject) + if isinstance(p1,Vector) and isinstance(p2,Vector): + obj.Start = p1 + obj.End = p2 + elif isinstance(p2,int) and isinstance(p3,int): + obj.Base = p1 + obj.LinkedVertices = [p2,p3] + p3 = p4 + elif isinstance(p3,str): + obj.Base = p1 + if p3 == "radius": + obj.LinkedVertices = [p2,1,1] + obj.ViewObject.Override = "rdim" + elif p3 == "diameter": + obj.LinkedVertices = [p2,2,1] + obj.ViewObject.Override = "ddim" + p3 = p4 + if not p3: + p3 = p2.sub(p1) + p3.multiply(0.5) + p3 = p1.add(p3) + obj.Dimline = p3 + formatObject(obj) + select(obj) + FreeCAD.ActiveDocument.recompute() + return obj def makeAngularDimension(center,angles,p3): - '''makeAngularDimension(center,[angle1,angle2],p3): creates an angular Dimension - from the given center, with the given list of angles, passing through p3. - ''' - obj = FreeCAD.ActiveDocument.addObject("App::FeaturePython","Dimension") - AngularDimension(obj) - ViewProviderAngularDimension(obj.ViewObject) - obj.Center = center - for a in range(len(angles)): - if angles[a] > 2*math.pi: - angles[a] = angles[a]-(2*math.pi) - obj.FirstAngle = math.degrees(angles[1]) - obj.LastAngle = math.degrees(angles[0]) - obj.Dimline = p3 - formatObject(obj) - select(obj) - FreeCAD.ActiveDocument.recompute() - return obj + '''makeAngularDimension(center,[angle1,angle2],p3): creates an angular Dimension + from the given center, with the given list of angles, passing through p3. + ''' + obj = FreeCAD.ActiveDocument.addObject("App::FeaturePython","Dimension") + AngularDimension(obj) + ViewProviderAngularDimension(obj.ViewObject) + obj.Center = center + for a in range(len(angles)): + if angles[a] > 2*math.pi: + angles[a] = angles[a]-(2*math.pi) + obj.FirstAngle = math.degrees(angles[1]) + obj.LastAngle = math.degrees(angles[0]) + obj.Dimline = p3 + formatObject(obj) + select(obj) + FreeCAD.ActiveDocument.recompute() + return obj def makeWire(pointslist,closed=False,placement=None,face=True,support=None): - '''makeWire(pointslist,[closed],[placement]): Creates a Wire object - from the given list of vectors. If closed is True or first - and last points are identical, the wire is closed. If face is - true (and wire is closed), the wire will appear filled. Instead of - a pointslist, you can also pass a Part Wire.''' - if not isinstance(pointslist,list): - nlist = [] - for v in pointslist.Vertexes: - nlist.append(v.Point) - if fcgeo.isReallyClosed(pointslist): - nlist.append(pointslist.Vertexes[0].Point) - pointslist = nlist - if placement: typecheck([(placement,FreeCAD.Placement)], "makeWire") - if len(pointslist) == 2: fname = "Line" - else: fname = "Wire" - obj = FreeCAD.ActiveDocument.addObject("Part::Part2DObjectPython",fname) - Wire(obj) - ViewProviderWire(obj.ViewObject) - obj.Points = pointslist - obj.Closed = closed - obj.Support = support - if not face: obj.ViewObject.DisplayMode = "Wireframe" - if placement: obj.Placement = placement - formatObject(obj) - select(obj) - FreeCAD.ActiveDocument.recompute() - return obj + '''makeWire(pointslist,[closed],[placement]): Creates a Wire object + from the given list of vectors. If closed is True or first + and last points are identical, the wire is closed. If face is + true (and wire is closed), the wire will appear filled. Instead of + a pointslist, you can also pass a Part Wire.''' + if not isinstance(pointslist,list): + nlist = [] + for v in pointslist.Vertexes: + nlist.append(v.Point) + if fcgeo.isReallyClosed(pointslist): + nlist.append(pointslist.Vertexes[0].Point) + pointslist = nlist + if placement: typecheck([(placement,FreeCAD.Placement)], "makeWire") + if len(pointslist) == 2: fname = "Line" + else: fname = "Wire" + obj = FreeCAD.ActiveDocument.addObject("Part::Part2DObjectPython",fname) + Wire(obj) + ViewProviderWire(obj.ViewObject) + obj.Points = pointslist + obj.Closed = closed + obj.Support = support + if not face: obj.ViewObject.DisplayMode = "Wireframe" + if placement: obj.Placement = placement + formatObject(obj) + select(obj) + FreeCAD.ActiveDocument.recompute() + return obj def makePolygon(nfaces,radius=1,inscribed=True,placement=None,face=True,support=None): - '''makePolgon(nfaces,[radius],[inscribed],[placement],[face]): Creates a - polygon object with the given number of faces and the radius. - if inscribed is False, the polygon is circumscribed around a circle - with the given radius, otherwise it is inscribed. If face is True, - the resulting shape is displayed as a face, otherwise as a wireframe. - ''' - if nfaces < 3: return None - obj = FreeCAD.ActiveDocument.addObject("Part::Part2DObjectPython","Polygon") - Polygon(obj) - ViewProviderDraft(obj.ViewObject) - obj.FacesNumber = nfaces - obj.Radius = radius - if inscribed: - obj.DrawMode = "inscribed" - else: - obj.DrawMode = "circumscribed" - if not face: obj.ViewObject.DisplayMode = "Wireframe" - obj.Support = support - if placement: obj.Placement = placement - formatObject(obj) - select(obj) - FreeCAD.ActiveDocument.recompute() - return obj + '''makePolgon(nfaces,[radius],[inscribed],[placement],[face]): Creates a + polygon object with the given number of faces and the radius. + if inscribed is False, the polygon is circumscribed around a circle + with the given radius, otherwise it is inscribed. If face is True, + the resulting shape is displayed as a face, otherwise as a wireframe. + ''' + if nfaces < 3: return None + obj = FreeCAD.ActiveDocument.addObject("Part::Part2DObjectPython","Polygon") + Polygon(obj) + ViewProviderDraft(obj.ViewObject) + obj.FacesNumber = nfaces + obj.Radius = radius + if inscribed: + obj.DrawMode = "inscribed" + else: + obj.DrawMode = "circumscribed" + if not face: obj.ViewObject.DisplayMode = "Wireframe" + obj.Support = support + if placement: obj.Placement = placement + formatObject(obj) + select(obj) + FreeCAD.ActiveDocument.recompute() + return obj def makeLine(p1,p2): - '''makeLine(p1,p2): Creates a line between p1 and p2.''' - obj = makeWire([p1,p2]) - return obj + '''makeLine(p1,p2): Creates a line between p1 and p2.''' + obj = makeWire([p1,p2]) + return obj def makeBSpline(pointslist,closed=False,placement=None,face=True,support=None): - '''makeBSpline(pointslist,[closed],[placement]): Creates a B-Spline object - from the given list of vectors. If closed is True or first - and last points are identical, the wire is closed. If face is - true (and wire is closed), the wire will appear filled. Instead of - a pointslist, you can also pass a Part Wire.''' - if not isinstance(pointslist,list): - nlist = [] - for v in pointslist.Vertexes: - nlist.append(v.Point) - pointslist = nlist - if placement: typecheck([(placement,FreeCAD.Placement)], "makeBSpline") - if len(pointslist) == 2: fname = "Line" - else: fname = "BSpline" - obj = FreeCAD.ActiveDocument.addObject("Part::Part2DObjectPython",fname) - BSpline(obj) - ViewProviderBSpline(obj.ViewObject) - obj.Points = pointslist - obj.Closed = closed - obj.Support = support - if not face: obj.ViewObject.DisplayMode = "Wireframe" - if placement: obj.Placement = placement - formatObject(obj) - select(obj) - FreeCAD.ActiveDocument.recompute() - return obj + '''makeBSpline(pointslist,[closed],[placement]): Creates a B-Spline object + from the given list of vectors. If closed is True or first + and last points are identical, the wire is closed. If face is + true (and wire is closed), the wire will appear filled. Instead of + a pointslist, you can also pass a Part Wire.''' + if not isinstance(pointslist,list): + nlist = [] + for v in pointslist.Vertexes: + nlist.append(v.Point) + pointslist = nlist + if placement: typecheck([(placement,FreeCAD.Placement)], "makeBSpline") + if len(pointslist) == 2: fname = "Line" + else: fname = "BSpline" + obj = FreeCAD.ActiveDocument.addObject("Part::Part2DObjectPython",fname) + BSpline(obj) + ViewProviderBSpline(obj.ViewObject) + obj.Points = pointslist + obj.Closed = closed + obj.Support = support + if not face: obj.ViewObject.DisplayMode = "Wireframe" + if placement: obj.Placement = placement + formatObject(obj) + select(obj) + FreeCAD.ActiveDocument.recompute() + return obj def makeText(stringslist,point=Vector(0,0,0),screen=False): - '''makeText(strings,[point],[screen]): Creates a Text object at the given point, - containing the strings given in the strings list, one string by line (strings - can also be one single string). The current color and text height and font - specified in preferences are used. - If screen is True, the text always faces the view direction.''' - typecheck([(point,Vector)], "makeText") - if not isinstance(stringslist,list): stringslist = [stringslist] - textbuffer = [] - for l in stringslist: textbuffer.append(unicode(l).encode('utf-8')) - obj=FreeCAD.ActiveDocument.addObject("App::Annotation","Text") - obj.LabelText=textbuffer - obj.Position=point - if not screen: obj.ViewObject.DisplayMode="World" - h = getParam("textheight") - if screen: h = h*10 - obj.ViewObject.FontSize = h - obj.ViewObject.FontName = getParam("textfont") - obj.ViewObject.LineSpacing = 0.6 - formatObject(obj) - select(obj) - return obj + '''makeText(strings,[point],[screen]): Creates a Text object at the given point, + containing the strings given in the strings list, one string by line (strings + can also be one single string). The current color and text height and font + specified in preferences are used. + If screen is True, the text always faces the view direction.''' + typecheck([(point,Vector)], "makeText") + if not isinstance(stringslist,list): stringslist = [stringslist] + textbuffer = [] + for l in stringslist: textbuffer.append(unicode(l).encode('utf-8')) + obj=FreeCAD.ActiveDocument.addObject("App::Annotation","Text") + obj.LabelText=textbuffer + obj.Position=point + if not screen: obj.ViewObject.DisplayMode="World" + h = getParam("textheight") + if screen: h = h*10 + obj.ViewObject.FontSize = h + obj.ViewObject.FontName = getParam("textfont") + obj.ViewObject.LineSpacing = 0.6 + formatObject(obj) + select(obj) + return obj def makeCopy(obj): - '''makeCopy(object): returns an exact copy of an object''' - newobj = FreeCAD.ActiveDocument.addObject(obj.Type,getRealName(obj.Name)) - if getType(obj) == "Rectangle": - Rectangle(newobj) - ViewProviderRectangle(newobj.ViewObject) - elif getType(obj) == "Wire": - Wire(newobj) - ViewProviderWire(newobj.ViewObject) - elif getType(obj) == "Circle": - Circle(newobj) - ViewProviderCircle(newobj.ViewObject) - elif getType(obj) == "Polygon": - Polygon(newobj) - ViewProviderPolygon(newobj.ViewObject) - elif getType(obj) == "BSpline": - BSpline(newobj) - ViewProviderBSpline(newobj.ViewObject) - elif getType(obj) == "Block": - Block(newobj) - ViewProviderBlock(newobj.ViewObject) - elif getType(obj) == "Structure": - import Structure - Structure.Structure(newobj) - Structure.ViewProviderStructure(newobj.ViewObject) - elif getType(obj) == "Wall": - import Wall - Wall.Wall(newobj) - Wall.ViewProviderWall(newobj.ViewObject) - elif obj.isDerivedFrom("Part::Feature"): - newobj.Shape = obj.Shape - else: - print "Error: Object type cannot be copied" - return None - for p in obj.PropertiesList: - if p in newobj.PropertiesList: - setattr(newobj,p,obj.getPropertyByName(p)) - formatObject(newobj,obj) - return newobj + '''makeCopy(object): returns an exact copy of an object''' + newobj = FreeCAD.ActiveDocument.addObject(obj.Type,getRealName(obj.Name)) + if getType(obj) == "Rectangle": + Rectangle(newobj) + ViewProviderRectangle(newobj.ViewObject) + elif getType(obj) == "Wire": + Wire(newobj) + ViewProviderWire(newobj.ViewObject) + elif getType(obj) == "Circle": + Circle(newobj) + ViewProviderCircle(newobj.ViewObject) + elif getType(obj) == "Polygon": + Polygon(newobj) + ViewProviderPolygon(newobj.ViewObject) + elif getType(obj) == "BSpline": + BSpline(newobj) + ViewProviderBSpline(newobj.ViewObject) + elif getType(obj) == "Block": + Block(newobj) + ViewProviderBlock(newobj.ViewObject) + elif getType(obj) == "Structure": + import Structure + Structure.Structure(newobj) + Structure.ViewProviderStructure(newobj.ViewObject) + elif getType(obj) == "Wall": + import Wall + Wall.Wall(newobj) + Wall.ViewProviderWall(newobj.ViewObject) + elif obj.isDerivedFrom("Part::Feature"): + newobj.Shape = obj.Shape + else: + print "Error: Object type cannot be copied" + return None + for p in obj.PropertiesList: + if p in newobj.PropertiesList: + setattr(newobj,p,obj.getPropertyByName(p)) + formatObject(newobj,obj) + return newobj def makeBlock(objectslist): - '''makeBlock(objectslist): Creates a Draft Block from the given objects''' - obj = FreeCAD.ActiveDocument.addObject("Part::Part2DObjectPython","Block") - Block(obj) - ViewProviderBlock(obj.ViewObject) - obj.Components = objectslist - for o in objectslist: - o.ViewObject.Visibility = False - select(obj) - return obj + '''makeBlock(objectslist): Creates a Draft Block from the given objects''' + obj = FreeCAD.ActiveDocument.addObject("Part::Part2DObjectPython","Block") + Block(obj) + ViewProviderBlock(obj.ViewObject) + obj.Components = objectslist + for o in objectslist: + o.ViewObject.Visibility = False + select(obj) + return obj def extrude(obj,vector): - '''makeExtrusion(object,vector): extrudes the given object - in the direction given by the vector. The original object - gets hidden.''' - newobj = FreeCAD.ActiveDocument.addObject("Part::Extrusion","Extrusion") - newobj.Base = obj - newobj.Dir = vector - obj.ViewObject.Visibility = False - formatObject(newobj,obj) - FreeCAD.ActiveDocument.recompute() - return newobj + '''makeExtrusion(object,vector): extrudes the given object + in the direction given by the vector. The original object + gets hidden.''' + newobj = FreeCAD.ActiveDocument.addObject("Part::Extrusion","Extrusion") + newobj.Base = obj + newobj.Dir = vector + obj.ViewObject.Visibility = False + formatObject(newobj,obj) + FreeCAD.ActiveDocument.recompute() + return newobj def fuse(object1,object2): - '''fuse(oject1,object2): returns an object made from - the union of the 2 given objects. If the objects are - coplanar, a special Draft Wire is used, otherwise we use - a standard Part fuse.''' - if fcgeo.isCoplanar(object1.Shape.fuse(object2.Shape).Faces): - obj = FreeCAD.ActiveDocument.addObject("Part::Part2DObjectPython","Fusion") - Wire(obj) - ViewProviderWire(obj.ViewObject) - else: - obj = FreeCAD.ActiveDocument.addObject("Part::Fuse","Fusion") - obj.Base = object1 - obj.Tool = object2 - object1.ViewObject.Visibility = False - object2.ViewObject.Visibility = False - formatObject(obj,object1) - FreeCAD.ActiveDocument.recompute() - return obj + '''fuse(oject1,object2): returns an object made from + the union of the 2 given objects. If the objects are + coplanar, a special Draft Wire is used, otherwise we use + a standard Part fuse.''' + if fcgeo.isCoplanar(object1.Shape.fuse(object2.Shape).Faces): + obj = FreeCAD.ActiveDocument.addObject("Part::Part2DObjectPython","Fusion") + Wire(obj) + ViewProviderWire(obj.ViewObject) + else: + obj = FreeCAD.ActiveDocument.addObject("Part::Fuse","Fusion") + obj.Base = object1 + obj.Tool = object2 + object1.ViewObject.Visibility = False + object2.ViewObject.Visibility = False + formatObject(obj,object1) + FreeCAD.ActiveDocument.recompute() + return obj def cut(object1,object2): - '''cut(oject1,object2): returns a cut object made from - the difference of the 2 given objects.''' - obj = FreeCAD.ActiveDocument.addObject("Part::Cut","Cut") - obj.Base = object1 - obj.Tool = object2 - object1.ViewObject.Visibility = False - object2.ViewObject.Visibility = False - formatObject(obj,object1) - FreeCAD.ActiveDocument.recompute() - return obj + '''cut(oject1,object2): returns a cut object made from + the difference of the 2 given objects.''' + obj = FreeCAD.ActiveDocument.addObject("Part::Cut","Cut") + obj.Base = object1 + obj.Tool = object2 + object1.ViewObject.Visibility = False + object2.ViewObject.Visibility = False + formatObject(obj,object1) + FreeCAD.ActiveDocument.recompute() + return obj def move(objectslist,vector,copy=False): - '''move(objects,vector,[copy]): Moves the objects contained - in objects (that can be an object or a list of objects) - in the direction and distance indicated by the given - vector. If copy is True, the actual objects are not moved, but copies - are created instead.he objects (or their copies) are returned.''' - typecheck([(vector,Vector), (copy,bool)], "move") - if not isinstance(objectslist,list): objectslist = [objectslist] - newobjlist = [] - for obj in objectslist: - if (obj.isDerivedFrom("Part::Feature")): - if copy: - newobj = makeCopy(obj) - else: - newobj = obj - pla = newobj.Placement - pla.move(vector) - elif getType(obj) == "Annotation": - if copy: - newobj = FreeCAD.ActiveDocument.addObject("App::Annotation",getRealName(obj.Name)) - newobj.LabelText = obj.LabelText - else: - newobj = obj - newobj.Position = obj.Position.add(vector) - elif getType(obj) == "Dimension": - if copy: - newobj = FreeCAD.ActiveDocument.addObject("App::FeaturePython",getRealName(obj.Name)) - Dimension(newobj) - DimensionViewProvider(newobj.ViewObject) - else: - newobj = obj - newobj.Start = obj.Start.add(vector) - newobj.End = obj.End.add(vector) - newobj.Dimline = obj.Dimline.add(vector) - else: - if copy: print "Mesh copy not supported at the moment" # TODO - newobj = obj - if "Placement" in obj.PropertiesList: - pla = obj.Placement - pla.move(vector) - newobjlist.append(newobj) - if copy and getParam("selectBaseObjects"): - select(objectslist) + '''move(objects,vector,[copy]): Moves the objects contained + in objects (that can be an object or a list of objects) + in the direction and distance indicated by the given + vector. If copy is True, the actual objects are not moved, but copies + are created instead.he objects (or their copies) are returned.''' + typecheck([(vector,Vector), (copy,bool)], "move") + if not isinstance(objectslist,list): objectslist = [objectslist] + newobjlist = [] + for obj in objectslist: + if (obj.isDerivedFrom("Part::Feature")): + if copy: + newobj = makeCopy(obj) + else: + newobj = obj + pla = newobj.Placement + pla.move(vector) + elif getType(obj) == "Annotation": + if copy: + newobj = FreeCAD.ActiveDocument.addObject("App::Annotation",getRealName(obj.Name)) + newobj.LabelText = obj.LabelText + else: + newobj = obj + newobj.Position = obj.Position.add(vector) + elif getType(obj) == "Dimension": + if copy: + newobj = FreeCAD.ActiveDocument.addObject("App::FeaturePython",getRealName(obj.Name)) + Dimension(newobj) + DimensionViewProvider(newobj.ViewObject) + else: + newobj = obj + newobj.Start = obj.Start.add(vector) + newobj.End = obj.End.add(vector) + newobj.Dimline = obj.Dimline.add(vector) else: - select(newobjlist) - if len(newobjlist) == 1: return newobjlist[0] - return newobjlist + if copy: print "Mesh copy not supported at the moment" # TODO + newobj = obj + if "Placement" in obj.PropertiesList: + pla = obj.Placement + pla.move(vector) + newobjlist.append(newobj) + if copy and getParam("selectBaseObjects"): + select(objectslist) + else: + select(newobjlist) + if len(newobjlist) == 1: return newobjlist[0] + return newobjlist def array(objectslist,arg1,arg2,arg3,arg4=None): - '''array(objectslist,xvector,yvector,xnum,ynum) for rectangular array, or - array(objectslist,center,totalangle,totalnum) for polar array: Creates an array - of the objects contained in list (that can be an object or a list of objects) - with, in case of rectangular array, xnum of iterations in the x direction - at xvector distance between iterations, and same for y direction with yvector - and ynum. In case of polar array, center is a vector, totalangle is the angle - to cover (in degrees) and totalnum is the number of objects, including the original.''' - - def rectArray(objectslist,xvector,yvector,xnum,ynum): - typecheck([(xvector,Vector), (yvector,Vector), (xnum,int), (ynum,int)], "rectArray") - if not isinstance(objectslist,list): objectslist = [objectslist] - for xcount in range(xnum): - currentxvector=fcvec.scale(xvector,xcount) - if not xcount==0: - move(objectslist,currentxvector,True) - for ycount in range(ynum): - currentxvector=FreeCAD.Base.Vector(currentxvector) - currentyvector=currentxvector.add(fcvec.scale(yvector,ycount)) - if not ycount==0: - move(objectslist,currentyvector,True) - def polarArray(objectslist,center,angle,num): - typecheck([(center,Vector), (num,int)], "polarArray") - if not isinstance(objectslist,list): objectslist = [objectslist] - fraction = angle/num - for i in range(num): - currangle = fraction + (i*fraction) - rotate(objectslist,currangle,center,copy=True) + '''array(objectslist,xvector,yvector,xnum,ynum) for rectangular array, or + array(objectslist,center,totalangle,totalnum) for polar array: Creates an array + of the objects contained in list (that can be an object or a list of objects) + with, in case of rectangular array, xnum of iterations in the x direction + at xvector distance between iterations, and same for y direction with yvector + and ynum. In case of polar array, center is a vector, totalangle is the angle + to cover (in degrees) and totalnum is the number of objects, including the original.''' + + def rectArray(objectslist,xvector,yvector,xnum,ynum): + typecheck([(xvector,Vector), (yvector,Vector), (xnum,int), (ynum,int)], "rectArray") + if not isinstance(objectslist,list): objectslist = [objectslist] + for xcount in range(xnum): + currentxvector=fcvec.scale(xvector,xcount) + if not xcount==0: + move(objectslist,currentxvector,True) + for ycount in range(ynum): + currentxvector=FreeCAD.Base.Vector(currentxvector) + currentyvector=currentxvector.add(fcvec.scale(yvector,ycount)) + if not ycount==0: + move(objectslist,currentyvector,True) + def polarArray(objectslist,center,angle,num): + typecheck([(center,Vector), (num,int)], "polarArray") + if not isinstance(objectslist,list): objectslist = [objectslist] + fraction = angle/num + for i in range(num): + currangle = fraction + (i*fraction) + rotate(objectslist,currangle,center,copy=True) - if arg4: - rectArray(objectslist,arg1,arg2,arg3,arg4) - else: - polarArray(objectslist,arg1,arg2,arg3) + if arg4: + rectArray(objectslist,arg1,arg2,arg3,arg4) + else: + polarArray(objectslist,arg1,arg2,arg3) def rotate(objectslist,angle,center=Vector(0,0,0),axis=Vector(0,0,1),copy=False): - '''rotate(objects,angle,[center,axis,copy]): Rotates the objects contained - in objects (that can be a list of objects or an object) of the given angle - (in degrees) around the center, using axis as a rotation axis. If axis is - omitted, the rotation will be around the vertical Z axis. - If copy is True, the actual objects are not moved, but copies - are created instead. The objects (or their copies) are returned.''' - typecheck([(copy,bool)], "rotate") - if not isinstance(objectslist,list): objectslist = [objectslist] - newobjlist = [] - for obj in objectslist: - if copy: - newobj = makeCopy(obj) - else: - newobj = obj - if (obj.isDerivedFrom("Part::Feature")): - shape = obj.Shape.copy() - shape.rotate(fcvec.tup(center), fcvec.tup(axis), angle) - newobj.Shape = shape - elif hasattr(obj,"Placement"): - shape = Part.Shape() - shape.Placement = obj.Placement - shape.rotate(fcvec.tup(center), fcvec.tup(axis), angle) - newobj.Placement = shape.Placement - if copy: - formatObject(newobj,obj) - newobjlist.append(newobj) - if copy and getParam("selectBaseObjects"): - select(objectslist) + '''rotate(objects,angle,[center,axis,copy]): Rotates the objects contained + in objects (that can be a list of objects or an object) of the given angle + (in degrees) around the center, using axis as a rotation axis. If axis is + omitted, the rotation will be around the vertical Z axis. + If copy is True, the actual objects are not moved, but copies + are created instead. The objects (or their copies) are returned.''' + typecheck([(copy,bool)], "rotate") + if not isinstance(objectslist,list): objectslist = [objectslist] + newobjlist = [] + for obj in objectslist: + if copy: + newobj = makeCopy(obj) else: - select(newobjlist) - if len(newobjlist) == 1: return newobjlist[0] - return newobjlist + newobj = obj + if (obj.isDerivedFrom("Part::Feature")): + shape = obj.Shape.copy() + shape.rotate(fcvec.tup(center), fcvec.tup(axis), angle) + newobj.Shape = shape + elif hasattr(obj,"Placement"): + shape = Part.Shape() + shape.Placement = obj.Placement + shape.rotate(fcvec.tup(center), fcvec.tup(axis), angle) + newobj.Placement = shape.Placement + if copy: + formatObject(newobj,obj) + newobjlist.append(newobj) + if copy and getParam("selectBaseObjects"): + select(objectslist) + else: + select(newobjlist) + if len(newobjlist) == 1: return newobjlist[0] + return newobjlist def scale(objectslist,delta,center=Vector(0,0,0),copy=False): - '''scale(objects,vector,[center,copy]): Scales the objects contained - in objects (that can be a list of objects or an object) of the given scale - factors defined by the given vector (in X, Y and Z directions) around - given center. If copy is True, the actual objects are not moved, but copies - are created instead. The objects (or their copies) are returned.''' - if not isinstance(objectslist,list): objectslist = [objectslist] - newobjlist = [] - for obj in objectslist: - if copy: - newobj = makeCopy(obj) - else: - newobj = obj - sh = obj.Shape.copy() - m = FreeCAD.Matrix() - m.scale(delta) - sh = sh.transformGeometry(m) - corr = Vector(center.x,center.y,center.z) - corr.scale(delta.x,delta.y,delta.z) - corr = fcvec.neg(corr.sub(center)) - sh.translate(corr) - if getType(obj) == "Rectangle": - p = [] - for v in sh.Vertexes: p.append(v.Point) - pl = obj.Placement.copy() - pl.Base = p[0] - diag = p[2].sub(p[0]) - bb = p[1].sub(p[0]) - bh = p[3].sub(p[0]) - nb = fcvec.project(diag,bb) - nh = fcvec.project(diag,bh) - if obj.Length < 0: l = -nb.Length - else: l = nb.Length - if obj.Height < 0: h = -nh.Length - else: h = nh.Length - newobj.Length = l - newobj.Height = h - tr = p[0].sub(obj.Shape.Vertexes[0].Point) - newobj.Placement = pl - elif getType(obj) == "Wire": - p = [] - for v in sh.Vertexes: p.append(v.Point) - newobj.Points = p - elif (obj.isDerivedFrom("Part::Feature")): - newobj.Shape = sh - elif (obj.Type == "App::Annotation"): - factor = delta.x * delta.y * delta.z * obj.ViewObject.FontSize - obj.ViewObject.Fontsize = factor - if copy: formatObject(newobj,obj) - newobjlist.append(newobj) - if copy and getParam("selectBaseObjects"): - select(objectslist) + '''scale(objects,vector,[center,copy]): Scales the objects contained + in objects (that can be a list of objects or an object) of the given scale + factors defined by the given vector (in X, Y and Z directions) around + given center. If copy is True, the actual objects are not moved, but copies + are created instead. The objects (or their copies) are returned.''' + if not isinstance(objectslist,list): objectslist = [objectslist] + newobjlist = [] + for obj in objectslist: + if copy: + newobj = makeCopy(obj) else: - select(newobjlist) - if len(newobjlist) == 1: return newobjlist[0] - return newobjlist + newobj = obj + sh = obj.Shape.copy() + m = FreeCAD.Matrix() + m.scale(delta) + sh = sh.transformGeometry(m) + corr = Vector(center.x,center.y,center.z) + corr.scale(delta.x,delta.y,delta.z) + corr = fcvec.neg(corr.sub(center)) + sh.translate(corr) + if getType(obj) == "Rectangle": + p = [] + for v in sh.Vertexes: p.append(v.Point) + pl = obj.Placement.copy() + pl.Base = p[0] + diag = p[2].sub(p[0]) + bb = p[1].sub(p[0]) + bh = p[3].sub(p[0]) + nb = fcvec.project(diag,bb) + nh = fcvec.project(diag,bh) + if obj.Length < 0: l = -nb.Length + else: l = nb.Length + if obj.Height < 0: h = -nh.Length + else: h = nh.Length + newobj.Length = l + newobj.Height = h + tr = p[0].sub(obj.Shape.Vertexes[0].Point) + newobj.Placement = pl + elif getType(obj) == "Wire": + p = [] + for v in sh.Vertexes: p.append(v.Point) + newobj.Points = p + elif (obj.isDerivedFrom("Part::Feature")): + newobj.Shape = sh + elif (obj.Type == "App::Annotation"): + factor = delta.x * delta.y * delta.z * obj.ViewObject.FontSize + obj.ViewObject.Fontsize = factor + if copy: formatObject(newobj,obj) + newobjlist.append(newobj) + if copy and getParam("selectBaseObjects"): + select(objectslist) + else: + select(newobjlist) + if len(newobjlist) == 1: return newobjlist[0] + return newobjlist def offset(obj,delta,copy=False,bind=False,sym=False,occ=False): - '''offset(object,Vector,[copymode],[bind]): offsets the given wire by - applying the given Vector to its first vertex. If copymode is - True, another object is created, otherwise the same object gets - offsetted. If bind is True, and provided the wire is open, the original - and the offsetted wires will be bound by their endpoints, forming a face - if sym is True, bind must be true too, and the offset is made on both - sides, the total width being the given delta length.''' + '''offset(object,Vector,[copymode],[bind]): offsets the given wire by + applying the given Vector to its first vertex. If copymode is + True, another object is created, otherwise the same object gets + offsetted. If bind is True, and provided the wire is open, the original + and the offsetted wires will be bound by their endpoints, forming a face + if sym is True, bind must be true too, and the offset is made on both + sides, the total width being the given delta length.''' - def getRect(p,obj): - "returns length,heigh,placement" - pl = obj.Placement.copy() - pl.Base = p[0] - diag = p[2].sub(p[0]) - bb = p[1].sub(p[0]) - bh = p[3].sub(p[0]) - nb = fcvec.project(diag,bb) - nh = fcvec.project(diag,bh) - if obj.Length < 0: l = -nb.Length - else: l = nb.Length - if obj.Height < 0: h = -nh.Length - else: h = nh.Length - return l,h,pl + def getRect(p,obj): + "returns length,heigh,placement" + pl = obj.Placement.copy() + pl.Base = p[0] + diag = p[2].sub(p[0]) + bb = p[1].sub(p[0]) + bh = p[3].sub(p[0]) + nb = fcvec.project(diag,bb) + nh = fcvec.project(diag,bh) + if obj.Length < 0: l = -nb.Length + else: l = nb.Length + if obj.Height < 0: h = -nh.Length + else: h = nh.Length + return l,h,pl - def getRadius(obj,delta): - "returns a new radius for a regular polygon" - an = math.pi/obj.FacesNumber - nr = fcvec.rotate(delta,-an) - nr.multiply(1/math.cos(an)) - nr = obj.Shape.Vertexes[0].Point.add(nr) - nr = nr.sub(obj.Placement.Base) - nr = nr.Length - if obj.DrawMode == "inscribed": - return nr - else: - return nr * math.cos(math.pi/obj.FacesNumber) + def getRadius(obj,delta): + "returns a new radius for a regular polygon" + an = math.pi/obj.FacesNumber + nr = fcvec.rotate(delta,-an) + nr.multiply(1/math.cos(an)) + nr = obj.Shape.Vertexes[0].Point.add(nr) + nr = nr.sub(obj.Placement.Base) + nr = nr.Length + if obj.DrawMode == "inscribed": + return nr + else: + return nr * math.cos(math.pi/obj.FacesNumber) - if getType(obj) == "Circle": - pass + if getType(obj) == "Circle": + pass + else: + if sym: + d1 = delta.multiply(0.5) + d2 = fcvec.neg(d1) + n1 = fcgeo.offsetWire(obj.Shape,d1) + n2 = fcgeo.offsetWire(obj.Shape,d2) else: - if sym: - d1 = delta.multiply(0.5) - d2 = fcvec.neg(d1) - n1 = fcgeo.offsetWire(obj.Shape,d1) - n2 = fcgeo.offsetWire(obj.Shape,d2) - else: - newwire = fcgeo.offsetWire(obj.Shape,delta) - p = fcgeo.getVerts(newwire) - if occ: - newobj = FreeCAD.ActiveDocument.addObject("Part::Feature","Offset") - newobj.Shape = fcgeo.offsetWire(obj.Shape,delta,occ=True) - formatObject(newobj,obj) - elif bind: - if not fcgeo.isReallyClosed(obj.Shape): - if sym: - s1 = n1 - s2 = n2 - else: - s1 = obj.Shape - s2 = newwire - w1 = s1.Edges - w2 = s2.Edges - w3 = Part.Line(s1.Vertexes[0].Point,s2.Vertexes[0].Point).toShape() - w4 = Part.Line(s1.Vertexes[-1].Point,s2.Vertexes[-1].Point).toShape() - newobj = Part.Face(Part.Wire(w1+[w3]+w2+[w4])) - else: - newobj = Part.Face(obj.Shape.Wires[0]) - elif copy: - if sym: return None - if getType(obj) == "Wire": - newobj = makeWire(p) - newobj.Closed = obj.Closed - elif getType(obj) == "Rectangle": - length,height,plac = getRect(p,obj) - newobj = makeRectangle(length,height,plac) - elif getType(obj) == "Circle": - pl = obj.Placement - newobj = makeCircle(delta) - newobj.FirstAngle = obj.FirstAngle - newobj.LastAngle = obj.LastAngle - newobj.Placement = pl - elif getType(obj) == "Polygon": - pl = obj.Placement - newobj = makePolygon(obj.FacesNumber) - newobj.Radius = getRadius(obj,delta) - newobj.DrawMode = obj.DrawMode - newobj.Placement = pl - elif getType(obj) == "Part": - newobj = makeWire(p) - newobj.Closed = obj.Shape.isClosed() - formatObject(newobj,obj) + newwire = fcgeo.offsetWire(obj.Shape,delta) + p = fcgeo.getVerts(newwire) + if occ: + newobj = FreeCAD.ActiveDocument.addObject("Part::Feature","Offset") + newobj.Shape = fcgeo.offsetWire(obj.Shape,delta,occ=True) + formatObject(newobj,obj) + elif bind: + if not fcgeo.isReallyClosed(obj.Shape): + if sym: + s1 = n1 + s2 = n2 + else: + s1 = obj.Shape + s2 = newwire + w1 = s1.Edges + w2 = s2.Edges + w3 = Part.Line(s1.Vertexes[0].Point,s2.Vertexes[0].Point).toShape() + w4 = Part.Line(s1.Vertexes[-1].Point,s2.Vertexes[-1].Point).toShape() + newobj = Part.Face(Part.Wire(w1+[w3]+w2+[w4])) else: - if sym: return None - if getType(obj) == "Wire": - if obj.Base or obj.Tool: - FreeCAD.Console.PrintWarning("Warning: object history removed\n") - obj.Base = None - obj.Tool = None - obj.Points = p - elif getType(obj) == "Rectangle": - length,height,plac = getRect(p,obj) - obj.Placement = plac - obj.Length = length - obj.Height = height - elif getType(obj) == "Circle": - obj.Radius = delta - elif getType(obj) == "Polygon": - obj.Radius = getRadius(obj,delta) - elif getType(obj) == 'Part': - print "unsupported object" # TODO - newobj = obj - if copy and getParam("selectBaseObjects"): - select(newobj) - else: - select(obj) - return newobj + newobj = Part.Face(obj.Shape.Wires[0]) + elif copy: + if sym: return None + if getType(obj) == "Wire": + newobj = makeWire(p) + newobj.Closed = obj.Closed + elif getType(obj) == "Rectangle": + length,height,plac = getRect(p,obj) + newobj = makeRectangle(length,height,plac) + elif getType(obj) == "Circle": + pl = obj.Placement + newobj = makeCircle(delta) + newobj.FirstAngle = obj.FirstAngle + newobj.LastAngle = obj.LastAngle + newobj.Placement = pl + elif getType(obj) == "Polygon": + pl = obj.Placement + newobj = makePolygon(obj.FacesNumber) + newobj.Radius = getRadius(obj,delta) + newobj.DrawMode = obj.DrawMode + newobj.Placement = pl + elif getType(obj) == "Part": + newobj = makeWire(p) + newobj.Closed = obj.Shape.isClosed() + formatObject(newobj,obj) + else: + if sym: return None + if getType(obj) == "Wire": + if obj.Base or obj.Tool: + FreeCAD.Console.PrintWarning("Warning: object history removed\n") + obj.Base = None + obj.Tool = None + obj.Points = p + elif getType(obj) == "Rectangle": + length,height,plac = getRect(p,obj) + obj.Placement = plac + obj.Length = length + obj.Height = height + elif getType(obj) == "Circle": + obj.Radius = delta + elif getType(obj) == "Polygon": + obj.Radius = getRadius(obj,delta) + elif getType(obj) == 'Part': + print "unsupported object" # TODO + newobj = obj + if copy and getParam("selectBaseObjects"): + select(newobj) + else: + select(obj) + return newobj def draftify(objectslist): - '''draftify(objectslist): turns each object of the given list - (objectslist can also be a single object) into a Draft parametric - wire''' - if not isinstance(objectslist,list): objectslist = [objectslist] - newobjlist = [] - for obj in objectslist: - if obj.isDerivedFrom('Part::Feature'): - for w in obj.Shape.Wires: - verts = [] - edges = fcgeo.sortEdges(w.Edges) - for e in edges: - verts.append(e.Vertexes[0].Point) - if w.isClosed(): - verts.append(edges[-1].Vertexes[-1].Point) - newobj = makeWire(verts) - if obj.Shape.Faces: - newobj.Closed = True - newobj.ViewObject.DisplayMode = "Flat Lines" - else: - newobj.ViewObject.DisplayMode = "Wireframe" - if obj.Shape.Wires[0].isClosed: - newobj.Closed = True - newobjlist.append(newobj) - FreeCAD.ActiveDocument.removeObject(obj.Name) - if len(newobjlist) == 1: return newobjlist[0] - return newobjlist + '''draftify(objectslist): turns each object of the given list + (objectslist can also be a single object) into a Draft parametric + wire''' + if not isinstance(objectslist,list): objectslist = [objectslist] + newobjlist = [] + for obj in objectslist: + if obj.isDerivedFrom('Part::Feature'): + for w in obj.Shape.Wires: + verts = [] + edges = fcgeo.sortEdges(w.Edges) + for e in edges: + verts.append(e.Vertexes[0].Point) + if w.isClosed(): + verts.append(edges[-1].Vertexes[-1].Point) + newobj = makeWire(verts) + if obj.Shape.Faces: + newobj.Closed = True + newobj.ViewObject.DisplayMode = "Flat Lines" + else: + newobj.ViewObject.DisplayMode = "Wireframe" + if obj.Shape.Wires[0].isClosed: + newobj.Closed = True + newobjlist.append(newobj) + FreeCAD.ActiveDocument.removeObject(obj.Name) + if len(newobjlist) == 1: return newobjlist[0] + return newobjlist def getrgb(color): - "getRGB(color): returns a rgb value #000000 from a freecad color" - r = str(hex(int(color[0]*255)))[2:].zfill(2) - g = str(hex(int(color[1]*255)))[2:].zfill(2) - b = str(hex(int(color[2]*255)))[2:].zfill(2) - return "#"+r+g+b + "getRGB(color): returns a rgb value #000000 from a freecad color" + r = str(hex(int(color[0]*255)))[2:].zfill(2) + g = str(hex(int(color[1]*255)))[2:].zfill(2) + b = str(hex(int(color[2]*255)))[2:].zfill(2) + return "#"+r+g+b def getSVG(obj,modifier=100,textmodifier=100,linestyle="continuous",fillstyle="shape color",direction=None): - '''getSVG(object,[modifier],[textmodifier],[linestyle],[fillstyle],[direction]): - returns a string containing a SVG representation of the given object. the modifier attribute - specifies a scale factor for linewidths in %, and textmodifier specifies - a scale factor for texts, in % (both default = 100). You can also supply - an arbitrary projection vector.''' - svg = "" - tmod = ((textmodifier-100)/2)+100 - if tmod == 0: tmod = 0.01 - modifier = 200-modifier - if modifier == 0: modifier = 0.01 - pmod = (200-textmodifier)/20 - if pmod == 0: pmod = 0.01 - plane = None - if direction: - if direction != Vector(0,0,0): - plane = WorkingPlane.plane() - plane.alignToPointAndAxis(Vector(0,0,0),fcvec.neg(direction),0) + '''getSVG(object,[modifier],[textmodifier],[linestyle],[fillstyle],[direction]): + returns a string containing a SVG representation of the given object. the modifier attribute + specifies a scale factor for linewidths in %, and textmodifier specifies + a scale factor for texts, in % (both default = 100). You can also supply + an arbitrary projection vector.''' + svg = "" + tmod = ((textmodifier-100)/2)+100 + if tmod == 0: tmod = 0.01 + modifier = 200-modifier + if modifier == 0: modifier = 0.01 + pmod = (200-textmodifier)/20 + if pmod == 0: pmod = 0.01 + plane = None + if direction: + if direction != Vector(0,0,0): + plane = WorkingPlane.plane() + plane.alignToPointAndAxis(Vector(0,0,0),fcvec.neg(direction),0) - def getProj(vec): - if not plane: return vec - nx = fcvec.project(vec,plane.u) - lx = nx.Length - if abs(nx.getAngle(plane.u)) > 0.1: lx = -lx - ny = fcvec.project(vec,plane.v) - ly = ny.Length - if abs(ny.getAngle(plane.v)) > 0.1: ly = -ly - return Vector(lx,ly,0) + def getProj(vec): + if not plane: return vec + nx = fcvec.project(vec,plane.u) + lx = nx.Length + if abs(nx.getAngle(plane.u)) > 0.1: lx = -lx + ny = fcvec.project(vec,plane.v) + ly = ny.Length + if abs(ny.getAngle(plane.v)) > 0.1: ly = -ly + return Vector(lx,ly,0) - def getPath(edges): - svg ='' - svg += dimText % p3.sub(p2).Length - svg += '\n\n' - - elif getType(obj) == "Annotation": - "returns an svg representation of a document annotation" - p = getProj(obj.Position) - svg = '\n' - for l in obj.LabelText: - svg += ''+l+'\n' - svg += '\n' - - elif obj.isDerivedFrom('Part::Feature'): - if obj.Shape.isNull(): return '' - color = getrgb(obj.ViewObject.LineColor) - # setting fill - if obj.Shape.Faces and (obj.ViewObject.DisplayMode != "Wireframe"): - if fillstyle == "shape color": - fill = getrgb(obj.ViewObject.ShapeColor) - else: - fill = 'url(#'+hatch+')' - else: - fill = 'none' - # setting linetype - if linestyle == "dashed": - lstyle = "0.09,0.05" - elif linestyle == "dashdotted": - lstyle = "0.09,0.05,0.02,0.05" - elif linestyle == "dotted": - lstyle = "0.02,0.02" - else: - lstyle = "none" - name = obj.Name - if obj.ViewObject.DisplayMode == "Shaded": - stroke = "none" - else: - stroke = getrgb(obj.ViewObject.LineColor) - width = obj.ViewObject.LineWidth/modifier - if len(obj.Shape.Vertexes) > 1: - wiredEdges = [] - if obj.Shape.Faces: - for f in obj.Shape.Faces: - svg += getPath(f.Edges) - wiredEdges.extend(f.Edges) - else: - for w in obj.Shape.Wires: - svg += getPath(w.Edges) - wiredEdges.extend(w.Edges) - if len(wiredEdges) != len(obj.Shape.Edges): - for e in obj.Shape.Edges: - if (fcgeo.findEdge(e,wiredEdges) == None): - svg += getPath([e]) - else: - cen = getProj(obj.Shape.Edges[0].Curve.Center) - rad = obj.Shape.Edges[0].Curve.Radius - svg = '' + svg += dimText % p3.sub(p2).Length + svg += '\n\n' + + elif getType(obj) == "Annotation": + "returns an svg representation of a document annotation" + p = getProj(obj.Position) + svg = '\n' + for l in obj.LabelText: + svg += ''+l+'\n' + svg += '\n' + + elif obj.isDerivedFrom('Part::Feature'): + if obj.Shape.isNull(): return '' + color = getrgb(obj.ViewObject.LineColor) + # setting fill + if obj.Shape.Faces and (obj.ViewObject.DisplayMode != "Wireframe"): + if fillstyle == "shape color": + fill = getrgb(obj.ViewObject.ShapeColor) + else: + fill = 'url(#'+hatch+')' + else: + fill = 'none' + # setting linetype + if linestyle == "dashed": + lstyle = "0.09,0.05" + elif linestyle == "dashdotted": + lstyle = "0.09,0.05,0.02,0.05" + elif linestyle == "dotted": + lstyle = "0.02,0.02" + else: + lstyle = "none" + name = obj.Name + if obj.ViewObject.DisplayMode == "Shaded": + stroke = "none" + else: + stroke = getrgb(obj.ViewObject.LineColor) + width = obj.ViewObject.LineWidth/modifier + if len(obj.Shape.Vertexes) > 1: + wiredEdges = [] + if obj.Shape.Faces: + for f in obj.Shape.Faces: + svg += getPath(f.Edges) + wiredEdges.extend(f.Edges) + else: + for w in obj.Shape.Wires: + svg += getPath(w.Edges) + wiredEdges.extend(w.Edges) + if len(wiredEdges) != len(obj.Shape.Edges): + for e in obj.Shape.Edges: + if (fcgeo.findEdge(e,wiredEdges) == None): + svg += getPath([e]) + else: + cen = getProj(obj.Shape.Edges[0].Curve.Center) + rad = obj.Shape.Edges[0].Curve.Radius + svg = ' dmax): - p1 = p2.add(fcvec.scaleTo(proj,dmax)) - p4 = p3.add(fcvec.scaleTo(proj,dmax)) - midpoint = p2.add(fcvec.scale(p3.sub(p2),0.5)) - if not proj: - ed = fcgeo.vec(base) - proj = ed.cross(Vector(0,0,1)) - if not proj: norm = Vector(0,0,1) - else: norm = fcvec.neg(p3.sub(p2).cross(proj)) - norm.normalize() - va = FreeCADGui.ActiveDocument.ActiveView.getViewDirection() - if va.getAngle(norm) < math.pi/2: - norm = fcvec.neg(norm) - u = p3.sub(p2) - u.normalize() - c = FreeCADGui.ActiveDocument.ActiveView.getCameraNode() - r = c.orientation.getValue() - ru = Vector(r.multVec(coin.SbVec3f(1,0,0)).getValue()) - if ru.getAngle(u) > math.pi/2: u = fcvec.neg(u) - v = norm.cross(u) - offset = fcvec.scaleTo(v,obj.ViewObject.FontSize*.2) - if obj.ViewObject: - if hasattr(obj.ViewObject,"DisplayMode"): - if obj.ViewObject.DisplayMode == "3D": - offset = fcvec.neg(offset) - if obj.ViewObject.Position == Vector(0,0,0): - tbase = midpoint.add(offset) + def calcGeom(self,obj): + p1 = obj.Start + p4 = obj.End + base = Part.Line(p1,p4).toShape() + proj = fcgeo.findDistance(obj.Dimline,base) + if not proj: + p2 = p1 + p3 = p4 + else: + p2 = p1.add(fcvec.neg(proj)) + p3 = p4.add(fcvec.neg(proj)) + dmax = obj.ViewObject.ExtLines + if dmax and (proj.Length > dmax): + p1 = p2.add(fcvec.scaleTo(proj,dmax)) + p4 = p3.add(fcvec.scaleTo(proj,dmax)) + midpoint = p2.add(fcvec.scale(p3.sub(p2),0.5)) + if not proj: + ed = fcgeo.vec(base) + proj = ed.cross(Vector(0,0,1)) + if not proj: norm = Vector(0,0,1) + else: norm = fcvec.neg(p3.sub(p2).cross(proj)) + norm.normalize() + va = FreeCADGui.ActiveDocument.ActiveView.getViewDirection() + if va.getAngle(norm) < math.pi/2: + norm = fcvec.neg(norm) + u = p3.sub(p2) + u.normalize() + c = FreeCADGui.ActiveDocument.ActiveView.getCameraNode() + r = c.orientation.getValue() + ru = Vector(r.multVec(coin.SbVec3f(1,0,0)).getValue()) + if ru.getAngle(u) > math.pi/2: u = fcvec.neg(u) + v = norm.cross(u) + offset = fcvec.scaleTo(v,obj.ViewObject.FontSize*.2) + if obj.ViewObject: + if hasattr(obj.ViewObject,"DisplayMode"): + if obj.ViewObject.DisplayMode == "3D": + offset = fcvec.neg(offset) + if obj.ViewObject.Position == Vector(0,0,0): + tbase = midpoint.add(offset) + else: + tbase = obj.ViewObject.Position + rot = FreeCAD.Placement(fcvec.getPlaneRotation(u,v,norm)).Rotation.Q + return p1,p2,p3,p4,tbase,norm,rot + + def attach(self, obj): + self.Object = obj.Object + p1,p2,p3,p4,tbase,norm,rot = self.calcGeom(obj.Object) + self.color = coin.SoBaseColor() + self.color.rgb.setValue(obj.LineColor[0], + obj.LineColor[1], + obj.LineColor[2]) + self.font = coin.SoFont() + self.font3d = coin.SoFont() + self.text = coin.SoAsciiText() + self.text3d = coin.SoText2() + self.text.justification = self.text3d.justification = coin.SoAsciiText.CENTER + self.text.string = self.text3d.string = '' + self.textpos = coin.SoTransform() + self.textpos.translation.setValue([tbase.x,tbase.y,tbase.z]) + tm = fcvec.getPlaneRotation(p3.sub(p2),norm) + rm = coin.SbRotation() + self.textpos.rotation = rm + label = coin.SoSeparator() + label.addChild(self.textpos) + label.addChild(self.color) + label.addChild(self.font) + label.addChild(self.text) + label3d = coin.SoSeparator() + label3d.addChild(self.textpos) + label3d.addChild(self.color) + label3d.addChild(self.font3d) + label3d.addChild(self.text3d) + self.coord1 = coin.SoCoordinate3() + self.coord1.point.setValue((p2.x,p2.y,p2.z)) + self.coord2 = coin.SoCoordinate3() + self.coord2.point.setValue((p3.x,p3.y,p3.z)) + marks = coin.SoAnnotation() + marks.addChild(self.color) + marks.addChild(self.coord1) + marks.addChild(dimSymbol()) + marks.addChild(self.coord2) + marks.addChild(dimSymbol()) + self.drawstyle = coin.SoDrawStyle() + self.drawstyle.lineWidth = 1 + self.line = coin.SoLineSet() + self.coords = coin.SoCoordinate3() + selnode=coin.SoType.fromName("SoFCSelection").createInstance() + selnode.documentName.setValue(FreeCAD.ActiveDocument.Name) + selnode.objectName.setValue(obj.Object.Name) + selnode.subElementName.setValue("Line") + selnode.addChild(self.line) + self.node = coin.SoGroup() + self.node.addChild(self.color) + self.node.addChild(self.drawstyle) + self.node.addChild(self.coords) + self.node.addChild(selnode) + self.node.addChild(marks) + self.node.addChild(label) + self.node3d = coin.SoGroup() + self.node3d.addChild(self.color) + self.node3d.addChild(self.drawstyle) + self.node3d.addChild(self.coords) + self.node3d.addChild(selnode) + self.node3d.addChild(marks) + self.node3d.addChild(label3d) + obj.addDisplayMode(self.node,"2D") + obj.addDisplayMode(self.node3d,"3D") + self.onChanged(obj,"FontSize") + self.onChanged(obj,"FontName") + + def updateData(self, obj, prop): + text = None + if obj.Base and obj.LinkedVertices: + if "Shape" in obj.Base.PropertiesList: + if len(obj.LinkedVertices) == 3: + # arc linked dimension + e = obj.Base.Shape.Edges[obj.LinkedVertices[0]] + c = e.Curve.Center + bray = fcvec.scaleTo(obj.Dimline.sub(c),e.Curve.Radius) + if obj.LinkedVertices[1] == 1: + v1 = c + else: + v1 = c.add(fcvec.neg(bray)) + v2 = c.add(bray) else: - tbase = obj.ViewObject.Position - rot = FreeCAD.Placement(fcvec.getPlaneRotation(u,v,norm)).Rotation.Q - return p1,p2,p3,p4,tbase,norm,rot + # linear linked dimension + v1 = obj.Base.Shape.Vertexes[obj.LinkedVertices[0]].Point + v2 = obj.Base.Shape.Vertexes[obj.LinkedVertices[1]].Point + if v1 != obj.Start: obj.Start = v1 + if v2 != obj.End: obj.End = v2 + p1,p2,p3,p4,tbase,norm,rot = self.calcGeom(obj) + if 'Override' in obj.ViewObject.PropertiesList: + text = str(obj.ViewObject.Override) + dtext = getParam("dimPrecision") + dtext = "%."+str(dtext)+"f" + dtext = (dtext % p3.sub(p2).Length) + if text: + text = text.replace("dim",dtext) + else: + text = dtext + self.text.string = self.text3d.string = text + self.textpos.rotation = coin.SbRotation(rot[0],rot[1],rot[2],rot[3]) + self.textpos.translation.setValue([tbase.x,tbase.y,tbase.z]) + if obj.ViewObject.DisplayMode == "2D": + self.coords.point.setValues([[p1.x,p1.y,p1.z], + [p2.x,p2.y,p2.z], + [p3.x,p3.y,p3.z], + [p4.x,p4.y,p4.z]]) + self.line.numVertices.setValues([4]) + else: + ts = (len(text)*obj.ViewObject.FontSize)/4 + rm = ((p3.sub(p2)).Length/2)-ts + p2a = p2.add(fcvec.scaleTo(p3.sub(p2),rm)) + p2b = p3.add(fcvec.scaleTo(p2.sub(p3),rm)) + self.coords.point.setValues([[p1.x,p1.y,p1.z], + [p2.x,p2.y,p2.z], + [p2a.x,p2a.y,p2a.z], + [p2b.x,p2b.y,p2b.z], + [p3.x,p3.y,p3.z], + [p4.x,p4.y,p4.z]]) + self.line.numVertices.setValues([3,3]) + self.coord1.point.setValue((p2.x,p2.y,p2.z)) + self.coord2.point.setValue((p3.x,p3.y,p3.z)) - def attach(self, obj): - self.Object = obj.Object - p1,p2,p3,p4,tbase,norm,rot = self.calcGeom(obj.Object) - self.color = coin.SoBaseColor() - self.color.rgb.setValue(obj.LineColor[0], - obj.LineColor[1], - obj.LineColor[2]) - self.font = coin.SoFont() - self.font3d = coin.SoFont() - self.text = coin.SoAsciiText() - self.text3d = coin.SoText2() - self.text.justification = self.text3d.justification = coin.SoAsciiText.CENTER - self.text.string = self.text3d.string = '' - self.textpos = coin.SoTransform() - self.textpos.translation.setValue([tbase.x,tbase.y,tbase.z]) - tm = fcvec.getPlaneRotation(p3.sub(p2),norm) - rm = coin.SbRotation() - self.textpos.rotation = rm - label = coin.SoSeparator() - label.addChild(self.textpos) - label.addChild(self.color) - label.addChild(self.font) - label.addChild(self.text) - label3d = coin.SoSeparator() - label3d.addChild(self.textpos) - label3d.addChild(self.color) - label3d.addChild(self.font3d) - label3d.addChild(self.text3d) - self.coord1 = coin.SoCoordinate3() - self.coord1.point.setValue((p2.x,p2.y,p2.z)) - self.coord2 = coin.SoCoordinate3() - self.coord2.point.setValue((p3.x,p3.y,p3.z)) - marks = coin.SoAnnotation() - marks.addChild(self.color) - marks.addChild(self.coord1) - marks.addChild(dimSymbol()) - marks.addChild(self.coord2) - marks.addChild(dimSymbol()) - self.drawstyle = coin.SoDrawStyle() - self.drawstyle.lineWidth = 1 - self.line = coin.SoLineSet() - self.coords = coin.SoCoordinate3() - selnode=coin.SoType.fromName("SoFCSelection").createInstance() - selnode.documentName.setValue(FreeCAD.ActiveDocument.Name) - selnode.objectName.setValue(obj.Object.Name) - selnode.subElementName.setValue("Line") - selnode.addChild(self.line) - self.node = coin.SoGroup() - self.node.addChild(self.color) - self.node.addChild(self.drawstyle) - self.node.addChild(self.coords) - self.node.addChild(selnode) - self.node.addChild(marks) - self.node.addChild(label) - self.node3d = coin.SoGroup() - self.node3d.addChild(self.color) - self.node3d.addChild(self.drawstyle) - self.node3d.addChild(self.coords) - self.node3d.addChild(selnode) - self.node3d.addChild(marks) - self.node3d.addChild(label3d) - obj.addDisplayMode(self.node,"2D") - obj.addDisplayMode(self.node3d,"3D") - self.onChanged(obj,"FontSize") - self.onChanged(obj,"FontName") + def onChanged(self, vp, prop): + if prop == "FontSize": + self.font.size = vp.FontSize + self.font3d.size = vp.FontSize*100 + elif prop == "FontName": + self.font.name = self.font3d.name = str(vp.FontName) + elif prop == "LineColor": + c = vp.LineColor + self.color.rgb.setValue(c[0],c[1],c[2]) + elif prop == "LineWidth": + self.drawstyle.lineWidth = vp.LineWidth + else: + self.updateData(vp.Object, None) - def updateData(self, obj, prop): - text = None - if obj.Base and obj.LinkedVertices: - if "Shape" in obj.Base.PropertiesList: - if len(obj.LinkedVertices) == 3: - # arc linked dimension - e = obj.Base.Shape.Edges[obj.LinkedVertices[0]] - c = e.Curve.Center - bray = fcvec.scaleTo(obj.Dimline.sub(c),e.Curve.Radius) - if obj.LinkedVertices[1] == 1: - v1 = c - else: - v1 = c.add(fcvec.neg(bray)) - v2 = c.add(bray) - # linear linked dimension - else: - v1 = obj.Base.Shape.Vertexes[obj.LinkedVertices[0]].Point - v2 = obj.Base.Shape.Vertexes[obj.LinkedVertices[1]].Point - if v1 != obj.Start: obj.Start = v1 - if v2 != obj.End: obj.End = v2 - p1,p2,p3,p4,tbase,norm,rot = self.calcGeom(obj) - if 'Override' in obj.ViewObject.PropertiesList: - text = str(obj.ViewObject.Override) - dtext = getParam("dimPrecision") - dtext = "%."+str(dtext)+"f" - dtext = (dtext % p3.sub(p2).Length) - if text: - text = text.replace("dim",dtext) - else: - text = dtext - self.text.string = self.text3d.string = text - self.textpos.rotation = coin.SbRotation(rot[0],rot[1],rot[2],rot[3]) - self.textpos.translation.setValue([tbase.x,tbase.y,tbase.z]) - if obj.ViewObject.DisplayMode == "2D": - self.coords.point.setValues([[p1.x,p1.y,p1.z], - [p2.x,p2.y,p2.z], - [p3.x,p3.y,p3.z], - [p4.x,p4.y,p4.z]]) - self.line.numVertices.setValues([4]) - else: - ts = (len(text)*obj.ViewObject.FontSize)/4 - rm = ((p3.sub(p2)).Length/2)-ts - p2a = p2.add(fcvec.scaleTo(p3.sub(p2),rm)) - p2b = p3.add(fcvec.scaleTo(p2.sub(p3),rm)) - self.coords.point.setValues([[p1.x,p1.y,p1.z], - [p2.x,p2.y,p2.z], - [p2a.x,p2a.y,p2a.z], - [p2b.x,p2b.y,p2b.z], - [p3.x,p3.y,p3.z], - [p4.x,p4.y,p4.z]]) - self.line.numVertices.setValues([3,3]) - self.coord1.point.setValue((p2.x,p2.y,p2.z)) - self.coord2.point.setValue((p3.x,p3.y,p3.z)) + def getDisplayModes(self,obj): + modes=[] + modes.extend(["2D","3D"]) + return modes - def onChanged(self, vp, prop): - if prop == "FontSize": - self.font.size = vp.FontSize - self.font3d.size = vp.FontSize*100 - elif prop == "FontName": - self.font.name = self.font3d.name = str(vp.FontName) - elif prop == "LineColor": - c = vp.LineColor - self.color.rgb.setValue(c[0],c[1],c[2]) - elif prop == "LineWidth": - self.drawstyle.lineWidth = vp.LineWidth - else: - self.updateData(vp.Object, None) + def getDefaultDisplayMode(self): + return "2D" - def getDisplayModes(self,obj): - modes=[] - modes.extend(["2D","3D"]) - return modes + def getIcon(self): + if self.Object.Base: + return """ + /* XPM */ + static char * dim_xpm[] = { + "16 16 6 1", + " c None", + ". c #000000", + "+ c #FFFF00", + "@ c #FFFFFF", + "$ c #141010", + "# c #615BD2", + " $$$$$$$$", + " $##$$#$$", + " . $##$$##$", + " .. $##$$##$", + " .+. $######$", + " .++. $##$$##$", + " .+++. .$##$$##$", + ".++++. .$######$", + " .+++. .$$$$$$$$" + " .++. .++. ", + " .+. .+. ", + " .. .. ", + " . . ", + " ", + " ", + " "}; + """ + else: + return """ + /* XPM */ + static char * dim_xpm[] = { + "16 16 4 1", + " c None", + ". c #000000", + "+ c #FFFF00", + "@ c #FFFFFF", + " ", + " ", + " . . ", + " .. .. ", + " .+. .+. ", + " .++. .++. ", + " .+++. .. .+++. ", + ".++++. .. .++++.", + " .+++. .. .+++. ", + " .++. .++. ", + " .+. .+. ", + " .. .. ", + " . . ", + " ", + " ", + " "}; + """ - def getDefaultDisplayMode(self): - return "2D" - - def getIcon(self): - if self.Object.Base: - return """ - /* XPM */ - static char * dim_xpm[] = { - "16 16 6 1", - " c None", - ". c #000000", - "+ c #FFFF00", - "@ c #FFFFFF", - "$ c #141010", - "# c #615BD2", - " $$$$$$$$", - " $##$$#$$", - " . $##$$##$", - " .. $##$$##$", - " .+. $######$", - " .++. $##$$##$", - " .+++. .$##$$##$", - ".++++. .$######$", - " .+++. .$$$$$$$$" - " .++. .++. ", - " .+. .+. ", - " .. .. ", - " . . ", - " ", - " ", - " "}; - """ - else: - return """ - /* XPM */ - static char * dim_xpm[] = { - "16 16 4 1", - " c None", - ". c #000000", - "+ c #FFFF00", - "@ c #FFFFFF", - " ", - " ", - " . . ", - " .. .. ", - " .+. .+. ", - " .++. .++. ", - " .+++. .. .+++. ", - ".++++. .. .++++.", - " .+++. .. .+++. ", - " .++. .++. ", - " .+. .+. ", - " .. .. ", - " . . ", - " ", - " ", - " "}; - """ - - def __getstate__(self): - return None - - def __setstate__(self,state): - return None + def __getstate__(self): + return None + + def __setstate__(self,state): + return None class AngularDimension: - "The AngularDimension object" - def __init__(self, obj): - obj.addProperty("App::PropertyAngle","FirstAngle","Base", - "Start angle of the dimension") - obj.addProperty("App::PropertyAngle","LastAngle","Base", - "End angle of the dimension") - obj.addProperty("App::PropertyVector","Dimline","Base", - "Point through which the dimension line passes") - obj.addProperty("App::PropertyVector","Center","Base", - "The center point of this dimension") - obj.FirstAngle = 0 - obj.LastAngle = 90 - obj.Dimline = FreeCAD.Vector(0,1,0) - obj.Center = FreeCAD.Vector(0,0,0) - obj.Proxy = self - self.Type = "AngularDimension" - - def onChanged(self, fp, prop): - pass + "The AngularDimension object" + def __init__(self, obj): + obj.addProperty("App::PropertyAngle","FirstAngle","Base", + "Start angle of the dimension") + obj.addProperty("App::PropertyAngle","LastAngle","Base", + "End angle of the dimension") + obj.addProperty("App::PropertyVector","Dimline","Base", + "Point through which the dimension line passes") + obj.addProperty("App::PropertyVector","Center","Base", + "The center point of this dimension") + obj.FirstAngle = 0 + obj.LastAngle = 90 + obj.Dimline = FreeCAD.Vector(0,1,0) + obj.Center = FreeCAD.Vector(0,0,0) + obj.Proxy = self + self.Type = "AngularDimension" + + def onChanged(self, fp, prop): + pass - def execute(self, fp): - if fp.ViewObject: - fp.ViewObject.update() + def execute(self, fp): + if fp.ViewObject: + fp.ViewObject.update() class ViewProviderAngularDimension: - "A View Provider for the Angular Dimension object" - def __init__(self, obj): - obj.addProperty("App::PropertyLength","FontSize","Base","Font size") - obj.addProperty("App::PropertyString","FontName","Base","Font name") - obj.addProperty("App::PropertyLength","LineWidth","Base","Line width") - obj.addProperty("App::PropertyColor","LineColor","Base","Line color") - obj.addProperty("App::PropertyVector","Position","Base","The position of the text. Leave (0,0,0) for automatic position") - obj.addProperty("App::PropertyString","Override","Base","Text override. Use 'dim' to insert the dimension length") - obj.Proxy = self - obj.FontSize=getParam("textheight") - obj.FontName=getParam("textfont") - obj.Override = '' + "A View Provider for the Angular Dimension object" + def __init__(self, obj): + obj.addProperty("App::PropertyLength","FontSize","Base","Font size") + obj.addProperty("App::PropertyString","FontName","Base","Font name") + obj.addProperty("App::PropertyLength","LineWidth","Base","Line width") + obj.addProperty("App::PropertyColor","LineColor","Base","Line color") + obj.addProperty("App::PropertyVector","Position","Base","The position of the text. Leave (0,0,0) for automatic position") + obj.addProperty("App::PropertyString","Override","Base","Text override. Use 'dim' to insert the dimension length") + obj.Proxy = self + obj.FontSize=getParam("textheight") + obj.FontName=getParam("textfont") + obj.Override = '' - def attach(self, vobj): - self.Object = vobj.Object - self.arc = None - c,tbase,trot,p2,p3 = self.calcGeom(vobj.Object) - self.color = coin.SoBaseColor() - self.color.rgb.setValue(vobj.LineColor[0], - vobj.LineColor[1], - vobj.LineColor[2]) - self.font = coin.SoFont() - self.font3d = coin.SoFont() - self.text = coin.SoAsciiText() - self.text3d = coin.SoText2() - self.text.justification = self.text3d.justification = coin.SoAsciiText.CENTER - self.text.string = self.text3d.string = '' - self.textpos = coin.SoTransform() - self.textpos.translation.setValue([tbase.x,tbase.y,tbase.z]) - self.textpos.rotation = coin.SbRotation() - label = coin.SoSeparator() - label.addChild(self.textpos) - label.addChild(self.color) - label.addChild(self.font) - label.addChild(self.text) - label3d = coin.SoSeparator() - label3d.addChild(self.textpos) - label3d.addChild(self.color) - label3d.addChild(self.font3d) - label3d.addChild(self.text3d) - self.coord1 = coin.SoCoordinate3() - self.coord1.point.setValue((p2.x,p2.y,p2.z)) - self.coord2 = coin.SoCoordinate3() - self.coord2.point.setValue((p3.x,p3.y,p3.z)) - marks = coin.SoAnnotation() - marks.addChild(self.color) - marks.addChild(self.coord1) - marks.addChild(dimSymbol()) - marks.addChild(self.coord2) - marks.addChild(dimSymbol()) - self.drawstyle = coin.SoDrawStyle() - self.drawstyle.lineWidth = 1 - self.coords = coin.SoCoordinate3() - self.selnode=coin.SoType.fromName("SoFCSelection").createInstance() - self.selnode.documentName.setValue(FreeCAD.ActiveDocument.Name) - self.selnode.objectName.setValue(vobj.Object.Name) - self.selnode.subElementName.setValue("Arc") - self.node = coin.SoGroup() - self.node.addChild(self.color) - self.node.addChild(self.drawstyle) - self.node.addChild(self.coords) - self.node.addChild(self.selnode) - self.node.addChild(marks) - self.node.addChild(label) - self.node3d = coin.SoGroup() - self.node3d.addChild(self.color) - self.node3d.addChild(self.drawstyle) - self.node3d.addChild(self.coords) - self.node3d.addChild(self.selnode) - self.node3d.addChild(marks) - self.node3d.addChild(label3d) - vobj.addDisplayMode(self.node,"2D") - vobj.addDisplayMode(self.node3d,"3D") - self.onChanged(vobj,"FontSize") - self.onChanged(vobj,"FontName") + def attach(self, vobj): + self.Object = vobj.Object + self.arc = None + c,tbase,trot,p2,p3 = self.calcGeom(vobj.Object) + self.color = coin.SoBaseColor() + self.color.rgb.setValue(vobj.LineColor[0], + vobj.LineColor[1], + vobj.LineColor[2]) + self.font = coin.SoFont() + self.font3d = coin.SoFont() + self.text = coin.SoAsciiText() + self.text3d = coin.SoText2() + self.text.justification = self.text3d.justification = coin.SoAsciiText.CENTER + self.text.string = self.text3d.string = '' + self.textpos = coin.SoTransform() + self.textpos.translation.setValue([tbase.x,tbase.y,tbase.z]) + self.textpos.rotation = coin.SbRotation() + label = coin.SoSeparator() + label.addChild(self.textpos) + label.addChild(self.color) + label.addChild(self.font) + label.addChild(self.text) + label3d = coin.SoSeparator() + label3d.addChild(self.textpos) + label3d.addChild(self.color) + label3d.addChild(self.font3d) + label3d.addChild(self.text3d) + self.coord1 = coin.SoCoordinate3() + self.coord1.point.setValue((p2.x,p2.y,p2.z)) + self.coord2 = coin.SoCoordinate3() + self.coord2.point.setValue((p3.x,p3.y,p3.z)) + marks = coin.SoAnnotation() + marks.addChild(self.color) + marks.addChild(self.coord1) + marks.addChild(dimSymbol()) + marks.addChild(self.coord2) + marks.addChild(dimSymbol()) + self.drawstyle = coin.SoDrawStyle() + self.drawstyle.lineWidth = 1 + self.coords = coin.SoCoordinate3() + self.selnode=coin.SoType.fromName("SoFCSelection").createInstance() + self.selnode.documentName.setValue(FreeCAD.ActiveDocument.Name) + self.selnode.objectName.setValue(vobj.Object.Name) + self.selnode.subElementName.setValue("Arc") + self.node = coin.SoGroup() + self.node.addChild(self.color) + self.node.addChild(self.drawstyle) + self.node.addChild(self.coords) + self.node.addChild(self.selnode) + self.node.addChild(marks) + self.node.addChild(label) + self.node3d = coin.SoGroup() + self.node3d.addChild(self.color) + self.node3d.addChild(self.drawstyle) + self.node3d.addChild(self.coords) + self.node3d.addChild(self.selnode) + self.node3d.addChild(marks) + self.node3d.addChild(label3d) + vobj.addDisplayMode(self.node,"2D") + vobj.addDisplayMode(self.node3d,"3D") + self.onChanged(vobj,"FontSize") + self.onChanged(vobj,"FontName") - def calcGeom(self,obj): - rad = (obj.Dimline.sub(obj.Center)).Length - cir = Part.makeCircle(rad,obj.Center,Vector(0,0,1),obj.FirstAngle,obj.LastAngle) - cp = fcgeo.findMidpoint(cir.Edges[0]) - rv = cp.sub(obj.Center) - rv = fcvec.scaleTo(rv,rv.Length + obj.ViewObject.FontSize*.2) - tbase = obj.Center.add(rv) - trot = fcvec.angle(rv)-math.pi/2 - if (trot > math.pi/2) or (trot < -math.pi/2): - trot = trot + math.pi - s = getParam("dimorientation") - if s == 0: - if round(trot,precision()) == round(-math.pi/2,precision()): - trot = math.pi/2 - return cir, tbase, trot, cir.Vertexes[0].Point, cir.Vertexes[-1].Point + def calcGeom(self,obj): + rad = (obj.Dimline.sub(obj.Center)).Length + cir = Part.makeCircle(rad,obj.Center,Vector(0,0,1),obj.FirstAngle,obj.LastAngle) + cp = fcgeo.findMidpoint(cir.Edges[0]) + rv = cp.sub(obj.Center) + rv = fcvec.scaleTo(rv,rv.Length + obj.ViewObject.FontSize*.2) + tbase = obj.Center.add(rv) + trot = fcvec.angle(rv)-math.pi/2 + if (trot > math.pi/2) or (trot < -math.pi/2): + trot = trot + math.pi + s = getParam("dimorientation") + if s == 0: + if round(trot,precision()) == round(-math.pi/2,precision()): + trot = math.pi/2 + return cir, tbase, trot, cir.Vertexes[0].Point, cir.Vertexes[-1].Point - def updateData(self, obj, prop): - text = None - ivob = None - c,tbase,trot,p2,p3 = self.calcGeom(obj) - buf=c.writeInventor(2,0.01) - ivin = coin.SoInput() - ivin.setBuffer(buf) - ivob = coin.SoDB.readAll(ivin) - arc = ivob.getChildren()[1] - # In case reading from buffer failed - if ivob and ivob.getNumChildren() > 1: - arc = ivob.getChild(1).getChild(0) - arc.removeChild(arc.getChild(0)) - arc.removeChild(arc.getChild(0)) - if self.arc: - self.selnode.removeChild(self.arc) - self.arc = arc - self.selnode.addChild(self.arc) - if 'Override' in obj.ViewObject.PropertiesList: - text = str(obj.ViewObject.Override) - dtext = getParam("dimPrecision") - dtext = "%."+str(dtext)+"f" - if obj.LastAngle > obj.FirstAngle: - dtext = (dtext % (obj.LastAngle-obj.FirstAngle))+'\xb0' - else: - dtext = (dtext % ((360-obj.FirstAngle)+obj.LastAngle))+'\xb0' - if text: - text = text.replace("dim",dtext) - else: - text = dtext - self.text.string = self.text3d.string = text - self.textpos.translation.setValue([tbase.x,tbase.y,tbase.z]) - m = FreeCAD.Matrix() - m.rotateZ(trot) - tm = FreeCAD.Placement(m).Rotation.Q - self.textpos.rotation = coin.SbRotation(tm[0],tm[1],tm[2],tm[3]) - self.coord1.point.setValue((p2.x,p2.y,p2.z)) - self.coord2.point.setValue((p3.x,p3.y,p3.z)) + def updateData(self, obj, prop): + text = None + ivob = None + c,tbase,trot,p2,p3 = self.calcGeom(obj) + buf=c.writeInventor(2,0.01) + ivin = coin.SoInput() + ivin.setBuffer(buf) + ivob = coin.SoDB.readAll(ivin) + arc = ivob.getChildren()[1] + # In case reading from buffer failed + if ivob and ivob.getNumChildren() > 1: + arc = ivob.getChild(1).getChild(0) + arc.removeChild(arc.getChild(0)) + arc.removeChild(arc.getChild(0)) + if self.arc: + self.selnode.removeChild(self.arc) + self.arc = arc + self.selnode.addChild(self.arc) + if 'Override' in obj.ViewObject.PropertiesList: + text = str(obj.ViewObject.Override) + dtext = getParam("dimPrecision") + dtext = "%."+str(dtext)+"f" + if obj.LastAngle > obj.FirstAngle: + dtext = (dtext % (obj.LastAngle-obj.FirstAngle))+'\xb0' + else: + dtext = (dtext % ((360-obj.FirstAngle)+obj.LastAngle))+'\xb0' + if text: + text = text.replace("dim",dtext) + else: + text = dtext + self.text.string = self.text3d.string = text + self.textpos.translation.setValue([tbase.x,tbase.y,tbase.z]) + m = FreeCAD.Matrix() + m.rotateZ(trot) + tm = FreeCAD.Placement(m).Rotation.Q + self.textpos.rotation = coin.SbRotation(tm[0],tm[1],tm[2],tm[3]) + self.coord1.point.setValue((p2.x,p2.y,p2.z)) + self.coord2.point.setValue((p3.x,p3.y,p3.z)) - def onChanged(self, vobj, prop): - if prop == "FontSize": - self.font.size = vobj.FontSize - self.font3d.size = vobj.FontSize*100 - elif prop == "FontName": - self.font.name = self.font3d.name = str(vobj.FontName) - elif prop == "LineColor": - c = vobj.LineColor - self.color.rgb.setValue(c[0],c[1],c[2]) - elif prop == "LineWidth": - self.drawstyle.lineWidth = vobj.LineWidth - elif prop == "DisplayMode": - pass - else: - self.updateData(vobj.Object, None) + def onChanged(self, vobj, prop): + if prop == "FontSize": + self.font.size = vobj.FontSize + self.font3d.size = vobj.FontSize*100 + elif prop == "FontName": + self.font.name = self.font3d.name = str(vobj.FontName) + elif prop == "LineColor": + c = vobj.LineColor + self.color.rgb.setValue(c[0],c[1],c[2]) + elif prop == "LineWidth": + self.drawstyle.lineWidth = vobj.LineWidth + elif prop == "DisplayMode": + pass + else: + self.updateData(vobj.Object, None) - def getDisplayModes(self,obj): - modes=[] - modes.extend(["2D","3D"]) - return modes + def getDisplayModes(self,obj): + modes=[] + modes.extend(["2D","3D"]) + return modes - def getDefaultDisplayMode(self): - return "2D" + def getDefaultDisplayMode(self): + return "2D" - def getIcon(self): - return """ + def getIcon(self): + return """ /* XPM */ static char * dim_xpm[] = { "16 16 4 1", @@ -1676,395 +1675,395 @@ class ViewProviderAngularDimension: """ class Rectangle: - "The Rectangle object" + "The Rectangle object" - def __init__(self, obj): - obj.addProperty("App::PropertyDistance","Length","Base","Length of the rectangle") - obj.addProperty("App::PropertyDistance","Height","Base","Height of the rectange") - obj.Proxy = self - obj.Length=1 - obj.Height=1 - self.Type = "Rectangle" + def __init__(self, obj): + obj.addProperty("App::PropertyDistance","Length","Base","Length of the rectangle") + obj.addProperty("App::PropertyDistance","Height","Base","Height of the rectange") + obj.Proxy = self + obj.Length=1 + obj.Height=1 + self.Type = "Rectangle" - def execute(self, fp): - self.createGeometry(fp) + def execute(self, fp): + self.createGeometry(fp) - def onChanged(self, fp, prop): - if prop in ["Length","Height"]: - self.createGeometry(fp) + def onChanged(self, fp, prop): + if prop in ["Length","Height"]: + self.createGeometry(fp) - def createGeometry(self,fp): - plm = fp.Placement - p1 = Vector(0,0,0) - p2 = Vector(p1.x+fp.Length,p1.y,p1.z) - p3 = Vector(p1.x+fp.Length,p1.y+fp.Height,p1.z) - p4 = Vector(p1.x,p1.y+fp.Height,p1.z) - shape = Part.makePolygon([p1,p2,p3,p4,p1]) - shape = Part.Face(shape) - fp.Shape = shape - fp.Placement = plm + def createGeometry(self,fp): + plm = fp.Placement + p1 = Vector(0,0,0) + p2 = Vector(p1.x+fp.Length,p1.y,p1.z) + p3 = Vector(p1.x+fp.Length,p1.y+fp.Height,p1.z) + p4 = Vector(p1.x,p1.y+fp.Height,p1.z) + shape = Part.makePolygon([p1,p2,p3,p4,p1]) + shape = Part.Face(shape) + fp.Shape = shape + fp.Placement = plm class ViewProviderRectangle(ViewProviderDraft): - "A View Provider for the Rectangle object" - def __init__(self, obj): - ViewProviderDraft.__init__(self,obj) - obj.addProperty("App::PropertyFile","TextureImage", - "Base","Uses an image as a texture map") + "A View Provider for the Rectangle object" + def __init__(self, obj): + ViewProviderDraft.__init__(self,obj) + obj.addProperty("App::PropertyFile","TextureImage", + "Base","Uses an image as a texture map") - def attach(self,obj): - self.texture = None + def attach(self,obj): + self.texture = None - def onChanged(self, vp, prop): - if prop == "TextureImage": - r = vp.RootNode - if os.path.exists(vp.TextureImage): - self.texture = coin.SoTexture2() - self.texture.filename = str(vp.TextureImage) - r.insertChild(self.texture,1) - else: - if self.texture: - r.removeChild(self.texture) - self.texture = None - return + def onChanged(self, vp, prop): + if prop == "TextureImage": + r = vp.RootNode + if os.path.exists(vp.TextureImage): + self.texture = coin.SoTexture2() + self.texture.filename = str(vp.TextureImage) + r.insertChild(self.texture,1) + else: + if self.texture: + r.removeChild(self.texture) + self.texture = None + return class Circle: - "The Circle object" + "The Circle object" - def __init__(self, obj): - obj.addProperty("App::PropertyAngle","FirstAngle","Arc", - "Start angle of the arc") - obj.addProperty("App::PropertyAngle","LastAngle","Arc", - "End angle of the arc (for a full circle, give it same value as First Angle)") - obj.addProperty("App::PropertyDistance","Radius","Base", - "Radius of the circle") - obj.Proxy = self - self.Type = "Circle" + def __init__(self, obj): + obj.addProperty("App::PropertyAngle","FirstAngle","Arc", + "Start angle of the arc") + obj.addProperty("App::PropertyAngle","LastAngle","Arc", + "End angle of the arc (for a full circle, give it same value as First Angle)") + obj.addProperty("App::PropertyDistance","Radius","Base", + "Radius of the circle") + obj.Proxy = self + self.Type = "Circle" - def execute(self, fp): - self.createGeometry(fp) + def execute(self, fp): + self.createGeometry(fp) - def onChanged(self, fp, prop): - if prop in ["Radius","FirstAngle","LastAngle"]: - self.createGeometry(fp) + def onChanged(self, fp, prop): + if prop in ["Radius","FirstAngle","LastAngle"]: + self.createGeometry(fp) - def createGeometry(self,fp): - plm = fp.Placement - shape = Part.makeCircle(fp.Radius,Vector(0,0,0), - Vector(0,0,1),fp.FirstAngle,fp.LastAngle) - if fp.FirstAngle == fp.LastAngle: - shape = Part.Wire(shape) - shape = Part.Face(shape) - fp.Shape = shape - fp.Placement = plm + def createGeometry(self,fp): + plm = fp.Placement + shape = Part.makeCircle(fp.Radius,Vector(0,0,0), + Vector(0,0,1),fp.FirstAngle,fp.LastAngle) + if fp.FirstAngle == fp.LastAngle: + shape = Part.Wire(shape) + shape = Part.Face(shape) + fp.Shape = shape + fp.Placement = plm class Wire: - "The Wire object" + "The Wire object" - def __init__(self, obj): - obj.addProperty("App::PropertyVectorList","Points","Base", - "The vertices of the wire") - obj.addProperty("App::PropertyBool","Closed","Base", - "If the wire is closed or not") - obj.addProperty("App::PropertyLink","Base","Base", - "The base object is the wire is formed from 2 objects") - obj.addProperty("App::PropertyLink","Tool","Base", - "The tool object is the wire is formed from 2 objects") - obj.Proxy = self - obj.Closed = False - self.Type = "Wire" + def __init__(self, obj): + obj.addProperty("App::PropertyVectorList","Points","Base", + "The vertices of the wire") + obj.addProperty("App::PropertyBool","Closed","Base", + "If the wire is closed or not") + obj.addProperty("App::PropertyLink","Base","Base", + "The base object is the wire is formed from 2 objects") + obj.addProperty("App::PropertyLink","Tool","Base", + "The tool object is the wire is formed from 2 objects") + obj.Proxy = self + obj.Closed = False + self.Type = "Wire" - def execute(self, fp): - self.createGeometry(fp) + def execute(self, fp): + self.createGeometry(fp) - def onChanged(self, fp, prop): - if prop in ["Points","Closed","Base","Tool"]: - self.createGeometry(fp) + def onChanged(self, fp, prop): + if prop in ["Points","Closed","Base","Tool"]: + self.createGeometry(fp) - def createGeometry(self,fp): - plm = fp.Placement - if fp.Base and (not fp.Tool): - if fp.Base.isDerivedFrom("Sketcher::SketchObject"): - shape = fp.Base.Shape.copy() - if fp.Base.Shape.isClosed(): - shape = Part.Face(shape) - fp.Shape = shape - p = [] - for v in shape.Vertexes: p.append(v.Point) - if fp.Points != p: fp.Points = p - elif fp.Base and fp.Tool: - if ('Shape' in fp.Base.PropertiesList) and ('Shape' in fp.Tool.PropertiesList): - sh1 = fp.Base.Shape.copy() - sh2 = fp.Tool.Shape.copy() - shape = sh1.fuse(sh2) - if fcgeo.isCoplanar(shape.Faces): - shape = fcgeo.concatenate(shape) - fp.Shape = shape - p = [] - for v in shape.Vertexes: p.append(v.Point) - if fp.Points != p: fp.Points = p - elif fp.Points: - if fp.Points[0] == fp.Points[-1]: - if not fp.Closed: fp.Closed = True - fp.Points.pop() - if fp.Closed and (len(fp.Points) > 2): - shape = Part.makePolygon(fp.Points+[fp.Points[0]]) - shape = Part.Face(shape) - else: - edges = [] - pts = fp.Points[1:] - lp = fp.Points[0] - for p in pts: - edges.append(Part.Line(lp,p).toShape()) - lp = p - shape = Part.Wire(edges) - fp.Shape = shape - fp.Placement = plm + def createGeometry(self,fp): + plm = fp.Placement + if fp.Base and (not fp.Tool): + if fp.Base.isDerivedFrom("Sketcher::SketchObject"): + shape = fp.Base.Shape.copy() + if fp.Base.Shape.isClosed(): + shape = Part.Face(shape) + fp.Shape = shape + p = [] + for v in shape.Vertexes: p.append(v.Point) + if fp.Points != p: fp.Points = p + elif fp.Base and fp.Tool: + if ('Shape' in fp.Base.PropertiesList) and ('Shape' in fp.Tool.PropertiesList): + sh1 = fp.Base.Shape.copy() + sh2 = fp.Tool.Shape.copy() + shape = sh1.fuse(sh2) + if fcgeo.isCoplanar(shape.Faces): + shape = fcgeo.concatenate(shape) + fp.Shape = shape + p = [] + for v in shape.Vertexes: p.append(v.Point) + if fp.Points != p: fp.Points = p + elif fp.Points: + if fp.Points[0] == fp.Points[-1]: + if not fp.Closed: fp.Closed = True + fp.Points.pop() + if fp.Closed and (len(fp.Points) > 2): + shape = Part.makePolygon(fp.Points+[fp.Points[0]]) + shape = Part.Face(shape) + else: + edges = [] + pts = fp.Points[1:] + lp = fp.Points[0] + for p in pts: + edges.append(Part.Line(lp,p).toShape()) + lp = p + shape = Part.Wire(edges) + fp.Shape = shape + fp.Placement = plm class ViewProviderWire(ViewProviderDraft): - "A View Provider for the Wire object" - def __init__(self, obj): - ViewProviderDraft.__init__(self,obj) - obj.addProperty("App::PropertyBool","EndArrow","Base", - "Displays a dim symbol at the end of the wire") + "A View Provider for the Wire object" + def __init__(self, obj): + ViewProviderDraft.__init__(self,obj) + obj.addProperty("App::PropertyBool","EndArrow","Base", + "Displays a dim symbol at the end of the wire") - def attach(self, obj): - self.Object = obj.Object - col = coin.SoBaseColor() - col.rgb.setValue(obj.LineColor[0], - obj.LineColor[1], - obj.LineColor[2]) - self.coords = coin.SoCoordinate3() - self.pt = coin.SoAnnotation() - self.pt.addChild(col) - self.pt.addChild(self.coords) - self.pt.addChild(dimSymbol()) + def attach(self, obj): + self.Object = obj.Object + col = coin.SoBaseColor() + col.rgb.setValue(obj.LineColor[0], + obj.LineColor[1], + obj.LineColor[2]) + self.coords = coin.SoCoordinate3() + self.pt = coin.SoAnnotation() + self.pt.addChild(col) + self.pt.addChild(self.coords) + self.pt.addChild(dimSymbol()) - def updateData(self, obj, prop): - if prop == "Points": - if obj.Points: - p = obj.Points[-1] - self.coords.point.setValue((p.x,p.y,p.z)) - return + def updateData(self, obj, prop): + if prop == "Points": + if obj.Points: + p = obj.Points[-1] + self.coords.point.setValue((p.x,p.y,p.z)) + return - def onChanged(self, vp, prop): - if prop == "EndArrow": - rn = vp.RootNode - if vp.EndArrow: - rn.addChild(self.pt) - else: - rn.removeChild(self.pt) - return + def onChanged(self, vp, prop): + if prop == "EndArrow": + rn = vp.RootNode + if vp.EndArrow: + rn.addChild(self.pt) + else: + rn.removeChild(self.pt) + return - def claimChildren(self): - return [self.Object.Base,self.Object.Tool] + def claimChildren(self): + return [self.Object.Base,self.Object.Tool] class Polygon: - "The Polygon object" + "The Polygon object" - def __init__(self, obj): - obj.addProperty("App::PropertyInteger","FacesNumber","Base","Number of faces") - obj.addProperty("App::PropertyDistance","Radius","Base","Radius of the control circle") - obj.addProperty("App::PropertyEnumeration","DrawMode","Base","How the polygon must be drawn from the control circle") - obj.DrawMode = ['inscribed','circumscribed'] - obj.FacesNumber = 3 - obj.Radius = 1 - obj.Proxy = self - self.Type = "Polygon" + def __init__(self, obj): + obj.addProperty("App::PropertyInteger","FacesNumber","Base","Number of faces") + obj.addProperty("App::PropertyDistance","Radius","Base","Radius of the control circle") + obj.addProperty("App::PropertyEnumeration","DrawMode","Base","How the polygon must be drawn from the control circle") + obj.DrawMode = ['inscribed','circumscribed'] + obj.FacesNumber = 3 + obj.Radius = 1 + obj.Proxy = self + self.Type = "Polygon" - def execute(self, fp): - self.createGeometry(fp) + def execute(self, fp): + self.createGeometry(fp) - def onChanged(self, fp, prop): - if prop in ["FacesNumber","Radius","DrawMode"]: - self.createGeometry(fp) + def onChanged(self, fp, prop): + if prop in ["FacesNumber","Radius","DrawMode"]: + self.createGeometry(fp) - def createGeometry(self,fp): - plm = fp.Placement - angle = (math.pi*2)/fp.FacesNumber - if fp.DrawMode == 'inscribed': - delta = fp.Radius - else: - delta = fp.Radius/math.cos(angle/2) - pts = [Vector(delta,0,0)] - for i in range(fp.FacesNumber-1): - ang = (i+1)*angle - pts.append(Vector(delta*math.cos(ang),delta*math.sin(ang),0)) - pts.append(pts[0]) - shape = Part.makePolygon(pts) - shape = Part.Face(shape) - fp.Shape = shape - fp.Placement = plm + def createGeometry(self,fp): + plm = fp.Placement + angle = (math.pi*2)/fp.FacesNumber + if fp.DrawMode == 'inscribed': + delta = fp.Radius + else: + delta = fp.Radius/math.cos(angle/2) + pts = [Vector(delta,0,0)] + for i in range(fp.FacesNumber-1): + ang = (i+1)*angle + pts.append(Vector(delta*math.cos(ang),delta*math.sin(ang),0)) + pts.append(pts[0]) + shape = Part.makePolygon(pts) + shape = Part.Face(shape) + fp.Shape = shape + fp.Placement = plm class DrawingView: - def __init__(self, obj): - obj.addProperty("App::PropertyVector","Direction","Shape view","Projection direction") - obj.addProperty("App::PropertyFloat","LinewidthModifier","Drawing view","Modifies the linewidth of the lines inside this object") - obj.addProperty("App::PropertyFloat","TextModifier","Drawing view","Modifies the size of the texts inside this object") - obj.addProperty("App::PropertyLink","Source","Base","The linked object") - obj.addProperty("App::PropertyEnumeration","LineStyle","Drawing view","Line Style") - obj.addProperty("App::PropertyEnumeration","FillStyle","Drawing view","Shape Fill Style") - obj.LineStyle = ['continuous','dashed','dashdotted','dotted'] - fills = ['shape color'] - for f in FreeCAD.svgpatterns.keys(): - fills.append(f) - obj.FillStyle = fills + def __init__(self, obj): + obj.addProperty("App::PropertyVector","Direction","Shape view","Projection direction") + obj.addProperty("App::PropertyFloat","LinewidthModifier","Drawing view","Modifies the linewidth of the lines inside this object") + obj.addProperty("App::PropertyFloat","TextModifier","Drawing view","Modifies the size of the texts inside this object") + obj.addProperty("App::PropertyLink","Source","Base","The linked object") + obj.addProperty("App::PropertyEnumeration","LineStyle","Drawing view","Line Style") + obj.addProperty("App::PropertyEnumeration","FillStyle","Drawing view","Shape Fill Style") + obj.LineStyle = ['continuous','dashed','dashdotted','dotted'] + fills = ['shape color'] + for f in FreeCAD.svgpatterns.keys(): + fills.append(f) + obj.FillStyle = fills - obj.Proxy = self - obj.LinewidthModifier = 100 - obj.TextModifier = 100 - self.Type = "DrawingView" + obj.Proxy = self + obj.LinewidthModifier = 100 + obj.TextModifier = 100 + self.Type = "DrawingView" - def execute(self, obj): - if obj.Source: - obj.ViewResult = self.updateSVG(obj) + def execute(self, obj): + if obj.Source: + obj.ViewResult = self.updateSVG(obj) - def onChanged(self, obj, prop): - if prop in ["X","Y","Scale","LinewidthModifier","TextModifier","LineStyle","FillStyle","Direction"]: - obj.ViewResult = self.updateSVG(obj) + def onChanged(self, obj, prop): + if prop in ["X","Y","Scale","LinewidthModifier","TextModifier","LineStyle","FillStyle","Direction"]: + obj.ViewResult = self.updateSVG(obj) - def updateSVG(self, obj): - "encapsulates a svg fragment into a transformation node" - svg = getSVG(obj.Source,obj.LinewidthModifier,obj.TextModifier,obj.LineStyle,obj.FillStyle,obj.Direction) - result = '' - result += ' 2): - spline = Part.BSplineCurve() - spline.interpolate(fp.Points, True) - # DNC: bug fix: convert to face if closed - shape = Part.Wire(spline.toShape()) - shape = Part.Face(shape) - fp.Shape = shape - else: - spline = Part.BSplineCurve() - spline.interpolate(fp.Points, False) - fp.Shape = spline.toShape() - fp.Placement = plm + def createGeometry(self,fp): + plm = fp.Placement + if fp.Points: + if fp.Points[0] == fp.Points[-1]: + if not fp.Closed: fp.Closed = True + fp.Points.pop() + if fp.Closed and (len(fp.Points) > 2): + spline = Part.BSplineCurve() + spline.interpolate(fp.Points, True) + # DNC: bug fix: convert to face if closed + shape = Part.Wire(spline.toShape()) + shape = Part.Face(shape) + fp.Shape = shape + else: + spline = Part.BSplineCurve() + spline.interpolate(fp.Points, False) + fp.Shape = spline.toShape() + fp.Placement = plm class ViewProviderBSpline(ViewProviderDraft): - "A View Provider for the BSPline object" - def __init__(self, obj): - ViewProviderDraft.__init__(self,obj) - obj.addProperty("App::PropertyBool","EndArrow", - "Base","Displays a dim symbol at the end of the wire") - col = coin.SoBaseColor() - col.rgb.setValue(obj.LineColor[0], - obj.LineColor[1], - obj.LineColor[2]) - self.coords = coin.SoCoordinate3() - self.pt = coin.SoAnnotation() - self.pt.addChild(col) - self.pt.addChild(self.coords) - self.pt.addChild(dimSymbol()) + "A View Provider for the BSPline object" + def __init__(self, obj): + ViewProviderDraft.__init__(self,obj) + obj.addProperty("App::PropertyBool","EndArrow", + "Base","Displays a dim symbol at the end of the wire") + col = coin.SoBaseColor() + col.rgb.setValue(obj.LineColor[0], + obj.LineColor[1], + obj.LineColor[2]) + self.coords = coin.SoCoordinate3() + self.pt = coin.SoAnnotation() + self.pt.addChild(col) + self.pt.addChild(self.coords) + self.pt.addChild(dimSymbol()) - def updateData(self, obj, prop): - if prop == "Points": - if obj.Points: - p = obj.Points[-1] - self.coords.point.setValue((p.x,p.y,p.z)) - return + def updateData(self, obj, prop): + if prop == "Points": + if obj.Points: + p = obj.Points[-1] + self.coords.point.setValue((p.x,p.y,p.z)) + return - def onChanged(self, vp, prop): - if prop == "EndArrow": - rn = vp.RootNode - if vp.EndArrow: - rn.addChild(self.pt) - else: - rn.removeChild(self.pt) - return + def onChanged(self, vp, prop): + if prop == "EndArrow": + rn = vp.RootNode + if vp.EndArrow: + rn.addChild(self.pt) + else: + rn.removeChild(self.pt) + return class Block: - "The Block object" - - def __init__(self, obj): - obj.addProperty("App::PropertyLinkList","Components","Base", - "The components of this block") - obj.Proxy = self - self.Type = "Block" + "The Block object" + + def __init__(self, obj): + obj.addProperty("App::PropertyLinkList","Components","Base", + "The components of this block") + obj.Proxy = self + self.Type = "Block" - def execute(self, fp): - self.createGeometry(fp) + def execute(self, fp): + self.createGeometry(fp) - def onChanged(self, fp, prop): - if prop in ["Components"]: - self.createGeometry(fp) + def onChanged(self, fp, prop): + if prop in ["Components"]: + self.createGeometry(fp) - def createGeometry(self,fp): - plm = fp.Placement - shps = [] - for c in fp.Components: - shps.append(c.Shape) - if shps: - shape = Part.makeCompound(shps) - fp.Shape = shape - fp.Placement = plm + def createGeometry(self,fp): + plm = fp.Placement + shps = [] + for c in fp.Components: + shps.append(c.Shape) + if shps: + shape = Part.makeCompound(shps) + fp.Shape = shape + fp.Placement = plm class ViewProviderBlock(ViewProviderDraft): - "A View Provider for the Block object" + "A View Provider for the Block object" - def claimChildren(self): - return self.Object.Components + def claimChildren(self): + return self.Object.Components class Shape2DView: - "The Shape2DView object" + "The Shape2DView object" - def __init__(self,obj): - obj.addProperty("App::PropertyLink","Base","Base", - "The base object this 2D view must represent") - obj.addProperty("App::PropertyVector","Projection","Base", - "The projection vector of this object") - obj.Projection = Vector(0,0,-1) - obj.Proxy = self - self.Type = "2DShapeView" + def __init__(self,obj): + obj.addProperty("App::PropertyLink","Base","Base", + "The base object this 2D view must represent") + obj.addProperty("App::PropertyVector","Projection","Base", + "The projection vector of this object") + obj.Projection = Vector(0,0,-1) + obj.Proxy = self + self.Type = "2DShapeView" - def execute(self,obj): - self.createGeometry(obj) + def execute(self,obj): + self.createGeometry(obj) - def onChanged(self,obj,prop): - if prop in ["Projection","Base"]: - print "changing",prop - self.createGeometry(obj) + def onChanged(self,obj,prop): + if prop in ["Projection","Base"]: + print "changing",prop + self.createGeometry(obj) - def createGeometry(self,obj): - pl = obj.Placement - if obj.Base: - if obj.Base.isDerivedFrom("Part::Feature"): - [visibleG0,visibleG1,hiddenG0,hiddenG1] = Drawing.project(obj.Base.Shape,obj.Projection) - print visibleG0.Edges - if visibleG0: - obj.Shape = visibleG0 - if not fcgeo.isNull(pl): - obj.Placement = pl + def createGeometry(self,obj): + pl = obj.Placement + if obj.Base: + if obj.Base.isDerivedFrom("Part::Feature"): + [visibleG0,visibleG1,hiddenG0,hiddenG1] = Drawing.project(obj.Base.Shape,obj.Projection) + print visibleG0.Edges + if visibleG0: + obj.Shape = visibleG0 + if not fcgeo.isNull(pl): + obj.Placement = pl diff --git a/src/Mod/Draft/InitGui.py b/src/Mod/Draft/InitGui.py index cbb537c97..fd59394b5 100644 --- a/src/Mod/Draft/InitGui.py +++ b/src/Mod/Draft/InitGui.py @@ -29,200 +29,200 @@ import os class DraftWorkbench (Workbench): - "the Draft Workbench" - Icon = """ - /* XPM */ - static char * draft_xpm[] = { - "14 16 96 2", - " c None", - ". c #584605", - "+ c #513E03", - "@ c #E6B50D", - "# c #C29F0E", - "$ c #6E5004", - "% c #F7BD0B", - "& c #8F7008", - "* c #F3C711", - "= c #B1950F", - "- c #785402", - "; c #946C05", - "> c #FABF0B", - ", c #F7C20E", - "' c #8D740A", - ") c #F8D115", - "! c #9F8A0F", - "~ c #593D00", - "{ c #FEB304", - "] c #F3B208", - "^ c #987407", - "/ c #FDC70E", - "( c #EFC311", - "_ c #8F790C", - ": c #FBDA18", - "< c #8B7C0F", - "[ c #B88203", - "} c #FEBA08", - "| c #E7B00A", - "1 c #A17E09", - "2 c #FCCE12", - "3 c #E6C213", - "4 c #96830E", - "5 c #FBE11C", - "6 c #786F0F", - "7 c #CA9406", - "8 c #FDC10B", - "9 c #D8AA0C", - "0 c #AE8E0C", - "a c #FCD415", - "b c #DBBF15", - "c c #A09012", - "d c #F9E61F", - "e c #69650E", - "f c #4B3702", - "g c #DAA609", - "h c #CAA50E", - "i c #BB9D10", - "j c #FCDB18", - "k c #CEB817", - "l c #AB9E15", - "m c #F2E821", - "n c #5E5C0E", - "o c #503D03", - "p c #E8B60D", - "q c #CAAF13", - "r c #C1B218", - "s c #B6AE19", - "t c #EAE625", - "u c #575723", - "v c #594605", - "w c #F1C511", - "x c #AB9510", - "y c #D7C018", - "z c #FBE81F", - "A c #B3AC18", - "B c #BCB81D", - "C c #7F8051", - "D c #645207", - "E c #9D8C11", - "F c #E4D31C", - "G c #BEB62F", - "H c #6C6A3F", - "I c #E1E1E1", - "J c #73610A", - "K c #7C720F", - "L c #A1A084", - "M c #FFFFFF", - "N c #565656", - "O c #887921", - "P c #988F44", - "Q c #BFBEB7", - "R c #EEEEEC", - "S c #C0C0C0", - "T c #323232", - "U c #4D4B39", - "V c #C7C7C7", - "W c #FBFBFB", - "X c #BFBFBF", - "Y c #141414", - "Z c #222222", - "` c #303030", - " . c #313131", - ".. c #282828", - "+. c #121212", - "@. c #000000", - " . ", - " + @ # ", - " $ % & * = ", - " - ; > , ' ) ! ", - "~ { ] ^ / ( _ : < ", - " [ } | 1 2 3 4 5 6 ", - " 7 8 9 0 a b c d e ", - " f g / h i j k l m n ", - " o p 2 i q 5 r s t u ", - " v w a x y z A B C ", - " D ) j E F G H I ", - " J : 5 K L M M N ", - " O P Q R M S T ", - " U V W X Y Z ", - " ` ...+.", - " @.@.@.@.@.@.@.@. "}; - """ + "the Draft Workbench" + Icon = """ + /* XPM */ + static char * draft_xpm[] = { + "14 16 96 2", + " c None", + ". c #584605", + "+ c #513E03", + "@ c #E6B50D", + "# c #C29F0E", + "$ c #6E5004", + "% c #F7BD0B", + "& c #8F7008", + "* c #F3C711", + "= c #B1950F", + "- c #785402", + "; c #946C05", + "> c #FABF0B", + ", c #F7C20E", + "' c #8D740A", + ") c #F8D115", + "! c #9F8A0F", + "~ c #593D00", + "{ c #FEB304", + "] c #F3B208", + "^ c #987407", + "/ c #FDC70E", + "( c #EFC311", + "_ c #8F790C", + ": c #FBDA18", + "< c #8B7C0F", + "[ c #B88203", + "} c #FEBA08", + "| c #E7B00A", + "1 c #A17E09", + "2 c #FCCE12", + "3 c #E6C213", + "4 c #96830E", + "5 c #FBE11C", + "6 c #786F0F", + "7 c #CA9406", + "8 c #FDC10B", + "9 c #D8AA0C", + "0 c #AE8E0C", + "a c #FCD415", + "b c #DBBF15", + "c c #A09012", + "d c #F9E61F", + "e c #69650E", + "f c #4B3702", + "g c #DAA609", + "h c #CAA50E", + "i c #BB9D10", + "j c #FCDB18", + "k c #CEB817", + "l c #AB9E15", + "m c #F2E821", + "n c #5E5C0E", + "o c #503D03", + "p c #E8B60D", + "q c #CAAF13", + "r c #C1B218", + "s c #B6AE19", + "t c #EAE625", + "u c #575723", + "v c #594605", + "w c #F1C511", + "x c #AB9510", + "y c #D7C018", + "z c #FBE81F", + "A c #B3AC18", + "B c #BCB81D", + "C c #7F8051", + "D c #645207", + "E c #9D8C11", + "F c #E4D31C", + "G c #BEB62F", + "H c #6C6A3F", + "I c #E1E1E1", + "J c #73610A", + "K c #7C720F", + "L c #A1A084", + "M c #FFFFFF", + "N c #565656", + "O c #887921", + "P c #988F44", + "Q c #BFBEB7", + "R c #EEEEEC", + "S c #C0C0C0", + "T c #323232", + "U c #4D4B39", + "V c #C7C7C7", + "W c #FBFBFB", + "X c #BFBFBF", + "Y c #141414", + "Z c #222222", + "` c #303030", + " . c #313131", + ".. c #282828", + "+. c #121212", + "@. c #000000", + " . ", + " + @ # ", + " $ % & * = ", + " - ; > , ' ) ! ", + "~ { ] ^ / ( _ : < ", + " [ } | 1 2 3 4 5 6 ", + " 7 8 9 0 a b c d e ", + " f g / h i j k l m n ", + " o p 2 i q 5 r s t u ", + " v w a x y z A B C ", + " D ) j E F G H I ", + " J : 5 K L M M N ", + " O P Q R M S T ", + " U V W X Y Z ", + " ` ...+.", + " @.@.@.@.@.@.@.@. "}; + """ - MenuText = "Draft" - ToolTip = "The Draft module is used for basic 2D CAD Drafting" + MenuText = "Draft" + ToolTip = "The Draft module is used for basic 2D CAD Drafting" - def Initialize(self): - # run self-tests - depsOK = False - try: - from pivy import coin - if FreeCADGui.getSoDBVersion() != coin.SoDB.getVersion(): - raise AssertionError("FreeCAD and Pivy use different versions of Coin. This will lead to unexpected behaviour.") - except AssertionError: - FreeCAD.Console.PrintWarning("Error: FreeCAD and Pivy use different versions of Coin. This will lead to unexpected behaviour.\n") - except ImportError: - FreeCAD.Console.PrintWarning("Error: Pivy not found, Draft workbench will be disabled.\n") - except: - FreeCAD.Console.PrintWarning("Error: Unknown error while trying to load Pivy\n") - else: - try: - import PyQt4 - except ImportError: - FreeCAD.Console.PrintWarning("Error: PyQt4 not found, Draft workbench will be disabled.\n") - else: - depsOK = True + def Initialize(self): + # run self-tests + depsOK = False + try: + from pivy import coin + if FreeCADGui.getSoDBVersion() != coin.SoDB.getVersion(): + raise AssertionError("FreeCAD and Pivy use different versions of Coin. This will lead to unexpected behaviour.") + except AssertionError: + FreeCAD.Console.PrintWarning("Error: FreeCAD and Pivy use different versions of Coin. This will lead to unexpected behaviour.\n") + except ImportError: + FreeCAD.Console.PrintWarning("Error: Pivy not found, Draft workbench will be disabled.\n") + except: + FreeCAD.Console.PrintWarning("Error: Unknown error while trying to load Pivy\n") + else: + try: + import PyQt4 + except ImportError: + FreeCAD.Console.PrintWarning("Error: PyQt4 not found, Draft workbench will be disabled.\n") + else: + depsOK = True - if depsOK: - import Draft_rc - FreeCADGui.addLanguagePath(":/translations") - FreeCADGui.addIconPath(":/icons") - FreeCADGui.addPreferencePage(":/ui/userprefs-base.ui","Draft") - FreeCADGui.addPreferencePage(":/ui/userprefs-import.ui","Draft") - else: - return - Log ('Loading Draft GUI...\n') - try: - import draftTools,draftGui,macros - self.appendMenu(["&Macro","Installed Macros"],macros.macrosList) - except: - pass - self.cmdList = ["Draft_Line","Draft_Wire","Draft_Circle","Draft_Arc", - "Draft_Polygon","Draft_Rectangle", "Draft_Text", - "Draft_Dimension", "Draft_BSpline"] - self.modList = ["Draft_Move","Draft_Rotate","Draft_Offset", - "Draft_Trimex", "Draft_Upgrade", "Draft_Downgrade", "Draft_Scale", - "Draft_Drawing","Draft_Edit","Draft_WireToBSpline","Draft_AddPoint", - "Draft_DelPoint","Draft_Shape2DView"] - self.treecmdList = ["Draft_ApplyStyle","Draft_ToggleDisplayMode","Draft_AddToGroup","Draft_SelectGroup"] - self.lineList = ["Draft_UndoLine","Draft_FinishLine","Draft_CloseLine"] - self.appendToolbar("Draft tools",self.cmdList+self.modList) - self.appendMenu("Draft",self.cmdList+self.modList) - self.appendMenu(["Draft","Display options"],self.treecmdList) - self.appendMenu(["Draft","Wire tools"],self.lineList) + if depsOK: + import Draft_rc + FreeCADGui.addLanguagePath(":/translations") + FreeCADGui.addIconPath(":/icons") + FreeCADGui.addPreferencePage(":/ui/userprefs-base.ui","Draft") + FreeCADGui.addPreferencePage(":/ui/userprefs-import.ui","Draft") + else: + return + Log ('Loading Draft GUI...\n') + try: + import draftTools,draftGui,macros + self.appendMenu(["&Macro","Installed Macros"],macros.macrosList) + except: + pass + self.cmdList = ["Draft_Line","Draft_Wire","Draft_Circle","Draft_Arc", + "Draft_Polygon","Draft_Rectangle", "Draft_Text", + "Draft_Dimension", "Draft_BSpline"] + self.modList = ["Draft_Move","Draft_Rotate","Draft_Offset", + "Draft_Trimex", "Draft_Upgrade", "Draft_Downgrade", "Draft_Scale", + "Draft_Drawing","Draft_Edit","Draft_WireToBSpline","Draft_AddPoint", + "Draft_DelPoint","Draft_Shape2DView"] + self.treecmdList = ["Draft_ApplyStyle","Draft_ToggleDisplayMode","Draft_AddToGroup","Draft_SelectGroup"] + self.lineList = ["Draft_UndoLine","Draft_FinishLine","Draft_CloseLine"] + self.appendToolbar("Draft tools",self.cmdList+self.modList) + self.appendMenu("Draft",self.cmdList+self.modList) + self.appendMenu(["Draft","Display options"],self.treecmdList) + self.appendMenu(["Draft","Wire tools"],self.lineList) - def Activated(self): - FreeCADGui.draftToolBar.Activated() + def Activated(self): + FreeCADGui.draftToolBar.Activated() - def Deactivated(self): - FreeCADGui.draftToolBar.Deactivated() + def Deactivated(self): + FreeCADGui.draftToolBar.Deactivated() - def ContextMenu(self, recipient): - if (recipient == "View"): - if (FreeCAD.activeDraftCommand == None): - if (FreeCADGui.Selection.getSelection() != []): - self.appendContextMenu("Draft",self.cmdList+self.modList) - self.appendContextMenu("Display options",self.treecmdList) - else: - self.appendContextMenu("Draft",self.cmdList) - else: - if (FreeCAD.activeDraftCommand.featureName == "Line"): - self.appendContextMenu("",self.lineList) + def ContextMenu(self, recipient): + if (recipient == "View"): + if (FreeCAD.activeDraftCommand == None): + if (FreeCADGui.Selection.getSelection() != []): + self.appendContextMenu("Draft",self.cmdList+self.modList) + self.appendContextMenu("Display options",self.treecmdList) else: - if (FreeCADGui.Selection.getSelection() != []): - self.appendContextMenu("Display options",self.treecmdList) + self.appendContextMenu("Draft",self.cmdList) + else: + if (FreeCAD.activeDraftCommand.featureName == "Line"): + self.appendContextMenu("",self.lineList) + else: + if (FreeCADGui.Selection.getSelection() != []): + self.appendContextMenu("Display options",self.treecmdList) - def GetClassName(self): - return "Gui::PythonWorkbench" + def GetClassName(self): + return "Gui::PythonWorkbench" FreeCADGui.addWorkbench(DraftWorkbench) App.addImportType("Autodesk DXF (*.dxf)","importDXF") diff --git a/src/Mod/Draft/draftGui.py b/src/Mod/Draft/draftGui.py index e366af55a..c80998719 100644 --- a/src/Mod/Draft/draftGui.py +++ b/src/Mod/Draft/draftGui.py @@ -33,63 +33,63 @@ Report to Draft.py for info import FreeCAD, FreeCADGui, os, Draft try: - from PyQt4 import QtCore,QtGui,QtSvg + from PyQt4 import QtCore,QtGui,QtSvg except: - FreeCAD.Console.PrintMessage("Error: Python-qt4 package must be installed on your system to use the Draft module.") + FreeCAD.Console.PrintMessage("Error: Python-qt4 package must be installed on your system to use the Draft module.") def getMainWindow(): - "returns the main window" - # using QtGui.qApp.activeWindow() isn't very reliable because if another - # widget than the mainwindow is active (e.g. a dialog) the wrong widget is - # returned - toplevel = QtGui.qApp.topLevelWidgets() - for i in toplevel: - if i.metaObject().className() == "Gui::MainWindow": - return i - raise Exception("No main window found") + "returns the main window" + # using QtGui.qApp.activeWindow() isn't very reliable because if another + # widget than the mainwindow is active (e.g. a dialog) the wrong widget is + # returned + toplevel = QtGui.qApp.topLevelWidgets() + for i in toplevel: + if i.metaObject().className() == "Gui::MainWindow": + return i + raise Exception("No main window found") class todo: - ''' static todo class, delays execution of functions. Use todo.delay - to schedule geometry manipulation that would crash coin if done in the - event callback''' + ''' static todo class, delays execution of functions. Use todo.delay + to schedule geometry manipulation that would crash coin if done in the + event callback''' - '''List of (function, argument) pairs to be executed by - QtCore.QTimer.singleShot(0,doTodo).''' - itinerary = [] - commitlist = [] + '''List of (function, argument) pairs to be executed by + QtCore.QTimer.singleShot(0,doTodo).''' + itinerary = [] + commitlist = [] + + @staticmethod + def doTasks(): + # print "debug: doing delayed tasks: commitlist: ",todo.commitlist," itinerary: ",todo.itinerary + for f, arg in todo.itinerary: + try: + # print "debug: executing",f + f(arg) + except: + wrn = "[Draft.todo] Unexpected error:" + sys.exc_info()[0] + FreeCAD.Console.PrintWarning (wrn) + todo.itinerary = [] + if todo.commitlist: + for name,func in todo.commitlist: + # print "debug: committing ",str(name) + name = str(name) + FreeCAD.ActiveDocument.openTransaction(name) + func() + FreeCAD.ActiveDocument.commitTransaction() + todo.commitlist = [] - @staticmethod - def doTasks(): - # print "debug: doing delayed tasks: commitlist: ",todo.commitlist," itinerary: ",todo.itinerary - for f, arg in todo.itinerary: - try: - # print "debug: executing",f - f(arg) - except: - wrn = "[Draft.todo] Unexpected error:" + sys.exc_info()[0] - FreeCAD.Console.PrintWarning (wrn) - todo.itinerary = [] - if todo.commitlist: - for name,func in todo.commitlist: - # print "debug: committing ",str(name) - name = str(name) - FreeCAD.ActiveDocument.openTransaction(name) - func() - FreeCAD.ActiveDocument.commitTransaction() - todo.commitlist = [] + @staticmethod + def delay (f, arg): + # print "debug: delaying",f + if todo.itinerary == []: + QtCore.QTimer.singleShot(0, todo.doTasks) + todo.itinerary.append((f,arg)) - @staticmethod - def delay (f, arg): - # print "debug: delaying",f - if todo.itinerary == []: - QtCore.QTimer.singleShot(0, todo.doTasks) - todo.itinerary.append((f,arg)) - - @staticmethod - def delayCommit (cl): - # print "debug: delaying commit",cl - QtCore.QTimer.singleShot(0, todo.doTasks) - todo.commitlist = cl + @staticmethod + def delayCommit (cl): + # print "debug: delaying commit",cl + QtCore.QTimer.singleShot(0, todo.doTasks) + todo.commitlist = cl def translate(context,text): "convenience function for Qt translator" @@ -101,955 +101,954 @@ def translate(context,text): #--------------------------------------------------------------------------- class DraftDockWidget(QtGui.QWidget): - "custom Widget that emits a resized() signal when resized" - def __init__(self,parent = None): - QtGui.QDockWidget.__init__(self,parent) - def resizeEvent(self,event): - self.emit(QtCore.SIGNAL("resized()")) - def changeEvent(self, event): - if event.type() == QtCore.QEvent.LanguageChange: - self.emit(QtCore.SIGNAL("retranslate()")) - else: - QtGui.QWidget.changeEvent(self,event) + "custom Widget that emits a resized() signal when resized" + def __init__(self,parent = None): + QtGui.QDockWidget.__init__(self,parent) + def resizeEvent(self,event): + self.emit(QtCore.SIGNAL("resized()")) + def changeEvent(self, event): + if event.type() == QtCore.QEvent.LanguageChange: + self.emit(QtCore.SIGNAL("retranslate()")) + else: + QtGui.QWidget.changeEvent(self,event) class DraftLineEdit(QtGui.QLineEdit): - "custom QLineEdit widget that has the power to catch Escape keypress" - def __init__(self, parent=None): - QtGui.QLineEdit.__init__(self, parent) - def keyPressEvent(self, event): - if event.key() == QtCore.Qt.Key_Escape: - self.emit(QtCore.SIGNAL("escaped()")) - elif event.key() == QtCore.Qt.Key_Up: - self.emit(QtCore.SIGNAL("up()")) - elif event.key() == QtCore.Qt.Key_Down: - self.emit(QtCore.SIGNAL("down()")) - elif (event.key() == QtCore.Qt.Key_Z) and QtCore.Qt.ControlModifier: - self.emit(QtCore.SIGNAL("undo()")) - else: - QtGui.QLineEdit.keyPressEvent(self, event) + "custom QLineEdit widget that has the power to catch Escape keypress" + def __init__(self, parent=None): + QtGui.QLineEdit.__init__(self, parent) + def keyPressEvent(self, event): + if event.key() == QtCore.Qt.Key_Escape: + self.emit(QtCore.SIGNAL("escaped()")) + elif event.key() == QtCore.Qt.Key_Up: + self.emit(QtCore.SIGNAL("up()")) + elif event.key() == QtCore.Qt.Key_Down: + self.emit(QtCore.SIGNAL("down()")) + elif (event.key() == QtCore.Qt.Key_Z) and QtCore.Qt.ControlModifier: + self.emit(QtCore.SIGNAL("undo()")) + else: + QtGui.QLineEdit.keyPressEvent(self, event) class DraftTaskPanel: def __init__(self,widget): - self.form = widget + self.form = widget def accept(self): - if FreeCAD.activeDraftCommand: - FreeCAD.activeDraftCommand.finish() - return True + if FreeCAD.activeDraftCommand: + FreeCAD.activeDraftCommand.finish() + return True def reject(self): - if FreeCAD.activeDraftCommand: - FreeCAD.activeDraftCommand.finish() - return True + if FreeCAD.activeDraftCommand: + FreeCAD.activeDraftCommand.finish() + return True class DraftToolBar: - "main draft Toolbar" - def __init__(self): - self.tray = None - self.sourceCmd = None - self.taskmode = Draft.getParam("UiMode") - self.paramcolor = Draft.getParam("color")>>8 - self.color = QtGui.QColor(self.paramcolor) - self.facecolor = QtGui.QColor(204,204,204) - self.linewidth = Draft.getParam("linewidth") - self.fontsize = Draft.getParam("textheight") - self.paramconstr = Draft.getParam("constructioncolor")>>8 - self.constrMode = False - self.continueMode = False - self.state = None - self.textbuffer = [] - self.crossedViews = [] - - if self.taskmode: - # only a dummy widget, since widgets are created on demand - self.baseWidget = QtGui.QWidget() - else: - # create the draft Toolbar - self.draftWidget = QtGui.QDockWidget() - self.baseWidget = DraftDockWidget() - self.draftWidget.setObjectName("draftToolbar") - self.draftWidget.setTitleBarWidget(self.baseWidget) - self.draftWidget.setWindowTitle(translate("draft", "draft Command Bar")) - self.mw = getMainWindow() - self.mw.addDockWidget(QtCore.Qt.TopDockWidgetArea,self.draftWidget) - self.draftWidget.setVisible(False) - self.draftWidget.toggleViewAction().setVisible(False) - self.mw = getMainWindow() - self.baseWidget.setObjectName("draftToolbar") - self.layout = QtGui.QHBoxLayout(self.baseWidget) - self.layout.setObjectName("layout") - self.toptray = self.layout - self.bottomtray = self.layout - self.setupToolBar() - self.setupTray() - self.setupStyle() - self.retranslateUi(self.baseWidget) + "main draft Toolbar" + def __init__(self): + self.tray = None + self.sourceCmd = None + self.taskmode = Draft.getParam("UiMode") + self.paramcolor = Draft.getParam("color")>>8 + self.color = QtGui.QColor(self.paramcolor) + self.facecolor = QtGui.QColor(204,204,204) + self.linewidth = Draft.getParam("linewidth") + self.fontsize = Draft.getParam("textheight") + self.paramconstr = Draft.getParam("constructioncolor")>>8 + self.constrMode = False + self.continueMode = False + self.state = None + self.textbuffer = [] + self.crossedViews = [] + + if self.taskmode: + # only a dummy widget, since widgets are created on demand + self.baseWidget = QtGui.QWidget() + else: + # create the draft Toolbar + self.draftWidget = QtGui.QDockWidget() + self.baseWidget = DraftDockWidget() + self.draftWidget.setObjectName("draftToolbar") + self.draftWidget.setTitleBarWidget(self.baseWidget) + self.draftWidget.setWindowTitle(translate("draft", "draft Command Bar")) + self.mw = getMainWindow() + self.mw.addDockWidget(QtCore.Qt.TopDockWidgetArea,self.draftWidget) + self.draftWidget.setVisible(False) + self.draftWidget.toggleViewAction().setVisible(False) + self.mw = getMainWindow() + self.baseWidget.setObjectName("draftToolbar") + self.layout = QtGui.QHBoxLayout(self.baseWidget) + self.layout.setObjectName("layout") + self.toptray = self.layout + self.bottomtray = self.layout + self.setupToolBar() + self.setupTray() + self.setupStyle() + self.retranslateUi(self.baseWidget) #--------------------------------------------------------------------------- # General UI setup #--------------------------------------------------------------------------- - def _pushbutton (self,name, layout, hide=True, icon=None, width=66, checkable=False): - button = QtGui.QPushButton(self.baseWidget) - button.setObjectName(name) - button.setMaximumSize(QtCore.QSize(width,26)) - if hide: - button.hide() - if icon: - button.setIcon(QtGui.QIcon(':/icons/'+icon+'.svg')) - button.setIconSize(QtCore.QSize(16, 16)) - if checkable: - button.setCheckable(True) - button.setChecked(False) - layout.addWidget(button) - return button + def _pushbutton (self,name, layout, hide=True, icon=None, width=66, checkable=False): + button = QtGui.QPushButton(self.baseWidget) + button.setObjectName(name) + button.setMaximumSize(QtCore.QSize(width,26)) + if hide: + button.hide() + if icon: + button.setIcon(QtGui.QIcon(':/icons/'+icon+'.svg')) + button.setIconSize(QtCore.QSize(16, 16)) + if checkable: + button.setCheckable(True) + button.setChecked(False) + layout.addWidget(button) + return button - def _label (self,name, layout, hide=True): - label = QtGui.QLabel(self.baseWidget) - label.setObjectName(name) - if hide: label.hide() - layout.addWidget(label) - return label + def _label (self,name, layout, hide=True): + label = QtGui.QLabel(self.baseWidget) + label.setObjectName(name) + if hide: label.hide() + layout.addWidget(label) + return label - def _lineedit (self,name, layout, hide=True, width=None): - lineedit = DraftLineEdit(self.baseWidget) - lineedit.setObjectName(name) - if hide: lineedit.hide() - if not width: width = 800 - lineedit.setMaximumSize(QtCore.QSize(width,22)) - layout.addWidget(lineedit) - return lineedit + def _lineedit (self,name, layout, hide=True, width=None): + lineedit = DraftLineEdit(self.baseWidget) + lineedit.setObjectName(name) + if hide: lineedit.hide() + if not width: width = 800 + lineedit.setMaximumSize(QtCore.QSize(width,22)) + layout.addWidget(lineedit) + return lineedit - def _spinbox (self,name, layout, val=None, vmax=None, hide=True, double=False, size=None): - if double: - sbox = QtGui.QDoubleSpinBox(self.baseWidget) - sbox.setDecimals(2) - else: - sbox = QtGui.QSpinBox(self.baseWidget) - sbox.setObjectName(name) - if val: sbox.setValue(val) - if vmax: sbox.setMaximum(vmax) - if size: sbox.setMaximumSize(QtCore.QSize(size[0],size[1])) - if hide: sbox.hide() - layout.addWidget(sbox) - return sbox + def _spinbox (self,name, layout, val=None, vmax=None, hide=True, double=False, size=None): + if double: + sbox = QtGui.QDoubleSpinBox(self.baseWidget) + sbox.setDecimals(2) + else: + sbox = QtGui.QSpinBox(self.baseWidget) + sbox.setObjectName(name) + if val: sbox.setValue(val) + if vmax: sbox.setMaximum(vmax) + if size: sbox.setMaximumSize(QtCore.QSize(size[0],size[1])) + if hide: sbox.hide() + layout.addWidget(sbox) + return sbox - def _checkbox (self,name, layout, checked=True, hide=True): - chk = QtGui.QCheckBox(self.baseWidget) - chk.setChecked(checked) - chk.setObjectName(name) - if hide: chk.hide() - layout.addWidget(chk) - return chk + def _checkbox (self,name, layout, checked=True, hide=True): + chk = QtGui.QCheckBox(self.baseWidget) + chk.setChecked(checked) + chk.setObjectName(name) + if hide: chk.hide() + layout.addWidget(chk) + return chk - def setupToolBar(self,task=False): - "sets the draft toolbar up" + def setupToolBar(self,task=False): + "sets the draft toolbar up" + + # command - # command + self.promptlabel = self._label("promptlabel", self.layout, hide=task) + self.cmdlabel = self._label("cmdlabel", self.layout, hide=task) + boldtxt = QtGui.QFont() + boldtxt.setWeight(75) + boldtxt.setBold(True) + self.cmdlabel.setFont(boldtxt) - self.promptlabel = self._label("promptlabel", self.layout, hide=task) - self.cmdlabel = self._label("cmdlabel", self.layout, hide=task) - boldtxt = QtGui.QFont() - boldtxt.setWeight(75) - boldtxt.setBold(True) - self.cmdlabel.setFont(boldtxt) + # subcommands - # subcommands + self.addButton = self._pushbutton("addButton", self.layout, icon="Draft_AddPoint", width=22, checkable=True) + self.delButton = self._pushbutton("delButton", self.layout, icon="Draft_DelPoint", width=22, checkable=True) - self.addButton = self._pushbutton("addButton", self.layout, icon="Draft_AddPoint", width=22, checkable=True) - self.delButton = self._pushbutton("delButton", self.layout, icon="Draft_DelPoint", width=22, checkable=True) + # point - # point + xl = QtGui.QHBoxLayout() + yl = QtGui.QHBoxLayout() + zl = QtGui.QHBoxLayout() + self.layout.addLayout(xl) + self.layout.addLayout(yl) + self.layout.addLayout(zl) + self.labelx = self._label("labelx", xl) + self.xValue = self._lineedit("xValue", xl, width=60) + self.xValue.setText("0.00") + self.labely = self._label("labely", yl) + self.yValue = self._lineedit("yValue", yl, width=60) + self.yValue.setText("0.00") + self.labelz = self._label("labelz", zl) + self.zValue = self._lineedit("zValue", zl, width=60) + self.zValue.setText("0.00") + self.textValue = self._lineedit("textValue", self.layout) - xl = QtGui.QHBoxLayout() - yl = QtGui.QHBoxLayout() - zl = QtGui.QHBoxLayout() - self.layout.addLayout(xl) - self.layout.addLayout(yl) - self.layout.addLayout(zl) - self.labelx = self._label("labelx", xl) - self.xValue = self._lineedit("xValue", xl, width=60) - self.xValue.setText("0.00") - self.labely = self._label("labely", yl) - self.yValue = self._lineedit("yValue", yl, width=60) - self.yValue.setText("0.00") - self.labelz = self._label("labelz", zl) - self.zValue = self._lineedit("zValue", zl, width=60) - self.zValue.setText("0.00") - self.textValue = self._lineedit("textValue", self.layout) + # options - # options + self.numFaces = self._spinbox("numFaces", self.layout, 3) + self.offsetLabel = self._label("offsetlabel", self.layout) + self.offsetValue = self._lineedit("offsetValue", self.layout, width=60) + self.offsetValue.setText("0.00") + self.labelRadius = self._label("labelRadius", self.layout) + self.radiusValue = self._lineedit("radiusValue", self.layout, width=60) + self.radiusValue.setText("0.00") + self.isRelative = self._checkbox("isRelative",self.layout,checked=True) + self.hasFill = self._checkbox("hasFill",self.layout,checked=Draft.getParam("fillmode")) + self.continueCmd = self._checkbox("continueCmd",self.layout,checked=False) + self.occOffset = self._checkbox("occOffset",self.layout,checked=False) + self.undoButton = self._pushbutton("undoButton", self.layout, icon='Draft_Rotate') + self.finishButton = self._pushbutton("finishButton", self.layout, icon='Draft_Finish') + self.closeButton = self._pushbutton("closeButton", self.layout, icon='Draft_Lock') + self.wipeButton = self._pushbutton("wipeButton", self.layout, icon='Draft_Wipe') + self.xyButton = self._pushbutton("xyButton", self.layout) + self.xzButton = self._pushbutton("xzButton", self.layout) + self.yzButton = self._pushbutton("yzButton", self.layout) + self.currentViewButton = self._pushbutton("view", self.layout) + self.resetPlaneButton = self._pushbutton("none", self.layout) + self.isCopy = self._checkbox("isCopy",self.layout,checked=False) - self.numFaces = self._spinbox("numFaces", self.layout, 3) - self.offsetLabel = self._label("offsetlabel", self.layout) - self.offsetValue = self._lineedit("offsetValue", self.layout, width=60) - self.offsetValue.setText("0.00") - self.labelRadius = self._label("labelRadius", self.layout) - self.radiusValue = self._lineedit("radiusValue", self.layout, width=60) - self.radiusValue.setText("0.00") - self.isRelative = self._checkbox("isRelative",self.layout,checked=True) - self.hasFill = self._checkbox("hasFill",self.layout,checked=Draft.getParam("fillmode")) - self.continueCmd = self._checkbox("continueCmd",self.layout,checked=False) - self.occOffset = self._checkbox("occOffset",self.layout,checked=False) - self.undoButton = self._pushbutton("undoButton", self.layout, icon='Draft_Rotate') - self.finishButton = self._pushbutton("finishButton", self.layout, icon='Draft_Finish') - self.closeButton = self._pushbutton("closeButton", self.layout, icon='Draft_Lock') - self.wipeButton = self._pushbutton("wipeButton", self.layout, icon='Draft_Wipe') - self.xyButton = self._pushbutton("xyButton", self.layout) - self.xzButton = self._pushbutton("xzButton", self.layout) - self.yzButton = self._pushbutton("yzButton", self.layout) - self.currentViewButton = self._pushbutton("view", self.layout) - self.resetPlaneButton = self._pushbutton("none", self.layout) - self.isCopy = self._checkbox("isCopy",self.layout,checked=False) + # spacer - # spacer + spacerItem = QtGui.QSpacerItem(40, 20, QtGui.QSizePolicy.Expanding, + QtGui.QSizePolicy.Minimum) + self.layout.addItem(spacerItem) + + QtCore.QObject.connect(self.xValue,QtCore.SIGNAL("returnPressed()"),self.checkx) + QtCore.QObject.connect(self.yValue,QtCore.SIGNAL("returnPressed()"),self.checky) + QtCore.QObject.connect(self.xValue,QtCore.SIGNAL("textEdited(QString)"),self.checkSpecialChars) + QtCore.QObject.connect(self.yValue,QtCore.SIGNAL("textEdited(QString)"),self.checkSpecialChars) + QtCore.QObject.connect(self.zValue,QtCore.SIGNAL("textEdited(QString)"),self.checkSpecialChars) + QtCore.QObject.connect(self.radiusValue,QtCore.SIGNAL("textEdited(QString)"),self.checkSpecialChars) + QtCore.QObject.connect(self.zValue,QtCore.SIGNAL("returnPressed()"),self.validatePoint) + QtCore.QObject.connect(self.radiusValue,QtCore.SIGNAL("returnPressed()"),self.validatePoint) + QtCore.QObject.connect(self.textValue,QtCore.SIGNAL("returnPressed()"),self.sendText) + QtCore.QObject.connect(self.textValue,QtCore.SIGNAL("escaped()"),self.finish) + QtCore.QObject.connect(self.textValue,QtCore.SIGNAL("down()"),self.sendText) + QtCore.QObject.connect(self.textValue,QtCore.SIGNAL("up()"),self.lineUp) + QtCore.QObject.connect(self.zValue,QtCore.SIGNAL("returnPressed()"),self.xValue.setFocus) + QtCore.QObject.connect(self.zValue,QtCore.SIGNAL("returnPressed()"),self.xValue.selectAll) + QtCore.QObject.connect(self.offsetValue,QtCore.SIGNAL("textEdited(QString)"),self.checkSpecialChars) + QtCore.QObject.connect(self.offsetValue,QtCore.SIGNAL("returnPressed()"),self.validatePoint) + QtCore.QObject.connect(self.addButton,QtCore.SIGNAL("toggled(bool)"),self.setAddMode) + QtCore.QObject.connect(self.delButton,QtCore.SIGNAL("toggled(bool)"),self.setDelMode) + QtCore.QObject.connect(self.finishButton,QtCore.SIGNAL("pressed()"),self.finish) + QtCore.QObject.connect(self.closeButton,QtCore.SIGNAL("pressed()"),self.closeLine) + QtCore.QObject.connect(self.wipeButton,QtCore.SIGNAL("pressed()"),self.wipeLine) + QtCore.QObject.connect(self.undoButton,QtCore.SIGNAL("pressed()"),self.undoSegment) + QtCore.QObject.connect(self.xyButton,QtCore.SIGNAL("clicked()"),self.selectXY) + QtCore.QObject.connect(self.xzButton,QtCore.SIGNAL("clicked()"),self.selectXZ) + QtCore.QObject.connect(self.yzButton,QtCore.SIGNAL("clicked()"),self.selectYZ) + QtCore.QObject.connect(self.continueCmd,QtCore.SIGNAL("stateChanged(int)"),self.setContinue) + QtCore.QObject.connect(self.currentViewButton,QtCore.SIGNAL("clicked()"),self.selectCurrentView) + QtCore.QObject.connect(self.resetPlaneButton,QtCore.SIGNAL("clicked()"),self.selectResetPlane) + QtCore.QObject.connect(self.xValue,QtCore.SIGNAL("escaped()"),self.finish) + QtCore.QObject.connect(self.xValue,QtCore.SIGNAL("undo()"),self.undoSegment) + QtCore.QObject.connect(self.yValue,QtCore.SIGNAL("escaped()"),self.finish) + QtCore.QObject.connect(self.yValue,QtCore.SIGNAL("undo()"),self.undoSegment) + QtCore.QObject.connect(self.zValue,QtCore.SIGNAL("escaped()"),self.finish) + QtCore.QObject.connect(self.zValue,QtCore.SIGNAL("undo()"),self.undoSegment) + QtCore.QObject.connect(self.radiusValue,QtCore.SIGNAL("escaped()"),self.finish) + QtCore.QObject.connect(self.baseWidget,QtCore.SIGNAL("resized()"),self.relocate) + QtCore.QObject.connect(self.baseWidget,QtCore.SIGNAL("retranslate()"),self.retranslateUi) - spacerItem = QtGui.QSpacerItem(40, 20, QtGui.QSizePolicy.Expanding, - QtGui.QSizePolicy.Minimum) - self.layout.addItem(spacerItem) + def setupTray(self): + "sets draft tray buttons up" - QtCore.QObject.connect(self.xValue,QtCore.SIGNAL("returnPressed()"),self.checkx) - QtCore.QObject.connect(self.yValue,QtCore.SIGNAL("returnPressed()"),self.checky) - QtCore.QObject.connect(self.xValue,QtCore.SIGNAL("textEdited(QString)"),self.checkSpecialChars) - QtCore.QObject.connect(self.yValue,QtCore.SIGNAL("textEdited(QString)"),self.checkSpecialChars) - QtCore.QObject.connect(self.zValue,QtCore.SIGNAL("textEdited(QString)"),self.checkSpecialChars) - QtCore.QObject.connect(self.radiusValue,QtCore.SIGNAL("textEdited(QString)"),self.checkSpecialChars) - QtCore.QObject.connect(self.zValue,QtCore.SIGNAL("returnPressed()"),self.validatePoint) - QtCore.QObject.connect(self.radiusValue,QtCore.SIGNAL("returnPressed()"),self.validatePoint) - QtCore.QObject.connect(self.textValue,QtCore.SIGNAL("returnPressed()"),self.sendText) - QtCore.QObject.connect(self.textValue,QtCore.SIGNAL("escaped()"),self.finish) - QtCore.QObject.connect(self.textValue,QtCore.SIGNAL("down()"),self.sendText) - QtCore.QObject.connect(self.textValue,QtCore.SIGNAL("up()"),self.lineUp) - QtCore.QObject.connect(self.zValue,QtCore.SIGNAL("returnPressed()"),self.xValue.setFocus) - QtCore.QObject.connect(self.zValue,QtCore.SIGNAL("returnPressed()"),self.xValue.selectAll) - QtCore.QObject.connect(self.offsetValue,QtCore.SIGNAL("textEdited(QString)"),self.checkSpecialChars) - QtCore.QObject.connect(self.offsetValue,QtCore.SIGNAL("returnPressed()"),self.validatePoint) - QtCore.QObject.connect(self.addButton,QtCore.SIGNAL("toggled(bool)"),self.setAddMode) - QtCore.QObject.connect(self.delButton,QtCore.SIGNAL("toggled(bool)"),self.setDelMode) - QtCore.QObject.connect(self.finishButton,QtCore.SIGNAL("pressed()"),self.finish) - QtCore.QObject.connect(self.closeButton,QtCore.SIGNAL("pressed()"),self.closeLine) - QtCore.QObject.connect(self.wipeButton,QtCore.SIGNAL("pressed()"),self.wipeLine) - QtCore.QObject.connect(self.undoButton,QtCore.SIGNAL("pressed()"),self.undoSegment) - QtCore.QObject.connect(self.xyButton,QtCore.SIGNAL("clicked()"),self.selectXY) - QtCore.QObject.connect(self.xzButton,QtCore.SIGNAL("clicked()"),self.selectXZ) - QtCore.QObject.connect(self.yzButton,QtCore.SIGNAL("clicked()"),self.selectYZ) - QtCore.QObject.connect(self.continueCmd,QtCore.SIGNAL("stateChanged(int)"),self.setContinue) - QtCore.QObject.connect(self.currentViewButton,QtCore.SIGNAL("clicked()"),self.selectCurrentView) - QtCore.QObject.connect(self.resetPlaneButton,QtCore.SIGNAL("clicked()"),self.selectResetPlane) - QtCore.QObject.connect(self.xValue,QtCore.SIGNAL("escaped()"),self.finish) - QtCore.QObject.connect(self.xValue,QtCore.SIGNAL("undo()"),self.undoSegment) - QtCore.QObject.connect(self.yValue,QtCore.SIGNAL("escaped()"),self.finish) - QtCore.QObject.connect(self.yValue,QtCore.SIGNAL("undo()"),self.undoSegment) - QtCore.QObject.connect(self.zValue,QtCore.SIGNAL("escaped()"),self.finish) - QtCore.QObject.connect(self.zValue,QtCore.SIGNAL("undo()"),self.undoSegment) - QtCore.QObject.connect(self.radiusValue,QtCore.SIGNAL("escaped()"),self.finish) - QtCore.QObject.connect(self.baseWidget,QtCore.SIGNAL("resized()"),self.relocate) - QtCore.QObject.connect(self.baseWidget,QtCore.SIGNAL("retranslate()"),self.retranslateUi) + self.wplabel = self._pushbutton("wplabel", self.toptray, icon='Draft_SelectPlane',hide=False,width=120) + defaultWP = Draft.getParam("defaultWP") + if defaultWP == 1: + self.wplabel.setText("Top") + elif defaultWP == 2: + self.wplabel.setText("Front") + elif defaultWP == 3: + self.wplabel.setText("Side") + else: + self.wplabel.setText("None") + self.constrButton = self._pushbutton("constrButton", self.toptray, hide=False, icon='Draft_Construction',width=22, checkable=True) + self.constrColor = QtGui.QColor(self.paramconstr) + self.colorButton = self._pushbutton("colorButton",self.bottomtray, hide=False,width=22) + self.colorPix = QtGui.QPixmap(16,16) + self.colorPix.fill(self.color) + self.colorButton.setIcon(QtGui.QIcon(self.colorPix)) + self.facecolorButton = self._pushbutton("facecolorButton",self.bottomtray, hide=False,width=22) + self.facecolorPix = QtGui.QPixmap(16,16) + self.facecolorPix.fill(self.facecolor) + self.facecolorButton.setIcon(QtGui.QIcon(self.facecolorPix)) + self.widthButton = self._spinbox("widthButton", self.bottomtray, val=self.linewidth,hide=False,size=(50,22)) + self.widthButton.setSuffix("px") + self.fontsizeButton = self._spinbox("fontsizeButton",self.bottomtray, val=self.fontsize,hide=False,double=True,size=(50,22)) + self.applyButton = self._pushbutton("applyButton", self.toptray, hide=False, icon='Draft_Apply',width=22) - def setupTray(self): - "sets draft tray buttons up" + QtCore.QObject.connect(self.wplabel,QtCore.SIGNAL("pressed()"),self.selectplane) + QtCore.QObject.connect(self.colorButton,QtCore.SIGNAL("pressed()"),self.getcol) + QtCore.QObject.connect(self.facecolorButton,QtCore.SIGNAL("pressed()"),self.getfacecol) + QtCore.QObject.connect(self.widthButton,QtCore.SIGNAL("valueChanged(int)"),self.setwidth) + QtCore.QObject.connect(self.fontsizeButton,QtCore.SIGNAL("valueChanged(double)"),self.setfontsize) + QtCore.QObject.connect(self.applyButton,QtCore.SIGNAL("pressed()"),self.apply) + QtCore.QObject.connect(self.constrButton,QtCore.SIGNAL("toggled(bool)"),self.toggleConstrMode) - self.wplabel = self._pushbutton("wplabel", self.toptray, icon='Draft_SelectPlane',hide=False,width=120) - defaultWP = Draft.getParam("defaultWP") - if defaultWP == 1: - self.wplabel.setText("Top") - elif defaultWP == 2: - self.wplabel.setText("Front") - elif defaultWP == 3: - self.wplabel.setText("Side") - else: - self.wplabel.setText("None") - self.constrButton = self._pushbutton("constrButton", self.toptray, hide=False, icon='Draft_Construction',width=22, checkable=True) - self.constrColor = QtGui.QColor(self.paramconstr) - self.colorButton = self._pushbutton("colorButton",self.bottomtray, hide=False,width=22) - self.colorPix = QtGui.QPixmap(16,16) - self.colorPix.fill(self.color) - self.colorButton.setIcon(QtGui.QIcon(self.colorPix)) - self.facecolorButton = self._pushbutton("facecolorButton",self.bottomtray, hide=False,width=22) - self.facecolorPix = QtGui.QPixmap(16,16) - self.facecolorPix.fill(self.facecolor) - self.facecolorButton.setIcon(QtGui.QIcon(self.facecolorPix)) - self.widthButton = self._spinbox("widthButton", self.bottomtray, val=self.linewidth,hide=False,size=(50,22)) - self.widthButton.setSuffix("px") - self.fontsizeButton = self._spinbox("fontsizeButton",self.bottomtray, val=self.fontsize,hide=False,double=True,size=(50,22)) - self.applyButton = self._pushbutton("applyButton", self.toptray, hide=False, icon='Draft_Apply',width=22) - - QtCore.QObject.connect(self.wplabel,QtCore.SIGNAL("pressed()"),self.selectplane) - QtCore.QObject.connect(self.colorButton,QtCore.SIGNAL("pressed()"),self.getcol) - QtCore.QObject.connect(self.facecolorButton,QtCore.SIGNAL("pressed()"),self.getfacecol) - QtCore.QObject.connect(self.widthButton,QtCore.SIGNAL("valueChanged(int)"),self.setwidth) - QtCore.QObject.connect(self.fontsizeButton,QtCore.SIGNAL("valueChanged(double)"),self.setfontsize) - QtCore.QObject.connect(self.applyButton,QtCore.SIGNAL("pressed()"),self.apply) - QtCore.QObject.connect(self.constrButton,QtCore.SIGNAL("toggled(bool)"),self.toggleConstrMode) - - def setupStyle(self): - style = "#constrButton:Checked {background-color: " - style += self.getDefaultColor("constr",rgb=True)+" } " - style += "#addButton:Checked, #delButton:checked {" - style += "background-color: rgb(20,100,250) }" - self.baseWidget.setStyleSheet(style) + def setupStyle(self): + style = "#constrButton:Checked {background-color: " + style += self.getDefaultColor("constr",rgb=True)+" } " + style += "#addButton:Checked, #delButton:checked {" + style += "background-color: rgb(20,100,250) }" + self.baseWidget.setStyleSheet(style) #--------------------------------------------------------------------------- # language tools #--------------------------------------------------------------------------- - def retranslateUi(self, widget=None): - self.promptlabel.setText(translate("draft", "active command:")) - self.cmdlabel.setText(translate("draft", "None")) - self.cmdlabel.setToolTip(translate("draft", "Active Draft command")) - self.xValue.setToolTip(translate("draft", "X coordinate of next point")) - self.labelx.setText(translate("draft", "X")) - self.labely.setText(translate("draft", "Y")) - self.labelz.setText(translate("draft", "Z")) - self.yValue.setToolTip(translate("draft", "Y coordinate of next point")) - self.zValue.setToolTip(translate("draft", "Z coordinate of next point")) - self.labelRadius.setText(translate("draft", "Radius")) - self.radiusValue.setToolTip(translate("draft", "Radius of Circle")) - self.isRelative.setText(translate("draft", "&Relative")) - self.isRelative.setToolTip(translate("draft", "Coordinates relative to last point or absolute (SPACE)")) - self.hasFill.setText(translate("draft", "F&illed")) - self.hasFill.setToolTip(translate("draft", "Check this if the object should appear as filled, otherwise it will appear as wireframe (i)")) - self.finishButton.setText(translate("draft", "&Finish")) - self.finishButton.setToolTip(translate("draft", "Finishes the current drawing or editing operation (F)")) - self.continueCmd.setToolTip(translate("draft", "If checked, command will not finish until you press the command button again")) - self.continueCmd.setText(translate("draft", "&Continue")) - self.occOffset.setToolTip(translate("draft", "If checked, an OCC-style offset will be performed instead of the classic offset")) - self.occOffset.setText(translate("draft", "&OCC-style offset")) - self.addButton.setToolTip(translate("draft", "Add points to the current object")) - self.delButton.setToolTip(translate("draft", "Remove points from the current object")) - self.undoButton.setText(translate("draft", "&Undo")) - self.undoButton.setToolTip(translate("draft", "Undo the last segment (CTRL+Z)")) - self.closeButton.setText(translate("draft", "&Close")) - self.closeButton.setToolTip(translate("draft", "Finishes and closes the current line (C)")) - self.wipeButton.setText(translate("draft", "&Wipe")) - self.wipeButton.setToolTip(translate("draft", "Wipes the existing segments of this line and starts again from the last point (W)")) - self.numFaces.setToolTip(translate("draft", "Number of sides")) - self.offsetLabel.setText(translate("draft", "Offset")) - self.xyButton.setText(translate("draft", "XY")) - self.xyButton.setToolTip(translate("draft", "Select XY plane")) - self.xzButton.setText(translate("draft", "XZ")) - self.xzButton.setToolTip(translate("draft", "Select XZ plane")) - self.yzButton.setText(translate("draft", "YZ")) - self.yzButton.setToolTip(translate("draft", "Select YZ plane")) - self.currentViewButton.setText(translate("draft", "View")) - self.currentViewButton.setToolTip(translate("draft", "Select plane perpendicular to the current view")) - self.resetPlaneButton.setText(translate("draft", "None")) - self.resetPlaneButton.setToolTip(translate("draft", "Do not project points to a drawing plane")) - self.isCopy.setText(translate("draft", "&Copy")) - self.isCopy.setToolTip(translate("draft", "If checked, objects will be copied instead of moved (C)")) - if (not self.taskmode) or self.tray: - self.colorButton.setToolTip(translate("draft", "Line Color")) - self.facecolorButton.setToolTip(translate("draft", "Face Color")) - self.widthButton.setToolTip(translate("draft", "Line Width")) - self.fontsizeButton.setToolTip(translate("draft", "Font Size")) - self.applyButton.setToolTip(translate("draft", "Apply to selected objects")) - self.constrButton.setToolTip(translate("draft", "Toggles Construction Mode")) + def retranslateUi(self, widget=None): + self.promptlabel.setText(translate("draft", "active command:")) + self.cmdlabel.setText(translate("draft", "None")) + self.cmdlabel.setToolTip(translate("draft", "Active Draft command")) + self.xValue.setToolTip(translate("draft", "X coordinate of next point")) + self.labelx.setText(translate("draft", "X")) + self.labely.setText(translate("draft", "Y")) + self.labelz.setText(translate("draft", "Z")) + self.yValue.setToolTip(translate("draft", "Y coordinate of next point")) + self.zValue.setToolTip(translate("draft", "Z coordinate of next point")) + self.labelRadius.setText(translate("draft", "Radius")) + self.radiusValue.setToolTip(translate("draft", "Radius of Circle")) + self.isRelative.setText(translate("draft", "&Relative")) + self.isRelative.setToolTip(translate("draft", "Coordinates relative to last point or absolute (SPACE)")) + self.hasFill.setText(translate("draft", "F&illed")) + self.hasFill.setToolTip(translate("draft", "Check this if the object should appear as filled, otherwise it will appear as wireframe (i)")) + self.finishButton.setText(translate("draft", "&Finish")) + self.finishButton.setToolTip(translate("draft", "Finishes the current drawing or editing operation (F)")) + self.continueCmd.setToolTip(translate("draft", "If checked, command will not finish until you press the command button again")) + self.continueCmd.setText(translate("draft", "&Continue")) + self.occOffset.setToolTip(translate("draft", "If checked, an OCC-style offset will be performed instead of the classic offset")) + self.occOffset.setText(translate("draft", "&OCC-style offset")) + self.addButton.setToolTip(translate("draft", "Add points to the current object")) + self.delButton.setToolTip(translate("draft", "Remove points from the current object")) + self.undoButton.setText(translate("draft", "&Undo")) + self.undoButton.setToolTip(translate("draft", "Undo the last segment (CTRL+Z)")) + self.closeButton.setText(translate("draft", "&Close")) + self.closeButton.setToolTip(translate("draft", "Finishes and closes the current line (C)")) + self.wipeButton.setText(translate("draft", "&Wipe")) + self.wipeButton.setToolTip(translate("draft", "Wipes the existing segments of this line and starts again from the last point (W)")) + self.numFaces.setToolTip(translate("draft", "Number of sides")) + self.offsetLabel.setText(translate("draft", "Offset")) + self.xyButton.setText(translate("draft", "XY")) + self.xyButton.setToolTip(translate("draft", "Select XY plane")) + self.xzButton.setText(translate("draft", "XZ")) + self.xzButton.setToolTip(translate("draft", "Select XZ plane")) + self.yzButton.setText(translate("draft", "YZ")) + self.yzButton.setToolTip(translate("draft", "Select YZ plane")) + self.currentViewButton.setText(translate("draft", "View")) + self.currentViewButton.setToolTip(translate("draft", "Select plane perpendicular to the current view")) + self.resetPlaneButton.setText(translate("draft", "None")) + self.resetPlaneButton.setToolTip(translate("draft", "Do not project points to a drawing plane")) + self.isCopy.setText(translate("draft", "&Copy")) + self.isCopy.setToolTip(translate("draft", "If checked, objects will be copied instead of moved (C)")) + if (not self.taskmode) or self.tray: + self.colorButton.setToolTip(translate("draft", "Line Color")) + self.facecolorButton.setToolTip(translate("draft", "Face Color")) + self.widthButton.setToolTip(translate("draft", "Line Width")) + self.fontsizeButton.setToolTip(translate("draft", "Font Size")) + self.applyButton.setToolTip(translate("draft", "Apply to selected objects")) + self.constrButton.setToolTip(translate("draft", "Toggles Construction Mode")) #--------------------------------------------------------------------------- # Interface modes #--------------------------------------------------------------------------- - def taskUi(self,title): - if self.taskmode: - FreeCADGui.Control.closeDialog() - self.baseWidget = QtGui.QWidget() - self.setTitle(title) - self.layout = QtGui.QVBoxLayout(self.baseWidget) - self.setupToolBar(task=True) - self.retranslateUi(self.baseWidget) - self.panel = DraftTaskPanel(self.baseWidget) - FreeCADGui.Control.showDialog(self.panel) - else: - self.setTitle(title) + def taskUi(self,title): + if self.taskmode: + FreeCADGui.Control.closeDialog() + self.baseWidget = QtGui.QWidget() + self.setTitle(title) + self.layout = QtGui.QVBoxLayout(self.baseWidget) + self.setupToolBar(task=True) + self.retranslateUi(self.baseWidget) + self.panel = DraftTaskPanel(self.baseWidget) + FreeCADGui.Control.showDialog(self.panel) + else: + self.setTitle(title) - def selectPlaneUi(self): - self.taskUi(translate("draft", "Select Plane")) - self.xyButton.show() - self.xzButton.show() - self.yzButton.show() - self.currentViewButton.show() - self.resetPlaneButton.show() - self.offsetLabel.show() - self.offsetValue.show() + def selectPlaneUi(self): + self.taskUi(translate("draft", "Select Plane")) + self.xyButton.show() + self.xzButton.show() + self.yzButton.show() + self.currentViewButton.show() + self.resetPlaneButton.show() + self.offsetLabel.show() + self.offsetValue.show() - def lineUi(self): - self.pointUi(translate("draft", "Line")) - self.xValue.setEnabled(True) - self.yValue.setEnabled(True) - self.isRelative.show() - self.hasFill.show() - self.finishButton.show() - self.closeButton.show() - self.wipeButton.show() - self.undoButton.show() - self.continueCmd.show() + def lineUi(self): + self.pointUi(translate("draft", "Line")) + self.xValue.setEnabled(True) + self.yValue.setEnabled(True) + self.isRelative.show() + self.hasFill.show() + self.finishButton.show() + self.closeButton.show() + self.wipeButton.show() + self.undoButton.show() + self.continueCmd.show() - def circleUi(self): - self.pointUi(translate("draft", "Circle")) - self.continueCmd.show() - self.labelx.setText(translate("draft", "Center X")) - self.hasFill.show() + def circleUi(self): + self.pointUi(translate("draft", "Circle")) + self.continueCmd.show() + self.labelx.setText(translate("draft", "Center X")) + self.hasFill.show() - def arcUi(self): - self.pointUi(translate("draft", "Arc")) - self.labelx.setText(translate("draft", "Center X")) - self.continueCmd.show() + def arcUi(self): + self.pointUi(translate("draft", "Arc")) + self.labelx.setText(translate("draft", "Center X")) + self.continueCmd.show() - def pointUi(self,title=translate("draft","Point")): - self.taskUi(title) - self.xValue.setEnabled(True) - self.yValue.setEnabled(True) - self.labelx.setText(translate("draft", "X")) - self.labelx.show() - self.labely.show() - self.labelz.show() - self.xValue.show() - self.yValue.show() - self.zValue.show() - self.xValue.setFocus() - self.xValue.selectAll() + def pointUi(self,title=translate("draft","Point")): + self.taskUi(title) + self.xValue.setEnabled(True) + self.yValue.setEnabled(True) + self.labelx.setText(translate("draft", "X")) + self.labelx.show() + self.labely.show() + self.labelz.show() + self.xValue.show() + self.yValue.show() + self.zValue.show() + self.xValue.setFocus() + self.xValue.selectAll() - def offsetUi(self): - self.taskUi(translate("draft","Offset")) - self.radiusUi() - self.isCopy.show() - self.occOffset.show() - self.labelRadius.setText(translate("draft","Distance")) - self.radiusValue.setFocus() - self.radiusValue.selectAll() + def offsetUi(self): + self.taskUi(translate("draft","Offset")) + self.radiusUi() + self.isCopy.show() + self.occOffset.show() + self.labelRadius.setText(translate("draft","Distance")) + self.radiusValue.setFocus() + self.radiusValue.selectAll() - def offUi(self): - if self.taskmode: - FreeCADGui.Control.closeDialog() - self.baseWidget = QtGui.QWidget() - print "UI turned off" - else: - self.setTitle(translate("draft", "None")) - self.labelx.setText(translate("draft", "X")) - self.labelx.hide() - self.labely.hide() - self.labelz.hide() - self.xValue.hide() - self.yValue.hide() - self.zValue.hide() - self.numFaces.hide() - self.isRelative.hide() - self.hasFill.hide() - self.finishButton.hide() - self.addButton.hide() - self.delButton.hide() - self.undoButton.hide() - self.closeButton.hide() - self.wipeButton.hide() - self.xyButton.hide() - self.xzButton.hide() - self.yzButton.hide() - self.currentViewButton.hide() - self.resetPlaneButton.hide() - self.offsetLabel.hide() - self.offsetValue.hide() - self.labelRadius.hide() - self.radiusValue.hide() - self.isCopy.hide() - self.textValue.hide() - self.continueCmd.hide() - self.occOffset.hide() + def offUi(self): + if self.taskmode: + FreeCADGui.Control.closeDialog() + self.baseWidget = QtGui.QWidget() + # print "UI turned off" + else: + self.setTitle(translate("draft", "None")) + self.labelx.setText(translate("draft", "X")) + self.labelx.hide() + self.labely.hide() + self.labelz.hide() + self.xValue.hide() + self.yValue.hide() + self.zValue.hide() + self.numFaces.hide() + self.isRelative.hide() + self.hasFill.hide() + self.finishButton.hide() + self.addButton.hide() + self.delButton.hide() + self.undoButton.hide() + self.closeButton.hide() + self.wipeButton.hide() + self.xyButton.hide() + self.xzButton.hide() + self.yzButton.hide() + self.currentViewButton.hide() + self.resetPlaneButton.hide() + self.offsetLabel.hide() + self.offsetValue.hide() + self.labelRadius.hide() + self.radiusValue.hide() + self.isCopy.hide() + self.textValue.hide() + self.continueCmd.hide() + self.occOffset.hide() - def radiusUi(self): - self.labelx.hide() - self.labely.hide() - self.labelz.hide() - self.xValue.hide() - self.yValue.hide() - self.zValue.hide() - self.labelRadius.setText(translate("draft", "Radius")) - self.labelRadius.show() - self.radiusValue.show() + def radiusUi(self): + self.labelx.hide() + self.labely.hide() + self.labelz.hide() + self.xValue.hide() + self.yValue.hide() + self.zValue.hide() + self.labelRadius.setText(translate("draft", "Radius")) + self.labelRadius.show() + self.radiusValue.show() - def textUi(self): - self.labelx.hide() - self.labely.hide() - self.labelz.hide() - self.xValue.hide() - self.yValue.hide() - self.zValue.hide() - self.textValue.show() - self.textValue.setText('') - self.textValue.setFocus() - self.textbuffer=[] - self.textline=0 - self.continueCmd.show() + def textUi(self): + self.labelx.hide() + self.labely.hide() + self.labelz.hide() + self.xValue.hide() + self.yValue.hide() + self.zValue.hide() + self.textValue.show() + self.textValue.setText('') + self.textValue.setFocus() + self.textbuffer=[] + self.textline=0 + self.continueCmd.show() + + def switchUi(self,store=True): + if store: + self.state = [] + self.state.append(self.labelx.isVisible()) + self.state.append(self.labely.isVisible()) + self.state.append(self.labelz.isVisible()) + self.state.append(self.xValue.isVisible()) + self.state.append(self.yValue.isVisible()) + self.state.append(self.zValue.isVisible()) + self.labelx.hide() + self.labely.hide() + self.labelz.hide() + self.xValue.hide() + self.yValue.hide() + self.zValue.hide() + else: + if self.state: + if self.state[0]:self.labelx.show() + if self.state[1]:self.labely.show() + if self.state[2]:self.labelz.show() + if self.state[3]:self.xValue.show() + if self.state[4]:self.yValue.show() + if self.state[5]:self.zValue.show() + self.state = None - def switchUi(self,store=True): - if store: - self.state = [] - self.state.append(self.labelx.isVisible()) - self.state.append(self.labely.isVisible()) - self.state.append(self.labelz.isVisible()) - self.state.append(self.xValue.isVisible()) - self.state.append(self.yValue.isVisible()) - self.state.append(self.zValue.isVisible()) - self.labelx.hide() - self.labely.hide() - self.labelz.hide() - self.xValue.hide() - self.yValue.hide() - self.zValue.hide() - else: - if self.state: - if self.state[0]:self.labelx.show() - if self.state[1]:self.labely.show() - if self.state[2]:self.labelz.show() - if self.state[3]:self.xValue.show() - if self.state[4]:self.yValue.show() - if self.state[5]:self.zValue.show() - self.state = None + def setTitle(self,title): + if self.taskmode: + self.baseWidget.setWindowTitle(title) + else: + self.cmdlabel.setText(title) - def setTitle(self,title): - if self.taskmode: - self.baseWidget.setWindowTitle(title) - else: - self.cmdlabel.setText(title) + def selectUi(self): + self.labelx.setText(translate("draft", "Pick Object")) + self.labelx.show() - def selectUi(self): - self.labelx.setText(translate("draft", "Pick Object")) - self.labelx.show() + def editUi(self): + self.taskUi(translate("draft", "Edit")) + self.labelx.hide() + self.labely.hide() + self.labelz.hide() + self.xValue.hide() + self.yValue.hide() + self.zValue.hide() + self.numFaces.hide() + self.isRelative.hide() + self.hasFill.hide() + self.addButton.show() + self.delButton.show() + self.finishButton.show() + self.closeButton.show() - def editUi(self): - self.taskUi(translate("draft", "Edit")) - self.labelx.hide() - self.labely.hide() - self.labelz.hide() - self.xValue.hide() - self.yValue.hide() - self.zValue.hide() - self.numFaces.hide() - self.isRelative.hide() - self.hasFill.hide() - self.addButton.show() - self.delButton.show() - self.finishButton.show() - self.closeButton.show() + def extUi(self): + self.hasFill.show() + self.continueCmd.show() - def extUi(self): - self.hasFill.show() - self.continueCmd.show() + def modUi(self): + self.isCopy.show() + self.continueCmd.show() - def modUi(self): - self.isCopy.show() - self.continueCmd.show() - - def relocate(self): - "relocates the right-aligned buttons depending on the toolbar size" - if self.baseWidget.geometry().width() < 400: - self.layout.setDirection(QtGui.QBoxLayout.TopToBottom) - else: - self.layout.setDirection(QtGui.QBoxLayout.LeftToRight) + def relocate(self): + "relocates the right-aligned buttons depending on the toolbar size" + if self.baseWidget.geometry().width() < 400: + self.layout.setDirection(QtGui.QBoxLayout.TopToBottom) + else: + self.layout.setDirection(QtGui.QBoxLayout.LeftToRight) #--------------------------------------------------------------------------- # Processing functions #--------------------------------------------------------------------------- - def getcol(self): - "opens a color picker dialog" - self.color=QtGui.QColorDialog.getColor() - self.colorPix.fill(self.color) - self.colorButton.setIcon(QtGui.QIcon(self.colorPix)) - if Draft.getParam("saveonexit"): - Draft.setParam("color",self.color.rgb()<<8) - r = float(self.color.red()/255.0) - g = float(self.color.green()/255.0) - b = float(self.color.blue()/255.0) - col = (r,g,b,0.0) - for i in FreeCADGui.Selection.getSelection(): - if (i.Type == "App::Annotation"): - i.ViewObject.TextColor=col - else: - if "LineColor" in i.ViewObject.PropertiesList: - i.ViewObject.LineColor = col - if "PointColor" in i.ViewObject.PropertiesList: - i.ViewObject.PointColor = col + def getcol(self): + "opens a color picker dialog" + self.color=QtGui.QColorDialog.getColor() + self.colorPix.fill(self.color) + self.colorButton.setIcon(QtGui.QIcon(self.colorPix)) + if Draft.getParam("saveonexit"): + Draft.setParam("color",self.color.rgb()<<8) + r = float(self.color.red()/255.0) + g = float(self.color.green()/255.0) + b = float(self.color.blue()/255.0) + col = (r,g,b,0.0) + for i in FreeCADGui.Selection.getSelection(): + if (i.Type == "App::Annotation"): + i.ViewObject.TextColor=col + else: + if "LineColor" in i.ViewObject.PropertiesList: + i.ViewObject.LineColor = col + if "PointColor" in i.ViewObject.PropertiesList: + i.ViewObject.PointColor = col - def getfacecol(self): - "opens a color picker dialog" - self.facecolor=QtGui.QColorDialog.getColor() - self.facecolorPix.fill(self.facecolor) - self.facecolorButton.setIcon(QtGui.QIcon(self.facecolorPix)) - r = float(self.facecolor.red()/255.0) - g = float(self.facecolor.green()/255.0) - b = float(self.facecolor.blue()/255.0) - col = (r,g,b,0.0) - for i in FreeCADGui.Selection.getSelection(): - if "ShapeColor" in i.ViewObject.PropertiesList: - i.ViewObject.ShapeColor = col + def getfacecol(self): + "opens a color picker dialog" + self.facecolor=QtGui.QColorDialog.getColor() + self.facecolorPix.fill(self.facecolor) + self.facecolorButton.setIcon(QtGui.QIcon(self.facecolorPix)) + r = float(self.facecolor.red()/255.0) + g = float(self.facecolor.green()/255.0) + b = float(self.facecolor.blue()/255.0) + col = (r,g,b,0.0) + for i in FreeCADGui.Selection.getSelection(): + if "ShapeColor" in i.ViewObject.PropertiesList: + i.ViewObject.ShapeColor = col - def setwidth(self,val): - self.linewidth = float(val) - if Draft.getParam("saveonexit"): - Draft.setParam("linewidth",int(val)) - for i in FreeCADGui.Selection.getSelection(): - if "LineWidth" in i.ViewObject.PropertiesList: - i.ViewObject.LineWidth = float(val) + def setwidth(self,val): + self.linewidth = float(val) + if Draft.getParam("saveonexit"): + Draft.setParam("linewidth",int(val)) + for i in FreeCADGui.Selection.getSelection(): + if "LineWidth" in i.ViewObject.PropertiesList: + i.ViewObject.LineWidth = float(val) - def setfontsize(self,val): - self.fontsize = float(val) - if Draft.getParam("saveonexit"): - Draft.setParam("textheight",float(val)) - for i in FreeCADGui.Selection.getSelection(): - if "FontSize" in i.ViewObject.PropertiesList: - i.ViewObject.FontSize = float(val) + def setfontsize(self,val): + self.fontsize = float(val) + if Draft.getParam("saveonexit"): + Draft.setParam("textheight",float(val)) + for i in FreeCADGui.Selection.getSelection(): + if "FontSize" in i.ViewObject.PropertiesList: + i.ViewObject.FontSize = float(val) - def setContinue(self,val): - self.continueMode = bool(val) + def setContinue(self,val): + self.continueMode = bool(val) - def apply(self): - for i in FreeCADGui.Selection.getSelection(): - Draft.formatObject(i) + def apply(self): + for i in FreeCADGui.Selection.getSelection(): + Draft.formatObject(i) - def checkx(self): - if self.yValue.isEnabled(): - self.yValue.setFocus() - self.yValue.selectAll() + def checkx(self): + if self.yValue.isEnabled(): + self.yValue.setFocus() + self.yValue.selectAll() + else: + self.checky() + + def checky(self): + if self.zValue.isEnabled(): + self.zValue.setFocus() + self.zValue.selectAll() + else: + self.validatePoint() + + def validatePoint(self): + "function for checking and sending numbers entered manually" + if self.sourceCmd != None: + if (self.labelRadius.isVisible()): + try: + rad=float(self.radiusValue.text()) + except ValueError: + pass else: - self.checky() - - def checky(self): - if self.zValue.isEnabled(): - self.zValue.setFocus() - self.zValue.selectAll() + self.sourceCmd.numericRadius(rad) + elif (self.offsetLabel.isVisible()): + try: + offset=float(self.offsetValue.text()) + except ValueError: + pass else: - self.validatePoint() + self.sourceCmd.offsetHandler(offset) + else: + try: + numx=float(self.xValue.text()) + numy=float(self.yValue.text()) + numz=float(self.zValue.text()) + except ValueError: + pass + else: + if self.isRelative.isVisible() and self.isRelative.isChecked(): + if self.sourceCmd.node: + if self.sourceCmd.featureName == "Rectangle": + last = self.sourceCmd.node[0] + else: + last = self.sourceCmd.node[-1] + numx = last.x + numx + numy = last.y + numy + numz = last.z + numz + if FreeCAD.DraftWorkingPlane: + v = FreeCAD.Vector(numx,numy,numz) + v = FreeCAD.DraftWorkingPlane.getGlobalCoords(v) + numx = v.x + numy = v.y + numz = v.z + self.sourceCmd.numericInput(numx,numy,numz) - def validatePoint(self): - "function for checking and sending numbers entered manually" - if self.sourceCmd != None: - if (self.labelRadius.isVisible()): - try: - rad=float(self.radiusValue.text()) - except ValueError: - pass - else: - self.sourceCmd.numericRadius(rad) - elif (self.offsetLabel.isVisible()): - try: - offset=float(self.offsetValue.text()) - except ValueError: - pass - else: - self.sourceCmd.offsetHandler(offset) - else: - try: - numx=float(self.xValue.text()) - numy=float(self.yValue.text()) - numz=float(self.zValue.text()) - except ValueError: - pass - else: - if self.isRelative.isVisible() and self.isRelative.isChecked(): - if self.sourceCmd.node: - if self.sourceCmd.featureName == "Rectangle": - last = self.sourceCmd.node[0] - else: - last = self.sourceCmd.node[-1] - numx = last.x + numx - numy = last.y + numy - numz = last.z + numz - if FreeCAD.DraftWorkingPlane: - v = FreeCAD.Vector(numx,numy,numz) - v = FreeCAD.DraftWorkingPlane.getGlobalCoords(v) - numx = v.x - numy = v.y - numz = v.z - self.sourceCmd.numericInput(numx,numy,numz) + def finish(self): + "finish button action" + self.sourceCmd.finish(False) - def finish(self): - "finish button action" - self.sourceCmd.finish(False) + def closeLine(self): + "close button action" + self.sourceCmd.finish(True) - def closeLine(self): - "close button action" - self.sourceCmd.finish(True) + def wipeLine(self): + "wipes existing segments of a line" + self.sourceCmd.wipe() - def wipeLine(self): - "wipes existing segments of a line" - self.sourceCmd.wipe() + def selectXY(self): + self.sourceCmd.selectHandler("XY") - def selectXY(self): - self.sourceCmd.selectHandler("XY") + def selectXZ(self): + self.sourceCmd.selectHandler("XZ") - def selectXZ(self): - self.sourceCmd.selectHandler("XZ") + def selectYZ(self): + self.sourceCmd.selectHandler("YZ") - def selectYZ(self): - self.sourceCmd.selectHandler("YZ") + def selectCurrentView(self): + self.sourceCmd.selectHandler("currentView") - def selectCurrentView(self): - self.sourceCmd.selectHandler("currentView") + def selectResetPlane(self): + self.sourceCmd.selectHandler("reset") - def selectResetPlane(self): - self.sourceCmd.selectHandler("reset") + def undoSegment(self): + "undo last line segment" + self.sourceCmd.undolast() - def undoSegment(self): - "undo last line segment" - self.sourceCmd.undolast() - - def checkSpecialChars(self,txt): - ''' - checks for special characters in the entered coords that mut be - treated as shortcuts - ''' - spec = False - if txt.endsWith(" ") or txt.endsWith("r"): - self.isRelative.setChecked(not self.isRelative.isChecked()) - spec = True - elif txt.endsWith("i"): - if self.hasFill.isVisible(): - self.hasFill.setChecked(not self.hasFill.isChecked()) - spec = True - elif txt.endsWith("f"): - if self.finishButton.isVisible(): - self.finish() - spec = True - elif txt.endsWith("w"): - self.wipeLine() - elif txt.endsWith("c"): - if self.closeButton.isVisible(): - self.closeLine() - elif self.isCopy.isVisible(): - self.isCopy.setChecked(not self.isCopy.isChecked()) - elif self.continueCmd.isVisible(): - self.continueCmd.setChecked(not self.continueCmd.isChecked()) - spec = True - if spec and (not self.taskmode): - for i in [self.xValue,self.yValue,self.zValue]: - if (i.text() == txt): i.setText("") + def checkSpecialChars(self,txt): + ''' + checks for special characters in the entered coords that mut be + treated as shortcuts + ''' + spec = False + if txt.endsWith(" ") or txt.endsWith("r"): + self.isRelative.setChecked(not self.isRelative.isChecked()) + spec = True + elif txt.endsWith("i"): + if self.hasFill.isVisible(): + self.hasFill.setChecked(not self.hasFill.isChecked()) + spec = True + elif txt.endsWith("f"): + if self.finishButton.isVisible(): + self.finish() + spec = True + elif txt.endsWith("w"): + self.wipeLine() + elif txt.endsWith("c"): + if self.closeButton.isVisible(): + self.closeLine() + elif self.isCopy.isVisible(): + self.isCopy.setChecked(not self.isCopy.isChecked()) + elif self.continueCmd.isVisible(): + self.continueCmd.setChecked(not self.continueCmd.isChecked()) + spec = True + if spec and (not self.taskmode): + for i in [self.xValue,self.yValue,self.zValue]: + if (i.text() == txt): i.setText("") - def sendText(self): - ''' - this function sends the entered text to the active draft command - if enter has been pressed twice. Otherwise it blanks the line. - ''' - if self.textline == len(self.textbuffer): - if self.textline: - if not self.textValue.text(): - self.sourceCmd.text=self.textbuffer - self.sourceCmd.createObject() - self.textbuffer.append(self.textValue.text()) - self.textline += 1 - self.textValue.setText('') - elif self.textline < len(self.textbuffer): - self.textbuffer[self.textline] = self.textValue.text() - self.textline += 1 - if self.textline < len(self.textbuffer): - self.textValue.setText(self.textbuffer[self.textline]) - else: - self.textValue.setText('') + def sendText(self): + ''' + this function sends the entered text to the active draft command + if enter has been pressed twice. Otherwise it blanks the line. + ''' + if self.textline == len(self.textbuffer): + if self.textline: + if not self.textValue.text(): + self.sourceCmd.text=self.textbuffer + self.sourceCmd.createObject() + self.textbuffer.append(self.textValue.text()) + self.textline += 1 + self.textValue.setText('') + elif self.textline < len(self.textbuffer): + self.textbuffer[self.textline] = self.textValue.text() + self.textline += 1 + if self.textline < len(self.textbuffer): + self.textValue.setText(self.textbuffer[self.textline]) + else: + self.textValue.setText('') - def lineUp(self): - "displays previous line in text editor" - if self.textline: - if self.textline == len(self.textbuffer): - self.textbuffer.append(self.textValue.text()) - self.textline -= 1 - if self.textValue.text(): - self.textValue.setText(self.textbuffer[self.textline]) - elif self.textline < len(self.textbuffer): - self.textbuffer[self.textline] = self.textValue.text() - self.textline -= 1 - self.textValue.setText(self.textbuffer[self.textline]) + def lineUp(self): + "displays previous line in text editor" + if self.textline: + if self.textline == len(self.textbuffer): + self.textbuffer.append(self.textValue.text()) + self.textline -= 1 + if self.textValue.text(): + self.textValue.setText(self.textbuffer[self.textline]) + elif self.textline < len(self.textbuffer): + self.textbuffer[self.textline] = self.textValue.text() + self.textline -= 1 + self.textValue.setText(self.textbuffer[self.textline]) - def displayPoint(self, point, last=None, plane=None): - "this function displays the passed coords in the x, y, and z widgets" - dp = point - if self.isRelative.isChecked() and (last != None): - if plane: - dp = plane.getLocalCoords(FreeCAD.Vector(point.x-last.x, point.y-last.y, point.z-last.z)) - else: - dp = FreeCAD.Vector(point.x-last.x, point.y-last.y, point.z-last.z) - self.xValue.setText("%.2f" % dp.x) - self.yValue.setText("%.2f" % dp.y) - if self.zValue.isEnabled(): self.zValue.setText("%.2f" % dp.z) - if self.xValue.isEnabled(): - self.xValue.setFocus() - self.xValue.selectAll() - else: - self.yValue.setFocus() - self.yValue.selectAll() + def displayPoint(self, point, last=None, plane=None): + "this function displays the passed coords in the x, y, and z widgets" + dp = point + if self.isRelative.isChecked() and (last != None): + if plane: + dp = plane.getLocalCoords(FreeCAD.Vector(point.x-last.x, point.y-last.y, point.z-last.z)) + else: + dp = FreeCAD.Vector(point.x-last.x, point.y-last.y, point.z-last.z) + self.xValue.setText("%.2f" % dp.x) + self.yValue.setText("%.2f" % dp.y) + if self.zValue.isEnabled(): self.zValue.setText("%.2f" % dp.z) + if self.xValue.isEnabled(): + self.xValue.setFocus() + self.xValue.selectAll() + else: + self.yValue.setFocus() + self.yValue.selectAll() - def getDefaultColor(self,type,rgb=False): - "gets color from the preferences or toolbar" - if type == "snap": - color = Draft.getParam("snapcolor") - r = ((color>>24)&0xFF)/255 - g = ((color>>16)&0xFF)/255 - b = ((color>>8)&0xFF)/255 - elif type == "ui": - r = float(self.color.red()/255.0) - g = float(self.color.green()/255.0) - b = float(self.color.blue()/255.0) - elif type == "face": - r = float(self.facecolor.red()/255.0) - g = float(self.facecolor.green()/255.0) - b = float(self.facecolor.blue()/255.0) - elif type == "constr": - color = QtGui.QColor(Draft.getParam("constructioncolor")>>8) - r = color.red()/255.0 - g = color.green()/255.0 - b = color.blue()/255.0 - else: print "draft: error: couldn't get a color for ",type," type." - if rgb: - return("rgb("+str(int(r*255))+","+str(int(g*255))+","+str(int(b*255))+")") - else: - return (r,g,b) + def getDefaultColor(self,type,rgb=False): + "gets color from the preferences or toolbar" + if type == "snap": + color = Draft.getParam("snapcolor") + r = ((color>>24)&0xFF)/255 + g = ((color>>16)&0xFF)/255 + b = ((color>>8)&0xFF)/255 + elif type == "ui": + r = float(self.color.red()/255.0) + g = float(self.color.green()/255.0) + b = float(self.color.blue()/255.0) + elif type == "face": + r = float(self.facecolor.red()/255.0) + g = float(self.facecolor.green()/255.0) + b = float(self.facecolor.blue()/255.0) + elif type == "constr": + color = QtGui.QColor(Draft.getParam("constructioncolor")>>8) + r = color.red()/255.0 + g = color.green()/255.0 + b = color.blue()/255.0 + else: print "draft: error: couldn't get a color for ",type," type." + if rgb: + return("rgb("+str(int(r*255))+","+str(int(g*255))+","+str(int(b*255))+")") + else: + return (r,g,b) - def cross(self,on=True): - if on: - if not self.crossedViews: - mw = getMainWindow() - self.crossedViews = mw.findChildren(QtGui.QFrame,"SoQtWidgetName") - for w in self.crossedViews: - w.setCursor(QtCore.Qt.CrossCursor) - else: - for w in self.crossedViews: - w.unsetCursor() - self.crossedViews = [] + def cross(self,on=True): + if on: + if not self.crossedViews: + mw = getMainWindow() + self.crossedViews = mw.findChildren(QtGui.QFrame,"SoQtWidgetName") + for w in self.crossedViews: + w.setCursor(QtCore.Qt.CrossCursor) + else: + for w in self.crossedViews: + w.unsetCursor() + self.crossedViews = [] - def toggleConstrMode(self,checked): - self.baseWidget.setStyleSheet("#constrButton:Checked {background-color: "+self.getDefaultColor("constr",rgb=True)+" }") - self.constrMode = checked + def toggleConstrMode(self,checked): + self.baseWidget.setStyleSheet("#constrButton:Checked {background-color: "+self.getDefaultColor("constr",rgb=True)+" }") + self.constrMode = checked - def isConstructionMode(self): - if self.tray or (not self.taskmode): - return self.constrButton.isChecked() - else: - return False + def isConstructionMode(self): + if self.tray or (not self.taskmode): + return self.constrButton.isChecked() + else: + return False - def drawPage(self): - self.sourceCmd.draw() + def drawPage(self): + self.sourceCmd.draw() - def changePage(self,index): - pagename = str(self.pageBox.itemText(index)) - vobj = FreeCADGui.ActiveDocument.getObject(pagename) - if vobj: - self.scaleBox.setEditText(str(vobj.HintScale)) - self.marginXValue.setValue(float(vobj.HintOffsetX)) - self.marginYValue.setValue(float(vobj.HintOffsetY)) + def changePage(self,index): + pagename = str(self.pageBox.itemText(index)) + vobj = FreeCADGui.ActiveDocument.getObject(pagename) + if vobj: + self.scaleBox.setEditText(str(vobj.HintScale)) + self.marginXValue.setValue(float(vobj.HintOffsetX)) + self.marginYValue.setValue(float(vobj.HintOffsetY)) - def selectplane(self): - FreeCADGui.runCommand("Draft_SelectPlane") + def selectplane(self): + FreeCADGui.runCommand("Draft_SelectPlane") - def popupMenu(self,mlist): - "pops up a menu filled with the given list" - self.groupmenu = QtGui.QMenu() - for i in mlist: - self.groupmenu.addAction(i) - pos = getMainWindow().cursor().pos() - self.groupmenu.popup(pos) - QtCore.QObject.connect(self.groupmenu,QtCore.SIGNAL("triggered(QAction *)"),self.popupTriggered) + def popupMenu(self,mlist): + "pops up a menu filled with the given list" + self.groupmenu = QtGui.QMenu() + for i in mlist: + self.groupmenu.addAction(i) + pos = getMainWindow().cursor().pos() + self.groupmenu.popup(pos) + QtCore.QObject.connect(self.groupmenu,QtCore.SIGNAL("triggered(QAction *)"),self.popupTriggered) - def popupTriggered(self,action): - self.sourceCmd.proceed(str(action.text())) + def popupTriggered(self,action): + self.sourceCmd.proceed(str(action.text())) - def setAddMode(self,bool): - if self.addButton.isChecked(): - self.delButton.setChecked(False) + def setAddMode(self,bool): + if self.addButton.isChecked(): + self.delButton.setChecked(False) - def setDelMode(self,bool): - if self.delButton.isChecked(): - self.addButton.setChecked(False) + def setDelMode(self,bool): + if self.delButton.isChecked(): + self.addButton.setChecked(False) - def setRadiusValue(self,val): - self.radiusValue.setText("%.2f" % val) - self.radiusValue.setFocus() - self.radiusValue.selectAll() + def setRadiusValue(self,val): + self.radiusValue.setText("%.2f" % val) + self.radiusValue.setFocus() + self.radiusValue.selectAll() - def show(self): - if not self.taskmode: - self.draftWidget.setVisible(True) + def show(self): + if not self.taskmode: + self.draftWidget.setVisible(True) - def hide(self): - if not self.taskmode: - self.draftWidget.setVisible(False) + def hide(self): + if not self.taskmode: + self.draftWidget.setVisible(False) - def getXPM(self,iconname,size=16): - i = QtGui.QIcon(":/icons/"+iconname+".svg") - p = i.pixmap(size,size) - a = QtCore.QByteArray() - b = QtCore.QBuffer(a) - b.open(QtCore.QIODevice.WriteOnly) - p.save(b,"XPM") - b.close() - return str(a) + def getXPM(self,iconname,size=16): + i = QtGui.QIcon(":/icons/"+iconname+".svg") + p = i.pixmap(size,size) + a = QtCore.QByteArray() + b = QtCore.QBuffer(a) + b.open(QtCore.QIODevice.WriteOnly) + p.save(b,"XPM") + b.close() + return str(a) #--------------------------------------------------------------------------- # TaskView operations #--------------------------------------------------------------------------- - def setWatchers(self): - print "adding draft widgets to taskview..." - class DraftCreateWatcher: - def __init__(self): - self.commands = ["Draft_Line","Draft_Wire", - "Draft_Rectangle","Draft_Arc", - "Draft_Circle","Draft_BSpline", - "Draft_Text","Draft_Dimension"] - self.title = "Create objects" - def shouldShow(self): - return (FreeCAD.ActiveDocument != None) and (not FreeCADGui.Selection.getSelection()) + def setWatchers(self): + print "adding draft widgets to taskview..." + class DraftCreateWatcher: + def __init__(self): + self.commands = ["Draft_Line","Draft_Wire", + "Draft_Rectangle","Draft_Arc", + "Draft_Circle","Draft_BSpline", + "Draft_Text","Draft_Dimension"] + self.title = "Create objects" + def shouldShow(self): + return (FreeCAD.ActiveDocument != None) and (not FreeCADGui.Selection.getSelection()) - class DraftModifyWatcher: - def __init__(self): - self.commands = ["Draft_Move","Draft_Rotate", - "Draft_Scale","Draft_Offset", - "Draft_Trimex","Draft_Upgrade", - "Draft_Downgrade","Draft_Edit", - "Draft_Drawing"] - self.title = "Modify objects" - def shouldShow(self): - return (FreeCAD.ActiveDocument != None) and (FreeCADGui.Selection.getSelection() != []) + class DraftModifyWatcher: + def __init__(self): + self.commands = ["Draft_Move","Draft_Rotate", + "Draft_Scale","Draft_Offset", + "Draft_Trimex","Draft_Upgrade", + "Draft_Downgrade","Draft_Edit", + "Draft_Drawing"] + self.title = "Modify objects" + def shouldShow(self): + return (FreeCAD.ActiveDocument != None) and (FreeCADGui.Selection.getSelection() != []) - class DraftTrayWatcher: - def __init__(self,traywidget): - self.form = traywidget - self.widgets = [self.form] - def shouldShow(self): - return True + class DraftTrayWatcher: + def __init__(self,traywidget): + self.form = traywidget + self.widgets = [self.form] + def shouldShow(self): + return True - print "setting tray" - self.traywidget = QtGui.QWidget() - self.tray = QtGui.QVBoxLayout(self.traywidget) - self.tray.setObjectName("traylayout") - self.toptray = QtGui.QHBoxLayout() - self.bottomtray = QtGui.QHBoxLayout() - self.tray.addLayout(self.toptray) - self.tray.addLayout(self.bottomtray) - self.setupTray() - self.setupStyle() - w = DraftTrayWatcher(self.traywidget) - FreeCADGui.Control.addTaskWatcher([w,DraftCreateWatcher(),DraftModifyWatcher()]) + print "setting tray" + self.traywidget = QtGui.QWidget() + self.tray = QtGui.QVBoxLayout(self.traywidget) + self.tray.setObjectName("traylayout") + self.toptray = QtGui.QHBoxLayout() + self.bottomtray = QtGui.QHBoxLayout() + self.tray.addLayout(self.toptray) + self.tray.addLayout(self.bottomtray) + self.setupTray() + self.setupStyle() + w = DraftTrayWatcher(self.traywidget) + FreeCADGui.Control.addTaskWatcher([w,DraftCreateWatcher(),DraftModifyWatcher()]) - def changeEvent(self, event): - if event.type() == QtCore.QEvent.LanguageChange: - print "Language changed!" - self.ui.retranslateUi(self) + def changeEvent(self, event): + if event.type() == QtCore.QEvent.LanguageChange: + print "Language changed!" + self.ui.retranslateUi(self) - def Activated(self): - if self.taskmode: - self.setWatchers() - else: - self.draftWidget.setVisible(True) - self.draftWidget.toggleViewAction().setVisible(True) - - def Deactivated(self): - if (FreeCAD.activeDraftCommand != None): - FreeCAD.activeDraftCommand.finish() - if self.taskmode: - FreeCADGui.Control.clearTaskWatcher() - self.tray = None - else: - self.draftWidget.setVisible(False) - self.draftWidget.toggleViewAction().setVisible(False) + def Activated(self): + if self.taskmode: + self.setWatchers() + else: + self.draftWidget.setVisible(True) + self.draftWidget.toggleViewAction().setVisible(True) + def Deactivated(self): + if (FreeCAD.activeDraftCommand != None): + FreeCAD.activeDraftCommand.finish() + if self.taskmode: + FreeCADGui.Control.clearTaskWatcher() + self.tray = None + else: + self.draftWidget.setVisible(False) + self.draftWidget.toggleViewAction().setVisible(False) if not hasattr(FreeCADGui,"draftToolBar"): - FreeCADGui.draftToolBar = DraftToolBar() + FreeCADGui.draftToolBar = DraftToolBar() diff --git a/src/Mod/Draft/draftTools.py b/src/Mod/Draft/draftTools.py index 34273d665..65c6c7eea 100755 --- a/src/Mod/Draft/draftTools.py +++ b/src/Mod/Draft/draftTools.py @@ -44,28 +44,28 @@ from pivy import coin FreeCADGui.updateLocale() def translate(context,text): - "convenience function for Qt translator" - return QtGui.QApplication.translate(context, text, None, QtGui.QApplication.UnicodeUTF8).toUtf8() + "convenience function for Qt translator" + return QtGui.QApplication.translate(context, text, None, QtGui.QApplication.UnicodeUTF8).toUtf8() def msg(text=None,mode=None): - "prints the given message on the FreeCAD status bar" - if not text: FreeCAD.Console.PrintMessage("") + "prints the given message on the FreeCAD status bar" + if not text: FreeCAD.Console.PrintMessage("") + else: + if mode == 'warning': + FreeCAD.Console.PrintWarning(text) + elif mode == 'error': + FreeCAD.Console.PrintError(text) else: - if mode == 'warning': - FreeCAD.Console.PrintWarning(text) - elif mode == 'error': - FreeCAD.Console.PrintError(text) - else: - FreeCAD.Console.PrintMessage(text) + FreeCAD.Console.PrintMessage(text) # loads the fill patterns FreeCAD.svgpatterns = importSVG.getContents(Draft_rc.qt_resource_data,'pattern',True) altpat = Draft.getParam("patternFile") if os.path.isdir(altpat): - for f in os.listdir(altpat): - if '.svg' in f: - p = importSVG.getContents(altpat+os.sep+f,'pattern') - if p: FreeCAD.svgpatterns[p[0]]=p[1] + for f in os.listdir(altpat): + if '.svg' in f: + p = importSVG.getContents(altpat+os.sep+f,'pattern') + if p: FreeCAD.svgpatterns[p[0]]=p[1] # sets the default working plane plane = WorkingPlane.plane() @@ -84,640 +84,628 @@ MODCONSTRAIN = MODS[Draft.getParam("modconstrain")] MODSNAP = MODS[Draft.getParam("modsnap")] MODALT = MODS[Draft.getParam("modalt")] -#--------------------------------------------------------------------------- -# Global state -#--------------------------------------------------------------------------- - -''' plane selection code used to look like this: - if self.ui.lockedz: - self.axis = Vector(0,0,1) - self.xVec = Vector(1,0,0) - self.upVec = Vector(0,1,0) - else: - self.axis = fcvec.neg(self.view.getViewDirection()) - rot = self.view.getCameraNode().orientation.getValue() - self.upVec = Vector(rot.multVec(coin.SbVec3f((0,1,0))).getValue()) - self.xVec = fcvec.rotate(self.upVec,math.pi/2,fcvec.neg(self.axis)) -''' - - #--------------------------------------------------------------------------- # Snapping stuff #--------------------------------------------------------------------------- def snapPoint(target,point,cursor,ctrl=False): - ''' - Snap function used by the Draft tools - - Currently has two modes: passive and active. Pressing CTRL while - clicking puts you in active mode: - - - In passive mode (an open circle appears), your point is - snapped to the nearest point on any underlying geometry. - - - In active mode (ctrl pressed, a filled circle appears), your point - can currently be snapped to the following points: - - Nodes and midpoints of all Part shapes - - Nodes and midpoints of lines/wires - - Centers and quadrant points of circles - - Endpoints of arcs - - Intersection between line, wires segments, arcs and circles - - When constrained (SHIFT pressed), Intersections between - constraining axis and lines/wires - ''' + ''' + Snap function used by the Draft tools + + Currently has two modes: passive and active. Pressing CTRL while + clicking puts you in active mode: + + - In passive mode (an open circle appears), your point is + snapped to the nearest point on any underlying geometry. + + - In active mode (ctrl pressed, a filled circle appears), your point + can currently be snapped to the following points: + - Nodes and midpoints of all Part shapes + - Nodes and midpoints of lines/wires + - Centers and quadrant points of circles + - Endpoints of arcs + - Intersection between line, wires segments, arcs and circles + - When constrained (SHIFT pressed), Intersections between + constraining axis and lines/wires + ''' - def getConstrainedPoint(edge,last,constrain): - "check for constrained snappoint" - p1 = edge.Vertexes[0].Point - p2 = edge.Vertexes[-1].Point - ar = [] - if (constrain == 0): - if ((last.y > p1.y) and (last.y < p2.y) or (last.y > p2.y) and (last.y < p1.y)): - pc = (last.y-p1.y)/(p2.y-p1.y) - cp = (Vector(p1.x+pc*(p2.x-p1.x),p1.y+pc*(p2.y-p1.y),p1.z+pc*(p2.z-p1.z))) - ar.append([cp,1,cp]) # constrainpoint - if (constrain == 1): - if ((last.x > p1.x) and (last.x < p2.x) or (last.x > p2.x) and (last.x < p1.x)): - pc = (last.x-p1.x)/(p2.x-p1.x) - cp = (Vector(p1.x+pc*(p2.x-p1.x),p1.y+pc*(p2.y-p1.y),p1.z+pc*(p2.z-p1.z))) - ar.append([cp,1,cp]) # constrainpoint - return ar + def getConstrainedPoint(edge,last,constrain): + "check for constrained snappoint" + p1 = edge.Vertexes[0].Point + p2 = edge.Vertexes[-1].Point + ar = [] + if (constrain == 0): + if ((last.y > p1.y) and (last.y < p2.y) or (last.y > p2.y) and (last.y < p1.y)): + pc = (last.y-p1.y)/(p2.y-p1.y) + cp = (Vector(p1.x+pc*(p2.x-p1.x),p1.y+pc*(p2.y-p1.y),p1.z+pc*(p2.z-p1.z))) + ar.append([cp,1,cp]) # constrainpoint + if (constrain == 1): + if ((last.x > p1.x) and (last.x < p2.x) or (last.x > p2.x) and (last.x < p1.x)): + pc = (last.x-p1.x)/(p2.x-p1.x) + cp = (Vector(p1.x+pc*(p2.x-p1.x),p1.y+pc*(p2.y-p1.y),p1.z+pc*(p2.z-p1.z))) + ar.append([cp,1,cp]) # constrainpoint + return ar - def getPassivePoint(info): - "returns a passive snap point" - cur = Vector(info['x'],info['y'],info['z']) - return [cur,2,cur] + def getPassivePoint(info): + "returns a passive snap point" + cur = Vector(info['x'],info['y'],info['z']) + return [cur,2,cur] - def getScreenDist(dist,cursor): - "returns a 3D distance from a screen pixels distance" - p1 = FreeCADGui.ActiveDocument.ActiveView.getPoint(cursor) - p2 = FreeCADGui.ActiveDocument.ActiveView.getPoint((cursor[0]+dist,cursor[1])) - return (p2.sub(p1)).Length + def getScreenDist(dist,cursor): + "returns a 3D distance from a screen pixels distance" + p1 = FreeCADGui.ActiveDocument.ActiveView.getPoint(cursor) + p2 = FreeCADGui.ActiveDocument.ActiveView.getPoint((cursor[0]+dist,cursor[1])) + return (p2.sub(p1)).Length - def getGridSnap(target,point): - "returns a grid snap point if available" - if target.grid: - return target.grid.getClosestNode(point) - return None + def getGridSnap(target,point): + "returns a grid snap point if available" + if target.grid: + return target.grid.getClosestNode(point) + return None - def getPerpendicular(edge,last): - "returns a point on an edge, perpendicular to the given point" - dv = last.sub(edge.Vertexes[0].Point) - nv = fcvec.project(dv,fcgeo.vec(edge)) - np = (edge.Vertexes[0].Point).add(nv) - return np + def getPerpendicular(edge,last): + "returns a point on an edge, perpendicular to the given point" + dv = last.sub(edge.Vertexes[0].Point) + nv = fcvec.project(dv,fcgeo.vec(edge)) + np = (edge.Vertexes[0].Point).add(nv) + return np - # checking if alwaySnap setting is on - extractrl = False - if Draft.getParam("alwaysSnap"): - extractrl = ctrl - ctrl = True + # checking if alwaySnap setting is on + extractrl = False + if Draft.getParam("alwaysSnap"): + extractrl = ctrl + ctrl = True - # setting Radius - radius = getScreenDist(Draft.getParam("snapRange"),cursor) + # setting Radius + radius = getScreenDist(Draft.getParam("snapRange"),cursor) - # checking if parallel to one of the edges of the last objects - target.snap.off() - target.extsnap.off() - if (len(target.node) > 0): - for o in [lastObj[1],lastObj[0]]: - if o: - ob = target.doc.getObject(o) - if ob: - edges = ob.Shape.Edges - if len(edges)<10: - for e in edges: - if isinstance(e.Curve,Part.Line): - last = target.node[len(target.node)-1] - de = Part.Line(last,last.add(fcgeo.vec(e))).toShape() - np = getPerpendicular(e,point) - if (np.sub(point)).Length < radius: - target.snap.coords.point.setValue((np.x,np.y,np.z)) - target.snap.setMarker("circle") - target.snap.on() - target.extsnap.p1(e.Vertexes[0].Point) - target.extsnap.p2(np) - target.extsnap.on() - point = np - else: - last = target.node[len(target.node)-1] - de = Part.Line(last,last.add(fcgeo.vec(e))).toShape() - np = getPerpendicular(de,point) - if (np.sub(point)).Length < radius: - target.snap.coords.point.setValue((np.x,np.y,np.z)) - target.snap.setMarker("circle") - target.snap.on() - point = np + # checking if parallel to one of the edges of the last objects + target.snap.off() + target.extsnap.off() + if (len(target.node) > 0): + for o in [lastObj[1],lastObj[0]]: + if o: + ob = target.doc.getObject(o) + if ob: + edges = ob.Shape.Edges + if len(edges)<10: + for e in edges: + if isinstance(e.Curve,Part.Line): + last = target.node[len(target.node)-1] + de = Part.Line(last,last.add(fcgeo.vec(e))).toShape() + np = getPerpendicular(e,point) + if (np.sub(point)).Length < radius: + target.snap.coords.point.setValue((np.x,np.y,np.z)) + target.snap.setMarker("circle") + target.snap.on() + target.extsnap.p1(e.Vertexes[0].Point) + target.extsnap.p2(np) + target.extsnap.on() + point = np + else: + last = target.node[len(target.node)-1] + de = Part.Line(last,last.add(fcgeo.vec(e))).toShape() + np = getPerpendicular(de,point) + if (np.sub(point)).Length < radius: + target.snap.coords.point.setValue((np.x,np.y,np.z)) + target.snap.setMarker("circle") + target.snap.on() + point = np - # check if we snapped to something - snapped=target.view.getObjectInfo((cursor[0],cursor[1])) + # check if we snapped to something + snapped=target.view.getObjectInfo((cursor[0],cursor[1])) - if (snapped == None): - gpt = getGridSnap(target,point) - if gpt: - if radius != 0: - dv = point.sub(gpt) - if dv.Length <= radius: - target.snap.coords.point.setValue((gpt.x,gpt.y,gpt.z)) - target.snap.setMarker("point") - target.snap.on() - return gpt - return point - else: - obj = target.doc.getObject(snapped['Object']) - if hasattr(obj.ViewObject,"Selectable"): + if (snapped == None): + # nothing has been snapped, check fro grid snap + gpt = getGridSnap(target,point) + if gpt: + if radius != 0: + dv = point.sub(gpt) + if dv.Length <= radius: + target.snap.coords.point.setValue((gpt.x,gpt.y,gpt.z)) + target.snap.setMarker("point") + target.snap.on() + return gpt + return point + else: + # we have something to snap + obj = target.doc.getObject(snapped['Object']) + if hasattr(obj.ViewObject,"Selectable"): if not obj.ViewObject.Selectable: return point - if not ctrl: + if not ctrl: # are we in passive snap? snapArray = [getPassivePoint(snapped)] - else: - snapArray = [] - comp = snapped['Component'] - if obj.isDerivedFrom("Part::Feature"): - if "Edge" in comp: - intedges = [] - if lastObj[0]: - lo = target.doc.getObject(lastObj[0]) - if lo: - if lo.isDerivedFrom("Part::Feature"): - intedges = lo.Shape.Edges + else: + snapArray = [] + comp = snapped['Component'] + if obj.isDerivedFrom("Part::Feature"): + if "Edge" in comp: + # get the stored objects to calculate intersections + intedges = [] + if lastObj[0]: + lo = target.doc.getObject(lastObj[0]) + if lo: + if lo.isDerivedFrom("Part::Feature"): + intedges = lo.Shape.Edges - nr = int(comp[4:])-1 - edge = obj.Shape.Edges[nr] - for v in edge.Vertexes: - snapArray.append([v.Point,0,v.Point]) - if isinstance(edge.Curve,Part.Line): - midpoint = fcgeo.findMidpoint(edge) - snapArray.append([midpoint,1,midpoint]) - if (len(target.node) > 0): - last = target.node[len(target.node)-1] - snapArray.extend(getConstrainedPoint(edge,last,target.constrain)) - np = getPerpendicular(edge,last) - snapArray.append([np,1,np]) + nr = int(comp[4:])-1 + edge = obj.Shape.Edges[nr] + for v in edge.Vertexes: + snapArray.append([v.Point,0,v.Point]) + if isinstance(edge.Curve,Part.Line): + # the edge is a line + midpoint = fcgeo.findMidpoint(edge) + snapArray.append([midpoint,1,midpoint]) + if (len(target.node) > 0): + last = target.node[len(target.node)-1] + snapArray.extend(getConstrainedPoint(edge,last,target.constrain)) + np = getPerpendicular(edge,last) + snapArray.append([np,1,np]) - elif isinstance (edge.Curve,Part.Circle): - rad = edge.Curve.Radius - pos = edge.Curve.Center - for i in [0,30,45,60,90,120,135,150,180,210,225,240,270,300,315,330]: - ang = math.radians(i) - cur = Vector(math.sin(ang)*rad+pos.x,math.cos(ang)*rad+pos.y,pos.z) - snapArray.append([cur,1,cur]) - for i in [15,37.5,52.5,75,105,127.5,142.5,165,195,217.5,232.5,255,285,307.5,322.5,345]: - ang = math.radians(i) - cur = Vector(math.sin(ang)*rad+pos.x,math.cos(ang)*rad+pos.y,pos.z) - snapArray.append([cur,0,pos]) + elif isinstance (edge.Curve,Part.Circle): + # the edge is an arc + rad = edge.Curve.Radius + pos = edge.Curve.Center + for i in [0,30,45,60,90,120,135,150,180,210,225,240,270,300,315,330]: + ang = math.radians(i) + cur = Vector(math.sin(ang)*rad+pos.x,math.cos(ang)*rad+pos.y,pos.z) + snapArray.append([cur,1,cur]) + for i in [15,37.5,52.5,75,105,127.5,142.5,165,195,217.5,232.5,255,285,307.5,322.5,345]: + ang = math.radians(i) + cur = Vector(math.sin(ang)*rad+pos.x,math.cos(ang)*rad+pos.y,pos.z) + snapArray.append([cur,0,pos]) - for e in intedges: - pt = fcgeo.findIntersection(e,edge) - if pt: - for p in pt: - snapArray.append([p,3,p]) - elif ("Vertex" in comp): - p = Vector(snapped['x'],snapped['y'],snapped['z']) - snapArray.append([p,0,p]) - elif (comp == ''): - # workaround for the new view provider - p = Vector(snapped['x'],snapped['y'],snapped['z']) - snapArray.append([p,2,p]) - else: - snapArray = [getPassivePoint(snapped)] - elif Draft.getType(obj) == "Dimension": - for pt in [obj.Start,obj.End,obj.Dimline]: - snapArray.append([pt,0,pt]) - elif Draft.getType(obj) == "Mesh": - for v in obj.Mesh.Points: - snapArray.append([v.Vector,0,v.Vector]) - if not lastObj[0]: - lastObj[0] = obj.Name - lastObj[1] = obj.Name - if (lastObj[1] != obj.Name): - lastObj[0] = lastObj[1] - lastObj[1] = obj.Name + for e in intedges: + # get the intersection points + pt = fcgeo.findIntersection(e,edge) + if pt: + for p in pt: + snapArray.append([p,3,p]) + elif "Vertex" in comp: + # directly snapped to a vertex + p = Vector(snapped['x'],snapped['y'],snapped['z']) + snapArray.append([p,0,p]) + elif comp == '': + # workaround for the new view provider + p = Vector(snapped['x'],snapped['y'],snapped['z']) + snapArray.append([p,2,p]) + else: + snapArray = [getPassivePoint(snapped)] + elif Draft.getType(obj) == "Dimension": + for pt in [obj.Start,obj.End,obj.Dimline]: + snapArray.append([pt,0,pt]) + elif Draft.getType(obj) == "Mesh": + for v in obj.Mesh.Points: + snapArray.append([v.Vector,0,v.Vector]) + if not lastObj[0]: + lastObj[0] = obj.Name + lastObj[1] = obj.Name + if (lastObj[1] != obj.Name): + lastObj[0] = lastObj[1] + lastObj[1] = obj.Name - # calculating shortest distance - shortest = 1000000000000000000 - spt = Vector(snapped['x'],snapped['y'],snapped['z']) - newpoint = [Vector(0,0,0),0,Vector(0,0,0)] - for pt in snapArray: - if pt[0] == None: print "snapPoint: debug 'i[0]' is 'None'" - di = pt[0].sub(spt) - if di.Length < shortest: - shortest = di.Length - newpoint = pt - if radius != 0: - dv = point.sub(newpoint[2]) - if (not extractrl) and (dv.Length > radius): - newpoint = getPassivePoint(snapped) - target.snap.coords.point.setValue((newpoint[2].x,newpoint[2].y,newpoint[2].z)) - if (newpoint[1] == 1): - target.snap.setMarker("square") - elif (newpoint[1] == 0): - target.snap.setMarker("point") - elif (newpoint[1] == 3): - target.snap.setMarker("square") - else: - target.snap.setMarker("circle") - target.snap.on() - return newpoint[2] + # calculating shortest distance + shortest = 1000000000000000000 + spt = Vector(snapped['x'],snapped['y'],snapped['z']) + newpoint = [Vector(0,0,0),0,Vector(0,0,0)] + for pt in snapArray: + if pt[0] == None: print "snapPoint: debug 'i[0]' is 'None'" + di = pt[0].sub(spt) + if di.Length < shortest: + shortest = di.Length + newpoint = pt + if radius != 0: + dv = point.sub(newpoint[2]) + if (not extractrl) and (dv.Length > radius): + newpoint = getPassivePoint(snapped) + target.snap.coords.point.setValue((newpoint[2].x,newpoint[2].y,newpoint[2].z)) + if (newpoint[1] == 1): + target.snap.setMarker("square") + elif (newpoint[1] == 0): + target.snap.setMarker("point") + elif (newpoint[1] == 3): + target.snap.setMarker("square") + else: + target.snap.setMarker("circle") + target.snap.on() + return newpoint[2] def constrainPoint (target,pt,mobile=False,sym=False): - ''' - Constrain function used by the Draft tools - On commands that need to enter several points (currently only line/wire), - you can constrain the next point to be picked to the last drawn point by - pressing SHIFT. The vertical or horizontal constraining depends on the - position of your mouse in relation to last point at the moment you press - SHIFT. if mobile=True, mobile behaviour applies. If sym=True, x alway = y - ''' - point = Vector(pt) - if len(target.node) > 0: - last = target.node[-1] - dvec = point.sub(last) - affinity = plane.getClosestAxis(dvec) - if ((target.constrain == None) or mobile): - if affinity == "x": - dv = fcvec.project(dvec,plane.u) - point = last.add(dv) - if sym: - l = dv.Length - if dv.getAngle(plane.u) > 1: - l = -l - point = last.add(plane.getGlobalCoords(Vector(l,l,l))) - target.constrain = 0 #x direction - target.ui.xValue.setEnabled(True) - target.ui.yValue.setEnabled(False) - target.ui.zValue.setEnabled(False) - target.ui.xValue.setFocus() - elif affinity == "y": - dv = fcvec.project(dvec,plane.v) - point = last.add(dv) - if sym: - l = dv.Length - if dv.getAngle(plane.v) > 1: - l = -l - point = last.add(plane.getGlobalCoords(Vector(l,l,l))) - target.constrain = 1 #y direction - target.ui.xValue.setEnabled(False) - target.ui.yValue.setEnabled(True) - target.ui.zValue.setEnabled(False) - target.ui.yValue.setFocus() - elif affinity == "z": - dv = fcvec.project(dvec,plane.axis) - point = last.add(dv) - if sym: - l = dv.Length - if dv.getAngle(plane.axis) > 1: - l = -l - point = last.add(plane.getGlobalCoords(Vector(l,l,l))) - target.constrain = 2 #z direction - target.ui.xValue.setEnabled(False) - target.ui.yValue.setEnabled(False) - target.ui.zValue.setEnabled(True) - target.ui.zValue.setFocus() - else: target.constrain = 3 - elif (target.constrain == 0): - dv = fcvec.project(dvec,plane.u) - point = last.add(dv) - if sym: - l = dv.Length - if dv.getAngle(plane.u) > 1: - l = -l - point = last.add(plane.getGlobalCoords(Vector(l,l,l))) - elif (target.constrain == 1): - dv = fcvec.project(dvec,plane.v) - point = last.add(dv) - if sym: - l = dv.Length - if dv.getAngle(plane.u) > 1: - l = -l - point = last.add(plane.getGlobalCoords(Vector(l,l,l))) - elif (target.constrain == 2): - dv = fcvec.project(dvec,plane.axis) - point = last.add(dv) - if sym: - l = dv.Length - if dv.getAngle(plane.u) > 1: - l = -l - point = last.add(plane.getGlobalCoords(Vector(l,l,l))) - return point + ''' + Constrain function used by the Draft tools + On commands that need to enter several points (currently only line/wire), + you can constrain the next point to be picked to the last drawn point by + pressing SHIFT. The vertical or horizontal constraining depends on the + position of your mouse in relation to last point at the moment you press + SHIFT. if mobile=True, mobile behaviour applies. If sym=True, x alway = y + ''' + point = Vector(pt) + if len(target.node) > 0: + last = target.node[-1] + dvec = point.sub(last) + affinity = plane.getClosestAxis(dvec) + if ((target.constrain == None) or mobile): + if affinity == "x": + dv = fcvec.project(dvec,plane.u) + point = last.add(dv) + if sym: + l = dv.Length + if dv.getAngle(plane.u) > 1: + l = -l + point = last.add(plane.getGlobalCoords(Vector(l,l,l))) + target.constrain = 0 #x direction + target.ui.xValue.setEnabled(True) + target.ui.yValue.setEnabled(False) + target.ui.zValue.setEnabled(False) + target.ui.xValue.setFocus() + elif affinity == "y": + dv = fcvec.project(dvec,plane.v) + point = last.add(dv) + if sym: + l = dv.Length + if dv.getAngle(plane.v) > 1: + l = -l + point = last.add(plane.getGlobalCoords(Vector(l,l,l))) + target.constrain = 1 #y direction + target.ui.xValue.setEnabled(False) + target.ui.yValue.setEnabled(True) + target.ui.zValue.setEnabled(False) + target.ui.yValue.setFocus() + elif affinity == "z": + dv = fcvec.project(dvec,plane.axis) + point = last.add(dv) + if sym: + l = dv.Length + if dv.getAngle(plane.axis) > 1: + l = -l + point = last.add(plane.getGlobalCoords(Vector(l,l,l))) + target.constrain = 2 #z direction + target.ui.xValue.setEnabled(False) + target.ui.yValue.setEnabled(False) + target.ui.zValue.setEnabled(True) + target.ui.zValue.setFocus() + else: target.constrain = 3 + elif (target.constrain == 0): + dv = fcvec.project(dvec,plane.u) + point = last.add(dv) + if sym: + l = dv.Length + if dv.getAngle(plane.u) > 1: + l = -l + point = last.add(plane.getGlobalCoords(Vector(l,l,l))) + elif (target.constrain == 1): + dv = fcvec.project(dvec,plane.v) + point = last.add(dv) + if sym: + l = dv.Length + if dv.getAngle(plane.u) > 1: + l = -l + point = last.add(plane.getGlobalCoords(Vector(l,l,l))) + elif (target.constrain == 2): + dv = fcvec.project(dvec,plane.axis) + point = last.add(dv) + if sym: + l = dv.Length + if dv.getAngle(plane.u) > 1: + l = -l + point = last.add(plane.getGlobalCoords(Vector(l,l,l))) + return point def selectObject(arg): - '''this is a scene even handler, to be called from the Draft tools - when they need to select an object''' - if (arg["Type"] == "SoKeyboardEvent"): - if (arg["Key"] == "ESCAPE"): - FreeCAD.activeDraftCommand.finish() - #TODO : this part raises a coin3D warning about scene traversal, to be fixed. - if (arg["Type"] == "SoMouseButtonEvent"): - if (arg["State"] == "DOWN") and (arg["Button"] == "BUTTON1"): - cursor = arg["Position"] - snapped = FreeCADGui.ActiveDocument.ActiveView.getObjectInfo((cursor[0],cursor[1])) - if snapped: - obj = FreeCAD.ActiveDocument.getObject(snapped['Object']) - FreeCADGui.Selection.addSelection(obj) - FreeCAD.activeDraftCommand.component=snapped['Component'] - FreeCAD.activeDraftCommand.proceed() - + '''this is a scene even handler, to be called from the Draft tools + when they need to select an object''' + if (arg["Type"] == "SoKeyboardEvent"): + if (arg["Key"] == "ESCAPE"): + FreeCAD.activeDraftCommand.finish() + # TODO : this part raises a coin3D warning about scene traversal, to be fixed. + if (arg["Type"] == "SoMouseButtonEvent"): + if (arg["State"] == "DOWN") and (arg["Button"] == "BUTTON1"): + cursor = arg["Position"] + snapped = FreeCADGui.ActiveDocument.ActiveView.getObjectInfo((cursor[0],cursor[1])) + if snapped: + obj = FreeCAD.ActiveDocument.getObject(snapped['Object']) + FreeCADGui.Selection.addSelection(obj) + FreeCAD.activeDraftCommand.component=snapped['Component'] + FreeCAD.activeDraftCommand.proceed() def getPoint(target,args,mobile=False,sym=False,workingplane=True): - ''' - Function used by the Draft Tools. - returns a constrained 3d point and its original point. - if mobile=True, the constraining occurs from the location of - mouse cursor when Shift is pressed, otherwise from last entered - point. If sym=True, x and y values stay always equal. If workingplane=False, - the point wont be projected on the Working Plane. - ''' - ui = FreeCADGui.draftToolBar - view = FreeCADGui.ActiveDocument.ActiveView - point = view.getPoint(args["Position"][0],args["Position"][1]) - point = snapPoint(target,point,args["Position"],hasMod(args,MODSNAP)) + ''' + Function used by the Draft Tools. + returns a constrained 3d point and its original point. + if mobile=True, the constraining occurs from the location of + mouse cursor when Shift is pressed, otherwise from last entered + point. If sym=True, x and y values stay always equal. If workingplane=False, + the point wont be projected on the Working Plane. + ''' + ui = FreeCADGui.draftToolBar + view = FreeCADGui.ActiveDocument.ActiveView + point = view.getPoint(args["Position"][0],args["Position"][1]) + point = snapPoint(target,point,args["Position"],hasMod(args,MODSNAP)) - if (not plane.weak) and workingplane: - # working plane was explicitely selected - project onto it - viewDirection = view.getViewDirection() - if FreeCADGui.ActiveDocument.ActiveView.getCameraType() == "Perspective": - camera = FreeCADGui.ActiveDocument.ActiveView.getCameraNode() - p = camera.getField("position").getValue() - # view is from camera to point: - viewDirection = point.sub(Vector(p[0],p[1],p[2])) - # if we are not snapping to anything, project along view axis, - # otherwise perpendicularly - if view.getObjectInfo((args["Position"][0],args["Position"][1])): - pass - # point = plane.projectPoint(point) - else: - point = plane.projectPoint(point, viewDirection) - ctrlPoint = Vector(point.x,point.y,point.z) - if (hasMod(args,MODCONSTRAIN)): # constraining - if mobile and (target.constrain == None): - target.node.append(point) - point = constrainPoint(target,point,mobile=mobile,sym=sym) - else: - target.constrain = None - ui.xValue.setEnabled(True) - ui.yValue.setEnabled(True) - ui.zValue.setEnabled(True) - if target.node: - if target.featureName == "Rectangle": - ui.displayPoint(point, target.node[0], plane=plane) - else: - ui.displayPoint(point, target.node[-1], plane=plane) - else: ui.displayPoint(point, plane=plane) - return point,ctrlPoint + if (not plane.weak) and workingplane: + # working plane was explicitely selected - project onto it + viewDirection = view.getViewDirection() + if FreeCADGui.ActiveDocument.ActiveView.getCameraType() == "Perspective": + camera = FreeCADGui.ActiveDocument.ActiveView.getCameraNode() + p = camera.getField("position").getValue() + # view is from camera to point: + viewDirection = point.sub(Vector(p[0],p[1],p[2])) + # if we are not snapping to anything, project along view axis, + # otherwise perpendicularly + if view.getObjectInfo((args["Position"][0],args["Position"][1])): + pass + # point = plane.projectPoint(point) + else: + point = plane.projectPoint(point, viewDirection) + ctrlPoint = Vector(point.x,point.y,point.z) + if (hasMod(args,MODCONSTRAIN)): # constraining + if mobile and (target.constrain == None): + target.node.append(point) + point = constrainPoint(target,point,mobile=mobile,sym=sym) + else: + target.constrain = None + ui.xValue.setEnabled(True) + ui.yValue.setEnabled(True) + ui.zValue.setEnabled(True) + if target.node: + if target.featureName == "Rectangle": + ui.displayPoint(point, target.node[0], plane=plane) + else: + ui.displayPoint(point, target.node[-1], plane=plane) + else: ui.displayPoint(point, plane=plane) + return point,ctrlPoint def getSupport(args): - "returns the supporting object and sets the working plane" - snapped = FreeCADGui.ActiveDocument.ActiveView.getObjectInfo((args["Position"][0],args["Position"][1])) - if not snapped: return None - obj = None - plane.save() - try: - obj = FreeCAD.ActiveDocument.getObject(snapped['Object']) - shape = obj.Shape - component = getattr(shape,snapped["Component"]) - if plane.alignToFace(component, 0) \ - or plane.alignToCurve(component, 0): - self.display(plane.axis) - except: - pass - return obj + "returns the supporting object and sets the working plane" + snapped = FreeCADGui.ActiveDocument.ActiveView.getObjectInfo((args["Position"][0],args["Position"][1])) + if not snapped: return None + obj = None + plane.save() + try: + obj = FreeCAD.ActiveDocument.getObject(snapped['Object']) + shape = obj.Shape + component = getattr(shape,snapped["Component"]) + if plane.alignToFace(component, 0) \ + or plane.alignToCurve(component, 0): + self.display(plane.axis) + except: + pass + return obj def hasMod(args,mod): - "checks if args has a specific modifier" - if mod == "shift": - return args["ShiftDown"] - elif mod == "ctrl": - return args["CtrlDown"] - elif mod == "alt": - return args["AltDown"] + "checks if args has a specific modifier" + if mod == "shift": + return args["ShiftDown"] + elif mod == "ctrl": + return args["CtrlDown"] + elif mod == "alt": + return args["AltDown"] def setMod(args,mod,state): - "sets a specific modifier state in args" - if mod == "shift": - args["ShiftDown"] = state - elif mod == "ctrl": - args["CtrlDown"] = state - elif mod == "alt": - args["AltDown"] = state - + "sets a specific modifier state in args" + if mod == "shift": + args["ShiftDown"] = state + elif mod == "ctrl": + args["CtrlDown"] = state + elif mod == "alt": + args["AltDown"] = state #--------------------------------------------------------------------------- # Trackers #--------------------------------------------------------------------------- class Tracker: - "A generic Draft Tracker, to be used by other specific trackers" - def __init__(self,dotted=False,scolor=None,swidth=None,children=[],ontop=False): - self.ontop = ontop - color = coin.SoBaseColor() - color.rgb = scolor or FreeCADGui.draftToolBar.getDefaultColor("ui") - drawstyle = coin.SoDrawStyle() - if swidth: - drawstyle.lineWidth = swidth - if dotted: - drawstyle.style = coin.SoDrawStyle.LINES - drawstyle.lineWeight = 3 - drawstyle.linePattern = 0x0f0f #0xaa - node = coin.SoSeparator() - for c in [drawstyle, color] + children: - node.addChild(c) - self.switch = coin.SoSwitch() # this is the on/off switch - self.switch.addChild(node) - self.switch.whichChild = -1 - self.Visible = False - todo.delay(self._insertSwitch, self.switch) + "A generic Draft Tracker, to be used by other specific trackers" + def __init__(self,dotted=False,scolor=None,swidth=None,children=[],ontop=False): + self.ontop = ontop + color = coin.SoBaseColor() + color.rgb = scolor or FreeCADGui.draftToolBar.getDefaultColor("ui") + drawstyle = coin.SoDrawStyle() + if swidth: + drawstyle.lineWidth = swidth + if dotted: + drawstyle.style = coin.SoDrawStyle.LINES + drawstyle.lineWeight = 3 + drawstyle.linePattern = 0x0f0f #0xaa + node = coin.SoSeparator() + for c in [drawstyle, color] + children: + node.addChild(c) + self.switch = coin.SoSwitch() # this is the on/off switch + self.switch.addChild(node) + self.switch.whichChild = -1 + self.Visible = False + todo.delay(self._insertSwitch, self.switch) - def finalize(self): - todo.delay(self._removeSwitch, self.switch) - self.switch = None + def finalize(self): + todo.delay(self._removeSwitch, self.switch) + self.switch = None - def _insertSwitch(self, switch): - '''insert self.switch into the scene graph. Must not be called - from an event handler (or other scene graph traversal).''' - sg=FreeCADGui.ActiveDocument.ActiveView.getSceneGraph() - if self.ontop: - sg.insertChild(switch,0) - else: - sg.addChild(switch) + def _insertSwitch(self, switch): + '''insert self.switch into the scene graph. Must not be called + from an event handler (or other scene graph traversal).''' + sg=FreeCADGui.ActiveDocument.ActiveView.getSceneGraph() + if self.ontop: + sg.insertChild(switch,0) + else: + sg.addChild(switch) - def _removeSwitch(self, switch): - '''remove self.switch from the scene graph. As with _insertSwitch, - must not be called during scene graph traversal).''' - sg=FreeCADGui.ActiveDocument.ActiveView.getSceneGraph() - sg.removeChild(switch) + def _removeSwitch(self, switch): + '''remove self.switch from the scene graph. As with _insertSwitch, + must not be called during scene graph traversal).''' + sg=FreeCADGui.ActiveDocument.ActiveView.getSceneGraph() + sg.removeChild(switch) - def on(self): - self.switch.whichChild = 0 - self.Visible = True + def on(self): + self.switch.whichChild = 0 + self.Visible = True - def off(self): - self.switch.whichChild = -1 - self.Visible = False + def off(self): + self.switch.whichChild = -1 + self.Visible = False class snapTracker(Tracker): - "A Snap Mark tracker, used by tools that support snapping" - def __init__(self): - color = coin.SoBaseColor() - color.rgb = FreeCADGui.draftToolBar.getDefaultColor("snap") - self.marker = coin.SoMarkerSet() # this is the marker symbol - self.marker.markerIndex = coin.SoMarkerSet.CIRCLE_FILLED_9_9 - self.coords = coin.SoCoordinate3() # this is the coordinate - self.coords.point.setValue((0,0,0)) - node = coin.SoAnnotation() - node.addChild(self.coords) - node.addChild(color) - node.addChild(self.marker) - Tracker.__init__(self,children=[node]) + "A Snap Mark tracker, used by tools that support snapping" + def __init__(self): + color = coin.SoBaseColor() + color.rgb = FreeCADGui.draftToolBar.getDefaultColor("snap") + self.marker = coin.SoMarkerSet() # this is the marker symbol + self.marker.markerIndex = coin.SoMarkerSet.CIRCLE_FILLED_9_9 + self.coords = coin.SoCoordinate3() # this is the coordinate + self.coords.point.setValue((0,0,0)) + node = coin.SoAnnotation() + node.addChild(self.coords) + node.addChild(color) + node.addChild(self.marker) + Tracker.__init__(self,children=[node]) - def setMarker(self,style): - if (style == "point"): - self.marker.markerIndex = coin.SoMarkerSet.CIRCLE_FILLED_9_9 - elif (style == "square"): - self.marker.markerIndex = coin.SoMarkerSet.DIAMOND_FILLED_9_9 - elif (style == "circle"): - self.marker.markerIndex = coin.SoMarkerSet.CIRCLE_LINE_9_9 + def setMarker(self,style): + if (style == "point"): + self.marker.markerIndex = coin.SoMarkerSet.CIRCLE_FILLED_9_9 + elif (style == "square"): + self.marker.markerIndex = coin.SoMarkerSet.DIAMOND_FILLED_9_9 + elif (style == "circle"): + self.marker.markerIndex = coin.SoMarkerSet.CIRCLE_LINE_9_9 class lineTracker(Tracker): - "A Line tracker, used by the tools that need to draw temporary lines" - def __init__(self,dotted=False,scolor=None,swidth=None): - line = coin.SoLineSet() - line.numVertices.setValue(2) - self.coords = coin.SoCoordinate3() # this is the coordinate - self.coords.point.setValues(0,2,[[0,0,0],[1,0,0]]) - Tracker.__init__(self,dotted,scolor,swidth,[self.coords,line]) + "A Line tracker, used by the tools that need to draw temporary lines" + def __init__(self,dotted=False,scolor=None,swidth=None): + line = coin.SoLineSet() + line.numVertices.setValue(2) + self.coords = coin.SoCoordinate3() # this is the coordinate + self.coords.point.setValues(0,2,[[0,0,0],[1,0,0]]) + Tracker.__init__(self,dotted,scolor,swidth,[self.coords,line]) - def p1(self,point=None): - "sets or gets the first point of the line" - if point: - self.coords.point.set1Value(0,point.x,point.y,point.z) - else: - return Vector(self.coords.point.getValues()[0].getValue()) + def p1(self,point=None): + "sets or gets the first point of the line" + if point: + self.coords.point.set1Value(0,point.x,point.y,point.z) + else: + return Vector(self.coords.point.getValues()[0].getValue()) - def p2(self,point=None): - "sets or gets the second point of the line" - if point: - self.coords.point.set1Value(1,point.x,point.y,point.z) - else: - return Vector(self.coords.point.getValues()[-1].getValue()) + def p2(self,point=None): + "sets or gets the second point of the line" + if point: + self.coords.point.set1Value(1,point.x,point.y,point.z) + else: + return Vector(self.coords.point.getValues()[-1].getValue()) - def getLength(self): - "returns the length of the line" - p1 = Vector(self.coords.point.getValues()[0].getValue()) - p2 = Vector(self.coords.point.getValues()[-1].getValue()) - return (p2.sub(p1)).Length + def getLength(self): + "returns the length of the line" + p1 = Vector(self.coords.point.getValues()[0].getValue()) + p2 = Vector(self.coords.point.getValues()[-1].getValue()) + return (p2.sub(p1)).Length class rectangleTracker(Tracker): - "A Rectangle tracker, used by the rectangle tool" - def __init__(self,dotted=False,scolor=None,swidth=None): - self.origin = Vector(0,0,0) - line = coin.SoLineSet() - line.numVertices.setValue(5) - self.coords = coin.SoCoordinate3() # this is the coordinate - self.coords.point.setValues(0,50,[[0,0,0],[2,0,0],[2,2,0],[0,2,0],[0,0,0]]) - Tracker.__init__(self,dotted,scolor,swidth,[self.coords,line]) - self.u = plane.u - self.v = plane.v + "A Rectangle tracker, used by the rectangle tool" + def __init__(self,dotted=False,scolor=None,swidth=None): + self.origin = Vector(0,0,0) + line = coin.SoLineSet() + line.numVertices.setValue(5) + self.coords = coin.SoCoordinate3() # this is the coordinate + self.coords.point.setValues(0,50,[[0,0,0],[2,0,0],[2,2,0],[0,2,0],[0,0,0]]) + Tracker.__init__(self,dotted,scolor,swidth,[self.coords,line]) + self.u = plane.u + self.v = plane.v - def setorigin(self,point): - "sets the base point of the rectangle" - self.coords.point.set1Value(0,point.x,point.y,point.z) - self.coords.point.set1Value(4,point.x,point.y,point.z) - self.origin = point + def setorigin(self,point): + "sets the base point of the rectangle" + self.coords.point.set1Value(0,point.x,point.y,point.z) + self.coords.point.set1Value(4,point.x,point.y,point.z) + self.origin = point - def update(self,point): - "sets the opposite (diagonal) point of the rectangle" - diagonal = point.sub(self.origin) - inpoint1 = self.origin.add(fcvec.project(diagonal,self.v)) - inpoint2 = self.origin.add(fcvec.project(diagonal,self.u)) - self.coords.point.set1Value(1,inpoint1.x,inpoint1.y,inpoint1.z) - self.coords.point.set1Value(2,point.x,point.y,point.z) - self.coords.point.set1Value(3,inpoint2.x,inpoint2.y,inpoint2.z) + def update(self,point): + "sets the opposite (diagonal) point of the rectangle" + diagonal = point.sub(self.origin) + inpoint1 = self.origin.add(fcvec.project(diagonal,self.v)) + inpoint2 = self.origin.add(fcvec.project(diagonal,self.u)) + self.coords.point.set1Value(1,inpoint1.x,inpoint1.y,inpoint1.z) + self.coords.point.set1Value(2,point.x,point.y,point.z) + self.coords.point.set1Value(3,inpoint2.x,inpoint2.y,inpoint2.z) - def setPlane(self,u,v=None): - '''sets given (u,v) vectors as working plane. You can give only u - and v will be deduced automatically given current workplane''' - self.u = u - if v: - self.v = v - else: - norm = plane.u.cross(plane.v) - self.v = self.u.cross(norm) + def setPlane(self,u,v=None): + '''sets given (u,v) vectors as working plane. You can give only u + and v will be deduced automatically given current workplane''' + self.u = u + if v: + self.v = v + else: + norm = plane.u.cross(plane.v) + self.v = self.u.cross(norm) - def p1(self,point=None): - "sets or gets the base point of the rectangle" - if point: - self.setorigin(point) - else: - return Vector(self.coords.point.getValues()[0].getValue()) + def p1(self,point=None): + "sets or gets the base point of the rectangle" + if point: + self.setorigin(point) + else: + return Vector(self.coords.point.getValues()[0].getValue()) - def p2(self): - "gets the second point (on u axis) of the rectangle" - return Vector(self.coords.point.getValues()[3].getValue()) + def p2(self): + "gets the second point (on u axis) of the rectangle" + return Vector(self.coords.point.getValues()[3].getValue()) - def p3(self,point=None): - "sets or gets the opposite (diagonal) point of the rectangle" - if point: - self.update(point) - else: - return Vector(self.coords.point.getValues()[2].getValue()) + def p3(self,point=None): + "sets or gets the opposite (diagonal) point of the rectangle" + if point: + self.update(point) + else: + return Vector(self.coords.point.getValues()[2].getValue()) - def p4(self): - "gets the fourth point (on v axis) of the rectangle" - return Vector(self.coords.point.getValues()[1].getValue()) + def p4(self): + "gets the fourth point (on v axis) of the rectangle" + return Vector(self.coords.point.getValues()[1].getValue()) - def getSize(self): - "returns (length,width) of the rectangle" - p1 = Vector(self.coords.point.getValues()[0].getValue()) - p2 = Vector(self.coords.point.getValues()[2].getValue()) - diag = p2.sub(p1) - return ((fcvec.project(diag,self.u)).Length,(fcvec.project(diag,self.v)).Length) + def getSize(self): + "returns (length,width) of the rectangle" + p1 = Vector(self.coords.point.getValues()[0].getValue()) + p2 = Vector(self.coords.point.getValues()[2].getValue()) + diag = p2.sub(p1) + return ((fcvec.project(diag,self.u)).Length,(fcvec.project(diag,self.v)).Length) - def getNormal(self): - "returns the normal of the rectangle" - return (self.u.cross(self.v)).normalize() + def getNormal(self): + "returns the normal of the rectangle" + return (self.u.cross(self.v)).normalize() class dimTracker(Tracker): - "A Dimension tracker, used by the dimension tool" - def __init__(self,dotted=False,scolor=None,swidth=None): - line = coin.SoLineSet() - line.numVertices.setValue(4) - self.coords = coin.SoCoordinate3() # this is the coordinate - self.coords.point.setValues(0,4,[[0,0,0],[0,0,0],[0,0,0],[0,0,0]]) - Tracker.__init__(self,dotted,scolor,swidth,[self.coords,line]) - self.p1 = self.p2 = self.p3 = None + "A Dimension tracker, used by the dimension tool" + def __init__(self,dotted=False,scolor=None,swidth=None): + line = coin.SoLineSet() + line.numVertices.setValue(4) + self.coords = coin.SoCoordinate3() # this is the coordinate + self.coords.point.setValues(0,4,[[0,0,0],[0,0,0],[0,0,0],[0,0,0]]) + Tracker.__init__(self,dotted,scolor,swidth,[self.coords,line]) + self.p1 = self.p2 = self.p3 = None - def update(self,pts): - if len(pts) == 1: - self.p3 = pts[0] - else: - self.p1 = pts[0] - self.p2 = pts[1] - if len(pts) > 2: - self.p3 = pts[2] - self.calc() + def update(self,pts): + if len(pts) == 1: + self.p3 = pts[0] + else: + self.p1 = pts[0] + self.p2 = pts[1] + if len(pts) > 2: + self.p3 = pts[2] + self.calc() - def calc(self): - if (self.p1 != None) and (self.p2 != None): - points = [fcvec.tup(self.p1,True),fcvec.tup(self.p2,True),\ - fcvec.tup(self.p1,True),fcvec.tup(self.p2,True)] - if self.p3 != None: - p1 = self.p1 - p4 = self.p2 - if fcvec.equals(p1,p4): - proj = None - else: - base = Part.Line(p1,p4).toShape() - proj = fcgeo.findDistance(self.p3,base) - if not proj: - p2 = p1 - p3 = p4 - else: - p2 = p1.add(fcvec.neg(proj)) - p3 = p4.add(fcvec.neg(proj)) - points = [fcvec.tup(p1),fcvec.tup(p2),fcvec.tup(p3),fcvec.tup(p4)] - self.coords.point.setValues(0,4,points) + def calc(self): + if (self.p1 != None) and (self.p2 != None): + points = [fcvec.tup(self.p1,True),fcvec.tup(self.p2,True),\ + fcvec.tup(self.p1,True),fcvec.tup(self.p2,True)] + if self.p3 != None: + p1 = self.p1 + p4 = self.p2 + if fcvec.equals(p1,p4): + proj = None + else: + base = Part.Line(p1,p4).toShape() + proj = fcgeo.findDistance(self.p3,base) + if not proj: + p2 = p1 + p3 = p4 + else: + p2 = p1.add(fcvec.neg(proj)) + p3 = p4.add(fcvec.neg(proj)) + points = [fcvec.tup(p1),fcvec.tup(p2),fcvec.tup(p3),fcvec.tup(p4)] + self.coords.point.setValues(0,4,points) class bsplineTracker(Tracker): "A bspline tracker" @@ -740,16 +728,16 @@ class bsplineTracker(Tracker): c = Part.BSplineCurve() # DNC: allows to close the curve by placing ends close to each other if ( len(self.points) >= 3 ) and ( (self.points[0] - self.points[-1]).Length < Draft.tolerance() ): - # YVH: Added a try to bypass some hazardous situations - try: - c.interpolate(self.points[:-1], True) - except: - pass + # YVH: Added a try to bypass some hazardous situations + try: + c.interpolate(self.points[:-1], True) + except: + pass elif self.points: - try: - c.interpolate(self.points, False) - except: - pass + try: + c.interpolate(self.points, False) + except: + pass c = c.toShape() buf=c.writeInventor(2,0.01) #fp=open("spline.iv","w") @@ -768,325 +756,325 @@ class bsplineTracker(Tracker): FreeCAD.Console.PrintWarning("bsplineTracker.recompute() failed to read-in Inventor string\n") class arcTracker(Tracker): - "An arc tracker" - def __init__(self,dotted=False,scolor=None,swidth=None,start=0,end=math.pi*2): - self.circle = None - self.startangle = math.degrees(start) - self.endangle = math.degrees(end) - self.trans = coin.SoTransform() - self.trans.translation.setValue([0,0,0]) - self.sep = coin.SoSeparator() - self.recompute() - Tracker.__init__(self,dotted,scolor,swidth,[self.trans, self.sep]) + "An arc tracker" + def __init__(self,dotted=False,scolor=None,swidth=None,start=0,end=math.pi*2): + self.circle = None + self.startangle = math.degrees(start) + self.endangle = math.degrees(end) + self.trans = coin.SoTransform() + self.trans.translation.setValue([0,0,0]) + self.sep = coin.SoSeparator() + self.recompute() + Tracker.__init__(self,dotted,scolor,swidth,[self.trans, self.sep]) - def setCenter(self,cen): - "sets the center point" - self.trans.translation.setValue([cen.x,cen.y,cen.z]) + def setCenter(self,cen): + "sets the center point" + self.trans.translation.setValue([cen.x,cen.y,cen.z]) - def setRadius(self,rad): - "sets the radius" - self.trans.scaleFactor.setValue([rad,rad,rad]) + def setRadius(self,rad): + "sets the radius" + self.trans.scaleFactor.setValue([rad,rad,rad]) - def getRadius(self): - "returns the current radius" - return self.trans.scaleFactor.getValue()[0] + def getRadius(self): + "returns the current radius" + return self.trans.scaleFactor.getValue()[0] - def setStartAngle(self,ang): - "sets the start angle" - self.startangle = math.degrees(ang) - self.recompute() + def setStartAngle(self,ang): + "sets the start angle" + self.startangle = math.degrees(ang) + self.recompute() - def setEndAngle(self,ang): - "sets the end angle" - self.endangle = math.degrees(ang) - self.recompute() + def setEndAngle(self,ang): + "sets the end angle" + self.endangle = math.degrees(ang) + self.recompute() - def getAngle(self,pt): - "returns the angle of a given vector" - c = self.trans.translation.getValue() - center = Vector(c[0],c[1],c[2]) - base = plane.u - rad = pt.sub(center) - return(fcvec.angle(rad,base,plane.axis)) + def getAngle(self,pt): + "returns the angle of a given vector" + c = self.trans.translation.getValue() + center = Vector(c[0],c[1],c[2]) + base = plane.u + rad = pt.sub(center) + return(fcvec.angle(rad,base,plane.axis)) - def getAngles(self): - "returns the start and end angles" - return(self.startangle,self.endangle) + def getAngles(self): + "returns the start and end angles" + return(self.startangle,self.endangle) - def setStartPoint(self,pt): - "sets the start angle from a point" - self.setStartAngle(-self.getAngle(pt)) + def setStartPoint(self,pt): + "sets the start angle from a point" + self.setStartAngle(-self.getAngle(pt)) - def setEndPoint(self,pt): - "sets the end angle from a point" - self.setEndAngle(self.getAngle(pt)) + def setEndPoint(self,pt): + "sets the end angle from a point" + self.setEndAngle(self.getAngle(pt)) - def setApertureAngle(self,ang): - "sets the end angle by giving the aperture angle" - ap = math.degrees(ang) - self.endangle = self.startangle + ap - self.recompute() + def setApertureAngle(self,ang): + "sets the end angle by giving the aperture angle" + ap = math.degrees(ang) + self.endangle = self.startangle + ap + self.recompute() - def recompute(self): - if self.circle: self.sep.removeChild(self.circle) - self.circle = None - if self.endangle < self.startangle: - c = Part.makeCircle(1,Vector(0,0,0),plane.axis,self.endangle,self.startangle) - else: - c = Part.makeCircle(1,Vector(0,0,0),plane.axis,self.startangle,self.endangle) - buf=c.writeInventor(2,0.01) - ivin = coin.SoInput() - ivin.setBuffer(buf) - ivob = coin.SoDB.readAll(ivin) - # In case reading from buffer failed - if ivob and ivob.getNumChildren() > 1: - self.circle = ivob.getChild(1).getChild(0) - self.circle.removeChild(self.circle.getChild(0)) - self.circle.removeChild(self.circle.getChild(0)) - self.sep.addChild(self.circle) - else: - FreeCAD.Console.PrintWarning("arcTracker.recompute() failed to read-in Inventor string\n") + def recompute(self): + if self.circle: self.sep.removeChild(self.circle) + self.circle = None + if self.endangle < self.startangle: + c = Part.makeCircle(1,Vector(0,0,0),plane.axis,self.endangle,self.startangle) + else: + c = Part.makeCircle(1,Vector(0,0,0),plane.axis,self.startangle,self.endangle) + buf=c.writeInventor(2,0.01) + ivin = coin.SoInput() + ivin.setBuffer(buf) + ivob = coin.SoDB.readAll(ivin) + # In case reading from buffer failed + if ivob and ivob.getNumChildren() > 1: + self.circle = ivob.getChild(1).getChild(0) + self.circle.removeChild(self.circle.getChild(0)) + self.circle.removeChild(self.circle.getChild(0)) + self.sep.addChild(self.circle) + else: + FreeCAD.Console.PrintWarning("arcTracker.recompute() failed to read-in Inventor string\n") class ghostTracker(Tracker): - '''A Ghost tracker, that allows to copy whole object representations. - You can pass it an object or a list of objects, or a shape.''' - def __init__(self,sel): - self.trans = coin.SoTransform() - self.trans.translation.setValue([0,0,0]) - self.children = [self.trans] - self.ivsep = coin.SoSeparator() - try: - if isinstance(sel,Part.Shape): - ivin = coin.SoInput() - ivin.setBuffer(sel.writeInventor()) - ivob = coin.SoDB.readAll(ivin) - self.ivsep.addChild(ivob.getChildren()[1]) - else: - if not isinstance(sel,list): - sel = [sel] - for obj in sel: - self.ivsep.addChild(obj.ViewObject.RootNode.copy()) - except: - print "draft: Couldn't create ghost" - self.children.append(self.ivsep) - Tracker.__init__(self,children=self.children) + '''A Ghost tracker, that allows to copy whole object representations. + You can pass it an object or a list of objects, or a shape.''' + def __init__(self,sel): + self.trans = coin.SoTransform() + self.trans.translation.setValue([0,0,0]) + self.children = [self.trans] + self.ivsep = coin.SoSeparator() + try: + if isinstance(sel,Part.Shape): + ivin = coin.SoInput() + ivin.setBuffer(sel.writeInventor()) + ivob = coin.SoDB.readAll(ivin) + self.ivsep.addChild(ivob.getChildren()[1]) + else: + if not isinstance(sel,list): + sel = [sel] + for obj in sel: + self.ivsep.addChild(obj.ViewObject.RootNode.copy()) + except: + print "draft: Couldn't create ghost" + self.children.append(self.ivsep) + Tracker.__init__(self,children=self.children) - def update(self,obj): - obj.ViewObject.show() - self.finalize() - self.ivsep = coin.SoSeparator() - self.ivsep.addChild(obj.ViewObject.RootNode.copy()) - Tracker.__init__(self,children=[self.ivsep]) - self.on() - obj.ViewObject.hide() + def update(self,obj): + obj.ViewObject.show() + self.finalize() + self.ivsep = coin.SoSeparator() + self.ivsep.addChild(obj.ViewObject.RootNode.copy()) + Tracker.__init__(self,children=[self.ivsep]) + self.on() + obj.ViewObject.hide() class editTracker(Tracker): - "A node edit tracker" - def __init__(self,pos=Vector(0,0,0),name="None",idx=0,objcol=None): - color = coin.SoBaseColor() - if objcol: - color.rgb = objcol[:3] - else: - color.rgb = FreeCADGui.draftToolBar.getDefaultColor("snap") - self.marker = coin.SoMarkerSet() # this is the marker symbol - self.marker.markerIndex = coin.SoMarkerSet.SQUARE_FILLED_9_9 - self.coords = coin.SoCoordinate3() # this is the coordinate - self.coords.point.setValue((pos.x,pos.y,pos.z)) - selnode = coin.SoType.fromName("SoFCSelection").createInstance() - selnode.documentName.setValue(FreeCAD.ActiveDocument.Name) - selnode.objectName.setValue(name) - selnode.subElementName.setValue("EditNode"+str(idx)) - node = coin.SoAnnotation() - selnode.addChild(self.coords) - selnode.addChild(color) - selnode.addChild(self.marker) - node.addChild(selnode) - Tracker.__init__(self,children=[node],ontop=True) - self.on() + "A node edit tracker" + def __init__(self,pos=Vector(0,0,0),name="None",idx=0,objcol=None): + color = coin.SoBaseColor() + if objcol: + color.rgb = objcol[:3] + else: + color.rgb = FreeCADGui.draftToolBar.getDefaultColor("snap") + self.marker = coin.SoMarkerSet() # this is the marker symbol + self.marker.markerIndex = coin.SoMarkerSet.SQUARE_FILLED_9_9 + self.coords = coin.SoCoordinate3() # this is the coordinate + self.coords.point.setValue((pos.x,pos.y,pos.z)) + selnode = coin.SoType.fromName("SoFCSelection").createInstance() + selnode.documentName.setValue(FreeCAD.ActiveDocument.Name) + selnode.objectName.setValue(name) + selnode.subElementName.setValue("EditNode"+str(idx)) + node = coin.SoAnnotation() + selnode.addChild(self.coords) + selnode.addChild(color) + selnode.addChild(self.marker) + node.addChild(selnode) + Tracker.__init__(self,children=[node],ontop=True) + self.on() - def set(self,pos): - self.coords.point.setValue((pos.x,pos.y,pos.z)) + def set(self,pos): + self.coords.point.setValue((pos.x,pos.y,pos.z)) - def get(self): - p = self.coords.point.getValues()[0] - return Vector(p[0],p[1],p[2]) + def get(self): + p = self.coords.point.getValues()[0] + return Vector(p[0],p[1],p[2]) - def move(self,delta): - self.set(self.get().add(delta)) + def move(self,delta): + self.set(self.get().add(delta)) class PlaneTracker(Tracker): - "A working plane tracker" - def __init__(self): - # getting screen distance - p1 = FreeCADGui.ActiveDocument.ActiveView.getPoint((100,100)) - p2 = FreeCADGui.ActiveDocument.ActiveView.getPoint((110,100)) - bl = (p2.sub(p1)).Length * (Draft.getParam("snapRange")/2) - self.trans = coin.SoTransform() - self.trans.translation.setValue([0,0,0]) - m1 = coin.SoMaterial() - m1.transparency.setValue(0.8) - m1.diffuseColor.setValue([0.4,0.4,0.6]) - c1 = coin.SoCoordinate3() - c1.point.setValues([[-bl,-bl,0],[bl,-bl,0],[bl,bl,0],[-bl,bl,0]]) - f = coin.SoIndexedFaceSet() - f.coordIndex.setValues([0,1,2,3]) - m2 = coin.SoMaterial() - m2.transparency.setValue(0.7) - m2.diffuseColor.setValue([0.2,0.2,0.3]) - c2 = coin.SoCoordinate3() - c2.point.setValues([[0,bl,0],[0,0,0],[bl,0,0],[-.05*bl,.95*bl,0],[0,bl,0], - [.05*bl,.95*bl,0],[.95*bl,.05*bl,0],[bl,0,0],[.95*bl,-.05*bl,0]]) - l = coin.SoLineSet() - l.numVertices.setValues([3,3,3]) - s = coin.SoSeparator() - s.addChild(self.trans) - s.addChild(m1) - s.addChild(c1) - s.addChild(f) - s.addChild(m2) - s.addChild(c2) - s.addChild(l) - Tracker.__init__(self,children=[s]) + "A working plane tracker" + def __init__(self): + # getting screen distance + p1 = FreeCADGui.ActiveDocument.ActiveView.getPoint((100,100)) + p2 = FreeCADGui.ActiveDocument.ActiveView.getPoint((110,100)) + bl = (p2.sub(p1)).Length * (Draft.getParam("snapRange")/2) + self.trans = coin.SoTransform() + self.trans.translation.setValue([0,0,0]) + m1 = coin.SoMaterial() + m1.transparency.setValue(0.8) + m1.diffuseColor.setValue([0.4,0.4,0.6]) + c1 = coin.SoCoordinate3() + c1.point.setValues([[-bl,-bl,0],[bl,-bl,0],[bl,bl,0],[-bl,bl,0]]) + f = coin.SoIndexedFaceSet() + f.coordIndex.setValues([0,1,2,3]) + m2 = coin.SoMaterial() + m2.transparency.setValue(0.7) + m2.diffuseColor.setValue([0.2,0.2,0.3]) + c2 = coin.SoCoordinate3() + c2.point.setValues([[0,bl,0],[0,0,0],[bl,0,0],[-.05*bl,.95*bl,0],[0,bl,0], + [.05*bl,.95*bl,0],[.95*bl,.05*bl,0],[bl,0,0],[.95*bl,-.05*bl,0]]) + l = coin.SoLineSet() + l.numVertices.setValues([3,3,3]) + s = coin.SoSeparator() + s.addChild(self.trans) + s.addChild(m1) + s.addChild(c1) + s.addChild(f) + s.addChild(m2) + s.addChild(c2) + s.addChild(l) + Tracker.__init__(self,children=[s]) - def set(self,pos=None): - if pos: - Q = plane.getRotation().Rotation.Q - else: - plm = plane.getPlacement() - Q = plm.Rotation.Q - pos = plm.Base - self.trans.translation.setValue([pos.x,pos.y,pos.z]) - self.trans.rotation.setValue([Q[0],Q[1],Q[2],Q[3]]) - self.on() + def set(self,pos=None): + if pos: + Q = plane.getRotation().Rotation.Q + else: + plm = plane.getPlacement() + Q = plm.Rotation.Q + pos = plm.Base + self.trans.translation.setValue([pos.x,pos.y,pos.z]) + self.trans.rotation.setValue([Q[0],Q[1],Q[2],Q[3]]) + self.on() class wireTracker(Tracker): - "A wire tracker" - def __init__(self,wire): - self.line = coin.SoLineSet() - self.closed = fcgeo.isReallyClosed(wire) - if self.closed: - self.line.numVertices.setValue(len(wire.Vertexes)+1) - else: - self.line.numVertices.setValue(len(wire.Vertexes)) - self.coords = coin.SoCoordinate3() - self.update(wire) - Tracker.__init__(self,children=[self.coords,self.line]) + "A wire tracker" + def __init__(self,wire): + self.line = coin.SoLineSet() + self.closed = fcgeo.isReallyClosed(wire) + if self.closed: + self.line.numVertices.setValue(len(wire.Vertexes)+1) + else: + self.line.numVertices.setValue(len(wire.Vertexes)) + self.coords = coin.SoCoordinate3() + self.update(wire) + Tracker.__init__(self,children=[self.coords,self.line]) - def update(self,wire): - if wire: - self.line.numVertices.setValue(len(wire.Vertexes)) - for i in range(len(wire.Vertexes)): - p=wire.Vertexes[i].Point - self.coords.point.set1Value(i,[p.x,p.y,p.z]) - if self.closed: - t = len(wire.Vertexes) - p = wire.Vertexes[0].Point - self.coords.point.set1Value(t,[p.x,p.y,p.z]) + def update(self,wire): + if wire: + self.line.numVertices.setValue(len(wire.Vertexes)) + for i in range(len(wire.Vertexes)): + p=wire.Vertexes[i].Point + self.coords.point.set1Value(i,[p.x,p.y,p.z]) + if self.closed: + t = len(wire.Vertexes) + p = wire.Vertexes[0].Point + self.coords.point.set1Value(t,[p.x,p.y,p.z]) class gridTracker(Tracker): - "A grid tracker" - def __init__(self): - # self.space = 1 - self.space = Draft.getParam("gridSpacing") - # self.mainlines = 10 - self.mainlines = Draft.getParam("gridEvery") - self.numlines = 100 - col = [0.2,0.2,0.3] - - self.trans = coin.SoTransform() - self.trans.translation.setValue([0,0,0]) + "A grid tracker" + def __init__(self): + # self.space = 1 + self.space = Draft.getParam("gridSpacing") + # self.mainlines = 10 + self.mainlines = Draft.getParam("gridEvery") + self.numlines = 100 + col = [0.2,0.2,0.3] + + self.trans = coin.SoTransform() + self.trans.translation.setValue([0,0,0]) - bound = (self.numlines/2)*self.space - pts = [] - mpts = [] - for i in range(self.numlines+1): - curr = -bound + i*self.space - z = 0 - if i/float(self.mainlines) == i/self.mainlines: - mpts.extend([[-bound,curr,z],[bound,curr,z]]) - mpts.extend([[curr,-bound,z],[curr,bound,z]]) - else: - pts.extend([[-bound,curr,z],[bound,curr,z]]) - pts.extend([[curr,-bound,z],[curr,bound,z]]) - idx = [] - midx = [] - for p in range(0,len(pts),2): - idx.append(2) - for mp in range(0,len(mpts),2): - midx.append(2) + bound = (self.numlines/2)*self.space + pts = [] + mpts = [] + for i in range(self.numlines+1): + curr = -bound + i*self.space + z = 0 + if i/float(self.mainlines) == i/self.mainlines: + mpts.extend([[-bound,curr,z],[bound,curr,z]]) + mpts.extend([[curr,-bound,z],[curr,bound,z]]) + else: + pts.extend([[-bound,curr,z],[bound,curr,z]]) + pts.extend([[curr,-bound,z],[curr,bound,z]]) + idx = [] + midx = [] + for p in range(0,len(pts),2): + idx.append(2) + for mp in range(0,len(mpts),2): + midx.append(2) - mat1 = coin.SoMaterial() - mat1.transparency.setValue(0.7) - mat1.diffuseColor.setValue(col) - self.coords1 = coin.SoCoordinate3() - self.coords1.point.setValues(pts) - lines1 = coin.SoLineSet() - lines1.numVertices.setValues(idx) - mat2 = coin.SoMaterial() - mat2.transparency.setValue(0.3) - mat2.diffuseColor.setValue(col) - self.coords2 = coin.SoCoordinate3() - self.coords2.point.setValues(mpts) - lines2 = coin.SoLineSet() - lines2.numVertices.setValues(midx) - s = coin.SoSeparator() - s.addChild(self.trans) - s.addChild(mat1) - s.addChild(self.coords1) - s.addChild(lines1) - s.addChild(mat2) - s.addChild(self.coords2) - s.addChild(lines2) - Tracker.__init__(self,children=[s]) - self.update() + mat1 = coin.SoMaterial() + mat1.transparency.setValue(0.7) + mat1.diffuseColor.setValue(col) + self.coords1 = coin.SoCoordinate3() + self.coords1.point.setValues(pts) + lines1 = coin.SoLineSet() + lines1.numVertices.setValues(idx) + mat2 = coin.SoMaterial() + mat2.transparency.setValue(0.3) + mat2.diffuseColor.setValue(col) + self.coords2 = coin.SoCoordinate3() + self.coords2.point.setValues(mpts) + lines2 = coin.SoLineSet() + lines2.numVertices.setValues(midx) + s = coin.SoSeparator() + s.addChild(self.trans) + s.addChild(mat1) + s.addChild(self.coords1) + s.addChild(lines1) + s.addChild(mat2) + s.addChild(self.coords2) + s.addChild(lines2) + Tracker.__init__(self,children=[s]) + self.update() - def update(self): - bound = (self.numlines/2)*self.space - pts = [] - mpts = [] - for i in range(self.numlines+1): - curr = -bound + i*self.space - if i/float(self.mainlines) == i/self.mainlines: - mpts.extend([[-bound,curr,0],[bound,curr,0]]) - mpts.extend([[curr,-bound,0],[curr,bound,0]]) - else: - pts.extend([[-bound,curr,0],[bound,curr,0]]) - pts.extend([[curr,-bound,0],[curr,bound,0]]) - self.coords1.point.setValues(pts) - self.coords2.point.setValues(mpts) + def update(self): + bound = (self.numlines/2)*self.space + pts = [] + mpts = [] + for i in range(self.numlines+1): + curr = -bound + i*self.space + if i/float(self.mainlines) == i/self.mainlines: + mpts.extend([[-bound,curr,0],[bound,curr,0]]) + mpts.extend([[curr,-bound,0],[curr,bound,0]]) + else: + pts.extend([[-bound,curr,0],[bound,curr,0]]) + pts.extend([[curr,-bound,0],[curr,bound,0]]) + self.coords1.point.setValues(pts) + self.coords2.point.setValues(mpts) - def setSpacing(self,space): - self.space = space - self.update() + def setSpacing(self,space): + self.space = space + self.update() - def setMainlines(self,ml): - self.mainlines = ml - self.update() + def setMainlines(self,ml): + self.mainlines = ml + self.update() - def set(self): - Q = plane.getRotation().Rotation.Q - self.trans.rotation.setValue([Q[0],Q[1],Q[2],Q[3]]) - self.on() + def set(self): + Q = plane.getRotation().Rotation.Q + self.trans.rotation.setValue([Q[0],Q[1],Q[2],Q[3]]) + self.on() - def getClosestNode(self,point): - "returns the closest node from the given point" - # get the 2D coords. - point = plane.projectPoint(point) - u = fcvec.project(point,plane.u) - lu = u.Length - if u.getAngle(plane.u) > 1.5: - lu = -lu - v = fcvec.project(point,plane.v) - lv = v.Length - if v.getAngle(plane.v) > 1.5: - lv = -lv - # print "u = ",u," v = ",v - # find nearest grid node - pu = (round(lu/self.space,0))*self.space - pv = (round(lv/self.space,0))*self.space - rot = FreeCAD.Rotation() - rot.Q = self.trans.rotation.getValue().getValue() - return rot.multVec(Vector(pu,pv,0)) + def getClosestNode(self,point): + "returns the closest node from the given point" + # get the 2D coords. + point = plane.projectPoint(point) + u = fcvec.project(point,plane.u) + lu = u.Length + if u.getAngle(plane.u) > 1.5: + lu = -lu + v = fcvec.project(point,plane.v) + lv = v.Length + if v.getAngle(plane.v) > 1.5: + lv = -lv + # print "u = ",u," v = ",v + # find nearest grid node + pu = (round(lu/self.space,0))*self.space + pv = (round(lv/self.space,0))*self.space + rot = FreeCAD.Rotation() + rot.Q = self.trans.rotation.getValue().getValue() + return rot.multVec(Vector(pu,pv,0)) #--------------------------------------------------------------------------- @@ -1094,107 +1082,107 @@ class gridTracker(Tracker): #--------------------------------------------------------------------------- class SelectPlane: - "The Draft_SelectPlane FreeCAD command definition" + "The Draft_SelectPlane FreeCAD command definition" - def GetResources(self): - return {'Pixmap' : 'Draft_SelectPlane', - 'Accel' : "W, P", - 'MenuText': QtCore.QT_TRANSLATE_NOOP("Draft_SelectPlane", "SelectPlane"), - 'ToolTip' : QtCore.QT_TRANSLATE_NOOP("Draft_SelectPlane", "Select a working plane for geometry creation")} + def GetResources(self): + return {'Pixmap' : 'Draft_SelectPlane', + 'Accel' : "W, P", + 'MenuText': QtCore.QT_TRANSLATE_NOOP("Draft_SelectPlane", "SelectPlane"), + 'ToolTip' : QtCore.QT_TRANSLATE_NOOP("Draft_SelectPlane", "Select a working plane for geometry creation")} - def IsActive(self): - if FreeCADGui.ActiveDocument: - return True - else: - return False + def IsActive(self): + if FreeCADGui.ActiveDocument: + return True + else: + return False - def Activated(self): - if FreeCAD.activeDraftCommand: - FreeCAD.activeDraftCommand.finish() - self.offset = 0 - self.ui = None - self.call = None - self.doc = FreeCAD.ActiveDocument - if self.doc: - FreeCAD.activeDraftCommand = self - self.view = FreeCADGui.ActiveDocument.ActiveView - self.ui = FreeCADGui.draftToolBar - self.ui.selectPlaneUi() - msg(translate("draft", "Pick a face to define the drawing plane\n")) - self.ui.sourceCmd = self - if plane.alignToSelection(self.offset): - FreeCADGui.Selection.clearSelection() - self.display(plane.axis) - self.finish() - else: - self.call = self.view.addEventCallback("SoEvent", self.action) + def Activated(self): + if FreeCAD.activeDraftCommand: + FreeCAD.activeDraftCommand.finish() + self.offset = 0 + self.ui = None + self.call = None + self.doc = FreeCAD.ActiveDocument + if self.doc: + FreeCAD.activeDraftCommand = self + self.view = FreeCADGui.ActiveDocument.ActiveView + self.ui = FreeCADGui.draftToolBar + self.ui.selectPlaneUi() + msg(translate("draft", "Pick a face to define the drawing plane\n")) + self.ui.sourceCmd = self + if plane.alignToSelection(self.offset): + FreeCADGui.Selection.clearSelection() + self.display(plane.axis) + self.finish() + else: + self.call = self.view.addEventCallback("SoEvent", self.action) - def action(self, arg): - if arg["Type"] == "SoKeyboardEvent" and arg["Key"] == "ESCAPE": - self.finish() - if arg["Type"] == "SoMouseButtonEvent": - if (arg["State"] == "DOWN") and (arg["Button"] == "BUTTON1"): - cursor = arg["Position"] - doc = FreeCADGui.ActiveDocument - info = doc.ActiveView.getObjectInfo((cursor[0],cursor[1])) - if info: - try: - shape = doc.getObject(info["Object"]).Object.Shape - component = getattr(shape, info["Component"]) - if plane.alignToFace(component, self.offset) \ - or plane.alignToCurve(component, self.offset): - self.display(plane.axis) - self.finish() - except: - pass + def action(self, arg): + if arg["Type"] == "SoKeyboardEvent" and arg["Key"] == "ESCAPE": + self.finish() + if arg["Type"] == "SoMouseButtonEvent": + if (arg["State"] == "DOWN") and (arg["Button"] == "BUTTON1"): + cursor = arg["Position"] + doc = FreeCADGui.ActiveDocument + info = doc.ActiveView.getObjectInfo((cursor[0],cursor[1])) + if info: + try: + shape = doc.getObject(info["Object"]).Object.Shape + component = getattr(shape, info["Component"]) + if plane.alignToFace(component, self.offset) \ + or plane.alignToCurve(component, self.offset): + self.display(plane.axis) + self.finish() + except: + pass - def selectHandler(self, arg): - try: - self.offset = float(self.ui.offsetValue.text()) - except: - self.offset = 0 - if arg == "XY": - plane.alignToPointAndAxis(Vector(0,0,0), Vector(0,0,1), self.offset) - self.display('top') - self.finish() - elif arg == "XZ": - plane.alignToPointAndAxis(Vector(0,0,0), Vector(0,-1,0), self.offset) - self.display('front') - self.finish() - elif arg == "YZ": - plane.alignToPointAndAxis(Vector(0,0,0), Vector(1,0,0), self.offset) - self.display('side') - self.finish() - elif arg == "currentView": - viewDirection = fcvec.neg(self.view.getViewDirection()) - plane.alignToPointAndAxis(Vector(0,0,0), viewDirection, self.offset) - self.display(viewDirection) - self.finish() - elif arg == "reset": - plane.reset() - self.display('None') - self.finish() + def selectHandler(self, arg): + try: + self.offset = float(self.ui.offsetValue.text()) + except: + self.offset = 0 + if arg == "XY": + plane.alignToPointAndAxis(Vector(0,0,0), Vector(0,0,1), self.offset) + self.display('top') + self.finish() + elif arg == "XZ": + plane.alignToPointAndAxis(Vector(0,0,0), Vector(0,-1,0), self.offset) + self.display('front') + self.finish() + elif arg == "YZ": + plane.alignToPointAndAxis(Vector(0,0,0), Vector(1,0,0), self.offset) + self.display('side') + self.finish() + elif arg == "currentView": + viewDirection = fcvec.neg(self.view.getViewDirection()) + plane.alignToPointAndAxis(Vector(0,0,0), viewDirection, self.offset) + self.display(viewDirection) + self.finish() + elif arg == "reset": + plane.reset() + self.display('None') + self.finish() - def offsetHandler(self, arg): - self.offset = arg + def offsetHandler(self, arg): + self.offset = arg - def display(self,arg): - if self.offset: - if self.offset > 0: suffix = ' + '+str(self.offset) - else: suffix = ' - '+str(self.offset) - else: suffix = '' - if type(arg).__name__ == 'str': - self.ui.wplabel.setText(arg+suffix) - elif type(arg).__name__ == 'Vector': - plv = 'd('+str(arg.x)+','+str(arg.y)+','+str(arg.z)+')' - self.ui.wplabel.setText(plv+suffix) + def display(self,arg): + if self.offset: + if self.offset > 0: suffix = ' + '+str(self.offset) + else: suffix = ' - '+str(self.offset) + else: suffix = '' + if type(arg).__name__ == 'str': + self.ui.wplabel.setText(arg+suffix) + elif type(arg).__name__ == 'Vector': + plv = 'd('+str(arg.x)+','+str(arg.y)+','+str(arg.z)+')' + self.ui.wplabel.setText(plv+suffix) - def finish(self): - if self.call: - self.view.removeEventCallback("SoEvent",self.call) - FreeCAD.activeDraftCommand = None - if self.ui: - self.ui.offUi() + def finish(self): + if self.call: + self.view.removeEventCallback("SoEvent",self.call) + FreeCAD.activeDraftCommand = None + if self.ui: + self.ui.offUi() #--------------------------------------------------------------------------- @@ -1202,1289 +1190,1333 @@ class SelectPlane: #--------------------------------------------------------------------------- class Creator: - "A generic Draft Creator Tool used by creation tools such as line or arc" - def __init__(self): - self.commitList = [] + "A generic Draft Creator Tool used by creation tools such as line or arc" + + def __init__(self): + self.commitList = [] - def Activated(self,name="None"): - if FreeCAD.activeDraftCommand: - FreeCAD.activeDraftCommand.finish() - self.ui = None - self.call = None - self.doc = None - self.support = None - self.commitList = [] - self.doc = FreeCAD.ActiveDocument - self.view = FreeCADGui.ActiveDocument.ActiveView - self.featureName = name - if not self.doc: - self.finish() - else: - FreeCAD.activeDraftCommand = self - self.ui = FreeCADGui.draftToolBar - self.ui.cross(True) - self.ui.sourceCmd = self - self.ui.setTitle(name) - self.ui.show() - rot = self.view.getCameraNode().getField("orientation").getValue() - upv = Vector(rot.multVec(coin.SbVec3f(0,1,0)).getValue()) - plane.setup(fcvec.neg(self.view.getViewDirection()), Vector(0,0,0), upv) - self.node = [] - self.pos = [] - self.constrain = None - self.obj = None - self.snap = snapTracker() - self.extsnap = lineTracker(dotted=True) - self.planetrack = PlaneTracker() - if Draft.getParam("grid"): - self.grid = gridTracker() - self.grid.set() - else: - self.grid = None + def Activated(self,name="None"): + if FreeCAD.activeDraftCommand: + FreeCAD.activeDraftCommand.finish() + self.ui = None + self.call = None + self.doc = None + self.support = None + self.commitList = [] + self.doc = FreeCAD.ActiveDocument + self.view = FreeCADGui.ActiveDocument.ActiveView + self.featureName = name + if not self.doc: + self.finish() + else: + FreeCAD.activeDraftCommand = self + self.ui = FreeCADGui.draftToolBar + self.ui.cross(True) + self.ui.sourceCmd = self + self.ui.setTitle(name) + self.ui.show() + rot = self.view.getCameraNode().getField("orientation").getValue() + upv = Vector(rot.multVec(coin.SbVec3f(0,1,0)).getValue()) + plane.setup(fcvec.neg(self.view.getViewDirection()), Vector(0,0,0), upv) + self.node = [] + self.pos = [] + self.constrain = None + self.obj = None + self.snap = snapTracker() + self.extsnap = lineTracker(dotted=True) + self.planetrack = PlaneTracker() + if Draft.getParam("grid"): + self.grid = gridTracker() + self.grid.set() + else: + self.grid = None + def IsActive(self): + if FreeCADGui.ActiveDocument: + return True + else: + return False - def IsActive(self): - if FreeCADGui.ActiveDocument: - return True - else: - return False + def finish(self): + self.snap.finalize() + self.extsnap.finalize() + self.node=[] + self.planetrack.finalize() + if self.grid: self.grid.finalize() + if self.support: plane.restore() + FreeCAD.activeDraftCommand = None + if self.ui: + self.ui.offUi() + self.ui.cross(False) + self.ui.sourceCmd = None + msg("") + if self.call: + self.view.removeEventCallback("SoEvent",self.call) + self.call = None + if self.commitList: + todo.delayCommit(self.commitList) + self.commitList = [] - def finish(self): - self.snap.finalize() - self.extsnap.finalize() - self.node=[] - self.planetrack.finalize() - if self.grid: self.grid.finalize() - if self.support: plane.restore() - FreeCAD.activeDraftCommand = None - if self.ui: - self.ui.offUi() - self.ui.cross(False) - self.ui.sourceCmd = None - msg("") - if self.call: - self.view.removeEventCallback("SoEvent",self.call) - self.call = None - if self.commitList: - todo.delayCommit(self.commitList) - self.commitList = [] - - def commit(self,name,func): - "stores partial actions to be committed to the FreeCAD document" - self.commitList.append((name,func)) + def commit(self,name,func): + "stores partial actions to be committed to the FreeCAD document" + self.commitList.append((name,func)) class Line(Creator): - "The Line FreeCAD command definition" + "The Line FreeCAD command definition" - def __init__(self, wiremode=False): - self.isWire = wiremode + def __init__(self, wiremode=False): + self.isWire = wiremode - def GetResources(self): - return {'Pixmap' : 'Draft_Line', - 'Accel' : "L,I", - 'MenuText': QtCore.QT_TRANSLATE_NOOP("Draft_Line", "Line"), - 'ToolTip': QtCore.QT_TRANSLATE_NOOP("Draft_Line", "Creates a 2-point line. CTRL to snap, SHIFT to constrain")} + def GetResources(self): + return {'Pixmap' : 'Draft_Line', + 'Accel' : "L,I", + 'MenuText': QtCore.QT_TRANSLATE_NOOP("Draft_Line", "Line"), + 'ToolTip': QtCore.QT_TRANSLATE_NOOP("Draft_Line", "Creates a 2-point line. CTRL to snap, SHIFT to constrain")} - def Activated(self,name="Line"): - Creator.Activated(self,name) - if self.doc: - self.obj = None - self.ui.lineUi() - self.linetrack = lineTracker() - self.constraintrack = lineTracker(dotted=True) - self.obj=self.doc.addObject("Part::Feature",self.featureName) - # self.obj.ViewObject.Selectable = False - Draft.formatObject(self.obj) - if not Draft.getParam("UiMode"): self.makeDumbTask() - self.call = self.view.addEventCallback("SoEvent",self.action) - msg(translate("draft", "Pick first point:\n")) + def Activated(self,name="Line"): + Creator.Activated(self,name) + if self.doc: + self.obj = None + self.ui.lineUi() + self.linetrack = lineTracker() + self.constraintrack = lineTracker(dotted=True) + self.obj=self.doc.addObject("Part::Feature",self.featureName) + # self.obj.ViewObject.Selectable = False + Draft.formatObject(self.obj) + if not Draft.getParam("UiMode"): self.makeDumbTask() + self.call = self.view.addEventCallback("SoEvent",self.action) + msg(translate("draft", "Pick first point:\n")) - def makeDumbTask(self): - "create a dumb taskdialog to prevent deleting the temp object" - class TaskPanel: - def __init__(self): - pass - def getStandardButtons(self): - return 0 - panel = TaskPanel() - FreeCADGui.Control.showDialog(panel) + def makeDumbTask(self): + "create a dumb taskdialog to prevent deleting the temp object" + class TaskPanel: + def __init__(self): + pass + def getStandardButtons(self): + return 0 + panel = TaskPanel() + FreeCADGui.Control.showDialog(panel) - def finish(self,closed=False,cont=False): - "terminates the operation and closes the poly if asked" - if not Draft.getParam("UiMode"): - FreeCADGui.Control.closeDialog() - if self.obj: - old = self.obj.Name - todo.delay(self.doc.removeObject,old) - self.obj = None - if (len(self.node) > 1): - self.commit(translate("draft","Create Wire"),partial(Draft.makeWire,self.node,closed,face=self.ui.hasFill.isChecked(),support=self.support)) - if self.ui: - self.linetrack.finalize() - self.constraintrack.finalize() - Creator.finish(self) - if cont and self.ui: - if self.ui.continueMode: - self.Activated() + def finish(self,closed=False,cont=False): + "terminates the operation and closes the poly if asked" + if not Draft.getParam("UiMode"): + FreeCADGui.Control.closeDialog() + if self.obj: + old = self.obj.Name + todo.delay(self.doc.removeObject,old) + self.obj = None + if (len(self.node) > 1): + self.commit(translate("draft","Create Wire"), + partial(Draft.makeWire,self.node,closed, + face=self.ui.hasFill.isChecked(),support=self.support)) + if self.ui: + self.linetrack.finalize() + self.constraintrack.finalize() + Creator.finish(self) + if cont and self.ui: + if self.ui.continueMode: + self.Activated() - def action(self,arg): - "scene event handler" - if arg["Type"] == "SoKeyboardEvent" and arg["Key"] == "ESCAPE": - self.finish() - if (arg["Type"] == "SoLocation2Event"): #mouse movement detection - point,ctrlPoint = getPoint(self,arg) - self.ui.cross(True) - self.linetrack.p2(point) - # Draw constraint tracker line. - if hasMod(arg,MODCONSTRAIN): - self.constraintrack.p1(point) - self.constraintrack.p2(ctrlPoint) - self.constraintrack.on() - else: self.constraintrack.off() - elif (arg["Type"] == "SoMouseButtonEvent"): - if (arg["State"] == "DOWN") and (arg["Button"] == "BUTTON1"): - if (arg["Position"] == self.pos): - self.finish(False,cont=True) - else: - if not self.node: self.support = getSupport(arg) - point,ctrlPoint = getPoint(self,arg) - self.pos = arg["Position"] - self.node.append(point) - self.linetrack.p1(point) - self.drawSegment(point) - if (not self.isWire and len(self.node) == 2): - self.finish(False,cont=True) - if (len(self.node) > 2): - # DNC: allows to close the curve - # by placing ends close to each other - # with tol = Draft tolerance - # old code has been to insensitive - # if fcvec.equals(point,self.node[0]): - if ((point-self.node[0]).Length < Draft.tolerance()): - self.undolast() - self.finish(True,cont=True) - msg(translate("draft", "Wire has been closed\n")) - - def undolast(self): - "undoes last line segment" - if (len(self.node) > 1): - self.node.pop() - last = self.node[len(self.node)-1] - self.linetrack.p1(last) - if self.obj.Shape.Edges: - edges = self.obj.Shape.Edges - if len(edges) > 1: - edges.pop() - newshape = Part.Wire(edges) - else: - newshape = Part.Shape() - self.obj.Shape = newshape - # DNC: report on removal - msg(translate("draft", "Last point has been removed\n")) - - def drawSegment(self,point): - "draws a new segment" - if (len(self.node) == 1): - self.linetrack.on() - msg(translate("draft", "Pick next point:\n")) - self.planetrack.set(self.node[0]) - elif (len(self.node) == 2): - last = self.node[len(self.node)-2] - newseg = Part.Line(last,point).toShape() - self.obj.Shape = newseg - self.obj.ViewObject.Visibility = True - if self.isWire: - msg(translate("draft", "Pick next point, or (F)inish or (C)lose:\n")) - else: - currentshape = self.obj.Shape - last = self.node[len(self.node)-2] - newseg = Part.Line(last,point).toShape() - newshape=currentshape.fuse(newseg) - self.obj.Shape = newshape - msg(translate("draft", "Pick next point, or (F)inish or (C)lose:\n")) - - def wipe(self): - "removes all previous segments and starts from last point" - if len(self.node) > 1: - print "nullifying" - #self.obj.Shape.nullify() - self.obj.ViewObject.Visibility = False - self.node = [self.node[-1]] - print "setting trackers" - self.linetrack.p1(self.node[0]) - self.planetrack.set(self.node[0]) - msg(translate("draft", "Pick next point:\n")) - print "done" - - def numericInput(self,numx,numy,numz): - "this function gets called by the toolbar when valid x, y, and z have been entered there" - point = Vector(numx,numy,numz) - self.node.append(point) - self.linetrack.p1(point) - self.drawSegment(point) - if (not self.isWire and len(self.node) == 2): - self.finish(False,cont=True) - if self.ui.xValue.isEnabled(): - self.ui.xValue.setFocus() - self.ui.xValue.selectAll() - elif self.ui.yValue.isEnabled(): - self.ui.yValue.setFocus() - self.ui.yValue.selectAll() + def action(self,arg): + "scene event handler" + if arg["Type"] == "SoKeyboardEvent": + if arg["Key"] == "ESCAPE": + self.finish() + elif arg["Type"] == "SoLocation2Event": #mouse movement detection + point,ctrlPoint = getPoint(self,arg) + self.ui.cross(True) + self.linetrack.p2(point) + # Draw constraint tracker line. + if hasMod(arg,MODCONSTRAIN): + self.constraintrack.p1(point) + self.constraintrack.p2(ctrlPoint) + self.constraintrack.on() + else: + self.constraintrack.off() + elif arg["Type"] == "SoMouseButtonEvent": + if (arg["State"] == "DOWN") and (arg["Button"] == "BUTTON1"): + if (arg["Position"] == self.pos): + self.finish(False,cont=True) else: - self.ui.zValue.setFocus() - self.ui.zValue.selectAll() + if not self.node: self.support = getSupport(arg) + point,ctrlPoint = getPoint(self,arg) + self.pos = arg["Position"] + self.node.append(point) + self.linetrack.p1(point) + self.drawSegment(point) + if (not self.isWire and len(self.node) == 2): + self.finish(False,cont=True) + if (len(self.node) > 2): + # DNC: allows to close the curve + # by placing ends close to each other + # with tol = Draft tolerance + # old code has been to insensitive + # if fcvec.equals(point,self.node[0]): + if ((point-self.node[0]).Length < Draft.tolerance()): + self.undolast() + self.finish(True,cont=True) + msg(translate("draft", "Wire has been closed\n")) + def undolast(self): + "undoes last line segment" + if (len(self.node) > 1): + self.node.pop() + last = self.node[len(self.node)-1] + self.linetrack.p1(last) + if self.obj.Shape.Edges: + edges = self.obj.Shape.Edges + if len(edges) > 1: + edges.pop() + newshape = Part.Wire(edges) + else: + newshape = Part.Shape() + self.obj.Shape = newshape + # DNC: report on removal + msg(translate("draft", "Last point has been removed\n")) + + def drawSegment(self,point): + "draws a new segment" + if (len(self.node) == 1): + self.linetrack.on() + msg(translate("draft", "Pick next point:\n")) + self.planetrack.set(self.node[0]) + elif (len(self.node) == 2): + last = self.node[len(self.node)-2] + newseg = Part.Line(last,point).toShape() + self.obj.Shape = newseg + self.obj.ViewObject.Visibility = True + if self.isWire: + msg(translate("draft", "Pick next point, or (F)inish or (C)lose:\n")) + else: + currentshape = self.obj.Shape + last = self.node[len(self.node)-2] + newseg = Part.Line(last,point).toShape() + newshape=currentshape.fuse(newseg) + self.obj.Shape = newshape + msg(translate("draft", "Pick next point, or (F)inish or (C)lose:\n")) + + def wipe(self): + "removes all previous segments and starts from last point" + if len(self.node) > 1: + print "nullifying" + # self.obj.Shape.nullify() - for some reason this fails + self.obj.ViewObject.Visibility = False + self.node = [self.node[-1]] + print "setting trackers" + self.linetrack.p1(self.node[0]) + self.planetrack.set(self.node[0]) + msg(translate("draft", "Pick next point:\n")) + print "done" + + def numericInput(self,numx,numy,numz): + "this function gets called by the toolbar when valid x, y, and z have been entered there" + point = Vector(numx,numy,numz) + self.node.append(point) + self.linetrack.p1(point) + self.drawSegment(point) + if (not self.isWire and len(self.node) == 2): + self.finish(False,cont=True) + if self.ui.xValue.isEnabled(): + self.ui.xValue.setFocus() + self.ui.xValue.selectAll() + elif self.ui.yValue.isEnabled(): + self.ui.yValue.setFocus() + self.ui.yValue.selectAll() + else: + self.ui.zValue.setFocus() + self.ui.zValue.selectAll() + + class Wire(Line): - "a FreeCAD command for creating a wire" - def __init__(self): - Line.__init__(self,wiremode=True) - def GetResources(self): - return {'Pixmap' : 'Draft_Wire', - 'Accel' : "W, I", - 'MenuText': QtCore.QT_TRANSLATE_NOOP("Draft_Wire", "Wire"), - 'ToolTip': QtCore.QT_TRANSLATE_NOOP("Draft_Wire", "Creates a multiple-point wire. CTRL to snap, SHIFT to constrain")} + "a FreeCAD command for creating a wire" + def __init__(self): + Line.__init__(self,wiremode=True) + def GetResources(self): + return {'Pixmap' : 'Draft_Wire', + 'Accel' : "W, I", + 'MenuText': QtCore.QT_TRANSLATE_NOOP("Draft_Wire", "Wire"), + 'ToolTip': QtCore.QT_TRANSLATE_NOOP("Draft_Wire", "Creates a multiple-point wire. CTRL to snap, SHIFT to constrain")} + class BSpline(Line): - "a FreeCAD command for creating a b-spline" - def __init__(self): - Line.__init__(self,wiremode=True) + "a FreeCAD command for creating a b-spline" + + def __init__(self): + Line.__init__(self,wiremode=True) - def GetResources(self): - return {'Pixmap' : 'Draft_BSpline', - 'Accel' : "B, S", - 'MenuText': QtCore.QT_TRANSLATE_NOOP("Draft_BSpline", "B-Spline"), - 'ToolTip': QtCore.QT_TRANSLATE_NOOP("Draft_BSpline", "Creates a multiple-point b-spline. CTRL to snap, SHIFT to constrain")} + def GetResources(self): + return {'Pixmap' : 'Draft_BSpline', + 'Accel' : "B, S", + 'MenuText': QtCore.QT_TRANSLATE_NOOP("Draft_BSpline", "B-Spline"), + 'ToolTip': QtCore.QT_TRANSLATE_NOOP("Draft_BSpline", "Creates a multiple-point b-spline. CTRL to snap, SHIFT to constrain")} - def Activated(self): - Line.Activated(self,"BSpline") - if self.doc: - self.bsplinetrack = bsplineTracker() + def Activated(self): + Line.Activated(self,"BSpline") + if self.doc: + self.bsplinetrack = bsplineTracker() - def action(self,arg): - "scene event handler" - if arg["Type"] == "SoKeyboardEvent" and arg["Key"] == "ESCAPE": - self.finish() - if (arg["Type"] == "SoLocation2Event"): #mouse movement detection - point,ctrlPoint = getPoint(self,arg) - self.ui.cross(True) - self.bsplinetrack.update(self.node + [point]) - # Draw constraint tracker line. - if hasMod(arg,MODCONSTRAIN): - self.constraintrack.p1(point) - self.constraintrack.p2(ctrlPoint) - self.constraintrack.on() - else: self.constraintrack.off() - elif (arg["Type"] == "SoMouseButtonEvent"): - if (arg["State"] == "DOWN") and (arg["Button"] == "BUTTON1"): - if (arg["Position"] == self.pos): - self.finish(False,cont=True) - else: - if not self.node: self.support = getSupport(arg) - point,ctrlPoint = getPoint(self,arg) - self.pos = arg["Position"] - self.node.append(point) - self.drawUpdate(point) - if (not self.isWire and len(self.node) == 2): - self.finish(False,cont=True) - if (len(self.node) > 2): - # DNC: allows to close the curve - # by placing ends close to each other - # with tol = Draft tolerance - # old code has been to insensitive - if ((point-self.node[0]).Length < Draft.tolerance()): - self.undolast() - self.finish(True,cont=True) - msg(translate("draft", "Spline has been closed\n")) + def action(self,arg): + "scene event handler" + if arg["Type"] == "SoKeyboardEvent": + if arg["Key"] == "ESCAPE": + self.finish() + elif arg["Type"] == "SoLocation2Event": #mouse movement detection + point,ctrlPoint = getPoint(self,arg) + self.ui.cross(True) + self.bsplinetrack.update(self.node + [point]) + # Draw constraint tracker line. + if hasMod(arg,MODCONSTRAIN): + self.constraintrack.p1(point) + self.constraintrack.p2(ctrlPoint) + self.constraintrack.on() + else: self.constraintrack.off() + elif arg["Type"] == "SoMouseButtonEvent": + if (arg["State"] == "DOWN") and (arg["Button"] == "BUTTON1"): + if (arg["Position"] == self.pos): + self.finish(False,cont=True) + else: + if not self.node: self.support = getSupport(arg) + point,ctrlPoint = getPoint(self,arg) + self.pos = arg["Position"] + self.node.append(point) + self.drawUpdate(point) + if (not self.isWire and len(self.node) == 2): + self.finish(False,cont=True) + if (len(self.node) > 2): + # DNC: allows to close the curve + # by placing ends close to each other + # with tol = Draft tolerance + # old code has been to insensitive + if ((point-self.node[0]).Length < Draft.tolerance()): + self.undolast() + self.finish(True,cont=True) + msg(translate("draft", "Spline has been closed\n")) - def undolast(self): - "undoes last line segment" - if (len(self.node) > 1): - self.node.pop() - self.bsplinetrack.update(self.node) - spline = Part.BSplineCurve() - spline.interpolate(self.node, False) - self.obj.Shape = spline.toShape() - msg(translate("draft", "Last point has been removed\n")) + def undolast(self): + "undoes last line segment" + if (len(self.node) > 1): + self.node.pop() + self.bsplinetrack.update(self.node) + spline = Part.BSplineCurve() + spline.interpolate(self.node, False) + self.obj.Shape = spline.toShape() + msg(translate("draft", "Last point has been removed\n")) - def drawUpdate(self,point): - if (len(self.node) == 1): - self.bsplinetrack.on() - self.planetrack.set(self.node[0]) - msg(translate("draft", "Pick next point:\n")) - else: - spline = Part.BSplineCurve() - spline.interpolate(self.node, False) - self.obj.Shape = spline.toShape() - msg(translate("draft", "Pick next point, or (F)inish or (C)lose:\n")) + def drawUpdate(self,point): + if (len(self.node) == 1): + self.bsplinetrack.on() + self.planetrack.set(self.node[0]) + msg(translate("draft", "Pick next point:\n")) + else: + spline = Part.BSplineCurve() + spline.interpolate(self.node, False) + self.obj.Shape = spline.toShape() + msg(translate("draft", "Pick next point, or (F)inish or (C)lose:\n")) - def finish(self,closed=False,cont=False): - "terminates the operation and closes the poly if asked" - if not Draft.getParam("UiMode"): - FreeCADGui.Control.closeDialog() - if (len(self.node) > 1): - old = self.obj.Name - self.doc.removeObject(old) - self.commit(translate("draft","Create BSpline"),partial(Draft.makeBSpline,self.node,closed,face=self.ui.hasFill.isChecked(),support=self.support)) - if self.ui: + def finish(self,closed=False,cont=False): + "terminates the operation and closes the poly if asked" + if not Draft.getParam("UiMode"): + FreeCADGui.Control.closeDialog() + if (len(self.node) > 1): + old = self.obj.Name + self.doc.removeObject(old) + self.commit(translate("draft","Create BSpline"), + partial(Draft.makeBSpline,self.node,closed, + face=self.ui.hasFill.isChecked(),support=self.support)) + if self.ui: self.bsplinetrack.finalize() self.constraintrack.finalize() - Creator.finish(self) - if cont and self.ui: - if self.ui.continueMode: - self.Activated() + Creator.finish(self) + if cont and self.ui: + if self.ui.continueMode: + self.Activated() + class FinishLine: - "a FreeCAD command to finish any running Line drawing operation" - def Activated(self): - if (FreeCAD.activeDraftCommand != None): - if (FreeCAD.activeDraftCommand.featureName == "Line"): - FreeCAD.activeDraftCommand.finish(False) - def GetResources(self): - return {'Pixmap' : 'Draft_Finish', - 'MenuText': QtCore.QT_TRANSLATE_NOOP("Draft_FinishLine", "Finish line"), - 'ToolTip': QtCore.QT_TRANSLATE_NOOP("Draft_FinishLine", "Finishes a line without closing it")} - def IsActive(self): - if FreeCAD.activeDraftCommand: - if FreeCAD.activeDraftCommand.featureName == "Line": - return True - return False - + "a FreeCAD command to finish any running Line drawing operation" + + def Activated(self): + if (FreeCAD.activeDraftCommand != None): + if (FreeCAD.activeDraftCommand.featureName == "Line"): + FreeCAD.activeDraftCommand.finish(False) + def GetResources(self): + return {'Pixmap' : 'Draft_Finish', + 'MenuText': QtCore.QT_TRANSLATE_NOOP("Draft_FinishLine", "Finish line"), + 'ToolTip': QtCore.QT_TRANSLATE_NOOP("Draft_FinishLine", "Finishes a line without closing it")} + def IsActive(self): + if FreeCAD.activeDraftCommand: + if FreeCAD.activeDraftCommand.featureName == "Line": + return True + return False + + class CloseLine: - "a FreeCAD command to close any running Line drawing operation" - def Activated(self): - if (FreeCAD.activeDraftCommand != None): - if (FreeCAD.activeDraftCommand.featureName == "Line"): - FreeCAD.activeDraftCommand.finish(True) - def GetResources(self): - return {'Pixmap' : 'Draft_Lock', - 'MenuText': QtCore.QT_TRANSLATE_NOOP("Draft_CloseLine", "Close Line"), - 'ToolTip': QtCore.QT_TRANSLATE_NOOP("Draft_CloseLine", "Closes the line being drawn")} - def IsActive(self): - if FreeCAD.activeDraftCommand: - if FreeCAD.activeDraftCommand.featureName == "Line": - return True - return False + "a FreeCAD command to close any running Line drawing operation" + + def Activated(self): + if (FreeCAD.activeDraftCommand != None): + if (FreeCAD.activeDraftCommand.featureName == "Line"): + FreeCAD.activeDraftCommand.finish(True) + + def GetResources(self): + return {'Pixmap' : 'Draft_Lock', + 'MenuText': QtCore.QT_TRANSLATE_NOOP("Draft_CloseLine", "Close Line"), + 'ToolTip': QtCore.QT_TRANSLATE_NOOP("Draft_CloseLine", "Closes the line being drawn")} + + def IsActive(self): + if FreeCAD.activeDraftCommand: + if FreeCAD.activeDraftCommand.featureName == "Line": + return True + return False class UndoLine: - "a FreeCAD command to undo last drawn segment of a line" - def Activated(self): - if (FreeCAD.activeDraftCommand != None): - if (FreeCAD.activeDraftCommand.featureName == "Line"): - FreeCAD.activeDraftCommand.undolast() - def GetResources(self): - return {'Pixmap' : 'Draft_Rotate', - 'MenuText': QtCore.QT_TRANSLATE_NOOP("Draft_UndoLine", "Undo last segment"), - 'ToolTip': QtCore.QT_TRANSLATE_NOOP("Draft_UndoLine", "Undoes the last drawn segment of the line being drawn")} - def IsActive(self): - if FreeCAD.activeDraftCommand: - if FreeCAD.activeDraftCommand.featureName == "Line": - return True - return False - + "a FreeCAD command to undo last drawn segment of a line" + + def Activated(self): + if (FreeCAD.activeDraftCommand != None): + if (FreeCAD.activeDraftCommand.featureName == "Line"): + FreeCAD.activeDraftCommand.undolast() + + def GetResources(self): + return {'Pixmap' : 'Draft_Rotate', + 'MenuText': QtCore.QT_TRANSLATE_NOOP("Draft_UndoLine", "Undo last segment"), + 'ToolTip': QtCore.QT_TRANSLATE_NOOP("Draft_UndoLine", "Undoes the last drawn segment of the line being drawn")} + + def IsActive(self): + if FreeCAD.activeDraftCommand: + if FreeCAD.activeDraftCommand.featureName == "Line": + return True + return False + + class Rectangle(Creator): - "the Draft_Rectangle FreeCAD command definition" + "the Draft_Rectangle FreeCAD command definition" + + def GetResources(self): + return {'Pixmap' : 'Draft_Rectangle', + 'Accel' : "R, E", + 'MenuText': QtCore.QT_TRANSLATE_NOOP("Draft_Rectangle", "Rectangle"), + 'ToolTip': QtCore.QT_TRANSLATE_NOOP("Draft_Rectangle", "Creates a 2-point rectangle. CTRL to snap")} - def GetResources(self): - return {'Pixmap' : 'Draft_Rectangle', - 'Accel' : "R, E", - 'MenuText': QtCore.QT_TRANSLATE_NOOP("Draft_Rectangle", "Rectangle"), - 'ToolTip': QtCore.QT_TRANSLATE_NOOP("Draft_Rectangle", "Creates a 2-point rectangle. CTRL to snap")} + def Activated(self): + Creator.Activated(self,"Rectangle") + if self.ui: + self.refpoint = None + self.ui.pointUi() + self.ui.extUi() + self.call = self.view.addEventCallback("SoEvent",self.action) + self.rect = rectangleTracker() + msg(translate("draft", "Pick first point:\n")) - def Activated(self): - Creator.Activated(self,"Rectangle") - if self.ui: - self.refpoint = None - self.ui.pointUi() - self.ui.extUi() - self.call = self.view.addEventCallback("SoEvent",self.action) - self.rect = rectangleTracker() - msg(translate("draft", "Pick first point:\n")) + def finish(self,closed=False,cont=False): + "terminates the operation and closes the poly if asked" + Creator.finish(self) + if self.ui: + self.rect.off() + self.rect.finalize() + if cont and self.ui: + if self.ui.continueMode: + self.Activated() - def finish(self,closed=False,cont=False): - "terminates the operation and closes the poly if asked" - Creator.finish(self) - if self.ui: - self.rect.off() - self.rect.finalize() - if cont and self.ui: - if self.ui.continueMode: - self.Activated() + def createObject(self): + "creates the final object in the current doc" + p1 = self.node[0] + p3 = self.node[-1] + diagonal = p3.sub(p1) + p2 = p1.add(fcvec.project(diagonal, plane.v)) + p4 = p1.add(fcvec.project(diagonal, plane.u)) + length = p4.sub(p1).Length + if abs(fcvec.angle(p4.sub(p1),plane.u,plane.axis)) > 1: length = -length + height = p2.sub(p1).Length + if abs(fcvec.angle(p2.sub(p1),plane.v,plane.axis)) > 1: height = -height + p = plane.getRotation() + p.move(p1) + self.commit(translate("draft","Create Rectangle"), + partial(Draft.makeRectangle,length,height, + p,self.ui.hasFill.isChecked(),support=self.support)) + self.finish(cont=True) - def createObject(self): - "creates the final object in the current doc" - p1 = self.node[0] - p3 = self.node[-1] - diagonal = p3.sub(p1) - p2 = p1.add(fcvec.project(diagonal, plane.v)) - p4 = p1.add(fcvec.project(diagonal, plane.u)) - length = p4.sub(p1).Length - if abs(fcvec.angle(p4.sub(p1),plane.u,plane.axis)) > 1: length = -length - height = p2.sub(p1).Length - if abs(fcvec.angle(p2.sub(p1),plane.v,plane.axis)) > 1: height = -height - p = plane.getRotation() - p.move(p1) - self.commit(translate("draft","Create Rectangle"),partial(Draft.makeRectangle,length,height,p,self.ui.hasFill.isChecked(),support=self.support)) - self.finish(cont=True) + def action(self,arg): + "scene event handler" + if arg["Type"] == "SoKeyboardEvent": + if arg["Key"] == "ESCAPE": + self.finish() + elif arg["Type"] == "SoLocation2Event": #mouse movement detection + point,ctrlPoint = getPoint(self,arg,mobile=True) + self.rect.update(point) + self.ui.cross(True) + elif arg["Type"] == "SoMouseButtonEvent": + if (arg["State"] == "DOWN") and (arg["Button"] == "BUTTON1"): + if (arg["Position"] == self.pos): + self.finish() + else: + if not self.node: self.support = getSupport(arg) + point,ctrlPoint = getPoint(self,arg) + self.appendPoint(point) - def action(self,arg): - "scene event handler" - if arg["Type"] == "SoKeyboardEvent" and arg["Key"] == "ESCAPE": - self.finish() - if (arg["Type"] == "SoLocation2Event"): #mouse movement detection - point,ctrlPoint = getPoint(self,arg,mobile=True) - self.rect.update(point) - self.ui.cross(True) - elif (arg["Type"] == "SoMouseButtonEvent"): - if (arg["State"] == "DOWN") and (arg["Button"] == "BUTTON1"): - if (arg["Position"] == self.pos): - self.finish() - else: - if not self.node: self.support = getSupport(arg) - point,ctrlPoint = getPoint(self,arg) - self.appendPoint(point) + def numericInput(self,numx,numy,numz): + "this function gets called by the toolbar when valid x, y, and z have been entered there" + point = Vector(numx,numy,numz) + self.appendPoint(point) - def numericInput(self,numx,numy,numz): - "this function gets called by the toolbar when valid x, y, and z have been entered there" - point = Vector(numx,numy,numz) - self.appendPoint(point) - - def appendPoint(self,point): - self.node.append(point) - if (len(self.node) > 1): - self.rect.update(point) - self.createObject() - else: - msg(translate("draft", "Pick opposite point:\n")) - self.ui.isRelative.show() - self.rect.setorigin(point) - self.rect.on() - self.planetrack.set(point) + def appendPoint(self,point): + self.node.append(point) + if (len(self.node) > 1): + self.rect.update(point) + self.createObject() + else: + msg(translate("draft", "Pick opposite point:\n")) + self.ui.isRelative.show() + self.rect.setorigin(point) + self.rect.on() + self.planetrack.set(point) class Arc(Creator): - "the Draft_Arc FreeCAD command definition" + "the Draft_Arc FreeCAD command definition" - def __init__(self): - self.closedCircle=False - self.featureName = "Arc" + def __init__(self): + self.closedCircle=False + self.featureName = "Arc" - def GetResources(self): - return {'Pixmap' : 'Draft_Arc', - 'Accel' : "A, R", - 'MenuText': QtCore.QT_TRANSLATE_NOOP("Draft_Arc", "Arc"), - 'ToolTip': QtCore.QT_TRANSLATE_NOOP("Draft_Arc", "Creates an arc. CTRL to snap, SHIFT to constrain")} + def GetResources(self): + return {'Pixmap' : 'Draft_Arc', + 'Accel' : "A, R", + 'MenuText': QtCore.QT_TRANSLATE_NOOP("Draft_Arc", "Arc"), + 'ToolTip': QtCore.QT_TRANSLATE_NOOP("Draft_Arc", "Creates an arc. CTRL to snap, SHIFT to constrain")} - def Activated(self): - Creator.Activated(self,self.featureName) - if self.ui: - self.step = 0 - self.center = None - self.rad = None - self.angle = 0 # angle inscribed by arc - self.tangents = [] - self.tanpoints = [] - if self.featureName == "Arc": self.ui.arcUi() - else: self.ui.circleUi() - self.altdown = False - self.ui.sourceCmd = self - self.linetrack = lineTracker(dotted=True) - self.constraintrack = lineTracker(dotted=True) - self.arctrack = arcTracker() - self.call = self.view.addEventCallback("SoEvent",self.action) - msg(translate("draft", "Pick center point:\n")) + def Activated(self): + Creator.Activated(self,self.featureName) + if self.ui: + self.step = 0 + self.center = None + self.rad = None + self.angle = 0 # angle inscribed by arc + self.tangents = [] + self.tanpoints = [] + if self.featureName == "Arc": self.ui.arcUi() + else: self.ui.circleUi() + self.altdown = False + self.ui.sourceCmd = self + self.linetrack = lineTracker(dotted=True) + self.constraintrack = lineTracker(dotted=True) + self.arctrack = arcTracker() + self.call = self.view.addEventCallback("SoEvent",self.action) + msg(translate("draft", "Pick center point:\n")) - def finish(self,closed=False,cont=False): - "finishes the arc" - Creator.finish(self) - if self.ui: - self.linetrack.finalize() - self.constraintrack.finalize() - self.arctrack.finalize() - self.doc.recompute() - if cont and self.ui: - if self.ui.continueMode: - self.Activated() + def finish(self,closed=False,cont=False): + "finishes the arc" + Creator.finish(self) + if self.ui: + self.linetrack.finalize() + self.constraintrack.finalize() + self.arctrack.finalize() + self.doc.recompute() + if cont and self.ui: + if self.ui.continueMode: + self.Activated() - def updateAngle(self, angle): - # previous absolute angle - lastangle = self.firstangle + self.angle - if lastangle <= -2*math.pi: lastangle += 2*math.pi - if lastangle >= 2*math.pi: lastangle -= 2*math.pi - # compute delta = change in angle: - d0 = angle-lastangle - d1 = d0 + 2*math.pi - d2 = d0 - 2*math.pi - if abs(d0) < min(abs(d1), abs(d2)): - delta = d0 - elif abs(d1) < abs(d2): - delta = d1 - else: - delta = d2 - newangle = self.angle + delta - # normalize angle, preserving direction - if newangle >= 2*math.pi: newangle -= 2*math.pi - if newangle <= -2*math.pi: newangle += 2*math.pi - self.angle = newangle + def updateAngle(self, angle): + # previous absolute angle + lastangle = self.firstangle + self.angle + if lastangle <= -2*math.pi: lastangle += 2*math.pi + if lastangle >= 2*math.pi: lastangle -= 2*math.pi + # compute delta = change in angle: + d0 = angle-lastangle + d1 = d0 + 2*math.pi + d2 = d0 - 2*math.pi + if abs(d0) < min(abs(d1), abs(d2)): + delta = d0 + elif abs(d1) < abs(d2): + delta = d1 + else: + delta = d2 + newangle = self.angle + delta + # normalize angle, preserving direction + if newangle >= 2*math.pi: newangle -= 2*math.pi + if newangle <= -2*math.pi: newangle += 2*math.pi + self.angle = newangle - def action(self,arg): - "scene event handler" - if arg["Type"] == "SoKeyboardEvent" and arg["Key"] == "ESCAPE": - self.finish() - if (arg["Type"] == "SoLocation2Event"): - point,ctrlPoint = getPoint(self,arg) - # this is to make sure radius is what you see on screen + def action(self,arg): + "scene event handler" + if arg["Type"] == "SoKeyboardEvent": + if arg["Key"] == "ESCAPE": + self.finish() + elif arg["Type"] == "SoLocation2Event": + point,ctrlPoint = getPoint(self,arg) + # this is to make sure radius is what you see on screen + self.ui.cross(True) + if self.center and fcvec.dist(point,self.center) > 0: + viewdelta = fcvec.project(point.sub(self.center), plane.axis) + if not fcvec.isNull(viewdelta): + point = point.add(fcvec.neg(viewdelta)) + if (self.step == 0): # choose center + if hasMod(arg,MODALT): + if not self.altdown: + self.ui.cross(False) + self.altdown = True + self.ui.switchUi(True) + else: + if self.altdown: + self.ui.cross(True) + self.altdown = False + self.ui.switchUi(False) + elif (self.step == 1): # choose radius + if len(self.tangents) == 2: + cir = fcgeo.circleFrom2tan1pt(self.tangents[0], self.tangents[1], point) + self.center = fcgeo.findClosestCircle(point,cir).Center + self.arctrack.setCenter(self.center) + elif self.tangents and self.tanpoints: + cir = fcgeo.circleFrom1tan2pt(self.tangents[0], self.tanpoints[0], point) + self.center = fcgeo.findClosestCircle(point,cir).Center + self.arctrack.setCenter(self.center) + if hasMod(arg,MODALT): + if not self.altdown: + self.ui.cross(False) + self.altdown = True + snapped = self.view.getObjectInfo((arg["Position"][0],arg["Position"][1])) + if snapped: + ob = self.doc.getObject(snapped['Object']) + num = int(snapped['Component'].lstrip('Edge'))-1 + ed = ob.Shape.Edges[num] + if len(self.tangents) == 2: + cir = fcgeo.circleFrom3tan(self.tangents[0], self.tangents[1], ed) + cl = fcgeo.findClosestCircle(point,cir) + self.center = cl.Center + self.rad = cl.Radius + self.arctrack.setCenter(self.center) + else: + self.rad = self.center.add(fcgeo.findDistance(self.center,ed).sub(self.center)).Length + else: + self.rad = fcvec.dist(point,self.center) + else: + if self.altdown: self.ui.cross(True) - if self.center and fcvec.dist(point,self.center) > 0: - viewdelta = fcvec.project(point.sub(self.center), plane.axis) - if not fcvec.isNull(viewdelta): - point = point.add(fcvec.neg(viewdelta)) - if (self.step == 0): # choose center - if hasMod(arg,MODALT): - if not self.altdown: - self.ui.cross(False) - self.altdown = True - self.ui.switchUi(True) - else: - if self.altdown: - self.ui.cross(True) - self.altdown = False - self.ui.switchUi(False) - elif (self.step == 1): # choose radius - if len(self.tangents) == 2: - cir = fcgeo.circleFrom2tan1pt(self.tangents[0], self.tangents[1], point) - self.center = fcgeo.findClosestCircle(point,cir).Center - self.arctrack.setCenter(self.center) - elif self.tangents and self.tanpoints: - cir = fcgeo.circleFrom1tan2pt(self.tangents[0], self.tanpoints[0], point) - self.center = fcgeo.findClosestCircle(point,cir).Center - self.arctrack.setCenter(self.center) - if hasMod(arg,MODALT): - if not self.altdown: - self.ui.cross(False) - self.altdown = True - snapped = self.view.getObjectInfo((arg["Position"][0],arg["Position"][1])) - if snapped: - ob = self.doc.getObject(snapped['Object']) - num = int(snapped['Component'].lstrip('Edge'))-1 - ed = ob.Shape.Edges[num] - if len(self.tangents) == 2: - cir = fcgeo.circleFrom3tan(self.tangents[0], self.tangents[1], ed) - cl = fcgeo.findClosestCircle(point,cir) - self.center = cl.Center - self.rad = cl.Radius - self.arctrack.setCenter(self.center) - else: - self.rad = self.center.add(fcgeo.findDistance(self.center,ed).sub(self.center)).Length - else: - self.rad = fcvec.dist(point,self.center) - else: - if self.altdown: - self.ui.cross(True) - self.altdown = False - self.rad = fcvec.dist(point,self.center) - self.ui.setRadiusValue(self.rad) - self.arctrack.setRadius(self.rad) - # Draw constraint tracker line. - if hasMod(arg,MODCONSTRAIN): - self.constraintrack.p1(point) - self.constraintrack.p2(ctrlPoint) - self.constraintrack.on() - else: self.constraintrack.off() - self.linetrack.p1(self.center) - self.linetrack.p2(point) - self.linetrack.on() - elif (self.step == 2): # choose first angle - currentrad = fcvec.dist(point,self.center) - if currentrad != 0: - angle = fcvec.angle(plane.u, point.sub(self.center), plane.axis) - else: angle = 0 - self.linetrack.p2(fcvec.scaleTo(point.sub(self.center),self.rad).add(self.center)) - # Draw constraint tracker line. - if hasMod(arg,MODCONSTRAIN): - self.constraintrack.p1(point) - self.constraintrack.p2(ctrlPoint) - self.constraintrack.on() - else: self.constraintrack.off() - self.ui.setRadiusValue(math.degrees(angle)) - self.firstangle = angle - else: # choose second angle - currentrad = fcvec.dist(point,self.center) - if currentrad != 0: - angle = fcvec.angle(plane.u, point.sub(self.center), plane.axis) - else: angle = 0 - self.linetrack.p2(fcvec.scaleTo(point.sub(self.center),self.rad).add(self.center)) - # Draw constraint tracker line. - if hasMod(arg,MODCONSTRAIN): - self.constraintrack.p1(point) - self.constraintrack.p2(ctrlPoint) - self.constraintrack.on() - else: self.constraintrack.off() - self.ui.setRadiusValue(math.degrees(angle)) - self.updateAngle(angle) - self.arctrack.setApertureAngle(self.angle) + self.altdown = False + self.rad = fcvec.dist(point,self.center) + self.ui.setRadiusValue(self.rad) + self.arctrack.setRadius(self.rad) + # Draw constraint tracker line. + if hasMod(arg,MODCONSTRAIN): + self.constraintrack.p1(point) + self.constraintrack.p2(ctrlPoint) + self.constraintrack.on() + else: + self.constraintrack.off() + self.linetrack.p1(self.center) + self.linetrack.p2(point) + self.linetrack.on() + elif (self.step == 2): # choose first angle + currentrad = fcvec.dist(point,self.center) + if currentrad != 0: + angle = fcvec.angle(plane.u, point.sub(self.center), plane.axis) + else: angle = 0 + self.linetrack.p2(fcvec.scaleTo(point.sub(self.center),self.rad).add(self.center)) + # Draw constraint tracker line. + if hasMod(arg,MODCONSTRAIN): + self.constraintrack.p1(point) + self.constraintrack.p2(ctrlPoint) + self.constraintrack.on() + else: + self.constraintrack.off() + self.ui.setRadiusValue(math.degrees(angle)) + self.firstangle = angle + else: # choose second angle + currentrad = fcvec.dist(point,self.center) + if currentrad != 0: + angle = fcvec.angle(plane.u, point.sub(self.center), plane.axis) + else: angle = 0 + self.linetrack.p2(fcvec.scaleTo(point.sub(self.center),self.rad).add(self.center)) + # Draw constraint tracker line. + if hasMod(arg,MODCONSTRAIN): + self.constraintrack.p1(point) + self.constraintrack.p2(ctrlPoint) + self.constraintrack.on() + else: + self.constraintrack.off() + self.ui.setRadiusValue(math.degrees(angle)) + self.updateAngle(angle) + self.arctrack.setApertureAngle(self.angle) - if (arg["Type"] == "SoMouseButtonEvent"): - if (arg["State"] == "DOWN") and (arg["Button"] == "BUTTON1"): - point,ctrlPoint = getPoint(self,arg) - # this is to make sure radius is what you see on screen - if self.center and fcvec.dist(point,self.center) > 0: - viewdelta = fcvec.project(point.sub(self.center), plane.axis) - if not fcvec.isNull(viewdelta): - point = point.add(fcvec.neg(viewdelta)) - if (self.step == 0): # choose center - self.support = getSupport(arg) - if hasMod(arg,MODALT): - snapped=self.view.getObjectInfo((arg["Position"][0],arg["Position"][1])) - if snapped: - ob = self.doc.getObject(snapped['Object']) - num = int(snapped['Component'].lstrip('Edge'))-1 - ed = ob.Shape.Edges[num] - self.tangents.append(ed) - if len(self.tangents) == 2: - self.arctrack.on() - self.ui.radiusUi() - self.step = 1 - self.linetrack.on() - msg(translate("draft", "Pick radius:\n")) - else: - if len(self.tangents) == 1: - self.tanpoints.append(point) - else: - self.center = point - self.node = [point] - self.arctrack.setCenter(self.center) - self.linetrack.p1(self.center) - self.linetrack.p2(self.view.getPoint(arg["Position"][0],arg["Position"][1])) - self.arctrack.on() - self.ui.radiusUi() - self.step = 1 - self.linetrack.on() - msg(translate("draft", "Pick radius:\n")) - self.planetrack.set(point) - - elif (self.step == 1): # choose radius - if self.closedCircle: - self.ui.cross(False) - self.drawArc() - else: - self.ui.labelRadius.setText("Start angle") - self.linetrack.p1(self.center) - self.linetrack.on() - self.step = 2 - msg(translate("draft", "Pick start angle:\n")) - elif (self.step == 2): # choose first angle - self.ui.labelRadius.setText("Aperture") - self.step = 3 - # scale center->point vector for proper display - u = fcvec.scaleTo(point.sub(self.center), self.rad) - self.arctrack.setStartAngle(self.firstangle) - msg(translate("draft", "Pick aperture:\n")) - else: # choose second angle - self.step = 4 - self.drawArc() + elif arg["Type"] == "SoMouseButtonEvent": + if (arg["State"] == "DOWN") and (arg["Button"] == "BUTTON1"): + point,ctrlPoint = getPoint(self,arg) + # this is to make sure radius is what you see on screen + if self.center and fcvec.dist(point,self.center) > 0: + viewdelta = fcvec.project(point.sub(self.center), plane.axis) + if not fcvec.isNull(viewdelta): + point = point.add(fcvec.neg(viewdelta)) + if (self.step == 0): # choose center + self.support = getSupport(arg) + if hasMod(arg,MODALT): + snapped=self.view.getObjectInfo((arg["Position"][0],arg["Position"][1])) + if snapped: + ob = self.doc.getObject(snapped['Object']) + num = int(snapped['Component'].lstrip('Edge'))-1 + ed = ob.Shape.Edges[num] + self.tangents.append(ed) + if len(self.tangents) == 2: + self.arctrack.on() + self.ui.radiusUi() + self.step = 1 + self.linetrack.on() + msg(translate("draft", "Pick radius:\n")) + else: + if len(self.tangents) == 1: + self.tanpoints.append(point) + else: + self.center = point + self.node = [point] + self.arctrack.setCenter(self.center) + self.linetrack.p1(self.center) + self.linetrack.p2(self.view.getPoint(arg["Position"][0],arg["Position"][1])) + self.arctrack.on() + self.ui.radiusUi() + self.step = 1 + self.linetrack.on() + msg(translate("draft", "Pick radius:\n")) + self.planetrack.set(point) + elif (self.step == 1): # choose radius + if self.closedCircle: + self.ui.cross(False) + self.drawArc() + else: + self.ui.labelRadius.setText("Start angle") + self.linetrack.p1(self.center) + self.linetrack.on() + self.step = 2 + msg(translate("draft", "Pick start angle:\n")) + elif (self.step == 2): # choose first angle + self.ui.labelRadius.setText("Aperture") + self.step = 3 + # scale center->point vector for proper display + u = fcvec.scaleTo(point.sub(self.center), self.rad) + self.arctrack.setStartAngle(self.firstangle) + msg(translate("draft", "Pick aperture:\n")) + else: # choose second angle + self.step = 4 + self.drawArc() - def drawArc(self): - "actually draws the FreeCAD object" - p = plane.getRotation() - p.move(self.center) - if self.closedCircle: - self.commit(translate("draft","Create Circle"),partial(Draft.makeCircle,self.rad,p,self.ui.hasFill.isChecked(),support=self.support)) - else: - sta = math.degrees(self.firstangle) - end = math.degrees(self.firstangle+self.angle) - print "debug:",sta, end - if end < sta: sta,end = end,sta - self.commit(translate("draft","Create Arc"),partial(Draft.makeCircle,self.rad,p,self.ui.hasFill.isChecked(),sta,end,support=self.support)) - self.finish(cont=True) + def drawArc(self): + "actually draws the FreeCAD object" + p = plane.getRotation() + p.move(self.center) + if self.closedCircle: + self.commit(translate("draft","Create Circle"), + partial(Draft.makeCircle,self.rad,p, + self.ui.hasFill.isChecked(),support=self.support)) + else: + sta = math.degrees(self.firstangle) + end = math.degrees(self.firstangle+self.angle) + print "debug:",sta, end + if end < sta: sta,end = end,sta + self.commit(translate("draft","Create Arc"), + partial(Draft.makeCircle,self.rad,p,self.ui.hasFill.isChecked(), + sta,end,support=self.support)) + self.finish(cont=True) - def numericInput(self,numx,numy,numz): - "this function gets called by the toolbar when valid x, y, and z have been entered there" - self.center = Vector(numx,numy,numz) - self.node = [self.center] - self.arctrack.setCenter(self.center) - self.arctrack.on() - self.ui.radiusUi() - self.step = 1 + def numericInput(self,numx,numy,numz): + "this function gets called by the toolbar when valid x, y, and z have been entered there" + self.center = Vector(numx,numy,numz) + self.node = [self.center] + self.arctrack.setCenter(self.center) + self.arctrack.on() + self.ui.radiusUi() + self.step = 1 + self.ui.radiusValue.setFocus() + msg(translate("draft", "Pick radius:\n")) + + def numericRadius(self,rad): + "this function gets called by the toolbar when valid radius have been entered there" + if (self.step == 1): + self.rad = rad + if len(self.tangents) == 2: + cir = fcgeo.circleFrom2tan1rad(self.tangents[0], self.tangents[1], rad) + if self.center: + self.center = fcgeo.findClosestCircle(self.center,cir).Center + else: + self.center = cir[-1].Center + elif self.tangents and self.tanpoints: + cir = fcgeo.circleFrom1tan1pt1rad(self.tangents[0],self.tanpoints[0],rad) + if self.center: + self.center = fcgeo.findClosestCircle(self.center,cir).Center + else: + self.center = cir[-1].Center + if self.closedCircle: + self.drawArc() + else: + self.step = 2 + self.arctrack.setCenter(self.center) + self.ui.labelRadius.setText("Start angle") + self.linetrack.p1(self.center) + self.linetrack.on() + self.ui.radiusValue.setText("") self.ui.radiusValue.setFocus() - msg(translate("draft", "Pick radius:\n")) - - def numericRadius(self,rad): - "this function gets called by the toolbar when valid radius have been entered there" - if (self.step == 1): - self.rad = rad - if len(self.tangents) == 2: - cir = fcgeo.circleFrom2tan1rad(self.tangents[0], self.tangents[1], rad) - if self.center: - self.center = fcgeo.findClosestCircle(self.center,cir).Center - else: - self.center = cir[-1].Center - elif self.tangents and self.tanpoints: - cir = fcgeo.circleFrom1tan1pt1rad(self.tangents[0],self.tanpoints[0],rad) - if self.center: - self.center = fcgeo.findClosestCircle(self.center,cir).Center - else: - self.center = cir[-1].Center - if self.closedCircle: - self.drawArc() - else: - self.step = 2 - self.arctrack.setCenter(self.center) - self.ui.labelRadius.setText("Start angle") - self.linetrack.p1(self.center) - self.linetrack.on() - self.ui.radiusValue.setText("") - self.ui.radiusValue.setFocus() - msg(translate("draft", "Pick start angle:\n")) - elif (self.step == 2): - self.ui.labelRadius.setText("Aperture") - self.firstangle = math.radians(rad) - if fcvec.equals(plane.axis, Vector(1,0,0)): u = Vector(0,self.rad,0) - else: u = fcvec.scaleTo(Vector(1,0,0).cross(plane.axis), self.rad) - urotated = fcvec.rotate(u, math.radians(rad), plane.axis) - self.arctrack.setStartAngle(self.firstangle) - self.step = 3 - self.ui.radiusValue.setText("") - self.ui.radiusValue.setFocus() - msg(translate("draft", "Aperture angle:\n")) - else: - self.updateAngle(rad) - self.angle = math.radians(rad) - self.step = 4 - self.drawArc() - + msg(translate("draft", "Pick start angle:\n")) + elif (self.step == 2): + self.ui.labelRadius.setText("Aperture") + self.firstangle = math.radians(rad) + if fcvec.equals(plane.axis, Vector(1,0,0)): u = Vector(0,self.rad,0) + else: u = fcvec.scaleTo(Vector(1,0,0).cross(plane.axis), self.rad) + urotated = fcvec.rotate(u, math.radians(rad), plane.axis) + self.arctrack.setStartAngle(self.firstangle) + self.step = 3 + self.ui.radiusValue.setText("") + self.ui.radiusValue.setFocus() + msg(translate("draft", "Aperture angle:\n")) + else: + self.updateAngle(rad) + self.angle = math.radians(rad) + self.step = 4 + self.drawArc() + class Circle(Arc): - "The Draft_Circle FreeCAD command definition" + "The Draft_Circle FreeCAD command definition" - def __init__(self): - self.closedCircle=True - self.featureName = "Circle" - - def GetResources(self): - return {'Pixmap' : 'Draft_Circle', - 'Accel' : "C, I", - 'MenuText': QtCore.QT_TRANSLATE_NOOP("Draft_Circle", "Circle"), - 'ToolTip': QtCore.QT_TRANSLATE_NOOP("Draft_Circle", "Creates a circle. CTRL to snap, ALT to select tangent objects")} + def __init__(self): + self.closedCircle=True + self.featureName = "Circle" + + def GetResources(self): + return {'Pixmap' : 'Draft_Circle', + 'Accel' : "C, I", + 'MenuText': QtCore.QT_TRANSLATE_NOOP("Draft_Circle", "Circle"), + 'ToolTip': QtCore.QT_TRANSLATE_NOOP("Draft_Circle", "Creates a circle. CTRL to snap, ALT to select tangent objects")} class Polygon(Creator): - "the Draft_Polygon FreeCAD command definition" + "the Draft_Polygon FreeCAD command definition" - def GetResources(self): - return {'Pixmap' : 'Draft_Polygon', - 'Accel' : "P, G", - 'MenuText': QtCore.QT_TRANSLATE_NOOP("Draft_Polygon", "Polygon"), - 'ToolTip': QtCore.QT_TRANSLATE_NOOP("Draft_Polygon", "Creates a regular polygon. CTRL to snap, SHIFT to constrain")} + def GetResources(self): + return {'Pixmap' : 'Draft_Polygon', + 'Accel' : "P, G", + 'MenuText': QtCore.QT_TRANSLATE_NOOP("Draft_Polygon", "Polygon"), + 'ToolTip': QtCore.QT_TRANSLATE_NOOP("Draft_Polygon", "Creates a regular polygon. CTRL to snap, SHIFT to constrain")} - def Activated(self): - Creator.Activated(self,"Polygon") - if self.ui: - self.step = 0 - self.center = None - self.rad = None - self.tangents = [] - self.tanpoints = [] - self.ui.pointUi() - self.ui.extUi() - self.ui.numFaces.show() - self.altdown = False - self.ui.sourceCmd = self - self.linetrack = lineTracker(dotted=True) - self.constraintrack = lineTracker(dotted=True) - self.arctrack = arcTracker() - self.call = self.view.addEventCallback("SoEvent",self.action) - msg(translate("draft", "Pick center point:\n")) + def Activated(self): + Creator.Activated(self,"Polygon") + if self.ui: + self.step = 0 + self.center = None + self.rad = None + self.tangents = [] + self.tanpoints = [] + self.ui.pointUi() + self.ui.extUi() + self.ui.numFaces.show() + self.altdown = False + self.ui.sourceCmd = self + self.linetrack = lineTracker(dotted=True) + self.constraintrack = lineTracker(dotted=True) + self.arctrack = arcTracker() + self.call = self.view.addEventCallback("SoEvent",self.action) + msg(translate("draft", "Pick center point:\n")) - def finish(self,closed=False,cont=False): - "finishes the arc" - Creator.finish(self) - if self.ui: - self.linetrack.finalize() - self.constraintrack.finalize() - self.arctrack.finalize() - self.doc.recompute() - if cont and self.ui: - if self.ui.continueMode: - self.Activated() + def finish(self,closed=False,cont=False): + "finishes the arc" + Creator.finish(self) + if self.ui: + self.linetrack.finalize() + self.constraintrack.finalize() + self.arctrack.finalize() + self.doc.recompute() + if cont and self.ui: + if self.ui.continueMode: + self.Activated() - def action(self,arg): - "scene event handler" - if arg["Type"] == "SoKeyboardEvent" and arg["Key"] == "ESCAPE": - self.finish() - if (arg["Type"] == "SoLocation2Event"): - point,ctrlPoint = getPoint(self,arg) - # this is to make sure radius is what you see on screen + def action(self,arg): + "scene event handler" + if arg["Type"] == "SoKeyboardEvent": + if arg["Key"] == "ESCAPE": + self.finish() + elif arg["Type"] == "SoLocation2Event": + point,ctrlPoint = getPoint(self,arg) + # this is to make sure radius is what you see on screen + self.ui.cross(True) + if self.center and fcvec.dist(point,self.center) > 0: + viewdelta = fcvec.project(point.sub(self.center), plane.axis) + if not fcvec.isNull(viewdelta): + point = point.add(fcvec.neg(viewdelta)) + if (self.step == 0): # choose center + if hasMod(arg,MODALT): + if not self.altdown: + self.ui.cross(False) + self.altdown = True + self.ui.switchUi(True) + else: + if self.altdown: self.ui.cross(True) - if self.center and fcvec.dist(point,self.center) > 0: - viewdelta = fcvec.project(point.sub(self.center), plane.axis) - if not fcvec.isNull(viewdelta): - point = point.add(fcvec.neg(viewdelta)) - if (self.step == 0): # choose center - if hasMod(arg,MODALT): - if not self.altdown: - self.ui.cross(False) - self.altdown = True - self.ui.switchUi(True) - else: - if self.altdown: - self.ui.cross(True) - self.altdown = False - self.ui.switchUi(False) - else: # choose radius - if len(self.tangents) == 2: - cir = fcgeo.circleFrom2tan1pt(self.tangents[0], self.tangents[1], point) - self.center = fcgeo.findClosestCircle(point,cir).Center - self.arctrack.setCenter(self.center) - elif self.tangents and self.tanpoints: - cir = fcgeo.circleFrom1tan2pt(self.tangents[0], self.tanpoints[0], point) - self.center = fcgeo.findClosestCircle(point,cir).Center - self.arctrack.setCenter(self.center) - if hasMod(arg,MODALT): - if not self.altdown: - self.ui.cross(False) - self.altdown = True - snapped = self.view.getObjectInfo((arg["Position"][0],arg["Position"][1])) - if snapped: - ob = self.doc.getObject(snapped['Object']) - num = int(snapped['Component'].lstrip('Edge'))-1 - ed = ob.Shape.Edges[num] - if len(self.tangents) == 2: - cir = fcgeo.circleFrom3tan(self.tangents[0], self.tangents[1], ed) - cl = fcgeo.findClosestCircle(point,cir) - self.center = cl.Center - self.rad = cl.Radius - self.arctrack.setCenter(self.center) - else: - self.rad = self.center.add(fcgeo.findDistance(self.center,ed).sub(self.center)).Length - else: - self.rad = fcvec.dist(point,self.center) - else: - if self.altdown: - self.ui.cross(True) - self.altdown = False - self.rad = fcvec.dist(point,self.center) - self.ui.setRadiusValue(self.rad) - self.arctrack.setRadius(self.rad) - # Draw constraint tracker line. - if hasMod(arg,MODCONSTRAIN): - self.constraintrack.p1(point) - self.constraintrack.p2(ctrlPoint) - self.constraintrack.on() - else: self.constraintrack.off() - self.linetrack.p1(self.center) - self.linetrack.p2(point) - self.linetrack.on() - - if (arg["Type"] == "SoMouseButtonEvent"): - if (arg["State"] == "DOWN") and (arg["Button"] == "BUTTON1"): - point,ctrlPoint = getPoint(self,arg) - # this is to make sure radius is what you see on screen - if self.center and fcvec.dist(point,self.center) > 0: - viewdelta = fcvec.project(point.sub(self.center), plane.axis) - if not fcvec.isNull(viewdelta): - point = point.add(fcvec.neg(viewdelta)) - if (self.step == 0): # choose center - if not self.node: self.support = getSupport(arg) - if hasMod(arg,MODALT): - snapped=self.view.getObjectInfo((arg["Position"][0],arg["Position"][1])) - if snapped: - ob = self.doc.getObject(snapped['Object']) - num = int(snapped['Component'].lstrip('Edge'))-1 - ed = ob.Shape.Edges[num] - self.tangents.append(ed) - if len(self.tangents) == 2: - self.arctrack.on() - self.ui.radiusUi() - self.step = 1 - self.linetrack.on() - msg(translate("draft", "Pick radius:\n")) - else: - if len(self.tangents) == 1: - self.tanpoints.append(point) - else: - self.center = point - self.node = [point] - self.arctrack.setCenter(self.center) - self.linetrack.p1(self.center) - self.linetrack.p2(self.view.getPoint(arg["Position"][0],arg["Position"][1])) - self.arctrack.on() - self.ui.radiusUi() - self.step = 1 - self.linetrack.on() - msg(translate("draft", "Pick radius:\n")) - self.planetrack.set(point) - elif (self.step == 1): # choose radius - self.ui.cross(False) - self.drawPolygon() - - def drawPolygon(self): - "actually draws the FreeCAD object" - p = plane.getRotation() - p.move(self.center) - self.commit(translate("draft","Create Polygon"),partial(Draft.makePolygon,self.ui.numFaces.value(),self.rad,True,p,face=self.ui.hasFill.isChecked(),support=self.support)) - self.finish(cont=True) - - def numericInput(self,numx,numy,numz): - "this function gets called by the toolbar when valid x, y, and z have been entered there" - self.center = Vector(numx,numy,numz) - self.node = [self.center] - self.arctrack.setCenter(self.center) - self.arctrack.on() - self.ui.radiusUi() - self.step = 1 - self.ui.radiusValue.setFocus() - msg(translate("draft", "Pick radius:\n")) - - def numericRadius(self,rad): - "this function gets called by the toolbar when valid radius have been entered there" - self.rad = rad + self.altdown = False + self.ui.switchUi(False) + else: # choose radius if len(self.tangents) == 2: - cir = fcgeo.circleFrom2tan1rad(self.tangents[0], self.tangents[1], rad) - if self.center: - self.center = fcgeo.findClosestCircle(self.center,cir).Center - else: - self.center = cir[-1].Center + cir = fcgeo.circleFrom2tan1pt(self.tangents[0], self.tangents[1], point) + self.center = fcgeo.findClosestCircle(point,cir).Center + self.arctrack.setCenter(self.center) elif self.tangents and self.tanpoints: - cir = fcgeo.circleFrom1tan1pt1rad(self.tangents[0],self.tanpoints[0],rad) - if self.center: - self.center = fcgeo.findClosestCircle(self.center,cir).Center + cir = fcgeo.circleFrom1tan2pt(self.tangents[0], self.tanpoints[0], point) + self.center = fcgeo.findClosestCircle(point,cir).Center + self.arctrack.setCenter(self.center) + if hasMod(arg,MODALT): + if not self.altdown: + self.ui.cross(False) + self.altdown = True + snapped = self.view.getObjectInfo((arg["Position"][0],arg["Position"][1])) + if snapped: + ob = self.doc.getObject(snapped['Object']) + num = int(snapped['Component'].lstrip('Edge'))-1 + ed = ob.Shape.Edges[num] + if len(self.tangents) == 2: + cir = fcgeo.circleFrom3tan(self.tangents[0], self.tangents[1], ed) + cl = fcgeo.findClosestCircle(point,cir) + self.center = cl.Center + self.rad = cl.Radius + self.arctrack.setCenter(self.center) else: - self.center = cir[-1].Center - self.drawPolygon() + self.rad = self.center.add(fcgeo.findDistance(self.center,ed).sub(self.center)).Length + else: + self.rad = fcvec.dist(point,self.center) + else: + if self.altdown: + self.ui.cross(True) + self.altdown = False + self.rad = fcvec.dist(point,self.center) + self.ui.setRadiusValue(self.rad) + self.arctrack.setRadius(self.rad) + # Draw constraint tracker line. + if hasMod(arg,MODCONSTRAIN): + self.constraintrack.p1(point) + self.constraintrack.p2(ctrlPoint) + self.constraintrack.on() + else: self.constraintrack.off() + self.linetrack.p1(self.center) + self.linetrack.p2(point) + self.linetrack.on() + + elif arg["Type"] == "SoMouseButtonEvent": + if (arg["State"] == "DOWN") and (arg["Button"] == "BUTTON1"): + point,ctrlPoint = getPoint(self,arg) + # this is to make sure radius is what you see on screen + if self.center and fcvec.dist(point,self.center) > 0: + viewdelta = fcvec.project(point.sub(self.center), plane.axis) + if not fcvec.isNull(viewdelta): + point = point.add(fcvec.neg(viewdelta)) + if (self.step == 0): # choose center + if not self.node: self.support = getSupport(arg) + if hasMod(arg,MODALT): + snapped=self.view.getObjectInfo((arg["Position"][0],arg["Position"][1])) + if snapped: + ob = self.doc.getObject(snapped['Object']) + num = int(snapped['Component'].lstrip('Edge'))-1 + ed = ob.Shape.Edges[num] + self.tangents.append(ed) + if len(self.tangents) == 2: + self.arctrack.on() + self.ui.radiusUi() + self.step = 1 + self.linetrack.on() + msg(translate("draft", "Pick radius:\n")) + else: + if len(self.tangents) == 1: + self.tanpoints.append(point) + else: + self.center = point + self.node = [point] + self.arctrack.setCenter(self.center) + self.linetrack.p1(self.center) + self.linetrack.p2(self.view.getPoint(arg["Position"][0],arg["Position"][1])) + self.arctrack.on() + self.ui.radiusUi() + self.step = 1 + self.linetrack.on() + msg(translate("draft", "Pick radius:\n")) + self.planetrack.set(point) + elif (self.step == 1): # choose radius + self.ui.cross(False) + self.drawPolygon() + + def drawPolygon(self): + "actually draws the FreeCAD object" + p = plane.getRotation() + p.move(self.center) + self.commit(translate("draft","Create Polygon"), + partial(Draft.makePolygon,self.ui.numFaces.value(),self.rad, + True,p,face=self.ui.hasFill.isChecked(),support=self.support)) + self.finish(cont=True) + + def numericInput(self,numx,numy,numz): + "this function gets called by the toolbar when valid x, y, and z have been entered there" + self.center = Vector(numx,numy,numz) + self.node = [self.center] + self.arctrack.setCenter(self.center) + self.arctrack.on() + self.ui.radiusUi() + self.step = 1 + self.ui.radiusValue.setFocus() + msg(translate("draft", "Pick radius:\n")) + + def numericRadius(self,rad): + "this function gets called by the toolbar when valid radius have been entered there" + self.rad = rad + if len(self.tangents) == 2: + cir = fcgeo.circleFrom2tan1rad(self.tangents[0], self.tangents[1], rad) + if self.center: + self.center = fcgeo.findClosestCircle(self.center,cir).Center + else: + self.center = cir[-1].Center + elif self.tangents and self.tanpoints: + cir = fcgeo.circleFrom1tan1pt1rad(self.tangents[0],self.tanpoints[0],rad) + if self.center: + self.center = fcgeo.findClosestCircle(self.center,cir).Center + else: + self.center = cir[-1].Center + self.drawPolygon() + class Text(Creator): - ''' - This class creates an annotation feature. - ''' + "This class creates an annotation feature." - def GetResources(self): - return {'Pixmap' : 'Draft_Text', - 'Accel' : "T, E", - 'MenuText': QtCore.QT_TRANSLATE_NOOP("Draft_Text", "Text"), - 'ToolTip': QtCore.QT_TRANSLATE_NOOP("Draft_Text", "Creates an annotation. CTRL to snap")} + def GetResources(self): + return {'Pixmap' : 'Draft_Text', + 'Accel' : "T, E", + 'MenuText': QtCore.QT_TRANSLATE_NOOP("Draft_Text", "Text"), + 'ToolTip': QtCore.QT_TRANSLATE_NOOP("Draft_Text", "Creates an annotation. CTRL to snap")} - def Activated(self): - Creator.Activated(self,"Text") - if self.ui: - self.dialog = None - self.text = '' - self.ui.sourceCmd = self - self.ui.pointUi() - self.call = self.view.addEventCallback("SoEvent",self.action) - self.ui.xValue.setFocus() - self.ui.xValue.selectAll() - msg(translate("draft", "Pick location point:\n")) - FreeCADGui.draftToolBar.show() + def Activated(self): + Creator.Activated(self,"Text") + if self.ui: + self.dialog = None + self.text = '' + self.ui.sourceCmd = self + self.ui.pointUi() + self.call = self.view.addEventCallback("SoEvent",self.action) + self.ui.xValue.setFocus() + self.ui.xValue.selectAll() + msg(translate("draft", "Pick location point:\n")) + FreeCADGui.draftToolBar.show() - def finish(self,closed=False,cont=False): - "terminates the operation" - Creator.finish(self) - if self.ui: - del self.dialog - if cont and self.ui: - if self.ui.continueMode: - self.Activated() + def finish(self,closed=False,cont=False): + "terminates the operation" + Creator.finish(self) + if self.ui: + del self.dialog + if cont and self.ui: + if self.ui.continueMode: + self.Activated() - def createObject(self): - "creates an object in the current doc" - self.commit(translate("draft","Create Text"),partial(Draft.makeText,self.text,self.node[0])) - self.finish(cont=True) + def createObject(self): + "creates an object in the current doc" + self.commit(translate("draft","Create Text"), + partial(Draft.makeText,self.text,self.node[0])) + self.finish(cont=True) - def action(self,arg): - "scene event handler" - if arg["Type"] == "SoKeyboardEvent" and arg["Key"] == "ESCAPE": - self.finish() - if (arg["Type"] == "SoLocation2Event"): #mouse movement detection - point,ctrlPoint = getPoint(self,arg) + def action(self,arg): + "scene event handler" + if arg["Type"] == "SoKeyboardEvent": + if arg["Key"] == "ESCAPE": + self.finish() + elif arg["Type"] == "SoLocation2Event": #mouse movement detection + point,ctrlPoint = getPoint(self,arg) + elif arg["Type"] == "SoMouseButtonEvent": + if (arg["State"] == "DOWN") and (arg["Button"] == "BUTTON1"): + point,dtrlPoint = getPoint(self,arg) + self.node.append(point) + self.ui.textUi() + self.ui.textValue.setFocus() + self.ui.cross(False) - elif (arg["Type"] == "SoMouseButtonEvent"): - if (arg["State"] == "DOWN") and (arg["Button"] == "BUTTON1"): - point,dtrlPoint = getPoint(self,arg) - self.node.append(point) - self.ui.textUi() - self.ui.textValue.setFocus() - self.ui.cross(False) + def numericInput(self,numx,numy,numz): + '''this function gets called by the toolbar when valid + x, y, and z have been entered there''' + point = Vector(numx,numy,numz) + self.node.append(point) + self.ui.textUi() + self.ui.textValue.setFocus() + self.ui.cross(False) - def numericInput(self,numx,numy,numz): - "this function gets called by the toolbar when valid x, y, and z have been entered there" - point = Vector(numx,numy,numz) - self.node.append(point) - self.ui.textUi() - self.ui.textValue.setFocus() - self.ui.cross(False) - -class Dimension(Creator): - "The Draft_Dimension FreeCAD command definition" - def __init__(self): - self.max=2 - self.cont = None - self.dir = None +class Dimension(Creator): + "The Draft_Dimension FreeCAD command definition" + + def __init__(self): + self.max=2 + self.cont = None + self.dir = None - def GetResources(self): - return {'Pixmap' : 'Draft_Dimension', - 'Accel' : "D, I", - 'MenuText': QtCore.QT_TRANSLATE_NOOP("Draft_Dimension", "Dimension"), - 'ToolTip': QtCore.QT_TRANSLATE_NOOP("Draft_Dimension", "Creates a dimension. CTRL to snap, SHIFT to constrain, ALT to select a segment")} + def GetResources(self): + return {'Pixmap' : 'Draft_Dimension', + 'Accel' : "D, I", + 'MenuText': QtCore.QT_TRANSLATE_NOOP("Draft_Dimension", "Dimension"), + 'ToolTip': QtCore.QT_TRANSLATE_NOOP("Draft_Dimension", "Creates a dimension. CTRL to snap, SHIFT to constrain, ALT to select a segment")} - def Activated(self): - if self.cont: - self.finish() - elif self.hasMeasures(): - Creator.Activated(self,"Dimension") - self.dimtrack = dimTracker() - self.arctrack = arcTracker() - self.constraintrack = lineTracker(dotted=True) - self.createOnMeasures() - self.finish() - else: - Creator.Activated(self,"Dimension") - if self.ui: - self.ui.pointUi() - self.ui.continueCmd.show() - self.altdown = False - self.call = self.view.addEventCallback("SoEvent",self.action) - self.dimtrack = dimTracker() - self.arctrack = arcTracker() - self.link = None - self.edges = [] - self.pts = [] - self.angledata = None - self.indices = [] - self.center = None - self.arcmode = False - self.point2 = None - self.constraintrack = lineTracker(dotted=True) - msg(translate("draft", "Pick first point:\n")) - FreeCADGui.draftToolBar.show() - - def hasMeasures(self): - "checks if only measurements objects are selected" - sel = FreeCADGui.Selection.getSelection() - if not sel: - return False - for o in sel: - if not o.isDerivedFrom("App::MeasureDistance"): - return False - return True - - def finish(self,closed=False): - "terminates the operation" - self.cont = None - self.dir = None - Creator.finish(self) - if self.ui: - self.dimtrack.finalize() - self.arctrack.finalize() - self.constraintrack.finalize() - - def createOnMeasures(self): - for o in FreeCADGui.Selection.getSelection(): - p1 = o.P1 - p2 = o.P2 - pt = o.ViewObject.RootNode.getChildren()[1].getChildren()[0].getChildren()[0].getChildren()[3] - p3 = Vector(pt.point.getValues()[2].getValue()) - self.commit(translate("draft","Create Dimension"),partial(Draft.makeDimension,p1,p2,p3)) - self.commit(translate("draft","Delete Measurement"),partial(FreeCAD.ActiveDocument.removeObject,o.Name)) - - def createObject(self): - "creates an object in the current doc" - if self.angledata: - self.commit(translate("draft","Create Dimension"),partial(Draft.makeAngularDimension,self.center,self.angledata,self.node[-1])) - elif self.link and (not self.arcmode): - self.commit(translate("draft","Create Dimension"),partial(Draft.makeDimension,self.link[0],self.link[1],self.link[2],self.node[2])) - elif self.arcmode: - self.commit(translate("draft","Create Dimension"),partial(Draft.makeDimension,self.link[0],self.link[1],self.arcmode,self.node[2])) - else: - self.commit(translate("draft","Create Dimension"),partial(Draft.makeDimension,self.node[0],self.node[1],self.node[2])) - if self.ui.continueMode: - self.cont = self.node[2] - if not self.dir: - if self.link: - v1 = self.link[0].Shape.Vertexes[self.link[1]].Point - v2 = self.link[0].Shape.Vertexes[self.link[2]].Point - self.dir = v2.sub(v1) - else: - self.dir = self.node[1].sub(self.node[0]) - self.node = [self.node[1]] + def Activated(self): + if self.cont: + self.finish() + elif self.hasMeasures(): + Creator.Activated(self,"Dimension") + self.dimtrack = dimTracker() + self.arctrack = arcTracker() + self.constraintrack = lineTracker(dotted=True) + self.createOnMeasures() + self.finish() + else: + Creator.Activated(self,"Dimension") + if self.ui: + self.ui.pointUi() + self.ui.continueCmd.show() + self.altdown = False + self.call = self.view.addEventCallback("SoEvent",self.action) + self.dimtrack = dimTracker() + self.arctrack = arcTracker() self.link = None + self.edges = [] + self.pts = [] + self.angledata = None + self.indices = [] + self.center = None + self.arcmode = False + self.point2 = None + self.constraintrack = lineTracker(dotted=True) + msg(translate("draft", "Pick first point:\n")) + FreeCADGui.draftToolBar.show() - def action(self,arg): - "scene event handler" - if arg["Type"] == "SoKeyboardEvent" and arg["Key"] == "ESCAPE": - self.finish() - if (arg["Type"] == "SoLocation2Event"): #mouse movement detection - shift = hasMod(arg,MODCONSTRAIN) - if self.arcmode or self.point2: - setMod(arg,MODCONSTRAIN,False) - point,ctrlPoint = getPoint(self,arg) - self.ui.cross(True) - if hasMod(arg,MODALT) and (len(self.node)<3): - self.ui.cross(False) - self.dimtrack.off() - if not self.altdown: - self.altdown = True - self.ui.switchUi(True) - snapped = self.view.getObjectInfo((arg["Position"][0],arg["Position"][1])) - if snapped: - ob = self.doc.getObject(snapped['Object']) - if "Edge" in snapped['Component']: - num = int(snapped['Component'].lstrip('Edge'))-1 - ed = ob.Shape.Edges[num] - v1 = ed.Vertexes[0].Point - v2 = ed.Vertexes[-1].Point - self.dimtrack.update([v1,v2,self.cont]) - else: - self.ui.cross(True) - if self.node and (len(self.edges) < 2): - self.dimtrack.on() - if len(self.edges) == 2: - # angular dimension - self.dimtrack.off() - r = point.sub(self.center) - self.arctrack.setRadius(r.Length) - a = self.arctrack.getAngle(point) - pair = fcgeo.getBoundaryAngles(a,self.pts) - if not (pair[0] < a < pair[1]): - self.angledata = [4*math.pi-pair[0],2*math.pi-pair[1]] - else: - self.angledata = [2*math.pi-pair[0],2*math.pi-pair[1]] - self.arctrack.setStartAngle(self.angledata[0]) - self.arctrack.setEndAngle(self.angledata[1]) - if self.altdown: - self.altdown = False - self.ui.switchUi(False) - if self.dir: - point = self.node[0].add(fcvec.project(point.sub(self.node[0]),self.dir)) - if len(self.node) == 2: - if self.arcmode and self.edges: - cen = self.edges[0].Curve.Center - rad = self.edges[0].Curve.Radius - baseray = point.sub(cen) - v2 = fcvec.scaleTo(baseray,rad) - v1 = fcvec.neg(v2) - if shift: - self.node = [cen,cen.add(v2)] - self.arcmode = "radius" - else: - self.node = [cen.add(v1),cen.add(v2)] - self.arcmode = "diameter" - self.dimtrack.update(self.node) - # Draw constraint tracker line. - if shift and (not self.arcmode): - if len(self.node) == 2: - if not self.point2: - self.point2 = self.node[1] - else: - self.node[1] = self.point2 - a=abs(point.sub(self.node[0]).getAngle(plane.u)) - if (a > math.pi/4) and (a <= 0.75*math.pi): - self.node[1] = Vector(self.node[0].x,self.node[1].y,self.node[0].z) - else: - self.node[1] = Vector(self.node[1].x,self.node[0].y,self.node[0].z) - self.constraintrack.p1(point) - self.constraintrack.p2(ctrlPoint) - self.constraintrack.on() - else: - if self.point2: - self.node[1] = self.point2 - self.point2 = None - self.constraintrack.off() - # update the dimline - if self.node and (not self.arcmode): - self.dimtrack.update(self.node+[point]+[self.cont]) - elif (arg["Type"] == "SoMouseButtonEvent"): - if (arg["State"] == "DOWN") and (arg["Button"] == "BUTTON1"): - point,ctrlPoint = getPoint(self,arg) - if not self.node: self.support = getSupport(arg) - if hasMod(arg,MODALT) and (len(self.node)<3): - snapped = self.view.getObjectInfo((arg["Position"][0],arg["Position"][1])) - if snapped: - ob = self.doc.getObject(snapped['Object']) - if 'Edge' in snapped['Component']: - num = int(snapped['Component'].lstrip('Edge'))-1 - ed = ob.Shape.Edges[num] - v1 = ed.Vertexes[0].Point - v2 = ed.Vertexes[-1].Point - i1 = i2 = None - for i in range(len(ob.Shape.Vertexes)): - if v1 == ob.Shape.Vertexes[i].Point: - i1 = i - if v2 == ob.Shape.Vertexes[i].Point: - i2 = i - if (i1 != None) and (i2 != None): - self.indices.append(num) - if not self.edges: - # nothing snapped yet, we treat it as normal edge-snapped dimension - self.node = [v1,v2] - self.link = [ob,i1,i2] - self.edges.append(ed) - if isinstance(ed.Curve,Part.Circle): - # snapped edge is an arc - self.arcmode = "diameter" - self.link = [ob,num] - else: - # there is already a snapped edge, so we start angular dimension - self.edges.append(ed) - self.node.extend([v1,v2]) # self.node now has the 4 endpoints - c = fcgeo.findIntersection(self.node[0], - self.node[1], - self.node[2], - self.node[3], - True,True) - if c: - self.center = c[0] - self.arctrack.setCenter(self.center) - self.arctrack.on() - for e in self.edges: - for v in e.Vertexes: - self.pts.append(self.arctrack.getAngle(v.Point)) - self.link = [self.link[0],ob] - else: - msg(translate("draft", "Edges don't intersect!\n")) - self.finish() - - self.dimtrack.on() - else: - if self.dir: - point = self.node[0].add(fcvec.project(point.sub(self.node[0]),self.dir)) - self.node.append(point) - self.dimtrack.update(self.node) - if (len(self.node) == 2): - self.point2 = self.node[1] - if (len(self.node) == 1): - self.dimtrack.on() - self.planetrack.set(self.node[0]) - elif (len(self.node) == 2) and self.cont: - self.node.append(self.cont) - self.createObject() - if not self.cont: self.finish() - elif (len(self.node) == 3): - # for unlinked arc mode: - #if self.arcmode: - # v = self.node[1].sub(self.node[0]) - # v = fcvec.scale(v,0.5) - # cen = self.node[0].add(v) - # self.node = [self.node[0],self.node[1],cen] - self.createObject() - if not self.cont: self.finish() - elif self.angledata: - self.node.append(point) - self.createObject() - self.finish() + def hasMeasures(self): + "checks if only measurements objects are selected" + sel = FreeCADGui.Selection.getSelection() + if not sel: + return False + for o in sel: + if not o.isDerivedFrom("App::MeasureDistance"): + return False + return True - def numericInput(self,numx,numy,numz): - "this function gets called by the toolbar when valid x, y, and z have been entered there" - point = Vector(numx,numy,numz) - self.node.append(point) - self.dimtrack.update(self.node) - if (len(self.node) == 1): - self.dimtrack.on() - elif (len(self.node) == 3): - self.createObject() - if not self.cont: self.finish() + def finish(self,closed=False): + "terminates the operation" + self.cont = None + self.dir = None + Creator.finish(self) + if self.ui: + self.dimtrack.finalize() + self.arctrack.finalize() + self.constraintrack.finalize() + def createOnMeasures(self): + for o in FreeCADGui.Selection.getSelection(): + p1 = o.P1 + p2 = o.P2 + pt = o.ViewObject.RootNode.getChildren()[1].getChildren()[0].getChildren()[0].getChildren()[3] + p3 = Vector(pt.point.getValues()[2].getValue()) + self.commit(translate("draft","Create Dimension"), + partial(Draft.makeDimension,p1,p2,p3)) + self.commit(translate("draft","Delete Measurement"), + partial(FreeCAD.ActiveDocument.removeObject,o.Name)) + + def createObject(self): + "creates an object in the current doc" + if self.angledata: + self.commit(translate("draft","Create Dimension"), + partial(Draft.makeAngularDimension,self.center, + self.angledata,self.node[-1])) + elif self.link and (not self.arcmode): + self.commit(translate("draft","Create Dimension"), + partial(Draft.makeDimension,self.link[0],self.link[1], + self.link[2],self.node[2])) + elif self.arcmode: + self.commit(translate("draft","Create Dimension"), + partial(Draft.makeDimension,self.link[0],self.link[1], + self.arcmode,self.node[2])) + else: + self.commit(translate("draft","Create Dimension"), + partial(Draft.makeDimension,self.node[0],self.node[1], + self.node[2])) + if self.ui.continueMode: + self.cont = self.node[2] + if not self.dir: + if self.link: + v1 = self.link[0].Shape.Vertexes[self.link[1]].Point + v2 = self.link[0].Shape.Vertexes[self.link[2]].Point + self.dir = v2.sub(v1) + else: + self.dir = self.node[1].sub(self.node[0]) + self.node = [self.node[1]] + self.link = None + + def action(self,arg): + "scene event handler" + if arg["Type"] == "SoKeyboardEvent": + if arg["Key"] == "ESCAPE": + self.finish() + elif arg["Type"] == "SoLocation2Event": #mouse movement detection + shift = hasMod(arg,MODCONSTRAIN) + if self.arcmode or self.point2: + setMod(arg,MODCONSTRAIN,False) + point,ctrlPoint = getPoint(self,arg) + self.ui.cross(True) + if hasMod(arg,MODALT) and (len(self.node)<3): + self.ui.cross(False) + self.dimtrack.off() + if not self.altdown: + self.altdown = True + self.ui.switchUi(True) + snapped = self.view.getObjectInfo((arg["Position"][0],arg["Position"][1])) + if snapped: + ob = self.doc.getObject(snapped['Object']) + if "Edge" in snapped['Component']: + num = int(snapped['Component'].lstrip('Edge'))-1 + ed = ob.Shape.Edges[num] + v1 = ed.Vertexes[0].Point + v2 = ed.Vertexes[-1].Point + self.dimtrack.update([v1,v2,self.cont]) + else: + self.ui.cross(True) + if self.node and (len(self.edges) < 2): + self.dimtrack.on() + if len(self.edges) == 2: + # angular dimension + self.dimtrack.off() + r = point.sub(self.center) + self.arctrack.setRadius(r.Length) + a = self.arctrack.getAngle(point) + pair = fcgeo.getBoundaryAngles(a,self.pts) + if not (pair[0] < a < pair[1]): + self.angledata = [4*math.pi-pair[0],2*math.pi-pair[1]] + else: + self.angledata = [2*math.pi-pair[0],2*math.pi-pair[1]] + self.arctrack.setStartAngle(self.angledata[0]) + self.arctrack.setEndAngle(self.angledata[1]) + if self.altdown: + self.altdown = False + self.ui.switchUi(False) + if self.dir: + point = self.node[0].add(fcvec.project(point.sub(self.node[0]),self.dir)) + if len(self.node) == 2: + if self.arcmode and self.edges: + cen = self.edges[0].Curve.Center + rad = self.edges[0].Curve.Radius + baseray = point.sub(cen) + v2 = fcvec.scaleTo(baseray,rad) + v1 = fcvec.neg(v2) + if shift: + self.node = [cen,cen.add(v2)] + self.arcmode = "radius" + else: + self.node = [cen.add(v1),cen.add(v2)] + self.arcmode = "diameter" + self.dimtrack.update(self.node) + # Draw constraint tracker line. + if shift and (not self.arcmode): + if len(self.node) == 2: + if not self.point2: + self.point2 = self.node[1] + else: + self.node[1] = self.point2 + a=abs(point.sub(self.node[0]).getAngle(plane.u)) + if (a > math.pi/4) and (a <= 0.75*math.pi): + self.node[1] = Vector(self.node[0].x,self.node[1].y,self.node[0].z) + else: + self.node[1] = Vector(self.node[1].x,self.node[0].y,self.node[0].z) + self.constraintrack.p1(point) + self.constraintrack.p2(ctrlPoint) + self.constraintrack.on() + else: + if self.point2: + self.node[1] = self.point2 + self.point2 = None + self.constraintrack.off() + # update the dimline + if self.node and (not self.arcmode): + self.dimtrack.update(self.node+[point]+[self.cont]) + elif arg["Type"] == "SoMouseButtonEvent": + if (arg["State"] == "DOWN") and (arg["Button"] == "BUTTON1"): + point,ctrlPoint = getPoint(self,arg) + if not self.node: self.support = getSupport(arg) + if hasMod(arg,MODALT) and (len(self.node)<3): + snapped = self.view.getObjectInfo((arg["Position"][0],arg["Position"][1])) + if snapped: + ob = self.doc.getObject(snapped['Object']) + if 'Edge' in snapped['Component']: + num = int(snapped['Component'].lstrip('Edge'))-1 + ed = ob.Shape.Edges[num] + v1 = ed.Vertexes[0].Point + v2 = ed.Vertexes[-1].Point + i1 = i2 = None + for i in range(len(ob.Shape.Vertexes)): + if v1 == ob.Shape.Vertexes[i].Point: + i1 = i + if v2 == ob.Shape.Vertexes[i].Point: + i2 = i + if (i1 != None) and (i2 != None): + self.indices.append(num) + if not self.edges: + # nothing snapped yet, we treat it as normal edge-snapped dimension + self.node = [v1,v2] + self.link = [ob,i1,i2] + self.edges.append(ed) + if isinstance(ed.Curve,Part.Circle): + # snapped edge is an arc + self.arcmode = "diameter" + self.link = [ob,num] + else: + # there is already a snapped edge, so we start angular dimension + self.edges.append(ed) + self.node.extend([v1,v2]) # self.node now has the 4 endpoints + c = fcgeo.findIntersection(self.node[0], + self.node[1], + self.node[2], + self.node[3], + True,True) + if c: + self.center = c[0] + self.arctrack.setCenter(self.center) + self.arctrack.on() + for e in self.edges: + for v in e.Vertexes: + self.pts.append(self.arctrack.getAngle(v.Point)) + self.link = [self.link[0],ob] + else: + msg(translate("draft", "Edges don't intersect!\n")) + self.finish() + self.dimtrack.on() + else: + if self.dir: + point = self.node[0].add(fcvec.project(point.sub(self.node[0]),self.dir)) + self.node.append(point) + self.dimtrack.update(self.node) + if (len(self.node) == 2): + self.point2 = self.node[1] + if (len(self.node) == 1): + self.dimtrack.on() + self.planetrack.set(self.node[0]) + elif (len(self.node) == 2) and self.cont: + self.node.append(self.cont) + self.createObject() + if not self.cont: self.finish() + elif (len(self.node) == 3): + # for unlinked arc mode: + # if self.arcmode: + # v = self.node[1].sub(self.node[0]) + # v = fcvec.scale(v,0.5) + # cen = self.node[0].add(v) + # self.node = [self.node[0],self.node[1],cen] + self.createObject() + if not self.cont: self.finish() + elif self.angledata: + self.node.append(point) + self.createObject() + self.finish() + + def numericInput(self,numx,numy,numz): + "this function gets called by the toolbar when valid x, y, and z have been entered there" + point = Vector(numx,numy,numz) + self.node.append(point) + self.dimtrack.update(self.node) + if (len(self.node) == 1): + self.dimtrack.on() + elif (len(self.node) == 3): + self.createObject() + if not self.cont: self.finish() #--------------------------------------------------------------------------- @@ -2492,1855 +2524,1922 @@ class Dimension(Creator): #--------------------------------------------------------------------------- class Modifier: - "A generic Modifier Tool, used by modification tools such as move" - def __init__(self): - self.commitList = [] + "A generic Modifier Tool, used by modification tools such as move" + + def __init__(self): + self.commitList = [] + + def Activated(self,name="None"): + if FreeCAD.activeDraftCommand: + FreeCAD.activeDraftCommand.finish() + self.ui = None + self.call = None + self.commitList = [] + self.doc = FreeCAD.ActiveDocument + if not self.doc: + self.finish() + else: + FreeCAD.activeDraftCommand = self + self.view = FreeCADGui.ActiveDocument.ActiveView + self.ui = FreeCADGui.draftToolBar + FreeCADGui.draftToolBar.show() + rot = self.view.getCameraNode().getField("orientation").getValue() + upv = Vector(rot.multVec(coin.SbVec3f(0,1,0)).getValue()) + plane.setup(fcvec.neg(self.view.getViewDirection()), Vector(0,0,0), upv) + self.node = [] + self.ui.sourceCmd = self + self.constrain = None + self.obj = None + self.extendedCopy = False + self.ui.setTitle(name) + self.featureName = name + self.snap = snapTracker() + self.extsnap = lineTracker(dotted=True) + self.planetrack = PlaneTracker() + if Draft.getParam("grid"): + self.grid = gridTracker() + self.grid.set() + else: + self.grid = None - def Activated(self,name="None"): - if FreeCAD.activeDraftCommand: - FreeCAD.activeDraftCommand.finish() - self.ui = None - self.call = None - self.commitList = [] - self.doc = FreeCAD.ActiveDocument - if not self.doc: - self.finish() - else: - FreeCAD.activeDraftCommand = self - self.view = FreeCADGui.ActiveDocument.ActiveView - self.ui = FreeCADGui.draftToolBar - FreeCADGui.draftToolBar.show() - rot = self.view.getCameraNode().getField("orientation").getValue() - upv = Vector(rot.multVec(coin.SbVec3f(0,1,0)).getValue()) - plane.setup(fcvec.neg(self.view.getViewDirection()), Vector(0,0,0), upv) - self.node = [] - self.ui.sourceCmd = self - self.constrain = None - self.obj = None - self.extendedCopy = False - self.ui.setTitle(name) - self.featureName = name - self.snap = snapTracker() - self.extsnap = lineTracker(dotted=True) - self.planetrack = PlaneTracker() - if Draft.getParam("grid"): - self.grid = gridTracker() - self.grid.set() - else: - self.grid = None - - def IsActive(self): - if FreeCADGui.ActiveDocument: - return True - else: - return False + def IsActive(self): + if FreeCADGui.ActiveDocument: + return True + else: + return False - def finish(self): - self.node = [] - self.snap.finalize() - self.extsnap.finalize() - FreeCAD.activeDraftCommand = None - if self.ui: - self.ui.offUi() - self.ui.sourceCmd=None - self.ui.cross(False) - msg("") - self.planetrack.finalize() - if self.grid: self.grid.finalize() - if self.call: - self.view.removeEventCallback("SoEvent",self.call) - self.call = None - if self.commitList: - todo.delayCommit(self.commitList) - self.commitList = [] + def finish(self): + self.node = [] + self.snap.finalize() + self.extsnap.finalize() + FreeCAD.activeDraftCommand = None + if self.ui: + self.ui.offUi() + self.ui.sourceCmd=None + self.ui.cross(False) + msg("") + self.planetrack.finalize() + if self.grid: self.grid.finalize() + if self.call: + self.view.removeEventCallback("SoEvent",self.call) + self.call = None + if self.commitList: + todo.delayCommit(self.commitList) + self.commitList = [] + + def commit(self,name,func): + "stores partial actions to be committed to the FreeCAD document" + # print "committing" + self.commitList.append((name,func)) + - def commit(self,name,func): - "stores partial actions to be committed to the FreeCAD document" - # print "committing" - self.commitList.append((name,func)) - class Move(Modifier): - "The Draft_Move FreeCAD command definition" + "The Draft_Move FreeCAD command definition" - def GetResources(self): - return {'Pixmap' : 'Draft_Move', - 'Accel' : "M, V", - 'MenuText': QtCore.QT_TRANSLATE_NOOP("Draft_Move", "Move"), - 'ToolTip': QtCore.QT_TRANSLATE_NOOP("Draft_Move", "Moves the selected objects between 2 points. CTRL to snap, SHIFT to constrain, ALT to copy")} - - def Activated(self): - Modifier.Activated(self,"Move") - if self.ui: - if not Draft.getSelection(): - self.ghost = None - self.linetrack = None - self.constraintrack = None - self.ui.selectUi() - msg(translate("draft", "Select an object to move\n")) - self.call = self.view.addEventCallback("SoEvent",selectObject) - else: - self.proceed() - - def proceed(self): - if self.call: self.view.removeEventCallback("SoEvent",self.call) - self.sel = Draft.getSelection() - self.sel = Draft.getGroupContents(self.sel) - self.ui.pointUi() - self.ui.modUi() - self.ui.xValue.setFocus() - self.ui.xValue.selectAll() - self.linetrack = lineTracker() - self.constraintrack = lineTracker(dotted=True) - self.ghost = ghostTracker(self.sel) - self.call = self.view.addEventCallback("SoEvent",self.action) - msg(translate("draft", "Pick start point:\n")) - self.ui.cross(True) - - def finish(self,closed=False,cont=False): - if self.ui: - self.ghost.finalize() - self.linetrack.finalize() - self.constraintrack.finalize() - Modifier.finish(self) - if cont and self.ui: - if self.ui.continueMode: - FreeCADGui.Selection.clearSelection() - self.Activated() - - def move(self,delta,copy=False): - "moving the real shapes" - if copy: - self.commit(translate("draft","Copy"),partial(Draft.move,self.sel,delta,copy)) - else: - self.commit(translate("draft","Move"),partial(Draft.move,self.sel,delta,copy)) - self.doc.recompute() - - def action(self,arg): - "scene event handler" - if arg["Type"] == "SoKeyboardEvent" and arg["Key"] == "ESCAPE": - self.finish() - if (arg["Type"] == "SoLocation2Event"): #mouse movement detection - point,ctrlPoint = getPoint(self,arg) - self.linetrack.p2(point) - self.ui.cross(True) - # Draw constraint tracker line. - if hasMod(arg,MODCONSTRAIN): - self.constraintrack.p1(point) - self.constraintrack.p2(ctrlPoint) - self.constraintrack.on() - else: self.constraintrack.off() - if (len(self.node) > 0): - last = self.node[len(self.node)-1] - delta = point.sub(last) - self.ghost.trans.translation.setValue([delta.x,delta.y,delta.z]) - if self.extendedCopy: - if not hasMod(arg,MODALT): self.finish() - if (arg["Type"] == "SoMouseButtonEvent"): - if (arg["State"] == "DOWN") and (arg["Button"] == "BUTTON1"): - point,ctrlPoint = getPoint(self,arg) - if (self.node == []): - self.node.append(point) - self.ui.isRelative.show() - self.linetrack.on() - self.ghost.on() - self.linetrack.p1(point) - msg(translate("draft", "Pick end point:\n")) - self.planetrack.set(point) - else: - last = self.node[0] - if self.ui.isCopy.isChecked() or hasMod(arg,MODALT): - self.move(point.sub(last),True) - else: - self.move(point.sub(last)) - if hasMod(arg,MODALT): - self.extendedCopy = True - else: - self.finish(cont=True) - - def numericInput(self,numx,numy,numz): - "this function gets called by the toolbar when valid x, y, and z have been entered there" - point = Vector(numx,numy,numz) - if not self.node: - self.node.append(point) - self.ui.isRelative.show() - self.ui.isCopy.show() - self.linetrack.p1(point) - self.linetrack.on() - self.ghost.on() - msg(translate("draft", "Pick end point:\n")) - else: - last = self.node[-1] - if self.ui.isCopy.isChecked(): - self.move(point.sub(last),True) - else: - self.move(point.sub(last)) - self.finish() - - -class ApplyStyle(Modifier): - "The Draft_ApplyStyle FreeCA command definition" - - def GetResources(self): - return {'Pixmap' : 'Draft_Apply', - 'MenuText': QtCore.QT_TRANSLATE_NOOP("Draft_ApplyStyle", "Apply Current Style"), - 'ToolTip' : QtCore.QT_TRANSLATE_NOOP("Draft_ApplyStyle", "Applies current line width and color to selected objects")} - - def IsActive(self): - if Draft.getSelection(): - return True - else: - return False - - def Activated(self): - Modifier.Activated(self) - if self.ui: - self.sel = Draft.getSelection() - if (len(self.sel)>0): - for ob in self.sel: - if (ob.Type == "App::DocumentObjectGroup"): - self.formatGroup(ob) - else: - self.commit(translate("draft","Change Style"),partial(Draft.formatObject,ob)) - - def formatGroup(self,grpob): - for ob in grpob.Group: - if (ob.Type == "App::DocumentObjectGroup"): - self.formatGroup(ob) - else: - self.commit(translate("draft","Change Style"),partial(Draft.formatObject,ob)) - - -class Rotate(Modifier): - "The Draft_Rotate FreeCAD command definition" - - def GetResources(self): - return {'Pixmap' : 'Draft_Rotate', - 'Accel' : "R, O", - 'MenuText': QtCore.QT_TRANSLATE_NOOP("Draft_Rotate", "Rotate"), - 'ToolTip': QtCore.QT_TRANSLATE_NOOP("Draft_Rotate", "Rotates the selected objects. CTRL to snap, SHIFT to constrain, ALT creates a copy")} - - def Activated(self): - Modifier.Activated(self,"Rotate") - if self.ui: - if not Draft.getSelection(): - self.ghost = None - self.linetrack = None - self.arctrack = None - self.constraintrack = None - self.ui.selectUi() - msg(translate("draft", "Select an object to rotate\n")) - self.call = self.view.addEventCallback("SoEvent",selectObject) - else: - self.proceed() - - def proceed(self): - if self.call: self.view.removeEventCallback("SoEvent",self.call) - self.sel = Draft.getSelection() - self.sel = Draft.getGroupContents(self.sel) - self.step = 0 - self.center = None - self.ui.arcUi() - self.ui.isCopy.show() - self.ui.setTitle("Rotate") - self.linetrack = lineTracker() - self.constraintrack = lineTracker(dotted=True) - self.arctrack = arcTracker() - self.ghost = ghostTracker(self.sel) - self.call = self.view.addEventCallback("SoEvent",self.action) - msg(translate("draft", "Pick rotation center:\n")) - self.ui.cross(True) - - def finish(self,closed=False,cont=False): - "finishes the arc" - Modifier.finish(self) - if self.ui: - self.linetrack.finalize() - self.constraintrack.finalize() - self.arctrack.finalize() - self.ghost.finalize() - self.doc.recompute() - if cont and self.ui: - if self.ui.continueMode: - FreeCADGui.Selection.clearSelection() - self.Activated() - - def rot (self,angle,copy=False): - "rotating the real shapes" - if copy: - self.commit(translate("draft","Copy"),partial(Draft.rotate,self.sel,math.degrees(angle),self.center,plane.axis,copy)) - else: - self.commit(translate("draft","Rotate"),partial(Draft.rotate,self.sel,math.degrees(angle),self.center,plane.axis,copy)) - - def action(self,arg): - "scene event handler" - if arg["Type"] == "SoKeyboardEvent" and arg["Key"] == "ESCAPE": - self.finish() - if (arg["Type"] == "SoLocation2Event"): - point,ctrlPoint = getPoint(self,arg) - self.ui.cross(True) - # this is to make sure radius is what you see on screen - if self.center and fcvec.dist(point,self.center): - viewdelta = fcvec.project(point.sub(self.center), plane.axis) - if not fcvec.isNull(viewdelta): - point = point.add(fcvec.neg(viewdelta)) - if self.extendedCopy: - if not hasMod(arg,MODALT): - self.step = 3 - self.finish() - if (self.step == 0): - pass - elif (self.step == 1): - currentrad = fcvec.dist(point,self.center) - if (currentrad != 0): - angle = fcvec.angle(plane.u, point.sub(self.center), plane.axis) - else: angle = 0 - self.linetrack.p2(point) - # Draw constraint tracker line. - if hasMod(arg,MODCONSTRAIN): - self.constraintrack.p1(point) - self.constraintrack.p2(ctrlPoint) - self.constraintrack.on() - else: self.constraintrack.off() - self.ui.radiusValue.setText("%.2f" % math.degrees(angle)) - self.firstangle = angle - self.ui.radiusValue.setFocus() - self.ui.radiusValue.selectAll() - elif (self.step == 2): - currentrad = fcvec.dist(point,self.center) - if (currentrad != 0): - angle = fcvec.angle(plane.u, point.sub(self.center), plane.axis) - else: angle = 0 - if (angle < self.firstangle): - sweep = (2*math.pi-self.firstangle)+angle - else: - sweep = angle - self.firstangle - self.arctrack.setApertureAngle(sweep) - self.ghost.trans.rotation.setValue(coin.SbVec3f(fcvec.tup(plane.axis)),sweep) - self.linetrack.p2(point) - # Draw constraint tracker line. - if hasMod(arg,MODCONSTRAIN): - self.constraintrack.p1(point) - self.constraintrack.p2(ctrlPoint) - self.constraintrack.on() - else: self.constraintrack.off() - self.ui.radiusValue.setText("%.2f" % math.degrees(sweep)) - self.ui.radiusValue.setFocus() - self.ui.radiusValue.selectAll() - - if (arg["Type"] == "SoMouseButtonEvent"): - if (arg["State"] == "DOWN") and (arg["Button"] == "BUTTON1"): - point,ctrlPoint = getPoint(self,arg) - if self.center and fcvec.dist(point,self.center): - viewdelta = fcvec.project(point.sub(self.center), plane.axis) - if not fcvec.isNull(viewdelta): point = point.add(fcvec.neg(viewdelta)) - if (self.step == 0): - self.center = point - self.node = [point] - self.ui.radiusUi() - self.ui.hasFill.hide() - self.ui.labelRadius.setText("Base angle") - self.linetrack.p1(self.center) - self.arctrack.setCenter(self.center) - self.ghost.trans.center.setValue(self.center.x,self.center.y,self.center.z) - self.linetrack.on() - self.step = 1 - msg(translate("draft", "Pick base angle:\n")) - self.planetrack.set(point) - elif (self.step == 1): - self.ui.labelRadius.setText("Rotation") - self.rad = fcvec.dist(point,self.center) - self.arctrack.on() - self.arctrack.setStartPoint(point) - self.ghost.on() - self.step = 2 - msg(translate("draft", "Pick rotation angle:\n")) - else: - currentrad = fcvec.dist(point,self.center) - angle = point.sub(self.center).getAngle(plane.u) - if fcvec.project(point.sub(self.center), plane.v).getAngle(plane.v) > 1: - angle = -angle - if (angle < self.firstangle): - sweep = (2*math.pi-self.firstangle)+angle - else: - sweep = angle - self.firstangle - if self.ui.isCopy.isChecked() or hasMod(arg,MODALT): - self.rot(sweep,True) - else: - self.rot(sweep) - if hasMod(arg,MODALT): - self.extendedCopy = True - else: - self.finish(cont=True) - - def numericInput(self,numx,numy,numz): - "this function gets called by the toolbar when valid x, y, and z have been entered there" - self.center = Vector(numx,numy,numz) - self.node = [self.center] - self.arctrack.setCenter(self.center) - self.ghost.trans.center.setValue(self.center.x,self.center.y,self.center.z) - self.linetrack.p1(self.center) - #self.arctrack.on() - self.linetrack.on() - self.ui.radiusUi() - self.ui.hasFill.hide() - self.ui.labelRadius.setText("Base angle") - self.step = 1 - msg(translate("draft", "Pick base angle:\n")) - - def numericRadius(self,rad): - "this function gets called by the toolbar when valid radius have been entered there" - if (self.step == 1): - self.ui.labelRadius.setText("Rotation") - self.firstangle = math.radians(rad) - self.arctrack.setStartAngle(self.firstangle) - self.arctrack.on() - self.ghost.on() - self.step = 2 - msg(translate("draft", "Pick rotation angle:\n")) - else: - self.rot(math.radians(rad),self.ui.isCopy.isChecked()) - self.finish(cont=True) - - -class Offset(Modifier): - "The Draft_Offset FreeCAD command definition" - - def GetResources(self): - return {'Pixmap' : 'Draft_Offset', - 'Accel' : "O, S", - 'MenuText': QtCore.QT_TRANSLATE_NOOP("Draft_Offset", "Offset"), - 'ToolTip': QtCore.QT_TRANSLATE_NOOP("Draft_Offset", "Offsets the active object. CTRL to snap, SHIFT to constrain, ALT to copy")} - - def Activated(self): - self.running = False - Modifier.Activated(self,"Offset") - if self.ui: - if not Draft.getSelection(): - self.ghost = None - self.linetrack = None - self.arctrack = None - self.constraintrack = None - self.ui.selectUi() - msg(translate("draft", "Select an object to offset\n")) - self.call = self.view.addEventCallback("SoEvent",selectObject) - elif len(Draft.getSelection()) > 1: - msg(translate("draft", "Offset only works on one object at a time\n"),"warning") - else: - self.proceed() - - def proceed(self): - if self.call: self.view.removeEventCallback("SoEvent",self.call) - self.sel = Draft.getSelection()[0] - if not self.sel.isDerivedFrom("Part::Feature"): - msg(translate("draft", "Cannot offset this object type\n"),"warning") - self.finish() - else: - self.step = 0 - self.dvec = None - self.constrainSeg = None - self.ui.offsetUi() - self.linetrack = lineTracker() - self.constraintrack = lineTracker(dotted=True) - self.faces = False - self.shape = self.sel.Shape - self.mode = None - if Draft.getType(self.sel) in ["Circle","Arc"]: - self.ghost = arcTracker() - self.mode = "Circle" - self.center = self.shape.Edges[0].Curve.Center - self.ghost.setCenter(self.center) - self.ghost.setStartAngle(math.radians(self.sel.FirstAngle)) - self.ghost.setEndAngle(math.radians(self.sel.LastAngle)) - else: - self.ghost = wireTracker(self.shape) - self.mode = "Wire" - self.call = self.view.addEventCallback("SoEvent",self.action) - msg(translate("draft", "Pick distance:\n")) - self.ui.cross(True) - self.planetrack.set(self.shape.Vertexes[0].Point) - self.running = True - - def action(self,arg): - "scene event handler" - if arg["Type"] == "SoKeyboardEvent" and arg["Key"] == "ESCAPE": - self.finish() - if (arg["Type"] == "SoLocation2Event"): - self.ui.cross(True) - point,ctrlPoint = getPoint(self,arg) - if hasMod(arg,MODCONSTRAIN) and self.constrainSeg: - dist = fcgeo.findPerpendicular(point,self.shape,self.constrainSeg[1]) - e = self.shape.Edges[self.constrainSeg[1]] - self.constraintrack.p1(e.Vertexes[0].Point) - self.constraintrack.p2(point.add(dist[0])) - self.constraintrack.on() - else: - dist = fcgeo.findPerpendicular(point,self.shape.Edges) - self.constraintrack.off() - if dist: - self.ghost.on() - if self.mode == "Wire": - d = fcvec.neg(dist[0]) - v1 = fcgeo.getTangent(self.shape.Edges[0],point) - v2 = fcgeo.getTangent(self.shape.Edges[dist[1]],point) - a = -fcvec.angle(v1,v2) - self.dvec = fcvec.rotate(d,a,plane.axis) - self.ghost.update(fcgeo.offsetWire(self.shape,self.dvec,occ=self.ui.occOffset.isChecked())) - elif self.mode == "Circle": - self.dvec = point.sub(self.center).Length - self.ghost.setRadius(self.dvec) - self.constrainSeg = dist - self.linetrack.on() - self.linetrack.p1(point) - self.linetrack.p2(point.add(dist[0])) - self.ui.radiusValue.setText("%.2f" % dist[0].Length) - else: - self.dvec = None - self.ghost.off() - self.constrainSeg = None - self.linetrack.off() - self.ui.radiusValue.setText("off") - self.ui.radiusValue.setFocus() - self.ui.radiusValue.selectAll() - if self.extendedCopy: - if not hasMod(arg,MODALT): self.finish() - if (arg["Type"] == "SoMouseButtonEvent"): - if (arg["State"] == "DOWN") and (arg["Button"] == "BUTTON1"): - copymode = False - occmode = self.ui.occOffset.isChecked() - if hasMod(arg,MODALT) or self.ui.isCopy.isChecked(): copymode = True - if self.dvec: - self.commit(translate("draft","Offset"),partial(Draft.offset,self.sel,self.dvec,copymode,occ=occmode)) - if hasMod(arg,MODALT): - self.extendedCopy = True - else: - self.finish() - - def finish(self,closed=False): - Modifier.finish(self) - if self.ui and self.running: - self.linetrack.finalize() - self.constraintrack.finalize() - self.ghost.finalize() - - def numericRadius(self,rad): - "this function gets called by the toolbar when valid radius have been entered there" - if self.dvec: - self.dvec.normalize() - self.dvec.multiply(rad) - copymode = False - occmode = self.ui.occOffset.isChecked() - if self.ui.isCopy.isChecked(): copymode = True - self.commit(translate("draft","Offset"),partial(Draft.offset,self.sel,self.dvec,copymode,occ=occmode)) - self.finish() - -class Upgrade(Modifier): - '''The Draft_Upgrade FreeCAD command definition. - This class upgrades selected objects in different ways, - following this list (in order): - - if there are more than one faces, the faces are merged (union) - - if there is only one face, nothing is done - - if there are closed wires, they are transformed in a face - - otherwise join all edges into a wire (closed if applicable) - - if nothing of the above is possible, a Compound is created - ''' - - def GetResources(self): - return {'Pixmap' : 'Draft_Upgrade', - 'Accel' : "U, P", - 'MenuText': QtCore.QT_TRANSLATE_NOOP("Draft_Upgrade", "Upgrade"), - 'ToolTip': QtCore.QT_TRANSLATE_NOOP("Draft_Upgrade", "Joins the selected objects into one, or converts closed wires to filled faces, or unite faces")} - - def Activated(self): - Modifier.Activated(self,"Upgrade") - if self.ui: - if not Draft.getSelection(): - self.ui.selectUi() - msg(translate("draft", "Select an object to upgrade\n")) - self.call = self.view.addEventCallback("SoEvent",selectObject) - else: - self.proceed() - - def compound(self): - #shapeslist = [] - #for ob in self.sel: shapeslist.append(ob.Shape) - #newob = self.doc.addObject("Part::Feature","Compound") - #newob.Shape = Part.makeCompound(shapeslist) - newob = Draft.makeBlock(self.sel) - self.nodelete = True - return newob - - def proceed(self): - if self.call: self.view.removeEventCallback("SoEvent",self.call) - self.sel = Draft.getSelection() - newob = None - self.nodelete = False - edges = [] - wires = [] - openwires = [] - faces = [] - groups = [] - curves = [] - facewires = [] - # determining what we have in our selection - for ob in self.sel: - if ob.Type == "App::DocumentObjectGroup": - groups.append(ob) - else: - if ob.Shape.ShapeType == 'Edge': openwires.append(ob.Shape) - for f in ob.Shape.Faces: - faces.append(f) - facewires.extend(f.Wires) - for w in ob.Shape.Wires: - if w.isClosed(): - wires.append(w) - else: - openwires.append(w) - for e in ob.Shape.Edges: - if not isinstance(e.Curve,Part.Line): - curves.append(e) - lastob = ob - # print "objects:",self.sel," edges:",edges," wires:",wires," openwires:",openwires," faces:",faces," groups:",groups," curves:",curves," facewires:",facewires - # applying transformation - self.doc.openTransaction("Upgrade") - if groups: - # if we have a group: turn each closed wire inside into a face - msg(translate("draft", "Found groups: closing each open object inside\n")) - for grp in groups: - for ob in grp.Group: - if not ob.Shape.Faces: - for w in ob.Shape.Wires: - newob = Draft.makeWire(w,closed=w.isClosed()) - self.sel.append(ob) - grp.addObject(newob) - elif faces and (len(wires)+len(openwires)==len(facewires)): - if (len(self.sel) == 1) and (len(faces) > 1): - # we have a shell: we try to make a solid - sol = Part.makeSolid(self.sel[0].Shape) - if sol.isClosed(): - msg(translate("draft", "Found 1 solidificable object: solidifying it\n")) - newob = self.doc.addObject("Part::Feature","Solid") - newob.Shape = sol - Draft.formatObject(newob,lastob) - - elif (len(self.sel) == 2) and (not curves): - # we have exactly 2 objects: we fuse them - msg(translate("draft", "Found 2 objects: fusing them\n")) - newob = Draft.fuse(self.sel[0],self.sel[1]) - self.nodelete = True - elif (len(self.sel) > 2) and (len(faces) > 10): - # we have many separate faces: we try to make a shell - sh = Part.makeShell(faces) - newob = self.doc.addObject("Part::Feature","Shell") - newob.Shape = sh - Draft.formatObject(newob,lastob) - elif (len(self.sel) > 2) or (len(faces) > 1): - # more than 2 objects or faces: we try the draft way: make one face out of them - u = faces.pop(0) - for f in faces: - u = u.fuse(f) - if fcgeo.isCoplanar(faces): - if self.sel[0].ViewObject.DisplayMode == "Wireframe": - f = False - else: - f = True - u = fcgeo.concatenate(u) - if not curves: - msg(translate("draft", "Found several objects or faces: making a parametric face\n")) - newob = Draft.makeWire(u.Wires[0],closed=True,face=f) - Draft.formatObject(newob,lastob) - else: - # if not possible, we do a non-parametric union - msg(translate("draft", "Found objects containing curves: fusing them\n")) - newob = self.doc.addObject("Part::Feature","Union") - newob.Shape = u - Draft.formatObject(newob,lastob) - else: - # if not possible, we do a non-parametric union - msg(translate("draft", "Found several objects: fusing them\n")) - # if we have a solid, make sure we really return a solid - if (len(u.Faces) > 1) and u.isClosed(): - u = Part.makeSolid(u) - newob = self.doc.addObject("Part::Feature","Union") - newob.Shape = u - Draft.formatObject(newob,lastob) - elif len(self.sel) == 1: - # only one object: if not parametric, we "draftify" it - self.nodelete = True - if (not curves) and (Draft.getType(self.sel[0]) == "Part"): - msg(translate("draft", "Found 1 non-parametric objects: draftifying it\n")) - Draft.draftify(self.sel[0]) - - elif wires and (not faces) and (not openwires): - if (len(self.sel) == 1) and self.sel[0].isDerivedFrom("Sketcher::SketchObject") and (not curves): - msg(translate("draft", "Found 1 closed sketch object: making a face from it\n")) - newob = Draft.makeWire(self.sel[0].Shape,closed=True) - newob.Base = self.sel[0] - self.sel[0].ViewObject.Visibility = False - self.nodelete = True - else: - # only closed wires - for w in wires: - f = Part.Face(w) - faces.append(f) - for f in faces: - if not curves: - newob = Draft.makeWire(f.Wire,closed=True) - else: - # if there are curved segments, we do a non-parametric face - msg(translate("draft", "Found closed wires: making faces\n")) - newob = self.doc.addObject("Part::Feature","Face") - newob.Shape = f - Draft.formatObject(newob,lastob) - elif (len(openwires) == 1) and (not faces) and (not wires): - # special case, we have only one open wire. We close it!" - p0 = openwires[0].Vertexes[0].Point - p1 = openwires[0].Vertexes[-1].Point - edges = openwires[0].Edges - edges.append(Part.Line(p1,p0).toShape()) - w = Part.Wire(fcgeo.sortEdges(edges)) - msg(translate("draft", "Found 1 open wire: closing it\n")) - if not curves: - newob = Draft.makeWire(w,closed=True) - else: - # if not possible, we do a non-parametric union - newob = self.doc.addObject("Part::Feature","Wire") - newob.Shape = w - Draft.formatObject(newob,lastob) - elif openwires and (not wires) and (not faces): - # only open wires and edges: we try to join their edges - for ob in self.sel: - for e in ob.Shape.Edges: - edges.append(e) - newob = None - nedges = fcgeo.sortEdges(edges[:]) - # for e in nedges: print "debug: ",e.Curve,e.Vertexes[0].Point,e.Vertexes[-1].Point - w = Part.Wire(nedges) - if len(w.Edges) == len(edges): - msg(translate("draft", "Found several edges: wiring them\n")) - if not curves: - newob = Draft.makeWire(w) - else: - newob = self.doc.addObject("Part::Feature","Wire") - newob.Shape = w - Draft.formatObject(newob,lastob) - if not newob: - print "no new object found" - msg(translate("draft", "Found several non-connected edges: making compound\n")) - newob = self.compound() - Draft.formatObject(newob,lastob) - else: - msg(translate("draft", "Found several non-treatable objects: making compound\n")) - newob = self.compound() - Draft.formatObject(newob,lastob) - if not self.nodelete: - for ob in self.sel: - if not ob.Type == "App::DocumentObjectGroup": - self.doc.removeObject(ob.Name) - self.doc.commitTransaction() - if newob: Draft.select(newob) - Modifier.finish(self) - -class Downgrade(Modifier): - ''' - The Draft_Downgrade FreeCAD command definition. - This class downgrades selected objects in different ways, - following this list (in order): - - if there are more than one faces, the subsequent - faces are subtracted from the first one - - if there is only one face, it gets converted to a wire - - otherwise wires are exploded into single edges - ''' - - def GetResources(self): - return {'Pixmap' : 'Draft_Downgrade', - 'Accel' : "D, N", - 'MenuText': QtCore.QT_TRANSLATE_NOOP("Draft_Downgrade", "Downgrade"), - 'ToolTip': QtCore.QT_TRANSLATE_NOOP("Draft_Downgrade", "Explodes the selected objects into simpler objects, or subtract faces")} - - def Activated(self): - Modifier.Activated(self,"Downgrade") - if self.ui: - if not Draft.getSelection(): - self.ui.selectUi() - msg(translate("draft", "Select an object to upgrade\n")) - self.call = self.view.addEventCallback("SoEvent",selectObject) - else: - self.proceed() - - - def proceed(self): - self.sel = Draft.getSelection() - edges = [] - faces = [] - for ob in self.sel: - for f in ob.Shape.Faces: - faces.append(f) - for ob in self.sel: - for e in ob.Shape.Edges: - edges.append(e) - lastob = ob - # applying transformation - self.doc.openTransaction("Downgrade") - if (len(self.sel) == 1) and (Draft.getType(self.sel[0]) == "Block"): - # a block, we explode it - pl = self.sel[0].Placement - newob = [] - for ob in self.sel[0].Components: - ob.ViewObject.Visibility = True - ob.Placement = ob.Placement.multiply(pl) - newob.append(ob) - self.doc.removeObject(self.sel[0].Name) - elif (len(self.sel) == 1) and (self.sel[0].isDerivedFrom("Part::Feature")) and ("Base" in self.sel[0].PropertiesList): - # special case, we have one parametric object: we "de-parametrize" it - msg(translate("draft", "Found 1 parametric object: breaking its dependencies\n")) - Draft.shapify(self.sel[0]) - elif len(self.sel) == 2: - # we have only 2 objects: cut 2nd from 1st - msg(translate("draft", "Found 2 objects: subtracting them\n")) - newob = Draft.cut(self.sel[0],self.sel[1]) - elif (len(faces) > 1): - if len(self.sel) == 1: - # one object with several faces: split it - for f in faces: - msg(translate("draft", "Found several faces: splitting them\n")) - newob = self.doc.addObject("Part::Feature","Face") - newob.Shape = f - Draft.formatObject(newob,self.sel[0]) - self.doc.removeObject(ob.Name) - else: - # several objects: remove all the faces from the first one - msg(translate("draft", "Found several objects: subtracting them from the first one\n")) - u = faces.pop(0) - for f in faces: - u = u.cut(f) - newob = self.doc.addObject("Part::Feature","Subtraction") - newob.Shape = u - for ob in self.sel: - Draft.formatObject(newob,ob) - self.doc.removeObject(ob.Name) - elif (len(faces) > 0): - # only one face: we extract its wires - msg(translate("draft", "Found 1 face: extracting its wires\n")) - for w in faces[0].Wires: - newob = self.doc.addObject("Part::Feature","Wire") - newob.Shape = w - Draft.formatObject(newob,lastob) - for ob in self.sel: - self.doc.removeObject(ob.Name) - else: - # no faces: split wire into single edges - msg(translate("draft", "Found only wires: extracting their edges\n")) - for ob in self.sel: - for e in edges: - newob = self.doc.addObject("Part::Feature","Edge") - newob.Shape = e - Draft.formatObject(newob,ob) - self.doc.removeObject(ob.Name) - self.doc.commitTransaction() - Draft.select(newob) - Modifier.finish(self) - - -class Trimex(Modifier): - ''' The Draft_Trimex FreeCAD command definition. - This tool trims or extends lines, wires and arcs, - or extrudes single faces. SHIFT constrains to the last point - or extrudes in direction to the face normal.''' - - def GetResources(self): - return {'Pixmap' : 'Draft_Trimex', - 'Accel' : "T, R", - 'MenuText' : QtCore.QT_TRANSLATE_NOOP("Draft_Trimex", "Trimex"), - 'ToolTip' : QtCore.QT_TRANSLATE_NOOP("Draft_Trimex", "Trims or extends the selected object, or extrudes single faces. CTRL snaps, SHIFT constrains to current segment or to normal, ALT inverts")} - - def Activated(self): - Modifier.Activated(self,"Trimex") - self.edges = [] - self.placement = None + def GetResources(self): + return {'Pixmap' : 'Draft_Move', + 'Accel' : "M, V", + 'MenuText': QtCore.QT_TRANSLATE_NOOP("Draft_Move", "Move"), + 'ToolTip': QtCore.QT_TRANSLATE_NOOP("Draft_Move", "Moves the selected objects between 2 points. CTRL to snap, SHIFT to constrain, ALT to copy")} + + def Activated(self): + Modifier.Activated(self,"Move") + if self.ui: + if not Draft.getSelection(): self.ghost = None self.linetrack = None self.constraintrack = None - if self.ui: - if not Draft.getSelection(): - self.ui.selectUi() - msg(translate("draft", "Select an object to trim/extend\n")) - self.call = self.view.addEventCallback("SoEvent",selectObject) - else: - self.proceed() + self.ui.selectUi() + msg(translate("draft", "Select an object to move\n")) + self.call = self.view.addEventCallback("SoEvent",selectObject) + else: + self.proceed() - def proceed(self): - if self.call: self.view.removeEventCallback("SoEvent",self.call) - self.obj = Draft.getSelection()[0] - self.ui.radiusUi() - self.ui.labelRadius.setText("Distance") - self.ui.radiusValue.setFocus() - self.ui.radiusValue.selectAll() - self.linetrack = lineTracker() - self.constraintrack = lineTracker(dotted=True) - if not "Shape" in self.obj.PropertiesList: return - if "Placement" in self.obj.PropertiesList: - self.placement = self.obj.Placement - if len(self.obj.Shape.Faces) == 1: - # simple extrude mode, the object itself is extruded - self.extrudeMode = True - self.ghost = [ghostTracker([self.obj])] - self.normal = self.obj.Shape.Faces[0].normalAt(.5,.5) - for v in self.obj.Shape.Vertexes: - self.ghost.append(lineTracker()) - elif len(self.obj.Shape.Faces) > 1: - # face extrude mode, a new object is created - ss = FreeCADGui.Selection.getSelectionEx()[0] - if len(ss.SubObjects) == 1: - if ss.SubObjects[0].ShapeType == "Face": - self.obj = self.doc.addObject("Part::Feature","Face") - self.obj.Shape = ss.SubObjects[0] - self.extrudeMode = True - self.ghost = [ghostTracker([self.obj])] - self.normal = self.obj.Shape.Faces[0].normalAt(.5,.5) - for v in self.obj.Shape.Vertexes: - self.ghost.append(lineTracker()) + def proceed(self): + if self.call: self.view.removeEventCallback("SoEvent",self.call) + self.sel = Draft.getSelection() + self.sel = Draft.getGroupContents(self.sel) + self.ui.pointUi() + self.ui.modUi() + self.ui.xValue.setFocus() + self.ui.xValue.selectAll() + self.linetrack = lineTracker() + self.constraintrack = lineTracker(dotted=True) + self.ghost = ghostTracker(self.sel) + self.call = self.view.addEventCallback("SoEvent",self.action) + msg(translate("draft", "Pick start point:\n")) + self.ui.cross(True) + + def finish(self,closed=False,cont=False): + if self.ui: + self.ghost.finalize() + self.linetrack.finalize() + self.constraintrack.finalize() + Modifier.finish(self) + if cont and self.ui: + if self.ui.continueMode: + FreeCADGui.Selection.clearSelection() + self.Activated() + + def move(self,delta,copy=False): + "moving the real shapes" + if copy: + self.commit(translate("draft","Copy"),partial(Draft.move,self.sel,delta,copy)) + else: + self.commit(translate("draft","Move"),partial(Draft.move,self.sel,delta,copy)) + self.doc.recompute() + + def action(self,arg): + "scene event handler" + if arg["Type"] == "SoKeyboardEvent": + if arg["Key"] == "ESCAPE": + self.finish() + elif arg["Type"] == "SoLocation2Event": #mouse movement detection + point,ctrlPoint = getPoint(self,arg) + self.linetrack.p2(point) + self.ui.cross(True) + # Draw constraint tracker line. + if hasMod(arg,MODCONSTRAIN): + self.constraintrack.p1(point) + self.constraintrack.p2(ctrlPoint) + self.constraintrack.on() + else: self.constraintrack.off() + if (len(self.node) > 0): + last = self.node[len(self.node)-1] + delta = point.sub(last) + self.ghost.trans.translation.setValue([delta.x,delta.y,delta.z]) + if self.extendedCopy: + if not hasMod(arg,MODALT): self.finish() + elif arg["Type"] == "SoMouseButtonEvent": + if (arg["State"] == "DOWN") and (arg["Button"] == "BUTTON1"): + point,ctrlPoint = getPoint(self,arg) + if (self.node == []): + self.node.append(point) + self.ui.isRelative.show() + self.linetrack.on() + self.ghost.on() + self.linetrack.p1(point) + msg(translate("draft", "Pick end point:\n")) + self.planetrack.set(point) else: - # normal wire trimex mode - self.obj.ViewObject.Visibility = False - self.extrudeMode = False - if self.obj.Shape.Wires: - self.edges = self.obj.Shape.Wires[0].Edges - self.edges = fcgeo.sortEdges(self.edges) - else: - self.edges = self.obj.Shape.Edges - self.ghost = [] - lc = self.obj.ViewObject.LineColor - sc = (lc[0],lc[1],lc[2]) - sw = self.obj.ViewObject.LineWidth - for e in self.edges: - if isinstance(e.Curve,Part.Line): - self.ghost.append(lineTracker(scolor=sc,swidth=sw)) - else: - self.ghost.append(arcTracker(scolor=sc,swidth=sw)) - if not self.ghost: self.finish() - for g in self.ghost: g.on() - self.activePoint = 0 - self.nodes = [] - self.shift = False - self.alt = False - self.force = None - self.cv = None - self.call = self.view.addEventCallback("SoEvent",self.action) - msg(translate("draft", "Pick distance:\n")) - self.ui.cross(True) + last = self.node[0] + if self.ui.isCopy.isChecked() or hasMod(arg,MODALT): + self.move(point.sub(last),True) + else: + self.move(point.sub(last)) + if hasMod(arg,MODALT): + self.extendedCopy = True + else: + self.finish(cont=True) + + def numericInput(self,numx,numy,numz): + "this function gets called by the toolbar when valid x, y, and z have been entered there" + point = Vector(numx,numy,numz) + if not self.node: + self.node.append(point) + self.ui.isRelative.show() + self.ui.isCopy.show() + self.linetrack.p1(point) + self.linetrack.on() + self.ghost.on() + msg(translate("draft", "Pick end point:\n")) + else: + last = self.node[-1] + if self.ui.isCopy.isChecked(): + self.move(point.sub(last),True) + else: + self.move(point.sub(last)) + self.finish() + + +class ApplyStyle(Modifier): + "The Draft_ApplyStyle FreeCA command definition" + + def GetResources(self): + return {'Pixmap' : 'Draft_Apply', + 'MenuText': QtCore.QT_TRANSLATE_NOOP("Draft_ApplyStyle", "Apply Current Style"), + 'ToolTip' : QtCore.QT_TRANSLATE_NOOP("Draft_ApplyStyle", "Applies current line width and color to selected objects")} + + def IsActive(self): + if Draft.getSelection(): + return True + else: + return False + + def Activated(self): + Modifier.Activated(self) + if self.ui: + self.sel = Draft.getSelection() + if (len(self.sel)>0): + for ob in self.sel: + if (ob.Type == "App::DocumentObjectGroup"): + self.formatGroup(ob) + else: + self.commit(translate("draft","Change Style"),partial(Draft.formatObject,ob)) + + def formatGroup(self,grpob): + for ob in grpob.Group: + if (ob.Type == "App::DocumentObjectGroup"): + self.formatGroup(ob) + else: + self.commit(translate("draft","Change Style"),partial(Draft.formatObject,ob)) + + +class Rotate(Modifier): + "The Draft_Rotate FreeCAD command definition" + + def GetResources(self): + return {'Pixmap' : 'Draft_Rotate', + 'Accel' : "R, O", + 'MenuText': QtCore.QT_TRANSLATE_NOOP("Draft_Rotate", "Rotate"), + 'ToolTip': QtCore.QT_TRANSLATE_NOOP("Draft_Rotate", "Rotates the selected objects. CTRL to snap, SHIFT to constrain, ALT creates a copy")} + + def Activated(self): + Modifier.Activated(self,"Rotate") + if self.ui: + if not Draft.getSelection(): + self.ghost = None + self.linetrack = None + self.arctrack = None + self.constraintrack = None + self.ui.selectUi() + msg(translate("draft", "Select an object to rotate\n")) + self.call = self.view.addEventCallback("SoEvent",selectObject) + else: + self.proceed() + + def proceed(self): + if self.call: self.view.removeEventCallback("SoEvent",self.call) + self.sel = Draft.getSelection() + self.sel = Draft.getGroupContents(self.sel) + self.step = 0 + self.center = None + self.ui.arcUi() + self.ui.isCopy.show() + self.ui.setTitle("Rotate") + self.linetrack = lineTracker() + self.constraintrack = lineTracker(dotted=True) + self.arctrack = arcTracker() + self.ghost = ghostTracker(self.sel) + self.call = self.view.addEventCallback("SoEvent",self.action) + msg(translate("draft", "Pick rotation center:\n")) + self.ui.cross(True) - def action(self,arg): - "scene event handler" - if arg["Type"] == "SoKeyboardEvent" and arg["Key"] == "ESCAPE": - self.finish() - if (arg["Type"] == "SoLocation2Event"): #mouse movement detection - self.ui.cross(True) - self.shift = hasMod(arg,MODCONSTRAIN) - self.alt = hasMod(arg,MODALT) - wp = not(self.extrudeMode and self.shift) - self.point = getPoint(self,arg,workingplane=wp)[0] - if hasMod(arg,MODSNAP): self.snapped = None - else: self.snapped = self.view.getObjectInfo((arg["Position"][0],arg["Position"][1])) - if self.extrudeMode: - dist = self.extrude(self.shift) - else: - dist = self.redraw(self.point,self.snapped,self.shift,self.alt) - self.constraintrack.p1(self.point) - self.constraintrack.p2(self.newpoint) - self.constraintrack.on() - self.ui.radiusValue.setText("%.2f" % dist) - self.ui.radiusValue.setFocus() - self.ui.radiusValue.selectAll() - - if (arg["Type"] == "SoMouseButtonEvent"): - if (arg["State"] == "DOWN") and (arg["Button"] == "BUTTON1"): - cursor = arg["Position"] - self.shift = hasMod(arg,MODCONSTRAIN) - self.alt = hasMod(arg,MODALT) - if hasMod(arg,MODSNAP): self.snapped = None - else: self.snapped = self.view.getObjectInfo((cursor[0],cursor[1])) - self.trimObject() - self.finish() + def finish(self,closed=False,cont=False): + "finishes the arc" + Modifier.finish(self) + if self.ui: + self.linetrack.finalize() + self.constraintrack.finalize() + self.arctrack.finalize() + self.ghost.finalize() + self.doc.recompute() + if cont and self.ui: + if self.ui.continueMode: + FreeCADGui.Selection.clearSelection() + self.Activated() - def extrude(self,shift=False,real=False): - "redraws the ghost in extrude mode" - self.newpoint = self.obj.Shape.Faces[0].CenterOfMass - dvec = self.point.sub(self.newpoint) - if shift: delta = fcvec.project(dvec,self.normal) - else: delta = dvec - if self.force: - ratio = self.force/delta.Length - delta.multiply(ratio) - if real: return delta - self.ghost[0].trans.translation.setValue([delta.x,delta.y,delta.z]) - for i in range(1,len(self.ghost)): - base = self.obj.Shape.Vertexes[i-1].Point - self.ghost[i].p1(base) - self.ghost[i].p2(base.add(delta)) - return delta.Length - - def redraw(self,point,snapped=None,shift=False,alt=False,real=None): - "redraws the ghost" - #initializing - reverse = False - for g in self.ghost: g.off() - if real: newedges = [] - - # finding the active point - vlist = [] - for e in self.edges: vlist.append(e.Vertexes[0].Point) - vlist.append(self.edges[-1].Vertexes[-1].Point) - if shift: npoint = self.activePoint - else: npoint = fcgeo.findClosest(point,vlist) - if npoint > len(self.edges)/2: reverse = True - if alt: reverse = not reverse - self.activePoint = npoint - - # sorting out directions - if reverse and (npoint > 0): npoint = npoint-1 - if (npoint > len(self.edges)-1): - edge = self.edges[-1] - ghost = self.ghost[-1] - else: - edge = self.edges[npoint] - ghost = self.ghost[npoint] - if reverse: - v1 = edge.Vertexes[-1].Point - v2 = edge.Vertexes[0].Point - else: - v1 = edge.Vertexes[0].Point - v2 = edge.Vertexes[-1].Point - - # snapping - if snapped: - snapped = self.doc.getObject(snapped['Object']) - pts = [] - for e in snapped.Shape.Edges: - int = fcgeo.findIntersection(edge,e,True,True) - if int: pts.extend(int) - if pts: - point = pts[fcgeo.findClosest(point,pts)] + def rot (self,angle,copy=False): + "rotating the real shapes" + if copy: + self.commit(translate("draft","Copy"), + partial(Draft.rotate,self.sel, + math.degrees(angle),self.center,plane.axis,copy)) + else: + self.commit(translate("draft","Rotate"), + partial(Draft.rotate,self.sel, + math.degrees(angle),self.center,plane.axis,copy)) - # modifying active edge - if isinstance(edge.Curve,Part.Line): - perp = fcgeo.vec(edge).cross(Vector(0,0,1)) - chord = v1.sub(point) - proj = fcvec.project(chord,perp) - self.newpoint = Vector.add(point,proj) - dist = v1.sub(self.newpoint).Length - ghost.p1(self.newpoint) - ghost.p2(v2) - self.ui.labelRadius.setText("Distance") - if real: - if self.force: - ray = self.newpoint.sub(v1) - ray = fcvec.scale(ray,self.force/ray.Length) - self.newpoint = Vector.add(v1,ray) - newedges.append(Part.Line(self.newpoint,v2).toShape()) - else: - center = edge.Curve.Center - rad = edge.Curve.Radius - ang1 = fcvec.angle(v2.sub(center)) - ang2 = fcvec.angle(point.sub(center)) - self.newpoint=Vector.add(center,fcvec.rotate(Vector(rad,0,0),-ang2)) - self.ui.labelRadius.setText("Angle") - dist = math.degrees(-ang2) - # if ang1 > ang2: ang1,ang2 = ang2,ang1 - print "last calculated:",math.degrees(-ang1),math.degrees(-ang2) - ghost.setEndAngle(-ang2) - ghost.setStartAngle(-ang1) - ghost.setCenter(center) - ghost.setRadius(rad) - if real: - if self.force: - angle = math.radians(self.force) - newray = fcvec.rotate(Vector(rad,0,0),-angle) - self.newpoint = Vector.add(center,newray) - chord = self.newpoint.sub(v2) - perp = chord.cross(Vector(0,0,1)) - scaledperp = fcvec.scaleTo(perp,rad) - midpoint = Vector.add(center,scaledperp) - newedges.append(Part.Arc(self.newpoint,midpoint,v2).toShape()) - ghost.on() - - # resetting the visible edges - if not reverse: list = range(npoint+1,len(self.edges)) - else: list = range(npoint-1,-1,-1) - for i in list: - edge = self.edges[i] - ghost = self.ghost[i] - if isinstance(edge.Curve,Part.Line): - ghost.p1(edge.Vertexes[0].Point) - ghost.p2(edge.Vertexes[-1].Point) - else: - ang1 = fcvec.angle(edge.Vertexes[0].Point.sub(center)) - ang2 = fcvec.angle(edge.Vertexes[-1].Point.sub(center)) - #if ang1 > ang2: ang1,ang2 = ang2,ang1 - ghost.setEndAngle(-ang2) - ghost.setStartAngle(-ang1) - ghost.setCenter(edge.Curve.Center) - ghost.setRadius(edge.Curve.Radius) - if real: newedges.append(edge) - ghost.on() - - # finishing - if real: return newedges - else: return dist - - def trimObject(self): - "trims the actual object" - if self.extrudeMode: - delta = self.extrude(self.shift,real=True) - print "delta",delta - self.doc.openTransaction("Extrude") - obj = Draft.extrude(self.obj,delta) - self.doc.commitTransaction() - self.obj = obj - else: - edges = self.redraw(self.point,self.snapped,self.shift,self.alt,real=True) - newshape = Part.Wire(edges) - self.doc.openTransaction("Trim/extend") - if Draft.getType(self.obj) in ["Wire","BSpline"]: - p = [] - if self.placement: invpl = self.placement.inverse() - for v in newshape.Vertexes: - np = v.Point - if self.placement: np = invpl.multVec(np) - p.append(np) - self.obj.Points = p - elif Draft.getType(self.obj) == "Circle": - angles = self.ghost[0].getAngles() - print "original",self.obj.FirstAngle," ",self.obj.LastAngle - print "new",angles - if angles[0] > angles[1]: angles = (angles[1],angles[0]) - self.obj.FirstAngle = angles[0] - self.obj.LastAngle = angles[1] - else: - self.obj.Shape = newshape - self.doc.commitTransaction() - for g in self.ghost: g.off() - - def finish(self,closed=False): - Modifier.finish(self) - self.force = None - if self.ui: - self.ui.labelRadius.setText("Distance") - self.linetrack.finalize() - self.constraintrack.finalize() - if self.ghost: - for g in self.ghost: - g.finalize() - self.obj.ViewObject.Visibility = True - Draft.select(self.obj) - - def numericRadius(self,dist): - "this function gets called by the toolbar when valid distance have been entered there" - self.force = dist - self.trimObject() - self.finish() - -class Scale(Modifier): - '''The Draft_Scale FreeCAD command definition. - This tool scales the selected objects from a base point.''' - - def GetResources(self): - return {'Pixmap' : 'Draft_Scale', - 'Accel' : "S, C", - 'MenuText': QtCore.QT_TRANSLATE_NOOP("Draft_Scale", "Scale"), - 'ToolTip': QtCore.QT_TRANSLATE_NOOP("Draft_Scale", "Scales the selected objects from a base point. CTRL to snap, SHIFT to constrain, ALT to copy")} - - def Activated(self): - Modifier.Activated(self,"Scale") - if self.ui: - if not Draft.getSelection(): - self.ghost = None - self.linetrack = None - self.constraintrack = None - self.ui.selectUi() - msg(translate("draft", "Select an object to scale\n")) - self.call = self.view.addEventCallback("SoEvent",selectObject) - else: - self.proceed() - - def proceed(self): - if self.call: self.view.removeEventCallback("SoEvent",self.call) - self.sel = Draft.getSelection() - self.sel = Draft.getGroupContents(self.sel) - self.ui.pointUi() - self.ui.modUi() - self.ui.xValue.setFocus() - self.ui.xValue.selectAll() - self.linetrack = lineTracker() - self.constraintrack = lineTracker(dotted=True) - self.ghost = ghostTracker(self.sel) - self.call = self.view.addEventCallback("SoEvent",self.action) - msg(translate("draft", "Pick base point:\n")) - self.ui.cross(True) - - def finish(self,closed=False,cont=False): - Modifier.finish(self) - if self.ui: - self.ghost.finalize() - self.linetrack.finalize() - self.constraintrack.finalize() - if cont and self.ui: - if self.ui.continueMode: - FreeCADGui.Selection.clearSelection() - self.Activated() - - def scale(self,delta,copy=False): - "moving the real shapes" - if copy: - self.commit(translate("draft","Copy"),partial(Draft.scale,self.sel,delta,self.node[0],copy)) - else: - self.commit(translate("draft","Scale"),partial(Draft.scale,self.sel,delta,self.node[0],copy)) - - def action(self,arg): - "scene event handler" - if arg["Type"] == "SoKeyboardEvent" and arg["Key"] == "ESCAPE": - self.finish() - if (arg["Type"] == "SoLocation2Event"): #mouse movement detection - point,ctrlPoint = getPoint(self,arg,sym=True) - self.linetrack.p2(point) - self.ui.cross(True) - # Draw constraint tracker line. - if hasMod(arg,MODCONSTRAIN): - self.constraintrack.p1(point) - self.constraintrack.p2(ctrlPoint) - self.constraintrack.on() - else: self.constraintrack.off() - if (len(self.node) > 0): - last = self.node[len(self.node)-1] - delta = point.sub(last) - self.ghost.trans.scaleFactor.setValue([delta.x,delta.y,delta.z]) - corr = Vector(self.node[0].x,self.node[0].y,self.node[0].z) - corr.scale(delta.x,delta.y,delta.z) - corr = fcvec.neg(corr.sub(self.node[0])) - self.ghost.trans.translation.setValue([corr.x,corr.y,corr.z]) - if self.extendedCopy: - if not hasMod(arg,MODALT): self.finish() - if (arg["Type"] == "SoMouseButtonEvent"): - if (arg["State"] == "DOWN") and (arg["Button"] == "BUTTON1"): - point,ctrlPoint = getPoint(self,arg,sym=True) - if (self.node == []): - self.node.append(point) - self.ui.isRelative.show() - self.ui.isCopy.show() - self.linetrack.on() - self.ghost.on() - self.linetrack.p1(point) - msg(translate("draft", "Pick scale factor:\n")) - else: - last = self.node[0] - if self.ui.isCopy.isChecked() or hasMod(arg,MODALT): - self.scale(point.sub(last),True) - else: - self.scale(point.sub(last)) - if hasMod(arg,MODALT): - self.extendedCopy = True - else: - self.finish(cont=True) - - def numericInput(self,numx,numy,numz): - "this function gets called by the toolbar when valid x, y, and z have been entered there" - point = Vector(numx,numy,numz) - if not self.node: - self.node.append(point) - self.ui.isRelative.show() - self.ui.isCopy.show() - self.linetrack.p1(point) - self.linetrack.on() - self.ghost.on() - msg(translate("draft", "Pick scale factor:\n")) - else: - last = self.node[-1] - if self.ui.isCopy.isChecked(): - self.scale(point.sub(last),True) - else: - self.scale(point.sub(last)) - self.finish(cont=True) - -class ToggleConstructionMode(): - "The Draft_ToggleConstructionMode FreeCAD command definition" - - def GetResources(self): - return {'MenuText': QtCore.QT_TRANSLATE_NOOP("Draft_ToggleConstructionMode", "Toggle construcion Mode"), - 'Accel' : "C, M", - 'ToolTip': QtCore.QT_TRANSLATE_NOOP("Draft_ToggleConstructionMode", "Toggles the Construction Mode for next objects.")} - - def Activated(self): - FreeCADGui.draftToolBar.constrButton.toggle() - -class ToggleContinueMode(): - "The Draft_ToggleContinueMode FreeCAD command definition" - - def GetResources(self): - return {'MenuText': QtCore.QT_TRANSLATE_NOOP("Draft_ToggleContinueMode", "Toggle continue Mode"), - 'ToolTip': QtCore.QT_TRANSLATE_NOOP("Draft_ToggleContinueMode", "Toggles the Continue Mode for next commands.")} - - def Activated(self): - FreeCADGui.draftToolBar.continueCmd.toggle() + def action(self,arg): + "scene event handler" + if arg["Type"] == "SoKeyboardEvent": + if arg["Key"] == "ESCAPE": + self.finish() + elif arg["Type"] == "SoLocation2Event": + point,ctrlPoint = getPoint(self,arg) + self.ui.cross(True) + # this is to make sure radius is what you see on screen + if self.center and fcvec.dist(point,self.center): + viewdelta = fcvec.project(point.sub(self.center), plane.axis) + if not fcvec.isNull(viewdelta): + point = point.add(fcvec.neg(viewdelta)) + if self.extendedCopy: + if not hasMod(arg,MODALT): + self.step = 3 + self.finish() + if (self.step == 0): + pass + elif (self.step == 1): + currentrad = fcvec.dist(point,self.center) + if (currentrad != 0): + angle = fcvec.angle(plane.u, point.sub(self.center), plane.axis) + else: angle = 0 + self.linetrack.p2(point) + # Draw constraint tracker line. + if hasMod(arg,MODCONSTRAIN): + self.constraintrack.p1(point) + self.constraintrack.p2(ctrlPoint) + self.constraintrack.on() + else: + self.constraintrack.off() + self.ui.radiusValue.setText("%.2f" % math.degrees(angle)) + self.firstangle = angle + self.ui.radiusValue.setFocus() + self.ui.radiusValue.selectAll() + elif (self.step == 2): + currentrad = fcvec.dist(point,self.center) + if (currentrad != 0): + angle = fcvec.angle(plane.u, point.sub(self.center), plane.axis) + else: angle = 0 + if (angle < self.firstangle): + sweep = (2*math.pi-self.firstangle)+angle + else: + sweep = angle - self.firstangle + self.arctrack.setApertureAngle(sweep) + self.ghost.trans.rotation.setValue(coin.SbVec3f(fcvec.tup(plane.axis)),sweep) + self.linetrack.p2(point) + # Draw constraint tracker line. + if hasMod(arg,MODCONSTRAIN): + self.constraintrack.p1(point) + self.constraintrack.p2(ctrlPoint) + self.constraintrack.on() + else: + self.constraintrack.off() + self.ui.radiusValue.setText("%.2f" % math.degrees(sweep)) + self.ui.radiusValue.setFocus() + self.ui.radiusValue.selectAll() + elif arg["Type"] == "SoMouseButtonEvent": + if (arg["State"] == "DOWN") and (arg["Button"] == "BUTTON1"): + point,ctrlPoint = getPoint(self,arg) + if self.center and fcvec.dist(point,self.center): + viewdelta = fcvec.project(point.sub(self.center), plane.axis) + if not fcvec.isNull(viewdelta): point = point.add(fcvec.neg(viewdelta)) + if (self.step == 0): + self.center = point + self.node = [point] + self.ui.radiusUi() + self.ui.hasFill.hide() + self.ui.labelRadius.setText("Base angle") + self.linetrack.p1(self.center) + self.arctrack.setCenter(self.center) + self.ghost.trans.center.setValue(self.center.x,self.center.y,self.center.z) + self.linetrack.on() + self.step = 1 + msg(translate("draft", "Pick base angle:\n")) + self.planetrack.set(point) + elif (self.step == 1): + self.ui.labelRadius.setText("Rotation") + self.rad = fcvec.dist(point,self.center) + self.arctrack.on() + self.arctrack.setStartPoint(point) + self.ghost.on() + self.step = 2 + msg(translate("draft", "Pick rotation angle:\n")) + else: + currentrad = fcvec.dist(point,self.center) + angle = point.sub(self.center).getAngle(plane.u) + if fcvec.project(point.sub(self.center), plane.v).getAngle(plane.v) > 1: + angle = -angle + if (angle < self.firstangle): + sweep = (2*math.pi-self.firstangle)+angle + else: + sweep = angle - self.firstangle + if self.ui.isCopy.isChecked() or hasMod(arg,MODALT): + self.rot(sweep,True) + else: + self.rot(sweep) + if hasMod(arg,MODALT): + self.extendedCopy = True + else: + self.finish(cont=True) + + def numericInput(self,numx,numy,numz): + "this function gets called by the toolbar when valid x, y, and z have been entered there" + self.center = Vector(numx,numy,numz) + self.node = [self.center] + self.arctrack.setCenter(self.center) + self.ghost.trans.center.setValue(self.center.x,self.center.y,self.center.z) + self.linetrack.p1(self.center) + # self.arctrack.on() + self.linetrack.on() + self.ui.radiusUi() + self.ui.hasFill.hide() + self.ui.labelRadius.setText("Base angle") + self.step = 1 + msg(translate("draft", "Pick base angle:\n")) + + def numericRadius(self,rad): + "this function gets called by the toolbar when valid radius have been entered there" + if (self.step == 1): + self.ui.labelRadius.setText("Rotation") + self.firstangle = math.radians(rad) + self.arctrack.setStartAngle(self.firstangle) + self.arctrack.on() + self.ghost.on() + self.step = 2 + msg(translate("draft", "Pick rotation angle:\n")) + else: + self.rot(math.radians(rad),self.ui.isCopy.isChecked()) + self.finish(cont=True) + + +class Offset(Modifier): + "The Draft_Offset FreeCAD command definition" + + def GetResources(self): + return {'Pixmap' : 'Draft_Offset', + 'Accel' : "O, S", + 'MenuText': QtCore.QT_TRANSLATE_NOOP("Draft_Offset", "Offset"), + 'ToolTip': QtCore.QT_TRANSLATE_NOOP("Draft_Offset", "Offsets the active object. CTRL to snap, SHIFT to constrain, ALT to copy")} + + def Activated(self): + self.running = False + Modifier.Activated(self,"Offset") + if self.ui: + if not Draft.getSelection(): + self.ghost = None + self.linetrack = None + self.arctrack = None + self.constraintrack = None + self.ui.selectUi() + msg(translate("draft", "Select an object to offset\n")) + self.call = self.view.addEventCallback("SoEvent",selectObject) + elif len(Draft.getSelection()) > 1: + msg(translate("draft", "Offset only works on one object at a time\n"),"warning") + else: + self.proceed() + + def proceed(self): + if self.call: self.view.removeEventCallback("SoEvent",self.call) + self.sel = Draft.getSelection()[0] + if not self.sel.isDerivedFrom("Part::Feature"): + msg(translate("draft", "Cannot offset this object type\n"),"warning") + self.finish() + else: + self.step = 0 + self.dvec = None + self.constrainSeg = None + self.ui.offsetUi() + self.linetrack = lineTracker() + self.constraintrack = lineTracker(dotted=True) + self.faces = False + self.shape = self.sel.Shape + self.mode = None + if Draft.getType(self.sel) in ["Circle","Arc"]: + self.ghost = arcTracker() + self.mode = "Circle" + self.center = self.shape.Edges[0].Curve.Center + self.ghost.setCenter(self.center) + self.ghost.setStartAngle(math.radians(self.sel.FirstAngle)) + self.ghost.setEndAngle(math.radians(self.sel.LastAngle)) + else: + self.ghost = wireTracker(self.shape) + self.mode = "Wire" + self.call = self.view.addEventCallback("SoEvent",self.action) + msg(translate("draft", "Pick distance:\n")) + self.ui.cross(True) + self.planetrack.set(self.shape.Vertexes[0].Point) + self.running = True + + def action(self,arg): + "scene event handler" + if arg["Type"] == "SoKeyboardEvent": + if arg["Key"] == "ESCAPE": + self.finish() + elif arg["Type"] == "SoLocation2Event": + self.ui.cross(True) + point,ctrlPoint = getPoint(self,arg) + if hasMod(arg,MODCONSTRAIN) and self.constrainSeg: + dist = fcgeo.findPerpendicular(point,self.shape,self.constrainSeg[1]) + e = self.shape.Edges[self.constrainSeg[1]] + self.constraintrack.p1(e.Vertexes[0].Point) + self.constraintrack.p2(point.add(dist[0])) + self.constraintrack.on() + else: + dist = fcgeo.findPerpendicular(point,self.shape.Edges) + self.constraintrack.off() + if dist: + self.ghost.on() + if self.mode == "Wire": + d = fcvec.neg(dist[0]) + v1 = fcgeo.getTangent(self.shape.Edges[0],point) + v2 = fcgeo.getTangent(self.shape.Edges[dist[1]],point) + a = -fcvec.angle(v1,v2) + self.dvec = fcvec.rotate(d,a,plane.axis) + self.ghost.update(fcgeo.offsetWire(self.shape,self.dvec,occ=self.ui.occOffset.isChecked())) + elif self.mode == "Circle": + self.dvec = point.sub(self.center).Length + self.ghost.setRadius(self.dvec) + self.constrainSeg = dist + self.linetrack.on() + self.linetrack.p1(point) + self.linetrack.p2(point.add(dist[0])) + self.ui.radiusValue.setText("%.2f" % dist[0].Length) + else: + self.dvec = None + self.ghost.off() + self.constrainSeg = None + self.linetrack.off() + self.ui.radiusValue.setText("off") + self.ui.radiusValue.setFocus() + self.ui.radiusValue.selectAll() + if self.extendedCopy: + if not hasMod(arg,MODALT): self.finish() + + elif arg["Type"] == "SoMouseButtonEvent": + if (arg["State"] == "DOWN") and (arg["Button"] == "BUTTON1"): + copymode = False + occmode = self.ui.occOffset.isChecked() + if hasMod(arg,MODALT) or self.ui.isCopy.isChecked(): copymode = True + if self.dvec: + self.commit(translate("draft","Offset"), + partial(Draft.offset,self.sel, + self.dvec,copymode,occ=occmode)) + if hasMod(arg,MODALT): + self.extendedCopy = True + else: + self.finish() + + def finish(self,closed=False): + Modifier.finish(self) + if self.ui and self.running: + self.linetrack.finalize() + self.constraintrack.finalize() + self.ghost.finalize() + + def numericRadius(self,rad): + '''this function gets called by the toolbar when + valid radius have been entered there''' + if self.dvec: + self.dvec.normalize() + self.dvec.multiply(rad) + copymode = False + occmode = self.ui.occOffset.isChecked() + if self.ui.isCopy.isChecked(): copymode = True + self.commit(translate("draft","Offset"), + partial(Draft.offset,self.sel, + self.dvec,copymode,occ=occmode)) + self.finish() + + +class Upgrade(Modifier): + '''The Draft_Upgrade FreeCAD command definition. + This class upgrades selected objects in different ways, + following this list (in order): + - if there are more than one faces, the faces are merged (union) + - if there is only one face, nothing is done + - if there are closed wires, they are transformed in a face + - otherwise join all edges into a wire (closed if applicable) + - if nothing of the above is possible, a Compound is created + ''' + + def GetResources(self): + return {'Pixmap' : 'Draft_Upgrade', + 'Accel' : "U, P", + 'MenuText': QtCore.QT_TRANSLATE_NOOP("Draft_Upgrade", "Upgrade"), + 'ToolTip': QtCore.QT_TRANSLATE_NOOP("Draft_Upgrade", "Joins the selected objects into one, or converts closed wires to filled faces, or unite faces")} + + def Activated(self): + Modifier.Activated(self,"Upgrade") + if self.ui: + if not Draft.getSelection(): + self.ui.selectUi() + msg(translate("draft", "Select an object to upgrade\n")) + self.call = self.view.addEventCallback("SoEvent",selectObject) + else: + self.proceed() + + def compound(self): + # shapeslist = [] + # for ob in self.sel: shapeslist.append(ob.Shape) + # newob = self.doc.addObject("Part::Feature","Compound") + # newob.Shape = Part.makeCompound(shapeslist) + newob = Draft.makeBlock(self.sel) + self.nodelete = True + return newob + + def proceed(self): + if self.call: self.view.removeEventCallback("SoEvent",self.call) + self.sel = Draft.getSelection() + newob = None + self.nodelete = False + edges = [] + wires = [] + openwires = [] + faces = [] + groups = [] + curves = [] + facewires = [] + + # determining what we have in our selection + for ob in self.sel: + if ob.Type == "App::DocumentObjectGroup": + groups.append(ob) + else: + if ob.Shape.ShapeType == 'Edge': openwires.append(ob.Shape) + for f in ob.Shape.Faces: + faces.append(f) + facewires.extend(f.Wires) + for w in ob.Shape.Wires: + if w.isClosed(): + wires.append(w) + else: + openwires.append(w) + for e in ob.Shape.Edges: + if not isinstance(e.Curve,Part.Line): + curves.append(e) + lastob = ob + # print "objects:",self.sel," edges:",edges," wires:",wires," openwires:",openwires," faces:",faces + # print "groups:",groups," curves:",curves," facewires:",facewires + + # applying transformation + self.doc.openTransaction("Upgrade") + + if groups: + # if we have a group: turn each closed wire inside into a face + msg(translate("draft", "Found groups: closing each open object inside\n")) + for grp in groups: + for ob in grp.Group: + if not ob.Shape.Faces: + for w in ob.Shape.Wires: + newob = Draft.makeWire(w,closed=w.isClosed()) + self.sel.append(ob) + grp.addObject(newob) + + elif faces and (len(wires)+len(openwires)==len(facewires)): + # we have only faces here, no lone edges + + if (len(self.sel) == 1) and (len(faces) > 1): + # we have a shell: we try to make a solid + sol = Part.makeSolid(self.sel[0].Shape) + if sol.isClosed(): + msg(translate("draft", "Found 1 solidificable object: solidifying it\n")) + newob = self.doc.addObject("Part::Feature","Solid") + newob.Shape = sol + Draft.formatObject(newob,lastob) + + elif (len(self.sel) == 2) and (not curves): + # we have exactly 2 objects: we fuse them + msg(translate("draft", "Found 2 objects: fusing them\n")) + newob = Draft.fuse(self.sel[0],self.sel[1]) + self.nodelete = True + + elif (len(self.sel) > 2) and (len(faces) > 10): + # we have many separate faces: we try to make a shell + sh = Part.makeShell(faces) + newob = self.doc.addObject("Part::Feature","Shell") + newob.Shape = sh + Draft.formatObject(newob,lastob) + + elif (len(self.sel) > 2) or (len(faces) > 1): + # more than 2 objects or faces: we try the draft way: make one face out of them + u = faces.pop(0) + for f in faces: + u = u.fuse(f) + if fcgeo.isCoplanar(faces): + if self.sel[0].ViewObject.DisplayMode == "Wireframe": + f = False + else: + f = True + u = fcgeo.concatenate(u) + if not curves: + msg(translate("draft", "Found several objects or faces: making a parametric face\n")) + newob = Draft.makeWire(u.Wires[0],closed=True,face=f) + Draft.formatObject(newob,lastob) + else: + # if not possible, we do a non-parametric union + msg(translate("draft", "Found objects containing curves: fusing them\n")) + newob = self.doc.addObject("Part::Feature","Union") + newob.Shape = u + Draft.formatObject(newob,lastob) + else: + # if not possible, we do a non-parametric union + msg(translate("draft", "Found several objects: fusing them\n")) + # if we have a solid, make sure we really return a solid + if (len(u.Faces) > 1) and u.isClosed(): + u = Part.makeSolid(u) + newob = self.doc.addObject("Part::Feature","Union") + newob.Shape = u + Draft.formatObject(newob,lastob) + elif len(self.sel) == 1: + # only one object: if not parametric, we "draftify" it + self.nodelete = True + if (not curves) and (Draft.getType(self.sel[0]) == "Part"): + msg(translate("draft", "Found 1 non-parametric objects: draftifying it\n")) + Draft.draftify(self.sel[0]) + + elif wires and (not faces) and (not openwires): + # we have only wires, no faces + + if (len(self.sel) == 1) and self.sel[0].isDerivedFrom("Sketcher::SketchObject") and (not curves): + # we have a sketch + msg(translate("draft", "Found 1 closed sketch object: making a face from it\n")) + newob = Draft.makeWire(self.sel[0].Shape,closed=True) + newob.Base = self.sel[0] + self.sel[0].ViewObject.Visibility = False + self.nodelete = True + + else: + # only closed wires + for w in wires: + f = Part.Face(w) + faces.append(f) + for f in faces: + if not curves: + newob = Draft.makeWire(f.Wire,closed=True) + else: + # if there are curved segments, we do a non-parametric face + msg(translate("draft", "Found closed wires: making faces\n")) + newob = self.doc.addObject("Part::Feature","Face") + newob.Shape = f + Draft.formatObject(newob,lastob) + + elif (len(openwires) == 1) and (not faces) and (not wires): + # special case, we have only one open wire. We close it!" + p0 = openwires[0].Vertexes[0].Point + p1 = openwires[0].Vertexes[-1].Point + edges = openwires[0].Edges + edges.append(Part.Line(p1,p0).toShape()) + w = Part.Wire(fcgeo.sortEdges(edges)) + msg(translate("draft", "Found 1 open wire: closing it\n")) + if not curves: + newob = Draft.makeWire(w,closed=True) + else: + # if not possible, we do a non-parametric union + newob = self.doc.addObject("Part::Feature","Wire") + newob.Shape = w + Draft.formatObject(newob,lastob) + + elif openwires and (not wires) and (not faces): + # only open wires and edges: we try to join their edges + for ob in self.sel: + for e in ob.Shape.Edges: + edges.append(e) + newob = None + nedges = fcgeo.sortEdges(edges[:]) + # for e in nedges: print "debug: ",e.Curve,e.Vertexes[0].Point,e.Vertexes[-1].Point + w = Part.Wire(nedges) + if len(w.Edges) == len(edges): + msg(translate("draft", "Found several edges: wiring them\n")) + if not curves: + newob = Draft.makeWire(w) + else: + newob = self.doc.addObject("Part::Feature","Wire") + newob.Shape = w + Draft.formatObject(newob,lastob) + if not newob: + print "no new object found" + msg(translate("draft", "Found several non-connected edges: making compound\n")) + newob = self.compound() + Draft.formatObject(newob,lastob) + else: + # all other cases + msg(translate("draft", "Found several non-treatable objects: making compound\n")) + newob = self.compound() + Draft.formatObject(newob,lastob) + + if not self.nodelete: + # deleting original objects, if needed + for ob in self.sel: + if not ob.Type == "App::DocumentObjectGroup": + self.doc.removeObject(ob.Name) + + self.doc.commitTransaction() + if newob: Draft.select(newob) + Modifier.finish(self) + + +class Downgrade(Modifier): + ''' + The Draft_Downgrade FreeCAD command definition. + This class downgrades selected objects in different ways, + following this list (in order): + - if there are more than one faces, the subsequent + faces are subtracted from the first one + - if there is only one face, it gets converted to a wire + - otherwise wires are exploded into single edges + ''' + + def GetResources(self): + return {'Pixmap' : 'Draft_Downgrade', + 'Accel' : "D, N", + 'MenuText': QtCore.QT_TRANSLATE_NOOP("Draft_Downgrade", "Downgrade"), + 'ToolTip': QtCore.QT_TRANSLATE_NOOP("Draft_Downgrade", "Explodes the selected objects into simpler objects, or subtract faces")} + + def Activated(self): + Modifier.Activated(self,"Downgrade") + if self.ui: + if not Draft.getSelection(): + self.ui.selectUi() + msg(translate("draft", "Select an object to upgrade\n")) + self.call = self.view.addEventCallback("SoEvent",selectObject) + else: + self.proceed() + + def proceed(self): + self.sel = Draft.getSelection() + edges = [] + faces = [] + + # scanning objects + for ob in self.sel: + for f in ob.Shape.Faces: + faces.append(f) + for ob in self.sel: + for e in ob.Shape.Edges: + edges.append(e) + lastob = ob + + # applying transformation + self.doc.openTransaction("Downgrade") + + if (len(self.sel) == 1) and (Draft.getType(self.sel[0]) == "Block"): + # a block, we explode it + pl = self.sel[0].Placement + newob = [] + for ob in self.sel[0].Components: + ob.ViewObject.Visibility = True + ob.Placement = ob.Placement.multiply(pl) + newob.append(ob) + self.doc.removeObject(self.sel[0].Name) + + elif (len(self.sel) == 1) and (self.sel[0].isDerivedFrom("Part::Feature")) and ("Base" in self.sel[0].PropertiesList): + # special case, we have one parametric object: we "de-parametrize" it + msg(translate("draft", "Found 1 parametric object: breaking its dependencies\n")) + newob = Draft.shapify(self.sel[0]) + + elif len(self.sel) == 2: + # we have only 2 objects: cut 2nd from 1st + msg(translate("draft", "Found 2 objects: subtracting them\n")) + newob = Draft.cut(self.sel[0],self.sel[1]) + + elif (len(faces) > 1): + + if len(self.sel) == 1: + # one object with several faces: split it + for f in faces: + msg(translate("draft", "Found several faces: splitting them\n")) + newob = self.doc.addObject("Part::Feature","Face") + newob.Shape = f + Draft.formatObject(newob,self.sel[0]) + self.doc.removeObject(ob.Name) + + else: + # several objects: remove all the faces from the first one + msg(translate("draft", "Found several objects: subtracting them from the first one\n")) + u = faces.pop(0) + for f in faces: + u = u.cut(f) + newob = self.doc.addObject("Part::Feature","Subtraction") + newob.Shape = u + for ob in self.sel: + Draft.formatObject(newob,ob) + self.doc.removeObject(ob.Name) + + elif (len(faces) > 0): + # only one face: we extract its wires + msg(translate("draft", "Found 1 face: extracting its wires\n")) + for w in faces[0].Wires: + newob = self.doc.addObject("Part::Feature","Wire") + newob.Shape = w + Draft.formatObject(newob,lastob) + for ob in self.sel: + self.doc.removeObject(ob.Name) + + else: + # no faces: split wire into single edges + msg(translate("draft", "Found only wires: extracting their edges\n")) + for ob in self.sel: + for e in edges: + newob = self.doc.addObject("Part::Feature","Edge") + newob.Shape = e + Draft.formatObject(newob,ob) + self.doc.removeObject(ob.Name) + self.doc.commitTransaction() + Draft.select(newob) + Modifier.finish(self) + + +class Trimex(Modifier): + ''' The Draft_Trimex FreeCAD command definition. + This tool trims or extends lines, wires and arcs, + or extrudes single faces. SHIFT constrains to the last point + or extrudes in direction to the face normal.''' + + def GetResources(self): + return {'Pixmap' : 'Draft_Trimex', + 'Accel' : "T, R", + 'MenuText' : QtCore.QT_TRANSLATE_NOOP("Draft_Trimex", "Trimex"), + 'ToolTip' : QtCore.QT_TRANSLATE_NOOP("Draft_Trimex", "Trims or extends the selected object, or extrudes single faces. CTRL snaps, SHIFT constrains to current segment or to normal, ALT inverts")} + + def Activated(self): + Modifier.Activated(self,"Trimex") + self.edges = [] + self.placement = None + self.ghost = None + self.linetrack = None + self.constraintrack = None + if self.ui: + if not Draft.getSelection(): + self.ui.selectUi() + msg(translate("draft", "Select an object to trim/extend\n")) + self.call = self.view.addEventCallback("SoEvent",selectObject) + else: + self.proceed() + + def proceed(self): + if self.call: self.view.removeEventCallback("SoEvent",self.call) + self.obj = Draft.getSelection()[0] + self.ui.radiusUi() + self.ui.labelRadius.setText("Distance") + self.ui.radiusValue.setFocus() + self.ui.radiusValue.selectAll() + self.linetrack = lineTracker() + self.constraintrack = lineTracker(dotted=True) + if not "Shape" in self.obj.PropertiesList: return + if "Placement" in self.obj.PropertiesList: + self.placement = self.obj.Placement + if len(self.obj.Shape.Faces) == 1: + # simple extrude mode, the object itself is extruded + self.extrudeMode = True + self.ghost = [ghostTracker([self.obj])] + self.normal = self.obj.Shape.Faces[0].normalAt(.5,.5) + for v in self.obj.Shape.Vertexes: + self.ghost.append(lineTracker()) + elif len(self.obj.Shape.Faces) > 1: + # face extrude mode, a new object is created + ss = FreeCADGui.Selection.getSelectionEx()[0] + if len(ss.SubObjects) == 1: + if ss.SubObjects[0].ShapeType == "Face": + self.obj = self.doc.addObject("Part::Feature","Face") + self.obj.Shape = ss.SubObjects[0] + self.extrudeMode = True + self.ghost = [ghostTracker([self.obj])] + self.normal = self.obj.Shape.Faces[0].normalAt(.5,.5) + for v in self.obj.Shape.Vertexes: + self.ghost.append(lineTracker()) + else: + # normal wire trimex mode + self.obj.ViewObject.Visibility = False + self.extrudeMode = False + if self.obj.Shape.Wires: + self.edges = self.obj.Shape.Wires[0].Edges + self.edges = fcgeo.sortEdges(self.edges) + else: + self.edges = self.obj.Shape.Edges + self.ghost = [] + lc = self.obj.ViewObject.LineColor + sc = (lc[0],lc[1],lc[2]) + sw = self.obj.ViewObject.LineWidth + for e in self.edges: + if isinstance(e.Curve,Part.Line): + self.ghost.append(lineTracker(scolor=sc,swidth=sw)) + else: + self.ghost.append(arcTracker(scolor=sc,swidth=sw)) + if not self.ghost: self.finish() + for g in self.ghost: g.on() + self.activePoint = 0 + self.nodes = [] + self.shift = False + self.alt = False + self.force = None + self.cv = None + self.call = self.view.addEventCallback("SoEvent",self.action) + msg(translate("draft", "Pick distance:\n")) + self.ui.cross(True) + + def action(self,arg): + "scene event handler" + if arg["Type"] == "SoKeyboardEvent": + if arg["Key"] == "ESCAPE": + self.finish() + elif arg["Type"] == "SoLocation2Event": #mouse movement detection + self.ui.cross(True) + self.shift = hasMod(arg,MODCONSTRAIN) + self.alt = hasMod(arg,MODALT) + wp = not(self.extrudeMode and self.shift) + self.point = getPoint(self,arg,workingplane=wp)[0] + if hasMod(arg,MODSNAP): self.snapped = None + else: self.snapped = self.view.getObjectInfo((arg["Position"][0],arg["Position"][1])) + if self.extrudeMode: + dist = self.extrude(self.shift) + else: + dist = self.redraw(self.point,self.snapped,self.shift,self.alt) + self.constraintrack.p1(self.point) + self.constraintrack.p2(self.newpoint) + self.constraintrack.on() + self.ui.radiusValue.setText("%.2f" % dist) + self.ui.radiusValue.setFocus() + self.ui.radiusValue.selectAll() + + elif arg["Type"] == "SoMouseButtonEvent": + if (arg["State"] == "DOWN") and (arg["Button"] == "BUTTON1"): + cursor = arg["Position"] + self.shift = hasMod(arg,MODCONSTRAIN) + self.alt = hasMod(arg,MODALT) + if hasMod(arg,MODSNAP): self.snapped = None + else: self.snapped = self.view.getObjectInfo((cursor[0],cursor[1])) + self.trimObject() + self.finish() + + def extrude(self,shift=False,real=False): + "redraws the ghost in extrude mode" + self.newpoint = self.obj.Shape.Faces[0].CenterOfMass + dvec = self.point.sub(self.newpoint) + if shift: delta = fcvec.project(dvec,self.normal) + else: delta = dvec + if self.force: + ratio = self.force/delta.Length + delta.multiply(ratio) + if real: return delta + self.ghost[0].trans.translation.setValue([delta.x,delta.y,delta.z]) + for i in range(1,len(self.ghost)): + base = self.obj.Shape.Vertexes[i-1].Point + self.ghost[i].p1(base) + self.ghost[i].p2(base.add(delta)) + return delta.Length + + def redraw(self,point,snapped=None,shift=False,alt=False,real=None): + "redraws the ghost" + + # initializing + reverse = False + for g in self.ghost: g.off() + if real: newedges = [] + + # finding the active point + vlist = [] + for e in self.edges: vlist.append(e.Vertexes[0].Point) + vlist.append(self.edges[-1].Vertexes[-1].Point) + if shift: npoint = self.activePoint + else: npoint = fcgeo.findClosest(point,vlist) + if npoint > len(self.edges)/2: reverse = True + if alt: reverse = not reverse + self.activePoint = npoint + + # sorting out directions + if reverse and (npoint > 0): npoint = npoint-1 + if (npoint > len(self.edges)-1): + edge = self.edges[-1] + ghost = self.ghost[-1] + else: + edge = self.edges[npoint] + ghost = self.ghost[npoint] + if reverse: + v1 = edge.Vertexes[-1].Point + v2 = edge.Vertexes[0].Point + else: + v1 = edge.Vertexes[0].Point + v2 = edge.Vertexes[-1].Point + + # snapping + if snapped: + snapped = self.doc.getObject(snapped['Object']) + pts = [] + for e in snapped.Shape.Edges: + int = fcgeo.findIntersection(edge,e,True,True) + if int: pts.extend(int) + if pts: + point = pts[fcgeo.findClosest(point,pts)] + + # modifying active edge + if isinstance(edge.Curve,Part.Line): + perp = fcgeo.vec(edge).cross(Vector(0,0,1)) + chord = v1.sub(point) + proj = fcvec.project(chord,perp) + self.newpoint = Vector.add(point,proj) + dist = v1.sub(self.newpoint).Length + ghost.p1(self.newpoint) + ghost.p2(v2) + self.ui.labelRadius.setText("Distance") + if real: + if self.force: + ray = self.newpoint.sub(v1) + ray = fcvec.scale(ray,self.force/ray.Length) + self.newpoint = Vector.add(v1,ray) + newedges.append(Part.Line(self.newpoint,v2).toShape()) + else: + center = edge.Curve.Center + rad = edge.Curve.Radius + ang1 = fcvec.angle(v2.sub(center)) + ang2 = fcvec.angle(point.sub(center)) + self.newpoint=Vector.add(center,fcvec.rotate(Vector(rad,0,0),-ang2)) + self.ui.labelRadius.setText("Angle") + dist = math.degrees(-ang2) + # if ang1 > ang2: ang1,ang2 = ang2,ang1 + print "last calculated:",math.degrees(-ang1),math.degrees(-ang2) + ghost.setEndAngle(-ang2) + ghost.setStartAngle(-ang1) + ghost.setCenter(center) + ghost.setRadius(rad) + if real: + if self.force: + angle = math.radians(self.force) + newray = fcvec.rotate(Vector(rad,0,0),-angle) + self.newpoint = Vector.add(center,newray) + chord = self.newpoint.sub(v2) + perp = chord.cross(Vector(0,0,1)) + scaledperp = fcvec.scaleTo(perp,rad) + midpoint = Vector.add(center,scaledperp) + newedges.append(Part.Arc(self.newpoint,midpoint,v2).toShape()) + ghost.on() + + # resetting the visible edges + if not reverse: list = range(npoint+1,len(self.edges)) + else: list = range(npoint-1,-1,-1) + for i in list: + edge = self.edges[i] + ghost = self.ghost[i] + if isinstance(edge.Curve,Part.Line): + ghost.p1(edge.Vertexes[0].Point) + ghost.p2(edge.Vertexes[-1].Point) + else: + ang1 = fcvec.angle(edge.Vertexes[0].Point.sub(center)) + ang2 = fcvec.angle(edge.Vertexes[-1].Point.sub(center)) + # if ang1 > ang2: ang1,ang2 = ang2,ang1 + ghost.setEndAngle(-ang2) + ghost.setStartAngle(-ang1) + ghost.setCenter(edge.Curve.Center) + ghost.setRadius(edge.Curve.Radius) + if real: newedges.append(edge) + ghost.on() + + # finishing + if real: return newedges + else: return dist + + def trimObject(self): + "trims the actual object" + if self.extrudeMode: + delta = self.extrude(self.shift,real=True) + print "delta",delta + self.doc.openTransaction("Extrude") + obj = Draft.extrude(self.obj,delta) + self.doc.commitTransaction() + self.obj = obj + else: + edges = self.redraw(self.point,self.snapped,self.shift,self.alt,real=True) + newshape = Part.Wire(edges) + self.doc.openTransaction("Trim/extend") + if Draft.getType(self.obj) in ["Wire","BSpline"]: + p = [] + if self.placement: invpl = self.placement.inverse() + for v in newshape.Vertexes: + np = v.Point + if self.placement: np = invpl.multVec(np) + p.append(np) + self.obj.Points = p + elif Draft.getType(self.obj) == "Circle": + angles = self.ghost[0].getAngles() + print "original",self.obj.FirstAngle," ",self.obj.LastAngle + print "new",angles + if angles[0] > angles[1]: angles = (angles[1],angles[0]) + self.obj.FirstAngle = angles[0] + self.obj.LastAngle = angles[1] + else: + self.obj.Shape = newshape + self.doc.commitTransaction() + for g in self.ghost: g.off() + + def finish(self,closed=False): + Modifier.finish(self) + self.force = None + if self.ui: + self.ui.labelRadius.setText("Distance") + self.linetrack.finalize() + self.constraintrack.finalize() + if self.ghost: + for g in self.ghost: + g.finalize() + self.obj.ViewObject.Visibility = True + Draft.select(self.obj) + + def numericRadius(self,dist): + "this function gets called by the toolbar when valid distance have been entered there" + self.force = dist + self.trimObject() + self.finish() + + +class Scale(Modifier): + '''The Draft_Scale FreeCAD command definition. + This tool scales the selected objects from a base point.''' + + def GetResources(self): + return {'Pixmap' : 'Draft_Scale', + 'Accel' : "S, C", + 'MenuText': QtCore.QT_TRANSLATE_NOOP("Draft_Scale", "Scale"), + 'ToolTip': QtCore.QT_TRANSLATE_NOOP("Draft_Scale", "Scales the selected objects from a base point. CTRL to snap, SHIFT to constrain, ALT to copy")} + + def Activated(self): + Modifier.Activated(self,"Scale") + if self.ui: + if not Draft.getSelection(): + self.ghost = None + self.linetrack = None + self.constraintrack = None + self.ui.selectUi() + msg(translate("draft", "Select an object to scale\n")) + self.call = self.view.addEventCallback("SoEvent",selectObject) + else: + self.proceed() + + def proceed(self): + if self.call: self.view.removeEventCallback("SoEvent",self.call) + self.sel = Draft.getSelection() + self.sel = Draft.getGroupContents(self.sel) + self.ui.pointUi() + self.ui.modUi() + self.ui.xValue.setFocus() + self.ui.xValue.selectAll() + self.linetrack = lineTracker() + self.constraintrack = lineTracker(dotted=True) + self.ghost = ghostTracker(self.sel) + self.call = self.view.addEventCallback("SoEvent",self.action) + msg(translate("draft", "Pick base point:\n")) + self.ui.cross(True) + + def finish(self,closed=False,cont=False): + Modifier.finish(self) + if self.ui: + self.ghost.finalize() + self.linetrack.finalize() + self.constraintrack.finalize() + if cont and self.ui: + if self.ui.continueMode: + FreeCADGui.Selection.clearSelection() + self.Activated() + + def scale(self,delta,copy=False): + "moving the real shapes" + if copy: + self.commit(translate("draft","Copy"), + partial(Draft.scale,self.sel,delta,self.node[0],copy)) + else: + self.commit(translate("draft","Scale"), + partial(Draft.scale,self.sel,delta,self.node[0],copy)) + + def action(self,arg): + "scene event handler" + if arg["Type"] == "SoKeyboardEvent": + if arg["Key"] == "ESCAPE": + self.finish() + elif arg["Type"] == "SoLocation2Event": #mouse movement detection + point,ctrlPoint = getPoint(self,arg,sym=True) + self.linetrack.p2(point) + self.ui.cross(True) + # Draw constraint tracker line. + if hasMod(arg,MODCONSTRAIN): + self.constraintrack.p1(point) + self.constraintrack.p2(ctrlPoint) + self.constraintrack.on() + else: self.constraintrack.off() + if (len(self.node) > 0): + last = self.node[len(self.node)-1] + delta = point.sub(last) + self.ghost.trans.scaleFactor.setValue([delta.x,delta.y,delta.z]) + corr = Vector(self.node[0].x,self.node[0].y,self.node[0].z) + corr.scale(delta.x,delta.y,delta.z) + corr = fcvec.neg(corr.sub(self.node[0])) + self.ghost.trans.translation.setValue([corr.x,corr.y,corr.z]) + if self.extendedCopy: + if not hasMod(arg,MODALT): self.finish() + elif arg["Type"] == "SoMouseButtonEvent": + if (arg["State"] == "DOWN") and (arg["Button"] == "BUTTON1"): + point,ctrlPoint = getPoint(self,arg,sym=True) + if (self.node == []): + self.node.append(point) + self.ui.isRelative.show() + self.ui.isCopy.show() + self.linetrack.on() + self.ghost.on() + self.linetrack.p1(point) + msg(translate("draft", "Pick scale factor:\n")) + else: + last = self.node[0] + if self.ui.isCopy.isChecked() or hasMod(arg,MODALT): + self.scale(point.sub(last),True) + else: + self.scale(point.sub(last)) + if hasMod(arg,MODALT): + self.extendedCopy = True + else: + self.finish(cont=True) + + def numericInput(self,numx,numy,numz): + "this function gets called by the toolbar when valid x, y, and z have been entered there" + point = Vector(numx,numy,numz) + if not self.node: + self.node.append(point) + self.ui.isRelative.show() + self.ui.isCopy.show() + self.linetrack.p1(point) + self.linetrack.on() + self.ghost.on() + msg(translate("draft", "Pick scale factor:\n")) + else: + last = self.node[-1] + if self.ui.isCopy.isChecked(): + self.scale(point.sub(last),True) + else: + self.scale(point.sub(last)) + self.finish(cont=True) + + +class ToggleConstructionMode(): + "The Draft_ToggleConstructionMode FreeCAD command definition" + + def GetResources(self): + return {'MenuText': QtCore.QT_TRANSLATE_NOOP("Draft_ToggleConstructionMode", "Toggle construcion Mode"), + 'Accel' : "C, M", + 'ToolTip': QtCore.QT_TRANSLATE_NOOP("Draft_ToggleConstructionMode", "Toggles the Construction Mode for next objects.")} + + def Activated(self): + FreeCADGui.draftToolBar.constrButton.toggle() + + +class ToggleContinueMode(): + "The Draft_ToggleContinueMode FreeCAD command definition" + + def GetResources(self): + return {'MenuText': QtCore.QT_TRANSLATE_NOOP("Draft_ToggleContinueMode", "Toggle continue Mode"), + 'ToolTip': QtCore.QT_TRANSLATE_NOOP("Draft_ToggleContinueMode", "Toggles the Continue Mode for next commands.")} + + def Activated(self): + FreeCADGui.draftToolBar.continueCmd.toggle() + + class Drawing(Modifier): - "The Draft Drawing command definition" + "The Draft Drawing command definition" + + def GetResources(self): + return {'Pixmap' : 'Draft_Drawing', + 'Accel' : "D, D", + 'MenuText': QtCore.QT_TRANSLATE_NOOP("Draft_Drawing", "Drawing"), + 'ToolTip': QtCore.QT_TRANSLATE_NOOP("Draft_Drawing", "Puts the selected objects on a Drawing sheet.")} - def GetResources(self): - return {'Pixmap' : 'Draft_Drawing', - 'Accel' : "D, D", - 'MenuText': QtCore.QT_TRANSLATE_NOOP("Draft_Drawing", "Drawing"), - 'ToolTip': QtCore.QT_TRANSLATE_NOOP("Draft_Drawing", "Puts the selected objects on a Drawing sheet.")} + def IsActive(self): + if Draft.getSelection(): + return True + else: + return False - def IsActive(self): - if Draft.getSelection(): - return True - else: - return False + def Activated(self): + Modifier.Activated(self,"Drawing") + sel = Draft.getSelection() + if not sel: + self.page = self.createDefaultPage() + else: + self.page = None + for obj in sel: + if obj.isDerivedFrom("Drawing::FeaturePage"): + self.page = obj + sel.pop(sel.index(obj)) + if not self.page: + for obj in self.doc.Objects: + if obj.isDerivedFrom("Drawing::FeaturePage"): + self.page = obj + if not self.page: + self.page = self.createDefaultPage() + sel.reverse() + for obj in sel: + self.insertPattern(obj) + if obj.ViewObject.isVisible(): + name = 'View'+obj.Name + oldobj = self.page.getObject(name) + if oldobj: self.doc.removeObject(oldobj.Name) + Draft.makeDrawingView(obj,self.page) + self.doc.recompute() - def Activated(self): - Modifier.Activated(self,"Drawing") - sel = Draft.getSelection() - if not sel: - self.page = self.createDefaultPage() - else: - self.page = None - for obj in sel: - if obj.isDerivedFrom("Drawing::FeaturePage"): - self.page = obj - sel.pop(sel.index(obj)) - if not self.page: - for obj in self.doc.Objects: - if obj.isDerivedFrom("Drawing::FeaturePage"): - self.page = obj - if not self.page: - self.page = self.createDefaultPage() - sel.reverse() - for obj in sel: - self.insertPattern(obj) - if obj.ViewObject.isVisible(): - name = 'View'+obj.Name - oldobj = self.page.getObject(name) - if oldobj: self.doc.removeObject(oldobj.Name) - Draft.makeDrawingView(obj,self.page) - self.doc.recompute() + def insertPattern(self,obj): + "inserts a pattern object on the page" + if 'FillStyle' in obj.ViewObject.PropertiesList: + if obj.ViewObject.FillStyle != 'shape color': + hatch = obj.ViewObject.FillStyle + vobj = self.page.getObject('Pattern'+hatch) + if not vobj: + if hatch in FreeCAD.svgpatterns: + view = self.doc.addObject('Drawing::FeatureView','Pattern'+hatch) + svg = FreeCAD.svgpatterns[hatch] + view.ViewResult = svg + view.X = 0 + view.Y = 0 + view.Scale = 1 + self.page.addObject(view) - def insertPattern(self,obj): - if 'FillStyle' in obj.ViewObject.PropertiesList: - if obj.ViewObject.FillStyle != 'shape color': - hatch = obj.ViewObject.FillStyle - vobj = self.page.getObject('Pattern'+hatch) - if not vobj: - if hatch in FreeCAD.svgpatterns: - view = self.doc.addObject('Drawing::FeatureView','Pattern'+hatch) - svg = FreeCAD.svgpatterns[hatch] - view.ViewResult = svg - view.X = 0 - view.Y = 0 - view.Scale = 1 - self.page.addObject(view) + def createDefaultPage(self): + "created a default page" + template = Draft.getParam("template") + if not template: + template = FreeCAD.getResourceDir()+'Mod/Drawing/Templates/A3_Landscape.svg' + page = self.doc.addObject('Drawing::FeaturePage','Page') + page.ViewObject.HintOffsetX = 200 + page.ViewObject.HintOffsetY = 100 + page.ViewObject.HintScale = 20 + page.Template = template + self.doc.recompute() + return page - def createDefaultPage(self): - template = Draft.getParam("template") - if not template: - template = FreeCAD.getResourceDir()+'Mod/Drawing/Templates/A3_Landscape.svg' - page = self.doc.addObject('Drawing::FeaturePage','Page') - page.ViewObject.HintOffsetX = 200 - page.ViewObject.HintOffsetY = 100 - page.ViewObject.HintScale = 20 - page.Template = template - self.doc.recompute() - return page - + class ToggleDisplayMode(): - "The ToggleDisplayMode FreeCAD command definition" + "The ToggleDisplayMode FreeCAD command definition" - def GetResources(self): - return {'Pixmap' : 'Draft_SwitchMode', - 'Accel' : "Shift+Space", - 'MenuText': QtCore.QT_TRANSLATE_NOOP("Draft_ToggleDisplayMode", "Toggle display mode"), - 'ToolTip' : QtCore.QT_TRANSLATE_NOOP("Draft_ToggleDisplayMode", "Swaps display mode of selected objects between wireframe and flatlines")} + def GetResources(self): + return {'Pixmap' : 'Draft_SwitchMode', + 'Accel' : "Shift+Space", + 'MenuText': QtCore.QT_TRANSLATE_NOOP("Draft_ToggleDisplayMode", "Toggle display mode"), + 'ToolTip' : QtCore.QT_TRANSLATE_NOOP("Draft_ToggleDisplayMode", "Swaps display mode of selected objects between wireframe and flatlines")} - def IsActive(self): - if Draft.getSelection(): - return True - else: - return False + def IsActive(self): + if Draft.getSelection(): + return True + else: + return False - def Activated(self): - for obj in Draft.getSelection(): - if obj.ViewObject.DisplayMode == "Flat Lines": - if "Wireframe" in obj.ViewObject.listDisplayModes(): - obj.ViewObject.DisplayMode = "Wireframe" - elif obj.ViewObject.DisplayMode == "Wireframe": - if "Flat Lines" in obj.ViewObject.listDisplayModes(): - obj.ViewObject.DisplayMode = "Flat Lines" + def Activated(self): + for obj in Draft.getSelection(): + if obj.ViewObject.DisplayMode == "Flat Lines": + if "Wireframe" in obj.ViewObject.listDisplayModes(): + obj.ViewObject.DisplayMode = "Wireframe" + elif obj.ViewObject.DisplayMode == "Wireframe": + if "Flat Lines" in obj.ViewObject.listDisplayModes(): + obj.ViewObject.DisplayMode = "Flat Lines" class Edit(Modifier): - "The Draft_Edit FreeCAD command definition" + "The Draft_Edit FreeCAD command definition" - def __init__(self): - self.running = False + def __init__(self): + self.running = False - def GetResources(self): - return {'Pixmap' : 'Draft_Edit', - 'MenuText': QtCore.QT_TRANSLATE_NOOP("Draft_Edit", "Edit"), - 'ToolTip': QtCore.QT_TRANSLATE_NOOP("Draft_Edit", "Edits the active object")} + def GetResources(self): + return {'Pixmap' : 'Draft_Edit', + 'MenuText': QtCore.QT_TRANSLATE_NOOP("Draft_Edit", "Edit"), + 'ToolTip': QtCore.QT_TRANSLATE_NOOP("Draft_Edit", "Edits the active object")} - def IsActive(self): - if Draft.getSelection(): - self.selection = Draft.getSelection() - if "Proxy" in self.selection[0].PropertiesList: - if hasattr(self.selection[0].Proxy,"Type"): - return True - return False + def IsActive(self): + if Draft.getSelection(): + self.selection = Draft.getSelection() + if "Proxy" in self.selection[0].PropertiesList: + if hasattr(self.selection[0].Proxy,"Type"): + return True + return False - def Activated(self): - if self.running: + def Activated(self): + if self.running: + self.finish() + else: + Modifier.Activated(self,"Edit") + self.ui.editUi() + if self.doc: + self.obj = Draft.getSelection() + if self.obj: + self.obj = self.obj[0] + # store selectable state of the object + self.selectstate = self.obj.ViewObject.Selectable + self.obj.ViewObject.Selectable = False + if not Draft.getType(self.obj) in ["Wire","BSpline"]: + self.ui.addButton.setEnabled(False) + self.ui.delButton.setEnabled(False) + else: + self.ui.addButton.setEnabled(True) + self.ui.delButton.setEnabled(True) + # self.ui.addButton.setChecked(False) + # self.ui.delButton.setChecked(False) + self.editing = None + self.editpoints = [] + self.pl = None + if "Placement" in self.obj.PropertiesList: + self.pl = self.obj.Placement + self.invpl = self.pl.inverse() + if Draft.getType(self.obj) in ["Wire","BSpline"]: + for p in self.obj.Points: + if self.pl: p = self.pl.multVec(p) + self.editpoints.append(p) + elif Draft.getType(self.obj) == "Circle": + self.editpoints.append(self.obj.Placement.Base) + if self.obj.FirstAngle == self.obj.LastAngle: + self.editpoints.append(self.obj.Shape.Vertexes[0].Point) + elif Draft.getType(self.obj) == "Rectangle": + self.editpoints.append(self.obj.Placement.Base) + self.editpoints.append(self.obj.Shape.Vertexes[2].Point) + v = self.obj.Shape.Vertexes + self.bx = v[1].Point.sub(v[0].Point) + if self.obj.Length < 0: self.bx = fcvec.neg(self.bx) + self.by = v[2].Point.sub(v[1].Point) + if self.obj.Height < 0: self.by = fcvec.neg(self.by) + elif Draft.getType(self.obj) == "Polygon": + self.editpoints.append(self.obj.Placement.Base) + self.editpoints.append(self.obj.Shape.Vertexes[0].Point) + elif Draft.getType(self.obj) == "Dimension": + p = self.obj.ViewObject.Proxy.textpos.translation.getValue() + self.editpoints.append(self.obj.Start) + self.editpoints.append(self.obj.End) + self.editpoints.append(self.obj.Dimline) + self.editpoints.append(Vector(p[0],p[1],p[2])) + self.trackers = [] + self.constraintrack = None + if self.editpoints: + for ep in range(len(self.editpoints)): + self.trackers.append(editTracker(self.editpoints[ep],self.obj.Name, + ep,self.obj.ViewObject.LineColor)) + self.constraintrack = lineTracker(dotted=True) + self.call = self.view.addEventCallback("SoEvent",self.action) + self.running = True + plane.save() + if "Shape" in self.obj.PropertiesList: + plane.alignToFace(self.obj.Shape) + self.planetrack.set(self.editpoints[0]) + else: + msg(translate("draft", "This object type is not editable\n"),'warning') self.finish() else: - Modifier.Activated(self,"Edit") - self.ui.editUi() - if self.doc: - self.obj = Draft.getSelection() - if self.obj: - self.obj = self.obj[0] - # store selectable state of the object - self.selectstate = self.obj.ViewObject.Selectable - self.obj.ViewObject.Selectable = False - if not Draft.getType(self.obj) in ["Wire","BSpline"]: - self.ui.addButton.setEnabled(False) - self.ui.delButton.setEnabled(False) - else: - self.ui.addButton.setEnabled(True) - self.ui.delButton.setEnabled(True) - #self.ui.addButton.setChecked(False) - #self.ui.delButton.setChecked(False) - self.editing = None - self.editpoints = [] - self.pl = None - if "Placement" in self.obj.PropertiesList: - self.pl = self.obj.Placement - self.invpl = self.pl.inverse() - if Draft.getType(self.obj) in ["Wire","BSpline"]: - for p in self.obj.Points: - if self.pl: p = self.pl.multVec(p) - self.editpoints.append(p) - elif Draft.getType(self.obj) == "Circle": - self.editpoints.append(self.obj.Placement.Base) - if self.obj.FirstAngle == self.obj.LastAngle: - self.editpoints.append(self.obj.Shape.Vertexes[0].Point) - elif Draft.getType(self.obj) == "Rectangle": - self.editpoints.append(self.obj.Placement.Base) - self.editpoints.append(self.obj.Shape.Vertexes[2].Point) - v = self.obj.Shape.Vertexes - self.bx = v[1].Point.sub(v[0].Point) - if self.obj.Length < 0: self.bx = fcvec.neg(self.bx) - self.by = v[2].Point.sub(v[1].Point) - if self.obj.Height < 0: self.by = fcvec.neg(self.by) - elif Draft.getType(self.obj) == "Polygon": - self.editpoints.append(self.obj.Placement.Base) - self.editpoints.append(self.obj.Shape.Vertexes[0].Point) - elif Draft.getType(self.obj) == "Dimension": - p = self.obj.ViewObject.Proxy.textpos.translation.getValue() - self.editpoints.append(self.obj.Start) - self.editpoints.append(self.obj.End) - self.editpoints.append(self.obj.Dimline) - self.editpoints.append(Vector(p[0],p[1],p[2])) - self.trackers = [] - self.constraintrack = None - if self.editpoints: - for ep in range(len(self.editpoints)): - self.trackers.append(editTracker(self.editpoints[ep],self.obj.Name, - ep,self.obj.ViewObject.LineColor)) - self.constraintrack = lineTracker(dotted=True) - self.call = self.view.addEventCallback("SoEvent",self.action) - self.running = True - plane.save() - if "Shape" in self.obj.PropertiesList: - plane.alignToFace(self.obj.Shape) - self.planetrack.set(self.editpoints[0]) - else: - msg(translate("draft", "This object type is not editable\n"),'warning') - self.finish() - else: - self.finish() + self.finish() - def finish(self,closed=False): - "terminates the operation" - if closed: - if "Closed" in self.obj.PropertiesList: - if not self.obj.Closed: - self.obj.Closed = True - if self.ui: - if self.trackers: - for t in self.trackers: - t.finalize() - if self.constraintrack: - self.constraintrack.finalize() - self.obj.ViewObject.Selectable = self.selectstate - Modifier.finish(self) - plane.restore() - self.running = False + def finish(self,closed=False): + "terminates the operation" + if closed: + if "Closed" in self.obj.PropertiesList: + if not self.obj.Closed: + self.obj.Closed = True + if self.ui: + if self.trackers: + for t in self.trackers: + t.finalize() + if self.constraintrack: + self.constraintrack.finalize() + self.obj.ViewObject.Selectable = self.selectstate + Modifier.finish(self) + plane.restore() + self.running = False - def action(self,arg): - "scene event handler" - if arg["Type"] == "SoKeyboardEvent" and arg["Key"] == "ESCAPE": - self.finish() - if (arg["Type"] == "SoLocation2Event"): #mouse movement detection - if self.editing != None: + def action(self,arg): + "scene event handler" + if arg["Type"] == "SoKeyboardEvent": + if arg["Key"] == "ESCAPE": + self.finish() + elif arg["Type"] == "SoLocation2Event": #mouse movement detection + if self.editing != None: + point,ctrlPoint = getPoint(self,arg) + # Draw constraint tracker line. + if hasMod(arg,MODCONSTRAIN): + self.constraintrack.p1(point) + self.constraintrack.p2(ctrlPoint) + self.constraintrack.on() + else: + self.constraintrack.off() + self.trackers[self.editing].set(point) + self.update(self.trackers[self.editing].get()) + elif arg["Type"] == "SoMouseButtonEvent": + if (arg["State"] == "DOWN") and (arg["Button"] == "BUTTON1"): + if self.editing == None: + snapped = self.view.getObjectInfo((arg["Position"][0],arg["Position"][1])) + if snapped: + if snapped['Object'] == self.obj.Name: + if self.ui.addButton.isChecked(): point,ctrlPoint = getPoint(self,arg) - # Draw constraint tracker line. - if hasMod(arg,MODCONSTRAIN): - self.constraintrack.p1(point) - self.constraintrack.p2(ctrlPoint) - self.constraintrack.on() - else: self.constraintrack.off() - self.trackers[self.editing].set(point) - self.update(self.trackers[self.editing].get()) - elif (arg["Type"] == "SoMouseButtonEvent"): - if (arg["State"] == "DOWN") and (arg["Button"] == "BUTTON1"): - if self.editing == None: - snapped = self.view.getObjectInfo((arg["Position"][0],arg["Position"][1])) - if snapped: - if snapped['Object'] == self.obj.Name: - if self.ui.addButton.isChecked(): - point,ctrlPoint = getPoint(self,arg) - self.pos = arg["Position"] - self.addPoint(point) - elif self.ui.delButton.isChecked(): - if 'EditNode' in snapped['Component']: - self.delPoint(int(snapped['Component'][8:])) - elif 'EditNode' in snapped['Component']: - self.ui.pointUi() - self.ui.isRelative.show() - self.editing = int(snapped['Component'][8:]) - self.trackers[self.editing].off() - self.obj.ViewObject.Selectable = False - if "Points" in self.obj.PropertiesList: - self.node.append(self.obj.Points[self.editing]) - else: - self.trackers[self.editing].on() - self.obj.ViewObject.Selectable = True - self.numericInput(self.trackers[self.editing].get()) + self.pos = arg["Position"] + self.addPoint(point) + elif self.ui.delButton.isChecked(): + if 'EditNode' in snapped['Component']: + self.delPoint(int(snapped['Component'][8:])) + elif 'EditNode' in snapped['Component']: + self.ui.pointUi() + self.ui.isRelative.show() + self.editing = int(snapped['Component'][8:]) + self.trackers[self.editing].off() + self.obj.ViewObject.Selectable = False + if "Points" in self.obj.PropertiesList: + self.node.append(self.obj.Points[self.editing]) + else: + print "finishing edit" + self.trackers[self.editing].on() + self.obj.ViewObject.Selectable = True + self.numericInput(self.trackers[self.editing].get()) - def update(self,v): - if Draft.getType(self.obj) in ["Wire","BSpline"]: - pts = self.obj.Points - editPnt = self.invpl.multVec(v) - # DNC: allows to close the curve by placing ends close to each other - tol = 0.001 - if ( ( self.editing == 0 ) and ( (editPnt - pts[-1]).Length < tol) ) or ( self.editing == len(pts) - 1 ) and ( (editPnt - pts[0]).Length < tol): - self.obj.Closed = True - # DNC: fix error message if edited point coinsides with one of the existing points - if ( editPnt in pts ) == False: - pts[self.editing] = editPnt - self.obj.Points = pts - self.trackers[self.editing].set(v) - elif Draft.getType(self.obj) == "Circle": - delta = v.sub(self.obj.Placement.Base) - if self.editing == 0: - p = self.obj.Placement - p.move(delta) - self.obj.Placement = p - self.trackers[0].set(self.obj.Placement.Base) - elif self.editing == 1: - self.obj.Radius = delta.Length - self.trackers[1].set(self.obj.Shape.Vertexes[0].Point) - elif Draft.getType(self.obj) == "Rectangle": - delta = v.sub(self.obj.Placement.Base) - if self.editing == 0: - p = self.obj.Placement - p.move(delta) - self.obj.Placement = p - elif self.editing == 1: - diag = v.sub(self.obj.Placement.Base) - nx = fcvec.project(diag,self.bx) - ny = fcvec.project(diag,self.by) - ax = nx.Length - ay = ny.Length - if ax and ay: - if abs(nx.getAngle(self.bx)) > 0.1: - ax = -ax - if abs(ny.getAngle(self.by)) > 0.1: - ay = -ay - self.obj.Length = ax - self.obj.Height = ay - self.trackers[0].set(self.obj.Placement.Base) - self.trackers[1].set(self.obj.Shape.Vertexes[2].Point) - elif Draft.getType(self.obj) == "Polygon": - delta = v.sub(self.obj.Placement.Base) - if self.editing == 0: - p = self.obj.Placement - p.move(delta) - self.obj.Placement = p - self.trackers[0].set(self.obj.Placement.Base) - elif self.editing == 1: - if self.obj.DrawMode == 'inscribed': - self.obj.Radius = delta.Length - else: - halfangle = ((math.pi*2)/self.obj.FacesNumber)/2 - rad = math.cos(halfangle)*delta.Length - self.obj.Radius = rad - self.trackers[1].set(self.obj.Shape.Vertexes[0].Point) - elif Draft.getType(self.obj) == "Dimension": - if self.editing == 0: - self.obj.Start = v - elif self.editing == 1: - self.obj.End = v - elif self.editing == 2: - self.obj.Dimline = v - elif self.editing == 3: - self.obj.ViewObject.TextPosition = v - + def update(self,v): + if Draft.getType(self.obj) in ["Wire","BSpline"]: + pts = self.obj.Points + editPnt = self.invpl.multVec(v) + # DNC: allows to close the curve by placing ends close to each other + tol = 0.001 + if ( ( self.editing == 0 ) and ( (editPnt - pts[-1]).Length < tol) ) or ( self.editing == len(pts) - 1 ) and ( (editPnt - pts[0]).Length < tol): + self.obj.Closed = True + # DNC: fix error message if edited point coinsides with one of the existing points + if ( editPnt in pts ) == False: + pts[self.editing] = editPnt + self.obj.Points = pts + self.trackers[self.editing].set(v) + elif Draft.getType(self.obj) == "Circle": + delta = v.sub(self.obj.Placement.Base) + if self.editing == 0: + p = self.obj.Placement + p.move(delta) + self.obj.Placement = p + self.trackers[0].set(self.obj.Placement.Base) + elif self.editing == 1: + self.obj.Radius = delta.Length + self.trackers[1].set(self.obj.Shape.Vertexes[0].Point) + elif Draft.getType(self.obj) == "Rectangle": + delta = v.sub(self.obj.Placement.Base) + if self.editing == 0: + p = self.obj.Placement + p.move(delta) + self.obj.Placement = p + elif self.editing == 1: + diag = v.sub(self.obj.Placement.Base) + nx = fcvec.project(diag,self.bx) + ny = fcvec.project(diag,self.by) + ax = nx.Length + ay = ny.Length + if ax and ay: + if abs(nx.getAngle(self.bx)) > 0.1: + ax = -ax + if abs(ny.getAngle(self.by)) > 0.1: + ay = -ay + self.obj.Length = ax + self.obj.Height = ay + self.trackers[0].set(self.obj.Placement.Base) + self.trackers[1].set(self.obj.Shape.Vertexes[2].Point) + elif Draft.getType(self.obj) == "Polygon": + delta = v.sub(self.obj.Placement.Base) + if self.editing == 0: + p = self.obj.Placement + p.move(delta) + self.obj.Placement = p + self.trackers[0].set(self.obj.Placement.Base) + elif self.editing == 1: + if self.obj.DrawMode == 'inscribed': + self.obj.Radius = delta.Length + else: + halfangle = ((math.pi*2)/self.obj.FacesNumber)/2 + rad = math.cos(halfangle)*delta.Length + self.obj.Radius = rad + self.trackers[1].set(self.obj.Shape.Vertexes[0].Point) + elif Draft.getType(self.obj) == "Dimension": + if self.editing == 0: + self.obj.Start = v + elif self.editing == 1: + self.obj.End = v + elif self.editing == 2: + self.obj.Dimline = v + elif self.editing == 3: + self.obj.ViewObject.TextPosition = v - def numericInput(self,v,numy=None,numz=None): - '''this function gets called by the toolbar - when valid x, y, and z have been entered there''' - if (numy != None): - v = Vector(v,numy,numz) - self.doc.openTransaction("Edit "+self.obj.Name) - self.update(v) - self.doc.commitTransaction() - self.editing = None - self.ui.editUi() - self.node = [] + def numericInput(self,v,numy=None,numz=None): + '''this function gets called by the toolbar + when valid x, y, and z have been entered there''' + if (numy != None): + v = Vector(v,numy,numz) + self.doc.openTransaction("Edit "+self.obj.Name) + self.update(v) + self.doc.commitTransaction() + self.editing = None + self.ui.editUi() + self.node = [] - def addPoint(self,point): - if not (Draft.getType(self.obj) in ["Wire","BSpline"]): return - pts = self.obj.Points - if ( Draft.getType(self.obj) == "Wire" ): - if (self.obj.Closed == True): - # DNC: work around.... seems there is a - # bug in approximate method for closed wires... - edges = self.obj.Shape.Wires[0].Edges - e1 = edges[-1] # last edge - v1 = e1.Vertexes[0].Point - v2 = e1.Vertexes[1].Point - v2.multiply(0.9999) - edges[-1] = Part.makeLine(v1,v2) - edges.reverse() - wire = Part.Wire(edges) - curve = wire.approximate(0.0001,0.0001,100,25) - else: - # DNC: this version is much more reliable near sharp edges! - curve = self.obj.Shape.Wires[0].approximate(0.0001,0.0001,100,25) - elif ( Draft.getType(self.obj) == "BSpline" ): - if (self.obj.Closed == True): - curve = self.obj.Shape.Edges[0].Curve - else: - curve = self.obj.Shape.Curve - uNewPoint = curve.parameter(point) - uPoints = [] - for p in self.obj.Points: - uPoints.append(curve.parameter(p)) - for i in range(len(uPoints)-1): - if ( uNewPoint > uPoints[i] ) and ( uNewPoint < uPoints[i+1] ): - pts.insert(i+1, self.invpl.multVec(point)) - break - # DNC: fix: add points to last segment if curve is closed - if ( self.obj.Closed ) and ( uNewPoint > uPoints[-1] ) : - pts.append(self.invpl.multVec(point)) - self.doc.openTransaction("Edit "+self.obj.Name) - self.obj.Points = pts - self.doc.commitTransaction() - self.resetTrackers() - + def addPoint(self,point): + if not (Draft.getType(self.obj) in ["Wire","BSpline"]): return + pts = self.obj.Points + if ( Draft.getType(self.obj) == "Wire" ): + if (self.obj.Closed == True): + # DNC: work around.... seems there is a + # bug in approximate method for closed wires... + edges = self.obj.Shape.Wires[0].Edges + e1 = edges[-1] # last edge + v1 = e1.Vertexes[0].Point + v2 = e1.Vertexes[1].Point + v2.multiply(0.9999) + edges[-1] = Part.makeLine(v1,v2) + edges.reverse() + wire = Part.Wire(edges) + curve = wire.approximate(0.0001,0.0001,100,25) + else: + # DNC: this version is much more reliable near sharp edges! + curve = self.obj.Shape.Wires[0].approximate(0.0001,0.0001,100,25) + elif ( Draft.getType(self.obj) == "BSpline" ): + if (self.obj.Closed == True): + curve = self.obj.Shape.Edges[0].Curve + else: + curve = self.obj.Shape.Curve + uNewPoint = curve.parameter(point) + uPoints = [] + for p in self.obj.Points: + uPoints.append(curve.parameter(p)) + for i in range(len(uPoints)-1): + if ( uNewPoint > uPoints[i] ) and ( uNewPoint < uPoints[i+1] ): + pts.insert(i+1, self.invpl.multVec(point)) + break + # DNC: fix: add points to last segment if curve is closed + if ( self.obj.Closed ) and ( uNewPoint > uPoints[-1] ) : + pts.append(self.invpl.multVec(point)) + self.doc.openTransaction("Edit "+self.obj.Name) + self.obj.Points = pts + self.doc.commitTransaction() + self.resetTrackers() - def delPoint(self,point): - if not (Draft.getType(self.obj) in ["Wire","BSpline"]): return - if len(self.obj.Points) <= 2: - msg(translate("draft", "Active object must have more than two points/nodes\n"),'warning') - else: - pts = self.obj.Points - pts.pop(point) - self.doc.openTransaction("Edit "+self.obj.Name) - self.obj.Points = pts - self.doc.commitTransaction() - self.resetTrackers() + def delPoint(self,point): + if not (Draft.getType(self.obj) in ["Wire","BSpline"]): return + if len(self.obj.Points) <= 2: + msg(translate("draft", "Active object must have more than two points/nodes\n"),'warning') + else: + pts = self.obj.Points + pts.pop(point) + self.doc.openTransaction("Edit "+self.obj.Name) + self.obj.Points = pts + self.doc.commitTransaction() + self.resetTrackers() - def resetTrackers(self): - for t in self.trackers: - t.finalize() - self.trackers = [] - for ep in range(len(self.obj.Points)): - objPoints = self.obj.Points[ep] - if self.pl: objPoints = self.pl.multVec(objPoints) - self.trackers.append(editTracker(objPoints,self.obj.Name,ep,self.obj.ViewObject.LineColor)) + def resetTrackers(self): + for t in self.trackers: + t.finalize() + self.trackers = [] + for ep in range(len(self.obj.Points)): + objPoints = self.obj.Points[ep] + if self.pl: objPoints = self.pl.multVec(objPoints) + self.trackers.append(editTracker(objPoints,self.obj.Name,ep,self.obj.ViewObject.LineColor)) + class AddToGroup(): - "The AddToGroup FreeCAD command definition" + "The AddToGroup FreeCAD command definition" - def GetResources(self): - return {'Pixmap' : 'Draft_AddToGroup', - 'MenuText': QtCore.QT_TRANSLATE_NOOP("Draft_AddToGroup", "Add to group..."), - 'ToolTip': QtCore.QT_TRANSLATE_NOOP("Draft_AddToGroup", "Adds the selected object(s) to an existing group")} + def GetResources(self): + return {'Pixmap' : 'Draft_AddToGroup', + 'MenuText': QtCore.QT_TRANSLATE_NOOP("Draft_AddToGroup", "Add to group..."), + 'ToolTip': QtCore.QT_TRANSLATE_NOOP("Draft_AddToGroup", "Adds the selected object(s) to an existing group")} - def IsActive(self): - if Draft.getSelection(): - return True - else: - return False + def IsActive(self): + if Draft.getSelection(): + return True + else: + return False - def Activated(self): - self.groups = ["Ungroup"] - self.groups.extend(Draft.getGroupNames()) - self.labels = ["Ungroup"] - for g in self.groups: - o = FreeCAD.ActiveDocument.getObject(g) - if o: self.labels.append(o.Label) - self.ui = FreeCADGui.draftToolBar - self.ui.sourceCmd = self - self.ui.popupMenu(self.labels) + def Activated(self): + self.groups = ["Ungroup"] + self.groups.extend(Draft.getGroupNames()) + self.labels = ["Ungroup"] + for g in self.groups: + o = FreeCAD.ActiveDocument.getObject(g) + if o: self.labels.append(o.Label) + self.ui = FreeCADGui.draftToolBar + self.ui.sourceCmd = self + self.ui.popupMenu(self.labels) - def proceed(self,labelname): - self.ui.sourceCmd = None - if labelname == "Ungroup": - for obj in Draft.getSelection(): - try: - Draft.ungroup(obj) - except: - pass - else: - if labelname in self.labels: - i = self.labels.index(labelname) - g = FreeCAD.ActiveDocument.getObject(self.groups[i]) - for obj in Draft.getSelection(): - try: - g.addObject(obj) - except: - pass + def proceed(self,labelname): + self.ui.sourceCmd = None + if labelname == "Ungroup": + for obj in Draft.getSelection(): + try: + Draft.ungroup(obj) + except: + pass + else: + if labelname in self.labels: + i = self.labels.index(labelname) + g = FreeCAD.ActiveDocument.getObject(self.groups[i]) + for obj in Draft.getSelection(): + try: + g.addObject(obj) + except: + pass + class AddPoint(Modifier): - "The Draft_AddPoint FreeCAD command definition" + "The Draft_AddPoint FreeCAD command definition" - def __init__(self): - self.running = False + def __init__(self): + self.running = False - def GetResources(self): - return {'Pixmap' : 'Draft_AddPoint', - 'MenuText': QtCore.QT_TRANSLATE_NOOP("Draft_AddPoint", "Add Point"), - 'ToolTip': QtCore.QT_TRANSLATE_NOOP("Draft_AddPoint", "Adds a point to an existing wire/bspline")} + def GetResources(self): + return {'Pixmap' : 'Draft_AddPoint', + 'MenuText': QtCore.QT_TRANSLATE_NOOP("Draft_AddPoint", "Add Point"), + 'ToolTip': QtCore.QT_TRANSLATE_NOOP("Draft_AddPoint", "Adds a point to an existing wire/bspline")} - def IsActive(self): - self.selection = Draft.getSelection() - if (Draft.getType(self.selection[0]) in ['Wire','BSpline']): - return True - else: - return False + def IsActive(self): + self.selection = Draft.getSelection() + if (Draft.getType(self.selection[0]) in ['Wire','BSpline']): + return True + else: + return False - def Activated(self): - FreeCADGui.draftToolBar.addButton.setChecked(True) - FreeCADGui.draftToolBar.delButton.setChecked(False) - FreeCADGui.runCommand("Draft_Edit") - + def Activated(self): + FreeCADGui.draftToolBar.addButton.setChecked(True) + FreeCADGui.draftToolBar.delButton.setChecked(False) + FreeCADGui.runCommand("Draft_Edit") + + class DelPoint(Modifier): - "The Draft_DelPoint FreeCAD command definition" + "The Draft_DelPoint FreeCAD command definition" - def __init__(self): - self.running = False + def __init__(self): + self.running = False + + def GetResources(self): + return {'Pixmap' : 'Draft_DelPoint', + 'MenuText': QtCore.QT_TRANSLATE_NOOP("Draft_DelPoint", "Remove Point"), + 'ToolTip': QtCore.QT_TRANSLATE_NOOP("Draft_DelPoint", "Removes a point from an existing wire or bspline")} - def GetResources(self): - return {'Pixmap' : 'Draft_DelPoint', - 'MenuText': QtCore.QT_TRANSLATE_NOOP("Draft_DelPoint", "Remove Point"), - 'ToolTip': QtCore.QT_TRANSLATE_NOOP("Draft_DelPoint", "Removes a point from an existing wire or bspline")} + def IsActive(self): + self.selection = Draft.getSelection() + if (Draft.getType(self.selection[0]) in ['Wire','BSpline']): + return True + else: + return False - def IsActive(self): - self.selection = Draft.getSelection() - if (Draft.getType(self.selection[0]) in ['Wire','BSpline']): - return True - else: - return False - - def Activated(self): - FreeCADGui.draftToolBar.addButton.setChecked(False) - FreeCADGui.draftToolBar.delButton.setChecked(True) - FreeCADGui.runCommand("Draft_Edit") + def Activated(self): + FreeCADGui.draftToolBar.addButton.setChecked(False) + FreeCADGui.draftToolBar.delButton.setChecked(True) + FreeCADGui.runCommand("Draft_Edit") + class WireToBSpline(Modifier): - "The Draft_Wire2BSpline FreeCAD command definition" + "The Draft_Wire2BSpline FreeCAD command definition" - def __init__(self): - self.running = False + def __init__(self): + self.running = False + + def GetResources(self): + return {'Pixmap' : 'Draft_WireToBSpline', + 'MenuText': QtCore.QT_TRANSLATE_NOOP("Draft_WireToBSpline", "Wire to BSpline"), + 'ToolTip': QtCore.QT_TRANSLATE_NOOP("Draft_WireToBSpline", "Converts between Wire and BSpline")} - def GetResources(self): - return {'Pixmap' : 'Draft_WireToBSpline', - 'MenuText': QtCore.QT_TRANSLATE_NOOP("Draft_WireToBSpline", "Wire to BSpline"), - 'ToolTip': QtCore.QT_TRANSLATE_NOOP("Draft_WireToBSpline", "Converts between Wire and BSpline")} + def IsActive(self): + self.selection = Draft.getSelection() + if (Draft.getType(self.selection[0]) in ['Wire','BSpline']): + return True + else: + return False - def IsActive(self): - self.selection = Draft.getSelection() - if (Draft.getType(self.selection[0]) in ['Wire','BSpline']): - return True - else: - return False - - def Activated(self): - if self.running: - self.finish() + def Activated(self): + if self.running: + self.finish() + else: + Modifier.Activated(self,"Convert Curve Type") + if self.doc: + self.obj = Draft.getSelection() + if self.obj: + self.obj = self.obj[0] + self.pl = None + if "Placement" in self.obj.PropertiesList: + self.pl = self.obj.Placement + self.Points = self.obj.Points + self.closed = self.obj.Closed + n = None + if (Draft.getType(self.selection[0]) == 'Wire'): + n = Draft.makeBSpline(self.Points, self.closed, self.pl) + elif (Draft.getType(self.selection[0]) == 'BSpline'): + n = Draft.makeWire(self.Points, self.closed, self.pl) + if n: + Draft.formatObject(n,self.selection[0]) else: - Modifier.Activated(self,"Convert Curve Type") - if self.doc: - self.obj = Draft.getSelection() - if self.obj: - self.obj = self.obj[0] - self.pl = None - if "Placement" in self.obj.PropertiesList: - self.pl = self.obj.Placement - self.Points = self.obj.Points - self.closed = self.obj.Closed - n = None - if (Draft.getType(self.selection[0]) == 'Wire'): - n = Draft.makeBSpline(self.Points, self.closed, self.pl) - elif (Draft.getType(self.selection[0]) == 'BSpline'): - n = Draft.makeWire(self.Points, self.closed, self.pl) - if n: - Draft.formatObject(n,self.selection[0]) - else: - self.finish() + self.finish() def finish(self): Modifier.finish(self) + class SelectGroup(): - "The SelectGroup FreeCAD command definition" + "The SelectGroup FreeCAD command definition" - def GetResources(self): - return {'Pixmap' : 'Draft_SelectGroup', - 'MenuText': QtCore.QT_TRANSLATE_NOOP("Draft_SelectGroup", "Select group"), - 'ToolTip': QtCore.QT_TRANSLATE_NOOP("Draft_SelectGroup", "Selects all objects with the same parents as this group")} + def GetResources(self): + return {'Pixmap' : 'Draft_SelectGroup', + 'MenuText': QtCore.QT_TRANSLATE_NOOP("Draft_SelectGroup", "Select group"), + 'ToolTip': QtCore.QT_TRANSLATE_NOOP("Draft_SelectGroup", "Selects all objects with the same parents as this group")} - def IsActive(self): - if Draft.getSelection(): - return True - else: - return False + def IsActive(self): + if Draft.getSelection(): + return True + else: + return False - def Activated(self): - sellist = [] - for ob in Draft.getSelection(): - for child in ob.OutList: - FreeCADGui.Selection.addSelection(child) - for parent in ob.InList: - FreeCADGui.Selection.addSelection(parent) - for child in parent.OutList: - FreeCADGui.Selection.addSelection(child) + def Activated(self): + sellist = [] + for ob in Draft.getSelection(): + for child in ob.OutList: + FreeCADGui.Selection.addSelection(child) + for parent in ob.InList: + FreeCADGui.Selection.addSelection(parent) + for child in parent.OutList: + FreeCADGui.Selection.addSelection(child) + class Shape2DView(): - "The Shape2DView FreeCAD command definition" - def GetResources(self): - return {'Pixmap' : 'Draft_2DShapeView', - 'MenuText': QtCore.QT_TRANSLATE_NOOP("Draft_Shape2DView", "Shape 2D view"), - 'ToolTip': QtCore.QT_TRANSLATE_NOOP("Draft_Shape2DView", "Creates Shape 2D views of selected objects")} + "The Shape2DView FreeCAD command definition" + def GetResources(self): + return {'Pixmap' : 'Draft_2DShapeView', + 'MenuText': QtCore.QT_TRANSLATE_NOOP("Draft_Shape2DView", "Shape 2D view"), + 'ToolTip': QtCore.QT_TRANSLATE_NOOP("Draft_Shape2DView", "Creates Shape 2D views of selected objects")} - def IsActive(self): - if Draft.getSelection(): - return True - else: - return False + def IsActive(self): + if Draft.getSelection(): + return True + else: + return False - def Activated(self): - sellist = [] - for ob in Draft.getSelection(): - Draft.makeShape2DView(ob) + def Activated(self): + sellist = [] + for ob in Draft.getSelection(): + Draft.makeShape2DView(ob) #--------------------------------------------------------------------------- # Adds the icons & commands to the FreeCAD command manager, and sets defaults