Merge branch 'master' of github.com:FreeCAD/FreeCAD
This commit is contained in:
@@ -652,14 +652,14 @@ class Plane:
|
||||
if not geom_is_shape:
|
||||
FreeCAD.Console.PrintError(translate(
|
||||
"draft",
|
||||
"Object without Part.Shape geometry:'{}'\n".format(
|
||||
obj.ObjectName)))
|
||||
"Object without Part.Shape geometry:'{}'".format(
|
||||
obj.ObjectName)) + "\n")
|
||||
return False
|
||||
if geom.isNull():
|
||||
FreeCAD.Console.PrintError(translate(
|
||||
"draft",
|
||||
"Object with null Part.Shape geometry:'{}'\n".format(
|
||||
obj.ObjectName)))
|
||||
"Object with null Part.Shape geometry:'{}'".format(
|
||||
obj.ObjectName)) + "\n")
|
||||
return False
|
||||
if obj.HasSubObjects:
|
||||
shapes.extend(obj.SubObjects)
|
||||
@@ -672,7 +672,7 @@ class Plane:
|
||||
for n in range(len(shapes)):
|
||||
if not DraftGeomUtils.is_planar(shapes[n]):
|
||||
FreeCAD.Console.PrintError(translate(
|
||||
"draft","'{}' object is not planar\n".format(names[n])))
|
||||
"draft", "'{}' object is not planar".format(names[n])) + "\n")
|
||||
return False
|
||||
if not normal:
|
||||
normal = DraftGeomUtils.get_normal(shapes[n])
|
||||
@@ -683,8 +683,8 @@ class Plane:
|
||||
for n in range(len(shapes)):
|
||||
if not DraftGeomUtils.are_coplanar(shapes[shape_ref], shapes[n]):
|
||||
FreeCAD.Console.PrintError(translate(
|
||||
"draft","{} and {} aren't coplanar\n".format(
|
||||
names[shape_ref],names[n])))
|
||||
"draft", "{} and {} aren't coplanar".format(
|
||||
names[shape_ref],names[n])) + "\n")
|
||||
return False
|
||||
else:
|
||||
# suppose all geometries are straight lines or points
|
||||
@@ -693,7 +693,7 @@ class Plane:
|
||||
poly = Part.makePolygon(points)
|
||||
if not DraftGeomUtils.is_planar(poly):
|
||||
FreeCAD.Console.PrintError(translate(
|
||||
"draft","All Shapes must be coplanar\n"))
|
||||
"draft", "All Shapes must be coplanar") + "\n")
|
||||
return False
|
||||
normal = DraftGeomUtils.get_normal(poly)
|
||||
else:
|
||||
@@ -701,7 +701,7 @@ class Plane:
|
||||
|
||||
if not normal:
|
||||
FreeCAD.Console.PrintError(translate(
|
||||
"draft","Selected Shapes must define a plane\n"))
|
||||
"draft", "Selected Shapes must define a plane") + "\n")
|
||||
return False
|
||||
|
||||
# set center of mass
|
||||
|
||||
@@ -106,7 +106,7 @@ class Dimension(gui_base_original.Creator):
|
||||
self.arctrack = trackers.arcTracker()
|
||||
self.link = None
|
||||
self.edges = []
|
||||
self.pts = []
|
||||
self.angles = []
|
||||
self.angledata = None
|
||||
self.indices = []
|
||||
self.center = None
|
||||
@@ -397,7 +397,7 @@ class Dimension(gui_base_original.Creator):
|
||||
r = self.point.sub(self.center)
|
||||
self.arctrack.setRadius(r.Length)
|
||||
a = self.arctrack.getAngle(self.point)
|
||||
pair = DraftGeomUtils.getBoundaryAngles(a, self.pts)
|
||||
pair = DraftGeomUtils.getBoundaryAngles(a, self.angles)
|
||||
if not (pair[0] < a < pair[1]):
|
||||
self.angledata = [4 * math.pi - pair[0],
|
||||
2 * math.pi - pair[1]]
|
||||
@@ -504,8 +504,15 @@ class Dimension(gui_base_original.Creator):
|
||||
self.arctrack.setCenter(self.center)
|
||||
self.arctrack.on()
|
||||
for e in self.edges:
|
||||
for v in e.Vertexes:
|
||||
self.pts.append(self.arctrack.getAngle(v.Point))
|
||||
if e.Length < 0.00003: # Edge must be long enough for the tolerance of 0.00001mm to make sense.
|
||||
_msg(translate("draft", "Edge too short!"))
|
||||
self.finish()
|
||||
return
|
||||
for i in [0, 1]:
|
||||
pt = e.Vertexes[i].Point
|
||||
if pt.isEqual(self.center, 0.00001): # A relatively high tolerance is required.
|
||||
pt = e.Vertexes[i - 1].Point # Use the other point instead.
|
||||
self.angles.append(self.arctrack.getAngle(pt))
|
||||
self.link = [self.link[0], ob]
|
||||
else:
|
||||
_msg(translate("draft", "Edges don't intersect!"))
|
||||
|
||||
@@ -100,13 +100,15 @@ def make_sketch(objects_list, autoconstraints=False, addTo=None,
|
||||
if isinstance(obj,Part.Shape):
|
||||
shape = obj
|
||||
elif not hasattr(obj,'Shape'):
|
||||
App.Console.PrintError(translate("draft","No shape found\n"))
|
||||
App.Console.PrintError(translate("draft",
|
||||
"No shape found")+"\n")
|
||||
return None
|
||||
else:
|
||||
shape = obj.Shape
|
||||
|
||||
if not DraftGeomUtils.is_planar(shape, tol):
|
||||
App.Console.PrintError(translate("draft","All Shapes must be planar\n"))
|
||||
App.Console.PrintError(translate("draft",
|
||||
"All Shapes must be planar")+"\n")
|
||||
return None
|
||||
|
||||
if DraftGeomUtils.get_normal(shape, tol):
|
||||
@@ -121,7 +123,8 @@ def make_sketch(objects_list, autoconstraints=False, addTo=None,
|
||||
if len(shape_norm_yes) >= 1:
|
||||
for shape in shapes_list[1:]:
|
||||
if not DraftGeomUtils.are_coplanar(shapes_list[0], shape, tol):
|
||||
App.Console.PrintError(translate("draft","All Shapes must be coplanar\n"))
|
||||
App.Console.PrintError(translate("draft",
|
||||
"All Shapes must be coplanar")+"\n")
|
||||
return None
|
||||
# define sketch normal
|
||||
normal = DraftGeomUtils.get_normal(shapes_list[0], tol)
|
||||
@@ -132,7 +135,8 @@ def make_sketch(objects_list, autoconstraints=False, addTo=None,
|
||||
if len(points) >= 2:
|
||||
poly = Part.makePolygon(points)
|
||||
if not DraftGeomUtils.is_planar(poly, tol):
|
||||
App.Console.PrintError(translate("draft","All Shapes must be coplanar\n"))
|
||||
App.Console.PrintError(translate("draft",
|
||||
"All Shapes must be coplanar")+"\n")
|
||||
return None
|
||||
normal = DraftGeomUtils.get_normal(poly, tol)
|
||||
if not normal:
|
||||
|
||||
@@ -287,7 +287,7 @@ class Array(DraftLink):
|
||||
_tip = QT_TRANSLATE_NOOP("App::Property",
|
||||
"A parameter that determines "
|
||||
"how many symmetry planes "
|
||||
" the circular array will have.")
|
||||
"the circular array will have.")
|
||||
obj.addProperty("App::PropertyInteger",
|
||||
"Symmetry",
|
||||
"Circular array",
|
||||
@@ -380,7 +380,7 @@ class Array(DraftLink):
|
||||
obj.setPropertyStatus(pr, "Hidden")
|
||||
|
||||
def execute(self, obj):
|
||||
"""Execture when the object is created or recomputed."""
|
||||
"""Execute when the object is created or recomputed."""
|
||||
if not obj.Base:
|
||||
return
|
||||
|
||||
|
||||
@@ -163,7 +163,7 @@ class DimensionBase(DraftAnnotation):
|
||||
"There are various possibilities:\n"
|
||||
"- An object, and one of its edges.\n"
|
||||
"- An object, and two of its vertices.\n"
|
||||
"- An arc object, and its edge.\n")
|
||||
"- An arc object, and its edge.")
|
||||
obj.addProperty("App::PropertyLinkSubList",
|
||||
"LinkedGeometry",
|
||||
"Dimension",
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
# ***************************************************************************
|
||||
# * Copyright (c) 2014 Yorik van Havre <yorik@uncreated.net> *
|
||||
# * Copyright (c) 2020 Eliud Cabrera Castillo <e.cabrera-castillo@tum.de> *
|
||||
# * Copyright (c) 2021 FreeCAD Developers *
|
||||
# * *
|
||||
# * This file is part of the FreeCAD CAx development system. *
|
||||
# * *
|
||||
@@ -37,7 +38,7 @@ import FreeCAD as App
|
||||
import FreeCADGui as Gui
|
||||
|
||||
from draftutils.messages import _msg
|
||||
from draftutils.translate import translate
|
||||
from draftutils.translate import _tr
|
||||
from draftobjects.layer import Layer
|
||||
|
||||
|
||||
@@ -355,13 +356,13 @@ class ViewProviderLayer:
|
||||
def setupContextMenu(self, vobj, menu):
|
||||
"""Set up actions to perform in the context menu."""
|
||||
action1 = QtGui.QAction(QtGui.QIcon(":/icons/button_right.svg"),
|
||||
translate("draft", "Activate this layer"),
|
||||
_tr("Activate this layer"),
|
||||
menu)
|
||||
action1.triggered.connect(self.activate)
|
||||
menu.addAction(action1)
|
||||
|
||||
action2 = QtGui.QAction(QtGui.QIcon(":/icons/Draft_SelectGroup.svg"),
|
||||
translate("draft", "Select layer contents"),
|
||||
_tr("Select layer contents"),
|
||||
menu)
|
||||
action2.triggered.connect(self.select_contents)
|
||||
menu.addAction(action2)
|
||||
@@ -399,80 +400,76 @@ class ViewProviderLayerContainer:
|
||||
def setupContextMenu(self, vobj, menu):
|
||||
"""Set up actions to perform in the context menu."""
|
||||
action1 = QtGui.QAction(QtGui.QIcon(":/icons/Draft_Layer.svg"),
|
||||
translate("Draft", "Merge layer duplicates"),
|
||||
_tr("Merge layer duplicates"),
|
||||
menu)
|
||||
action1.triggered.connect(self.merge_by_name)
|
||||
menu.addAction(action1)
|
||||
action2 = QtGui.QAction(QtGui.QIcon(":/icons/Draft_NewLayer.svg"),
|
||||
translate("Draft", "Add new layer"),
|
||||
_tr("Add new layer"),
|
||||
menu)
|
||||
action2.triggered.connect(self.add_layer)
|
||||
menu.addAction(action2)
|
||||
|
||||
def merge_by_name(self):
|
||||
"""Merge the layers that have the same name."""
|
||||
"""Merge the layers that have the same base label."""
|
||||
if not hasattr(self, "Object") or not hasattr(self.Object, "Group"):
|
||||
return
|
||||
|
||||
obj = self.Object
|
||||
doc = App.ActiveDocument
|
||||
doc.openTransaction(_tr("Merge layer duplicates"))
|
||||
|
||||
layers = list()
|
||||
for iobj in obj.Group:
|
||||
if hasattr(iobj, "Proxy") and isinstance(iobj.Proxy, Layer):
|
||||
layers.append(iobj)
|
||||
layer_container = self.Object
|
||||
layers = []
|
||||
for obj in layer_container.Group:
|
||||
if hasattr(obj, "Proxy") and isinstance(obj.Proxy, Layer):
|
||||
layers.append(obj)
|
||||
|
||||
to_delete = list()
|
||||
to_delete = []
|
||||
for layer in layers:
|
||||
# Test the last three characters of the layer's Label to see
|
||||
# if it's a number, like `'Layer017'`
|
||||
if (layer.Label[-1].isdigit()
|
||||
and layer.Label[-2].isdigit()
|
||||
and layer.Label[-3].isdigit()):
|
||||
# If the object inside the layer has the same Label
|
||||
# as the layer, save this object
|
||||
orig = None
|
||||
for ol in layer.OutList:
|
||||
if ol.Label == layer.Label[:-3].strip():
|
||||
orig = ol
|
||||
break
|
||||
# Remove trailing digits (usually 3 but there might be more) and
|
||||
# trailing spaces from Label before comparing:
|
||||
base_label = layer.Label.rstrip("0123456789 ")
|
||||
|
||||
# Go into the objects that reference this layer object
|
||||
# and set the layer property with the previous `orig`
|
||||
# object found
|
||||
# Editor: when is this possible? Maybe if a layer is inside
|
||||
# another layer? Currently the code doesn't allow this
|
||||
# so maybe this was a previous behavior that was disabled
|
||||
# in `ViewProviderLayer`.
|
||||
if orig:
|
||||
for par in layer.InList:
|
||||
for prop in par.PropertiesList:
|
||||
if getattr(par, prop) == layer:
|
||||
_msg("Changed property '" + prop
|
||||
+ "' of object " + par.Label
|
||||
+ " from " + layer.Label
|
||||
+ " to " + orig.Label)
|
||||
setattr(par, prop, orig)
|
||||
to_delete.append(layer)
|
||||
# Try to find the `'base'` layer:
|
||||
base = None
|
||||
for other_layer in layers:
|
||||
if ((not other_layer in to_delete) # Required if there are duplicate labels.
|
||||
and other_layer != layer
|
||||
and other_layer.Label.upper() == base_label.upper()):
|
||||
base = other_layer
|
||||
break
|
||||
|
||||
if base:
|
||||
if layer.Group:
|
||||
base_group = base.Group
|
||||
for obj in layer.Group:
|
||||
if not obj in base_group:
|
||||
base_group.append(obj)
|
||||
base.Group = base_group
|
||||
to_delete.append(layer)
|
||||
elif layer.Label != base_label:
|
||||
_msg(_tr("Relabeling layer:")
|
||||
+ " '{}' -> '{}'".format(layer.Label, base_label))
|
||||
layer.Label = base_label
|
||||
|
||||
for layer in to_delete:
|
||||
if not layer.InList:
|
||||
_msg("Merging duplicate layer: " + layer.Label)
|
||||
App.ActiveDocument.removeObject(layer.Name)
|
||||
elif len(layer.InList) == 1:
|
||||
first = layer.InList[0]
|
||||
_msg(_tr("Merging layer:") + " '{}'".format(layer.Label))
|
||||
doc.removeObject(layer.Name)
|
||||
|
||||
if first.isDerivedFrom("App::DocumentObjectGroup"):
|
||||
_msg("Merging duplicate layer: " + layer.Label)
|
||||
App.ActiveDocument.removeObject(layer.Name)
|
||||
else:
|
||||
_msg("InList not empty. "
|
||||
"Unable to delete layer: " + layer.Label)
|
||||
doc.recompute()
|
||||
doc.commitTransaction()
|
||||
|
||||
def add_layer(self):
|
||||
"""Creates a new layer"""
|
||||
import Draft
|
||||
|
||||
doc = App.ActiveDocument
|
||||
doc.openTransaction(_tr("Add new layer"))
|
||||
|
||||
Draft.make_layer()
|
||||
App.ActiveDocument.recompute()
|
||||
|
||||
doc.recompute()
|
||||
doc.commitTransaction()
|
||||
|
||||
def __getstate__(self):
|
||||
"""Return a tuple of objects to save or None."""
|
||||
|
||||
Reference in New Issue
Block a user