FreeCAD

Форк
0
/
TopoShapeMapper.cpp 
206 строк · 7.1 Кб
1
// SPDX-License-Identifier: LGPL-2.1-or-later
2
/****************************************************************************
3
 *                                                                          *
4
 *   Copyright (c) 2002 Jürgen Riegel <juergen.riegel@web.de>               *
5
 *                                                                          *
6
 *   This file is part of FreeCAD.                                          *
7
 *                                                                          *
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.                        *
12
 *                                                                          *
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.                        *
17
 *                                                                          *
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/>.                                       *
21
 *                                                                          *
22
 ***************************************************************************/
23

24
#include "PreCompiled.h"
25

26
#ifndef _PreComp_
27
#include <BRep_Tool.hxx>
28
#include <TopoDS_Edge.hxx>
29
#endif
30

31
#include "TopoShapeMapper.h"
32
#include "Geometry.h"
33

34
namespace Part
35
{
36

37
void ShapeMapper::expand(const TopoDS_Shape& d, std::vector<TopoDS_Shape>& shapes)
38
{
39
    if (d.IsNull()) {
40
        return;
41
    }
42
    for (TopExp_Explorer xp(d, TopAbs_FACE); xp.More(); xp.Next()) {
43
        shapes.push_back(xp.Current());
44
    }
45
    for (TopExp_Explorer xp(d, TopAbs_EDGE, TopAbs_FACE); xp.More(); xp.Next()) {
46
        shapes.push_back(xp.Current());
47
    }
48
    for (TopExp_Explorer xp(d, TopAbs_VERTEX, TopAbs_EDGE); xp.More(); xp.Next()) {
49
        shapes.push_back(xp.Current());
50
    }
51
}
52

53
void ShapeMapper::populate(MappingStatus status,
54
                           const TopTools_ListOfShape& src,
55
                           const TopTools_ListOfShape& dst)
56
{
57
    for (TopTools_ListIteratorOfListOfShape it(src); it.More(); it.Next()) {
58
        populate(status, it.Value(), dst);
59
    }
60
}
61

62
void ShapeMapper::populate(MappingStatus status,
63
                           const TopoShape& src,
64
                           const TopTools_ListOfShape& dst)
65
{
66
    if (src.isNull()) {
67
        return;
68
    }
69
    std::vector<TopoDS_Shape> dstShapes;
70
    for (TopTools_ListIteratorOfListOfShape it(dst); it.More(); it.Next()) {
71
        expand(it.Value(), dstShapes);
72
    }
73
    insert(status, src.getShape(), dstShapes);
74
    if (shapeSet.insert(src.getShape()).second) {
75
        shapes.push_back(src);
76
    }
77
}
78

79
void ShapeMapper::insert(MappingStatus status, const TopoDS_Shape& s, const TopoDS_Shape& d)
80
{
81
    if (s.IsNull() || d.IsNull()) {
82
        return;
83
    }
84
    // Prevent an element shape from being both generated and modified
85
    if (status == MappingStatus::Generated) {
86
        if (_modifiedShapes.count(d)) {
87
            return;
88
        }
89
        _generatedShapes.insert(d);
90
    }
91
    else {
92
        if (_generatedShapes.count(d)) {
93
            return;
94
        }
95
        _modifiedShapes.insert(d);
96
    }
97
    auto& entry = (status == MappingStatus::Generated) ? _generated[s] : _modified[s];
98
    if (entry.shapeSet.insert(d).second) {
99
        entry.shapes.push_back(d);
100
    }
101
};
102

103
void ShapeMapper::insert(MappingStatus status,
104
                         const TopoDS_Shape& s,
105
                         const std::vector<TopoDS_Shape>& d)
106
{
107
    if (s.IsNull() || d.empty()) {
108
        return;
109
    }
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)) {
115
                continue;
116
            }
117
            _generatedShapes.insert(shape);
118
        }
119
        else {
120
            if (_generatedShapes.count(shape)) {
121
                continue;
122
            }
123
            _modifiedShapes.insert(shape);
124
        }
125
        if (entry.shapeSet.insert(shape).second) {
126
            entry.shapes.push_back(shape);
127
        }
128
    }
129
};
130

131
void GenericShapeMapper::init(const TopoShape& src, const TopoDS_Shape& dst)
132
{
133
    for (TopExp_Explorer exp(dst, TopAbs_FACE); exp.More(); exp.Next()) {
134
        const TopoDS_Shape& dstFace = exp.Current();
135
        if (src.findShape(dstFace)) {
136
            continue;
137
        }
138
#if OCC_VERSION_HEX < 0x070800
139
        struct TopoDS_ShapeHasher
140
        {
141
            std::size_t operator()(const TopoDS_Shape& key) const
142
            {
143
                return key.HashCode(IntegerLast());
144
            }
145
        };
146
        std::unordered_map<TopoDS_Shape, int, TopoDS_ShapeHasher> map;
147
#else
148
        std::unordered_map<TopoDS_Shape, int> map;
149
#endif
150
        bool found = false;
151

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());
157
            if (!idx) {
158
                continue;
159
            }
160
            TopoDS_Edge e = TopoDS::Edge(it.Current());
161
            if (BRep_Tool::IsClosed(e)) {
162
                // closed edge, one face is enough
163
                TopoDS_Shape face =
164
                    src.findAncestorShape(src.getSubShape(TopAbs_EDGE, idx), TopAbs_FACE);
165
                if (!face.IsNull()) {
166
                    this->insert(MappingStatus::Generated, face, dstFace);
167
                    found = true;
168
                    break;
169
                }
170
                continue;
171
            }
172
            for (auto& face :
173
                 src.findAncestorsShapes(src.getSubShape(TopAbs_EDGE, idx), TopAbs_FACE)) {
174
                int& cnt = map[face];
175
                if (++cnt == 2) {
176
                    this->insert(MappingStatus::Generated, face, dstFace);
177
                    found = true;
178
                    break;
179
                }
180
                if (found) {
181
                    break;
182
                }
183
            }
184
        }
185

186
        if (found) {
187
            continue;
188
        }
189

190
        // if no face matches, try search by geometry surface
191
        std::unique_ptr<Geometry> g(Geometry::fromShape(dstFace));
192
        if (!g) {
193
            continue;
194
        }
195

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);
200
                break;
201
            }
202
        }
203
    }
204
}
205

206
}  // namespace Part
207

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.