Merge branch 'master' into master
This commit is contained in:
@@ -1241,14 +1241,14 @@ class _Wall(ArchComponent.Component):
|
||||
# in some corner case != getSortedClusters()
|
||||
elif obj.Base.isDerivedFrom("Sketcher::SketchObject"):
|
||||
self.basewires = []
|
||||
skGeom = obj.Base.Geometry
|
||||
skGeom = obj.Base.GeometryFacadeList
|
||||
skGeomEdges = []
|
||||
skPlacement = obj.Base.Placement # Get Sketch's placement to restore later
|
||||
for i in skGeom:
|
||||
if not i.Construction:
|
||||
# support Line, Arc, Circle for Sketch as Base at the moment
|
||||
if isinstance(i, (Part.LineSegment, Part.Circle, Part.ArcOfCircle)):
|
||||
skGeomEdgesI = i.toShape()
|
||||
if isinstance(i.Geometry, (Part.LineSegment, Part.Circle, Part.ArcOfCircle)):
|
||||
skGeomEdgesI = i.Geometry.toShape()
|
||||
skGeomEdges.append(skGeomEdgesI)
|
||||
for cluster in Part.getSortedClusters(skGeomEdges):
|
||||
clusterTransformed = []
|
||||
|
||||
@@ -1107,6 +1107,7 @@ class DraftToolBar:
|
||||
self.continueCmd.show()
|
||||
|
||||
def modUi(self):
|
||||
self.undoButton.hide()
|
||||
self.isCopy.show()
|
||||
self.isSubelementMode.show()
|
||||
p = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Draft")
|
||||
|
||||
@@ -42,6 +42,7 @@ import draftmake.make_block as make_block
|
||||
|
||||
from draftutils.messages import _msg, _err
|
||||
from draftutils.translate import _tr
|
||||
from draftgeoutils.geometry import is_straight_line
|
||||
|
||||
# Delay import of module until first use because it is heavy
|
||||
Part = lz.LazyLoader("Part", globals(), "Part")
|
||||
@@ -160,6 +161,8 @@ def upgrade(objects, delete=False, force=None):
|
||||
return None
|
||||
if len(obj.Shape.Edges) == 1:
|
||||
return None
|
||||
if is_straight_line(obj.Shape) == True:
|
||||
return None
|
||||
if utils.get_type(obj) == "Wire":
|
||||
obj.Closed = True
|
||||
return True
|
||||
@@ -333,26 +336,35 @@ def upgrade(objects, delete=False, force=None):
|
||||
def makeWires(objectslist):
|
||||
"""Join edges in the given objects list into wires."""
|
||||
edges = []
|
||||
for o in objectslist:
|
||||
for e in o.Shape.Edges:
|
||||
edges.append(e)
|
||||
for object in objectslist:
|
||||
for edge in object.Shape.Edges:
|
||||
edges.append(edge)
|
||||
|
||||
try:
|
||||
nedges = Part.__sortEdges__(edges[:])
|
||||
sorted_edges = Part.sortEdges(edges)
|
||||
if _DEBUG:
|
||||
for e in nedges:
|
||||
print("Curve: {}".format(e.Curve))
|
||||
print("first: {}, last: {}".format(e.Vertexes[0].Point,
|
||||
for item_sorted_edges in sorted_edges:
|
||||
for e in item_sorted_edges:
|
||||
print("Curve: {}".format(e.Curve))
|
||||
print("first: {}, last: {}".format(e.Vertexes[0].Point,
|
||||
e.Vertexes[-1].Point))
|
||||
w = Part.Wire(nedges)
|
||||
wires = [Part.Wire(e) for e in sorted_edges]
|
||||
except Part.OCCError:
|
||||
return None
|
||||
else:
|
||||
if len(w.Edges) == len(edges):
|
||||
for wire in wires:
|
||||
newobj = doc.addObject("Part::Feature", "Wire")
|
||||
newobj.Shape = w
|
||||
newobj.Shape = wire
|
||||
add_list.append(newobj)
|
||||
delete_list.extend(objectslist)
|
||||
return True
|
||||
# delete object only if there are no links to it
|
||||
# TODO: A more refined criteria to delete object
|
||||
for object in objectslist:
|
||||
if object.InList:
|
||||
if App.GuiUp:
|
||||
object.ViewObject.Visibility = False
|
||||
else:
|
||||
delete_list.append(object)
|
||||
return True
|
||||
return None
|
||||
|
||||
# analyzing what we have in our selection
|
||||
@@ -475,54 +487,56 @@ def upgrade(objects, delete=False, force=None):
|
||||
_msg(_tr("Found 1 non-parametric objects: "
|
||||
"draftifying it"))
|
||||
|
||||
# we have only one object that contains one edge
|
||||
elif not faces and len(objects) == 1 and len(edges) == 1:
|
||||
# we have a closed sketch: extract a face
|
||||
if (objects[0].isDerivedFrom("Sketcher::SketchObject")
|
||||
and len(edges[0].Vertexes) == 1):
|
||||
result = makeSketchFace(objects[0])
|
||||
# in the following cases there are no faces
|
||||
elif not faces:
|
||||
# we have only closed wires
|
||||
if wires and not openwires and not loneedges:
|
||||
# we have a sketch: extract a face
|
||||
if (len(objects) == 1
|
||||
and objects[0].isDerivedFrom("Sketcher::SketchObject")):
|
||||
result = makeSketchFace(objects[0])
|
||||
if result:
|
||||
_msg(_tr("Found 1 closed sketch object: "
|
||||
"creating a face from it"))
|
||||
# only closed wires
|
||||
else:
|
||||
result = makeFaces(objects)
|
||||
if result:
|
||||
_msg(_tr("Found closed wires: creating faces"))
|
||||
# wires or edges: we try to join them
|
||||
elif len(wires) > 1 or len(loneedges) > 1:
|
||||
result = makeWires(objects)
|
||||
if result:
|
||||
_msg(_tr("Found 1 closed sketch object: "
|
||||
"creating a face from it"))
|
||||
else:
|
||||
_msg(_tr("Found several wires or edges: wiring them"))
|
||||
# TODO: improve draftify function
|
||||
# only one object: if not parametric, we "draftify" it
|
||||
# elif (len(objects) == 1
|
||||
# and not objects[0].isDerivedFrom("Part::Part2DObjectPython")):
|
||||
# result = ext_draftify.draftify(objects[0])
|
||||
# if result:
|
||||
# _msg(_tr("Found 1 non-parametric objects: "
|
||||
# "draftifying it"))
|
||||
# special case, we have only one open wire. We close it,
|
||||
# unless it has only 1 edge!
|
||||
elif len(objects) == 1 and len(openwires) == 1:
|
||||
result = closeWire(objects[0])
|
||||
_msg(_tr("trying: closing it"))
|
||||
if result:
|
||||
_msg(_tr("Found 1 open wire: closing it"))
|
||||
# we have only one object that contains one edge
|
||||
# TODO: this case should be considered in draftify
|
||||
elif len(objects) == 1 and len(edges) == 1:
|
||||
# turn to Draft Line
|
||||
e = objects[0].Shape.Edges[0]
|
||||
if isinstance(e.Curve, (Part.LineSegment, Part.Line)):
|
||||
result = turnToLine(objects[0])
|
||||
if result:
|
||||
_msg(_tr("Found 1 linear object: converting to line"))
|
||||
|
||||
# we have only closed wires, no faces
|
||||
elif wires and not faces and not openwires:
|
||||
# we have a sketch: extract a face
|
||||
if (len(objects) == 1
|
||||
and objects[0].isDerivedFrom("Sketcher::SketchObject")):
|
||||
result = makeSketchFace(objects[0])
|
||||
# only points, no edges
|
||||
elif not edges and len(objects) > 1:
|
||||
result = makeCompound(objects)
|
||||
if result:
|
||||
_msg(_tr("Found 1 closed sketch object: "
|
||||
"creating a face from it"))
|
||||
# only closed wires
|
||||
else:
|
||||
result = makeFaces(objects)
|
||||
if result:
|
||||
_msg(_tr("Found closed wires: creating faces"))
|
||||
|
||||
# special case, we have only one open wire. We close it,
|
||||
# unless it has only 1 edge!
|
||||
elif len(openwires) == 1 and not faces and not loneedges:
|
||||
result = closeWire(objects[0])
|
||||
if result:
|
||||
_msg(_tr("Found 1 open wire: closing it"))
|
||||
# only open wires and edges: we try to join their edges
|
||||
elif openwires and not wires and not faces:
|
||||
result = makeWires(objects)
|
||||
if result:
|
||||
_msg(_tr("Found several open wires: joining them"))
|
||||
# only loneedges: we try to join them
|
||||
elif loneedges and not facewires:
|
||||
result = makeWires(objects)
|
||||
if result:
|
||||
_msg(_tr("Found several edges: wiring them"))
|
||||
_msg(_tr("Found points: creating compound"))
|
||||
# all other cases, if more than 1 object, make a compound
|
||||
elif len(objects) > 1:
|
||||
result = makeCompound(objects)
|
||||
|
||||
@@ -53,21 +53,21 @@ class ScaleTaskPanel:
|
||||
layout.addWidget(self.xLabel, 0, 0, 1, 1)
|
||||
self.xValue = QtGui.QDoubleSpinBox()
|
||||
self.xValue.setRange(0.0000001, 1000000.0)
|
||||
self.xValue.setDecimals(Draft.getParam("precision"))
|
||||
self.xValue.setDecimals(Draft.precision())
|
||||
self.xValue.setValue(1)
|
||||
layout.addWidget(self.xValue,0,1,1,1)
|
||||
self.yLabel = QtGui.QLabel()
|
||||
layout.addWidget(self.yLabel,1,0,1,1)
|
||||
self.yValue = QtGui.QDoubleSpinBox()
|
||||
self.yValue.setRange(.0000001,1000000.0)
|
||||
self.yValue.setDecimals(Draft.getParam("precision"))
|
||||
self.yValue.setDecimals(Draft.precision())
|
||||
self.yValue.setValue(1)
|
||||
layout.addWidget(self.yValue,1,1,1,1)
|
||||
self.zLabel = QtGui.QLabel()
|
||||
layout.addWidget(self.zLabel,2,0,1,1)
|
||||
self.zValue = QtGui.QDoubleSpinBox()
|
||||
self.zValue.setRange(.0000001,1000000.0)
|
||||
self.zValue.setDecimals(Draft.getParam("precision"))
|
||||
self.zValue.setDecimals(Draft.precision())
|
||||
self.zValue.setValue(1)
|
||||
layout.addWidget(self.zValue,2,1,1,1)
|
||||
self.lock = QtGui.QCheckBox()
|
||||
|
||||
@@ -232,7 +232,7 @@ class DraftModification(unittest.TestCase):
|
||||
self.assertTrue(obj, "'{}' failed".format(operation))
|
||||
|
||||
def test_upgrade(self):
|
||||
"""Upgrade two Draft Lines into a closed Draft Wire."""
|
||||
"""Upgrade two Lines into a closed Wire, then draftify it."""
|
||||
operation = "Draft Upgrade"
|
||||
_msg(" Test '{}'".format(operation))
|
||||
a = Vector(0, 0, 0)
|
||||
@@ -242,8 +242,12 @@ class DraftModification(unittest.TestCase):
|
||||
_msg(" a={0}, b={1}".format(a, b))
|
||||
_msg(" Line 2")
|
||||
_msg(" b={0}, c={1}".format(b, c))
|
||||
line_1 = Draft.make_line(a, b)
|
||||
line_2 = Draft.make_line(b, c)
|
||||
shape_line_1 = Part.makeLine(a, b)
|
||||
shape_line_2 = Part.makeLine(b, c)
|
||||
line_1 = App.ActiveDocument.addObject("Part::Feature")
|
||||
line_2 = App.ActiveDocument.addObject("Part::Feature")
|
||||
line_1.Shape = shape_line_1
|
||||
line_2.Shape = shape_line_2
|
||||
App.ActiveDocument.recompute()
|
||||
|
||||
obj = Draft.upgrade([line_1, line_2], delete=True)
|
||||
@@ -255,8 +259,7 @@ class DraftModification(unittest.TestCase):
|
||||
obj2 = Draft.upgrade(obj[0], delete=True)
|
||||
App.ActiveDocument.recompute()
|
||||
s2 = obj2[0][0]
|
||||
_msg(" 2: Result '{0}' ({1})".format(s2.Shape.ShapeType,
|
||||
s2.TypeId))
|
||||
_msg(" 2: Result '{0}' ({1})".format(s2.Shape.ShapeType, s2.TypeId))
|
||||
self.assertTrue(bool(obj2[0]), "'{}' failed".format(operation))
|
||||
|
||||
obj3 = Draft.upgrade(obj2[0], delete=True)
|
||||
@@ -265,10 +268,15 @@ class DraftModification(unittest.TestCase):
|
||||
_msg(" 3: Result '{0}' ({1})".format(s3.Shape.ShapeType, s3.TypeId))
|
||||
self.assertTrue(bool(obj3[0]), "'{}' failed".format(operation))
|
||||
|
||||
obj4 = Draft.upgrade(obj3[0], delete=True)
|
||||
# when draftify, upgrade dont return a new object
|
||||
Draft.upgrade(obj3[0], delete=True)
|
||||
App.ActiveDocument.recompute()
|
||||
wire = App.ActiveDocument.Wire
|
||||
_msg(" 4: Result '{0}' ({1})".format(wire.Proxy.Type, wire.TypeId))
|
||||
self.assertTrue(bool(wire), "'{}' failed".format(operation))
|
||||
|
||||
obj4 = Draft.upgrade(wire, delete=True)
|
||||
App.ActiveDocument.recompute()
|
||||
_msg(" The last object cannot be upgraded further")
|
||||
self.assertFalse(bool(obj4[0]), "'{}' failed".format(operation))
|
||||
|
||||
|
||||
@@ -157,9 +157,9 @@ def process(doc, filename):
|
||||
with the parsed information.
|
||||
"""
|
||||
# Regex to identify data rows and throw away unused metadata
|
||||
xval = '(?P<xval>(\-|\d*)\.\d+(E\-?\d+)?)'
|
||||
yval = '(?P<yval>\-?\s*\d*\.\d+(E\-?\d+)?)'
|
||||
_regex = '^\s*' + xval + '\,?\s*' + yval + '\s*$'
|
||||
xval = r'(?P<xval>(\-|\d*)\.*\d*([Ee]\-?\d+)?)'
|
||||
yval = r'(?P<yval>\-?\s*\d*\.*\d*([Ee]\-?\d+)?)'
|
||||
_regex = r'^\s*' + xval + r'\,?\s*' + yval + r'\s*$'
|
||||
|
||||
regex = re.compile(_regex)
|
||||
afile = pythonopen(filename, 'r')
|
||||
|
||||
@@ -171,6 +171,8 @@
|
||||
# include <APIHeaderSection_MakeHeader.hxx>
|
||||
# include <ShapeAnalysis_FreeBoundsProperties.hxx>
|
||||
# include <ShapeAnalysis_FreeBoundData.hxx>
|
||||
# include <BRepLProp_SLProps.hxx>
|
||||
# include <BRepGProp_Face.hxx>
|
||||
|
||||
#if OCC_VERSION_HEX < 0x070300
|
||||
# include <BRepAlgo_Fuse.hxx>
|
||||
@@ -4161,26 +4163,13 @@ bool TopoShape::findPlane(gp_Pln &pln, double tol) const {
|
||||
if(_Shape.IsNull())
|
||||
return false;
|
||||
TopoDS_Shape shape = _Shape;
|
||||
TopExp_Explorer exp(_Shape,TopAbs_FACE);
|
||||
TopExp_Explorer exp(_Shape,TopAbs_EDGE);
|
||||
if(exp.More()) {
|
||||
auto face = exp.Current();
|
||||
TopoDS_Shape edge = exp.Current();
|
||||
exp.Next();
|
||||
if(!exp.More()) {
|
||||
BRepAdaptor_Surface adapt(TopoDS::Face(face));
|
||||
if(adapt.GetType() != GeomAbs_Plane)
|
||||
return false;
|
||||
pln = adapt.Plane();
|
||||
return true;
|
||||
}
|
||||
}else{
|
||||
TopExp_Explorer exp(_Shape,TopAbs_EDGE);
|
||||
if(exp.More()) {
|
||||
TopoDS_Shape edge = exp.Current();
|
||||
exp.Next();
|
||||
if(!exp.More()) {
|
||||
// To deal with OCCT bug of wrong edge transformation
|
||||
shape = BRepBuilderAPI_Copy(edge).Shape();
|
||||
}
|
||||
if (!exp.More()) {
|
||||
// To deal with OCCT bug of wrong edge transformation
|
||||
shape = BRepBuilderAPI_Copy(_Shape).Shape();
|
||||
}
|
||||
}
|
||||
try {
|
||||
@@ -4188,6 +4177,24 @@ bool TopoShape::findPlane(gp_Pln &pln, double tol) const {
|
||||
if (!finder.Found())
|
||||
return false;
|
||||
pln = GeomAdaptor_Surface(finder.Surface()).Plane();
|
||||
|
||||
// To make the returned plane normal more stable, if the shape has any
|
||||
// face, use the normal of the first face.
|
||||
TopExp_Explorer exp(shape, TopAbs_FACE);
|
||||
if(exp.More()) {
|
||||
BRepAdaptor_Surface adapt(TopoDS::Face(exp.Current()));
|
||||
double u = adapt.FirstUParameter()
|
||||
+ (adapt.LastUParameter() - adapt.FirstUParameter())/2.;
|
||||
double v = adapt.FirstVParameter()
|
||||
+ (adapt.LastVParameter() - adapt.FirstVParameter())/2.;
|
||||
BRepLProp_SLProps prop(adapt,u,v,2,Precision::Confusion());
|
||||
if(prop.IsNormalDefined()) {
|
||||
gp_Pnt pnt; gp_Vec vec;
|
||||
// handles the orientation state of the shape
|
||||
BRepGProp_Face(TopoDS::Face(exp.Current())).Normal(u,v,pnt,vec);
|
||||
pln = gp_Pln(pnt, gp_Dir(vec));
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}catch (Standard_Failure &e) {
|
||||
// For some reason the above BRepBuilderAPI_Copy failed to copy
|
||||
|
||||
@@ -2963,20 +2963,19 @@ std::list<TopoDS_Shape> Area::sortWires(const std::list<TopoDS_Shape> &shapes,
|
||||
pstart = *_pstart;
|
||||
bool use_bound = !has_start || _pstart==NULL;
|
||||
|
||||
if(use_bound || sort_mode == SortMode2D5 || sort_mode == SortModeGreedy) {
|
||||
//Second stage, group shape by its plane, and find overall boundary
|
||||
//Second stage, group shape by its plane, and find overall boundary
|
||||
|
||||
if(arcPlaneFound || use_bound) {
|
||||
for(auto &info : shape_list) {
|
||||
if(arcPlaneFound) {
|
||||
info.myShape.Move(trsf);
|
||||
if(info.myPlanar) info.myPln.Transform(trsf);
|
||||
}
|
||||
if(use_bound)
|
||||
BRepBndLib::Add(info.myShape, bounds, Standard_False);
|
||||
}
|
||||
for(auto &info : shape_list) {
|
||||
if(arcPlaneFound) {
|
||||
info.myShape.Move(trsf);
|
||||
if(info.myPlanar) info.myPln.Transform(trsf);
|
||||
}
|
||||
|
||||
BRepBndLib::Add(info.myShape, bounds, Standard_False);
|
||||
}
|
||||
|
||||
if(use_bound || sort_mode == SortMode2D5 || sort_mode == SortModeGreedy) {
|
||||
|
||||
for(auto itNext=shape_list.begin(),it=itNext;it!=shape_list.end();it=itNext) {
|
||||
++itNext;
|
||||
if(!it->myPlanar) continue;
|
||||
@@ -3005,16 +3004,36 @@ std::list<TopoDS_Shape> Area::sortWires(const std::list<TopoDS_Shape> &shapes,
|
||||
|
||||
//FC_DURATION_DECL_INIT(td);
|
||||
|
||||
bounds.SetGap(0.0);
|
||||
Standard_Real xMin, yMin, zMin, xMax, yMax, zMax;
|
||||
bounds.Get(xMin, yMin, zMin, xMax, yMax, zMax);
|
||||
AREA_TRACE("bound (" << xMin<<", "<<xMax<<"), ("<<
|
||||
yMin<<", "<<yMax<<"), ("<<zMin<<", "<<zMax<<')');
|
||||
|
||||
if(use_bound) {
|
||||
bounds.SetGap(0.0);
|
||||
Standard_Real xMin, yMin, zMin, xMax, yMax, zMax;
|
||||
bounds.Get(xMin, yMin, zMin, xMax, yMax, zMax);
|
||||
AREA_TRACE("bound (" << xMin<<", "<<xMax<<"), ("<<
|
||||
yMin<<", "<<yMax<<"), ("<<zMin<<", "<<zMax<<')');
|
||||
pstart.SetCoord(xMax,yMax,zMax);
|
||||
if(_pstart) *_pstart = pstart;
|
||||
}else{
|
||||
switch(retract_axis) {
|
||||
case RetractAxisX:
|
||||
if (pstart.X()<xMax){
|
||||
pstart.SetX(xMax);
|
||||
}
|
||||
break;
|
||||
case RetractAxisY:
|
||||
if (pstart.Y()<yMax){
|
||||
pstart.SetY(yMax);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
if (pstart.Z()<zMax){
|
||||
pstart.SetZ(zMax);
|
||||
}
|
||||
}
|
||||
if(_pstart) *_pstart = pstart;
|
||||
}
|
||||
|
||||
|
||||
gp_Pln pln;
|
||||
double hint = 0.0;
|
||||
bool hint_first = true;
|
||||
|
||||
@@ -103,12 +103,12 @@ int TooltablePy::PyInit(PyObject* args, PyObject* /*kwd*/)
|
||||
|
||||
Py::Dict TooltablePy::getTools(void) const
|
||||
{
|
||||
PyObject *dict = PyDict_New();
|
||||
Py::Dict dict;
|
||||
for(std::map<int,Path::Tool*>::iterator i = getTooltablePtr()->Tools.begin(); i != getTooltablePtr()->Tools.end(); ++i) {
|
||||
PyObject *tool = new Path::ToolPy(i->second);
|
||||
PyDict_SetItem(dict,PYINT_FROMLONG(i->first),tool);
|
||||
dict.setItem(Py::Long(i->first), Py::asObject(tool));
|
||||
}
|
||||
return Py::Dict(dict);
|
||||
return dict;
|
||||
}
|
||||
|
||||
void TooltablePy::setTools(Py::Dict arg)
|
||||
|
||||
@@ -30,6 +30,7 @@ import copy
|
||||
# lazily loaded modules
|
||||
from lazy_loader.lazy_loader import LazyLoader
|
||||
DraftGeomUtils = LazyLoader('DraftGeomUtils', globals(), 'DraftGeomUtils')
|
||||
Part = LazyLoader('Part', globals(), 'Part')
|
||||
|
||||
from PySide import QtCore
|
||||
|
||||
@@ -69,9 +70,11 @@ class ObjectOp(PathOp.ObjectOp):
|
||||
|
||||
# reorder the wire
|
||||
if hasattr(obj, 'StartVertex'):
|
||||
offset = DraftGeomUtils.rebaseWire(offset, obj.StartVertex)
|
||||
start_idx = obj.StartVertex
|
||||
|
||||
edges = copy.copy(PathOpTools.orientWire(offset, forward).Edges)
|
||||
edges = Part.sortEdges(edges)[0];
|
||||
|
||||
last = None
|
||||
|
||||
for z in zValues:
|
||||
|
||||
@@ -253,6 +253,8 @@ class ToolControllerEditor(object):
|
||||
self.form.vertFeed.editingFinished.connect(self.refresh)
|
||||
self.form.horizRapid.editingFinished.connect(self.refresh)
|
||||
self.form.vertRapid.editingFinished.connect(self.refresh)
|
||||
self.form.spindleSpeed.editingFinished.connect(self.refresh)
|
||||
self.form.spindleDirection.currentIndexChanged.connect(self.refresh)
|
||||
|
||||
|
||||
class TaskPanel:
|
||||
|
||||
@@ -105,11 +105,16 @@ DrawViewBalloon::DrawViewBalloon(void)
|
||||
ADD_PROPERTY_TYPE(ShapeScale,(1.0),"",(App::PropertyType)(App::Prop_None),"Balloon shape scale");
|
||||
ShapeScale.setConstraints(&SymbolScaleRange);
|
||||
|
||||
ADD_PROPERTY_TYPE(EndTypeScale,(1.0),"",(App::PropertyType)(App::Prop_None),"EndType shape scale");
|
||||
ShapeScale.setConstraints(&SymbolScaleRange);
|
||||
|
||||
ADD_PROPERTY_TYPE(TextWrapLen,(-1),"",(App::PropertyType)(App::Prop_None),"Text wrap length; -1 means no wrap");
|
||||
|
||||
ADD_PROPERTY_TYPE(KinkLength,(prefKinkLength()),"",(App::PropertyType)(App::Prop_None),
|
||||
"Distance from symbol to leader kink");
|
||||
|
||||
ADD_PROPERTY_TYPE(LineVisible,(true),"",(App::PropertyType)(App::Prop_None),"Balloon line visible or hidden");
|
||||
|
||||
SourceView.setScope(App::LinkScope::Global);
|
||||
Rotation.setStatus(App::Property::Hidden,true);
|
||||
Caption.setStatus(App::Property::Hidden,true);
|
||||
|
||||
@@ -49,15 +49,17 @@ public:
|
||||
DrawViewBalloon();
|
||||
virtual ~DrawViewBalloon();
|
||||
|
||||
App::PropertyLink SourceView;
|
||||
App::PropertyString Text;
|
||||
App::PropertyEnumeration EndType;
|
||||
App::PropertyEnumeration BubbleShape;
|
||||
App::PropertyLink SourceView;
|
||||
App::PropertyString Text;
|
||||
App::PropertyEnumeration EndType;
|
||||
App::PropertyEnumeration BubbleShape;
|
||||
App::PropertyFloatConstraint ShapeScale;
|
||||
App::PropertyDistance OriginX;
|
||||
App::PropertyDistance OriginY;
|
||||
App::PropertyFloat TextWrapLen;
|
||||
App::PropertyDistance KinkLength;
|
||||
App::PropertyFloatConstraint EndTypeScale;
|
||||
App::PropertyDistance OriginX;
|
||||
App::PropertyDistance OriginY;
|
||||
App::PropertyFloat TextWrapLen;
|
||||
App::PropertyDistance KinkLength;
|
||||
App::PropertyBool LineVisible;
|
||||
|
||||
short mustExecute() const override;
|
||||
|
||||
|
||||
@@ -691,21 +691,12 @@ std::string DrawViewDimension::formatValue(qreal value, QString qFormatSpec, int
|
||||
// - the value in the base unit but without displayed unit
|
||||
// - the value + unit (not necessarily the base unit!)
|
||||
// the user can overwrite the decimal settings, so we must in every case use the formatSpecifier
|
||||
// if useDecimals(), then formatSpecifier = global decimals, otherwise it is %.2f
|
||||
// the default is: if useDecimals(), then formatSpecifier = global decimals, otherwise it is %.2f
|
||||
QLocale loc;
|
||||
double userVal;
|
||||
bool checkDecimals = true;
|
||||
if (showUnits() || (Type.isValue("Angle")) || (Type.isValue("Angle3Pt"))) {
|
||||
formattedValue = qUserString; // result value + unit (not necessarily base unit!)
|
||||
// remove unit
|
||||
formattedValue.remove(rxUnits);
|
||||
// to number
|
||||
userVal = loc.toDouble(formattedValue);
|
||||
if (userVal >= 1.0)
|
||||
// we can assure we didn't make an error > 10% via getUserString()
|
||||
checkDecimals = false;
|
||||
}
|
||||
if (checkDecimals){
|
||||
userVal = asQuantity.getValue();
|
||||
} else {
|
||||
// get value in the base unit with default decimals
|
||||
// for the conversion we use the same method as in DlgUnitsCalculator::valueChanged
|
||||
// get the conversion factor for the unit
|
||||
@@ -750,7 +741,6 @@ std::string DrawViewDimension::formatValue(qreal value, QString qFormatSpec, int
|
||||
//qUserString from Quantity includes units - prefix + R + nnn ft + suffix
|
||||
qMultiValueStr = formatPrefix + qGenPrefix + qUserString + formatSuffix;
|
||||
}
|
||||
|
||||
formattedValue = qMultiValueStr;
|
||||
}
|
||||
|
||||
|
||||
@@ -193,7 +193,11 @@ private:
|
||||
} else {
|
||||
vpp->showMDIViewPage();
|
||||
mdi = vpp->getMDIViewPage();
|
||||
mdi->printPdf(filePath);
|
||||
if (mdi) {
|
||||
mdi->printPdf(filePath);
|
||||
} else {
|
||||
throw Py::TypeError("Page not available! Is it Hidden?");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -234,7 +238,11 @@ private:
|
||||
} else {
|
||||
vpp->showMDIViewPage();
|
||||
mdi = vpp->getMDIViewPage();
|
||||
mdi->saveSVG(filePath);
|
||||
if (mdi) {
|
||||
mdi->saveSVG(filePath);
|
||||
} else {
|
||||
throw Py::TypeError("Page not available! Is it Hidden?");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -717,14 +717,14 @@ void QGIViewBalloon::draw()
|
||||
double yAdj = 0.0;
|
||||
int endType = balloon->EndType.getValue();
|
||||
double arrowAdj = QGIArrow::getOverlapAdjust(endType,
|
||||
QGIArrow::getPrefArrowSize());
|
||||
balloon->EndTypeScale.getValue()*QGIArrow::getPrefArrowSize());
|
||||
|
||||
if (endType == ArrowType::NONE) {
|
||||
arrow->hide();
|
||||
} else {
|
||||
arrow->setStyle(endType);
|
||||
|
||||
arrow->setSize(QGIArrow::getPrefArrowSize());
|
||||
arrow->setSize(balloon->EndTypeScale.getValue()*QGIArrow::getPrefArrowSize());
|
||||
arrow->draw();
|
||||
|
||||
Base::Vector3d arrowTipPos(arrowTipX, arrowTipY, 0.0);
|
||||
@@ -738,7 +738,7 @@ void QGIViewBalloon::draw()
|
||||
float arAngle = atan2(dirballoonLinesLine.y, dirballoonLinesLine.x) * 180 / M_PI;
|
||||
|
||||
arrow->setPos(arrowTipX, arrowTipY);
|
||||
if ( (endType == ArrowType::FILLED_TRIANGLE) &&
|
||||
if ( (endType == ArrowType::FILLED_TRIANGLE) &&
|
||||
(prefOrthoPyramid()) ) {
|
||||
if (arAngle < 0.0) {
|
||||
arAngle += 360.0;
|
||||
@@ -765,6 +765,12 @@ void QGIViewBalloon::draw()
|
||||
dLinePath.lineTo(arrowTipX - xAdj, arrowTipY - yAdj);
|
||||
balloonLines->setPath(dLinePath);
|
||||
|
||||
// This overwrites the previously created QPainterPath with empty one, in case it should be hidden. Should be refactored.
|
||||
if (!balloon->LineVisible.getValue()) {
|
||||
arrow->hide();
|
||||
balloonLines->setPath(QPainterPath());
|
||||
}
|
||||
|
||||
// redraw the Balloon and the parent View
|
||||
if (hasHover && !isSelected()) {
|
||||
setPrettyPre();
|
||||
|
||||
Reference in New Issue
Block a user