FreeCAD

Форк
0
/
FeaturePartFuse.cpp 
220 строк · 9.3 Кб
1
/***************************************************************************
2
 *   Copyright (c) 2007 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 <BRepAlgoAPI_Fuse.hxx>
26
# include <BRepCheck_Analyzer.hxx>
27
# include <Standard_Failure.hxx>
28
# include <TopoDS_Iterator.hxx>
29
# include <TopExp.hxx>
30
# include <TopTools_IndexedMapOfShape.hxx>
31
#endif
32

33
#include <App/Application.h>
34
#include <Base/Console.h>
35
#include <Base/Parameter.h>
36

37
#include "FeaturePartFuse.h"
38
#include "TopoShape.h"
39
#include "modelRefine.h"
40
#include "TopoShapeOpCode.h"
41

42
FC_LOG_LEVEL_INIT("Part",true,true);
43

44
using namespace Part;
45

46
PROPERTY_SOURCE(Part::Fuse, Part::Boolean)
47

48

49
Fuse::Fuse() = default;
50

51
BRepAlgoAPI_BooleanOperation* Fuse::makeOperation(const TopoDS_Shape& base, const TopoDS_Shape& tool) const
52
{
53
    // Let's call algorithm computing a fuse operation:
54
    return new BRepAlgoAPI_Fuse(base, tool);
55
}
56

57
const char *Fuse::opCode() const
58
{
59
    return Part::OpCodes::Fuse;
60
}
61

62
// ----------------------------------------------------
63

64
PROPERTY_SOURCE(Part::MultiFuse, Part::Feature)
65

66

67
MultiFuse::MultiFuse()
68
{
69
    ADD_PROPERTY(Shapes,(nullptr));
70
    Shapes.setSize(0);
71
    ADD_PROPERTY_TYPE(History,(ShapeHistory()), "Boolean", (App::PropertyType)
72
        (App::Prop_Output|App::Prop_Transient|App::Prop_Hidden), "Shape history");
73
    History.setSize(0);
74

75
    ADD_PROPERTY_TYPE(Refine,(0),"Boolean",(App::PropertyType)(App::Prop_None),"Refine shape (clean up redundant edges) after this boolean operation");
76

77
    //init Refine property
78
    Base::Reference<ParameterGrp> hGrp = App::GetApplication().GetUserParameter()
79
        .GetGroup("BaseApp")->GetGroup("Preferences")->GetGroup("Mod/Part/Boolean");
80
    this->Refine.setValue(hGrp->GetBool("RefineModel", false));
81

82
}
83

84
short MultiFuse::mustExecute() const
85
{
86
    if (Shapes.isTouched())
87
        return 1;
88
    return 0;
89
}
90

91
App::DocumentObjectExecReturn *MultiFuse::execute()
92
{
93
    std::vector<TopoShape> shapes;
94
    std::vector<App::DocumentObject*> obj = Shapes.getValues();
95

96
    std::vector<App::DocumentObject*>::iterator it;
97
    for (it = obj.begin(); it != obj.end(); ++it) {
98
        shapes.push_back(Feature::getTopoShape(*it));
99
    }
100

101
    bool argumentsAreInCompound = false;
102
    TopoShape compoundOfArguments;
103

104
    // if only one source shape, and it is a compound - fuse children of the compound
105
    if (shapes.size() == 1) {
106
        compoundOfArguments = shapes[0];
107
        if (compoundOfArguments.getShape().ShapeType() == TopAbs_COMPOUND) {
108
            shapes.clear();
109
            shapes = compoundOfArguments.getSubTopoShapes();
110
            argumentsAreInCompound = true;
111
        }
112
    }
113

114
    if (shapes.size() >= 2) {
115
        try {
116
            std::vector<ShapeHistory> history;
117
            BRepAlgoAPI_Fuse mkFuse;
118
            TopTools_ListOfShape shapeArguments, shapeTools;
119
            const TopoShape& shape = shapes.front();
120
            if (shape.isNull()) {
121
                throw Base::RuntimeError("Input shape is null");
122
            }
123
            shapeArguments.Append(shape.getShape());
124

125
            for (auto it2 = shapes.begin() + 1; it2 != shapes.end(); ++it2) {
126
                if (it2->isNull()) {
127
                    throw Base::RuntimeError("Input shape is null");
128
                }
129
                shapeTools.Append(it2->getShape());
130
            }
131

132
            mkFuse.SetArguments(shapeArguments);
133
            mkFuse.SetTools(shapeTools);
134
            mkFuse.Build();
135

136
            if (!mkFuse.IsDone()) {
137
                throw Base::RuntimeError("MultiFusion failed");
138
            }
139

140
            TopoShape res(0);
141
            res = res.makeShapeWithElementMap(mkFuse.Shape(), MapperMaker(mkFuse), shapes, OpCodes::Fuse);
142
            for (const auto& it2 : shapes) {
143
                history.push_back(
144
                    buildHistory(mkFuse, TopAbs_FACE, res.getShape(), it2.getShape()));
145
            }
146
            if (res.isNull()) {
147
                throw Base::RuntimeError("Resulting shape is null");
148
            }
149

150
            Base::Reference<ParameterGrp> hGrp = App::GetApplication()
151
                                                     .GetUserParameter()
152
                                                     .GetGroup("BaseApp")
153
                                                     ->GetGroup("Preferences")
154
                                                     ->GetGroup("Mod/Part/Boolean");
155
            if (hGrp->GetBool("CheckModel", true)) {
156
                BRepCheck_Analyzer aChecker(res.getShape());
157
                if (!aChecker.IsValid()) {
158
                    return new App::DocumentObjectExecReturn("Resulting shape is invalid");
159
                }
160
            }
161
            if (this->Refine.getValue()) {
162
                try {
163
                    TopoDS_Shape oldShape = res.getShape();
164
                    BRepBuilderAPI_RefineModel mkRefine(oldShape);
165
                    // We just built an element map above for the fuse, don't erase it for a refine.
166
                    res.setShape(mkRefine.Shape(), false);
167
                    ShapeHistory hist =
168
                            buildHistory(mkRefine, TopAbs_FACE, res.getShape(), oldShape);
169
                    for (auto& jt : history) {
170
                        jt = joinHistory(jt, hist);
171
                    }
172
                }
173
                catch (Standard_Failure&) {
174
                    // do nothing
175
                }
176
            }
177

178
            if (argumentsAreInCompound) {
179
                // combine histories of every child of source compound into one
180
                ShapeHistory overallHist;
181
                TopTools_IndexedMapOfShape facesOfCompound;
182
                TopAbs_ShapeEnum type = TopAbs_FACE;
183
                TopExp::MapShapes(compoundOfArguments.getShape(), type, facesOfCompound);
184
                for (std::size_t iChild = 0; iChild < history.size();
185
                     iChild++) {  // loop over children of source compound
186
                    // for each face of a child, find the inex of the face in compound, and assign
187
                    // the corresponding right-hand-size of the history
188
                    TopTools_IndexedMapOfShape facesOfChild;
189
                    TopExp::MapShapes(shapes[iChild].getShape(), type, facesOfChild);
190
                    for (std::pair<const int, ShapeHistory::List>& histitem :
191
                         history[iChild].shapeMap) {  // loop over elements of history - that is -
192
                                                      // over faces of the child of source compound
193
                        int iFaceInChild = histitem.first;
194
                        ShapeHistory::List& iFacesInResult = histitem.second;
195
                        const TopoDS_Shape& srcFace = facesOfChild(
196
                            iFaceInChild
197
                            + 1);  //+1 to convert our 0-based to OCC 1-bsed conventions
198
                        int iFaceInCompound = facesOfCompound.FindIndex(srcFace) - 1;
199
                        overallHist.shapeMap[iFaceInCompound] =
200
                            iFacesInResult;  // this may overwrite existing info if the same face is
201
                                             // used in several children of compound. This shouldn't
202
                                             // be a problem, because the histories should match
203
                                             // anyway...
204
                    }
205
                }
206
                history.clear();
207
                history.push_back(overallHist);
208
            }
209
            this->Shape.setValue(res);
210
            this->History.setValues(history);
211
            return Part::Feature::execute();
212
        }
213
        catch (Standard_Failure& e) {
214
            return new App::DocumentObjectExecReturn(e.GetMessageString());
215
        }
216
    }
217
    else {
218
        throw Base::CADKernelError("Not enough shape objects linked");
219
    }
220
}
221

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

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

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

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