1 // Created on: 1998-04-27
2 // Created by: Roman LYGIN
3 // Copyright (c) 1998-1999 Matra Datavision
4 // Copyright (c) 1999-2012 OPEN CASCADE SAS
6 // The content of this file is subject to the Open CASCADE Technology Public
7 // License Version 6.5 (the "License"). You may not use the content of this file
8 // except in compliance with the License. Please obtain a copy of the License
9 // at http://www.opencascade.org and read it completely before using this file.
11 // The Initial Developer of the Original Code is Open CASCADE S.A.S., having its
12 // main offices at: 1, place des Freres Montgolfier, 78280 Guyancourt, France.
14 // The Original Code and all software distributed under the License is
15 // distributed on an "AS IS" basis, without warranty of any kind, and the
16 // Initial Developer hereby disclaims all such warranties, including without
17 // limitation, any warranties of merchantability, fitness for a particular
18 // purpose or non-infringement. Please see the License for the specific terms
19 // and conditions governing the rights and limitations under the License.
21 // Modified: Thu Sep 17 12:27:58 1998
22 // 25.12.98 pdn transmission from BRepTools_Sewing to BRepBuilderAPI_Sewing
24 // 11.01.00 svv #1: porting on DEC
26 #include <ShapeAnalysis_FreeBounds.ixx>
28 #include <BRep_Builder.hxx>
29 #include <BRep_Tool.hxx>
30 #include <BRepBuilderAPI_Sewing.hxx>
32 #include <Precision.hxx>
35 #include <TopoDS_Vertex.hxx>
36 #include <TopoDS_Wire.hxx>
37 #include <TopoDS_Edge.hxx>
38 #include <TopoDS_Iterator.hxx>
40 #include <TColStd_Array1OfBoolean.hxx>
41 #include <TColStd_Array1OfInteger.hxx>
42 #include <TColStd_SequenceOfInteger.hxx>
44 #include <ShapeExtend_WireData.hxx>
45 #include <ShapeExtend_Explorer.hxx>
46 #include <ShapeBuild_Vertex.hxx>
47 #include <ShapeBuild_Edge.hxx>
48 #include <ShapeAnalysis.hxx>
49 #include <ShapeAnalysis_Edge.hxx>
50 #include <ShapeAnalysis_Wire.hxx>
51 #include <ShapeAnalysis_Shell.hxx>
53 #include <gp_Pnt.hxx> //ied_modif_for_compil_Nov-19-1998
54 #include <TopExp_Explorer.hxx>
55 #include <TopTools_MapOfShape.hxx>
56 #include <TopTools_MapIteratorOfMapOfShape.hxx>
57 #include <TopoDS_Shell.hxx>
58 #include <ShapeAnalysis_BoxBndTree.hxx>
59 #include <NCollection_UBTreeFiller.hxx>
60 #include <TColStd_ListIteratorOfListOfInteger.hxx>
61 #include <TopTools_HArray1OfShape.hxx>
64 //=======================================================================
65 //function : ShapeAnalysis_FreeBounds
66 //purpose : Empty constructor
67 //=======================================================================
69 ShapeAnalysis_FreeBounds::ShapeAnalysis_FreeBounds() {}
71 //=======================================================================
72 //function : ShapeAnalysis_FreeBounds
74 //=======================================================================
76 ShapeAnalysis_FreeBounds::ShapeAnalysis_FreeBounds(const TopoDS_Shape& shape,
77 const Standard_Real toler,
78 const Standard_Boolean splitclosed,
79 const Standard_Boolean splitopen) :
80 myTolerance (toler), myShared (Standard_False),
81 mySplitClosed (splitclosed), mySplitOpen (splitopen)
83 BRepBuilderAPI_Sewing Sew(toler, Standard_False, Standard_False);
84 for (TopoDS_Iterator S (shape); S.More(); S.Next()) Sew.Add(S.Value());
87 // Extract free edges.
89 Standard_Integer nbedge = Sew.NbFreeEdges();
90 Handle(TopTools_HSequenceOfShape) edges = new TopTools_HSequenceOfShape;
91 Handle(TopTools_HSequenceOfShape) wires;
93 for (Standard_Integer iedge = 1 ; iedge <= nbedge ; iedge++) {
94 anEdge = TopoDS::Edge (Sew.FreeEdge(iedge));
95 if ( !BRep_Tool::Degenerated(anEdge) ) edges->Append (anEdge);
100 ConnectEdgesToWires (edges, toler, Standard_False, wires);
101 DispatchWires (wires, myWires, myEdges);
107 //=======================================================================
108 //function : ShapeAnalysis_FreeBounds
110 //=======================================================================
112 ShapeAnalysis_FreeBounds::ShapeAnalysis_FreeBounds(const TopoDS_Shape& shape,
113 const Standard_Boolean splitclosed,
114 const Standard_Boolean splitopen,
115 const Standard_Boolean checkinternaledges) :
116 myTolerance (0.), myShared (Standard_True),
117 mySplitClosed (splitclosed), mySplitOpen (splitopen)
119 TopoDS_Shell aTmpShell;
121 aB.MakeShell(aTmpShell);
122 for(TopExp_Explorer aExpFace(shape,TopAbs_FACE);aExpFace.More(); aExpFace.Next())
123 aB.Add(aTmpShell,aExpFace.Current());
125 ShapeAnalysis_Shell sas;
126 sas.CheckOrientedShells (aTmpShell, Standard_True, checkinternaledges);
128 if (sas.HasFreeEdges()) {
129 ShapeExtend_Explorer see;
130 Handle(TopTools_HSequenceOfShape) edges = see.SeqFromCompound (sas.FreeEdges(), Standard_False);
132 Handle(TopTools_HSequenceOfShape) wires;
133 ConnectEdgesToWires (edges, Precision::Confusion(), Standard_True, wires);
134 DispatchWires (wires, myWires, myEdges);
141 //=======================================================================
142 //function : ConnectEdgesToWires
144 //=======================================================================
146 void ShapeAnalysis_FreeBounds::ConnectEdgesToWires(Handle(TopTools_HSequenceOfShape)& edges,
147 const Standard_Real toler,
148 const Standard_Boolean shared,
149 Handle(TopTools_HSequenceOfShape)& wires)
151 Handle(TopTools_HSequenceOfShape) iwires = new TopTools_HSequenceOfShape;
154 Standard_Integer i; // svv #1
155 for (i = 1; i <= edges->Length(); i++) {
158 B.Add (wire, edges->Value (i));
159 iwires->Append (wire);
162 ConnectWiresToWires (iwires, toler, shared, wires);
164 for (i = 1; i <= edges->Length(); i++)
165 if (iwires->Value(i).Orientation() == TopAbs_REVERSED)
166 edges->ChangeValue(i).Reverse();
169 //=======================================================================
170 //function : ConnectWiresToWires
172 //=======================================================================
174 void ShapeAnalysis_FreeBounds::ConnectWiresToWires(Handle(TopTools_HSequenceOfShape)& iwires,
175 const Standard_Real toler,
176 const Standard_Boolean shared,
177 Handle(TopTools_HSequenceOfShape)& owires)
179 TopTools_DataMapOfShapeShape map;
180 ConnectWiresToWires (iwires, toler, shared, owires, map);
183 //=======================================================================
184 //function : ConnectWiresToWires
186 //=======================================================================
188 void ShapeAnalysis_FreeBounds::ConnectWiresToWires(Handle(TopTools_HSequenceOfShape)& iwires,
189 const Standard_Real toler,
190 const Standard_Boolean shared,
191 Handle(TopTools_HSequenceOfShape)& owires,
192 TopTools_DataMapOfShapeShape& vertices)
194 if (iwires.IsNull() || !iwires->Length()) return;
195 Handle(TopTools_HArray1OfShape) arrwires = new TopTools_HArray1OfShape(1, iwires->Length());
198 for (i = 1; i <= arrwires->Length(); i++)
199 arrwires->SetValue(i, iwires->Value(i));
200 owires = new TopTools_HSequenceOfShape;
201 Standard_Real tolerance = Max (toler, Precision::Confusion());
203 Handle(ShapeExtend_WireData)
204 sewd = new ShapeExtend_WireData (TopoDS::Wire (arrwires->Value (1)));
206 Handle(ShapeAnalysis_Wire) saw = new ShapeAnalysis_Wire;
208 saw->SetPrecision (tolerance);
210 ShapeAnalysis_BoxBndTree aBBTree;
211 NCollection_UBTreeFiller <Standard_Integer, Bnd_Box> aTreeFiller(aBBTree);
212 ShapeAnalysis_BoxBndTreeSelector aSel(arrwires, shared);
215 for (Standard_Integer inbW = 2; inbW <= arrwires->Length(); inbW++){
216 TopoDS_Wire trW = TopoDS::Wire (arrwires->Value (inbW));
218 TopoDS_Vertex trV1, trV2;
219 ShapeAnalysis::FindBounds (trW, trV1, trV2);
220 gp_Pnt trP1 = BRep_Tool::Pnt(trV1);
221 gp_Pnt trP2 = BRep_Tool::Pnt(trV2);
224 aBox.SetGap(tolerance);
225 aTreeFiller.Add(inbW, aBox);
227 Standard_Integer nbFill;
228 nbFill = aTreeFiller.Fill();
229 Standard_Integer nsel;
231 ShapeAnalysis_Edge sae; //szv#4:S4163:12Mar99 moved
232 Standard_Boolean done = Standard_False;
235 Standard_Boolean found = Standard_False, tail = Standard_False, direct = Standard_False;
236 Standard_Integer lwire=0;
238 Bnd_Box FVBox, LVBox;
239 TopoDS_Vertex Vf, Vl;
240 Vf = sae.FirstVertex(sewd->Edge(1));
241 Vl = sae.LastVertex(sewd->Edge(sewd->NbEdges()));
243 pf = BRep_Tool::Pnt(Vf);
244 pl = BRep_Tool::Pnt(Vl);
246 FVBox.SetGap(tolerance);
248 LVBox.SetGap(tolerance);
250 aSel.DefineBoxes(FVBox, LVBox);
253 aSel.DefineVertexes(Vf,Vl);
255 aSel.DefinePnt(pf,pl);
256 aSel.SetTolerance(tolerance);
259 nsel = aBBTree.Select(aSel);
261 if (nsel != 0 && !aSel.LastCheckStatus(ShapeExtend_FAIL)) {
262 found = Standard_True;
263 lwire = aSel.GetNb();
264 tail = aSel.LastCheckStatus (ShapeExtend_DONE1) ||
265 aSel.LastCheckStatus (ShapeExtend_DONE2);
266 direct = aSel.LastCheckStatus (ShapeExtend_DONE1) ||
267 aSel.LastCheckStatus (ShapeExtend_DONE3);
268 aSel.LoadList(lwire);
272 if (!direct) arrwires->ChangeValue(lwire).Reverse();
273 TopoDS_Wire aCurW = TopoDS::Wire (arrwires->Value (lwire));
274 Handle(ShapeExtend_WireData) acurwd =
275 new ShapeExtend_WireData ( TopoDS::Wire (arrwires->Value (lwire)));
276 sewd->Add (acurwd, (tail ? 0 : 1));
280 //1.providing connection (see ShapeFix_Wire::FixConnected())
281 //Standard_Integer i; // svv #1
282 for (/*Standard_Integer*/ i = 1; i <= saw->NbEdges(); i++) {
283 if (saw->CheckConnected (i)) {
284 Standard_Integer n2 = i;
285 Standard_Integer n1 = (n2 > 1 ? n2 - 1 : saw->NbEdges());
286 TopoDS_Edge E1 = sewd->Edge(n1);
287 TopoDS_Edge E2 = sewd->Edge(n2);
289 TopoDS_Vertex Vprev, Vfol, V; //connection vertex
290 Vprev = sae.LastVertex (E1);
291 Vfol = sae.FirstVertex (E2);
293 if (saw->LastCheckStatus (ShapeExtend_DONE1)) //absolutely confused
296 ShapeBuild_Vertex sbv;
297 V = sbv.CombineVertex (Vprev, Vfol);
299 vertices.Bind (Vprev, V);
300 vertices.Bind (Vfol, V);
302 //replace vertices to a new one
304 if (saw->NbEdges() < 2)
305 sewd->Set (sbe.CopyReplaceVertices (E2, V, V), n2);
307 sewd->Set (sbe.CopyReplaceVertices (E2, V, TopoDS_Vertex()), n2);
308 if (!saw->LastCheckStatus (ShapeExtend_DONE1))
309 sewd->Set (sbe.CopyReplaceVertices (E1, TopoDS_Vertex(), V), n1);
315 TopoDS_Wire wire = sewd->Wire();
316 if (!saw->CheckConnected (1) && saw->LastCheckStatus (ShapeExtend_OK))
317 wire.Closed (Standard_True);
318 owires->Append (wire);
321 // Recherche de la premier edge non traitee pour un autre wire.
322 //Searching for first edge for next wire
324 for (/*Standard_Integer*/ i = 1 ; i <= arrwires->Length() && lwire == -1; i++)
325 if (!aSel.ContWire(i)) lwire = i; //szv#4:S4163:12Mar99 optimized
327 if (lwire == -1) done = 1;
329 sewd->Add (TopoDS::Wire (arrwires->Value (lwire)));
330 aSel.LoadList(lwire);
334 for ( /*Standard_Integer*/ i = 1; i <= iwires->Length(); i++)
335 iwires->SetValue (i, arrwires->Value(i));
338 static void SplitWire(const TopoDS_Wire& wire,
339 const Standard_Real toler,
340 const Standard_Boolean shared,
341 Handle(TopTools_HSequenceOfShape)& closed,
342 Handle(TopTools_HSequenceOfShape)& open)
344 closed = new TopTools_HSequenceOfShape;
345 open = new TopTools_HSequenceOfShape;
346 Standard_Real tolerance = Max (toler, Precision::Confusion());
349 ShapeAnalysis_Edge sae;
351 Handle(ShapeExtend_WireData) sewd = new ShapeExtend_WireData (wire);
352 Standard_Integer nbedges = sewd->NbEdges();
354 //ConnectedEdgeSequence - list of indices of connected edges to build a wire
355 TColStd_SequenceOfInteger ces;
356 //statuses - array of flags describing the edge:
357 //0-free, 1-in CES, 2-already in wire,
358 //3-no closed wire can be produced starting at this edge
359 TColStd_Array1OfInteger statuses (1, nbedges);
362 //building closed wires
363 Standard_Integer i; // svv #1
364 for (i = 1; i <= nbedges; i++)
365 if (statuses.Value (i) == 0) {
366 ces.Append (i); statuses.SetValue (i, 1); //putting into CES
367 Standard_Boolean SearchBackward = Standard_True;
370 Standard_Integer ei = ces.Last(); //ei-edge index, number of current edge analyzed for connection
371 Standard_Boolean found;
373 TopoDS_Vertex lvertex;
376 //searching for connection in ces
377 if (SearchBackward) {
378 SearchBackward = Standard_False;
379 found = Standard_False;
380 edge = sewd->Edge (ces.Last());
381 lvertex = sae.LastVertex (edge);
382 lpoint = BRep_Tool::Pnt (lvertex);
383 Standard_Integer j; // svv #1
384 for (j = ces.Length(); (j >= 1) && !found; j--) {
385 TopoDS_Vertex fv = sae.FirstVertex (sewd->Edge (ces.Value (j)) );
386 gp_Pnt fp = BRep_Tool::Pnt (fv);
387 if ((shared && lvertex.IsSame (fv)) ||
388 (!shared && lpoint.IsEqual (fp, tolerance)))
389 found = Standard_True;
393 j++;//because of decreasing last iteration
397 for (Standard_Integer cesindex = j; cesindex <= ces.Length(); cesindex++) {
398 B.Add (wire1, sewd->Edge (ces.Value (cesindex)));
399 statuses.SetValue (ces.Value (cesindex), 2);
401 wire1.Closed (Standard_True);
402 closed->Append (wire1);
403 ces.Remove (j, ces.Length());
404 if (ces.IsEmpty()) break;
408 //searching for connection among free edges
409 found = Standard_False;
411 edge = sewd->Edge (ces.Last());
412 lvertex = sae.LastVertex (edge);
413 lpoint = BRep_Tool::Pnt (lvertex);
414 Standard_Integer j; // svv #1
415 for (j = 1; (j <= nbedges) && !found; j++)
416 if (statuses.Value (j) == 0) {
417 TopoDS_Vertex fv = sae.FirstVertex (sewd->Edge (j));
418 gp_Pnt fp = BRep_Tool::Pnt (fv);
419 if ((shared && lvertex.IsSame (fv)) ||
420 (!shared && lpoint.IsEqual (fp, tolerance)))
421 found = Standard_True;
425 j--;//because of last iteration
426 ces.Append (j); statuses.SetValue (j, 1);//putting into CES
427 SearchBackward = Standard_True;
431 //no edges found - mark the branch as open (use status 3)
432 statuses.SetValue (ces.Last(), 3);
433 ces.Remove (ces.Length());
434 if (ces.IsEmpty()) break;
438 //building open wires
439 Handle(TopTools_HSequenceOfShape) edges = new TopTools_HSequenceOfShape;
440 for (i = 1; i <= nbedges; i++)
441 if (statuses.Value (i) != 2) edges->Append (sewd->Edge(i));
443 ShapeAnalysis_FreeBounds::ConnectEdgesToWires (edges, toler, shared, open);
446 void ShapeAnalysis_FreeBounds::SplitWires(const Handle(TopTools_HSequenceOfShape)& wires,
447 const Standard_Real toler,
448 const Standard_Boolean shared,
449 Handle(TopTools_HSequenceOfShape)& closed,
450 Handle(TopTools_HSequenceOfShape)& open)
452 closed = new TopTools_HSequenceOfShape;
453 open = new TopTools_HSequenceOfShape;
455 for (Standard_Integer i = 1; i <= wires->Length(); i++) {
456 Handle(TopTools_HSequenceOfShape) tmpclosed, tmpopen;
457 SplitWire (TopoDS::Wire (wires->Value (i)), toler, shared, tmpclosed, tmpopen);
458 closed->Append (tmpclosed);
459 open->Append (tmpopen);
463 //=======================================================================
464 //function : DispatchWires
466 //=======================================================================
468 void ShapeAnalysis_FreeBounds::DispatchWires(const Handle(TopTools_HSequenceOfShape)& wires,
469 TopoDS_Compound& closed,
470 TopoDS_Compound& open)
473 if (closed.IsNull()) B.MakeCompound (closed);
474 if (open.IsNull()) B.MakeCompound (open);
475 if (wires.IsNull()) return;
477 for (Standard_Integer iw = 1 ; iw <= wires->Length(); iw++)
478 if ( wires->Value (iw).Closed() )
479 B.Add (closed, wires->Value (iw));
481 B.Add (open, wires->Value (iw));
484 //=======================================================================
485 //function : SplitWires
486 //purpose : Splits compounds of closed (myWires) and open (myEdges) wires
487 // into small closed wires according to fields mySplitClosed and
488 // mySplitOpen and rebuilds compounds
489 //=======================================================================
491 void ShapeAnalysis_FreeBounds::SplitWires()
493 if (!mySplitClosed && !mySplitOpen) return; //nothing to do
495 ShapeExtend_Explorer see;
496 Handle(TopTools_HSequenceOfShape) closedwires, cw1, cw2,
498 closedwires = see.SeqFromCompound (myWires, Standard_False);
499 openwires = see.SeqFromCompound (myEdges, Standard_False);
501 if (mySplitClosed) SplitWires (closedwires, myTolerance, myShared, cw1, ow1);
502 else {cw1 = closedwires; ow1 = new TopTools_HSequenceOfShape;}
504 if (mySplitOpen) SplitWires (openwires, myTolerance, myShared, cw2, ow2);
505 else {cw2 = new TopTools_HSequenceOfShape; ow2 = openwires;}
507 closedwires = cw1; closedwires->Append (cw2);
508 openwires = ow1; openwires->Append (ow2);
510 //szv#4:S4163:12Mar99 SGI warns
511 TopoDS_Shape compWires = see.CompoundFromSeq (closedwires);
512 TopoDS_Shape compEdges = see.CompoundFromSeq (openwires);
513 myWires = TopoDS::Compound (compWires);
514 myEdges = TopoDS::Compound (compEdges);