Draft: Added mirror tool (more graphical version of Part Mirror) - fixes #2215

This commit is contained in:
Yorik van Havre
2015-12-05 14:19:35 -02:00
parent cf3e69de08
commit 2e91633da9
7 changed files with 331 additions and 2 deletions

View File

@@ -91,7 +91,8 @@ class ArchWorkbench(Workbench):
"Draft_Trimex", "Draft_Upgrade", "Draft_Downgrade", "Draft_Scale",
"Draft_Shape2DView","Draft_Draft2Sketch","Draft_Array",
"Draft_Clone"]
self.draftextratools = ["Draft_WireToBSpline","Draft_AddPoint","Draft_DelPoint","Draft_ShapeString","Draft_PathArray"]
self.draftextratools = ["Draft_WireToBSpline","Draft_AddPoint","Draft_DelPoint","Draft_ShapeString",
"Draft_PathArray","Draft_Mirror"]
self.draftcontexttools = ["Draft_ApplyStyle","Draft_ToggleDisplayMode","Draft_AddToGroup",
"Draft_SelectGroup","Draft_SelectPlane",
"Draft_ShowSnapBar","Draft_ToggleGrid","Draft_UndoLine",

View File

@@ -2456,6 +2456,41 @@ def getCloneBase(obj,strict=False):
return False
return obj
def mirror(objlist,p1,p2):
'''mirror(objlist,p1,p2,[clone]): creates a mirrored version of the given object(s)
along an axis that passes through the two vectors p1 and p2.'''
if not objlist:
FreeCAD.Console.PrintError(translate("draft","No object given\n"))
return
if p1 == p2:
FreeCAD.Console.PrintError(translate("draft","The two points are coincident\n"))
return
if not isinstance(objlist,list):
objlist = [objlist]
result = []
for obj in objlist:
mir = FreeCAD.ActiveDocument.addObject("Part::Mirroring","mirror")
mir.Label = "Mirror of "+obj.Label
mir.Source = obj
if gui:
norm = FreeCADGui.ActiveDocument.ActiveView.getViewDirection().negative()
else:
norm = FreeCAD.Vector(0,0,1)
pnorm = p2.sub(p1).cross(norm).normalize()
mir.Base = p1
mir.Normal = pnorm
formatObject(mir,obj)
result.append(mir)
if len(result) == 1:
result = result[0]
return result
def heal(objlist=None,delete=True,reparent=True):
'''heal([objlist],[delete],[reparent]) - recreates Draft objects that are damaged,
for example if created from an earlier version. If delete is True,

View File

@@ -4409,6 +4409,129 @@ class VisGroup():
FreeCAD.ActiveDocument.recompute()
class Mirror(Modifier):
"The Draft_Mirror FreeCAD command definition"
def GetResources(self):
return {'Pixmap' : 'Draft_Mirror',
'Accel' : "M, I",
'MenuText': QtCore.QT_TRANSLATE_NOOP("Draft_Mirror", "Mirror"),
'ToolTip': QtCore.QT_TRANSLATE_NOOP("Draft_Mirror", "Mirrors the selected objects along a line defined by two points")}
def Activated(self):
self.name = translate("draft","Mirror").decode("utf8")
Modifier.Activated(self,self.name)
self.ghost = None
if self.ui:
if not FreeCADGui.Selection.getSelection():
self.ui.selectUi()
msg(translate("draft", "Select an object to mirror\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 = FreeCADGui.Selection.getSelection()
self.ui.pointUi(self.name)
self.ui.modUi()
self.ui.xValue.setFocus()
self.ui.xValue.selectAll()
#self.ghost = ghostTracker(self.sel) TODO: solve this (see below)
self.call = self.view.addEventCallback("SoEvent",self.action)
msg(translate("draft", "Pick start point of mirror line:\n"))
self.ui.isCopy.hide()
def finish(self,closed=False,cont=False):
if self.ghost:
self.ghost.finalize()
Modifier.finish(self)
if cont and self.ui:
if self.ui.continueMode:
FreeCADGui.Selection.clearSelection()
self.Activated()
def mirror(self,p1,p2,copy=False):
"mirroring the real shapes"
sel = '['
for o in self.sel:
if len(sel) > 1:
sel += ','
sel += 'FreeCAD.ActiveDocument.'+o.Name
sel += ']'
FreeCADGui.addModule("Draft")
self.commit(translate("draft","Mirror"),
['Draft.mirror('+sel+','+DraftVecUtils.toString(p1)+','+DraftVecUtils.toString(p2)+')',
'FreeCAD.ActiveDocument.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
self.point,ctrlPoint,info = getPoint(self,arg)
if (len(self.node) > 0):
last = self.node[-1]
if self.ghost:
if self.point != last:
# TODO : the following doesn't work at the moment
mu = self.point.sub(last).normalize()
if FreeCAD.GuiUp:
mv = FreeCADGui.ActiveDocument.ActiveView.getViewDirection().negative()
else:
mv = FreeCAD.Vector(0,0,1)
mw = mv.cross(mu)
import WorkingPlane
tm = WorkingPlane.plane(u=mu,v=mv,w=mw,pos=last).getPlacement().toMatrix()
m = self.ghost.getMatrix()
m = m.multiply(tm.inverse())
m.scale(FreeCAD.Vector(1,1,-1))
m = m.multiply(tm)
m.scale(FreeCAD.Vector(-1,1,1))
self.ghost.setMatrix(m)
if self.extendedCopy:
if not hasMod(arg,MODALT): self.finish()
elif arg["Type"] == "SoMouseButtonEvent":
if (arg["State"] == "DOWN") and (arg["Button"] == "BUTTON1"):
if self.point:
self.ui.redraw()
if (self.node == []):
self.node.append(self.point)
self.ui.isRelative.show()
if self.ghost:
self.ghost.on()
msg(translate("draft", "Pick end point of mirror line:\n"))
if self.planetrack:
self.planetrack.set(self.point)
else:
last = self.node[0]
if self.ui.isCopy.isChecked() or hasMod(arg,MODALT):
self.mirror(last,self.point,True)
else:
self.mirror(last,self.point)
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.point = Vector(numx,numy,numz)
if not self.node:
self.node.append(self.point)
if self.ghost:
self.ghost.on()
msg(translate("draft", "Pick end point of mirror line:\n"))
else:
last = self.node[-1]
if self.ui.isCopy.isChecked():
self.mirror(last,self.point,True)
else:
self.mirror(last,self.point)
self.finish()
#---------------------------------------------------------------------------
# Snap tools
#---------------------------------------------------------------------------
@@ -4620,6 +4743,7 @@ FreeCADGui.addCommand('Draft_Clone',Draft_Clone())
FreeCADGui.addCommand('Draft_PathArray',PathArray())
FreeCADGui.addCommand('Draft_Heal',Heal())
FreeCADGui.addCommand('Draft_VisGroup',VisGroup())
FreeCADGui.addCommand('Draft_Mirror',Mirror())
# context commands
FreeCADGui.addCommand('Draft_FinishLine',FinishLine())

View File

@@ -611,6 +611,27 @@ class ghostTracker(Tracker):
except:
print("Error retrieving coin node")
return sep
def getMatrix(self):
r = FreeCADGui.ActiveDocument.ActiveView.getViewer().getSoRenderManager().getViewportRegion()
v = coin.SoGetMatrixAction(r)
m = self.trans.getMatrix(v)
if m:
m = m.getValue()
return FreeCAD.Matrix(m[0][0],m[0][1],m[0][2],m[0][3],
m[1][0],m[1][1],m[1][2],m[1][3],
m[2][0],m[2][1],m[2][2],m[2][3],
m[3][0],m[3][1],m[3][2],m[3][3])
else:
return FreeCAD.Matrix()
def setMatrix(self,matrix):
m = coin.SbMatrix(matrix.A11,matrix.A12,matrix.A13,matrix.A14,
matrix.A21,matrix.A22,matrix.A23,matrix.A24,
matrix.A31,matrix.A32,matrix.A33,matrix.A34,
matrix.A41,matrix.A42,matrix.A43,matrix.A44)
self.trans.setMatrix(m)
class editTracker(Tracker):
"A node edit tracker"

View File

@@ -112,7 +112,7 @@ class DraftWorkbench (Workbench):
"Draft_Trimex", "Draft_Upgrade", "Draft_Downgrade", "Draft_Scale",
"Draft_Edit","Draft_WireToBSpline","Draft_AddPoint",
"Draft_DelPoint","Draft_Shape2DView","Draft_Draft2Sketch","Draft_Array",
"Draft_PathArray","Draft_Clone","Draft_Drawing"]
"Draft_PathArray","Draft_Clone","Draft_Drawing","Draft_Mirror"]
self.treecmdList = ["Draft_ApplyStyle","Draft_ToggleDisplayMode","Draft_AddToGroup",
"Draft_SelectGroup","Draft_SelectPlane",
"Draft_ShowSnapBar","Draft_ToggleGrid"]

View File

@@ -66,6 +66,7 @@
<file>icons/Draft_ShapeString.svg</file>
<file>icons/Draft_Facebinder.svg</file>
<file>icons/Draft_FlipDimension.svg</file>
<file>icons/Draft_Mirror.svg</file>
<file>patterns/concrete.svg</file>
<file>patterns/cross.svg</file>
<file>patterns/line.svg</file>

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 5.8 KiB