PartDesign: Fix hole centered on point edge case (#21257)

* Light refactor of getTopoShape function

* Fix hole edge case

* [pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci

* Update src/Mod/Part/App/PartFeature.cpp

Co-authored-by: Kacper Donat <[email protected]>

* Update src/Mod/Part/App/PartFeature.cpp

Co-authored-by: Kacper Donat <[email protected]>

* Update src/Mod/Part/App/PartFeature.cpp

Co-authored-by: Kacper Donat <[email protected]>

* Update src/Mod/Part/App/PartFeature.cpp

Co-authored-by: Kacper Donat <[email protected]>

* Refactor simplifyCompound()

* Use Base::Flags<GetShapeOption>

* [pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci

* Shorten enum name and move it from class scope to namespace scope

* [pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci

---------

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
Co-authored-by: Kacper Donat <[email protected]>
This commit is contained in:
theo-vt
2025-05-29 22:37:54 +02:00
committed by GitHub
co-authored by pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Kacper Donat
parent 17e56f6570
commit 13e7952ccc
52 changed files with 449 additions and 223 deletions
+9 -2
View File
@@ -381,7 +381,12 @@ TDF_Label ExportOCAF2::exportObject(App::DocumentObject* parentObj,
const char* name)
{
App::DocumentObject* obj;
auto shape = Part::Feature::getTopoShape(parentObj, sub, false, nullptr, &obj, false, !sub);
auto shape = Part::Feature::getTopoShape(
parentObj,
(sub ? Part::ShapeOption::NoFlag : Part::ShapeOption::Transform),
sub,
nullptr,
&obj);
if (!obj || shape.isNull()) {
if (obj) {
FC_WARN(obj->getFullName() << " has null shape");
@@ -415,7 +420,9 @@ TDF_Label ExportOCAF2::exportObject(App::DocumentObject* parentObj,
auto linked = obj;
auto linkedShape = shape;
while (true) {
auto s = Part::Feature::getTopoShape(linked);
auto s = Part::Feature::getTopoShape(linked,
Part::ShapeOption::ResolveLink
| Part::ShapeOption::Transform);
if (s.isNull() || !s.getShape().IsPartner(shape.getShape())) {
break;
}
+3 -1
View File
@@ -557,7 +557,9 @@ App::DocumentObject* ImportOCAF2::loadShapes()
ret->recomputeFeature(true);
}
if (options.merge && ret && !ret->isDerivedFrom<Part::Feature>()) {
auto shape = Part::Feature::getTopoShape(ret);
auto shape = Part::Feature::getTopoShape(ret,
Part::ShapeOption::ResolveLink
| Part::ShapeOption::Transform);
auto feature = pDocument->addObject<Part::Feature>("Feature");
auto name = Tools::labelName(pDoc->Main());
feature->Label.setValue(name.empty() ? default_name.c_str() : name.c_str());
+12 -2
View File
@@ -125,7 +125,12 @@ MeasureType Measurement::findType()
for (; obj != objects.end(); ++obj, ++subEl) {
TopoDS_Shape refSubShape;
try {
refSubShape = Part::Feature::getShape(*obj, (*subEl).c_str(), true);
refSubShape = Part::Feature::getShape(*obj,
Part::ShapeOption::NeedSubElement
| Part::ShapeOption::ResolveLink
| Part::ShapeOption::Transform,
(*subEl).c_str());
if (refSubShape.IsNull()) {
return MeasureType::Invalid;
}
@@ -751,7 +756,12 @@ bool Measurement::planesAreParallel() const
for (size_t i = 0; i < objects.size(); ++i) {
TopoDS_Shape refSubShape;
try {
refSubShape = Part::Feature::getShape(objects[i], subElements[i].c_str(), true);
refSubShape = Part::Feature::getShape(objects[i],
Part::ShapeOption::NeedSubElement
| Part::ShapeOption::ResolveLink
| Part::ShapeOption::Transform,
subElements[i].c_str());
if (refSubShape.IsNull()) {
return false;
}
+3 -1
View File
@@ -114,7 +114,9 @@ TopoDS_Shape ShapeFinder::getLocatedShape(const App::DocumentObject& rootObject,
return {};
}
TopoDS_Shape shape = Part::Feature::getShape(target);
TopoDS_Shape shape =
Part::Feature::getShape(target,
Part::ShapeOption::ResolveLink | Part::ShapeOption::Transform);
if (isShapeReallyNull(shape)) {
return {};
}
+12 -3
View File
@@ -217,7 +217,10 @@ void Tessellation::onEstimateMaximumEdgeLengthClicked()
double edgeLen = 0;
for (auto& sel : Gui::Selection().getSelection("*", Gui::ResolveMode::NoResolve)) {
auto shape = Part::Feature::getTopoShape(sel.pObject, sel.SubName);
auto shape = Part::Feature::getTopoShape(sel.pObject,
Part::ShapeOption::ResolveLink
| Part::ShapeOption::Transform,
sel.SubName);
if (shape.hasSubShape(TopAbs_FACE)) {
Base::BoundBox3d bbox = shape.getBoundBox();
edgeLen = std::max<double>(edgeLen, bbox.LengthX());
@@ -249,7 +252,10 @@ bool Tessellation::accept()
bool bodyWithNoTip = false;
bool partWithNoFace = false;
for (auto& sel : Gui::Selection().getSelection("*", Gui::ResolveMode::NoResolve)) {
auto shape = Part::Feature::getTopoShape(sel.pObject, sel.SubName);
auto shape = Part::Feature::getTopoShape(sel.pObject,
Part::ShapeOption::ResolveLink
| Part::ShapeOption::Transform,
sel.SubName);
if (shape.hasSubShape(TopAbs_FACE)) {
shapeObjects.emplace_back(sel.pObject, sel.SubName);
}
@@ -568,7 +574,10 @@ bool Mesh2ShapeGmsh::writeProject(QString& inpFile, QString& outFile)
App::DocumentObject* part = sub.getObject();
if (part) {
Part::TopoShape shape = Part::Feature::getTopoShape(part, sub.getSubName().c_str());
Part::TopoShape shape = Part::Feature::getTopoShape(part,
Part::ShapeOption::ResolveLink
| Part::ShapeOption::Transform,
sub.getSubName().c_str());
shape.exportBrep(d->cadFile.c_str());
d->label = part->Label.getStrValue() + " (Meshed)";
+12 -4
View File
@@ -861,7 +861,7 @@ private:
shape = static_cast<GeometryPy *>(pcObj)->getGeometryPtr()->toShape();
else if (PyObject_TypeCheck(pcObj, &App::DocumentObjectPy::Type)) {
auto obj = static_cast<App::DocumentObjectPy *>(pcObj)->getDocumentObjectPtr();
shape = Feature::getTopoShape(obj);
shape = Feature::getTopoShape(obj, ShapeOption::ResolveLink | ShapeOption::Transform);
} else {
throw Py::TypeError("Expects argument of type DocumentObject, Shape, or Geometry");
}
@@ -2288,9 +2288,17 @@ private:
Base::Matrix4D mat;
if(pyMat)
mat = *static_cast<Base::MatrixPy*>(pyMat)->getMatrixPtr();
auto shape = Feature::getTopoShape(obj,subname,Base::asBoolean(needSubElement),
&mat,&subObj,retType==2,Base::asBoolean(transform),
Base::asBoolean(noElementMap));
bool resolveLink = (retType == 2);
auto shape = Feature::getTopoShape(obj,
(resolveLink ? ShapeOption::ResolveLink : ShapeOption::NoFlag)
| (Base::asBoolean(needSubElement) ? ShapeOption::NeedSubElement : ShapeOption::NoFlag)
| (Base::asBoolean(transform) ? ShapeOption::Transform : ShapeOption::NoFlag)
| (Base::asBoolean(noElementMap) ? ShapeOption::NoElementMap : ShapeOption::NoFlag),
subname,
&mat,
&subObj);
if (Base::asBoolean(refine)) {
shape = TopoShape(0, shape.Hasher).makeElementRefine(shape);
}
+5 -1
View File
@@ -881,7 +881,11 @@ TopoShape AttachEngine::extractSubShape(App::DocumentObject* obj, const std::str
try {
// getTopoShape support fully qualified subnames and should return shape with correct
// global placement.
shape = Feature::getTopoShape(obj, subname.c_str(), true);
shape = Feature::getTopoShape(obj,
ShapeOption::NeedSubElement
| ShapeOption::ResolveLink
| ShapeOption::Transform,
subname.c_str());
for (;;) {
if (shape.isNull()) {
+2 -2
View File
@@ -48,8 +48,8 @@ App::DocumentObjectExecReturn *Chamfer::execute()
return new App::DocumentObjectExecReturn("No object linked");
try {
TopoShape baseTopoShape = Feature::getTopoShape(link);
auto baseShape = Feature::getShape(link);
TopoShape baseTopoShape = Feature::getTopoShape(link, ShapeOption::ResolveLink | ShapeOption::Transform);
auto baseShape = Feature::getShape(link, ShapeOption::ResolveLink | ShapeOption::Transform);
BRepFilletAPI_MakeChamfer mkChamfer(baseShape);
TopTools_IndexedDataMapOfShapeListOfShape mapEdgeFace;
TopExp::MapShapesAndAncestors(baseShape, TopAbs_EDGE, TopAbs_FACE, mapEdgeFace);
+1 -1
View File
@@ -63,7 +63,7 @@ App::DocumentObjectExecReturn *Compound::execute()
if (!tempLinks.insert(obj).second) {
continue;
}
auto sh = Feature::getTopoShape(obj);
auto sh = Feature::getTopoShape(obj, ShapeOption::ResolveLink | ShapeOption::Transform);
if (!sh.isNull()) {
shapes.push_back(sh);
}
+13 -4
View File
@@ -170,10 +170,14 @@ bool Extrusion::fetchAxisLink(const App::PropertyLinkSub& axisLink, Base::Vector
TopoDS_Shape axEdge;
if (!axisLink.getSubValues().empty() && axisLink.getSubValues()[0].length() > 0) {
axEdge = Feature::getTopoShape(linked, axisLink.getSubValues()[0].c_str(), true /*need element*/).getShape();
axEdge = Feature::getTopoShape(linked,
ShapeOption::NeedSubElement
| ShapeOption::ResolveLink
| ShapeOption::Transform,
axisLink.getSubValues()[0].c_str()).getShape();
}
else {
axEdge = Feature::getShape(linked);
axEdge = Feature::getShape(linked, ShapeOption::ResolveLink | ShapeOption::Transform);
}
if (axEdge.IsNull())
@@ -263,7 +267,12 @@ Base::Vector3d Extrusion::calculateShapeNormal(const App::PropertyLink& shapeLin
{
App::DocumentObject* docobj = nullptr;
Base::Matrix4D mat;
TopoDS_Shape sh = Feature::getShape(shapeLink.getValue(), nullptr, false, &mat, &docobj);
TopoDS_Shape sh = Feature::getShape(shapeLink.getValue(),
ShapeOption::ResolveLink
| ShapeOption::Transform,
nullptr,
&mat,
&docobj);
if (!docobj)
throw Base::ValueError("calculateShapeNormal: link is empty");
@@ -366,7 +375,7 @@ App::DocumentObjectExecReturn* Extrusion::execute()
try {
ExtrusionParameters params = computeFinalParameters();
TopoShape result(0);
extrudeShape(result, Feature::getTopoShape(link), params);
extrudeShape(result, Feature::getTopoShape(link, ShapeOption::ResolveLink | ShapeOption::Transform), params);
this->Shape.setValue(result);
return App::DocumentObject::StdReturn;
}
+1 -1
View File
@@ -68,7 +68,7 @@ App::DocumentObjectExecReturn *Face::execute()
for (std::vector<App::DocumentObject*>::iterator it = links.begin(); it != links.end(); ++it) {
if (!(*it))
return new App::DocumentObjectExecReturn("Linked object is not a Part object (has no Shape).");
TopoDS_Shape shape = Feature::getShape(*it);
TopoDS_Shape shape = Feature::getShape(*it, ShapeOption::ResolveLink | ShapeOption::Transform);
if (shape.IsNull())
return new App::DocumentObjectExecReturn("Linked shape object is empty");
+2 -2
View File
@@ -54,8 +54,8 @@ App::DocumentObjectExecReturn *Fillet::execute()
#if defined(__GNUC__) && defined (FC_OS_LINUX)
Base::SignalException se;
#endif
auto baseShape = Feature::getShape(link);
TopoShape baseTopoShape = Feature::getTopoShape(link);
auto baseShape = Feature::getShape(link, ShapeOption::ResolveLink | ShapeOption::Transform);
TopoShape baseTopoShape = Feature::getTopoShape(link, ShapeOption::ResolveLink | ShapeOption::Transform);
BRepFilletAPI_MakeFillet mkFillet(baseShape);
TopTools_IndexedMapOfShape mapOfShape;
TopExp::MapShapes(baseShape, TopAbs_EDGE, mapOfShape);
+10 -3
View File
@@ -170,7 +170,13 @@ App::DocumentObjectExecReturn *Mirroring::execute()
bool isEdge = false; //will be true if user selected edge subobject or if object only has 1 edge
TopoDS_Shape shape;
if (!subStrings.empty() && subStrings[0].length() > 0){
shape = Feature::getTopoShape(linked, subStrings[0].c_str(), true).getShape();
shape = Feature::getTopoShape(linked,
ShapeOption::NeedSubElement
| ShapeOption::ResolveLink
| ShapeOption::Transform,
subStrings[0].c_str()).getShape();
if (strstr(subStrings[0].c_str(), "Face")){
isFace = true; //was face subobject, e.g. Face3
} else {
@@ -179,7 +185,8 @@ App::DocumentObjectExecReturn *Mirroring::execute()
}
}
} else {
shape = Feature::getShape(linked); //no subobjects were selected, so this is entire shape of feature
//no subobjects were selected, so this is entire shape of feature
shape = Feature::getShape(linked, ShapeOption::ResolveLink | ShapeOption::Transform);
}
// if there is only 1 face or 1 edge, then we don't need to force the user to select that face or edge
@@ -253,7 +260,7 @@ App::DocumentObjectExecReturn *Mirroring::execute()
try {
gp_Ax2 ax2(gp_Pnt(base.x,base.y,base.z), gp_Dir(norm.x,norm.y,norm.z));
auto shape = Feature::getTopoShape(link);
auto shape = Feature::getTopoShape(link, ShapeOption::ResolveLink | ShapeOption::Transform);
if (shape.isNull())
Standard_Failure::Raise("Cannot mirror empty shape");
this->Shape.setValue(TopoShape(0).makeElementMirror(shape,ax2));
+2 -2
View File
@@ -85,7 +85,7 @@ App::DocumentObjectExecReturn *Offset::execute()
bool self = SelfIntersection.getValue();
short mode = (short)Mode.getValue();
bool fill = Fill.getValue();
auto shape = Feature::getTopoShape(source);
auto shape = Feature::getTopoShape(source, ShapeOption::ResolveLink | ShapeOption::Transform);
if(shape.isNull())
return new App::DocumentObjectExecReturn("Invalid source link");
auto join = static_cast<JoinType>(Join.getValue());
@@ -132,7 +132,7 @@ App::DocumentObjectExecReturn *Offset2D::execute()
if (!source) {
return new App::DocumentObjectExecReturn("No source shape linked.");
}
const TopoShape shape = Part::Feature::getTopoShape(source);
const TopoShape shape = Part::Feature::getTopoShape(source, ShapeOption::ResolveLink | ShapeOption::Transform);
if (shape.isNull()) {
return new App::DocumentObjectExecReturn("No source shape linked.");
}
+2 -2
View File
@@ -116,12 +116,12 @@ App::DocumentObjectExecReturn* Boolean::execute()
std::vector<TopoShape> shapes;
shapes.reserve(2);
// Now, let's get the TopoDS_Shape
shapes.push_back(Feature::getTopoShape(Base.getValue()));
shapes.push_back(Feature::getTopoShape(Base.getValue(), ShapeOption::ResolveLink | ShapeOption::Transform));
auto BaseShape = shapes[0].getShape();
if (BaseShape.IsNull()) {
throw NullShapeException("Base shape is null");
}
shapes.push_back(Feature::getTopoShape(Tool.getValue()));
shapes.push_back(Feature::getTopoShape(Tool.getValue(), ShapeOption::ResolveLink | ShapeOption::Transform));
auto ToolShape = shapes[1].getShape();
if (ToolShape.IsNull()) {
throw NullShapeException("Tool shape is null");
+1 -1
View File
@@ -88,7 +88,7 @@ App::DocumentObjectExecReturn *MultiCommon::execute()
{
std::vector<TopoShape> shapes;
for (auto obj : Shapes.getValues()) {
TopoShape sh = Feature::getTopoShape(obj);
TopoShape sh = Feature::getTopoShape(obj, ShapeOption::ResolveLink | ShapeOption::Transform);
if (sh.isNull()) {
return new App::DocumentObjectExecReturn("Input shape is null");
}
+1 -1
View File
@@ -93,7 +93,7 @@ App::DocumentObjectExecReturn *MultiFuse::execute()
std::vector<App::DocumentObject*>::iterator it;
for (it = obj.begin(); it != obj.end(); ++it) {
shapes.push_back(Feature::getTopoShape(*it));
shapes.push_back(Feature::getTopoShape(*it, ShapeOption::ResolveLink | ShapeOption::Transform));
}
bool argumentsAreInCompound = false;
+10 -2
View File
@@ -108,7 +108,11 @@ TopoDS_Face ProjectOnSurface::getSupportFace() const
throw Base::ValueError("Expect exactly one support face");
}
auto topoSupport = Feature::getTopoShape(support, subStrings[0].c_str(), true);
auto topoSupport = Feature::getTopoShape(support,
ShapeOption::NeedSubElement
| ShapeOption::ResolveLink
| ShapeOption::Transform,
subStrings[0].c_str());
return TopoDS::Face(topoSupport.getShape());
}
@@ -122,7 +126,11 @@ std::vector<TopoDS_Shape> ProjectOnSurface::getProjectionShapes() const
}
for (std::size_t index = 0; index < objects.size(); index++) {
auto topoSupport = Feature::getTopoShape(objects[index], subvalues[index].c_str(), true);
auto topoSupport = Feature::getTopoShape(objects[index],
ShapeOption::NeedSubElement
| ShapeOption::ResolveLink
| ShapeOption::Transform,
subvalues[index].c_str());
shapes.push_back(topoSupport.getShape());
}
+7 -3
View File
@@ -91,9 +91,13 @@ bool Revolution::fetchAxisLink(const App::PropertyLinkSub &axisLink,
TopoDS_Shape axEdge;
if (!axisLink.getSubValues().empty() && axisLink.getSubValues()[0].length() > 0){
axEdge = Feature::getTopoShape(linked, axisLink.getSubValues()[0].c_str(), true /*need element*/).getShape();
axEdge = Feature::getTopoShape(linked,
ShapeOption::NeedSubElement
| ShapeOption::ResolveLink
| ShapeOption::Transform,
axisLink.getSubValues()[0].c_str()).getShape();
} else {
axEdge = Feature::getShape(linked);
axEdge = Feature::getShape(linked, ShapeOption::ResolveLink | ShapeOption::Transform);
}
if (axEdge.IsNull())
@@ -149,7 +153,7 @@ App::DocumentObjectExecReturn *Revolution::execute()
angle = angle_edge;
//apply "midplane" symmetry
TopoShape sourceShape = Feature::getTopoShape(link);
TopoShape sourceShape = Feature::getTopoShape(link, ShapeOption::ResolveLink | ShapeOption::Transform);
if (Symmetric.getValue()) {
//rotate source shape backwards by half angle, to make resulting revolution symmetric to the profile
gp_Trsf mov;
+1 -1
View File
@@ -151,7 +151,7 @@ App::DocumentObjectExecReturn* Scale::execute()
try {
Scale::ScaleParameters params = computeFinalParameters();
TopoShape result = scaleShape(Feature::getTopoShape(link), params);
TopoShape result = scaleShape(Feature::getTopoShape(link, ShapeOption::ResolveLink | ShapeOption::Transform), params);
this->Shape.setValue(result);
return App::DocumentObject::StdReturn;
}
+20 -4
View File
@@ -98,7 +98,13 @@ TopoDS_Shape getLocatedShape(const App::SubObjectT& subject, Base::Matrix4D* mat
return {};
}
Part::TopoShape shape = Part::Feature::getTopoShape(obj, subject.getElementName(), false, mat, nullptr, true);
Part::TopoShape shape = Part::Feature::getTopoShape(
obj,
Part::ShapeOption::ResolveLink
| Part::ShapeOption::Transform,
subject.getElementName(),
mat);
if (shape.isNull()) {
Base::Console().log("Part::MeasureClient::getLocatedShape: Did not retrieve shape for %s, %s\n", obj->getNameInDocument(), subject.getElementName());
return {};
@@ -121,7 +127,12 @@ TopoDS_Shape getLocatedShape(const App::SubObjectT& subject, Base::Matrix4D* mat
App::MeasureElementType PartMeasureTypeCb(App::DocumentObject* ob, const char* subName)
{
TopoDS_Shape shape = Part::Feature::getShape(ob, subName, true);
TopoDS_Shape shape = Part::Feature::getShape(ob,
Part::ShapeOption::NeedSubElement
| Part::ShapeOption::ResolveLink
| Part::ShapeOption::Transform,
subName);
if (shape.IsNull()) {
// failure here on loading document with existing measurement.
Base::Console().message("Part::PartMeasureTypeCb did not retrieve shape for %s, %s\n", ob->getNameInDocument(), subName);
@@ -177,8 +188,13 @@ bool getShapeFromStrings(TopoDS_Shape &shapeOut, const App::SubObjectT& subject,
if (!obj) {
return {};
}
shapeOut = Part::Feature::getShape(obj, subject.getElementName(), true, mat);
return !shapeOut.IsNull();
shapeOut = Part::Feature::getShape(obj,
Part::ShapeOption::NeedSubElement
| Part::ShapeOption::ResolveLink
| Part::ShapeOption::Transform,
subject.getElementName(),
mat);
return !shapeOut.IsNull();
}
+106 -80
View File
@@ -544,7 +544,13 @@ static std::vector<std::pair<long, Data::MappedName>> getElementSource(App::Docu
doc = nullptr;
}
else {
shape = Part::Feature::getTopoShape(obj, 0, false, 0, &owner);
shape =
Part::Feature::getTopoShape(obj,
Part::ShapeOption::ResolveLink
| Part::ShapeOption::Transform,
nullptr,
nullptr,
&owner);
}
if (type && shape.elementType(original) != type) {
break;
@@ -571,7 +577,7 @@ std::list<Data::HistoryItem> Feature::getElementHistory(App::DocumentObject* fea
bool sameType)
{
std::list<Data::HistoryItem> ret;
TopoShape shape = getTopoShape(feature);
TopoShape shape = getTopoShape(feature, ShapeOption::ResolveLink | ShapeOption::Transform);
Data::IndexedName idx(name);
Data::MappedName element;
Data::MappedName prevElement;
@@ -648,7 +654,7 @@ std::list<Data::HistoryItem> Feature::getElementHistory(App::DocumentObject* fea
}
}
feature = obj;
shape = Feature::getTopoShape(feature);
shape = Feature::getTopoShape(feature, ShapeOption::ResolveLink | ShapeOption::Transform);
element = original;
if (element_type && shape.elementType(original) != element_type) {
break;
@@ -667,16 +673,14 @@ QVector<Data::MappedElement> Feature::getElementFromSource(App::DocumentObject*
if (!obj || !src) {
return res;
}
auto shape = getTopoShape(obj,
subname,
false,
nullptr,
nullptr,
true,
/*transform = */ false);
auto shape = getTopoShape(obj, ShapeOption::ResolveLink, subname, nullptr, nullptr);
App::DocumentObject* owner = nullptr;
auto srcShape = getTopoShape(src, srcSub, false, nullptr, &owner);
auto srcShape = getTopoShape(src,
ShapeOption::ResolveLink
| ShapeOption::Transform,
srcSub,
nullptr,
&owner);
int tagChanges;
Data::MappedElement element;
Data::IndexedName checkingSubname;
@@ -792,7 +796,12 @@ QVector<Data::MappedElement> Feature::getRelatedElements(App::DocumentObject* ob
bool withCache)
{
auto owner = obj;
auto shape = getTopoShape(obj, nullptr, false, 0, &owner);
auto shape = getTopoShape(obj,
ShapeOption::ResolveLink
| ShapeOption::Transform,
nullptr,
nullptr,
&owner);
QVector<Data::MappedElement> ret;
Data::MappedElement mapped = shape.getElementName(name);
if (!mapped.name) {
@@ -859,11 +868,13 @@ QVector<Data::MappedElement> Feature::getRelatedElements(App::DocumentObject* ob
return ret;
}
TopoDS_Shape Feature::getShape(const App::DocumentObject *obj, const char *subname,
bool needSubElement, Base::Matrix4D *pmat, App::DocumentObject **powner,
bool resolveLink, bool transform)
TopoDS_Shape Feature::getShape( const App::DocumentObject *obj,
ShapeOptions options,
const char *subname,
Base::Matrix4D *pmat,
App::DocumentObject **powner)
{
return getTopoShape(obj,subname,needSubElement,pmat,powner,resolveLink,transform,true).getShape();
return getTopoShape(obj, options | ShapeOption::NoElementMap, subname, pmat, powner).getShape();
}
App::Material Feature::getMaterialAppearance() const
@@ -886,7 +897,8 @@ void Feature::clearShapeCache() {
// _ShapeCache.cache.clear();
}
static TopoShape _getTopoShape(const App::DocumentObject* obj,
/*
(const App::DocumentObject* obj,
const char* subname,
bool needSubElement,
Base::Matrix4D* pmat,
@@ -895,6 +907,14 @@ static TopoShape _getTopoShape(const App::DocumentObject* obj,
bool noElementMap,
const std::set<std::string> hiddens,
const App::DocumentObject* lastLink)
*/
static TopoShape _getTopoShape(const App::DocumentObject* obj,
ShapeOptions options,
const char* subname,
Base::Matrix4D* pmat,
App::DocumentObject** powner,
const std::set<std::string> hiddens,
const App::DocumentObject* lastLink)
{
TopoShape shape;
@@ -911,7 +931,7 @@ static TopoShape _getTopoShape(const App::DocumentObject* obj,
std::string _subname;
auto subelement = Data::findElementName(subname);
if (!needSubElement && subname) {
if (!options.testFlag(ShapeOption::NeedSubElement) && subname) {
// strip out element name if not needed
if (subelement && *subelement) {
_subname = std::string(subname, subelement);
@@ -924,7 +944,7 @@ static TopoShape _getTopoShape(const App::DocumentObject* obj,
};
if (canCache(obj) && PropertyShapeCache::getShape(obj, shape, subname)) {
if (noElementMap) {
if (options.testFlag(ShapeOption::NoElementMap)) {
shape.resetElementMap();
shape.Tag = 0;
if ( shape.Hasher ) {
@@ -948,7 +968,7 @@ static TopoShape _getTopoShape(const App::DocumentObject* obj,
hasher = owner->getDocument()->getStringHasher();
linked = owner->getLinkedObject(true, &linkMat, false);
if (pmat) {
if (resolveLink && obj != owner) {
if (options.testFlag(ShapeOption::ResolveLink) && obj != owner) {
*pmat = mat * linkMat;
}
else {
@@ -959,7 +979,7 @@ static TopoShape _getTopoShape(const App::DocumentObject* obj,
linked = owner;
}
if (powner) {
*powner = resolveLink ? linked : owner;
*powner = options.testFlag(ShapeOption::ResolveLink) ? linked : owner;
}
if (!shape.isNull()) {
@@ -976,7 +996,7 @@ static TopoShape _getTopoShape(const App::DocumentObject* obj,
PropertyShapeCache::setShape(obj, shape, subname);
}
}
if (noElementMap) {
if (options.testFlag(ShapeOption::NoElementMap)) {
shape.resetElementMap();
shape.Tag = 0;
if ( shape.Hasher ) {
@@ -1064,7 +1084,7 @@ static TopoShape _getTopoShape(const App::DocumentObject* obj,
}
// nothing can be done if there is sub-element references
if (needSubElement && subelement && *subelement) {
if (options.testFlag(ShapeOption::NeedSubElement) && subelement && *subelement) {
return shape;
}
@@ -1081,7 +1101,7 @@ static TopoShape _getTopoShape(const App::DocumentObject* obj,
}
}
if (!shape.isNull()) {
if (noElementMap) {
if (options.testFlag(ShapeOption::NoElementMap)) {
shape.resetElementMap();
shape.Tag = 0;
if ( shape.Hasher) {
@@ -1099,7 +1119,7 @@ static TopoShape _getTopoShape(const App::DocumentObject* obj,
&& (!link || (!link->_ChildCache.getSize() && link->getSubElements().size() <= 1))) {
// if there is a linked object, and there is no child cache (which is used
// for special handling of plain group), obtain shape from the linked object
shape = Feature::getTopoShape(linked, nullptr, false, nullptr, nullptr, false, false);
shape = Feature::getTopoShape(linked, ShapeOption::ResolveLink | ShapeOption::Transform);
if (shape.isNull()) {
return shape;
}
@@ -1125,7 +1145,7 @@ static TopoShape _getTopoShape(const App::DocumentObject* obj,
linked = link->getTrueLinkedObject(false, &baseMat);
if (linked && linked != owner) {
baseShape =
Feature::getTopoShape(linked, nullptr, false, nullptr, nullptr, false, false);
Feature::getTopoShape(linked, ShapeOption::ResolveLink | ShapeOption::Transform);
if (!link->getShowElementValue()) {
baseShape.reTagElementMap(owner->getID(),
owner->getDocument()->getStringHasher());
@@ -1181,14 +1201,13 @@ static TopoShape _getTopoShape(const App::DocumentObject* obj,
}
if (doGetShape) {
shape = _getTopoShape(owner,
ShapeOption::NeedSubElement,
sub.c_str(),
true,
0,
nullptr,
&subObj,
false,
false,
nextHiddens,
nextLink);
if (shape.isNull()) {
continue;
}
@@ -1233,7 +1252,7 @@ static TopoShape _getTopoShape(const App::DocumentObject* obj,
PropertyShapeCache::setShape(obj, shape, subname);
}
}
if (noElementMap) {
if (options.testFlag(ShapeOption::NoElementMap)) {
shape.resetElementMap();
shape.Tag = 0;
if ( shape.Hasher ) {
@@ -1243,17 +1262,15 @@ static TopoShape _getTopoShape(const App::DocumentObject* obj,
return shape;
}
TopoShape Feature::getTopoShape(const App::DocumentObject* obj,
const char* subname,
bool needSubElement,
Base::Matrix4D* pmat,
App::DocumentObject** powner,
bool resolveLink,
bool transform,
bool noElementMap)
TopoShape Feature::getTopoShape(const App::DocumentObject* obj,
ShapeOptions options,
const char* subname,
Base::Matrix4D* pmat,
App::DocumentObject** powner)
{
if (!obj || !obj->getNameInDocument()) {
return TopoShape();
return {};
}
const App::DocumentObject* lastLink = 0;
@@ -1268,7 +1285,7 @@ TopoShape Feature::getTopoShape(const App::DocumentObject* obj,
// transformation for easy shape caching, i.e. with `transform` set
// to false. So we manually apply the top level transform if asked.
if (needSubElement && (!pmat || *pmat == Base::Matrix4D())
if (options.testFlag(ShapeOption::NeedSubElement) && (!pmat || *pmat == Base::Matrix4D())
&& obj->isDerivedFrom<Part::Feature>()
&& !obj->hasExtension(App::LinkBaseExtension::getExtensionClassTypeId())) {
// Some OCC shape making is very sensitive to shape transformation. So
@@ -1276,10 +1293,10 @@ TopoShape Feature::getTopoShape(const App::DocumentObject* obj,
// processing here.
if (subname && *subname && Data::findElementName(subname) == subname) {
TopoShape ts = static_cast<const Part::Feature*>(obj)->Shape.getShape();
if (!transform) {
if (!options.testFlag(ShapeOption::Transform)) {
ts.setShape(ts.getShape().Located(TopLoc_Location()), false);
}
if (noElementMap) {
if (options.testFlag(ShapeOption::NoElementMap)) {
ts = ts.getSubShape(subname, true);
}
else {
@@ -1289,7 +1306,7 @@ TopoShape Feature::getTopoShape(const App::DocumentObject* obj,
if (powner) {
*powner = const_cast<App::DocumentObject*>(obj);
}
if (pmat && transform) {
if (pmat && options.testFlag(ShapeOption::Transform)) {
*pmat = static_cast<const Part::Feature*>(obj)->Placement.getValue().toMatrix();
}
return ts;
@@ -1299,52 +1316,56 @@ TopoShape Feature::getTopoShape(const App::DocumentObject* obj,
Base::Matrix4D mat;
auto shape = _getTopoShape(obj,
options,
subname,
needSubElement,
&mat,
powner,
resolveLink,
noElementMap,
hiddens,
lastLink);
if (needSubElement && shape.shapeType(true) == TopAbs_COMPOUND) {
if (shape.countSubShapes(TopAbs_SOLID) == 1)
shape = shape.getSubTopoShape(TopAbs_SOLID, 1);
else if (shape.countSubShapes(TopAbs_COMPSOLID) == 1)
shape = shape.getSubTopoShape(TopAbs_COMPSOLID, 1);
else if (shape.countSubShapes(TopAbs_FACE) == 1)
shape = shape.getSubTopoShape(TopAbs_FACE, 1);
else if (shape.countSubShapes(TopAbs_SHELL) == 1)
shape = shape.getSubTopoShape(TopAbs_SHELL, 1);
else if (shape.countSubShapes(TopAbs_EDGE) == 1)
shape = shape.getSubTopoShape(TopAbs_EDGE, 1);
else if (shape.countSubShapes(TopAbs_WIRE) == 1)
shape = shape.getSubTopoShape(TopAbs_WIRE, 1);
else if (shape.countSubShapes(TopAbs_VERTEX) == 1)
shape = shape.getSubTopoShape(TopAbs_VERTEX, 1);
if (options.testFlag(ShapeOption::NeedSubElement)
&& !options.testFlag(ShapeOption::DontSimplifyCompound)
&& shape.shapeType(true) == TopAbs_COMPOUND) {
shape = simplifyCompound(shape);
}
Base::Matrix4D topMat;
if (pmat || transform) {
// Obtain top level transformation
if (pmat) {
topMat = *pmat;
}
if (transform) {
obj->getSubObject(nullptr, nullptr, &topMat);
}
if (pmat) {
topMat = *pmat;
}
if (options.testFlag(ShapeOption::Transform)) {
obj->getSubObject(nullptr, nullptr, &topMat);
}
if ((pmat || options.testFlag(ShapeOption::Transform)) && !shape.isNull()) {
// Apply the top level transformation
if (!shape.isNull()) {
shape.transformShape(topMat, false, true);
}
if (pmat) {
*pmat = topMat * mat;
}
shape.transformShape(topMat, false, true);
}
if (pmat) {
*pmat = topMat * mat;
}
return shape;
}
TopoShape Feature::simplifyCompound(TopoShape compoundShape)
{
std::initializer_list<TopAbs_ShapeEnum> simplificationOrder = {
TopAbs_SOLID,
TopAbs_COMPSOLID,
TopAbs_FACE,
TopAbs_SHELL,
TopAbs_SHELL,
TopAbs_WIRE,
TopAbs_VERTEX};
auto foundSimplification =
std::ranges::find_if(simplificationOrder,
[&](TopAbs_ShapeEnum topType) {
return compoundShape.countSubShapes(topType) == 1;
});
if (foundSimplification != simplificationOrder.end()) {
return compoundShape.getSubTopoShape(*foundSimplification, 1);
}
return compoundShape;
}
App::DocumentObject *Feature::getShapeOwner(const App::DocumentObject *obj, const char *subname)
{
@@ -1698,7 +1719,12 @@ bool Feature::isElementMappingDisabled(App::PropertyContainer* container)
bool Feature::getCameraAlignmentDirection(Base::Vector3d& directionZ, Base::Vector3d &directionX, const char* subname) const
{
const auto topoShape = getTopoShape(this, subname, true);
const auto topoShape = getTopoShape(this,
ShapeOptions(
ShapeOption::NeedSubElement
| ShapeOption::ResolveLink
| ShapeOption::Transform),
subname);
if (topoShape.isNull()) {
return false;
+21 -7
View File
@@ -27,6 +27,7 @@
#include <App/GeoFeature.h>
#include <Mod/Material/App/PropertyMaterial.h>
#include <Mod/Part/PartGlobal.h>
#include <Base/Bitmask.h>
#include <TopoDS_Face.hxx>
@@ -44,6 +45,18 @@ struct HistoryItem;
namespace Part
{
enum class ShapeOption
{
NoFlag = 0,
NeedSubElement = 1,
ResolveLink = 2,
Transform = 4,
NoElementMap = 8,
DontSimplifyCompound = 16
};
using ShapeOptions = Base::Flags<ShapeOption>;
class PartFeaturePy;
/** Base class of all shape feature classes in FreeCAD
@@ -130,15 +143,15 @@ public:
* @param transform: if true, apply obj's transformation. Set to false
* if pmat already include obj's transformation matrix.
*/
static TopoDS_Shape getShape(const App::DocumentObject *obj,
const char *subname=nullptr, bool needSubElement=false, Base::Matrix4D *pmat=nullptr,
App::DocumentObject **owner=nullptr, bool resolveLink=true, bool transform=true);
static TopoDS_Shape getShape(const App::DocumentObject *obj, ShapeOptions options,
const char *subname=nullptr, Base::Matrix4D *pmat=nullptr,
App::DocumentObject **owner=nullptr);
static TopoShape getTopoShape(const App::DocumentObject *obj,
const char *subname=nullptr, bool needSubElement=false, Base::Matrix4D *pmat=nullptr,
App::DocumentObject **owner=nullptr, bool resolveLink=true, bool transform=true,
bool noElementMap=false);
static TopoShape getTopoShape(const App::DocumentObject* obj, ShapeOptions options,
const char* subname=nullptr, Base::Matrix4D* pmat=nullptr,
App::DocumentObject**owner=nullptr);
static TopoShape simplifyCompound(TopoShape compoundShape);
static void clearShapeCache();
static App::DocumentObject *getShapeOwner(const App::DocumentObject *obj, const char *subname=nullptr);
@@ -282,6 +295,7 @@ bool checkIntersection(const TopoDS_Shape& first, const TopoDS_Shape& second,
} //namespace Part
ENABLE_BITMASK_OPERATORS(Part::ShapeOption)
#endif // PART_FEATURE_H
+12 -8
View File
@@ -90,7 +90,7 @@ App::DocumentObjectExecReturn* RuledSurface::getShape(const App::PropertyLinkSub
TopoDS_Shape& shape) const
{
App::DocumentObject* obj = link.getValue();
const Part::TopoShape part = Part::Feature::getTopoShape(obj);
const Part::TopoShape part = Part::Feature::getTopoShape(obj, ShapeOption::ResolveLink | ShapeOption::Transform);
if (part.isNull()) {
return new App::DocumentObjectExecReturn("No shape linked.");
}
@@ -127,7 +127,7 @@ App::DocumentObjectExecReturn* RuledSurface::execute()
std::array<App::PropertyLinkSub*, 2> links = {&Curve1, &Curve2};
for (auto link : links) {
App::DocumentObject* obj = link->getValue();
const Part::TopoShape part = Part::Feature::getTopoShape(obj);
const Part::TopoShape part = Part::Feature::getTopoShape(obj, ShapeOption::ResolveLink | ShapeOption::Transform);
if (part.isNull()) {
return new App::DocumentObjectExecReturn("No shape linked.");
}
@@ -140,7 +140,11 @@ App::DocumentObjectExecReturn* RuledSurface::execute()
return new App::DocumentObjectExecReturn("Not exactly one sub-shape linked.");
}
else {
shapes.push_back(getTopoShape(link->getValue(), subs.front().c_str(), true));
shapes.push_back(getTopoShape(link->getValue(),
ShapeOption::NeedSubElement
| ShapeOption::ResolveLink
| ShapeOption::Transform,
subs.front().c_str()));
}
if (shapes.back().isNull()) {
return new App::DocumentObjectExecReturn("Invalid link.");
@@ -216,7 +220,7 @@ App::DocumentObjectExecReturn* Loft::execute()
try {
std::vector<TopoShape> shapes;
for (auto& obj : Sections.getValues()) {
shapes.emplace_back(getTopoShape(obj));
shapes.emplace_back(getTopoShape(obj, ShapeOption::ResolveLink | ShapeOption::Transform));
if (shapes.back().isNull()) {
return new App::DocumentObjectExecReturn("Invalid section link");
}
@@ -300,7 +304,7 @@ App::DocumentObjectExecReturn* Sweep::execute()
if (!Spine.getValue()) {
return new App::DocumentObjectExecReturn("No spine");
}
TopoShape spine = getTopoShape(Spine.getValue());
TopoShape spine = getTopoShape(Spine.getValue(), ShapeOption::ResolveLink | ShapeOption::Transform);
const auto& subs = Spine.getSubValues();
if (spine.isNull()) {
return new App::DocumentObjectExecReturn("Invalid spine");
@@ -319,7 +323,7 @@ App::DocumentObjectExecReturn* Sweep::execute()
std::vector<TopoShape> shapes;
shapes.push_back(spine);
for (auto& obj : Sections.getValues()) {
shapes.emplace_back(getTopoShape(obj));
shapes.emplace_back(getTopoShape(obj, ShapeOption::ResolveLink | ShapeOption::Transform));
if (shapes.back().isNull()) {
return new App::DocumentObjectExecReturn("Invalid section link");
}
@@ -415,7 +419,7 @@ void Thickness::handleChangedPropertyType(Base::XMLReader& reader,
App::DocumentObjectExecReturn* Thickness::execute()
{
std::vector<TopoShape> shapes;
auto base = getTopoShape(Faces.getValue());
auto base = getTopoShape(Faces.getValue(), ShapeOption::ResolveLink | ShapeOption::Transform);
if (base.isNull()) {
return new App::DocumentObjectExecReturn("Invalid source shape");
}
@@ -485,7 +489,7 @@ Reverse::Reverse()
App::DocumentObjectExecReturn* Reverse::execute()
{
App::DocumentObject* source = Source.getValue<App::DocumentObject*>();
Part::TopoShape topoShape = Part::Feature::getTopoShape(source);
Part::TopoShape topoShape = Part::Feature::getTopoShape(source, ShapeOption::ResolveLink | ShapeOption::Transform);
if (topoShape.isNull()) {
return new App::DocumentObjectExecReturn("No part object linked.");
}
+30 -17
View File
@@ -263,7 +263,7 @@ std::vector<Part::TopoShape> getShapesFromSelection()
std::vector<App::DocumentObject*> objs = Gui::Selection().getObjectsOfType(App::DocumentObject::getClassTypeId());
std::vector <Part::TopoShape> shapes;
for (auto it : objs) {
Part::TopoShape shp = Part::Feature::getTopoShape(it);
Part::TopoShape shp = Part::Feature::getTopoShape(it, Part::ShapeOption::ResolveLink | Part::ShapeOption::Transform);
if (!shp.isNull()){
shapes.push_back(shp);
}
@@ -279,8 +279,7 @@ bool hasShapesInSelection()
bool hasShapes = false;
std::vector<App::DocumentObject*> docobjs = Gui::Selection().getObjectsOfType(App::DocumentObject::getClassTypeId());
for (auto it : docobjs) {
// Only check for the existence of a shape but don't perform a transformation
if (!Part::Feature::getTopoShape(it, nullptr, false, nullptr, nullptr, true, false, false).isNull()) {
if (!Part::Feature::getTopoShape(it, Part::ShapeOption::ResolveLink).isNull()) {
hasShapes = true;
break;
}
@@ -321,7 +320,7 @@ void CmdPartCut::activated(int iMsg)
std::vector<std::string> names;
for (const auto & it : Sel) {
const App::DocumentObject* obj = it.getObject();
const TopoDS_Shape& shape = Part::Feature::getShape(obj);
const TopoDS_Shape& shape = Part::Feature::getShape(obj, Part::ShapeOption::ResolveLink | Part::ShapeOption::Transform);
if (!PartGui::checkForSolids(shape) && !askUser) {
int ret = QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Non-solids selected"),
QObject::tr("The use of non-solids for boolean operations may lead to unexpected results.\n"
@@ -380,7 +379,7 @@ void CmdPartCommon::activated(int iMsg)
std::vector<std::string> names;
for (const auto & it : Sel) {
const App::DocumentObject* obj = it.getObject();
const TopoDS_Shape& shape = Part::Feature::getShape(obj);
const TopoDS_Shape& shape = Part::Feature::getShape(obj, Part::ShapeOption::ResolveLink | Part::ShapeOption::Transform);
if (!PartGui::checkForSolids(shape) && !askUser) {
int ret = QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Non-solids selected"),
QObject::tr("The use of non-solids for boolean operations may lead to unexpected results.\n"
@@ -434,7 +433,7 @@ void CmdPartFuse::activated(int iMsg)
if (Sel.size() == 1){
numShapes = 1; //to be updated later in code
Gui::SelectionObject selobj = Sel[0];
TopoDS_Shape sh = Part::Feature::getShape(selobj.getObject());
TopoDS_Shape sh = Part::Feature::getShape(selobj.getObject(), Part::ShapeOption::ResolveLink | Part::ShapeOption::Transform);
while (numShapes==1 && sh.ShapeType() == TopAbs_COMPOUND) {
numShapes = 0;
TopoDS_Iterator it(sh);
@@ -458,7 +457,7 @@ void CmdPartFuse::activated(int iMsg)
std::vector<std::string> names;
for (const auto & it : Sel) {
const App::DocumentObject* obj = it.getObject();
const TopoDS_Shape& shape = Part::Feature::getShape(obj);
const TopoDS_Shape& shape = Part::Feature::getShape(obj, Part::ShapeOption::ResolveLink | Part::ShapeOption::Transform);
if (!PartGui::checkForSolids(shape) && !askUser) {
int ret = QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Non-solids selected"),
QObject::tr("The use of non-solids for boolean operations may lead to unexpected results.\n"
@@ -1102,7 +1101,7 @@ void CmdPartMakeSolid::activated(int iMsg)
(App::DocumentObject::getClassTypeId(), nullptr, Gui::ResolveMode::FollowLink);
runCommand(Doc, "import Part");
for (auto it : objs) {
const TopoDS_Shape& shape = Part::Feature::getShape(it);
const TopoDS_Shape& shape = Part::Feature::getShape(it, Part::ShapeOption::ResolveLink | Part::ShapeOption::Transform);
if (!shape.IsNull()) {
TopAbs_ShapeEnum type = shape.ShapeType();
QString str;
@@ -1180,7 +1179,7 @@ void CmdPartReverseShape::activated(int iMsg)
(App::DocumentObject::getClassTypeId());
openCommand(QT_TRANSLATE_NOOP("Command", "Reverse"));
for (auto it : objs) {
const TopoDS_Shape& shape = Part::Feature::getShape(it);
const TopoDS_Shape& shape = Part::Feature::getShape(it, Part::ShapeOption::ResolveLink | Part::ShapeOption::Transform);
if (!shape.IsNull()) {
std::string name = it->getNameInDocument();
name += "_rev";
@@ -1619,7 +1618,7 @@ void CmdPartOffset::activated(int iMsg)
std::vector<App::DocumentObject*> docobjs = Gui::Selection().getObjectsOfType(App::DocumentObject::getClassTypeId());
std::vector<App::DocumentObject*> shapes;
for (auto it : docobjs) {
if (!Part::Feature::getTopoShape(it).isNull()) {
if (!Part::Feature::getTopoShape(it, Part::ShapeOption::ResolveLink | Part::ShapeOption::Transform).isNull()) {
shapes.push_back(it);
}
}
@@ -1677,7 +1676,7 @@ void CmdPartOffset2D::activated(int iMsg)
std::vector<App::DocumentObject*> shapes;
for (auto it : docobjs) {
if (!Part::Feature::getTopoShape(it).isNull()) {
if (!Part::Feature::getTopoShape(it, Part::ShapeOption::ResolveLink | Part::ShapeOption::Transform).isNull()) {
shapes.push_back(it);
}
}
@@ -1831,7 +1830,7 @@ void CmdPartThickness::activated(int iMsg)
selection = selobjs[0].getAsPropertyLinkSubString();
const std::vector<std::string>& subnames = selobjs[0].getSubNames();
obj = selobjs[0].getObject();
topoShape = Part::Feature::getTopoShape(obj);
topoShape = Part::Feature::getTopoShape(obj, Part::ShapeOption::ResolveLink | Part::ShapeOption::Transform);
if (!topoShape.isNull()) {
for (std::vector<std::string>::const_iterator it = subnames.begin(); it != subnames.end(); ++it) {
subShapes.emplace_back(topoShape.getSubShape(subnames[0].c_str()));
@@ -1966,17 +1965,26 @@ void CmdPartRuledSurface::activated(int iMsg)
docobj1 = selobjs[0].getObject();
obj1 = docobj1->getNameInDocument();
obj2 = obj1; //changed later if 2 objects were selected
const Part::TopoShape& shape1 = Part::Feature::getTopoShape(docobj1);
const Part::TopoShape& shape1 = Part::Feature::getTopoShape(docobj1, Part::ShapeOption::ResolveLink | Part::ShapeOption::Transform);
if (shape1.isNull()) {
ok = false;
}
if (ok && subnames1.size() <= 2) {
if (!subnames1.empty()) {
curve1 = Part::Feature::getTopoShape(docobj1, subnames1[0].c_str(), true /*need element*/).getShape();
curve2 = Part::Feature::getTopoShape(docobj1,
Part::ShapeOption::NeedSubElement
| Part::ShapeOption::ResolveLink
| Part::ShapeOption::Transform,
subnames1[0].c_str()).getShape();
link1 = subnames1[0];
}
if (subnames1.size() == 2) {
curve2 = Part::Feature::getTopoShape(docobj1, subnames1[1].c_str(), true /*need element*/).getShape();
curve2 = Part::Feature::getTopoShape(docobj1,
Part::ShapeOption::NeedSubElement
| Part::ShapeOption::ResolveLink
| Part::ShapeOption::Transform,
subnames1[1].c_str()).getShape();
link2 = subnames1[1];
}
if (subnames1.empty()) {
@@ -1991,12 +1999,17 @@ void CmdPartRuledSurface::activated(int iMsg)
docobj2 = selobjs[1].getObject();
obj2 = docobj2->getNameInDocument();
const Part::TopoShape& shape2 = Part::Feature::getTopoShape(docobj2);
const Part::TopoShape& shape2 = Part::Feature::getTopoShape(docobj2, Part::ShapeOption::ResolveLink | Part::ShapeOption::Transform);
if (shape2.isNull()) {
ok = false;
}
if (ok && subnames2.size() == 1) {
curve2 = Part::Feature::getTopoShape(docobj2, subnames2[0].c_str(), true /*need element*/).getShape();
curve2 = Part::Feature::getTopoShape(docobj2,
Part::ShapeOption::NeedSubElement
| Part::ShapeOption::ResolveLink
| Part::ShapeOption::Transform,
subnames2[0].c_str()).getShape();
link2 = subnames2[0];
} else {
if (subnames2.empty()) {
+1 -1
View File
@@ -215,7 +215,7 @@ void CrossSections::apply()
getObjectsOfType(App::DocumentObject::getClassTypeId());
std::vector<App::DocumentObject*> obj;
for (auto it : docobjs) {
if (!Part::Feature::getTopoShape(it).isNull()) {
if (!Part::Feature::getTopoShape(it, Part::ShapeOption::ResolveLink | Part::ShapeOption::Transform).isNull()) {
obj.push_back(it);
}
}
+10 -5
View File
@@ -77,12 +77,17 @@ public:
std::string element(sSubName);
if (element.substr(0,4) != "Edge")
return false;
Part::TopoShape part = Part::Feature::getTopoShape(pObj);
Part::TopoShape part = Part::Feature::getTopoShape(pObj, Part::ShapeOption::ResolveLink | Part::ShapeOption::Transform);
if (part.isNull()) {
return false;
}
try {
TopoDS_Shape sub = Part::Feature::getTopoShape(pObj, sSubName, true /*need element*/).getShape();
TopoDS_Shape sub = Part::Feature::getTopoShape(pObj,
Part::ShapeOption::NeedSubElement
| Part::ShapeOption::ResolveLink
| Part::ShapeOption::Transform,
sSubName).getShape();
if (!sub.IsNull() && sub.ShapeType() == TopAbs_EDGE) {
const TopoDS_Edge& edge = TopoDS::Edge(sub);
BRepAdaptor_Curve adapt(edge);
@@ -350,7 +355,7 @@ void DlgExtrusion::autoSolid()
{
try{
App::DocumentObject* dobj = &this->getShapeToExtrude();
Part::TopoShape shape = Part::Feature::getTopoShape(dobj);
Part::TopoShape shape = Part::Feature::getTopoShape(dobj, Part::ShapeOption::ResolveLink | Part::ShapeOption::Transform);
if (shape.isNull()) {
return;
}
@@ -388,7 +393,7 @@ void DlgExtrusion::findShapes()
std::vector<App::DocumentObject*> objs = activeDoc->getObjectsOfType<App::DocumentObject>();
for (auto obj : objs) {
Part::TopoShape topoShape = Part::Feature::getTopoShape(obj);
Part::TopoShape topoShape = Part::Feature::getTopoShape(obj, Part::ShapeOption::ResolveLink | Part::ShapeOption::Transform);
if (topoShape.isNull()) {
continue;
}
@@ -467,7 +472,7 @@ void DlgExtrusion::apply()
for (App::DocumentObject* sourceObj: objects) {
assert(sourceObj);
if (Part::Feature::getTopoShape(sourceObj).isNull()){
if (Part::Feature::getTopoShape(sourceObj, Part::ShapeOption::ResolveLink | Part::ShapeOption::Transform).isNull()){
FC_ERR("Object " << sourceObj->getFullName()
<< " is not Part object (has no OCC shape). Can't extrude it.");
continue;
+1 -1
View File
@@ -626,7 +626,7 @@ void DlgFilletEdges::setupFillet(const std::vector<App::DocumentObject*>& objs)
std::vector<std::string> subElements;
QStandardItemModel *model = qobject_cast<QStandardItemModel*>(ui->treeView->model());
bool block = model->blockSignals(true); // do not call toggleCheckState
auto baseShape = Part::Feature::getTopoShape(base);
auto baseShape = Part::Feature::getTopoShape(base, Part::ShapeOption::ResolveLink | Part::ShapeOption::Transform);
std::set<Part::FilletElement> elements;
for(size_t i=0;i<e.size();++i) {
auto &sub = subs[i];
+1 -1
View File
@@ -1436,7 +1436,7 @@ void DlgProjectOnSurface::addWire(const Gui::SelectionChanges& msg)
return;
}
Part::TopoShape part = Part::Feature::getTopoShape(selObj.getObject());
Part::TopoShape part = Part::Feature::getTopoShape(selObj.getObject(), Part::ShapeOption::ResolveLink | Part::ShapeOption::Transform);
if (part.isNull()) {
return;
}
+3 -3
View File
@@ -74,7 +74,7 @@ public:
std::string element(sSubName);
if (element.substr(0,4) != "Edge")
return false;
Part::TopoShape part = Part::Feature::getTopoShape(pObj);
Part::TopoShape part = Part::Feature::getTopoShape(pObj, Part::ShapeOption::ResolveLink | Part::ShapeOption::Transform);
if (part.isNull()) {
return false;
}
@@ -347,7 +347,7 @@ void DlgRevolution::findShapes()
std::vector<App::DocumentObject*> objs = activeDoc->getObjectsOfType<App::DocumentObject>();
for (auto obj : objs) {
Part::TopoShape topoShape = Part::Feature::getTopoShape(obj);
Part::TopoShape topoShape = Part::Feature::getTopoShape(obj, Part::ShapeOption::ResolveLink | Part::ShapeOption::Transform);
if (topoShape.isNull()) {
continue;
}
@@ -542,7 +542,7 @@ void DlgRevolution::autoSolid()
{
try{
App::DocumentObject &dobj = this->getShapeToRevolve();
Part::TopoShape topoShape = Part::Feature::getTopoShape(&dobj);
Part::TopoShape topoShape = Part::Feature::getTopoShape(&dobj, Part::ShapeOption::ResolveLink | Part::ShapeOption::Transform);
if (topoShape.isNull()) {
return;
} else {
+2 -2
View File
@@ -123,7 +123,7 @@ void DlgScale::findShapes()
std::vector<App::DocumentObject*> objs = activeDoc->getObjectsOfType<App::DocumentObject>();
for (auto obj : objs) {
Part::TopoShape topoShape = Part::Feature::getTopoShape(obj);
Part::TopoShape topoShape = Part::Feature::getTopoShape(obj, Part::ShapeOption::ResolveLink | Part::ShapeOption::Transform);
if (topoShape.isNull()) {
continue;
}
@@ -216,7 +216,7 @@ void DlgScale::apply()
for (App::DocumentObject* sourceObj: objects) {
assert(sourceObj);
if (Part::Feature::getTopoShape(sourceObj).isNull()){
if (Part::Feature::getTopoShape(sourceObj, Part::ShapeOption::ResolveLink | Part::ShapeOption::Transform).isNull()){
FC_ERR("Object " << sourceObj->getFullName()
<< " is not Part object (has no OCC shape). Can't scale it.");
continue;
+9 -3
View File
@@ -100,7 +100,12 @@ public:
bool isEdge = false; //will be true if user selected edge subobject or if object only has 1 edge
TopoDS_Shape shape;
if (subString.length() > 0){
shape = Part::Feature::getTopoShape(pObj, subString.c_str(), true).getShape();
shape = Part::Feature::getTopoShape(pObj,
Part::ShapeOption::NeedSubElement
| Part::ShapeOption::ResolveLink
| Part::ShapeOption::Transform,
sSubName).getShape();
if (strstr(subString.c_str(), "Face")){
isFace = true; //was face subobject, e.g. Face3
} else {
@@ -109,7 +114,8 @@ public:
}
}
} else {
shape = Part::Feature::getShape(pObj); //no subobjects were selected, so this is entire shape of feature
//no subobjects were selected, so this is entire shape of feature
shape = Part::Feature::getShape(pObj, Part::ShapeOption::ResolveLink | Part::ShapeOption::Transform);
}
// if there is only 1 face or 1 edge, then we don't need to force the user to select that face or edge
@@ -250,7 +256,7 @@ void Mirroring::findShapes()
std::vector<App::DocumentObject*> objs = activeDoc->getObjectsOfType<App::DocumentObject>();
for (auto obj : objs) {
Part::TopoShape shape = Part::Feature::getTopoShape(obj);
Part::TopoShape shape = Part::Feature::getTopoShape(obj, Part::ShapeOption::ResolveLink | Part::ShapeOption::Transform);
if (!shape.isNull()) {
QString label = QString::fromUtf8(obj->Label.getValue());
QString name = QString::fromLatin1(obj->getNameInDocument());
+7 -1
View File
@@ -443,7 +443,13 @@ void TaskCheckGeometryResults::goCheck()
baseStream << " (" << label.c_str() << ")";
}
TopoDS_Shape shape = Part::Feature::getShape(sel.pObject,sel.SubName,true);
TopoDS_Shape shape = Part::Feature::getShape(
sel.pObject,
Part::ShapeOption::NeedSubElement
| Part::ShapeOption::ResolveLink
| Part::ShapeOption::Transform,
sel.SubName);
if (shape.IsNull()) {
ResultEntry *entry = new ResultEntry();
entry->parent = theRoot;
+1 -1
View File
@@ -99,7 +99,7 @@ void LoftWidget::findShapes()
std::vector<App::DocumentObject*> objs = activeDoc->getObjectsOfType<App::DocumentObject>();
for (auto obj : objs) {
Part::TopoShape topoShape = Part::Feature::getTopoShape(obj);
Part::TopoShape topoShape = Part::Feature::getTopoShape(obj, Part::ShapeOption::ResolveLink | Part::ShapeOption::Transform);
if (topoShape.isNull()) {
continue;
}
+9 -5
View File
@@ -80,7 +80,7 @@ public:
if (Base::Tools::isNullOrEmpty(sSubName)) {
// If selecting again the same edge the passed sub-element is empty. If the whole
// shape is an edge or wire we can use it completely.
Part::TopoShape topoShape = Part::Feature::getTopoShape(pObj);
Part::TopoShape topoShape = Part::Feature::getTopoShape(pObj, Part::ShapeOption::ResolveLink | Part::ShapeOption::Transform);
if (topoShape.isNull()) {
return false;
}
@@ -162,7 +162,7 @@ void SweepWidget::findShapes()
std::vector<App::DocumentObject*> objs = activeDoc->getObjectsOfType<App::DocumentObject>();
for (auto obj : objs) {
Part::TopoShape topoShape = Part::Feature::getTopoShape(obj);
Part::TopoShape topoShape = Part::Feature::getTopoShape(obj, Part::ShapeOption::ResolveLink | Part::ShapeOption::Transform);
if (topoShape.isNull()) {
continue;
}
@@ -225,7 +225,7 @@ bool SweepWidget::isPathValid(const Gui::SelectionObject& sel) const
const std::vector<std::string>& sub = sel.getSubNames();
TopoDS_Shape pathShape;
const Part::TopoShape& shape = Part::Feature::getTopoShape(path);
const Part::TopoShape& shape = Part::Feature::getTopoShape(path, Part::ShapeOption::ResolveLink | Part::ShapeOption::Transform);
if (shape.isNull()){
return false;
}
@@ -295,10 +295,14 @@ bool SweepWidget::accept()
docobj = selobjs[0].getObject();
spineObject = selobjs[0].getFeatName();
spineLabel = docobj->Label.getValue();
topoShape = Part::Feature::getTopoShape(docobj);
topoShape = Part::Feature::getTopoShape(docobj, Part::ShapeOption::ResolveLink | Part::ShapeOption::Transform);
if (!topoShape.isNull()) {
for (std::vector<std::string>::const_iterator it = subnames.begin(); it != subnames.end(); ++it) {
subShapes.push_back(Part::Feature::getTopoShape(docobj, subnames[0].c_str(), true /*need element*/));
subShapes.push_back(Part::Feature::getTopoShape(docobj,
Part::ShapeOption::NeedSubElement
| Part::ShapeOption::ResolveLink
| Part::ShapeOption::Transform,
subnames[0].c_str()));
}
for (const auto & it : subShapes) {
TopoDS_Shape dsShape = it.getShape();
+2 -2
View File
@@ -564,7 +564,7 @@ std::vector<Base::Vector3d> ViewProviderPartExt::getModelPoints(const SoPickedPo
try {
std::vector<Base::Vector3d> pts;
std::string element = this->getElement(pp->getDetail());
const auto &shape = Part::Feature::getTopoShape(getObject());
const auto &shape = Part::Feature::getTopoShape(getObject(), Part::ShapeOption::ResolveLink | Part::ShapeOption::Transform);
TopoDS_Shape subShape = shape.getSubShape(element.c_str());
@@ -943,7 +943,7 @@ void ViewProviderPartExt::updateVisual()
haction.apply(this->lineset);
haction.apply(this->nodeset);
TopoDS_Shape cShape = Part::Feature::getShape(getObject());
TopoDS_Shape cShape = Part::Feature::getShape(getObject(), Part::ShapeOption::ResolveLink | Part::ShapeOption::Transform);
if (cShape.IsNull()) {
coords ->point .setNum(0);
norm ->vector .setNum(0);
+1 -1
View File
@@ -69,7 +69,7 @@ App::DocumentObjectExecReturn* FeatureBase::execute()
QT_TRANSLATE_NOOP("Exception", "BaseFeature must be a Part::Feature"));
}
auto shape = Part::Feature::getTopoShape(BaseFeature.getValue());
auto shape = Part::Feature::getTopoShape(BaseFeature.getValue(), Part::ShapeOption::ResolveLink | Part::ShapeOption::Transform);
if (!shape.countSubShapes(TopAbs_SOLID)) {
shape = shape.makeElementSolid();
}
+1 -1
View File
@@ -107,7 +107,7 @@ App::DocumentObjectExecReturn *Boolean::execute()
std::vector<TopoShape> shapes;
shapes.push_back(baseTopShape);
for(auto it=tools.begin(); it<tools.end(); ++it) {
auto shape = getTopoShape(*it);
auto shape = getTopoShape(*it, Part::ShapeOption::ResolveLink | Part::ShapeOption::Transform);
if (shape.isNull())
return new App::DocumentObjectExecReturn(QT_TRANSLATE_NOOP("Exception","Tool shape is null"));
shapes.push_back(shape);
+6 -1
View File
@@ -514,7 +514,12 @@ App::DocumentObjectExecReturn* FeatureExtrude::buildExtrusion(ExtrudeOptions opt
if (sub.empty() && subs.size() > 1) {
continue;
}
TopoShape shape = Part::Feature::getTopoShape(obj, sub.c_str(), true);
TopoShape shape = Part::Feature::getTopoShape(obj,
Part::ShapeOption::NeedSubElement
| Part::ShapeOption::ResolveLink
| Part::ShapeOption::Transform,
sub.c_str());
if (shape.isNull()) {
FC_ERR(getFullName()
<< ": failed to get profile shape " << obj->getFullName() << "." << sub);
+5 -1
View File
@@ -1855,7 +1855,11 @@ static gp_Pnt toPnt(gp_Vec dir)
App::DocumentObjectExecReturn* Hole::execute()
{
TopoShape profileshape = getProfileShape();
TopoShape profileshape =
getProfileShape( Part::ShapeOption::NeedSubElement
| Part::ShapeOption::ResolveLink
| Part::ShapeOption::Transform
| Part::ShapeOption::DontSimplifyCompound);
// Find the base shape
TopoShape base;
+6 -2
View File
@@ -77,13 +77,17 @@ Loft::getSectionShape(const char *name,
auto subName = subs.empty() ? "" : subs.front();
auto useEntireSketch = obj->isDerivedFrom<Part::Part2DObject>() && subName.find("Vertex") != 0;
if (subs.empty() || std::ranges::find(subs, std::string()) != subs.end() || useEntireSketch ) {
shapes.push_back(Part::Feature::getTopoShape(obj));
shapes.push_back(Part::Feature::getTopoShape(obj, Part::ShapeOption::ResolveLink | Part::ShapeOption::Transform));
if (shapes.back().isNull())
FC_THROWM(Part::NullShapeException, "Failed to get shape of "
<< name << " " << App::SubObjectT(obj, "").getSubObjectFullName(obj->getDocument()->getName()));
} else {
for (const auto &sub : subs) {
shapes.push_back(Part::Feature::getTopoShape(obj, sub.c_str(), /*needSubElement*/true));
shapes.push_back(Part::Feature::getTopoShape(obj,
Part::ShapeOption::NeedSubElement
| Part::ShapeOption::ResolveLink
| Part::ShapeOption::Transform,
sub.c_str()));
if (shapes.back().isNull())
FC_THROWM(Part::NullShapeException, "Failed to get shape of " << name << " "
<< App::SubObjectT(obj, sub.c_str()).getSubObjectFullName(obj->getDocument()->getName()));
+44 -15
View File
@@ -184,13 +184,18 @@ TopoShape ProfileBased::getTopoShapeVerifiedFace(bool silent,
TopoShape shape;
if (AllowMultiFace.getValue()) {
if (subs.empty()) {
shape = Part::Feature::getTopoShape(obj);
shape = Part::Feature::getTopoShape(obj, Part::ShapeOption::ResolveLink | Part::ShapeOption::Transform);
}
else {
std::vector<TopoShape> shapes;
for (auto& sub : subs) {
auto subshape =
Part::Feature::getTopoShape(obj, sub.c_str(), /*needSubElement*/ true);
auto subshape = Part::Feature::getTopoShape(obj,
Part::ShapeOption::NeedSubElement
| Part::ShapeOption::ResolveLink
| Part::ShapeOption::Transform,
sub.c_str());
if (subshape.isNull()) {
FC_THROWM(Base::CADKernelError,
"Sub shape not found: " << obj->getFullName() << "." << sub);
@@ -207,7 +212,11 @@ TopoShape ProfileBased::getTopoShapeVerifiedFace(bool silent,
sub = subs[0];
}
}
shape = Part::Feature::getTopoShape(obj, sub.c_str(), !sub.empty());
shape = Part::Feature::getTopoShape(obj,
(sub.empty() ? Part::ShapeOption::NoFlag : Part::ShapeOption::NeedSubElement)
| Part::ShapeOption::ResolveLink
| Part::ShapeOption::Transform,
sub.c_str());
}
if (shape.isNull()) {
if (silent) {
@@ -404,19 +413,20 @@ TopoDS_Shape ProfileBased::getVerifiedFace(bool silent) const {
return TopoDS_Face();
}
TopoShape ProfileBased::getProfileShape() const
TopoShape ProfileBased::getProfileShape(Part::ShapeOptions subShapeOptions) const
{
TopoShape shape;
const auto& subs = Profile.getSubValues();
auto profile = Profile.getValue();
if (subs.empty()) {
shape = Part::Feature::getTopoShape(profile);
shape = Part::Feature::getTopoShape(profile, Part::ShapeOption::ResolveLink | Part::ShapeOption::Transform);
}
else {
std::vector<TopoShape> shapes;
for (auto& sub : subs) {
shapes.push_back(
Part::Feature::getTopoShape(profile, sub.c_str(), /* needSubElement */ true));
shapes.push_back(Part::Feature::getTopoShape(profile,
subShapeOptions,
sub.c_str()));
}
shape = TopoShape(shape.Tag).makeElementCompound(shapes);
}
@@ -567,9 +577,11 @@ TopoShape ProfileBased::getTopoShapeSupportFace() const
const auto& Support = sketch->AttachmentSupport;
App::DocumentObject* ref = Support.getValue();
shape = Part::Feature::getTopoShape(
ref,
Support.getSubValues().size() ? Support.getSubValues()[0].c_str() : "",
true);
ref,
Part::ShapeOption::NeedSubElement
| Part::ShapeOption::ResolveLink
| Part::ShapeOption::Transform,
Support.getSubValues().empty() ? "" : Support.getSubValues()[0].c_str());
}
if (!shape.isNull()) {
if (shape.shapeType(true) != TopAbs_FACE) {
@@ -663,7 +675,13 @@ void ProfileBased::getUpToFaceFromLinkSub(TopoShape& upToFace, const App::Proper
}
const auto& subs = refFace.getSubValues();
upToFace = Part::Feature::getTopoShape(ref, subs.size() ? subs[0].c_str() : nullptr, true);
upToFace = Part::Feature::getTopoShape(
ref,
Part::ShapeOption::NeedSubElement
| Part::ShapeOption::ResolveLink
| Part::ShapeOption::Transform,
subs.empty() ? nullptr : subs[0].c_str());
if (!upToFace.hasSubShape(TopAbs_FACE)) {
throw Base::ValueError("SketchBased: Up to face: Failed to extract face");
}
@@ -687,7 +705,12 @@ int ProfileBased::getUpToShapeFromLinkSubList(TopoShape& upToShape, const App::P
auto subStrings = subSet.second;
if (subStrings.empty() || subStrings[0].empty()) {
TopoShape baseShape = Part::Feature::getTopoShape(ref, nullptr, true);
TopoShape baseShape = Part::Feature::getTopoShape(ref,
Part::ShapeOption::NeedSubElement
| Part::ShapeOption::ResolveLink
| Part::ShapeOption::Transform);
for (auto face : baseShape.getSubTopoShapes(TopAbs_FACE)){
faceList.push_back(face);
ret ++;
@@ -695,7 +718,13 @@ int ProfileBased::getUpToShapeFromLinkSubList(TopoShape& upToShape, const App::P
}
else {
for (auto &subString : subStrings){
auto shape = Part::Feature::getTopoShape(ref, subString.c_str(), true);
auto shape = Part::Feature::getShape(
ref,
Part::ShapeOption::NeedSubElement
| Part::ShapeOption::ResolveLink
| Part::ShapeOption::Transform,
subString.c_str());
TopoShape face = shape;
face = face.makeElementFace();
if (face.isNull()) {
@@ -1419,7 +1448,7 @@ Base::Vector3d ProfileBased::getProfileNormal() const {
if (shape.hasSubShape(TopAbs_EDGE)) {
// Find the first planar face that contains the edge, and return the plane normal
TopoShape objShape = Part::Feature::getTopoShape(obj);
TopoShape objShape = Part::Feature::getTopoShape(obj, Part::ShapeOption::ResolveLink | Part::ShapeOption::Transform);
for (int idx : objShape.findAncestors(shape.getSubShape(TopAbs_EDGE, 1), TopAbs_FACE)) {
if (objShape.getSubTopoShape(TopAbs_FACE, idx).findPlane(pln)) {
gp_Dir dir = pln.Axis().Direction();
+5 -1
View File
@@ -131,7 +131,11 @@ public:
virtual Base::Vector3d getProfileNormal() const;
TopoShape getProfileShape() const;
// Use Part::ShapeOptions enum to pass flags
TopoShape getProfileShape(Part::ShapeOptions subShapeOptions =
Part::ShapeOption::NeedSubElement
| Part::ShapeOption::ResolveLink
| Part::ShapeOption::Transform) const;
/// retrieves the number of axes in the linked sketch (defined as construction lines)
int getSketchAxisCount() const;
+5 -1
View File
@@ -670,7 +670,11 @@ void SubShapeBinder::update(SubShapeBinder::UpdateOption options) {
for (const auto& sub : subs) {
++subidx;
try {
auto shape = Part::Feature::getTopoShape(obj, sub.c_str(), true);
auto shape = Part::Feature::getTopoShape(obj,
Part::ShapeOption::NeedSubElement
| Part::ShapeOption::ResolveLink
| Part::ShapeOption::Transform,
sub.c_str());
if (!shape.isNull()) {
shapes.push_back(shape);
shapeOwners.emplace_back(sidx, subidx);
@@ -151,7 +151,8 @@ void TaskDressUpParameters::addAllEdges(QListWidget* widget)
if (!base) {
return;
}
int count = Part::Feature::getTopoShape(base).countSubShapes(TopAbs_EDGE);
int count = Part::Feature::getTopoShape(base, Part::ShapeOption::ResolveLink
| Part::ShapeOption::Transform).countSubShapes(TopAbs_EDGE);
auto subValues = pcDressUp->Base.getSubValues(false);
std::size_t len = subValues.size();
for (int i = 0; i < count; ++i) {
+3 -1
View File
@@ -7099,7 +7099,9 @@ int SketchObject::addExternal(App::DocumentObject* Obj,
return -1;
}
auto wholeShape = Part::Feature::getTopoShape(Obj);
auto wholeShape =
Part::Feature::getTopoShape(Obj,
Part::ShapeOption::ResolveLink | Part::ShapeOption::Transform);
auto shape = wholeShape.getSubTopoShape(SubName, /*silent*/ true);
TopAbs_ShapeEnum shapeType = TopAbs_SHAPE;
if (shape.shapeType(/*silent*/ true) != TopAbs_FACE) {
@@ -136,12 +136,15 @@ BlendPoint FeatureBlendCurve::GetBlendPoint(App::PropertyLinkSub& link,
TopoDS_Shape axEdge;
if (link.getSubValues().size() > 0 && link.getSubValues()[0].length() > 0) {
axEdge =
Feature::getTopoShape(linked, link.getSubValues()[0].c_str(), true /*need element*/)
.getShape();
axEdge = Part::Feature::getShape(linked,
Part::ShapeOption::NeedSubElement
| Part::ShapeOption::ResolveLink
| Part::ShapeOption::Transform,
link.getSubValues()[0].c_str());
}
else {
axEdge = Feature::getShape(linked);
axEdge = Feature::getShape(linked,
Part::ShapeOption::ResolveLink | Part::ShapeOption::Transform);
}
if (axEdge.IsNull()) {
@@ -345,7 +345,7 @@ bool DimensionAutoCorrect::findExactEdge3d(ReferenceEntry& refToFix, const Part:
// no match in refObj, so now search the cached objects
for (auto& objectName : m_3dObjectCache) {
auto object3d = getDimension()->getDocument()->getObject(objectName.c_str());
auto shape3d = Part::Feature::getShape(object3d);
auto shape3d = Part::Feature::getShape(object3d, Part::ShapeOption::ResolveLink | Part::ShapeOption::Transform);
auto edgesAll = getDimension()->getEdges(shape3d);
size_t iEdge {1};
for (auto& edge : edgesAll) {
@@ -531,7 +531,7 @@ ReferenceEntry DimensionAutoCorrect::searchObjForEdge(App::DocumentObject* obj,
{
// Base::Console().message("DAC::searchObjForEdge(%s)\n", obj->Label.getValue());
(void)exact;
auto shape3d = Part::Feature::getShape(obj);
auto shape3d = Part::Feature::getShape(obj, Part::ShapeOption::ResolveLink | Part::ShapeOption::Transform);
if (shape3d.IsNull()) {
// how to handle this?
return {};
+1 -1
View File
@@ -309,7 +309,7 @@ bool ReferenceEntry::hasGeometry() const
// 3d reference
// TODO: shouldn't this be ShapeFinder.getLocatedShape?
auto shape = Part::Feature::getTopoShape(getObject());
auto shape = Part::Feature::getTopoShape(getObject(), Part::ShapeOption::ResolveLink | Part::ShapeOption::Transform);
auto subShape = shape.getSubShape(getSubName().c_str());
return !subShape.IsNull();
+6 -6
View File
@@ -594,7 +594,7 @@ TopoDS_Wire DrawComplexSection::makeProfileWire(App::DocumentObject* toolObj)
return {};
}
TopoDS_Shape toolShape = Part::Feature::getShape(toolObj);
TopoDS_Shape toolShape = Part::Feature::getShape(toolObj, Part::ShapeOption::ResolveLink | Part::ShapeOption::Transform);
if (toolShape.IsNull()) {
return {};
}
@@ -709,7 +709,7 @@ TopoDS_Wire DrawComplexSection::makeSectionLineWire()
App::DocumentObject* toolObj = CuttingToolWireObject.getValue();
DrawViewPart* baseDvp = freecad_cast<DrawViewPart*>(BaseView.getValue());
if (baseDvp) {
TopoDS_Shape toolShape = Part::Feature::getShape(toolObj);
TopoDS_Shape toolShape = Part::Feature::getShape(toolObj, Part::ShapeOption::ResolveLink | Part::ShapeOption::Transform);
if (toolShape.IsNull()) {
// CuttingToolWireObject is likely still restoring and has no shape yet
return {};
@@ -968,7 +968,7 @@ bool DrawComplexSection::canBuild(gp_Ax2 sectionCS, App::DocumentObject* profile
return false;
}
TopoDS_Shape shape = Part::Feature::getShape(profileObject);
TopoDS_Shape shape = Part::Feature::getShape(profileObject, Part::ShapeOption::ResolveLink | Part::ShapeOption::Transform);
if (BRep_Tool::IsClosed(shape)) {
//closed profiles don't have a profile vector but should always make a section?
return true;
@@ -1090,7 +1090,7 @@ TopoDS_Wire DrawComplexSection::makeNoseToTailWire(const TopoDS_Wire& inWire)
bool DrawComplexSection::isProfileObject(App::DocumentObject* obj)
{
//if the object's shape is a wire or an edge, then it can be a profile object
TopoDS_Shape shape = Part::Feature::getShape(obj);
TopoDS_Shape shape = Part::Feature::getShape(obj, Part::ShapeOption::ResolveLink | Part::ShapeOption::Transform);
if (shape.IsNull()) {
return false;
}
@@ -1104,7 +1104,7 @@ bool DrawComplexSection::isProfileObject(App::DocumentObject* obj)
bool DrawComplexSection::isMultiSegmentProfile(App::DocumentObject* obj)
{
//if the object's shape is a wire or an edge, then it can be a profile object
TopoDS_Shape shape = Part::Feature::getShape(obj);
TopoDS_Shape shape = Part::Feature::getShape(obj, Part::ShapeOption::ResolveLink | Part::ShapeOption::Transform);
if (shape.IsNull()) {
return false;
}
@@ -1132,7 +1132,7 @@ bool DrawComplexSection::isMultiSegmentProfile(App::DocumentObject* obj)
//check if the profile has curves in it
bool DrawComplexSection::isLinearProfile(App::DocumentObject* obj)
{
TopoDS_Shape shape = Part::Feature::getShape(obj);
TopoDS_Shape shape = Part::Feature::getShape(obj, Part::ShapeOption::ResolveLink | Part::ShapeOption::Transform);
if (shape.IsNull()) {
return false;
}
+5 -4
View File
@@ -135,7 +135,7 @@ TopoDS_Shape ShapeExtractor::getShapes(const std::vector<App::DocumentObject*> l
}
}
else {
auto shape = Part::Feature::getShape(obj);
auto shape = Part::Feature::getShape(obj, Part::ShapeOption::ResolveLink | Part::ShapeOption::Transform);
// if source obj has a shape, we use that shape.
if(!SU::isShapeReallyNull(shape)) {
if (checkShape(obj, shape)) {
@@ -225,7 +225,8 @@ std::vector<TopoDS_Shape> ShapeExtractor::getXShapes(const App::Link* xLink)
childNeedsTransform = true;
}
}
auto shape = Part::Feature::getShape(l); // TODO: getTopoShape() ?
// TODO: getTopoShape() ?
auto shape = Part::Feature::getShape(l, Part::ShapeOption::ResolveLink | Part::ShapeOption::Transform);
Part::TopoShape ts(shape);
if (ts.isInfinite()) {
shape = ShapeFinder::stripInfiniteShapes(shape);
@@ -280,7 +281,7 @@ TopoDS_Shape ShapeExtractor::getShapeFromXLink(const App::Link* xLink)
App::DocumentObject* linkedObject = xLink->getLink(depth);
if (linkedObject) {
// have a linked object, get the shape
TopoDS_Shape shape = Part::Feature::getShape(linkedObject);
TopoDS_Shape shape = Part::Feature::getShape(linkedObject, Part::ShapeOption::ResolveLink | Part::ShapeOption::Transform);
if (shape.IsNull()) {
// this is where we need to parse the target for objects with a shape??
return TopoDS_Shape();
@@ -465,7 +466,7 @@ Base::Vector3d ShapeExtractor::getLocation3dFromFeat(const App::DocumentObject*
//! get the located and oriented version of docObj shape
TopoDS_Shape ShapeExtractor::getLocatedShape(const App::DocumentObject* docObj)
{
Part::TopoShape shape = Part::Feature::getTopoShape(docObj);
Part::TopoShape shape = Part::Feature::getTopoShape(docObj, Part::ShapeOption::ResolveLink | Part::ShapeOption::Transform);
const Part::Feature* pf = dynamic_cast<const Part::Feature*>(docObj);
if (pf) {
shape.setPlacement(pf->globalPlacement());
+6 -1
View File
@@ -645,7 +645,12 @@ std::pair<Base::Vector3d, Base::Vector3d> DrawGuiUtil::getProjDirFromFace(App::D
projDir = d3Dirs.first;
rotVec = d3Dirs.second;
auto ts = Part::Feature::getShape(obj, faceName.c_str(), true);
auto ts = Part::Feature::getShape(obj,
Part::ShapeOption::NeedSubElement
| Part::ShapeOption::ResolveLink
| Part::ShapeOption::Transform,
faceName.c_str());
if (ts.IsNull() || ts.ShapeType() != TopAbs_FACE) {
Base::Console().warning("getProjDirFromFace(%s) is not a Face\n", faceName.c_str());
return dirs;