FreeCAD

Форк
0
/
BRepOffsetAPI_MakeOffsetFix.cpp 
290 строк · 9.4 Кб
1
/***************************************************************************
2
 *   Copyright (c) 2019 Werner Mayer <wmayer[at]users.sourceforge.net>     *
3
 *                                                                         *
4
 *   This file is part of the FreeCAD CAx development system.              *
5
 *                                                                         *
6
 *   This library is free software; you can redistribute it and/or         *
7
 *   modify it under the terms of the GNU Library General Public           *
8
 *   License as published by the Free Software Foundation; either          *
9
 *   version 2 of the License, or (at your option) any later version.      *
10
 *                                                                         *
11
 *   This library  is distributed in the hope that it will be useful,      *
12
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
13
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
14
 *   GNU Library General Public License for more details.                  *
15
 *                                                                         *
16
 *   You should have received a copy of the GNU Library General Public     *
17
 *   License along with this library; see the file COPYING.LIB. If not,    *
18
 *   write to the Free Software Foundation, Inc., 59 Temple Place,         *
19
 *   Suite 330, Boston, MA  02111-1307, USA                                *
20
 *                                                                         *
21
 ***************************************************************************/
22

23
#include "PreCompiled.h"
24
#ifndef _PreComp_
25
# include <BRep_Builder.hxx>
26
# include <BRepAdaptor_Curve.hxx>
27
# include <BRepBuilderAPI_MakeEdge.hxx>
28
# include <BRepBuilderAPI_MakeWire.hxx>
29
# include <Geom_BSplineCurve.hxx>
30
# include <Precision.hxx>
31
# include <ShapeConstruct_Curve.hxx>
32
# include <Standard_ConstructionError.hxx>
33
# include <Standard_Version.hxx>
34
# include <TopExp_Explorer.hxx>
35
# include <TopLoc_Location.hxx>
36
# include <TopoDS.hxx>
37
# include <TopoDS_Compound.hxx>
38
# include <TopoDS_Edge.hxx>
39
# include <TopoDS_Wire.hxx>
40
# include <TopTools_ListIteratorOfListOfShape.hxx>
41
# include <TopTools_ListOfShape.hxx>
42
# include <TopTools_MapOfShape.hxx>
43
#endif
44

45
#include "BRepOffsetAPI_MakeOffsetFix.h"
46

47

48
using namespace Part;
49

50
BRepOffsetAPI_MakeOffsetFix::BRepOffsetAPI_MakeOffsetFix() = default;
51

52
BRepOffsetAPI_MakeOffsetFix::BRepOffsetAPI_MakeOffsetFix(const GeomAbs_JoinType Join, const Standard_Boolean IsOpenResult)
53
{
54
    mkOffset.Init(Join, IsOpenResult);
55
}
56

57
BRepOffsetAPI_MakeOffsetFix::~BRepOffsetAPI_MakeOffsetFix() = default;
58

59
void BRepOffsetAPI_MakeOffsetFix::AddWire(const TopoDS_Wire& Spine)
60
{
61
    TopoDS_Wire wire = Spine;
62
    int numEdges = 0;
63
    TopExp_Explorer xp(wire, TopAbs_EDGE);
64
    while (xp.More()) {
65
        numEdges++;
66
        xp.Next();
67
    }
68
    if (numEdges == 1) {
69
        TopLoc_Location edgeLocation;
70

71
        BRepBuilderAPI_MakeWire mkWire;
72
        TopExp_Explorer xp(wire, TopAbs_EDGE);
73
        while (xp.More()) {
74
            // The trick is to reset the placement of an edge before
75
            // passing it to BRepOffsetAPI_MakeOffset because then it
76
            // will create the expected result.
77
            // Afterwards apply the placement again on the result shape.
78
            // See the method MakeWire()
79
            TopoDS_Edge edge = TopoDS::Edge(xp.Current());
80
            edgeLocation = edge.Location();
81
            edge.Location(TopLoc_Location());
82
            mkWire.Add(edge);
83
            myLocations.emplace_back(edge, edgeLocation);
84
            xp.Next();
85
        }
86

87
        wire = mkWire.Wire();
88

89
        // Make sure that the new wire has the same orientation as the source wire
90
        // because otherwise the offset will shrink the wire
91
        wire.Orientation(Spine.Orientation());
92
    }
93
    mkOffset.AddWire(wire);
94
    myResult.Nullify();
95
}
96

97
void BRepOffsetAPI_MakeOffsetFix::Perform (const Standard_Real Offset, const Standard_Real Alt)
98
{
99
    mkOffset.Perform(Offset, Alt);
100
}
101

102
#if OCC_VERSION_HEX >= 0x070600
103
void BRepOffsetAPI_MakeOffsetFix::Build(const Message_ProgressRange&)
104
#else
105
void BRepOffsetAPI_MakeOffsetFix::Build()
106
#endif
107
{
108
    mkOffset.Build();
109
}
110

111
void BRepOffsetAPI_MakeOffsetFix::Init(const TopoDS_Face& Spine, const GeomAbs_JoinType Join,
112
                                       const Standard_Boolean IsOpenResult)
113
{
114
    mkOffset.Init(Spine, Join, IsOpenResult);
115
}
116

117
void BRepOffsetAPI_MakeOffsetFix::Init(const GeomAbs_JoinType Join, const Standard_Boolean IsOpenResult)
118
{
119
    mkOffset.Init(Join, IsOpenResult);
120
}
121

122
Standard_Boolean BRepOffsetAPI_MakeOffsetFix::IsDone() const
123
{
124
    return mkOffset.IsDone();
125
}
126

127
void BRepOffsetAPI_MakeOffsetFix::MakeWire(TopoDS_Shape& wire)
128
{
129
    // get the edges of the wire and check which of the stored edges
130
    // serve as input of the wire
131
    TopTools_MapOfShape aMap;
132
    TopExp_Explorer xp(wire, TopAbs_EDGE);
133
    while (xp.More()) {
134
        aMap.Add(xp.Current());
135
        xp.Next();
136
    }
137

138
    std::list<TopoDS_Edge> edgeList;
139
    for (const auto& itLoc : myLocations) {
140
        TopTools_ListOfShape newShapes = mkOffset.Generated(itLoc.first);
141
        // Check generated shapes for the vertexes, too
142
        TopExp_Explorer xpv(itLoc.first, TopAbs_VERTEX);
143
        while (xpv.More()) {
144
            TopTools_ListOfShape newEdge = mkOffset.Generated(xpv.Current());
145
            if (!newEdge.IsEmpty()) {
146
                newShapes.Append(newEdge);
147
            }
148
            xpv.Next();
149
        }
150
        for (TopTools_ListIteratorOfListOfShape it(newShapes); it.More(); it.Next()) {
151
            TopoDS_Shape newShape = it.Value();
152

153
            if (aMap.Contains(newShape)) {
154
                newShape.Move(itLoc.second);
155
                edgeList.push_back(TopoDS::Edge(newShape));
156
            }
157
        }
158
    }
159

160
    if (!edgeList.empty()) {
161
        BRepBuilderAPI_MakeWire mkWire;
162
        mkWire.Add(edgeList.front());
163
        edgeList.pop_front();
164
        wire = mkWire.Wire();
165

166
        bool found = false;
167
        do {
168
            found = false;
169
            for (std::list<TopoDS_Edge>::iterator pE = edgeList.begin(); pE != edgeList.end(); ++pE) {
170
                mkWire.Add(*pE);
171
                if (mkWire.Error() != BRepBuilderAPI_DisconnectedWire) {
172
                    // edge added ==> remove it from list
173
                    found = true;
174
                    edgeList.erase(pE);
175
                    wire = mkWire.Wire();
176
                    break;
177
                }
178
            }
179
        }
180
        while (found);
181
    }
182
}
183

184
const TopoDS_Shape& BRepOffsetAPI_MakeOffsetFix::Shape()
185
{
186
    if (myResult.IsNull()) {
187
        TopoDS_Shape result = mkOffset.Shape();
188
        if (result.IsNull()) {
189
            myResult = result;
190
            return myResult;
191
        }
192

193
        if (result.ShapeType() == TopAbs_WIRE) {
194
            MakeWire(result);
195
        }
196
        else if (result.ShapeType() == TopAbs_COMPOUND) {
197
            BRep_Builder builder;
198
            TopoDS_Compound comp;
199
            builder.MakeCompound(comp);
200

201
            TopExp_Explorer xp(result, TopAbs_WIRE);
202
            while (xp.More()) {
203
                TopoDS_Wire wire = TopoDS::Wire(xp.Current());
204
                MakeWire(wire);
205
                builder.Add(comp, wire);
206
                xp.Next();
207
            }
208

209
            result = comp;
210
        }
211

212
        myResult = result;
213
    }
214
    return myResult;
215
}
216

217
const TopTools_ListOfShape& BRepOffsetAPI_MakeOffsetFix::Generated(const TopoDS_Shape& S)
218
{
219
    return mkOffset.Generated(S);
220
}
221

222
const TopTools_ListOfShape& BRepOffsetAPI_MakeOffsetFix::Modified (const TopoDS_Shape& S)
223
{
224
    return mkOffset.Modified(S);
225
}
226

227
Standard_Boolean BRepOffsetAPI_MakeOffsetFix::IsDeleted (const TopoDS_Shape& S)
228
{
229
    return mkOffset.IsDeleted(S);
230
}
231

232
TopoDS_Shape BRepOffsetAPI_MakeOffsetFix::Replace(GeomAbs_CurveType type, const TopoDS_Shape& S) const
233
{
234
    if (S.IsNull())
235
        throw Standard_ConstructionError("Input shape is null");
236

237
    // Nothing to do
238
    if (type == GeomAbs_BSplineCurve)
239
        return S;
240

241
    if (S.ShapeType() == TopAbs_COMPOUND) {
242
        BRep_Builder builder;
243
        TopoDS_Compound comp;
244
        builder.MakeCompound(comp);
245
        comp.Location(S.Location());
246

247
        TopExp_Explorer xp(S, TopAbs_WIRE);
248
        while (xp.More()) {
249
            TopoDS_Wire wire = TopoDS::Wire(xp.Current());
250
            wire = ReplaceEdges(type, wire);
251
            builder.Add(comp, wire);
252
            xp.Next();
253
        }
254

255
        return TopoDS_Compound(std::move(comp));
256
    }
257
    else if (S.ShapeType() == TopAbs_WIRE) {
258
        return ReplaceEdges(type, TopoDS::Wire(S));
259
    }
260
    else {
261
        throw Standard_ConstructionError("Wrong shape type");
262
    }
263
}
264

265
TopoDS_Wire BRepOffsetAPI_MakeOffsetFix::ReplaceEdges(GeomAbs_CurveType type, const TopoDS_Wire& wire) const
266
{
267
    BRepBuilderAPI_MakeWire mkWire;
268
    for (TopExp_Explorer xp(wire, TopAbs_EDGE); xp.More(); xp.Next()) {
269
        TopoDS_Edge edge = TopoDS::Edge(xp.Current());
270
        TopLoc_Location edgeLocation = edge.Location();
271

272
        BRepAdaptor_Curve curve(edge);
273

274
        if (curve.GetType() == type) {
275
            ShapeConstruct_Curve scc;
276
            double u = curve.FirstParameter();
277
            double v = curve.LastParameter();
278
            Handle(Geom_BSplineCurve) spline = scc.ConvertToBSpline(curve.Curve().Curve(), u, v, Precision::Confusion());
279
            if (!spline.IsNull()) {
280
                BRepBuilderAPI_MakeEdge mkEdge(spline, u, v);
281
                edge = mkEdge.Edge();
282
                edge.Location(edgeLocation);
283
            }
284
        }
285

286
        mkWire.Add(edge);
287
    }
288

289
    return mkWire.Wire();
290
}
291

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

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

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

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