Part: changes to Part Module
* Added Part::Feature::getTopoShape/getShape() function that can obtain
shape from any object with proper implementation of getSubObject(). It
can even construct compound from group object with proper implementation
of getSubObjects().
* Modified ViewProviderExt to work on any object, because it now obtain
the shape using Part::Feature::getShape()
* Modified various Part features to obtain base/tool shapes using
Part::getShape(), which allows them to be any type of object,
including Link and groups.
* Modified various Part command to relax type requirement on selected
objects.
* Add support of link and group to dimension, and add dimension refresh
command
* Support link and group in simple command command, and add a few more
copy command variations.
* Add special handling of 'Shape' attribute in PropertyContainerPy and
use Part::Feature::getShape() to return shape for any object without
Shape property. This allows many python feature work with any object
without modification.
* GeometrySurface/CurvePy, add convenience attribute 'Rotation'
* TopoShapePy:
* Extended support of sub shape attribute, e.g. Compound1, Solid2,
SubShape3 ('SubShape' is used to access child shape of a compound)
* makeWires(), new API to sort and return wires given a list of edges.
* transformed/translated/rotated/scaled(), return a new shape with
some transformation.
* findPlane(), find the plane of a planar shape
* isCoplanar(), check if two shape are coplanar
This commit is contained in:
@@ -515,6 +515,8 @@ public:
|
||||
*/
|
||||
virtual int canLoadPartial() const {return 0;}
|
||||
|
||||
virtual void onUpdateElementReference(const Property *) {}
|
||||
|
||||
/** Allow object to redirect a subname path
|
||||
*
|
||||
* @param ss: input as the current subname path from \a topParent leading
|
||||
|
||||
@@ -506,6 +506,27 @@ PyObject *PropertyContainerPy::getCustomAttributes(const char* attr) const
|
||||
}
|
||||
}
|
||||
return dict;
|
||||
} else if(Base::streq(attr,"Shape")
|
||||
&& getPropertyContainerPtr()->isDerivedFrom(App::DocumentObject::getClassTypeId()))
|
||||
{
|
||||
// Special treatment of Shape property
|
||||
static PyObject *_getShape = 0;
|
||||
if(!_getShape) {
|
||||
_getShape = Py_None;
|
||||
PyObject *mod = PyImport_ImportModule("Part");
|
||||
if(!mod) {
|
||||
PyErr_Clear();
|
||||
} else {
|
||||
Py::Object pyMod = Py::asObject(mod);
|
||||
if(pyMod.hasAttr("getShape"))
|
||||
_getShape = Py::new_reference_to(pyMod.getAttr("getShape"));
|
||||
}
|
||||
}
|
||||
if(_getShape != Py_None) {
|
||||
Py::Tuple args(1);
|
||||
args.setItem(0,Py::Object(const_cast<PropertyContainerPy*>(this)));
|
||||
return PyObject_CallObject(_getShape, args.ptr());
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
@@ -452,6 +452,7 @@ PyMOD_INIT_FUNC(Part)
|
||||
Part::Fillet ::init();
|
||||
Part::Chamfer ::init();
|
||||
Part::Compound ::init();
|
||||
Part::Compound2 ::init();
|
||||
Part::Extrusion ::init();
|
||||
Part::Revolution ::init();
|
||||
Part::Mirroring ::init();
|
||||
|
||||
@@ -126,7 +126,9 @@
|
||||
#include "ImportStep.h"
|
||||
#include "edgecluster.h"
|
||||
#include "FaceMaker.h"
|
||||
#include "PartFeature.h"
|
||||
#include "PartPyCXX.h"
|
||||
#include "modelRefine.h"
|
||||
|
||||
#ifdef FCUseFreeType
|
||||
# include "FT2FC.h"
|
||||
@@ -134,10 +136,6 @@
|
||||
|
||||
extern const char* BRepBuilderAPI_FaceErrorText(BRepBuilderAPI_FaceError fe);
|
||||
|
||||
namespace Part {
|
||||
extern Py::Object shape2pyshape(const TopoDS_Shape &shape);
|
||||
}
|
||||
|
||||
#ifndef M_PI
|
||||
#define M_PI 3.14159265358979323846 /* pi */
|
||||
#endif
|
||||
@@ -147,6 +145,35 @@ extern Py::Object shape2pyshape(const TopoDS_Shape &shape);
|
||||
#endif
|
||||
|
||||
namespace Part {
|
||||
|
||||
PartExport void getPyShapes(PyObject *obj, std::vector<TopoShape> &shapes) {
|
||||
if(!obj)
|
||||
return;
|
||||
if(PyObject_TypeCheck(obj,&Part::TopoShapePy::Type))
|
||||
shapes.push_back(*static_cast<TopoShapePy*>(obj)->getTopoShapePtr());
|
||||
else if (PyObject_TypeCheck(obj, &GeometryPy::Type))
|
||||
shapes.push_back(TopoShape(static_cast<GeometryPy*>(obj)->getGeometryPtr()->toShape()));
|
||||
else if(PySequence_Check(obj)) {
|
||||
Py::Sequence list(obj);
|
||||
for (Py::Sequence::iterator it = list.begin(); it != list.end(); ++it) {
|
||||
if (PyObject_TypeCheck((*it).ptr(), &(Part::TopoShapePy::Type)))
|
||||
shapes.push_back(*static_cast<TopoShapePy*>((*it).ptr())->getTopoShapePtr());
|
||||
else if (PyObject_TypeCheck((*it).ptr(), &GeometryPy::Type))
|
||||
shapes.push_back(TopoShape(static_cast<GeometryPy*>(
|
||||
(*it).ptr())->getGeometryPtr()->toShape()));
|
||||
else
|
||||
throw Py::TypeError("expect shape in sequence");
|
||||
}
|
||||
}else
|
||||
throw Py::TypeError("expect shape or sequence of shapes");
|
||||
}
|
||||
|
||||
PartExport std::vector<TopoShape> getPyShapes(PyObject *obj) {
|
||||
std::vector<TopoShape> ret;
|
||||
getPyShapes(obj,ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
struct EdgePoints {
|
||||
gp_Pnt v1, v2;
|
||||
std::list<TopoDS_Edge>::iterator it;
|
||||
@@ -425,12 +452,74 @@ public:
|
||||
add_varargs_method("__fromPythonOCC__",&Module::fromPythonOCC,
|
||||
"__fromPythonOCC__(occ) -- Helper method to convert a pythonocc shape to an internal shape"
|
||||
);
|
||||
add_varargs_method("clearShapeCache",&Module::clearShapeCache,
|
||||
"clearShapeCache() -- Clears internal shape cache"
|
||||
);
|
||||
add_keyword_method("getShape",&Module::getShape,
|
||||
"getShape(obj,subname=None,mat=None,needSubElement=False,transform=True,retType=0):\n"
|
||||
"Obtain the the TopoShape of a given object with SubName reference\n\n"
|
||||
"* obj: the input object\n"
|
||||
"* subname: dot separated sub-object reference\n"
|
||||
"* mat: the current transformation matrix\n"
|
||||
"* needSubElement: if False, ignore the sub-element (e.g. Face1, Edge1) reference in 'subname'\n"
|
||||
"* transform: if False, then skip obj's transformation. Use this if mat already include obj's\n"
|
||||
" transformation matrix\n"
|
||||
"* retType: 0: return TopoShape,\n"
|
||||
" 1: return (shape,subObj,mat), where subObj is the object referenced in 'subname',\n"
|
||||
" and 'mat' is the accumulated transformation matrix of that sub-object.\n"
|
||||
" 2: same as 1, but make sure 'subObj' is resolved if it is a link.\n"
|
||||
"* refine: refine the returned shape"
|
||||
);
|
||||
add_varargs_method("splitSubname",&Module::splitSubname,
|
||||
"splitSubname(subname) -> list(sub,mapped,subElement)\n"
|
||||
"Split the given subname into a list\n\n"
|
||||
"sub: subname without any sub-element reference\n"
|
||||
"mapped: mapped element name, or '' if none\n"
|
||||
"subElement: old style element name, or '' if none"
|
||||
);
|
||||
add_varargs_method("joinSubname",&Module::joinSubname,
|
||||
"joinSubname(sub,mapped,subElement) -> subname\n"
|
||||
);
|
||||
initialize("This is a module working with shapes."); // register with Python
|
||||
}
|
||||
|
||||
virtual ~Module() {}
|
||||
|
||||
private:
|
||||
virtual Py::Object invoke_method_keyword( void *method_def,
|
||||
const Py::Tuple &args, const Py::Dict &keywords ) override
|
||||
{
|
||||
try {
|
||||
return Py::ExtensionModule<Module>::invoke_method_keyword(method_def, args, keywords);
|
||||
}
|
||||
catch (const Standard_Failure &e) {
|
||||
std::string str;
|
||||
Standard_CString msg = e.GetMessageString();
|
||||
str += typeid(e).name();
|
||||
str += " ";
|
||||
if (msg) {str += msg;}
|
||||
else {str += "No OCCT Exception Message";}
|
||||
Base::Console().Error("%s\n", str.c_str());
|
||||
throw Py::Exception(Part::PartExceptionOCCError, str);
|
||||
}
|
||||
catch (const Base::Exception &e) {
|
||||
std::string str;
|
||||
str += "FreeCAD exception thrown (";
|
||||
str += e.what();
|
||||
str += ")";
|
||||
e.ReportException();
|
||||
throw Py::RuntimeError(str);
|
||||
}
|
||||
catch (const std::exception &e) {
|
||||
std::string str;
|
||||
str += "C++ exception thrown (";
|
||||
str += e.what();
|
||||
str += ")";
|
||||
Base::Console().Error("%s\n", str.c_str());
|
||||
throw Py::RuntimeError(str);
|
||||
}
|
||||
}
|
||||
|
||||
virtual Py::Object invoke_method_varargs(void *method_def, const Py::Tuple &args)
|
||||
{
|
||||
try {
|
||||
@@ -638,21 +727,13 @@ private:
|
||||
TopoDS_Compound Comp;
|
||||
builder.MakeCompound(Comp);
|
||||
|
||||
try {
|
||||
Py::Sequence list(pcObj);
|
||||
for (Py::Sequence::iterator it = list.begin(); it != list.end(); ++it) {
|
||||
if (PyObject_TypeCheck((*it).ptr(), &(Part::TopoShapePy::Type))) {
|
||||
const TopoDS_Shape& sh = static_cast<TopoShapePy*>((*it).ptr())->
|
||||
getTopoShapePtr()->getShape();
|
||||
if (!sh.IsNull())
|
||||
builder.Add(Comp, sh);
|
||||
}
|
||||
PY_TRY {
|
||||
for(auto &s : getPyShapes(pcObj)) {
|
||||
const auto &sh = s.getShape();
|
||||
if (!sh.IsNull())
|
||||
builder.Add(Comp, sh);
|
||||
}
|
||||
}
|
||||
catch (Standard_Failure& e) {
|
||||
throw Py::Exception(PartExceptionOCCError, e.GetMessageString());
|
||||
}
|
||||
|
||||
} _PY_CATCH_OCC(throw Py::Exception())
|
||||
return Py::asObject(new TopoShapeCompoundPy(new TopoShape(Comp)));
|
||||
}
|
||||
Py::Object makeShell(const Py::Tuple& args)
|
||||
@@ -1980,6 +2061,95 @@ private:
|
||||
throw Py::Exception(PartExceptionOCCError, e.what());
|
||||
}
|
||||
}
|
||||
|
||||
Py::Object getShape(const Py::Tuple& args, const Py::Dict &kwds) {
|
||||
PyObject *pObj;
|
||||
const char *subname = 0;
|
||||
PyObject *pyMat = 0;
|
||||
PyObject *needSubElement = Py_False;
|
||||
PyObject *transform = Py_True;
|
||||
PyObject *noElementMap = Py_False;
|
||||
PyObject *refine = Py_False;
|
||||
short retType = 0;
|
||||
static char* kwd_list[] = {"obj", "subname", "mat",
|
||||
"needSubElement","transform","retType","noElementMap","refine",0};
|
||||
if(!PyArg_ParseTupleAndKeywords(args.ptr(), kwds.ptr(), "O!|sO!OOhOO", kwd_list,
|
||||
&App::DocumentObjectPy::Type, &pObj, &subname, &Base::MatrixPy::Type, &pyMat,
|
||||
&needSubElement,&transform,&retType,&noElementMap,&refine))
|
||||
throw Py::Exception();
|
||||
|
||||
App::DocumentObject *obj =
|
||||
static_cast<App::DocumentObjectPy*>(pObj)->getDocumentObjectPtr();
|
||||
App::DocumentObject *subObj = 0;
|
||||
Base::Matrix4D mat;
|
||||
if(pyMat)
|
||||
mat = *static_cast<Base::MatrixPy*>(pyMat)->getMatrixPtr();
|
||||
auto shape = Feature::getTopoShape(obj,subname,PyObject_IsTrue(needSubElement),
|
||||
&mat,&subObj,retType==2,PyObject_IsTrue(transform),PyObject_IsTrue(noElementMap));
|
||||
if(PyObject_IsTrue(refine)) {
|
||||
// shape = TopoShape(0,shape.Hasher).makERefine(shape);
|
||||
BRepBuilderAPI_RefineModel mkRefine(shape.getShape());
|
||||
shape.setShape(mkRefine.Shape());
|
||||
}
|
||||
Py::Object sret(shape2pyshape(shape));
|
||||
if(retType==0)
|
||||
return sret;
|
||||
|
||||
return Py::TupleN(sret,Py::Object(new Base::MatrixPy(new Base::Matrix4D(mat))),
|
||||
subObj?Py::Object(subObj->getPyObject(),true):Py::Object());
|
||||
}
|
||||
|
||||
Py::Object clearShapeCache(const Py::Tuple &args) {
|
||||
if (!PyArg_ParseTuple(args.ptr(),""))
|
||||
throw Py::Exception();
|
||||
Part::Feature::clearShapeCache();
|
||||
return Py::Object();
|
||||
}
|
||||
|
||||
Py::Object splitSubname(const Py::Tuple& args) {
|
||||
const char *subname;
|
||||
if (!PyArg_ParseTuple(args.ptr(), "s",&subname))
|
||||
throw Py::Exception();
|
||||
auto element = Data::ComplexGeoData::findElementName(subname);
|
||||
std::string sub(subname,element-subname);
|
||||
Py::List list;
|
||||
list.append(Py::String(sub));
|
||||
const char *dot = strchr(element,'.');
|
||||
if(!dot)
|
||||
dot = element+strlen(element);
|
||||
const char *mapped = Data::ComplexGeoData::isMappedElement(element);
|
||||
if(mapped)
|
||||
list.append(Py::String(std::string(mapped,dot-mapped)));
|
||||
else
|
||||
list.append(Py::String());
|
||||
if(*dot=='.')
|
||||
list.append(Py::String(dot+1));
|
||||
else if(!mapped)
|
||||
list.append(Py::String(element));
|
||||
else
|
||||
list.append(Py::String());
|
||||
return list;
|
||||
}
|
||||
|
||||
Py::Object joinSubname(const Py::Tuple& args) {
|
||||
const char *sub;
|
||||
const char *mapped;
|
||||
const char *element;
|
||||
if (!PyArg_ParseTuple(args.ptr(), "sss",&sub,&mapped,&element))
|
||||
throw Py::Exception();
|
||||
std::string subname(sub);
|
||||
if(subname.size() && subname[subname.size()-1]!='.')
|
||||
subname += '.';
|
||||
if(mapped && mapped[0]) {
|
||||
if(!Data::ComplexGeoData::isMappedElement(mapped))
|
||||
subname += Data::ComplexGeoData::elementMapPrefix();
|
||||
subname += mapped;
|
||||
if(element && element[0] && subname[subname.size()-1]!='.')
|
||||
subname += '.';
|
||||
}
|
||||
subname += element;
|
||||
return Py::String(subname);
|
||||
}
|
||||
};
|
||||
|
||||
PyObject* initModule()
|
||||
|
||||
@@ -51,16 +51,14 @@ App::DocumentObjectExecReturn *Chamfer::execute(void)
|
||||
App::DocumentObject* link = Base.getValue();
|
||||
if (!link)
|
||||
return new App::DocumentObjectExecReturn("No object linked");
|
||||
if (!link->getTypeId().isDerivedFrom(Part::Feature::getClassTypeId()))
|
||||
return new App::DocumentObjectExecReturn("Linked object is not a Part object");
|
||||
Part::Feature *base = static_cast<Part::Feature*>(Base.getValue());
|
||||
|
||||
try {
|
||||
BRepFilletAPI_MakeChamfer mkChamfer(base->Shape.getValue());
|
||||
auto baseShape = Feature::getShape(link);
|
||||
BRepFilletAPI_MakeChamfer mkChamfer(baseShape);
|
||||
TopTools_IndexedMapOfShape mapOfEdges;
|
||||
TopTools_IndexedDataMapOfShapeListOfShape mapEdgeFace;
|
||||
TopExp::MapShapesAndAncestors(base->Shape.getValue(), TopAbs_EDGE, TopAbs_FACE, mapEdgeFace);
|
||||
TopExp::MapShapes(base->Shape.getValue(), TopAbs_EDGE, mapOfEdges);
|
||||
TopExp::MapShapesAndAncestors(baseShape, TopAbs_EDGE, TopAbs_FACE, mapEdgeFace);
|
||||
TopExp::MapShapes(baseShape, TopAbs_EDGE, mapOfEdges);
|
||||
|
||||
std::vector<FilletElement> values = Edges.getValues();
|
||||
for (std::vector<FilletElement>::iterator it = values.begin(); it != values.end(); ++it) {
|
||||
@@ -75,7 +73,7 @@ App::DocumentObjectExecReturn *Chamfer::execute(void)
|
||||
TopoDS_Shape shape = mkChamfer.Shape();
|
||||
if (shape.IsNull())
|
||||
return new App::DocumentObjectExecReturn("Resulting shape is null");
|
||||
ShapeHistory history = buildHistory(mkChamfer, TopAbs_FACE, shape, base->Shape.getValue());
|
||||
ShapeHistory history = buildHistory(mkChamfer, TopAbs_FACE, shape, baseShape);
|
||||
this->Shape.setValue(shape);
|
||||
|
||||
// make sure the 'PropertyShapeHistory' is not safed in undo/redo (#0001889)
|
||||
|
||||
@@ -72,12 +72,10 @@ App::DocumentObjectExecReturn *Compound::execute(void)
|
||||
|
||||
const std::vector<DocumentObject*>& links = Links.getValues();
|
||||
for (std::vector<DocumentObject*>::const_iterator it = links.begin(); it != links.end(); ++it) {
|
||||
if (*it && (*it)->getTypeId().isDerivedFrom(Part::Feature::getClassTypeId())) {
|
||||
Part::Feature* fea = static_cast<Part::Feature*>(*it);
|
||||
|
||||
auto pos = tempLinks.insert(fea);
|
||||
if (*it) {
|
||||
auto pos = tempLinks.insert(*it);
|
||||
if (pos.second) {
|
||||
const TopoDS_Shape& sh = fea->Shape.getValue();
|
||||
const TopoDS_Shape& sh = Feature::getShape(*it);
|
||||
if (!sh.IsNull()) {
|
||||
builder.Add(comp, sh);
|
||||
TopTools_IndexedMapOfShape faceMap;
|
||||
@@ -108,3 +106,15 @@ App::DocumentObjectExecReturn *Compound::execute(void)
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
PROPERTY_SOURCE(Part::Compound2, Part::Compound)
|
||||
|
||||
Compound2::Compound2() {
|
||||
Shape.setStatus(App::Property::Transient,true);
|
||||
}
|
||||
|
||||
void Compound2::onDocumentRestored() {
|
||||
auto res = execute();
|
||||
delete res;
|
||||
}
|
||||
|
||||
@@ -52,6 +52,14 @@ public:
|
||||
//@}
|
||||
};
|
||||
|
||||
/// Same as Part::Compound, except it marks the Shape as transient, and rebuild it during restore
|
||||
class Compound2 : public Compound {
|
||||
PROPERTY_HEADER(Part::Compound2);
|
||||
public:
|
||||
Compound2();
|
||||
virtual void onDocumentRestored() override;
|
||||
};
|
||||
|
||||
} //namespace Part
|
||||
|
||||
|
||||
|
||||
@@ -102,16 +102,13 @@ bool Extrusion::fetchAxisLink(const App::PropertyLinkSub& axisLink, Base::Vector
|
||||
if (!axisLink.getValue())
|
||||
return false;
|
||||
|
||||
if (!axisLink.getValue()->isDerivedFrom(Part::Feature::getClassTypeId()))
|
||||
throw Base::TypeError("AxisLink has no OCC shape");
|
||||
|
||||
Part::Feature* linked = static_cast<Part::Feature*>(axisLink.getValue());
|
||||
auto linked = axisLink.getValue();
|
||||
|
||||
TopoDS_Shape axEdge;
|
||||
if (axisLink.getSubValues().size() > 0 && axisLink.getSubValues()[0].length() > 0){
|
||||
axEdge = linked->Shape.getShape().getSubShape(axisLink.getSubValues()[0].c_str());
|
||||
axEdge = Feature::getTopoShape(linked).getSubShape(axisLink.getSubValues()[0].c_str());
|
||||
} else {
|
||||
axEdge = linked->Shape.getValue();
|
||||
axEdge = Feature::getShape(linked);
|
||||
}
|
||||
|
||||
if (axEdge.IsNull())
|
||||
@@ -196,25 +193,21 @@ Extrusion::ExtrusionParameters Extrusion::computeFinalParameters()
|
||||
|
||||
Base::Vector3d Extrusion::calculateShapeNormal(const App::PropertyLink& shapeLink)
|
||||
{
|
||||
if (!shapeLink.getValue())
|
||||
App::DocumentObject* docobj = 0;
|
||||
Base::Matrix4D mat;
|
||||
TopoDS_Shape sh = Feature::getShape(shapeLink.getValue(),0,false, &mat,&docobj);
|
||||
|
||||
if (!docobj)
|
||||
throw Base::ValueError("calculateShapeNormal: link is empty");
|
||||
const App::DocumentObject* docobj = shapeLink.getValue();
|
||||
|
||||
//special case for sketches and the like: no matter what shape they have, use their local Z axis.
|
||||
if (docobj->isDerivedFrom(Part::Part2DObject::getClassTypeId())){
|
||||
const Part::Part2DObject* p2do = static_cast<const Part::Part2DObject*>(docobj);
|
||||
Base::Vector3d OZ (0.0, 0.0, 1.0);
|
||||
Base::Vector3d result;
|
||||
p2do->Placement.getValue().getRotation().multVec(OZ, result);
|
||||
Base::Rotation(mat).multVec(OZ, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
//extract the shape
|
||||
if (! docobj->isDerivedFrom(Part::Feature::getClassTypeId()))
|
||||
throw Base::TypeError("Linked object doesn't have shape.");
|
||||
|
||||
const TopoShape &tsh = static_cast<const Part::Feature*>(docobj)->Shape.getShape();
|
||||
TopoDS_Shape sh = tsh.getShape();
|
||||
if (sh.IsNull())
|
||||
throw NullShapeException("calculateShapeNormal: link points to a valid object, but its shape is null.");
|
||||
|
||||
@@ -327,13 +320,10 @@ App::DocumentObjectExecReturn *Extrusion::execute(void)
|
||||
App::DocumentObject* link = Base.getValue();
|
||||
if (!link)
|
||||
return new App::DocumentObjectExecReturn("No object linked");
|
||||
if (!link->getTypeId().isDerivedFrom(Part::Feature::getClassTypeId()))
|
||||
return new App::DocumentObjectExecReturn("Linked object is not a Part object");
|
||||
Part::Feature *base = static_cast<Part::Feature*>(Base.getValue());
|
||||
|
||||
try {
|
||||
Extrusion::ExtrusionParameters params = computeFinalParameters();
|
||||
TopoShape result = extrudeShape(base->Shape.getShape(),params);
|
||||
TopoShape result = extrudeShape(Feature::getShape(link),params);
|
||||
this->Shape.setValue(result);
|
||||
return App::DocumentObject::StdReturn;
|
||||
}
|
||||
|
||||
@@ -84,9 +84,9 @@ App::DocumentObjectExecReturn *Face::execute(void)
|
||||
std::unique_ptr<FaceMaker> facemaker = FaceMaker::ConstructFromType(this->FaceMakerClass.getValue());
|
||||
|
||||
for (std::vector<App::DocumentObject*>::iterator it = links.begin(); it != links.end(); ++it) {
|
||||
if (!(*it && (*it)->isDerivedFrom(Part::Feature::getClassTypeId())))
|
||||
if (!(*it))
|
||||
return new App::DocumentObjectExecReturn("Linked object is not a Part object (has no Shape).");
|
||||
TopoDS_Shape shape = static_cast<Part::Part2DObject*>(*it)->Shape.getShape().getShape();
|
||||
TopoDS_Shape shape = Feature::getShape(*it);
|
||||
if (shape.IsNull())
|
||||
return new App::DocumentObjectExecReturn("Linked shape object is empty");
|
||||
|
||||
|
||||
@@ -50,17 +50,16 @@ App::DocumentObjectExecReturn *Fillet::execute(void)
|
||||
App::DocumentObject* link = Base.getValue();
|
||||
if (!link)
|
||||
return new App::DocumentObjectExecReturn("No object linked");
|
||||
if (!link->getTypeId().isDerivedFrom(Part::Feature::getClassTypeId()))
|
||||
return new App::DocumentObjectExecReturn("Linked object is not a Part object");
|
||||
Part::Feature *base = static_cast<Part::Feature*>(Base.getValue());
|
||||
|
||||
auto baseShape = Feature::getShape(link);
|
||||
|
||||
try {
|
||||
#if defined(__GNUC__) && defined (FC_OS_LINUX)
|
||||
Base::SignalException se;
|
||||
#endif
|
||||
BRepFilletAPI_MakeFillet mkFillet(base->Shape.getValue());
|
||||
BRepFilletAPI_MakeFillet mkFillet(baseShape);
|
||||
TopTools_IndexedMapOfShape mapOfShape;
|
||||
TopExp::MapShapes(base->Shape.getValue(), TopAbs_EDGE, mapOfShape);
|
||||
TopExp::MapShapes(baseShape, TopAbs_EDGE, mapOfShape);
|
||||
|
||||
std::vector<FilletElement> values = Edges.getValues();
|
||||
for (std::vector<FilletElement>::iterator it = values.begin(); it != values.end(); ++it) {
|
||||
@@ -74,7 +73,7 @@ App::DocumentObjectExecReturn *Fillet::execute(void)
|
||||
TopoDS_Shape shape = mkFillet.Shape();
|
||||
if (shape.IsNull())
|
||||
return new App::DocumentObjectExecReturn("Resulting shape is null");
|
||||
ShapeHistory history = buildHistory(mkFillet, TopAbs_FACE, shape, base->Shape.getValue());
|
||||
ShapeHistory history = buildHistory(mkFillet, TopAbs_FACE, shape, baseShape);
|
||||
this->Shape.setValue(shape);
|
||||
|
||||
// make sure the 'PropertyShapeHistory' is not safed in undo/redo (#0001889)
|
||||
|
||||
@@ -95,14 +95,11 @@ App::DocumentObjectExecReturn *Mirroring::execute(void)
|
||||
App::DocumentObject* link = Source.getValue();
|
||||
if (!link)
|
||||
return new App::DocumentObjectExecReturn("No object linked");
|
||||
if (!link->getTypeId().isDerivedFrom(Part::Feature::getClassTypeId()))
|
||||
return new App::DocumentObjectExecReturn("Linked object is not a Part object");
|
||||
Part::Feature *source = static_cast<Part::Feature*>(link);
|
||||
Base::Vector3d base = Base.getValue();
|
||||
Base::Vector3d norm = Normal.getValue();
|
||||
|
||||
try {
|
||||
const TopoDS_Shape& shape = source->Shape.getValue();
|
||||
const TopoDS_Shape& shape = Feature::getShape(link);
|
||||
if (shape.IsNull())
|
||||
Standard_Failure::Raise("Cannot mirroR empty shape");
|
||||
gp_Ax2 ax2(gp_Pnt(base.x,base.y,base.z), gp_Dir(norm.x,norm.y,norm.z));
|
||||
|
||||
@@ -77,7 +77,7 @@ short Offset::mustExecute() const
|
||||
App::DocumentObjectExecReturn *Offset::execute(void)
|
||||
{
|
||||
App::DocumentObject* source = Source.getValue();
|
||||
if (!(source && source->getTypeId().isDerivedFrom(Part::Feature::getClassTypeId())))
|
||||
if (!source)
|
||||
return new App::DocumentObjectExecReturn("No source shape linked.");
|
||||
double offset = Value.getValue();
|
||||
double tol = Precision::Confusion();
|
||||
@@ -86,7 +86,7 @@ App::DocumentObjectExecReturn *Offset::execute(void)
|
||||
short mode = (short)Mode.getValue();
|
||||
short join = (short)Join.getValue();
|
||||
bool fill = Fill.getValue();
|
||||
const TopoShape& shape = static_cast<Part::Feature*>(source)->Shape.getShape();
|
||||
const TopoShape& shape = Feature::getShape(source);
|
||||
if (fabs(offset) > 2*tol)
|
||||
this->Shape.setValue(shape.makeOffsetShape(offset, tol, inter, self, mode, join, fill));
|
||||
else
|
||||
|
||||
@@ -73,17 +73,17 @@ App::DocumentObjectExecReturn *Boolean::execute(void)
|
||||
#if defined(__GNUC__) && defined (FC_OS_LINUX)
|
||||
Base::SignalException se;
|
||||
#endif
|
||||
Part::Feature *base = dynamic_cast<Part::Feature*>(Base.getValue());
|
||||
Part::Feature *tool = dynamic_cast<Part::Feature*>(Tool.getValue());
|
||||
auto base = Base.getValue();
|
||||
auto tool = Tool.getValue();
|
||||
|
||||
if (!base || !tool)
|
||||
return new App::DocumentObjectExecReturn("Linked object is not a Part object");
|
||||
|
||||
// Now, let's get the TopoDS_Shape
|
||||
TopoDS_Shape BaseShape = base->Shape.getValue();
|
||||
TopoDS_Shape BaseShape = Feature::getShape(base);
|
||||
if (BaseShape.IsNull())
|
||||
throw NullShapeException("Base shape is null");
|
||||
TopoDS_Shape ToolShape = tool->Shape.getValue();
|
||||
TopoDS_Shape ToolShape = Feature::getShape(tool);
|
||||
if (ToolShape.IsNull())
|
||||
throw NullShapeException("Tool shape is null");
|
||||
|
||||
|
||||
@@ -91,6 +91,16 @@ void Box::Restore(Base::XMLReader &reader)
|
||||
{
|
||||
reader.readElement("Properties");
|
||||
int Cnt = reader.getAttributeAsInteger("Count");
|
||||
int transientCount = 0;
|
||||
if(reader.hasAttribute("TransientCount"))
|
||||
transientCount = reader.getAttributeAsUnsigned("TransientCount");
|
||||
|
||||
for (int i=0;i<transientCount; ++i) {
|
||||
reader.readElement("_Property");
|
||||
App::Property* prop = getPropertyByName(reader.getAttribute("name"));
|
||||
if(prop && reader.hasAttribute("status"))
|
||||
prop->setStatusValue(reader.getAttributeAsUnsigned("status"));
|
||||
}
|
||||
|
||||
bool location_xyz = false;
|
||||
bool location_axis = false;
|
||||
@@ -104,7 +114,27 @@ void Box::Restore(Base::XMLReader &reader)
|
||||
reader.readElement("Property");
|
||||
const char* PropName = reader.getAttribute("name");
|
||||
const char* TypeName = reader.getAttribute("type");
|
||||
App::Property* prop = getPropertyByName(PropName);
|
||||
auto prop = dynamicProps.restore(*this,PropName,TypeName,reader);
|
||||
if(!prop)
|
||||
prop = getPropertyByName(PropName);
|
||||
|
||||
std::bitset<32> status;
|
||||
if(reader.hasAttribute("status")) {
|
||||
status = reader.getAttributeAsUnsigned("status");
|
||||
if(prop)
|
||||
prop->setStatusValue(status.to_ulong());
|
||||
}
|
||||
if (prop && strcmp(prop->getTypeId().getName(), TypeName) == 0) {
|
||||
if (!prop->testStatus(App::Property::Transient)
|
||||
&& !status.test(App::Property::Transient)
|
||||
&& !status.test(App::Property::PropTransient)
|
||||
&& !(getPropertyType(prop) & App::Prop_Transient))
|
||||
{
|
||||
prop->Restore(reader);
|
||||
}
|
||||
reader.readEndElement("Property");
|
||||
continue;
|
||||
}
|
||||
if (!prop) {
|
||||
// in case this comes from an old document we must use the new properties
|
||||
if (strcmp(PropName, "l") == 0) {
|
||||
|
||||
@@ -89,9 +89,7 @@ App::DocumentObjectExecReturn *MultiCommon::execute(void)
|
||||
|
||||
std::vector<App::DocumentObject*>::iterator it;
|
||||
for (it = obj.begin(); it != obj.end(); ++it) {
|
||||
if ((*it)->getTypeId().isDerivedFrom(Part::Feature::getClassTypeId())) {
|
||||
s.push_back(static_cast<Part::Feature*>(*it)->Shape.getValue());
|
||||
}
|
||||
s.push_back(Feature::getShape(*it));
|
||||
}
|
||||
|
||||
bool argumentsAreInCompound = false;
|
||||
|
||||
@@ -89,9 +89,7 @@ App::DocumentObjectExecReturn *MultiFuse::execute(void)
|
||||
|
||||
std::vector<App::DocumentObject*>::iterator it;
|
||||
for (it = obj.begin(); it != obj.end(); ++it) {
|
||||
if ((*it)->getTypeId().isDerivedFrom(Part::Feature::getClassTypeId())) {
|
||||
s.push_back(static_cast<Part::Feature*>(*it)->Shape.getValue());
|
||||
}
|
||||
s.push_back(Feature::getShape(*it));
|
||||
}
|
||||
|
||||
bool argumentsAreInCompound = false;
|
||||
|
||||
@@ -90,16 +90,13 @@ bool Revolution::fetchAxisLink(const App::PropertyLinkSub &axisLink,
|
||||
if (!axisLink.getValue())
|
||||
return false;
|
||||
|
||||
if (!axisLink.getValue()->isDerivedFrom(Part::Feature::getClassTypeId()))
|
||||
throw Base::TypeError("AxisLink has no OCC shape");
|
||||
|
||||
Part::Feature* linked = static_cast<Part::Feature*>(axisLink.getValue());
|
||||
auto linked = axisLink.getValue();
|
||||
|
||||
TopoDS_Shape axEdge;
|
||||
if (axisLink.getSubValues().size() > 0 && axisLink.getSubValues()[0].length() > 0){
|
||||
axEdge = linked->Shape.getShape().getSubShape(axisLink.getSubValues()[0].c_str());
|
||||
axEdge = Feature::getTopoShape(linked).getSubShape(axisLink.getSubValues()[0].c_str());
|
||||
} else {
|
||||
axEdge = linked->Shape.getValue();
|
||||
axEdge = Feature::getShape(linked);
|
||||
}
|
||||
|
||||
if (axEdge.IsNull())
|
||||
@@ -133,9 +130,6 @@ App::DocumentObjectExecReturn *Revolution::execute(void)
|
||||
App::DocumentObject* link = Source.getValue();
|
||||
if (!link)
|
||||
return new App::DocumentObjectExecReturn("No object linked");
|
||||
if (!link->getTypeId().isDerivedFrom(Part::Feature::getClassTypeId()))
|
||||
return new App::DocumentObjectExecReturn("Linked object is not a Part object");
|
||||
Part::Feature *base = static_cast<Part::Feature*>(Source.getValue());
|
||||
|
||||
try {
|
||||
//read out axis link
|
||||
@@ -158,7 +152,7 @@ App::DocumentObjectExecReturn *Revolution::execute(void)
|
||||
angle = angle_edge;
|
||||
|
||||
//apply "midplane" symmetry
|
||||
TopoShape sourceShape = base->Shape.getShape();
|
||||
TopoShape sourceShape = Feature::getShape(link);
|
||||
if (Symmetric.getValue()) {
|
||||
//rotate source shape backwards by half angle, to make resulting revolution symmetric to the profile
|
||||
gp_Trsf mov;
|
||||
|
||||
@@ -217,5 +217,11 @@ or raises an exception if it is not periodic.</UserDocu>
|
||||
</Documentation>
|
||||
<Parameter Name="LastParameter" Type="Float"/>
|
||||
</Attribute>
|
||||
<Attribute Name="Rotation" ReadOnly="true">
|
||||
<Documentation>
|
||||
<UserDocu>Returns a rotation object to describe the orientation for curve that supports it</UserDocu>
|
||||
</Documentation>
|
||||
<Parameter Name="Rotation" Type="Object"/>
|
||||
</Attribute>
|
||||
</PythonExport>
|
||||
</GenerateModel>
|
||||
|
||||
@@ -28,6 +28,7 @@
|
||||
# include <gp_Dir.hxx>
|
||||
# include <gp_Vec.hxx>
|
||||
# include <gp_Pln.hxx>
|
||||
# include <gp_Quaternion.hxx>
|
||||
# include <GCPnts_UniformAbscissa.hxx>
|
||||
# include <GCPnts_UniformDeflection.hxx>
|
||||
# include <GCPnts_TangentialDeflection.hxx>
|
||||
@@ -851,6 +852,17 @@ PyObject* GeometryCurvePy::intersect(PyObject *args)
|
||||
return 0;
|
||||
}
|
||||
|
||||
Py::Object GeometryCurvePy::getRotation(void) const
|
||||
{
|
||||
Handle(Geom_Conic) s = Handle(Geom_Conic)::DownCast(getGeometryPtr()->handle());
|
||||
if(!s)
|
||||
return Py::Object();
|
||||
gp_Trsf trsf;
|
||||
trsf.SetTransformation(s->Position(),gp_Ax3());
|
||||
auto q = trsf.GetRotation();
|
||||
return Py::Rotation(Base::Rotation(q.X(),q.Y(),q.Z(),q.W()));
|
||||
}
|
||||
|
||||
PyObject* GeometryCurvePy::reverse(PyObject *args)
|
||||
{
|
||||
if (!PyArg_ParseTuple(args, ""))
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<GenerateModel xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="generateMetaModel_Module.xsd">
|
||||
<PythonExport
|
||||
Father="PyObjectBase"
|
||||
Father="PersistencePy"
|
||||
Name="GeometryPy"
|
||||
Twin="Geometry"
|
||||
TwinPointer="Geometry"
|
||||
Include="Mod/Part/App/Geometry.h"
|
||||
Namespace="Part"
|
||||
FatherInclude="Base/PyObjectBase.h"
|
||||
FatherInclude="Base/PersistencePy.h"
|
||||
FatherNamespace="Base"
|
||||
Constructor="true"
|
||||
Delete="true">
|
||||
|
||||
@@ -87,6 +87,12 @@ Checks if the surface is planar within a certain tolerance.
|
||||
</Documentation>
|
||||
<Parameter Name="Continuity" Type="String"/>
|
||||
</Attribute>
|
||||
<Attribute Name="Rotation" ReadOnly="true">
|
||||
<Documentation>
|
||||
<UserDocu>Returns a rotation object to describe the orientation for surface that supports it</UserDocu>
|
||||
</Documentation>
|
||||
<Parameter Name="Rotation" Type="Object"/>
|
||||
</Attribute>
|
||||
<Methode Name="uIso" Const="true">
|
||||
<Documentation>
|
||||
<UserDocu>Builds the U isoparametric curve</UserDocu>
|
||||
|
||||
@@ -31,6 +31,7 @@
|
||||
# include <gp_Parab.hxx>
|
||||
# include <gp_Vec.hxx>
|
||||
# include <gp_Lin.hxx>
|
||||
# include <gp_Quaternion.hxx>
|
||||
# include <Geom_Geometry.hxx>
|
||||
# include <Geom_Surface.hxx>
|
||||
# include <GeomConvert_ApproxSurface.hxx>
|
||||
@@ -855,3 +856,16 @@ PyObject* GeometrySurfacePy::intersect(PyObject *args)
|
||||
PyErr_SetString(PyExc_TypeError, "intersect(): Geometry is not a surface");
|
||||
return 0;
|
||||
}
|
||||
|
||||
Py::Object GeometrySurfacePy::getRotation(void) const
|
||||
{
|
||||
Handle(Geom_ElementarySurface) s = Handle(Geom_ElementarySurface)::DownCast
|
||||
(getGeometryPtr()->handle());
|
||||
if(!s)
|
||||
return Py::Object();
|
||||
gp_Trsf trsf;
|
||||
trsf.SetTransformation(s->Position().Ax2(),gp_Ax3());
|
||||
auto q = trsf.GetRotation();
|
||||
return Py::Rotation(Base::Rotation(q.X(),q.Y(),q.Z(),q.W()));
|
||||
}
|
||||
|
||||
|
||||
@@ -70,9 +70,9 @@ PartExport extern PyObject* PartExceptionOCCDimensionError;
|
||||
|
||||
#define PY_TRY try
|
||||
|
||||
#ifndef DONT_CATCH_CXX_EXCEPTIONS
|
||||
/// see docu of PY_TRY
|
||||
# define PY_CATCH_OCC catch (Standard_Failure &e) \
|
||||
# define _PY_CATCH_OCC(R) \
|
||||
catch (Standard_Failure &e) \
|
||||
{ \
|
||||
std::string str; \
|
||||
Standard_CString msg = e.GetMessageString(); \
|
||||
@@ -81,80 +81,11 @@ PartExport extern PyObject* PartExceptionOCCDimensionError;
|
||||
if (msg) {str += msg;} \
|
||||
else {str += "No OCCT Exception Message";} \
|
||||
Base::Console().Error(str.c_str()); \
|
||||
Py_Error(Part::PartExceptionOCCError,str.c_str()); \
|
||||
_Py_Error(R,Part::PartExceptionOCCError,str.c_str()); \
|
||||
} \
|
||||
catch(Base::Exception &e) \
|
||||
{ \
|
||||
std::string str; \
|
||||
str += "FreeCAD exception thrown ("; \
|
||||
str += e.what(); \
|
||||
str += ")"; \
|
||||
e.ReportException(); \
|
||||
Py_Error(Base::BaseExceptionFreeCADError,str.c_str()); \
|
||||
} \
|
||||
catch(std::exception &e) \
|
||||
{ \
|
||||
std::string str; \
|
||||
str += "STL exception thrown ("; \
|
||||
str += e.what(); \
|
||||
str += ")"; \
|
||||
Base::Console().Error(str.c_str()); \
|
||||
Py_Error(Base::BaseExceptionFreeCADError,str.c_str()); \
|
||||
} \
|
||||
catch(const Py::Exception&) \
|
||||
{ \
|
||||
return NULL; \
|
||||
} \
|
||||
catch(const char *e) \
|
||||
{ \
|
||||
Py_Error(Base::BaseExceptionFreeCADError,e); \
|
||||
} \
|
||||
catch(...) \
|
||||
{ \
|
||||
Py_Error(Base::BaseExceptionFreeCADError,"Unknown C++ exception"); \
|
||||
}
|
||||
|
||||
#else
|
||||
/// see docu of PY_TRY
|
||||
# define PY_CATCH_OCC catch (Standard_Failure &e) \
|
||||
{ \
|
||||
std::string str; \
|
||||
Standard_CString msg = e.GetMessageString(); \
|
||||
str += typeid(e).name(); \
|
||||
str += " "; \
|
||||
if (msg) {str += msg;} \
|
||||
else {str += "No OCCT Exception Message";} \
|
||||
Base::Console().Error(str.c_str()); \
|
||||
Py_Error(Part::PartExceptionOCCError,str.c_str()); \
|
||||
} \
|
||||
catch(Base::Exception &e) \
|
||||
{ \
|
||||
std::string str; \
|
||||
str += "FreeCAD exception thrown ("; \
|
||||
str += e.what(); \
|
||||
str += ")"; \
|
||||
e.ReportException(); \
|
||||
Py_Error(Base::BaseExceptionFreeCADError,str.c_str()); \
|
||||
} \
|
||||
catch(std::exception &e) \
|
||||
{ \
|
||||
std::string str; \
|
||||
str += "STL exception thrown ("; \
|
||||
str += e.what(); \
|
||||
str += ")"; \
|
||||
Base::Console().Error(str.c_str()); \
|
||||
Py_Error(Base::BaseExceptionFreeCADError,str.c_str()); \
|
||||
} \
|
||||
catch(const Py::Exception&) \
|
||||
{ \
|
||||
return NULL; \
|
||||
} \
|
||||
catch(const char *e) \
|
||||
{ \
|
||||
Py_Error(Base::BaseExceptionFreeCADError,e); \
|
||||
}
|
||||
|
||||
#endif // DONT_CATCH_CXX_EXCEPTIONS
|
||||
_PY_CATCH(R)
|
||||
} //namespace Part
|
||||
|
||||
#define PY_CATCH_OCC _PY_CATCH_OCC(return(NULL))
|
||||
#endif // _OCCError_h_
|
||||
|
||||
|
||||
@@ -234,6 +234,7 @@
|
||||
#include <BRepExtrema_ShapeProximity.hxx>
|
||||
#endif
|
||||
#include <BRepFeat_SplitShape.hxx>
|
||||
#include <BRepFeat_MakePrism.hxx>
|
||||
#include <BRepFilletAPI_MakeChamfer.hxx>
|
||||
#include <BRepFilletAPI_MakeFillet.hxx>
|
||||
#include <BRepFill.hxx>
|
||||
@@ -252,6 +253,7 @@
|
||||
#include <BRepOffsetAPI_MakeThickSolid.hxx>
|
||||
#include <BRepOffsetAPI_ThruSections.hxx>
|
||||
#include <BRepBuilderAPI_NurbsConvert.hxx>
|
||||
#include <BRepOffsetAPI_DraftAngle.hxx>
|
||||
#include <BRepPrimAPI_MakeBox.hxx>
|
||||
#include <BRepPrimAPI_MakeCone.hxx>
|
||||
#include <BRepPrimAPI_MakeCylinder.hxx>
|
||||
@@ -419,6 +421,7 @@
|
||||
#include <gp_Trsf.hxx>
|
||||
#include <gp_Vec.hxx>
|
||||
#include <gp_Vec2d.hxx>
|
||||
#include <gp_Quaternion.hxx>
|
||||
|
||||
// Adaptors
|
||||
#include <Adaptor3d_HCurve.hxx>
|
||||
|
||||
@@ -52,6 +52,8 @@
|
||||
# include <gce_MakeDir.hxx>
|
||||
#endif
|
||||
|
||||
#include <boost/algorithm/string/predicate.hpp>
|
||||
#include <boost/bind.hpp>
|
||||
#include <Base/Console.h>
|
||||
#include <Base/Writer.h>
|
||||
#include <Base/Reader.h>
|
||||
@@ -63,6 +65,8 @@
|
||||
#include <App/Application.h>
|
||||
#include <App/FeaturePythonPyImp.h>
|
||||
#include <App/Document.h>
|
||||
#include <App/Link.h>
|
||||
#include <App/GeoFeatureGroupExtension.h>
|
||||
|
||||
#include "PartPyCXX.h"
|
||||
#include "PartFeature.h"
|
||||
@@ -126,8 +130,10 @@ App::DocumentObject *Feature::getSubObject(const char *subname,
|
||||
if(subname && !Data::ComplexGeoData::isMappedElement(subname) && strchr(subname,'.'))
|
||||
return App::DocumentObject::getSubObject(subname,pyObj,pmat,transform,depth);
|
||||
|
||||
if(pmat && transform)
|
||||
*pmat *= Placement.getValue().toMatrix();
|
||||
Base::Matrix4D _mat;
|
||||
auto &mat = pmat?*pmat:_mat;
|
||||
if(transform)
|
||||
mat *= Placement.getValue().toMatrix();
|
||||
|
||||
if(!pyObj) {
|
||||
#if 0
|
||||
@@ -142,13 +148,11 @@ App::DocumentObject *Feature::getSubObject(const char *subname,
|
||||
|
||||
try {
|
||||
TopoShape ts(Shape.getShape());
|
||||
bool doTransform = pmat && *pmat!=ts.getTransform();
|
||||
if(doTransform) {
|
||||
ts.setShape(ts.getShape().Located(TopLoc_Location()),false);
|
||||
ts.initCache(1);
|
||||
}
|
||||
bool doTransform = mat!=ts.getTransform();
|
||||
if(doTransform)
|
||||
ts.setShape(ts.getShape().Located(TopLoc_Location()));
|
||||
if(subname && *subname && !ts.isNull())
|
||||
ts = ts.getSubTopoShape(subname,true);
|
||||
ts = ts.getSubShape(subname);
|
||||
if(doTransform && !ts.isNull()) {
|
||||
static int sCopy = -1;
|
||||
if(sCopy<0) {
|
||||
@@ -171,7 +175,7 @@ App::DocumentObject *Feature::getSubObject(const char *subname,
|
||||
}
|
||||
}
|
||||
}
|
||||
ts.transformShape(*pmat,copy,true);
|
||||
ts.transformShape(mat,copy,true);
|
||||
}
|
||||
*pyObj = Py::new_reference_to(shape2pyshape(ts));
|
||||
return const_cast<Feature*>(this);
|
||||
@@ -189,6 +193,330 @@ App::DocumentObject *Feature::getSubObject(const char *subname,
|
||||
}
|
||||
}
|
||||
|
||||
TopoDS_Shape Feature::getShape(const App::DocumentObject *obj, const char *subname,
|
||||
bool needSubElement, Base::Matrix4D *pmat, App::DocumentObject **powner,
|
||||
bool resolveLink, bool transform)
|
||||
{
|
||||
return getTopoShape(obj,subname,needSubElement,pmat,powner,resolveLink,transform,true).getShape();
|
||||
}
|
||||
|
||||
struct ShapeCache {
|
||||
|
||||
std::unordered_map<const App::Document*,
|
||||
std::map<std::pair<const App::DocumentObject*, std::string> ,TopoShape> > cache;
|
||||
|
||||
bool inited = false;
|
||||
void init() {
|
||||
if(inited)
|
||||
return;
|
||||
inited = true;
|
||||
App::GetApplication().signalDeleteDocument.connect(
|
||||
boost::bind(&ShapeCache::slotDeleteDocument, this, _1));
|
||||
App::GetApplication().signalDeletedObject.connect(
|
||||
boost::bind(&ShapeCache::slotClear, this, _1));
|
||||
App::GetApplication().signalChangedObject.connect(
|
||||
boost::bind(&ShapeCache::slotChanged, this, _1,_2));
|
||||
}
|
||||
|
||||
void slotDeleteDocument(const App::Document &doc) {
|
||||
cache.erase(&doc);
|
||||
}
|
||||
|
||||
void slotChanged(const App::DocumentObject &obj, const App::Property &prop) {
|
||||
const char *propName = prop.getName();
|
||||
if(!propName)
|
||||
return;
|
||||
if(strcmp(propName,"Shape")==0
|
||||
|| strcmp(propName,"Group")==0
|
||||
|| strstr(propName,"Touched")!=0)
|
||||
slotClear(obj);
|
||||
}
|
||||
|
||||
void slotClear(const App::DocumentObject &obj) {
|
||||
auto it = cache.find(obj.getDocument());
|
||||
if(it==cache.end())
|
||||
return;
|
||||
auto &map = it->second;
|
||||
for(auto it2=map.lower_bound(std::make_pair(&obj,std::string()));
|
||||
it2!=map.end() && it2->first.first==&obj;)
|
||||
{
|
||||
it2 = map.erase(it2);
|
||||
}
|
||||
}
|
||||
|
||||
bool getShape(const App::DocumentObject *obj, TopoShape &shape, const char *subname=0) {
|
||||
init();
|
||||
auto &entry = cache[obj->getDocument()];
|
||||
if(!subname) subname = "";
|
||||
auto it = entry.find(std::make_pair(obj,std::string(subname)));
|
||||
if(it!=entry.end()) {
|
||||
shape = it->second;
|
||||
return !shape.isNull();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void setShape(const App::DocumentObject *obj, const TopoShape &shape, const char *subname=0) {
|
||||
init();
|
||||
if(!subname) subname = "";
|
||||
cache[obj->getDocument()][std::make_pair(obj,std::string(subname))] = shape;
|
||||
}
|
||||
};
|
||||
static ShapeCache _ShapeCache;
|
||||
|
||||
void Feature::clearShapeCache() {
|
||||
_ShapeCache.cache.clear();
|
||||
}
|
||||
|
||||
static TopoShape _getTopoShape(const App::DocumentObject *obj, const char *subname,
|
||||
bool needSubElement, Base::Matrix4D *pmat, App::DocumentObject **powner,
|
||||
bool resolveLink, bool noElementMap, std::vector<App::DocumentObject*> &linkStack)
|
||||
|
||||
{
|
||||
TopoShape shape;
|
||||
|
||||
if(!obj) return shape;
|
||||
|
||||
PyObject *pyobj = 0;
|
||||
Base::Matrix4D mat;
|
||||
if(powner) *powner = 0;
|
||||
|
||||
std::string _subname;
|
||||
auto subelement = Data::ComplexGeoData::findElementName(subname);
|
||||
if(!needSubElement && subname) {
|
||||
// strip out element name if not needed
|
||||
if(subelement && *subelement) {
|
||||
_subname = std::string(subname,subelement);
|
||||
subname = _subname.c_str();
|
||||
}
|
||||
}
|
||||
|
||||
if(_ShapeCache.getShape(obj,shape,subname)) {
|
||||
if(noElementMap) {
|
||||
// shape.resetElementMap();
|
||||
// shape.Tag = 0;
|
||||
// shape.Hasher.reset();
|
||||
}
|
||||
}
|
||||
|
||||
App::DocumentObject *linked = 0;
|
||||
App::DocumentObject *owner = 0;
|
||||
Base::Matrix4D linkMat;
|
||||
// App::StringHasherRef hasher;
|
||||
// long tag;
|
||||
{
|
||||
Base::PyGILStateLocker lock;
|
||||
owner = obj->getSubObject(subname,shape.isNull()?&pyobj:0,&mat,false);
|
||||
if(!owner)
|
||||
return shape;
|
||||
// tag = owner->getID();
|
||||
// hasher = owner->getDocument()->getStringHasher();
|
||||
linked = owner->getLinkedObject(true,&linkMat,false);
|
||||
if(pmat) {
|
||||
if(resolveLink && obj!=owner)
|
||||
*pmat = mat * linkMat;
|
||||
else
|
||||
*pmat = mat;
|
||||
}
|
||||
if(!linked)
|
||||
linked = owner;
|
||||
if(powner)
|
||||
*powner = resolveLink?linked:owner;
|
||||
|
||||
if(!shape.isNull())
|
||||
return shape;
|
||||
|
||||
if(pyobj && PyObject_TypeCheck(pyobj,&TopoShapePy::Type)) {
|
||||
shape = *static_cast<TopoShapePy*>(pyobj)->getTopoShapePtr();
|
||||
if(!shape.isNull()) {
|
||||
if(obj->getDocument() != linked->getDocument())
|
||||
_ShapeCache.setShape(obj,shape,subname);
|
||||
if(noElementMap) {
|
||||
// shape.resetElementMap();
|
||||
// shape.Tag = 0;
|
||||
// shape.Hasher.reset();
|
||||
}
|
||||
Py_DECREF(pyobj);
|
||||
return shape;
|
||||
}
|
||||
}
|
||||
|
||||
Py_XDECREF(pyobj);
|
||||
}
|
||||
|
||||
// nothing can be done if there is sub-element references
|
||||
if(needSubElement && subelement && *subelement)
|
||||
return shape;
|
||||
|
||||
bool scaled = false;
|
||||
if(obj!=owner) {
|
||||
if(_ShapeCache.getShape(owner,shape)) {
|
||||
auto scaled = shape.transformShape(mat,false,true);
|
||||
if(owner->getDocument()!=obj->getDocument()) {
|
||||
// shape.reTagElementMap(obj->getID(),obj->getDocument()->getStringHasher());
|
||||
_ShapeCache.setShape(obj,shape,subname);
|
||||
} else if(scaled)
|
||||
_ShapeCache.setShape(obj,shape,subname);
|
||||
}
|
||||
if(!shape.isNull()) {
|
||||
if(noElementMap) {
|
||||
// shape.resetElementMap();
|
||||
// shape.Tag = 0;
|
||||
// shape.Hasher.reset();
|
||||
}
|
||||
return shape;
|
||||
}
|
||||
}
|
||||
|
||||
auto link = owner->getExtensionByType<App::LinkBaseExtension>(true);
|
||||
if(owner!=linked && (!link || !link->_ChildCache.getSize())) {
|
||||
// if there is a linked object, and there is no child cache (which is used
|
||||
// for special handling of plain group), obtain shape from the linked object
|
||||
shape = Feature::getTopoShape(linked,0,false,0,0,false,false);
|
||||
if(shape.isNull())
|
||||
return shape;
|
||||
if(owner==obj)
|
||||
shape.transformShape(mat*linkMat,false,true);
|
||||
else
|
||||
shape.transformShape(linkMat,false,true);
|
||||
// shape.reTagElementMap(tag,hasher);
|
||||
|
||||
} else {
|
||||
|
||||
if(link || owner->getExtensionByType<App::GeoFeatureGroupExtension>(true))
|
||||
linkStack.push_back(owner);
|
||||
|
||||
// Construct a compound of sub objects
|
||||
std::vector<TopoShape> shapes;
|
||||
|
||||
// Acceleration for link array. Unlike non-array link, a link array does
|
||||
// not return the linked object when calling getLinkedObject().
|
||||
// Therefore, it should be handled here.
|
||||
TopoShape baseShape;
|
||||
std::string op;
|
||||
if(link && link->getElementCountValue()) {
|
||||
linked = link->getTrueLinkedObject(false);
|
||||
if(linked && linked!=owner) {
|
||||
baseShape = Feature::getTopoShape(linked,0,false,0,0,false,false);
|
||||
// if(!link->getShowElementValue())
|
||||
// baseShape.reTagElementMap(owner->getID(),owner->getDocument()->getStringHasher());
|
||||
}
|
||||
}
|
||||
for(auto &sub : owner->getSubObjects()) {
|
||||
if(sub.empty()) continue;
|
||||
int visible;
|
||||
if(sub[sub.size()-1] != '.')
|
||||
sub += '.';
|
||||
std::string childName;
|
||||
App::DocumentObject *parent=0;
|
||||
Base::Matrix4D mat;
|
||||
auto subObj = owner->resolve(sub.c_str(), &parent, &childName,0,0,&mat,false);
|
||||
if(!parent || !subObj)
|
||||
continue;
|
||||
if(linkStack.size()
|
||||
&& parent->getExtensionByType<App::GroupExtension>(true,false))
|
||||
{
|
||||
visible = linkStack.back()->isElementVisible(childName.c_str());
|
||||
}else
|
||||
visible = parent->isElementVisible(childName.c_str());
|
||||
if(visible==0)
|
||||
continue;
|
||||
TopoShape shape;
|
||||
if(baseShape.isNull()) {
|
||||
shape = _getTopoShape(owner,sub.c_str(),false,0,&subObj,false,false,linkStack);
|
||||
if(shape.isNull())
|
||||
continue;
|
||||
if(visible<0 && subObj && !subObj->Visibility.getValue())
|
||||
continue;
|
||||
}else{
|
||||
if(link && !link->getShowElementValue())
|
||||
shape = baseShape.makETransform(mat,(TopoShape::indexPostfix()+childName).c_str());
|
||||
else {
|
||||
shape = baseShape.makETransform(mat);
|
||||
// shape.reTagElementMap(subObj->getID(),subObj->getDocument()->getStringHasher());
|
||||
}
|
||||
}
|
||||
shapes.push_back(shape);
|
||||
}
|
||||
|
||||
if(linkStack.size() && linkStack.back()==owner)
|
||||
linkStack.pop_back();
|
||||
|
||||
if(shapes.empty())
|
||||
return shape;
|
||||
|
||||
// shape.Tag = tag;
|
||||
// shape.Hasher = hasher;
|
||||
shape.makECompound(shapes);
|
||||
}
|
||||
|
||||
_ShapeCache.setShape(owner,shape);
|
||||
|
||||
if(owner!=obj) {
|
||||
scaled = shape.transformShape(mat,false,true);
|
||||
if(owner->getDocument()!=obj->getDocument()) {
|
||||
// shape.reTagElementMap(obj->getID(),obj->getDocument()->getStringHasher());
|
||||
_ShapeCache.setShape(obj,shape,subname);
|
||||
}else if(scaled)
|
||||
_ShapeCache.setShape(obj,shape,subname);
|
||||
}
|
||||
if(noElementMap) {
|
||||
// shape.resetElementMap();
|
||||
// shape.Tag = 0;
|
||||
// shape.Hasher.reset();
|
||||
}
|
||||
return shape;
|
||||
}
|
||||
|
||||
TopoShape Feature::getTopoShape(const App::DocumentObject *obj, const char *subname,
|
||||
bool needSubElement, Base::Matrix4D *pmat, App::DocumentObject **powner,
|
||||
bool resolveLink, bool transform, bool noElementMap)
|
||||
{
|
||||
if(!obj || !obj->getNameInDocument())
|
||||
return TopoShape();
|
||||
|
||||
std::vector<App::DocumentObject*> linkStack;
|
||||
|
||||
// NOTE! _getTopoShape() always return shape without top level
|
||||
// transformation for easy shape caching, i.e. with `transform` set
|
||||
// to false. So we manually apply the top level transform if asked.
|
||||
|
||||
Base::Matrix4D mat;
|
||||
auto shape = _getTopoShape(obj, subname, needSubElement, &mat,
|
||||
powner, resolveLink, noElementMap, linkStack);
|
||||
|
||||
Base::Matrix4D topMat;
|
||||
if(pmat || transform) {
|
||||
// Obtain top level transformation
|
||||
if(pmat)
|
||||
topMat = *pmat;
|
||||
if(transform)
|
||||
obj->getSubObject(0,0,&topMat);
|
||||
|
||||
// Apply the top level transformation
|
||||
if(!shape.isNull())
|
||||
shape.transformShape(topMat,false,true);
|
||||
|
||||
if(pmat)
|
||||
*pmat = topMat * mat;
|
||||
}
|
||||
|
||||
return shape;
|
||||
|
||||
}
|
||||
|
||||
App::DocumentObject *Feature::getShapeOwner(const App::DocumentObject *obj, const char *subname)
|
||||
{
|
||||
if(!obj) return 0;
|
||||
auto owner = obj->getSubObject(subname);
|
||||
if(owner) {
|
||||
auto linked = owner->getLinkedObject(true);
|
||||
if(linked)
|
||||
owner = linked;
|
||||
}
|
||||
return owner;
|
||||
}
|
||||
|
||||
void Feature::onChanged(const App::Property* prop)
|
||||
{
|
||||
// if the placement has changed apply the change to the point data as well
|
||||
|
||||
@@ -71,6 +71,44 @@ public:
|
||||
virtual DocumentObject *getSubObject(const char *subname, PyObject **pyObj,
|
||||
Base::Matrix4D *mat, bool transform, int depth) const override;
|
||||
|
||||
/** Convenience function to extract shape from fully qualified subname
|
||||
*
|
||||
* @param obj: the parent object
|
||||
*
|
||||
* @param subname: dot separated full qualified subname
|
||||
*
|
||||
* @param needSubElement: whether to ignore the non-object subelement
|
||||
* reference inside \c subname
|
||||
*
|
||||
* @param pmat: used as current transformation on input, and return the
|
||||
* accumulated transformation on output
|
||||
*
|
||||
* @param owner: return the owner of the shape returned
|
||||
*
|
||||
* @param resolveLink: if true, resolve link(s) of the returned 'owner'
|
||||
* by calling its getLinkedObject(true) function
|
||||
*
|
||||
* @param transform: if true, apply obj's transformation. Set to false
|
||||
* if pmat already include obj's transformation matrix.
|
||||
*/
|
||||
static TopoDS_Shape getShape(const App::DocumentObject *obj,
|
||||
const char *subname=0, bool needSubElement=false, Base::Matrix4D *pmat=0,
|
||||
App::DocumentObject **owner=0, bool resolveLink=true, bool transform=true);
|
||||
|
||||
static TopoShape getTopoShape(const App::DocumentObject *obj,
|
||||
const char *subname=0, bool needSubElement=false, Base::Matrix4D *pmat=0,
|
||||
App::DocumentObject **owner=0, bool resolveLink=true, bool transform=true,
|
||||
bool noElementMap=false);
|
||||
|
||||
static void clearShapeCache();
|
||||
|
||||
static App::DocumentObject *getShapeOwner(const App::DocumentObject *obj, const char *subname=0);
|
||||
|
||||
static bool hasShapeOwner(const App::DocumentObject *obj, const char *subname=0) {
|
||||
auto owner = getShapeOwner(obj,subname);
|
||||
return owner && owner->isDerivedFrom(getClassTypeId());
|
||||
}
|
||||
|
||||
protected:
|
||||
/// recompute only this object
|
||||
virtual App::DocumentObjectExecReturn *recompute(void);
|
||||
|
||||
@@ -84,20 +84,20 @@ App::DocumentObjectExecReturn* RuledSurface::getShape(const App::PropertyLinkSub
|
||||
TopoDS_Shape& shape) const
|
||||
{
|
||||
App::DocumentObject* obj = link.getValue();
|
||||
if (!(obj && obj->getTypeId().isDerivedFrom(Part::Feature::getClassTypeId())))
|
||||
if(!obj)
|
||||
return new App::DocumentObjectExecReturn("No shape linked.");
|
||||
|
||||
// if no explicit sub-shape is selected use the whole part
|
||||
const std::vector<std::string>& element = link.getSubValues();
|
||||
if (element.empty()) {
|
||||
shape = static_cast<Part::Feature*>(obj)->Shape.getValue();
|
||||
shape = Feature::getShape(obj);
|
||||
return nullptr;
|
||||
}
|
||||
else if (element.size() != 1) {
|
||||
return new App::DocumentObjectExecReturn("Not exactly one sub-shape linked.");
|
||||
}
|
||||
|
||||
const Part::TopoShape& part = static_cast<Part::Feature*>(obj)->Shape.getValue();
|
||||
const Part::TopoShape& part = Feature::getTopoShape(obj);
|
||||
if (!part.getShape().IsNull()) {
|
||||
if (!element[0].empty()) {
|
||||
shape = part.getSubShape(element[0].c_str());
|
||||
@@ -311,9 +311,7 @@ App::DocumentObjectExecReturn *Loft::execute(void)
|
||||
const std::vector<App::DocumentObject*>& shapes = Sections.getValues();
|
||||
std::vector<App::DocumentObject*>::const_iterator it;
|
||||
for (it = shapes.begin(); it != shapes.end(); ++it) {
|
||||
if (!(*it)->isDerivedFrom(Part::Feature::getClassTypeId()))
|
||||
return new App::DocumentObjectExecReturn("Linked object is not a shape.");
|
||||
TopoDS_Shape shape = static_cast<Part::Feature*>(*it)->Shape.getValue();
|
||||
TopoDS_Shape shape = Feature::getShape(*it);
|
||||
if (shape.IsNull())
|
||||
return new App::DocumentObjectExecReturn("Linked shape is invalid.");
|
||||
|
||||
@@ -424,12 +422,12 @@ App::DocumentObjectExecReturn *Sweep::execute(void)
|
||||
if (Sections.getSize() == 0)
|
||||
return new App::DocumentObjectExecReturn("No sections linked.");
|
||||
App::DocumentObject* spine = Spine.getValue();
|
||||
if (!(spine && spine->getTypeId().isDerivedFrom(Part::Feature::getClassTypeId())))
|
||||
if (!spine)
|
||||
return new App::DocumentObjectExecReturn("No spine linked.");
|
||||
const std::vector<std::string>& subedge = Spine.getSubValues();
|
||||
|
||||
TopoDS_Shape path;
|
||||
const Part::TopoShape& shape = static_cast<Part::Feature*>(spine)->Shape.getValue();
|
||||
const Part::TopoShape& shape = Feature::getTopoShape(spine);
|
||||
if (!shape.getShape().IsNull()) {
|
||||
try {
|
||||
if (!subedge.empty()) {
|
||||
@@ -483,9 +481,7 @@ App::DocumentObjectExecReturn *Sweep::execute(void)
|
||||
const std::vector<App::DocumentObject*>& shapes = Sections.getValues();
|
||||
std::vector<App::DocumentObject*>::const_iterator it;
|
||||
for (it = shapes.begin(); it != shapes.end(); ++it) {
|
||||
if (!(*it)->isDerivedFrom(Part::Feature::getClassTypeId()))
|
||||
return new App::DocumentObjectExecReturn("Linked object is not a shape.");
|
||||
TopoDS_Shape shape = static_cast<Part::Feature*>(*it)->Shape.getValue();
|
||||
TopoDS_Shape shape = Feature::getShape(*it);
|
||||
if (shape.IsNull())
|
||||
return new App::DocumentObjectExecReturn("Linked shape is invalid.");
|
||||
|
||||
@@ -638,9 +634,9 @@ void Thickness::handleChangedPropertyType(Base::XMLReader &reader, const char *T
|
||||
App::DocumentObjectExecReturn *Thickness::execute(void)
|
||||
{
|
||||
App::DocumentObject* source = Faces.getValue();
|
||||
if (!(source && source->getTypeId().isDerivedFrom(Part::Feature::getClassTypeId())))
|
||||
if (!source)
|
||||
return new App::DocumentObjectExecReturn("No source shape linked.");
|
||||
const TopoShape& shape = static_cast<Part::Feature*>(source)->Shape.getShape();
|
||||
const TopoShape& shape = Feature::getTopoShape(source);
|
||||
if (shape.isNull())
|
||||
return new App::DocumentObjectExecReturn("Source shape is empty.");
|
||||
|
||||
|
||||
@@ -33,11 +33,11 @@
|
||||
#include <Mod/Part/App/TopoShapeCompoundPy.h>
|
||||
|
||||
namespace Part {
|
||||
PartExport Py::Object shape2pyshape(const TopoDS_Shape &shape)
|
||||
PartExport Py::Object shape2pyshape(const TopoShape &shape)
|
||||
{
|
||||
PyObject* ret = 0;
|
||||
if (!shape.IsNull()) {
|
||||
TopAbs_ShapeEnum type = shape.ShapeType();
|
||||
if (!shape.isNull()) {
|
||||
TopAbs_ShapeEnum type = shape.getShape().ShapeType();
|
||||
switch (type)
|
||||
{
|
||||
case TopAbs_COMPOUND:
|
||||
@@ -79,6 +79,11 @@ PartExport Py::Object shape2pyshape(const TopoDS_Shape &shape)
|
||||
|
||||
return Py::asObject(ret);
|
||||
}
|
||||
|
||||
PartExport Py::Object shape2pyshape(const TopoDS_Shape &shape) {
|
||||
return shape2pyshape(TopoShape(shape));
|
||||
}
|
||||
|
||||
} //namespace Part
|
||||
|
||||
|
||||
|
||||
@@ -32,4 +32,11 @@ namespace Py {
|
||||
bool TopoShape::accepts (PyObject *pyob) const;
|
||||
}
|
||||
|
||||
namespace Part {
|
||||
PartExport Py::Object shape2pyshape(const TopoShape &shape);
|
||||
PartExport Py::Object shape2pyshape(const TopoDS_Shape &shape);
|
||||
PartExport void getPyShapes(PyObject *obj, std::vector<TopoShape> &shapes);
|
||||
PartExport std::vector<TopoShape> getPyShapes(PyObject *obj);
|
||||
}
|
||||
|
||||
#endif //PART_PYCXX_H
|
||||
|
||||
@@ -181,6 +181,8 @@
|
||||
#endif
|
||||
#endif // _PreComp_
|
||||
|
||||
#include <boost/algorithm/string/predicate.hpp>
|
||||
|
||||
#include <Base/Builder3D.h>
|
||||
#include <Base/FileInfo.h>
|
||||
#include <Base/Exception.h>
|
||||
@@ -188,6 +190,7 @@
|
||||
#include <Base/Console.h>
|
||||
#include <App/Material.h>
|
||||
|
||||
#include "PartPyCXX.h"
|
||||
#include "TopoShape.h"
|
||||
#include "CrossSection.h"
|
||||
#include "TopoShapeFacePy.h"
|
||||
@@ -200,6 +203,8 @@
|
||||
#include "FaceMakerBullseye.h"
|
||||
#include "BRepOffsetAPI_MakeOffsetFix.h"
|
||||
|
||||
FC_LOG_LEVEL_INIT("TopoShape",true,true);
|
||||
|
||||
using namespace Part;
|
||||
|
||||
const char* BRepBuilderAPI_FaceErrorText(BRepBuilderAPI_FaceError et)
|
||||
@@ -298,6 +303,7 @@ TopoShape::TopoShape(const TopoDS_Shape& shape)
|
||||
TopoShape::TopoShape(const TopoShape& shape)
|
||||
: _Shape(shape._Shape)
|
||||
{
|
||||
Tag = shape.Tag;
|
||||
}
|
||||
|
||||
std::vector<const char*> TopoShape::getElementTypes(void) const
|
||||
@@ -323,88 +329,188 @@ Data::Segment* TopoShape::getSubElement(const char* Type, unsigned long n) const
|
||||
return new ShapeSegment(getSubShape(temp.c_str()));
|
||||
}
|
||||
|
||||
TopoDS_Shape TopoShape::getSubShape(const char* Type) const
|
||||
TopoDS_Shape TopoShape::getSubShape(const char* Type, bool silent) const
|
||||
{
|
||||
if (!Type)
|
||||
Standard_Failure::Raise("No sub-shape type given");
|
||||
if (this->_Shape.IsNull())
|
||||
auto res = shapeTypeAndIndex(Type);
|
||||
return getSubShape(res.first,res.second,silent);
|
||||
}
|
||||
|
||||
TopoDS_Shape TopoShape::getSubShape(TopAbs_ShapeEnum type, int index, bool silent) const
|
||||
{
|
||||
if(index <= 0) {
|
||||
if(silent)
|
||||
return TopoDS_Shape();
|
||||
Standard_Failure::Raise("Unsupported sub-shape type");
|
||||
}
|
||||
|
||||
if (this->_Shape.IsNull()) {
|
||||
if(silent)
|
||||
return TopoDS_Shape();
|
||||
Standard_Failure::Raise("Cannot get sub-shape from empty shape");
|
||||
|
||||
std::string shapetype(Type);
|
||||
if (shapetype.size() > 4 && shapetype.substr(0,4) == "Face") {
|
||||
int index=std::atoi(&shapetype[4]);
|
||||
TopTools_IndexedMapOfShape anIndices;
|
||||
TopExp::MapShapes(this->_Shape, TopAbs_FACE, anIndices);
|
||||
// To avoid a segmentation fault we have to check if container is empty
|
||||
if (anIndices.IsEmpty())
|
||||
Standard_Failure::Raise("Shape has no faces");
|
||||
return anIndices.FindKey(index);
|
||||
}
|
||||
else if (shapetype.size() > 4 && shapetype.substr(0,4) == "Edge") {
|
||||
int index=std::atoi(&shapetype[4]);
|
||||
TopTools_IndexedMapOfShape anIndices;
|
||||
TopExp::MapShapes(this->_Shape, TopAbs_EDGE, anIndices);
|
||||
// To avoid a segmentation fault we have to check if container is empty
|
||||
if (anIndices.IsEmpty())
|
||||
Standard_Failure::Raise("Shape has no edges");
|
||||
return anIndices.FindKey(index);
|
||||
}
|
||||
else if (shapetype.size() > 6 && shapetype.substr(0,6) == "Vertex") {
|
||||
int index=std::atoi(&shapetype[6]);
|
||||
TopTools_IndexedMapOfShape anIndices;
|
||||
TopExp::MapShapes(this->_Shape, TopAbs_VERTEX, anIndices);
|
||||
// To avoid a segmentation fault we have to check if container is empty
|
||||
if (anIndices.IsEmpty())
|
||||
Standard_Failure::Raise("Shape has no vertexes");
|
||||
return anIndices.FindKey(index);
|
||||
}
|
||||
|
||||
Standard_Failure::Raise("Unsupported sub-shape type");
|
||||
return TopoDS_Shape(); // avoid compiler warning
|
||||
try {
|
||||
if(type == TopAbs_SHAPE) {
|
||||
int i=1;
|
||||
for(TopoDS_Iterator it(_Shape);it.More();it.Next(),++i) {
|
||||
if(i == index)
|
||||
return it.Value();
|
||||
}
|
||||
} else {
|
||||
TopTools_IndexedMapOfShape anIndices;
|
||||
TopExp::MapShapes(this->_Shape, type, anIndices);
|
||||
if(index <= anIndices.Extent())
|
||||
return anIndices.FindKey(index);
|
||||
}
|
||||
} catch(Standard_Failure &) {
|
||||
if(silent)
|
||||
return TopoDS_Shape();
|
||||
throw;
|
||||
}
|
||||
if(!silent)
|
||||
Standard_Failure::Raise("Index out of bound");
|
||||
return TopoDS_Shape();
|
||||
}
|
||||
|
||||
unsigned long TopoShape::countSubShapes(const char* Type) const
|
||||
{
|
||||
std::string shapetype(Type);
|
||||
if (shapetype == "Face") {
|
||||
TopTools_IndexedMapOfShape anIndices;
|
||||
TopExp::MapShapes(this->_Shape, TopAbs_FACE, anIndices);
|
||||
return anIndices.Extent();
|
||||
}
|
||||
else if (shapetype == "Edge") {
|
||||
TopTools_IndexedMapOfShape anIndices;
|
||||
TopExp::MapShapes(this->_Shape, TopAbs_EDGE, anIndices);
|
||||
return anIndices.Extent();
|
||||
}
|
||||
else if (shapetype == "Vertex") {
|
||||
TopTools_IndexedMapOfShape anIndices;
|
||||
TopExp::MapShapes(this->_Shape, TopAbs_VERTEX, anIndices);
|
||||
return anIndices.Extent();
|
||||
}
|
||||
|
||||
return 0;
|
||||
if(!Type) return 0;
|
||||
if(strcmp(Type,"SubShape")==0)
|
||||
return countSubShapes(TopAbs_SHAPE);
|
||||
auto type = shapeType(Type,true);
|
||||
if(type == TopAbs_SHAPE)
|
||||
return 0;
|
||||
return countSubShapes(type);
|
||||
}
|
||||
|
||||
PyObject * TopoShape::getPySubShape(const char* Type) const
|
||||
unsigned long TopoShape::countSubShapes(TopAbs_ShapeEnum Type) const
|
||||
{
|
||||
// get the shape
|
||||
TopoDS_Shape Shape = getSubShape(Type);
|
||||
// destinquish the return type
|
||||
std::string shapetype(Type);
|
||||
if (shapetype.size() > 4 && shapetype.substr(0,4) == "Face")
|
||||
return new TopoShapeFacePy(new TopoShape(Shape));
|
||||
else if (shapetype.size() > 4 && shapetype.substr(0,4) == "Edge")
|
||||
return new TopoShapeEdgePy(new TopoShape(Shape));
|
||||
else if (shapetype.size() > 6 && shapetype.substr(0,6) == "Vertex")
|
||||
return new TopoShapeVertexPy(new TopoShape(Shape));
|
||||
else
|
||||
return 0;
|
||||
if(Type == TopAbs_SHAPE) {
|
||||
int count = 0;
|
||||
for(TopoDS_Iterator it(_Shape);it.More();it.Next())
|
||||
++count;
|
||||
return count;
|
||||
}
|
||||
TopTools_IndexedMapOfShape anIndices;
|
||||
TopExp::MapShapes(this->_Shape, Type, anIndices);
|
||||
return anIndices.Extent();
|
||||
}
|
||||
|
||||
bool TopoShape::hasSubShape(TopAbs_ShapeEnum type) const {
|
||||
if(type == TopAbs_SHAPE) {
|
||||
TopoDS_Iterator it(_Shape);
|
||||
return !!it.More();
|
||||
}
|
||||
TopExp_Explorer exp(_Shape,type);
|
||||
return !!exp.More();
|
||||
}
|
||||
|
||||
bool TopoShape::hasSubShape(const char *Type) const {
|
||||
auto idx = shapeTypeAndIndex(Type);
|
||||
return idx.second>0 && idx.second<=(int)countSubShapes(idx.first);
|
||||
}
|
||||
|
||||
static std::array<std::string,TopAbs_SHAPE> _ShapeNames;
|
||||
|
||||
static void initShapeNameMap() {
|
||||
if(_ShapeNames[TopAbs_VERTEX].empty()) {
|
||||
_ShapeNames[TopAbs_VERTEX] = "Vertex";
|
||||
_ShapeNames[TopAbs_EDGE] = "Edge";
|
||||
_ShapeNames[TopAbs_FACE] = "Face";
|
||||
_ShapeNames[TopAbs_WIRE] = "Wire";
|
||||
_ShapeNames[TopAbs_SHELL] = "Shell";
|
||||
_ShapeNames[TopAbs_SOLID] = "Solid";
|
||||
_ShapeNames[TopAbs_COMPOUND] = "Compound";
|
||||
_ShapeNames[TopAbs_COMPSOLID] = "CompSolid";
|
||||
}
|
||||
}
|
||||
|
||||
std::pair<TopAbs_ShapeEnum,int> TopoShape::shapeTypeAndIndex(const char *name) {
|
||||
int idx = 0;
|
||||
TopAbs_ShapeEnum type = TopAbs_SHAPE;
|
||||
static const std::string _subshape("SubShape");
|
||||
if(boost::starts_with(name,_subshape)) {
|
||||
std::istringstream iss(name+_subshape.size());
|
||||
iss >> idx;
|
||||
if(!iss.eof())
|
||||
idx = 0;
|
||||
} else {
|
||||
type = shapeType(name,true);
|
||||
if(type != TopAbs_SHAPE) {
|
||||
std::istringstream iss(name+shapeName(type).size());
|
||||
iss >> idx;
|
||||
if(!iss.eof()) {
|
||||
idx = 0;
|
||||
type = TopAbs_SHAPE;
|
||||
}
|
||||
}
|
||||
}
|
||||
return std::make_pair(type,idx);
|
||||
}
|
||||
|
||||
TopAbs_ShapeEnum TopoShape::shapeType(const char *type, bool silent) {
|
||||
if(type) {
|
||||
initShapeNameMap();
|
||||
for(size_t idx=0;idx<_ShapeNames.size();++idx) {
|
||||
if(_ShapeNames[idx].size() && boost::starts_with(type,_ShapeNames[idx]))
|
||||
return (TopAbs_ShapeEnum)idx;
|
||||
}
|
||||
}
|
||||
if(!silent) {
|
||||
if(Data::ComplexGeoData::hasMissingElement(type))
|
||||
FC_THROWM(Base::CADKernelError,"missing shape element: " << (type?type:"?"));
|
||||
FC_THROWM(Base::CADKernelError,"invalid shape type: " << (type?type:"?"));
|
||||
}
|
||||
return TopAbs_SHAPE;
|
||||
}
|
||||
|
||||
TopAbs_ShapeEnum TopoShape::shapeType(char type, bool silent) {
|
||||
switch(type) {
|
||||
case 'E':
|
||||
return TopAbs_EDGE;
|
||||
case 'V':
|
||||
return TopAbs_VERTEX;
|
||||
case 'F':
|
||||
return TopAbs_FACE;
|
||||
default:
|
||||
if(!silent)
|
||||
FC_THROWM(Base::CADKernelError, "invalid shape type '" << type << "'");
|
||||
return TopAbs_SHAPE;
|
||||
}
|
||||
}
|
||||
|
||||
TopAbs_ShapeEnum TopoShape::shapeType(bool silent) const {
|
||||
if(isNull()) {
|
||||
if(!silent)
|
||||
FC_THROWM(NullShapeException, "Input shape is null");
|
||||
return TopAbs_SHAPE;
|
||||
}
|
||||
return getShape().ShapeType();
|
||||
}
|
||||
|
||||
const std::string &TopoShape::shapeName(TopAbs_ShapeEnum type, bool silent) {
|
||||
initShapeNameMap();
|
||||
if(type>=0 && type<_ShapeNames.size() && _ShapeNames[type].size())
|
||||
return _ShapeNames[type];
|
||||
if(!silent)
|
||||
FC_THROWM(Base::CADKernelError, "invalid shape type '" << type << "'");
|
||||
static std::string ret("");
|
||||
return ret;
|
||||
}
|
||||
|
||||
const std::string &TopoShape::shapeName(bool silent) const {
|
||||
return shapeName(shapeType(silent),silent);
|
||||
}
|
||||
|
||||
PyObject * TopoShape::getPySubShape(const char* Type, bool silent) const
|
||||
{
|
||||
return Py::new_reference_to(shape2pyshape(getSubShape(Type,silent)));
|
||||
}
|
||||
|
||||
void TopoShape::operator = (const TopoShape& sh)
|
||||
{
|
||||
if (this != &sh) {
|
||||
this->Tag = sh.Tag;
|
||||
this->_Shape = sh._Shape;
|
||||
}
|
||||
}
|
||||
@@ -470,6 +576,18 @@ void TopoShape::convertToMatrix(const gp_Trsf& trsf, Base::Matrix4D& mtrx)
|
||||
#endif
|
||||
}
|
||||
|
||||
Base::Matrix4D TopoShape::convert(const gp_Trsf& trsf) {
|
||||
Base::Matrix4D mat;
|
||||
convertToMatrix(trsf,mat);
|
||||
return mat;
|
||||
}
|
||||
|
||||
gp_Trsf TopoShape::convert(const Base::Matrix4D& mtrx) {
|
||||
gp_Trsf trsf;
|
||||
convertTogpTrsf(mtrx,trsf);
|
||||
return trsf;
|
||||
}
|
||||
|
||||
void TopoShape::setTransform(const Base::Matrix4D& rclTrf)
|
||||
{
|
||||
gp_Trsf mov;
|
||||
@@ -2841,7 +2959,10 @@ TopoDS_Shape TopoShape::makeThickSolid(const TopTools_ListOfShape& remFace,
|
||||
|
||||
void TopoShape::transformGeometry(const Base::Matrix4D &rclMat)
|
||||
{
|
||||
this->_Shape = transformGShape(rclMat);
|
||||
if (this->_Shape.IsNull())
|
||||
Standard_Failure::Raise("Cannot transform null shape");
|
||||
|
||||
*this = makEGTransform(rclMat);
|
||||
}
|
||||
|
||||
TopoDS_Shape TopoShape::transformGShape(const Base::Matrix4D& rclTrf) const
|
||||
@@ -2868,23 +2989,12 @@ TopoDS_Shape TopoShape::transformGShape(const Base::Matrix4D& rclTrf) const
|
||||
return mkTrf.Shape();
|
||||
}
|
||||
|
||||
void TopoShape::transformShape(const Base::Matrix4D& rclTrf, bool copy)
|
||||
bool TopoShape::transformShape(const Base::Matrix4D& rclTrf, bool copy, bool checkScale)
|
||||
{
|
||||
if (this->_Shape.IsNull())
|
||||
Standard_Failure::Raise("Cannot transform null shape");
|
||||
|
||||
gp_Trsf mat;
|
||||
mat.SetValues(rclTrf[0][0],rclTrf[0][1],rclTrf[0][2],rclTrf[0][3],
|
||||
rclTrf[1][0],rclTrf[1][1],rclTrf[1][2],rclTrf[1][3],
|
||||
rclTrf[2][0],rclTrf[2][1],rclTrf[2][2],rclTrf[2][3]
|
||||
#if OCC_VERSION_HEX < 0x060800
|
||||
, 0.00001,0.00001
|
||||
#endif
|
||||
); //precision was removed in OCCT CR0025194
|
||||
|
||||
// location transformation
|
||||
BRepBuilderAPI_Transform mkTrf(this->_Shape, mat, copy ? Standard_True : Standard_False);
|
||||
this->_Shape = mkTrf.Shape();
|
||||
return _makETransform(TopoShape(*this),rclTrf,0,checkScale,copy);
|
||||
}
|
||||
|
||||
TopoDS_Shape TopoShape::mirror(const gp_Ax2& ax2) const
|
||||
@@ -3428,6 +3538,10 @@ void TopoShape::getLinesFromSubelement(const Data::Segment* element,
|
||||
return;
|
||||
}
|
||||
|
||||
// build up map edge->face
|
||||
TopTools_IndexedDataMapOfShapeListOfShape edge2Face;
|
||||
TopExp::MapShapesAndAncestors(this->_Shape, TopAbs_EDGE, TopAbs_FACE, edge2Face);
|
||||
|
||||
for(TopExp_Explorer exp(shape,TopAbs_EDGE);exp.More();exp.Next()) {
|
||||
|
||||
TopoDS_Edge aEdge = TopoDS::Edge(exp.Current());
|
||||
@@ -3460,12 +3574,16 @@ void TopoShape::getLinesFromSubelement(const Data::Segment* element,
|
||||
// must provide this triangulation
|
||||
|
||||
// Look for one face in our map (it doesn't care which one we take)
|
||||
auto aFace = findAncestorShape(aEdge, TopAbs_FACE);
|
||||
if(aFace.IsNull())
|
||||
int index = edge2Face.FindIndex(aEdge);
|
||||
if(!index)
|
||||
continue;
|
||||
const auto &faces = edge2Face.FindFromIndex(index);
|
||||
if(!faces.Extent())
|
||||
continue;
|
||||
const TopoDS_Face& aFace = TopoDS::Face(faces.First());
|
||||
|
||||
// take the face's triangulation instead
|
||||
Handle(Poly_Triangulation) aPolyTria = BRep_Tool::Triangulation(TopoDS::Face(aFace),aLoc);
|
||||
Handle(Poly_Triangulation) aPolyTria = BRep_Tool::Triangulation(aFace,aLoc);
|
||||
if (!aLoc.IsIdentity()) {
|
||||
myTransf = aLoc.Transformation();
|
||||
}
|
||||
@@ -3691,3 +3809,286 @@ TopoDS_Shape TopoShape::makeShell(const TopoDS_Shape& input) const
|
||||
return input;
|
||||
}
|
||||
}
|
||||
|
||||
#define _HANDLE_NULL_SHAPE(_msg,_throw) do {\
|
||||
if(_throw) {\
|
||||
FC_THROWM(NullShapeException,_msg);\
|
||||
}\
|
||||
FC_WARN(_msg);\
|
||||
}while(0)
|
||||
|
||||
#define HANDLE_NULL_SHAPE _HANDLE_NULL_SHAPE("Null shape",true)
|
||||
#define HANDLE_NULL_INPUT _HANDLE_NULL_SHAPE("Null input shape",true)
|
||||
#define WARN_NULL_INPUT _HANDLE_NULL_SHAPE("Null input shape",false)
|
||||
|
||||
TopoShape &TopoShape::makEWires(const TopoShape &shape, const char *op, bool fix, double tol)
|
||||
{
|
||||
_Shape.Nullify();
|
||||
|
||||
if(shape.isNull())
|
||||
HANDLE_NULL_INPUT;
|
||||
|
||||
if(tol<Precision::Confusion()) tol = Precision::Confusion();
|
||||
|
||||
(void)op;
|
||||
(void)fix;
|
||||
std::vector<TopoShape> edges;
|
||||
std::list<TopoShape> edge_list;
|
||||
std::vector<TopoShape> wires;
|
||||
|
||||
TopTools_IndexedMapOfShape anIndices;
|
||||
TopExp::MapShapes(shape.getShape(), TopAbs_EDGE, anIndices);
|
||||
for(int i=1;i<=anIndices.Extent();++i)
|
||||
edge_list.push_back(anIndices.FindKey(i));
|
||||
|
||||
edges.reserve(edge_list.size());
|
||||
wires.reserve(edge_list.size());
|
||||
|
||||
// sort them together to wires
|
||||
while (edge_list.size() > 0) {
|
||||
BRepBuilderAPI_MakeWire mkWire;
|
||||
// add and erase first edge
|
||||
edges.push_back(edge_list.front());
|
||||
edge_list.pop_front();
|
||||
mkWire.Add(TopoDS::Edge(edges.back().getShape()));
|
||||
edges.back().setShape(mkWire.Edge());
|
||||
|
||||
TopoDS_Wire new_wire = mkWire.Wire(); // current new wire
|
||||
|
||||
// try to connect each edge to the wire, the wire is complete if no more edges are connectible
|
||||
bool found = false;
|
||||
do {
|
||||
found = false;
|
||||
for (auto it=edge_list.begin();it!=edge_list.end();++it) {
|
||||
mkWire.Add(TopoDS::Edge(it->getShape()));
|
||||
if (mkWire.Error() != BRepBuilderAPI_DisconnectedWire) {
|
||||
// edge added ==> remove it from list
|
||||
found = true;
|
||||
edges.push_back(*it);
|
||||
edges.back().setShape(mkWire.Edge());
|
||||
edge_list.erase(it);
|
||||
new_wire = mkWire.Wire();
|
||||
break;
|
||||
}
|
||||
}
|
||||
} while (found);
|
||||
|
||||
// Fix any topological issues of the wire
|
||||
ShapeFix_Wire aFix;
|
||||
aFix.SetPrecision(tol);
|
||||
aFix.Load(new_wire);
|
||||
|
||||
aFix.FixReorder();
|
||||
// Assuming FixReorder() just reorder and don't change the underlying
|
||||
// edges, we get the wire and do a name mapping now, as the following
|
||||
// two operations (FixConnected and FixClosed) may change the edges.
|
||||
wires.push_back(aFix.Wire());
|
||||
|
||||
aFix.FixConnected();
|
||||
aFix.FixClosed();
|
||||
// Now retrieve the shape and set it without touching element map
|
||||
wires.back().setShape(aFix.Wire());
|
||||
}
|
||||
return makECompound(wires,0,false);
|
||||
}
|
||||
|
||||
TopoShape &TopoShape::makECompound(const std::vector<TopoShape> &shapes, const char *op, bool force)
|
||||
{
|
||||
(void)op;
|
||||
_Shape.Nullify();
|
||||
|
||||
if(shapes.empty())
|
||||
HANDLE_NULL_INPUT;
|
||||
|
||||
if(!force && shapes.size()==1) {
|
||||
*this = shapes[0];
|
||||
return *this;
|
||||
}
|
||||
|
||||
BRep_Builder builder;
|
||||
TopoDS_Compound comp;
|
||||
builder.MakeCompound(comp);
|
||||
int count = 0;
|
||||
for(auto &s : shapes) {
|
||||
if(s.isNull()) {
|
||||
WARN_NULL_INPUT;
|
||||
continue;
|
||||
}
|
||||
builder.Add(comp,s.getShape());
|
||||
++count;
|
||||
}
|
||||
if(!count)
|
||||
HANDLE_NULL_SHAPE;
|
||||
_Shape = comp;
|
||||
return *this;
|
||||
}
|
||||
|
||||
TopoShape &TopoShape::makEFace(const TopoShape &shape, const char *op, const char *maker)
|
||||
{
|
||||
std::vector<TopoShape> shapes;
|
||||
if(shape.getShape().ShapeType() == TopAbs_COMPOUND) {
|
||||
for(TopoDS_Iterator it(_Shape);it.More();it.Next())
|
||||
shapes.push_back(it.Value());
|
||||
} else
|
||||
shapes.push_back(shape);
|
||||
return makEFace(shapes,op,maker);
|
||||
}
|
||||
|
||||
TopoShape &TopoShape::makEFace(const std::vector<TopoShape> &shapes, const char *op, const char *maker)
|
||||
{
|
||||
(void)op;
|
||||
_Shape.Nullify();
|
||||
|
||||
if(!maker || !maker[0]) maker = "Part::FaceMakerBullseye";
|
||||
std::unique_ptr<FaceMaker> mkFace = FaceMaker::ConstructFromType(maker);
|
||||
for(auto &s : shapes) {
|
||||
if (s.getShape().ShapeType() == TopAbs_COMPOUND)
|
||||
mkFace->useCompound(TopoDS::Compound(s.getShape()));
|
||||
else
|
||||
mkFace->addShape(s.getShape());
|
||||
}
|
||||
mkFace->Build();
|
||||
_Shape = mkFace->Shape();
|
||||
return *this;
|
||||
}
|
||||
|
||||
TopoShape &TopoShape::makERefine(const TopoShape &shape, const char *op, bool no_fail) {
|
||||
(void)op;
|
||||
_Shape.Nullify();
|
||||
if(shape.isNull()) {
|
||||
if(!no_fail)
|
||||
HANDLE_NULL_SHAPE;
|
||||
return *this;
|
||||
}
|
||||
try {
|
||||
BRepBuilderAPI_RefineModel mkRefine(shape.getShape());
|
||||
_Shape = mkRefine.Shape();
|
||||
return *this;
|
||||
}catch (Standard_Failure &) {
|
||||
if(!no_fail) throw;
|
||||
}
|
||||
*this = shape;
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool TopoShape::findPlane(gp_Pln &pln, double tol) const {
|
||||
if(_Shape.IsNull())
|
||||
return false;
|
||||
TopoDS_Shape shape = _Shape;
|
||||
TopExp_Explorer exp(_Shape,TopAbs_FACE);
|
||||
if(exp.More()) {
|
||||
auto face = 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();
|
||||
}
|
||||
}
|
||||
}
|
||||
try {
|
||||
BRepLib_FindSurface finder(shape,tol,Standard_True);
|
||||
if (!finder.Found())
|
||||
return false;
|
||||
pln = GeomAdaptor_Surface(finder.Surface()).Plane();
|
||||
return true;
|
||||
}catch (Standard_Failure &e) {
|
||||
// For some reason the above BRepBuilderAPI_Copy failed to copy
|
||||
// the geometry of some edge, causing exception with message
|
||||
// BRepAdaptor_Curve::No geometry. However, without the above
|
||||
// copy, circular edges often have the wrong transformation!
|
||||
FC_LOG("failed to find surface: " << e.GetMessageString());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool TopoShape::isCoplanar(const TopoShape &other, double tol) const {
|
||||
if(isNull() || other.isNull())
|
||||
return false;
|
||||
if(_Shape.IsEqual(other._Shape))
|
||||
return true;
|
||||
gp_Pln pln1,pln2;
|
||||
if(!findPlane(pln1,tol) || !other.findPlane(pln2,tol))
|
||||
return false;
|
||||
if(tol<0.0)
|
||||
tol = Precision::Confusion();
|
||||
return pln1.Position().IsCoplanar(pln2.Position(),tol,tol);
|
||||
}
|
||||
|
||||
bool TopoShape::_makETransform(const TopoShape &shape,
|
||||
const Base::Matrix4D &rclTrf, const char *op, bool checkScale, bool copy)
|
||||
{
|
||||
if(checkScale) {
|
||||
if(rclTrf.hasScale()<0) {
|
||||
makEGTransform(shape,rclTrf,op,copy);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
makETransform(shape,convert(rclTrf),op,copy);
|
||||
return false;
|
||||
}
|
||||
|
||||
TopoShape &TopoShape::makETransform(const TopoShape &shape, const gp_Trsf &trsf, const char *op, bool copy) {
|
||||
// resetElementMap();
|
||||
|
||||
if(!copy) {
|
||||
// OCCT checks the ScaleFactor against gp::Resolution() which is DBL_MIN!!!
|
||||
copy = trsf.ScaleFactor()*trsf.HVectorialPart().Determinant() < 0. ||
|
||||
Abs(Abs(trsf.ScaleFactor()) - 1) > Precision::Confusion();
|
||||
}
|
||||
TopoShape tmp(shape);
|
||||
if(copy) {
|
||||
BRepBuilderAPI_Transform mkTrf(shape.getShape(), trsf, Standard_True);
|
||||
// TODO: calling Moved() is to make sure the shape has some Location,
|
||||
// which is necessary for STEP export to work. However, if we reach
|
||||
// here, it porabably means BRepBuilderAPI_Transform has modified
|
||||
// underlying shapes (because of scaling), it will break compound child
|
||||
// parent relationship anyway. In short, STEP import/export will most
|
||||
// likely break badly if there is any scaling involved
|
||||
tmp._Shape = mkTrf.Shape().Moved(gp_Trsf());
|
||||
}else
|
||||
tmp._Shape.Move(trsf);
|
||||
if(op || (shape.Tag && shape.Tag!=Tag)) {
|
||||
_Shape = tmp._Shape;
|
||||
// tmp.initCache(1);
|
||||
// mapSubElement(tmp,op);
|
||||
} else
|
||||
*this = tmp;
|
||||
return *this;
|
||||
}
|
||||
|
||||
TopoShape &TopoShape::makEGTransform(const TopoShape &shape,
|
||||
const Base::Matrix4D &rclTrf, const char *op, bool copy)
|
||||
{
|
||||
(void)op;
|
||||
gp_GTrsf mat;
|
||||
mat.SetValue(1,1,rclTrf[0][0]);
|
||||
mat.SetValue(2,1,rclTrf[1][0]);
|
||||
mat.SetValue(3,1,rclTrf[2][0]);
|
||||
mat.SetValue(1,2,rclTrf[0][1]);
|
||||
mat.SetValue(2,2,rclTrf[1][1]);
|
||||
mat.SetValue(3,2,rclTrf[2][1]);
|
||||
mat.SetValue(1,3,rclTrf[0][2]);
|
||||
mat.SetValue(2,3,rclTrf[1][2]);
|
||||
mat.SetValue(3,3,rclTrf[2][2]);
|
||||
mat.SetValue(1,4,rclTrf[0][3]);
|
||||
mat.SetValue(2,4,rclTrf[1][3]);
|
||||
mat.SetValue(3,4,rclTrf[2][3]);
|
||||
|
||||
// geometric transformation
|
||||
BRepBuilderAPI_GTransform mkTrf(shape.getShape(), mat, copy);
|
||||
_Shape = mkTrf.Shape();
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
@@ -123,6 +123,8 @@ public:
|
||||
virtual bool getCenterOfGravity(Base::Vector3d& center) const;
|
||||
static void convertTogpTrsf(const Base::Matrix4D& mtrx, gp_Trsf& trsf);
|
||||
static void convertToMatrix(const gp_Trsf& trsf, Base::Matrix4D& mtrx);
|
||||
static Base::Matrix4D convert(const gp_Trsf& trsf);
|
||||
static gp_Trsf convert(const Base::Matrix4D& mtrx);
|
||||
//@}
|
||||
|
||||
/** @name Subelement management */
|
||||
@@ -148,10 +150,14 @@ public:
|
||||
std::vector<Facet> &faces) const;
|
||||
//@}
|
||||
/// get the Topo"sub"Shape with the given name
|
||||
TopoDS_Shape getSubShape(const char* Type) const;
|
||||
TopoDS_Shape getSubShape(const char* Type, bool silent=false) const;
|
||||
TopoDS_Shape getSubShape(TopAbs_ShapeEnum type, int idx, bool silent=false) const;
|
||||
unsigned long countSubShapes(const char* Type) const;
|
||||
unsigned long countSubShapes(TopAbs_ShapeEnum type) const;
|
||||
bool hasSubShape(const char *Type) const;
|
||||
bool hasSubShape(TopAbs_ShapeEnum type) const;
|
||||
/// get the Topo"sub"Shape with the given name
|
||||
PyObject * getPySubShape(const char* Type) const;
|
||||
PyObject * getPySubShape(const char* Type, bool silent=false) const;
|
||||
|
||||
/** @name Save/restore */
|
||||
//@{
|
||||
@@ -189,6 +195,8 @@ public:
|
||||
bool isValid() const;
|
||||
bool analyze(bool runBopCheck, std::ostream&) const;
|
||||
bool isClosed() const;
|
||||
bool isCoplanar(const TopoShape &other, double tol=-1) const;
|
||||
bool findPlane(gp_Pln &pln, double tol=-1) const;
|
||||
//@}
|
||||
|
||||
/** @name Boolean operation*/
|
||||
@@ -263,7 +271,7 @@ public:
|
||||
//@{
|
||||
void transformGeometry(const Base::Matrix4D &rclMat);
|
||||
TopoDS_Shape transformGShape(const Base::Matrix4D&) const;
|
||||
void transformShape(const Base::Matrix4D&, bool copy);
|
||||
bool transformShape(const Base::Matrix4D&, bool copy, bool checkScale=false);
|
||||
TopoDS_Shape mirror(const gp_Ax2&) const;
|
||||
TopoDS_Shape toNurbs() const;
|
||||
TopoDS_Shape replaceShape(const std::vector< std::pair<TopoDS_Shape,TopoDS_Shape> >& s) const;
|
||||
@@ -289,6 +297,68 @@ public:
|
||||
void getDomains(std::vector<Domain>&) const;
|
||||
//@}
|
||||
|
||||
/** @name Element name mapping aware shape maker
|
||||
*
|
||||
* To be complete in next batch of patches
|
||||
*/
|
||||
//@{
|
||||
TopoShape &makECompound(const std::vector<TopoShape> &shapes, const char *op=0, bool force=true);
|
||||
|
||||
TopoShape &makEWires(const TopoShape &shape, const char *op=0, bool fix=false, double tol=0.0);
|
||||
TopoShape makEWires(const char *op=0, bool fix=false, double tol=0.0) const {
|
||||
return TopoShape().makEWires(*this,op,fix,tol);
|
||||
}
|
||||
TopoShape &makEFace(const std::vector<TopoShape> &shapes, const char *op=0, const char *maker=0);
|
||||
TopoShape &makEFace(const TopoShape &shape, const char *op=0, const char *maker=0);
|
||||
TopoShape makEFace(const char *op=0, const char *maker=0) const {
|
||||
return TopoShape().makEFace(*this,op,maker);
|
||||
}
|
||||
bool _makETransform(const TopoShape &shape, const Base::Matrix4D &mat,
|
||||
const char *op=0, bool checkScale=false, bool copy=false);
|
||||
|
||||
TopoShape &makETransform(const TopoShape &shape, const Base::Matrix4D &mat,
|
||||
const char *op=0, bool checkScale=false, bool copy=false) {
|
||||
_makETransform(shape,mat,op,checkScale,copy);
|
||||
return *this;
|
||||
}
|
||||
TopoShape makETransform(const Base::Matrix4D &mat, const char *op=0,
|
||||
bool checkScale=false, bool copy=false) const {
|
||||
return TopoShape().makETransform(*this,mat,op,checkScale,copy);
|
||||
}
|
||||
|
||||
TopoShape &makETransform(const TopoShape &shape, const gp_Trsf &trsf,
|
||||
const char *op=0, bool copy=false);
|
||||
TopoShape makETransform(const gp_Trsf &trsf, const char *op=0, bool copy=false) const {
|
||||
return TopoShape().makETransform(*this,trsf,op,copy);
|
||||
}
|
||||
|
||||
void move(const TopLoc_Location &loc) {
|
||||
_Shape.Move(loc);
|
||||
}
|
||||
TopoShape moved(const TopLoc_Location &loc) const {
|
||||
TopoShape ret(*this);
|
||||
ret._Shape.Move(loc);
|
||||
return ret;
|
||||
}
|
||||
|
||||
TopoShape &makEGTransform(const TopoShape &shape, const Base::Matrix4D &mat,
|
||||
const char *op=0, bool copy=false);
|
||||
TopoShape makEGTransform(const Base::Matrix4D &mat, const char *op=0, bool copy=false) const {
|
||||
return TopoShape().makEGTransform(*this,mat,op,copy);
|
||||
}
|
||||
|
||||
TopoShape &makERefine(const TopoShape &shape, const char *op=0, bool no_fail=true);
|
||||
TopoShape makERefine(const char *op=0, bool no_fail=true) const {
|
||||
return TopoShape().makERefine(*this,op,no_fail);
|
||||
}
|
||||
//@}
|
||||
|
||||
static TopAbs_ShapeEnum shapeType(const char *type,bool silent=false);
|
||||
static TopAbs_ShapeEnum shapeType(char type,bool silent=false);
|
||||
TopAbs_ShapeEnum shapeType(bool silent=false) const;
|
||||
static const std::string &shapeName(TopAbs_ShapeEnum type,bool silent=false);
|
||||
const std::string &shapeName(bool silent=false) const;
|
||||
static std::pair<TopAbs_ShapeEnum,int> shapeTypeAndIndex(const char *name);
|
||||
private:
|
||||
TopoDS_Shape _Shape;
|
||||
};
|
||||
|
||||
@@ -335,7 +335,19 @@ transformGeometry(Matrix) -> Shape
|
||||
<Documentation>
|
||||
<UserDocu>Apply transformation on a shape without changing
|
||||
the underlying geometry.
|
||||
transformShape(Matrix,[boolean copy=False]) -> None</UserDocu>
|
||||
transformShape(Matrix,[boolean copy=False, checkScale=False]) -> None
|
||||
|
||||
If checkScale is True, it will use transformGeometry if non-uniform
|
||||
scaling is detected.</UserDocu>
|
||||
</Documentation>
|
||||
</Methode>
|
||||
<Methode Name="transformed" Const="true" Keyword="true">
|
||||
<Documentation>
|
||||
<UserDocu>
|
||||
transformed(Matrix,copy=False,checkScale=False,op=None) -> shape
|
||||
|
||||
Create a new transformed shape
|
||||
</UserDocu>
|
||||
</Documentation>
|
||||
</Methode>
|
||||
<Methode Name="translate">
|
||||
@@ -343,11 +355,29 @@ transformShape(Matrix,[boolean copy=False]) -> None</UserDocu>
|
||||
<UserDocu>Apply the translation to the current location of this shape.</UserDocu>
|
||||
</Documentation>
|
||||
</Methode>
|
||||
<Methode Name="translated">
|
||||
<Documentation>
|
||||
<UserDocu>
|
||||
translated(vector) -> shape
|
||||
|
||||
Create a new shape with translation
|
||||
</UserDocu>
|
||||
</Documentation>
|
||||
</Methode>
|
||||
<Methode Name="rotate">
|
||||
<Documentation>
|
||||
<UserDocu>
|
||||
Apply the rotation (degree) to the current location of this shape
|
||||
Shp.rotate(Vector(0,0,0),Vector(0,0,1),180) - rotate the shape around the Z Axis 180 degrees.
|
||||
Apply the rotation (base,dir,degree) to the current location of this shape
|
||||
Shp.rotate(Vector(0,0,0),Vector(0,0,1),180) - rotate the shape around the Z Axis 180 degrees.
|
||||
</UserDocu>
|
||||
</Documentation>
|
||||
</Methode>
|
||||
<Methode Name="rotated">
|
||||
<Documentation>
|
||||
<UserDocu>
|
||||
rotated(base,dir,degree) -> shape
|
||||
|
||||
Create a new shape with rotation.
|
||||
</UserDocu>
|
||||
</Documentation>
|
||||
</Methode>
|
||||
@@ -356,6 +386,15 @@ transformShape(Matrix,[boolean copy=False]) -> None</UserDocu>
|
||||
<UserDocu>Apply scaling with point and factor to this shape.</UserDocu>
|
||||
</Documentation>
|
||||
</Methode>
|
||||
<Methode Name="scaled">
|
||||
<Documentation>
|
||||
<UserDocu>
|
||||
scaled(factor,base=Vector(0,0,0)) -> shape
|
||||
|
||||
Create a new shape with scale.
|
||||
</UserDocu>
|
||||
</Documentation>
|
||||
</Methode>
|
||||
<Methode Name="makeFillet" Const="true">
|
||||
<Documentation>
|
||||
<UserDocu>Make fillet.</UserDocu>
|
||||
@@ -428,6 +467,23 @@ Returns: result of offsetting (wire or face or compound of those). Compounding
|
||||
structure follows that of source shape.</UserDocu>
|
||||
</Documentation>
|
||||
</Methode>
|
||||
<Methode Name="makeWires">
|
||||
<Documentation>
|
||||
<UserDocu>
|
||||
makeWires(op=None): make wire(s) using the edges of this shape
|
||||
|
||||
The function will sort any edges inside the current shape, and connect them
|
||||
into wire. If more than one wire is found, then it will make a compound out of
|
||||
all found wires.
|
||||
|
||||
This function is element mapping aware. If the input shape has non-zero Tag,
|
||||
it will map any edge and vertex element name inside the input shape into the
|
||||
itself.
|
||||
|
||||
op: an optional string to be appended when auto generates element mapping.
|
||||
</UserDocu>
|
||||
</Documentation>
|
||||
</Methode>
|
||||
<Methode Name="reverse">
|
||||
<Documentation>
|
||||
<UserDocu>Reverses the orientation of this shape.</UserDocu>
|
||||
@@ -486,6 +542,16 @@ If the shape is an edge it returns True if its vertices are the same.
|
||||
<UserDocu>Checks if the shape is valid, i.e. neither null, nor empty nor corrupted.</UserDocu>
|
||||
</Documentation>
|
||||
</Methode>
|
||||
<Methode Name="isCoplanar" Const="true">
|
||||
<Documentation>
|
||||
<UserDocu>isCoplanar(shape,tol=None) -- Checks if this shape is coplanar with the given shape.</UserDocu>
|
||||
</Documentation>
|
||||
</Methode>
|
||||
<Methode Name="findPlane" Const="true">
|
||||
<Documentation>
|
||||
<UserDocu>findPlane(tol=None) -- return a plane if the shape is planar</UserDocu>
|
||||
</Documentation>
|
||||
</Methode>
|
||||
<Methode Name="fix">
|
||||
<Documentation>
|
||||
<UserDocu>Tries to fix a broken shape. True is returned if the operation succeeded, False otherwise.
|
||||
@@ -635,6 +701,11 @@ infos contains additional info on the solutions. It is a list of tuples:
|
||||
<UserDocu>Returns a SubElement</UserDocu>
|
||||
</Documentation>
|
||||
</Methode>
|
||||
<Methode Name="countElement" Const="true">
|
||||
<Documentation>
|
||||
<UserDocu>Returns the count of a type of element</UserDocu>
|
||||
</Documentation>
|
||||
</Methode>
|
||||
<Methode Name="getTolerance" Const="true">
|
||||
<Documentation>
|
||||
<UserDocu>
|
||||
@@ -796,6 +867,12 @@ infos contains additional info on the solutions. It is a list of tuples:
|
||||
</Documentation>
|
||||
<Parameter Name="Compounds" Type="List"/>
|
||||
</Attribute>
|
||||
<Attribute Name="SubShapes" ReadOnly="true">
|
||||
<Documentation>
|
||||
<UserDocu>List of sub-shapes in this shape.</UserDocu>
|
||||
</Documentation>
|
||||
<Parameter Name="SubShapes" Type="List"/>
|
||||
</Attribute>
|
||||
<Attribute Name="Length" ReadOnly="true">
|
||||
<Documentation>
|
||||
<UserDocu>Total length of the edges of the shape.</UserDocu>
|
||||
|
||||
@@ -47,6 +47,7 @@
|
||||
# include <gp_Dir.hxx>
|
||||
# include <gp_Pnt.hxx>
|
||||
# include <gp_Trsf.hxx>
|
||||
# include <gp_Pln.hxx>
|
||||
# include <Poly_Polygon3D.hxx>
|
||||
# include <Poly_Triangulation.hxx>
|
||||
# include <TopExp_Explorer.hxx>
|
||||
@@ -58,6 +59,7 @@
|
||||
# include <TopLoc_Location.hxx>
|
||||
# include <TopExp.hxx>
|
||||
# include <Precision.hxx>
|
||||
# include <Geom_Plane.hxx>
|
||||
# include <HLRAppli_ReflectLines.hxx>
|
||||
# include <BRepGProp.hxx>
|
||||
# include <GProp_GProps.hxx>
|
||||
@@ -91,6 +93,7 @@
|
||||
#include <Mod/Part/App/TopoShapeShellPy.h>
|
||||
#include <Mod/Part/App/TopoShapeCompSolidPy.h>
|
||||
#include <Mod/Part/App/TopoShapeCompoundPy.h>
|
||||
#include <Mod/Part/App/PlanePy.h>
|
||||
|
||||
using namespace Part;
|
||||
|
||||
@@ -102,10 +105,6 @@ using namespace Part;
|
||||
#define M_PI_2 1.57079632679489661923 /* pi/2 */
|
||||
#endif
|
||||
|
||||
namespace Part {
|
||||
extern Py::Object shape2pyshape(const TopoDS_Shape &shape);
|
||||
}
|
||||
|
||||
// returns a string which represents the object e.g. when printed in python
|
||||
std::string TopoShapePy::representation(void) const
|
||||
{
|
||||
@@ -127,29 +126,31 @@ int TopoShapePy::PyInit(PyObject* args, PyObject*)
|
||||
if (!PyArg_ParseTuple(args, "|O", &pcObj))
|
||||
return -1;
|
||||
|
||||
auto shapes = getPyShapes(pcObj);
|
||||
|
||||
if (pcObj) {
|
||||
TopoShape shape;
|
||||
try {
|
||||
Py::Sequence list(pcObj);
|
||||
bool first = true;
|
||||
for (Py::Sequence::iterator it = list.begin(); it != list.end(); ++it) {
|
||||
if (PyObject_TypeCheck((*it).ptr(), &(Part::GeometryPy::Type))) {
|
||||
TopoDS_Shape sh = static_cast<GeometryPy*>((*it).ptr())->
|
||||
getGeometryPtr()->toShape();
|
||||
if (first) {
|
||||
first = false;
|
||||
shape.setShape(sh);
|
||||
}
|
||||
else {
|
||||
shape.setShape(shape.fuse(sh));
|
||||
PY_TRY {
|
||||
if(PyObject_TypeCheck(pcObj,&TopoShapePy::Type)) {
|
||||
shape = *static_cast<TopoShapePy*>(pcObj)->getTopoShapePtr();
|
||||
}else{
|
||||
Py::Sequence list(pcObj);
|
||||
bool first = true;
|
||||
for (Py::Sequence::iterator it = list.begin(); it != list.end(); ++it) {
|
||||
if (PyObject_TypeCheck((*it).ptr(), &(Part::GeometryPy::Type))) {
|
||||
TopoDS_Shape sh = static_cast<GeometryPy*>((*it).ptr())->
|
||||
getGeometryPtr()->toShape();
|
||||
if (first) {
|
||||
first = false;
|
||||
shape.setShape(sh);
|
||||
}
|
||||
else {
|
||||
shape.setShape(shape.fuse(sh));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Standard_Failure& e) {
|
||||
PyErr_SetString(PartExceptionOCCError, e.GetMessageString());
|
||||
return -1;
|
||||
}
|
||||
}_PY_CATCH_OCC(return(-1))
|
||||
|
||||
getTopoShapePtr()->setShape(shape.getShape());
|
||||
}
|
||||
@@ -1399,19 +1400,35 @@ PyObject* TopoShapePy::transformShape(PyObject *args)
|
||||
{
|
||||
PyObject *obj;
|
||||
PyObject *copy = Py_False;
|
||||
if (!PyArg_ParseTuple(args, "O!|O!", &(Base::MatrixPy::Type),&obj,&(PyBool_Type), ©))
|
||||
PyObject *checkScale = Py_False;
|
||||
if (!PyArg_ParseTuple(args, "O!|O!O", &(Base::MatrixPy::Type),&obj,&(PyBool_Type), ©,&checkScale))
|
||||
return NULL;
|
||||
|
||||
Base::Matrix4D mat = static_cast<Base::MatrixPy*>(obj)->value();
|
||||
try {
|
||||
this->getTopoShapePtr()->transformShape(mat, PyObject_IsTrue(copy) ? true : false);
|
||||
Py_Return;
|
||||
}
|
||||
catch (Standard_Failure& e) {
|
||||
PY_TRY {
|
||||
this->getTopoShapePtr()->transformShape(mat, PyObject_IsTrue(copy) ? true : false,
|
||||
PyObject_IsTrue(checkScale));
|
||||
return IncRef();
|
||||
} PY_CATCH_OCC
|
||||
}
|
||||
|
||||
PyErr_SetString(PartExceptionOCCError, e.GetMessageString());
|
||||
return NULL;
|
||||
}
|
||||
PyObject* TopoShapePy::transformed(PyObject *args, PyObject *keywds)
|
||||
{
|
||||
static char *kwlist[] = {"matrix", "copy", "checkScale", "op", NULL};
|
||||
PyObject* pymat;
|
||||
PyObject* copy = Py_False;
|
||||
PyObject* checkScale = Py_False;
|
||||
const char *op = 0;
|
||||
if (!PyArg_ParseTupleAndKeywords(args, keywds, "O!|OOs", kwlist,
|
||||
&Base::MatrixPy::Type, &pymat,©,&checkScale,&op))
|
||||
return 0;
|
||||
Base::Matrix4D mat = static_cast<Base::MatrixPy*>(pymat)->value();
|
||||
(void)op;
|
||||
PY_TRY {
|
||||
TopoShape s(*getTopoShapePtr());
|
||||
s.transformShape(mat,PyObject_IsTrue(copy),PyObject_IsTrue(checkScale));
|
||||
return Py::new_reference_to(shape2pyshape(s));
|
||||
}PY_CATCH_OCC
|
||||
}
|
||||
|
||||
PyObject* TopoShapePy::translate(PyObject *args)
|
||||
@@ -1438,7 +1455,7 @@ PyObject* TopoShapePy::translate(PyObject *args)
|
||||
TopoDS_Shape shape = getTopoShapePtr()->getShape();
|
||||
shape.Move(loc);
|
||||
getTopoShapePtr()->setShape(shape);
|
||||
Py_Return;
|
||||
return IncRef();
|
||||
}
|
||||
|
||||
PyObject* TopoShapePy::rotate(PyObject *args)
|
||||
@@ -1448,7 +1465,7 @@ PyObject* TopoShapePy::rotate(PyObject *args)
|
||||
if (!PyArg_ParseTuple(args, "OOd", &obj1, &obj2, &angle))
|
||||
return NULL;
|
||||
|
||||
try {
|
||||
PY_TRY {
|
||||
// Vector also supports sequence
|
||||
Py::Sequence p1(obj1), p2(obj2);
|
||||
// Convert into OCC representation
|
||||
@@ -1466,11 +1483,8 @@ PyObject* TopoShapePy::rotate(PyObject *args)
|
||||
TopoDS_Shape shape = getTopoShapePtr()->getShape();
|
||||
shape.Move(loc);
|
||||
getTopoShapePtr()->setShape(shape);
|
||||
Py_Return;
|
||||
}
|
||||
catch (const Py::Exception&) {
|
||||
return NULL;
|
||||
}
|
||||
return IncRef();
|
||||
} PY_CATCH_OCC
|
||||
}
|
||||
|
||||
PyObject* TopoShapePy::scale(PyObject *args)
|
||||
@@ -1492,20 +1506,30 @@ PyObject* TopoShapePy::scale(PyObject *args)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
try {
|
||||
PY_TRY {
|
||||
gp_Trsf scl;
|
||||
scl.SetScale(pos, factor);
|
||||
BRepBuilderAPI_Transform BRepScale(scl);
|
||||
bool bCopy = true;
|
||||
BRepScale.Perform(getTopoShapePtr()->getShape(),bCopy);
|
||||
getTopoShapePtr()->setShape(BRepScale.Shape());
|
||||
Py_Return;
|
||||
}
|
||||
catch (Standard_Failure& e) {
|
||||
return IncRef();
|
||||
} PY_CATCH_OCC
|
||||
}
|
||||
|
||||
PyErr_SetString(PartExceptionOCCError, e.GetMessageString());
|
||||
return NULL;
|
||||
}
|
||||
PyObject* TopoShapePy::translated(PyObject *args) {
|
||||
Py::Object pyobj(shape2pyshape(*getTopoShapePtr()));
|
||||
return static_cast<TopoShapePy*>(pyobj.ptr())->translate(args);
|
||||
}
|
||||
|
||||
PyObject* TopoShapePy::rotated(PyObject *args) {
|
||||
Py::Object pyobj(shape2pyshape(*getTopoShapePtr()));
|
||||
return static_cast<TopoShapePy*>(pyobj.ptr())->rotate(args);
|
||||
}
|
||||
|
||||
PyObject* TopoShapePy::scaled(PyObject *args) {
|
||||
Py::Object pyobj(shape2pyshape(*getTopoShapePtr()));
|
||||
return static_cast<TopoShapePy*>(pyobj.ptr())->scale(args);
|
||||
}
|
||||
|
||||
PyObject* TopoShapePy::makeFillet(PyObject *args)
|
||||
@@ -1827,13 +1851,34 @@ PyObject* TopoShapePy::isValid(PyObject *args)
|
||||
{
|
||||
if (!PyArg_ParseTuple(args, ""))
|
||||
return NULL;
|
||||
try {
|
||||
PY_TRY {
|
||||
return Py_BuildValue("O", (getTopoShapePtr()->isValid() ? Py_True : Py_False));
|
||||
}
|
||||
catch (...) {
|
||||
PyErr_SetString(PyExc_RuntimeError, "check failed, shape may be empty");
|
||||
} PY_CATCH_OCC
|
||||
}
|
||||
|
||||
PyObject* TopoShapePy::isCoplanar(PyObject *args)
|
||||
{
|
||||
PyObject *pyObj;
|
||||
double tol = -1;
|
||||
if (!PyArg_ParseTuple(args, "O!|d", &TopoShapePy::Type, &pyObj, &tol))
|
||||
return NULL;
|
||||
}
|
||||
PY_TRY {
|
||||
return Py::new_reference_to(Py::Boolean(getTopoShapePtr()->isCoplanar(
|
||||
*static_cast<TopoShapePy*>(pyObj)->getTopoShapePtr(),tol)));
|
||||
}PY_CATCH_OCC
|
||||
}
|
||||
|
||||
PyObject* TopoShapePy::findPlane(PyObject *args)
|
||||
{
|
||||
double tol = -1;
|
||||
if (!PyArg_ParseTuple(args, "|d", &tol))
|
||||
return NULL;
|
||||
PY_TRY {
|
||||
gp_Pln pln;
|
||||
if(getTopoShapePtr()->findPlane(pln,tol))
|
||||
return new PlanePy(new GeomPlane(new Geom_Plane(pln)));
|
||||
Py_Return;
|
||||
}PY_CATCH_OCC
|
||||
}
|
||||
|
||||
PyObject* TopoShapePy::fix(PyObject *args)
|
||||
@@ -2052,10 +2097,16 @@ PyObject* TopoShapePy::makeShapeFromMesh(PyObject *args)
|
||||
|
||||
getTopoShapePtr()->setFaces(Points, Facets,tolerance);
|
||||
Py_Return;
|
||||
}
|
||||
catch (const Py::Exception&) {
|
||||
return 0;
|
||||
}
|
||||
} PY_CATCH_OCC
|
||||
}
|
||||
|
||||
PyObject* TopoShapePy::makeWires(PyObject *args) {
|
||||
const char *op = 0;
|
||||
if (!PyArg_ParseTuple(args, "s", &op))
|
||||
return NULL;
|
||||
PY_TRY {
|
||||
return Py::new_reference_to(shape2pyshape(getTopoShapePtr()->makEWires(op)));
|
||||
}PY_CATCH_OCC
|
||||
}
|
||||
|
||||
PyObject* TopoShapePy::toNurbs(PyObject *args)
|
||||
@@ -2157,6 +2208,16 @@ PyObject* TopoShapePy::getElement(PyObject *args)
|
||||
return 0;
|
||||
}
|
||||
|
||||
PyObject* TopoShapePy::countElement(PyObject *args)
|
||||
{
|
||||
char* input;
|
||||
if (!PyArg_ParseTuple(args, "s", &input))
|
||||
return NULL;
|
||||
PY_TRY {
|
||||
return Py::new_reference_to(Py::Int((long)getTopoShapePtr()->countSubShapes(input)));
|
||||
} PY_CATCH_OCC
|
||||
}
|
||||
|
||||
PyObject* TopoShapePy::getTolerance(PyObject *args)
|
||||
{
|
||||
int mode;
|
||||
@@ -2900,6 +2961,14 @@ void TopoShapePy::setOrientation(Py::String arg)
|
||||
getTopoShapePtr()->setShape(sh);
|
||||
}
|
||||
|
||||
Py::List TopoShapePy::getSubShapes(void) const
|
||||
{
|
||||
Py::List ret;
|
||||
for(TopoDS_Iterator it(getTopoShapePtr()->getShape());it.More();it.Next())
|
||||
ret.append(shape2pyshape(it.Value()));
|
||||
return ret;
|
||||
}
|
||||
|
||||
Py::List TopoShapePy::getFaces(void) const
|
||||
{
|
||||
Py::List ret;
|
||||
@@ -3117,38 +3186,11 @@ Py::Float TopoShapePy::getVolume(void) const
|
||||
PyObject *TopoShapePy::getCustomAttributes(const char* attr) const
|
||||
{
|
||||
if (!attr) return 0;
|
||||
std::string name(attr);
|
||||
try {
|
||||
if (name.size() > 4 && name.substr(0,4) == "Face" && name[4]>=48 && name[4]<=57) {
|
||||
std::unique_ptr<Part::ShapeSegment> s(static_cast<Part::ShapeSegment*>
|
||||
(getTopoShapePtr()->getSubElementByName(attr)));
|
||||
TopoDS_Shape Shape = s->Shape;
|
||||
TopoShapeFacePy* face = new TopoShapeFacePy(new TopoShape(Shape));
|
||||
face->setNotTracking();
|
||||
return face;
|
||||
}
|
||||
else if (name.size() > 4 && name.substr(0,4) == "Edge" && name[4]>=48 && name[4]<=57) {
|
||||
std::unique_ptr<Part::ShapeSegment> s(static_cast<Part::ShapeSegment*>
|
||||
(getTopoShapePtr()->getSubElementByName(attr)));
|
||||
TopoDS_Shape Shape = s->Shape;
|
||||
TopoShapeEdgePy* edge = new TopoShapeEdgePy(new TopoShape(Shape));
|
||||
edge->setNotTracking();
|
||||
return edge;
|
||||
}
|
||||
else if (name.size() > 6 && name.substr(0,6) == "Vertex" && name[6]>=48 && name[6]<=57) {
|
||||
std::unique_ptr<Part::ShapeSegment> s(static_cast<Part::ShapeSegment*>
|
||||
(getTopoShapePtr()->getSubElementByName(attr)));
|
||||
TopoDS_Shape Shape = s->Shape;
|
||||
TopoShapeVertexPy* vertex = new TopoShapeVertexPy(new TopoShape(Shape));
|
||||
vertex->setNotTracking();
|
||||
return vertex;
|
||||
}
|
||||
}
|
||||
catch (Standard_Failure& e) {
|
||||
|
||||
PyErr_SetString(PartExceptionOCCError, e.GetMessageString());
|
||||
return 0;
|
||||
}
|
||||
PY_TRY {
|
||||
TopoDS_Shape res = getTopoShapePtr()->getSubShape(attr,true);
|
||||
if(!res.IsNull())
|
||||
return Py::new_reference_to(shape2pyshape(res));
|
||||
}PY_CATCH_OCC
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -280,7 +280,8 @@ CmdPartCut::CmdPartCut()
|
||||
void CmdPartCut::activated(int iMsg)
|
||||
{
|
||||
Q_UNUSED(iMsg);
|
||||
std::vector<Gui::SelectionObject> Sel = getSelection().getSelectionEx(0, Part::Feature::getClassTypeId());
|
||||
std::vector<Gui::SelectionObject> Sel =
|
||||
getSelection().getSelectionEx(0, App::DocumentObject::getClassTypeId(),3);
|
||||
if (Sel.size() != 2) {
|
||||
QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Wrong selection"),
|
||||
QObject::tr("Select two shapes please."));
|
||||
@@ -290,16 +291,14 @@ void CmdPartCut::activated(int iMsg)
|
||||
bool askUser = false;
|
||||
for (std::vector<Gui::SelectionObject>::iterator it = Sel.begin(); it != Sel.end(); ++it) {
|
||||
App::DocumentObject* obj = it->getObject();
|
||||
if (obj->getTypeId().isDerivedFrom(Part::Feature::getClassTypeId())) {
|
||||
const TopoDS_Shape& shape = static_cast<Part::Feature*>(obj)->Shape.getValue();
|
||||
if (!PartGui::checkForSolids(shape) && !askUser) {
|
||||
int ret = QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Non-solids selected"),
|
||||
QObject::tr("The use of non-solids for boolean operations may lead to unexpected results.\n"
|
||||
"Do you want to continue?"), QMessageBox::Yes, QMessageBox::No);
|
||||
if (ret == QMessageBox::No)
|
||||
return;
|
||||
askUser = true;
|
||||
}
|
||||
const TopoDS_Shape& shape = Part::Feature::getShape(obj);
|
||||
if (!PartGui::checkForSolids(shape) && !askUser) {
|
||||
int ret = QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Non-solids selected"),
|
||||
QObject::tr("The use of non-solids for boolean operations may lead to unexpected results.\n"
|
||||
"Do you want to continue?"), QMessageBox::Yes, QMessageBox::No);
|
||||
if (ret == QMessageBox::No)
|
||||
return;
|
||||
askUser = true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -335,7 +334,8 @@ void CmdPartCut::activated(int iMsg)
|
||||
|
||||
bool CmdPartCut::isActive(void)
|
||||
{
|
||||
return getSelection().countObjectsOfType(Part::Feature::getClassTypeId())==2;
|
||||
return getSelection().countObjectsOfType(
|
||||
App::DocumentObject::getClassTypeId(),0,3)==2;
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
@@ -358,21 +358,20 @@ CmdPartCommon::CmdPartCommon()
|
||||
void CmdPartCommon::activated(int iMsg)
|
||||
{
|
||||
Q_UNUSED(iMsg);
|
||||
std::vector<Gui::SelectionObject> Sel = getSelection().getSelectionEx(0, Part::Feature::getClassTypeId());
|
||||
std::vector<Gui::SelectionObject> Sel =
|
||||
getSelection().getSelectionEx(0, App::DocumentObject::getClassTypeId(), 3);
|
||||
|
||||
//test if selected object is a compound, and if it is, look how many children it has...
|
||||
std::size_t numShapes = 0;
|
||||
if (Sel.size() == 1){
|
||||
numShapes = 1; //to be updated later in code, if
|
||||
Gui::SelectionObject selobj = Sel[0];
|
||||
if (selobj.getObject()->isDerivedFrom(Part::Feature::getClassTypeId())){
|
||||
TopoDS_Shape sh = static_cast<Part::Feature*>(selobj.getObject())->Shape.getValue();
|
||||
if (sh.ShapeType() == TopAbs_COMPOUND) {
|
||||
numShapes = 0;
|
||||
TopoDS_Iterator it(sh);
|
||||
for (; it.More(); it.Next()) {
|
||||
++numShapes;
|
||||
}
|
||||
TopoDS_Shape sh = Part::Feature::getShape(selobj.getObject());
|
||||
if (sh.ShapeType() == TopAbs_COMPOUND) {
|
||||
numShapes = 0;
|
||||
TopoDS_Iterator it(sh);
|
||||
for (; it.More(); it.Next()) {
|
||||
++numShapes;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@@ -392,19 +391,17 @@ void CmdPartCommon::activated(int iMsg)
|
||||
str << "App.activeDocument()." << FeatName << ".Shapes = [";
|
||||
for (std::vector<Gui::SelectionObject>::iterator it = Sel.begin(); it != Sel.end(); ++it) {
|
||||
App::DocumentObject* obj = it->getObject();
|
||||
if (obj->getTypeId().isDerivedFrom(Part::Feature::getClassTypeId())) {
|
||||
const TopoDS_Shape& shape = static_cast<Part::Feature*>(obj)->Shape.getValue();
|
||||
if (!PartGui::checkForSolids(shape) && !askUser) {
|
||||
int ret = QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Non-solids selected"),
|
||||
QObject::tr("The use of non-solids for boolean operations may lead to unexpected results.\n"
|
||||
"Do you want to continue?"), QMessageBox::Yes, QMessageBox::No);
|
||||
if (ret == QMessageBox::No)
|
||||
return;
|
||||
askUser = true;
|
||||
}
|
||||
str << "App.activeDocument()." << it->getFeatName() << ",";
|
||||
partObjects.push_back(*it);
|
||||
const TopoDS_Shape& shape = Part::Feature::getShape(obj);
|
||||
if (!PartGui::checkForSolids(shape) && !askUser) {
|
||||
int ret = QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Non-solids selected"),
|
||||
QObject::tr("The use of non-solids for boolean operations may lead to unexpected results.\n"
|
||||
"Do you want to continue?"), QMessageBox::Yes, QMessageBox::No);
|
||||
if (ret == QMessageBox::No)
|
||||
return;
|
||||
askUser = true;
|
||||
}
|
||||
str << "App.activeDocument()." << it->getFeatName() << ",";
|
||||
partObjects.push_back(*it);
|
||||
}
|
||||
str << "]";
|
||||
|
||||
@@ -437,7 +434,8 @@ void CmdPartCommon::activated(int iMsg)
|
||||
|
||||
bool CmdPartCommon::isActive(void)
|
||||
{
|
||||
return getSelection().countObjectsOfType(Part::Feature::getClassTypeId())>=1;
|
||||
return getSelection().countObjectsOfType(
|
||||
App::DocumentObject::getClassTypeId(),0,3)>=1;
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
@@ -460,21 +458,20 @@ CmdPartFuse::CmdPartFuse()
|
||||
void CmdPartFuse::activated(int iMsg)
|
||||
{
|
||||
Q_UNUSED(iMsg);
|
||||
std::vector<Gui::SelectionObject> Sel = getSelection().getSelectionEx(0, Part::Feature::getClassTypeId());
|
||||
std::vector<Gui::SelectionObject> Sel =
|
||||
getSelection().getSelectionEx(0, App::DocumentObject::getClassTypeId(),3);
|
||||
|
||||
//test if selected object is a compound, and if it is, look how many children it has...
|
||||
std::size_t numShapes = 0;
|
||||
if (Sel.size() == 1){
|
||||
numShapes = 1; //to be updated later in code
|
||||
Gui::SelectionObject selobj = Sel[0];
|
||||
if (selobj.getObject()->isDerivedFrom(Part::Feature::getClassTypeId())){
|
||||
TopoDS_Shape sh = static_cast<Part::Feature*>(selobj.getObject())->Shape.getValue();
|
||||
if (sh.ShapeType() == TopAbs_COMPOUND) {
|
||||
numShapes = 0;
|
||||
TopoDS_Iterator it(sh);
|
||||
for (; it.More(); it.Next()) {
|
||||
++numShapes;
|
||||
}
|
||||
TopoDS_Shape sh = Part::Feature::getShape(selobj.getObject());
|
||||
if (sh.ShapeType() == TopAbs_COMPOUND) {
|
||||
numShapes = 0;
|
||||
TopoDS_Iterator it(sh);
|
||||
for (; it.More(); it.Next()) {
|
||||
++numShapes;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@@ -494,19 +491,17 @@ void CmdPartFuse::activated(int iMsg)
|
||||
str << "App.activeDocument()." << FeatName << ".Shapes = [";
|
||||
for (std::vector<Gui::SelectionObject>::iterator it = Sel.begin(); it != Sel.end(); ++it) {
|
||||
App::DocumentObject* obj = it->getObject();
|
||||
if (obj->getTypeId().isDerivedFrom(Part::Feature::getClassTypeId())) {
|
||||
const TopoDS_Shape& shape = static_cast<Part::Feature*>(obj)->Shape.getValue();
|
||||
if (!PartGui::checkForSolids(shape) && !askUser) {
|
||||
int ret = QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Non-solids selected"),
|
||||
QObject::tr("The use of non-solids for boolean operations may lead to unexpected results.\n"
|
||||
"Do you want to continue?"), QMessageBox::Yes, QMessageBox::No);
|
||||
if (ret == QMessageBox::No)
|
||||
return;
|
||||
askUser = true;
|
||||
}
|
||||
str << "App.activeDocument()." << it->getFeatName() << ",";
|
||||
partObjects.push_back(*it);
|
||||
const TopoDS_Shape& shape = Part::Feature::getShape(obj);
|
||||
if (!PartGui::checkForSolids(shape) && !askUser) {
|
||||
int ret = QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Non-solids selected"),
|
||||
QObject::tr("The use of non-solids for boolean operations may lead to unexpected results.\n"
|
||||
"Do you want to continue?"), QMessageBox::Yes, QMessageBox::No);
|
||||
if (ret == QMessageBox::No)
|
||||
return;
|
||||
askUser = true;
|
||||
}
|
||||
str << "App.activeDocument()." << it->getFeatName() << ",";
|
||||
partObjects.push_back(*it);
|
||||
}
|
||||
str << "]";
|
||||
|
||||
@@ -539,7 +534,8 @@ void CmdPartFuse::activated(int iMsg)
|
||||
|
||||
bool CmdPartFuse::isActive(void)
|
||||
{
|
||||
return getSelection().countObjectsOfType(Part::Feature::getClassTypeId())>=1;
|
||||
return getSelection().countObjectsOfType(
|
||||
App::DocumentObject::getClassTypeId(),0,3)>=1;
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
@@ -898,7 +894,8 @@ CmdPartCompound::CmdPartCompound()
|
||||
void CmdPartCompound::activated(int iMsg)
|
||||
{
|
||||
Q_UNUSED(iMsg);
|
||||
unsigned int n = getSelection().countObjectsOfType(Part::Feature::getClassTypeId());
|
||||
unsigned int n = getSelection().countObjectsOfType(
|
||||
App::DocumentObject::getClassTypeId(),0,3);
|
||||
if (n < 1) {
|
||||
QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Wrong selection"),
|
||||
QObject::tr("Select one shape or more, please."));
|
||||
@@ -930,7 +927,8 @@ void CmdPartCompound::activated(int iMsg)
|
||||
|
||||
bool CmdPartCompound::isActive(void)
|
||||
{
|
||||
return getSelection().countObjectsOfType(Part::Feature::getClassTypeId())>=1;
|
||||
return getSelection().countObjectsOfType(
|
||||
App::DocumentObject::getClassTypeId(),0,3)>=1;
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
@@ -953,7 +951,8 @@ CmdPartSection::CmdPartSection()
|
||||
void CmdPartSection::activated(int iMsg)
|
||||
{
|
||||
Q_UNUSED(iMsg);
|
||||
std::vector<Gui::SelectionObject> Sel = getSelection().getSelectionEx(0, Part::Feature::getClassTypeId());
|
||||
std::vector<Gui::SelectionObject> Sel =
|
||||
getSelection().getSelectionEx(0, App::DocumentObject::getClassTypeId(),3);
|
||||
if (Sel.size() != 2) {
|
||||
QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Wrong selection"),
|
||||
QObject::tr("Select two shapes please."));
|
||||
@@ -977,7 +976,7 @@ void CmdPartSection::activated(int iMsg)
|
||||
|
||||
bool CmdPartSection::isActive(void)
|
||||
{
|
||||
return getSelection().countObjectsOfType(Part::Feature::getClassTypeId())==2;
|
||||
return getSelection().countObjectsOfType(App::DocumentObject::getClassTypeId(),0,3)==2;
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
@@ -1084,7 +1083,7 @@ void CmdPartExport::activated(int iMsg)
|
||||
|
||||
bool CmdPartExport::isActive(void)
|
||||
{
|
||||
return Gui::Selection().countObjectsOfType(Part::Feature::getClassTypeId()) > 0;
|
||||
return Gui::Selection().countObjectsOfType(App::DocumentObject::getClassTypeId(),0,3) > 0;
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
@@ -1155,10 +1154,10 @@ void CmdPartMakeSolid::activated(int iMsg)
|
||||
{
|
||||
Q_UNUSED(iMsg);
|
||||
std::vector<App::DocumentObject*> objs = Gui::Selection().getObjectsOfType
|
||||
(Part::Feature::getClassTypeId());
|
||||
(App::DocumentObject::getClassTypeId(),0,3);
|
||||
runCommand(Doc, "import Part");
|
||||
for (std::vector<App::DocumentObject*>::iterator it = objs.begin(); it != objs.end(); ++it) {
|
||||
const TopoDS_Shape& shape = static_cast<Part::Feature*>(*it)->Shape.getValue();
|
||||
const TopoDS_Shape& shape = Part::Feature::getShape(*it);
|
||||
if (!shape.IsNull()) {
|
||||
TopAbs_ShapeEnum type = shape.ShapeType();
|
||||
QString str;
|
||||
@@ -1210,7 +1209,7 @@ void CmdPartMakeSolid::activated(int iMsg)
|
||||
bool CmdPartMakeSolid::isActive(void)
|
||||
{
|
||||
return Gui::Selection().countObjectsOfType
|
||||
(Part::Feature::getClassTypeId()) > 0;
|
||||
(App::DocumentObject::getClassTypeId(),0,3) > 0;
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
@@ -1236,7 +1235,7 @@ void CmdPartReverseShape::activated(int iMsg)
|
||||
(Part::Feature::getClassTypeId());
|
||||
runCommand(Doc, "import Part");
|
||||
for (std::vector<App::DocumentObject*>::iterator it = objs.begin(); it != objs.end(); ++it) {
|
||||
const TopoDS_Shape& shape = static_cast<Part::Feature*>(*it)->Shape.getValue();
|
||||
const TopoDS_Shape& shape = Part::Feature::getShape(*it);
|
||||
if (!shape.IsNull()) {
|
||||
QString str = QString::fromLatin1(
|
||||
"__s__=App.ActiveDocument.%1.Shape.copy()\n"
|
||||
@@ -1345,7 +1344,7 @@ CmdPartMakeFace::CmdPartMakeFace()
|
||||
void CmdPartMakeFace::activated(int iMsg)
|
||||
{
|
||||
Q_UNUSED(iMsg);
|
||||
std::vector<Part::Feature*> sketches = Gui::Selection().getObjectsOfType<Part::Feature>();
|
||||
auto sketches = Gui::Selection().getObjectsOfType(App::DocumentObject::getClassTypeId(),0,3);
|
||||
openCommand("Make face");
|
||||
|
||||
try {
|
||||
@@ -1353,9 +1352,8 @@ void CmdPartMakeFace::activated(int iMsg)
|
||||
std::stringstream str;
|
||||
str << doc.getDocumentPython()
|
||||
<< ".addObject(\"Part::Face\", \"Face\").Sources = (";
|
||||
for (std::vector<Part::Feature*>::iterator it = sketches.begin(); it != sketches.end(); ++it) {
|
||||
App::DocumentObjectT obj(*it);
|
||||
str << obj.getObjectPython() << ", ";
|
||||
for (auto &obj : sketches) {
|
||||
str << App::DocumentObjectT(obj).getObjectPython() << ", ";
|
||||
}
|
||||
|
||||
str << ")";
|
||||
@@ -1372,7 +1370,7 @@ void CmdPartMakeFace::activated(int iMsg)
|
||||
|
||||
bool CmdPartMakeFace::isActive(void)
|
||||
{
|
||||
return (Gui::Selection().countObjectsOfType(Part::Feature::getClassTypeId()) > 0 &&
|
||||
return (Gui::Selection().countObjectsOfType(App::DocumentObject::getClassTypeId(),0,3) > 0 &&
|
||||
!Gui::Control().activeDialog());
|
||||
}
|
||||
|
||||
@@ -1643,7 +1641,6 @@ void CmdPartOffset::activated(int iMsg)
|
||||
doCommand(Doc,"App.ActiveDocument.%s.Source = App.ActiveDocument.%s" ,offset.c_str(), shape->getNameInDocument());
|
||||
doCommand(Doc,"App.ActiveDocument.%s.Value = 1.0",offset.c_str());
|
||||
updateActive();
|
||||
doCommand(Gui,"Gui.ActiveDocument.%s.DisplayMode = 'Wireframe'", shape->getNameInDocument());
|
||||
//if (isActiveObjectValid())
|
||||
// doCommand(Gui,"Gui.ActiveDocument.hide(\"%s\")",shape->getNameInDocument());
|
||||
doCommand(Gui,"Gui.ActiveDocument.setEdit('%s')",offset.c_str());
|
||||
@@ -1659,7 +1656,7 @@ void CmdPartOffset::activated(int iMsg)
|
||||
bool CmdPartOffset::isActive(void)
|
||||
{
|
||||
Base::Type partid = Base::Type::fromName("Part::Feature");
|
||||
bool objectsSelected = Gui::Selection().countObjectsOfType(partid) == 1;
|
||||
bool objectsSelected = Gui::Selection().countObjectsOfType(partid,0,3) == 1;
|
||||
return (objectsSelected && !Gui::Control().activeDialog());
|
||||
}
|
||||
|
||||
@@ -1685,7 +1682,7 @@ CmdPartOffset2D::CmdPartOffset2D()
|
||||
void CmdPartOffset2D::activated(int iMsg)
|
||||
{
|
||||
Q_UNUSED(iMsg);
|
||||
App::DocumentObject* shape = getSelection().getObjectsOfType(Part::Feature::getClassTypeId()).front();
|
||||
App::DocumentObject* shape = getSelection().getObjectsOfType(Part::Feature::getClassTypeId(),0,3).front();
|
||||
std::string offset = getUniqueObjectName("Offset2D");
|
||||
|
||||
openCommand("Make 2D Offset");
|
||||
@@ -1708,7 +1705,7 @@ void CmdPartOffset2D::activated(int iMsg)
|
||||
bool CmdPartOffset2D::isActive(void)
|
||||
{
|
||||
Base::Type partid = Base::Type::fromName("Part::Feature");
|
||||
bool objectsSelected = Gui::Selection().countObjectsOfType(partid) == 1;
|
||||
bool objectsSelected = Gui::Selection().countObjectsOfType(partid,0,3) == 1;
|
||||
return (objectsSelected && !Gui::Control().activeDialog());
|
||||
}
|
||||
|
||||
@@ -1801,7 +1798,7 @@ void CmdPartCompOffset::languageChange()
|
||||
bool CmdPartCompOffset::isActive(void)
|
||||
{
|
||||
Base::Type partid = Base::Type::fromName("Part::Feature");
|
||||
bool objectsSelected = Gui::Selection().countObjectsOfType(partid) == 1;
|
||||
bool objectsSelected = Gui::Selection().countObjectsOfType(partid,0,3) == 1;
|
||||
return (objectsSelected && !Gui::Control().activeDialog());
|
||||
}
|
||||
|
||||
@@ -2225,6 +2222,35 @@ bool CmdMeasureAngular::isActive(void)
|
||||
return hasActiveDocument();
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
// Part_Measure_Refresh
|
||||
//===========================================================================
|
||||
|
||||
DEF_STD_CMD_A(CmdMeasureRefresh);
|
||||
|
||||
CmdMeasureRefresh::CmdMeasureRefresh()
|
||||
: Command("Part_Measure_Refresh")
|
||||
{
|
||||
sAppModule = "Part";
|
||||
sGroup = QT_TR_NOOP("Part");
|
||||
sMenuText = QT_TR_NOOP("Refresh");
|
||||
sToolTipText = QT_TR_NOOP("Refresh");
|
||||
sWhatsThis = "Part_Measure_Refresh";
|
||||
sStatusTip = sToolTipText;
|
||||
sPixmap = "Part_Measure_Refresh";
|
||||
}
|
||||
|
||||
void CmdMeasureRefresh::activated(int iMsg)
|
||||
{
|
||||
Q_UNUSED(iMsg);
|
||||
PartGui::refreshDimensions();
|
||||
}
|
||||
|
||||
bool CmdMeasureRefresh::isActive(void)
|
||||
{
|
||||
return hasActiveDocument();
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
// Part_Measure_Clear_All
|
||||
//===========================================================================
|
||||
@@ -2449,6 +2475,7 @@ void CreatePartCommands(void)
|
||||
rcCmdMgr.addCommand(new CmdColorPerFace());
|
||||
rcCmdMgr.addCommand(new CmdMeasureLinear());
|
||||
rcCmdMgr.addCommand(new CmdMeasureAngular());
|
||||
rcCmdMgr.addCommand(new CmdMeasureRefresh());
|
||||
rcCmdMgr.addCommand(new CmdMeasureClearAll());
|
||||
rcCmdMgr.addCommand(new CmdMeasureToggleAll());
|
||||
rcCmdMgr.addCommand(new CmdMeasureToggle3d());
|
||||
|
||||
@@ -186,33 +186,114 @@ CmdPartSimpleCopy::CmdPartSimpleCopy()
|
||||
sPixmap = "Tree_Part";
|
||||
}
|
||||
|
||||
static void _copyShape(const char *cmdName, bool resolve,bool needElement=false, bool refine=false) {
|
||||
Gui::WaitCursor wc;
|
||||
Gui::Command::openCommand(cmdName);
|
||||
for(auto &sel : Gui::Selection().getSelectionEx("*",App::DocumentObject::getClassTypeId(),resolve)) {
|
||||
std::map<std::string,App::DocumentObject*> subMap;
|
||||
auto obj = sel.getObject();
|
||||
if(!obj) continue;
|
||||
if(resolve || !sel.hasSubNames())
|
||||
subMap.emplace("",obj);
|
||||
else {
|
||||
for(const auto &sub : sel.getSubNames()) {
|
||||
const char *element = 0;
|
||||
auto sobj = obj->resolve(sub.c_str(),0,0,&element);
|
||||
if(!sobj) continue;
|
||||
if(!needElement && element)
|
||||
subMap.emplace(sub.substr(0,element-sub.c_str()),sobj);
|
||||
else
|
||||
subMap.emplace(sub,sobj);
|
||||
}
|
||||
if(subMap.empty())
|
||||
continue;
|
||||
}
|
||||
auto parentName = Gui::Command::getObjectCmd(obj);
|
||||
for(auto &v : subMap) {
|
||||
Gui::Command::doCommand(Gui::Command::Doc,
|
||||
"__shape = Part.getShape(%s,'%s',needSubElement=%s,refine=%s)%s\n"
|
||||
"App.ActiveDocument.addObject('Part::Feature','%s').Shape=__shape\n"
|
||||
"App.ActiveDocument.ActiveObject.Label=%s.Label\n",
|
||||
parentName.c_str(), v.first.c_str(),
|
||||
needElement?"True":"False", refine?"True":"False",
|
||||
needElement?".copy()":"",
|
||||
v.second->getNameInDocument(),
|
||||
Gui::Command::getObjectCmd(v.second).c_str());
|
||||
auto newObj = App::GetApplication().getActiveDocument()->getActiveObject();
|
||||
Gui::Command::copyVisual(newObj, "ShapeColor", v.second);
|
||||
Gui::Command::copyVisual(newObj, "LineColor", v.second);
|
||||
Gui::Command::copyVisual(newObj, "PointColor", v.second);
|
||||
}
|
||||
}
|
||||
Gui::Command::commitCommand();
|
||||
Gui::Command::updateActive();
|
||||
}
|
||||
|
||||
void CmdPartSimpleCopy::activated(int iMsg)
|
||||
{
|
||||
Q_UNUSED(iMsg);
|
||||
Base::Type partid = Base::Type::fromName("Part::Feature");
|
||||
std::vector<Gui::SelectionObject> objs = Gui::Selection().getSelectionEx(0, partid);
|
||||
openCommand("Create Copy");
|
||||
for (std::vector<Gui::SelectionObject>::iterator it = objs.begin(); it != objs.end(); ++it) {
|
||||
doCommand(Doc,"App.ActiveDocument.addObject('Part::Feature','%s').Shape="
|
||||
"App.ActiveDocument.%s.Shape\n"
|
||||
"App.ActiveDocument.ActiveObject.Label="
|
||||
"App.ActiveDocument.%s.Label\n",
|
||||
it->getFeatName(),
|
||||
it->getFeatName(),
|
||||
it->getFeatName());
|
||||
copyVisual("ActiveObject", "ShapeColor", it->getFeatName());
|
||||
copyVisual("ActiveObject", "LineColor", it->getFeatName());
|
||||
copyVisual("ActiveObject", "PointColor", it->getFeatName());
|
||||
copyVisual("ActiveObject", "DiffuseColor", it->getFeatName());
|
||||
}
|
||||
commitCommand();
|
||||
updateActive();
|
||||
_copyShape("Simple copy",true);
|
||||
}
|
||||
|
||||
bool CmdPartSimpleCopy::isActive(void)
|
||||
{
|
||||
Base::Type partid = Base::Type::fromName("Part::Feature");
|
||||
return Gui::Selection().countObjectsOfType(partid) > 0;
|
||||
return Gui::Selection().hasSelection();
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
// Part_TransformedCopy
|
||||
//===========================================================================
|
||||
DEF_STD_CMD_A(CmdPartTransformedCopy);
|
||||
|
||||
CmdPartTransformedCopy::CmdPartTransformedCopy()
|
||||
: Command("Part_TransformedCopy")
|
||||
{
|
||||
sAppModule = "Part";
|
||||
sGroup = QT_TR_NOOP("Part");
|
||||
sMenuText = QT_TR_NOOP("Create transformed copy");
|
||||
sToolTipText = QT_TR_NOOP("Create a non-parametric copy with transformed placement");
|
||||
sWhatsThis = "Part_TransformCopy";
|
||||
sStatusTip = sToolTipText;
|
||||
sPixmap = "Part_Transformed_Copy.svg";
|
||||
}
|
||||
|
||||
void CmdPartTransformedCopy::activated(int iMsg)
|
||||
{
|
||||
Q_UNUSED(iMsg);
|
||||
_copyShape("Transformed copy",false);
|
||||
}
|
||||
|
||||
bool CmdPartTransformedCopy::isActive(void)
|
||||
{
|
||||
return Gui::Selection().hasSelection();
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
// Part_ElementCopy
|
||||
//===========================================================================
|
||||
DEF_STD_CMD_A(CmdPartElementCopy);
|
||||
|
||||
CmdPartElementCopy::CmdPartElementCopy()
|
||||
: Command("Part_ElementCopy")
|
||||
{
|
||||
sAppModule = "Part";
|
||||
sGroup = QT_TR_NOOP("Part");
|
||||
sMenuText = QT_TR_NOOP("Create shape element copy");
|
||||
sToolTipText = QT_TR_NOOP("Create a non-parametric copy of the selected shape element");
|
||||
sWhatsThis = "Part_ElementCopy";
|
||||
sStatusTip = sToolTipText;
|
||||
sPixmap = "Part_Element_Copy.svg";
|
||||
}
|
||||
|
||||
void CmdPartElementCopy::activated(int iMsg)
|
||||
{
|
||||
Q_UNUSED(iMsg);
|
||||
_copyShape("Element copy",false,true);
|
||||
}
|
||||
|
||||
bool CmdPartElementCopy::isActive(void)
|
||||
{
|
||||
return Gui::Selection().hasSelection();
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
@@ -235,53 +316,12 @@ CmdPartRefineShape::CmdPartRefineShape()
|
||||
void CmdPartRefineShape::activated(int iMsg)
|
||||
{
|
||||
Q_UNUSED(iMsg);
|
||||
ParameterGrp::handle hGrp = App::GetApplication().GetParameterGroupByPath("User parameter:BaseApp/Preferences/Mod/Part");
|
||||
bool parametric = hGrp->GetBool("ParametricRefine", true);
|
||||
|
||||
Gui::WaitCursor wc;
|
||||
Base::Type partid = Base::Type::fromName("Part::Feature");
|
||||
std::vector<App::DocumentObject*> objs = Gui::Selection().getObjectsOfType(partid);
|
||||
openCommand("Refine shape");
|
||||
for (std::vector<App::DocumentObject*>::iterator it = objs.begin(); it != objs.end(); ++it) {
|
||||
try {
|
||||
if (parametric) {
|
||||
doCommand(Doc,"App.ActiveDocument.addObject('Part::Refine','%s').Source="
|
||||
"App.ActiveDocument.%s\n"
|
||||
"App.ActiveDocument.ActiveObject.Label="
|
||||
"App.ActiveDocument.%s.Label\n"
|
||||
"Gui.ActiveDocument.%s.hide()\n",
|
||||
(*it)->getNameInDocument(),
|
||||
(*it)->getNameInDocument(),
|
||||
(*it)->getNameInDocument(),
|
||||
(*it)->getNameInDocument());
|
||||
}
|
||||
else {
|
||||
doCommand(Doc,"App.ActiveDocument.addObject('Part::Feature','%s').Shape="
|
||||
"App.ActiveDocument.%s.Shape.removeSplitter()\n"
|
||||
"App.ActiveDocument.ActiveObject.Label="
|
||||
"App.ActiveDocument.%s.Label\n"
|
||||
"Gui.ActiveDocument.%s.hide()\n",
|
||||
(*it)->getNameInDocument(),
|
||||
(*it)->getNameInDocument(),
|
||||
(*it)->getNameInDocument(),
|
||||
(*it)->getNameInDocument());
|
||||
}
|
||||
copyVisual("ActiveObject", "ShapeColor", (*it)->getNameInDocument());
|
||||
copyVisual("ActiveObject", "LineColor", (*it)->getNameInDocument());
|
||||
copyVisual("ActiveObject", "PointColor", (*it)->getNameInDocument());
|
||||
}
|
||||
catch (const Base::Exception& e) {
|
||||
Base::Console().Warning("%s: %s\n", (*it)->Label.getValue(), e.what());
|
||||
}
|
||||
}
|
||||
commitCommand();
|
||||
updateActive();
|
||||
_copyShape("Refined copy",true,false,true);
|
||||
}
|
||||
|
||||
bool CmdPartRefineShape::isActive(void)
|
||||
{
|
||||
Base::Type partid = Base::Type::fromName("Part::Feature");
|
||||
return Gui::Selection().countObjectsOfType(partid) > 0;
|
||||
return Gui::Selection().hasSelection();
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
@@ -381,6 +421,8 @@ void CreateSimplePartCommands(void)
|
||||
rcCmdMgr.addCommand(new CmdPartSimpleCylinder());
|
||||
rcCmdMgr.addCommand(new CmdPartShapeFromMesh());
|
||||
rcCmdMgr.addCommand(new CmdPartSimpleCopy());
|
||||
rcCmdMgr.addCommand(new CmdPartElementCopy());
|
||||
rcCmdMgr.addCommand(new CmdPartTransformedCopy());
|
||||
rcCmdMgr.addCommand(new CmdPartRefineShape());
|
||||
rcCmdMgr.addCommand(new CmdPartDefeaturing());
|
||||
}
|
||||
|
||||
@@ -57,6 +57,8 @@
|
||||
#include <Gui/WaitCursor.h>
|
||||
#include <Gui/Utilities.h>
|
||||
|
||||
FC_LOG_LEVEL_INIT("Part",true,true);
|
||||
|
||||
using namespace PartGui;
|
||||
|
||||
class DlgExtrusion::EdgeSelection : public Gui::SelectionFilterGate
|
||||
@@ -433,9 +435,8 @@ void DlgExtrusion::apply()
|
||||
assert(sourceObj);
|
||||
|
||||
if (!sourceObj->isDerivedFrom(Part::Feature::getClassTypeId())){
|
||||
std::stringstream errmsg;
|
||||
errmsg << "Object " << sourceObj->getNameInDocument() << " is not Part object (has no OCC shape). Can't extrude it.\n";
|
||||
Base::Console().Error(errmsg.str().c_str());
|
||||
FC_ERR("Object " << sourceObj->getFullName()
|
||||
<< " is not Part object (has no OCC shape). Can't extrude it.");
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -447,16 +448,16 @@ void DlgExtrusion::apply()
|
||||
//label = QString::fromLatin1("%1_Extrude").arg((*it)->text(0));
|
||||
}
|
||||
|
||||
Gui::Command::doCommand(Gui::Command::Doc, "f = FreeCAD.getDocument('%s').addObject('Part::Extrusion', '%s')", sourceObj->getDocument()->getName(), name.c_str());
|
||||
FCMD_OBJ_DOC_CMD(sourceObj,"addObject('Part::Extrusion','" << name << "')");
|
||||
auto newObj = sourceObj->getDocument()->getObject(name.c_str());
|
||||
|
||||
this->writeParametersToFeature(*(sourceObj->getDocument()->getObject(name.c_str())), sourceObj);
|
||||
this->writeParametersToFeature(*newObj, sourceObj);
|
||||
|
||||
std::string sourceObjectName = sourceObj->getNameInDocument();
|
||||
Gui::Command::copyVisual(name.c_str(), "ShapeColor", sourceObjectName.c_str());
|
||||
Gui::Command::copyVisual(name.c_str(), "LineColor", sourceObjectName.c_str());
|
||||
Gui::Command::copyVisual(name.c_str(), "PointColor", sourceObjectName.c_str());
|
||||
Gui::Command::copyVisual(newObj, "ShapeColor", sourceObj);
|
||||
Gui::Command::copyVisual(newObj, "LineColor", sourceObj);
|
||||
Gui::Command::copyVisual(newObj, "PointColor", sourceObj);
|
||||
|
||||
Gui::Command::doCommand(Gui::Command::Gui,"f.Base.ViewObject.hide()");
|
||||
FCMD_OBJ_HIDE(sourceObj);
|
||||
}
|
||||
|
||||
activeDoc->commitTransaction();
|
||||
|
||||
@@ -632,6 +632,11 @@ void DlgFilletEdges::setupFillet(const std::vector<App::DocumentObject*>& objs)
|
||||
std::vector<Gui::SelectionObject>::iterator selIt = std::find_if(selObj.begin(), selObj.end(),
|
||||
Private::SelectionObjectCompare(d->object));
|
||||
|
||||
|
||||
/*
|
||||
* Edit: the following check is no longer necessary, as Gui::Selection
|
||||
* will do the check
|
||||
*
|
||||
// If sub-objects are already selected then only add the un-selected parts.
|
||||
// This is impotant to avoid recursive calls of rmvSelection() which
|
||||
// invalidates the internal iterator (#0002200).
|
||||
@@ -645,9 +650,12 @@ void DlgFilletEdges::setupFillet(const std::vector<App::DocumentObject*>& objs)
|
||||
std::set_difference(subElements.begin(), subElements.end(), selElements.begin(), selElements.end(), biit);
|
||||
subElements = complementary;
|
||||
}
|
||||
*/
|
||||
|
||||
Gui::Selection().clearSelection(doc->getName());
|
||||
|
||||
if (!subElements.empty()) {
|
||||
Gui::Selection().addSelection(doc->getName(),
|
||||
Gui::Selection().addSelections(doc->getName(),
|
||||
d->object->getNameInDocument(),
|
||||
subElements);
|
||||
}
|
||||
@@ -795,7 +803,7 @@ void DlgFilletEdges::on_selectAllButton_clicked()
|
||||
|
||||
if (d->object) {
|
||||
App::Document* doc = d->object->getDocument();
|
||||
Gui::Selection().addSelection(doc->getName(),
|
||||
Gui::Selection().addSelections(doc->getName(),
|
||||
d->object->getNameInDocument(),
|
||||
subElements);
|
||||
}
|
||||
|
||||
@@ -59,7 +59,10 @@
|
||||
<file>icons/Part_Measure_Toggle_Delta.svg</file>
|
||||
<file>icons/Part_Measure_Step_Active.svg</file>
|
||||
<file>icons/Part_Measure_Step_Done.svg</file>
|
||||
<file>icons/Part_Measure_Refresh.svg</file>
|
||||
<file>icons/Part_Refine_Shape.svg</file>
|
||||
<file>icons/Part_Element_Copy.svg</file>
|
||||
<file>icons/Part_Transformed_Copy.svg</file>
|
||||
<file>icons/Tree_Part_Box_Parametric.svg</file>
|
||||
<file>icons/Tree_Part_Cylinder_Parametric.svg</file>
|
||||
<file>icons/Tree_Part_Cone_Parametric.svg</file>
|
||||
|
||||
246
src/Mod/Part/Gui/Resources/icons/Part_Element_Copy.svg
Normal file
246
src/Mod/Part/Gui/Resources/icons/Part_Element_Copy.svg
Normal file
@@ -0,0 +1,246 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
width="64px"
|
||||
height="64px"
|
||||
id="svg2980"
|
||||
sodipodi:version="0.32"
|
||||
inkscape:version="0.91 r13725"
|
||||
sodipodi:docname="Part_Element_Copy.svg"
|
||||
inkscape:output_extension="org.inkscape.output.svg.inkscape"
|
||||
version="1.1">
|
||||
<defs
|
||||
id="defs2982">
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
id="linearGradient3794">
|
||||
<stop
|
||||
style="stop-color:#000000;stop-opacity:1;"
|
||||
offset="0"
|
||||
id="stop3796" />
|
||||
<stop
|
||||
style="stop-color:#000000;stop-opacity:0;"
|
||||
offset="1"
|
||||
id="stop3798" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="linearGradient3864">
|
||||
<stop
|
||||
id="stop3866"
|
||||
offset="0"
|
||||
style="stop-color:#71b2f8;stop-opacity:1;" />
|
||||
<stop
|
||||
id="stop3868"
|
||||
offset="1"
|
||||
style="stop-color:#002795;stop-opacity:1;" />
|
||||
</linearGradient>
|
||||
<inkscape:perspective
|
||||
sodipodi:type="inkscape:persp3d"
|
||||
inkscape:vp_x="0 : 32 : 1"
|
||||
inkscape:vp_y="0 : 1000 : 0"
|
||||
inkscape:vp_z="64 : 32 : 1"
|
||||
inkscape:persp3d-origin="32 : 21.333333 : 1"
|
||||
id="perspective2988" />
|
||||
<linearGradient
|
||||
gradientTransform="translate(0,-4)"
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient3767"
|
||||
id="linearGradient3773"
|
||||
x1="22.116516"
|
||||
y1="55.717518"
|
||||
x2="17.328547"
|
||||
y2="21.31134"
|
||||
gradientUnits="userSpaceOnUse" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
id="linearGradient3767">
|
||||
<stop
|
||||
style="stop-color:#3465a4;stop-opacity:1"
|
||||
offset="0"
|
||||
id="stop3769" />
|
||||
<stop
|
||||
style="stop-color:#729fcf;stop-opacity:1"
|
||||
offset="1"
|
||||
id="stop3771" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
gradientTransform="translate(0,-4)"
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient3777"
|
||||
id="linearGradient3783"
|
||||
x1="53.896763"
|
||||
y1="51.179787"
|
||||
x2="47.502235"
|
||||
y2="21.83742"
|
||||
gradientUnits="userSpaceOnUse" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
id="linearGradient3777">
|
||||
<stop
|
||||
style="stop-color:#204a87;stop-opacity:1"
|
||||
offset="0"
|
||||
id="stop3779" />
|
||||
<stop
|
||||
style="stop-color:#3465a4;stop-opacity:1"
|
||||
offset="1"
|
||||
id="stop3781" />
|
||||
</linearGradient>
|
||||
<radialGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient3794"
|
||||
id="radialGradient3800"
|
||||
cx="1"
|
||||
cy="45"
|
||||
fx="1"
|
||||
fy="45"
|
||||
r="41"
|
||||
gradientTransform="matrix(0.93348213,-2.2905276e-8,0,0.28687573,0.06651751,32.090592)"
|
||||
gradientUnits="userSpaceOnUse" />
|
||||
<linearGradient
|
||||
gradientTransform="translate(72,0)"
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient3777-6"
|
||||
id="linearGradient3783-3"
|
||||
x1="53.896763"
|
||||
y1="51.179787"
|
||||
x2="47.502235"
|
||||
y2="21.83742"
|
||||
gradientUnits="userSpaceOnUse" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
id="linearGradient3777-6">
|
||||
<stop
|
||||
style="stop-color:#c4a000;stop-opacity:1"
|
||||
offset="0"
|
||||
id="stop3779-7" />
|
||||
<stop
|
||||
style="stop-color:#edd400;stop-opacity:1"
|
||||
offset="1"
|
||||
id="stop3781-5" />
|
||||
</linearGradient>
|
||||
</defs>
|
||||
<sodipodi:namedview
|
||||
id="base"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="3.4052734"
|
||||
inkscape:cx="16.869406"
|
||||
inkscape:cy="47.934459"
|
||||
inkscape:current-layer="layer1"
|
||||
showgrid="true"
|
||||
inkscape:document-units="px"
|
||||
inkscape:grid-bbox="true"
|
||||
inkscape:window-width="1375"
|
||||
inkscape:window-height="876"
|
||||
inkscape:window-x="65"
|
||||
inkscape:window-y="24"
|
||||
inkscape:snap-bbox="true"
|
||||
inkscape:snap-nodes="false"
|
||||
inkscape:window-maximized="1">
|
||||
<inkscape:grid
|
||||
type="xygrid"
|
||||
id="grid2991"
|
||||
empspacing="2"
|
||||
visible="true"
|
||||
enabled="true"
|
||||
snapvisiblegridlinesonly="true" />
|
||||
</sodipodi:namedview>
|
||||
<metadata
|
||||
id="metadata2985">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title></dc:title>
|
||||
<dc:creator>
|
||||
<cc:Agent>
|
||||
<dc:title>[wmayer]</dc:title>
|
||||
</cc:Agent>
|
||||
</dc:creator>
|
||||
<dc:title>Tree_Part</dc:title>
|
||||
<dc:date>2011-10-10</dc:date>
|
||||
<dc:relation>http://www.freecadweb.org/wiki/index.php?title=Artwork</dc:relation>
|
||||
<dc:publisher>
|
||||
<cc:Agent>
|
||||
<dc:title>FreeCAD</dc:title>
|
||||
</cc:Agent>
|
||||
</dc:publisher>
|
||||
<dc:identifier>FreeCAD/src/Mod/Part/Gui/Resources/icons/Tree_Part.svg</dc:identifier>
|
||||
<dc:rights>
|
||||
<cc:Agent>
|
||||
<dc:title>FreeCAD LGPL2+</dc:title>
|
||||
</cc:Agent>
|
||||
</dc:rights>
|
||||
<cc:license>https://www.gnu.org/copyleft/lesser.html</cc:license>
|
||||
<dc:contributor>
|
||||
<cc:Agent>
|
||||
<dc:title>[agryson] Alexander Gryson</dc:title>
|
||||
</cc:Agent>
|
||||
</dc:contributor>
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g
|
||||
id="layer1"
|
||||
inkscape:label="Layer 1"
|
||||
inkscape:groupmode="layer">
|
||||
<path
|
||||
style="fill:#729fcf;stroke:#0b1521;stroke-width:2;stroke-linecap:butt;stroke-linejoin:round;stroke-opacity:1"
|
||||
d="M 3,13 37,19 61,11 31,7 z"
|
||||
id="path2993"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="ccccc" />
|
||||
<path
|
||||
style="fill:url(#linearGradient3783);fill-opacity:1;stroke:#0b1521;stroke-width:2;stroke-linecap:butt;stroke-linejoin:round;stroke-opacity:1"
|
||||
d="M 61,11 61,47 37,57 37,19 z"
|
||||
id="path2995"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="ccccc"
|
||||
id="path3825"
|
||||
d="M 3,13 37,19 37,57 3,51 z"
|
||||
style="fill:url(#linearGradient3773);fill-opacity:1;fill-rule:evenodd;stroke:#0b1521;stroke-width:2;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
|
||||
<path
|
||||
style="fill:none;stroke:#729fcf;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="m 5,15.42772 0.00867,33.919116 30.008671,5.268799 -0.0087,-33.933614 z"
|
||||
id="path3765"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="ccccc" />
|
||||
<path
|
||||
style="fill:none;stroke:#3465a4;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="m 39.01243,20.433833 -0.01226,33.535301 20.001105,-8.300993 3.6e-4,-31.867363 z"
|
||||
id="path3775"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="ccccc" />
|
||||
<g
|
||||
id="g5368"
|
||||
transform="translate(-71.997618,-3.9896317)">
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path2995-3"
|
||||
d="m 133,15 0,36 -24,10 0,-38 z"
|
||||
style="fill:url(#linearGradient3783-3);fill-opacity:1;stroke:#302b00;stroke-width:2;stroke-linecap:butt;stroke-linejoin:round;stroke-opacity:1" />
|
||||
<path
|
||||
sodipodi:nodetypes="ccccc"
|
||||
inkscape:connector-curvature="0"
|
||||
id="path3775-5"
|
||||
d="m 111.01243,24.433833 -0.0123,33.535301 20.0011,-8.300993 3.6e-4,-31.867363 z"
|
||||
style="fill:none;stroke:#edd400;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 8.1 KiB |
659
src/Mod/Part/Gui/Resources/icons/Part_Measure_Refresh.svg
Normal file
659
src/Mod/Part/Gui/Resources/icons/Part_Measure_Refresh.svg
Normal file
@@ -0,0 +1,659 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
xmlns:osb="http://www.openswatchbook.org/uri/2009/osb"
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
width="64px"
|
||||
height="64px"
|
||||
id="svg2943"
|
||||
sodipodi:version="0.32"
|
||||
inkscape:version="0.91 r13725"
|
||||
sodipodi:docname="Part_Measure_Refresh.svg"
|
||||
inkscape:output_extension="org.inkscape.output.svg.inkscape"
|
||||
version="1.1">
|
||||
<defs
|
||||
id="defs2945">
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
id="linearGradient3961">
|
||||
<stop
|
||||
style="stop-color:#babdb6;stop-opacity:1"
|
||||
offset="0"
|
||||
id="stop3963" />
|
||||
<stop
|
||||
style="stop-color:#d3d7cf;stop-opacity:1"
|
||||
offset="1"
|
||||
id="stop3965" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
id="linearGradient3953">
|
||||
<stop
|
||||
style="stop-color:#babdb6;stop-opacity:1"
|
||||
offset="0"
|
||||
id="stop3955" />
|
||||
<stop
|
||||
style="stop-color:#555753;stop-opacity:1"
|
||||
offset="1"
|
||||
id="stop3957" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="linearGradient4158">
|
||||
<stop
|
||||
style="stop-color:#000000;stop-opacity:1;"
|
||||
offset="0"
|
||||
id="stop4160" />
|
||||
<stop
|
||||
style="stop-color:#f6f6f6;stop-opacity:0;"
|
||||
offset="1"
|
||||
id="stop4162" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="linearGradient4122">
|
||||
<stop
|
||||
style="stop-color:#e3d328;stop-opacity:1;"
|
||||
offset="0"
|
||||
id="stop4124" />
|
||||
<stop
|
||||
style="stop-color:#e1dec3;stop-opacity:1;"
|
||||
offset="1"
|
||||
id="stop4126" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="linearGradient4088">
|
||||
<stop
|
||||
style="stop-color:#e9cd23;stop-opacity:1;"
|
||||
offset="0"
|
||||
id="stop4090" />
|
||||
<stop
|
||||
style="stop-color:#040000;stop-opacity:0;"
|
||||
offset="1"
|
||||
id="stop4092" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
id="linearGradient4060">
|
||||
<stop
|
||||
style="stop-color:#ada9a9;stop-opacity:1;"
|
||||
offset="0"
|
||||
id="stop4062" />
|
||||
<stop
|
||||
style="stop-color:#ada9a9;stop-opacity:0;"
|
||||
offset="1"
|
||||
id="stop4064" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="linearGradient4052">
|
||||
<stop
|
||||
style="stop-color:#ada9a9;stop-opacity:1;"
|
||||
offset="0"
|
||||
id="stop4054" />
|
||||
<stop
|
||||
style="stop-color:#ada9a9;stop-opacity:0;"
|
||||
offset="1"
|
||||
id="stop4056" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="linearGradient4349">
|
||||
<stop
|
||||
style="stop-color:#898709;stop-opacity:1;"
|
||||
offset="0"
|
||||
id="stop4351" />
|
||||
<stop
|
||||
style="stop-color:#000000;stop-opacity:1;"
|
||||
offset="1"
|
||||
id="stop4353" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="linearGradient5241">
|
||||
<stop
|
||||
style="stop-color:#212c45;stop-opacity:1;"
|
||||
offset="0"
|
||||
id="stop5243" />
|
||||
<stop
|
||||
style="stop-color:#000000;stop-opacity:1;"
|
||||
offset="1"
|
||||
id="stop5245" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="linearGradient5227"
|
||||
osb:paint="solid">
|
||||
<stop
|
||||
style="stop-color:#000000;stop-opacity:1;"
|
||||
offset="0"
|
||||
id="stop5229" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="linearGradient3902">
|
||||
<stop
|
||||
style="stop-color:#000000;stop-opacity:0.58823532;"
|
||||
offset="0"
|
||||
id="stop3904" />
|
||||
<stop
|
||||
style="stop-color:#000000;stop-opacity:0.39215687;"
|
||||
offset="1"
|
||||
id="stop3906" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="linearGradient3894">
|
||||
<stop
|
||||
style="stop-color:#45351d;stop-opacity:1;"
|
||||
offset="0"
|
||||
id="stop3896" />
|
||||
<stop
|
||||
style="stop-color:#000000;stop-opacity:1;"
|
||||
offset="1"
|
||||
id="stop3898" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="linearGradient3886">
|
||||
<stop
|
||||
style="stop-color:#45351d;stop-opacity:1;"
|
||||
offset="0"
|
||||
id="stop3888" />
|
||||
<stop
|
||||
style="stop-color:#000000;stop-opacity:1;"
|
||||
offset="1"
|
||||
id="stop3890" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="linearGradient3792">
|
||||
<stop
|
||||
style="stop-color:#aaaaaa;stop-opacity:1;"
|
||||
offset="0"
|
||||
id="stop3794" />
|
||||
<stop
|
||||
style="stop-color:#d2d2d2;stop-opacity:1;"
|
||||
offset="1"
|
||||
id="stop3796" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="linearGradient3784">
|
||||
<stop
|
||||
style="stop-color:#bebebe;stop-opacity:1;"
|
||||
offset="0"
|
||||
id="stop3786" />
|
||||
<stop
|
||||
style="stop-color:#ffffff;stop-opacity:0.39215687;"
|
||||
offset="1"
|
||||
id="stop3788" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="linearGradient3377">
|
||||
<stop
|
||||
id="stop3379"
|
||||
offset="0"
|
||||
style="stop-color:#71b2f8;stop-opacity:1;" />
|
||||
<stop
|
||||
id="stop3381"
|
||||
offset="1"
|
||||
style="stop-color:#002795;stop-opacity:1;" />
|
||||
</linearGradient>
|
||||
<inkscape:perspective
|
||||
sodipodi:type="inkscape:persp3d"
|
||||
inkscape:vp_x="0 : 32 : 1"
|
||||
inkscape:vp_y="0 : 1000 : 0"
|
||||
inkscape:vp_z="64 : 32 : 1"
|
||||
inkscape:persp3d-origin="32 : 21.333333 : 1"
|
||||
id="perspective2951" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient4158"
|
||||
id="linearGradient3092"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="translate(-129.22376,-0.88388348)"
|
||||
x1="419.99387"
|
||||
y1="102.77802"
|
||||
x2="458.7193"
|
||||
y2="69.431564" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient4052"
|
||||
id="linearGradient3094"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="translate(168.6744,65.825928)"
|
||||
x1="138.99986"
|
||||
y1="44.863674"
|
||||
x2="92.497559"
|
||||
y2="-14.356517" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient4122"
|
||||
id="linearGradient3096"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="translate(-88.034794,-1.0606602)"
|
||||
x1="391.3074"
|
||||
y1="120.81136"
|
||||
x2="394.43201"
|
||||
y2="112.43636" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient4060"
|
||||
id="linearGradient3098"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="translate(168.6744,65.825928)"
|
||||
x1="103.93729"
|
||||
y1="49.179436"
|
||||
x2="120.49899"
|
||||
y2="0.21229285" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient3953"
|
||||
id="linearGradient3959"
|
||||
x1="214.70918"
|
||||
y1="80.886589"
|
||||
x2="218.70918"
|
||||
y2="104.88659"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="translate(80,0)" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient3961"
|
||||
id="linearGradient3967"
|
||||
x1="196.70918"
|
||||
y1="106.88659"
|
||||
x2="190.70918"
|
||||
y2="80.886589"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="translate(80,0)" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient3953-5"
|
||||
id="linearGradient3959-3"
|
||||
x1="214.70918"
|
||||
y1="80.886589"
|
||||
x2="218.70918"
|
||||
y2="104.88659"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="translate(80,0)" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
id="linearGradient3953-5">
|
||||
<stop
|
||||
style="stop-color:#babdb6;stop-opacity:1"
|
||||
offset="0"
|
||||
id="stop3955-6" />
|
||||
<stop
|
||||
style="stop-color:#555753;stop-opacity:1"
|
||||
offset="1"
|
||||
id="stop3957-2" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient2831-2"
|
||||
id="linearGradient4585"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(1.370336,0,0,1.3589114,0.02150968,-18.214919)"
|
||||
x1="13.478554"
|
||||
y1="10.612206"
|
||||
x2="15.419417"
|
||||
y2="19.115122" />
|
||||
<linearGradient
|
||||
id="linearGradient2831-2">
|
||||
<stop
|
||||
style="stop-color:#3465a4;stop-opacity:1;"
|
||||
offset="0"
|
||||
id="stop2833-3" />
|
||||
<stop
|
||||
id="stop2855-1"
|
||||
offset="0.33333334"
|
||||
style="stop-color:#5b86be;stop-opacity:1;" />
|
||||
<stop
|
||||
style="stop-color:#83a8d8;stop-opacity:0;"
|
||||
offset="1"
|
||||
id="stop2835-6" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient2871"
|
||||
id="linearGradient1488"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(-1.370336,0,0,-1.3589114,64.512944,44.464873)"
|
||||
x1="37.128052"
|
||||
y1="29.729605"
|
||||
x2="37.065414"
|
||||
y2="26.194071" />
|
||||
<linearGradient
|
||||
id="linearGradient2871"
|
||||
inkscape:collect="always">
|
||||
<stop
|
||||
id="stop2873"
|
||||
offset="0"
|
||||
style="stop-color:#3465a4;stop-opacity:1;" />
|
||||
<stop
|
||||
id="stop2875"
|
||||
offset="1"
|
||||
style="stop-color:#3465a4;stop-opacity:1" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient3063-2"
|
||||
id="linearGradient4587"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
x1="42.703487"
|
||||
y1="20.547306"
|
||||
x2="26.605606"
|
||||
y2="33.634254" />
|
||||
<linearGradient
|
||||
id="linearGradient3063-2">
|
||||
<stop
|
||||
id="stop3065-6"
|
||||
offset="0"
|
||||
style="stop-color:#729fcf;stop-opacity:1" />
|
||||
<stop
|
||||
id="stop3067-0"
|
||||
offset="1"
|
||||
style="stop-color:#204a87;stop-opacity:1" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient2380-9"
|
||||
id="linearGradient3034"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
x1="41.791897"
|
||||
y1="20.134634"
|
||||
x2="23.705669"
|
||||
y2="34.083359" />
|
||||
<linearGradient
|
||||
id="linearGradient2380-9">
|
||||
<stop
|
||||
style="stop-color:#729fcf;stop-opacity:1"
|
||||
offset="0"
|
||||
id="stop2382-4" />
|
||||
<stop
|
||||
style="stop-color:#3465a4;stop-opacity:1"
|
||||
offset="1"
|
||||
id="stop2384-6" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient2380-9"
|
||||
id="linearGradient3034-4"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
x1="26.221533"
|
||||
y1="31.125586"
|
||||
x2="46.731483"
|
||||
y2="21.766298" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient2831-2"
|
||||
id="linearGradient4295"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(1.370336,0,0,1.3589114,0.02150968,-18.214919)"
|
||||
x1="13.478554"
|
||||
y1="10.612206"
|
||||
x2="15.419417"
|
||||
y2="19.115122" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient2871"
|
||||
id="linearGradient4297"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(-1.370336,0,0,-1.3589114,64.512944,44.464873)"
|
||||
x1="37.128052"
|
||||
y1="29.729605"
|
||||
x2="37.065414"
|
||||
y2="26.194071" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient3063-2"
|
||||
id="linearGradient4299"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
x1="42.703487"
|
||||
y1="20.547306"
|
||||
x2="26.605606"
|
||||
y2="33.634254" />
|
||||
</defs>
|
||||
<sodipodi:namedview
|
||||
id="base"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="7.6761244"
|
||||
inkscape:cx="44.088329"
|
||||
inkscape:cy="36.738683"
|
||||
inkscape:current-layer="g3629"
|
||||
showgrid="true"
|
||||
inkscape:document-units="px"
|
||||
inkscape:grid-bbox="true"
|
||||
inkscape:window-width="1375"
|
||||
inkscape:window-height="876"
|
||||
inkscape:window-x="65"
|
||||
inkscape:window-y="24"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:snap-bbox="false"
|
||||
inkscape:snap-nodes="true">
|
||||
<inkscape:grid
|
||||
type="xygrid"
|
||||
id="grid3059"
|
||||
empspacing="2"
|
||||
visible="true"
|
||||
enabled="true"
|
||||
snapvisiblegridlinesonly="true" />
|
||||
</sodipodi:namedview>
|
||||
<metadata
|
||||
id="metadata2948">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title></dc:title>
|
||||
<dc:creator>
|
||||
<cc:Agent>
|
||||
<dc:title>[blobfish]</dc:title>
|
||||
</cc:Agent>
|
||||
</dc:creator>
|
||||
<dc:title>Part_Measure_Linear</dc:title>
|
||||
<dc:date>2013-12-17</dc:date>
|
||||
<dc:relation>http://www.freecadweb.org/wiki/index.php?title=Artwork</dc:relation>
|
||||
<dc:publisher>
|
||||
<cc:Agent>
|
||||
<dc:title>FreeCAD</dc:title>
|
||||
</cc:Agent>
|
||||
</dc:publisher>
|
||||
<dc:identifier>FreeCAD/src/Mod/Part/Gui/Resources/icons/Part_Measure_Linear.svg</dc:identifier>
|
||||
<dc:rights>
|
||||
<cc:Agent>
|
||||
<dc:title>FreeCAD LGPL2+</dc:title>
|
||||
</cc:Agent>
|
||||
</dc:rights>
|
||||
<cc:license>https://www.gnu.org/copyleft/lesser.html</cc:license>
|
||||
<dc:contributor>
|
||||
<cc:Agent>
|
||||
<dc:title>[agryson] Alexander Gryson</dc:title>
|
||||
</cc:Agent>
|
||||
</dc:contributor>
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g
|
||||
id="layer1"
|
||||
inkscape:label="Layer 1"
|
||||
inkscape:groupmode="layer">
|
||||
<g
|
||||
id="g3629"
|
||||
transform="translate(-256.70919,-66.886588)">
|
||||
<path
|
||||
style="fill:#e3d328;fill-opacity:1;stroke:#040400;stroke-width:0.08838835;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
|
||||
d=""
|
||||
id="path4102"
|
||||
inkscape:connector-curvature="0"
|
||||
transform="translate(256.70919,66.886588)" />
|
||||
<path
|
||||
style="fill:#babdb6;stroke:#2e3436;stroke-width:2;stroke-linecap:butt;stroke-linejoin:round;stroke-opacity:1"
|
||||
d="m 285.70919,77.886588 -26,-4 c 0,11 0,26 2,36.000002 l 30,12 0,-6 -2,-4 c 8,-12.000002 0,-24.000002 -4,-34.000002 z"
|
||||
id="path3100"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="ccccccc" />
|
||||
<path
|
||||
style="fill:#555753;stroke:#2e3436;stroke-width:2;stroke-linecap:butt;stroke-linejoin:round;stroke-opacity:1"
|
||||
d="m 291.70919,121.88659 12,-4 0,-6 -12,4 z"
|
||||
id="path3890"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
style="fill:#d3d7cf;stroke:#2e3436;stroke-width:2;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
|
||||
d="m 301.70919,107.88659 -12,4 2,4 12,-4 z"
|
||||
id="path3892"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
style="fill:#888a85;stroke:#2e3436;stroke-width:2;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
|
||||
d="m 285.70919,77.886588 c 4,10 12,22 4,34.000002 l 12,-4 c 8,-12.000002 0,-24.000002 -4,-34.000002 z"
|
||||
id="path3894"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="ccccc" />
|
||||
<path
|
||||
style="fill:#d3d7cf;stroke:#2e3436;stroke-width:2;stroke-linecap:butt;stroke-linejoin:round;stroke-opacity:1"
|
||||
d="m 259.70919,73.886588 12,-4 26,4 -12,4 z"
|
||||
id="path3888"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="ccccc" />
|
||||
<path
|
||||
style="fill:url(#linearGradient3967);fill-opacity:1;stroke:#d3d7cf;stroke-width:1.99999975999999990;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="m 284.30919,79.786588 -22.6,-3.9 c 0,10.043478 -0.0125,23.469561 1.8,32.600002 l 26.2,10.4 0,-2.5 -2.2,-4.5 c 8,-12.000002 1.2,-22.000002 -3.2,-32.100002 z"
|
||||
id="path3100-6"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="ccccccc" />
|
||||
<path
|
||||
style="fill:url(#linearGradient3959);fill-opacity:1;stroke:#babdb6;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
|
||||
d="m 288.30919,79.086588 c 4,10 9.4,18.3 5.4,29.300002 l 6.6,-2.2 c 6,-9.000002 1.4,-19.300002 -3.8,-29.900002 z"
|
||||
id="path3894-7"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="ccccc" />
|
||||
<path
|
||||
sodipodi:type="arc"
|
||||
style="fill:#555753;fill-opacity:1;stroke:#2e3436;stroke-width:2.25831866;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:1.6"
|
||||
id="path3932"
|
||||
sodipodi:cx="-93"
|
||||
sodipodi:cy="39"
|
||||
sodipodi:rx="15"
|
||||
sodipodi:ry="15"
|
||||
d="m -78,39 a 15,15 0 0 1 -15,15 15,15 0 0 1 -15,-15 15,15 0 0 1 15,-15 15,15 0 0 1 15,15 z"
|
||||
transform="matrix(0.79999998,0.19607832,0,0.9803916,350.10919,74.8866)" />
|
||||
<path
|
||||
style="fill:#edd400;fill-opacity:1;stroke:#302b00;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dashoffset:1.6"
|
||||
d="m 287.70919,97.827762 -24,-5.882349 c 0,0 -0.82229,-14.095015 12,-11.764699 11.12322,2.021527 12,17.647048 12,17.647048 z"
|
||||
id="path3932-5"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="ccsc" />
|
||||
<path
|
||||
style="fill:#edd400;fill-opacity:1;stroke:#302b00;stroke-width:2;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
|
||||
d="m 294.70919,90.886588 c 2,4 3,11.000002 1,15.000002 l 4,-1 c 2,-4 2,-11.000002 0,-15.000002 z"
|
||||
id="path3894-7-9"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="ccccc" />
|
||||
<path
|
||||
style="fill:#edd400;stroke:#302b00;stroke-width:2;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
|
||||
d="m 37,51 8,-3 16,5 -6,4 z"
|
||||
id="path4003"
|
||||
inkscape:connector-curvature="0"
|
||||
transform="translate(256.70919,66.886588)"
|
||||
sodipodi:nodetypes="ccccc" />
|
||||
<path
|
||||
style="fill:#d3d7cf;stroke:#2e3436;stroke-width:2;stroke-linecap:butt;stroke-linejoin:round;stroke-opacity:1"
|
||||
d="m 61,53 0,4 -6,4 0,-4 z"
|
||||
id="path4005"
|
||||
inkscape:connector-curvature="0"
|
||||
transform="translate(256.70919,66.886588)"
|
||||
sodipodi:nodetypes="ccccc" />
|
||||
<g
|
||||
id="g4314">
|
||||
<g
|
||||
id="g3863"
|
||||
transform="matrix(0.59299466,0,0,0.59299466,283.4333,77.218635)">
|
||||
<path
|
||||
style="color:#000000;display:block;overflow:visible;visibility:visible;fill:url(#linearGradient4295);fill-opacity:1;fill-rule:nonzero;stroke:url(#linearGradient4297);stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none"
|
||||
d="m 27,-3.6915582 c 0,0 -12.247378,-0.8493196 -8.478954,13.4192502 l -10.534458,0 c 0,0 0.685168,-16.137073 19.013412,-13.4192502 z"
|
||||
id="path2865-9"
|
||||
inkscape:r_cx="true"
|
||||
inkscape:r_cy="true"
|
||||
sodipodi:nodetypes="cccc"
|
||||
inkscape:connector-curvature="0" />
|
||||
<g
|
||||
id="g1878-1"
|
||||
transform="matrix(-0.79349441,-0.66481753,-0.67040672,0.78687903,77.66003,0.94046451)"
|
||||
inkscape:r_cx="true"
|
||||
inkscape:r_cy="true"
|
||||
style="fill:url(#linearGradient4299);fill-opacity:1;stroke:#204a87;stroke-width:0.73280919;stroke-opacity:1">
|
||||
<path
|
||||
sodipodi:nodetypes="ccccccc"
|
||||
id="path1880-27"
|
||||
d="M 44.306783,50.229694 C 62.821497,35.818859 49.664587,13.411704 22.462411,12.49765 L 22.113843,3.1515478 7.6245439,20.496754 22.714328,33.219189 c 0,0 -0.251917,-9.88122 -0.251917,-9.88122 18.82976,0.998977 32.981627,14.071729 21.844372,26.891725 z"
|
||||
style="color:#000000;display:block;overflow:visible;visibility:visible;fill:url(#linearGradient3034);fill-opacity:1;fill-rule:nonzero;stroke:#0b1521;stroke-width:3.26039815;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none"
|
||||
inkscape:r_cx="true"
|
||||
inkscape:r_cy="true"
|
||||
inkscape:connector-curvature="0" />
|
||||
</g>
|
||||
<g
|
||||
style="fill:none;stroke:#729fcf;stroke-width:0.73280919;stroke-opacity:1"
|
||||
inkscape:r_cy="true"
|
||||
inkscape:r_cx="true"
|
||||
transform="matrix(-0.69686517,-0.58385766,-0.58876622,0.69105539,72.350404,1.0127423)"
|
||||
id="g2805-0">
|
||||
<path
|
||||
inkscape:r_cy="true"
|
||||
inkscape:r_cx="true"
|
||||
style="color:#000000;display:block;overflow:visible;visibility:visible;fill:none;stroke:#729fcf;stroke-width:2.20148993;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:21;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none"
|
||||
d="M 52.368857,42.344789 C 57.336994,33.465615 49.176003,12.601866 19.05552,12.672851 L 18.677956,5.6633463 7.4378077,19.282655 19.129354,29.167094 18.807724,20.554957 c 18.244937,0.381972 33.804002,9.457851 33.561133,21.789832 z"
|
||||
id="path2807-9"
|
||||
sodipodi:nodetypes="ccccccc"
|
||||
inkscape:connector-curvature="0" />
|
||||
</g>
|
||||
</g>
|
||||
<g
|
||||
id="g3863-0"
|
||||
transform="matrix(-0.59299466,0,0,-0.59299466,322.563,94.41548)">
|
||||
<path
|
||||
style="color:#000000;display:block;overflow:visible;visibility:visible;fill:url(#linearGradient4585);fill-opacity:1;fill-rule:nonzero;stroke:url(#linearGradient1488);stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none"
|
||||
d="m 27,-3.6915582 c 0,0 -12.247378,-0.8493196 -8.478954,13.4192502 l -10.534458,0 c 0,0 0.685168,-16.137073 19.013412,-13.4192502 z"
|
||||
id="path2865-3"
|
||||
inkscape:r_cx="true"
|
||||
inkscape:r_cy="true"
|
||||
sodipodi:nodetypes="cccc"
|
||||
inkscape:connector-curvature="0" />
|
||||
<g
|
||||
id="g1878-6"
|
||||
transform="matrix(-0.79349441,-0.66481753,-0.67040672,0.78687903,77.66003,0.94046451)"
|
||||
inkscape:r_cx="true"
|
||||
inkscape:r_cy="true"
|
||||
style="fill:url(#linearGradient4587);fill-opacity:1;stroke:#204a87;stroke-width:0.73280919;stroke-opacity:1">
|
||||
<path
|
||||
sodipodi:nodetypes="ccccccc"
|
||||
id="path1880-2"
|
||||
d="M 44.306783,50.229694 C 62.821497,35.818859 49.664587,13.411704 22.462411,12.49765 L 22.113843,3.1515478 7.6245439,20.496754 22.714328,33.219189 c 0,0 -0.251917,-9.88122 -0.251917,-9.88122 18.82976,0.998977 32.981627,14.071729 21.844372,26.891725 z"
|
||||
style="color:#000000;display:block;overflow:visible;visibility:visible;fill:url(#linearGradient3034-4);fill-opacity:1;fill-rule:nonzero;stroke:#0b1521;stroke-width:3.26039815;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none"
|
||||
inkscape:r_cx="true"
|
||||
inkscape:r_cy="true"
|
||||
inkscape:connector-curvature="0" />
|
||||
</g>
|
||||
<g
|
||||
style="fill:none;stroke:#729fcf;stroke-width:0.73280919;stroke-opacity:1"
|
||||
inkscape:r_cy="true"
|
||||
inkscape:r_cx="true"
|
||||
transform="matrix(-0.69686517,-0.58385766,-0.58876622,0.69105539,72.350404,1.0127423)"
|
||||
id="g2805-4">
|
||||
<path
|
||||
inkscape:r_cy="true"
|
||||
inkscape:r_cx="true"
|
||||
style="color:#000000;display:block;overflow:visible;visibility:visible;fill:none;stroke:#729fcf;stroke-width:2.20148993;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:21;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none"
|
||||
d="M 52.368857,42.344789 C 57.864671,33.591679 49.176003,12.601866 19.05552,12.672851 L 18.677956,5.6633463 7.4378077,19.282655 19.129354,29.167094 18.807724,20.554957 c 18.244937,0.381972 33.804002,9.457851 33.561133,21.789832 z"
|
||||
id="path2807-5"
|
||||
sodipodi:nodetypes="ccccccc"
|
||||
inkscape:connector-curvature="0" />
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 24 KiB |
290
src/Mod/Part/Gui/Resources/icons/Part_Transformed_Copy.svg
Normal file
290
src/Mod/Part/Gui/Resources/icons/Part_Transformed_Copy.svg
Normal file
@@ -0,0 +1,290 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
width="64px"
|
||||
height="64px"
|
||||
id="svg2980"
|
||||
sodipodi:version="0.32"
|
||||
inkscape:version="0.91 r13725"
|
||||
sodipodi:docname="Part_Transformed_Copy.svg"
|
||||
inkscape:output_extension="org.inkscape.output.svg.inkscape"
|
||||
version="1.1">
|
||||
<defs
|
||||
id="defs2982">
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
id="linearGradient3794">
|
||||
<stop
|
||||
style="stop-color:#000000;stop-opacity:1;"
|
||||
offset="0"
|
||||
id="stop3796" />
|
||||
<stop
|
||||
style="stop-color:#000000;stop-opacity:0;"
|
||||
offset="1"
|
||||
id="stop3798" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="linearGradient3864">
|
||||
<stop
|
||||
id="stop3866"
|
||||
offset="0"
|
||||
style="stop-color:#71b2f8;stop-opacity:1;" />
|
||||
<stop
|
||||
id="stop3868"
|
||||
offset="1"
|
||||
style="stop-color:#002795;stop-opacity:1;" />
|
||||
</linearGradient>
|
||||
<inkscape:perspective
|
||||
sodipodi:type="inkscape:persp3d"
|
||||
inkscape:vp_x="0 : 32 : 1"
|
||||
inkscape:vp_y="0 : 1000 : 0"
|
||||
inkscape:vp_z="64 : 32 : 1"
|
||||
inkscape:persp3d-origin="32 : 21.333333 : 1"
|
||||
id="perspective2988" />
|
||||
<linearGradient
|
||||
gradientTransform="translate(0,-4)"
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient3767"
|
||||
id="linearGradient3773"
|
||||
x1="22.116516"
|
||||
y1="55.717518"
|
||||
x2="17.328547"
|
||||
y2="21.31134"
|
||||
gradientUnits="userSpaceOnUse" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
id="linearGradient3767">
|
||||
<stop
|
||||
style="stop-color:#edd400;stop-opacity:1"
|
||||
offset="0"
|
||||
id="stop3769" />
|
||||
<stop
|
||||
style="stop-color:#fce94f;stop-opacity:1"
|
||||
offset="1"
|
||||
id="stop3771" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
gradientTransform="translate(0,-4)"
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient3777"
|
||||
id="linearGradient3783"
|
||||
x1="53.896763"
|
||||
y1="51.179787"
|
||||
x2="47.502235"
|
||||
y2="21.83742"
|
||||
gradientUnits="userSpaceOnUse" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
id="linearGradient3777">
|
||||
<stop
|
||||
style="stop-color:#c4a000;stop-opacity:1"
|
||||
offset="0"
|
||||
id="stop3779" />
|
||||
<stop
|
||||
style="stop-color:#edd400;stop-opacity:1"
|
||||
offset="1"
|
||||
id="stop3781" />
|
||||
</linearGradient>
|
||||
<radialGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient3794"
|
||||
id="radialGradient3800"
|
||||
cx="1"
|
||||
cy="45"
|
||||
fx="1"
|
||||
fy="45"
|
||||
r="41"
|
||||
gradientTransform="matrix(0.93348213,-2.2905276e-8,0,0.28687573,0.06651751,32.090592)"
|
||||
gradientUnits="userSpaceOnUse" />
|
||||
<linearGradient
|
||||
gradientTransform="translate(-32,-36)"
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient3767-6"
|
||||
id="linearGradient3773-3"
|
||||
x1="22.116516"
|
||||
y1="55.717518"
|
||||
x2="17.328547"
|
||||
y2="21.31134"
|
||||
gradientUnits="userSpaceOnUse" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
id="linearGradient3767-6">
|
||||
<stop
|
||||
style="stop-color:#3465a4;stop-opacity:1"
|
||||
offset="0"
|
||||
id="stop3769-7" />
|
||||
<stop
|
||||
style="stop-color:#729fcf;stop-opacity:1"
|
||||
offset="1"
|
||||
id="stop3771-5" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
gradientTransform="translate(-32,-36)"
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient3777-5"
|
||||
id="linearGradient3783-3"
|
||||
x1="53.896763"
|
||||
y1="51.179787"
|
||||
x2="47.502235"
|
||||
y2="21.83742"
|
||||
gradientUnits="userSpaceOnUse" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
id="linearGradient3777-5">
|
||||
<stop
|
||||
style="stop-color:#204a87;stop-opacity:1"
|
||||
offset="0"
|
||||
id="stop3779-6" />
|
||||
<stop
|
||||
style="stop-color:#3465a4;stop-opacity:1"
|
||||
offset="1"
|
||||
id="stop3781-2" />
|
||||
</linearGradient>
|
||||
</defs>
|
||||
<sodipodi:namedview
|
||||
id="base"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="4.2166862"
|
||||
inkscape:cx="-19.30221"
|
||||
inkscape:cy="11.865722"
|
||||
inkscape:current-layer="layer1"
|
||||
showgrid="true"
|
||||
inkscape:document-units="px"
|
||||
inkscape:grid-bbox="true"
|
||||
inkscape:window-width="1375"
|
||||
inkscape:window-height="876"
|
||||
inkscape:window-x="65"
|
||||
inkscape:window-y="24"
|
||||
inkscape:snap-bbox="true"
|
||||
inkscape:snap-nodes="false"
|
||||
inkscape:window-maximized="1">
|
||||
<inkscape:grid
|
||||
type="xygrid"
|
||||
id="grid2991"
|
||||
empspacing="2"
|
||||
visible="true"
|
||||
enabled="true"
|
||||
snapvisiblegridlinesonly="true" />
|
||||
</sodipodi:namedview>
|
||||
<metadata
|
||||
id="metadata2985">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title></dc:title>
|
||||
<dc:creator>
|
||||
<cc:Agent>
|
||||
<dc:title>[wmayer]</dc:title>
|
||||
</cc:Agent>
|
||||
</dc:creator>
|
||||
<dc:title>Part_Box</dc:title>
|
||||
<dc:date>2011-10-10</dc:date>
|
||||
<dc:relation>http://www.freecadweb.org/wiki/index.php?title=Artwork</dc:relation>
|
||||
<dc:publisher>
|
||||
<cc:Agent>
|
||||
<dc:title>FreeCAD</dc:title>
|
||||
</cc:Agent>
|
||||
</dc:publisher>
|
||||
<dc:identifier>FreeCAD/src/Mod/Part/Gui/Resources/icons/Part_Box.svg</dc:identifier>
|
||||
<dc:rights>
|
||||
<cc:Agent>
|
||||
<dc:title>FreeCAD LGPL2+</dc:title>
|
||||
</cc:Agent>
|
||||
</dc:rights>
|
||||
<cc:license>https://www.gnu.org/copyleft/lesser.html</cc:license>
|
||||
<dc:contributor>
|
||||
<cc:Agent>
|
||||
<dc:title>[agryson] Alexander Gryson</dc:title>
|
||||
</cc:Agent>
|
||||
</dc:contributor>
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g
|
||||
id="layer1"
|
||||
inkscape:label="Layer 1"
|
||||
inkscape:groupmode="layer">
|
||||
<g
|
||||
id="g4185"
|
||||
transform="matrix(0.66,0,0,0.66,24.009277,20.913856)">
|
||||
<path
|
||||
sodipodi:nodetypes="ccccc"
|
||||
inkscape:connector-curvature="0"
|
||||
id="path2993-9"
|
||||
d="m -29,-19 34,6 24,-8 -30,-4 z"
|
||||
style="fill:#729fcf;stroke:#0b1521;stroke-width:3.03030303;stroke-linecap:butt;stroke-linejoin:round;stroke-opacity:1;stroke-miterlimit:4;stroke-dasharray:none" />
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path2995-1"
|
||||
d="M 29,-21 29,15 5,25 5,-13 Z"
|
||||
style="fill:url(#linearGradient3783-3);fill-opacity:1;stroke:#0b1521;stroke-width:3.03030303;stroke-linecap:butt;stroke-linejoin:round;stroke-opacity:1;stroke-miterlimit:4;stroke-dasharray:none" />
|
||||
<path
|
||||
style="display:inline;overflow:visible;visibility:visible;fill:url(#linearGradient3773-3);fill-opacity:1;fill-rule:evenodd;stroke:#0b1521;stroke-width:3.030303;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;enable-background:accumulate"
|
||||
d="M -29,-19 4.5508465,-13.089831 4.3711851,24.820339 -29,19 Z"
|
||||
id="path3825-2"
|
||||
sodipodi:nodetypes="ccccc"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
sodipodi:nodetypes="ccccc"
|
||||
inkscape:connector-curvature="0"
|
||||
id="path3765-7"
|
||||
d="m -26.237761,-16.064121 -0.24538,33.029838 28.400747,5.06734 -0.07222,-32.996227 z"
|
||||
style="fill:none;stroke:#729fcf;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
|
||||
<path
|
||||
sodipodi:nodetypes="ccccc"
|
||||
inkscape:connector-curvature="0"
|
||||
id="path3775-0"
|
||||
d="M 7.01243,-11.058008 7.00017,21.969134 27.001275,13.668141 26.620516,-17.564023 Z"
|
||||
style="fill:none;stroke:#3465a4;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
|
||||
</g>
|
||||
<g
|
||||
id="g4192"
|
||||
transform="matrix(0.66,0,0,0.66,19.293871,22.570766)">
|
||||
<path
|
||||
sodipodi:nodetypes="ccccc"
|
||||
inkscape:connector-curvature="0"
|
||||
id="path2993"
|
||||
d="M 3,13 37,19 61,11 31,7 Z"
|
||||
style="fill:#fce94f;stroke:#302b00;stroke-width:3.03030303;stroke-linecap:butt;stroke-linejoin:round;stroke-opacity:1;stroke-miterlimit:4;stroke-dasharray:none" />
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path2995"
|
||||
d="M 61,11 61,47 37,57 37,19 Z"
|
||||
style="fill:url(#linearGradient3783);fill-opacity:1;stroke:#302b00;stroke-width:3.03030303;stroke-linecap:butt;stroke-linejoin:round;stroke-opacity:1;stroke-miterlimit:4;stroke-dasharray:none" />
|
||||
<path
|
||||
style="display:inline;overflow:visible;visibility:visible;fill:url(#linearGradient3773);fill-opacity:1;fill-rule:evenodd;stroke:#302b00;stroke-width:3.030303;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;enable-background:accumulate"
|
||||
d="M 3,13 36.364801,19.25408 36.281354,56.820339 3,51 Z"
|
||||
id="path3825"
|
||||
sodipodi:nodetypes="ccccc"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
sodipodi:nodetypes="ccccc"
|
||||
inkscape:connector-curvature="0"
|
||||
id="path3765"
|
||||
d="M 5.4491535,15.966704 5.6374849,48.987513 33.58005,53.896989 33.751011,21.310836 Z"
|
||||
style="fill:none;stroke:#fce94f;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
|
||||
<path
|
||||
sodipodi:nodetypes="ccccc"
|
||||
inkscape:connector-curvature="0"
|
||||
id="path3775"
|
||||
d="m 39.01243,20.433833 -0.01226,33.535301 20.001105,-8.300993 3.6e-4,-31.867363 z"
|
||||
style="fill:none;stroke:#edd400;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 10 KiB |
@@ -109,6 +109,7 @@ void TaskAttacher::makeRefStrings(std::vector<QString>& refstrings, std::vector<
|
||||
|
||||
TaskAttacher::TaskAttacher(Gui::ViewProviderDocumentObject *ViewProvider,QWidget *parent, QString picture, QString text)
|
||||
: TaskBox(Gui::BitmapFactory().pixmap(picture.toLatin1()), text, true, parent),
|
||||
SelectionObserver(ViewProvider),
|
||||
ViewProvider(ViewProvider)
|
||||
{
|
||||
//check if we are attachable
|
||||
@@ -348,8 +349,8 @@ void TaskAttacher::onSelectionChanged(const Gui::SelectionChanges& msg)
|
||||
std::vector<App::DocumentObject*> refs = pcAttach->Support.getValues();
|
||||
std::vector<std::string> refnames = pcAttach->Support.getSubValues();
|
||||
App::DocumentObject* selObj = ViewProvider->getObject()->getDocument()->getObject(msg.pObjectName);
|
||||
if (selObj == ViewProvider->getObject()) return;//prevent self-referencing
|
||||
|
||||
if (!selObj || selObj == ViewProvider->getObject()) return;//prevent self-referencing
|
||||
|
||||
std::string subname = msg.pSubName;
|
||||
|
||||
// Remove subname for planes and datum features
|
||||
@@ -1021,36 +1022,28 @@ bool TaskDlgAttacher::accept()
|
||||
return true;
|
||||
|
||||
Part::AttachExtension* pcAttach = ViewProvider->getObject()->getExtensionByType<Part::AttachExtension>();
|
||||
std::string name = ViewProvider->getObject()->getNameInDocument();
|
||||
std::string appDocument = doc.getAppDocumentPython();
|
||||
std::string guiDocument = doc.getGuiDocumentPython();
|
||||
auto obj = ViewProvider->getObject();
|
||||
|
||||
//DeepSOIC: changed this to heavily rely on dialog constantly updating feature properties
|
||||
if (pcAttach->AttachmentOffset.isTouched()){
|
||||
Base::Placement plm = pcAttach->AttachmentOffset.getValue();
|
||||
double yaw, pitch, roll;
|
||||
plm.getRotation().getYawPitchRoll(yaw,pitch,roll);
|
||||
Gui::Command::doCommand(Gui::Command::Doc,"%s.%s.AttachmentOffset = App.Placement(App.Vector(%.10f, %.10f, %.10f), App.Rotation(%.10f, %.10f, %.10f))",
|
||||
appDocument.c_str(), name.c_str(),
|
||||
FCMD_OBJ_CMD2("AttachmentOffset = App.Placement(App.Vector(%.10f, %.10f, %.10f), App.Rotation(%.10f, %.10f, %.10f))",
|
||||
obj,
|
||||
plm.getPosition().x, plm.getPosition().y, plm.getPosition().z,
|
||||
yaw, pitch, roll);
|
||||
}
|
||||
|
||||
Gui::Command::doCommand(Gui::Command::Doc,"%s.%s.MapReversed = %s",
|
||||
appDocument.c_str(), name.c_str(),
|
||||
pcAttach->MapReversed.getValue() ? "True" : "False");
|
||||
FCMD_OBJ_CMD2("MapReversed = %s", obj, pcAttach->MapReversed.getValue() ? "True" : "False");
|
||||
|
||||
Gui::Command::doCommand(Gui::Command::Doc,"%s.%s.Support = %s",
|
||||
appDocument.c_str(), name.c_str(),
|
||||
pcAttach->Support.getPyReprString().c_str());
|
||||
FCMD_OBJ_CMD2("Support = %s", obj, pcAttach->Support.getPyReprString().c_str());
|
||||
|
||||
Gui::Command::doCommand(Gui::Command::Doc,"%s.%s.MapMode = '%s'",
|
||||
appDocument.c_str(), name.c_str(),
|
||||
AttachEngine::getModeName(eMapMode(pcAttach->MapMode.getValue())).c_str());
|
||||
FCMD_OBJ_CMD2("MapMode = '%s'", obj, AttachEngine::getModeName(eMapMode(pcAttach->MapMode.getValue())).c_str());
|
||||
|
||||
Gui::Command::doCommand(Gui::Command::Doc,"%s.recompute()", appDocument.c_str());
|
||||
FCMD_OBJ_DOC_CMD(obj, "recompute()");
|
||||
|
||||
Gui::Command::doCommand(Gui::Command::Gui, "%s.resetEdit()", guiDocument.c_str());
|
||||
FCMD_VOBJ_DOC_CMD(obj,"resetEdit()");
|
||||
document->commitCommand();
|
||||
}
|
||||
catch (const Base::Exception& e) {
|
||||
|
||||
@@ -415,38 +415,25 @@ void TaskCheckGeometryResults::goCheck()
|
||||
{
|
||||
Gui::WaitCursor wc;
|
||||
int selectedCount(0), checkedCount(0), invalidShapes(0);
|
||||
std::vector<Gui::SelectionSingleton::SelObj> selection = Gui::Selection().getSelection();
|
||||
std::vector<Gui::SelectionSingleton::SelObj>::iterator it;
|
||||
ResultEntry *theRoot = new ResultEntry();
|
||||
|
||||
Handle(Message_ProgressIndicator) theProgress = new BOPProgressIndicator(tr("Check geometry"), Gui::getMainWindow());
|
||||
theProgress->NewScope("BOP check...");
|
||||
#if OCC_VERSION_HEX >= 0x060900
|
||||
theProgress->Show();
|
||||
#endif
|
||||
|
||||
selectedCount = static_cast<int>(selection.size());
|
||||
for (it = selection.begin(); it != selection.end(); ++it)
|
||||
{
|
||||
Part::Feature *feature = dynamic_cast<Part::Feature *>((*it).pObject);
|
||||
if (!feature)
|
||||
continue;
|
||||
currentSeparator = Gui::Application::Instance->activeDocument()->getViewProvider(feature)->getRoot();
|
||||
if (!currentSeparator)
|
||||
continue;
|
||||
TopoDS_Shape shape = feature->Shape.getValue();
|
||||
QString baseName;
|
||||
QTextStream baseStream(&baseName);
|
||||
baseStream << (*it).DocName;
|
||||
baseStream << "." << (*it).FeatName;
|
||||
if (strlen((*it).SubName) > 0)
|
||||
{
|
||||
shape = feature->Shape.getShape().getSubShape((*it).SubName);
|
||||
baseStream << "." << (*it).SubName;
|
||||
}
|
||||
|
||||
for(const auto &sel : Gui::Selection().getSelection()) {
|
||||
selectedCount++;
|
||||
TopoDS_Shape shape = Part::Feature::getShape(sel.pObject,sel.SubName,true);
|
||||
if (shape.IsNull())
|
||||
continue;
|
||||
currentSeparator = Gui::Application::Instance->getViewProvider(sel.pObject)->getRoot();
|
||||
if (!currentSeparator)
|
||||
continue;
|
||||
QString baseName;
|
||||
QTextStream baseStream(&baseName);
|
||||
baseStream << sel.DocName;
|
||||
baseStream << "." << sel.FeatName;
|
||||
checkedCount++;
|
||||
checkedMap.Clear();
|
||||
|
||||
@@ -483,7 +470,7 @@ void TaskCheckGeometryResults::goCheck()
|
||||
group->SetBool("RunBOPCheck", runSignal);
|
||||
if (runSignal) {
|
||||
std::string label = "Checking ";
|
||||
label += feature->Label.getStrValue();
|
||||
label += sel.pObject->Label.getStrValue();
|
||||
label += "...";
|
||||
theProgress->NewScope(label.c_str());
|
||||
invalidShapes += goBOPSingleCheck(shape, theRoot, baseName, theProgress);
|
||||
|
||||
@@ -78,7 +78,30 @@
|
||||
|
||||
#include "TaskDimension.h"
|
||||
|
||||
bool PartGui::getShapeFromStrings(TopoDS_Shape &shapeOut, const std::string &doc, const std::string &object, const std::string &sub)
|
||||
static bool _MeasureInfoInited;
|
||||
|
||||
static void slotDeleteDocument(const App::Document &doc);
|
||||
|
||||
struct MeasureInfo {
|
||||
PartGui::DimSelections sel1;
|
||||
PartGui::DimSelections sel2;
|
||||
bool linear;
|
||||
MeasureInfo(const PartGui::DimSelections &sel1, const PartGui::DimSelections &sel2, bool linear)
|
||||
:sel1(sel1),sel2(sel2),linear(linear)
|
||||
{
|
||||
if(!_MeasureInfoInited) {
|
||||
_MeasureInfoInited = true;
|
||||
App::GetApplication().signalDeleteDocument.connect(boost::bind(slotDeleteDocument, _1));
|
||||
}
|
||||
}
|
||||
};
|
||||
static std::map<std::string, std::list<MeasureInfo> > _Measures;
|
||||
|
||||
static void slotDeleteDocument(const App::Document &doc) {
|
||||
_Measures.erase(doc.getName());
|
||||
}
|
||||
|
||||
bool PartGui::getShapeFromStrings(TopoDS_Shape &shapeOut, const std::string &doc, const std::string &object, const std::string &sub, Base::Matrix4D *mat)
|
||||
{
|
||||
App::Document *docPointer = App::GetApplication().getDocument(doc.c_str());
|
||||
if (!docPointer)
|
||||
@@ -86,15 +109,7 @@ bool PartGui::getShapeFromStrings(TopoDS_Shape &shapeOut, const std::string &doc
|
||||
App::DocumentObject *objectPointer = docPointer->getObject(object.c_str());
|
||||
if (!objectPointer)
|
||||
return false;
|
||||
Part::Feature *feature = dynamic_cast<Part::Feature *>(objectPointer);
|
||||
if (!feature)
|
||||
return false;
|
||||
Base::Placement placement = feature->globalPlacement();
|
||||
Part::TopoShape topoShape = feature->Shape.getShape();
|
||||
topoShape.setPlacement(placement);
|
||||
shapeOut = topoShape.getShape();
|
||||
if (sub.size() > 0)
|
||||
shapeOut = topoShape.getSubShape(sub.c_str());
|
||||
shapeOut = Part::Feature::getShape(objectPointer,sub.c_str(),true,mat);
|
||||
if (shapeOut.IsNull())
|
||||
return false;
|
||||
return true;
|
||||
@@ -102,23 +117,26 @@ bool PartGui::getShapeFromStrings(TopoDS_Shape &shapeOut, const std::string &doc
|
||||
|
||||
bool PartGui::evaluateLinearPreSelection(TopoDS_Shape &shape1, TopoDS_Shape &shape2)
|
||||
{
|
||||
std::vector<Gui::SelectionSingleton::SelObj> selections = Gui::Selection().getSelection();
|
||||
std::vector<Gui::SelectionSingleton::SelObj> selections = Gui::Selection().getSelection(0,false);
|
||||
if (selections.size() != 2)
|
||||
return false;
|
||||
std::vector<Gui::SelectionSingleton::SelObj>::iterator it;
|
||||
std::vector<TopoDS_Shape> shapes;
|
||||
|
||||
DimSelections sels[2];
|
||||
|
||||
int i=0;
|
||||
for (it = selections.begin(); it != selections.end(); ++it)
|
||||
{
|
||||
Part::Feature *feature = dynamic_cast<Part::Feature *>((*it).pObject);
|
||||
if (!feature)
|
||||
break;
|
||||
TopoDS_Shape shape = feature->Shape.getValue();
|
||||
if (strlen((*it).SubName) > 0)
|
||||
shape = feature->Shape.getShape().getSubShape((*it).SubName);
|
||||
TopoDS_Shape shape = Part::Feature::getShape(it->pObject,it->SubName,true);
|
||||
if (shape.IsNull())
|
||||
break;
|
||||
shapes.push_back(shape);
|
||||
sels[i].selections.push_back(DimSelections::DimSelection());
|
||||
auto &sel = sels[i].selections[0];
|
||||
++i;
|
||||
sel.documentName = it->DocName;
|
||||
sel.objectName = it->FeatName;
|
||||
sel.subObjectName = it->SubName;
|
||||
}
|
||||
|
||||
if (shapes.size() != 2)
|
||||
@@ -126,7 +144,10 @@ bool PartGui::evaluateLinearPreSelection(TopoDS_Shape &shape1, TopoDS_Shape &sha
|
||||
|
||||
shape1 = shapes.front();
|
||||
shape2 = shapes.back();
|
||||
|
||||
|
||||
auto doc = App::GetApplication().getActiveDocument();
|
||||
if(doc)
|
||||
_Measures[doc->getName()].emplace_back(sels[0],sels[1],true);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -266,6 +287,7 @@ void PartGui::eraseAllDimensions()
|
||||
Gui::Document *doc = Gui::Application::Instance->activeDocument();
|
||||
if (!doc)
|
||||
return;
|
||||
_Measures.erase(doc->getDocument()->getName());
|
||||
Gui::View3DInventor *view = dynamic_cast<Gui::View3DInventor*>(doc->getActiveView());
|
||||
if (!view)
|
||||
return;
|
||||
@@ -275,6 +297,24 @@ void PartGui::eraseAllDimensions()
|
||||
viewer->eraseAllDimensions();
|
||||
}
|
||||
|
||||
void PartGui::refreshDimensions() {
|
||||
auto doc = App::GetApplication().getActiveDocument();
|
||||
if(!doc)
|
||||
return;
|
||||
auto it = _Measures.find(doc->getName());
|
||||
if(it == _Measures.end())
|
||||
return;
|
||||
std::list<MeasureInfo> measures;
|
||||
measures.swap(it->second);
|
||||
eraseAllDimensions();
|
||||
for(auto &info : measures) {
|
||||
if(info.linear)
|
||||
PartGui::TaskMeasureLinear::buildDimension(info.sel1,info.sel2);
|
||||
else
|
||||
PartGui::TaskMeasureAngular::buildDimension(info.sel1,info.sel2);
|
||||
}
|
||||
}
|
||||
|
||||
void PartGui::toggle3d()
|
||||
{
|
||||
ParameterGrp::handle group = App::GetApplication().GetUserParameter().
|
||||
@@ -470,7 +510,9 @@ void PartGui::DimensionLinear::setupDimension()
|
||||
textSep->addChild(rTrans);
|
||||
}
|
||||
|
||||
PartGui::TaskMeasureLinear::TaskMeasureLinear(): selections1(), selections2(), buttonSelectedIndex(0)
|
||||
PartGui::TaskMeasureLinear::TaskMeasureLinear()
|
||||
: Gui::SelectionObserver(true,false)
|
||||
, selections1(), selections2(), buttonSelectedIndex(0)
|
||||
{
|
||||
setUpGui();
|
||||
}
|
||||
@@ -535,14 +577,18 @@ void PartGui::TaskMeasureLinear::selectionClearDelayedSlot()
|
||||
this->blockConnection(false);
|
||||
}
|
||||
|
||||
void PartGui::TaskMeasureLinear::buildDimension()
|
||||
void PartGui::TaskMeasureLinear::buildDimension() {
|
||||
buildDimension(selections1,selections2);
|
||||
}
|
||||
|
||||
void PartGui::TaskMeasureLinear::buildDimension(const DimSelections &sel1, const DimSelections &sel2)
|
||||
{
|
||||
if(selections1.selections.size() != 1 || selections2.selections.size() != 1)
|
||||
if(sel1.selections.size() != 1 || sel2.selections.size() != 1)
|
||||
return;
|
||||
|
||||
DimSelections::DimSelection current1 = selections1.selections.at(0);
|
||||
DimSelections::DimSelection current2 = selections2.selections.at(0);
|
||||
|
||||
|
||||
DimSelections::DimSelection current1 = sel1.selections.at(0);
|
||||
DimSelections::DimSelection current2 = sel2.selections.at(0);
|
||||
|
||||
TopoDS_Shape shape1, shape2;
|
||||
if (!getShapeFromStrings(shape1, current1.documentName, current1.objectName, current1.subObjectName))
|
||||
{
|
||||
@@ -554,6 +600,9 @@ void PartGui::TaskMeasureLinear::buildDimension()
|
||||
Base::Console().Message("\nFailed to get shape\n\n");
|
||||
return;
|
||||
}
|
||||
auto doc = App::GetApplication().getActiveDocument();
|
||||
if(doc)
|
||||
_Measures[doc->getName()].emplace_back(sel1,sel2,true);
|
||||
goDimensionLinearNoTask(shape1, shape2);
|
||||
}
|
||||
|
||||
@@ -771,25 +820,41 @@ void PartGui::goDimensionAngularRoot()
|
||||
|
||||
bool PartGui::evaluateAngularPreSelection(VectorAdapter &vector1Out, VectorAdapter &vector2Out)
|
||||
{
|
||||
std::vector<Gui::SelectionSingleton::SelObj> selections = Gui::Selection().getSelection();
|
||||
std::vector<Gui::SelectionSingleton::SelObj> selections = Gui::Selection().getSelection(0,false);
|
||||
if (selections.size() > 4 || selections.size() < 2)
|
||||
return false;
|
||||
std::vector<Gui::SelectionSingleton::SelObj>::iterator it;
|
||||
std::vector<VectorAdapter> adapters;
|
||||
std::vector<DimSelections> sels;
|
||||
TopoDS_Vertex lastVertex;
|
||||
for (it = selections.begin(); it != selections.end(); ++it)
|
||||
{
|
||||
Part::Feature *feature = dynamic_cast<Part::Feature *>((*it).pObject);
|
||||
if (!feature)
|
||||
break;
|
||||
TopoDS_Shape shape = feature->Shape.getValue();
|
||||
if (strlen((*it).SubName) > 0)
|
||||
shape = feature->Shape.getShape().getSubShape((*it).SubName);
|
||||
Base::Matrix4D mat;
|
||||
TopoDS_Shape shape = Part::Feature::getShape(it->pObject,it->SubName,true,&mat);
|
||||
if (shape.IsNull())
|
||||
break;
|
||||
|
||||
mat.inverse();
|
||||
|
||||
if (shape.ShapeType() == TopAbs_VERTEX)
|
||||
{
|
||||
if(sels.empty() ||
|
||||
sels.back().selections.back().shapeType!=DimSelections::Vertex ||
|
||||
sels.back().selections.size()==1)
|
||||
{
|
||||
sels.push_back(PartGui::DimSelections());
|
||||
}
|
||||
sels.back().selections.push_back(DimSelections::DimSelection());
|
||||
auto &sel = sels.back().selections.back();
|
||||
sel.documentName = it->DocName;
|
||||
sel.objectName = it->FeatName;
|
||||
sel.subObjectName = it->SubName;
|
||||
sel.shapeType = DimSelections::Vertex;
|
||||
Base::Vector3d v(it->x,it->y,it->z);
|
||||
v = mat*v;
|
||||
sel.x = v.x;
|
||||
sel.y = v.y;
|
||||
sel.z = v.z;
|
||||
|
||||
TopoDS_Vertex currentVertex = TopoDS::Vertex(shape);
|
||||
if (!lastVertex.IsNull())
|
||||
{
|
||||
@@ -815,8 +880,21 @@ bool PartGui::evaluateAngularPreSelection(VectorAdapter &vector1Out, VectorAdapt
|
||||
continue;
|
||||
}
|
||||
|
||||
sels.push_back(PartGui::DimSelections());
|
||||
sels.back().selections.push_back(DimSelections::DimSelection());
|
||||
auto &sel = sels.back().selections.back();
|
||||
sel.documentName = it->DocName;
|
||||
sel.objectName = it->FeatName;
|
||||
sel.subObjectName = it->SubName;
|
||||
Base::Vector3d v(it->x,it->y,it->z);
|
||||
v = mat*v;
|
||||
sel.x = v.x;
|
||||
sel.y = v.y;
|
||||
sel.z = v.z;
|
||||
|
||||
if (shape.ShapeType() == TopAbs_EDGE)
|
||||
{
|
||||
sel.shapeType = DimSelections::Edge;
|
||||
TopoDS_Edge edge = TopoDS::Edge(shape);
|
||||
// make edge orientation so that end of edge closest to pick is head of vector.
|
||||
gp_Vec firstPoint = PartGui::convert(TopExp::FirstVertex(edge, Standard_True));
|
||||
@@ -836,6 +914,7 @@ bool PartGui::evaluateAngularPreSelection(VectorAdapter &vector1Out, VectorAdapt
|
||||
|
||||
if (shape.ShapeType() == TopAbs_FACE)
|
||||
{
|
||||
sel.shapeType = DimSelections::Face;
|
||||
TopoDS_Face face = TopoDS::Face(shape);
|
||||
adapters.push_back(VectorAdapter(face, pickPoint));
|
||||
continue;
|
||||
@@ -857,6 +936,9 @@ bool PartGui::evaluateAngularPreSelection(VectorAdapter &vector1Out, VectorAdapt
|
||||
return false;
|
||||
}
|
||||
|
||||
auto doc = App::GetApplication().getActiveDocument();
|
||||
if(doc)
|
||||
_Measures[doc->getName()].emplace_back(sels[0],sels[1],false);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1401,7 +1483,9 @@ void PartGui::DimensionControl::clearAllSlot(bool)
|
||||
PartGui::eraseAllDimensions();
|
||||
}
|
||||
|
||||
PartGui::TaskMeasureAngular::TaskMeasureAngular(): selections1(), selections2(), buttonSelectedIndex(0)
|
||||
PartGui::TaskMeasureAngular::TaskMeasureAngular()
|
||||
: Gui::SelectionObserver(true,false)
|
||||
, selections1(), selections2(), buttonSelectedIndex(0)
|
||||
{
|
||||
setUpGui();
|
||||
}
|
||||
@@ -1414,16 +1498,21 @@ PartGui::TaskMeasureAngular::~TaskMeasureAngular()
|
||||
void PartGui::TaskMeasureAngular::onSelectionChanged(const Gui::SelectionChanges& msg)
|
||||
{
|
||||
TopoDS_Shape shape;
|
||||
if (!getShapeFromStrings(shape, std::string(msg.pDocName), std::string(msg.pObjectName), std::string(msg.pSubName)))
|
||||
Base::Matrix4D mat;
|
||||
if (!getShapeFromStrings(shape, std::string(msg.pDocName),
|
||||
std::string(msg.pObjectName), std::string(msg.pSubName),&mat))
|
||||
return;
|
||||
mat.inverse();
|
||||
DimSelections::DimSelection newSelection;
|
||||
newSelection.documentName = msg.pDocName;
|
||||
newSelection.objectName = msg.pObjectName;
|
||||
newSelection.subObjectName = msg.pSubName;
|
||||
newSelection.x = msg.x;
|
||||
newSelection.y = msg.y;
|
||||
newSelection.z = msg.z;
|
||||
gp_Vec pickPoint(msg.x, msg.y, msg.z);
|
||||
Base::Vector3d v(msg.x,msg.y,msg.z);
|
||||
v = mat*v;
|
||||
newSelection.x = v.x;
|
||||
newSelection.y = v.y;
|
||||
newSelection.z = v.z;
|
||||
if (buttonSelectedIndex == 0)
|
||||
{
|
||||
if (msg.Type == Gui::SelectionChanges::AddSelection)
|
||||
@@ -1544,8 +1633,9 @@ void PartGui::TaskMeasureAngular::selectionClearDelayedSlot()
|
||||
this->blockConnection(false);
|
||||
}
|
||||
|
||||
PartGui::VectorAdapter PartGui::TaskMeasureAngular::buildAdapter(const PartGui::DimSelections& selection) const
|
||||
PartGui::VectorAdapter PartGui::TaskMeasureAngular::buildAdapter(const PartGui::DimSelections& selection)
|
||||
{
|
||||
Base::Matrix4D mat;
|
||||
assert(selection.selections.size() > 0 && selection.selections.size() < 3);
|
||||
if (selection.selections.size() == 1)
|
||||
{
|
||||
@@ -1553,7 +1643,7 @@ PartGui::VectorAdapter PartGui::TaskMeasureAngular::buildAdapter(const PartGui::
|
||||
if (current.shapeType == DimSelections::Edge)
|
||||
{
|
||||
TopoDS_Shape edgeShape;
|
||||
if (!getShapeFromStrings(edgeShape, current.documentName, current.objectName, current.subObjectName))
|
||||
if (!getShapeFromStrings(edgeShape, current.documentName, current.objectName, current.subObjectName,&mat))
|
||||
return VectorAdapter();
|
||||
TopoDS_Edge edge = TopoDS::Edge(edgeShape);
|
||||
// make edge orientation so that end of edge closest to pick is head of vector.
|
||||
@@ -1563,7 +1653,9 @@ PartGui::VectorAdapter PartGui::TaskMeasureAngular::buildAdapter(const PartGui::
|
||||
return VectorAdapter();
|
||||
gp_Vec firstPoint = PartGui::convert(firstVertex);
|
||||
gp_Vec lastPoint = PartGui::convert(lastVertex);
|
||||
gp_Vec pickPoint(current.x, current.y, current.z);
|
||||
Base::Vector3d v(current.x,current.y,current.z);
|
||||
v = mat*v;
|
||||
gp_Vec pickPoint(v.x, v.y, v.z);
|
||||
double firstDistance = (firstPoint - pickPoint).Magnitude();
|
||||
double lastDistance = (lastPoint - pickPoint).Magnitude();
|
||||
if (lastDistance > firstDistance)
|
||||
@@ -1578,11 +1670,13 @@ PartGui::VectorAdapter PartGui::TaskMeasureAngular::buildAdapter(const PartGui::
|
||||
if (current.shapeType == DimSelections::Face)
|
||||
{
|
||||
TopoDS_Shape faceShape;
|
||||
if (!getShapeFromStrings(faceShape, current.documentName, current.objectName, current.subObjectName))
|
||||
if (!getShapeFromStrings(faceShape, current.documentName, current.objectName, current.subObjectName,&mat))
|
||||
return VectorAdapter();
|
||||
|
||||
TopoDS_Face face = TopoDS::Face(faceShape);
|
||||
gp_Vec pickPoint(current.x, current.y, current.z);
|
||||
Base::Vector3d v(current.x,current.y,current.z);
|
||||
v = mat*v;
|
||||
gp_Vec pickPoint(v.x, v.y, v.z);
|
||||
return VectorAdapter(face, pickPoint);
|
||||
}
|
||||
}
|
||||
@@ -1604,17 +1698,24 @@ PartGui::VectorAdapter PartGui::TaskMeasureAngular::buildAdapter(const PartGui::
|
||||
return VectorAdapter(PartGui::convert(vertex2), PartGui::convert(vertex1));
|
||||
}
|
||||
|
||||
void PartGui::TaskMeasureAngular::buildDimension()
|
||||
void PartGui::TaskMeasureAngular::buildDimension() {
|
||||
buildDimension(selections1,selections2);
|
||||
}
|
||||
|
||||
void PartGui::TaskMeasureAngular::buildDimension(const DimSelections &sel1, const DimSelections &sel2)
|
||||
{
|
||||
//build adapters.
|
||||
VectorAdapter adapt1 = buildAdapter(selections1);
|
||||
VectorAdapter adapt2 = buildAdapter(selections2);
|
||||
|
||||
VectorAdapter adapt1 = buildAdapter(sel1);
|
||||
VectorAdapter adapt2 = buildAdapter(sel2);
|
||||
|
||||
if (!adapt1.isValid() || !adapt2.isValid())
|
||||
{
|
||||
Base::Console().Message("\ncouldn't build adapter\n\n");
|
||||
return;
|
||||
}
|
||||
auto doc = App::GetApplication().getActiveDocument();
|
||||
if(doc)
|
||||
_Measures[doc->getName()].emplace_back(sel1,sel2,false);
|
||||
goDimensionAngularNoTask(adapt1, adapt2);
|
||||
}
|
||||
|
||||
|
||||
@@ -38,6 +38,7 @@
|
||||
|
||||
#include <Gui/TaskView/TaskDialog.h>
|
||||
#include <Gui/TaskView/TaskView.h>
|
||||
#include <Base/Matrix.h>
|
||||
|
||||
class TopoDS_Shape;
|
||||
class TopoDS_Face;
|
||||
@@ -61,7 +62,7 @@ namespace PartGui
|
||||
* @param sub sub-object name to search.
|
||||
* @return signal if the search was successful.
|
||||
*/
|
||||
bool getShapeFromStrings(TopoDS_Shape &shapeOut, const std::string &doc, const std::string &object, const std::string &sub);
|
||||
bool getShapeFromStrings(TopoDS_Shape &shapeOut, const std::string &doc, const std::string &object, const std::string &sub, Base::Matrix4D *mat=0);
|
||||
/*!examine pre selection
|
||||
* @param shape1 first shape in current selection
|
||||
* @param shape2 second shape in current selection
|
||||
@@ -95,6 +96,8 @@ namespace PartGui
|
||||
SoNode* createLinearDimension(const gp_Pnt &point1, const gp_Pnt &point2, const SbColor &color);
|
||||
/*!erases all the dimensions in the viewer.*/
|
||||
void eraseAllDimensions();
|
||||
/*!refresh all the dimensions in the viewer.*/
|
||||
void refreshDimensions();
|
||||
/*!toggles the display status of the 3d dimensions*/
|
||||
void toggle3d();
|
||||
/*!toggles the display status of the delta dimensions*/
|
||||
@@ -259,6 +262,9 @@ protected Q_SLOTS:
|
||||
void clearAllSlot(bool);
|
||||
void selectionClearDelayedSlot();
|
||||
|
||||
public:
|
||||
static void buildDimension(const DimSelections &sel1, const DimSelections &sel2);
|
||||
|
||||
private:
|
||||
void setUpGui();
|
||||
void buildDimension();
|
||||
@@ -335,15 +341,18 @@ protected Q_SLOTS:
|
||||
void clearAllSlot(bool);
|
||||
void selectionClearDelayedSlot();
|
||||
|
||||
public:
|
||||
static void buildDimension(const DimSelections &sel1, const DimSelections &sel2);
|
||||
|
||||
private:
|
||||
void setUpGui();
|
||||
void buildDimension();
|
||||
void setUpGui();
|
||||
void clearSelection();
|
||||
DimSelections selections1;
|
||||
DimSelections selections2;
|
||||
uint buttonSelectedIndex;
|
||||
SteppedSelection *stepped;
|
||||
VectorAdapter buildAdapter(const DimSelections &selection) const;
|
||||
static VectorAdapter buildAdapter(const DimSelections &selection);
|
||||
};
|
||||
|
||||
/*!start of the measure angular command*/
|
||||
|
||||
@@ -178,21 +178,14 @@ void OffsetWidget::on_updateView_toggled(bool on)
|
||||
|
||||
bool OffsetWidget::accept()
|
||||
{
|
||||
std::string name = d->offset->getNameInDocument();
|
||||
|
||||
try {
|
||||
double offsetValue = d->ui.spinOffset->value().getValue();
|
||||
Gui::Command::doCommand(Gui::Command::Doc,"App.ActiveDocument.%s.Value = %f",
|
||||
name.c_str(),offsetValue);
|
||||
FCMD_OBJ_CMD2("Value = %f", d->offset,offsetValue);
|
||||
d->ui.spinOffset->apply();
|
||||
Gui::Command::doCommand(Gui::Command::Doc,"App.ActiveDocument.%s.Mode = %i",
|
||||
name.c_str(),d->ui.modeType->currentIndex());
|
||||
Gui::Command::doCommand(Gui::Command::Doc,"App.ActiveDocument.%s.Join = %i",
|
||||
name.c_str(),d->ui.joinType->currentIndex());
|
||||
Gui::Command::doCommand(Gui::Command::Doc,"App.ActiveDocument.%s.Intersection = %s",
|
||||
name.c_str(),d->ui.intersection->isChecked() ? "True" : "False");
|
||||
Gui::Command::doCommand(Gui::Command::Doc,"App.ActiveDocument.%s.SelfIntersection = %s",
|
||||
name.c_str(),d->ui.selfIntersection->isChecked() ? "True" : "False");
|
||||
FCMD_OBJ_CMD2("Mode = %i", d->offset,d->ui.modeType->currentIndex());
|
||||
FCMD_OBJ_CMD2("Join = %i", d->offset,d->ui.joinType->currentIndex());
|
||||
FCMD_OBJ_CMD2("Intersection = %s", d->offset,d->ui.intersection->isChecked() ? "True" : "False");
|
||||
FCMD_OBJ_CMD2("SelfIntersection = %s", d->offset,d->ui.selfIntersection->isChecked() ? "True" : "False");
|
||||
|
||||
Gui::Command::doCommand(Gui::Command::Doc,"App.ActiveDocument.recompute()");
|
||||
if (!d->offset->isValid())
|
||||
|
||||
@@ -225,22 +225,17 @@ bool ThicknessWidget::accept()
|
||||
if (d->loop.isRunning())
|
||||
return false;
|
||||
|
||||
std::string name = d->thickness->getNameInDocument();
|
||||
try {
|
||||
if (!d->selection.empty()) {
|
||||
Gui::Command::doCommand(Gui::Command::Doc,"App.ActiveDocument.%s.Faces = %s",
|
||||
name.c_str(),d->selection.c_str());
|
||||
FCMD_OBJ_CMD2("Faces = %s", d->thickness,d->selection.c_str());
|
||||
}
|
||||
Gui::Command::doCommand(Gui::Command::Doc,"App.ActiveDocument.%s.Value = %f",
|
||||
name.c_str(),d->ui.spinOffset->value().getValue());
|
||||
Gui::Command::doCommand(Gui::Command::Doc,"App.ActiveDocument.%s.Mode = %i",
|
||||
name.c_str(),d->ui.modeType->currentIndex());
|
||||
Gui::Command::doCommand(Gui::Command::Doc,"App.ActiveDocument.%s.Join = %i",
|
||||
name.c_str(),d->ui.joinType->currentIndex());
|
||||
Gui::Command::doCommand(Gui::Command::Doc,"App.ActiveDocument.%s.Intersection = %s",
|
||||
name.c_str(),d->ui.intersection->isChecked() ? "True" : "False");
|
||||
Gui::Command::doCommand(Gui::Command::Doc,"App.ActiveDocument.%s.SelfIntersection = %s",
|
||||
name.c_str(),d->ui.selfIntersection->isChecked() ? "True" : "False");
|
||||
FCMD_OBJ_CMD2("Value = %f", d->thickness,d->ui.spinOffset->value().getValue());
|
||||
FCMD_OBJ_CMD2("Mode = %i", d->thickness,d->ui.modeType->currentIndex());
|
||||
FCMD_OBJ_CMD2("Join = %i", d->thickness,d->ui.joinType->currentIndex());
|
||||
FCMD_OBJ_CMD2("Intersection = %s",
|
||||
d->thickness,d->ui.intersection->isChecked() ? "True" : "False");
|
||||
FCMD_OBJ_CMD2("SelfIntersection = %s",
|
||||
d->thickness,d->ui.selfIntersection->isChecked() ? "True" : "False");
|
||||
|
||||
Gui::Command::doCommand(Gui::Command::Doc,"App.ActiveDocument.recompute()");
|
||||
if (!d->thickness->isValid())
|
||||
|
||||
@@ -28,6 +28,7 @@
|
||||
|
||||
#include <Base/Console.h>
|
||||
#include <Base/Exception.h>
|
||||
#include <App/Document.h>
|
||||
#include <Gui/Command.h>
|
||||
|
||||
#include <Mod/Part/App/PartFeature.h>
|
||||
@@ -54,8 +55,7 @@ bool ViewProviderPart::doubleClicked(void)
|
||||
Msg += this->pcObject->Label.getValue();
|
||||
try {
|
||||
Gui::Command::openCommand(Msg.c_str());
|
||||
Gui::Command::doCommand(Gui::Command::Gui,"Gui.ActiveDocument.setEdit('%s',0)",
|
||||
this->pcObject->getNameInDocument());
|
||||
FCMD_SET_EDIT(pcObject);
|
||||
return true;
|
||||
}
|
||||
catch (const Base::Exception& e) {
|
||||
|
||||
@@ -34,6 +34,7 @@
|
||||
# include <Inventor/nodes/SoPickStyle.h>
|
||||
# include <Inventor/nodes/SoSeparator.h>
|
||||
# include <Inventor/nodes/SoVertexProperty.h>
|
||||
# include <Inventor/nodes/SoAnnotation.h>
|
||||
# include <cfloat>
|
||||
#endif
|
||||
|
||||
@@ -69,7 +70,7 @@ ViewProvider2DObject::ViewProvider2DObject()
|
||||
ADD_PROPERTY_TYPE(TightGrid,(true),"Grid",(App::PropertyType)(App::Prop_None),"Switch the tight grid mode on/off");
|
||||
ADD_PROPERTY_TYPE(GridSnap,(false),"Grid",(App::PropertyType)(App::Prop_None),"Switch the grid snap on/off");
|
||||
|
||||
GridRoot = new SoSeparator();
|
||||
GridRoot = new SoAnnotation();
|
||||
GridRoot->ref();
|
||||
GridRoot->setName("GridRoot");
|
||||
MinX = MinY = -100;
|
||||
@@ -150,9 +151,18 @@ SoSeparator* ViewProvider2DObject::createGrid(void)
|
||||
carpet->vertexProperty = vts;
|
||||
parent->addChild(carpet);*/
|
||||
|
||||
// It seems that SoDepthBuffer will mess up with other object's
|
||||
// pre-selection highlight. No idea why the setting can leak out of a
|
||||
// separator.
|
||||
//
|
||||
// What's the purpose of using SoDepthBuffer here anyway? If the intension
|
||||
// is to render grid always on top, shouldn't it be better to use
|
||||
// SoAnnotation?
|
||||
#if 0
|
||||
SoDepthBuffer *depth = new SoDepthBuffer;
|
||||
depth->function = SoDepthBuffer::ALWAYS;
|
||||
parent->addChild(depth);
|
||||
#endif
|
||||
|
||||
// gridlines
|
||||
mycolor = new SoBaseColor;
|
||||
|
||||
@@ -88,8 +88,10 @@ void ViewProviderBoolean::updateData(const App::Property* prop)
|
||||
Part::Boolean* objBool = dynamic_cast<Part::Boolean*>(getObject());
|
||||
if (!objBool)
|
||||
return;
|
||||
Part::Feature* objBase = dynamic_cast<Part::Feature*>(objBool->Base.getValue());
|
||||
Part::Feature* objTool = dynamic_cast<Part::Feature*>(objBool->Tool.getValue());
|
||||
Part::Feature* objBase = dynamic_cast<Part::Feature*>(
|
||||
Part::Feature::getShapeOwner(objBool->Base.getValue()));
|
||||
Part::Feature* objTool = dynamic_cast<Part::Feature*>(
|
||||
Part::Feature::getShapeOwner(objBool->Tool.getValue()));
|
||||
if (objBase && objTool) {
|
||||
const TopoDS_Shape& baseShape = objBase->Shape.getValue();
|
||||
const TopoDS_Shape& toolShape = objTool->Shape.getValue();
|
||||
@@ -152,18 +154,6 @@ bool ViewProviderBoolean::onDelete(const std::vector<std::string> &)
|
||||
return true;
|
||||
}
|
||||
|
||||
void ViewProviderBoolean::replaceObject(App::DocumentObject* oldValue, App::DocumentObject* newValue)
|
||||
{
|
||||
Part::Boolean* pBool = static_cast<Part::Boolean*>(getObject());
|
||||
if (oldValue == pBool->Base.getValue()) {
|
||||
pBool->Base.setValue(newValue);
|
||||
}
|
||||
else if (oldValue == pBool->Tool.getValue()) {
|
||||
pBool->Tool.setValue(newValue);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
PROPERTY_SOURCE(PartGui::ViewProviderMultiFuse,PartGui::ViewProviderPart)
|
||||
|
||||
ViewProviderMultiFuse::ViewProviderMultiFuse()
|
||||
@@ -204,7 +194,7 @@ void ViewProviderMultiFuse::updateData(const App::Property* prop)
|
||||
|
||||
int index=0;
|
||||
for (std::vector<App::DocumentObject*>::iterator it = sources.begin(); it != sources.end(); ++it, ++index) {
|
||||
Part::Feature* objBase = dynamic_cast<Part::Feature*>(*it);
|
||||
Part::Feature* objBase = dynamic_cast<Part::Feature*>(Part::Feature::getShapeOwner(*it));
|
||||
if (!objBase)
|
||||
continue;
|
||||
const TopoDS_Shape& baseShape = objBase->Shape.getValue();
|
||||
@@ -257,7 +247,9 @@ bool ViewProviderMultiFuse::canDragObjects() const
|
||||
|
||||
bool ViewProviderMultiFuse::canDragObject(App::DocumentObject* obj) const
|
||||
{
|
||||
return obj->getTypeId().isDerivedFrom(Part::Feature::getClassTypeId());
|
||||
(void)obj;
|
||||
// return Part::Feature::hasShapeOwner(obj);
|
||||
return true;
|
||||
}
|
||||
|
||||
void ViewProviderMultiFuse::dragObject(App::DocumentObject* obj)
|
||||
@@ -280,7 +272,9 @@ bool ViewProviderMultiFuse::canDropObjects() const
|
||||
|
||||
bool ViewProviderMultiFuse::canDropObject(App::DocumentObject* obj) const
|
||||
{
|
||||
return obj->getTypeId().isDerivedFrom(Part::Feature::getClassTypeId());
|
||||
(void)obj;
|
||||
// return Part::Feature::hasShapeOwner(obj);
|
||||
return true;
|
||||
}
|
||||
|
||||
void ViewProviderMultiFuse::dropObject(App::DocumentObject* obj)
|
||||
@@ -291,14 +285,6 @@ void ViewProviderMultiFuse::dropObject(App::DocumentObject* obj)
|
||||
pBool->Shapes.setValues(pShapes);
|
||||
}
|
||||
|
||||
void ViewProviderMultiFuse::replaceObject(App::DocumentObject* oldValue, App::DocumentObject* newValue)
|
||||
{
|
||||
Part::MultiFuse* pBool = static_cast<Part::MultiFuse*>(getObject());
|
||||
std::vector<App::DocumentObject*> pShapes = pBool->Shapes.getValues();
|
||||
std::replace(pShapes.begin(), pShapes.end(), oldValue, newValue);
|
||||
pBool->Shapes.setValues(pShapes);
|
||||
}
|
||||
|
||||
PROPERTY_SOURCE(PartGui::ViewProviderMultiCommon,PartGui::ViewProviderPart)
|
||||
|
||||
ViewProviderMultiCommon::ViewProviderMultiCommon()
|
||||
@@ -339,7 +325,7 @@ void ViewProviderMultiCommon::updateData(const App::Property* prop)
|
||||
|
||||
int index=0;
|
||||
for (std::vector<App::DocumentObject*>::iterator it = sources.begin(); it != sources.end(); ++it, ++index) {
|
||||
Part::Feature* objBase = dynamic_cast<Part::Feature*>(*it);
|
||||
Part::Feature* objBase = dynamic_cast<Part::Feature*>(Part::Feature::getShapeOwner(*it));
|
||||
if (!objBase)
|
||||
continue;
|
||||
const TopoDS_Shape& baseShape = objBase->Shape.getValue();
|
||||
@@ -392,7 +378,9 @@ bool ViewProviderMultiCommon::canDragObjects() const
|
||||
|
||||
bool ViewProviderMultiCommon::canDragObject(App::DocumentObject* obj) const
|
||||
{
|
||||
return obj->getTypeId().isDerivedFrom(Part::Feature::getClassTypeId());
|
||||
(void)obj;
|
||||
// return Part::Feature::hasShapeOwner(obj);
|
||||
return true;
|
||||
}
|
||||
|
||||
void ViewProviderMultiCommon::dragObject(App::DocumentObject* obj)
|
||||
@@ -415,7 +403,9 @@ bool ViewProviderMultiCommon::canDropObjects() const
|
||||
|
||||
bool ViewProviderMultiCommon::canDropObject(App::DocumentObject* obj) const
|
||||
{
|
||||
return obj->getTypeId().isDerivedFrom(Part::Feature::getClassTypeId());
|
||||
(void)obj;
|
||||
// return Part::Feature::hasShapeOwner(obj);
|
||||
return true;
|
||||
}
|
||||
|
||||
void ViewProviderMultiCommon::dropObject(App::DocumentObject* obj)
|
||||
@@ -426,10 +416,3 @@ void ViewProviderMultiCommon::dropObject(App::DocumentObject* obj)
|
||||
pBool->Shapes.setValues(pShapes);
|
||||
}
|
||||
|
||||
void ViewProviderMultiCommon::replaceObject(App::DocumentObject* oldValue, App::DocumentObject* newValue)
|
||||
{
|
||||
Part::MultiFuse* pBool = static_cast<Part::MultiFuse*>(getObject());
|
||||
std::vector<App::DocumentObject*> pShapes = pBool->Shapes.getValues();
|
||||
std::replace(pShapes.begin(), pShapes.end(), oldValue, newValue);
|
||||
pBool->Shapes.setValues(pShapes);
|
||||
}
|
||||
|
||||
@@ -44,7 +44,6 @@ public:
|
||||
QIcon getIcon(void) const;
|
||||
void updateData(const App::Property*);
|
||||
bool onDelete(const std::vector<std::string> &);
|
||||
virtual void replaceObject(App::DocumentObject*, App::DocumentObject*);
|
||||
};
|
||||
|
||||
/// ViewProvider for the MultiFuse feature
|
||||
@@ -71,8 +70,6 @@ public:
|
||||
bool canDropObjects() const;
|
||||
bool canDropObject(App::DocumentObject*) const;
|
||||
void dropObject(App::DocumentObject*);
|
||||
/** Replace an object to the view provider by drag and drop */
|
||||
virtual void replaceObject(App::DocumentObject*, App::DocumentObject*);
|
||||
};
|
||||
|
||||
/// ViewProvider for the MultiFuse feature
|
||||
@@ -99,8 +96,6 @@ public:
|
||||
bool canDropObjects() const;
|
||||
bool canDropObject(App::DocumentObject*) const;
|
||||
void dropObject(App::DocumentObject*);
|
||||
/** Replace an object to the view provider by drag and drop */
|
||||
virtual void replaceObject(App::DocumentObject*, App::DocumentObject*);
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -102,7 +102,7 @@ void ViewProviderCompound::updateData(const App::Property* prop)
|
||||
|
||||
int index=0;
|
||||
for (std::vector<App::DocumentObject*>::iterator it = sources.begin(); it != sources.end(); ++it, ++index) {
|
||||
Part::Feature* objBase = dynamic_cast<Part::Feature*>(*it);
|
||||
Part::Feature* objBase = dynamic_cast<Part::Feature*>(Part::Feature::getShapeOwner(*it));
|
||||
if (!objBase)
|
||||
continue;
|
||||
|
||||
@@ -174,10 +174,3 @@ void ViewProviderCompound::dropObject(App::DocumentObject* obj)
|
||||
pComp->Links.setValues(pShapes);
|
||||
}
|
||||
|
||||
void ViewProviderCompound::replaceObject(App::DocumentObject* oldValue, App::DocumentObject* newValue)
|
||||
{
|
||||
Part::Compound* pBool = static_cast<Part::Compound*>(getObject());
|
||||
std::vector<App::DocumentObject*> pShapes = pBool->Links.getValues();
|
||||
std::replace(pShapes.begin(), pShapes.end(), oldValue, newValue);
|
||||
pBool->Links.setValues(pShapes);
|
||||
}
|
||||
|
||||
@@ -48,8 +48,6 @@ public:
|
||||
bool canDropObjects() const;
|
||||
bool canDropObject(App::DocumentObject*) const;
|
||||
void dropObject(App::DocumentObject*);
|
||||
/** Replace an object to the view provider by drag and drop */
|
||||
virtual void replaceObject(App::DocumentObject*, App::DocumentObject*);
|
||||
|
||||
protected:
|
||||
void updateData(const App::Property*);
|
||||
|
||||
@@ -112,7 +112,9 @@
|
||||
#include <Gui/View3DInventorViewer.h>
|
||||
#include <Gui/Utilities.h>
|
||||
#include <Gui/Control.h>
|
||||
#include <Gui/ViewProviderLink.h>
|
||||
|
||||
#include <Gui/ViewParams.h>
|
||||
#include "ViewProviderExt.h"
|
||||
#include "SoBrepPointSet.h"
|
||||
#include "SoBrepEdgeSet.h"
|
||||
@@ -122,6 +124,7 @@
|
||||
#include <Mod/Part/App/PartFeature.h>
|
||||
#include <Mod/Part/App/PrimitiveFeature.h>
|
||||
|
||||
FC_LOG_LEVEL_INIT("Part", true, true);
|
||||
|
||||
using namespace PartGui;
|
||||
|
||||
@@ -228,14 +231,13 @@ const char* ViewProviderPartExt::DrawStyleEnums[]= {"Solid","Dashed","Dotted","D
|
||||
ViewProviderPartExt::ViewProviderPartExt()
|
||||
{
|
||||
VisualTouched = true;
|
||||
forceUpdateCount = 0;
|
||||
NormalsFromUV = true;
|
||||
|
||||
ParameterGrp::handle hView = App::GetApplication().GetParameterGroupByPath("User parameter:BaseApp/Preferences/View");
|
||||
|
||||
unsigned long lcol = hView->GetUnsigned("DefaultShapeLineColor",421075455UL); // dark grey (25,25,25)
|
||||
unsigned long lcol = Gui::ViewParams::instance()->getDefaultShapeLineColor(); // dark grey (25,25,25)
|
||||
float r,g,b;
|
||||
r = ((lcol >> 24) & 0xff) / 255.0; g = ((lcol >> 16) & 0xff) / 255.0; b = ((lcol >> 8) & 0xff) / 255.0;
|
||||
int lwidth = hView->GetInt("DefaultShapeLineWidth",2);
|
||||
int lwidth = Gui::ViewParams::instance()->getDefaultShapeLineWidth();
|
||||
|
||||
ParameterGrp::handle hPart = App::GetApplication().GetParameterGroupByPath
|
||||
("User parameter:BaseApp/Preferences/Mod/Part");
|
||||
@@ -346,16 +348,15 @@ void ViewProviderPartExt::onChanged(const App::Property* prop)
|
||||
// The lower limit of the deviation has been increased to avoid
|
||||
// to freeze the GUI
|
||||
// https://forum.freecadweb.org/viewtopic.php?f=3&t=24912&p=195613
|
||||
Part::Feature* feature = dynamic_cast<Part::Feature*>(pcObject);
|
||||
if (prop == &Deviation) {
|
||||
if(Visibility.getValue() && feature && !feature->Shape.getValue().IsNull())
|
||||
updateVisual(feature->Shape.getValue());
|
||||
if(isUpdateForced()||Visibility.getValue())
|
||||
updateVisual();
|
||||
else
|
||||
VisualTouched = true;
|
||||
}
|
||||
if (prop == &AngularDeflection) {
|
||||
if(Visibility.getValue() && feature && !feature->Shape.getValue().IsNull())
|
||||
updateVisual(feature->Shape.getValue());
|
||||
if(isUpdateForced()||Visibility.getValue())
|
||||
updateVisual();
|
||||
else
|
||||
VisualTouched = true;
|
||||
}
|
||||
@@ -456,8 +457,8 @@ void ViewProviderPartExt::onChanged(const App::Property* prop)
|
||||
}
|
||||
else {
|
||||
// if the object was invisible and has been changed, recreate the visual
|
||||
if (prop == &Visibility && Visibility.getValue() && VisualTouched) {
|
||||
updateVisual(feature->Shape.getValue());
|
||||
if (prop == &Visibility && (isUpdateForced() || Visibility.getValue()) && VisualTouched) {
|
||||
updateVisual();
|
||||
// The material has to be checked again (#0001736)
|
||||
onChanged(&DiffuseColor);
|
||||
}
|
||||
@@ -472,10 +473,19 @@ void ViewProviderPartExt::attach(App::DocumentObject *pcFeat)
|
||||
ViewProviderGeometryObject::attach(pcFeat);
|
||||
|
||||
// Workaround for #0000433, i.e. use SoSeparator instead of SoGroup
|
||||
SoGroup* pcNormalRoot = new SoSeparator();
|
||||
SoGroup* pcFlatRoot = new SoSeparator();
|
||||
SoGroup* pcWireframeRoot = new SoSeparator();
|
||||
SoGroup* pcPointsRoot = new SoSeparator();
|
||||
auto* pcNormalRoot = new SoSeparator();
|
||||
auto* pcFlatRoot = new SoSeparator();
|
||||
auto* pcWireframeRoot = new SoSeparator();
|
||||
auto* pcPointsRoot = new SoSeparator();
|
||||
auto* wireframe = new SoSeparator();
|
||||
|
||||
// Must turn off all intermediate render caching, and let pcRoot to handle
|
||||
// cache without interference.
|
||||
pcNormalRoot->renderCaching =
|
||||
pcFlatRoot->renderCaching =
|
||||
pcWireframeRoot->renderCaching =
|
||||
pcPointsRoot->renderCaching =
|
||||
wireframe->renderCaching = SoSeparator::OFF;
|
||||
|
||||
// enable two-side rendering
|
||||
pShapeHints->vertexOrdering = SoShapeHints::COUNTERCLOCKWISE;
|
||||
@@ -486,7 +496,6 @@ void ViewProviderPartExt::attach(App::DocumentObject *pcFeat)
|
||||
SoPolygonOffset* offset = new SoPolygonOffset();
|
||||
|
||||
// wireframe node
|
||||
SoSeparator* wireframe = new SoSeparator();
|
||||
wireframe->setName("Edge");
|
||||
wireframe->addChild(pcLineBind);
|
||||
wireframe->addChild(pcLineMaterial);
|
||||
@@ -494,10 +503,10 @@ void ViewProviderPartExt::attach(App::DocumentObject *pcFeat)
|
||||
wireframe->addChild(lineset);
|
||||
|
||||
// normal viewing with edges and points
|
||||
pcNormalRoot->addChild(pcPointsRoot);
|
||||
pcNormalRoot->addChild(wireframe);
|
||||
pcNormalRoot->addChild(offset);
|
||||
pcNormalRoot->addChild(pcFlatRoot);
|
||||
pcNormalRoot->addChild(pcPointsRoot);
|
||||
|
||||
// just faces with no edges or points
|
||||
pcFlatRoot->addChild(pShapeHints);
|
||||
@@ -616,7 +625,7 @@ std::vector<Base::Vector3d> ViewProviderPartExt::getModelPoints(const SoPickedPo
|
||||
try {
|
||||
std::vector<Base::Vector3d> pts;
|
||||
std::string element = this->getElement(pp->getDetail());
|
||||
const Part::TopoShape& shape = static_cast<Part::Feature*>(getObject())->Shape.getShape();
|
||||
const auto &shape = Part::Feature::getTopoShape(getObject());
|
||||
|
||||
TopoDS_Shape subShape = shape.getSubShape(element.c_str());
|
||||
|
||||
@@ -663,6 +672,9 @@ std::vector<Base::Vector3d> ViewProviderPartExt::getSelectionShape(const char* /
|
||||
|
||||
void ViewProviderPartExt::setHighlightedFaces(const std::vector<App::Color>& colors)
|
||||
{
|
||||
Gui::SoUpdateVBOAction action;
|
||||
action.apply(this->faceset);
|
||||
|
||||
int size = static_cast<int>(colors.size());
|
||||
if (size > 1 && size == this->faceset->partIndex.getNum()) {
|
||||
pcFaceBind->value = SoMaterialBinding::PER_PART;
|
||||
@@ -766,7 +778,7 @@ void ViewProviderPartExt::setHighlightedPoints(const std::vector<App::Color>& co
|
||||
{
|
||||
int size = static_cast<int>(colors.size());
|
||||
if (size > 1) {
|
||||
#ifdef FC_DEBUG
|
||||
#if 0
|
||||
int numPoints = coords->point.getNum() - nodeset->startIndex.getValue();
|
||||
if (numPoints != size) {
|
||||
SoDebugError::postWarning("ViewProviderPartExt::setHighlightedPoints",
|
||||
@@ -813,22 +825,19 @@ bool ViewProviderPartExt::loadParameter()
|
||||
|
||||
void ViewProviderPartExt::reload()
|
||||
{
|
||||
if (loadParameter()) {
|
||||
App::Property* shape = pcObject->getPropertyByName("Shape");
|
||||
if (shape) update(shape);
|
||||
}
|
||||
if (loadParameter())
|
||||
updateVisual();
|
||||
}
|
||||
|
||||
void ViewProviderPartExt::updateData(const App::Property* prop)
|
||||
{
|
||||
if (prop->getTypeId() == Part::PropertyPartShape::getClassTypeId()) {
|
||||
// get the shape to show
|
||||
const TopoDS_Shape &cShape = static_cast<const Part::PropertyPartShape*>(prop)->getValue();
|
||||
|
||||
const char *propName = prop?prop->getName():"";
|
||||
if(propName && (strcmp(propName,"Shape")==0 || strstr(propName,"Touched")!=0))
|
||||
{
|
||||
// calculate the visual only if visible
|
||||
if (Visibility.getValue())
|
||||
updateVisual(cShape);
|
||||
else
|
||||
if (isUpdateForced()||Visibility.getValue())
|
||||
updateVisual();
|
||||
else
|
||||
VisualTouched = true;
|
||||
|
||||
if (!VisualTouched) {
|
||||
@@ -878,7 +887,7 @@ void ViewProviderPartExt::unsetEdit(int ModNum)
|
||||
}
|
||||
}
|
||||
|
||||
void ViewProviderPartExt::updateVisual(const TopoDS_Shape& inputShape)
|
||||
void ViewProviderPartExt::updateVisual()
|
||||
{
|
||||
Gui::SoUpdateVBOAction action;
|
||||
action.apply(this->faceset);
|
||||
@@ -895,7 +904,7 @@ void ViewProviderPartExt::updateVisual(const TopoDS_Shape& inputShape)
|
||||
haction.apply(this->lineset);
|
||||
haction.apply(this->nodeset);
|
||||
|
||||
TopoDS_Shape cShape(inputShape);
|
||||
TopoDS_Shape cShape = Part::Feature::getShape(getObject());
|
||||
if (cShape.IsNull()) {
|
||||
coords ->point .setNum(0);
|
||||
norm ->vector .setNum(0);
|
||||
@@ -1214,7 +1223,7 @@ void ViewProviderPartExt::updateVisual(const TopoDS_Shape& inputShape)
|
||||
lineset ->coordIndex .finishEditing();
|
||||
}
|
||||
catch (...) {
|
||||
Base::Console().Error("Cannot compute Inventor representation for the shape of %s.\n",pcObject->getNameInDocument());
|
||||
FC_ERR("Cannot compute Inventor representation for the shape of " << pcObject->getFullName());
|
||||
}
|
||||
|
||||
# ifdef FC_DEBUG
|
||||
@@ -1224,3 +1233,13 @@ void ViewProviderPartExt::updateVisual(const TopoDS_Shape& inputShape)
|
||||
# endif
|
||||
VisualTouched = false;
|
||||
}
|
||||
void ViewProviderPartExt::forceUpdate(bool enable) {
|
||||
if(enable) {
|
||||
if(++forceUpdateCount == 1) {
|
||||
if(!isShow())
|
||||
Visibility.touch();
|
||||
}
|
||||
}else if(forceUpdateCount)
|
||||
--forceUpdateCount;
|
||||
}
|
||||
|
||||
|
||||
@@ -33,6 +33,7 @@
|
||||
#include <App/PropertyUnits.h>
|
||||
#include <Gui/ViewProviderGeometryObject.h>
|
||||
#include <map>
|
||||
#include <Mod/Part/App/PartFeature.h>
|
||||
|
||||
class TopoDS_Shape;
|
||||
class TopoDS_Edge;
|
||||
@@ -128,9 +129,15 @@ public:
|
||||
void unsetHighlightedPoints();
|
||||
//@}
|
||||
|
||||
virtual bool isUpdateForced() const override {
|
||||
return forceUpdateCount>0;
|
||||
}
|
||||
virtual void forceUpdate(bool enable = true) override;
|
||||
|
||||
/** @name Edit methods */
|
||||
//@{
|
||||
void setupContextMenu(QMenu*, QObject*, const char*);
|
||||
|
||||
protected:
|
||||
bool setEdit(int ModNum);
|
||||
void unsetEdit(int ModNum);
|
||||
@@ -140,7 +147,7 @@ protected:
|
||||
/// get called by the container whenever a property has been changed
|
||||
virtual void onChanged(const App::Property* prop);
|
||||
bool loadParameter();
|
||||
void updateVisual(const TopoDS_Shape &);
|
||||
void updateVisual();
|
||||
void getNormals(const TopoDS_Face& theFace, const Handle(Poly_Triangulation)& aPolyTri,
|
||||
TColgp_Array1OfDir& theNormals);
|
||||
|
||||
@@ -166,6 +173,7 @@ protected:
|
||||
|
||||
private:
|
||||
// settings stuff
|
||||
int forceUpdateCount;
|
||||
static App::PropertyFloatConstraint::Constraints sizeRange;
|
||||
static App::PropertyFloatConstraint::Constraints tessRange;
|
||||
static App::PropertyQuantityConstraint::Constraints angDeflectionRange;
|
||||
|
||||
@@ -242,7 +242,8 @@ void ViewProviderFillet::updateData(const App::Property* prop)
|
||||
Part::Fillet* objFill = dynamic_cast<Part::Fillet*>(getObject());
|
||||
if (!objFill)
|
||||
return;
|
||||
Part::Feature* objBase = dynamic_cast<Part::Feature*>(objFill->Base.getValue());
|
||||
Part::Feature* objBase = dynamic_cast<Part::Feature*>(
|
||||
Part::Feature::getShapeOwner(objFill->Base.getValue()));
|
||||
if (objBase) {
|
||||
const TopoDS_Shape& baseShape = objBase->Shape.getValue();
|
||||
const TopoDS_Shape& fillShape = objFill->Shape.getValue();
|
||||
@@ -345,7 +346,8 @@ void ViewProviderChamfer::updateData(const App::Property* prop)
|
||||
Part::Chamfer* objCham = dynamic_cast<Part::Chamfer*>(getObject());
|
||||
if (!objCham)
|
||||
return;
|
||||
Part::Feature* objBase = dynamic_cast<Part::Feature*>(objCham->Base.getValue());
|
||||
Part::Feature* objBase = dynamic_cast<Part::Feature*>(
|
||||
Part::Feature::getShapeOwner(objCham->Base.getValue()));
|
||||
if (objBase) {
|
||||
const TopoDS_Shape& baseShape = objBase->Shape.getValue();
|
||||
const TopoDS_Shape& chamShape = objCham->Shape.getValue();
|
||||
@@ -493,7 +495,11 @@ ViewProviderSweep::~ViewProviderSweep()
|
||||
|
||||
std::vector<App::DocumentObject*> ViewProviderSweep::claimChildren() const
|
||||
{
|
||||
return static_cast<Part::Sweep*>(getObject())->Sections.getValues();
|
||||
auto obj = static_cast<Part::Sweep*>(getObject());
|
||||
auto children = obj->Sections.getValues();
|
||||
if(obj->Spine.getValue())
|
||||
children.push_back(obj->Spine.getValue());
|
||||
return children;
|
||||
}
|
||||
|
||||
bool ViewProviderSweep::onDelete(const std::vector<std::string> &)
|
||||
|
||||
@@ -88,12 +88,9 @@ bool ViewProviderFace::canDragObjects() const
|
||||
|
||||
bool ViewProviderFace::canDragObject(App::DocumentObject* obj) const
|
||||
{
|
||||
if (!obj)
|
||||
return false;
|
||||
if (obj->getTypeId().isDerivedFrom(Part::Part2DObject::getClassTypeId()))
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
(void)obj;
|
||||
// return Part::Feature::hasShapeOwner(obj);
|
||||
return true;
|
||||
}
|
||||
|
||||
void ViewProviderFace::dragObject(App::DocumentObject* obj)
|
||||
|
||||
@@ -72,6 +72,13 @@ Gui::MenuItem* Workbench::setupMenuBar() const
|
||||
<< "Separator"
|
||||
<< "Part_MakeTube";
|
||||
|
||||
Gui::MenuItem* copy = new Gui::MenuItem;
|
||||
copy->setCommand("Create a copy");
|
||||
*copy << "Part_SimpleCopy"
|
||||
<< "Part_TransformedCopy"
|
||||
<< "Part_ElementCopy"
|
||||
<< "Part_RefineShape";
|
||||
|
||||
Gui::MenuItem* bop = new Gui::MenuItem;
|
||||
bop->setCommand("Boolean");
|
||||
*bop << "Part_Boolean"
|
||||
@@ -113,8 +120,7 @@ Gui::MenuItem* Workbench::setupMenuBar() const
|
||||
<< "Part_ShapeFromMesh"
|
||||
<< "Part_MakeSolid"
|
||||
<< "Part_ReverseShape"
|
||||
<< "Part_SimpleCopy"
|
||||
<< "Part_RefineShape"
|
||||
<< copy
|
||||
<< "Part_CheckGeometry"
|
||||
<< "Part_Defeaturing"
|
||||
<< "Separator"
|
||||
@@ -144,6 +150,7 @@ Gui::MenuItem* Workbench::setupMenuBar() const
|
||||
*measure << "Part_Measure_Linear"
|
||||
<< "Part_Measure_Angular"
|
||||
<< "Separator"
|
||||
<< "Part_Measure_Refresh"
|
||||
<< "Part_Measure_Clear_All"
|
||||
<< "Part_Measure_Toggle_All"
|
||||
<< "Part_Measure_Toggle_3d"
|
||||
@@ -211,6 +218,7 @@ Gui::ToolBarItem* Workbench::setupToolBars() const
|
||||
*measure << "Part_Measure_Linear"
|
||||
<< "Part_Measure_Angular"
|
||||
<< "Separator"
|
||||
<< "Part_Measure_Refresh"
|
||||
<< "Part_Measure_Clear_All"
|
||||
<< "Part_Measure_Toggle_All"
|
||||
<< "Part_Measure_Toggle_3d"
|
||||
|
||||
Reference in New Issue
Block a user