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