From 408b4dcd85249b5fe74dfa94f245fbf5e09b5a92 Mon Sep 17 00:00:00 2001 From: bgbsww Date: Sun, 28 Jan 2024 11:40:27 -0500 Subject: [PATCH] Cleanup merge issues and linter concerns --- src/Mod/Part/App/TopoShape.h | 29 +- src/Mod/Part/App/TopoShapeExpansion.cpp | 148 +-- ....sync-conflict-20240128-110016-QVQC5GY.cpp | 1096 ----------------- 3 files changed, 43 insertions(+), 1230 deletions(-) delete mode 100644 src/Mod/Part/App/TopoShapeExpansion.sync-conflict-20240128-110016-QVQC5GY.cpp diff --git a/src/Mod/Part/App/TopoShape.h b/src/Mod/Part/App/TopoShape.h index f779a7a6c6..876b221e0e 100644 --- a/src/Mod/Part/App/TopoShape.h +++ b/src/Mod/Part/App/TopoShape.h @@ -40,14 +40,6 @@ #include #include -// FIXME? -// including instead of the incomplete class declaration -// below results in a broken link on Windows but builds on other platforms. I suspect -// that's why these class declarations appear in the RT branch. -// Something about how that compiler is mangling the names? Maybe we're missing a -// magic windows specific qualifier on the declarations. - -class BRepPrimAPI_MakeHalfSpace; class gp_Ax1; class gp_Ax2; class gp_Pln; @@ -62,7 +54,6 @@ namespace Part { class TopoShapeCache; -class TopoShape; /* A special sub-class to indicate null shapes */ @@ -731,9 +722,9 @@ public: * a self reference so that multiple operations can be carried out * for the same shape in the same line of code. */ - // TopoShape& makeElementShellFromWires(const std::vector& wires, - // bool silent = true, - // const char* op = nullptr); + TopoShape& makeElementShellFromWires(const std::vector& wires, + bool silent = true, + const char* op = nullptr); /* Make a shell with input wires * * @param wires: input wires @@ -743,10 +734,10 @@ public: * * @return Return the new shape. The TopoShape itself is not modified. */ - // TopoShape& makeElementShellFromWires(bool silent = true, const char* op = nullptr) - // { - // return makeElementShellFromWires(getSubTopoShapes(TopAbs_WIRE), silent, op); - // } + TopoShape& makeElementShellFromWires(bool silent = true, const char* op = nullptr) + { + return makeElementShellFromWires(getSubTopoShapes(TopAbs_WIRE), silent, op); + } TopoShape& makeElementFace(const std::vector& shapes, const char* op = nullptr, @@ -1195,11 +1186,11 @@ private: struct PartExport MapperMaker: TopoShape::Mapper { BRepBuilderAPI_MakeShape& maker; - MapperMaker(BRepBuilderAPI_MakeShape& maker) + explicit MapperMaker(BRepBuilderAPI_MakeShape& maker) : maker(maker) {} - virtual const std::vector& modified(const TopoDS_Shape& s) const override; - virtual const std::vector& generated(const TopoDS_Shape& s) const override; + const std::vector& modified(const TopoDS_Shape& s) const override; + const std::vector& generated(const TopoDS_Shape& s) const override; }; } // namespace Part diff --git a/src/Mod/Part/App/TopoShapeExpansion.cpp b/src/Mod/Part/App/TopoShapeExpansion.cpp index 733d1b495e..b861b58eb4 100644 --- a/src/Mod/Part/App/TopoShapeExpansion.cpp +++ b/src/Mod/Part/App/TopoShapeExpansion.cpp @@ -42,7 +42,6 @@ #include "TopoShape.h" #include "TopoShapeCache.h" -#include "TopoShapeOpCode.h" #include "FaceMaker.h" #include "TopoShapeOpCode.h" @@ -263,6 +262,7 @@ size_t checkSubshapeCount(const TopoShape& topoShape1, } return count; } + } // namespace void TopoShape::setupChild(Data::ElementMap::MappedChildElements& child, @@ -316,7 +316,7 @@ void warnIfLogging() if (FC_LOG_INSTANCE.isEnabled(FC_LOGLEVEL_LOG)) { FC_WARN("hasher mismatch"); // NOLINT } -}; +} void hasherMismatchError() { @@ -392,11 +392,11 @@ void TopoShape::mapSubElementTypeForShape(const TopoShape& other, sids.clear(); } } - std::ostringstream ss; char elementType {shapeName(type)[0]}; if (!elementMap()) { FC_THROWM(NullShapeException, "No element map"); // NOLINT } + std::ostringstream ss; elementMap()->encodeElementName(elementType, name, ss, &sids, Tag, op, other.Tag); elementMap()->setElementName(element, name, Tag, &sids); } @@ -530,7 +530,7 @@ struct ShapeInfo , shapetype(TopoShape::shapeName(type).c_str()) {} - int count() const + [[nodiscard]] int count() const { return cache.count(); } @@ -1301,10 +1301,10 @@ TopoShape::makeElementCompound(const std::vector& shapes, const char* struct MapperSewing: Part::TopoShape::Mapper { BRepBuilderAPI_Sewing& maker; - MapperSewing(BRepBuilderAPI_Sewing& maker) + explicit MapperSewing(BRepBuilderAPI_Sewing& maker) : maker(maker) {} - virtual const std::vector& modified(const TopoDS_Shape& s) const override + const std::vector& modified(const TopoDS_Shape& s) const override { _res.clear(); try { @@ -1343,14 +1343,14 @@ struct MapperThruSections: MapperMaker lastProfile = profiles.back(); } } - virtual const std::vector& generated(const TopoDS_Shape& s) const override + const std::vector& generated(const TopoDS_Shape& s) const override { MapperMaker::generated(s); - if (_res.size()) { + if ( ! _res.empty()) { return _res; } try { - auto& tmaker = static_cast(maker); + auto& tmaker = dynamic_cast(maker); auto shape = tmaker.GeneratedFace(s); if (!shape.IsNull()) { _res.push_back(shape); @@ -1531,7 +1531,7 @@ Data::MappedName TopoShape::setElementComboName(const Data::IndexedName& element const Data::ElementIDRefs* _sids) { if (names.empty()) { - return Data::MappedName(); + return Data::MappedName {}; } std::string _marker; if (!marker) { @@ -1610,7 +1610,7 @@ TopoShape TopoShape::splitWires(std::vector* inner, SplitWireReorient tmp = BRepTools::OuterWire(TopoDS::Face(getSubShape(TopAbs_FACE, 1))); } if (tmp.IsNull()) { - return TopoShape(); + return TopoShape {}; } const auto& wires = getSubTopoShapes(TopAbs_WIRE); auto it = wires.begin(); @@ -1677,91 +1677,9 @@ TopoShape TopoShape::splitWires(std::vector* inner, SplitWireReorient } } } - return TopoShape(); + return TopoShape {}; } -TopoShape& TopoShape::makeElementShape(BRepBuilderAPI_MakeShape& mkShape, - const TopoShape& source, - const char* op) -{ - std::vector sources(1, source); - return makeElementShape(mkShape, sources, op); -} - -TopoShape& TopoShape::makeElementShape(BRepBuilderAPI_MakeShape& mkShape, - const std::vector& shapes, - const char* op) -{ - return makeShapeWithElementMap(mkShape.Shape(), MapperMaker(mkShape), shapes, op); -} - -TopoShape& -TopoShape::makeElementShape(BRepOffsetAPI_ThruSections& mk, const TopoShape& source, const char* op) -{ - if (!op) { - op = Part::OpCodes::ThruSections; - } - return makeElementShape(mk, std::vector(1, source), op); -} - -TopoShape& TopoShape::makeElementShape(BRepOffsetAPI_ThruSections& mk, - const std::vector& sources, - const char* op) -{ - if (!op) { - op = Part::OpCodes::ThruSections; - } - return makeShapeWithElementMap(mk.Shape(), MapperThruSections(mk, sources), sources, op); -} - -TopoShape& TopoShape::makeElementShape(BRepBuilderAPI_Sewing& mk, - const std::vector& shapes, - const char* op) -{ - if (!op) { - op = Part::OpCodes::Sewing; - } - return makeShapeWithElementMap(mk.SewedShape(), MapperSewing(mk), shapes, op); -} - -TopoShape& -TopoShape::makeElementShape(BRepBuilderAPI_Sewing& mkShape, const TopoShape& source, const char* op) -{ - if (!op) { - op = Part::OpCodes::Sewing; - } - return makeElementShape(mkShape, std::vector(1, source), op); -} - -struct MapperSewing: Part::TopoShape::Mapper -{ - BRepBuilderAPI_Sewing& maker; - MapperSewing(BRepBuilderAPI_Sewing& maker) - : maker(maker) - {} - virtual const std::vector& modified(const TopoDS_Shape& s) const override - { - _res.clear(); - try { - const auto& shape = maker.Modified(s); - if (!shape.IsNull() && !shape.IsSame(s)) { - _res.push_back(shape); - } - else { - const auto& sshape = maker.ModifiedSubShape(s); - if (!sshape.IsNull() && !sshape.IsSame(s)) { - _res.push_back(sshape); - } - } - } - catch (const Standard_Failure& e) { - if (FC_LOG_INSTANCE.isEnabled(FC_LOGLEVEL_LOG)) { - FC_WARN("Exception on shape mapper: " << e.GetMessageString()); - } - } - return _res; - } -}; struct MapperFill: Part::TopoShape::Mapper { BRepFill_Generator& maker; @@ -1911,26 +1829,26 @@ TopoShape& TopoShape::makeElementShell(bool silent, const char* op) return *this; } -// TopoShape& TopoShape::makeElementShellFromWires(const std::vector& wires, -// bool silent, -// const char* op) -// { -// BRepFill_Generator maker; -// for (auto& w : wires) { -// if (w.shapeType(silent) == TopAbs_WIRE) { -// maker.AddWire(TopoDS::Wire(w.getShape())); -// } -// } -// if (wires.empty()) { -// if (silent) { -// _Shape.Nullify(); -// return *this; -// } -// FC_THROWM(NullShapeException, "No input shapes"); -// } -// maker.Perform(); -// this->makeShapeWithElementMap(maker.Shell(), MapperFill(maker), wires, op); -// return *this; -// } +TopoShape& TopoShape::makeElementShellFromWires(const std::vector& wires, + bool silent, + const char* op) +{ + BRepFill_Generator maker; + for (auto& w : wires) { + if (w.shapeType(silent) == TopAbs_WIRE) { + maker.AddWire(TopoDS::Wire(w.getShape())); + } + } + if (wires.empty()) { + if (silent) { + _Shape.Nullify(); + return *this; + } + FC_THROWM(NullShapeException, "No input shapes"); + } + maker.Perform(); + this->makeShapeWithElementMap(maker.Shell(), MapperFill(maker), wires, op); + return *this; +} } // namespace Part diff --git a/src/Mod/Part/App/TopoShapeExpansion.sync-conflict-20240128-110016-QVQC5GY.cpp b/src/Mod/Part/App/TopoShapeExpansion.sync-conflict-20240128-110016-QVQC5GY.cpp deleted file mode 100644 index e96233cfbe..0000000000 --- a/src/Mod/Part/App/TopoShapeExpansion.sync-conflict-20240128-110016-QVQC5GY.cpp +++ /dev/null @@ -1,1096 +0,0 @@ -// SPDX-License-Identifier: LGPL-2.1-or-later -/**************************************************************************** - * * - * Copyright (c) 2022 Zheng, Lei * - * Copyright (c) 2023 FreeCAD Project Association * - * * - * This file is part of FreeCAD. * - * * - * FreeCAD is free software: you can redistribute it and/or modify it * - * under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 2.1 of the * - * License, or (at your option) any later version. * - * * - * FreeCAD is distributed in the hope that it will be useful, but * - * WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * - * Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public * - * License along with FreeCAD. If not, see * - * . * - * * - ***************************************************************************/ - - -#include "PreCompiled.h" -#ifndef _PreComp_ -#include -#include -#include -#include - -#include -#include - -#endif - -#include "TopoShape.h" -#include "TopoShapeCache.h" -#include "FaceMaker.h" - -#include "TopoShapeOpCode.h" - -FC_LOG_LEVEL_INIT("TopoShape", true, true) // NOLINT - -namespace Part -{ - -void TopoShape::initCache(int reset) const -{ - if (reset > 0 || !_cache || _cache->isTouched(_Shape)) { - if (_parentCache) { - _parentCache.reset(); - _subLocation.Identity(); - } - _cache = std::make_shared(_Shape); - } -} - -void TopoShape::setShape(const TopoDS_Shape& shape, bool resetElementMap) -{ - if (resetElementMap) { - this->resetElementMap(); - } - else if (_cache && _cache->isTouched(shape)) { - this->flushElementMap(); - } - //_Shape._Shape = shape; // TODO: Replace the next line with this once ShapeProtector is - // available. - _Shape = shape; - if (_cache) { - initCache(); - } -} - - -TopoDS_Shape& TopoShape::move(TopoDS_Shape& tds, const TopLoc_Location& location) -{ -#if OCC_VERSION_HEX < 0x070600 - tds.Move(location); -#else - tds.Move(location, false); -#endif - return tds; -} - -TopoDS_Shape TopoShape::moved(const TopoDS_Shape& tds, const TopLoc_Location& location) -{ -#if OCC_VERSION_HEX < 0x070600 - return tds.Moved(location); -#else - return tds.Moved(location, false); -#endif -} - -TopoDS_Shape& TopoShape::move(TopoDS_Shape& tds, const gp_Trsf& transfer) -{ -#if OCC_VERSION_HEX < 0x070600 - static constexpr double scalePrecision {1e-14}; - if (std::abs(transfer.ScaleFactor()) > scalePrecision) -#else - if (std::abs(transfer.ScaleFactor()) > TopLoc_Location::ScalePrec()) -#endif - { - auto transferCopy(transfer); - transferCopy.SetScaleFactor(1.0); - tds.Move(transferCopy); - } - else { - tds.Move(transfer); - } - return tds; -} - -TopoDS_Shape TopoShape::moved(const TopoDS_Shape& tds, const gp_Trsf& transfer) -{ - TopoDS_Shape sCopy(tds); - return move(sCopy, transfer); -} - -TopoDS_Shape& TopoShape::locate(TopoDS_Shape& tds, const TopLoc_Location& loc) -{ - tds.Location(TopLoc_Location()); - return move(tds, loc); -} - -TopoDS_Shape TopoShape::located(const TopoDS_Shape& tds, const TopLoc_Location& loc) -{ - auto sCopy(tds); - sCopy.Location(TopLoc_Location()); - return moved(sCopy, loc); -} - -TopoDS_Shape& TopoShape::locate(TopoDS_Shape& tds, const gp_Trsf& transfer) -{ - tds.Location(TopLoc_Location()); - return move(tds, transfer); -} - -TopoDS_Shape TopoShape::located(const TopoDS_Shape& tds, const gp_Trsf& transfer) -{ - auto sCopy(tds); - sCopy.Location(TopLoc_Location()); - return moved(sCopy, transfer); -} - - -int TopoShape::findShape(const TopoDS_Shape& subshape) const -{ - initCache(); - return _cache->findShape(_Shape, subshape); -} - - -TopoDS_Shape TopoShape::findShape(const char* name) const -{ - if (!name) { - return {}; - } - - Data::MappedElement res = getElementName(name); - if (!res.index) { - return {}; - } - - auto idx = shapeTypeAndIndex(name); - if (idx.second == 0) { - return {}; - } - initCache(); - return _cache->findShape(_Shape, idx.first, idx.second); -} - -TopoDS_Shape TopoShape::findShape(TopAbs_ShapeEnum type, int idx) const -{ - initCache(); - return _cache->findShape(_Shape, type, idx); -} - -int TopoShape::findAncestor(const TopoDS_Shape& subshape, TopAbs_ShapeEnum type) const -{ - initCache(); - return _cache->findShape(_Shape, _cache->findAncestor(_Shape, subshape, type)); -} - -TopoDS_Shape TopoShape::findAncestorShape(const TopoDS_Shape& subshape, TopAbs_ShapeEnum type) const -{ - initCache(); - return _cache->findAncestor(_Shape, subshape, type); -} - -std::vector TopoShape::findAncestors(const TopoDS_Shape& subshape, TopAbs_ShapeEnum type) const -{ - const auto& shapes = findAncestorsShapes(subshape, type); - std::vector ret; - ret.reserve(shapes.size()); - for (const auto& shape : shapes) { - ret.push_back(findShape(shape)); - } - return ret; -} - -std::vector TopoShape::findAncestorsShapes(const TopoDS_Shape& subshape, - TopAbs_ShapeEnum type) const -{ - initCache(); - std::vector shapes; - _cache->findAncestor(_Shape, subshape, type, &shapes); - return shapes; -} - -// The following lines should be used for now to replace the original macros (in the future we can -// refactor to use std::source_location and eliminate the use of the macros entirely). -// FC_THROWM(NullShapeException, "Null shape"); -// FC_THROWM(NullShapeException, "Null input shape"); -// FC_WARN("Null input shape"); // NOLINT -// -// The original macros: -// #define HANDLE_NULL_SHAPE _HANDLE_NULL_SHAPE("Null shape",true) -// #define HANDLE_NULL_INPUT _HANDLE_NULL_SHAPE("Null input shape",true) -// #define WARN_NULL_INPUT _HANDLE_NULL_SHAPE("Null input shape",false) - -bool TopoShape::hasPendingElementMap() const -{ - return !elementMap(false) && this->_cache - && (this->_parentCache || this->_cache->cachedElementMap); -} - -bool TopoShape::canMapElement(const TopoShape& other) const -{ - if (isNull() || other.isNull() || this == &other || other.Tag == -1 || Tag == -1) { - return false; - } - if ((other.Tag == 0) && !other.elementMap(false) && !other.hasPendingElementMap()) { - return false; - } - initCache(); - other.initCache(); - _cache->relations.clear(); - return true; -} - -namespace -{ -size_t checkSubshapeCount(const TopoShape& topoShape1, - const TopoShape& topoShape2, - TopAbs_ShapeEnum elementType) -{ - auto count = topoShape1.countSubShapes(elementType); - auto other = topoShape2.countSubShapes(elementType); - if (count != other) { - FC_WARN("sub shape mismatch"); // NOLINT - if (count > other) { - count = other; - } - } - return count; -} -} // namespace - -void TopoShape::setupChild(Data::ElementMap::MappedChildElements& child, - TopAbs_ShapeEnum elementType, - const TopoShape& topoShape, - size_t shapeCount, - const char* op) -{ - child.indexedName = Data::IndexedName::fromConst(TopoShape::shapeName(elementType).c_str(), 1); - child.offset = 0; - child.count = static_cast(shapeCount); - child.elementMap = topoShape.elementMap(); - if (this->Tag != topoShape.Tag) { - child.tag = topoShape.Tag; - } - else { - child.tag = 0; - } - if (op) { - child.postfix = op; - } -} - -void TopoShape::copyElementMap(const TopoShape& topoShape, const char* op) -{ - if (topoShape.isNull() || isNull()) { - return; - } - std::vector children; - std::array elementTypes = {TopAbs_VERTEX, TopAbs_EDGE, TopAbs_FACE}; - for (const auto elementType : elementTypes) { - auto count = checkSubshapeCount(*this, topoShape, elementType); - if (count == 0) { - continue; - } - children.emplace_back(); - auto& child = children.back(); - setupChild(child, elementType, topoShape, count, op); - } - resetElementMap(); - if (!Hasher) { - Hasher = topoShape.Hasher; - } - setMappedChildElements(children); -} - -namespace -{ -void warnIfLogging() -{ - if (FC_LOG_INSTANCE.isEnabled(FC_LOGLEVEL_LOG)) { - FC_WARN("hasher mismatch"); // NOLINT - } -}; - -void hasherMismatchError() -{ - FC_ERR("hasher mismatch"); // NOLINT -} - - -void checkAndMatchHasher(TopoShape& topoShape1, const TopoShape& topoShape2) -{ - if (topoShape1.Hasher) { - if (topoShape2.Hasher != topoShape1.Hasher) { - if (topoShape1.getElementMapSize(false) == 0U) { - warnIfLogging(); - } - else { - hasherMismatchError(); - } - topoShape1.Hasher = topoShape2.Hasher; - } - } - else { - topoShape1.Hasher = topoShape2.Hasher; - } -} -} // namespace - -void TopoShape::mapSubElementTypeForShape(const TopoShape& other, - TopAbs_ShapeEnum type, - const char* op, - int count, - bool forward, - bool& warned) -{ - auto& shapeMap = _cache->getAncestry(type); - auto& otherMap = other._cache->getAncestry(type); - const char* shapeType = shapeName(type).c_str(); - - // 1-indexed for readability (e.g. there is no "Edge0", we started at "Edge1", etc.) - for (int outerCounter = 1; outerCounter <= count; ++outerCounter) { - int innerCounter {0}; - int index {0}; - if (forward) { - innerCounter = outerCounter; - index = shapeMap.find(_Shape, otherMap.find(other._Shape, outerCounter)); - if (index == 0) { - continue; - } - } - else { - index = outerCounter; - innerCounter = otherMap.find(other._Shape, shapeMap.find(_Shape, outerCounter)); - if (innerCounter == 0) { - continue; - } - } - Data::IndexedName element = Data::IndexedName::fromConst(shapeType, index); - for (auto& mappedName : - other.getElementMappedNames(Data::IndexedName::fromConst(shapeType, innerCounter), - true)) { - auto& name = mappedName.first; - auto& sids = mappedName.second; - if (!sids.empty()) { - if (!Hasher) { - Hasher = sids[0].getHasher(); - } - else if (!sids[0].isFromSameHasher(Hasher)) { - if (!warned) { - warned = true; - FC_WARN("hasher mismatch"); // NOLINT - } - sids.clear(); - } - } - std::ostringstream ss; - char elementType {shapeName(type)[0]}; - if ( ! elementMap() ) { - FC_THROWM(NullShapeException, "No element map"); - } - elementMap()->encodeElementName(elementType, name, ss, &sids, Tag, op, other.Tag); - elementMap()->setElementName(element, name, Tag, &sids); - } - } -} - -void TopoShape::mapSubElementForShape(const TopoShape& other, const char* op) -{ - bool warned = false; - static const std::array types = {TopAbs_VERTEX, TopAbs_EDGE, TopAbs_FACE}; - - for (auto type : types) { - auto& shapeMap = _cache->getAncestry(type); - auto& otherMap = other._cache->getAncestry(type); - if ((shapeMap.count() == 0) || (otherMap.count() == 0)) { - continue; - } - - bool forward {false}; - int count {0}; - if (otherMap.count() <= shapeMap.count()) { - forward = true; - count = otherMap.count(); - } - else { - forward = false; - count = shapeMap.count(); - } - mapSubElementTypeForShape(other, type, op, count, forward, warned); - } -} - -void TopoShape::mapSubElement(const TopoShape& other, const char* op, bool forceHasher) -{ - 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); -} - -std::vector -TopoShape::createChildMap(size_t count, const std::vector& shapes, const char* op) -{ - std::vector children; - children.reserve(count * (size_t)3); - std::array types = {TopAbs_VERTEX, TopAbs_EDGE, TopAbs_FACE}; - for (const auto topAbsType : types) { - size_t offset = 0; - for (auto& topoShape : shapes) { - if (topoShape.isNull()) { - continue; - } - auto subShapeCount = topoShape.countSubShapes(topAbsType); - if (subShapeCount == 0) { - continue; - } - children.emplace_back(); - auto& child = children.back(); - child.indexedName = - Data::IndexedName::fromConst(TopoShape::shapeName(topAbsType).c_str(), 1); - child.offset = static_cast(offset); - offset += subShapeCount; - child.count = static_cast(subShapeCount); - child.elementMap = topoShape.elementMap(); - child.tag = topoShape.Tag; - if (op) { - child.postfix = op; - } - } - } - return children; -} - -void TopoShape::mapCompoundSubElements(const std::vector& shapes, const char* op) -{ - int count = 0; - for (auto& topoShape : shapes) { - if (topoShape.isNull()) { - continue; - } - ++count; - auto subshape = getSubShape(TopAbs_SHAPE, count, /*silent = */ true); - if (!subshape.IsPartner(topoShape._Shape)) { - return; // Not a partner shape, don't do any mapping at all - } - } - auto children {createChildMap(count, shapes, op)}; - setMappedChildElements(children); -} - -void TopoShape::mapSubElement(const std::vector& shapes, const char* op) -{ - if (shapes.empty()) { - return; - } - - if (shapeType(true) == TopAbs_COMPOUND) { - mapCompoundSubElements(shapes, op); - } - else { - for (auto& shape : shapes) { - mapSubElement(shape, op); - } - } -} - -namespace -{ -void addShapesToBuilder(const std::vector& shapes, - BRep_Builder& builder, - TopoDS_Compound& comp) -{ - int count = 0; - for (auto& topoShape : shapes) { - if (topoShape.isNull()) { - FC_WARN("Null input shape"); // NOLINT - continue; - } - builder.Add(comp, topoShape.getShape()); - ++count; - } - if (count == 0) { - FC_THROWM(NullShapeException, "Null shape"); - } -} -} // namespace - -TopoShape& -TopoShape::makeElementCompound(const std::vector& shapes, const char* op, bool force) -{ - if (!force && shapes.size() == 1) { - *this = shapes[0]; - return *this; - } - - BRep_Builder builder; - TopoDS_Compound comp; - builder.MakeCompound(comp); - - if (shapes.empty()) { - setShape(comp); - return *this; - } - addShapesToBuilder(shapes, builder, comp); - setShape(comp); - initCache(); - - mapSubElement(shapes, op); - return *this; -} - -struct MapperSewing: Part::TopoShape::Mapper -{ - BRepBuilderAPI_Sewing& maker; - MapperSewing(BRepBuilderAPI_Sewing& maker) - : maker(maker) - {} - virtual const std::vector& modified(const TopoDS_Shape& s) const override - { - _res.clear(); - try { - const auto& shape = maker.Modified(s); - if (!shape.IsNull() && !shape.IsSame(s)) { - _res.push_back(shape); - } - else { - const auto& sshape = maker.ModifiedSubShape(s); - if (!sshape.IsNull() && !sshape.IsSame(s)) { - _res.push_back(sshape); - } - } - } - catch (const Standard_Failure& e) { - if (FC_LOG_INSTANCE.isEnabled(FC_LOGLEVEL_LOG)) { - FC_WARN("Exception on shape mapper: " << e.GetMessageString()); - } - } - return _res; - } -}; - -struct MapperThruSections: MapperMaker -{ - TopoShape firstProfile; - TopoShape lastProfile; - - MapperThruSections(BRepOffsetAPI_ThruSections& tmaker, const std::vector& profiles) - : MapperMaker(tmaker) - { - if (!tmaker.FirstShape().IsNull()) { - firstProfile = profiles.front(); - } - if (!tmaker.LastShape().IsNull()) { - lastProfile = profiles.back(); - } - } - virtual const std::vector& generated(const TopoDS_Shape& s) const override - { - MapperMaker::generated(s); - if (_res.size()) { - return _res; - } - try { - auto& tmaker = static_cast(maker); - auto shape = tmaker.GeneratedFace(s); - if (!shape.IsNull()) { - _res.push_back(shape); - } - if (firstProfile.getShape().IsSame(s) || firstProfile.findShape(s)) { - _res.push_back(tmaker.FirstShape()); - } - else if (lastProfile.getShape().IsSame(s) || lastProfile.findShape(s)) { - _res.push_back(tmaker.LastShape()); - } - } - catch (const Standard_Failure& e) { - if (FC_LOG_INSTANCE.isEnabled(FC_LOGLEVEL_LOG)) { - FC_WARN("Exception on shape mapper: " << e.GetMessageString()); - } - } - return _res; - } -}; - - -TopoShape& TopoShape::makeElementShape(BRepBuilderAPI_MakeShape& mkShape, - const TopoShape& source, - const char* op) -{ - std::vector sources(1, source); - return makeElementShape(mkShape, sources, op); -} - -TopoShape& TopoShape::makeElementShape(BRepBuilderAPI_MakeShape& mkShape, - const std::vector& shapes, - const char* op) -{ - return makeShapeWithElementMap(mkShape.Shape(), MapperMaker(mkShape), shapes, op); -} - -TopoShape& -TopoShape::makeElementShape(BRepOffsetAPI_ThruSections& mk, const TopoShape& source, const char* op) -{ - if (!op) { - op = Part::OpCodes::ThruSections; - } - return makeElementShape(mk, std::vector(1, source), op); -} - -TopoShape& TopoShape::makeElementShape(BRepOffsetAPI_ThruSections& mk, - const std::vector& sources, - const char* op) -{ - if (!op) { - op = Part::OpCodes::ThruSections; - } - return makeShapeWithElementMap(mk.Shape(), MapperThruSections(mk, sources), sources, op); -} - -TopoShape& TopoShape::makeElementShape(BRepBuilderAPI_Sewing& mk, - const std::vector& shapes, - const char* op) -{ - if (!op) { - op = Part::OpCodes::Sewing; - } - return makeShapeWithElementMap(mk.SewedShape(), MapperSewing(mk), shapes, op); -} - -TopoShape& -TopoShape::makeElementShape(BRepBuilderAPI_Sewing& mkShape, const TopoShape& source, const char* op) -{ - if (!op) { - op = Part::OpCodes::Sewing; - } - return makeElementShape(mkShape, std::vector(1, source), op); -} - -TopoShape& TopoShape::makeElementShape(BRepPrimAPI_MakeHalfSpace& mkShape, - const TopoShape& source, - const char* op) -{ - if (!op) { - op = Part::OpCodes::HalfSpace; - } - return makeShapeWithElementMap(mkShape.Solid(), MapperMaker(mkShape), {source}, op); -} - -TopoShape& TopoShape::makeElementFace(const TopoShape& shape, - const char* op, - const char* maker, - const gp_Pln* plane) -{ - std::vector shapes; - if (shape.isNull()) { - FC_THROWM(NullShapeException, "Null shape"); - } - if (shape.getShape().ShapeType() == TopAbs_COMPOUND) { - shapes = shape.getSubTopoShapes(); - } - else { - shapes.push_back(shape); - } - return makeElementFace(shapes, op, maker, plane); -} - -TopoShape& TopoShape::makeElementFace(const std::vector& shapes, - const char* op, - const char* maker, - const gp_Pln* plane) -{ - if (!maker || !maker[0]) { - maker = "Part::FaceMakerBullseye"; - } - std::unique_ptr mkFace = FaceMaker::ConstructFromType(maker); - mkFace->MyHasher = Hasher; - mkFace->MyOp = op; - if (plane) { - mkFace->setPlane(*plane); - } - - for (auto& shape : shapes) { - if (shape.getShape().ShapeType() == TopAbs_COMPOUND) { - mkFace->useTopoCompound(shape); - } - else { - mkFace->addTopoShape(shape); - } - } - mkFace->Build(); - - const auto& ret = mkFace->getTopoShape(); - setShape(ret._Shape); - Hasher = ret.Hasher; - resetElementMap(ret.elementMap()); - if (!isValid()) { - ShapeFix_ShapeTolerance aSFT; - aSFT.LimitTolerance(getShape(), - Precision::Confusion(), - Precision::Confusion(), - TopAbs_SHAPE); - - // In some cases, the OCC reports the returned shape having invalid - // tolerance. Not sure about the real cause. - // - // Update: one of the cause is related to OCC bug in - // BRepBuilder_FindPlane, A possible call sequence is, - // - // makEOffset2D() -> TopoShape::findPlane() -> BRepLib_FindSurface - // - // See code comments in findPlane() for the description of the bug and - // work around. - - ShapeFix_Shape fixer(getShape()); - fixer.Perform(); - setShape(fixer.Shape(), false); - - if (!isValid()) { - FC_WARN("makeElementFace: resulting face is invalid"); - } - } - return *this; -} - -/** - * Encode and set an element name in the elementMap. If a hasher is defined, apply it to the name. - * - * @param element The element name(type) that provides 1 one character suffix to the name IF . - * @param names The subnames to build the name from. If empty, return the TopoShape MappedName. - * @param marker The elementMap name or suffix to start the name with. If null, use the - * elementMapPrefix. - * @param op The op text passed to the element name encoder along with the TopoShape Tag - * @param _sids If defined, records the sub ids processed. - * - * @return The encoded, possibly hashed name. - */ -Data::MappedName TopoShape::setElementComboName(const Data::IndexedName& element, - const std::vector& names, - const char* marker, - const char* op, - const Data::ElementIDRefs* _sids) -{ - if (names.empty()) { - return Data::MappedName(); - } - std::string _marker; - if (!marker) { - marker = elementMapPrefix().c_str(); - } - else if (!boost::starts_with(marker, elementMapPrefix())) { - _marker = elementMapPrefix() + marker; - marker = _marker.c_str(); - } - auto it = names.begin(); - Data::MappedName newName = *it; - std::ostringstream ss; - Data::ElementIDRefs sids; - if (_sids) { - sids = *_sids; - } - if (names.size() == 1) { - ss << marker; - } - else { - bool first = true; - ss.str(""); - if (!Hasher) { - ss << marker; - } - ss << '('; - for (++it; it != names.end(); ++it) { - if (first) { - first = false; - } - else { - ss << '|'; - } - ss << *it; - } - ss << ')'; - if (Hasher) { - sids.push_back(Hasher->getID(ss.str().c_str())); - ss.str(""); - ss << marker << sids.back().toString(); - } - } - elementMap()->encodeElementName(element[0], newName, ss, &sids, Tag, op); - return elementMap()->setElementName(element, newName, Tag, &sids); -} - -/** - * Reorient the outer and inner wires of the TopoShape - * - * @param inner If this is not a nullptr, then any inner wires processed will be returned in this - * vector. - * @param reorient One of NoReorient, Reorient ( Outer forward, inner reversed ), - * ReorientForward ( all forward ), or ReorientReversed ( all reversed ) - * @return The outer wire, or an empty TopoShape if this isn't a Face, has no Face subShapes, or the - * outer wire isn't found. - */ -TopoShape TopoShape::splitWires(std::vector* inner, SplitWireReorient reorient) const -{ - // ShapeAnalysis::OuterWire() is un-reliable for some reason. OCC source - // code shows it works by creating face using each wire, and then test using - // BRepTopAdaptor_FClass2d::PerformInfinitePoint() to check if it is an out - // bound wire. And practice shows it sometimes returns the incorrect - // result. Need more investigation. Note that this may be related to - // unreliable solid face orientation - // (https://forum.freecadweb.org/viewtopic.php?p=446006#p445674) - // - // Use BrepTools::OuterWire() instead. OCC source code shows it is - // implemented using simple bound box checking. This should be a - // reliable method, especially so for a planar face. - - TopoDS_Shape tmp; - if (shapeType(true) == TopAbs_FACE) { - tmp = BRepTools::OuterWire(TopoDS::Face(_Shape)); - } - else if (countSubShapes(TopAbs_FACE) == 1) { - tmp = BRepTools::OuterWire(TopoDS::Face(getSubShape(TopAbs_FACE, 1))); - } - if (tmp.IsNull()) { - return TopoShape(); - } - const auto& wires = getSubTopoShapes(TopAbs_WIRE); - auto it = wires.begin(); - - TopAbs_Orientation orientOuter, orientInner; - switch (reorient) { - case ReorientReversed: - orientOuter = orientInner = TopAbs_REVERSED; - break; - case ReorientForward: - orientOuter = orientInner = TopAbs_FORWARD; - break; - default: - orientOuter = TopAbs_FORWARD; - orientInner = TopAbs_REVERSED; - break; - } - - auto doReorient = [](TopoShape& s, TopAbs_Orientation orient) { - // Special case of single edge wire. Make sure the edge is in the - // required orientation. This is necessary because BRepFill_OffsetWire - // has special handling of circular edge offset, which seem to only - // respect the edge orientation and disregard the wire orientation. The - // orientation is used to determine whether to shrink or expand. - if (s.countSubShapes(TopAbs_EDGE) == 1) { - TopoDS_Shape e = s.getSubShape(TopAbs_EDGE, 1); - if (e.Orientation() == orient) { - if (s._Shape.Orientation() == orient) { - return; - } - } - else { - e = e.Oriented(orient); - } - BRepBuilderAPI_MakeWire mkWire(TopoDS::Edge(e)); - s.setShape(mkWire.Shape(), false); - } - else if (s._Shape.Orientation() != orient) { - s.setShape(s._Shape.Oriented(orient), false); - } - }; - - for (; it != wires.end(); ++it) { - auto& wire = *it; - if (wire.getShape().IsSame(tmp)) { - if (inner) { - for (++it; it != wires.end(); ++it) { - inner->push_back(*it); - if (reorient) { - doReorient(inner->back(), orientInner); - } - } - } - auto res = wire; - if (reorient) { - doReorient(res, orientOuter); - } - return res; - } - if (inner) { - inner->push_back(wire); - if (reorient) { - doReorient(inner->back(), orientInner); - } - } - } - return TopoShape(); -} - -TopoShape& TopoShape::makeElementShape(BRepBuilderAPI_MakeShape& mkShape, - const TopoShape& source, - const char* op) -{ - std::vector sources(1, source); - return makeElementShape(mkShape, sources, op); -} - -TopoShape& TopoShape::makeElementShape(BRepBuilderAPI_MakeShape& mkShape, - const std::vector& shapes, - const char* op) -{ - return makeShapeWithElementMap(mkShape.Shape(), MapperMaker(mkShape), shapes, op); -} - -TopoShape& -TopoShape::makeElementShape(BRepOffsetAPI_ThruSections& mk, const TopoShape& source, const char* op) -{ - if (!op) { - op = Part::OpCodes::ThruSections; - } - return makeElementShape(mk, std::vector(1, source), op); -} - -TopoShape& TopoShape::makeElementShape(BRepOffsetAPI_ThruSections& mk, - const std::vector& sources, - const char* op) -{ - if (!op) { - op = Part::OpCodes::ThruSections; - } - return makeShapeWithElementMap(mk.Shape(), MapperThruSections(mk, sources), sources, op); -} - -TopoShape& TopoShape::makeElementShape(BRepBuilderAPI_Sewing& mk, - const std::vector& shapes, - const char* op) -{ - if (!op) { - op = Part::OpCodes::Sewing; - } - return makeShapeWithElementMap(mk.SewedShape(), MapperSewing(mk), shapes, op); -} - -TopoShape& -TopoShape::makeElementShape(BRepBuilderAPI_Sewing& mkShape, const TopoShape& source, const char* op) -{ - if (!op) { - op = Part::OpCodes::Sewing; - } - return makeElementShape(mkShape, std::vector(1, source), op); -} - -struct MapperSewing: Part::TopoShape::Mapper -{ - BRepBuilderAPI_Sewing& maker; - MapperSewing(BRepBuilderAPI_Sewing& maker) - : maker(maker) - {} - virtual const std::vector& modified(const TopoDS_Shape& s) const override - { - _res.clear(); - try { - const auto& shape = maker.Modified(s); - if (!shape.IsNull() && !shape.IsSame(s)) { - _res.push_back(shape); - } - else { - const auto& sshape = maker.ModifiedSubShape(s); - if (!sshape.IsNull() && !sshape.IsSame(s)) { - _res.push_back(sshape); - } - } - } - catch (const Standard_Failure& e) { - if (FC_LOG_INSTANCE.isEnabled(FC_LOGLEVEL_LOG)) { - FC_WARN("Exception on shape mapper: " << e.GetMessageString()); - } - } - return _res; - } -}; - -struct MapperThruSections: MapperMaker -{ - TopoShape firstProfile; - TopoShape lastProfile; - - MapperThruSections(BRepOffsetAPI_ThruSections& tmaker, const std::vector& profiles) - : MapperMaker(tmaker) - { - if (!tmaker.FirstShape().IsNull()) { - firstProfile = profiles.front(); - } - if (!tmaker.LastShape().IsNull()) { - lastProfile = profiles.back(); - } - } - virtual const std::vector& generated(const TopoDS_Shape& s) const override - { - MapperMaker::generated(s); - if (_res.size()) { - return _res; - } - try { - auto& tmaker = static_cast(maker); - auto shape = tmaker.GeneratedFace(s); - if (!shape.IsNull()) { - _res.push_back(shape); - } - if (firstProfile.getShape().IsSame(s) || firstProfile.findShape(s)) { - _res.push_back(tmaker.FirstShape()); - } - else if (lastProfile.getShape().IsSame(s) || lastProfile.findShape(s)) { - _res.push_back(tmaker.LastShape()); - } - } - catch (const Standard_Failure& e) { - if (FC_LOG_INSTANCE.isEnabled(FC_LOGLEVEL_LOG)) { - FC_WARN("Exception on shape mapper: " << e.GetMessageString()); - } - } - return _res; - } -}; - -const std::vector& MapperMaker::modified(const TopoDS_Shape& s) const -{ - _res.clear(); - try { - TopTools_ListIteratorOfListOfShape it; - for (it.Initialize(maker.Modified(s)); it.More(); it.Next()) { - _res.push_back(it.Value()); - } - } - catch (const Standard_Failure& e) { - if (FC_LOG_INSTANCE.isEnabled(FC_LOGLEVEL_LOG)) { - FC_WARN("Exception on shape mapper: " << e.GetMessageString()); - } - } - return _res; -} - -const std::vector& MapperMaker::generated(const TopoDS_Shape& s) const -{ - _res.clear(); - try { - TopTools_ListIteratorOfListOfShape it; - for (it.Initialize(maker.Generated(s)); it.More(); it.Next()) { - _res.push_back(it.Value()); - } - } - catch (const Standard_Failure& e) { - if (FC_LOG_INSTANCE.isEnabled(FC_LOGLEVEL_LOG)) { - FC_WARN("Exception on shape mapper: " << e.GetMessageString()); - } - } - return _res; -} - -} // namespace Part