1
// SPDX-License-Identifier: LGPL-2.1-or-later
2
/****************************************************************************
4
* Copyright (c) 2002 Jürgen Riegel <juergen.riegel@web.de> *
6
* This file is part of FreeCAD. *
8
* FreeCAD is free software: you can redistribute it and/or modify it *
9
* under the terms of the GNU Lesser General Public License as *
10
* published by the Free Software Foundation, either version 2.1 of the *
11
* License, or (at your option) any later version. *
13
* FreeCAD is distributed in the hope that it will be useful, but *
14
* WITHOUT ANY WARRANTY; without even the implied warranty of *
15
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
16
* Lesser General Public License for more details. *
18
* You should have received a copy of the GNU Lesser General Public *
19
* License along with FreeCAD. If not, see *
20
* <https://www.gnu.org/licenses/>. *
22
***************************************************************************/
24
#include "PreCompiled.h"
27
#include <BRep_Tool.hxx>
28
#include <TopoDS_Edge.hxx>
31
#include "TopoShapeMapper.h"
37
void ShapeMapper::expand(const TopoDS_Shape& d, std::vector<TopoDS_Shape>& shapes)
42
for (TopExp_Explorer xp(d, TopAbs_FACE); xp.More(); xp.Next()) {
43
shapes.push_back(xp.Current());
45
for (TopExp_Explorer xp(d, TopAbs_EDGE, TopAbs_FACE); xp.More(); xp.Next()) {
46
shapes.push_back(xp.Current());
48
for (TopExp_Explorer xp(d, TopAbs_VERTEX, TopAbs_EDGE); xp.More(); xp.Next()) {
49
shapes.push_back(xp.Current());
53
void ShapeMapper::populate(MappingStatus status,
54
const TopTools_ListOfShape& src,
55
const TopTools_ListOfShape& dst)
57
for (TopTools_ListIteratorOfListOfShape it(src); it.More(); it.Next()) {
58
populate(status, it.Value(), dst);
62
void ShapeMapper::populate(MappingStatus status,
64
const TopTools_ListOfShape& dst)
69
std::vector<TopoDS_Shape> dstShapes;
70
for (TopTools_ListIteratorOfListOfShape it(dst); it.More(); it.Next()) {
71
expand(it.Value(), dstShapes);
73
insert(status, src.getShape(), dstShapes);
74
if (shapeSet.insert(src.getShape()).second) {
75
shapes.push_back(src);
79
void ShapeMapper::insert(MappingStatus status, const TopoDS_Shape& s, const TopoDS_Shape& d)
81
if (s.IsNull() || d.IsNull()) {
84
// Prevent an element shape from being both generated and modified
85
if (status == MappingStatus::Generated) {
86
if (_modifiedShapes.count(d)) {
89
_generatedShapes.insert(d);
92
if (_generatedShapes.count(d)) {
95
_modifiedShapes.insert(d);
97
auto& entry = (status == MappingStatus::Generated) ? _generated[s] : _modified[s];
98
if (entry.shapeSet.insert(d).second) {
99
entry.shapes.push_back(d);
103
void ShapeMapper::insert(MappingStatus status,
104
const TopoDS_Shape& s,
105
const std::vector<TopoDS_Shape>& d)
107
if (s.IsNull() || d.empty()) {
110
auto& entry = (status == MappingStatus::Generated) ? _generated[s] : _modified[s];
111
for (auto& shape : d) {
112
// Prevent an element shape from being both generated and modified
113
if (status == MappingStatus::Generated) {
114
if (_modifiedShapes.count(shape)) {
117
_generatedShapes.insert(shape);
120
if (_generatedShapes.count(shape)) {
123
_modifiedShapes.insert(shape);
125
if (entry.shapeSet.insert(shape).second) {
126
entry.shapes.push_back(shape);
131
void GenericShapeMapper::init(const TopoShape& src, const TopoDS_Shape& dst)
133
for (TopExp_Explorer exp(dst, TopAbs_FACE); exp.More(); exp.Next()) {
134
const TopoDS_Shape& dstFace = exp.Current();
135
if (src.findShape(dstFace)) {
138
#if OCC_VERSION_HEX < 0x070800
139
struct TopoDS_ShapeHasher
141
std::size_t operator()(const TopoDS_Shape& key) const
143
return key.HashCode(IntegerLast());
146
std::unordered_map<TopoDS_Shape, int, TopoDS_ShapeHasher> map;
148
std::unordered_map<TopoDS_Shape, int> map;
152
// Try to find a face in the src that shares at least two edges (or one
153
// closed edge) with dstFace.
154
// TODO: consider degenerative cases of two or more edges on the same line.
155
for (TopExp_Explorer it(dstFace, TopAbs_EDGE); it.More(); it.Next()) {
156
int idx = src.findShape(it.Current());
160
TopoDS_Edge e = TopoDS::Edge(it.Current());
161
if (BRep_Tool::IsClosed(e)) {
162
// closed edge, one face is enough
164
src.findAncestorShape(src.getSubShape(TopAbs_EDGE, idx), TopAbs_FACE);
165
if (!face.IsNull()) {
166
this->insert(MappingStatus::Generated, face, dstFace);
173
src.findAncestorsShapes(src.getSubShape(TopAbs_EDGE, idx), TopAbs_FACE)) {
174
int& cnt = map[face];
176
this->insert(MappingStatus::Generated, face, dstFace);
190
// if no face matches, try search by geometry surface
191
std::unique_ptr<Geometry> g(Geometry::fromShape(dstFace));
196
for (auto& v : map) {
197
std::unique_ptr<Geometry> g2(Geometry::fromShape(v.first));
198
if (g2 && g2->isSame(*g, 1e-7, 1e-12)) {
199
this->insert(MappingStatus::Generated, v.first, dstFace);