Files
create/src/Mod/Part/App/TopoShapeExpansion.cpp
2023-12-27 21:16:59 -06:00

200 lines
5.9 KiB
C++

// SPDX-License-Identifier: LGPL-2.1-or-later
/****************************************************************************
* *
* Copyright (c) 2022 Zheng, Lei <realthunder.dev@gmail.com> *
* 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 *
* <https://www.gnu.org/licenses/>. *
* *
***************************************************************************/
#include <BRep_Tool.hxx>
#include "PreCompiled.h"
#include "TopoShape.h"
#include "TopoShapeCache.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<TopoShapeCache>(_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<int> TopoShape::findAncestors(const TopoDS_Shape& subshape, TopAbs_ShapeEnum type) const
{
const auto& shapes = findAncestorsShapes(subshape, type);
std::vector<int> ret;
ret.reserve(shapes.size());
for (const auto& shape : shapes) {
ret.push_back(findShape(shape));
}
return ret;
}
std::vector<TopoDS_Shape> TopoShape::findAncestorsShapes(const TopoDS_Shape& subshape,
TopAbs_ShapeEnum type) const
{
initCache();
std::vector<TopoDS_Shape> shapes;
_cache->findAncestor(_Shape, subshape, type, &shapes);
return shapes;
}
} // namespace Part