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