diff --git a/src/Mod/Draft/draftmake/make_dimension.py b/src/Mod/Draft/draftmake/make_dimension.py index b3a3030b29..923ffffab0 100644 --- a/src/Mod/Draft/draftmake/make_dimension.py +++ b/src/Mod/Draft/draftmake/make_dimension.py @@ -36,9 +36,12 @@ This includes linear dimensions, radial dimensions, and angular dimensions. import math import FreeCAD as App +import DraftVecUtils import WorkingPlane +from draftgeoutils import edges from draftutils import gui_utils +from draftutils import params from draftutils import utils from draftutils.messages import _wrn, _err from draftutils.translate import translate @@ -51,6 +54,51 @@ if App.GuiUp: ViewProviderAngularDimension) +def _get_flip_text_lin(p1, p2, wp, normal): + # for linear, radial dimensions + if not params.get_param("DimAutoFlipText"): + return False + p1 = wp.project_point(p1) + p2 = wp.project_point(p2) + ang = DraftVecUtils.angle(wp.u, p2.sub(p1), normal) + tol = 1e-4 # high tolerance + if math.isclose(ang, 0, abs_tol=tol): + return False + if math.isclose(ang, math.pi, abs_tol=tol): + return True + if math.isclose(ang, math.pi/2, abs_tol=tol): + return False + if math.isclose(ang, -math.pi/2, abs_tol=tol): + return True + # 90-180 (in that quadrant + 1st point closest to the origin): + if math.pi/2 < ang < math.pi: + return True + # 180-270: + if -math.pi < ang < -math.pi/2: + return True + # 0-90 and 270-360: + return False + + +def _get_flip_text_ang(cen, sta, end, normal): + # for angular dimensions + if not params.get_param("DimAutoFlipText"): + return False + import Part + circle = Part.makeCircle(1, cen, normal, sta, end) + mid = edges.findMidpoint(circle) + wp = WorkingPlane.get_working_plane(update=False) + ang = DraftVecUtils.angle(wp.u, mid.sub(cen), normal) + tol = 1e-4 # high tolerance + if math.isclose(ang, 0, abs_tol=tol): + return True + if math.isclose(ang, math.pi, abs_tol=tol): + return False + if ang > 0: + return False + return True + + def make_dimension(p1, p2, p3=None, p4=None): """Create one of three types of dimension objects. @@ -77,13 +125,24 @@ def make_dimension(p1, p2, p3=None, p4=None): _err("No active document. Aborting") return None - new_obj = App.ActiveDocument.addObject("App::FeaturePython", - "Dimension") + new_obj = App.ActiveDocument.addObject("App::FeaturePython", "Dimension") LinearDimension(new_obj) if App.GuiUp: ViewProviderLinearDimension(new_obj.ViewObject) + wp = WorkingPlane.get_working_plane(update=False) + normal = wp.axis + flip_text = False + + if App.GuiUp: + # invert the normal if we are viewing it from the back + vnorm = gui_utils.get3DView().getViewDirection() + if vnorm.getAngle(normal) < math.pi/2: + normal = normal.negative() + + new_obj.Normal = normal + if isinstance(p1, App.Vector) and isinstance(p2, App.Vector): # Measure a straight distance between p1 and p2 new_obj.Start = p1 @@ -93,6 +152,9 @@ def make_dimension(p1, p2, p3=None, p4=None): p3.multiply(0.5) p3 = p1.add(p3) + if App.GuiUp: + flip_text = _get_flip_text_lin(p1, p2, wp, normal) + elif isinstance(p2, int) and isinstance(p3, int): # p1 is an object, and measure the distance between vertices p2 and p3 # of this object @@ -103,21 +165,18 @@ def make_dimension(p1, p2, p3=None, p4=None): new_obj.LinkedGeometry = linked new_obj.Support = p1 - # p4, and now p3, is the point through which the dimension line - # will go through + v1 = p1.Shape.Vertexes[idx[0]].Point + v2 = p1.Shape.Vertexes[idx[1]].Point + # p4, and now p3, is the point through which the dimension line will pass p3 = p4 if not p3: - # When used from the GUI command, this will never run - # because p4 will always be assigned to a vector, - # so p3 will never be `None`. - # Moreover, `new_obj.Base` doesn't exist, and certainly `Shape` - # doesn't exist, so if this ever runs it will be an error. - v1 = new_obj.Base.Shape.Vertexes[idx[0]].Point - v2 = new_obj.Base.Shape.Vertexes[idx[1]].Point p3 = v2.sub(v1) p3.multiply(0.5) p3 = v1.add(p3) + if App.GuiUp: + flip_text = _get_flip_text_lin(v1, v2, wp, normal) + elif isinstance(p3, str): # If the original p3 is a string, we are measuring a circular arc # p2 should be an integer number starting from 0 @@ -137,29 +196,22 @@ def make_dimension(p1, p2, p3=None, p4=None): new_obj.LinkedGeometry = linked new_obj.Support = p1 - # p4, and now p3, is the point through which the dimension line - # will go through + cen = p1.Shape.Edges[p2].Curve.Center + # p4, and now p3, is the point through which the dimension line will pass p3 = p4 if not p3: - p3 = p1.Shape.Edges[p2].Curve.Center.add(App.Vector(1, 0, 0)) + p3 = cen.add(App.Vector(1, 0, 0)) + + if App.GuiUp: + flip_text = _get_flip_text_lin(cen, p3, wp, normal) # This p3 is the point through which the dimension line will pass, # but this may not be the original p3, it could have been p4 # depending on the first three parameter values new_obj.Dimline = p3 - normal = WorkingPlane.get_working_plane(update=False).axis - - if App.GuiUp: - # invert the normal if we are viewing it from the back - vnorm = gui_utils.get3DView().getViewDirection() - - if vnorm.getAngle(normal) < math.pi/2: - normal = normal.negative() - - new_obj.Normal = normal - if App.GuiUp: + new_obj.ViewObject.FlipText = flip_text gui_utils.format_object(new_obj) gui_utils.select(new_obj) @@ -577,15 +629,9 @@ def make_angular_dimension(center=App.Vector(0, 0, 0), if not normal: normal = WorkingPlane.get_working_plane(update=False).axis - new_obj = App.ActiveDocument.addObject("App::FeaturePython", - "Dimension") + new_obj = App.ActiveDocument.addObject("App::FeaturePython", "Dimension") AngularDimension(new_obj) - new_obj.Center = center - new_obj.FirstAngle = angles[0] - new_obj.LastAngle = angles[1] - new_obj.Dimline = dim_line - if App.GuiUp: ViewProviderAngularDimension(new_obj.ViewObject) @@ -596,9 +642,14 @@ def make_angular_dimension(center=App.Vector(0, 0, 0), if vnorm.getAngle(normal) < math.pi/2: normal = normal.negative() + new_obj.Center = center + new_obj.FirstAngle = angles[0] + new_obj.LastAngle = angles[1] + new_obj.Dimline = dim_line new_obj.Normal = normal if App.GuiUp: + new_obj.ViewObject.FlipText = _get_flip_text_ang(center, angles[0], angles[1], normal) gui_utils.format_object(new_obj) gui_utils.select(new_obj) diff --git a/src/Mod/Draft/draftutils/params.py b/src/Mod/Draft/draftutils/params.py index 51bf6b9983..70d86a19fb 100644 --- a/src/Mod/Draft/draftutils/params.py +++ b/src/Mod/Draft/draftutils/params.py @@ -388,6 +388,7 @@ def _get_param_dictionary(): "DefaultDisplayMode": ("int", 0), "DefaultDrawStyle": ("int", 0), "DefaultPrintColor": ("unsigned", 255), + "DimAutoFlipText": ("bool", True), "Draft_array_fuse": ("bool", False), "Draft_array_Link": ("bool", True), "FilletRadius": ("float", 100.0), diff --git a/src/Mod/Draft/draftviewproviders/view_dimension.py b/src/Mod/Draft/draftviewproviders/view_dimension.py index 289c296916..7b5e898bb9 100644 --- a/src/Mod/Draft/draftviewproviders/view_dimension.py +++ b/src/Mod/Draft/draftviewproviders/view_dimension.py @@ -376,7 +376,7 @@ class ViewProviderLinearDimension(ViewProviderDimensionBase): vobj = obj.ViewObject if prop == "Diameter": - if hasattr(vobj, "Override") and vobj.Override: + if getattr(vobj, "Override", False): if obj.Diameter: vobj.Override = vobj.Override.replace("R $dim", "Ø $dim") else: @@ -503,7 +503,7 @@ class ViewProviderLinearDimension(ViewProviderDimensionBase): else: self.trot = (0, 0, 0, 1) - if hasattr(vobj, "FlipArrows") and vobj.FlipArrows: + if getattr(vobj, "FlipArrows", False): u = u.negative() v2 = norm.cross(u) @@ -535,7 +535,7 @@ class ViewProviderLinearDimension(ViewProviderDimensionBase): else: offset = DraftVecUtils.scaleTo(v1, 0.05) - if hasattr(vobj, "FlipText") and vobj.FlipText: + if getattr(vobj, "FlipText", False): _rott = App.Rotation(self.trot[0], self.trot[1], self.trot[2], self.trot[3]) self.trot = _rott.multiply(App.Rotation(App.Vector(0, 0, 1), 180)).Q offset = offset.negative() @@ -602,7 +602,7 @@ class ViewProviderLinearDimension(ViewProviderDimensionBase): None, 'Length', show_unit, unit) - if hasattr(vobj, "Override") and vobj.Override: + if getattr(vobj, "Override", False): self.string = vobj.Override.replace("$dim", self.string) self.text_wld.string = utils.string_encode_coin(self.string) @@ -935,7 +935,7 @@ class ViewProviderAngularDimension(ViewProviderDimensionBase): obj.LastAngle.Value) self.p2 = self.circle.Vertexes[0].Point self.p3 = self.circle.Vertexes[-1].Point - midp = DraftGeomUtils.findMidpoint(self.circle.Edges[0]) + midp = DraftGeomUtils.findMidpoint(self.circle) ray = midp - obj.Center # Set text value @@ -1085,12 +1085,16 @@ class ViewProviderAngularDimension(ViewProviderDimensionBase): r = App.Placement(_plane_rot_3).Rotation offset = r.multVec(App.Vector(0, 1, 0)) - if hasattr(vobj, "TextSpacing"): - offset = DraftVecUtils.scaleTo(offset, - vobj.TextSpacing.Value) + if hasattr(vobj, "TextSpacing") and hasattr(vobj, "ScaleMultiplier"): + ts = vobj.TextSpacing.Value * vobj.ScaleMultiplier + offset = DraftVecUtils.scaleTo(offset, ts) else: offset = DraftVecUtils.scaleTo(offset, 0.05) + if getattr(vobj, "FlipText", False): + r = r.multiply(App.Rotation(App.Vector(0, 0, 1), 180)) + offset = offset.negative() + if m == "Screen": offset = offset.negative()