0030940: BRepFilletAPI_MakeFillet algorithm fails on closed shell
[occt.git] / src / BRepOffset / BRepOffset_Analyse.cxx
CommitLineData
b311480e 1// Created on: 1995-10-20
2// Created by: Yves FRICAUD
3// Copyright (c) 1995-1999 Matra Datavision
973c2be1 4// Copyright (c) 1999-2014 OPEN CASCADE SAS
b311480e 5//
973c2be1 6// This file is part of Open CASCADE Technology software library.
b311480e 7//
d5f74e42 8// This library is free software; you can redistribute it and/or modify it under
9// the terms of the GNU Lesser General Public License version 2.1 as published
973c2be1 10// by the Free Software Foundation, with special exception defined in the file
11// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
12// distribution for complete text of the license and disclaimer of any warranty.
b311480e 13//
973c2be1 14// Alternatively, this file may be used under the terms of Open CASCADE
15// commercial license or contractual agreement.
7fd59977 16
42cf5bc1 17
18#include <Adaptor3d_Surface.hxx>
19#include <BRep_Builder.hxx>
20#include <BRep_Tool.hxx>
21#include <BRepAdaptor_Curve.hxx>
22#include <BRepAdaptor_Surface.hxx>
23#include <BRepOffset_Analyse.hxx>
7fd59977 24#include <BRepOffset_Interval.hxx>
7fd59977 25#include <BRepOffset_ListIteratorOfListOfInterval.hxx>
42cf5bc1 26#include <BRepOffset_Tool.hxx>
7fd59977 27#include <BRepTools.hxx>
42cf5bc1 28#include <Geom2d_Curve.hxx>
29#include <Geom_Curve.hxx>
30#include <Geom_Surface.hxx>
7fd59977 31#include <gp.hxx>
7fd59977 32#include <gp_Dir.hxx>
33#include <gp_Pnt.hxx>
34#include <gp_Pnt2d.hxx>
42cf5bc1 35#include <gp_Vec.hxx>
36#include <Precision.hxx>
7fd59977 37#include <TopExp.hxx>
38#include <TopExp_Explorer.hxx>
7fd59977 39#include <TopoDS.hxx>
42cf5bc1 40#include <TopoDS_Compound.hxx>
7fd59977 41#include <TopoDS_Edge.hxx>
42cf5bc1 42#include <TopoDS_Face.hxx>
43#include <TopoDS_Shape.hxx>
44#include <TopoDS_Vertex.hxx>
7fd59977 45#include <TopTools_ListIteratorOfListOfShape.hxx>
46#include <TopTools_MapOfShape.hxx>
eff3eff9 47#include <ChFi3d.hxx>
7fd59977 48
d804b26d 49static void CorrectOrientationOfTangent(gp_Vec& TangVec,
50 const TopoDS_Vertex& aVertex,
51 const TopoDS_Edge& anEdge)
52{
53 TopoDS_Vertex Vlast = TopExp::LastVertex(anEdge);
54 if (aVertex.IsSame(Vlast))
55 TangVec.Reverse();
56}
7fd59977 57//=======================================================================
58//function : BRepOffset_Analyse
59//purpose :
60//=======================================================================
61
62BRepOffset_Analyse::BRepOffset_Analyse()
63:myDone(Standard_False)
64{
65}
66
67
68//=======================================================================
69//function : BRepOffset_Analyse
70//purpose :
71//=======================================================================
72
73BRepOffset_Analyse::BRepOffset_Analyse(const TopoDS_Shape& S,
74 const Standard_Real Angle)
75:myDone(Standard_False)
76{
77 Perform( S, Angle);
78}
79
80//=======================================================================
81//function : EdgeAnlyse
82//purpose :
83//=======================================================================
84
85static void EdgeAnalyse(const TopoDS_Edge& E,
b0091bc9 86 const TopoDS_Face& F1,
87 const TopoDS_Face& F2,
88 const Standard_Real SinTol,
89 BRepOffset_ListOfInterval& LI)
7fd59977 90{
7fd59977 91
7fd59977 92 Standard_Real f,l;
b0091bc9 93 BRep_Tool::Range(E, F1, f, l);
94 BRepOffset_Interval I;
95 I.First(f); I.Last(l);
96 //
0d969553 97 // Tangent if the regularity is at least G1.
7fd59977 98 if (BRep_Tool::HasContinuity(E,F1,F2)) {
99 if (BRep_Tool::Continuity(E,F1,F2) > GeomAbs_C0) {
eff3eff9 100 I.Type(ChFiDS_Tangential);
7fd59977 101 LI.Append(I);
102 return;
103 }
104 }
b0091bc9 105 //
eff3eff9 106 ChFiDS_TypeOfConcavity aType = ChFi3d::DefineConnectType(E, F1, F2,
107 SinTol, Standard_False);
108 if(aType != ChFiDS_Tangential)
b0091bc9 109 {
eff3eff9 110 aType = ChFi3d::DefineConnectType(E, F1, F2, SinTol, Standard_True);
7fd59977 111 }
b0091bc9 112 I.Type(aType);
7fd59977 113 LI.Append(I);
114}
115
116//=======================================================================
117//function : BuildAncestors
118//purpose :
119//=======================================================================
120
121static void BuildAncestors (const TopoDS_Shape& S,
f1191d30 122 TopTools_IndexedDataMapOfShapeListOfShape& MA)
7fd59977 123{
124 MA.Clear();
f1191d30 125 TopExp::MapShapesAndUniqueAncestors(S,TopAbs_VERTEX,TopAbs_EDGE,MA);
126 TopExp::MapShapesAndUniqueAncestors(S,TopAbs_EDGE ,TopAbs_FACE,MA);
7fd59977 127}
128
129//=======================================================================
130//function : IsDone
131//purpose :
132//=======================================================================
133
134Standard_Boolean BRepOffset_Analyse::IsDone() const
135{
136 return myDone;
137}
138
139
140//=======================================================================
141//function : Perform
142//purpose :
143//=======================================================================
144
145void BRepOffset_Analyse::Perform (const TopoDS_Shape& S,
146 const Standard_Real Angle)
147{
148 myShape = S;
149
150 angle = Angle;
03383c97 151 Standard_Real SinTol = Sin(Angle);
7fd59977 152
153 // Build ancestors.
154 BuildAncestors (S,ancestors);
155
156
157 TopExp_Explorer Exp(S.Oriented(TopAbs_FORWARD),TopAbs_EDGE);
158 for ( ; Exp.More(); Exp.Next()) {
159 const TopoDS_Edge& E = TopoDS::Edge(Exp.Current());
160 if (!mapEdgeType.IsBound(E)) {
161 BRepOffset_ListOfInterval LI;
162 mapEdgeType.Bind(E,LI);
163
164 const TopTools_ListOfShape& L = Ancestors(E);
165 if ( L.IsEmpty())
166 continue;
167
168 if (L.Extent() == 2) {
169 const TopoDS_Face& F1 = TopoDS::Face(L.First());
170 const TopoDS_Face& F2 = TopoDS::Face(L.Last ());
171 EdgeAnalyse(E,F1,F2,SinTol,mapEdgeType(E));
172 }
173 else if (L.Extent() == 1) {
174 Standard_Real U1,U2;
175 const TopoDS_Face& F = TopoDS::Face(L.First());
176 BRep_Tool::Range(E,F,U1,U2);
eff3eff9 177 BRepOffset_Interval Inter(U1,U2,ChFiDS_Other);
7fd59977 178
179 if (! BRepTools::IsReallyClosed(E,F)) {
eff3eff9 180 Inter.Type(ChFiDS_FreeBound);
7fd59977 181 }
182 mapEdgeType(E).Append(Inter);
183 }
184 else {
0797d9d3 185#ifdef OCCT_DEBUG
04232180 186 std::cout <<"edge shared by more than two faces"<<std::endl;
7fd59977 187#endif
188 }
189 }
190 }
191 myDone = Standard_True;
192}
193
194//=======================================================================
195//function : Clear
196//purpose :
197//=======================================================================
198
199void BRepOffset_Analyse::Clear()
200{
201 myDone = Standard_False;
202 myShape .Nullify();
203 mapEdgeType.Clear();
204 ancestors .Clear();
205}
206
207
208
209
210
211//=======================================================================
212//function : BRepOffset_ListOfInterval&
213//purpose :
214//=======================================================================
215
216const BRepOffset_ListOfInterval& BRepOffset_Analyse::Type(const TopoDS_Edge& E)
217const
218{
219 return mapEdgeType (E);
220}
221
222
223//=======================================================================
224//function : Edges
225//purpose :
226//=======================================================================
227
228void BRepOffset_Analyse::Edges(const TopoDS_Vertex& V,
eff3eff9 229 const ChFiDS_TypeOfConcavity T,
7fd59977 230 TopTools_ListOfShape& LE)
231const
232{
233 LE.Clear();
234 const TopTools_ListOfShape& L = Ancestors (V);
235 TopTools_ListIteratorOfListOfShape it(L);
236
237 for ( ;it.More(); it.Next()) {
238 const TopoDS_Edge& E = TopoDS::Edge(it.Value());
239 TopoDS_Vertex V1,V2;
240 BRepOffset_Tool::EdgeVertices (E,V1,V2);
241 if (V1.IsSame(V)) {
242 if (mapEdgeType(E).Last().Type() == T)
243 LE.Append(E);
244 }
245 if (V2.IsSame(V)) {
246 if (mapEdgeType(E).First().Type() == T)
247 LE.Append(E);
248 }
249 }
250}
251
252
253//=======================================================================
254//function : Edges
255//purpose :
256//=======================================================================
257
258void BRepOffset_Analyse::Edges(const TopoDS_Face& F,
eff3eff9 259 const ChFiDS_TypeOfConcavity T,
7fd59977 260 TopTools_ListOfShape& LE)
261const
262{
263 LE.Clear();
264 TopExp_Explorer exp(F, TopAbs_EDGE);
265
266 for ( ;exp.More(); exp.Next()) {
267 const TopoDS_Edge& E = TopoDS::Edge(exp.Current());
268
269 const BRepOffset_ListOfInterval& Lint = Type(E);
270 BRepOffset_ListIteratorOfListOfInterval it(Lint);
271 for ( ;it.More(); it.Next()) {
272 if (it.Value().Type() == T) LE.Append(E);
273 }
274 }
275}
276
277//=======================================================================
278//function : TangentEdges
279//purpose :
280//=======================================================================
281
282void BRepOffset_Analyse::TangentEdges(const TopoDS_Edge& Edge ,
283 const TopoDS_Vertex& Vertex,
284 TopTools_ListOfShape& Edges ) const
285{
286 gp_Vec V,VRef;
287
288
289 Standard_Real U,URef;
290 BRepAdaptor_Curve C3d, C3dRef;
291
292 URef = BRep_Tool::Parameter(Vertex,Edge);
293 C3dRef = BRepAdaptor_Curve(Edge);
294 VRef = C3dRef.DN(URef,1);
d804b26d 295 CorrectOrientationOfTangent(VRef, Vertex, Edge);
7fd59977 296 if (VRef.SquareMagnitude() < gp::Resolution()) return;
297
298 Edges.Clear();
299
300 const TopTools_ListOfShape& Anc = Ancestors(Vertex);
301 TopTools_ListIteratorOfListOfShape it(Anc);
302 for ( ; it.More(); it.Next()) {
303 const TopoDS_Edge& CurE = TopoDS::Edge(it.Value());
304 if ( CurE.IsSame(Edge)) continue;
305 U = BRep_Tool::Parameter(Vertex,CurE);
306 C3d = BRepAdaptor_Curve(CurE);
307 V = C3d.DN(U,1);
d804b26d 308 CorrectOrientationOfTangent(V, Vertex, CurE);
7fd59977 309 if (V.SquareMagnitude() < gp::Resolution()) continue;
d804b26d 310 if (V.IsOpposite(VRef,angle)) {
7fd59977 311 Edges.Append(CurE);
312 }
313 }
314}
315
316
317
318//=======================================================================
319//function : HasAncestor
320//purpose :
321//=======================================================================
322
323Standard_Boolean BRepOffset_Analyse::HasAncestor (const TopoDS_Shape& S) const
324{
325 return ancestors.Contains(S);
326}
327
328
329//=======================================================================
330//function : Ancestors
331//purpose :
332//=======================================================================
333
334const TopTools_ListOfShape& BRepOffset_Analyse::Ancestors
335(const TopoDS_Shape& S) const
336{
337 return ancestors.FindFromKey(S);
338}
339
340
341//=======================================================================
342//function : Explode
343//purpose :
344//=======================================================================
345
eff3eff9 346void BRepOffset_Analyse::Explode( TopTools_ListOfShape& List,
347 const ChFiDS_TypeOfConcavity T ) const
7fd59977 348{
349 List.Clear();
350 BRep_Builder B;
351 TopTools_MapOfShape Map;
352
353 TopExp_Explorer Fexp;
354 for (Fexp.Init(myShape,TopAbs_FACE); Fexp.More(); Fexp.Next()) {
355 if ( Map.Add(Fexp.Current())) {
356 TopoDS_Face Face = TopoDS::Face(Fexp.Current());
357 TopoDS_Compound Co;
358 B.MakeCompound(Co);
359 B.Add(Co,Face);
0d969553
Y
360 // add to Co all faces from the cloud of faces
361 // G1 created from <Face>
7fd59977 362 AddFaces(Face,Co,Map,T);
363 List.Append(Co);
364 }
365 }
366}
367
368//=======================================================================
369//function : Explode
370//purpose :
371//=======================================================================
372
eff3eff9 373void BRepOffset_Analyse::Explode( TopTools_ListOfShape& List,
374 const ChFiDS_TypeOfConcavity T1,
375 const ChFiDS_TypeOfConcavity T2) const
7fd59977 376{
377 List.Clear();
378 BRep_Builder B;
379 TopTools_MapOfShape Map;
380
381 TopExp_Explorer Fexp;
382 for (Fexp.Init(myShape,TopAbs_FACE); Fexp.More(); Fexp.Next()) {
383 if ( Map.Add(Fexp.Current())) {
384 TopoDS_Face Face = TopoDS::Face(Fexp.Current());
385 TopoDS_Compound Co;
386 B.MakeCompound(Co);
387 B.Add(Co,Face);
0d969553
Y
388 // add to Co all faces from the cloud of faces
389 // G1 created from <Face>
7fd59977 390 AddFaces(Face,Co,Map,T1,T2);
391 List.Append(Co);
392 }
393 }
394}
395
396
397//=======================================================================
398//function : AddFaces
399//purpose :
400//=======================================================================
401
402void BRepOffset_Analyse::AddFaces (const TopoDS_Face& Face,
403 TopoDS_Compound& Co,
404 TopTools_MapOfShape& Map,
eff3eff9 405 const ChFiDS_TypeOfConcavity T) const
7fd59977 406{
407 BRep_Builder B;
408 TopExp_Explorer exp(Face,TopAbs_EDGE);
409 for ( ; exp.More(); exp.Next()) {
410 const TopoDS_Edge& E = TopoDS::Edge(exp.Current());
411 const BRepOffset_ListOfInterval& LI = Type(E);
412 if (!LI.IsEmpty() && LI.First().Type() == T) {
0d969553 413 // so <NewFace> is attached to G1 by <Face>
7fd59977 414 const TopTools_ListOfShape& L = Ancestors(E);
415 if (L.Extent() == 2) {
416 TopoDS_Face F1 = TopoDS::Face(L.First());
417 if ( F1.IsSame(Face))
418 F1 = TopoDS::Face(L.Last ());
419 if ( Map.Add(F1)) {
420 B.Add(Co,F1);
421 AddFaces(F1,Co,Map,T);
422 }
423 }
424 }
425 }
426}
427//=======================================================================
428//function : AddFaces
429//purpose :
430//=======================================================================
431
432void BRepOffset_Analyse::AddFaces (const TopoDS_Face& Face,
433 TopoDS_Compound& Co,
434 TopTools_MapOfShape& Map,
eff3eff9 435 const ChFiDS_TypeOfConcavity T1,
436 const ChFiDS_TypeOfConcavity T2) const
7fd59977 437{
438 BRep_Builder B;
439 TopExp_Explorer exp(Face,TopAbs_EDGE);
440 for ( ; exp.More(); exp.Next()) {
441 const TopoDS_Edge& E = TopoDS::Edge(exp.Current());
442 const BRepOffset_ListOfInterval& LI = Type(E);
443 if (!LI.IsEmpty() &&
444 (LI.First().Type() == T1 || LI.First().Type() == T2)) {
0d969553 445 // so <NewFace> is attached to G1 by <Face>
7fd59977 446 const TopTools_ListOfShape& L = Ancestors(E);
447 if (L.Extent() == 2) {
448 TopoDS_Face F1 = TopoDS::Face(L.First());
449 if ( F1.IsSame(Face))
450 F1 = TopoDS::Face(L.Last ());
451 if ( Map.Add(F1)) {
452 B.Add(Co,F1);
453 AddFaces(F1,Co,Map,T1,T2);
454 }
455 }
456 }
457 }
458}
b0091bc9 459