0024530: TKMesh - remove unused package IntPoly
[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//
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
55BRepOffset_Analyse::BRepOffset_Analyse()
56:myDone(Standard_False)
57{
58}
59
60
61//=======================================================================
62//function : BRepOffset_Analyse
63//purpose :
64//=======================================================================
65
66BRepOffset_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
78static 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
180static 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
209Standard_Boolean BRepOffset_Analyse::IsDone() const
210{
211 return myDone;
212}
213
214
215//=======================================================================
216//function : Perform
217//purpose :
218//=======================================================================
219
220void 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
274void 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
291const BRepOffset_ListOfInterval& BRepOffset_Analyse::Type(const TopoDS_Edge& E)
292const
293{
294 return mapEdgeType (E);
295}
296
297
298//=======================================================================
299//function : Edges
300//purpose :
301//=======================================================================
302
303void BRepOffset_Analyse::Edges(const TopoDS_Vertex& V,
304 const BRepOffset_Type T,
305 TopTools_ListOfShape& LE)
306const
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
333void BRepOffset_Analyse::Edges(const TopoDS_Face& F,
334 const BRepOffset_Type T,
335 TopTools_ListOfShape& LE)
336const
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
357void 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
396Standard_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
407const 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
419void 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
446void 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
475void 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
505void 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}