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