diff --git a/src/Mod/Draft/DraftGui.py b/src/Mod/Draft/DraftGui.py
index 9afe2cd512..45ccea8769 100644
--- a/src/Mod/Draft/DraftGui.py
+++ b/src/Mod/Draft/DraftGui.py
@@ -1155,6 +1155,10 @@ class DraftToolBar:
if hasattr(FreeCADGui,"Snapper"):
FreeCADGui.Snapper.addHoldPoint()
spec = True
+ elif txt == _get_incmd_shortcut("Recenter"):
+ if hasattr(FreeCADGui,"Snapper"):
+ FreeCADGui.Snapper.recenter_workingplane()
+ spec = True
elif txt == _get_incmd_shortcut("Snap"):
self.togglesnap()
spec = True
diff --git a/src/Mod/Draft/Resources/Draft.qrc b/src/Mod/Draft/Resources/Draft.qrc
index 089dac09c9..10d86ded07 100644
--- a/src/Mod/Draft/Resources/Draft.qrc
+++ b/src/Mod/Draft/Resources/Draft.qrc
@@ -94,6 +94,7 @@
icons/Draft_Snap_Ortho.svg
icons/Draft_Snap_Parallel.svg
icons/Draft_Snap_Perpendicular.svg
+ icons/Draft_Snap_Recenter.svg
icons/Draft_Snap_Special.svg
icons/Draft_Snap_WorkingPlane.svg
icons/Draft_Split.svg
diff --git a/src/Mod/Draft/Resources/icons/Draft_Snap_Recenter.svg b/src/Mod/Draft/Resources/icons/Draft_Snap_Recenter.svg
new file mode 100644
index 0000000000..3c2c1ff83d
--- /dev/null
+++ b/src/Mod/Draft/Resources/icons/Draft_Snap_Recenter.svg
@@ -0,0 +1,224 @@
+
+
diff --git a/src/Mod/Draft/Resources/ui/preferences-draftinterface.ui b/src/Mod/Draft/Resources/ui/preferences-draftinterface.ui
index bcb96e972f..ce2d03cc55 100644
--- a/src/Mod/Draft/Resources/ui/preferences-draftinterface.ui
+++ b/src/Mod/Draft/Resources/ui/preferences-draftinterface.ui
@@ -6,8 +6,8 @@
0
0
- 456
- 338
+ 513
+ 516
@@ -41,7 +41,7 @@
1
-
+
false
@@ -89,7 +89,7 @@
1
-
+
false
@@ -137,7 +137,7 @@
1
-
+
false
@@ -185,7 +185,7 @@
1
-
+
false
@@ -217,7 +217,7 @@
1
-
+
false
@@ -249,7 +249,7 @@
1
-
+
false
@@ -281,7 +281,7 @@
1
-
+
false
@@ -313,7 +313,7 @@
1
-
+
false
@@ -345,7 +345,7 @@
1
-
+
false
@@ -377,7 +377,7 @@
1
-
+
false
@@ -409,7 +409,7 @@
1
-
+
false
@@ -441,7 +441,7 @@
1
-
+
false
@@ -473,7 +473,7 @@
1
-
+
false
@@ -505,7 +505,7 @@
1
-
+
false
@@ -537,7 +537,7 @@
1
-
+
false
@@ -569,7 +569,7 @@
1
-
+
false
@@ -601,7 +601,7 @@
1
-
+
false
@@ -633,7 +633,7 @@
1
-
+
false
@@ -665,7 +665,7 @@
1
-
+
false
@@ -697,7 +697,7 @@
1
-
+
false
@@ -729,7 +729,7 @@
1
-
+
false
@@ -740,6 +740,38 @@
+ -
+
+
+ Recenter
+
+
+
+ -
+
+
+
+ 25
+ 16777215
+
+
+
+ D
+
+
+ 1
+
+
+ false
+
+
+ inCommandShortcutRecenter
+
+
+ Mod/Draft
+
+
+
@@ -814,6 +846,12 @@
Qt::Vertical
+
+
+ 0
+ 0
+
+
diff --git a/src/Mod/Draft/WorkingPlane.py b/src/Mod/Draft/WorkingPlane.py
index 657c1c9019..3f26173a4c 100644
--- a/src/Mod/Draft/WorkingPlane.py
+++ b/src/Mod/Draft/WorkingPlane.py
@@ -241,6 +241,40 @@ class PlaneBase:
self.position = pos + (self.axis * offset)
return True
+ def align_to_face_and_edge(self, face, edge, offset=0):
+ """Align the WP to a face and an edge.
+
+ The face must be planar.
+
+ The WP will lie on the face, but its `position` will be the
+ first vertex of the edge, and its `u` vector will be aligned
+ with the edge.
+
+ Parameters
+ ----------
+
+ face: Part.Face
+ Face.
+ edge: Part.Edge
+ Edge, need not be an edge of the face.
+ offset: float, optional
+ Defaults to zero.
+ Offset along the WP `axis`.
+
+ Returns
+ -------
+ `True`/`False`
+ `True` if successful.
+ """
+ if face.Surface.isPlanar() is False:
+ return False
+ axis = face.normalAt(0,0)
+ point = edge.Vertexes[0].Point
+ upvec = edge.Vertexes[-1].Point.sub(point)
+ return self.align_to_point_and_axis(point, axis, offset, upvec)
+ #vertex = Part.Vertex(face.CenterOfMass)
+ #return self.align_to_edges_vertexes([edge, vertex], offset)
+
def align_to_face(self, shape, offset=0):
"""Align the WP to a face with an optional offset.
@@ -1256,11 +1290,14 @@ class PlaneGui(PlaneBase):
objs.append(Part.getShape(sel.Object, sub, needSubElement=True, retType=1))
if len(objs) != 1:
+ ret = False
if all([obj[0].isNull() is False and obj[0].ShapeType in ["Edge", "Vertex"] for obj in objs]):
ret = self.align_to_edges_vertexes([obj[0] for obj in objs], offset, _hist_add)
- else:
- ret = False
-
+ elif all([obj[0].isNull() is False and obj[0].ShapeType in ["Edge", "Face"] for obj in objs]):
+ edges = [obj[0] for obj in objs if obj[0].ShapeType == "Edge"]
+ faces = [obj[0] for obj in objs if obj[0].ShapeType == "Face"]
+ if faces and edges:
+ ret = self.align_to_face_and_edge(faces[0], edges[0], offset, _hist_add)
if ret is False:
_wrn(translate("draft", "Selected shapes do not define a plane"))
return ret
@@ -1329,6 +1366,13 @@ class PlaneGui(PlaneBase):
self._handle_custom(_hist_add)
return True
+ def align_to_face_and_edge(self, face, edge, offset=0, _hist_add=True):
+ """See PlaneBase.align_to_face."""
+ if super().align_to_face_and_edge(face, edge, offset) is False:
+ return False
+ self._handle_custom(_hist_add)
+ return True
+
def align_to_placement(self, place, offset=0, _hist_add=True):
"""See PlaneBase.align_to_placement."""
super().align_to_placement(place, offset)
diff --git a/src/Mod/Draft/draftguitools/gui_snapper.py b/src/Mod/Draft/draftguitools/gui_snapper.py
index fe36aea2e7..28215cfa21 100644
--- a/src/Mod/Draft/draftguitools/gui_snapper.py
+++ b/src/Mod/Draft/draftguitools/gui_snapper.py
@@ -49,6 +49,7 @@ import Part
import Draft
import DraftVecUtils
import DraftGeomUtils
+import WorkingPlane
from draftguitools import gui_trackers as trackers
from draftutils import gui_utils
from draftutils import params
@@ -159,7 +160,7 @@ class Snapper:
def _get_wp(self):
- return App.DraftWorkingPlane
+ return WorkingPlane.get_working_plane()
def init_active_snaps(self):
@@ -1649,4 +1650,10 @@ class Snapper:
self.holdTracker.on()
self.holdPoints.append(self.spoint)
+ def recenter_workingplane(self):
+ """Recenters the working plane on the current snap position"""
+ if self.spoint:
+ self._get_wp().set_to_position(self.toWP(self.spoint))
+
+
## @}