0024510: Remove unused local variables
[occt.git] / src / ShapeAnalysis / ShapeAnalysis_FreeBounds.cxx
CommitLineData
b311480e 1// Created on: 1998-04-27
2// Created by: Roman LYGIN
3// Copyright (c) 1998-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.
b311480e 16
7fd59977 17// Modified: Thu Sep 17 12:27:58 1998
7fd59977 18// 25.12.98 pdn transmission from BRepTools_Sewing to BRepBuilderAPI_Sewing
19//szv#4 S4163
20// 11.01.00 svv #1: porting on DEC
21
22#include <ShapeAnalysis_FreeBounds.ixx>
23
24#include <BRep_Builder.hxx>
25#include <BRep_Tool.hxx>
26#include <BRepBuilderAPI_Sewing.hxx>
27
28#include <Precision.hxx>
29
30#include <TopoDS.hxx>
31#include <TopoDS_Vertex.hxx>
32#include <TopoDS_Wire.hxx>
33#include <TopoDS_Edge.hxx>
34#include <TopoDS_Iterator.hxx>
35
36#include <TColStd_Array1OfBoolean.hxx>
37#include <TColStd_Array1OfInteger.hxx>
38#include <TColStd_SequenceOfInteger.hxx>
39
40#include <ShapeExtend_WireData.hxx>
41#include <ShapeExtend_Explorer.hxx>
42#include <ShapeBuild_Vertex.hxx>
43#include <ShapeBuild_Edge.hxx>
44#include <ShapeAnalysis.hxx>
45#include <ShapeAnalysis_Edge.hxx>
46#include <ShapeAnalysis_Wire.hxx>
47#include <ShapeAnalysis_Shell.hxx>
48
49#include <gp_Pnt.hxx> //ied_modif_for_compil_Nov-19-1998
50#include <TopExp_Explorer.hxx>
51#include <TopTools_MapOfShape.hxx>
52#include <TopTools_MapIteratorOfMapOfShape.hxx>
53#include <TopoDS_Shell.hxx>
54#include <ShapeAnalysis_BoxBndTree.hxx>
55#include <NCollection_UBTreeFiller.hxx>
56#include <TColStd_ListIteratorOfListOfInteger.hxx>
57#include <TopTools_HArray1OfShape.hxx>
58#include <TopExp.hxx>
59
60//=======================================================================
61//function : ShapeAnalysis_FreeBounds
62//purpose : Empty constructor
63//=======================================================================
64
65ShapeAnalysis_FreeBounds::ShapeAnalysis_FreeBounds() {}
66
67//=======================================================================
68//function : ShapeAnalysis_FreeBounds
69//purpose :
70//=======================================================================
71
72ShapeAnalysis_FreeBounds::ShapeAnalysis_FreeBounds(const TopoDS_Shape& shape,
73 const Standard_Real toler,
74 const Standard_Boolean splitclosed,
75 const Standard_Boolean splitopen) :
76 myTolerance (toler), myShared (Standard_False),
77 mySplitClosed (splitclosed), mySplitOpen (splitopen)
78{
79 BRepBuilderAPI_Sewing Sew(toler, Standard_False, Standard_False);
80 for (TopoDS_Iterator S (shape); S.More(); S.Next()) Sew.Add(S.Value());
81 Sew.Perform();
82 //
83 // Extract free edges.
84 //
85 Standard_Integer nbedge = Sew.NbFreeEdges();
86 Handle(TopTools_HSequenceOfShape) edges = new TopTools_HSequenceOfShape;
87 Handle(TopTools_HSequenceOfShape) wires;
88 TopoDS_Edge anEdge;
89 for (Standard_Integer iedge = 1 ; iedge <= nbedge ; iedge++) {
90 anEdge = TopoDS::Edge (Sew.FreeEdge(iedge));
91 if ( !BRep_Tool::Degenerated(anEdge) ) edges->Append (anEdge);
92 }
93 //
94 // Chainage.
95 //
96 ConnectEdgesToWires (edges, toler, Standard_False, wires);
97 DispatchWires (wires, myWires, myEdges);
98 SplitWires ();
99
100 return ;
101}
102
103//=======================================================================
104//function : ShapeAnalysis_FreeBounds
105//purpose :
106//=======================================================================
107
108ShapeAnalysis_FreeBounds::ShapeAnalysis_FreeBounds(const TopoDS_Shape& shape,
109 const Standard_Boolean splitclosed,
110 const Standard_Boolean splitopen,
111 const Standard_Boolean checkinternaledges) :
112 myTolerance (0.), myShared (Standard_True),
113 mySplitClosed (splitclosed), mySplitOpen (splitopen)
114{
115 TopoDS_Shell aTmpShell;
116 BRep_Builder aB;
117 aB.MakeShell(aTmpShell);
118 for(TopExp_Explorer aExpFace(shape,TopAbs_FACE);aExpFace.More(); aExpFace.Next())
119 aB.Add(aTmpShell,aExpFace.Current());
120
121 ShapeAnalysis_Shell sas;
122 sas.CheckOrientedShells (aTmpShell, Standard_True, checkinternaledges);
123
124 if (sas.HasFreeEdges()) {
125 ShapeExtend_Explorer see;
126 Handle(TopTools_HSequenceOfShape) edges = see.SeqFromCompound (sas.FreeEdges(), Standard_False);
127
128 Handle(TopTools_HSequenceOfShape) wires;
129 ConnectEdgesToWires (edges, Precision::Confusion(), Standard_True, wires);
130 DispatchWires (wires, myWires, myEdges);
131 SplitWires ();
132 }
133
134
135}
136
137//=======================================================================
138//function : ConnectEdgesToWires
139//purpose :
140//=======================================================================
141
142 void ShapeAnalysis_FreeBounds::ConnectEdgesToWires(Handle(TopTools_HSequenceOfShape)& edges,
143 const Standard_Real toler,
144 const Standard_Boolean shared,
145 Handle(TopTools_HSequenceOfShape)& wires)
146{
147 Handle(TopTools_HSequenceOfShape) iwires = new TopTools_HSequenceOfShape;
148 BRep_Builder B;
149
150 Standard_Integer i; // svv #1
151 for (i = 1; i <= edges->Length(); i++) {
152 TopoDS_Wire wire;
153 B.MakeWire (wire);
154 B.Add (wire, edges->Value (i));
155 iwires->Append (wire);
156 }
157
158 ConnectWiresToWires (iwires, toler, shared, wires);
159
160 for (i = 1; i <= edges->Length(); i++)
161 if (iwires->Value(i).Orientation() == TopAbs_REVERSED)
162 edges->ChangeValue(i).Reverse();
163}
164
165//=======================================================================
166//function : ConnectWiresToWires
167//purpose :
168//=======================================================================
169
170 void ShapeAnalysis_FreeBounds::ConnectWiresToWires(Handle(TopTools_HSequenceOfShape)& iwires,
171 const Standard_Real toler,
172 const Standard_Boolean shared,
173 Handle(TopTools_HSequenceOfShape)& owires)
174{
175 TopTools_DataMapOfShapeShape map;
176 ConnectWiresToWires (iwires, toler, shared, owires, map);
177}
178
179//=======================================================================
180//function : ConnectWiresToWires
181//purpose :
182//=======================================================================
183
184 void ShapeAnalysis_FreeBounds::ConnectWiresToWires(Handle(TopTools_HSequenceOfShape)& iwires,
185 const Standard_Real toler,
186 const Standard_Boolean shared,
187 Handle(TopTools_HSequenceOfShape)& owires,
188 TopTools_DataMapOfShapeShape& vertices)
189{
190 if (iwires.IsNull() || !iwires->Length()) return;
191 Handle(TopTools_HArray1OfShape) arrwires = new TopTools_HArray1OfShape(1, iwires->Length());
192 //amv
193 Standard_Integer i;
194 for (i = 1; i <= arrwires->Length(); i++)
195 arrwires->SetValue(i, iwires->Value(i));
196 owires = new TopTools_HSequenceOfShape;
197 Standard_Real tolerance = Max (toler, Precision::Confusion());
198
199 Handle(ShapeExtend_WireData)
200 sewd = new ShapeExtend_WireData (TopoDS::Wire (arrwires->Value (1)));
201
202 Handle(ShapeAnalysis_Wire) saw = new ShapeAnalysis_Wire;
203 saw->Load (sewd);
204 saw->SetPrecision (tolerance);
205
206 ShapeAnalysis_BoxBndTree aBBTree;
207 NCollection_UBTreeFiller <Standard_Integer, Bnd_Box> aTreeFiller(aBBTree);
208 ShapeAnalysis_BoxBndTreeSelector aSel(arrwires, shared);
209 aSel.LoadList(1);
210
211 for (Standard_Integer inbW = 2; inbW <= arrwires->Length(); inbW++){
212 TopoDS_Wire trW = TopoDS::Wire (arrwires->Value (inbW));
213 Bnd_Box aBox;
214 TopoDS_Vertex trV1, trV2;
215 ShapeAnalysis::FindBounds (trW, trV1, trV2);
216 gp_Pnt trP1 = BRep_Tool::Pnt(trV1);
217 gp_Pnt trP2 = BRep_Tool::Pnt(trV2);
218 aBox.Set(trP1);
219 aBox.Add(trP2);
220 aBox.SetGap(tolerance);
221 aTreeFiller.Add(inbW, aBox);
222 }
96a95605 223 aTreeFiller.Fill();
7fd59977 224 Standard_Integer nsel;
225
226 ShapeAnalysis_Edge sae; //szv#4:S4163:12Mar99 moved
227 Standard_Boolean done = Standard_False;
228
229 while (!done) {
230 Standard_Boolean found = Standard_False, tail = Standard_False, direct = Standard_False;
231 Standard_Integer lwire=0;
232 aSel.SetStop();
233 Bnd_Box FVBox, LVBox;
234 TopoDS_Vertex Vf, Vl;
235 Vf = sae.FirstVertex(sewd->Edge(1));
236 Vl = sae.LastVertex(sewd->Edge(sewd->NbEdges()));
237 gp_Pnt pf, pl;
238 pf = BRep_Tool::Pnt(Vf);
239 pl = BRep_Tool::Pnt(Vl);
240 FVBox.Set(pf);
241 FVBox.SetGap(tolerance);
242 LVBox.Set(pl);
243 LVBox.SetGap(tolerance);
244
245 aSel.DefineBoxes(FVBox, LVBox);
246
247 if (shared)
248 aSel.DefineVertexes(Vf,Vl);
249 else{
250 aSel.DefinePnt(pf,pl);
251 aSel.SetTolerance(tolerance);
252 }
253
254 nsel = aBBTree.Select(aSel);
255
256 if (nsel != 0 && !aSel.LastCheckStatus(ShapeExtend_FAIL)) {
257 found = Standard_True;
258 lwire = aSel.GetNb();
259 tail = aSel.LastCheckStatus (ShapeExtend_DONE1) ||
260 aSel.LastCheckStatus (ShapeExtend_DONE2);
261 direct = aSel.LastCheckStatus (ShapeExtend_DONE1) ||
262 aSel.LastCheckStatus (ShapeExtend_DONE3);
263 aSel.LoadList(lwire);
264 }
265
266 if (found) {
267 if (!direct) arrwires->ChangeValue(lwire).Reverse();
268 TopoDS_Wire aCurW = TopoDS::Wire (arrwires->Value (lwire));
269 Handle(ShapeExtend_WireData) acurwd =
270 new ShapeExtend_WireData ( TopoDS::Wire (arrwires->Value (lwire)));
271 sewd->Add (acurwd, (tail ? 0 : 1));
272 }
273 else {
274 //making wire
275 //1.providing connection (see ShapeFix_Wire::FixConnected())
276 //Standard_Integer i; // svv #1
277 for (/*Standard_Integer*/ i = 1; i <= saw->NbEdges(); i++) {
278 if (saw->CheckConnected (i)) {
279 Standard_Integer n2 = i;
280 Standard_Integer n1 = (n2 > 1 ? n2 - 1 : saw->NbEdges());
281 TopoDS_Edge E1 = sewd->Edge(n1);
282 TopoDS_Edge E2 = sewd->Edge(n2);
283
284 TopoDS_Vertex Vprev, Vfol, V; //connection vertex
285 Vprev = sae.LastVertex (E1);
286 Vfol = sae.FirstVertex (E2);
287
288 if (saw->LastCheckStatus (ShapeExtend_DONE1)) //absolutely confused
289 V = Vprev;
290 else {
291 ShapeBuild_Vertex sbv;
292 V = sbv.CombineVertex (Vprev, Vfol);
293 }
294 vertices.Bind (Vprev, V);
295 vertices.Bind (Vfol, V);
296
297 //replace vertices to a new one
298 ShapeBuild_Edge sbe;
299 if (saw->NbEdges() < 2)
300 sewd->Set (sbe.CopyReplaceVertices (E2, V, V), n2);
301 else {
302 sewd->Set (sbe.CopyReplaceVertices (E2, V, TopoDS_Vertex()), n2);
303 if (!saw->LastCheckStatus (ShapeExtend_DONE1))
304 sewd->Set (sbe.CopyReplaceVertices (E1, TopoDS_Vertex(), V), n1);
305 }
306 }
307 }
308
309 //2.making wire
310 TopoDS_Wire wire = sewd->Wire();
311 if (!saw->CheckConnected (1) && saw->LastCheckStatus (ShapeExtend_OK))
312 wire.Closed (Standard_True);
313 owires->Append (wire);
314 sewd->Clear();
315
316 // Recherche de la premier edge non traitee pour un autre wire.
317 //Searching for first edge for next wire
318 lwire = -1;
319 for (/*Standard_Integer*/ i = 1 ; i <= arrwires->Length() && lwire == -1; i++)
320 if (!aSel.ContWire(i)) lwire = i; //szv#4:S4163:12Mar99 optimized
321
322 if (lwire == -1) done = 1;
323 else {
324 sewd->Add (TopoDS::Wire (arrwires->Value (lwire)));
325 aSel.LoadList(lwire);
326 }
327 }
328 }
329 for ( /*Standard_Integer*/ i = 1; i <= iwires->Length(); i++)
330 iwires->SetValue (i, arrwires->Value(i));
331}
332
333static void SplitWire(const TopoDS_Wire& wire,
334 const Standard_Real toler,
335 const Standard_Boolean shared,
336 Handle(TopTools_HSequenceOfShape)& closed,
337 Handle(TopTools_HSequenceOfShape)& open)
338{
339 closed = new TopTools_HSequenceOfShape;
340 open = new TopTools_HSequenceOfShape;
341 Standard_Real tolerance = Max (toler, Precision::Confusion());
342
343 BRep_Builder B;
344 ShapeAnalysis_Edge sae;
345
346 Handle(ShapeExtend_WireData) sewd = new ShapeExtend_WireData (wire);
347 Standard_Integer nbedges = sewd->NbEdges();
348
349 //ConnectedEdgeSequence - list of indices of connected edges to build a wire
350 TColStd_SequenceOfInteger ces;
351 //statuses - array of flags describing the edge:
352 //0-free, 1-in CES, 2-already in wire,
353 //3-no closed wire can be produced starting at this edge
354 TColStd_Array1OfInteger statuses (1, nbedges);
355 statuses.Init (0);
356
357 //building closed wires
358 Standard_Integer i; // svv #1
359 for (i = 1; i <= nbedges; i++)
360 if (statuses.Value (i) == 0) {
361 ces.Append (i); statuses.SetValue (i, 1); //putting into CES
362 Standard_Boolean SearchBackward = Standard_True;
363
302f96fb 364 for(;;) {
7fd59977 365 Standard_Boolean found;
366 TopoDS_Edge edge;
367 TopoDS_Vertex lvertex;
368 gp_Pnt lpoint;
369
370 //searching for connection in ces
371 if (SearchBackward) {
372 SearchBackward = Standard_False;
373 found = Standard_False;
374 edge = sewd->Edge (ces.Last());
375 lvertex = sae.LastVertex (edge);
376 lpoint = BRep_Tool::Pnt (lvertex);
377 Standard_Integer j; // svv #1
378 for (j = ces.Length(); (j >= 1) && !found; j--) {
379 TopoDS_Vertex fv = sae.FirstVertex (sewd->Edge (ces.Value (j)) );
380 gp_Pnt fp = BRep_Tool::Pnt (fv);
381 if ((shared && lvertex.IsSame (fv)) ||
382 (!shared && lpoint.IsEqual (fp, tolerance)))
383 found = Standard_True;
384 }
385
386 if (found) {
387 j++;//because of decreasing last iteration
388 //making closed wire
389 TopoDS_Wire wire1;
390 B.MakeWire (wire1);
391 for (Standard_Integer cesindex = j; cesindex <= ces.Length(); cesindex++) {
392 B.Add (wire1, sewd->Edge (ces.Value (cesindex)));
393 statuses.SetValue (ces.Value (cesindex), 2);
394 }
395 wire1.Closed (Standard_True);
396 closed->Append (wire1);
397 ces.Remove (j, ces.Length());
398 if (ces.IsEmpty()) break;
399 }
400 }
401
402 //searching for connection among free edges
403 found = Standard_False;
7fd59977 404 edge = sewd->Edge (ces.Last());
405 lvertex = sae.LastVertex (edge);
406 lpoint = BRep_Tool::Pnt (lvertex);
407 Standard_Integer j; // svv #1
408 for (j = 1; (j <= nbedges) && !found; j++)
409 if (statuses.Value (j) == 0) {
410 TopoDS_Vertex fv = sae.FirstVertex (sewd->Edge (j));
411 gp_Pnt fp = BRep_Tool::Pnt (fv);
412 if ((shared && lvertex.IsSame (fv)) ||
413 (!shared && lpoint.IsEqual (fp, tolerance)))
414 found = Standard_True;
415 }
416
417 if (found) {
418 j--;//because of last iteration
419 ces.Append (j); statuses.SetValue (j, 1);//putting into CES
420 SearchBackward = Standard_True;
421 continue;
422 }
423
424 //no edges found - mark the branch as open (use status 3)
425 statuses.SetValue (ces.Last(), 3);
426 ces.Remove (ces.Length());
427 if (ces.IsEmpty()) break;
428 }
429 }
430
431 //building open wires
432 Handle(TopTools_HSequenceOfShape) edges = new TopTools_HSequenceOfShape;
433 for (i = 1; i <= nbedges; i++)
434 if (statuses.Value (i) != 2) edges->Append (sewd->Edge(i));
435
436 ShapeAnalysis_FreeBounds::ConnectEdgesToWires (edges, toler, shared, open);
437}
438
439 void ShapeAnalysis_FreeBounds::SplitWires(const Handle(TopTools_HSequenceOfShape)& wires,
440 const Standard_Real toler,
441 const Standard_Boolean shared,
442 Handle(TopTools_HSequenceOfShape)& closed,
443 Handle(TopTools_HSequenceOfShape)& open)
444{
445 closed = new TopTools_HSequenceOfShape;
446 open = new TopTools_HSequenceOfShape;
447
448 for (Standard_Integer i = 1; i <= wires->Length(); i++) {
449 Handle(TopTools_HSequenceOfShape) tmpclosed, tmpopen;
450 SplitWire (TopoDS::Wire (wires->Value (i)), toler, shared, tmpclosed, tmpopen);
451 closed->Append (tmpclosed);
452 open->Append (tmpopen);
453 }
454}
455
456//=======================================================================
457//function : DispatchWires
458//purpose :
459//=======================================================================
460
461 void ShapeAnalysis_FreeBounds::DispatchWires(const Handle(TopTools_HSequenceOfShape)& wires,
462 TopoDS_Compound& closed,
463 TopoDS_Compound& open)
464{
465 BRep_Builder B;
466 if (closed.IsNull()) B.MakeCompound (closed);
467 if (open.IsNull()) B.MakeCompound (open);
468 if (wires.IsNull()) return;
469
470 for (Standard_Integer iw = 1 ; iw <= wires->Length(); iw++)
471 if ( wires->Value (iw).Closed() )
472 B.Add (closed, wires->Value (iw));
473 else
474 B.Add (open, wires->Value (iw));
475}
476
477//=======================================================================
478//function : SplitWires
479//purpose : Splits compounds of closed (myWires) and open (myEdges) wires
480// into small closed wires according to fields mySplitClosed and
481// mySplitOpen and rebuilds compounds
482//=======================================================================
483
484 void ShapeAnalysis_FreeBounds::SplitWires()
485{
486 if (!mySplitClosed && !mySplitOpen) return; //nothing to do
487
488 ShapeExtend_Explorer see;
489 Handle(TopTools_HSequenceOfShape) closedwires, cw1, cw2,
490 openwires, ow1, ow2;
491 closedwires = see.SeqFromCompound (myWires, Standard_False);
492 openwires = see.SeqFromCompound (myEdges, Standard_False);
493
494 if (mySplitClosed) SplitWires (closedwires, myTolerance, myShared, cw1, ow1);
495 else {cw1 = closedwires; ow1 = new TopTools_HSequenceOfShape;}
496
497 if (mySplitOpen) SplitWires (openwires, myTolerance, myShared, cw2, ow2);
498 else {cw2 = new TopTools_HSequenceOfShape; ow2 = openwires;}
499
500 closedwires = cw1; closedwires->Append (cw2);
501 openwires = ow1; openwires->Append (ow2);
502
503 //szv#4:S4163:12Mar99 SGI warns
504 TopoDS_Shape compWires = see.CompoundFromSeq (closedwires);
505 TopoDS_Shape compEdges = see.CompoundFromSeq (openwires);
506 myWires = TopoDS::Compound (compWires);
507 myEdges = TopoDS::Compound (compEdges);
508}