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 | // |
973c2be1 | 8 | // This library is free software; you can redistribute it and / or modify it |
9 | // under the terms of the GNU Lesser General Public version 2.1 as published | |
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 | |
17 | #include <BRepOffset_Analyse.ixx> | |
18 | #include <BRepOffset_Interval.hxx> | |
19 | #include <BRepOffset_Tool.hxx> | |
20 | #include <BRepOffset_ListIteratorOfListOfInterval.hxx> | |
21 | #include <BRep_Tool.hxx> | |
22 | #include <BRepTools.hxx> | |
23 | #include <BRep_Builder.hxx> | |
24 | ||
25 | #include <BRepAdaptor_Curve.hxx> | |
26 | ||
27 | #include <gp.hxx> | |
28 | #include <gp_Vec.hxx> | |
29 | #include <gp_Dir.hxx> | |
30 | #include <gp_Pnt.hxx> | |
31 | #include <gp_Pnt2d.hxx> | |
32 | ||
33 | #include <Geom_Surface.hxx> | |
34 | #include <Geom_Curve.hxx> | |
35 | #include <Geom2d_Curve.hxx> | |
36 | ||
37 | #include <TopExp.hxx> | |
38 | #include <TopExp_Explorer.hxx> | |
39 | ||
40 | #include <TopoDS.hxx> | |
41 | #include <TopoDS_Face.hxx> | |
42 | #include <TopoDS_Edge.hxx> | |
43 | #include <TopTools_ListIteratorOfListOfShape.hxx> | |
44 | #include <TopTools_MapOfShape.hxx> | |
45 | ||
46 | #include <Precision.hxx> | |
47 | #include <gp.hxx> | |
48 | ||
49 | ||
50 | //======================================================================= | |
51 | //function : BRepOffset_Analyse | |
52 | //purpose : | |
53 | //======================================================================= | |
54 | ||
55 | BRepOffset_Analyse::BRepOffset_Analyse() | |
56 | :myDone(Standard_False) | |
57 | { | |
58 | } | |
59 | ||
60 | ||
61 | //======================================================================= | |
62 | //function : BRepOffset_Analyse | |
63 | //purpose : | |
64 | //======================================================================= | |
65 | ||
66 | BRepOffset_Analyse::BRepOffset_Analyse(const TopoDS_Shape& S, | |
67 | const Standard_Real Angle) | |
68 | :myDone(Standard_False) | |
69 | { | |
70 | Perform( S, Angle); | |
71 | } | |
72 | ||
73 | //======================================================================= | |
74 | //function : EdgeAnlyse | |
75 | //purpose : | |
76 | //======================================================================= | |
77 | ||
78 | static void EdgeAnalyse(const TopoDS_Edge& E, | |
79 | const TopoDS_Face& F1, | |
80 | const TopoDS_Face& F2, | |
81 | const Standard_Real SinTol, | |
82 | BRepOffset_ListOfInterval& LI) | |
83 | { | |
84 | ||
85 | ||
86 | TopLoc_Location L; | |
87 | Standard_Real f,l; | |
88 | ||
89 | Handle (Geom_Surface) S1 = BRep_Tool::Surface(F1); | |
90 | Handle (Geom_Surface) S2 = BRep_Tool::Surface(F2); | |
91 | Handle (Geom2d_Curve) C1 = BRep_Tool::CurveOnSurface(E,F1,f,l); | |
92 | Handle (Geom2d_Curve) C2 = BRep_Tool::CurveOnSurface(E,F2,f,l); | |
93 | ||
94 | BRepAdaptor_Curve C(E); | |
95 | f = C.FirstParameter(); | |
96 | l = C.LastParameter(); | |
97 | ||
0d969553 | 98 | // Tangent if the regularity is at least G1. |
7fd59977 | 99 | if (BRep_Tool::HasContinuity(E,F1,F2)) { |
100 | if (BRep_Tool::Continuity(E,F1,F2) > GeomAbs_C0) { | |
101 | BRepOffset_Interval I; | |
102 | I.First(f); I.Last(l); | |
103 | I.Type(BRepOffset_Tangent); | |
104 | LI.Append(I); | |
105 | return; | |
106 | } | |
107 | } | |
0d969553 Y |
108 | // First stage : Type determined by one of ends. |
109 | // Calculate normals and tangents on the curves and surface. | |
110 | // normals are oriented outwards. | |
7fd59977 | 111 | |
112 | Standard_Real ParOnC = 0.5*(f+l); | |
113 | gp_Vec T1 = C.DN(ParOnC,1).Transformed(L.Transformation()); | |
114 | if (T1.SquareMagnitude() > gp::Resolution()) { | |
115 | T1.Normalize(); | |
116 | } | |
117 | ||
118 | if (BRepOffset_Tool::OriEdgeInFace(E,F1) == TopAbs_REVERSED) { | |
119 | T1.Reverse(); | |
120 | } | |
121 | if (F1.Orientation() == TopAbs_REVERSED) T1.Reverse(); | |
122 | ||
123 | gp_Pnt2d P = C1->Value(ParOnC); | |
124 | gp_Pnt P3; | |
125 | gp_Vec D1U,D1V; | |
126 | ||
127 | S1->D1(P.X(),P.Y(),P3,D1U,D1V); | |
128 | gp_Vec DN1(D1U^D1V); | |
129 | if (F1.Orientation() == TopAbs_REVERSED) DN1.Reverse(); | |
130 | ||
131 | P = C2->Value(ParOnC); | |
132 | S2->D1(P.X(),P.Y(),P3,D1U,D1V); | |
133 | gp_Vec DN2(D1U^D1V); | |
134 | if (F2.Orientation() == TopAbs_REVERSED) DN2.Reverse(); | |
135 | ||
136 | DN1.Normalize(); | |
137 | DN2.Normalize(); | |
138 | ||
139 | gp_Vec ProVec = DN1^DN2; | |
140 | Standard_Real NormProVec = ProVec.Magnitude(); | |
141 | ||
142 | BRepOffset_Interval I; | |
143 | I.First(f); I.Last(l); | |
144 | ||
145 | if (Abs(NormProVec) < SinTol) { | |
0d969553 | 146 | // plane |
7fd59977 | 147 | if (DN1.Dot(DN2) > 0) { |
148 | //Tangent | |
149 | I.Type(BRepOffset_Tangent); | |
150 | } | |
151 | else { | |
0d969553 | 152 | //Mixed not finished! |
7fd59977 | 153 | #ifdef DEB |
0d969553 | 154 | cout <<" faces locally mixed"<<endl; |
7fd59977 | 155 | #endif |
156 | I.Type(BRepOffset_Convex); | |
157 | } | |
158 | } | |
159 | else { | |
160 | if (NormProVec > gp::Resolution()) | |
161 | ProVec.Normalize(); | |
162 | Standard_Real Prod = T1.Dot(DN1^DN2); | |
163 | if (Prod > 0.) { | |
0d969553 | 164 | // |
7fd59977 | 165 | I.Type(BRepOffset_Convex); |
166 | } | |
167 | else { | |
0d969553 | 168 | //reenters |
7fd59977 | 169 | I.Type(BRepOffset_Concave); |
170 | } | |
171 | } | |
172 | LI.Append(I); | |
173 | } | |
174 | ||
175 | //======================================================================= | |
176 | //function : BuildAncestors | |
177 | //purpose : | |
178 | //======================================================================= | |
179 | ||
180 | static void BuildAncestors (const TopoDS_Shape& S, | |
181 | TopTools_IndexedDataMapOfShapeListOfShape& MA) | |
182 | { | |
183 | MA.Clear(); | |
184 | TopExp::MapShapesAndAncestors(S,TopAbs_VERTEX,TopAbs_EDGE,MA); | |
185 | TopExp::MapShapesAndAncestors(S,TopAbs_EDGE ,TopAbs_FACE,MA); | |
186 | ||
0d969553 | 187 | // Purge ancestors. |
7fd59977 | 188 | TopTools_MapOfShape Map; |
189 | for (Standard_Integer i = 1; i <= MA.Extent(); i++) { | |
190 | Map.Clear(); | |
191 | TopTools_ListOfShape& L = MA(i); | |
192 | TopTools_ListIteratorOfListOfShape it(L); | |
193 | while (it.More()) { | |
194 | if (!Map.Add(it.Value())) { | |
195 | L.Remove(it); | |
196 | } | |
197 | else { | |
198 | it.Next(); | |
199 | } | |
200 | } | |
201 | } | |
202 | } | |
203 | ||
204 | //======================================================================= | |
205 | //function : IsDone | |
206 | //purpose : | |
207 | //======================================================================= | |
208 | ||
209 | Standard_Boolean BRepOffset_Analyse::IsDone() const | |
210 | { | |
211 | return myDone; | |
212 | } | |
213 | ||
214 | ||
215 | //======================================================================= | |
216 | //function : Perform | |
217 | //purpose : | |
218 | //======================================================================= | |
219 | ||
220 | void BRepOffset_Analyse::Perform (const TopoDS_Shape& S, | |
221 | const Standard_Real Angle) | |
222 | { | |
223 | myShape = S; | |
224 | ||
225 | angle = Angle; | |
226 | Standard_Real SinTol = sin(Angle); | |
227 | ||
228 | // Build ancestors. | |
229 | BuildAncestors (S,ancestors); | |
230 | ||
231 | ||
232 | TopExp_Explorer Exp(S.Oriented(TopAbs_FORWARD),TopAbs_EDGE); | |
233 | for ( ; Exp.More(); Exp.Next()) { | |
234 | const TopoDS_Edge& E = TopoDS::Edge(Exp.Current()); | |
235 | if (!mapEdgeType.IsBound(E)) { | |
236 | BRepOffset_ListOfInterval LI; | |
237 | mapEdgeType.Bind(E,LI); | |
238 | ||
239 | const TopTools_ListOfShape& L = Ancestors(E); | |
240 | if ( L.IsEmpty()) | |
241 | continue; | |
242 | ||
243 | if (L.Extent() == 2) { | |
244 | const TopoDS_Face& F1 = TopoDS::Face(L.First()); | |
245 | const TopoDS_Face& F2 = TopoDS::Face(L.Last ()); | |
246 | EdgeAnalyse(E,F1,F2,SinTol,mapEdgeType(E)); | |
247 | } | |
248 | else if (L.Extent() == 1) { | |
249 | Standard_Real U1,U2; | |
250 | const TopoDS_Face& F = TopoDS::Face(L.First()); | |
251 | BRep_Tool::Range(E,F,U1,U2); | |
252 | BRepOffset_Interval Inter(U1,U2,BRepOffset_Other); | |
253 | ||
254 | if (! BRepTools::IsReallyClosed(E,F)) { | |
255 | Inter.Type(BRepOffset_FreeBoundary); | |
256 | } | |
257 | mapEdgeType(E).Append(Inter); | |
258 | } | |
259 | else { | |
260 | #ifdef DEB | |
261 | cout <<"edge shared by more than two faces"<<endl; | |
262 | #endif | |
263 | } | |
264 | } | |
265 | } | |
266 | myDone = Standard_True; | |
267 | } | |
268 | ||
269 | //======================================================================= | |
270 | //function : Clear | |
271 | //purpose : | |
272 | //======================================================================= | |
273 | ||
274 | void BRepOffset_Analyse::Clear() | |
275 | { | |
276 | myDone = Standard_False; | |
277 | myShape .Nullify(); | |
278 | mapEdgeType.Clear(); | |
279 | ancestors .Clear(); | |
280 | } | |
281 | ||
282 | ||
283 | ||
284 | ||
285 | ||
286 | //======================================================================= | |
287 | //function : BRepOffset_ListOfInterval& | |
288 | //purpose : | |
289 | //======================================================================= | |
290 | ||
291 | const BRepOffset_ListOfInterval& BRepOffset_Analyse::Type(const TopoDS_Edge& E) | |
292 | const | |
293 | { | |
294 | return mapEdgeType (E); | |
295 | } | |
296 | ||
297 | ||
298 | //======================================================================= | |
299 | //function : Edges | |
300 | //purpose : | |
301 | //======================================================================= | |
302 | ||
303 | void BRepOffset_Analyse::Edges(const TopoDS_Vertex& V, | |
304 | const BRepOffset_Type T, | |
305 | TopTools_ListOfShape& LE) | |
306 | const | |
307 | { | |
308 | LE.Clear(); | |
309 | const TopTools_ListOfShape& L = Ancestors (V); | |
310 | TopTools_ListIteratorOfListOfShape it(L); | |
311 | ||
312 | for ( ;it.More(); it.Next()) { | |
313 | const TopoDS_Edge& E = TopoDS::Edge(it.Value()); | |
314 | TopoDS_Vertex V1,V2; | |
315 | BRepOffset_Tool::EdgeVertices (E,V1,V2); | |
316 | if (V1.IsSame(V)) { | |
317 | if (mapEdgeType(E).Last().Type() == T) | |
318 | LE.Append(E); | |
319 | } | |
320 | if (V2.IsSame(V)) { | |
321 | if (mapEdgeType(E).First().Type() == T) | |
322 | LE.Append(E); | |
323 | } | |
324 | } | |
325 | } | |
326 | ||
327 | ||
328 | //======================================================================= | |
329 | //function : Edges | |
330 | //purpose : | |
331 | //======================================================================= | |
332 | ||
333 | void BRepOffset_Analyse::Edges(const TopoDS_Face& F, | |
334 | const BRepOffset_Type T, | |
335 | TopTools_ListOfShape& LE) | |
336 | const | |
337 | { | |
338 | LE.Clear(); | |
339 | TopExp_Explorer exp(F, TopAbs_EDGE); | |
340 | ||
341 | for ( ;exp.More(); exp.Next()) { | |
342 | const TopoDS_Edge& E = TopoDS::Edge(exp.Current()); | |
343 | ||
344 | const BRepOffset_ListOfInterval& Lint = Type(E); | |
345 | BRepOffset_ListIteratorOfListOfInterval it(Lint); | |
346 | for ( ;it.More(); it.Next()) { | |
347 | if (it.Value().Type() == T) LE.Append(E); | |
348 | } | |
349 | } | |
350 | } | |
351 | ||
352 | //======================================================================= | |
353 | //function : TangentEdges | |
354 | //purpose : | |
355 | //======================================================================= | |
356 | ||
357 | void BRepOffset_Analyse::TangentEdges(const TopoDS_Edge& Edge , | |
358 | const TopoDS_Vertex& Vertex, | |
359 | TopTools_ListOfShape& Edges ) const | |
360 | { | |
361 | gp_Vec V,VRef; | |
362 | ||
363 | ||
364 | Standard_Real U,URef; | |
365 | BRepAdaptor_Curve C3d, C3dRef; | |
366 | ||
367 | URef = BRep_Tool::Parameter(Vertex,Edge); | |
368 | C3dRef = BRepAdaptor_Curve(Edge); | |
369 | VRef = C3dRef.DN(URef,1); | |
370 | if (VRef.SquareMagnitude() < gp::Resolution()) return; | |
371 | ||
372 | Edges.Clear(); | |
373 | ||
374 | const TopTools_ListOfShape& Anc = Ancestors(Vertex); | |
375 | TopTools_ListIteratorOfListOfShape it(Anc); | |
376 | for ( ; it.More(); it.Next()) { | |
377 | const TopoDS_Edge& CurE = TopoDS::Edge(it.Value()); | |
378 | if ( CurE.IsSame(Edge)) continue; | |
379 | U = BRep_Tool::Parameter(Vertex,CurE); | |
380 | C3d = BRepAdaptor_Curve(CurE); | |
381 | V = C3d.DN(U,1); | |
382 | if (V.SquareMagnitude() < gp::Resolution()) continue; | |
383 | if (V.IsParallel(VRef,angle)) { | |
384 | Edges.Append(CurE); | |
385 | } | |
386 | } | |
387 | } | |
388 | ||
389 | ||
390 | ||
391 | //======================================================================= | |
392 | //function : HasAncestor | |
393 | //purpose : | |
394 | //======================================================================= | |
395 | ||
396 | Standard_Boolean BRepOffset_Analyse::HasAncestor (const TopoDS_Shape& S) const | |
397 | { | |
398 | return ancestors.Contains(S); | |
399 | } | |
400 | ||
401 | ||
402 | //======================================================================= | |
403 | //function : Ancestors | |
404 | //purpose : | |
405 | //======================================================================= | |
406 | ||
407 | const TopTools_ListOfShape& BRepOffset_Analyse::Ancestors | |
408 | (const TopoDS_Shape& S) const | |
409 | { | |
410 | return ancestors.FindFromKey(S); | |
411 | } | |
412 | ||
413 | ||
414 | //======================================================================= | |
415 | //function : Explode | |
416 | //purpose : | |
417 | //======================================================================= | |
418 | ||
419 | void BRepOffset_Analyse::Explode( TopTools_ListOfShape& List, | |
420 | const BRepOffset_Type T ) const | |
421 | { | |
422 | List.Clear(); | |
423 | BRep_Builder B; | |
424 | TopTools_MapOfShape Map; | |
425 | ||
426 | TopExp_Explorer Fexp; | |
427 | for (Fexp.Init(myShape,TopAbs_FACE); Fexp.More(); Fexp.Next()) { | |
428 | if ( Map.Add(Fexp.Current())) { | |
429 | TopoDS_Face Face = TopoDS::Face(Fexp.Current()); | |
430 | TopoDS_Compound Co; | |
431 | B.MakeCompound(Co); | |
432 | B.Add(Co,Face); | |
0d969553 Y |
433 | // add to Co all faces from the cloud of faces |
434 | // G1 created from <Face> | |
7fd59977 | 435 | AddFaces(Face,Co,Map,T); |
436 | List.Append(Co); | |
437 | } | |
438 | } | |
439 | } | |
440 | ||
441 | //======================================================================= | |
442 | //function : Explode | |
443 | //purpose : | |
444 | //======================================================================= | |
445 | ||
446 | void BRepOffset_Analyse::Explode( TopTools_ListOfShape& List, | |
447 | const BRepOffset_Type T1, | |
448 | const BRepOffset_Type T2) const | |
449 | { | |
450 | List.Clear(); | |
451 | BRep_Builder B; | |
452 | TopTools_MapOfShape Map; | |
453 | ||
454 | TopExp_Explorer Fexp; | |
455 | for (Fexp.Init(myShape,TopAbs_FACE); Fexp.More(); Fexp.Next()) { | |
456 | if ( Map.Add(Fexp.Current())) { | |
457 | TopoDS_Face Face = TopoDS::Face(Fexp.Current()); | |
458 | TopoDS_Compound Co; | |
459 | B.MakeCompound(Co); | |
460 | B.Add(Co,Face); | |
0d969553 Y |
461 | // add to Co all faces from the cloud of faces |
462 | // G1 created from <Face> | |
7fd59977 | 463 | AddFaces(Face,Co,Map,T1,T2); |
464 | List.Append(Co); | |
465 | } | |
466 | } | |
467 | } | |
468 | ||
469 | ||
470 | //======================================================================= | |
471 | //function : AddFaces | |
472 | //purpose : | |
473 | //======================================================================= | |
474 | ||
475 | void BRepOffset_Analyse::AddFaces (const TopoDS_Face& Face, | |
476 | TopoDS_Compound& Co, | |
477 | TopTools_MapOfShape& Map, | |
478 | const BRepOffset_Type T) const | |
479 | { | |
480 | BRep_Builder B; | |
481 | TopExp_Explorer exp(Face,TopAbs_EDGE); | |
482 | for ( ; exp.More(); exp.Next()) { | |
483 | const TopoDS_Edge& E = TopoDS::Edge(exp.Current()); | |
484 | const BRepOffset_ListOfInterval& LI = Type(E); | |
485 | if (!LI.IsEmpty() && LI.First().Type() == T) { | |
0d969553 | 486 | // so <NewFace> is attached to G1 by <Face> |
7fd59977 | 487 | const TopTools_ListOfShape& L = Ancestors(E); |
488 | if (L.Extent() == 2) { | |
489 | TopoDS_Face F1 = TopoDS::Face(L.First()); | |
490 | if ( F1.IsSame(Face)) | |
491 | F1 = TopoDS::Face(L.Last ()); | |
492 | if ( Map.Add(F1)) { | |
493 | B.Add(Co,F1); | |
494 | AddFaces(F1,Co,Map,T); | |
495 | } | |
496 | } | |
497 | } | |
498 | } | |
499 | } | |
500 | //======================================================================= | |
501 | //function : AddFaces | |
502 | //purpose : | |
503 | //======================================================================= | |
504 | ||
505 | void BRepOffset_Analyse::AddFaces (const TopoDS_Face& Face, | |
506 | TopoDS_Compound& Co, | |
507 | TopTools_MapOfShape& Map, | |
508 | const BRepOffset_Type T1, | |
509 | const BRepOffset_Type T2) const | |
510 | { | |
511 | BRep_Builder B; | |
512 | TopExp_Explorer exp(Face,TopAbs_EDGE); | |
513 | for ( ; exp.More(); exp.Next()) { | |
514 | const TopoDS_Edge& E = TopoDS::Edge(exp.Current()); | |
515 | const BRepOffset_ListOfInterval& LI = Type(E); | |
516 | if (!LI.IsEmpty() && | |
517 | (LI.First().Type() == T1 || LI.First().Type() == T2)) { | |
0d969553 | 518 | // so <NewFace> is attached to G1 by <Face> |
7fd59977 | 519 | const TopTools_ListOfShape& L = Ancestors(E); |
520 | if (L.Extent() == 2) { | |
521 | TopoDS_Face F1 = TopoDS::Face(L.First()); | |
522 | if ( F1.IsSame(Face)) | |
523 | F1 = TopoDS::Face(L.Last ()); | |
524 | if ( Map.Add(F1)) { | |
525 | B.Add(Co,F1); | |
526 | AddFaces(F1,Co,Map,T1,T2); | |
527 | } | |
528 | } | |
529 | } | |
530 | } | |
531 | } |