0024023: Revamp the OCCT Handle -- ambiguity
[occt.git] / src / BRepOffsetAPI / BRepOffsetAPI_MakeOffset.cxx
CommitLineData
b311480e 1// Created on: 1995-09-18
2// Created by: Bruno DUMORTIER
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 <BRepOffsetAPI_MakeOffset.ixx>
18#include <BRepBuilderAPI_MakeFace.hxx>
19#include <BRep_Builder.hxx>
20#include <BRep_Tool.hxx>
21#include <BRepAlgo_FaceRestrictor.hxx>
22#include <Extrema_ExtPS.hxx>
23#include <BRepAdaptor_Surface.hxx>
24#include <BRepFill_OffsetWire.hxx>
25#include <BRepFill_ListIteratorOfListOfOffsetWire.hxx>
26#include <BRepTopAdaptor_FClass2d.hxx>
27#include <gp_Pnt2d.hxx>
28#include <gp_Pnt.hxx>
29#include <Precision.hxx>
30#include <TopTools_ListIteratorOfListOfShape.hxx>
31#include <TopExp_Explorer.hxx>
32#include <TopExp.hxx>
33#include <TopoDS.hxx>
34#include <TopoDS_Vertex.hxx>
35#include <TopoDS_Compound.hxx>
36#include <TopoDS_Wire.hxx>
37
38#include <StdFail_NotDone.hxx>
873c119f 39#ifdef OCCT_DEBUG
40#include <BRepTools.hxx>
41static Standard_Boolean AffichSpine = Standard_False;
42#endif
7fd59977 43
44//=======================================================================
45//function : BRepOffsetAPI_MakeOffset
46//purpose :
47//=======================================================================
48
49BRepOffsetAPI_MakeOffset::BRepOffsetAPI_MakeOffset()
75d1222c 50 : myIsInitialized( Standard_False),
51 myJoin(GeomAbs_Arc),
52 myIsOpenResult(Standard_False)
7fd59977 53{
54}
55
56
57//=======================================================================
58//function : BRepOffsetAPI_MakeOffset
59//purpose :
60//=======================================================================
61
62BRepOffsetAPI_MakeOffset::BRepOffsetAPI_MakeOffset(const TopoDS_Face& Spine,
6a442250 63 const GeomAbs_JoinType Join,
64 const Standard_Boolean IsOpenResult)
7fd59977 65{
6a442250 66 Init(Spine, Join, IsOpenResult);
7fd59977 67}
68
69
70//=======================================================================
71//function : Init
72//purpose :
73//=======================================================================
74
75void BRepOffsetAPI_MakeOffset::Init(const TopoDS_Face& Spine,
6a442250 76 const GeomAbs_JoinType Join,
77 const Standard_Boolean IsOpenResult)
7fd59977 78{
79 myFace = Spine;
80 myIsInitialized = Standard_True;
81 myJoin = Join;
6a442250 82 myIsOpenResult = IsOpenResult;
7fd59977 83 TopExp_Explorer exp;
84 for (exp.Init(myFace,TopAbs_WIRE); exp.More();exp.Next()) {
85 myWires.Append(exp.Current());
86 }
87}
88
89//=======================================================================
90//function : BRepOffsetAPI_MakeOffset
91//purpose :
92//=======================================================================
93
94BRepOffsetAPI_MakeOffset::BRepOffsetAPI_MakeOffset(const TopoDS_Wire& Spine,
6a442250 95 const GeomAbs_JoinType Join,
96 const Standard_Boolean IsOpenResult)
7fd59977 97{
98 myWires.Append(Spine);
99 myIsInitialized = Standard_True;
100 myJoin = Join;
6a442250 101 myIsOpenResult = IsOpenResult;
7fd59977 102}
103
104//=======================================================================
105//function : Init
106//purpose :
107//=======================================================================
108
6a442250 109void BRepOffsetAPI_MakeOffset::Init(const GeomAbs_JoinType Join,
110 const Standard_Boolean IsOpenResult)
7fd59977 111{
112 myJoin = Join;
6a442250 113 myIsOpenResult = IsOpenResult;
7fd59977 114}
73cd8a8a 115
7fd59977 116//=======================================================================
117//function : BRepOffsetAPI_MakeOffset
118//purpose :
119//=======================================================================
120
121void BRepOffsetAPI_MakeOffset::AddWire(const TopoDS_Wire& Spine)
73cd8a8a 122
7fd59977 123{
124 myIsInitialized = Standard_True;
125 myWires.Append(Spine);
126}
127
128//=======================================================================
129//function : BuildDomain
130//purpose :
131//=======================================================================
132
133static void BuildDomains(TopoDS_Face& myFace,
6a442250 134 TopTools_ListOfShape& WorkWires,
135 BRepFill_ListOfOffsetWire& myAlgos,
136 GeomAbs_JoinType myJoin,
137 Standard_Boolean myIsOpenResult,
138 Standard_Boolean isPositive)
7fd59977 139{
140 BRepAlgo_FaceRestrictor FR;
141 TopoDS_Vertex VF,VL;
142 TopTools_ListOfShape LOW;
143 BRep_Builder B;
144
145 if (myFace.IsNull()) {
146 myFace = BRepBuilderAPI_MakeFace(TopoDS::Wire(WorkWires.First()),Standard_True);
147 if (myFace.IsNull())
148 StdFail_NotDone::Raise ("BRepOffsetAPI_MakeOffset : the wire is not planar");
149 }
150// Modified by Sergey KHROMOV - Thu Apr 26 16:04:43 2001 Begin
151 TopExp_Explorer anExp(myFace, TopAbs_WIRE);
152 TopoDS_Shape aWire1 = WorkWires.First();
153 TopoDS_Shape aWire2;
154 if (anExp.More()) {
155 aWire2 = anExp.Current();
156 if ((aWire1.Orientation() == aWire2.Orientation() && isPositive) ||
73cd8a8a 157 (aWire1.Orientation() == TopAbs::Complement(aWire2.Orientation()) && !isPositive)) {
158 TopTools_ListOfShape LWires;
159 TopTools_ListIteratorOfListOfShape itl;
160 for (itl.Initialize(WorkWires); itl.More(); itl.Next()) {
161 const TopoDS_Shape& W = itl.Value();
162 LWires.Append(W.Reversed());
163 }
164 WorkWires = LWires;
7fd59977 165 }
166 }
167// Modified by Sergey KHROMOV - Thu Apr 26 16:04:44 2001 End
168 FR.Init(myFace,Standard_True);
169 //====================================================
0d969553 170 // Construction of faces limited by closed wires.
7fd59977 171 //====================================================
172 TopTools_ListIteratorOfListOfShape itl(WorkWires);
173 for (; itl.More(); itl.Next()) {
174 TopoDS_Wire& W = TopoDS::Wire(itl.Value());
175 if (W.Closed()){
176 FR.Add(W);
177 continue;
178 }
179 TopExp::Vertices (W,VF,VL);
180 if (VF.IsSame(VL)) {
181 FR.Add(W);
182 }
183 else {
184 LOW.Append(W);
185 }
186 }
187 FR.Perform();
188 if (!FR.IsDone()) {
189 StdFail_NotDone::Raise ("BRepOffsetAPI_MakeOffset : Build Domains");
190 }
191 TopTools_ListOfShape Faces;
873c119f 192#ifdef OCCT_DEBUG
193 Standard_Integer ns = 0;
194#endif
7fd59977 195 for (; FR.More(); FR.Next()) {
196 Faces.Append(FR.Current());
873c119f 197#ifdef OCCT_DEBUG
198 if(AffichSpine)
199 {
200 char name[32];
201 ns++;
202 sprintf(name, "FR%d",ns);
203 BRepTools::Write(FR.Current(), name);
204 }
205#endif
7fd59977 206 }
207
208 //===========================================
0d969553 209 // No closed wire => only one domain
7fd59977 210 //===========================================
211 if (Faces.IsEmpty()) {
212 TopoDS_Shape aLocalShape = myFace.EmptyCopied();
213 TopoDS_Face F = TopoDS::Face(aLocalShape);
214// TopoDS_Face F = TopoDS::Face(myFace.EmptyCopied());
215 TopTools_ListIteratorOfListOfShape itW(LOW);
216 for ( ; itW.More(); itW.Next()) {
217 B.Add(F,itW.Value());
218 }
6a442250 219 BRepFill_OffsetWire Algo(F, myJoin, myIsOpenResult);
7fd59977 220 myAlgos.Append(Algo);
221 return;
222 }
73cd8a8a 223
7fd59977 224 //====================================================
0d969553 225 // Classification of open wires.
7fd59977 226 //====================================================
227// for (TopTools_ListIteratorOfListOfShape itF(Faces); itF.More(); itF.Next()) {
228 TopTools_ListIteratorOfListOfShape itF;
229 for (itF.Initialize(Faces) ; itF.More(); itF.Next()) {
230 TopoDS_Face& F = TopoDS::Face(itF.Value());
231 BRepAdaptor_Surface S(F,0);
232 Standard_Real Tol = BRep_Tool::Tolerance(F);
233
234 BRepTopAdaptor_FClass2d CL(F,Precision::Confusion());
235
236 TopTools_ListIteratorOfListOfShape itW(LOW);
237 while (itW.More()) {
238 TopoDS_Wire& W = TopoDS::Wire(itW.Value());
239 //=======================================================
0d969553 240 // Choice of a point on the wire. + projection on the face.
7fd59977 241 //=======================================================
242 TopExp_Explorer exp(W,TopAbs_VERTEX);
243 TopoDS_Vertex V = TopoDS::Vertex(exp.Current());
244 gp_Pnt2d PV;
245 gp_Pnt P3d = BRep_Tool::Pnt(V);
246 Extrema_ExtPS ExtPS (P3d,S,Tol,Tol);
247 Standard_Real Dist2Min = Precision::Infinite();
248 Standard_Real Found = Standard_False;
249 for (Standard_Integer ie = 1; ie <= ExtPS.NbExt(); ie++) {
73cd8a8a 250 Standard_Real X,Y;
251 if (ExtPS.SquareDistance(ie) < Dist2Min) {
252 Dist2Min = ExtPS.SquareDistance(ie);
253 Found = Standard_True;
254 ExtPS.Point(ie).Parameter(X,Y);
255 PV.SetCoord(X,Y);
256 }
7fd59977 257 }
258 if ( Found && (CL.Perform(PV) == TopAbs_IN)) {
73cd8a8a 259 // The face that contains a wire is found and it is removed from the list
260 B.Add(F,W);
261 LOW.Remove(itW);
7fd59977 262 }
263 else {
73cd8a8a 264 itW.Next();
7fd59977 265 }
266 }
267 }
268 //========================================
0d969553 269 // Creation of algorithms on each domain.
7fd59977 270 //========================================
271 for (itF.Initialize(Faces); itF.More(); itF.Next()) {
6a442250 272 BRepFill_OffsetWire Algo(TopoDS::Face(itF.Value()), myJoin, myIsOpenResult);
7fd59977 273 myAlgos.Append(Algo);
274 }
275}
276
277//=======================================================================
278//function : Perform
279//purpose :
280//=======================================================================
281
6a442250 282void BRepOffsetAPI_MakeOffset::Perform(const Standard_Real Offset,
283 const Standard_Real Alt)
73cd8a8a 284{
7fd59977 285 StdFail_NotDone_Raise_if ( !myIsInitialized,
73cd8a8a 286 "BRepOffsetAPI_MakeOffset : Perform without Init");
7fd59977 287
ab87e6fc 288 try
73cd8a8a 289 {
ab87e6fc 290 Standard_Integer i = 1;
291 BRepFill_ListIteratorOfListOfOffsetWire itOW;
292 TopoDS_Compound Res;
293 BRep_Builder B;
294 B.MakeCompound (Res);
295 myLastIsLeft = (Offset <= 0);
73cd8a8a 296
ab87e6fc 297 if( Offset <= 0. )
73cd8a8a 298 {
ab87e6fc 299 if( myLeft.IsEmpty() )
73cd8a8a 300 {
ab87e6fc 301 // Modified by Sergey KHROMOV - Fri Apr 27 14:35:26 2001 Begin
6a442250 302 BuildDomains(myFace,myWires,myLeft,myJoin,myIsOpenResult, Standard_False);
ab87e6fc 303 // Modified by Sergey KHROMOV - Fri Apr 27 14:35:26 2001 End
73cd8a8a 304 }
7fd59977 305
ab87e6fc 306 for (itOW.Initialize(myLeft); itOW.More(); itOW.Next())
73cd8a8a 307 {
ab87e6fc 308 BRepFill_OffsetWire& Algo = itOW.Value();
309 Algo.Perform(Abs(Offset),Alt);
310 if (Algo.IsDone() && !Algo.Shape().IsNull())
73cd8a8a 311 {
ab87e6fc 312 B.Add(Res,Algo.Shape());
313 if (i == 1)
314 myShape = Algo.Shape();
315
316 i++;
ab87e6fc 317 }
7fd59977 318 }
73cd8a8a 319 }
ab87e6fc 320 else
73cd8a8a 321 {
ab87e6fc 322 if (myRight.IsEmpty())
73cd8a8a 323 {
ab87e6fc 324 // Modified by Sergey KHROMOV - Fri Apr 27 14:35:28 2001 Begin
6a442250 325 BuildDomains(myFace,myWires,myRight,myJoin,myIsOpenResult, Standard_True);
ab87e6fc 326 // Modified by Sergey KHROMOV - Fri Apr 27 14:35:35 2001 End
73cd8a8a 327 }
ab87e6fc 328
329 for(itOW.Initialize(myRight); itOW.More(); itOW.Next())
73cd8a8a 330 {
ab87e6fc 331 BRepFill_OffsetWire& Algo = itOW.Value();
332 Algo.Perform(Offset,Alt);
73cd8a8a 333
ab87e6fc 334 if (Algo.IsDone() && !Algo.Shape().IsNull())
73cd8a8a 335 {
ab87e6fc 336 B.Add(Res,Algo.Shape());
337
338 if (i == 1)
339 myShape = Algo.Shape();
340
341 i++;
ab87e6fc 342 }
7fd59977 343 }
73cd8a8a 344 }
ab87e6fc 345
346 if( i > 2 )
347 myShape = Res;
348
349 if(myShape.IsNull())
350 NotDone();
351 else
352 Done();
73cd8a8a 353 }
b350f6ee 354 catch(Standard_Failure) //Every exception was caught.
73cd8a8a 355 {
0797d9d3 356#ifdef OCCT_DEBUG
ab87e6fc 357 cout<<"An exception was caught in BRepOffsetAPI_MakeOffset::Perform : ";
358 Standard_ConstructionError::Caught()->Print(cout);
359 cout<<endl;
63c629aa 360#endif
ab87e6fc 361 NotDone();
362 myShape.Nullify();
7fd59977 363 }
73cd8a8a 364}
7fd59977 365
366//=======================================================================
367//function : Build
368//purpose :
369//=======================================================================
370
371void BRepOffsetAPI_MakeOffset::Build()
372{
373 Done();
374}
375
376
377//=======================================================================
378//function : ShapesFromShape
379//purpose :
380//=======================================================================
381
382const TopTools_ListOfShape& BRepOffsetAPI_MakeOffset::Generated
73cd8a8a 383 (const TopoDS_Shape& S)
7fd59977 384{
385 myGenerated.Clear();
386 BRepFill_ListIteratorOfListOfOffsetWire itOW;
387 BRepFill_ListOfOffsetWire* Algos;
388 Algos= &myLeft;
389 if (!myLastIsLeft) {
390 Algos = &myRight;
391 }
392 for (itOW.Initialize(*Algos); itOW.More(); itOW.Next()) {
393 BRepFill_OffsetWire& OW = itOW.Value();
394 TopTools_ListOfShape L;
395 L = OW.GeneratedShapes(S.Oriented(TopAbs_FORWARD));
396 myGenerated.Append(L);
397 L = OW.GeneratedShapes(S.Oriented(TopAbs_REVERSED));
398 myGenerated.Append(L);
399 }
400 return myGenerated;
401}