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 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + Fri Mar 7 15:58:51 2014 -0300 + + + [Yorik van Havre] + + + + + FreeCAD LGPL2+ + + + + + FreeCAD + + + FreeCAD/src/Mod/Draft/Resources/icons/Draft_Snap_WorkingPlane.svg + https://www.freecad.org/wiki/index.php?title=Artwork + + + [agryson] Alexander Gryson + + + Square with small circe in lower left corner + + + plane + square + circle + + + + + + 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)) + + ## @}