Toponaming: Remove all FC_USE_TNP_FIX protected old code
This commit is contained in:
@@ -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
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
@@ -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,
|
||||
°Max)) {
|
||||
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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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());
|
||||
|
||||
@@ -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());
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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());
|
||||
|
||||
@@ -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());
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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());
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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, ©Geom, &PyBool_Type, ©Mesh))
|
||||
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());
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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) {
|
||||
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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());
|
||||
|
||||
@@ -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());
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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());
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user