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