Merge pull request #10425 from Roy-043/Draft-FixDraft_Mirror-preview

Draft: Fix Draft_Mirror preview
This commit is contained in:
Yorik van Havre
2023-09-01 12:48:16 +02:00
committed by GitHub
4 changed files with 68 additions and 25 deletions

View File

@@ -78,6 +78,7 @@ from draftgeoutils.geometry import (findPerpendicular,
mirror,
are_coplanar,
is_straight_line,
mirror_matrix,
uv_vectors_from_face,
placement_from_face,
placement_from_points)

View File

@@ -517,6 +517,32 @@ def mirror(point, edge):
return None
def mirror_matrix(mtx, pos, nor):
"""Return a mirrored copy of a matrix.
Parameters
----------
mtx: Base::Matrix
Matrix.
pos: Base::Vector3
Point on mirror plane.
nor: Base::Vector3
Normal of mirror plane.
Return
------
Base::Matrix
"""
# Code by Jolbas:
# https://forum.freecad.org/viewtopic.php?p=702793#p702793
mtx_copy = App.Matrix(mtx)
mtx_copy.move(-pos)
mtx_copy.scale(-1)
mtx_copy = App.Rotation(nor, 180) * mtx_copy
mtx_copy.move(pos)
return mtx_copy
def uv_vectors_from_face(face, vec_z=App.Vector(0, 0, 1), tol=-1):
"""Return the u and v vectors of a planar face.
@@ -525,6 +551,8 @@ def uv_vectors_from_face(face, vec_z=App.Vector(0, 0, 1), tol=-1):
If the u vector matches +/-vec_z, or the v vector matches -vec_z, the
vectors are rotated to ensure the v vector matches +vec_z.
Parameters
----------
face: Part.Face
Face.
vec_z: Base::Vector3, optional

View File

@@ -40,9 +40,10 @@ from PySide.QtCore import QT_TRANSLATE_NOOP
import FreeCAD as App
import FreeCADGui as Gui
import Draft_rc
import DraftGeomUtils
import DraftVecUtils
import WorkingPlane
import draftguitools.gui_base_original as gui_base_original
import draftguitools.gui_trackers as trackers
import draftguitools.gui_tool_utils as gui_tool_utils
from draftutils.messages import _msg
@@ -86,8 +87,7 @@ class Mirror(gui_base_original.Modifier):
self.ui.pointUi(title=translate("draft", self.featureName), icon="Draft_Mirror")
self.ui.xValue.setFocus()
self.ui.xValue.selectAll()
# self.ghost = trackers.ghostTracker(self.sel)
# TODO: solve this (see below)
self.ghost = trackers.ghostTracker(self.sel, mirror=True)
self.call = self.view.addEventCallback("SoEvent", self.action)
_msg(translate("draft", "Pick start point of mirror line"))
self.ui.isCopy.hide()
@@ -133,29 +133,19 @@ class Mirror(gui_base_original.Modifier):
if arg["Key"] == "ESCAPE":
self.finish()
elif arg["Type"] == "SoLocation2Event": # mouse movement detection
(self.point,
ctrlPoint, info) = gui_tool_utils.getPoint(self, arg)
self.point, ctrlPoint, info = gui_tool_utils.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()
# This part used to test for the GUI to obtain
# the camera view but this is unnecessary
# as this command is always launched in the GUI.
_view = Gui.ActiveDocument.ActiveView
mv = _view.getViewDirection().negative()
mw = mv.cross(mu)
_plane = WorkingPlane.plane(u=mu, v=mv, w=mw,
pos=last)
tm = _plane.getPlacement().toMatrix()
m = self.ghost.getMatrix()
m = m.multiply(tm.inverse())
m.scale(App.Vector(1, 1, -1))
m = m.multiply(tm)
m.scale(App.Vector(-1, 1, 1))
self.ghost.setMatrix(m)
tol = 1e-7
if self.point.sub(last).Length > tol:
# The normal of the mirror plane must be same as in mirror.py.
nor = self.point.sub(last).cross(self.wp.axis)
if nor.Length > tol:
nor.normalize()
mtx = DraftGeomUtils.mirror_matrix(App.Matrix(), last, nor)
self.ghost.setMatrix(mtx) # Ignores the position of the matrix.
self.ghost.move(App.Vector(mtx.col(3)[:3]))
if self.extendedCopy:
if not gui_tool_utils.hasMod(arg, gui_tool_utils.MODALT):
self.finish()

View File

@@ -666,7 +666,7 @@ class ghostTracker(Tracker):
You can pass it an object or a list of objects, or a shape.
"""
def __init__(self, sel, dotted=False, scolor=None, swidth=None):
def __init__(self, sel, dotted=False, scolor=None, swidth=None, mirror=False):
self.trans = coin.SoTransform()
self.trans.translation.setValue([0, 0, 0])
self.children = [self.trans]
@@ -691,6 +691,8 @@ class ghostTracker(Tracker):
selnode.addChild(self.marker)
node.addChild(selnode)
rootsep.addChild(node)
if mirror is True:
self._flip(rootsep)
self.children.append(rootsep)
super().__init__(dotted, scolor, swidth,
children=self.children, name="ghostTracker")
@@ -776,13 +778,35 @@ class ghostTracker(Tracker):
return FreeCAD.Matrix()
def setMatrix(self, matrix):
"""Set the transformation matrix."""
"""Set the transformation matrix.
The 4th column of the matrix (the position) is ignored.
"""
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)
def _flip(self, root):
"""Flip the normals of the coin faces."""
# Code by wmayer:
# https://forum.freecad.org/viewtopic.php?p=702640#p702640
search = coin.SoSearchAction()
search.setType(coin.SoIndexedFaceSet.getClassTypeId())
search.apply(root)
path = search.getPath()
if path:
node = path.getTail()
index = node.coordIndex.getValues()
if len(index) % 4 == 0:
for i in range(0, len(index), 4):
tmp = index[i]
index[i] = index[i+1]
index[i+1] = tmp
node.coordIndex.setValues(index)
class editTracker(Tracker):
"""A node edit tracker."""