Commit | Line | Data |
---|---|---|
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 | 49 | static 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 | ||
62 | BRepOffset_Analyse::BRepOffset_Analyse() | |
63 | :myDone(Standard_False) | |
64 | { | |
65 | } | |
66 | ||
67 | ||
68 | //======================================================================= | |
69 | //function : BRepOffset_Analyse | |
70 | //purpose : | |
71 | //======================================================================= | |
72 | ||
73 | BRepOffset_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 | ||
85 | static 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 | ||
121 | static 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 | ||
134 | Standard_Boolean BRepOffset_Analyse::IsDone() const | |
135 | { | |
136 | return myDone; | |
137 | } | |
138 | ||
139 | ||
140 | //======================================================================= | |
141 | //function : Perform | |
142 | //purpose : | |
143 | //======================================================================= | |
144 | ||
145 | void 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 | ||
199 | void 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 | ||
216 | const BRepOffset_ListOfInterval& BRepOffset_Analyse::Type(const TopoDS_Edge& E) | |
217 | const | |
218 | { | |
219 | return mapEdgeType (E); | |
220 | } | |
221 | ||
222 | ||
223 | //======================================================================= | |
224 | //function : Edges | |
225 | //purpose : | |
226 | //======================================================================= | |
227 | ||
228 | void BRepOffset_Analyse::Edges(const TopoDS_Vertex& V, | |
eff3eff9 | 229 | const ChFiDS_TypeOfConcavity T, |
7fd59977 | 230 | TopTools_ListOfShape& LE) |
231 | const | |
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 | ||
258 | void BRepOffset_Analyse::Edges(const TopoDS_Face& F, | |
eff3eff9 | 259 | const ChFiDS_TypeOfConcavity T, |
7fd59977 | 260 | TopTools_ListOfShape& LE) |
261 | const | |
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 | ||
282 | void 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 | ||
323 | Standard_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 | ||
334 | const 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 | 346 | void 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 | 373 | void 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 | ||
402 | void 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 | ||
432 | void 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 |