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