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 | |
55 | ShapeAnalysis_FreeBounds::ShapeAnalysis_FreeBounds() {} |
56 | |
57 | //======================================================================= |
58 | //function : ShapeAnalysis_FreeBounds |
59 | //purpose : |
60 | //======================================================================= |
61 | |
62 | ShapeAnalysis_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 | |
98 | ShapeAnalysis_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 | |
324 | static 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 | } |