Toponaming: Remove all FC_USE_TNP_FIX protected old code

This commit is contained in:
bgbsww
2024-08-26 11:12:48 -05:00
committed by Chris Hennes
parent 60640fa441
commit ecf7e51ab3
52 changed files with 22 additions and 4760 deletions
-7
View File
@@ -555,14 +555,7 @@ void ComplexGeoDataPy::setPlacement(Py::Object arg)
Py::String ComplexGeoDataPy::getElementMapVersion() const
{
#ifdef FC_USE_TNP_FIX
return Py::String(getComplexGeoDataPtr()->getElementMapVersion());
#else
// This is to allow python level tests visibility into whether element maps are in use, so that
// expectations can be adjusted. Eventually this ifdef and clause should be removed, and at the
// same time all python tests checking for ElementMapVersion != '' should also be removed.
return Py::String();
#endif
}
-19
View File
@@ -89,11 +89,6 @@ GeoFeature::getElementName(const char *name, ElementNameType type) const
if(!name)
return {};
#ifndef FC_USE_TNP_FIX
ret.oldName = name;
return ret;
#else
auto prop = getPropertyOfGeometry();
if (!prop) {
return ElementNamePair("",name);
@@ -105,7 +100,6 @@ GeoFeature::getElementName(const char *name, ElementNameType type) const
}
return _getElementName(name, geo->getElementName(name));
#endif
}
ElementNamePair
@@ -143,17 +137,14 @@ DocumentObject *GeoFeature::resolveElement(DocumentObject *obj, const char *subn
ElementNameType type, const DocumentObject *filter,
const char **_element, GeoFeature **geoFeature)
{
#ifdef FC_USE_TNP_FIX
elementName.newName.clear();
elementName.oldName.clear();
#endif
if(!obj || !obj->isAttachedToDocument())
return nullptr;
if(!subname)
subname = "";
const char *element = Data::findElementName(subname);
if(_element) *_element = element;
#ifdef FC_USE_TNP_FIX
auto sobj = obj->getSubObject(std::string(subname, element).c_str());
if(!sobj)
return nullptr;
@@ -164,13 +155,6 @@ DocumentObject *GeoFeature::resolveElement(DocumentObject *obj, const char *subn
if(ext)
geo = Base::freecad_dynamic_cast<GeoFeature>(ext->getTrueLinkedObject(true));
}
#else
auto sobj = obj->getSubObject(subname);
if(!sobj)
return nullptr;
obj = sobj->getLinkedObject(true);
auto geo = dynamic_cast<GeoFeature*>(obj);
#endif
if(geoFeature)
*geoFeature = geo;
if(!obj || (filter && obj!=filter))
@@ -217,7 +201,6 @@ bool GeoFeature::getCameraAlignmentDirection(Base::Vector3d& direction, const ch
return false;
}
#ifdef FC_USE_TNP_FIX
bool GeoFeature::hasMissingElement(const char* subname)
{
return Data::hasMissingElement(subname);
@@ -287,5 +270,3 @@ GeoFeature::getHigherElements(const char *element, bool silent) const
return {};
return prop->getComplexData()->getHigherElements(element, silent);
}
#endif
-3
View File
@@ -148,7 +148,6 @@ public:
* @return bool whether or not a direction is found.
*/
virtual bool getCameraAlignmentDirection(Base::Vector3d& direction, const char* subname = nullptr) const;
#ifdef FC_USE_TNP_FIX
/** Search sub element using internal cached geometry
*
* @param element: element name
@@ -184,8 +183,6 @@ protected:
void onChanged(const Property* prop) override;
// void onDocumentRestored() override;
void updateElementReference();
#endif
protected:
ElementNamePair _getElementName(const char* name,
const Data::MappedElement& mapped) const;
-85
View File
@@ -111,7 +111,6 @@ bool PropertyLinkBase::isSame(const Property &other) const
}
void PropertyLinkBase::unregisterElementReference() {
#ifdef FC_USE_TNP_FIX
for (auto obj : _ElementRefs) {
auto it = _ElementRefMap.find(obj);
if (it != _ElementRefMap.end()) {
@@ -122,7 +121,6 @@ void PropertyLinkBase::unregisterElementReference() {
}
}
_ElementRefs.clear();
#endif
}
void PropertyLinkBase::unregisterLabelReferences()
@@ -241,7 +239,6 @@ PropertyLinkBase::getElementReferences(DocumentObject* feature)
}
void PropertyLinkBase::updateElementReferences(DocumentObject *feature, bool reverse) {
#ifdef FC_USE_TNP_FIX
if (!feature || !feature->getNameInDocument()) {
return;
}
@@ -267,15 +264,10 @@ void PropertyLinkBase::updateElementReferences(DocumentObject *feature, bool rev
}
}
}
#else
(void)feature;
(void)reverse;
#endif
}
void PropertyLinkBase::_registerElementReference(App::DocumentObject *obj, std::string &sub, ShadowSub &shadow)
{
#ifdef FC_USE_TNP_FIX
if (!obj || !obj->getNameInDocument() || sub.empty()) {
return;
}
@@ -301,11 +293,6 @@ void PropertyLinkBase::_registerElementReference(App::DocumentObject *obj, std::
if (_ElementRefs.insert(geo).second) {
_ElementRefMap[geo].insert(this);
}
#else
(void)obj;
(void)sub;
(void)shadow;
#endif
}
class StringGuard {
@@ -370,7 +357,6 @@ bool PropertyLinkBase::_updateElementReference(DocumentObject *feature,
App::DocumentObject *obj, std::string &sub, ShadowSub &shadow,
bool reverse, bool notify)
{
#ifdef FC_USE_TNP_FIX
if (!obj || !obj->getNameInDocument()) {
return false;
}
@@ -512,14 +498,6 @@ bool PropertyLinkBase::_updateElementReference(DocumentObject *feature,
updateSub(shadow.oldName);
}
return true;
#else
(void)feature;
(void)obj;
(void)reverse;
(void)notify;
shadow.oldName = sub;
return false;
#endif
}
std::pair<DocumentObject*, std::string>
@@ -545,14 +523,12 @@ PropertyLinkBase::tryReplaceLink(const PropertyContainer* owner,
return res;
}
return res;
#ifdef FC_USE_TNP_FIX
}
else if (newObj == obj) {
// This means the new object is already sub-object of this parent
// (consider a case of swapping the tool and base object of the Cut
// feature). We'll swap the old and new object.
return tryReplaceLink(owner, obj, parent, newObj, oldObj, subname);
#endif
}
if (!subname || !subname[0]) {
return res;
@@ -586,11 +562,9 @@ PropertyLinkBase::tryReplaceLink(const PropertyContainer* owner,
return res;
}
break;
#ifdef FC_USE_TNP_FIX
}
else if (sobj == newObj) {
return tryReplaceLink(owner, obj, parent, newObj, oldObj, subname);
#endif
}
else if (prev == parent) {
break;
@@ -1291,7 +1265,6 @@ static inline const std::string &getSubNameWithStyle(const std::string &subName,
if(!shadow.oldName.empty())
return shadow.oldName;
}else if(!shadow.newName.empty()) {
#ifdef FC_USE_TNP_FIX
if (Data::hasMissingElement(shadow.oldName.c_str())) {
auto pos = shadow.newName.rfind('.');
if (pos != std::string::npos) {
@@ -1300,9 +1273,6 @@ static inline const std::string &getSubNameWithStyle(const std::string &subName,
return tmp;
}
}
#else
(void) tmp;
#endif
return shadow.newName;
}
return subName;
@@ -1320,7 +1290,6 @@ std::vector<std::string> PropertyLinkSub::getSubValues(bool newStyle) const {
std::vector<std::string> PropertyLinkSub::getSubValuesStartsWith(const char* starter, bool newStyle) const
{
#ifdef FC_USE_TNP_FIX
assert(_cSubList.size() == _ShadowSubList.size());
std::vector<std::string> ret;
std::string tmp;
@@ -1331,18 +1300,6 @@ std::vector<std::string> PropertyLinkSub::getSubValuesStartsWith(const char* sta
ret.emplace_back(element);
}
return ret;
#else
(void)newStyle;
std::vector<std::string> temp;
for(const auto & it : _cSubList) {
if(strncmp(starter, it.c_str(), strlen(starter)) == 0) {
temp.push_back(it);
}
}
return temp;
#endif
}
App::DocumentObject * PropertyLinkSub::getValue(Base::Type t) const
@@ -1356,14 +1313,9 @@ PyObject *PropertyLinkSub::getPyObject()
Py::List list(static_cast<int>(_cSubList.size()));
if (_pcLinkSub) {
tup[0] = Py::asObject(_pcLinkSub->getPyObject());
#ifdef FC_USE_TNP_FIX
int i = 0;
for (auto &sub : getSubValues(testFlag(LinkNewElement)))
list[i++] = Py::String(sub);
#else
for(unsigned int i = 0;i<_cSubList.size(); i++)
list[i] = Py::String(_cSubList[i]);
#endif
tup[1] = list;
return Py::new_reference_to(tup);
}
@@ -1692,12 +1644,7 @@ void PropertyLinkBase::_getLinksTo(std::vector<App::ObjectIdentifier>& identifie
#define ATTR_SHADOW "shadow"
#define ATTR_MAPPED "mapped"
#ifdef FC_USE_TNP_FIX
#define IGNORE_SHADOW false
#else
// We do not have topo naming yet, ignore shadow sub for now
#define IGNORE_SHADOW true
#endif
void PropertyLinkSub::Save (Base::Writer &writer) const
{
@@ -1885,9 +1832,7 @@ Property *PropertyLinkSub::Copy() const
PropertyLinkSub *p= new PropertyLinkSub();
p->_pcLinkSub = _pcLinkSub;
p->_cSubList = _cSubList;
#ifdef FC_USE_TNP_FIX
p->_ShadowSubList = _ShadowSubList;
#endif
return p;
}
@@ -1896,12 +1841,8 @@ void PropertyLinkSub::Paste(const Property &from)
if(!from.isDerivedFrom(PropertyLinkSub::getClassTypeId()))
throw Base::TypeError("Incompatible property to paste to");
auto &link = static_cast<const PropertyLinkSub&>(from);
#ifdef FC_USE_TNP_FIX
setValue(link._pcLinkSub, link._cSubList,
std::vector<ShadowSub>(link._ShadowSubList));
#else
setValue(link._pcLinkSub, link._cSubList);
#endif
}
void PropertyLinkSub::getLinks(std::vector<App::DocumentObject *> &objs,
@@ -2360,7 +2301,6 @@ void PropertyLinkSubList::setSubListValues(const std::vector<PropertyLinkSubList
{
std::vector<DocumentObject*> links;
std::vector<std::string> subs;
#ifdef FC_USE_TNP_FIX
for (std::vector<PropertyLinkSubList::SubSet>::const_iterator it = values.begin(); it != values.end(); ++it) {
if (it->second.empty()) {
links.push_back(it->first);
@@ -2372,14 +2312,6 @@ void PropertyLinkSubList::setSubListValues(const std::vector<PropertyLinkSubList
subs.push_back(*jt);
}
}
#else
for (const auto & value : values) {
for (const auto& jt : value.second) {
links.push_back(value.first);
subs.push_back(jt);
}
}
#endif
setValues(links, subs);
}
@@ -2844,9 +2776,7 @@ Property *PropertyLinkSubList::Copy() const
PropertyLinkSubList *p = new PropertyLinkSubList();
p->_lValueList = _lValueList;
p->_lSubList = _lSubList;
#ifdef FC_USE_TNP_FIX
p->_ShadowSubList = _ShadowSubList;
#endif
return p;
}
@@ -2855,12 +2785,8 @@ void PropertyLinkSubList::Paste(const Property &from)
if(!from.isDerivedFrom(PropertyLinkSubList::getClassTypeId()))
throw Base::TypeError("Incompatible property to paste to");
auto &link = static_cast<const PropertyLinkSubList&>(from);
#ifdef FC_USE_TNP_FIX
setValues(link._lValueList, link._lSubList,
std::vector<ShadowSub>(link._ShadowSubList));
#else
setValues(link._lValueList, link._lSubList);
#endif
}
unsigned int PropertyLinkSubList::getMemSize () const
@@ -3480,9 +3406,7 @@ void PropertyXLink::setSubValues(std::vector<std::string> &&subs,
_ShadowSubList.clear();
if(shadows.size() == _SubList.size()) {
_ShadowSubList = std::move(shadows);
#ifdef FC_USE_TNP_FIX
onContainerRestored(); // re-register element references
#endif
} else
updateElementReference(nullptr);
checkLabelReferences(_SubList);
@@ -3990,9 +3914,7 @@ void PropertyXLink::copyTo(PropertyXLink &other,
other._SubList = std::move(*subs);
else {
other._SubList = _SubList;
#ifdef FC_USE_TNP_FIX
other._ShadowSubList = _ShadowSubList;
#endif
}
other._Flags = _Flags;
}
@@ -4021,19 +3943,12 @@ void PropertyXLink::Paste(const Property &from)
FC_WARN("Object '" << other.docName << '#' << other.objectName << "' not found");
return;
}
#ifdef FC_USE_TNP_FIX
setValue(obj,std::vector<std::string>(other._SubList),
std::vector<ShadowSub>(other._ShadowSubList));
} else
setValue(std::string(other.filePath),std::string(other.objectName),
std::vector<std::string>(other._SubList),
std::vector<ShadowSub>(other._ShadowSubList));
#else
setValue(obj,std::vector<std::string>(other._SubList));
} else
setValue(std::string(other.filePath),std::string(other.objectName),
std::vector<std::string>(other._SubList));
#endif
setFlag(LinkAllowPartial,other.testFlag(LinkAllowPartial));
}
+14 -431
View File
@@ -432,7 +432,6 @@ public:
add_varargs_method("getFacets",&Module::getFacets,
"getFacets(shape): simplified mesh generation"
);
#ifdef FC_USE_TNP_FIX
add_keyword_method("makeCompound",&Module::makeCompound,
"makeCompound(list) -- Create a compound out of a list of shapes."
);
@@ -452,27 +451,6 @@ public:
add_keyword_method("makeSolid",&Module::makeSolid,
"makeSolid(shape): Create a solid out of shells of shape. If shape is a compsolid, the overall volume solid is created."
);
#else
add_varargs_method("makeCompound",&Module::makeCompound,
"makeCompound(list) -- Create a compound out of a list of shapes."
);
add_varargs_method("makeShell",&Module::makeShell,
"makeShell(list) -- Create a shell out of a list of faces."
);
add_varargs_method("makeFace",&Module::makeFace,
"makeFace(list_of_shapes_or_compound, maker_class_name) -- Create a face (faces) using facemaker class.\n"
"maker_class_name is a string like 'Part::FaceMakerSimple'."
);
add_varargs_method("makeFilledSurface",&Module::makeFilledSurface,
"makeFilledSurface(list of curves, tolerance) -- Create a surface out of a list of curves."
);
add_varargs_method("makeFilledFace",&Module::makeFilledFace,
"makeFilledFace(list) -- Create a face out of a list of edges."
);
add_varargs_method("makeSolid",&Module::makeSolid,
"makeSolid(shape): Create a solid out of shells of shape. If shape is a compsolid, the overall volume solid is created."
);
#endif
add_varargs_method("makePlane",&Module::makePlane,
"makePlane(length,width,[pnt,dirZ,dirX]) -- Make a plane\n"
"By default pnt=Vector(0,0,0) and dirZ=Vector(0,0,1), dirX is ignored in this case"
@@ -553,7 +531,6 @@ public:
"By default vmin/vmax=bounds of the curve, angle=360, pnt=Vector(0,0,0),\n"
"dir=Vector(0,0,1) and shapetype=Part.Solid"
);
#ifdef FC_USE_TNP_FIX
add_keyword_method("makeRuledSurface",&Module::makeRuledSurface,
"makeRuledSurface(Edge|Wire,Edge|Wire) -- Make a ruled surface\n"
"Create a ruled surface out of two edges or wires. If wires are used then"
@@ -566,20 +543,6 @@ public:
add_keyword_method("makeLoft",&Module::makeLoft,
"makeLoft(list of wires,[solid=False,ruled=False,closed=False,maxDegree=5]) -- Create a loft shape."
);
#else
add_varargs_method("makeRuledSurface",&Module::makeRuledSurface,
"makeRuledSurface(Edge|Wire,Edge|Wire) -- Make a ruled surface\n"
"Create a ruled surface out of two edges or wires. If wires are used then"
"these must have the same number of edges."
);
add_varargs_method("makeShellFromWires",&Module::makeShellFromWires,
"makeShellFromWires(Wires) -- Make a shell from wires.\n"
"The wires must have the same number of edges."
);
add_varargs_method("makeLoft",&Module::makeLoft,
"makeLoft(list of wires,[solid=False,ruled=False,closed=False,maxDegree=5]) -- Create a loft shape."
);
#endif
add_varargs_method("makeTube",&Module::makeTube,
"makeTube(edge,radius,[continuity,max degree,max segments]) -- Create a tube.\n"
"continuity is a string which must be 'C0','C1','C2','C3','CN','G1' or 'G1',"
@@ -893,36 +856,22 @@ private:
App::Document *pcDoc = App::GetApplication().getActiveDocument();
if (!pcDoc)
pcDoc = App::GetApplication().newDocument();
#ifndef FC_USE_TNP_FIX
TopoShapePy* pShape = static_cast<TopoShapePy*>(pcObj);
Part::Feature *pcFeature = static_cast<Part::Feature*>(pcDoc->addObject("Part::Feature", name));
// copy the data
pcFeature->Shape.setValue(pShape->getTopoShapePtr()->getShape());
pcDoc->recompute();
return Py::asObject(pcFeature->getPyObject());
#else
TopoShape shape;
if (PyObject_TypeCheck(pcObj, &TopoShapePy::Type)) {
shape = *static_cast<TopoShapePy*>(pcObj)->getTopoShapePtr();
}
else if (PyObject_TypeCheck(pcObj, &GeometryPy::Type)) {
shape = static_cast<GeometryPy*>(pcObj)->getGeometryPtr()->toShape();
}
if (PyObject_TypeCheck(pcObj, &TopoShapePy::Type))
shape = *static_cast<TopoShapePy *>(pcObj)->getTopoShapePtr();
else if (PyObject_TypeCheck(pcObj, &GeometryPy::Type))
shape = static_cast<GeometryPy *>(pcObj)->getGeometryPtr()->toShape();
else if (PyObject_TypeCheck(pcObj, &App::DocumentObjectPy::Type)) {
auto obj = static_cast<App::DocumentObjectPy*>(pcObj)->getDocumentObjectPtr();
auto obj = static_cast<App::DocumentObjectPy *>(pcObj)->getDocumentObjectPtr();
shape = Feature::getTopoShape(obj);
}
else {
} else {
throw Py::TypeError("Expects argument of type DocumentObject, Shape, or Geometry");
}
Part::Feature *pcFeature = static_cast<Part::Feature*>(pcDoc->addObject("Part::Feature", name));
// copy the data
pcFeature->Shape.setValue(shape);
pcFeature->purgeTouched();
return Py::asObject(pcFeature->getPyObject());
#endif
}
Py::Object getFacets(const Py::Tuple& args)
{
@@ -957,7 +906,6 @@ private:
}
return list;
}
#ifdef FC_USE_TNP_FIX
Py::Object makeCompound(const Py::Tuple& args, const Py::Dict &kwds)
{
PyObject* pcObj;
@@ -984,28 +932,7 @@ private:
Py_DECREF(policyEnum);
return shape2pyshape(Part::TopoShape().makeElementCompound(getPyShapes(pcObj), op, policy));
#else
Py::Object makeCompound(const Py::Tuple& args)
{
PyObject *pcObj;
if (!PyArg_ParseTuple(args.ptr(), "O", &pcObj))
throw Py::Exception();
BRep_Builder builder;
TopoDS_Compound Comp;
builder.MakeCompound(Comp);
PY_TRY {
for(auto &s : getPyShapes(pcObj)) {
const auto &sh = s.getShape();
if (!sh.IsNull())
builder.Add(Comp, sh);
}
} _PY_CATCH_OCC(throw Py::Exception())
return Py::asObject(new TopoShapeCompoundPy(new TopoShape(Comp)));
#endif
}
#ifdef FC_USE_TNP_FIX
Py::Object makeShell(const Py::Tuple& args, const Py::Dict &kwds)
{
PyObject* obj;
@@ -1021,45 +948,7 @@ private:
}
return shape2pyshape(
Part::TopoShape().makeElementBoolean(Part::OpCodes::Shell, getPyShapes(obj), op));
#else
Py::Object makeShell(const Py::Tuple& args)
{
PyObject *obj;
if (!PyArg_ParseTuple(args.ptr(), "O", &obj))
throw Py::Exception();
BRep_Builder builder;
TopoDS_Shape shape;
TopoDS_Shell shell;
//BRepOffsetAPI_Sewing mkShell;
builder.MakeShell(shell);
try {
Py::Sequence list(obj);
for (Py::Sequence::iterator it = list.begin(); it != list.end(); ++it) {
if (PyObject_TypeCheck((*it).ptr(), &(Part::TopoShapeFacePy::Type))) {
const TopoDS_Shape& sh = static_cast<TopoShapeFacePy*>((*it).ptr())->
getTopoShapePtr()->getShape();
if (!sh.IsNull())
builder.Add(shell, sh);
}
}
shape = shell;
BRepCheck_Analyzer check(shell);
if (!check.IsValid()) {
ShapeUpgrade_ShellSewing sewShell;
shape = sewShell.ApplySewing(shell);
}
}
catch (Standard_Failure& e) {
throw Py::Exception(PartExceptionOCCError, e.GetMessageString());
}
return Py::asObject(new TopoShapeShellPy(new TopoShape(shape)));
#endif
}
#ifdef FC_USE_TNP_FIX
Py::Object makeFace(const Py::Tuple& args, const Py::Dict &kwds)
{
PyObject* obj;
@@ -1076,55 +965,6 @@ private:
throw Py::Exception();
}
return shape2pyshape(TopoShape().makeElementFace(getPyShapes(obj), op, className));
#else
Py::Object makeFace(const Py::Tuple& args)
{
try {
char* className = nullptr;
PyObject* pcPyShapeOrList = nullptr;
PyErr_Clear();
if (PyArg_ParseTuple(args.ptr(), "Os", &pcPyShapeOrList, &className)) {
std::unique_ptr<FaceMaker> fm = Part::FaceMaker::ConstructFromType(className);
//dump all supplied shapes to facemaker, no matter what type (let facemaker decide).
if (PySequence_Check(pcPyShapeOrList)){
Py::Sequence list(pcPyShapeOrList);
for (Py::Sequence::iterator it = list.begin(); it != list.end(); ++it) {
PyObject* item = (*it).ptr();
if (PyObject_TypeCheck(item, &(Part::TopoShapePy::Type))) {
const TopoDS_Shape& sh = static_cast<Part::TopoShapePy*>(item)->getTopoShapePtr()->getShape();
fm->addShape(sh);
} else {
throw Py::TypeError("Object is not a shape.");
}
}
} else if (PyObject_TypeCheck(pcPyShapeOrList, &(Part::TopoShapePy::Type))) {
const TopoDS_Shape& sh = static_cast<Part::TopoShapePy*>(pcPyShapeOrList)->getTopoShapePtr()->getShape();
if (sh.IsNull())
throw NullShapeException("Shape is null!");
if (sh.ShapeType() == TopAbs_COMPOUND)
fm->useCompound(TopoDS::Compound(sh));
else
fm->addShape(sh);
} else {
throw Py::Exception(PyExc_TypeError, "First argument is neither a shape nor list of shapes.");
}
fm->Build();
TopoShape topo(fm->Shape());
return Py::asObject(topo.getPyObject());
}
throw Py::TypeError(std::string("Argument type signature not recognized. Should be either (list, string), or (shape, string)"));
} catch (Standard_Failure& e) {
throw Py::Exception(PartExceptionOCCError, e.GetMessageString());
} catch (Base::Exception &e){
e.setPyException();
throw Py::Exception();
}
#endif
}
template<class F>
@@ -1150,7 +990,6 @@ private:
}
#ifdef FC_USE_TNP_FIX
Py::Object makeFilledSurface(const Py::Tuple &args, const Py::Dict &kwds)
{
TopoShape::BRepFillingParams params;
@@ -1226,41 +1065,8 @@ private:
}
return shape2pyshape(
TopoShape(0, shapes.front().Hasher).makeElementFilledFace(shapes, params, op));
#else
Py::Object makeFilledSurface(const Py::Tuple &args)
{
PyObject *obj;
double tolerance;
if (!PyArg_ParseTuple(args.ptr(), "Od", &obj, &tolerance))
throw Py::Exception();
try {
GeomFill_Generator generator;
Py::Sequence list(obj);
for (Py::Sequence::iterator it = list.begin(); it != list.end(); ++it) {
if (PyObject_TypeCheck((*it).ptr(), &(Part::GeometryCurvePy::Type))) {
Handle(Geom_Curve) hCurve = Handle(Geom_Curve)::DownCast(static_cast<Part::GeometryCurvePy*>((*it).ptr())->getGeomCurvePtr()->handle());
if (!hCurve.IsNull()) {
generator.AddCurve(hCurve);
}
}
}
generator.Perform(tolerance);
Handle(Geom_Surface) hSurface = generator.Surface();
if (!hSurface.IsNull()) {
return Py::asObject(makeFromSurface(hSurface)->getPyObject());
}
else {
throw Py::Exception(PartExceptionOCCError, "Failed to created surface by filling curves");
}
}
catch (Standard_Failure& e) {
throw Py::Exception(PartExceptionOCCError, e.GetMessageString());
}
#endif
}
#ifdef FC_USE_TNP_FIX
Py::Object makeFilledFace(const Py::Tuple& args, const Py::Dict &kwds)
{
TopoShape::BRepFillingParams params;
@@ -1336,68 +1142,8 @@ private:
}
return shape2pyshape(
TopoShape(0, shapes.front().Hasher).makeElementFilledFace(shapes, params, op));
#else
Py::Object makeFilledFace(const Py::Tuple& args)
{
// TODO: BRepFeat_SplitShape
PyObject *obj;
PyObject *surf=nullptr;
if (!PyArg_ParseTuple(args.ptr(), "O|O!", &obj, &TopoShapeFacePy::Type, &surf))
throw Py::Exception();
// See also BRepOffsetAPI_MakeFilling
BRepFill_Filling builder;
try {
if (surf) {
const TopoDS_Shape& face = static_cast<TopoShapeFacePy*>(surf)->
getTopoShapePtr()->getShape();
if (!face.IsNull() && face.ShapeType() == TopAbs_FACE) {
builder.LoadInitSurface(TopoDS::Face(face));
}
}
Py::Sequence list(obj);
int numConstraints = 0;
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()) {
if (sh.ShapeType() == TopAbs_EDGE) {
builder.Add(TopoDS::Edge(sh), GeomAbs_C0);
numConstraints++;
}
else if (sh.ShapeType() == TopAbs_FACE) {
builder.Add(TopoDS::Face(sh), GeomAbs_C0);
numConstraints++;
}
else if (sh.ShapeType() == TopAbs_VERTEX) {
const TopoDS_Vertex& v = TopoDS::Vertex(sh);
gp_Pnt pnt = BRep_Tool::Pnt(v);
builder.Add(pnt);
numConstraints++;
}
}
}
}
if (numConstraints == 0) {
throw Py::Exception(PartExceptionOCCError, "Failed to create face with no constraints");
}
builder.Build();
if (builder.IsDone()) {
return Py::asObject(new TopoShapeFacePy(new TopoShape(builder.Face())));
}
else {
throw Py::Exception(PartExceptionOCCError, "Failed to created face by filling edges");
}
}
catch (Standard_Failure& e) {
throw Py::Exception(PartExceptionOCCError, e.GetMessageString());
}
#endif
}
#ifdef FC_USE_TNP_FIX
Py::Object makeSolid(const Py::Tuple& args, const Py::Dict &kwds)
{
PyObject* obj;
@@ -1414,58 +1160,8 @@ private:
}
return shape2pyshape(
TopoShape().makeElementSolid(*static_cast<TopoShapePy*>(obj)->getTopoShapePtr(), op));
#else
Py::Object makeSolid(const Py::Tuple& args)
{
PyObject *obj;
if (!PyArg_ParseTuple(args.ptr(), "O!", &(TopoShapePy::Type), &obj))
throw Py::Exception();
try {
const TopoDS_Shape& shape = static_cast<TopoShapePy*>(obj)
->getTopoShapePtr()->getShape();
//first, if we were given a compsolid, try making a solid out of it
TopExp_Explorer CSExp (shape, TopAbs_COMPSOLID);
TopoDS_CompSolid compsolid;
int count=0;
for (; CSExp.More(); CSExp.Next()) {
++count;
compsolid = TopoDS::CompSolid(CSExp.Current());
if (count > 1)
break;
}
if (count == 0) {
//no compsolids. Get shells...
BRepBuilderAPI_MakeSolid mkSolid;
TopExp_Explorer anExp (shape, TopAbs_SHELL);
count=0;
for (; anExp.More(); anExp.Next()) {
++count;
mkSolid.Add(TopoDS::Shell(anExp.Current()));
}
if (count == 0)//no shells?
Standard_Failure::Raise("No shells or compsolids found in shape");
TopoDS_Solid solid = mkSolid.Solid();
BRepLib::OrientClosedSolid(solid);
return Py::asObject(new TopoShapeSolidPy(new TopoShape(solid)));
} else if (count == 1) {
BRepBuilderAPI_MakeSolid mkSolid(compsolid);
TopoDS_Solid solid = mkSolid.Solid();
return Py::asObject(new TopoShapeSolidPy(new TopoShape(solid)));
} else { // if (count > 1)
Standard_Failure::Raise("Only one compsolid can be accepted. Provided shape has more than one compsolid.");
return Py::None(); //prevents compiler warning
}
}
catch (Standard_Failure& err) {
std::stringstream errmsg;
errmsg << "Creation of solid failed: " << err.GetMessageString();
throw Py::Exception(PartExceptionOCCError, errmsg.str().c_str());
}
#endif
}
Py::Object makePlane(const Py::Tuple& args)
{
double length, width;
@@ -2021,7 +1717,7 @@ private:
throw Py::Exception(PartExceptionOCCDomainError, "creation of revolved shape failed");
}
}
#ifdef FC_USE_TNP_FIX
Py::Object makeRuledSurface(const Py::Tuple& args, const Py::Dict &kwds)
{
const char* op = nullptr;
@@ -2049,37 +1745,8 @@ private:
shapes.push_back(*static_cast<TopoShapePy*>(sh1)->getTopoShapePtr());
shapes.push_back(*static_cast<TopoShapePy*>(sh2)->getTopoShapePtr());
return shape2pyshape(TopoShape().makeElementRuledSurface(shapes, orientation, op));
#else
Py::Object makeRuledSurface(const Py::Tuple& args)
{
// http://opencascade.blogspot.com/2009/10/surface-modeling-part1.html
PyObject *sh1, *sh2;
if (!PyArg_ParseTuple(args.ptr(), "O!O!", &(TopoShapePy::Type), &sh1,
&(TopoShapePy::Type), &sh2))
throw Py::Exception();
const TopoDS_Shape& shape1 = static_cast<TopoShapePy*>(sh1)->getTopoShapePtr()->getShape();
const TopoDS_Shape& shape2 = static_cast<TopoShapePy*>(sh2)->getTopoShapePtr()->getShape();
try {
if (shape1.ShapeType() == TopAbs_EDGE && shape2.ShapeType() == TopAbs_EDGE) {
TopoDS_Face face = BRepFill::Face(TopoDS::Edge(shape1), TopoDS::Edge(shape2));
return Py::asObject(new TopoShapeFacePy(new TopoShape(face)));
}
else if (shape1.ShapeType() == TopAbs_WIRE && shape2.ShapeType() == TopAbs_WIRE) {
TopoDS_Shell shell = BRepFill::Shell(TopoDS::Wire(shape1), TopoDS::Wire(shape2));
return Py::asObject(new TopoShapeShellPy(new TopoShape(shell)));
}
else {
throw Py::Exception(PartExceptionOCCError, "curves must either be edges or wires");
}
}
catch (Standard_Failure&) {
throw Py::Exception(PartExceptionOCCError, "creation of ruled surface failed");
}
#endif
}
#ifdef FC_USE_TNP_FIX
Py::Object makeShellFromWires(const Py::Tuple& args, const Py::Dict &kwds)
{
PyObject *pylist;
@@ -2100,32 +1767,8 @@ private:
catch (Standard_Failure&) {
throw Py::Exception(PartExceptionOCCError, "creation of shell failed");
}
#else
Py::Object makeShellFromWires(const Py::Tuple& args)
{
PyObject *pylist;
if (!PyArg_ParseTuple(args.ptr(), "O", &pylist))
throw Py::Exception();
try {
BRepFill_Generator fill;
Py::Sequence list(pylist);
for (Py::Sequence::iterator it = list.begin(); it != list.end(); ++it) {
Py::TopoShape shape(*it);
const TopoDS_Shape& s = shape.extensionObject()->getTopoShapePtr()->getShape();
if (!s.IsNull() && s.ShapeType() == TopAbs_WIRE) {
fill.AddWire(TopoDS::Wire(s));
}
}
fill.Perform();
return Py::asObject(new TopoShapeShellPy(new TopoShape(fill.Shell())));
}
catch (Standard_Failure&) {
throw Py::Exception(PartExceptionOCCError, "creation of shell failed");
}
#endif
}
Py::Object makeTube(const Py::Tuple& args)
{
PyObject *pshape;
@@ -2181,7 +1824,6 @@ private:
throw Py::Exception();
try {
#ifdef FC_USE_TNP_FIX
TopoShape mShape = *static_cast<TopoShapePy*>(path)->getTopoShapePtr();
// makeSweep uses GeomFill_Pipe which does not support shape
// history. So use makEPipeShell() as a replacement
@@ -2194,22 +1836,12 @@ private:
TransitionMode::Transformed,
nullptr,
tolerance));
#else
if (tolerance == 0.0)
tolerance=0.001;
const TopoDS_Shape& path_shape = static_cast<TopoShapePy*>(path)->getTopoShapePtr()->getShape();
const TopoDS_Shape& prof_shape = static_cast<TopoShapePy*>(profile)->getTopoShapePtr()->getShape();
TopoShape myShape(path_shape);
TopoDS_Shape face = myShape.makeSweep(prof_shape, tolerance, fillMode);
return Py::asObject(new TopoShapeFacePy(new TopoShape(face)));
#endif
}
catch (Standard_Failure& e) {
throw Py::Exception(PartExceptionOCCError, e.GetMessageString());
}
}
# ifdef FC_USE_TNP_FIX
Py::Object makeLoft(const Py::Tuple& args, const Py::Dict &kwds)
{
PyObject *pcObj;
@@ -2247,42 +1879,8 @@ private:
anIsClosed ? Part::IsClosed::closed : Part::IsClosed::notClosed,
degMax,
op));
#else
Py::Object makeLoft(const Py::Tuple& args)
{
PyObject *pcObj;
PyObject *psolid=Py_False;
PyObject *pruled=Py_False;
PyObject *pclosed=Py_False;
int degMax = 5;
if (!PyArg_ParseTuple(args.ptr(), "O|O!O!O!i", &pcObj,
&(PyBool_Type), &psolid,
&(PyBool_Type), &pruled,
&(PyBool_Type), &pclosed,
&degMax)) {
throw Py::Exception();
}
TopTools_ListOfShape profiles;
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();
profiles.Append(sh);
}
}
TopoShape myShape;
Standard_Boolean anIsSolid = Base::asBoolean(psolid);
Standard_Boolean anIsRuled = Base::asBoolean(pruled);
Standard_Boolean anIsClosed = Base::asBoolean(pclosed);
TopoDS_Shape aResult = myShape.makeLoft(profiles, anIsSolid, anIsRuled, anIsClosed, degMax);
return Py::asObject(new TopoShapePy(new TopoShape(aResult)));
#endif
}
Py::Object makeSplitShape(const Py::Tuple& args)
{
PyObject* shape;
@@ -2343,7 +1941,6 @@ private:
Py::List list1;
Py::List list2;
#ifdef FC_USE_TNP_FIX
MapperMaker mapper(splitShape);
for (TopTools_ListIteratorOfListOfShape it(d); it.More(); it.Next()) {
TopoShape s(0, sources.front().Hasher);
@@ -2355,15 +1952,6 @@ private:
list2.append(shape2pyshape(
s.makeShapeWithElementMap(it.Value(), mapper, sources, Part::OpCodes::Split)));
}
#else
for (TopTools_ListIteratorOfListOfShape it(d); it.More(); it.Next()) {
list1.append(shape2pyshape(it.Value()));
}
for (TopTools_ListIteratorOfListOfShape it(l); it.More(); it.Next()) {
list2.append(shape2pyshape(it.Value()));
}
#endif
Py::Tuple tuple(2);
tuple.setItem(0, list1);
tuple.setItem(1, list2);
@@ -2716,12 +2304,7 @@ private:
&mat,&subObj,retType==2,Base::asBoolean(transform),
Base::asBoolean(noElementMap));
if (Base::asBoolean(refine)) {
#ifdef FC_USE_TNP_FIX
shape = TopoShape(0, shape.Hasher).makeElementRefine(shape);
#else
BRepBuilderAPI_RefineModel mkRefine(shape.getShape());
shape.setShape(mkRefine.Shape());
#endif
}
Py::Object sret(shape2pyshape(shape));
if(retType==0)
-292
View File
@@ -87,8 +87,6 @@ namespace
EXTENSION_PROPERTY_SOURCE(Part::AttachExtension, App::DocumentObjectExtension)
#ifdef FC_USE_TNP_FIX
AttachExtension::AttachExtension()
{
EXTENSION_ADD_PROPERTY_TYPE(AttacherType,
@@ -646,296 +644,6 @@ AttachEngineException::AttachEngineException(const std::string& sMessage)
: Base::Exception(sMessage)
{}
#else
AttachExtension::AttachExtension()
{
EXTENSION_ADD_PROPERTY_TYPE(AttacherType, ("Attacher::AttachEngine3D"), "Attachment",(App::PropertyType)(App::Prop_None),"Class name of attach engine object driving the attachment.");
this->AttacherType.setStatus(App::Property::Status::Hidden, true);
EXTENSION_ADD_PROPERTY_TYPE(AttachmentSupport, (nullptr,nullptr), "Attachment",(App::PropertyType)(App::Prop_None),"Support of the 2D geometry");
EXTENSION_ADD_PROPERTY_TYPE(MapMode, (mmDeactivated), "Attachment", App::Prop_None, "Mode of attachment to other object");
MapMode.setEditorName("PartGui::PropertyEnumAttacherItem");
MapMode.setEnums(AttachEngine::eMapModeStrings);
//a rough test if mode string list in Attacher.cpp is in sync with eMapMode enum.
assert(MapMode.getEnumVector().size() == mmDummy_NumberOfModes);
EXTENSION_ADD_PROPERTY_TYPE(MapReversed, (false), "Attachment", App::Prop_None, "Reverse Z direction (flip sketch upside down)");
EXTENSION_ADD_PROPERTY_TYPE(MapPathParameter, (0.0), "Attachment", App::Prop_None, "Sets point of curve to map the sketch to. 0..1 = start..end");
EXTENSION_ADD_PROPERTY_TYPE(AttachmentOffset, (Base::Placement()), "Attachment", App::Prop_None, "Extra placement to apply in addition to attachment (in local coordinates)");
// Only show these properties when applicable. Controlled by extensionOnChanged
this->MapPathParameter.setStatus(App::Property::Status::Hidden, true);
this->MapReversed.setStatus(App::Property::Status::Hidden, true);
this->AttachmentOffset.setStatus(App::Property::Status::Hidden, true);
setAttacher(new AttachEngine3D);//default attacher
initExtensionType(AttachExtension::getExtensionClassTypeId());
}
AttachExtension::~AttachExtension()
{
if(_attacher)
delete _attacher;
}
void AttachExtension::setAttacher(AttachEngine* attacher)
{
if (_attacher)
delete _attacher;
_attacher = attacher;
if (_attacher){
const char* typeName = attacher->getTypeId().getName();
if(strcmp(this->AttacherType.getValue(),typeName)!=0) //make sure we need to change, to break recursive onChange->changeAttacherType->onChange...
this->AttacherType.setValue(typeName);
updateAttacherVals();
} else {
if (strlen(AttacherType.getValue()) != 0){ //make sure we need to change, to break recursive onChange->changeAttacherType->onChange...
this->AttacherType.setValue("");
}
}
}
bool AttachExtension::changeAttacherType(const char* typeName)
{
//check if we need to actually change anything
if (_attacher){
if (strcmp(_attacher->getTypeId().getName(),typeName)==0){
return false;
}
} else if (strlen(typeName) == 0){
return false;
}
if (strlen(typeName) == 0){
setAttacher(nullptr);
return true;
}
Base::Type t = Base::Type::fromName(typeName);
if (t.isDerivedFrom(AttachEngine::getClassTypeId())){
AttachEngine* pNewAttacher = static_cast<Attacher::AttachEngine*>(Base::Type::createInstanceByName(typeName));
this->setAttacher(pNewAttacher);
return true;
}
std::stringstream errMsg;
errMsg << "Object if this type is not derived from AttachEngine: " << typeName;
throw AttachEngineException(errMsg.str());
}
bool AttachExtension::positionBySupport()
{
_active = 0;
if (!_attacher)
throw Base::RuntimeError("AttachExtension: can't positionBySupport, because no AttachEngine is set.");
updateAttacherVals();
try {
if (_attacher->mapMode == mmDeactivated)
return false;
bool subChanged = false;
getPlacement().setValue(_attacher->calculateAttachedPlacement(getPlacement().getValue(), &subChanged));
if(subChanged)
AttachmentSupport.setValues(AttachmentSupport.getValues(),_attacher->getSubValues());
_active = 1;
return true;
} catch (ExceptionCancel&) {
//disabled, don't do anything
return false;
};
}
bool AttachExtension::isAttacherActive() const {
if(_active < 0) {
_active = 0;
try {
_attacher->calculateAttachedPlacement(getPlacement().getValue());
_active = 1;
} catch (ExceptionCancel&) {
}
}
return _active!=0;
}
short int AttachExtension::extensionMustExecute() {
return DocumentObjectExtension::extensionMustExecute();
}
App::DocumentObjectExecReturn *AttachExtension::extensionExecute()
{
if(this->isTouched_Mapping()) {
try{
positionBySupport();
// we let all Base::Exceptions thru, so that App:DocumentObject can take appropriate action
/*} catch (Base::Exception &e) {
return new App::DocumentObjectExecReturn(e.what());*/
// Convert OCC exceptions to Base::Exception
} catch (Standard_Failure &e){
throw Base::RuntimeError(e.GetMessageString());
// return new App::DocumentObjectExecReturn(e.GetMessageString());
}
}
return App::DocumentObjectExtension::extensionExecute();
}
void AttachExtension::extensionOnChanged(const App::Property* prop)
{
if(! getExtendedObject()->isRestoring()){
if ((prop == &AttachmentSupport
|| prop == &MapMode
|| prop == &MapPathParameter
|| prop == &MapReversed
|| prop == &AttachmentOffset)){
bool bAttached = false;
try{
bAttached = positionBySupport();
} catch (Base::Exception &e) {
getExtendedObject()->setStatus(App::Error, true);
Base::Console().Error("PositionBySupport: %s\n",e.what());
//set error message - how?
} catch (Standard_Failure &e){
getExtendedObject()->setStatus(App::Error, true);
Base::Console().Error("PositionBySupport: %s\n",e.GetMessageString());
}
// Hide properties when not applicable to reduce user confusion
eMapMode mmode = eMapMode(this->MapMode.getValue());
bool modeIsPointOnCurve = mmode == mmNormalToPath ||
mmode == mmFrenetNB || mmode == mmFrenetTN || mmode == mmFrenetTB ||
mmode == mmRevolutionSection || mmode == mmConcentric;
// MapPathParameter is only used if there is a reference to one edge and not edge + vertex
bool hasOneRef = false;
if (_attacher && _attacher->subnames.size() == 1) {
hasOneRef = true;
}
this->MapPathParameter.setStatus(App::Property::Status::Hidden, !bAttached || !(modeIsPointOnCurve && hasOneRef));
this->MapReversed.setStatus(App::Property::Status::Hidden, !bAttached);
this->AttachmentOffset.setStatus(App::Property::Status::Hidden, !bAttached);
getPlacement().setReadOnly(bAttached && mmode != mmTranslate); //for mmTranslate, orientation should remain editable even when attached.
}
}
if(prop == &(this->AttacherType)){
this->changeAttacherType(this->AttacherType.getValue());
}
App::DocumentObjectExtension::extensionOnChanged(prop);
}
bool AttachExtension::extensionHandleChangedPropertyName(Base::XMLReader &reader, const char* TypeName, const char *PropName)
{
// superPlacement -> AttachmentOffset
Base::Type type = Base::Type::fromName(TypeName);
if (strcmp(PropName, "superPlacement") == 0 && AttachmentOffset.getClassTypeId() == type) {
AttachmentOffset.Restore(reader);
return true;
}
// Support -> AttachmentSupport
else if (strcmp(PropName, "Support") == 0) {
// At one point, the type of Support changed from PropertyLinkSub to its present type of PropertyLinkSubList.
// Later, the property name changed to AttachmentSupport
App::PropertyLinkSub tmp;
if (0 == strcmp(tmp.getTypeId().getName(),TypeName)) {
tmp.setContainer(this->getExtendedContainer());
tmp.Restore(reader);
AttachmentSupport.setValue(tmp.getValue(), tmp.getSubValues());
this->MapMode.setValue(Attacher::mmFlatFace);
return true;
}
else if (AttachmentSupport.getClassTypeId() == type) {
AttachmentSupport.Restore(reader);
return true;
}
}
return App::DocumentObjectExtension::extensionHandleChangedPropertyName(reader, TypeName, PropName);
}
void AttachExtension::onExtendedDocumentRestored()
{
try {
bool bAttached = positionBySupport();
// Hide properties when not applicable to reduce user confusion
eMapMode mmode = eMapMode(this->MapMode.getValue());
bool modeIsPointOnCurve =
(mmode == mmNormalToPath ||
mmode == mmFrenetNB ||
mmode == mmFrenetTN ||
mmode == mmFrenetTB ||
mmode == mmRevolutionSection ||
mmode == mmConcentric);
// MapPathParameter is only used if there is a reference to one edge and not edge + vertex
bool hasOneRef = false;
if (_attacher && _attacher->subnames.size() == 1) {
hasOneRef = true;
}
this->MapPathParameter.setStatus(App::Property::Status::Hidden, !bAttached || !(modeIsPointOnCurve && hasOneRef));
this->MapReversed.setStatus(App::Property::Status::Hidden, !bAttached);
this->AttachmentOffset.setStatus(App::Property::Status::Hidden, !bAttached);
getPlacement().setReadOnly(bAttached && mmode != mmTranslate); //for mmTranslate, orientation should remain editable even when attached.
}
catch (Base::Exception&) {
}
catch (Standard_Failure &) {
}
}
void AttachExtension::updateAttacherVals()
{
if (!_attacher)
return;
_attacher->setUp(this->AttachmentSupport,
eMapMode(this->MapMode.getValue()),
this->MapReversed.getValue(),
this->MapPathParameter.getValue(),
0.0,0.0,
this->AttachmentOffset.getValue());
}
App::PropertyPlacement& AttachExtension::getPlacement() const {
auto pla = Base::freecad_dynamic_cast<App::PropertyPlacement>(
getExtendedObject()->getPropertyByName("Placement"));
if(!pla)
throw Base::RuntimeError("AttachExtension cannot find placement property");
return *pla;
}
PyObject* AttachExtension::getExtensionPyObject() {
if (ExtensionPythonObject.is(Py::_None())){
// ref counter is set to 1
ExtensionPythonObject = Py::Object(new AttachExtensionPy(this),true);
}
return Py::new_reference_to(ExtensionPythonObject);
}
// ------------------------------------------------
AttachEngineException::AttachEngineException()
: Base::Exception()
{
}
AttachEngineException::AttachEngineException(const char * sMessage)
: Base::Exception(sMessage)
{
}
AttachEngineException::AttachEngineException(const std::string& sMessage)
: Base::Exception(sMessage)
{
}
#endif
namespace App {
/// @cond DOXERR
EXTENSION_PROPERTY_SOURCE_TEMPLATE(Part::AttachExtensionPython, Part::AttachExtension)
-93
View File
@@ -40,7 +40,6 @@
namespace Part
{
#ifdef FC_USE_TNP_FIX
class PartExport AttachEngineException: public Base::Exception
{
@@ -163,98 +162,6 @@ private:
using AttachExtensionPython = App::ExtensionPythonT<AttachExtension>;
#else
class PartExport AttachEngineException : public Base::Exception
{
public:
/// Construction
AttachEngineException();
explicit AttachEngineException(const char * sMessage);
explicit AttachEngineException(const std::string& sMessage);
/// Destruction
~AttachEngineException() noexcept override = default;
};
/**
* @brief The AttachableObject class is the thing to extend an object with
* that should be attachable. It includes the required properties, and
* shortcuts for accessing the attachment math class.
*/
class PartExport AttachExtension : public App::DocumentObjectExtension
{
EXTENSION_PROPERTY_HEADER_WITH_OVERRIDE(Part::AttachableObject);
public:
AttachExtension();
~AttachExtension() override;
/**
* @brief setAttacher sets the AttachEngine object. The class takes the
* ownership of the pointer, it will be deleted when the class is
* destroyed, or when a new attacher is set. The default attacher is AttachEngine3D.
* @param attacher. AttachableObject takes ownership and will delete it eventually.
*/
virtual void setAttacher(Attacher::AttachEngine* attacher);
/**
* @brief changeAttacherType
* @param typeName is the typename of new attacher class. Must be derived
* from Attacher::AttachEngine.
* @return true if attacher was changed. false if attacher is already of the
* type requested. Throws if invalid type is supplied.
*/
bool changeAttacherType(const char* typeName);
Attacher::AttachEngine &attacher() const {if(!_attacher) throw AttachEngineException("AttachableObject: no attacher is set."); return *_attacher;}
App::PropertyString AttacherType;
App::PropertyLinkSubList AttachmentSupport;
App::PropertyEnumeration MapMode; //see AttachEngine::eMapMode
App::PropertyBool MapReversed; //inverts Z and X internal axes
App::PropertyPlacement AttachmentOffset;
/**
* @brief MapPathParameter is a parameter value for mmNormalToPath (the
* sketch will be mapped normal to a curve at point specified by parameter
* (from 0.0 to 1.0, from start to end) )
*/
App::PropertyFloat MapPathParameter;
/** calculate and update the Placement property based on the AttachmentSupport, and
* mode. Can throw FreeCAD and OCC exceptions. Returns true if attached,
* false if not, throws if attachment failed.
*/
virtual bool positionBySupport();
/** Return whether this attacher is active
*/
bool isAttacherActive() const;
virtual bool isTouched_Mapping()
{return true; /*AttachmentSupport.isTouched isn't true when linked objects are changed... why?..*/}
short int extensionMustExecute() override;
App::DocumentObjectExecReturn *extensionExecute() override;
PyObject* getExtensionPyObject() override;
void onExtendedDocumentRestored() override;
protected:
void extensionOnChanged(const App::Property* /*prop*/) override;
virtual bool extensionHandleChangedPropertyName(Base::XMLReader &reader, const char * TypeName, const char *PropName) override;
App::PropertyPlacement& getPlacement() const;
public:
void updateAttacherVals();
private:
Attacher::AttachEngine* _attacher = nullptr;
mutable int _active = -1;
};
using AttachExtensionPython = App::ExtensionPythonT<AttachExtension>;
#endif
} // namespace Part
#endif // PARTATTACHABLEOBJECT_H
-7
View File
@@ -216,7 +216,6 @@ void Part::FaceMaker::postBuild() {
std::vector<Data::MappedName> names;
Data::ElementIDRefs sids;
#ifdef FC_USE_TNP_FIX
// To avoid name collision, we keep track of any used names to make sure
// to use at least 'minElementNames' number of unused element names to
// generate the face name.
@@ -229,12 +228,6 @@ void Part::FaceMaker::postBuild() {
break;
}
}
#else
// We just use the first source element name to make the face name more
// stable
names.push_back(edgeNames.begin()->name);
sids = edgeNames.begin()->sids;
#endif
this->myTopoShape.setElementComboName(
Data::IndexedName::fromConst("Face",index),names,op,nullptr,&sids);
}
-38
View File
@@ -55,44 +55,7 @@ App::DocumentObjectExecReturn *Chamfer::execute()
TopExp::MapShapesAndAncestors(baseShape, TopAbs_EDGE, TopAbs_FACE, mapEdgeFace);
TopTools_IndexedMapOfShape mapOfEdges;
TopExp::MapShapes(baseShape, TopAbs_EDGE, mapOfEdges);
#ifndef FC_USE_TNP_FIX
std::vector<FilletElement> values = Edges.getValues();
for (const auto & value : values) {
int id = value.edgeid;
double radius1 = value.radius1;
double radius2 = value.radius2;
const TopoDS_Edge& edge = TopoDS::Edge(mapOfEdges.FindKey(id));
const TopoDS_Face& face = TopoDS::Face(mapEdgeFace.FindFromKey(edge).First());
mkChamfer.Add(radius1, radius2, edge, face);
}
TopoDS_Shape shape = mkChamfer.Shape();
if (shape.IsNull())
return new App::DocumentObjectExecReturn("Resulting shape is null");
//shapefix re #4285
//https://www.forum.freecad.org/viewtopic.php?f=3&t=43890&sid=dae2fa6fda71670863a103b42739e47f
TopoShape* ts = new TopoShape(shape);
double minTol = 2.0 * Precision::Confusion();
double maxTol = 4.0 * Precision::Confusion();
bool rc = ts->fix(Precision::Confusion(), minTol, maxTol);
if (rc) {
shape = ts->getShape();
}
delete ts;
ShapeHistory history = buildHistory(mkChamfer, TopAbs_FACE, shape, baseShape);
this->Shape.setValue(shape);
// make sure the 'PropertyShapeHistory' is not safed in undo/redo (#0001889)
PropertyShapeHistory prop;
prop.setValue(history);
prop.setContainer(this);
prop.touch();
return App::DocumentObject::StdReturn;
#else
const auto &vals = EdgeLinks.getSubValues();
const auto &subs = EdgeLinks.getShadowSubs();
if(subs.size()!=(size_t)Edges.getSize())
@@ -124,7 +87,6 @@ App::DocumentObjectExecReturn *Chamfer::execute()
TopoShape res(0);
this->Shape.setValue(res.makeElementShape(mkChamfer,baseTopoShape,Part::OpCodes::Chamfer));
return Part::Feature::execute();
#endif
}
catch (Standard_Failure& e) {
return new App::DocumentObjectExecReturn(e.GetMessageString());
-40
View File
@@ -58,45 +58,6 @@ App::DocumentObjectExecReturn *Compound::execute()
// See also ViewProviderCompound::updateData
std::set<DocumentObject*> tempLinks;
#ifndef FC_USE_TNP_FIX
std::vector<ShapeHistory> history;
int countFaces = 0;
BRep_Builder builder;
TopoDS_Compound comp;
builder.MakeCompound(comp);
const std::vector<DocumentObject*>& links = Links.getValues();
for (auto link : links) {
if (link) {
auto pos = tempLinks.insert(link);
if (pos.second) {
const TopoDS_Shape& sh = Feature::getShape(link);
if (!sh.IsNull()) {
builder.Add(comp, sh);
TopTools_IndexedMapOfShape faceMap;
TopExp::MapShapes(sh, TopAbs_FACE, faceMap);
ShapeHistory hist;
hist.type = TopAbs_FACE;
for (int i=1; i<=faceMap.Extent(); i++) {
hist.shapeMap[i-1].push_back(countFaces++);
}
history.push_back(hist);
}
}
}
}
this->Shape.setValue(comp);
// make sure the 'PropertyShapeHistory' is not safed in undo/redo (#0001889)
PropertyShapeHistory prop;
prop.setValues(history);
prop.setContainer(this);
prop.touch();
return App::DocumentObject::StdReturn;
#else
std::vector<TopoShape> shapes;
for (auto obj : Links.getValues()) {
if (!tempLinks.insert(obj).second) {
@@ -109,7 +70,6 @@ App::DocumentObjectExecReturn *Compound::execute()
}
this->Shape.setValue(TopoShape().makeElementCompound(shapes));
return Part::Feature::execute();
#endif
}
catch (Standard_Failure& e) {
return new App::DocumentObjectExecReturn(e.GetMessageString());
-78
View File
@@ -303,83 +303,6 @@ Base::Vector3d Extrusion::calculateShapeNormal(const App::PropertyLink& shapeLin
void Extrusion::extrudeShape(TopoShape &result, const TopoShape &source, const ExtrusionParameters& params)
{
gp_Vec vec = gp_Vec(params.dir).Multiplied(params.lengthFwd + params.lengthRev);//total vector of extrusion
#ifndef FC_USE_TNP_FIX
if (std::fabs(params.taperAngleFwd) >= Precision::Angular() ||
std::fabs(params.taperAngleRev) >= Precision::Angular()) {
//Tapered extrusion!
#if defined(__GNUC__) && defined (FC_OS_LINUX)
Base::SignalException se;
#endif
TopoDS_Shape myShape = source.getShape();
if (myShape.IsNull())
Standard_Failure::Raise("Cannot extrude empty shape");
// #0000910: Circles Extrude Only Surfaces, thus use BRepBuilderAPI_Copy
myShape = BRepBuilderAPI_Copy(myShape).Shape();
std::list<TopoDS_Shape> drafts;
bool isPartDesign = false; // there is an OCC bug with single-edge wires (circles) we need to treat differently for PD and Part
ExtrusionHelper::makeDraft(myShape, params.dir, params.lengthFwd, params.lengthRev,
params.taperAngleFwd, params.taperAngleRev, params.solid, drafts, isPartDesign);
if (drafts.empty()) {
Standard_Failure::Raise("Drafting shape failed");
}
else if (drafts.size() == 1) {
result = drafts.front();
}
else {
TopoDS_Compound comp;
BRep_Builder builder;
builder.MakeCompound(comp);
for (const auto & draft : drafts)
builder.Add(comp, draft);
result = comp;
}
}
else {
//Regular (non-tapered) extrusion!
TopoDS_Shape myShape = source.getShape();
if (myShape.IsNull())
Standard_Failure::Raise("Cannot extrude empty shape");
// #0000910: Circles Extrude Only Surfaces, thus use BRepBuilderAPI_Copy
myShape = BRepBuilderAPI_Copy(myShape).Shape();
//apply reverse part of extrusion by shifting the source shape
if (fabs(params.lengthRev) > Precision::Confusion()) {
gp_Trsf mov;
mov.SetTranslation(gp_Vec(params.dir) * (-params.lengthRev));
TopLoc_Location loc(mov);
myShape.Move(loc);
}
//make faces from wires
if (params.solid) {
//test if we need to make faces from wires. If there are faces - we don't.
TopExp_Explorer xp(myShape, TopAbs_FACE);
if (xp.More()) {
//source shape has faces. Just extrude as-is.
}
else {
std::unique_ptr<FaceMaker> mkFace = FaceMaker::ConstructFromType(params.faceMakerClass.c_str());
if (myShape.ShapeType() == TopAbs_COMPOUND)
mkFace->useCompound(TopoDS::Compound(myShape));
else
mkFace->addShape(myShape);
mkFace->Build();
myShape = mkFace->Shape();
}
}
//extrude!
BRepPrimAPI_MakePrism mkPrism(myShape, vec);
result = mkPrism.Shape();
}
if (result.isNull())
throw NullShapeException("Result of extrusion is null shape.");
// return TopoShape(result);
#else
// #0000910: Circles Extrude Only Surfaces, thus use BRepBuilderAPI_Copy
TopoShape myShape(source.makeElementCopy());
@@ -428,7 +351,6 @@ void Extrusion::extrudeShape(TopoShape &result, const TopoShape &source, const E
// extrude!
result.makeElementPrism(myShape, vec);
}
#endif
}
App::DocumentObjectExecReturn* Extrusion::execute()
-38
View File
@@ -61,43 +61,6 @@ App::DocumentObjectExecReturn *Fillet::execute()
TopExp::MapShapes(baseShape, TopAbs_EDGE, mapOfShape);
TopTools_IndexedMapOfShape mapOfEdges;
TopExp::MapShapes(baseShape, TopAbs_EDGE, mapOfEdges);
#ifndef FC_USE_TNP_FIX
std::vector<FilletElement> values = Edges.getValues();
for (const auto & value : values) {
int id = value.edgeid;
double radius1 = value.radius1;
double radius2 = value.radius2;
const TopoDS_Edge& edge = TopoDS::Edge(mapOfShape.FindKey(id));
mkFillet.Add(radius1, radius2, edge);
}
TopoDS_Shape shape = mkFillet.Shape();
if (shape.IsNull())
return new App::DocumentObjectExecReturn("Resulting shape is null");
//shapefix re #4285
//https://www.forum.freecad.org/viewtopic.php?f=3&t=43890&sid=dae2fa6fda71670863a103b42739e47f
TopoShape* ts = new TopoShape(shape);
double minTol = 2.0 * Precision::Confusion();
double maxTol = 4.0 * Precision::Confusion();
bool rc = ts->fix(Precision::Confusion(), minTol, maxTol);
if (rc) {
shape = ts->getShape();
}
delete ts;
ShapeHistory history = buildHistory(mkFillet, TopAbs_FACE, shape, baseShape);
this->Shape.setValue(shape);
// make sure the 'PropertyShapeHistory' is not safed in undo/redo (#0001889)
PropertyShapeHistory prop;
prop.setValue(history);
prop.setContainer(this);
prop.touch();
return App::DocumentObject::StdReturn;
#else
const auto &vals = EdgeLinks.getSubValues();
const auto &subs = EdgeLinks.getShadowSubs();
if(subs.size()!=(size_t)Edges.getSize())
@@ -128,7 +91,6 @@ App::DocumentObjectExecReturn *Fillet::execute()
TopoShape res(0);
this->Shape.setValue(res.makeElementShape(mkFillet,baseTopoShape,Part::OpCodes::Fillet));
return Part::Feature::execute();
#endif
}
catch (Standard_Failure& e) {
return new App::DocumentObjectExecReturn(e.GetMessageString());
-14
View File
@@ -253,25 +253,11 @@ App::DocumentObjectExecReturn *Mirroring::execute()
try {
gp_Ax2 ax2(gp_Pnt(base.x,base.y,base.z), gp_Dir(norm.x,norm.y,norm.z));
#ifndef FC_USE_TNP_FIX
const TopoDS_Shape& shape = Feature::getShape(link);
if (shape.IsNull())
Standard_Failure::Raise(std::string(std::string(this->getFullLabel()) + ": Cannot mirror empty shape").c_str());
gp_Trsf mat;
mat.SetMirror(ax2);
TopLoc_Location loc = shape.Location();
gp_Trsf placement = loc.Transformation();
mat = placement * mat;
BRepBuilderAPI_Transform mkTrf(shape, mat);
this->Shape.setValue(mkTrf.Shape());
return App::DocumentObject::StdReturn;
#else
auto shape = Feature::getTopoShape(link);
if (shape.isNull())
Standard_Failure::Raise("Cannot mirror empty shape");
this->Shape.setValue(TopoShape(0).makeElementMirror(shape,ax2));
return Part::Feature::execute();
#endif
}
catch (Standard_Failure& e) {
return new App::DocumentObjectExecReturn(e.GetMessageString());
-9
View File
@@ -85,21 +85,12 @@ App::DocumentObjectExecReturn *Offset::execute()
bool self = SelfIntersection.getValue();
short mode = (short)Mode.getValue();
bool fill = Fill.getValue();
#ifndef FC_USE_TNP_FIX
short join = (short)Join.getValue();
const TopoShape& shape = Feature::getShape(source);
if (fabs(offset) > 2*tol)
this->Shape.setValue(shape.makeOffsetShape(offset, tol, inter, self, mode, join, fill));
else
this->Shape.setValue(shape);
#else
auto shape = Feature::getTopoShape(source);
if(shape.isNull())
return new App::DocumentObjectExecReturn("Invalid source link");
auto join = static_cast<JoinType>(Join.getValue());
this->Shape.setValue(TopoShape(0).makeElementOffset(
shape,offset,tol,inter,self,mode,join,fill ? FillType::fill : FillType::noFill));
#endif
return App::DocumentObject::StdReturn;
}
-24
View File
@@ -130,29 +130,6 @@ App::DocumentObjectExecReturn* Boolean::execute()
return new App::DocumentObjectExecReturn("Resulting shape is invalid");
}
}
#ifndef FC_USE_TNP_FIX
std::vector<ShapeHistory> history;
history.push_back(buildHistory(*mkBool, TopAbs_FACE, resShape, BaseShape));
history.push_back(buildHistory(*mkBool, TopAbs_FACE, resShape, ToolShape));
if (this->Refine.getValue()) {
try {
TopoDS_Shape oldShape = resShape;
BRepBuilderAPI_RefineModel mkRefine(oldShape);
resShape = mkRefine.Shape();
ShapeHistory hist = buildHistory(mkRefine, TopAbs_FACE, resShape, oldShape);
history[0] = joinHistory(history[0], hist);
history[1] = joinHistory(history[1], hist);
}
catch (Standard_Failure&) {
// do nothing
}
}
this->Shape.setValue(resShape);
this->History.setValues(history);
return App::DocumentObject::StdReturn;
#else
TopoShape res(0);
res.makeElementShape(*mkBool, shapes, opCode());
if (this->Refine.getValue()) {
@@ -160,7 +137,6 @@ App::DocumentObjectExecReturn* Boolean::execute()
}
this->Shape.setValue(res);
return Part::Feature::execute();
#endif
}
catch (...) {
return new App::DocumentObjectExecReturn(
+1 -118
View File
@@ -86,122 +86,6 @@ short MultiCommon::mustExecute() const
App::DocumentObjectExecReturn *MultiCommon::execute()
{
#ifndef FC_USE_TNP_FIX
std::vector<TopoDS_Shape> s;
std::vector<App::DocumentObject*> obj = Shapes.getValues();
std::vector<App::DocumentObject*>::iterator it;
for (it = obj.begin(); it != obj.end(); ++it) {
s.push_back(Feature::getShape(*it));
}
bool argumentsAreInCompound = false;
TopoDS_Shape compoundOfArguments;
//if only one source shape, and it is a compound - fuse children of the compound
if (s.size() == 1){
compoundOfArguments = s[0];
if (compoundOfArguments.ShapeType() == TopAbs_COMPOUND){
s.clear();
TopoDS_Iterator it(compoundOfArguments);
for (; it.More(); it.Next()) {
const TopoDS_Shape& aChild = it.Value();
s.push_back(aChild);
}
argumentsAreInCompound = true;
}
}
if (s.size() >= 2) {
try {
std::vector<ShapeHistory> history;
TopoDS_Shape resShape = s.front();
if (resShape.IsNull())
throw NullShapeException("Input shape is null");
for (std::vector<TopoDS_Shape>::iterator it = s.begin()+1; it != s.end(); ++it) {
if (it->IsNull())
throw Base::RuntimeError("Input shape is null");
// Let's call algorithm computing a fuse operation:
BRepAlgoAPI_Common mkCommon(resShape, *it);
// Let's check if the fusion has been successful
if (!mkCommon.IsDone())
throw BooleanException("Intersection failed");
resShape = mkCommon.Shape();
ShapeHistory hist1 = buildHistory(mkCommon, TopAbs_FACE, resShape, mkCommon.Shape1());
ShapeHistory hist2 = buildHistory(mkCommon, TopAbs_FACE, resShape, mkCommon.Shape2());
if (history.empty()) {
history.push_back(hist1);
history.push_back(hist2);
}
else {
for (auto & jt : history)
jt = joinHistory(jt, hist1);
history.push_back(hist2);
}
}
if (resShape.IsNull())
throw NullShapeException("Resulting shape is invalid");
Base::Reference<ParameterGrp> hGrp = App::GetApplication().GetUserParameter()
.GetGroup("BaseApp")->GetGroup("Preferences")->GetGroup("Mod/Part/Boolean");
if (hGrp->GetBool("CheckModel", true)) {
BRepCheck_Analyzer aChecker(resShape);
if (! aChecker.IsValid() ) {
return new App::DocumentObjectExecReturn("Resulting shape is invalid");
}
}
if (this->Refine.getValue()) {
try {
TopoDS_Shape oldShape = resShape;
BRepBuilderAPI_RefineModel mkRefine(oldShape);
resShape = mkRefine.Shape();
ShapeHistory hist = buildHistory(mkRefine, TopAbs_FACE, resShape, oldShape);
for (auto & jt : history)
jt = joinHistory(jt, hist);
}
catch (Standard_Failure&) {
// do nothing
}
}
this->Shape.setValue(resShape);
if (argumentsAreInCompound){
//combine histories of every child of source compound into one
ShapeHistory overallHist;
TopTools_IndexedMapOfShape facesOfCompound;
TopAbs_ShapeEnum type = TopAbs_FACE;
TopExp::MapShapes(compoundOfArguments, type, facesOfCompound);
for (std::size_t iChild = 0; iChild < history.size(); iChild++){ //loop over children of source compound
//for each face of a child, find the inex of the face in compound, and assign the corresponding right-hand-size of the history
TopTools_IndexedMapOfShape facesOfChild;
TopExp::MapShapes(s[iChild], type, facesOfChild);
for(std::pair<const int,ShapeHistory::List> &histitem: history[iChild].shapeMap){ //loop over elements of history - that is - over faces of the child of source compound
int iFaceInChild = histitem.first;
ShapeHistory::List &iFacesInResult = histitem.second;
TopoDS_Shape srcFace = facesOfChild(iFaceInChild + 1); //+1 to convert our 0-based to OCC 1-bsed conventions
int iFaceInCompound = facesOfCompound.FindIndex(srcFace)-1;
overallHist.shapeMap[iFaceInCompound] = iFacesInResult; //this may overwrite existing info if the same face is used in several children of compound. This shouldn't be a problem, because the histories should match anyway...
}
}
history.clear();
history.push_back(overallHist);
}
this->History.setValues(history);
}
catch (Standard_Failure& e) {
return new App::DocumentObjectExecReturn(e.GetMessageString());
}
}
else {
throw Base::CADKernelError("Not enough shape objects linked");
}
return App::DocumentObject::StdReturn;
#else
std::vector<TopoShape> shapes;
for (auto obj : Shapes.getValues()) {
TopoShape sh = Feature::getTopoShape(obj);
@@ -222,7 +106,7 @@ App::DocumentObjectExecReturn *MultiCommon::execute()
.GetGroup("BaseApp")
->GetGroup("Preferences")
->GetGroup("Mod/Part/Boolean");
if (hGrp->GetBool("CheckModel", true)) {
if (hGrp->GetBool("CheckModel", false)) {
BRepCheck_Analyzer aChecker(res.getShape());
if (!aChecker.IsValid()) {
return new App::DocumentObjectExecReturn("Resulting shape is invalid");
@@ -235,5 +119,4 @@ App::DocumentObjectExecReturn *MultiCommon::execute()
this->Shape.setValue(res);
return Part::Feature::execute();
#endif
}
-115
View File
@@ -90,120 +90,6 @@ short MultiFuse::mustExecute() const
App::DocumentObjectExecReturn *MultiFuse::execute()
{
#ifndef FC_USE_TNP_FIX
std::vector<TopoDS_Shape> shapes;
std::vector<App::DocumentObject*> obj = Shapes.getValues();
std::vector<App::DocumentObject*>::iterator it;
for (it = obj.begin(); it != obj.end(); ++it) {
shapes.push_back(Feature::getShape(*it));
}
bool argumentsAreInCompound = false;
TopoDS_Shape compoundOfArguments;
//if only one source shape, and it is a compound - fuse children of the compound
if (shapes.size() == 1){
compoundOfArguments = shapes[0];
if (compoundOfArguments.ShapeType() == TopAbs_COMPOUND){
shapes.clear();
TopoDS_Iterator it2(compoundOfArguments);
for (; it2.More(); it2.Next()) {
const TopoDS_Shape& aChild = it2.Value();
shapes.push_back(aChild);
}
argumentsAreInCompound = true;
}
}
if (shapes.size() >= 2) {
try {
std::vector<ShapeHistory> history;
BRepAlgoAPI_Fuse mkFuse;
TopTools_ListOfShape shapeArguments,shapeTools;
const TopoDS_Shape& shape = shapes.front();
if (shape.IsNull())
throw Base::RuntimeError("Input shape is null");
shapeArguments.Append(shape);
for (auto it2 = shapes.begin()+1; it2 != shapes.end(); ++it2) {
if (it2->IsNull())
throw Base::RuntimeError("Input shape is null");
shapeTools.Append(*it2);
}
mkFuse.SetArguments(shapeArguments);
mkFuse.SetTools(shapeTools);
mkFuse.SetRunParallel(true);
mkFuse.Build();
if (!mkFuse.IsDone())
throw Base::RuntimeError("MultiFusion failed");
TopoDS_Shape resShape = mkFuse.Shape();
for (const auto & it2 : shapes) {
history.push_back(buildHistory(mkFuse, TopAbs_FACE, resShape, it2));
}
if (resShape.IsNull())
throw Base::RuntimeError("Resulting shape is null");
Base::Reference<ParameterGrp> hGrp = App::GetApplication().GetUserParameter()
.GetGroup("BaseApp")->GetGroup("Preferences")->GetGroup("Mod/Part/Boolean");
if (hGrp->GetBool("CheckModel", true)) {
BRepCheck_Analyzer aChecker(resShape);
if (! aChecker.IsValid() ) {
return new App::DocumentObjectExecReturn("Resulting shape is invalid");
}
}
if (this->Refine.getValue()) {
try {
TopoDS_Shape oldShape = resShape;
BRepBuilderAPI_RefineModel mkRefine(oldShape);
resShape = mkRefine.Shape();
ShapeHistory hist = buildHistory(mkRefine, TopAbs_FACE, resShape, oldShape);
for (auto & jt : history)
jt = joinHistory(jt, hist);
}
catch (Standard_Failure&) {
// do nothing
}
}
this->Shape.setValue(resShape);
if (argumentsAreInCompound){
//combine histories of every child of source compound into one
ShapeHistory overallHist;
TopTools_IndexedMapOfShape facesOfCompound;
TopAbs_ShapeEnum type = TopAbs_FACE;
TopExp::MapShapes(compoundOfArguments, type, facesOfCompound);
for (std::size_t iChild = 0; iChild < history.size(); iChild++){ //loop over children of source compound
//for each face of a child, find the inex of the face in compound, and assign the corresponding right-hand-size of the history
TopTools_IndexedMapOfShape facesOfChild;
TopExp::MapShapes(shapes[iChild], type, facesOfChild);
for(std::pair<const int,ShapeHistory::List> &histitem: history[iChild].shapeMap){ //loop over elements of history - that is - over faces of the child of source compound
int iFaceInChild = histitem.first;
ShapeHistory::List &iFacesInResult = histitem.second;
const TopoDS_Shape& srcFace = facesOfChild(iFaceInChild + 1); //+1 to convert our 0-based to OCC 1-bsed conventions
int iFaceInCompound = facesOfCompound.FindIndex(srcFace)-1;
overallHist.shapeMap[iFaceInCompound] = iFacesInResult; //this may overwrite existing info if the same face is used in several children of compound. This shouldn't be a problem, because the histories should match anyway...
}
}
history.clear();
history.push_back(overallHist);
}
this->History.setValues(history);
}
catch (Standard_Failure& e) {
return new App::DocumentObjectExecReturn(e.GetMessageString());
}
}
else {
throw Base::CADKernelError("Not enough shape objects linked");
}
return App::DocumentObject::StdReturn;
#else
std::vector<TopoShape> shapes;
std::vector<App::DocumentObject*> obj = Shapes.getValues();
@@ -331,5 +217,4 @@ App::DocumentObjectExecReturn *MultiFuse::execute()
else {
throw Base::CADKernelError("Not enough shape objects linked");
}
#endif
}
-35
View File
@@ -156,40 +156,6 @@ App::DocumentObjectExecReturn *Revolution::execute()
TopLoc_Location loc(mov);
sourceShape.setShape(sourceShape.getShape().Moved(loc));
}
#ifndef FC_USE_TNP_FIX
//"make solid" processing: make faces from wires.
Standard_Boolean makeSolid = Solid.getValue() ? Standard_True : Standard_False;
if (makeSolid){
//test if we need to make faces from wires. If there are faces - we don't.
TopExp_Explorer xp(sourceShape.getShape(), TopAbs_FACE);
if (xp.More())
//source shape has faces. Just revolve as-is.
makeSolid = Standard_False;
}
if (makeSolid && strlen(this->FaceMakerClass.getValue())>0){
//new facemaking behavior: use facemaker class
std::unique_ptr<FaceMaker> mkFace = FaceMaker::ConstructFromType(this->FaceMakerClass.getValue());
TopoDS_Shape myShape = sourceShape.getShape();
if(myShape.ShapeType() == TopAbs_COMPOUND)
mkFace->useCompound(TopoDS::Compound(myShape));
else
mkFace->addShape(myShape);
mkFace->Build();
myShape = mkFace->Shape();
sourceShape = TopoShape(myShape);
makeSolid = Standard_False;//don't ask TopoShape::revolve to make solid, as we've made faces...
}
// actual revolution!
TopoDS_Shape revolve = sourceShape.revolve(revAx, angle, makeSolid);
if (revolve.IsNull())
return new App::DocumentObjectExecReturn("Resulting shape is null");
this->Shape.setValue(revolve);
return App::DocumentObject::StdReturn;
#else
TopoShape revolve(0);
revolve.makeElementRevolve(sourceShape,
revAx,
@@ -200,7 +166,6 @@ App::DocumentObjectExecReturn *Revolution::execute()
}
this->Shape.setValue(revolve);
return Part::Feature::execute();
#endif
}
catch (Standard_Failure& e) {
return new App::DocumentObjectExecReturn(e.GetMessageString());
+2 -23
View File
@@ -1257,7 +1257,6 @@ TopoShape Feature::getTopoShape(const App::DocumentObject* obj,
noElementMap,
hiddens,
lastLink);
#ifdef FC_USE_TNP_FIX
if (needSubElement && shape.shapeType(true) == TopAbs_COMPOUND) {
if (shape.countSubShapes(TopAbs_SOLID) == 1)
shape = shape.getSubTopoShape(TopAbs_SOLID, 1);
@@ -1274,7 +1273,6 @@ TopoShape Feature::getTopoShape(const App::DocumentObject* obj,
else if (shape.countSubShapes(TopAbs_VERTEX) == 1)
shape = shape.getSubTopoShape(TopAbs_VERTEX, 1);
}
#endif
Base::Matrix4D topMat;
if (pmat || transform) {
// Obtain top level transformation
@@ -1426,7 +1424,6 @@ void Feature::onChanged(const App::Property* prop)
{
// if the placement has changed apply the change to the point data as well
if (prop == &this->Placement) {
#ifdef FC_USE_TNP_FIX
TopoShape shape = this->Shape.getShape();
auto oldTransform = shape.getTransform();
auto newTransform = this->Placement.getValue().toMatrix();
@@ -1437,19 +1434,11 @@ void Feature::onChanged(const App::Property* prop)
if ( oldTransform != newTransform) {
this->Shape.setValue(shape);
}
#else
this->Shape.setTransform(this->Placement.getValue().toMatrix());
#endif
}
// if the point data has changed check and adjust the transformation as well
else if (prop == &this->Shape) {
if (this->isRecomputing()) {
#ifdef FC_USE_TNP_FIX
this->Shape._Shape.setTransform(this->Placement.getValue().toMatrix());
#else
this->Shape.setTransform(this->Placement.getValue().toMatrix());
#endif
}
else {
Base::Placement p;
@@ -1457,13 +1446,7 @@ void Feature::onChanged(const App::Property* prop)
if (!this->Shape.getValue().IsNull()) {
try {
p.fromMatrix(this->Shape.getShape().getTransform());
#ifdef FC_USE_TNP_FIX
this->Placement.setValueIfChanged(p);
#else
if (p != this->Placement.getValue()) {
this->Placement.setValue(p);
}
#endif
}
catch (const Base::ValueError&) {
}
@@ -1474,7 +1457,6 @@ void Feature::onChanged(const App::Property* prop)
GeoFeature::onChanged(prop);
}
#ifdef FC_USE_TNP_FIX
const std::vector<std::string>& Feature::searchElementCache(const std::string& element,
Data::SearchOptions options,
@@ -1518,7 +1500,7 @@ const std::vector<std::string>& Feature::searchElementCache(const std::string& e
}
return it->second.names;
}
#endif
TopLoc_Location Feature::getLocation() const
{
Base::Placement pl = this->Placement.getValue();
@@ -1639,11 +1621,8 @@ const App::PropertyComplexGeoData* Feature::getPropertyOfGeometry() const
bool Feature::isElementMappingDisabled(App::PropertyContainer* container)
{
(void)container;
#ifdef FC_USE_TNP_FIX
return false;
#else
return true;
#endif
// TODO: March 2024 consider if any of this RT branch logic makes sense:
// if (!container) {
// return false;
-3
View File
@@ -157,13 +157,10 @@ public:
static void guessNewLink(std::string &replacementName, DocumentObject *base, const char *oldLink);
#ifdef FC_USE_TNP_FIX
const std::vector<std::string>& searchElementCache(const std::string &element,
Data::SearchOptions options = Data::SearchOption::CheckGeometry,
double tol = 1e-7,
double atol = 1e-10) const override;
#endif
protected:
/// recompute only this object
App::DocumentObjectExecReturn *recompute() override;
-419
View File
@@ -123,7 +123,6 @@ App::DocumentObjectExecReturn* RuledSurface::getShape(const App::PropertyLinkSub
App::DocumentObjectExecReturn* RuledSurface::execute()
{
try {
#ifdef FC_USE_TNP_FIX
std::vector<TopoShape> shapes;
std::array<App::PropertyLinkSub*, 2> links = {&Curve1, &Curve2};
for (auto link : links) {
@@ -146,134 +145,6 @@ App::DocumentObjectExecReturn* RuledSurface::execute()
this->Shape.setValue(res);
return Part::Feature::execute();
#else
App::DocumentObjectExecReturn* ret;
// get the first input shape
TopoDS_Shape S1;
ret = getShape(Curve1, S1);
if (ret) {
return ret;
}
// get the second input shape
TopoDS_Shape S2;
ret = getShape(Curve2, S2);
if (ret) {
return ret;
}
// check for expected type
if (S1.IsNull() || S2.IsNull()) {
return new App::DocumentObjectExecReturn("Linked shapes are empty.");
}
if (S1.ShapeType() != TopAbs_EDGE && S1.ShapeType() != TopAbs_WIRE) {
return new App::DocumentObjectExecReturn("Linked shape is neither edge nor wire.");
}
if (S2.ShapeType() != TopAbs_EDGE && S2.ShapeType() != TopAbs_WIRE) {
return new App::DocumentObjectExecReturn("Linked shape is neither edge nor wire.");
}
// https://forum.freecad.org/viewtopic.php?f=8&t=24052
//
// if both shapes are sub-elements of one common shape then the fill algorithm
// leads to problems if the shape has set a placement
// The workaround is to copy the sub-shape
S1 = BRepBuilderAPI_Copy(S1).Shape();
S2 = BRepBuilderAPI_Copy(S2).Shape();
// make both shapes to have the same type
Standard_Boolean isWire = Standard_False;
if (S1.ShapeType() == TopAbs_WIRE) {
isWire = Standard_True;
}
if (isWire) {
if (S2.ShapeType() == TopAbs_EDGE) {
S2 = BRepLib_MakeWire(TopoDS::Edge(S2));
}
}
else {
// S1 is an edge, if S2 is a wire convert S1 to a wire, too
if (S2.ShapeType() == TopAbs_WIRE) {
S1 = BRepLib_MakeWire(TopoDS::Edge(S1));
isWire = Standard_True;
}
}
if (Orientation.getValue() == 0) {
// Automatic
std::unique_ptr<Adaptor3d_Curve> a1;
std::unique_ptr<Adaptor3d_Curve> a2;
if (!isWire) {
a1 = std::make_unique<BRepAdaptor_Curve>(TopoDS::Edge(S1));
a2 = std::make_unique<BRepAdaptor_Curve>(TopoDS::Edge(S2));
}
else {
a1 = std::make_unique<BRepAdaptor_CompCurve>(TopoDS::Wire(S1));
a2 = std::make_unique<BRepAdaptor_CompCurve>(TopoDS::Wire(S2));
}
if (a1 && a2) {
// get end points of 1st curve
Standard_Real first, last;
first = a1->FirstParameter();
last = a1->LastParameter();
if (S1.Closed()) {
last = (first + last) / 2;
}
gp_Pnt p1 = a1->Value(first);
gp_Pnt p2 = a1->Value(last);
if (S1.Orientation() == TopAbs_REVERSED) {
std::swap(p1, p2);
}
// get end points of 2nd curve
first = a2->FirstParameter();
last = a2->LastParameter();
if (S2.Closed()) {
last = (first + last) / 2;
}
gp_Pnt p3 = a2->Value(first);
gp_Pnt p4 = a2->Value(last);
if (S2.Orientation() == TopAbs_REVERSED) {
std::swap(p3, p4);
}
// Form two triangles (P1,P2,P3) and (P4,P3,P2) and check their normals.
// If the dot product is negative then it's assumed that the resulting face
// is twisted, hence the 2nd edge is reversed.
gp_Vec v1(p1, p2);
gp_Vec v2(p1, p3);
gp_Vec n1 = v1.Crossed(v2);
gp_Vec v3(p4, p3);
gp_Vec v4(p4, p2);
gp_Vec n2 = v3.Crossed(v4);
if (n1.Dot(n2) < 0) {
S2.Reverse();
}
}
}
else if (Orientation.getValue() == 2) {
// Reverse
S2.Reverse();
}
TopoDS_Shape ruledShape;
if (!isWire) {
ruledShape = BRepFill::Face(TopoDS::Edge(S1), TopoDS::Edge(S2));
}
else {
ruledShape = BRepFill::Shell(TopoDS::Wire(S1), TopoDS::Wire(S2));
}
this->Shape.setValue(ruledShape);
return App::DocumentObject::StdReturn;
#endif
}
catch (Standard_Failure& e) {
@@ -337,7 +208,6 @@ App::DocumentObjectExecReturn* Loft::execute()
}
try {
#ifdef FC_USE_TNP_FIX
std::vector<TopoShape> shapes;
for (auto& obj : Sections.getValues()) {
shapes.emplace_back(getTopoShape(obj));
@@ -356,79 +226,6 @@ App::DocumentObjectExecReturn* Loft::execute()
}
this->Shape.setValue(result);
return Part::Feature::execute();
#else
TopTools_ListOfShape profiles;
const std::vector<App::DocumentObject*>& shapes = Sections.getValues();
std::vector<App::DocumentObject*>::const_iterator it;
for (it = shapes.begin(); it != shapes.end(); ++it) {
TopoDS_Shape shape = Feature::getShape(*it);
if (shape.IsNull()) {
return new App::DocumentObjectExecReturn("Linked shape is invalid.");
}
// Allow compounds with a single face, wire or vertex or
// if there are only edges building one wire
if (shape.ShapeType() == TopAbs_COMPOUND) {
Handle(TopTools_HSequenceOfShape) hEdges = new TopTools_HSequenceOfShape();
Handle(TopTools_HSequenceOfShape) hWires = new TopTools_HSequenceOfShape();
TopoDS_Iterator it(shape);
int numChilds = 0;
TopoDS_Shape child;
for (; it.More(); it.Next(), numChilds++) {
if (!it.Value().IsNull()) {
child = it.Value();
if (child.ShapeType() == TopAbs_EDGE) {
hEdges->Append(child);
}
}
}
// a single child
if (numChilds == 1) {
shape = child;
}
// or all children are edges
else if (hEdges->Length() == numChilds) {
ShapeAnalysis_FreeBounds::ConnectEdgesToWires(hEdges,
Precision::Confusion(),
Standard_False,
hWires);
if (hWires->Length() == 1) {
shape = hWires->Value(1);
}
}
}
if (shape.ShapeType() == TopAbs_FACE) {
TopoDS_Wire faceouterWire = ShapeAnalysis::OuterWire(TopoDS::Face(shape));
profiles.Append(faceouterWire);
}
else if (shape.ShapeType() == TopAbs_WIRE) {
BRepBuilderAPI_MakeWire mkWire(TopoDS::Wire(shape));
profiles.Append(mkWire.Wire());
}
else if (shape.ShapeType() == TopAbs_EDGE) {
BRepBuilderAPI_MakeWire mkWire(TopoDS::Edge(shape));
profiles.Append(mkWire.Wire());
}
else if (shape.ShapeType() == TopAbs_VERTEX) {
profiles.Append(shape);
}
else {
return new App::DocumentObjectExecReturn(
"Linked shape is not a vertex, edge, wire nor face.");
}
}
Standard_Boolean isSolid = Solid.getValue() ? Standard_True : Standard_False;
Standard_Boolean isRuled = Ruled.getValue() ? Standard_True : Standard_False;
Standard_Boolean isClosed = Closed.getValue() ? Standard_True : Standard_False;
int degMax = MaxDegree.getValue();
TopoShape myShape;
this->Shape.setValue(myShape.makeLoft(profiles, isSolid, isRuled, isClosed, degMax));
return App::DocumentObject::StdReturn;
#endif
}
catch (Standard_Failure& e) {
@@ -494,7 +291,6 @@ App::DocumentObjectExecReturn* Sweep::execute()
if (Sections.getSize() == 0) {
return new App::DocumentObjectExecReturn("No sections linked.");
}
#ifdef FC_USE_TNP_FIX
if (!Spine.getValue()) {
return new App::DocumentObjectExecReturn("No spine");
}
@@ -533,182 +329,6 @@ App::DocumentObjectExecReturn* Sweep::execute()
}
this->Shape.setValue(result);
return App::DocumentObject::StdReturn;
#else
App::DocumentObject* spine = Spine.getValue();
if (!spine) {
return new App::DocumentObjectExecReturn("No spine linked.");
}
const std::vector<std::string>& subedge = Spine.getSubValues();
TopoDS_Shape path;
const Part::TopoShape& shape = Feature::getTopoShape(spine);
if (!shape.getShape().IsNull()) {
try {
if (!subedge.empty()) {
BRepBuilderAPI_MakeWire mkWire;
for (const auto& it : subedge) {
TopoDS_Shape subshape =
Feature::getTopoShape(spine, it.c_str(), true /*need element*/).getShape();
mkWire.Add(TopoDS::Edge(subshape));
}
path = mkWire.Wire();
}
else if (shape.getShape().ShapeType() == TopAbs_EDGE) {
path = shape.getShape();
}
else if (shape.getShape().ShapeType() == TopAbs_WIRE) {
BRepBuilderAPI_MakeWire mkWire(TopoDS::Wire(shape.getShape()));
path = mkWire.Wire();
}
else if (shape.getShape().ShapeType() == TopAbs_COMPOUND) {
TopoDS_Iterator it(shape.getShape());
for (; it.More(); it.Next()) {
if (it.Value().IsNull()) {
return new App::DocumentObjectExecReturn("In valid element in spine.");
}
if ((it.Value().ShapeType() != TopAbs_EDGE)
&& (it.Value().ShapeType() != TopAbs_WIRE)) {
return new App::DocumentObjectExecReturn(
"Element in spine is neither an edge nor a wire.");
}
}
Handle(TopTools_HSequenceOfShape) hEdges = new TopTools_HSequenceOfShape();
Handle(TopTools_HSequenceOfShape) hWires = new TopTools_HSequenceOfShape();
for (TopExp_Explorer xp(shape.getShape(), TopAbs_EDGE); xp.More(); xp.Next()) {
hEdges->Append(xp.Current());
}
ShapeAnalysis_FreeBounds::ConnectEdgesToWires(hEdges,
Precision::Confusion(),
Standard_True,
hWires);
int len = hWires->Length();
if (len != 1) {
return new App::DocumentObjectExecReturn("Spine is not connected.");
}
path = hWires->Value(1);
}
else {
return new App::DocumentObjectExecReturn("Spine is neither an edge nor a wire.");
}
}
catch (Standard_Failure&) {
return new App::DocumentObjectExecReturn("Invalid spine.");
}
}
try {
TopTools_ListOfShape profiles;
const std::vector<App::DocumentObject*>& shapes = Sections.getValues();
std::vector<App::DocumentObject*>::const_iterator it;
for (it = shapes.begin(); it != shapes.end(); ++it) {
TopoDS_Shape shape = Feature::getShape(*it);
if (shape.IsNull()) {
return new App::DocumentObjectExecReturn("Linked shape is invalid.");
}
// Allow compounds with a single face, wire or vertex or
// if there are only edges building one wire
if (shape.ShapeType() == TopAbs_COMPOUND) {
Handle(TopTools_HSequenceOfShape) hEdges = new TopTools_HSequenceOfShape();
Handle(TopTools_HSequenceOfShape) hWires = new TopTools_HSequenceOfShape();
TopoDS_Iterator it(shape);
int numChilds = 0;
TopoDS_Shape child;
for (; it.More(); it.Next(), numChilds++) {
if (!it.Value().IsNull()) {
child = it.Value();
if (child.ShapeType() == TopAbs_EDGE) {
hEdges->Append(child);
}
}
}
// a single child
if (numChilds == 1) {
shape = child;
}
// or all children are edges
else if (hEdges->Length() == numChilds) {
ShapeAnalysis_FreeBounds::ConnectEdgesToWires(hEdges,
Precision::Confusion(),
Standard_False,
hWires);
if (hWires->Length() == 1) {
shape = hWires->Value(1);
}
}
}
// There is a weird behaviour of BRepOffsetAPI_MakePipeShell when trying to add the wire
// as is. If we re-create the wire then everything works fine.
// https://forum.freecad.org/viewtopic.php?f=10&t=2673&sid=fbcd2ff4589f0b2f79ed899b0b990648#p20268
if (shape.ShapeType() == TopAbs_FACE) {
TopoDS_Wire faceouterWire = ShapeAnalysis::OuterWire(TopoDS::Face(shape));
profiles.Append(faceouterWire);
}
else if (shape.ShapeType() == TopAbs_WIRE) {
BRepBuilderAPI_MakeWire mkWire(TopoDS::Wire(shape));
profiles.Append(mkWire.Wire());
}
else if (shape.ShapeType() == TopAbs_EDGE) {
BRepBuilderAPI_MakeWire mkWire(TopoDS::Edge(shape));
profiles.Append(mkWire.Wire());
}
else if (shape.ShapeType() == TopAbs_VERTEX) {
profiles.Append(shape);
}
else {
return new App::DocumentObjectExecReturn(
"Linked shape is not a vertex, edge, wire nor face.");
}
}
Standard_Boolean isSolid = Solid.getValue() ? Standard_True : Standard_False;
Standard_Boolean isFrenet = Frenet.getValue() ? Standard_True : Standard_False;
BRepBuilderAPI_TransitionMode transMode;
switch (Transition.getValue()) {
case 1:
transMode = BRepBuilderAPI_RightCorner;
break;
case 2:
transMode = BRepBuilderAPI_RoundCorner;
break;
default:
transMode = BRepBuilderAPI_Transformed;
break;
}
if (path.IsNull()) {
return new App::DocumentObjectExecReturn(
"Spine path missing, sweep operation stopped.");
}
if (path.ShapeType() == TopAbs_EDGE) {
BRepBuilderAPI_MakeWire mkWire(TopoDS::Edge(path));
path = mkWire.Wire();
}
BRepOffsetAPI_MakePipeShell mkPipeShell(TopoDS::Wire(path));
mkPipeShell.SetMode(isFrenet);
mkPipeShell.SetTransitionMode(transMode);
TopTools_ListIteratorOfListOfShape iter;
for (iter.Initialize(profiles); iter.More(); iter.Next()) {
mkPipeShell.Add(TopoDS_Shape(iter.Value()));
}
if (!mkPipeShell.IsReady()) {
Standard_Failure::Raise("shape is not ready to build");
}
mkPipeShell.Build();
if (isSolid) {
mkPipeShell.MakeSolid();
}
this->Shape.setValue(mkPipeShell.Shape());
return App::DocumentObject::StdReturn;
#endif
}
catch (Standard_Failure& e) {
@@ -788,7 +408,6 @@ void Thickness::handleChangedPropertyType(Base::XMLReader& reader,
App::DocumentObjectExecReturn* Thickness::execute()
{
#ifdef FC_USE_TNP_FIX
std::vector<TopoShape> shapes;
auto base = getTopoShape(Faces.getValue());
if (base.isNull()) {
@@ -803,33 +422,6 @@ App::DocumentObjectExecReturn* Thickness::execute()
return new App::DocumentObjectExecReturn("Invalid face selection");
}
}
#else
App::DocumentObject* source = Faces.getValue();
if (!source) {
return new App::DocumentObjectExecReturn("No source shape linked.");
}
const TopoShape& shape = Feature::getTopoShape(source);
if (shape.isNull()) {
return new App::DocumentObjectExecReturn("Source shape is empty.");
}
int countSolids = 0;
TopExp_Explorer xp;
xp.Init(shape.getShape(), TopAbs_SOLID);
for (; xp.More(); xp.Next()) {
countSolids++;
}
if (countSolids != 1) {
return new App::DocumentObjectExecReturn("Source shape is not a solid.");
}
TopTools_ListOfShape closingFaces;
const std::vector<std::string>& subStrings = Faces.getSubValues();
for (const auto& it : subStrings) {
TopoDS_Face face = TopoDS::Face(shape.getSubShape(it.c_str()));
closingFaces.Append(face);
}
#endif
double thickness = Value.getValue();
double tol = Precision::Confusion();
bool inter = Intersection.getValue();
@@ -837,7 +429,6 @@ App::DocumentObjectExecReturn* Thickness::execute()
short mode = (short)Mode.getValue();
short join = (short)Join.getValue();
#ifdef FC_USE_TNP_FIX
this->Shape.setValue(TopoShape(0,getDocument()->getStringHasher())
.makeElementThickSolid(base,
shapes,
@@ -848,16 +439,6 @@ App::DocumentObjectExecReturn* Thickness::execute()
mode,
static_cast<JoinType>(join)));
return Part::Feature::execute();
#else
if (fabs(thickness) > 2 * tol) {
this->Shape.setValue(
shape.makeThickSolid(closingFaces, thickness, tol, inter, self, mode, join));
}
else {
this->Shape.setValue(shape);
}
return App::DocumentObject::StdReturn;
#endif
}
// ----------------------------------------------------------------------------
-50
View File
@@ -3981,7 +3981,6 @@ TopoShape &TopoShape::makeRefine(const TopoShape &shape, const char *op, RefineF
return *this;
}
#ifdef FC_USE_TNP_FIX
bool TopoShape::findPlane(gp_Pln& pln, double tol, double atol) const
{
if (_Shape.IsNull()) {
@@ -4103,55 +4102,6 @@ bool TopoShape::findPlane(gp_Pln& pln, double tol, double atol) const
return false;
}
}
#else
bool TopoShape::findPlane(gp_Pln &pln, double tol, double atol) const {
(void)atol;
if(_Shape.IsNull())
return false;
TopoDS_Shape shape = _Shape;
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(_Shape).Shape();
}
}
try {
BRepLib_FindSurface finder(shape,tol,Standard_True);
if (!finder.Found())
return false;
pln = GeomAdaptor_Surface(finder.Surface()).Plane();
// To make the returned plane normal more stable, if the shape has any
// face, use the normal of the first face.
TopExp_Explorer exp(shape, TopAbs_FACE);
if(exp.More()) {
BRepAdaptor_Surface adapt(TopoDS::Face(exp.Current()));
double u = adapt.FirstUParameter()
+ (adapt.LastUParameter() - adapt.FirstUParameter())/2.;
double v = adapt.FirstVParameter()
+ (adapt.LastVParameter() - adapt.FirstVParameter())/2.;
BRepLProp_SLProps prop(adapt,u,v,2,Precision::Confusion());
if(prop.IsNormalDefined()) {
gp_Pnt pnt; gp_Vec vec;
// handles the orientation state of the shape
BRepGProp_Face(TopoDS::Face(exp.Current())).Normal(u,v,pnt,vec);
pln = gp_Pln(pnt, gp_Dir(vec));
}
}
return true;
}catch (Standard_Failure &e) {
// For some reason the above BRepBuilderAPI_Copy failed to copy
// 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;
}
}
#endif
bool TopoShape::isInfinite() const
{
@@ -68,36 +68,10 @@ int TopoShapeCompSolidPy::PyInit(PyObject* args, PyObject* /*kwd*/)
if (!PyArg_ParseTuple(args, "O", &pcObj)) {
return -1;
}
#ifdef FC_USE_TNP_FIX
try {
getTopoShapePtr()->makeElementBoolean(Part::OpCodes::Compsolid, getPyShapes(pcObj));
}
_PY_CATCH_OCC(return (-1))
#else
BRep_Builder builder;
TopoDS_CompSolid Comp;
builder.MakeCompSolid(Comp);
try {
Py::Sequence list(pcObj);
for (Py::Sequence::iterator it = list.begin(); it != list.end(); ++it) {
if (PyObject_TypeCheck((*it).ptr(), &(Part::TopoShapeSolidPy::Type))) {
const TopoDS_Shape& sh =
static_cast<TopoShapePy*>((*it).ptr())->getTopoShapePtr()->getShape();
if (!sh.IsNull()) {
builder.Add(Comp, sh);
}
}
}
}
catch (Standard_Failure& e) {
PyErr_SetString(PartExceptionOCCError, e.GetMessageString());
return -1;
}
getTopoShapePtr()->setShape(Comp);
#endif
return 0;
}
@@ -124,15 +98,11 @@ PyObject* TopoShapeCompSolidPy::add(PyObject* args)
Standard_Failure::Raise("Cannot empty shape to compound solid");
}
}
#ifdef FC_USE_TNP_FIX
auto& self = *getTopoShapePtr();
shapes.push_back(self);
TopoShape tmp(self.Tag, self.Hasher, comp);
tmp.mapSubElement(shapes);
self = tmp;
#else
getTopoShapePtr()->setShape(comp);
#endif
Py_Return;
}
catch (Standard_Failure& e) {
-36
View File
@@ -913,25 +913,6 @@ void TopoShape::mapSubElementForShape(const TopoShape& other, const char* op)
void TopoShape::mapSubElement(const TopoShape& other, const char* op, bool forceHasher)
{
#ifndef FC_USE_TNP_FIX
if (!canMapElement(other)) {
return;
}
if ((getElementMapSize(false) == 0U) && this->_Shape.IsPartner(other._Shape)) {
if (!this->Hasher) {
this->Hasher = other.Hasher;
}
copyElementMap(other, op);
return;
}
if (!forceHasher && other.Hasher) {
checkAndMatchHasher(*this, other);
}
mapSubElementForShape(other, op);
#else
if (!canMapElement(other)) {
return;
}
@@ -1030,8 +1011,6 @@ void TopoShape::mapSubElement(const TopoShape& other, const char* op, bool force
}
}
}
#endif
}
void TopoShape::mapSubElementsTo(std::vector<TopoShape>& shapes, const char* op) const
@@ -1093,20 +1072,6 @@ void TopoShape::mapCompoundSubElements(const std::vector<TopoShape>& shapes, con
void TopoShape::mapSubElement(const std::vector<TopoShape>& shapes, const char* op)
{
#ifndef FC_USE_TNP_FIX
if (shapes.empty()) {
return;
}
if (shapeType(true) == TopAbs_COMPOUND) {
mapCompoundSubElements(shapes, op);
}
else {
for (auto& shape : shapes) {
mapSubElement(shape, op);
}
}
#else
if (shapes.empty()) {
return;
}
@@ -1158,7 +1123,6 @@ void TopoShape::mapSubElement(const std::vector<TopoShape>& shapes, const char*
for (auto& shape : shapes) {
mapSubElement(shape, op);
}
#endif
}
std::vector<TopoDS_Shape> TopoShape::getSubShapes(TopAbs_ShapeEnum type,
-105
View File
@@ -325,41 +325,7 @@ int TopoShapeFacePy::PyInit(PyObject* args, PyObject* /*kwd*/)
PyErr_Clear();
if (PyArg_ParseTuple(args, "Os", &pcPyShapeOrList, &className)) {
try {
#ifdef FC_USE_TNP_FIX
getTopoShapePtr()->makeElementFace(getPyShapes(pcPyShapeOrList),0,className);
#else
std::unique_ptr<FaceMaker> fm = Part::FaceMaker::ConstructFromType(className);
//dump all supplied shapes to facemaker, no matter what type (let facemaker decide).
if (PySequence_Check(pcPyShapeOrList)){
Py::Sequence list(pcPyShapeOrList);
for (Py::Sequence::iterator it = list.begin(); it != list.end(); ++it) {
PyObject* item = (*it).ptr();
if (PyObject_TypeCheck(item, &(Part::TopoShapePy::Type))) {
const TopoDS_Shape& sh = static_cast<Part::TopoShapePy*>(item)->getTopoShapePtr()->getShape();
fm->addShape(sh);
} else {
PyErr_SetString(PyExc_TypeError, "Object is not a shape.");
return -1;
}
}
} else if (PyObject_TypeCheck(pcPyShapeOrList, &(Part::TopoShapePy::Type))) {
const TopoDS_Shape& sh = static_cast<Part::TopoShapePy*>(pcPyShapeOrList)->getTopoShapePtr()->getShape();
if (sh.IsNull())
throw NullShapeException("Shape is null!");
if (sh.ShapeType() == TopAbs_COMPOUND)
fm->useCompound(TopoDS::Compound(sh));
else
fm->addShape(sh);
} else {
PyErr_SetString(PyExc_TypeError, "First argument is neither a shape nor list of shapes.");
return -1;
}
fm->Build();
getTopoShapePtr()->setShape(fm->Face());
#endif
return 0;
} catch (Base::Exception &e) {
e.setPyException();
@@ -425,25 +391,8 @@ PyObject* TopoShapeFacePy::addWire(PyObject *args)
PyObject* TopoShapeFacePy::makeOffset(PyObject *args)
{
#ifdef FC_USE_TNP_FIX
Py::Dict dict;
return TopoShapePy::makeOffset2D(args, dict.ptr());
#else
double dist;
if (!PyArg_ParseTuple(args, "d",&dist))
return nullptr;
auto f = getTopoDSFace(this);
BRepBuilderAPI_FindPlane findPlane(f);
if (!findPlane.Found()) {
PyErr_SetString(PartExceptionOCCError, "No planar face");
return nullptr;
}
BRepOffsetAPI_MakeOffset mkOffset(f);
mkOffset.Perform(dist);
return new TopoShapePy(new TopoShape(mkOffset.Shape()));
#endif
}
/*
@@ -455,61 +404,7 @@ evolve = spine.makeEvolved(Profile=profile, Join=PartEnums.JoinType.Arc)
*/
PyObject* TopoShapeFacePy::makeEvolved(PyObject *args, PyObject *kwds)
{
#ifdef FC_USE_TNP_FIX
return TopoShapePy::makeEvolved(args, kwds);
#else
PyObject* Profile;
PyObject* AxeProf = Py_True;
PyObject* Solid = Py_False;
PyObject* ProfOnSpine = Py_False;
int JoinType = int(GeomAbs_Arc);
double Tolerance = 0.0000001;
static const std::array<const char *, 7> kwds_evolve{"Profile", "Join", "AxeProf", "Solid", "ProfOnSpine",
"Tolerance", nullptr};
if (!Base::Wrapped_ParseTupleAndKeywords(args, kwds, "O!|iO!O!O!d", kwds_evolve,
&TopoShapeWirePy::Type, &Profile, &JoinType,
&PyBool_Type, &AxeProf, &PyBool_Type, &Solid,
&PyBool_Type, &ProfOnSpine, &Tolerance)) {
return nullptr;
}
const TopoDS_Face& spine = TopoDS::Face(getTopoShapePtr()->getShape());
BRepBuilderAPI_FindPlane findPlane(spine);
if (!findPlane.Found()) {
PyErr_SetString(PartExceptionOCCError, "No planar face");
return nullptr;
}
const TopoDS_Wire& profile = TopoDS::Wire(static_cast<TopoShapeWirePy*>(Profile)->getTopoShapePtr()->getShape());
GeomAbs_JoinType joinType;
switch (JoinType) {
case GeomAbs_Tangent:
joinType = GeomAbs_Tangent;
break;
case GeomAbs_Intersection:
joinType = GeomAbs_Intersection;
break;
default:
joinType = GeomAbs_Arc;
break;
}
try {
BRepOffsetAPI_MakeEvolved evolved(spine, profile, joinType,
Base::asBoolean(AxeProf),
Base::asBoolean(Solid),
Base::asBoolean(ProfOnSpine),
Tolerance);
TopoDS_Shape shape = evolved.Shape();
return Py::new_reference_to(shape2pyshape(shape));
}
catch (Standard_Failure& e) {
PyErr_SetString(PartExceptionOCCError, e.GetMessageString());
return nullptr;
}
#endif
}
PyObject* TopoShapeFacePy::valueAt(PyObject *args)
+1 -728
View File
@@ -108,7 +108,6 @@ using namespace Part;
#define M_PI_2 1.57079632679489661923 /* pi/2 */
#endif
#ifdef FC_USE_TNP_FIX
static Py_hash_t _TopoShapeHash(PyObject* self)
{
if (!self) {
@@ -136,7 +135,6 @@ struct TopoShapePyInit
TopoShapePy::Type.tp_hash = _TopoShapeHash;
}
} _TopoShapePyInit;
#endif
// returns a string which represents the object e.g. when printed in python
std::string TopoShapePy::representation() const
@@ -155,7 +153,6 @@ PyObject *TopoShapePy::PyMake(struct _typeobject *, PyObject *, PyObject *) //
int TopoShapePy::PyInit(PyObject* args, PyObject* keywds)
{
#ifdef FC_USE_TNP_FIX
static const std::array<const char*, 5> kwlist{ "shape",
"op",
"tag",
@@ -206,45 +203,6 @@ int TopoShapePy::PyInit(PyObject* args, PyObject* keywds)
}
}
_PY_CATCH_OCC(return (-1))
#else
(void) keywds;
PyObject* pcObj = nullptr;
if (!PyArg_ParseTuple(args, "|O", &pcObj)) {
return -1;
}
auto shapes = getPyShapes(pcObj);
if (pcObj) {
TopoShape shape;
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));
}
}
}
}
}
_PY_CATCH_OCC(return (-1))
getTopoShapePtr()->setShape(shape.getShape());
}
#endif
return 0;
}
@@ -252,7 +210,6 @@ PyObject* TopoShapePy::copy(PyObject *args)
{
PyObject* copyGeom = Py_True;
PyObject* copyMesh = Py_False;
#ifdef FC_USE_TNP_FIX
const char* op = nullptr;
PyObject* pyHasher = nullptr;
if (!PyArg_ParseTuple(args,
@@ -280,61 +237,18 @@ PyObject* TopoShapePy::copy(PyObject *args)
return Py::new_reference_to(shape2pyshape(
TopoShape(self.Tag, hasher)
.makeElementCopy(self, op, PyObject_IsTrue(copyGeom), PyObject_IsTrue(copyMesh))));
#else
if (!PyArg_ParseTuple(args, "|O!O!", &PyBool_Type, &copyGeom, &PyBool_Type, &copyMesh))
return nullptr;
const TopoDS_Shape& shape = this->getTopoShapePtr()->getShape();
PyTypeObject* type = this->GetType();
PyObject* cpy = nullptr;
// let the type object decide
if (type->tp_new)
cpy = type->tp_new(type, this, nullptr);
if (!cpy) {
PyErr_SetString(PyExc_TypeError, "failed to create copy of shape");
return nullptr;
}
if (!shape.IsNull()) {
BRepBuilderAPI_Copy c(shape, Base::asBoolean(copyGeom), Base::asBoolean(copyMesh));
static_cast<TopoShapePy*>(cpy)->getTopoShapePtr()->setShape(c.Shape());
}
return cpy;
#endif
}
PyObject* TopoShapePy::cleaned(PyObject *args)
{
if (!PyArg_ParseTuple(args, ""))
return nullptr;
#ifdef FC_USE_TNP_FIX
auto& self = *getTopoShapePtr();
TopoShape copy(self.makeElementCopy());
if (!copy.isNull()) {
BRepTools::Clean(copy.getShape()); // remove triangulation
}
return Py::new_reference_to(shape2pyshape(copy));
#else
const TopoDS_Shape& shape = this->getTopoShapePtr()->getShape();
PyTypeObject* type = this->GetType();
PyObject* cpy = nullptr;
// let the type object decide
if (type->tp_new)
cpy = type->tp_new(type, this, nullptr);
if (!cpy) {
PyErr_SetString(PyExc_TypeError, "failed to create copy of shape");
return nullptr;
}
if (!shape.IsNull()) {
BRepBuilderAPI_Copy c(shape);
const TopoDS_Shape& copiedShape = c.Shape();
BRepTools::Clean(copiedShape); // remove triangulation
static_cast<TopoShapePy*>(cpy)->getTopoShapePtr()->setShape(c.Shape());
}
return cpy;
#endif
}
PyObject* TopoShapePy::replaceShape(PyObject *args)
@@ -344,7 +258,6 @@ PyObject* TopoShapePy::replaceShape(PyObject *args)
return nullptr;
try {
#ifdef FC_USE_TNP_FIX
Py::Sequence list(l);
std::vector<std::pair<TopoShape, TopoShape>> shapes;
for (Py::Sequence::iterator it = list.begin(); it != list.end(); ++it) {
@@ -355,24 +268,6 @@ PyObject* TopoShapePy::replaceShape(PyObject *args)
*sh2.extensionObject()->getTopoShapePtr()));
}
return Py::new_reference_to(shape2pyshape(getTopoShapePtr()->replaceElementShape(shapes)));
#else
Py::Sequence list(l);
std::vector< std::pair<TopoDS_Shape, TopoDS_Shape> > shapes;
for (Py::Sequence::iterator it = list.begin(); it != list.end(); ++it) {
Py::Tuple tuple(*it);
Py::TopoShape sh1(tuple[0]);
Py::TopoShape sh2(tuple[1]);
shapes.emplace_back(
sh1.extensionObject()->getTopoShapePtr()->getShape(),
sh2.extensionObject()->getTopoShapePtr()->getShape()
);
}
PyTypeObject* type = this->GetType();
PyObject* inst = type->tp_new(type, this, nullptr);
static_cast<TopoShapePy*>(inst)->getTopoShapePtr()->setShape
(this->getTopoShapePtr()->replaceShape(shapes));
return inst;
#endif
}
catch (const Py::Exception&) {
return nullptr;
@@ -390,22 +285,8 @@ PyObject* TopoShapePy::removeShape(PyObject *args)
return nullptr;
try {
#ifdef FC_USE_TNP_FIX
return Py::new_reference_to(
shape2pyshape(getTopoShapePtr()->removeElementShape(getPyShapes(l))));
#else
Py::Sequence list(l);
std::vector<TopoDS_Shape> shapes;
for (Py::Sequence::iterator it = list.begin(); it != list.end(); ++it) {
Py::TopoShape sh(*it);
shapes.push_back(sh.extensionObject()->getTopoShapePtr()->getShape());
}
PyTypeObject* type = this->GetType();
PyObject* inst = type->tp_new(type, this, nullptr);
static_cast<TopoShapePy*>(inst)->getTopoShapePtr()->setShape
(this->getTopoShapePtr()->removeShape(shapes));
return inst;
#endif
}
catch (...) {
PyErr_SetString(PartExceptionOCCError, "failed to remove shape");
@@ -754,38 +635,8 @@ PyObject* TopoShapePy::extrude(PyObject *args)
try {
Base::Vector3d vec = static_cast<Base::VectorPy*>(pVec)->value();
#ifdef FC_USE_TNP_FIX
return Py::new_reference_to(
shape2pyshape(getTopoShapePtr()->makeElementPrism(gp_Vec(vec.x, vec.y, vec.z))));
#else
TopoDS_Shape shape = this->getTopoShapePtr()->makePrism(gp_Vec(vec.x,vec.y,vec.z));
TopAbs_ShapeEnum type = shape.ShapeType();
switch (type) {
case TopAbs_COMPOUND:
return new TopoShapeCompoundPy(new TopoShape(shape));
case TopAbs_COMPSOLID:
return new TopoShapeCompSolidPy(new TopoShape(shape));
case TopAbs_SOLID:
return new TopoShapeSolidPy(new TopoShape(shape));
case TopAbs_SHELL:
return new TopoShapeShellPy(new TopoShape(shape));
case TopAbs_FACE:
return new TopoShapeFacePy(new TopoShape(shape));
case TopAbs_WIRE:
break;
case TopAbs_EDGE:
return new TopoShapeEdgePy(new TopoShape(shape));
case TopAbs_VERTEX:
break;
case TopAbs_SHAPE:
break;
default:
break;
}
PyErr_SetString(PartExceptionOCCError, "extrusion for this shape type not supported");
return nullptr;
#endif
}
catch (Standard_Failure& e) {
PyErr_SetString(PartExceptionOCCError, e.GetMessageString());
@@ -802,59 +653,9 @@ PyObject* TopoShapePy::revolve(PyObject *args)
Base::Vector3d pos = static_cast<Base::VectorPy*>(pPos)->value();
Base::Vector3d dir = static_cast<Base::VectorPy*>(pDir)->value();
try {
#ifdef FC_USE_TNP_FIX
return Py::new_reference_to(shape2pyshape(getTopoShapePtr()->makeElementRevolve(
gp_Ax1(gp_Pnt(pos.x, pos.y, pos.z), gp_Dir(dir.x, dir.y, dir.z)),
d * (M_PI / 180))));
#else
const TopoDS_Shape& input = this->getTopoShapePtr()->getShape();
if (input.IsNull()) {
PyErr_SetString(PartExceptionOCCError, "empty shape cannot be revolved");
return nullptr;
}
TopExp_Explorer xp;
xp.Init(input,TopAbs_SOLID);
if (xp.More()) {
PyErr_SetString(PartExceptionOCCError, "shape must not contain solids");
return nullptr;
}
xp.Init(input,TopAbs_COMPSOLID);
if (xp.More()) {
PyErr_SetString(PartExceptionOCCError, "shape must not contain compound solids");
return nullptr;
}
TopoDS_Shape shape = this->getTopoShapePtr()->revolve(
gp_Ax1(gp_Pnt(pos.x,pos.y,pos.z), gp_Dir(dir.x,dir.y,dir.z)),d*(M_PI/180));
TopAbs_ShapeEnum type = shape.ShapeType();
switch (type) {
case TopAbs_COMPOUND:
return new TopoShapeCompoundPy(new TopoShape(shape));
case TopAbs_COMPSOLID:
return new TopoShapeCompSolidPy(new TopoShape(shape));
case TopAbs_SOLID:
return new TopoShapeSolidPy(new TopoShape(shape));
case TopAbs_SHELL:
return new TopoShapeShellPy(new TopoShape(shape));
case TopAbs_FACE:
return new TopoShapeFacePy(new TopoShape(shape));
case TopAbs_WIRE:
break;
case TopAbs_EDGE:
return new TopoShapeEdgePy(new TopoShape(shape));
case TopAbs_VERTEX:
break;
case TopAbs_SHAPE:
break;
default:
break;
}
PyErr_SetString(PartExceptionOCCError, "revolution for this shape type not supported");
return nullptr;
#endif
}
catch (Standard_Failure& e) {
PyErr_SetString(PartExceptionOCCError, e.GetMessageString());
@@ -879,7 +680,6 @@ PyObject* TopoShapePy::check(PyObject *args)
Py_Return;
}
#ifdef FC_USE_TNP_FIX
static PyObject *makeShape(const char *op,const TopoShape &shape, PyObject *args) {
double tol=0;
PyObject *pcObj;
@@ -892,120 +692,15 @@ static PyObject *makeShape(const char *op,const TopoShape &shape, PyObject *args
return Py::new_reference_to(shape2pyshape(TopoShape().makeElementBoolean(op,shapes,0,tol)));
} PY_CATCH_OCC
}
#endif
PyObject* TopoShapePy::fuse(PyObject *args)
{
#ifdef FC_USE_TNP_FIX
return makeShape(Part::OpCodes::Fuse, *getTopoShapePtr(), args);
#else
PyObject *pcObj;
if (PyArg_ParseTuple(args, "O!", &(TopoShapePy::Type), &pcObj)) {
TopoDS_Shape shape = static_cast<TopoShapePy*>(pcObj)->getTopoShapePtr()->getShape();
try {
// Let's call algorithm computing a fuse operation:
TopoDS_Shape fusShape = this->getTopoShapePtr()->fuse(shape);
return new TopoShapePy(new TopoShape(fusShape));
}
catch (Standard_Failure& e) {
PyErr_SetString(PartExceptionOCCError, e.GetMessageString());
return nullptr;
}
catch (const std::exception& e) {
PyErr_SetString(PartExceptionOCCError, e.what());
return nullptr;
}
}
PyErr_Clear();
double tolerance = 0.0;
if (PyArg_ParseTuple(args, "O!d", &(TopoShapePy::Type), &pcObj, &tolerance)) {
std::vector<TopoDS_Shape> shapeVec;
shapeVec.push_back(static_cast<TopoShapePy*>(pcObj)->getTopoShapePtr()->getShape());
try {
// Let's call algorithm computing a fuse operation:
TopoDS_Shape fuseShape = this->getTopoShapePtr()->fuse(shapeVec,tolerance);
return new TopoShapePy(new TopoShape(fuseShape));
}
catch (Standard_Failure& e) {
PyErr_SetString(PartExceptionOCCError, e.GetMessageString());
return nullptr;
}
catch (const std::exception& e) {
PyErr_SetString(PartExceptionOCCError, e.what());
return nullptr;
}
}
PyErr_Clear();
if (PyArg_ParseTuple(args, "O|d", &pcObj, &tolerance)) {
std::vector<TopoDS_Shape> shapeVec;
Py::Sequence shapeSeq(pcObj);
for (Py::Sequence::iterator it = shapeSeq.begin(); it != shapeSeq.end(); ++it) {
PyObject* item = (*it).ptr();
if (PyObject_TypeCheck(item, &(Part::TopoShapePy::Type))) {
shapeVec.push_back(static_cast<Part::TopoShapePy*>(item)->getTopoShapePtr()->getShape());
}
else {
PyErr_SetString(PyExc_TypeError, "non-shape object in sequence");
return nullptr;
}
}
try {
TopoDS_Shape multiFusedShape = this->getTopoShapePtr()->fuse(shapeVec,tolerance);
return new TopoShapePy(new TopoShape(multiFusedShape));
}
catch (Standard_Failure& e) {
PyErr_SetString(PartExceptionOCCError, e.GetMessageString());
return nullptr;
}
catch (const std::exception& e) {
PyErr_SetString(PartExceptionOCCError, e.what());
return nullptr;
}
}
PyErr_SetString(PyExc_TypeError, "shape or sequence of shape expected");
return nullptr;
#endif
}
PyObject* TopoShapePy::multiFuse(PyObject *args)
{
#ifdef FC_USE_TNP_FIX
return makeShape(Part::OpCodes::Fuse, *getTopoShapePtr(), args);
#else
double tolerance = 0.0;
PyObject *pcObj;
if (!PyArg_ParseTuple(args, "O|d", &pcObj, &tolerance))
return nullptr;
std::vector<TopoDS_Shape> shapeVec;
Py::Sequence shapeSeq(pcObj);
for (Py::Sequence::iterator it = shapeSeq.begin(); it != shapeSeq.end(); ++it) {
PyObject* item = (*it).ptr();
if (PyObject_TypeCheck(item, &(Part::TopoShapePy::Type))) {
shapeVec.push_back(static_cast<Part::TopoShapePy*>(item)->getTopoShapePtr()->getShape());
}
else {
PyErr_SetString(PyExc_TypeError, "non-shape object in sequence");
return nullptr;
}
}
try {
TopoDS_Shape multiFusedShape = this->getTopoShapePtr()->fuse(shapeVec,tolerance);
return new TopoShapePy(new TopoShape(multiFusedShape));
}
catch (Standard_Failure& e) {
PyErr_SetString(PartExceptionOCCError, e.GetMessageString());
return nullptr;
}
catch (const std::exception& e) {
PyErr_SetString(PartExceptionOCCError, e.what());
return nullptr;
}
#endif
}
PyObject* TopoShapePy::oldFuse(PyObject *args)
@@ -1032,153 +727,12 @@ PyObject* TopoShapePy::oldFuse(PyObject *args)
PyObject* TopoShapePy::common(PyObject *args)
{
#ifdef FC_USE_TNP_FIX
return makeShape(Part::OpCodes::Common, *getTopoShapePtr(), args);
#else
PyObject *pcObj;
if (PyArg_ParseTuple(args, "O!", &(TopoShapePy::Type), &pcObj)) {
TopoDS_Shape shape = static_cast<TopoShapePy*>(pcObj)->getTopoShapePtr()->getShape();
try {
// Let's call algorithm computing a common operation:
TopoDS_Shape comShape = this->getTopoShapePtr()->common(shape);
return new TopoShapePy(new TopoShape(comShape));
}
catch (Standard_Failure& e) {
PyErr_SetString(PartExceptionOCCError, e.GetMessageString());
return nullptr;
}
catch (const std::exception& e) {
PyErr_SetString(PartExceptionOCCError, e.what());
return nullptr;
}
}
PyErr_Clear();
double tolerance = 0.0;
if (PyArg_ParseTuple(args, "O!d", &(TopoShapePy::Type), &pcObj, &tolerance)) {
std::vector<TopoDS_Shape> shapeVec;
shapeVec.push_back(static_cast<TopoShapePy*>(pcObj)->getTopoShapePtr()->getShape());
try {
TopoDS_Shape commonShape = this->getTopoShapePtr()->common(shapeVec,tolerance);
return new TopoShapePy(new TopoShape(commonShape));
}
catch (Standard_Failure& e) {
PyErr_SetString(PartExceptionOCCError, e.GetMessageString());
return nullptr;
}
catch (const std::exception& e) {
PyErr_SetString(PartExceptionOCCError, e.what());
return nullptr;
}
}
PyErr_Clear();
if (PyArg_ParseTuple(args, "O|d", &pcObj, &tolerance)) {
std::vector<TopoDS_Shape> shapeVec;
Py::Sequence shapeSeq(pcObj);
for (Py::Sequence::iterator it = shapeSeq.begin(); it != shapeSeq.end(); ++it) {
PyObject* item = (*it).ptr();
if (PyObject_TypeCheck(item, &(Part::TopoShapePy::Type))) {
shapeVec.push_back(static_cast<Part::TopoShapePy*>(item)->getTopoShapePtr()->getShape());
}
else {
PyErr_SetString(PyExc_TypeError, "non-shape object in sequence");
return nullptr;
}
}
try {
TopoDS_Shape multiCommonShape = this->getTopoShapePtr()->common(shapeVec,tolerance);
return new TopoShapePy(new TopoShape(multiCommonShape));
}
catch (Standard_Failure& e) {
PyErr_SetString(PartExceptionOCCError, e.GetMessageString());
return nullptr;
}
catch (const std::exception& e) {
PyErr_SetString(PartExceptionOCCError, e.what());
return nullptr;
}
}
PyErr_SetString(PyExc_TypeError, "shape or sequence of shape expected");
return nullptr;
#endif
}
PyObject* TopoShapePy::section(PyObject *args)
{
#ifdef FC_USE_TNP_FIX
return makeShape(Part::OpCodes::Section, *getTopoShapePtr(), args);
#else
PyObject *pcObj;
PyObject *approx = Py_False;
if (PyArg_ParseTuple(args, "O!|O!", &(TopoShapePy::Type), &pcObj, &(PyBool_Type), &approx)) {
TopoDS_Shape shape = static_cast<TopoShapePy*>(pcObj)->getTopoShapePtr()->getShape();
try {
// Let's call algorithm computing a section operation:
TopoDS_Shape secShape = this->getTopoShapePtr()->section(shape, Base::asBoolean(approx));
return new TopoShapePy(new TopoShape(secShape));
}
catch (Standard_Failure& e) {
PyErr_SetString(PartExceptionOCCError, e.GetMessageString());
return nullptr;
}
catch (const std::exception& e) {
PyErr_SetString(PartExceptionOCCError, e.what());
return nullptr;
}
}
PyErr_Clear();
double tolerance = 0.0;
if (PyArg_ParseTuple(args, "O!d|O!", &(TopoShapePy::Type), &pcObj, &tolerance, &(PyBool_Type), &approx)) {
std::vector<TopoDS_Shape> shapeVec;
shapeVec.push_back(static_cast<TopoShapePy*>(pcObj)->getTopoShapePtr()->getShape());
try {
TopoDS_Shape sectionShape = this->getTopoShapePtr()->section(shapeVec, tolerance, Base::asBoolean(approx));
return new TopoShapePy(new TopoShape(sectionShape));
}
catch (Standard_Failure& e) {
PyErr_SetString(PartExceptionOCCError, e.GetMessageString());
return nullptr;
}
catch (const std::exception& e) {
PyErr_SetString(PartExceptionOCCError, e.what());
return nullptr;
}
}
PyErr_Clear();
if (PyArg_ParseTuple(args, "O|dO!", &pcObj, &tolerance, &(PyBool_Type), &approx)) {
std::vector<TopoDS_Shape> shapeVec;
Py::Sequence shapeSeq(pcObj);
for (Py::Sequence::iterator it = shapeSeq.begin(); it != shapeSeq.end(); ++it) {
PyObject* item = (*it).ptr();
if (PyObject_TypeCheck(item, &(Part::TopoShapePy::Type))) {
shapeVec.push_back(static_cast<Part::TopoShapePy*>(item)->getTopoShapePtr()->getShape());
}
else {
PyErr_SetString(PyExc_TypeError, "non-shape object in sequence");
return nullptr;
}
}
try {
TopoDS_Shape multiSectionShape = this->getTopoShapePtr()->section(shapeVec, tolerance, Base::asBoolean(approx));
return new TopoShapePy(new TopoShape(multiSectionShape));
}
catch (Standard_Failure& e) {
PyErr_SetString(PartExceptionOCCError, e.GetMessageString());
return nullptr;
}
catch (const std::exception& e) {
PyErr_SetString(PartExceptionOCCError, e.what());
return nullptr;
}
}
PyErr_SetString(PyExc_TypeError, "shape or sequence of shape expected");
return nullptr;
#endif
}
PyObject* TopoShapePy::slice(PyObject *args)
@@ -1191,21 +745,11 @@ PyObject* TopoShapePy::slice(PyObject *args)
Base::Vector3d vec = Py::Vector(dir, false).toVector();
try {
#ifdef FC_USE_TNP_FIX
Py::List wires;
for (auto& w : getTopoShapePtr()->makeElementSlice(vec, d).getSubTopoShapes(TopAbs_WIRE)) {
wires.append(shape2pyshape(w));
}
return Py::new_reference_to(wires);
#else
std::list<TopoDS_Wire> slice = this->getTopoShapePtr()->slice(vec, d);
Py::List wire;
for (const auto & it : slice) {
wire.append(Py::asObject(new TopoShapeWirePy(new TopoShape(it))));
}
return Py::new_reference_to(wire);
#endif
}
catch (Standard_Failure& e) {
@@ -1231,12 +775,7 @@ PyObject* TopoShapePy::slices(PyObject *args)
d.reserve(list.size());
for (Py::Sequence::iterator it = list.begin(); it != list.end(); ++it)
d.push_back((double)Py::Float(*it));
#ifdef FC_USE_TNP_FIX
return Py::new_reference_to(shape2pyshape(getTopoShapePtr()->makeElementSlices(vec, d)));
#else
TopoDS_Compound slice = this->getTopoShapePtr()->slices(vec, d);
return new TopoShapeCompoundPy(new TopoShape(slice));
#endif
}
catch (Standard_Failure& e) {
PyErr_SetString(PartExceptionOCCError, e.GetMessageString());
@@ -1250,77 +789,7 @@ PyObject* TopoShapePy::slices(PyObject *args)
PyObject* TopoShapePy::cut(PyObject *args)
{
#ifdef FC_USE_TNP_FIX
return makeShape(Part::OpCodes::Cut, *getTopoShapePtr(), args);
#else
PyObject *pcObj;
if (PyArg_ParseTuple(args, "O!", &(TopoShapePy::Type), &pcObj)) {
TopoDS_Shape shape = static_cast<TopoShapePy*>(pcObj)->getTopoShapePtr()->getShape();
try {
// Let's call algorithm computing a cut operation:
TopoDS_Shape cutShape = this->getTopoShapePtr()->cut(shape);
return new TopoShapePy(new TopoShape(cutShape));
}
catch (Standard_Failure& e) {
PyErr_SetString(PartExceptionOCCError, e.GetMessageString());
return nullptr;
}
catch (const std::exception& e) {
PyErr_SetString(PartExceptionOCCError, e.what());
return nullptr;
}
}
PyErr_Clear();
double tolerance = 0.0;
if (PyArg_ParseTuple(args, "O!d", &(TopoShapePy::Type), &pcObj, &tolerance)) {
std::vector<TopoDS_Shape> shapeVec;
shapeVec.push_back(static_cast<TopoShapePy*>(pcObj)->getTopoShapePtr()->getShape());
try {
TopoDS_Shape cutShape = this->getTopoShapePtr()->cut(shapeVec,tolerance);
return new TopoShapePy(new TopoShape(cutShape));
}
catch (Standard_Failure& e) {
PyErr_SetString(PartExceptionOCCError, e.GetMessageString());
return nullptr;
}
catch (const std::exception& e) {
PyErr_SetString(PartExceptionOCCError, e.what());
return nullptr;
}
}
PyErr_Clear();
if (PyArg_ParseTuple(args, "O|d", &pcObj, &tolerance)) {
std::vector<TopoDS_Shape> shapeVec;
Py::Sequence shapeSeq(pcObj);
for (Py::Sequence::iterator it = shapeSeq.begin(); it != shapeSeq.end(); ++it) {
PyObject* item = (*it).ptr();
if (PyObject_TypeCheck(item, &(Part::TopoShapePy::Type))) {
shapeVec.push_back(static_cast<Part::TopoShapePy*>(item)->getTopoShapePtr()->getShape());
}
else {
PyErr_SetString(PyExc_TypeError, "non-shape object in sequence");
return nullptr;
}
}
try {
TopoDS_Shape multiCutShape = this->getTopoShapePtr()->cut(shapeVec,tolerance);
return new TopoShapePy(new TopoShape(multiCutShape));
}
catch (Standard_Failure& e) {
PyErr_SetString(PartExceptionOCCError, e.GetMessageString());
return nullptr;
}
catch (const std::exception& e) {
PyErr_SetString(PartExceptionOCCError, e.what());
return nullptr;
}
}
PyErr_SetString(PyExc_TypeError, "shape or sequence of shape expected");
return nullptr;
#endif
}
PyObject* TopoShapePy::generalFuse(PyObject *args)
@@ -1330,7 +799,6 @@ PyObject* TopoShapePy::generalFuse(PyObject *args)
if (!PyArg_ParseTuple(args, "O|d", &pcObj, &tolerance))
return nullptr;
#ifdef FC_USE_TNP_FIX
std::vector<std::vector<TopoShape>> modifies;
std::vector<TopoShape> shapes;
shapes.push_back(*getTopoShapePtr());
@@ -1352,45 +820,6 @@ PyObject* TopoShapePy::generalFuse(PyObject *args)
return Py::new_reference_to(ret);
}
PY_CATCH_OCC
#else
std::vector<TopoDS_Shape> shapeVec;
Py::Sequence shapeSeq(pcObj);
for (Py::Sequence::iterator it = shapeSeq.begin(); it != shapeSeq.end(); ++it) {
PyObject* item = (*it).ptr();
if (PyObject_TypeCheck(item, &(Part::TopoShapePy::Type))) {
shapeVec.push_back(static_cast<Part::TopoShapePy*>(item)->getTopoShapePtr()->getShape());
}
else {
PyErr_SetString(PyExc_TypeError, "non-shape object in sequence");
return nullptr;
}
}
try {
std::vector<TopTools_ListOfShape> map;
TopoDS_Shape gfaResultShape = this->getTopoShapePtr()->generalFuse(shapeVec,tolerance,&map);
Py::Object shapePy = shape2pyshape(gfaResultShape);
Py::List mapPy;
for (TopTools_ListOfShape& shapes : map) {
Py::List shapesPy;
for (TopTools_ListIteratorOfListOfShape it(shapes); it.More(); it.Next()) {
shapesPy.append(shape2pyshape(it.Value()));
}
mapPy.append(shapesPy);
}
Py::Tuple ret(2);
ret[0] = shapePy;
ret[1] = mapPy;
return Py::new_reference_to(ret);
}
catch (Standard_Failure& e) {
PyErr_SetString(PartExceptionOCCError, e.GetMessageString());
return nullptr;
}
catch (const std::exception& e) {
PyErr_SetString(PartExceptionOCCError, e.what());
return nullptr;
}
#endif
}
PyObject* TopoShapePy::sewShape(PyObject *args)
@@ -1416,7 +845,6 @@ PyObject* TopoShapePy::childShapes(PyObject *args)
if (!PyArg_ParseTuple(args, "|O!O!", &(PyBool_Type), &cumOri, &(PyBool_Type), &cumLoc))
return nullptr;
#ifdef FC_USE_TNP_FIX
TopoShape shape = *getTopoShapePtr();
if (!PyObject_IsTrue(cumOri)) {
shape.setShape(shape.getShape().Oriented(TopAbs_FORWARD), false);
@@ -1433,63 +861,6 @@ PyObject* TopoShapePy::childShapes(PyObject *args)
return Py::new_reference_to(list);
}
PY_CATCH_OCC
#else
try {
const TopoDS_Shape& shape = getTopoShapePtr()->getShape();
if (shape.IsNull()) {
PyErr_SetString(PyExc_ValueError, "Shape is null");
return nullptr;
}
TopoDS_Iterator it(shape, Base::asBoolean(cumOri), Base::asBoolean(cumLoc));
Py::List list;
for (; it.More(); it.Next()) {
const TopoDS_Shape& aChild = it.Value();
if (!aChild.IsNull()) {
TopAbs_ShapeEnum type = aChild.ShapeType();
PyObject* pyChild = nullptr;
switch (type) {
case TopAbs_COMPOUND:
pyChild = new TopoShapeCompoundPy(new TopoShape(aChild));
break;
case TopAbs_COMPSOLID:
pyChild = new TopoShapeCompSolidPy(new TopoShape(aChild));
break;
case TopAbs_SOLID:
pyChild = new TopoShapeSolidPy(new TopoShape(aChild));
break;
case TopAbs_SHELL:
pyChild = new TopoShapeShellPy(new TopoShape(aChild));
break;
case TopAbs_FACE:
pyChild = new TopoShapeFacePy(new TopoShape(aChild));
break;
case TopAbs_WIRE:
pyChild = new TopoShapeWirePy(new TopoShape(aChild));
break;
case TopAbs_EDGE:
pyChild = new TopoShapeEdgePy(new TopoShape(aChild));
break;
case TopAbs_VERTEX:
pyChild = new TopoShapeVertexPy(new TopoShape(aChild));
break;
case TopAbs_SHAPE:
break;
default:
break;
}
if (pyChild) {
list.append(Py::Object(pyChild,true));
}
}
}
return Py::new_reference_to(list);
}
catch (Standard_Failure& e) {
PyErr_SetString(PartExceptionOCCError, e.GetMessageString());
return nullptr;
}
#endif
}
namespace Part {
@@ -1597,12 +968,7 @@ PyObject* TopoShapePy::mirror(PyObject *args)
try {
gp_Ax2 ax2(gp_Pnt(base.x,base.y,base.z), gp_Dir(norm.x,norm.y,norm.z));
#ifdef FC_USE_TNP_FIX
return Py::new_reference_to(shape2pyshape(getTopoShapePtr()->makeElementMirror(ax2)));
#else
TopoDS_Shape shape = this->getTopoShapePtr()->mirror(ax2);
return new TopoShapePy(new TopoShape(shape));
#endif
}
catch (Standard_Failure& e) {
PyErr_SetString(PartExceptionOCCError, e.GetMessageString());
@@ -1753,12 +1119,8 @@ PyObject* TopoShapePy::scale(PyObject *args)
BRepBuilderAPI_Transform BRepScale(scl);
bool bCopy = true;
BRepScale.Perform(shape, bCopy);
#ifdef FC_USE_TNP_FIX
TopoShape copy(*getTopoShapePtr());
getTopoShapePtr()->makeElementShape(BRepScale, copy);
#else
getTopoShapePtr()->setShape(BRepScale.Shape());
#endif
}
return IncRef();
}
@@ -1788,7 +1150,6 @@ PyObject* TopoShapePy::makeFillet(PyObject *args)
// use two radii for all edges
double radius1, radius2;
PyObject *obj;
#ifdef FC_USE_TNP_FIX
if (!PyArg_ParseTuple(args, "ddO", &radius1, &radius2, &obj)) {
PyErr_Clear();
if (!PyArg_ParseTuple(args, "dO", &radius1, &obj)) {
@@ -1806,29 +1167,6 @@ PyObject* TopoShapePy::makeFillet(PyObject *args)
getTopoShapePtr()->makeElementFillet(getPyShapes(obj), radius1, radius2)));
}
PY_CATCH_OCC
#else
if (PyArg_ParseTuple(args, "ddO", &radius1, &radius2, &obj)) {
try {
const TopoDS_Shape& shape = this->getTopoShapePtr()->getShape();
BRepFilletAPI_MakeFillet mkFillet(shape);
Py::Sequence list(obj);
for (Py::Sequence::iterator it = list.begin(); it != list.end(); ++it) {
if (PyObject_TypeCheck((*it).ptr(), &(Part::TopoShapePy::Type))) {
const TopoDS_Shape& edge = static_cast<TopoShapePy*>((*it).ptr())->getTopoShapePtr()->getShape();
if (edge.ShapeType() == TopAbs_EDGE) {
//Add edge to fillet algorithm
mkFillet.Add(radius1, radius2, TopoDS::Edge(edge));
}
}
}
return new TopoShapePy(new TopoShape(mkFillet.Shape()));
}
catch (Standard_Failure& e) {
PyErr_SetString(PartExceptionOCCError, e.GetMessageString());
return nullptr;
}
}
#endif
PyErr_Clear();
// use one radius for all edges
double radius;
@@ -1866,7 +1204,6 @@ PyObject* TopoShapePy::makeChamfer(PyObject *args)
// use two radii for all edges
double radius1, radius2;
PyObject *obj;
#ifdef FC_USE_TNP_FIX
if (!PyArg_ParseTuple(args, "ddO", &radius1, &radius2, &obj)) {
if (!PyArg_ParseTuple(args, "dO", &radius1, &obj)) {
PyErr_SetString(PyExc_TypeError,
@@ -1884,35 +1221,6 @@ PyObject* TopoShapePy::makeChamfer(PyObject *args)
getTopoShapePtr()->makeElementChamfer(getPyShapes(obj), Part::ChamferType::twoDistances, radius1, radius2)));
}
PY_CATCH_OCC
#else
if (PyArg_ParseTuple(args, "ddO", &radius1, &radius2, &obj)) {
try {
const TopoDS_Shape& shape = this->getTopoShapePtr()->getShape();
BRepFilletAPI_MakeChamfer mkChamfer(shape);
TopTools_IndexedMapOfShape mapOfEdges;
TopTools_IndexedDataMapOfShapeListOfShape mapEdgeFace;
TopExp::MapShapesAndAncestors(shape, TopAbs_EDGE, TopAbs_FACE, mapEdgeFace);
TopExp::MapShapes(shape, TopAbs_EDGE, mapOfEdges);
Py::Sequence list(obj);
for (Py::Sequence::iterator it = list.begin(); it != list.end(); ++it) {
if (PyObject_TypeCheck((*it).ptr(), &(Part::TopoShapePy::Type))) {
const TopoDS_Shape& edge = static_cast<TopoShapePy*>((*it).ptr())->getTopoShapePtr()->getShape();
if (edge.ShapeType() == TopAbs_EDGE) {
//Add edge to fillet algorithm
const TopoDS_Face& face = TopoDS::Face(mapEdgeFace.FindFromKey(edge).First());
mkChamfer.Add(radius1, radius2, TopoDS::Edge(edge), face);
}
}
}
return new TopoShapePy(new TopoShape(mkChamfer.Shape()));
}
catch (Standard_Failure& e) {
PyErr_SetString(PartExceptionOCCError, e.GetMessageString());
return nullptr;
}
}
#endif
PyErr_Clear();
// use one radius for all edges
// TODO: Should this be using makeElementChamfer to support Toponaming fixes?
@@ -1962,7 +1270,6 @@ PyObject* TopoShapePy::makeThickness(PyObject *args)
return nullptr;
try {
#ifdef FC_USE_TNP_FIX
return Py::new_reference_to(shape2pyshape(
getTopoShapePtr()->makeElementThickSolid(getPyShapes(obj),
offset,
@@ -1971,20 +1278,6 @@ PyObject* TopoShapePy::makeThickness(PyObject *args)
PyObject_IsTrue(self_inter) ? true : false,
offsetMode,
static_cast<JoinType>(join))));
#else
TopTools_ListOfShape facesToRemove;
Py::Sequence list(obj);
for (Py::Sequence::iterator it = list.begin(); it != list.end(); ++it) {
if (PyObject_TypeCheck((*it).ptr(), &(Part::TopoShapePy::Type))) {
const TopoDS_Shape& shape = static_cast<TopoShapePy*>((*it).ptr())->getTopoShapePtr()->getShape();
facesToRemove.Append(shape);
}
}
TopoDS_Shape shape = this->getTopoShapePtr()->makeThickSolid(facesToRemove, offset, tolerance,
Base::asBoolean(inter), Base::asBoolean(self_inter), offsetMode, join);
return new TopoShapeSolidPy(new TopoShape(shape));
#endif
}
catch (Standard_Failure& e) {
PyErr_SetString(PartExceptionOCCError, e.GetMessageString());
@@ -2008,7 +1301,6 @@ PyObject* TopoShapePy::makeOffsetShape(PyObject *args, PyObject *keywds)
}
try {
#ifdef FC_USE_TNP_FIX
return Py::new_reference_to(shape2pyshape(getTopoShapePtr()->makeElementOffset(
offset,
tolerance,
@@ -2017,13 +1309,6 @@ PyObject* TopoShapePy::makeOffsetShape(PyObject *args, PyObject *keywds)
offsetMode,
static_cast<JoinType>(join),
PyObject_IsTrue(fill) ? FillType::fill : FillType::noFill)));
#else
TopoDS_Shape shape = this->getTopoShapePtr()->makeOffsetShape(offset, tolerance,
Base::asBoolean(inter),
Base::asBoolean(self_inter), offsetMode, join,
Base::asBoolean(fill));
return new TopoShapePy(new TopoShape(shape));
#endif
}
catch (Standard_Failure& e) {
PyErr_SetString(PartExceptionOCCError, e.GetMessageString());
@@ -2046,18 +1331,12 @@ PyObject* TopoShapePy::makeOffset2D(PyObject *args, PyObject *keywds)
}
try {
#ifdef FC_USE_TNP_FIX
return Py::new_reference_to(shape2pyshape(getTopoShapePtr()->makeElementOffset2D(
offset,
static_cast<JoinType>(join),
PyObject_IsTrue(fill) ? FillType::fill : FillType::noFill,
PyObject_IsTrue(openResult) ? OpenResult::allowOpenResult : OpenResult::noOpenResult,
PyObject_IsTrue(inter) ? true : false)));
#else
TopoDS_Shape resultShape = this->getTopoShapePtr()->makeOffset2D(offset, join,
Base::asBoolean(fill), Base::asBoolean(openResult), Base::asBoolean(inter));
return new_reference_to(shape2pyshape(resultShape));
#endif
}
PY_CATCH_OCC;
}
@@ -2480,7 +1759,7 @@ PyObject* TopoShapePy::makeEvolved(PyObject *args, PyObject *kwds)
PyObject* ProfOnSpine = Py_False;
auto JoinType = JoinType::arc;
double Tolerance = 0.0000001;
static const std::array<const char*, 7> kwds_evolve{"Profile", "Join", "AxeProf", "Solid", "ProfOnSpine", "Tolerance", nullptr};
if (!Base::Wrapped_ParseTupleAndKeywords(args, kwds, "O!|iO!O!O!d", kwds_evolve,
&TopoShapePy::Type, &Profile, &JoinType,
@@ -2585,13 +1864,7 @@ PyObject* TopoShapePy::removeSplitter(PyObject *args)
return nullptr;
try {
#ifdef FC_USE_TNP_FIX
return Py::new_reference_to(shape2pyshape(getTopoShapePtr()->makeElementRefine()));
#else
// Remove redundant splitter
TopoDS_Shape shape = this->getTopoShapePtr()->removeSplitter();
return new TopoShapePy(new TopoShape(shape));
#endif
}
catch (Standard_Failure& e) {
PyErr_SetString(PartExceptionOCCError, e.GetMessageString());
-49
View File
@@ -86,49 +86,10 @@ int TopoShapeShellPy::PyInit(PyObject* args, PyObject* /*kwd*/)
if (!PyArg_ParseTuple(args, "O", &obj))
return -1;
#ifdef FC_USE_TNP_FIX
try {
getTopoShapePtr()->makeElementBoolean(Part::OpCodes::Shell, getPyShapes(obj));
}
_PY_CATCH_OCC(return (-1))
#else
BRep_Builder builder;
TopoDS_Shape shape;
TopoDS_Shell shell;
//BRepOffsetAPI_Sewing mkShell;
builder.MakeShell(shell);
try {
Py::Sequence list(obj);
for (Py::Sequence::iterator it = list.begin(); it != list.end(); ++it) {
if (PyObject_TypeCheck((*it).ptr(), &(Part::TopoShapeFacePy::Type))) {
const TopoDS_Shape& sh = static_cast<TopoShapeFacePy*>((*it).ptr())->
getTopoShapePtr()->getShape();
if (!sh.IsNull())
builder.Add(shell, sh);
}
}
shape = shell;
BRepCheck_Analyzer check(shell);
if (!check.IsValid()) {
ShapeUpgrade_ShellSewing sewShell;
shape = sewShell.ApplySewing(shell);
}
if (shape.IsNull())
Standard_Failure::Raise("Shape is null");
if (shape.ShapeType() != TopAbs_SHELL)
Standard_Failure::Raise("Shape is not a shell");
}
catch (Standard_Failure& e) {
PyErr_SetString(PartExceptionOCCError, e.GetMessageString());
return -1;
}
getTopoShapePtr()->setShape(shape);
#endif
return 0;
}
@@ -150,9 +111,7 @@ PyObject* TopoShapeShellPy::add(PyObject *args)
if (!sh.IsNull()) {
builder.Add(shell, sh);
BRepCheck_Analyzer check(shell);
#ifdef FC_USE_TNP_FIX
getTopoShapePtr()->mapSubElement(shape);
#endif
if (!check.IsValid()) {
ShapeUpgrade_ShellSewing sewShell;
getTopoShapePtr()->setShape(sewShell.ApplySewing(shell));
@@ -181,14 +140,10 @@ PyObject* TopoShapeShellPy::getFreeEdges(PyObject *args)
as.CheckOrientedShells(getTopoShapePtr()->getShape(), Standard_True, Standard_True);
TopoDS_Compound comp = as.FreeEdges();
#ifdef FC_USE_TNP_FIX
TopoShape res;
res.setShape(comp);
res.mapSubElement(*getTopoShapePtr());
return Py::new_reference_to(shape2pyshape(res));
#else
return new TopoShapeCompoundPy(new TopoShape(comp));
#endif
}
PyObject* TopoShapeShellPy::getBadEdges(PyObject *args)
@@ -200,14 +155,10 @@ PyObject* TopoShapeShellPy::getBadEdges(PyObject *args)
as.CheckOrientedShells(getTopoShapePtr()->getShape(), Standard_True, Standard_True);
TopoDS_Compound comp = as.BadEdges();
#ifdef FC_USE_TNP_FIX
TopoShape res;
res.setShape(comp);
res.mapSubElement(*getTopoShapePtr());
return Py::new_reference_to(shape2pyshape(res));
#else
return new TopoShapeCompoundPy(new TopoShape(comp));
#endif
}
PyObject* TopoShapeShellPy::makeHalfSpace(PyObject *args)
-46
View File
@@ -88,45 +88,7 @@ int TopoShapeSolidPy::PyInit(PyObject* args, PyObject* /*kwd*/)
return -1;
try {
#ifdef FC_USE_TNP_FIX
getTopoShapePtr()->makeElementSolid(*static_cast<TopoShapePy*>(obj)->getTopoShapePtr());
#else
const TopoDS_Shape& shape = static_cast<TopoShapePy*>(obj)
->getTopoShapePtr()->getShape();
//first, if we were given a compsolid, try making a solid out of it
TopExp_Explorer CSExp (shape, TopAbs_COMPSOLID);
TopoDS_CompSolid compsolid;
int count=0;
for (; CSExp.More(); CSExp.Next()) {
++count;
compsolid = TopoDS::CompSolid(CSExp.Current());
if (count > 1)
break;
}
if (count == 0) {
//no compsolids. Get shells...
BRepBuilderAPI_MakeSolid mkSolid;
TopExp_Explorer anExp (shape, TopAbs_SHELL);
count=0;
for (; anExp.More(); anExp.Next()) {
++count;
mkSolid.Add(TopoDS::Shell(anExp.Current()));
}
if (count == 0)//no shells?
Standard_Failure::Raise("No shells or compsolids found in shape");
TopoDS_Solid solid = mkSolid.Solid();
BRepLib::OrientClosedSolid(solid);
getTopoShapePtr()->setShape(solid);
} else if (count == 1) {
BRepBuilderAPI_MakeSolid mkSolid(compsolid);
TopoDS_Solid solid = mkSolid.Solid();
getTopoShapePtr()->setShape(solid);
} else /*if (count > 1)*/ {
Standard_Failure::Raise("Only one compsolid can be accepted. Provided shape has more than one compsolid.");
}
#endif
}
catch (Standard_Failure& err) {
std::stringstream errmsg;
@@ -220,14 +182,10 @@ Py::Object TopoShapeSolidPy::getOuterShell() const
const TopoDS_Shape& shape = getTopoShapePtr()->getShape();
if (!shape.IsNull() && shape.ShapeType() == TopAbs_SOLID)
shell = BRepClass3d::OuterShell(TopoDS::Solid(shape));
#ifdef FC_USE_TNP_FIX
TopoShape res;
res.setShape(shell);
res.mapSubElement(*getTopoShapePtr());
return shape2pyshape(res);
#else
return Py::Object(new TopoShapeShellPy(new TopoShape(shell)),true);
#endif
}
PyObject* TopoShapeSolidPy::getMomentOfInertia(PyObject *args)
@@ -327,13 +285,9 @@ PyObject* TopoShapeSolidPy::offsetFaces(PyObject *args)
try {
builder.MakeOffsetShape();
const TopoDS_Shape& offsetshape = builder.Shape();
#ifdef FC_USE_TNP_FIX
TopoShape res;
res.setShape(offsetshape);
return Py::new_reference_to(shape2pyshape(res));
#else
return new TopoShapeSolidPy(new TopoShape(offsetshape));
#endif
}
catch (Standard_Failure& e) {
-3
View File
@@ -62,9 +62,6 @@ Feature::Feature()
BaseFeature.setStatus(App::Property::Hidden, true);
App::SuppressibleExtension::initExtension(this);
#ifndef FC_USE_TNP_FIX
Suppressed.setStatus(App::Property::Status::Hidden, true);
#endif
}
App::DocumentObjectExecReturn* Feature::recompute()
-106
View File
@@ -114,7 +114,6 @@ App::DocumentObjectExecReturn *Chamfer::execute()
return new App::DocumentObjectExecReturn(e.what());
}
#ifdef FC_USE_TNP_FIX
TopShape.setTransform(Base::Matrix4D());
auto edges = UseAllEdges.getValue() ? TopShape.getSubTopoShapes(TopAbs_EDGE)
@@ -124,24 +123,6 @@ App::DocumentObjectExecReturn *Chamfer::execute()
return new App::DocumentObjectExecReturn(
QT_TRANSLATE_NOOP("Exception", "No edges specified"));
}
#else
std::vector<std::string> SubNames = std::vector<std::string>(Base.getSubValues());
if (UseAllEdges.getValue()){
SubNames.clear();
std::string edgeTypeName = Part::TopoShape::shapeName(TopAbs_EDGE); //"Edge"
int count = TopShape.countSubElements(edgeTypeName.c_str());
for (int ii = 0; ii < count; ii++){
std::ostringstream edgeName;
edgeName << edgeTypeName << ii+1;
SubNames.push_back(edgeName.str());
}
}
std::vector<std::string> FaceNames;
getContinuousEdges(TopShape, SubNames, FaceNames);
#endif
const int chamferType = ChamferType.getValue();
const double size = Size.getValue();
double size2 = Size2.getValue();
@@ -155,22 +136,10 @@ App::DocumentObjectExecReturn *Chamfer::execute()
this->positionByBaseFeature();
#ifdef FC_USE_TNP_FIX
if ( static_cast<Part::ChamferType>(chamferType) == Part::ChamferType::distanceAngle ) {
size2 = angle;
}
#else
//If no element is selected, then we use a copy of previous feature.
if (SubNames.empty()) {
this->Shape.setValue(TopShape);
return App::DocumentObject::StdReturn;
}
// create an untransformed copy of the basefeature shape
Part::TopoShape baseShape(TopShape);
baseShape.setTransform(Base::Matrix4D());
#endif
try {
#ifdef FC_USE_TNP_FIX
TopoShape shape(0);
shape.makeElementChamfer(TopShape,
edges,
@@ -207,81 +176,6 @@ App::DocumentObjectExecReturn *Chamfer::execute()
QT_TRANSLATE_NOOP("Exception", "Resulting shape is invalid"));
}
return App::DocumentObject::StdReturn;
#else
BRepFilletAPI_MakeChamfer mkChamfer(baseShape.getShape());
TopTools_IndexedDataMapOfShapeListOfShape mapEdgeFace;
TopExp::MapShapesAndAncestors(baseShape.getShape(), TopAbs_EDGE, TopAbs_FACE, mapEdgeFace);
for (const auto &itSN : SubNames) {
TopoDS_Edge edge = TopoDS::Edge(baseShape.getSubShape(itSN.c_str()));
const TopoDS_Shape& faceLast = mapEdgeFace.FindFromKey(edge).Last();
const TopoDS_Shape& faceFirst = mapEdgeFace.FindFromKey(edge).First();
// Set the face based on flipDirection for all edges by default. Note for chamferType==0 it does not matter which face is used.
TopoDS_Face face = TopoDS::Face( flipDirection ? faceLast : faceFirst );
// for chamfer types otherthan Equal (type = 0) check if one of the faces associated with the edge
// is one of the originally selected faces. If so use the other face by default or the selected face if "flipDirection" is set
if (chamferType != 0) {
// for each selected face
for (const auto &itFN : FaceNames) {
const TopoDS_Shape selFace = baseShape.getSubShape(itFN.c_str());
if ( faceLast.IsEqual(selFace) )
face = TopoDS::Face( flipDirection ? faceFirst : faceLast );
else if ( faceFirst.IsEqual(selFace) )
face = TopoDS::Face( flipDirection ? faceLast : faceFirst );
}
}
switch (chamferType) {
case 0: // Equal distance
mkChamfer.Add(size, size, edge, face);
break;
case 1: // Two distances
mkChamfer.Add(size, size2, edge, face);
break;
case 2: // Distance and angle
mkChamfer.AddDA(size, Base::toRadians(angle), edge, face);
break;
}
}
mkChamfer.Build();
if (!mkChamfer.IsDone())
return new App::DocumentObjectExecReturn(QT_TRANSLATE_NOOP("Exception", "Failed to create chamfer"));
TopoDS_Shape shape = mkChamfer.Shape();
if (shape.IsNull())
return new App::DocumentObjectExecReturn(QT_TRANSLATE_NOOP("Exception", "Resulting shape is null"));
TopTools_ListOfShape aLarg;
aLarg.Append(baseShape.getShape());
if (!BRepAlgo::IsValid(aLarg, shape, Standard_False, Standard_False)) {
ShapeFix_ShapeTolerance aSFT;
aSFT.LimitTolerance(shape, Precision::Confusion(), Precision::Confusion(), TopAbs_SHAPE);
Handle(ShapeFix_Shape) aSfs = new ShapeFix_Shape(shape);
aSfs->Perform();
shape = aSfs->Shape();
if (!BRepAlgo::IsValid(aLarg, shape, Standard_False, Standard_False)) {
return new App::DocumentObjectExecReturn(QT_TRANSLATE_NOOP("Exception", "Resulting shape is invalid"));
}
}
if (!isSingleSolidRuleSatisfied(shape)) {
return new App::DocumentObjectExecReturn(QT_TRANSLATE_NOOP("Exception", "Result has multiple solids: that is not currently supported."));
}
shape = refineShapeIfActive(shape);
this->Shape.setValue(getSolid(shape));
return App::DocumentObject::StdReturn;
#endif
}
catch (Standard_Failure& e) {
return new App::DocumentObjectExecReturn(e.GetMessageString());
-17
View File
@@ -325,11 +325,7 @@ void DressUp::getAddSubShape(Part::TopoShape &addShape, Part::TopoShape &subShap
baseShape.move(base->getLocation().Inverted());
if (base->getAddSubType() == Additive) {
if(!baseShape.isNull() && baseShape.hasSubShape(TopAbs_SOLID))
#ifdef FC_USE_TNP_FIX
shapes.emplace_back(shape.makeElementCut(baseShape.getShape()));
#else
shapes.emplace_back(shape.cut(baseShape.getShape()));
#endif
else
shapes.push_back(shape);
} else {
@@ -339,35 +335,22 @@ void DressUp::getAddSubShape(Part::TopoShape &addShape, Part::TopoShape &subShap
// push an empty compound to indicate null additive shape
shapes.emplace_back(comp);
if(!baseShape.isNull() && baseShape.hasSubShape(TopAbs_SOLID))
#ifdef FC_USE_TNP_FIX
shapes.emplace_back(baseShape.makeElementCut(shape.getShape()));
#else
shapes.emplace_back(baseShape.cut(shape.getShape()));
#endif
else
shapes.push_back(shape);
}
} else {
baseShape = getBaseTopoShape();
baseShape.move(getLocation().Inverted());
#ifdef FC_USE_TNP_FIX
shapes.emplace_back(shape.makeElementCut(baseShape.getShape()));
shapes.emplace_back(baseShape.makeElementCut(shape.getShape()));
#else
shapes.emplace_back(shape.cut(baseShape.getShape()));
shapes.emplace_back(baseShape.cut(shape.getShape()));
#endif
}
// Make a compound to contain both additive and subtractive shape,
// bceause a dressing (e.g. a fillet) can either be additive or
// subtractive. And the dressup feature can contain mixture of both.
#ifdef FC_USE_TNP_FIX
AddSubShape.setValue(Part::TopoShape().makeElementCompound(shapes));
#else
AddSubShape.setValue(Part::TopoShape().makeCompound(shapes));
#endif
} catch (Standard_Failure &e) {
FC_THROWM(Base::CADKernelError, "Failed to calculate AddSub shape: "
<< e.GetMessageString());
-82
View File
@@ -65,7 +65,6 @@ short Fillet::mustExecute() const
App::DocumentObjectExecReturn *Fillet::execute()
{
#ifdef FC_USE_TNP_FIX
Part::TopoShape baseShape;
try {
baseShape = getBaseTopoShape();
@@ -127,87 +126,6 @@ App::DocumentObjectExecReturn *Fillet::execute()
catch (Standard_Failure& e) {
return new App::DocumentObjectExecReturn(e.GetMessageString());
}
#else
Part::TopoShape TopShape;
try {
TopShape = getBaseTopoShape();
}
catch (Base::Exception& e) {
return new App::DocumentObjectExecReturn(e.what());
}
std::vector<std::string> SubNames = std::vector<std::string>(Base.getSubValues());
if (UseAllEdges.getValue()){
SubNames.clear();
std::string edgeTypeName = Part::TopoShape::shapeName(TopAbs_EDGE); //"Edge"
int count = TopShape.countSubElements(edgeTypeName.c_str());
for (int ii = 0; ii < count; ii++){
std::ostringstream edgeName;
edgeName << edgeTypeName << ii+1;
SubNames.push_back(edgeName.str());
}
}
getContinuousEdges(TopShape, SubNames);
double radius = Radius.getValue();
if(radius <= 0)
return new App::DocumentObjectExecReturn(QT_TRANSLATE_NOOP("Exception", "Fillet radius must be greater than zero"));
this->positionByBaseFeature();
//If no element is selected, then we use a copy of previous feature.
if (SubNames.empty()) {
this->Shape.setValue(TopShape);
return App::DocumentObject::StdReturn;
}
// create an untransformed copy of the base shape
Part::TopoShape baseShape(TopShape);
baseShape.setTransform(Base::Matrix4D());
try {
BRepFilletAPI_MakeFillet mkFillet(baseShape.getShape());
for (const auto & it : SubNames) {
TopoDS_Edge edge = TopoDS::Edge(baseShape.getSubShape(it.c_str()));
mkFillet.Add(radius, edge);
}
mkFillet.Build();
if (!mkFillet.IsDone())
return new App::DocumentObjectExecReturn(QT_TRANSLATE_NOOP("Exception", "Failed to create fillet"));
TopoDS_Shape shape = mkFillet.Shape();
if (shape.IsNull())
return new App::DocumentObjectExecReturn(QT_TRANSLATE_NOOP("Exception", "Resulting shape is null"));
TopTools_ListOfShape aLarg;
aLarg.Append(baseShape.getShape());
if (!BRepAlgo::IsValid(aLarg, shape, Standard_False, Standard_False)) {
ShapeFix_ShapeTolerance aSFT;
aSFT.LimitTolerance(shape, Precision::Confusion(), Precision::Confusion(), TopAbs_SHAPE);
Handle(ShapeFix_Shape) aSfs = new ShapeFix_Shape(shape);
aSfs->Perform();
shape = aSfs->Shape();
if (!BRepAlgo::IsValid(aLarg, shape, Standard_False, Standard_False)) {
return new App::DocumentObjectExecReturn(QT_TRANSLATE_NOOP("Exception", "Resulting shape is invalid"));
}
}
if (!isSingleSolidRuleSatisfied(shape)) {
return new App::DocumentObjectExecReturn(QT_TRANSLATE_NOOP("Exception", "Result has multiple solids: that is not currently supported."));
}
shape = refineShapeIfActive(shape);
this->Shape.setValue(getSolid(shape));
return App::DocumentObject::StdReturn;
}
catch (Standard_Failure& e) {
return new App::DocumentObjectExecReturn(e.GetMessageString());
}
#endif
}
void Fillet::Restore(Base::XMLReader &reader)
-166
View File
@@ -79,170 +79,6 @@ short Groove::mustExecute() const
return ProfileBased::mustExecute();
}
#ifndef FC_USE_TNP_FIX
App::DocumentObjectExecReturn *Groove::execute()
{
// Validate parameters
// All angles are in radians unless explicitly stated
double angleDeg = Angle.getValue();
if (angleDeg > 360.0)
return new App::DocumentObjectExecReturn(QT_TRANSLATE_NOOP("Exception", "Angle of groove too large"));
double angle = Base::toRadians<double>(angleDeg);
if (angle < Precision::Angular())
return new App::DocumentObjectExecReturn(QT_TRANSLATE_NOOP("Exception", "Angle of groove too small"));
double angle2 = Base::toRadians(Angle2.getValue());
TopoDS_Shape sketchshape;
try {
sketchshape = getVerifiedFace();
} catch (const Base::Exception& e) {
return new App::DocumentObjectExecReturn(e.what());
}
// if the Base property has a valid shape, fuse the prism into it
TopoDS_Shape base;
try {
base = getBaseShape();
}
catch (const Base::Exception&) {
std::string text(QT_TRANSLATE_NOOP("Exception", "The requested feature cannot be created. The reason may be that:\n"
" - the active Body does not contain a base shape, so there is no\n"
" material to be removed;\n"
" - the selected sketch does not belong to the active Body."));
return new App::DocumentObjectExecReturn(text);
}
// update Axis from ReferenceAxis
try {
updateAxis();
} catch (const Base::Exception& e) {
return new App::DocumentObjectExecReturn(e.what());
}
// get revolve axis
Base::Vector3d b = Base.getValue();
gp_Pnt pnt(b.x,b.y,b.z);
Base::Vector3d v = Axis.getValue();
gp_Dir dir(v.x,v.y,v.z);
try {
if (sketchshape.IsNull())
return new App::DocumentObjectExecReturn(QT_TRANSLATE_NOOP("Exception", "Creating a face from sketch failed"));
RevolMethod method = methodFromString(Type.getValueAsString());
this->positionByPrevious();
TopLoc_Location invObjLoc = this->getLocation().Inverted();
pnt.Transform(invObjLoc.Transformation());
dir.Transform(invObjLoc.Transformation());
base.Move(invObjLoc);
sketchshape.Move(invObjLoc);
// Check distance between sketchshape and axis - to avoid failures and crashes
TopExp_Explorer xp;
xp.Init(sketchshape, TopAbs_FACE);
for (;xp.More(); xp.Next()) {
if (checkLineCrossesFace(gp_Lin(pnt, dir), TopoDS::Face(xp.Current())))
return new App::DocumentObjectExecReturn(QT_TRANSLATE_NOOP("Exception", "Revolve axis intersects the sketch"));
}
// Create a fresh support even when base exists so that it can be used for patterns
TopoDS_Shape result;
TopoDS_Face supportface = getSupportFace();
supportface.Move(invObjLoc);
if (method == RevolMethod::ToFace || method == RevolMethod::ToFirst) {
TopoDS_Face upToFace;
if (method == RevolMethod::ToFace) {
getFaceFromLinkSub(upToFace, UpToFace);
upToFace.Move(invObjLoc);
}
else
throw Base::RuntimeError("ProfileBased: Groove up to first is not yet supported");
// TODO: This method is designed for extrusions. needs to be adapted for grooves.
// getUpToFace(upToFace, base, supportface, sketchshape, method, dir);
TopoDS_Face supportface = getSupportFace();
supportface.Move(invObjLoc);
if (Reversed.getValue())
dir.Reverse();
TopExp_Explorer Ex(supportface,TopAbs_WIRE);
if (!Ex.More())
supportface = TopoDS_Face();
RevolMode mode = RevolMode::CutFromBase;
generateRevolution(result, base, sketchshape, supportface, upToFace, gp_Ax1(pnt, dir), method, mode, Standard_True);
result = refineShapeIfActive(result);
// the result we get here is the shape _after_ the operation is done
// And the really expensive way to get the SubShape...
BRepAlgoAPI_Cut mkCut(base, result);
if (!mkCut.IsDone())
return new App::DocumentObjectExecReturn("Groove: Up to face: Could not get SubShape!");
// FIXME: In some cases this affects the Shape property: It is set to the same shape as the SubShape!!!!
TopoDS_Shape subshape = refineShapeIfActive(mkCut.Shape());
this->AddSubShape.setValue(subshape);
if (!isSingleSolidRuleSatisfied(result)) {
return new App::DocumentObjectExecReturn("Groove: Result has multiple solids. This is not supported at this time.");
}
this->Shape.setValue(getSolid(result));
}
else {
bool midplane = Midplane.getValue();
bool reversed = Reversed.getValue();
generateRevolution(result, sketchshape, gp_Ax1(pnt, dir), angle, angle2, midplane, reversed, method);
if (result.IsNull())
return new App::DocumentObjectExecReturn(QT_TRANSLATE_NOOP("Exception", "Could not revolve the sketch!"));
// set the subtractive shape property for later usage in e.g. pattern
result = refineShapeIfActive(result);
this->AddSubShape.setValue(result);
// cut out groove to get one result object
BRepAlgoAPI_Cut mkCut(base, result);
// Let's check if the fusion has been successful
if (!mkCut.IsDone())
throw Base::CADKernelError(QT_TRANSLATE_NOOP("Exception", "Cut out of base feature failed"));
// we have to get the solids (fuse sometimes creates compounds)
TopoDS_Shape solRes = this->getSolid(mkCut.Shape());
if (solRes.IsNull())
return new App::DocumentObjectExecReturn(QT_TRANSLATE_NOOP("Exception", "Resulting shape is not a solid"));
solRes = refineShapeIfActive(solRes);
this->Shape.setValue(getSolid(solRes));
if (!isSingleSolidRuleSatisfied(solRes)) {
return new App::DocumentObjectExecReturn(QT_TRANSLATE_NOOP("Exception", "Result has multiple solids: that is not currently supported."));
}
}
// eventually disable some settings that are not valid for the current method
updateProperties(method);
return App::DocumentObject::StdReturn;
}
catch (Standard_Failure& e) {
if (std::string(e.GetMessageString()) == "TopoDS::Face")
return new App::DocumentObjectExecReturn(QT_TRANSLATE_NOOP("Exception", "Could not create face from sketch.\n"
"Intersecting sketch entities in a sketch are not allowed."));
else
return new App::DocumentObjectExecReturn(e.GetMessageString());
}
catch (Base::Exception& e) {
return new App::DocumentObjectExecReturn(e.what());
}
}
#else
App::DocumentObjectExecReturn *Groove::execute()
{
// Validate parameters
@@ -372,8 +208,6 @@ App::DocumentObjectExecReturn *Groove::execute()
}
}
#endif
bool Groove::suggestReversed()
{
updateAxis();
-269
View File
@@ -65,273 +65,6 @@ short Loft::mustExecute() const
return ProfileBased::mustExecute();
}
#ifndef FC_USE_TNP_FIX
App::DocumentObjectExecReturn *Loft::execute()
{
auto getSectionShape =
[](App::DocumentObject* feature, const std::vector<std::string> &subs) -> TopoDS_Shape {
if (!feature ||
!feature->isDerivedFrom(Part::Feature::getClassTypeId()))
throw Base::TypeError("Loft: Invalid profile/section");
auto subName = subs.empty() ? "" : subs.front();
// only take the entire shape when we have a sketch selected, but
// not a point of the sketch
if (feature->isDerivedFrom(Part::Part2DObject::getClassTypeId()) &&
subName.compare(0, 6, "Vertex") != 0)
return static_cast<Part::Part2DObject*>(feature)->Shape.getValue();
else {
if(subName.empty())
throw Base::ValueError("No valid subelement linked in Part::Feature");
return static_cast<Part::Feature*>(feature)->Shape.getShape().getSubShape(subName.c_str());
}
};
auto addWiresToWireSections =
[](TopoDS_Shape& section,
std::vector<std::vector<TopoDS_Shape>>& wiresections) -> size_t {
TopExp_Explorer ex;
size_t i=0;
bool initialWireSectionsEmpty = wiresections.empty();
for (ex.Init(section, TopAbs_WIRE); ex.More(); ex.Next(), ++i) {
// if profile was just a point then this is where we can first set our list
if (i>=wiresections.size()) {
if (initialWireSectionsEmpty)
wiresections.emplace_back(1, ex.Current());
else
throw Base::ValueError("Loft: Sections need to have the same amount of inner wires (except profile and last section, which can be points)");
}
else
wiresections[i].push_back(TopoDS::Wire(ex.Current()));
}
return i;
};
std::vector<TopoDS_Wire> wires;
TopoDS_Shape profilePoint;
// if the Base property has a valid shape, fuse the pipe into it
TopoDS_Shape base;
try {
base = getBaseShape();
} catch (const Base::Exception&) {
base = TopoDS_Shape();
}
try {
// setup the location
this->positionByPrevious();
TopLoc_Location invObjLoc = this->getLocation().Inverted();
if (!base.IsNull())
base.Move(invObjLoc);
// build up multisections
auto multisections = Sections.getSubListValues();
if (multisections.empty())
return new App::DocumentObjectExecReturn(QT_TRANSLATE_NOOP("Exception", "Loft: At least one section is needed"));
TopoDS_Shape profileShape = getSectionShape(Profile.getValue(),
Profile.getSubValues());
if (profileShape.IsNull())
return new App::DocumentObjectExecReturn(QT_TRANSLATE_NOOP("Exception", "Loft: Could not obtain profile shape"));
std::vector<std::vector<TopoDS_Shape>> wiresections;
size_t numWires = addWiresToWireSections(profileShape, wiresections);
if (numWires == 0) {
// profileShape had no wires so only other valid option is point section
TopExp_Explorer ex;
size_t i = 0;
for (ex.Init(profileShape, TopAbs_VERTEX); ex.More(); ex.Next(), ++i) {
profilePoint = ex.Current();
}
if (i > 1)
return new App::DocumentObjectExecReturn(QT_TRANSLATE_NOOP("Exception", "Loft: When using points for profile/sections, the sketch should have a single point"));
}
bool isLastSectionVertex = false;
size_t subSetCnt=0;
for (const auto & subSet : multisections) {
if (!subSet.first->isDerivedFrom(Part::Feature::getClassTypeId()))
return new App::DocumentObjectExecReturn(QT_TRANSLATE_NOOP("Exception", "Loft: All sections need to be part features"));
// if the selected subvalue is a point, pick that even if we have a sketch
TopoDS_Shape shape = getSectionShape(subSet.first, subSet.second);
if (shape.IsNull())
return new App::DocumentObjectExecReturn(QT_TRANSLATE_NOOP("Exception", "Loft: Could not obtain section shape"));
size_t numWiresAdded = addWiresToWireSections(shape, wiresections);
if (numWiresAdded == 0) {
// The shape of the given object doesn't contain any wires, though it still might be valid if it is a vertex (or a COMPOUND consisting a single vertex)
TopoDS_Shape vertexShape;
TopExp_Explorer ex{shape, TopAbs_VERTEX};
if (ex.More()) {
vertexShape = ex.Current();
ex.Next();
if (ex.More()) { // some additional vertexes in the shape, we shouldn't use it
vertexShape.Nullify();
}
}
if (vertexShape.IsNull())
return new App::DocumentObjectExecReturn(QT_TRANSLATE_NOOP("Exception", "Loft: A section doesn't contain any wires nor is a single vertex"));
if (subSetCnt != multisections.size()-1)
return new App::DocumentObjectExecReturn(QT_TRANSLATE_NOOP("Exception", "Loft: Only the profile and the last section can be vertices"));
if (Closed.getValue())
return new App::DocumentObjectExecReturn(QT_TRANSLATE_NOOP("Exception", "Loft: For closed lofts only the profile can be a vertex"));
// all good; push vertex to all wiresection list
for (auto &wires : wiresections)
wires.push_back(vertexShape);
isLastSectionVertex = true;
} else if (numWiresAdded != wiresections.size())
return new App::DocumentObjectExecReturn(QT_TRANSLATE_NOOP("Exception", "Loft: all loft sections need to have the same amount of inner wires"));
subSetCnt++;
}
if (Closed.getValue()) {
// For a closed loft add starting sketch again at the end
if (profilePoint.IsNull()) {
size_t numWiresAdded = addWiresToWireSections(profileShape, wiresections);
assert (numWiresAdded == wiresections.size());
boost::ignore_unused(numWiresAdded);
} else { // !profilePoint.IsNull()
for (auto &wires : wiresections)
wires.push_back(profilePoint);
}
}
// build all shells
std::vector<TopoDS_Shape> shells;
TopoDS_Shape copyProfilePoint(profilePoint);
if (!profilePoint.IsNull())
copyProfilePoint.Move(invObjLoc);
for (auto& wires : wiresections) {
BRepOffsetAPI_ThruSections mkTS(false, Ruled.getValue(), Precision::Confusion());
if (!profilePoint.IsNull())
mkTS.AddVertex(TopoDS::Vertex(copyProfilePoint));
for (auto& shape : wires) {
shape.Move(invObjLoc);
if (shape.ShapeType() == TopAbs_VERTEX)
mkTS.AddVertex(TopoDS::Vertex(shape));
else
mkTS.AddWire(TopoDS::Wire(shape));
}
mkTS.Build();
if (!mkTS.IsDone())
return new App::DocumentObjectExecReturn(QT_TRANSLATE_NOOP("Exception", "Loft could not be built"));
// build the shell use simulate to get the top and bottom wires in an easy way
shells.push_back(mkTS.Shape());
}
// build the top and bottom faces (where possible), sew the shell,
// and build the final solid
BRepBuilderAPI_Sewing sewer;
sewer.SetTolerance(Precision::Confusion());
if (!Closed.getValue()) {
if (profilePoint.IsNull()) {
TopoDS_Shape front = getVerifiedFace();
front.Move(invObjLoc);
sewer.Add(front);
}
if (!isLastSectionVertex) {
std::vector<TopoDS_Wire> backwires;
for (auto& wires : wiresections)
backwires.push_back(TopoDS::Wire(wires.back()));
TopoDS_Shape back = Part::FaceMakerCheese::makeFace(backwires);
sewer.Add(back);
}
}
for (TopoDS_Shape& s : shells)
sewer.Add(s);
sewer.Perform();
// build the solid
BRepBuilderAPI_MakeSolid mkSolid;
mkSolid.Add(TopoDS::Shell(sewer.SewedShape()));
if (!mkSolid.IsDone())
return new App::DocumentObjectExecReturn(QT_TRANSLATE_NOOP("Exception", "Loft: Result is not a solid"));
TopoDS_Shape result = mkSolid.Shape();
BRepClass3d_SolidClassifier SC(result);
SC.PerformInfinitePoint(Precision::Confusion());
if ( SC.State() == TopAbs_IN) {
result.Reverse();
}
AddSubShape.setValue(result);
if (base.IsNull()) {
if (getAddSubType() == FeatureAddSub::Subtractive)
return new App::DocumentObjectExecReturn(QT_TRANSLATE_NOOP("Exception", "Loft: There is nothing to subtract from"));
Shape.setValue(getSolid(result));
return App::DocumentObject::StdReturn;
}
if (getAddSubType() == FeatureAddSub::Additive) {
BRepAlgoAPI_Fuse mkFuse(base, result);
if (!mkFuse.IsDone())
return new App::DocumentObjectExecReturn(QT_TRANSLATE_NOOP("Exception", "Loft: Adding the loft failed"));
// we have to get the solids (fuse sometimes creates compounds)
TopoDS_Shape boolOp = this->getSolid(mkFuse.Shape());
// lets check if the result is a solid
if (boolOp.IsNull())
return new App::DocumentObjectExecReturn(QT_TRANSLATE_NOOP("Exception", "Resulting shape is not a solid"));
if (!isSingleSolidRuleSatisfied(boolOp)) {
return new App::DocumentObjectExecReturn(QT_TRANSLATE_NOOP("Exception", "Result has multiple solids: that is not currently supported."));
}
boolOp = refineShapeIfActive(boolOp);
Shape.setValue(getSolid(boolOp));
}
else if (getAddSubType() == FeatureAddSub::Subtractive) {
BRepAlgoAPI_Cut mkCut(base, result);
if (!mkCut.IsDone())
return new App::DocumentObjectExecReturn(QT_TRANSLATE_NOOP("Exception", "Loft: Subtracting the loft failed"));
// we have to get the solids (fuse sometimes creates compounds)
TopoDS_Shape boolOp = this->getSolid(mkCut.Shape());
// lets check if the result is a solid
if (boolOp.IsNull())
return new App::DocumentObjectExecReturn(QT_TRANSLATE_NOOP("Exception", "Resulting shape is not a solid"));
if (!isSingleSolidRuleSatisfied(boolOp)) {
return new App::DocumentObjectExecReturn(QT_TRANSLATE_NOOP("Exception", "Result has multiple solids: that is not currently supported."));
}
boolOp = refineShapeIfActive(boolOp);
Shape.setValue(getSolid(boolOp));
}
return App::DocumentObject::StdReturn;
}
catch (Standard_Failure& e) {
return new App::DocumentObjectExecReturn(e.GetMessageString());
}
catch (const Base::Exception& e) {
return new App::DocumentObjectExecReturn(e.what());
}
catch (...) {
return new App::DocumentObjectExecReturn(QT_TRANSLATE_NOOP("Exception", "Loft: A fatal error occurred when making the loft"));
}
}
#else
std::vector<Part::TopoShape>
Loft::getSectionShape(const char *name,
App::DocumentObject *obj,
@@ -533,8 +266,6 @@ App::DocumentObjectExecReturn *Loft::execute()
}
}
#endif
PROPERTY_SOURCE(PartDesign::AdditiveLoft, PartDesign::Loft)
AdditiveLoft::AdditiveLoft() {
addSubType = Additive;
-196
View File
@@ -68,204 +68,8 @@ Pad::Pad()
Length2.setConstraints(nullptr);
}
#ifdef FC_USE_TNP_FIX
App::DocumentObjectExecReturn* Pad::execute()
{
return buildExtrusion(ExtrudeOption::MakeFace | ExtrudeOption::MakeFuse);
}
#else
App::DocumentObjectExecReturn *Pad::execute()
{
double L = Length.getValue();
double L2 = Length2.getValue();
// if midplane is true, disable reversed and vice versa
bool hasMidplane = Midplane.getValue();
bool hasReversed = Reversed.getValue();
Midplane.setReadOnly(hasReversed);
Reversed.setReadOnly(hasMidplane);
std::string method(Type.getValueAsString());
TopoDS_Shape sketchshape;
try {
sketchshape = getVerifiedFace();
}
catch (const Base::Exception& e) {
return new App::DocumentObjectExecReturn(e.what());
}
// if the Base property has a valid shape, fuse the prism into it
TopoDS_Shape base;
try {
base = getBaseShape();
}
catch (const Base::Exception&) {
if (method == "UpToShape") {
return new App::DocumentObjectExecReturn(QT_TRANSLATE_NOOP("Exception", "Pad: Can't pad up to shape without base shape."));
}
base = TopoDS_Shape();
}
// get the normal vector of the sketch
Base::Vector3d SketchVector = getProfileNormal();
try {
this->positionByPrevious();
TopLoc_Location invObjLoc = this->getLocation().Inverted();
base.Move(invObjLoc);
Base::Vector3d paddingDirection = computeDirection(SketchVector, false);
// create vector in padding direction with length 1
gp_Dir dir(paddingDirection.x, paddingDirection.y, paddingDirection.z);
// The length of a gp_Dir is 1 so the resulting pad would have
// the length L in the direction of dir. But we want to have its height in the
// direction of the normal vector.
// Therefore we must multiply L by the factor that is necessary
// to make dir as long that its projection to the SketchVector
// equals the SketchVector.
// This is the scalar product of both vectors.
// Since the pad length cannot be negative, the factor must not be negative.
double factor = fabs(dir * gp_Dir(SketchVector.x, SketchVector.y, SketchVector.z));
// factor would be zero if vectors are orthogonal
if (factor < Precision::Confusion())
return new App::DocumentObjectExecReturn(QT_TRANSLATE_NOOP("Exception", "Pad: Creation failed because direction is orthogonal to sketch's normal vector"));
// perform the length correction if not along custom vector
if (AlongSketchNormal.getValue()) {
L = L / factor;
L2 = L2 / factor;
}
dir.Transform(invObjLoc.Transformation());
if (sketchshape.IsNull())
return new App::DocumentObjectExecReturn(QT_TRANSLATE_NOOP("Exception", "Pad: Creating a face from sketch failed"));
sketchshape.Move(invObjLoc);
TopoDS_Shape prism;
if (method == "UpToFirst" || method == "UpToLast" || method == "UpToFace" || method == "UpToShape") {
// Note: This will return an unlimited planar face if support is a datum plane
TopoDS_Face supportface = getSupportFace();
supportface.Move(invObjLoc);
if (Reversed.getValue())
dir.Reverse();
TopoDS_Face upToFace;
if (method != "UpToShape") {
// Find a valid face or datum plane to extrude up to
if (method == "UpToFace") {
getFaceFromLinkSub(upToFace, UpToFace);
upToFace.Move(invObjLoc);
}
getUpToFace(upToFace, base, sketchshape, method, dir);
addOffsetToFace(upToFace, dir, Offset.getValue());
}
// TODO: Write our own PrismMaker which does not depend on a solid base shape
if (base.IsNull()) {
//generatePrism(prism, sketchshape, "Length", dir, length, 0.0, false, false);
base = sketchshape;
supportface = TopoDS::Face(sketchshape);
TopExp_Explorer Ex(supportface,TopAbs_WIRE);
if (!Ex.More())
supportface = TopoDS_Face();
PrismMode mode = PrismMode::None;
if (method == "UpToShape")
generatePrism(prism, "UpToFace", base, sketchshape, supportface, base, dir, mode, Standard_True);
else
generatePrism(prism, method, base, sketchshape, supportface, upToFace, dir, mode, Standard_True);
base.Nullify();
}
else {
// A support object is always required and we need to use BRepFeat_MakePrism
// Problem: For Pocket/UpToFirst (or an equivalent Pocket/UpToFace) the resulting shape is invalid
// because the feature does not add any material. This only happens with the "2" option, though
// Note: It might be possible to pass a shell or a compound containing multiple faces
// as the Until parameter of Perform()
// Note: Multiple independent wires are not supported, we should check for that and
// warn the user
// FIXME: If the support shape is not the previous solid in the tree, then there will be unexpected results
// Check supportface for limits, otherwise Perform() throws an exception
TopExp_Explorer Ex(supportface,TopAbs_WIRE);
if (!Ex.More())
supportface = TopoDS_Face();
PrismMode mode = PrismMode::None;
if (method == "UpToShape")
generatePrism(prism, "UpToFace", base, sketchshape, supportface, base, dir, mode, Standard_True);
else
generatePrism(prism, method, base, sketchshape, supportface, upToFace, dir, mode, Standard_True);
}
}
else {
if (hasTaperedAngle()) {
if (hasReversed)
dir.Reverse();
generateTaperedPrism(prism, sketchshape, method, dir, L, L2, TaperAngle.getValue(), TaperAngle2.getValue(), hasMidplane);
}
else {
generatePrism(prism, sketchshape, method, dir, L, L2, hasMidplane, hasReversed);
}
}
if (prism.IsNull())
return new App::DocumentObjectExecReturn(QT_TRANSLATE_NOOP("Exception", "Pad: Resulting shape is empty"));
// set the additive shape property for later usage in e.g. pattern
prism = refineShapeIfActive(prism);
this->AddSubShape.setValue(prism);
if (!base.IsNull()) {
// Let's call algorithm computing a fuse operation:
BRepAlgoAPI_Fuse mkFuse(base, prism);
// Let's check if the fusion has been successful
if (!mkFuse.IsDone())
return new App::DocumentObjectExecReturn(QT_TRANSLATE_NOOP("Exception", "Pad: Fusion with base feature failed"));
TopoDS_Shape result = mkFuse.Shape();
// we have to get the solids (fuse sometimes creates compounds)
TopoDS_Shape solRes = this->getSolid(result);
// lets check if the result is a solid
if (solRes.IsNull())
return new App::DocumentObjectExecReturn(QT_TRANSLATE_NOOP("Exception", "Resulting shape is not a solid"));
if (!isSingleSolidRuleSatisfied(result)) {
return new App::DocumentObjectExecReturn(QT_TRANSLATE_NOOP("Exception", "Result has multiple solids: that is not currently supported."));
}
solRes = refineShapeIfActive(solRes);
this->Shape.setValue(getSolid(solRes));
}
else {
if (!isSingleSolidRuleSatisfied(prism)) {
return new App::DocumentObjectExecReturn(QT_TRANSLATE_NOOP("Exception", "Result has multiple solids: that is not currently supported."));
}
this->Shape.setValue(getSolid(prism));
}
// eventually disable some settings that are not valid for the current method
updateProperties(method);
return App::DocumentObject::StdReturn;
}
catch (Standard_Failure& e) {
if (std::string(e.GetMessageString()) == "TopoDS::Face")
return new App::DocumentObjectExecReturn(QT_TRANSLATE_NOOP("Exception", "Could not create face from sketch.\n"
"Intersecting sketch entities or multiple faces in a sketch are not allowed."));
else
return new App::DocumentObjectExecReturn(e.GetMessageString());
}
catch (Base::Exception& e) {
return new App::DocumentObjectExecReturn(e.what());
}
}
#endif
-336
View File
@@ -102,341 +102,6 @@ short Pipe::mustExecute() const
return ProfileBased::mustExecute();
}
#ifndef FC_USE_TNP_FIX
App::DocumentObjectExecReturn *Pipe::execute()
{
auto getSectionShape = [](App::DocumentObject* feature,
const std::vector<std::string>& subs) -> TopoDS_Shape {
if (!feature || !feature->isDerivedFrom(Part::Feature::getClassTypeId()))
throw Base::TypeError("Pipe: Invalid profile/section");
auto subName = subs.empty() ? "" : subs.front();
// only take the entire shape when we have a sketch selected, but
// not a point of the sketch
if (feature->isDerivedFrom(Part::Part2DObject::getClassTypeId())
&& subName.compare(0, 6, "Vertex") != 0)
return static_cast<Part::Part2DObject*>(feature)->Shape.getValue();
else {
if (subName.empty())
throw Base::ValueError("Pipe: No valid subelement linked in Part::Feature");
return static_cast<Part::Feature*>(feature)->Shape.getShape().getSubShape(
subName.c_str());
}
};
auto addWiresToWireSections =
[](TopoDS_Shape& section, std::vector<std::vector<TopoDS_Shape>>& wiresections) -> size_t {
TopExp_Explorer ex;
size_t i = 0;
bool initialWireSectionsEmpty = wiresections.empty();
for (ex.Init(section, TopAbs_WIRE); ex.More(); ex.Next(), ++i) {
// if profile was just a point then this is where we can first set our list
if (i >= wiresections.size()) {
if (initialWireSectionsEmpty)
wiresections.emplace_back(1, ex.Current());
else
throw Base::ValueError(
"Pipe: Sections need to have the same amount of inner wires (except "
"profile and last section, which can be points)");
}
else
wiresections[i].push_back(TopoDS::Wire(ex.Current()));
}
return i;
};
// TODO: currently we can only allow planar faces, so add that check.
// The reason for this is that with other faces in front, we could not use the
// current simulate approach and build the start and end face from the wires.
// As the shell begins always at the spine and not the profile, the sketchshape
// cannot be used directly as front face. We would need a method to translate
// the front shape to match the shell starting position somehow...
std::vector<TopoDS_Wire> wires;
TopoDS_Shape profilePoint;
// if the Base property has a valid shape, fuse the pipe into it
TopoDS_Shape base;
try {
base = getBaseShape();
} catch (const Base::Exception&) {
base = TopoDS_Shape();
}
try {
// setup the location
this->positionByPrevious();
TopLoc_Location invObjLoc = this->getLocation().Inverted();
if (!base.IsNull())
base.Move(invObjLoc);
// setup the profile section
TopoDS_Shape profileShape = getSectionShape(Profile.getValue(),
Profile.getSubValues());
if (profileShape.IsNull())
return new App::DocumentObjectExecReturn(QT_TRANSLATE_NOOP("Exception", "Pipe: Could not obtain profile shape"));
// build the paths
App::DocumentObject* spine = Spine.getValue();
if (!(spine && spine->isDerivedFrom<Part::Feature>()))
return new App::DocumentObjectExecReturn(QT_TRANSLATE_NOOP("Exception", "No spine linked"));
std::vector<std::string> subedge = Spine.getSubValues();
TopoDS_Shape path;
const Part::TopoShape& shape = static_cast<Part::Feature*>(spine)->Shape.getValue();
buildPipePath(shape, subedge, path);
path.Move(invObjLoc);
// auxiliary
TopoDS_Shape auxpath;
if (Mode.getValue() == 3) {
App::DocumentObject* auxspine = AuxillerySpine.getValue();
if (!(auxspine && auxspine->isDerivedFrom<Part::Feature>()))
return new App::DocumentObjectExecReturn(QT_TRANSLATE_NOOP("Exception", "No auxiliary spine linked."));
std::vector<std::string> auxsubedge = AuxillerySpine.getSubValues();
const Part::TopoShape& auxshape =
static_cast<Part::Feature*>(auxspine)->Shape.getValue();
buildPipePath(auxshape, auxsubedge, auxpath);
auxpath.Move(invObjLoc);
}
// build up multisections
auto multisections = Sections.getSubListValues();
std::vector<std::vector<TopoDS_Shape>> wiresections;
size_t numWires = addWiresToWireSections(profileShape, wiresections);
if (numWires == 0) {
// profileShape had no wires so only other valid option is single point section
TopExp_Explorer ex;
size_t i = 0;
for (ex.Init(profileShape, TopAbs_VERTEX); ex.More(); ex.Next(), ++i)
profilePoint = ex.Current();
if (i > 1)
return new App::DocumentObjectExecReturn(QT_TRANSLATE_NOOP("Exception",
"Pipe: Only one isolated point is needed if using a sketch with isolated "
"points for section"));
}
if (!profilePoint.IsNull() && (Transformation.getValue() != 1 || multisections.empty()))
return new App::DocumentObjectExecReturn(QT_TRANSLATE_NOOP("Exception",
"Pipe: At least one section is needed when using a single point for profile"));
// maybe we need a scaling law
Handle(Law_Function) scalinglaw;
bool isLastSectionVertex = false;
// see if we shall use multiple sections
if (Transformation.getValue() == 1) {
// TODO: we need to order the sections to prevent occ from crashing,
// as makepipeshell connects the sections in the order of adding
for (auto& subSet : multisections) {
if (!subSet.first->isDerivedFrom(Part::Feature::getClassTypeId()))
return new App::DocumentObjectExecReturn(QT_TRANSLATE_NOOP("Exception",
"Pipe: All sections need to be part features"));
// if the section is an object's face then take just the face
TopoDS_Shape shape = getSectionShape(subSet.first, subSet.second);
if (shape.IsNull())
return new App::DocumentObjectExecReturn(QT_TRANSLATE_NOOP("Exception",
"Pipe: Could not obtain section shape"));
size_t nWiresAdded = addWiresToWireSections(shape, wiresections);
if (nWiresAdded == 0) {
TopExp_Explorer ex;
size_t i = 0;
for (ex.Init(shape, TopAbs_VERTEX); ex.More(); ex.Next(), ++i) {
if (isLastSectionVertex)
return new App::DocumentObjectExecReturn(QT_TRANSLATE_NOOP("Exception",
"Pipe: Only the profile and last section can be vertices"));
isLastSectionVertex = true;
for (auto& wires : wiresections)
wires.push_back(ex.Current());
}
}
if (!isLastSectionVertex && nWiresAdded < wiresections.size())
return new App::DocumentObjectExecReturn(QT_TRANSLATE_NOOP("Exception",
"Multisections need to have the same amount of inner wires as the base "
"section"));
}
}
/*//build the law functions instead
else if (Transformation.getValue() == 2) {
if (ScalingData.getValues().size()<1)
return new App::DocumentObjectExecReturn("No valid data given for linear scaling mode");
Handle(Law_Linear) lin = new Law_Linear();
lin->Set(0, 1, 1, ScalingData[0].x);
scalinglaw = lin;
}
else if (Transformation.getValue() == 3) {
if (ScalingData.getValues().size()<1)
return new App::DocumentObjectExecReturn("No valid data given for S-shape scaling mode");
Handle(Law_S) s = new Law_S();
s->Set(0, 1, ScalingData[0].y, 1, ScalingData[0].x, ScalingData[0].z);
scalinglaw = s;
}*/
// Verify that path is not a null shape
if (path.IsNull())
return new App::DocumentObjectExecReturn(QT_TRANSLATE_NOOP(
"Exception", "Path must not be a null shape"));
// build all shells
std::vector<TopoDS_Shape> shells;
TopoDS_Shape copyProfilePoint(profilePoint);
if (!profilePoint.IsNull())
copyProfilePoint.Move(invObjLoc);
std::vector<TopoDS_Wire> frontwires, backwires;
for (auto& wires : wiresections) {
BRepOffsetAPI_MakePipeShell mkPS(TopoDS::Wire(path));
setupAlgorithm(mkPS, auxpath);
if (!scalinglaw) {
if (!profilePoint.IsNull())
mkPS.Add(copyProfilePoint);
for (auto& wire : wires) {
wire.Move(invObjLoc);
mkPS.Add(wire);
}
}
else {
if (!profilePoint.IsNull())
mkPS.SetLaw(copyProfilePoint, scalinglaw);
for (auto& wire : wires) {
wire.Move(invObjLoc);
mkPS.SetLaw(wire, scalinglaw);
}
}
if (!mkPS.IsReady())
return new App::DocumentObjectExecReturn(QT_TRANSLATE_NOOP("Exception", "Pipe could not be built"));
shells.push_back(mkPS.Shape());
if (!mkPS.Shape().Closed()) {
// shell is not closed - use simulate to get the end wires
TopTools_ListOfShape sim;
mkPS.Simulate(2, sim);
// Note that while we call them front and back, these sections
// appear to correspond to the front or back of the path. When one
// or both ends of the pipe are points, one or both of these wires
// (and eventually faces) will be null.
frontwires.push_back(TopoDS::Wire(sim.First()));
backwires.push_back(TopoDS::Wire(sim.Last()));
}
}
BRepBuilderAPI_MakeSolid mkSolid;
if (!frontwires.empty() || !backwires.empty()) {
BRepBuilderAPI_Sewing sewer;
sewer.SetTolerance(Precision::Confusion());
// build the end faces, sew the shell and build the final solid
if (!frontwires.empty()) {
TopoDS_Shape front = Part::FaceMakerCheese::makeFace(frontwires);
sewer.Add(front);
}
if (!backwires.empty()) {
TopoDS_Shape back = Part::FaceMakerCheese::makeFace(backwires);
sewer.Add(back);
}
for (TopoDS_Shape& s : shells)
sewer.Add(s);
sewer.Perform();
mkSolid.Add(TopoDS::Shell(sewer.SewedShape()));
} else {
// shells are already closed - add them directly
for (TopoDS_Shape& s : shells) {
mkSolid.Add(TopoDS::Shell(s));
}
}
if (!mkSolid.IsDone())
return new App::DocumentObjectExecReturn(QT_TRANSLATE_NOOP("Exception", "Result is not a solid"));
TopoDS_Shape result = mkSolid.Shape();
BRepClass3d_SolidClassifier SC(result);
SC.PerformInfinitePoint(Precision::Confusion());
if (SC.State() == TopAbs_IN) {
result.Reverse();
}
//result.Move(invObjLoc);
AddSubShape.setValue(result);
if (base.IsNull()) {
if (getAddSubType() == FeatureAddSub::Subtractive)
return new App::DocumentObjectExecReturn(
QT_TRANSLATE_NOOP("Exception", "Pipe: There is nothing to subtract from"));
result = refineShapeIfActive(result);
Shape.setValue(getSolid(result));
return App::DocumentObject::StdReturn;
}
if (getAddSubType() == FeatureAddSub::Additive) {
BRepAlgoAPI_Fuse mkFuse(base, result);
if (!mkFuse.IsDone())
return new App::DocumentObjectExecReturn(QT_TRANSLATE_NOOP("Exception", "Adding the pipe failed"));
// we have to get the solids (fuse sometimes creates compounds)
TopoDS_Shape boolOp = this->getSolid(mkFuse.Shape());
// lets check if the result is a solid
if (boolOp.IsNull())
return new App::DocumentObjectExecReturn(QT_TRANSLATE_NOOP("Exception", "Resulting shape is not a solid"));
if (!isSingleSolidRuleSatisfied(boolOp)) {
return new App::DocumentObjectExecReturn(QT_TRANSLATE_NOOP("Exception",
"Result has multiple solids: that is not currently supported."));
}
boolOp = refineShapeIfActive(boolOp);
Shape.setValue(getSolid(boolOp));
}
else if (getAddSubType() == FeatureAddSub::Subtractive) {
BRepAlgoAPI_Cut mkCut(base, result);
if (!mkCut.IsDone())
return new App::DocumentObjectExecReturn(QT_TRANSLATE_NOOP("Exception", "Subtracting the pipe failed"));
// we have to get the solids (fuse sometimes creates compounds)
TopoDS_Shape boolOp = this->getSolid(mkCut.Shape());
// lets check if the result is a solid
if (boolOp.IsNull())
return new App::DocumentObjectExecReturn(QT_TRANSLATE_NOOP("Exception", "Resulting shape is not a solid"));
if (!isSingleSolidRuleSatisfied(boolOp)) {
return new App::DocumentObjectExecReturn(QT_TRANSLATE_NOOP("Exception",
"Result has multiple solids: that is not currently supported."));
}
boolOp = refineShapeIfActive(boolOp);
Shape.setValue(getSolid(boolOp));
}
return App::DocumentObject::StdReturn;
}
catch (Standard_Failure& e) {
return new App::DocumentObjectExecReturn(e.GetMessageString());
}
catch (...) {
return new App::DocumentObjectExecReturn(QT_TRANSLATE_NOOP("Exception", "A fatal error occurred when making the pipe"));
}
}
#else
App::DocumentObjectExecReturn *Pipe::execute()
{
auto getSectionShape = [](App::DocumentObject* feature,
@@ -772,7 +437,6 @@ App::DocumentObjectExecReturn *Pipe::execute()
}
}
#endif
void Pipe::setupAlgorithm(BRepOffsetAPI_MakePipeShell& mkPipeShell, const TopoDS_Shape& auxshape) {
mkPipeShell.SetTolerance(Precision::Confusion());
-183
View File
@@ -71,200 +71,17 @@ Pocket::Pocket()
App::DocumentObjectExecReturn *Pocket::execute()
{
#ifdef FC_USE_TNP_FIX
// MakeFace|MakeFuse: because we want a solid.
// InverseDirection: to inverse the auto detected extrusion direction for
// backward compatibility to upstream
ExtrudeOptions options(ExtrudeOption::MakeFace | ExtrudeOption::MakeFuse
| ExtrudeOption::InverseDirection);
return buildExtrusion(options);
#else
// Handle legacy features, these typically have Type set to 3 (previously NULL, now UpToFace),
// empty FaceName (because it didn't exist) and a value for Length
if (std::string(Type.getValueAsString()) == "UpToFace" &&
(!UpToFace.getValue() && Length.getValue() > Precision::Confusion()))
Type.setValue("Length");
double L = Length.getValue();
double L2 = Length2.getValue();
TopoDS_Shape profileshape;
try {
profileshape = getVerifiedFace();
} catch (const Base::Exception& e) {
return new App::DocumentObjectExecReturn(e.what());
}
// if the Base property has a valid shape, fuse the prism into it
TopoShape base;
try {
base = getBaseTopoShape();
}
catch (const Base::Exception&) {
std::string text(QT_TRANSLATE_NOOP("Exception", ("The requested feature cannot be created. The reason may be that:\n"
" - the active Body does not contain a base shape, so there is no\n"
" material to be removed;\n"
" - the selected sketch does not belong to the active Body.")));
return new App::DocumentObjectExecReturn(text);
}
// get the normal vector of the sketch
Base::Vector3d SketchVector = getProfileNormal();
// turn around for pockets
SketchVector *= -1;
try {
this->positionByPrevious();
TopLoc_Location invObjLoc = this->getLocation().Inverted();
base.move(invObjLoc);
Base::Vector3d pocketDirection = computeDirection(SketchVector, false);
// create vector in pocketing direction with length 1
gp_Dir dir(pocketDirection.x, pocketDirection.y, pocketDirection.z);
// The length of a gp_Dir is 1 so the resulting pocket would have
// the length L in the direction of dir. But we want to have its height in the
// direction of the normal vector.
// Therefore we must multiply L by the factor that is necessary
// to make dir as long that its projection to the SketchVector
// equals the SketchVector.
// This is the scalar product of both vectors.
// Since the pocket length cannot be negative, the factor must not be negative.
double factor = fabs(dir * gp_Dir(SketchVector.x, SketchVector.y, SketchVector.z));
// factor would be zero if vectors are orthogonal
if (factor < Precision::Confusion())
return new App::DocumentObjectExecReturn(QT_TRANSLATE_NOOP("Exception", "Pocket: Creation failed because direction is orthogonal to sketch's normal vector"));
// perform the length correction if not along custom vector
if (AlongSketchNormal.getValue()) {
L = L / factor;
L2 = L2 / factor;
}
dir.Transform(invObjLoc.Transformation());
if (profileshape.IsNull())
return new App::DocumentObjectExecReturn(QT_TRANSLATE_NOOP("Exception", "Pocket: Creating a face from sketch failed"));
profileshape.Move(invObjLoc);
std::string method(Type.getValueAsString());
if (method == "UpToFirst" || method == "UpToFace") {
if (base.isNull())
return new App::DocumentObjectExecReturn(QT_TRANSLATE_NOOP("Exception", "Pocket: Extruding up to a face is only possible if the sketch is located on a face"));
// Note: This will return an unlimited planar face if support is a datum plane
TopoDS_Face supportface = getSupportFace();
supportface.Move(invObjLoc);
if (Reversed.getValue())
dir.Reverse();
// Find a valid face or datum plane to extrude up to
TopoDS_Face upToFace;
if (method == "UpToFace") {
getFaceFromLinkSub(upToFace, UpToFace);
upToFace.Move(invObjLoc);
}
getUpToFace(upToFace, base.getShape(), profileshape, method, dir);
addOffsetToFace(upToFace, dir, Offset.getValue());
// BRepFeat_MakePrism(..., 2, 1) in combination with PerForm(upToFace) is buggy when the
// prism that is being created is contained completely inside the base solid
// In this case the resulting shape is empty. This is not a problem for the Pad or Pocket itself
// but it leads to an invalid SubShape
// The bug only occurs when the upToFace is limited (by a wire), not for unlimited upToFace. But
// other problems occur with unlimited concave upToFace so it is not an option to always unlimit upToFace
// Check supportface for limits, otherwise Perform() throws an exception
TopExp_Explorer Ex(supportface,TopAbs_WIRE);
if (!Ex.More())
supportface = TopoDS_Face();
TopoDS_Shape prism;
PrismMode mode = PrismMode::CutFromBase;
generatePrism(prism, method, base.getShape(), profileshape, supportface, upToFace, dir, mode, Standard_True);
// And the really expensive way to get the SubShape...
BRepAlgoAPI_Cut mkCut(base.getShape(), prism);
if (!mkCut.IsDone())
return new App::DocumentObjectExecReturn(QT_TRANSLATE_NOOP("Exception", "Pocket: Up to face: Could not get SubShape!"));
// FIXME: In some cases this affects the Shape property: It is set to the same shape as the SubShape!!!!
TopoDS_Shape result = refineShapeIfActive(mkCut.Shape());
this->AddSubShape.setValue(result);
if (!isSingleSolidRuleSatisfied(result)) {
return new App::DocumentObjectExecReturn(QT_TRANSLATE_NOOP("Exception", "Result has multiple solids: that is not currently supported."));
}
this->Shape.setValue(getSolid(prism));
}
else {
TopoDS_Shape prism;
if (hasTaperedAngle()) {
if (Reversed.getValue())
dir.Reverse();
generateTaperedPrism(prism, profileshape, method, dir, L, L2, TaperAngle.getValue(), TaperAngle2.getValue(), Midplane.getValue());
}
else {
generatePrism(prism, profileshape, method, dir, L, L2, Midplane.getValue(), Reversed.getValue());
}
if (prism.IsNull())
return new App::DocumentObjectExecReturn(QT_TRANSLATE_NOOP("Exception", "Pocket: Resulting shape is empty"));
// set the subtractive shape property for later usage in e.g. pattern
prism = refineShapeIfActive(prism);
this->AddSubShape.setValue(prism);
// Cut the SubShape out of the base feature
BRepAlgoAPI_Cut mkCut(base.getShape(), prism);
if (!mkCut.IsDone())
return new App::DocumentObjectExecReturn(QT_TRANSLATE_NOOP("Exception", "Pocket: Cut out of base feature failed"));
TopoDS_Shape result = mkCut.Shape();
// we have to get the solids (fuse sometimes creates compounds)
TopoDS_Shape solRes = this->getSolid(result);
if (solRes.IsNull())
return new App::DocumentObjectExecReturn(QT_TRANSLATE_NOOP("Exception", "Resulting shape is not a solid"));
if (!isSingleSolidRuleSatisfied(result)) {
return new App::DocumentObjectExecReturn(QT_TRANSLATE_NOOP("Exception", "Result has multiple solids: that is not currently supported."));
}
solRes = refineShapeIfActive(solRes);
remapSupportShape(solRes);
this->Shape.setValue(getSolid(solRes));
}
// eventually disable some settings that are not valid for the current method
updateProperties(method);
return App::DocumentObject::StdReturn;
}
catch (Standard_Failure& e) {
if (std::string(e.GetMessageString()) == "TopoDS::Face" &&
(std::string(Type.getValueAsString()) == "UpToFirst" || std::string(Type.getValueAsString()) == "UpToFace"))
return new App::DocumentObjectExecReturn(QT_TRANSLATE_NOOP("Exception", "Could not create face from sketch.\n"
"Intersecting sketch entities or multiple faces in a sketch are not allowed "
"for making a pocket up to a face."));
else
return new App::DocumentObjectExecReturn(e.GetMessageString());
}
catch (Base::Exception& e) {
return new App::DocumentObjectExecReturn(e.what());
}
#endif
}
Base::Vector3d Pocket::getProfileNormal() const
{
auto res = FeatureExtrude::getProfileNormal();
// turn around for pockets
#ifdef FC_USE_TNP_FIX
return res * -1;
#else
return res;
#endif
}
@@ -73,7 +73,6 @@ App::DocumentObjectExecReturn* FeaturePrimitive::execute(const TopoDS_Shape& pri
FeatureAddSub::execute();
//if we have no base we just add the standard primitive shape
#ifdef FC_USE_TNP_FIX
TopoShape primitiveShape;
primitiveShape.setShape(primitive);
@@ -85,15 +84,6 @@ App::DocumentObjectExecReturn* FeaturePrimitive::execute(const TopoDS_Shape& pri
primitiveShape.Tag = -this->getID();
}
#else
auto primitiveShape = primitive;
TopoDS_Shape base;
try {
//if we have a base shape we need to make sure that it does not get our transformation to
BRepBuilderAPI_Transform trsf(getBaseShape(), getLocation().Transformation().Inverted(), true);
base = trsf.Shape();
}
#endif
catch (const Base::Exception&) {
//as we use this for preview we can add it even if useless for subtractive
@@ -106,7 +96,6 @@ App::DocumentObjectExecReturn* FeaturePrimitive::execute(const TopoDS_Shape& pri
return App::DocumentObject::StdReturn;
}
#ifdef FC_USE_TNP_FIX
AddSubShape.setValue(primitiveShape);
TopoShape boolOp(0);
@@ -136,40 +125,6 @@ App::DocumentObjectExecReturn* FeaturePrimitive::execute(const TopoDS_Shape& pri
return new App::DocumentObjectExecReturn(
QT_TRANSLATE_NOOP("Exception", "Resulting shape is not a solid"));
}
#else
TopoDS_Shape boolOp;
if (getAddSubType() == FeatureAddSub::Additive) {
BRepAlgoAPI_Fuse mkFuse(base, primitiveShape);
if (!mkFuse.IsDone())
return new App::DocumentObjectExecReturn(QT_TRANSLATE_NOOP("Exception", "Adding the primitive failed"));
// we have to get the solids (fuse sometimes creates compounds)
boolOp = this->getSolid(mkFuse.Shape());
// lets check if the result is a solid
if (boolOp.IsNull())
return new App::DocumentObjectExecReturn(QT_TRANSLATE_NOOP("Exception", "Resulting shape is not a solid"));
if (!isSingleSolidRuleSatisfied(boolOp)) {
return new App::DocumentObjectExecReturn(QT_TRANSLATE_NOOP("Exception", "Result has multiple solids: that is not currently supported."));
}
}
else if (getAddSubType() == FeatureAddSub::Subtractive) {
BRepAlgoAPI_Cut mkCut(base, primitiveShape);
if (!mkCut.IsDone())
return new App::DocumentObjectExecReturn(QT_TRANSLATE_NOOP("Exception", "Subtracting the primitive failed"));
// we have to get the solids (fuse sometimes creates compounds)
boolOp = this->getSolid(mkCut.Shape());
// lets check if the result is a solid
if (boolOp.IsNull())
return new App::DocumentObjectExecReturn(QT_TRANSLATE_NOOP("Exception", "Resulting shape is not a solid"));
if (!isSingleSolidRuleSatisfied(boolOp)) {
return new App::DocumentObjectExecReturn(QT_TRANSLATE_NOOP("Exception", "Result has multiple solids: that is not currently supported."));
}
}
#endif
boolOp = refineShapeIfActive(boolOp);
Shape.setValue(getSolid(boolOp));
AddSubShape.setValue(primitiveShape);
+3 -58
View File
@@ -160,11 +160,7 @@ App::DocumentObjectExecReturn* Revolution::execute()
}
// Create a fresh support even when base exists so that it can be used for patterns
#ifdef FC_USE_TNP_FIX
TopoShape result(0);
#else
TopoDS_Shape result;
#endif
TopoDS_Face supportface = getSupportFace();
supportface.Move(invObjLoc);
@@ -194,27 +190,15 @@ App::DocumentObjectExecReturn* Revolution::execute()
if (!Ex.More()) {
supportface = TopoDS_Face();
}
#ifdef FC_USE_TNP_FIX
RevolMode mode = RevolMode::None;
// revolve the face to a solid
// TopoShape result(0);
try {
result = base.makeElementRevolution(gp_Ax1(pnt, dir), supportface, upToFace);
result = base.makeElementRevolution(gp_Ax1(pnt, dir), supportface, upToFace);
}
catch (Standard_Failure&) {
return new App::DocumentObjectExecReturn("Could not revolve the sketch!");
}
#else
RevolMode mode = RevolMode::None;
generateRevolution(result,
base.getShape(),
sketchshape.getShape(),
supportface,
upToFace,
gp_Ax1(pnt, dir),
method,
mode,
Standard_True);
#endif
}
else {
bool midplane = Midplane.getValue();
@@ -229,7 +213,6 @@ App::DocumentObjectExecReturn* Revolution::execute()
method);
}
#ifdef FC_USE_TNP_FIX
if (!result.isNull()) {
result = refineShapeIfActive(result);
// set the additive shape property for later usage in e.g. pattern
@@ -239,25 +222,6 @@ App::DocumentObjectExecReturn* Revolution::execute()
result = result.makeElementFuse(base);
result = refineShapeIfActive(result);
}
#else
if (!result.IsNull()) {
result = refineShapeIfActive(result);
// set the additive shape property for later usage in e.g. pattern
this->AddSubShape.setValue(result);
if (!base.isNull()) {
// Let's call algorithm computing a fuse operation:
BRepAlgoAPI_Fuse mkFuse(base.getShape(), result);
// Let's check if the fusion has been successful
if (!mkFuse.IsDone()) {
throw Part::BooleanException(
QT_TRANSLATE_NOOP("Exception", "Fusion with base feature failed"));
}
result = mkFuse.Shape();
result = refineShapeIfActive(result);
}
#endif
this->Shape.setValue(getSolid(result));
}
else {
@@ -329,12 +293,7 @@ Revolution::RevolMethod Revolution::methodFromString(const std::string& methodSt
return RevolMethod::Dimension;
}
#ifdef FC_USE_TNP_FIX
void Revolution::generateRevolution(TopoShape& revol,
#else
void Revolution::generateRevolution(TopoDS_Shape& revol,
#endif
const TopoDS_Shape& sketchshape,
const gp_Ax1& axis,
const double angle,
@@ -373,22 +332,8 @@ void Revolution::generateRevolution(TopoDS_Shape& revol,
from.Move(loc);
}
#ifdef FC_USE_TNP_FIX
revol = TopoShape(from);
// revol.Tag = getID();
revol = revol.makeElementRevolve(revolAx,angleTotal);
revol = TopoShape(from).makeElementRevolve(revolAx,angleTotal);
revol.Tag = -getID();
#else
// revolve the face to a solid
// BRepPrimAPI is the only option that allows use of this shape for patterns.
// See https://forum.freecadweb.org/viewtopic.php?f=8&t=70185&p=611673#p611673.
BRepPrimAPI_MakeRevol RevolMaker(from, revolAx, angleTotal);
if (!RevolMaker.IsDone())
throw Base::RuntimeError("ProfileBased: RevolMaker failed! Could not revolve the sketch!");
else
revol = RevolMaker.Shape();
#endif
} else {
std::stringstream str;
str << "ProfileBased: Internal error: Unknown method for generateRevolution()";
@@ -95,11 +95,7 @@ protected:
/**
* Generates a revolution of the input sketchshape and stores it in the given \a revol.
*/
#ifdef FC_USE_TNP_FIX
void generateRevolution(TopoShape& revol,
#else
void generateRevolution(TopoDS_Shape& revol,
#endif
const TopoDS_Shape& sketchshape,
const gp_Ax1& ax1,
const double angle,
@@ -1134,105 +1134,11 @@ bool ProfileBased::checkLineCrossesFace(const gp_Lin& line, const TopoDS_Face& f
void ProfileBased::remapSupportShape(const TopoDS_Shape & newShape)
{
#if FC_USE_TNP_FIX
(void)newShape;
// Realthunder: with the new topological naming, I don't think this function
// is necessary. A missing element will cause an explicitly error, and the
// user will be force to manually select the element. Various editors, such
// as dress up editors, can perform element guessing when activated.
#else
TopTools_IndexedMapOfShape faceMap;
TopExp::MapShapes(newShape, TopAbs_FACE, faceMap);
// here we must reset the placement otherwise the geometric matching doesn't work
Part::TopoShape shape = this->Shape.getValue();
TopoDS_Shape sh = shape.getShape();
sh.Location(TopLoc_Location());
shape.setShape(sh);
std::vector<App::DocumentObject*> refs = this->getInList();
for (auto ref : refs) {
std::vector<App::Property*> props;
ref->getPropertyList(props);
for (auto prop : props) {
if (!prop->isDerivedFrom(App::PropertyLinkSub::getClassTypeId()))
continue;
App::PropertyLinkSub* link = static_cast<App::PropertyLinkSub*>(prop);
if (link->getValue() != this)
continue;
std::vector<std::string> subValues = link->getSubValues();
std::vector<std::string> newSubValues;
for (auto & subValue : subValues) {
std::string shapetype;
if (subValue.compare(0, 4, "Face") == 0) {
shapetype = "Face";
}
else if (subValue.compare(0, 4, "Edge") == 0) {
shapetype = "Edge";
}
else if (subValue.compare(0, 6, "Vertex") == 0) {
shapetype = "Vertex";
}
else {
newSubValues.push_back(subValue);
continue;
}
bool success = false;
TopoDS_Shape element;
try {
element = shape.getSubShape(subValue.c_str());
}
catch (Standard_Failure&) {
// This shape doesn't even exist, so no chance to do some tests
newSubValues.push_back(subValue);
continue;
}
try {
// as very first test check if old face and new face are parallel planes
TopoDS_Shape newElement = Part::TopoShape(newShape).getSubShape(subValue.c_str());
if (isParallelPlane(element, newElement)) {
newSubValues.push_back(subValue);
success = true;
}
}
catch (Standard_Failure&) {
}
// try an exact matching
if (!success) {
for (int i = 1; i < faceMap.Extent(); i++) {
if (isQuasiEqual(element, faceMap.FindKey(i))) {
std::stringstream str;
str << shapetype << i;
newSubValues.push_back(str.str());
success = true;
break;
}
}
}
// if an exact matching fails then try to compare only the geometries
if (!success) {
for (int i = 1; i < faceMap.Extent(); i++) {
if (isEqualGeometry(element, faceMap.FindKey(i))) {
std::stringstream str;
str << shapetype << i;
newSubValues.push_back(str.str());
success = true;
break;
}
}
}
// the new shape couldn't be found so keep the old sub-name
if (!success)
newSubValues.push_back(subValue);
}
link->setValue(this, newSubValues);
}
}
#endif
}
namespace PartDesign {
@@ -1514,7 +1420,6 @@ Base::Vector3d ProfileBased::getProfileNormal() const {
Base::Placement SketchPos = obj->Placement.getValue();
Base::Rotation SketchOrientation = SketchPos.getRotation();
SketchOrientation.multVec(SketchVector, SketchVector);
#ifdef FC_USE_TNP_FIX
return SketchVector;
}
@@ -1592,31 +1497,6 @@ Base::Vector3d ProfileBased::getProfileNormal() const {
}
return dir.Normalize();
}
#else
}
else {
TopoDS_Shape shape = getVerifiedFace(true);
if (shape.IsNull())
return SketchVector;
// the shape can be a single face or a compound of faces, only consider the first face
TopExp_Explorer ex(shape, TopAbs_FACE);
if (ex.More()) {
TopoDS_Face face = TopoDS::Face(ex.Current());
BRepAdaptor_Surface adapt(face);
double u = adapt.FirstUParameter() + (adapt.LastUParameter() - adapt.FirstUParameter()) / 2.;
double v = adapt.FirstVParameter() + (adapt.LastVParameter() - adapt.FirstVParameter()) / 2.;
BRepLProp_SLProps prop(adapt, u, v, 2, Precision::Confusion());
if (prop.IsNormalDefined()) {
gp_Pnt pnt; gp_Vec vec;
// handles the orientation state of the shape
BRepGProp_Face(face).Normal(u, v, pnt, vec);
SketchVector = Base::Vector3d(vec.X(), vec.Y(), vec.Z());
}
}
}
#endif
return SketchVector;
}
@@ -324,22 +324,12 @@ App::DocumentObjectExecReturn* Transformed::execute()
"Shape of additive/subtractive feature is empty"));
}
gp_Trsf trsf = feature->getLocation().Transformation().Multiplied(trsfInv);
#ifdef FC_USE_TNP_FIX
if (!fuseShape.isNull()) {
fuseShape = fuseShape.makeElementTransform(trsf);
}
if (!cutShape.isNull()) {
cutShape = cutShape.makeElementTransform(trsf);
}
#else
if (!fuseShape.isNull()) {
fuseShape = fuseShape.makeTransform(trsf);
}
if (!cutShape.isNull()) {
cutShape = cutShape.makeTransform(trsf);
}
#endif
if (!fuseShape.isNull()) {
supportShape.makeElementFuse(getTransformedCompShape(supportShape, fuseShape));
}
-34
View File
@@ -731,11 +731,7 @@ void SubShapeBinder::update(SubShapeBinder::UpdateOption options) {
else {
for (size_t i = 0; i < shapes.size(); ++i) {
auto& shape = shapes[i];
#ifdef FC_USE_TNP_FIX
shape = shape.makeElementTransform(*shapeMats[i]);
#else
shape = shape.makeTransform(*shapeMats[i]);
#endif
// if(shape.Hasher
// && shape.getElementMapSize()
// && shape.Hasher != getDocument()->getStringHasher())
@@ -750,11 +746,7 @@ void SubShapeBinder::update(SubShapeBinder::UpdateOption options) {
// Shape.resetElementMapVersion();
return;
}
#ifdef FC_USE_TNP_FIX
result.makeElementCompound(shapes);
#else
result.makeCompound(shapes);
#endif
bool fused = false;
if (Fuse.getValue()) {
// If the compound has solid, fuse them together, and ignore other type of
@@ -773,11 +765,7 @@ void SubShapeBinder::update(SubShapeBinder::UpdateOption options) {
}
else if (!solid.isNull()) {
// wrap the single solid in compound to keep its placement
#ifdef FC_USE_TNP_FIX
result.makeElementCompound({ solid });
#else
result.makeCompound({ solid });
#endif
fused = true;
}
}
@@ -786,7 +774,6 @@ void SubShapeBinder::update(SubShapeBinder::UpdateOption options) {
&& !result.hasSubShape(TopAbs_FACE)
&& result.hasSubShape(TopAbs_EDGE))
{
#ifdef FC_USE_TNP_FIX
result = result.makeElementWires();
if (MakeFace.getValue()) {
try {
@@ -794,33 +781,16 @@ void SubShapeBinder::update(SubShapeBinder::UpdateOption options) {
}
catch (...) {}
}
#else
result = result.makeWires();
if (MakeFace.getValue()) {
try {
result = result.makeFace(nullptr);
}
catch (...) {}
}
#endif
}
if (!fused && result.hasSubShape(TopAbs_WIRE)
&& Offset.getValue() != 0.0) {
try {
#ifdef FC_USE_TNP_FIX
result = result.makeElementOffset2D(Offset.getValue(),
(Part::JoinType) OffsetJoinType.getValue() ,
OffsetFill.getValue() ? Part::FillType::fill : Part::FillType::noFill,
OffsetOpenResult.getValue() ? Part::OpenResult::allowOpenResult : Part::OpenResult::noOpenResult,
OffsetIntersection.getValue());
#else
result = result.makeOffset2D(Offset.getValue(),
OffsetJoinType.getValue(),
OffsetFill.getValue(),
OffsetOpenResult.getValue(),
OffsetIntersection.getValue());
#endif
}
catch (...) {
std::ostringstream msg;
@@ -830,11 +800,7 @@ void SubShapeBinder::update(SubShapeBinder::UpdateOption options) {
}
if (Refine.getValue())
#ifdef FC_USE_TNP_FIX
result = result.makeElementRefine();
#else
result = result.makeRefine();
#endif
result.setPlacement(Placement.getValue());
Shape.setValue(result);
}
+1 -21
View File
@@ -325,9 +325,7 @@ void SketchObject::buildShape() {
if(GeometryFacade::getConstruction(geo)) {
continue;
}
if (geo->isDerivedFrom<Part::GeomPoint>())
#ifdef FC_USE_TNP_FIX
{
if (geo->isDerivedFrom<Part::GeomPoint>()) {
Part::TopoShape vertex(TopoDS::Vertex(geo->toShape()));
int idx = getVertexIndexGeoPos(geoId -1, Sketcher::PointPos::start);
std::string name = convertSubName(Data::IndexedName::fromConst("Vertex", idx+1), false);
@@ -346,17 +344,6 @@ void SketchObject::buildShape() {
FC_WARN("Edge too small: " << indexedName);
}
}
#else
{
vertices.emplace_back(TopoDS::Vertex(geo->toShape()));
int idx = getVertexIndexGeoPos(i-1, PointPos::start);
std::string name = convertSubName(Data::IndexedName::fromConst("Vertex", idx+1), false);
}
else
shapes.push_back(getEdge(geo,convertSubName(
Data::IndexedName::fromConst("Edge", i), false).c_str()));
#endif
}
for(int i=2;i<ExternalGeo.getSize();++i) {
@@ -11366,13 +11353,6 @@ const char *SketchObject::convertInternalName(const char *name)
App::ElementNamePair SketchObject::getElementName(
const char *name, ElementNameType type) const
{
// Todo: Toponaming Project March 2024: This method override breaks the sketcher - selection and deletion
// of constraints ceases to work. See #13169. We need to prove that this works before
// enabling it.
// return Part2DObject::getElementName(name,type);
#ifndef FC_USE_TNP_FIX
return Part2DObject::getElementName(name,type);
#endif
App::ElementNamePair ret;
if(!name) return ret;
@@ -42,7 +42,6 @@ TEST_F(FeatureMirroringTest, testXMirror)
// Mirrored it around X from 0,0,0 -> 1,2,3 to 0,0,-3 -> 1,2,0
EXPECT_TRUE(boxesMatch(bb, Base::BoundBox3d(0, 0, -3, 1, 2, 0)));
// Assert correct element Map
#ifdef FC_USE_TNP_FIX
EXPECT_TRUE(allElementsMatch(
_mirror->Shape.getShape(),
{
@@ -56,9 +55,6 @@ TEST_F(FeatureMirroringTest, testXMirror)
"Vertex4;:M;MIR;:H70c:7,V", "Vertex5;:M;MIR;:H70c:7,V", "Vertex6;:M;MIR;:H70c:7,V",
"Vertex7;:M;MIR;:H70c:7,V", "Vertex8;:M;MIR;:H70c:7,V",
}));
#else
EXPECT_EQ(_mirror->Shape.getShape().getElementMapSize(), 0);
#endif
}
TEST_F(FeatureMirroringTest, testYMirrorWithExistingElementMap)
@@ -80,7 +76,6 @@ TEST_F(FeatureMirroringTest, testYMirrorWithExistingElementMap)
// Mirrored it around X from 0,0,0 -> 1,2,3 to 0,0,-3 -> 1,2,0
EXPECT_TRUE(boxesMatch(bb, Base::BoundBox3d(0, 0, -3, 1, 3, 0)));
// Assert correct element Map
#ifdef FC_USE_TNP_FIX
EXPECT_TRUE(elementsMatch(_mirror->Shape.getShape(),
{
"Edge10;:H11c3,E;:M;MIR;:H11ca:7,E",
@@ -142,10 +137,6 @@ TEST_F(FeatureMirroringTest, testYMirrorWithExistingElementMap)
"Vertex8;:H11c3,V;:M;MIR;:H11ca:7,V",
"Vertex8;:H11c4,V;:M;MIR;:H11ca:7,V",
}));
#else
EXPECT_EQ(_mirror->Shape.getShape().getElementMapSize(), 0);
#endif
}
// NOLINTEND(readability-magic-numbers,cppcoreguidelines-avoid-magic-numbers)
-8
View File
@@ -43,13 +43,9 @@ TEST_F(FeatureOffsetTest, testOffset3D)
EXPECT_EQ(getVolume(_offset->Shape.getShape().getShape()), 60);
EXPECT_TRUE(boxesMatch(bb, Base::BoundBox3d(-1, -1, -1, 2, 3, 4)));
// Assert correct element Map
#ifdef FC_USE_TNP_FIX
EXPECT_EQ(_offset->Shape.getShape().countSubElements("Vertex"), 8);
EXPECT_EQ(_offset->Shape.getShape().countSubElements("Edge"), 12);
EXPECT_EQ(_offset->Shape.getShape().countSubElements("Face"), 6);
#else
EXPECT_EQ(_offset->Shape.getShape().getElementMapSize(), 0);
#endif
}
TEST_F(FeatureOffsetTest, testOffset3DWithExistingElementMap)
@@ -72,13 +68,9 @@ TEST_F(FeatureOffsetTest, testOffset3DWithExistingElementMap)
EXPECT_EQ(getVolume(_offset->Shape.getShape().getShape()), 245);
EXPECT_TRUE(boxesMatch(bb, Base::BoundBox3d(-2, -2, -2, 3, 5, 5)));
// Assert correct element Map
#ifdef FC_USE_TNP_FIX
EXPECT_EQ(_offset->Shape.getShape().countSubElements("Vertex"), 8);
EXPECT_EQ(_offset->Shape.getShape().countSubElements("Edge"), 12);
EXPECT_EQ(_offset->Shape.getShape().countSubElements("Face"), 6);
#else
EXPECT_EQ(_offset->Shape.getShape().getElementMapSize(), 0);
#endif
}
TEST_F(FeatureOffsetTest, testOffset2D)
@@ -185,24 +185,8 @@ TEST_F(FeaturePartCommonTest, testHistory)
_common->execute();
hist = _common->History.getValues();
// Assert
#ifndef FC_USE_TNP_FIX
ASSERT_EQ(hist.size(), 2);
EXPECT_EQ(hist[0].shapeMap, compare1);
EXPECT_EQ(hist[1].shapeMap, compare2);
// Act to reverse the histories
_common->Base.setValue(_boxes[1]);
_common->Tool.setValue(_boxes[0]);
_common->execute();
hist = _common->History.getValues();
// Assert
ASSERT_EQ(hist.size(), 2);
EXPECT_EQ(hist[0].shapeMap, compare2);
EXPECT_EQ(hist[1].shapeMap, compare1);
#else
ASSERT_EQ(hist.size(),
0); // TODO: with TNP enabled, this becomes 0, matches the code. Correct?
#endif
}
TEST_F(FeaturePartCommonTest, testMapping)
@@ -215,9 +199,5 @@ TEST_F(FeaturePartCommonTest, testMapping)
_common->execute();
const Part::TopoShape& ts1 = _common->Shape.getShape();
// Assert
#ifndef FC_USE_TNP_FIX
EXPECT_EQ(ts1.getElementMap().size(), 0);
#else
EXPECT_EQ(ts1.getElementMap().size(), 26);
#endif
}
@@ -183,11 +183,7 @@ TEST_F(FeaturePartCutTest, testMapping)
_cut->execute();
const Part::TopoShape& ts1 = _cut->Shape.getShape();
// Assert
#ifndef FC_USE_TNP_FIX
EXPECT_EQ(ts1.getElementMap().size(), 0);
#else
EXPECT_EQ(ts1.getElementMap().size(), 26);
#endif
}
// See FeaturePartCommon.cpp for a history test. It would be exactly the same and redundant here.
-8
View File
@@ -53,11 +53,7 @@ TEST_F(FeaturePartTest, testGetElementName)
EXPECT_STREQ(namePairExport.oldName.c_str(), "test");
EXPECT_STREQ(namePairSelf.newName.c_str(), "");
EXPECT_STREQ(namePairSelf.oldName.c_str(), "");
#ifndef FC_USE_TNP_FIX
EXPECT_EQ(ts.getElementMap().size(), 0);
#else
EXPECT_EQ(ts.getElementMap().size(), 26);
#endif
// TBD
}
@@ -166,14 +162,10 @@ TEST_F(FeaturePartTest, getRelatedElements)
HistoryTraceType::followTypeChange,
true);
// Assert
#ifdef FC_USE_TNP_FIX
EXPECT_EQ(result.size(), 1); // Found the one.
EXPECT_EQ(result2.size(), 0); // No element map, so no related elements
// The results are always going to vary, so we can't test for specific values:
// EXPECT_STREQ(result.front().name.toString().c_str(),"Edge3;:M;CMN;:H38d:7,E");
#else
EXPECT_EQ(result.size(), 0);
#endif
}
// Note that this test is pretty trivial and useless .. but the method in question is never
@@ -49,11 +49,7 @@ TEST_F(PropertyTopoShapeTest, testPropertyPartShapeTopoShape)
EXPECT_TRUE(topoShapeOut.isSame(topoShapeIn));
EXPECT_TRUE(topoDsShapeOut.IsSame(topoDsShapeIn));
EXPECT_EQ(getVolume(topoDsShapeOut), 3);
#ifdef FC_USE_TNP_FIX
EXPECT_EQ(topoShapeOut.getElementMapSize(), 26);
#else
EXPECT_EQ(topoShapeOut.getElementMapSize(), 0);
#endif
}
TEST_F(PropertyTopoShapeTest, testPropertyPartShapeTopoDSShape)
@@ -1432,14 +1432,6 @@ TEST_F(TopoShapeExpansionTest, makeElementBooleanCut)
// Assert elementMap is correct
EXPECT_EQ(elements.size(), 38);
EXPECT_EQ(elements.count(IndexedName("Face", 1)), 1);
#ifndef FC_USE_TNP_FIX
EXPECT_EQ(
elements[IndexedName("Face", 1)],
MappedName(
"Face3;:M;CUT;:H1:7,F;:U;CUT;:H1:7,E;:L(Face5;:M;CUT;:H1:7,F;:U2;CUT;:H1:8,E|Face5;:M;"
"CUT;:H1:7,F;:U2;CUT;:H1:8,E;:U;CUT;:H1:7,V;:L(Face6;:M;CUT;:H1:7,F;:U2;CUT;:H1:8,E;:U;"
"CUT;:H1:7,V);CUT;:H1:3c,E|Face6;:M;CUT;:H1:7,F;:U2;CUT;:H1:8,E);CUT;:H1:cb,F"));
#else
EXPECT_TRUE(allElementsMatch(result,
{
"Edge1",
@@ -1481,7 +1473,6 @@ TEST_F(TopoShapeExpansionTest, makeElementBooleanCut)
"Vertex7",
"Vertex8",
}));
#endif
}
TEST_F(TopoShapeExpansionTest, makeElementBooleanFuse)
@@ -1502,14 +1493,6 @@ TEST_F(TopoShapeExpansionTest, makeElementBooleanFuse)
// Assert element map is correct
EXPECT_EQ(elements.size(), 66);
EXPECT_EQ(elements.count(IndexedName("Face", 1)), 1);
#ifndef FC_USE_TNP_FIX
EXPECT_EQ(
elements[IndexedName("Face", 1)],
MappedName(
"Face3;:M;FUS;:H1:7,F;:U;FUS;:H1:7,E;:L(Face5;:M;FUS;:H1:7,F;:U2;FUS;:H1:8,E|Face5;:M;"
"FUS;:H1:7,F;:U2;FUS;:H1:8,E;:U;FUS;:H1:7,V;:L(Face6;:M;FUS;:H1:7,F;:U2;FUS;:H1:8,E;:U;"
"FUS;:H1:7,V);FUS;:H1:3c,E|Face6;:M;FUS;:H1:7,F;:U2;FUS;:H1:8,E);FUS;:H1:cb,F"));
#else
EXPECT_TRUE(allElementsMatch(result,
{
"Edge1",
@@ -1579,7 +1562,6 @@ TEST_F(TopoShapeExpansionTest, makeElementBooleanFuse)
"Vertex8",
"Vertex8;:H2,V",
}));
#endif
}
TEST_F(TopoShapeExpansionTest, makeElementDraft)
@@ -1852,14 +1834,6 @@ TEST_F(TopoShapeExpansionTest, makeElementGeneralFuse)
// Assert elementMap is correct
EXPECT_EQ(elements.size(), 72);
EXPECT_EQ(elements.count(IndexedName("Face", 1)), 1);
#ifndef FC_USE_TNP_FIX
EXPECT_EQ(
elements[IndexedName("Face", 1)],
MappedName(
"Face3;:M;GFS;:H1:7,F;:U;GFS;:H1:7,E;:L(Face5;:M;GFS;:H1:7,F;:U2;GFS;:H1:8,E|Face5;:M;"
"GFS;:H1:7,F;:U2;GFS;:H1:8,E;:U;GFS;:H1:7,V;:L(Face6;:M;GFS;:H1:7,F;:U2;GFS;:H1:8,E;:U;"
"GFS;:H1:7,V);GFS;:H1:3c,E|Face6;:M;GFS;:H1:7,F;:U2;GFS;:H1:8,E);GFS;:H1:cb,F"));
#else
EXPECT_TRUE(allElementsMatch(result,
{
"Edge1",
@@ -1935,7 +1909,6 @@ TEST_F(TopoShapeExpansionTest, makeElementGeneralFuse)
"Vertex8",
"Vertex8;:H2,V",
}));
#endif
}
TEST_F(TopoShapeExpansionTest, makeElementFuse)
@@ -1955,14 +1928,6 @@ TEST_F(TopoShapeExpansionTest, makeElementFuse)
// Assert elementMap is correct
EXPECT_EQ(elements.size(), 66);
EXPECT_EQ(elements.count(IndexedName("Face", 1)), 1);
#ifndef FC_USE_TNP_FIX
EXPECT_EQ(
elements[IndexedName("Face", 1)],
MappedName(
"Face3;:M;FUS;:H1:7,F;:U;FUS;:H1:7,E;:L(Face5;:M;FUS;:H1:7,F;:U2;FUS;:H1:8,E|Face5;:M;"
"FUS;:H1:7,F;:U2;FUS;:H1:8,E;:U;FUS;:H1:7,V;:L(Face6;:M;FUS;:H1:7,F;:U2;FUS;:H1:8,E;:U;"
"FUS;:H1:7,V);FUS;:H1:3c,E|Face6;:M;FUS;:H1:7,F;:U2;FUS;:H1:8,E);FUS;:H1:cb,F"));
#else
EXPECT_TRUE(allElementsMatch(result,
{
"Edge1",
@@ -2032,7 +1997,6 @@ TEST_F(TopoShapeExpansionTest, makeElementFuse)
"Vertex8",
"Vertex8;:H2,V",
}));
#endif
}
TEST_F(TopoShapeExpansionTest, makeElementCut)
@@ -2053,14 +2017,6 @@ TEST_F(TopoShapeExpansionTest, makeElementCut)
// Assert elementMap is correct
EXPECT_EQ(elements.size(), 38);
EXPECT_EQ(elements.count(IndexedName("Face", 1)), 1);
#ifndef FC_USE_TNP_FIX
EXPECT_EQ(
elements[IndexedName("Face", 1)],
MappedName(
"Face3;:M;CUT;:H1:7,F;:U;CUT;:H1:7,E;:L(Face5;:M;CUT;:H1:7,F;:U2;CUT;:H1:8,E|Face5;:M;"
"CUT;:H1:7,F;:U2;CUT;:H1:8,E;:U;CUT;:H1:7,V;:L(Face6;:M;CUT;:H1:7,F;:U2;CUT;:H1:8,E;:U;"
"CUT;:H1:7,V);CUT;:H1:3c,E|Face6;:M;CUT;:H1:7,F;:U2;CUT;:H1:8,E);CUT;:H1:cb,F"));
#else
EXPECT_TRUE(allElementsMatch(result,
{
"Edge1",
@@ -2102,7 +2058,6 @@ TEST_F(TopoShapeExpansionTest, makeElementCut)
"Vertex7",
"Vertex8",
}));
#endif
}
TEST_F(TopoShapeExpansionTest, makeElementChamfer)
@@ -2498,14 +2453,6 @@ TEST_F(TopoShapeExpansionTest, makeElementTransformWithMap)
// Assert elementMap is correct
EXPECT_EQ(elements.size(), 66);
EXPECT_EQ(elements.count(IndexedName("Face", 1)), 1);
#ifndef FC_USE_TNP_FIX
EXPECT_EQ(
elements[IndexedName("Face", 1)],
MappedName(
"Face3;:M;FUS;:H1:7,F;:U;FUS;:H1:7,E;:L(Face5;:M;FUS;:H1:7,F;:U2;FUS;:H1:8,E|Face5;:M;"
"FUS;:H1:7,F;:U2;FUS;:H1:8,E;:U;FUS;:H1:7,V;:L(Face6;:M;FUS;:H1:7,F;:U2;FUS;:H1:8,E;:U;"
"FUS;:H1:7,V);FUS;:H1:3c,E|Face6;:M;FUS;:H1:7,F;:U2;FUS;:H1:8,E);FUS;:H1:cb,F"));
#else
EXPECT_TRUE(allElementsMatch(result,
{
"Edge1",
@@ -2575,7 +2522,6 @@ TEST_F(TopoShapeExpansionTest, makeElementTransformWithMap)
"Vertex8",
"Vertex8;:H2,V",
}));
#endif
}
TEST_F(TopoShapeExpansionTest, makeElementGTransformWithoutMap)
@@ -2616,14 +2562,6 @@ TEST_F(TopoShapeExpansionTest, makeElementGTransformWithMap)
// Assert elementMap is correct
EXPECT_EQ(elements.size(), 66);
EXPECT_EQ(elements.count(IndexedName("Face", 1)), 1);
#ifndef FC_USE_TNP_FIX
EXPECT_EQ(
elements[IndexedName("Face", 1)],
MappedName(
"Face3;:M;FUS;:H1:7,F;:U;FUS;:H1:7,E;:L(Face5;:M;FUS;:H1:7,F;:U2;FUS;:H1:8,E|Face5;:M;"
"FUS;:H1:7,F;:U2;FUS;:H1:8,E;:U;FUS;:H1:7,V;:L(Face6;:M;FUS;:H1:7,F;:U2;FUS;:H1:8,E;:U;"
"FUS;:H1:7,V);FUS;:H1:3c,E|Face6;:M;FUS;:H1:7,F;:U2;FUS;:H1:8,E);FUS;:H1:cb,F"));
#else
EXPECT_TRUE(allElementsMatch(result,
{
"Edge1",
@@ -2693,7 +2631,6 @@ TEST_F(TopoShapeExpansionTest, makeElementGTransformWithMap)
"Vertex8",
"Vertex8;:H2,V",
}));
#endif
}
// Not testing _makeElementTransform as it is a thin wrapper that calls the same places as the four
@@ -3066,55 +3003,6 @@ TEST_F(TopoShapeExpansionTest, traceElement)
// Act
result.traceElement(mappedName, cb);
// Assert we have the element map we think we do.
#ifndef FC_USE_TNP_FIX
EXPECT_TRUE(allElementsMatch(
result,
{
"Edge10;:G(Edge2;K-1;:H2:4,E);CUT;:H1:1a,V",
"Edge10;:M;CUT;:H1:7,E",
"Edge10;:M;CUT;:H1:7,E;:U;CUT;:H1:7,V",
"Edge11;:M;CUT;:H2:7,E",
"Edge12;:M;CUT;:H2:7,E",
"Edge2;:M;CUT;:H2:7,E",
"Edge2;:M;CUT;:H2:7,E;:U;CUT;:H2:7,V",
"Edge4;:M;CUT;:H2:7,E",
"Edge4;:M;CUT;:H2:7,E;:U;CUT;:H2:7,V",
"Edge6;:G(Edge12;K-1;:H2:4,E);CUT;:H1:1b,V",
"Edge6;:M;CUT;:H1:7,E",
"Edge6;:M;CUT;:H1:7,E;:U;CUT;:H1:7,V",
"Edge8;:G(Edge11;K-1;:H2:4,E);CUT;:H1:1b,V",
"Edge8;:M;CUT;:H1:7,E",
"Edge8;:M;CUT;:H1:7,E;:U;CUT;:H1:7,V",
"Edge9;:G(Edge4;K-1;:H2:4,E);CUT;:H1:1a,V",
"Edge9;:M;CUT;:H1:7,E",
"Edge9;:M;CUT;:H1:7,E;:U;CUT;:H1:7,V",
"Face1;:M;CUT;:H2:7,F",
"Face1;:M;CUT;:H2:7,F;:U;CUT;:H2:7,E",
"Face2;:G(Face4;K-1;:H2:4,F);CUT;:H1:1a,E",
"Face2;:M;CUT;:H1:7,F",
"Face2;:M;CUT;:H1:7,F;:U;CUT;:H1:7,E",
"Face2;:M;CUT;:H1:7,F;:U;CUT;:H1:7,E;:L(Face5;:M;CUT;:H1:7,F;:U2;CUT;:H1:8,E;:U;CUT;:"
"H1:7,V;:L(Face6;:M;CUT;:H1:7,F;:U2;CUT;:H1:8,E;:U;CUT;:H1:7,V);CUT;:H1:3c,E|Face5;:M;"
"CUT;:H1:7,F;:U;CUT;:H1:7,E|Face6;:M;CUT;:H1:7,F;:U;CUT;:H1:7,E);CUT;:H1:c9,F",
"Face3;:G(Face1;K-1;:H2:4,F);CUT;:H1:1a,E",
"Face3;:M;CUT;:H1:7,F",
"Face3;:M;CUT;:H1:7,F;:U;CUT;:H1:7,E",
"Face3;:M;CUT;:H1:7,F;:U;CUT;:H1:7,E;:L(Face5;:M;CUT;:H1:7,F;:U2;CUT;:H1:8,E|Face5;:M;"
"CUT;:H1:7,F;:U2;CUT;:H1:8,E;:U;CUT;:H1:7,V;:L(Face6;:M;CUT;:H1:7,F;:U2;CUT;:H1:8,E;:U;"
"CUT;:H1:7,V);CUT;:H1:3c,E|Face6;:M;CUT;:H1:7,F;:U2;CUT;:H1:8,E);CUT;:H1:cb,F",
"Face4;:M;CUT;:H2:7,F",
"Face5;:M;CUT;:H1:7,F",
"Face5;:M;CUT;:H1:7,F;:U2;CUT;:H1:8,E",
"Face5;:M;CUT;:H1:7,F;:U2;CUT;:H1:8,E;:U;CUT;:H1:7,V",
"Face5;:M;CUT;:H1:7,F;:U2;CUT;:H1:8,E;:U;CUT;:H1:7,V;:L(Face6;:M;CUT;:H1:7,F;:U2;CUT;:"
"H1:8,E;:U;CUT;:H1:7,V);CUT;:H1:3c,E",
"Face5;:M;CUT;:H1:7,F;:U;CUT;:H1:7,E",
"Face6;:M;CUT;:H1:7,F",
"Face6;:M;CUT;:H1:7,F;:U2;CUT;:H1:8,E",
"Face6;:M;CUT;:H1:7,F;:U2;CUT;:H1:8,E;:U;CUT;:H1:7,V",
"Face6;:M;CUT;:H1:7,F;:U;CUT;:H1:7,E",
}));
#else
EXPECT_TRUE(allElementsMatch(result,
{
"Edge1",
@@ -3156,7 +3044,6 @@ TEST_F(TopoShapeExpansionTest, traceElement)
"Vertex7",
"Vertex8",
}));
#endif
}
TEST_F(TopoShapeExpansionTest, makeElementOffset)
@@ -286,19 +286,10 @@ TEST_F(SketchObjectTest, testGetElementName)
EXPECT_STREQ(map[2].name.toString().c_str(), (tagName + "v2;SKT").c_str());
EXPECT_EQ(map[2].index.toString(), "Vertex2");
// Assert
#ifndef FC_USE_TNP_FIX
EXPECT_STREQ(forward_normal_name.newName.c_str(), "");
EXPECT_STREQ(forward_normal_name.oldName.c_str(), "g1;SKT");
EXPECT_STREQ(reverse_normal_name.newName.c_str(), "");
EXPECT_STREQ(reverse_normal_name.oldName.c_str(), "Vertex2");
EXPECT_STREQ(reverse_export_name.newName.c_str(), ";g1v1;SKT.Vertex1");
EXPECT_STREQ(reverse_export_name.oldName.c_str(), "Vertex1");
#else
EXPECT_STREQ(forward_normal_name.newName.c_str(), (";" + tagName + ";SKT.Edge1").c_str());
EXPECT_STREQ(forward_normal_name.oldName.c_str(), "Edge1");
EXPECT_STREQ(reverse_normal_name.newName.c_str(), (";" + tagName + "v2;SKT.Vertex2").c_str());
EXPECT_STREQ(reverse_normal_name.oldName.c_str(), "Vertex2");
EXPECT_STREQ(reverse_export_name.newName.c_str(), (";" + tagName + "v1;SKT.Vertex1").c_str());
EXPECT_STREQ(reverse_export_name.oldName.c_str(), "Vertex1");
#endif
}