Salome HOME
Mantis issue 0021453: EDF GEOM: (regression). A fix by PKV.
[modules/geom.git] / src / GEOMImpl / GEOMImpl_Fillet2dDriver.cxx
1 // Copyright (C) 2007-2011  CEA/DEN, EDF R&D, OPEN CASCADE
2 //
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Lesser General Public
5 // License as published by the Free Software Foundation; either
6 // version 2.1 of the License.
7 //
8 // This library is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11 // Lesser General Public License for more details.
12 //
13 // You should have received a copy of the GNU Lesser General Public
14 // License along with this library; if not, write to the Free Software
15 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
16 //
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
18
19 #include <Standard_Stream.hxx>
20
21 #include <GEOMImpl_Fillet2dDriver.hxx>
22 #include <GEOMImpl_IFillet2d.hxx>
23 #include <GEOMImpl_Types.hxx>
24 #include <GEOMImpl_ILocalOperations.hxx>
25 #include <GEOMImpl_Block6Explorer.hxx>
26 #include <GEOM_Function.hxx>
27
28 #include <BRepFilletAPI_MakeFillet2d.hxx>
29 #include <BRepCheck_Analyzer.hxx>
30 #include <BRep_Tool.hxx>
31 #include <BRep_Builder.hxx>
32
33 #include <TopoDS.hxx>
34 #include <TopoDS_Shape.hxx>
35 #include <TopoDS_Edge.hxx>
36 #include <TopoDS_Iterator.hxx>
37 #include <TopAbs.hxx>
38 #include <TopExp_Explorer.hxx>
39 #include <TopTools_IndexedDataMapOfShapeListOfShape.hxx>
40 #include <TopTools_ListIteratorOfListOfShape.hxx>
41
42 #include <ShapeFix_ShapeTolerance.hxx>
43 #include <ShapeFix_Shape.hxx>
44
45 #include <Precision.hxx>
46 #include <gp_Pnt.hxx>
47 #include <StdFail_NotDone.hxx>
48
49 //=======================================================================
50 //function : GetID
51 //purpose  :
52 //=======================================================================
53 const Standard_GUID& GEOMImpl_Fillet2dDriver::GetID()
54 {
55   static Standard_GUID aFillet2dDriver("FF1AAB41-2A14-4df2-581B-3A568163BA46");
56   return aFillet2dDriver;
57 }
58
59
60 //=======================================================================
61 //function : GEOMImpl_Fillet2dDriver
62 //purpose  :
63 //=======================================================================
64 GEOMImpl_Fillet2dDriver::GEOMImpl_Fillet2dDriver()
65 {
66 }
67
68 //=======================================================================
69 //function : Execute
70 //purpose  :
71 //=======================================================================
72 Standard_Integer GEOMImpl_Fillet2dDriver::Execute(TFunction_Logbook& log) const
73 {
74   if (Label().IsNull()) return 0;
75   Handle(GEOM_Function) aFunction = GEOM_Function::GetFunction(Label());
76
77   GEOMImpl_IFillet2d aCI (aFunction);
78
79   TopoDS_Shape aShape;
80
81   Handle(GEOM_Function) aRefShape = aCI.GetShape();
82   TopoDS_Shape aFaceShape = aRefShape->GetValue();
83
84   int aLen = aCI.GetLength();
85   double rad = aCI.GetR();
86
87   if (aFaceShape.ShapeType() == TopAbs_FACE) {
88     BRepFilletAPI_MakeFillet2d fillet2d (TopoDS::Face(aFaceShape));
89
90     int ind = 1;
91     for (; ind <= aLen; ind++) {
92       TopoDS_Shape aShapeVertex;
93       if (GEOMImpl_ILocalOperations::GetSubShape
94           (aFaceShape, aCI.GetVertex(ind), aShapeVertex)) {
95         fillet2d.AddFillet(TopoDS::Vertex(aShapeVertex), rad);
96       }
97     }
98
99     fillet2d.Build();
100     if (!fillet2d.IsDone()) {
101       StdFail_NotDone::Raise("2D Fillet can't be computed on the given shape with the given radius");
102     }
103     aShape = fillet2d.Shape();
104   }
105   else if (aFaceShape.ShapeType() == TopAbs_SHELL) {
106     // 1. Map vertices to faces to build fillets only on corner vertices
107     TopTools_IndexedDataMapOfShapeListOfShape mapVertexFaces;
108     GEOMImpl_Block6Explorer::MapShapesAndAncestors
109       (aFaceShape, TopAbs_VERTEX, TopAbs_FACE, mapVertexFaces);
110
111     // 2. Map faces to vertices
112     TopTools_IndexedDataMapOfShapeListOfShape mapFaceVertices;
113     TopTools_ListOfShape empty;
114     int ind = 1;
115     for (; ind <= aLen; ind++) {
116       TopoDS_Shape aVi;
117       if (GEOMImpl_ILocalOperations::GetSubShape(aFaceShape, aCI.GetVertex(ind), aVi)) {
118         Standard_Integer aVi_index = mapVertexFaces.FindIndex(aVi);
119         if (aVi_index > 0) {
120           const TopTools_ListOfShape& aFacesOfVi = mapVertexFaces(aVi_index);
121           if (aFacesOfVi.Extent() == 1) { // we use only corner vertices of shell
122             TopoDS_Shape aFi = aFacesOfVi.First();
123             Standard_Integer aFi_index = mapFaceVertices.FindIndex(aFi);
124             if (aFi_index == 0) aFi_index = mapFaceVertices.Add(aFi, empty);
125             mapFaceVertices(aFi_index).Append(aVi);
126           }
127         }
128       }
129     }
130
131     // 3. Build fillet on each given vertex
132     TopoDS_Shell aResult;
133     BRep_Builder B;
134     B.MakeShell(aResult);
135
136     TopoDS_Iterator It (aFaceShape, Standard_True, Standard_True);
137     TopTools_MapOfShape mapShape;
138     for (; It.More(); It.Next()) {
139       if (mapShape.Add(It.Value())) {
140         Standard_Integer aFi_index = mapFaceVertices.FindIndex(It.Value());
141         if (aFi_index == 0) {
142           // No fillets requested on this face, add it as is
143           B.Add(aResult, It.Value());
144         }
145         else {
146           // Build a fillet and add the changed face
147           BRepFilletAPI_MakeFillet2d fillet2d (TopoDS::Face(It.Value()));
148           const TopTools_ListOfShape& aVertsOfFi = mapFaceVertices(aFi_index);
149           TopTools_ListIteratorOfListOfShape itV (aVertsOfFi);
150           for (; itV.More(); itV.Next()) {
151             fillet2d.AddFillet(TopoDS::Vertex(itV.Value()), rad);
152           }
153
154           fillet2d.Build();
155           if (!fillet2d.IsDone()) {
156             StdFail_NotDone::Raise("2D Fillet can't be computed on the given shape with the given radius");
157           }
158           TopoDS_Shape aFillet = fillet2d.Shape();
159
160           B.Add(aResult, aFillet);
161         }
162       }
163     }
164
165     // 4. Build a shell
166     // ?TODO?
167     aShape = aResult;
168   }
169   else {
170     Standard_ConstructionError::Raise("Wrong arguments: a face or a shell must be given");
171   }
172
173   if (aShape.IsNull()) return 0;
174
175   aFunction->SetValue(aShape);
176   log.SetTouched(Label());
177
178   return 1;
179 }
180
181
182 //=======================================================================
183 //function :  GEOMImpl_Fillet2dDriver_Type_
184 //purpose  :
185 //=======================================================================
186 Standard_EXPORT Handle_Standard_Type& GEOMImpl_Fillet2dDriver_Type_()
187 {
188   static Handle_Standard_Type aType1 = STANDARD_TYPE(TFunction_Driver);
189   if ( aType1.IsNull()) aType1 = STANDARD_TYPE(TFunction_Driver);
190   static Handle_Standard_Type aType2 = STANDARD_TYPE(MMgt_TShared);
191   if ( aType2.IsNull()) aType2 = STANDARD_TYPE(MMgt_TShared);
192   static Handle_Standard_Type aType3 = STANDARD_TYPE(Standard_Transient);
193   if ( aType3.IsNull()) aType3 = STANDARD_TYPE(Standard_Transient);
194
195   static Handle_Standard_Transient _Ancestors[]= {aType1,aType2,aType3,NULL};
196   static Handle_Standard_Type _aType = new Standard_Type("GEOMImpl_Fillet2dDriver",
197                                                          sizeof(GEOMImpl_Fillet2dDriver),
198                                                          1,
199                                                          (Standard_Address)_Ancestors,
200                                                          (Standard_Address)NULL);
201
202   return _aType;
203 }
204
205 //=======================================================================
206 //function : DownCast
207 //purpose  :
208 //=======================================================================
209 const Handle(GEOMImpl_Fillet2dDriver) Handle(GEOMImpl_Fillet2dDriver)::DownCast
210                                    (const Handle(Standard_Transient)& AnObject)
211 {
212   Handle(GEOMImpl_Fillet2dDriver) _anOtherObject;
213
214   if (!AnObject.IsNull()) {
215      if (AnObject->IsKind(STANDARD_TYPE(GEOMImpl_Fillet2dDriver))) {
216        _anOtherObject = Handle(GEOMImpl_Fillet2dDriver)((Handle(GEOMImpl_Fillet2dDriver)&)AnObject);
217      }
218   }
219
220   return _anOtherObject;
221 }