1 // Created on: 1995-10-20
2 // Created by: Yves FRICAUD
3 // Copyright (c) 1995-1999 Matra Datavision
4 // Copyright (c) 1999-2014 OPEN CASCADE SAS
6 // This file is part of Open CASCADE Technology software library.
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
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.
14 // Alternatively, this file may be used under the terms of Open CASCADE
15 // commercial license or contractual agreement.
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>
25 #include <BRepAdaptor_Curve.hxx>
31 #include <gp_Pnt2d.hxx>
33 #include <Geom_Surface.hxx>
34 #include <Geom_Curve.hxx>
35 #include <Geom2d_Curve.hxx>
38 #include <TopExp_Explorer.hxx>
41 #include <TopoDS_Face.hxx>
42 #include <TopoDS_Edge.hxx>
43 #include <TopTools_ListIteratorOfListOfShape.hxx>
44 #include <TopTools_MapOfShape.hxx>
46 #include <Precision.hxx>
50 //=======================================================================
51 //function : BRepOffset_Analyse
53 //=======================================================================
55 BRepOffset_Analyse::BRepOffset_Analyse()
56 :myDone(Standard_False)
61 //=======================================================================
62 //function : BRepOffset_Analyse
64 //=======================================================================
66 BRepOffset_Analyse::BRepOffset_Analyse(const TopoDS_Shape& S,
67 const Standard_Real Angle)
68 :myDone(Standard_False)
73 //=======================================================================
74 //function : EdgeAnlyse
76 //=======================================================================
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)
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);
94 BRepAdaptor_Curve C(E);
95 f = C.FirstParameter();
96 l = C.LastParameter();
98 // Tangent if the regularity is at least G1.
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);
108 // First stage : Type determined by one of ends.
109 // Calculate normals and tangents on the curves and surface.
110 // normals are oriented outwards.
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()) {
118 if (BRepOffset_Tool::OriEdgeInFace(E,F1) == TopAbs_REVERSED) {
121 if (F1.Orientation() == TopAbs_REVERSED) T1.Reverse();
123 gp_Pnt2d P = C1->Value(ParOnC);
127 S1->D1(P.X(),P.Y(),P3,D1U,D1V);
129 if (F1.Orientation() == TopAbs_REVERSED) DN1.Reverse();
131 P = C2->Value(ParOnC);
132 S2->D1(P.X(),P.Y(),P3,D1U,D1V);
134 if (F2.Orientation() == TopAbs_REVERSED) DN2.Reverse();
139 gp_Vec ProVec = DN1^DN2;
140 Standard_Real NormProVec = ProVec.Magnitude();
142 BRepOffset_Interval I;
143 I.First(f); I.Last(l);
145 if (Abs(NormProVec) < SinTol) {
147 if (DN1.Dot(DN2) > 0) {
149 I.Type(BRepOffset_Tangent);
152 //Mixed not finished!
154 cout <<" faces locally mixed"<<endl;
156 I.Type(BRepOffset_Convex);
160 if (NormProVec > gp::Resolution())
162 Standard_Real Prod = T1.Dot(DN1^DN2);
165 I.Type(BRepOffset_Convex);
169 I.Type(BRepOffset_Concave);
175 //=======================================================================
176 //function : BuildAncestors
178 //=======================================================================
180 static void BuildAncestors (const TopoDS_Shape& S,
181 TopTools_IndexedDataMapOfShapeListOfShape& MA)
184 TopExp::MapShapesAndAncestors(S,TopAbs_VERTEX,TopAbs_EDGE,MA);
185 TopExp::MapShapesAndAncestors(S,TopAbs_EDGE ,TopAbs_FACE,MA);
188 TopTools_MapOfShape Map;
189 for (Standard_Integer i = 1; i <= MA.Extent(); i++) {
191 TopTools_ListOfShape& L = MA(i);
192 TopTools_ListIteratorOfListOfShape it(L);
194 if (!Map.Add(it.Value())) {
204 //=======================================================================
207 //=======================================================================
209 Standard_Boolean BRepOffset_Analyse::IsDone() const
215 //=======================================================================
218 //=======================================================================
220 void BRepOffset_Analyse::Perform (const TopoDS_Shape& S,
221 const Standard_Real Angle)
226 Standard_Real SinTol = sin(Angle);
229 BuildAncestors (S,ancestors);
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);
239 const TopTools_ListOfShape& L = Ancestors(E);
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));
248 else if (L.Extent() == 1) {
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);
254 if (! BRepTools::IsReallyClosed(E,F)) {
255 Inter.Type(BRepOffset_FreeBoundary);
257 mapEdgeType(E).Append(Inter);
261 cout <<"edge shared by more than two faces"<<endl;
266 myDone = Standard_True;
269 //=======================================================================
272 //=======================================================================
274 void BRepOffset_Analyse::Clear()
276 myDone = Standard_False;
286 //=======================================================================
287 //function : BRepOffset_ListOfInterval&
289 //=======================================================================
291 const BRepOffset_ListOfInterval& BRepOffset_Analyse::Type(const TopoDS_Edge& E)
294 return mapEdgeType (E);
298 //=======================================================================
301 //=======================================================================
303 void BRepOffset_Analyse::Edges(const TopoDS_Vertex& V,
304 const BRepOffset_Type T,
305 TopTools_ListOfShape& LE)
309 const TopTools_ListOfShape& L = Ancestors (V);
310 TopTools_ListIteratorOfListOfShape it(L);
312 for ( ;it.More(); it.Next()) {
313 const TopoDS_Edge& E = TopoDS::Edge(it.Value());
315 BRepOffset_Tool::EdgeVertices (E,V1,V2);
317 if (mapEdgeType(E).Last().Type() == T)
321 if (mapEdgeType(E).First().Type() == T)
328 //=======================================================================
331 //=======================================================================
333 void BRepOffset_Analyse::Edges(const TopoDS_Face& F,
334 const BRepOffset_Type T,
335 TopTools_ListOfShape& LE)
339 TopExp_Explorer exp(F, TopAbs_EDGE);
341 for ( ;exp.More(); exp.Next()) {
342 const TopoDS_Edge& E = TopoDS::Edge(exp.Current());
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);
352 //=======================================================================
353 //function : TangentEdges
355 //=======================================================================
357 void BRepOffset_Analyse::TangentEdges(const TopoDS_Edge& Edge ,
358 const TopoDS_Vertex& Vertex,
359 TopTools_ListOfShape& Edges ) const
364 Standard_Real U,URef;
365 BRepAdaptor_Curve C3d, C3dRef;
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;
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);
382 if (V.SquareMagnitude() < gp::Resolution()) continue;
383 if (V.IsParallel(VRef,angle)) {
391 //=======================================================================
392 //function : HasAncestor
394 //=======================================================================
396 Standard_Boolean BRepOffset_Analyse::HasAncestor (const TopoDS_Shape& S) const
398 return ancestors.Contains(S);
402 //=======================================================================
403 //function : Ancestors
405 //=======================================================================
407 const TopTools_ListOfShape& BRepOffset_Analyse::Ancestors
408 (const TopoDS_Shape& S) const
410 return ancestors.FindFromKey(S);
414 //=======================================================================
417 //=======================================================================
419 void BRepOffset_Analyse::Explode( TopTools_ListOfShape& List,
420 const BRepOffset_Type T ) const
424 TopTools_MapOfShape Map;
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());
433 // add to Co all faces from the cloud of faces
434 // G1 created from <Face>
435 AddFaces(Face,Co,Map,T);
441 //=======================================================================
444 //=======================================================================
446 void BRepOffset_Analyse::Explode( TopTools_ListOfShape& List,
447 const BRepOffset_Type T1,
448 const BRepOffset_Type T2) const
452 TopTools_MapOfShape Map;
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());
461 // add to Co all faces from the cloud of faces
462 // G1 created from <Face>
463 AddFaces(Face,Co,Map,T1,T2);
470 //=======================================================================
471 //function : AddFaces
473 //=======================================================================
475 void BRepOffset_Analyse::AddFaces (const TopoDS_Face& Face,
477 TopTools_MapOfShape& Map,
478 const BRepOffset_Type T) const
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) {
486 // so <NewFace> is attached to G1 by <Face>
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 ());
494 AddFaces(F1,Co,Map,T);
500 //=======================================================================
501 //function : AddFaces
503 //=======================================================================
505 void BRepOffset_Analyse::AddFaces (const TopoDS_Face& Face,
507 TopTools_MapOfShape& Map,
508 const BRepOffset_Type T1,
509 const BRepOffset_Type T2) const
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);
517 (LI.First().Type() == T1 || LI.First().Type() == T2)) {
518 // so <NewFace> is attached to G1 by <Face>
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 ());
526 AddFaces(F1,Co,Map,T1,T2);