b311480e |
1 | // Created on: 1999-06-18 |
2 | // Created by: Sergei ZERTCHANINOV |
3 | // Copyright (c) 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. |
7fd59977 |
16 | |
17 | #include <ShapeFix_FaceConnect.ixx> |
18 | |
19 | #include <Standard_ErrorHandler.hxx> |
20 | #include <Standard_Failure.hxx> |
21 | |
22 | #include <TopoDS.hxx> |
23 | #include <TopoDS_Wire.hxx> |
24 | #include <TopoDS_Edge.hxx> |
25 | #include <TopoDS_Vertex.hxx> |
26 | #include <TopoDS_Iterator.hxx> |
27 | #include <TopTools_ListOfShape.hxx> |
28 | #include <TopTools_Array1OfShape.hxx> |
29 | #include <TopTools_ListIteratorOfListOfShape.hxx> |
30 | #include <TopTools_DataMapIteratorOfDataMapOfShapeShape.hxx> |
31 | #include <TopTools_DataMapIteratorOfDataMapOfShapeListOfShape.hxx> |
32 | |
33 | #include <BRep_Tool.hxx> |
34 | #include <BRep_Builder.hxx> |
35 | #include <BRepBuilderAPI_Sewing.hxx> |
36 | #include <TopExp_Explorer.hxx> |
37 | #include <TopExp.hxx> |
38 | #include <gp_Pnt.hxx> |
39 | |
40 | #include <ShapeBuild_ReShape.hxx> |
41 | |
42 | #include <ShapeFix_Face.hxx> |
43 | #include <ShapeFix_Wire.hxx> |
44 | #include <ShapeAnalysis_Edge.hxx> |
45 | #include <ShapeAnalysis_WireOrder.hxx> |
46 | #include <Geom2d_Curve.hxx> |
0797d9d3 |
47 | #ifdef OCCT_DEBUG |
7fd59977 |
48 | #include <TopTools_MapOfShape.hxx> |
49 | #endif |
50 | |
51 | //======================================================================= |
52 | //function : ShapeFix_FaceConnect |
53 | //======================================================================= |
54 | |
55 | ShapeFix_FaceConnect::ShapeFix_FaceConnect() {} |
56 | |
57 | //======================================================================= |
58 | //function : Connect |
59 | //purpose : |
60 | //======================================================================= |
61 | |
62 | Standard_Boolean ShapeFix_FaceConnect::Add(const TopoDS_Face& aFirst, |
63 | const TopoDS_Face& aSecond) |
64 | { |
65 | if (!aFirst.IsNull() && !aSecond.IsNull()) { |
66 | // Process first face |
67 | if (myConnected.IsBound(aFirst)) { |
68 | // Find list for the first face |
69 | TopTools_ListOfShape& theFirstList = myConnected(aFirst); |
70 | // Append second face to the first list |
71 | TopTools_ListIteratorOfListOfShape theIter; |
72 | for ( theIter.Initialize(theFirstList); theIter.More(); theIter.Next() ) |
73 | if (theIter.Value().IsSame(aSecond)) return Standard_True; |
74 | theFirstList.Append(aSecond); |
75 | } |
76 | else { |
77 | // Append second face to the first list |
78 | TopTools_ListOfShape theNewFirstList; |
79 | theNewFirstList.Append(aSecond); |
80 | myConnected.Bind(aFirst,theNewFirstList); |
81 | } |
82 | |
83 | // Process second face if not same |
84 | if (!aFirst.IsSame(aSecond)) { |
85 | if (myConnected.IsBound(aSecond)) { |
86 | // No need to iterate on faces - append first |
87 | myConnected(aSecond).Append(aFirst); |
88 | } |
89 | else { |
90 | // Append first face to the second list |
91 | TopTools_ListOfShape theNewSecondList; |
92 | theNewSecondList.Append(aFirst); |
93 | myConnected.Bind(aSecond,theNewSecondList); |
94 | } |
95 | } |
96 | |
97 | return Standard_True; |
98 | } |
99 | |
100 | return Standard_False; |
101 | } |
102 | |
103 | //======================================================================= |
104 | //function : Build |
105 | //purpose : |
106 | //======================================================================= |
107 | |
108 | TopoDS_Shell ShapeFix_FaceConnect::Build (const TopoDS_Shell& shell, |
109 | const Standard_Real sewtoler, |
110 | const Standard_Real fixtoler) |
111 | { |
112 | TopoDS_Shell result = shell; |
113 | |
114 | /*************************************************************** |
115 | / INITIAL PREPARATIONS |
116 | / Fill map of original free edges, |
117 | / fill maps of resulting free and shared edges |
118 | ***************************************************************/ |
119 | |
120 | // Clear maps of free and shared edges |
121 | myOriFreeEdges.Clear(); |
122 | myResFreeEdges.Clear(); |
123 | myResSharEdges.Clear(); |
124 | |
125 | TopTools_DataMapOfShapeShape theFreeEdges; |
126 | TopoDS_Shape theEdge, theFace; |
127 | |
128 | // Fill map of free edges / faces |
129 | for ( TopoDS_Iterator itf(result); itf.More(); itf.Next() ) { |
130 | theFace = itf.Value(); |
131 | for ( TopExp_Explorer expe(theFace,TopAbs_EDGE); expe.More(); expe.Next() ) { |
132 | theEdge = expe.Current(); |
133 | if (theFreeEdges.IsBound(theEdge)) theFreeEdges.UnBind(theEdge); |
134 | else theFreeEdges.Bind(theEdge,theFace); |
135 | } |
136 | } |
137 | |
138 | // Fill maps of original and resulting edges |
139 | for ( TopTools_DataMapIteratorOfDataMapOfShapeShape theFEIter( theFreeEdges ); |
140 | theFEIter.More(); theFEIter.Next() ) { |
141 | // Get pair (face / free edge) |
142 | theEdge = theFEIter.Key(), theFace = theFEIter.Value(); |
143 | // Process faces with bad connectivities only |
144 | if (myConnected.IsBound(theFace) && |
145 | !BRep_Tool::Degenerated(TopoDS::Edge(theEdge))) { |
146 | // Add to the map of original free edges |
147 | if (myOriFreeEdges.IsBound(theFace)) { |
148 | // Append free edge to the existing list |
149 | myOriFreeEdges(theFace).Append(theEdge); |
150 | } |
151 | else { |
152 | // Append free edge to the new list |
153 | TopTools_ListOfShape theNewList; |
154 | theNewList.Append(theEdge); |
155 | myOriFreeEdges.Bind(theFace,theNewList); |
156 | } |
157 | // Add to the maps of intermediate free and resulting edges |
158 | if (!myResFreeEdges.IsBound(theEdge)) { |
159 | TopTools_ListOfShape theFree, theShared; |
160 | theFree.Append(theEdge); |
161 | myResFreeEdges.Bind(theEdge,theFree); |
162 | myResSharEdges.Bind(theEdge,theShared); |
163 | } |
164 | } |
165 | } |
166 | |
167 | // Clear the temporary map of free edges |
168 | theFreeEdges.Clear(); |
169 | |
0797d9d3 |
170 | #ifdef OCCT_DEBUG |
7fd59977 |
171 | //------------------------------- |
172 | //szv debug - preparation results |
173 | //------------------------------- |
174 | if (!myOriFreeEdges.IsEmpty()) { |
175 | cout<<endl<<"FACE CONNECT PREPARATION RESULTS:"<<endl; |
176 | cout<<"---------------------------------"<<endl; |
177 | Standard_Integer freenum = 0, facenum = 0; |
178 | for ( TopTools_DataMapIteratorOfDataMapOfShapeListOfShape theOFIter( myOriFreeEdges ); |
179 | theOFIter.More(); theOFIter.Next() ) { |
180 | freenum += theOFIter.Value().Extent(); |
181 | facenum++; |
182 | } |
183 | cout<<"TOTAL: "<<facenum<<" faces containing "<<freenum<<" free edges"<<endl; |
184 | } |
185 | //------------------------------- |
186 | #endif |
187 | |
188 | /*************************************************************** |
189 | / APPLY SEWING ON CONNECTED FACES |
190 | / Change maps of original free edges and resulting shared edges |
191 | ***************************************************************/ |
192 | |
193 | if (!myOriFreeEdges.IsEmpty()) { |
194 | |
195 | // Allocate array of faces to be sewed |
196 | TopoDS_Shape theFirstFace, theSecondFace; |
197 | TopTools_Array1OfShape theFacesToSew(1,2); |
198 | Standard_Integer theNumOfFacesToSew = 0; |
199 | Standard_Boolean skip_pair = Standard_False; |
200 | |
201 | TopTools_ListIteratorOfListOfShape theOriginalIter, theResultsIter; |
202 | TopoDS_Shape theAuxE, theOrigE, theAuxF; |
203 | |
204 | BRep_Builder theBuilder; |
205 | |
206 | TopTools_DataMapOfShapeListOfShape theProcessed; |
207 | |
208 | for ( TopTools_DataMapIteratorOfDataMapOfShapeListOfShape theConnectedIter( myConnected ); |
209 | theConnectedIter.More(); theConnectedIter.Next() ) { |
210 | // Process first face only if it is in the map of faces / free edges |
211 | theFirstFace = theConnectedIter.Key(); |
212 | if (myOriFreeEdges.IsBound(theFirstFace)) { |
213 | |
214 | // Place first face into the array |
215 | theFacesToSew.SetValue(1,theFirstFace); |
216 | theNumOfFacesToSew = 1; |
217 | // Create the list of processed faces |
218 | TopTools_ListOfShape theProcessedList; |
219 | |
220 | // Explore the list of connected faces |
221 | const TopTools_ListOfShape& theConnectedList = theConnectedIter.Value(); |
222 | TopTools_ListIteratorOfListOfShape theConnectedListIter; |
223 | for ( theConnectedListIter.Initialize(theConnectedList); |
224 | theConnectedListIter.More(); theConnectedListIter.Next() ) { |
225 | // Process second face only if it is in the map of faces / free edges |
226 | theSecondFace = theConnectedListIter.Value(); |
227 | if (myOriFreeEdges.IsBound(theSecondFace)) { |
228 | |
229 | // Place second face into the array |
230 | theFacesToSew.SetValue(2,theSecondFace); |
231 | // Add second face to the list of processed faces |
232 | theProcessedList.Append(theSecondFace); |
233 | |
234 | // Skip the pair if already processed |
235 | skip_pair = Standard_False; |
236 | if (theProcessed.IsBound(theSecondFace)) { |
237 | TopTools_ListOfShape& theProcCnxList = theProcessed(theSecondFace); |
238 | TopTools_ListIteratorOfListOfShape theProcCnxListIter; |
239 | for ( theProcCnxListIter.Initialize(theProcCnxList); |
240 | theProcCnxListIter.More() && !skip_pair; theProcCnxListIter.Next() ) |
241 | if (theFirstFace.IsSame(theProcCnxListIter.Value())) |
242 | skip_pair = Standard_True; |
243 | } |
244 | if (!skip_pair) { |
245 | |
246 | // Process second face for the pair of different faces only |
247 | if (theFirstFace.IsSame(theSecondFace)) { |
0797d9d3 |
248 | #ifdef OCCT_DEBUG |
7fd59977 |
249 | cout<<"Warning: ShapeFix_FaceConnect::Build: Self-connected face"<<endl; |
250 | #endif |
251 | } |
252 | else theNumOfFacesToSew = 2; |
253 | |
254 | TopTools_DataMapOfShapeShape theSewerWires; |
255 | BRepBuilderAPI_Sewing theSewer(sewtoler); |
256 | |
257 | // Prepare set of faces containing free edges |
258 | Standard_Integer i = 1; |
259 | for (i=1; i<=theNumOfFacesToSew; i++) { |
260 | // Prepare empty face to fill with free edges |
261 | TopoDS_Shape theFaceToSew = theFacesToSew(i); |
262 | theAuxF = theFaceToSew.EmptyCopied(); |
263 | // Fill empty face with free edges |
264 | for ( theOriginalIter.Initialize(myOriFreeEdges(theFaceToSew)); |
265 | theOriginalIter.More(); theOriginalIter.Next() ) { |
266 | for ( theResultsIter.Initialize(myResFreeEdges(theOriginalIter.Value())); |
267 | theResultsIter.More(); theResultsIter.Next() ) { |
268 | // Bind free edge to wire to find results later |
269 | theAuxE = theResultsIter.Value(); |
270 | TopoDS_Wire theAuxW; |
271 | theBuilder.MakeWire(theAuxW); |
272 | theBuilder.Add(theAuxW,theAuxE); |
273 | theBuilder.Add(theAuxF,theAuxW); |
274 | theSewerWires.Bind(theAuxE,theAuxW); |
275 | theSewer.Add(theAuxW); |
276 | } |
277 | } |
278 | // Add constructed face to sewer |
279 | theSewer.Add(theAuxF); |
280 | } |
281 | |
282 | // Perform sewing on the list of free edges |
283 | Standard_Boolean sewing_ok = Standard_True; |
284 | { |
285 | try { OCC_CATCH_SIGNALS theSewer.Perform(); } |
286 | catch(Standard_Failure) { sewing_ok = Standard_False; } |
287 | } |
288 | if ( sewing_ok ) |
289 | if (theSewer.SewedShape().IsNull()) sewing_ok = Standard_False; |
290 | |
291 | if ( sewing_ok ) { |
292 | TopTools_DataMapOfShapeShape theResultEdges; |
293 | |
294 | // Find modified edges for the faces |
295 | for (i=1; i<=theNumOfFacesToSew; i++) { |
296 | for ( theOriginalIter.Initialize(myOriFreeEdges(theFacesToSew(i))); |
297 | theOriginalIter.More(); theOriginalIter.Next() ) { |
298 | // Get original free edge |
299 | theOrigE = theOriginalIter.Value(); |
300 | TopTools_ListOfShape& theOldFreeList = myResFreeEdges(theOrigE); |
301 | theResultsIter.Initialize(theOldFreeList); |
302 | while ( theResultsIter.More() ) { |
303 | theAuxE = theSewerWires(theResultsIter.Value()); |
304 | // Process modified edges |
305 | if (theSewer.IsModified(theAuxE)) { |
306 | // Fill map of result edges |
307 | for ( TopExp_Explorer expe(theSewer.Modified(theAuxE),TopAbs_EDGE); |
308 | expe.More(); expe.Next() ) { |
309 | theAuxE = expe.Current(); |
310 | // Check edge for being shared |
311 | if (theResultEdges.IsBound(theAuxE)) { |
312 | // Edge was shared - move in results list |
313 | myResSharEdges(theResultEdges(theAuxE)).Append(theAuxE); |
314 | myResSharEdges(theOrigE).Append(theAuxE); |
315 | theResultEdges.UnBind(theAuxE); |
316 | } |
317 | else theResultEdges.Bind(theAuxE,theOrigE); |
318 | } |
319 | // Remove modified free edge from the list |
320 | theOldFreeList.Remove(theResultsIter); |
321 | } |
322 | else theResultsIter.Next(); |
323 | } |
324 | } |
325 | } |
326 | |
327 | // Put free edges back to the lists of results |
328 | for ( TopTools_DataMapIteratorOfDataMapOfShapeShape theResIter( theResultEdges ); |
329 | theResIter.More(); theResIter.Next() ) { |
330 | theAuxE = theResIter.Key(); |
331 | myResFreeEdges(theResIter.Value()).Append(theAuxE); |
332 | } |
333 | } |
334 | } |
335 | } |
336 | } |
337 | |
338 | // Bind the list of processed faces to the processed face |
339 | theProcessed.Bind(theFirstFace,theProcessedList); |
340 | } |
341 | } |
342 | |
343 | // Clear the temporary map of processed faces |
344 | theProcessed.Clear(); |
345 | |
0797d9d3 |
346 | #ifdef OCCT_DEBUG |
7fd59977 |
347 | //------------------------------- |
348 | //szv debug - sewing results |
349 | //------------------------------- |
350 | cout<<endl<<"FACE CONNECT SEWING RESULTS:"<<endl; |
351 | cout<<"----------------------------"<<endl; |
352 | cout<<"Sewing tolerance was set to "<<sewtoler<<endl; |
353 | Standard_Integer totfree = 0, totshared = 0; |
354 | for ( TopTools_DataMapIteratorOfDataMapOfShapeListOfShape theOF2Iter( myOriFreeEdges ); |
355 | theOF2Iter.More(); theOF2Iter.Next() ) { |
356 | TopTools_ListIteratorOfListOfShape theOFL2Iter; |
357 | for ( theOFL2Iter.Initialize(theOF2Iter.Value()); |
358 | theOFL2Iter.More(); theOFL2Iter.Next() ) { |
359 | totfree += myResFreeEdges(theOFL2Iter.Value()).Extent(); |
360 | totshared += myResSharEdges(theOFL2Iter.Value()).Extent(); |
361 | } |
362 | } |
363 | cout<<"TOTAL: "<<totfree<<" free, "<<totshared<<" shared edges"<<endl; |
364 | //------------------------------- |
365 | #endif |
366 | |
367 | /*************************************************************** |
368 | / PERFORM EDGES REPLACEMENT |
369 | ***************************************************************/ |
370 | |
371 | TopTools_DataMapOfShapeShape theRepEdges; |
372 | TopTools_DataMapOfShapeListOfShape theRepVertices; |
373 | TopTools_DataMapOfShapeShape theOldVertices; |
374 | TopTools_DataMapOfShapeListOfShape theNewVertices; |
375 | |
376 | // Replace old edges by resulting ones |
377 | TopoDS_Wire theNewW; |
378 | TopoDS_Vertex theOldV1, theOldV2, theNewV1, theNewV2, theNewV; |
379 | gp_Pnt theOldP1, theOldP2; |
380 | Standard_Real dist1, dist2, curdist1, curdist2; |
381 | for ( TopTools_DataMapIteratorOfDataMapOfShapeListOfShape theOEIter( myOriFreeEdges ); |
382 | theOEIter.More(); theOEIter.Next() ) { |
383 | // Iterate on original free edges |
384 | for ( theOriginalIter.Initialize(theOEIter.Value()); |
385 | theOriginalIter.More(); theOriginalIter.Next() ) { |
386 | TopoDS_Edge theOldE = TopoDS::Edge(theOriginalIter.Value()); |
387 | |
388 | // Prepare empty wire to add new edges for reshape |
389 | theBuilder.MakeWire(theNewW); |
390 | |
391 | // Explore new edges and vertices |
392 | Standard_Boolean emptywire = Standard_True; |
393 | for (Standard_Integer i = 1; i<=2; i++) { |
394 | // Select list of free or shared edges |
395 | if (i==1) theResultsIter.Initialize(myResFreeEdges(theOldE)); |
396 | else theResultsIter.Initialize(myResSharEdges(theOldE)); |
397 | // Iterate on new edges |
398 | for ( ; theResultsIter.More(); theResultsIter.Next() ) { |
399 | theAuxE = theResultsIter.Value(); |
400 | if (!theAuxE.IsSame(theOldE)) { |
401 | // Add new edge to the wire |
402 | theBuilder.Add(theNewW,theAuxE); |
403 | emptywire = Standard_False; |
404 | } |
405 | } |
406 | } |
407 | |
408 | if (!emptywire) { |
409 | |
410 | // Get vertices on old and new edges |
411 | TopExp::Vertices(theOldE,theOldV1,theOldV2); |
412 | theOldP1 = BRep_Tool::Pnt(theOldV1); |
413 | theOldP2 = BRep_Tool::Pnt(theOldV2); |
414 | |
415 | // Process vertices for replacing |
416 | dist1 = -1.; dist2 = -1.; |
417 | for ( TopExp_Explorer expv(theNewW,TopAbs_VERTEX); |
418 | expv.More(); expv.Next() ) { |
419 | TopoDS_Vertex theNewVtx = TopoDS::Vertex(expv.Current()); |
420 | gp_Pnt theNewPt = BRep_Tool::Pnt(theNewVtx); |
421 | curdist1 = theOldP1.Distance(theNewPt); |
422 | curdist2 = theOldP2.Distance(theNewPt); |
423 | if (dist1<0 || curdist1<dist1) { dist1 = curdist1; theNewV1 = theNewVtx; } |
424 | if (dist2<0 || curdist2<dist2) { dist2 = curdist2; theNewV2 = theNewVtx; } |
425 | } |
426 | |
427 | // Place results in map for replacing |
428 | if (!theOldV1.IsSame(theNewV1)) { |
429 | if (theRepVertices.IsBound(theOldV1)) { |
430 | TopTools_ListOfShape& theList1 = theRepVertices(theOldV1); |
431 | TopTools_ListIteratorOfListOfShape theIter1; |
432 | Standard_Boolean found = Standard_False; |
433 | for ( theIter1.Initialize(theList1); theIter1.More(); theIter1.Next() ) |
434 | if (theIter1.Value().IsSame(theNewV1)) { found = Standard_True; break; } |
435 | if (!found) theList1.Append(theNewV1); |
436 | } |
437 | else { |
438 | TopTools_ListOfShape theNewList1; |
439 | theNewList1.Append(theNewV1); |
440 | theRepVertices.Bind(theOldV1,theNewList1); |
441 | } |
442 | } |
443 | if (!theOldV2.IsSame(theNewV2)) { |
444 | if (theRepVertices.IsBound(theOldV2)) { |
445 | TopTools_ListOfShape& theList2 = theRepVertices(theOldV2); |
446 | TopTools_ListIteratorOfListOfShape theIter2; |
447 | Standard_Boolean found = Standard_False; |
448 | for ( theIter2.Initialize(theList2); theIter2.More(); theIter2.Next() ) |
449 | if (theIter2.Value().IsSame(theNewV2)) { found = Standard_True; break; } |
450 | if (!found) theList2.Append(theNewV2); |
451 | } |
452 | else { |
453 | TopTools_ListOfShape theNewList2; |
454 | theNewList2.Append(theNewV2); |
455 | theRepVertices.Bind(theOldV2,theNewList2); |
456 | } |
457 | } |
458 | |
459 | // Bind edge to replace |
460 | theRepEdges.Bind(theOldE,theNewW); |
461 | } |
462 | } |
463 | } |
464 | |
465 | if (!theRepEdges.IsEmpty()) { |
466 | |
467 | Handle(ShapeBuild_ReShape) theReShape = new ShapeBuild_ReShape; |
468 | |
469 | // Replace edges |
470 | for ( TopTools_DataMapIteratorOfDataMapOfShapeShape theREIter( theRepEdges ); |
471 | theREIter.More(); theREIter.Next() ) { |
472 | theReShape->Replace(theREIter.Key()/*.Oriented(TopAbs_FORWARD)*/, |
473 | theREIter.Value()/*.Oriented(TopAbs_FORWARD)*/); |
474 | } |
475 | //smh#8 |
476 | TopoDS_Shape tmpReShape = theReShape->Apply(result); |
477 | result = TopoDS::Shell(tmpReShape); |
478 | if (theReShape->Status(ShapeExtend_OK)) { |
0797d9d3 |
479 | #ifdef OCCT_DEBUG |
7fd59977 |
480 | cout<<"Warning: ShapeFix_FaceConnect::Build: Edges not replaced by ReShape"<<endl; |
481 | #endif |
482 | } |
483 | else if (theReShape->Status(ShapeExtend_FAIL1)) { |
0797d9d3 |
484 | #ifdef OCCT_DEBUG |
7fd59977 |
485 | cout<<"Error: ShapeFix_FaceConnect::Build: ReShape failed on edges"<<endl; |
486 | #endif |
487 | } |
488 | else { |
489 | |
490 | Handle(ShapeFix_Wire) SFW = new ShapeFix_Wire; |
491 | Handle(ShapeFix_Face) SFF = new ShapeFix_Face; |
492 | ShapeAnalysis_Edge SAE; |
493 | Standard_Real f,l; |
494 | Handle(Geom2d_Curve) c2d; |
495 | Handle(ShapeExtend_WireData) sewd; |
496 | |
497 | // Perform necessary fixes on subshapes |
498 | //smh#8 |
499 | TopoDS_Shape emptyCopiedShell = result.EmptyCopied(); |
500 | TopoDS_Shell theShell = TopoDS::Shell(emptyCopiedShell); |
501 | for ( TopoDS_Iterator itf1(result); itf1.More(); itf1.Next() ) { |
502 | TopoDS_Face newface = TopoDS::Face(itf1.Value()); |
503 | //smh#8 |
504 | TopoDS_Shape emptyCopiedFace = newface.EmptyCopied(); |
505 | TopoDS_Face EmpFace = TopoDS::Face(emptyCopiedFace); |
506 | for ( TopoDS_Iterator itw(newface); itw.More(); itw.Next() ) { |
507 | if(itw.Value().ShapeType() != TopAbs_WIRE) |
508 | continue; |
509 | TopoDS_Wire theWire = TopoDS::Wire(itw.Value()); |
510 | |
511 | sewd = new ShapeExtend_WireData( theWire ); |
512 | ShapeAnalysis_WireOrder SAWO(Standard_False, 0); |
513 | for (Standard_Integer i = 1; i <= sewd->NbEdges(); i++) { |
514 | |
515 | //smh#8 |
516 | TopoDS_Shape tmpFace = EmpFace.Oriented(TopAbs_FORWARD); |
517 | if (!SAE.PCurve(sewd->Edge(i), |
518 | TopoDS::Face(tmpFace), |
519 | c2d,f,l)) continue; |
520 | SAWO.Add(c2d->Value(f).XY(),c2d->Value(l).XY()); |
521 | } |
522 | SAWO.Perform(); |
523 | |
524 | SFW->Load(sewd); |
525 | SFW->FixReorder(SAWO); |
526 | SFW->FixReorder(); |
527 | |
528 | SFW->SetFace(EmpFace); |
529 | SFW->SetPrecision(fixtoler); |
530 | SFW->SetMaxTolerance(sewtoler); |
531 | |
532 | SFW->FixEdgeCurves(); |
533 | SFW->FixSelfIntersection(); |
534 | theWire = SFW->Wire(); |
535 | theBuilder.Add(EmpFace,theWire); |
536 | } |
537 | // #ifdef AIX CKY : applies to all platforms |
538 | SFF->Init(EmpFace); |
539 | // SFF->Init(TopoDS::Face(EmpFace)); |
540 | |
541 | TopTools_DataMapOfShapeListOfShape MapWires; |
542 | MapWires.Clear(); |
543 | if (SFF->FixOrientation(MapWires)) EmpFace = SFF->Face(); |
544 | theBuilder.Add(theShell,EmpFace); |
545 | } |
ab860031 |
546 | theShell.Closed (BRep_Tool::IsClosed (theShell)); |
7fd59977 |
547 | result = theShell; |
548 | |
549 | if (!theRepVertices.IsEmpty()) { |
550 | |
551 | // Prepare vertices to replace |
552 | TopoDS_Shape theOld, theNew, theRep, theAux; |
553 | for ( TopTools_DataMapIteratorOfDataMapOfShapeListOfShape theRV1Iter( theRepVertices ); |
554 | theRV1Iter.More(); theRV1Iter.Next() ) { |
555 | // Get the old vertex, create empty list of replaced vertices |
556 | theOld = theRV1Iter.Key(); |
557 | TopTools_ListOfShape theNewList; |
558 | // Explore the list of new vertices |
559 | TopTools_ListIteratorOfListOfShape theN1Iter; |
560 | for ( theN1Iter.Initialize(theRV1Iter.Value()); theN1Iter.More(); theN1Iter.Next() ) { |
561 | theNew = theN1Iter.Value(); |
562 | if (theOldVertices.IsBound(theNew)) { |
563 | // Vertex has a replacing vertex in the map |
564 | theRep = theOldVertices(theNew); |
565 | if (!theRep.IsSame(theOld)) { |
566 | // Vertex is not in current list |
567 | theOldVertices.Bind(theRep,theOld); |
568 | theNewList.Append(theRep); |
569 | TopTools_ListIteratorOfListOfShape theN3Iter; |
570 | for ( theN3Iter.Initialize(theNewVertices(theRep)); |
571 | theN3Iter.More(); theN3Iter.Next() ) { |
572 | theAux = theN3Iter.Value(); |
573 | theOldVertices(theAux) = theOld; |
574 | theNewList.Append(theAux); |
575 | } |
576 | theNewVertices.UnBind(theRep); |
577 | } |
578 | } |
579 | else { |
580 | theOldVertices.Bind(theNew,theOld); |
581 | theNewList.Append(theNew); |
582 | } |
583 | } |
584 | theNewVertices.Bind(theOld,theNewList); |
585 | } |
586 | |
587 | // Update vertices positions and tolerances |
588 | TopoDS_Vertex theNewVert, theOldVert; |
589 | for ( TopTools_DataMapIteratorOfDataMapOfShapeListOfShape theRV2Iter( theNewVertices ); |
590 | theRV2Iter.More(); theRV2Iter.Next() ) { |
591 | theNewVert = TopoDS::Vertex(theRV2Iter.Key()); |
592 | // Calculate the vertex position |
593 | gp_Pnt theLBound, theRBound, thePosition; |
594 | theLBound = theRBound = BRep_Tool::Pnt(theNewVert); |
595 | TopTools_ListIteratorOfListOfShape theN2Iter; |
596 | for ( theN2Iter.Initialize(theRV2Iter.Value()); theN2Iter.More(); theN2Iter.Next() ) { |
597 | thePosition = BRep_Tool::Pnt(TopoDS::Vertex(theN2Iter.Value())); |
598 | Standard_Real val = thePosition.X(); |
599 | if ( val < theLBound.X() ) theLBound.SetX( val ); |
600 | else if ( val > theRBound.X() ) theRBound.SetX( val ); |
601 | val = thePosition.Y(); |
602 | if ( val < theLBound.Y() ) theLBound.SetY( val ); |
603 | else if ( val > theRBound.Y() ) theRBound.SetY( val ); |
604 | val = thePosition.Z(); |
605 | if ( val < theLBound.Z() ) theLBound.SetZ( val ); |
606 | else if ( val > theRBound.Z() ) theRBound.SetZ( val ); |
607 | } |
608 | thePosition = gp_Pnt((theLBound.XYZ() + theRBound.XYZ())/2.); |
609 | Standard_Real theTolerance = 0., curtoler; |
610 | // Calculate the vertex tolerance |
611 | for ( theN2Iter.Initialize(theRV2Iter.Value()); theN2Iter.More(); theN2Iter.Next() ) { |
612 | theOldVert = TopoDS::Vertex(theN2Iter.Value()); |
613 | curtoler = thePosition.Distance(BRep_Tool::Pnt(theOldVert)) + |
614 | BRep_Tool::Tolerance(theOldVert); |
615 | if (curtoler > theTolerance) theTolerance = curtoler; |
616 | } |
617 | curtoler = thePosition.Distance(BRep_Tool::Pnt(theNewVert)) + |
618 | BRep_Tool::Tolerance(theNewVert); |
619 | if (curtoler > theTolerance) theTolerance = curtoler; |
620 | theBuilder.UpdateVertex( theNewVert, thePosition, theTolerance ); |
621 | } |
622 | |
623 | // Replace vertices |
624 | theReShape->Clear(); |
625 | for ( TopTools_DataMapIteratorOfDataMapOfShapeShape theNVIter( theOldVertices ); |
626 | theNVIter.More(); theNVIter.Next() ) |
627 | theReShape->Replace(theNVIter.Key().Oriented(TopAbs_FORWARD), |
628 | theNVIter.Value().Oriented(TopAbs_FORWARD)); |
629 | //smh#8 |
630 | TopoDS_Shape tmpshape = theReShape->Apply(result); |
631 | result = TopoDS::Shell(tmpshape); |
632 | |
633 | if (theReShape->Status(ShapeExtend_FAIL1)) { |
0797d9d3 |
634 | #ifdef OCCT_DEBUG |
7fd59977 |
635 | cout<<"Error: ShapeFix_FaceConnect::Build: ReShape failed on vertices"<<endl; |
636 | #endif |
637 | } |
638 | } |
639 | |
0797d9d3 |
640 | #ifdef OCCT_DEBUG |
7fd59977 |
641 | //------------------------------- |
642 | //szv debug - reshape results |
643 | //------------------------------- |
644 | cout<<endl<<"FACE CONNECT REPLACEMENT RESULTS:"<<endl; |
645 | cout<<"---------------------------------"<<endl; |
646 | TopTools_MapOfShape theTmpMap; |
647 | Standard_Integer toteold = 0, totenew = 0; |
648 | for ( TopTools_DataMapIteratorOfDataMapOfShapeShape theR1Iter( theRepEdges ); |
649 | theR1Iter.More(); theR1Iter.Next() ) { |
650 | toteold++; |
651 | if (!theTmpMap.Contains(theR1Iter.Value())) { |
652 | theTmpMap.Add(theR1Iter.Value()); |
653 | for ( TopoDS_Iterator itw(TopoDS::Wire(theR1Iter.Value())); |
654 | itw.More(); itw.Next() ) totenew++; |
655 | } |
656 | } |
657 | Standard_Integer totvold = 0, totvnew = 0; |
658 | for ( TopTools_DataMapIteratorOfDataMapOfShapeShape theR2Iter( theOldVertices ); |
659 | theR2Iter.More(); theR2Iter.Next() ) { |
660 | totvold++; |
661 | if (!theTmpMap.Contains(theR2Iter.Value())) { |
662 | theTmpMap.Add(theR2Iter.Value()); |
663 | totvnew++; |
664 | } |
665 | } |
666 | cout<<"TOTAL: "<<toteold<<" edges, "<<totvold<<" vertices replaced by " |
667 | <<totenew<<" edges, "<<totvnew<<" vertices"<<endl<<endl; |
668 | //------------------------------- |
669 | #endif |
670 | |
671 | } |
672 | } |
673 | } |
674 | |
675 | return result; |
676 | } |
677 | |
678 | //======================================================================= |
679 | //function : Clear |
680 | //purpose : |
681 | //======================================================================= |
682 | |
683 | void ShapeFix_FaceConnect::Clear() |
684 | { |
685 | myConnected.Clear(); |
686 | myOriFreeEdges.Clear(); |
687 | myResFreeEdges.Clear(); |
688 | myResSharEdges.Clear(); |
689 | } |