Integration of OCCT 6.5.0 from SVN
[occt.git] / src / ShapeFix / ShapeFix_Face.cxx
CommitLineData
7fd59977 1// pdn 10.12.98: tr9_r0501-ug
2// pdn 28.12.98: PRO10366 shifting pcurve between two singularities
3//:k7 abv 5.01.99: USA60022.igs ent 243: FixMissingSeam() improved
4//:l2 abv 10.01.99: USA60022 7289: corrections for reversed face
5//gka 11.01.99 file PRO7755.stp #2018: work-around error in BRepLib_MakeFace
6//:p4 abv, pdn 23.02.99: PRO9234 #15720: call BRepTools::Update() for faces
7// rln 03.03.99 S4135: transmission of parameter precision to SA_Surface::NbSingularities
8//:q5 abv 19.03.99 code improvement
9//%14 pdn 15.03.99 adding function for fixing null area wires
10//%15 pdn 20.03.99 code improvement
11// abv 09.04.99 S4136: improve tolerance management; remove unused flag Closed
12//#4 szv S4163: optimization
13// smh 31.01.01 BUC60810 : Case of small wire on face in solid
14// sln 25.09.2001 checking order of 3d and 2d representation curves
15// abv 19.10.2001 FixAddNaturalBound improved and extracted as separate fix
16// skl,pdn 14.05.2002 OCC55 (correction precision for small faces)
17
18#include <ShapeFix_Face.ixx>
19
20#include <Standard_Failure.hxx>
21#include <Standard_ErrorHandler.hxx>
22
23#include <Precision.hxx>
24
25#include <Geom2d_Curve.hxx>
26#include <Geom2d_Line.hxx>
27#include <Geom_Curve.hxx>
28#include <Geom_BSplineSurface.hxx>
29#include <GeomAdaptor_HSurface.hxx>
30
31#include <TopoDS.hxx>
32#include <TopoDS_Edge.hxx>
33#include <TopoDS_Vertex.hxx>
34#include <TopoDS_Shell.hxx>
35#include <TopoDS_Compound.hxx>
36#include <TopoDS_Iterator.hxx>
37#include <TopExp_Explorer.hxx>
38#include <TopTools_SequenceOfShape.hxx>
39
40#include <BRep_Tool.hxx>
41#include <BRep_Builder.hxx>
42#include <BRepTopAdaptor_FClass2d.hxx>
43#include <BRepTools.hxx>
44#include <BRepBuilderAPI_MakeFace.hxx>
45
46#include <Message_Msg.hxx>
47#include <ShapeBuild_ReShape.hxx>
48#include <ShapeExtend_WireData.hxx>
49#include <ShapeAnalysis.hxx>
50#include <ShapeFix_Wire.hxx>
51#include <ShapeFix_Edge.hxx>
52#include <ShapeAnalysis_Edge.hxx>
53#include <Bnd_Box2d.hxx>
54#include <Geom_SphericalSurface.hxx>
55#include <Geom_RectangularTrimmedSurface.hxx>
56#include <ShapeAnalysis_Wire.hxx>
57#include <ShapeAnalysis_Surface.hxx>
58
59#include <ShapeExtend_CompositeSurface.hxx>
60#include <ShapeFix_ComposeShell.hxx>
61#include <TColGeom_HArray2OfSurface.hxx>
62#include <ShapeBuild_Edge.hxx>
63#include <TColgp_SequenceOfPnt2d.hxx>
64#include <Bnd_Box.hxx>
65#include <TopTools_IndexedMapOfShape.hxx>
66#include <TopTools_DataMapOfShapeListOfShape.hxx>
67#include <TopTools_ListIteratorOfListOfShape.hxx>
68#include <TopTools_MapOfShape.hxx>
69#include <TopoDS.hxx>
70#include <TopExp.hxx>
71
72#include <ShapeFix.hxx>
73#include <ShapeFix_DataMapOfShapeBox2d.hxx>
74#include <BndLib_Add2dCurve.hxx>
75#include <Geom2dAdaptor_Curve.hxx>
76#include <IntRes2d_Domain.hxx>
77#include <Geom2dInt_GInter.hxx>
78#include <IntRes2d_IntersectionPoint.hxx>
79#include <IntRes2d_Transition.hxx>
80#include <TopTools_SequenceOfShape.hxx>
81#include <IntRes2d_IntersectionSegment.hxx>
82#include <TopTools_DataMapOfShapeInteger.hxx>
83
84#include <ShapeFix_IntersectionTool.hxx>
85#include <ShapeFix_SplitTool.hxx>
86#include <TColStd_MapOfInteger.hxx>
87#include <TopTools_DataMapOfShapeShape.hxx>
88
89#ifdef DEB
90#define DEBUG
91#endif
92
93//=======================================================================
94//function : ShapeFix_Face
95//purpose :
96//=======================================================================
97
98ShapeFix_Face::ShapeFix_Face()
99{
100 myFwd = Standard_True;
101 myStatus = 0;
102 myFixWire = new ShapeFix_Wire;
103 ClearModes();
104}
105
106//=======================================================================
107//function : ShapeFix_Face
108//purpose :
109//=======================================================================
110
111ShapeFix_Face::ShapeFix_Face(const TopoDS_Face &face)
112{
113 myFwd = Standard_True;
114 myStatus = 0;
115 myFixWire = new ShapeFix_Wire;
116 ClearModes();
117 Init( face );
118}
119
120//=======================================================================
121//function : ClearModes
122//purpose :
123//=======================================================================
124
125void ShapeFix_Face::ClearModes()
126{
127 myFixWireMode = -1;
128 myFixOrientationMode = -1;
129 myFixAddNaturalBoundMode = -1;
130 myFixMissingSeamMode = -1;
131 myFixSmallAreaWireMode = -1;
132 myFixIntersectingWiresMode = -1;
133 myFixLoopWiresMode =-1;
134 myFixSplitFaceMode =-1;
135 myAutoCorrectPrecisionMode = 1;
136}
137
138//=======================================================================
139//function : SetMsgRegistrator
140//purpose :
141//=======================================================================
142
143void ShapeFix_Face::SetMsgRegistrator(const Handle(ShapeExtend_BasicMsgRegistrator)& msgreg)
144{
145 ShapeFix_Root::SetMsgRegistrator ( msgreg );
146 myFixWire->SetMsgRegistrator ( msgreg );
147}
148
149//=======================================================================
150//function : SetPrecision
151//purpose :
152//=======================================================================
153
154void ShapeFix_Face::SetPrecision (const Standard_Real preci)
155{
156 ShapeFix_Root::SetPrecision ( preci );
157 myFixWire->SetPrecision ( preci );
158}
159
160//=======================================================================
161//function : SetMinTolerance
162//purpose :
163//=======================================================================
164
165void ShapeFix_Face::SetMinTolerance (const Standard_Real mintol)
166{
167 ShapeFix_Root::SetMinTolerance ( mintol );
168 myFixWire->SetMinTolerance ( mintol );
169}
170
171//=======================================================================
172//function : SetMaxTolerance
173//purpose :
174//=======================================================================
175
176void ShapeFix_Face::SetMaxTolerance (const Standard_Real maxtol)
177{
178 ShapeFix_Root::SetMaxTolerance ( maxtol );
179 myFixWire->SetMaxTolerance ( maxtol );
180}
181
182//=======================================================================
183//function : Init
184//purpose :
185//=======================================================================
186
187void ShapeFix_Face::Init (const Handle(Geom_Surface)& surf,
188 const Standard_Real preci, const Standard_Boolean fwd)
189{
190 myStatus = 0;
191 Handle(ShapeAnalysis_Surface) sas = new ShapeAnalysis_Surface ( surf );
192 Init ( sas, preci, fwd );
193}
194
195//=======================================================================
196//function : Init
197//purpose :
198//=======================================================================
199
200void ShapeFix_Face::Init (const Handle(ShapeAnalysis_Surface)& surf,
201 const Standard_Real preci, const Standard_Boolean fwd)
202{
203 myStatus = 0;
204 mySurf = surf;
205 SetPrecision ( preci );
206 BRep_Builder B;
207 B.MakeFace ( myFace, mySurf->Surface(), ::Precision::Confusion() );
208 myShape = myFace;
209 myFwd = fwd;
210 if ( !fwd ) myFace.Orientation(TopAbs_REVERSED);
211}
212
213//=======================================================================
214//function : Init
215//purpose :
216//=======================================================================
217
218void ShapeFix_Face::Init (const TopoDS_Face& face)
219{
220 myStatus = 0;
221 mySurf = new ShapeAnalysis_Surface ( BRep_Tool::Surface (face) );
222 myFwd = ( face.Orientation() != TopAbs_REVERSED );
223 myFace = face;
224 myShape = myFace;
225// myFace = TopoDS::Face(face.EmptyCopied());
226// for (TopoDS_Iterator ws (face,Standard_False); ws.More(); ws.Next())
227// Add (TopoDS::Wire (ws.Value()) );
228}
229
230//=======================================================================
231//function : Add
232//purpose :
233//=======================================================================
234
235void ShapeFix_Face::Add (const TopoDS_Wire& wire)
236{
237 if ( wire.IsNull() ) return;
238 BRep_Builder B;
239 //szv#4:S4163:12Mar99 SGI warns
240 TopoDS_Shape fc = myFace.Oriented(TopAbs_FORWARD); //:l2 abv 10 Jan 99: Oriented()
241 B.Add ( fc, wire );
242}
243
244
245//=======================================================================
246//function : SplitWire
247//purpose : auxilary - try to split wire (it is needed if some segments
248// were removed in ShapeFix_Wire::FixSelfIntersection()
249//=======================================================================
250static Standard_Boolean SplitWire(const TopoDS_Wire& wire,
251 TopTools_SequenceOfShape& aResWires)
252{
253 TColStd_MapOfInteger UsedEdges;
254 Handle(ShapeExtend_WireData) sewd = new ShapeExtend_WireData(wire);
255 Standard_Integer i,j,k;
256 ShapeAnalysis_Edge sae;
257 for(i=1; i<=sewd->NbEdges(); i++) {
258 if(UsedEdges.Contains(i)) continue;
259 TopoDS_Edge E1 = sewd->Edge(i);
260 UsedEdges.Add(i);
261 TopoDS_Vertex V0,V1,V2;
262 V0 = sae.FirstVertex(E1);
263 V1 = sae.LastVertex(E1);
264 Handle(ShapeExtend_WireData) sewd1 = new ShapeExtend_WireData;
265 sewd1->Add(E1);
266 Standard_Boolean IsConnectedEdge = Standard_True;
267 for(j=2; j<=sewd->NbEdges() && IsConnectedEdge; j++) {
268 for(k=2; k<=sewd->NbEdges(); k++) {
269 if(UsedEdges.Contains(k)) continue;
270 TopoDS_Edge E2 = sewd->Edge(k);
271 TopoDS_Vertex V21 = sae.FirstVertex(E2);
272 TopoDS_Vertex V22 = sae.LastVertex(E2);
273 if( sae.FirstVertex(E2).IsSame(V1) ) {
274 sewd1->Add(E2);
275 UsedEdges.Add(k);
276 V1 = sae.LastVertex(E2);
277 break;
278 }
279 }
280 if(V1.IsSame(V0)) {
281 // new wire is closed, put it into sequence
282 aResWires.Append(sewd1->Wire());
283 break;
284 }
285 if(k>sewd->NbEdges()) {
286 IsConnectedEdge = Standard_False;
287 break;
288 }
289 }
290 if(!IsConnectedEdge) {
291 // create new notclosed wire
292 aResWires.Append(sewd1->Wire());
293 }
294 if(UsedEdges.Extent()==sewd->NbEdges()) break;
295 }
296
297 if(aResWires.Length()>1) {
298#ifdef DEBUG
299 cout<<"Wire was splitted on "<<aResWires.Length()<<" wires"<< endl;
300#endif
301 }
302
303 return Standard_True;
304}
305
306
307//=======================================================================
308//function : Perform
309//purpose :
310//=======================================================================
311
312Standard_Boolean ShapeFix_Face::Perform()
313{
314 myStatus = ShapeExtend::EncodeStatus ( ShapeExtend_OK );
315 myFixWire->SetContext ( Context() );
316 Handle(ShapeFix_Wire) theAdvFixWire = Handle(ShapeFix_Wire)::DownCast(myFixWire);
317 if (theAdvFixWire.IsNull()) return Standard_False;
318
319 BRep_Builder B;
320 TopoDS_Shape aInitFace = myFace;
321 // perform first part of fixes on wires
322 Standard_Boolean isfixReorder = Standard_False;
323 Standard_Boolean isReplaced = Standard_False;
324
325 //gka fix in order to avoid lost messages (following OCC21771)
326 TopTools_DataMapOfShapeShape aMapReorderedWires;
327
328 Standard_Real aSavPreci = Precision();
329 if ( NeedFix ( myFixWireMode ) ) {
330 theAdvFixWire->SetFace ( myFace );
331
332 Standard_Integer usFixLackingMode = theAdvFixWire->FixLackingMode();
333 Standard_Integer usFixNotchedEdgesMode = theAdvFixWire->FixNotchedEdgesMode();
334 Standard_Integer usFixSelfIntersectionMode = theAdvFixWire->FixSelfIntersectionMode();
335 theAdvFixWire->FixLackingMode() = Standard_False;
336 theAdvFixWire->FixNotchedEdgesMode() = Standard_False;
337 theAdvFixWire->FixSelfIntersectionMode() = Standard_False;
338
339 Standard_Boolean fixed = Standard_False;
340 TopoDS_Shape S = myFace;
341 if ( ! Context().IsNull() )
342 S = Context()->Apply ( myFace );
343 TopoDS_Shape emptyCopied = S.EmptyCopied();
344 TopoDS_Face tmpFace = TopoDS::Face(emptyCopied);
345 tmpFace.Orientation ( TopAbs_FORWARD );
346
347 /*
348 // skl 14.05.2002 OCC55 + corrected 03.03.2004
349 Standard_Real dPreci = aSavPreci*aSavPreci;
350 dPreci*=4;
351 Standard_Real newpreci=dPreci;
352 for(TopExp_Explorer exp(S,TopAbs_EDGE); exp.More(); exp.Next()) {
353 TopoDS_Edge edge = TopoDS::Edge ( exp.Current() );
354 Standard_Real first,last;
355 Handle(Geom_Curve) c3d = BRep_Tool::Curve(edge, first, last);
356 if(!c3d.IsNull()) {
357 Bnd_Box bb;
358 bb.Add(c3d->Value(first));
359 bb.Add(c3d->Value(last));
360 bb.Add(c3d->Value((last+first)/2.));
361 Standard_Real x1,x2,y1,y2,z1,z2,size;
362 bb.Get(x1,y1,z1,x2,y2,z2);
363 size = (x2-x1)*(x2-x1) + (y2-y1)*(y2-y1) + (z2-z1)*(z2-z1);
364 if(size<newpreci) newpreci=size;
365 }
366 }
367 newpreci=sqrt(newpreci)/2.*1.00001;
368 if( aSavPreci > newpreci && newpreci > Precision::Confusion()) {
369 SetPrecision(newpreci);
370 theAdvFixWire->SetPrecision(newpreci);
371 }
372 // end skl 14.05.2002
373 */
374
375 // skl 29.03.2010 (OCC21623)
376 if( myAutoCorrectPrecisionMode ) {
377 Standard_Real size = ShapeFix::LeastEdgeSize(S);
378 Standard_Real newpreci = Min(aSavPreci,size/2.);
379 newpreci = newpreci*1.00001;
380 if( aSavPreci > newpreci && newpreci > Precision::Confusion()) {
381 SetPrecision(newpreci);
382 theAdvFixWire->SetPrecision(newpreci);
383 }
384 }
385
386 isfixReorder = Standard_False;
387 for ( TopoDS_Iterator iter(S,Standard_False); iter.More(); iter.Next()) {
388 if(iter.Value().ShapeType() != TopAbs_WIRE) {
389 B.Add ( tmpFace, iter.Value() );
390 continue;
391 }
392 TopoDS_Wire wire = TopoDS::Wire ( iter.Value() );
393 theAdvFixWire->Load ( wire );
394 if(theAdvFixWire->NbEdges() == 0) {
395 if(theAdvFixWire->WireData()->NbNonManifoldEdges())
396 B.Add ( tmpFace, wire );
397 else {
398 fixed = Standard_True;
399 myStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE5 );
400 }
401 continue;
402 }
403 if ( theAdvFixWire->Perform() ) {
404 //fixed = Standard_True;
405 isfixReorder = (theAdvFixWire->StatusReorder(ShapeExtend_DONE) || isfixReorder);
406 fixed = (theAdvFixWire->StatusSmall(ShapeExtend_DONE) ||
407 theAdvFixWire->StatusConnected(ShapeExtend_DONE) ||
408 theAdvFixWire->StatusEdgeCurves(ShapeExtend_DONE) ||
409 theAdvFixWire->StatusDegenerated(ShapeExtend_DONE) ||
410 theAdvFixWire->StatusClosed(ShapeExtend_DONE));
411 TopoDS_Wire w = theAdvFixWire->Wire();
412 if(fixed) {
413 if ( ! Context().IsNull() ) Context()->Replace ( wire, w );
414 if(theAdvFixWire->NbEdges() == 0) {
415 myStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE5 );
416 continue;
417 }
418 }
419 else if(!wire.IsSame(w))
420 aMapReorderedWires.Bind(wire,w);
421
422 wire = w;
423 }
424 B.Add ( tmpFace, wire );
425 // if ( theAdvFixWire->Status ( ShapeExtend_FAIL ) )
426 // myStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_FAIL1 );
427 }
428
429 theAdvFixWire->FixLackingMode() = usFixLackingMode;
430 theAdvFixWire->FixNotchedEdgesMode() = usFixNotchedEdgesMode;
431 theAdvFixWire->FixSelfIntersectionMode() = usFixSelfIntersectionMode;
432 if ( ! myFwd ) tmpFace.Orientation ( TopAbs_REVERSED );
433
434 if ( fixed ) {
435 //if ( ! myFwd ) tmpFace.Orientation ( TopAbs_REVERSED );
436 if ( ! Context().IsNull() ) Context()->Replace ( S, tmpFace );
437 //myFace = tmpFace;
438 isReplaced = Standard_True;
439 myStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE1 );
440
441 }
442 if(fixed || isfixReorder)
443 myFace = tmpFace;
444 }
445
446 myResult = myFace;
447 TopoDS_Shape savShape = myFace; //gka BUG 6555
448 // fix missing seam
449 if ( NeedFix ( myFixMissingSeamMode ) ) {
450 if ( FixMissingSeam() ) {
451 myStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE3 );
452 }
453 }
454
455 // cycle by all possible faces coming from FixMissingSeam
456 // each face is processed as if it was single
457 TopExp_Explorer exp(myResult,TopAbs_FACE);
458 for ( ; exp.More(); exp.Next() ) {
459 myFace = TopoDS::Face ( exp.Current() );
460 Standard_Boolean NeedCheckSplitWire = Standard_False;
461
462 // perform second part of fixes on wires
463 if ( NeedFix ( myFixWireMode ) ) {
464 theAdvFixWire->SetFace ( myFace );
465
466 Standard_Integer usFixSmallMode = theAdvFixWire->FixSmallMode();
467 Standard_Integer usFixConnectedMode = theAdvFixWire->FixConnectedMode();
468 Standard_Integer usFixEdgeCurvesMode =theAdvFixWire->FixEdgeCurvesMode();
469 Standard_Integer usFixDegeneratedMode = theAdvFixWire->FixDegeneratedMode();
470 theAdvFixWire->FixSmallMode() = Standard_False;
471 theAdvFixWire->FixConnectedMode() = Standard_False;
472 theAdvFixWire->FixEdgeCurvesMode() = Standard_False;
473 theAdvFixWire->FixDegeneratedMode() = Standard_False;
474
475 Standard_Boolean fixed = Standard_False;
476 TopoDS_Shape S = myFace;
477 if ( ! Context().IsNull() )
478 S = Context()->Apply ( myFace );
479 TopoDS_Shape emptyCopied = S.EmptyCopied();
480 TopoDS_Face tmpFace = TopoDS::Face(emptyCopied);
481 tmpFace.Orientation ( TopAbs_FORWARD );
482 for ( TopoDS_Iterator iter(S,Standard_False); iter.More(); iter.Next()) {
483 if(iter.Value().ShapeType() != TopAbs_WIRE) {
484 B.Add ( tmpFace,iter.Value());
485 continue;
486 }
487
488 TopoDS_Wire wire = TopoDS::Wire ( iter.Value() );
489 theAdvFixWire->Load ( wire );
490 if(theAdvFixWire->NbEdges() == 0) {
491 if(theAdvFixWire->WireData()->NbNonManifoldEdges())
492 B.Add ( tmpFace, wire );
493 else {
494 fixed = Standard_True;
495 myStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE5 );
496 }
497 continue;
498 }
499 if ( theAdvFixWire->Perform() ) {
500 isfixReorder = theAdvFixWire->StatusReorder(ShapeExtend_DONE);
501 fixed = (theAdvFixWire->StatusLacking(ShapeExtend_DONE) ||
502 theAdvFixWire->StatusSelfIntersection(ShapeExtend_DONE) ||
503 theAdvFixWire->StatusNotches(ShapeExtend_DONE)); //Standard_True;
504 TopoDS_Wire w = theAdvFixWire->Wire();
505 if(fixed) {
506 if ( ! Context().IsNull() ) Context()->Replace ( wire, w );
507
508 }
509 else if(!wire.IsSame(w))
510 aMapReorderedWires.Bind(wire,w);
511
512 wire = w;
513 }
514 if(theAdvFixWire->StatusRemovedSegment())
515 NeedCheckSplitWire = Standard_True;
516
517 //fix for loop of wire
518 TopTools_SequenceOfShape aLoopWires;
519 if(NeedFix ( myFixLoopWiresMode) && FixLoopWire(aLoopWires)) {
520
521 myStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE7 );
522 fixed = Standard_True;
523 Standard_Integer k=1;
524 for( ; k <= aLoopWires.Length(); k++)
525 B.Add (tmpFace,aLoopWires.Value(k));
526 }
527 else
528 B.Add ( tmpFace, wire );
529 }
530
531 theAdvFixWire->FixSmallMode() = usFixSmallMode;
532 theAdvFixWire->FixConnectedMode() = usFixConnectedMode;
533 theAdvFixWire->FixEdgeCurvesMode() = usFixEdgeCurvesMode;
534 theAdvFixWire->FixDegeneratedMode() = usFixDegeneratedMode;
535
536 if ( fixed ) {
537 if ( ! myFwd ) tmpFace.Orientation ( TopAbs_REVERSED );
538 if(!isReplaced && !aInitFace.IsSame(myResult) && ! Context().IsNull()) //gka 06.09.04 BUG 6555
539 Context()->Replace(aInitFace,savShape);
540 if ( ! Context().IsNull() ) Context()->Replace ( S, tmpFace );
541 myFace = tmpFace;
542 myStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE1 );
543 }
544 }
545
546 if(NeedCheckSplitWire) {
547 // try to split wire - it is needed if some segments were removed
548 // in ShapeFix_Wire::FixSelfIntersection()
549 TopoDS_Shape S = myFace;
550 if ( ! Context().IsNull() )
551 S = Context()->Apply ( myFace );
552 TopoDS_Shape emptyCopied = S.EmptyCopied();
553 TopoDS_Face tmpFace = TopoDS::Face(emptyCopied);
554 tmpFace.Orientation ( TopAbs_FORWARD );
555 TopTools_SequenceOfShape aWires;
556 Standard_Integer nbw=0;
557 for ( TopoDS_Iterator iter(S,Standard_False); iter.More(); iter.Next()) {
558 if(iter.Value().ShapeType() != TopAbs_WIRE) {
559 B.Add (tmpFace,iter.Value());
560 continue;
561 }
562 if(iter.Value().Orientation() != TopAbs_FORWARD ||
563 iter.Value().Orientation() != TopAbs_REVERSED) {
564 B.Add (tmpFace,TopoDS::Wire(iter.Value()));
565 continue;
566 }
567 nbw++;
568 TopoDS_Wire wire = TopoDS::Wire ( iter.Value() );
569 SplitWire(wire,aWires);
570 }
571 if(nbw<aWires.Length()) {
572 for(Standard_Integer iw=1; iw<=aWires.Length(); iw++)
573 B.Add (tmpFace,aWires.Value(iw));
574 if ( ! Context().IsNull() ) Context()->Replace ( S, tmpFace );
575 myStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE8 );
576 myFace = tmpFace;
577 }
578 }
579
580 // fix intersecting wires
581 if(FixWiresTwoCoincEdges())
582 myStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE7 );
583 if ( NeedFix ( myFixIntersectingWiresMode ) ) {
584 if ( FixIntersectingWires() ) {
585 myStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE6 );
586 }
587 }
588
589 // fix orientation
590 TopTools_DataMapOfShapeListOfShape MapWires;
591 MapWires.Clear();
592 if ( NeedFix ( myFixOrientationMode ) ) {
593 if ( FixOrientation(MapWires) )
594 myStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE2 );
595 }
596
597 BRepTools::Update(myFace);
598
599 // fix natural bounds
600 Standard_Boolean NeedSplit = Standard_True;
601 if ( NeedFix ( myFixAddNaturalBoundMode ) ) {
602 if ( FixAddNaturalBound() ) {
603 NeedSplit = Standard_False;
604 myStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE5 );
605 }
606 }
607
608 // split face
609 if ( NeedFix ( myFixSplitFaceMode ) && NeedSplit && MapWires.Extent()>1 ) {
610 if ( FixSplitFace(MapWires) )
611 myStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE8 );
612 }
613
614 }
615
616 //return the original preci
617 SetPrecision(aSavPreci);
618 theAdvFixWire->SetPrecision(aSavPreci);
619
620 // cycle by all possible faces coming from FixAddNaturalBound
621 // each face is processed as if it was single
622 for ( exp.Init(myResult,TopAbs_FACE); exp.More(); exp.Next() ) {
623 myFace = TopoDS::Face ( exp.Current() );
624
625 // fix small-area wires
626 if ( NeedFix ( myFixSmallAreaWireMode, Standard_False ) ) {
627 if ( FixSmallAreaWire() )
628 myStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE4 );
629 }
630 }
631
632
633 if ( ! Context().IsNull() ) {
634 if(Status ( ShapeExtend_DONE ) && !isReplaced && !aInitFace.IsSame(savShape))
635 {
636 //gka fix in order to avoid lost messages (following OCC21771)
637 if(aMapReorderedWires.Extent())
638 {
639 TopoDS_Iterator aItW(aInitFace,Standard_False);
640 for( ; aItW.More() ; aItW.Next())
641 {
642 TopoDS_Shape aCurW = aItW.Value();
643 while(aMapReorderedWires.IsBound(aCurW))
644 {
645 TopoDS_Shape aFixW = aMapReorderedWires.Find(aCurW);
646 Context()->Replace(aCurW, aFixW);
647 aCurW = aFixW;
648 }
649 }
650
651 }
652 Context()->Replace(aInitFace, savShape);
653 }
654 myResult = Context()->Apply ( aInitFace ); //gka 06.09.04
655 }
656 else if(!Status ( ShapeExtend_DONE ))
657 myResult = aInitFace;
658
659 return Status ( ShapeExtend_DONE );
660}
661
662//=======================================================================
663//function : Auxiliary functions
664//purpose :
665//=======================================================================
666
667// Shift all pcurves of edges in the given wire on the given face
668// to vector <vec>
669static void Shift2dWire(const TopoDS_Wire w, const TopoDS_Face f,
670 const gp_Vec2d vec,
671 const Handle(ShapeAnalysis_Surface)& mySurf,
672 Standard_Boolean recompute3d = Standard_False)
673{
674 gp_Trsf2d tr2d;
675 tr2d.SetTranslation(vec.XY());
676 ShapeAnalysis_Edge sae;
677 ShapeBuild_Edge sbe;
678 BRep_Builder B;
679 for (TopoDS_Iterator ei (w,Standard_False); ei.More(); ei.Next()){
680 TopoDS_Edge edge = TopoDS::Edge(ei.Value());
681 Handle (Geom2d_Curve) C2d;
682 Standard_Real cf, cl;
683 if ( ! sae.PCurve(edge, f, C2d, cf, cl, Standard_True) ) continue;
684 C2d->Transform(tr2d);
685 if ( recompute3d ) {
686 // recompute 3d curve and vertex
687 sbe.RemoveCurve3d ( edge );
688 sbe.BuildCurve3d ( edge );
689 B.UpdateVertex ( sae.FirstVertex(edge), mySurf->Value(C2d->Value(cf)), 0. );
690 }
691 }
692}
693
694// Cut interval from the sequence of intervals
695static Standard_Boolean CutInterval (TColgp_SequenceOfPnt2d &intervals,
696 const gp_Pnt2d &toAddI,
697 const Standard_Real period)
698{
699 if ( intervals.Length() <=0 ) return Standard_False;
700 for ( Standard_Integer j=0; j <2; j++ ) { // try twice, align to bottom and to top
701 for ( Standard_Integer i=1; i <= intervals.Length(); i++ ) {
702 gp_Pnt2d interval = intervals(i);
703 // ACIS907, OCC921 a054a.sat (face 124)
704 Standard_Real shift = ShapeAnalysis::AdjustByPeriod ( ( j ? toAddI.X() : toAddI.Y() ),
705 0.5*( interval.X() + interval.Y() ),period);
706 gp_Pnt2d toAdd ( toAddI.X() + shift, toAddI.Y() + shift );
707 if ( toAdd.Y() <= interval.X() || toAdd.X() >= interval.Y() ) continue;
708 if ( toAdd.X() > interval.X() ) {
709 if ( toAdd.Y() < interval.Y() ) {
710 intervals.InsertBefore ( i, interval );
711 intervals.ChangeValue(i+1).SetX ( toAdd.Y() ); // i++...
712 }
713 intervals.ChangeValue(i).SetY ( toAdd.X() );
714 }
715 else if ( toAdd.Y() < interval.Y() ) {
716 intervals.ChangeValue(i).SetX ( toAdd.Y() );
717 }
718 else intervals.Remove ( i-- );
719 }
720 }
721 return Standard_True;
722}
723
724// Find middle of the biggest interval
725static Standard_Real FindBestInterval (TColgp_SequenceOfPnt2d &intervals)
726{
727 Standard_Real shift = 0., max = -1.;
728 for ( Standard_Integer i=1; i <= intervals.Length(); i++ ) {
729 gp_Pnt2d interval = intervals(i);
730 if ( interval.Y() - interval.X() <= max ) continue;
731 max = interval.Y() - interval.X();
732 shift = interval.X() + 0.5 * max;
733 }
734 return shift;
735}
736
737//=======================================================================
738//function : FixAddNaturalBound
739//purpose :
740//=======================================================================
741// Detect missing natural bounary on spherical surfaces and add it if
742// necessary
743//pdn 981202: add natural bounds if missing (on sphere only)
744//:abv 28.08.01: rewritten and extended for toruses
745
746Standard_Boolean ShapeFix_Face::FixAddNaturalBound()
747{
748 if ( ! Context().IsNull() ) {
749 TopoDS_Shape S = Context()->Apply ( myFace );
750 myFace = TopoDS::Face ( S );
751 }
752
753 // collect wires in sequence
754 TopTools_SequenceOfShape ws;
755 TopTools_SequenceOfShape vs;
756 TopoDS_Iterator wi (myFace,Standard_False);
757 for ( ; wi.More(); wi.Next()) {
758 if(wi.Value().ShapeType() == TopAbs_WIRE &&
759 (wi.Value().Orientation() == TopAbs_FORWARD || wi.Value().Orientation() == TopAbs_REVERSED))
760 ws.Append (wi.Value());
761 else
762 vs.Append(wi.Value());
763 }
764
765 // deal with case of empty face: just create a new one by standard tool
766 if ( ws.Length() <=0 ) {
767 BRepBuilderAPI_MakeFace mf (mySurf->Surface());
768 if ( ! Context().IsNull() ) Context()->Replace ( myFace, mf.Face() );
769 myFace = mf.Face();
770
771 //gka 11.01.99 file PRO7755.stp entity #2018 surface #1895: error BRepLib_MakeFace func IsDegenerated
772 Handle(ShapeFix_Edge) sfe = myFixWire->FixEdgeTool();
773 for (TopExp_Explorer Eed (myFace, TopAbs_EDGE); Eed.More(); Eed.Next()) {
774 TopoDS_Edge edg = TopoDS::Edge (Eed.Current());
775 sfe->FixVertexTolerance(edg);
776 }
777
778// B.UpdateFace (myFace,myPrecision);
779 SendWarning (Message_Msg ("FixAdvFace.FixOrientation.MSG0"));//Face created with natural bounds
780 BRepTools::Update(myFace);
781 return Standard_True;
782 }
783
784 // check that surface is double-closed and fix is needed
785 if ( ( mySurf->Adaptor3d()->GetType() != GeomAbs_Sphere &&
786 mySurf->Adaptor3d()->GetType() != GeomAbs_Torus ) ||
787 ShapeAnalysis::IsOuterBound (myFace) )
788 return Standard_False;
789
790 // Collect informations on free intervals in U and V
791 TColgp_SequenceOfPnt2d intU, intV, centers;
792 Standard_Real SUF, SUL, SVF, SVL;
793 mySurf->Bounds(SUF, SUL, SVF, SVL);
794 intU.Append ( gp_Pnt2d(SUF, SUL) );
795 intV.Append ( gp_Pnt2d(SVF, SVL) );
796 Standard_Integer nb = ws.Length();
797 Standard_Integer i;
798 for ( i=1; i <= nb; i ++) {
799 Standard_Real Umin, Vmin, Umax, Vmax;
800// Bnd_Box2d B;
801 TopoDS_Wire aw = TopoDS::Wire (ws.Value(i));
802 // PTV 01.11.2002 ACIS907, OCC921 begin
803// BRepTools::AddUVBounds(myFace,aw,B);
804// B.Get(Umin, Vmin, Umax, Vmax);
805 TopoDS_Face aWireFace = TopoDS::Face( myFace.EmptyCopied() );
806 BRep_Builder aB;
807 aB.Add( aWireFace, aw );
808 ShapeAnalysis::GetFaceUVBounds(aWireFace, Umin, Umax, Vmin, Vmax);
809 // PTV 01.11.2002 ACIS907, OCC921 end
810 if ( mySurf->IsUClosed() ) CutInterval ( intU, gp_Pnt2d(Umin,Umax), SUL-SUF );
811 if ( mySurf->IsVClosed() ) CutInterval ( intV, gp_Pnt2d(Vmin,Vmax), SVL-SVF );
812 centers.Append ( gp_Pnt2d ( 0.5*(Umin+Umax), 0.5*(Vmin+Vmax) ) );
813 }
814
815 // find best interval and thus compute shift
816 gp_Pnt2d shift(0.,0.);
817 if ( mySurf->IsUClosed() ) shift.SetX ( FindBestInterval ( intU ) );
818 if ( mySurf->IsVClosed() ) shift.SetY ( FindBestInterval ( intV ) );
819
820 // Adjust all other wires to be inside outer one
821 gp_Pnt2d center ( shift.X() + 0.5*(SUL-SUF), shift.Y() + 0.5*(SVL-SVF) );
822 for ( i=1; i <= nb; i++ ) {
823 TopoDS_Wire wire = TopoDS::Wire (ws.Value(i));
824 gp_Pnt2d sh(0.,0.);
825 if ( mySurf->IsUClosed() )
826 sh.SetX ( ShapeAnalysis::AdjustByPeriod ( centers(i).X(), center.X(), SUL-SUF ) );
827 if ( mySurf->IsVClosed() )
828 sh.SetY ( ShapeAnalysis::AdjustByPeriod ( centers(i).Y(), center.Y(), SVL-SVF ) );
829 Shift2dWire ( wire, myFace, sh.XY(), mySurf );
830 }
831
832 // Create naturally bounded surface and add that wire to sequence
833/* variant 1
834 // Create fictive grid and call ComposeShell
835 Handle(Geom_RectangularTrimmedSurface) RTS =
836 new Geom_RectangularTrimmedSurface ( mySurf->Surface(), SUF+shift.X(), SUL+shift.X(),
837 SVF+shift.Y(), SVL+shift.Y() );
838 Handle(TColGeom_HArray2OfSurface) grid = new TColGeom_HArray2OfSurface ( 1, 1, 1, 1 );
839 grid->SetValue ( 1, 1, RTS );
840 Handle(ShapeExtend_CompositeSurface) G = new ShapeExtend_CompositeSurface ( grid );
841 TopLoc_Location L;
842
843 ShapeFix_ComposeShell CompShell;
844 CompShell.Init ( G, L, myFace, ::Precision::Confusion() );
845 CompShell.ClosedMode() = Standard_True;
846 CompShell.NaturalBoundMode() = Standard_True;
847 CompShell.SetContext( Context() );
848 CompShell.SetMaxTolerance(MaxTolerance());
849 CompShell.Perform();
850 TopoDS_Shape res = CompShell.Result();
851
852 Context()->Replace ( myFace, res );
853 for (TopExp_Explorer exp ( res, TopAbs_FACE ); exp.More(); exp.Next() ) {
854 myFace = TopoDS::Face ( exp.Current() );
855 BRepTools::Update(myFace); //:p4
856 }
857 myResult = Context()->Apply ( myResult );
858*/
859/* variant 2 */
860 TopLoc_Location L;
861 Handle(Geom_Surface) surf = BRep_Tool::Surface ( myFace, L );
862 BRepBuilderAPI_MakeFace mf (surf);
863 TopoDS_Face ftmp = mf.Face();
864 ftmp.Location ( L );
865 for (wi.Initialize (ftmp,Standard_False); wi.More(); wi.Next()) {
866 if(wi.Value().ShapeType() != TopAbs_WIRE)
867 continue;
868 TopoDS_Wire wire = TopoDS::Wire ( wi.Value() );
869 ws.Append ( wire );
870 if ( shift.XY().Modulus() < ::Precision::PConfusion() ) continue;
871 Shift2dWire ( wire, myFace, shift.XY(), mySurf, Standard_True );
872 }
873
874 // Fix possible case on sphere when gap contains degenerated edge
875 // and thus has a common part with natural boundary
876 // Such hole should be merged with boundary
877 if ( mySurf->Adaptor3d()->GetType() == GeomAbs_Sphere &&
878 ws.Length() == nb+1 ) {
879 Handle(ShapeExtend_WireData) bnd =
880 new ShapeExtend_WireData ( TopoDS::Wire ( ws.Last() ) );
881 // code to become separate method FixTouchingWires()
882 for ( i=1; i <= nb; i++ ) {
883 Handle(ShapeExtend_WireData) sbwd =
884 new ShapeExtend_WireData ( TopoDS::Wire ( ws.Value(i) ) );
885 for (Standard_Integer j=1; j <= sbwd->NbEdges(); j++ ) {
886 if ( ! BRep_Tool::Degenerated ( sbwd->Edge(j) ) ) continue;
887 // find corresponding place in boundary
888 ShapeAnalysis_Edge sae;
889 TopoDS_Vertex V = sae.FirstVertex ( sbwd->Edge(j) );
890 Standard_Integer k;
891 for ( k=1; k <= bnd->NbEdges(); k++ ) {
892 if ( ! BRep_Tool::Degenerated ( bnd->Edge(k) ) ) continue;
893 if ( BRepTools::Compare ( V, sae.FirstVertex ( bnd->Edge(k) ) ) ) break;
894 }
895 if ( k > bnd->NbEdges() ) continue;
896 // and insert hole to that place
897 BRep_Builder B;
898 B.Degenerated ( sbwd->Edge(j), Standard_False );
899 B.Degenerated ( bnd->Edge(k), Standard_False );
900 sbwd->SetLast ( j );
901 bnd->Add ( sbwd, k+1 );
902 ws.Remove ( i-- );
903 nb--;
904 myFixWire->SetFace ( myFace );
905 myFixWire->Load ( bnd );
906 myFixWire->FixConnected();
907 myFixWire->FixDegenerated();
908 ws.SetValue ( ws.Length(), bnd->Wire() );
909 break;
910 }
911 }
912 }
913
914 // Create resulting face
915 BRep_Builder B;
916 TopoDS_Shape S = myFace.EmptyCopied();
917 S.Orientation ( TopAbs_FORWARD );
918 for ( i = 1; i <= ws.Length(); i++ ) B.Add ( S, ws.Value(i) );
919 for ( i = 1; i <= vs.Length(); i++ ) B.Add ( S, vs.Value(i) );
920 if ( ! myFwd ) S.Orientation (TopAbs_REVERSED);
921 if ( ! Context().IsNull() ) Context()->Replace ( myFace, S );
922 myFace = TopoDS::Face ( S );
923 BRepTools::Update(myFace);
924
925/**/
926#ifdef DEBUG
927 cout<<"Natural bound on sphere or torus with holes added"<<endl; // mise au point !
928#endif
929 SendWarning (Message_Msg ("FixAdvFace.FixOrientation.MSG0"));//Face created with natural bounds
930 return Standard_True;
931}
932
933
934//=======================================================================
935//function : FixOrientation
936//purpose :
937//=======================================================================
938
939Standard_Boolean ShapeFix_Face::FixOrientation()
940{
941 TopTools_DataMapOfShapeListOfShape MapWires;
942 MapWires.Clear();
943 return FixOrientation(MapWires);
944}
945
946
947//=======================================================================
948//function : FixOrientation
949//purpose :
950//=======================================================================
951
952Standard_Boolean ShapeFix_Face::FixOrientation(TopTools_DataMapOfShapeListOfShape &MapWires)
953{
954 Standard_Boolean done = Standard_False;
955
956 if ( ! Context().IsNull() ) {
957 TopoDS_Shape S = Context()->Apply ( myFace );
958 myFace = TopoDS::Face ( S );
959 }
960 TopTools_SequenceOfShape ws;
961 TopTools_SequenceOfShape allSubShapes;
962 // smh: BUC60810 : protection against very small wires (one-edge, null-length)
963 TopTools_SequenceOfShape VerySmallWires;
964 for ( TopoDS_Iterator wi (myFace,Standard_False); wi.More(); wi.Next()) {
965 if(wi.Value().ShapeType() == TopAbs_VERTEX ||
966 (wi.Value().Orientation() != TopAbs_FORWARD &&
967 wi.Value().Orientation() != TopAbs_REVERSED)) {
968 allSubShapes.Append (wi.Value());
969 //ws.Append (wi.Value());
970 continue;
971 }
972
973 TopoDS_Iterator ei (wi.Value(),Standard_False);
974 TopoDS_Edge anEdge;
975 Standard_Real length = RealLast();
976 if ( ei.More() ) {
977 anEdge = TopoDS::Edge(ei.Value());
978 ei.Next();
979 if ( ! ei.More() ) {
980 length = 0;
981 Standard_Real First, Last;
982 Handle(Geom_Curve) c3d;
983 ShapeAnalysis_Edge sae;
984 if ( sae.Curve3d(anEdge,c3d,First,Last) ) {
985 gp_Pnt pntIni = c3d->Value(First);
986 gp_XYZ prev;
987 prev = pntIni.XYZ();
988 Standard_Integer NbControl = 10;
989 for ( Standard_Integer j = 1; j < NbControl; j++) {
990 Standard_Real prm = ((NbControl-1-j)*First + j*Last)/(NbControl-1);
991 gp_Pnt pntCurr = c3d->Value(prm);
992 gp_XYZ curr = pntCurr.XYZ();
993 gp_XYZ delta = curr - prev;
994 length += delta.Modulus();
995 prev = curr;
996 }
997 }
998 }
999 }
1000 else length = 0;
1001 if (length > ::Precision::Confusion()) {
1002 ws.Append (wi.Value());
1003 allSubShapes.Append (wi.Value());
1004 }
1005 else VerySmallWires.Append (wi.Value());
1006 }
1007 if ( VerySmallWires.Length() >0 ) done = Standard_True;
1008
1009 Standard_Integer nb = ws.Length();
1010 Standard_Integer nbAll = allSubShapes.Length();
1011 BRep_Builder B;
1012
1013 // if no wires, just do nothing
1014 if ( nb <= 0) return Standard_False;
1015 Standard_Integer nbInternal=0;
1016 Standard_Boolean isAddNaturalBounds = (NeedFix (myFixAddNaturalBoundMode) &&
1017 ( mySurf->Adaptor3d()->GetType() == GeomAbs_Sphere ||
1018 mySurf->Adaptor3d()->GetType() == GeomAbs_Torus ));
1019 TColStd_SequenceOfInteger aSeqReversed;
1020 // if wire is only one, check its orientation
1021 if ( nb == 1 ) {
1022 // skl 12.04.2002 for cases with nbwires>1 (VerySmallWires>1)
1023 // make face with only one wire (ws.Value(1))
1024 TopoDS_Shape dummy = myFace.EmptyCopied();
1025 TopoDS_Face af = TopoDS::Face ( dummy );
1026 af.Orientation ( TopAbs_FORWARD );
1027 B.Add (af,ws.Value(1));
1028 if ( ( myFixAddNaturalBoundMode != Standard_True || //: abv 29.08.01: Spatial_firex_lofting.sat
1029 ( mySurf->Adaptor3d()->GetType() != GeomAbs_Sphere &&
1030 mySurf->Adaptor3d()->GetType() != GeomAbs_Torus ) ) &&
1031 ! ShapeAnalysis::IsOuterBound (af)) {
1032 Handle(ShapeExtend_WireData) sbdw =
1033 new ShapeExtend_WireData (TopoDS::Wire(ws.Value(1)));
1034 sbdw->Reverse ( myFace );
1035 ws.SetValue ( 1, sbdw->Wire() );
1036 SendWarning (Message_Msg ("FixAdvFace.FixOrientation.MSG5"));//Wire on face was reversed
1037 done = Standard_True;
1038#ifdef DEBUG
1039 cout<<"Wire reversed"<<endl; // mise au point !
1040#endif
1041 }
1042 }
1043 // in case of several wires, perform complex analysis
1044// ATTENTION ESSAI
1045// Plusieurs wires : orientations relatives
1046// Chaque wire doit "contenir" tous les autres
1047// Evidemment, en cas de peau de leopard, il peut y avoir probleme
1048 else {
1049// On prend chaque wire (NB: pcurves presentes !)
1050// En principe on devrait rejeter les wires non fermes (cf couture manque ?)
1051// On le classe par rapport aux autres, qui doivent tous etre, soit IN soit
1052// OUT. Sinon il y a imbrication -> SDB. Si IN, OK, si OUT on inverse
1053// (nb : ici pas myClos donc pas de pb de couture)
1054// Si au moins une inversion, il faut refaire la face (cf myRebil)
1055
1056 //:94 abv 30 Jan 98: calculate parametric precision
1057
1058// GeomAdaptor_Surface& Ads = mySurf->Adaptor3d()->ChangeSurface();
1059// Standard_Real toluv = Min ( Ads.UResolution(Precision()), Ads.VResolution(Precision()) );
1060 Standard_Boolean uclosed = mySurf->IsUClosed();
1061 Standard_Boolean vclosed = mySurf->IsVClosed();
1062 Standard_Real SUF, SUL, SVF, SVL;
1063 mySurf->Bounds(SUF, SUL, SVF, SVL);
1064
1065 TopTools_DataMapOfShapeListOfShape MW;
1066 TopTools_DataMapOfShapeInteger SI;
1067 TopTools_MapOfShape MapIntWires;
1068 MW.Clear();
1069 SI.Clear();
1070 MapIntWires.Clear();
1071 Standard_Integer NbOuts=0;
1072 Standard_Integer i;
1073
1074 for ( i = 1; i <= nb; i ++) {
1075 TopoDS_Shape asw = ws.Value(i);
1076 TopoDS_Wire aw = TopoDS::Wire (asw);
1077 TopoDS_Shape dummy = myFace.EmptyCopied();
1078 TopoDS_Face af = TopoDS::Face ( dummy );
1079// B.MakeFace (af,mySurf->Surface(),::Precision::Confusion());
1080 af.Orientation ( TopAbs_FORWARD );
1081 B.Add (af,aw);
1082 // PTV OCC945 06.11.2002 files ie_exhaust-A.stp (entities 3782, 3787)
1083 // tolerance is too big. It is seems that to identify placement of 2d point
1084 // it is enough Precision::PConfusion(), cause wea re know that 2d point in TopAbs_ON
1085 // BRepTopAdaptor_FClass2d clas (af,toluv);
1086 Standard_Boolean CheckShift = Standard_True;
1087 BRepTopAdaptor_FClass2d clas (af,::Precision::PConfusion());
1088 TopAbs_State sta = TopAbs_OUT;
1089 TopAbs_State staout = clas.PerformInfinitePoint();
1090 TopTools_ListOfShape IntWires;
1091 for ( Standard_Integer j = 1; j <= nbAll; j ++) {
1092 //if(i==j) continue;
1093 TopoDS_Shape aSh2 = allSubShapes.Value(j);
1094 if(aw == aSh2)
1095 continue;
1096 TopAbs_State stb = TopAbs_UNKNOWN;
1097 if(aSh2.ShapeType() == TopAbs_VERTEX) {
1098 gp_Pnt aP = BRep_Tool::Pnt(TopoDS::Vertex(aSh2));
1099 gp_Pnt2d p2d = mySurf->ValueOfUV(aP,Precision::Confusion());
1100 stb = clas.Perform (p2d,Standard_False);
1101 if(stb == staout && (uclosed || vclosed)) {
1102 gp_Pnt2d p2d1;
1103 if(uclosed) {
1104 Standard_Real period = SUL-SUF;
1105 p2d1.SetCoord(p2d.X()+period, p2d.Y());
1106 stb = clas.Perform (p2d1,Standard_False);
1107
1108 }
1109 if(stb == staout && vclosed) {
1110 Standard_Real period = SVL-SVF;
1111 p2d1.SetCoord(p2d.X(), p2d.Y()+ period);
1112 stb = clas.Perform (p2d1,Standard_False);
1113 }
1114 }
1115 }
1116 else if (aSh2.ShapeType() == TopAbs_WIRE) {
1117 CheckShift = Standard_True;
1118 TopoDS_Wire bw = TopoDS::Wire (aSh2);
1119 // Standard_Integer numin =0;
1120 TopoDS_Iterator ew (bw);
1121 for(;ew.More(); ew.Next()) {
1122 TopoDS_Edge ed = TopoDS::Edge (ew.Value());
1123 Standard_Real cf,cl;
1124 Handle(Geom2d_Curve) cw = BRep_Tool::CurveOnSurface (ed,myFace,cf,cl);
1125 if (cw.IsNull()) continue;
1126 gp_Pnt2d unp = cw->Value ((cf+cl)/2.);
1127 TopAbs_State ste = clas.Perform (unp,Standard_False);
1128 if( ste==TopAbs_OUT || ste==TopAbs_IN ) {
1129 if(stb==TopAbs_UNKNOWN) {
1130 stb = ste;
1131 }
1132 else {
1133 if(!(stb==ste)) {
1134 sta = TopAbs_UNKNOWN;
1135 SI.Bind(aw,0);
1136 j=nb;
1137 break;
1138 }
1139 }
1140 }
1141
1142 Standard_Boolean found = Standard_False;
1143 gp_Pnt2d unp1;
1144 if( stb == staout && CheckShift ) {
1145 CheckShift = Standard_False;
1146 if(uclosed) {
1147 Standard_Real period = SUL-SUF;
1148 unp1.SetCoord(unp.X()+period, unp.Y());
1149 found = (staout != clas.Perform (unp1,Standard_False));
1150 if(!found) {
1151 unp1.SetX(unp.X()-period);
1152 found = (staout != clas.Perform (unp1,Standard_False));
1153 }
1154 }
1155 if(vclosed&&!found) {
1156 Standard_Real period = SVL-SVF;
1157 unp1.SetCoord(unp.X(), unp.Y()+period);
1158 found = (staout != clas.Perform (unp1,Standard_False));
1159 if(!found) {
1160 unp1.SetY(unp.Y()-period);
1161 found = (staout != clas.Perform (unp1,Standard_False));
1162 }
1163 }
1164 }
1165 if(found) {
1166 if(stb==TopAbs_IN) stb = TopAbs_OUT;
1167 else stb = TopAbs_IN;
1168 Shift2dWire(bw,myFace,unp1.XY()-unp.XY(), mySurf);
1169 }
1170 }
1171 }
1172 if(stb==staout) {
1173 sta = TopAbs_IN;
1174 }
1175 else {
1176 IntWires.Append(aSh2);
1177 MapIntWires.Add(aSh2);
1178 }
1179 }
1180
1181 if (sta == TopAbs_UNKNOWN) { // ERREUR
1182 Message_Msg MSG ("FixAdvFace.FixOrientation.MSG11"); //Cannot orient wire %d of %d
1183 MSG.Arg (i);
1184 MSG.Arg (nb);
1185 SendWarning (MSG);
1186 }
1187 else {
1188 MW.Bind(aw,IntWires);
1189 if(sta==TopAbs_OUT) {
1190 NbOuts++;
1191 if(staout==TopAbs_IN) {
1192 // wire is OUT but InfinitePoint is IN => need to reverse
1193 ShapeExtend_WireData sewd (aw);
1194 sewd.Reverse(myFace);
1195 ws.SetValue (i,sewd.Wire());
1196 aSeqReversed.Append(i);
1197 done = Standard_True;
1198 SI.Bind(ws.Value(i),1);
1199 MapWires.Bind(ws.Value(i),IntWires);
1200 }
1201 else {
1202 SI.Bind(aw,1);
1203 MapWires.Bind(aw,IntWires);
1204 }
1205 }
1206 else {
1207 if(staout==TopAbs_OUT) SI.Bind(aw,2);
1208 else SI.Bind(aw,3);
1209 }
1210 }
1211
1212 }
1213
1214 for(i=1; i<=nb; i++) {
1215 TopoDS_Wire aw = TopoDS::Wire (ws.Value(i));
1216 Standard_Integer tmpi = SI.Find(aw);
1217 if(tmpi>1) {
1218 if(!MapIntWires.Contains(aw)) {
1219 NbOuts++;
1220 const TopTools_ListOfShape& IW = MW.Find(aw);
1221 if(tmpi==3) {
1222 // wire is OUT but InfinitePoint is IN => need to reverse
1223 ShapeExtend_WireData sewd (aw);
1224 sewd.Reverse(myFace);
1225 ws.SetValue (i,sewd.Wire());
1226 aSeqReversed.Append(i);
1227 done = Standard_True;
1228 MapWires.Bind(ws.Value(i),IW);
1229 }
1230 else MapWires.Bind(aw,IW);
1231 }
1232 else {
1233 if(tmpi==2) {
1234 // wire is IN but InfinitePoint is OUT => need to reverse
1235 ShapeExtend_WireData sewd (aw);
1236 sewd.Reverse(myFace);
1237 ws.SetValue (i,sewd.Wire());
1238 aSeqReversed.Append(i);
1239 done = Standard_True;
1240 }
1241 }
1242 }
1243 }
1244
1245 }
1246
1247 //done = (done && (nb ==1 || (isAddNaturalBounds || (!isAddNaturalBounds && nbInternal <nb))));
1248 if(isAddNaturalBounds && nb == aSeqReversed.Length())
1249 done = Standard_False;
1250 else
1251 done = (done && (nb ==1 || (isAddNaturalBounds || (!isAddNaturalBounds && nbInternal <nb))));
1252 // Faut-il reconstruire ? si myRebil est mis
1253 if ( done ) {
1254 TopoDS_Shape S = myFace.EmptyCopied();
1255 S.Orientation ( TopAbs_FORWARD );
1256 Standard_Integer i = 1;
1257 for ( ; i <= nb; i++ )
1258 B.Add ( S, ws.Value(i) );
1259
1260 if(nb < nbAll) {
1261 for( i =1; i <= nbAll;i++) {
1262 TopoDS_Shape aS2 = allSubShapes.Value(i);
1263 if(aS2.ShapeType() != TopAbs_WIRE ||
1264 (aS2.Orientation() != TopAbs_FORWARD && aS2.Orientation() != TopAbs_REVERSED))
1265 B.Add ( S,aS2);
1266 }
1267 }
1268
1269 if ( ! myFwd ) S.Orientation (TopAbs_REVERSED);
1270 if ( ! Context().IsNull() ) Context()->Replace ( myFace, S );
1271 myFace = TopoDS::Face ( S );
1272 BRepTools::Update(myFace);
1273 Standard_Integer k =1;
1274 for( ; k <= aSeqReversed.Length();k++) {
1275 Message_Msg MSG ("FixAdvFace.FixOrientation.MSG10"); //Wire %d of %d on face was reversed
1276 MSG.Arg (aSeqReversed.Value(k));
1277 MSG.Arg (nb);
1278 SendWarning (MSG);
1279#ifdef DEBUG
1280 cout<<"Wire no "<<aSeqReversed.Value(k)<<" of "<<nb<<" reversed"<<endl; // mise au point !
1281#endif
1282 }
1283
1284 }
1285 return done;
1286}
1287
1288
1289//=======================================================================
1290//function : CheckWire
1291//purpose : auxilary for FixMissingSeam
1292//=======================================================================
1293//:i7 abv 18 Sep 98: ProSTEP TR9 r0501-ug.stp: algorithm of fixing missing seam changed
1294// test whether the wire is opened on period of periodical surface
1295static Standard_Boolean CheckWire (const TopoDS_Wire &wire,
1296 const TopoDS_Face &face,
1297 const Standard_Real dU,
1298 const Standard_Real dV,
1299 Standard_Integer &isuopen,
1300 Standard_Integer &isvopen,
1301 Standard_Boolean &isDeg)
1302{
1303 gp_XY vec;
1304 vec.SetX(0);
1305 vec.SetY(0);
1306 ShapeAnalysis_Edge sae;
1307 isDeg = Standard_True;
1308 for ( TopoDS_Iterator ed(wire); ed.More(); ed.Next() ) {
1309 TopoDS_Edge edge = TopoDS::Edge ( ed.Value() );
1310 if ( ! BRep_Tool::Degenerated ( edge ) ) isDeg = Standard_False;
1311 Handle(Geom2d_Curve) c2d;
1312 Standard_Real f, l;
1313 if ( ! sae.PCurve ( edge, face, c2d, f, l, Standard_True ) )
1314 return Standard_False;
1315 vec += c2d->Value(l).XY() - c2d->Value(f).XY();
1316 }
1317 isuopen = ( Abs ( Abs ( vec.X() ) - dU ) < 0.1 * dU ? ( vec.X() >0 ? 1 : -1 ) : 0 );
1318 isvopen = ( Abs ( Abs ( vec.Y() ) - dV ) < 0.1 * dV ? ( vec.Y() >0 ? 1 : -1 ) : 0 );
1319 return isuopen || isvopen;
1320}
1321
1322
1323//=======================================================================
1324//function : FixMissingSeam
1325//purpose :
1326//=======================================================================
1327
1328Standard_Boolean ShapeFix_Face::FixMissingSeam()
1329{
1330 Standard_Boolean uclosed = mySurf->IsUClosed();
1331 Standard_Boolean vclosed = mySurf->IsVClosed();
1332
1333 if ( ! uclosed && ! vclosed ) return Standard_False;
1334
1335 if ( ! Context().IsNull() ) {
1336 TopoDS_Shape S = Context()->Apply ( myFace );
1337 myFace = TopoDS::Face ( S );
1338 }
1339
1340 //%pdn: surface should be made periodic before (see ShapeCustom_Surface)!
1341 if (mySurf->Surface()->IsKind(STANDARD_TYPE (Geom_BSplineSurface))) {
1342 Handle (Geom_BSplineSurface) BSpl = Handle (Geom_BSplineSurface)::DownCast (mySurf->Surface());
1343 if (!BSpl->IsUPeriodic() && !BSpl->IsVPeriodic())
1344 return Standard_False;
1345 }
1346
1347 Standard_Real URange, VRange, SUF, SUL, SVF, SVL;
1348 mySurf->Bounds ( SUF, SUL, SVF, SVL );
1349 Standard_Real fU1,fU2,fV1,fV2;
1350 BRepTools::UVBounds(myFace,fU1,fU2,fV1,fV2);
1351
1352 //pdn OCC55 fix to faces without the wires to avoid identical first and last parameters
1353 if ( ::Precision::IsInfinite ( SUF ) || ::Precision::IsInfinite ( SUL ) ) {
1354 if ( ::Precision::IsInfinite ( SUF ) ) SUF = fU1;
1355 if ( ::Precision::IsInfinite ( SUL ) ) SUL = fU2;
1356 if(Abs(SUL-SUF) < ::Precision::PConfusion())
1357 if ( ::Precision::IsInfinite ( SUF ) ) SUF-=1000.;
1358 else SUL+=1000.;
1359 }
1360 if ( ::Precision::IsInfinite ( SVF ) || ::Precision::IsInfinite ( SVL ) ) {
1361 if ( ::Precision::IsInfinite ( SVF ) ) SVF = fV1;
1362 if ( ::Precision::IsInfinite ( SVL ) ) SVL = fV2;
1363 if(Abs(SVL-SVF) < ::Precision::PConfusion())
1364 if ( ::Precision::IsInfinite ( SVF ) ) SVF-=1000.;
1365 else SVL+=1000.;
1366 }
1367
1368 URange = Abs ( SUL - SUF );
1369 VRange = Abs ( SVL - SVF );
1370// Standard_Real UTol = 0.2 * URange, VTol = 0.2 * VRange;
1371 Standard_Integer ismodeu = 0, ismodev = 0; //szv#4:S4163:12Mar99 was Boolean
1372 Standard_Integer isdeg1=0, isdeg2=0;
1373
1374 TopTools_SequenceOfShape ws;
1375 TopTools_SequenceOfShape aSeqNonManif;
1376 for ( TopoDS_Iterator wi(myFace,Standard_False); wi.More(); wi.Next() ) {
1377 if(wi.Value().ShapeType() != TopAbs_WIRE ||
1378 (wi.Value().Orientation() != TopAbs_FORWARD && wi.Value().Orientation() != TopAbs_REVERSED)) {
1379 aSeqNonManif.Append(wi.Value());
1380 continue;
1381 }
1382 ws.Append ( wi.Value() );
1383 }
1384
1385 TopoDS_Wire w1, w2;
1386 Standard_Integer i;
1387 for ( i=1; i <= ws.Length(); i++ ) {
1388 TopoDS_Wire wire = TopoDS::Wire ( ws.Value(i) );
1389 Standard_Integer isuopen, isvopen;
1390 Standard_Boolean isdeg;
1391 if ( ! CheckWire ( wire, myFace, URange, VRange, isuopen, isvopen, isdeg ) )
1392 continue;
1393 if ( w1.IsNull() ) { w1 = wire; ismodeu = isuopen; ismodev = isvopen; isdeg1 = isdeg ? i : 0; }
1394 else if ( w2.IsNull() ) {
1395 if ( ismodeu == -isuopen && ismodev == -isvopen ) { w2 = wire; isdeg2 = isdeg ? i : 0; }
1396 else if ( ismodeu == isuopen && ismodev == isvopen ) {
1397 w2 = wire;
1398 isdeg2 = isdeg;
1399 //:abv 29.08.01: If wires are contraversal, reverse one of them
1400 // If first one is single degenerated edge, reverse it; else second
1401 if ( isdeg1 ) {
1402 w1.Reverse();
1403 ismodeu = -ismodeu;
1404 ismodev = -ismodev;
1405 }
1406 else {
1407 w2.Reverse();
1408#ifdef DEB
1409 if ( ! isdeg2 ) cout << "Warning: ShapeFix_Face::FixMissingSeam(): wire reversed" << endl;
1410#endif
1411 }
1412 }
1413#ifdef DEB
1414 else cout << "Warning: ShapeFix_Face::FixMissingSeam(): incompatible open wires" << endl;
1415#endif
1416 }
1417// else return Standard_False; // abort
1418 else {
1419#ifdef DEB
1420 cout << "Warning: ShapeFix_Face::FixMissingSeam(): more than two open wires detected!" << endl;
1421#endif
1422 //:abv 30.08.09: if more than one open wires and more than two of them are
1423 // completely degenerated, remove any of them
1424 if ( isdeg || isdeg1 || isdeg2 ) {
1425 ws.Remove ( isdeg ? i : isdeg2 ? isdeg2 : isdeg1 );
1426 w1.Nullify();
1427 w2.Nullify();
1428 i = 0;
1429#ifdef DEB
1430 cout << "Warning: ShapeFix_Face::FixMissingSeam(): open degenerated wire removed" << endl;
1431#endif
1432 continue;
1433 }
1434 }
1435 }
1436
1437 BRep_Builder B;
1438 if ( w1.IsNull() ) return Standard_False;
1439 else if ( w2.IsNull() ) {
1440 // WARNING!!! Temporarily for spheres only:
1441 // If only one of wires limiting face on sphere is open in 2d,
1442 // this means that degenerated edge should be added to one of poles, and
1443 // then usual procedure applied
1444 if ( ismodeu && mySurf->Surface()->IsKind(STANDARD_TYPE(Geom_SphericalSurface)) ) {
1445 gp_Pnt2d p ( ( ismodeu < 0 ? 0. : 2.*PI ), ismodeu * 0.5 * PI );
1446 gp_Dir2d d ( -ismodeu, 0. );
1447 Handle(Geom2d_Line) line = new Geom2d_Line ( p, d );
1448 TopoDS_Edge edge;
1449 B.MakeEdge ( edge );
1450 B.Degenerated ( edge, Standard_True );
1451 B.UpdateEdge ( edge, line, myFace, ::Precision::Confusion() );
1452 B.Range ( edge, myFace, 0., 2*PI );
1453 TopoDS_Vertex V;
1454 B.MakeVertex ( V, mySurf->Value ( p.X(), p.Y() ), ::Precision::Confusion() );
1455 V.Orientation(TopAbs_FORWARD);
1456 B.Add(edge,V);
1457 V.Orientation(TopAbs_REVERSED);
1458 B.Add(edge,V);
1459 B.MakeWire ( w2 );
1460 B.Add ( w2, edge );
1461 ws.Append ( w2 );
1462 }
1463 else return Standard_False;
1464 }
1465
1466 // sort original wires
1467 Handle(ShapeFix_Wire) sfw = new ShapeFix_Wire;
1468 sfw->SetFace ( myFace );
1469 sfw->SetPrecision ( Precision() );
1470
1471 Handle(ShapeExtend_WireData) wd1 = new ShapeExtend_WireData ( w1 );
1472 Handle(ShapeExtend_WireData) wd2 = new ShapeExtend_WireData ( w2 );
1473
1474 // sorting
1475// Standard_Boolean degenerated = ( secondDeg != firstDeg );
1476// if ( ! degenerated ) {
1477 sfw->Load ( wd1 );
1478 sfw->FixReorder();
1479// }
1480 sfw->Load ( wd2 );
1481 sfw->FixReorder();
1482
1483 //:abv 29.08.01: reconstruct face taking into account reversing
1484 TopoDS_Shape dummy = myFace.EmptyCopied();
1485 TopoDS_Face tmpF = TopoDS::Face ( dummy );
1486 tmpF.Orientation ( TopAbs_FORWARD );
1487 for ( i=1; i <= ws.Length(); i++ ) {
1488 TopoDS_Wire wire = TopoDS::Wire ( ws.Value(i) );
1489 if ( wire.IsSame ( w1 ) ) wire = w1;
1490 else if ( wire.IsSame ( w2 ) ) wire = w2;
1491 B.Add ( tmpF, wire );
1492 }
1493 tmpF.Orientation ( myFace.Orientation() );
1494
1495 Standard_Real uf=SUF, vf=SVF;
1496
1497 // A special kind of FixShifted is necessary for torus-like
1498 // surfaces to adjust wires by period ALONG the missing SEAM direction
1499 // tr9_r0501-ug.stp #187640
1500 if ( uclosed && vclosed ) {
1501 Standard_Integer coord = ( ismodeu ? 1 : 0 );
1502 Standard_Integer isneg = ( ismodeu ? ismodeu : -ismodev );
1503 Standard_Real period = ( ismodeu ? URange : VRange );
1504 TopoDS_Shape S;
1505 Standard_Real m1[2][2], m2[2][2];
1506 S = tmpF.EmptyCopied();
1507 B.Add ( S, w1 );
1508 ShapeAnalysis::GetFaceUVBounds (TopoDS::Face(S), m1[0][0], m1[0][1], m1[1][0], m1[1][1]);
1509 S = tmpF.EmptyCopied();
1510 B.Add ( S, w2 );
1511 ShapeAnalysis::GetFaceUVBounds (TopoDS::Face(S), m2[0][0], m2[0][1], m2[1][0], m2[1][1]);
1512 Standard_Real shiftw2 =
1513 ShapeAnalysis::AdjustByPeriod ( 0.5 * ( m2[coord][0] + m2[coord][1] ),
1514 0.5 * ( m1[coord][0] + m1[coord][1] +
1515 isneg * ( period + ::Precision::PConfusion() ) ),
1516 period );
1517 m1[coord][0] = Min ( m1[coord][0], m2[coord][0] + shiftw2 );
1518 m1[coord][1] = Max ( m1[coord][1], m2[coord][1] + shiftw2 );
1519 for ( TopoDS_Iterator it(tmpF,Standard_False); it.More(); it.Next() ) {
1520 if(it.Value().ShapeType() != TopAbs_WIRE)
1521 continue;
1522 TopoDS_Wire w = TopoDS::Wire ( it.Value() );
1523 if ( w == w1 ) continue;
1524 Standard_Real shift;
1525 if ( w == w2 ) shift = shiftw2;
1526 else {
1527 S = tmpF.EmptyCopied();
1528 B.Add ( S, w );
1529 ShapeAnalysis::GetFaceUVBounds (TopoDS::Face(S), m2[0][0], m2[0][1], m2[1][0], m2[1][1]);
1530 shift = ShapeAnalysis::AdjustByPeriod ( 0.5 * ( m2[coord][0] + m2[coord][1] ),
1531 0.5 * ( m1[coord][0] + m1[coord][1] ), period );
1532 }
1533 if ( shift != 0. ) {
1534 gp_Vec2d V(0.,0.);
1535 V.SetCoord ( coord+1, shift );
1536 ShapeAnalysis_Edge sae;
1537 for ( TopoDS_Iterator iw(w); iw.More(); iw.Next() ) {
1538 TopoDS_Edge E = TopoDS::Edge ( iw.Value() );
1539 Handle(Geom2d_Curve) C;
1540 Standard_Real a, b;
1541 if ( ! sae.PCurve ( E, tmpF, C, a, b ) ) continue;
1542 C->Translate ( V );
1543 }
1544 }
1545 }
1546 // abv 05 Feb 02: OCC34
1547 // by the way, select proper split place by V to avoid extra intersections
1548 if ( m1[coord][1] - m1[coord][0] <= period ) {
1549 Standard_Real other = 0.5 * ( m1[coord][0] + m1[coord][1] - period );
1550 if ( ismodeu ) vf = other;
1551 else uf = other;
1552 }
1553 }
1554
1555 // find the best place by u and v to insert a seam
1556 // (so as to minimize splitting edges as possible)
1557 ShapeAnalysis_Edge sae;
1558 Standard_Integer foundU=0, foundV=0;
1559 Standard_Integer nb1 = wd1->NbEdges();
1560 Standard_Integer nb2 = wd2->NbEdges();
1561 for ( Standard_Integer i1 = 1; i1 <= nb1 + nb2; i1++ ) {
1562 TopoDS_Edge edge1 = ( i1 <= nb1 ? wd1->Edge ( i1 ) : wd2->Edge ( i1-nb1 ) );
1563 Handle(Geom2d_Curve) c2d;
1564 Standard_Real f, l;
1565 if ( ! sae.PCurve ( edge1, tmpF, c2d, f, l, Standard_True ) ) return Standard_False;
1566 gp_Pnt2d pos1 = c2d->Value(l).XY();
1567 // the best place is end of edge which is nearest to 0
1568 Standard_Boolean skipU = ! uclosed;
1569 if ( uclosed && ismodeu ) {
1570 pos1.SetX ( pos1.X() + ShapeAnalysis::AdjustByPeriod ( pos1.X(), SUF, URange ) );
1571 if ( foundU ==2 && Abs ( pos1.X() ) > Abs(uf) ) skipU = Standard_True;
1572 else if ( ! foundU || ( foundU ==1 && Abs ( pos1.X() ) < Abs(uf) ) ) {
1573 foundU = 1;
1574 uf = pos1.X();
1575 }
1576 }
1577 Standard_Boolean skipV = ! vclosed;
1578 if ( vclosed && ! ismodeu ) {
1579 pos1.SetY ( pos1.Y() + ShapeAnalysis::AdjustByPeriod ( pos1.Y(), SVF, URange ) );
1580 if ( foundV ==2 && Abs ( pos1.Y() ) > Abs(vf) ) skipV = Standard_True;
1581 else if ( ! foundV || ( foundV ==1 && Abs ( pos1.Y() ) < Abs(vf) ) ) {
1582 foundV = 1;
1583 vf = pos1.Y();
1584 }
1585 }
1586 if ( skipU && skipV )
1587 if ( i1 <= nb1 ) continue;
1588 else break;
1589 // or yet better - if it is end of some edges on both wires
1590 for ( Standard_Integer i2 = 1; i1 <= nb1 && i2 <= nb2; i2++ ) {
1591 TopoDS_Edge edge2 = wd2->Edge ( i2 );
1592 if ( ! sae.PCurve ( edge2, tmpF, c2d, f, l, Standard_True ) ) return Standard_False;
1593 gp_Pnt2d pos2 = c2d->Value(f).XY();
1594 if ( uclosed && ismodeu ) {
1595 pos2.SetX ( pos2.X() + ShapeAnalysis::AdjustByPeriod ( pos2.X(), pos1.X(), URange ) );
1596 if ( Abs ( pos2.X() - pos1.X() ) < ::Precision::PConfusion() &&
1597 ( foundU != 2 || Abs ( pos1.X() ) < Abs ( uf ) ) ) {
1598 foundU = 2;
1599 uf = pos1.X();
1600 }
1601 }
1602 if ( vclosed && ! ismodeu ) {
1603 pos2.SetY ( pos2.Y() + ShapeAnalysis::AdjustByPeriod ( pos2.Y(), pos1.Y(), VRange ) );
1604 if ( Abs ( pos2.Y() - pos1.Y() ) < ::Precision::PConfusion() &&
1605 ( foundV != 2 || Abs ( pos1.Y() ) < Abs ( vf ) ) ) {
1606 foundV = 2;
1607 vf = pos1.Y();
1608 }
1609 }
1610 }
1611 }
1612
1613 //pdn fixing RTS on offsets
1614 if ( uf < SUF || uf > SUL )
1615 uf+=ShapeAnalysis::AdjustToPeriod(uf,SUF,SUF+URange);
1616 if ( vf < SVF || vf > SVL )
1617 vf+=ShapeAnalysis::AdjustToPeriod(vf,SVF,SVF+VRange);
1618
1619 // Create fictive grid and call ComposeShell to insert a seam
1620 Handle(Geom_RectangularTrimmedSurface) RTS =
1621 new Geom_RectangularTrimmedSurface ( mySurf->Surface(), uf, uf+URange, vf, vf+VRange );
1622 Handle(TColGeom_HArray2OfSurface) grid = new TColGeom_HArray2OfSurface ( 1, 1, 1, 1 );
1623 grid->SetValue ( 1, 1, RTS ); //mySurf->Surface() );
1624 Handle(ShapeExtend_CompositeSurface) G = new ShapeExtend_CompositeSurface ( grid );
1625 TopLoc_Location L;
1626
1627 //addition non-manifold topology
1628 Standard_Integer j=1;
1629 for( ; j <= aSeqNonManif.Length(); j++)
1630 B.Add(tmpF,aSeqNonManif.Value(j));
1631
1632 ShapeFix_ComposeShell CompShell;
1633// TopoDS_Face tmpF = myFace;
1634// tmpF.Orientation(TopAbs_FORWARD);
1635 CompShell.Init ( G, L, tmpF, ::Precision::Confusion() );//myPrecision
1636 if ( Context().IsNull() ) SetContext ( new ShapeBuild_ReShape );
1637 CompShell.ClosedMode() = Standard_True;
1638 CompShell.SetContext( Context() );
1639 CompShell.SetMaxTolerance(MaxTolerance());
1640 CompShell.Perform();
1641
1642 // abv 03.07.00: CAX-IF TRJ4: trj4_k1_goe-tu-214.stp: #785: reset mySurf
1643 mySurf = new ShapeAnalysis_Surface ( RTS );
1644
1645 myResult = CompShell.Result();
1646// if ( myFace.Orientation() == TopAbs_REVERSED ) res.Reverse();
1647 Context()->Replace ( myFace, myResult );
1648 for (TopExp_Explorer exp ( myResult, TopAbs_FACE ); exp.More(); exp.Next() ) {
1649 myFace = TopoDS::Face ( exp.Current() );
1650 BRepTools::Update(myFace); //:p4
1651 }
1652
1653 SendWarning (Message_Msg ("FixAdvFace.FixMissingSeam.MSG0"));//Missing seam-edge added
1654 return Standard_True;
1655}
1656
1657//=======================================================================
1658//function : FixSmallAreaWire
1659//purpose :
1660//=======================================================================
1661
1662//%14 pdn 24.02.99 PRO10109, USA60293 fix wire on face with small area.
1663Standard_Boolean ShapeFix_Face::FixSmallAreaWire()
1664{
1665 if ( ! Context().IsNull() ) {
1666 TopoDS_Shape S = Context()->Apply ( myFace );
1667 myFace = TopoDS::Face ( S );
1668 }
1669
1670 //smh#8
1671 TopoDS_Shape emptyCopied = myFace.EmptyCopied();
1672 TopoDS_Face face = TopoDS::Face (emptyCopied);
1673 Standard_Integer nbRemoved = 0, nbWires = 0;
1674 BRep_Builder B;
1675 Standard_Real prec = ::Precision::PConfusion()*100;
1676 for (TopoDS_Iterator wi (myFace, Standard_False); wi.More(); wi.Next()) {
1677 if(wi.Value().ShapeType() != TopAbs_WIRE &&
1678 (wi.Value().Orientation() != TopAbs_FORWARD || wi.Value().Orientation() != TopAbs_REVERSED))
1679 continue;
1680 TopoDS_Wire wire = TopoDS::Wire ( wi.Value() );
1681 Handle(ShapeAnalysis_Wire) saw = new ShapeAnalysis_Wire(wire,myFace,prec);
1682 if ( saw->CheckSmallArea(prec) ) nbRemoved++;
1683 else {
1684 B.Add(face,wire);
1685 nbWires++;
1686 }
1687 }
1688 if ( nbRemoved <=0 ) return Standard_False;
1689
1690 if ( nbWires <=0 ) {
1691#ifdef DEB
1692 cout << "Warning: ShapeFix_Face: All wires on a face have small area; left untouched" << endl;
1693#endif
1694 return Standard_False;
1695 }
1696#ifdef DEB
1697 cout << "Warning: ShapeFix_Face: " << nbRemoved << " small area wire(s) removed" << endl;
1698#endif
1699 if ( ! Context().IsNull() ) Context()->Replace ( myFace, face );
1700 myFace = face;
1701 SendWarning (Message_Msg ("FixAdvFace.FixSmallAreaWire.MSG0"));//Null area wire detected, wire skipped
1702 return Standard_True;
1703}
1704//=======================================================================
1705//function : FixLoopWire
1706//purpose :
1707//=======================================================================
1708static void FindNext(const TopoDS_Shape& aVert,
1709 const TopoDS_Shape& ainitEdge,
1710 TopTools_IndexedMapOfShape& aMapVertices,
1711 TopTools_DataMapOfShapeListOfShape& aMapVertexEdges,
1712 const TopTools_MapOfShape& aMapSmallEdges,
1713 const TopTools_MapOfShape& aMapSeemEdges,
1714 TopTools_MapOfShape& aMapEdges,
1715 Handle(ShapeExtend_WireData)& aWireData)
1716{
1717 TopoDS_Iterator aItV(ainitEdge);
1718 TopoDS_Shape anextVert = aVert;
1719 Standard_Boolean isFind = Standard_False;
1720 for( ; aItV.More() && !isFind; aItV.Next())
1721 {
1722 if(!aItV.Value().IsSame(aVert) ) {
1723 isFind = Standard_True;
1724 anextVert = aItV.Value();
1725
1726 }
1727 }
1728
1729 if(!isFind && !aMapSmallEdges.Contains(ainitEdge))
1730 return;
1731 if(isFind && aMapVertices.Contains(anextVert))
1732 return;
1733
1734 const TopTools_ListOfShape& aledges = aMapVertexEdges.Find(anextVert);
1735 TopTools_ListIteratorOfListOfShape liter(aledges);
1736 isFind = Standard_False;
1737 TopoDS_Shape anextEdge;
1738 for( ; liter.More() && !isFind; liter.Next())
1739 {
1740 if(!aMapEdges.Contains(liter.Value()) && !liter.Value().IsSame(ainitEdge)) {
1741 anextEdge = liter.Value();
1742 aWireData->Add(anextEdge);
1743 if(aMapSeemEdges.Contains(anextEdge))
1744 aWireData->Add(anextEdge.Reversed());
1745 isFind = Standard_True;
1746 aMapEdges.Add(anextEdge);
1747 FindNext(anextVert,anextEdge,aMapVertices,aMapVertexEdges,aMapSmallEdges,aMapSeemEdges,aMapEdges,aWireData);
1748 }
1749 }
1750 return;
1751}
1752
1753static Standard_Boolean isClosed2D(const TopoDS_Face& aFace,const TopoDS_Wire& aWire)
1754{
1755 Standard_Boolean isClosed = Standard_True;
1756 Handle(ShapeAnalysis_Wire) asaw = new ShapeAnalysis_Wire(aWire,aFace,Precision::Confusion());
1757 for (Standard_Integer i = 1; i <= asaw->NbEdges() && isClosed; i++) {
1758 TopoDS_Edge edge1 = asaw->WireData()->Edge(i);
1759 //checking that wire is closed in 2D space with tolerance of vertex.
1760 ShapeAnalysis_Edge sae;
1761 TopoDS_Vertex v1 = sae.FirstVertex(edge1);
1762 asaw->SetPrecision(BRep_Tool::Tolerance(v1));
1763 asaw->CheckGap2d(i);
1764 isClosed = (asaw->LastCheckStatus(ShapeExtend_OK));
1765
1766 }
1767 return isClosed;
1768}
1769
1770//=======================================================================
1771//function : FixLoopWire
1772//purpose :
1773//=======================================================================
1774
1775Standard_Boolean ShapeFix_Face::FixLoopWire(TopTools_SequenceOfShape& aResWires)
1776{
1777 TopTools_IndexedMapOfShape aMapVertices;
1778 TopTools_DataMapOfShapeListOfShape aMapVertexEdges;
1779 TopTools_MapOfShape aMapSmallEdges;
1780 TopTools_MapOfShape aMapSeemEdges;
1781 if(!FixWireTool()->Analyzer()->CheckLoop(aMapVertices, aMapVertexEdges,aMapSmallEdges,aMapSeemEdges))
1782 return Standard_False;
1783
1784
1785 TopTools_MapOfShape aMapEdges;
1786 TopTools_SequenceOfShape aSeqWires;
1787
1788 //collecting wires from common vertex belonging more than 2 edges
1789 Standard_Integer i =1;
1790 for( ; i <= aMapVertices.Extent(); i++) {
1791 TopoDS_Shape aVert = aMapVertices.FindKey(i);
1792 const TopTools_ListOfShape& aledges = aMapVertexEdges.Find(aVert);
1793 TopTools_ListIteratorOfListOfShape liter(aledges);
1794 for( ; liter.More(); liter.Next())
1795 {
1796 TopoDS_Edge Edge = TopoDS::Edge(liter.Value());
1797 if(aMapEdges.Contains(Edge))
1798 continue;
1799
1800 Handle(ShapeExtend_WireData) aWireData = new ShapeExtend_WireData;
1801 aWireData->Add(Edge);
1802 if(aMapSeemEdges.Contains(Edge))
1803 aWireData->Add(Edge.Reversed());
1804 aMapEdges.Add(Edge);
1805 FindNext(aVert,Edge,aMapVertices,aMapVertexEdges,aMapSmallEdges,aMapSeemEdges,aMapEdges,aWireData);
1806 if(aWireData->NbEdges() ==1 && aMapSmallEdges.Contains(aWireData->Edge(1)))
1807 continue;
1808 TopoDS_Vertex aV1,aV2;
1809 TopoDS_Wire aWire = aWireData->Wire();
1810 TopExp::Vertices(aWire,aV1,aV2);
1811
1812 if(aV1.IsSame(aV2)) {
1813 Handle(ShapeExtend_WireData) asewd = new ShapeExtend_WireData(aWire);
1814 Handle(ShapeFix_Wire) asfw = new ShapeFix_Wire;
1815 asfw->Load(asewd);
1816 asfw->FixReorder();
1817 TopoDS_Wire awire2 = asfw->Wire();
1818 aResWires.Append(awire2);
1819
1820 }
1821 else aSeqWires.Append(aWireData->Wire());
1822 }
1823 }
1824
1825
1826 if(aSeqWires.Length() ==1) {
1827 aResWires.Append(aSeqWires.Value(1));
1828 }
1829 else {
1830 //collecting whole wire from two not closed wires having two common vertices.
1831 for( i =1; i <= aSeqWires.Length(); i++) {
1832 TopoDS_Vertex aV1,aV2;
1833 TopoDS_Wire aWire = TopoDS::Wire(aSeqWires.Value(i));
1834 TopExp::Vertices(aWire,aV1,aV2);
1835 Standard_Integer j = i+1;
1836 for( ; j <= aSeqWires.Length(); j++)
1837 {
1838 TopoDS_Vertex aV21,aV22;
1839 TopoDS_Wire aWire2 = TopoDS::Wire(aSeqWires.Value(j));
1840 TopExp::Vertices(aWire2,aV21,aV22);
1841 if((aV1.IsSame(aV21) || aV1.IsSame(aV22)) && (aV2.IsSame(aV21) || aV2.IsSame(aV22)))
1842 {
1843 Handle(ShapeExtend_WireData) asewd = new ShapeExtend_WireData(aWire);
1844 asewd->Add(aWire2);
1845 Handle(ShapeFix_Wire) asfw = new ShapeFix_Wire;
1846 asfw->Load(asewd);
1847 asfw->FixReorder();
1848 aResWires.Append(asfw->Wire());
1849 aSeqWires.Remove(j--);
1850 myStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE7 );
1851 break;
1852 }
1853
1854 }
1855 if(j <= aSeqWires.Length())
1856 aSeqWires.Remove(i--);
1857
1858 }
1859 if(aSeqWires.Length()<3) {
1860 for( i =1; i <= aSeqWires.Length(); i++)
1861 aResWires.Append(aSeqWires.Value(i));
1862
1863 }
1864 else {
1865 //collecting wires having one common vertex
1866 for( i =1; i <= aSeqWires.Length(); i++) {
1867 TopoDS_Vertex aV1,aV2;
1868 TopoDS_Wire aWire = TopoDS::Wire(aSeqWires.Value(i));
1869 TopExp::Vertices(aWire,aV1,aV2);
1870 Standard_Integer j =i+1;
1871 for( ; j <= aSeqWires.Length(); j++)
1872 {
1873 TopoDS_Vertex aV21,aV22;
1874 TopoDS_Wire aWire2 = TopoDS::Wire(aSeqWires.Value(j));
1875 TopExp::Vertices(aWire2,aV21,aV22);
1876 if((aV1.IsSame(aV21) || aV1.IsSame(aV22)) || (aV2.IsSame(aV21) || aV2.IsSame(aV22)))
1877 {
1878 Handle(ShapeExtend_WireData) asewd = new ShapeExtend_WireData(aWire);
1879 asewd->Add(aWire2);
1880 Handle(ShapeFix_Wire) asfw = new ShapeFix_Wire;
1881 asfw->Load(asewd);
1882 asfw->FixReorder();
1883 aWire = asfw->Wire();
1884 TopExp::Vertices(aWire,aV1,aV2);
1885 aSeqWires.Remove(j--);
1886 myStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE7 );
1887 }
1888 }
1889 aResWires.Append(aWire);
1890
1891 }
1892 }
1893 }
1894 Standard_Boolean isClosed = Standard_True;
1895
1896 //checking that obtained wires is closed in 2D space
1897 if (mySurf->Adaptor3d()->GetType() != GeomAbs_Plane) {
1898
1899 TopoDS_Shape emptyCopied = myFace.EmptyCopied();
1900 TopoDS_Face tmpFace = TopoDS::Face(emptyCopied);
1901 tmpFace.Orientation ( TopAbs_FORWARD );
1902
1903 for(i =1; i <= aResWires.Length() && isClosed; i++) {
1904 TopoDS_Wire awire = TopoDS::Wire(aResWires.Value(i));
1905 isClosed = isClosed2D(tmpFace,awire);
1906 }
1907 }
1908
1909 Standard_Boolean isDone =(aResWires.Length() && isClosed);
1910 if(isDone && aResWires.Length() >1) {
1911
1912 Message_Msg MSG ("FixAdvFace.FixLoopWire.MSG0"); //Wire was splitted on %d wires
1913 MSG.Arg (aResWires.Length());
1914#ifdef DEBUG
1915 cout<<"Wire was splitted on "<<aResWires.Length()<<" wires"<< endl;
1916#endif
1917 }
1918
1919 return isDone;
1920}
1921
1922
1923//=======================================================================
1924//function : GetPointOnEdge
1925//purpose : auxiliary
1926//:h0 abv 29 May 98: PRO10105 1949: like in BRepCheck, point is to be taken
1927// from 3d curve (but only if edge is SameParameter)
1928//=======================================================================
1929static gp_Pnt GetPointOnEdge ( const TopoDS_Edge &edge,
1930 const Handle(ShapeAnalysis_Surface) &surf,
1931 const Handle(Geom2d_Curve) &Crv2d,
1932 const Standard_Real param )
1933{
1934 if ( BRep_Tool::SameParameter ( edge ) ) {
1935 Standard_Real f,l;
1936 TopLoc_Location L;
1937 const Handle(Geom_Curve) ConS = BRep_Tool::Curve ( edge, L, f, l );
1938 if ( ! ConS.IsNull() )
1939 return ConS->Value ( param ).Transformed ( L.Transformation() );
1940 }
1941 return surf->Value ( Crv2d->Value ( param ) );
1942}
1943
1944
1945//=======================================================================
1946//function : SplitEdge
1947//purpose :
1948//=======================================================================
1949
1950Standard_Boolean ShapeFix_Face::SplitEdge(const Handle(ShapeExtend_WireData)& sewd,
1951 const Standard_Integer num,
1952 const Standard_Real param,
1953 const TopoDS_Vertex& vert,
1954 const Standard_Real preci,
1955 ShapeFix_DataMapOfShapeBox2d& boxes)
1956{
1957 TopoDS_Edge edge = sewd->Edge(num);
1958 TopoDS_Edge newE1, newE2;
1959 ShapeFix_SplitTool aTool;
1960 if(aTool.SplitEdge(edge,param,vert,myFace,newE1,newE2,preci,0.01*preci)) {
1961 // change context
1962 Handle(ShapeExtend_WireData) wd = new ShapeExtend_WireData;
1963 wd->Add(newE1);
1964 wd->Add(newE2);
1965 if(!Context().IsNull()) Context()->Replace( edge, wd->Wire() );
1966 for (TopExp_Explorer exp ( wd->Wire(), TopAbs_EDGE ); exp.More(); exp.Next() ) {
1967 TopoDS_Edge E = TopoDS::Edge ( exp.Current() );
1968 BRepTools::Update(E);
1969 }
1970
1971// for ( Standard_Integer i=1; i <= sewd->NbEdges(); i++ ) {
1972// TopoDS_Edge E = sewd->Edge(i);
1973// TopoDS_Shape S = Context()->Apply ( E );
1974// if ( S == E ) continue;
1975// for ( TopExp_Explorer exp(S,TopAbs_EDGE); exp.More(); exp.Next() )
1976// sewd->Add ( exp.Current(), i++ );
1977// sewd->Remove ( i-- );
1978// }
1979
1980 // change sewd and boxes
1981 sewd->Set(newE1,num);
1982 if(num==sewd->NbEdges())
1983 sewd->Add(newE2);
1984 else
1985 sewd->Add(newE2,num+1);
1986
1987 boxes.UnBind(edge);
1988 TopLoc_Location L;
1989 const Handle(Geom_Surface)& S = BRep_Tool::Surface(myFace,L);
1990 Handle(Geom2d_Curve) c2d;
1991 Standard_Real cf,cl;
1992 ShapeAnalysis_Edge sae;
1993 if(sae.PCurve(newE1,S,L,c2d,cf,cl,Standard_False)) {
1994 Bnd_Box2d box;
1995 Geom2dAdaptor_Curve gac;
1996 Standard_Real aFirst = c2d->FirstParameter();
1997 Standard_Real aLast = c2d->LastParameter();
1998 if(c2d->IsKind(STANDARD_TYPE(Geom2d_BSplineCurve))
1999 && (cf < aFirst || cl > aLast)) {
2000 //pdn avoiding problems with segment in Bnd_Box
2001 gac.Load(c2d);
2002 }
2003 else
2004 gac.Load(c2d,cf,cl);
2005 BndLib_Add2dCurve::Add(gac,::Precision::Confusion(),box);
2006 boxes.Bind(newE1,box);
2007 }
2008 if(sae.PCurve(newE2,S,L,c2d,cf,cl,Standard_False)) {
2009 Bnd_Box2d box;
2010 Geom2dAdaptor_Curve gac;
2011 Standard_Real aFirst = c2d->FirstParameter();
2012 Standard_Real aLast = c2d->LastParameter();
2013 if(c2d->IsKind(STANDARD_TYPE(Geom2d_BSplineCurve))
2014 && (cf < aFirst || cl > aLast)) {
2015 //pdn avoiding problems with segment in Bnd_Box
2016 gac.Load(c2d);
2017 }
2018 else
2019 gac.Load(c2d,cf,cl);
2020 BndLib_Add2dCurve::Add(gac,::Precision::Confusion(),box);
2021 boxes.Bind(newE2,box);
2022 }
2023 return Standard_True;
2024 }
2025 return Standard_False;
2026}
2027
2028
2029//=======================================================================
2030//function : SplitEdge
2031//purpose :
2032//=======================================================================
2033
2034Standard_Boolean ShapeFix_Face::SplitEdge(const Handle(ShapeExtend_WireData)& sewd,
2035 const Standard_Integer num,
2036 const Standard_Real param1,
2037 const Standard_Real param2,
2038 const TopoDS_Vertex& vert,
2039 const Standard_Real preci,
2040 ShapeFix_DataMapOfShapeBox2d& boxes)
2041{
2042 TopoDS_Edge edge = sewd->Edge(num);
2043 TopoDS_Edge newE1, newE2;
2044 ShapeFix_SplitTool aTool;
2045 if(aTool.SplitEdge(edge,param1,param2,vert,myFace,newE1,newE2,preci,0.01*preci)) {
2046 // change context
2047 Handle(ShapeExtend_WireData) wd = new ShapeExtend_WireData;
2048 wd->Add(newE1);
2049 wd->Add(newE2);
2050 if(!Context().IsNull()) Context()->Replace( edge, wd->Wire() );
2051 for (TopExp_Explorer exp ( wd->Wire(), TopAbs_EDGE ); exp.More(); exp.Next() ) {
2052 TopoDS_Edge E = TopoDS::Edge ( exp.Current() );
2053 BRepTools::Update(E);
2054 }
2055
2056 // change sewd and boxes
2057 sewd->Set(newE1,num);
2058 if(num==sewd->NbEdges())
2059 sewd->Add(newE2);
2060 else
2061 sewd->Add(newE2,num+1);
2062
2063 boxes.UnBind(edge);
2064 TopLoc_Location L;
2065 const Handle(Geom_Surface)& S = BRep_Tool::Surface(myFace,L);
2066 Handle(Geom2d_Curve) c2d;
2067 Standard_Real cf,cl;
2068 ShapeAnalysis_Edge sae;
2069 if(sae.PCurve(newE1,S,L,c2d,cf,cl,Standard_False)) {
2070 Bnd_Box2d box;
2071 Geom2dAdaptor_Curve gac;
2072 Standard_Real aFirst = c2d->FirstParameter();
2073 Standard_Real aLast = c2d->LastParameter();
2074 if(c2d->IsKind(STANDARD_TYPE(Geom2d_BSplineCurve))
2075 && (cf < aFirst || cl > aLast)) {
2076 //pdn avoiding problems with segment in Bnd_Box
2077 gac.Load(c2d);
2078 }
2079 else
2080 gac.Load(c2d,cf,cl);
2081 BndLib_Add2dCurve::Add(gac,::Precision::Confusion(),box);
2082 boxes.Bind(newE1,box);
2083 }
2084 if(sae.PCurve(newE2,S,L,c2d,cf,cl,Standard_False)) {
2085 Bnd_Box2d box;
2086 Geom2dAdaptor_Curve gac;
2087 Standard_Real aFirst = c2d->FirstParameter();
2088 Standard_Real aLast = c2d->LastParameter();
2089 if(c2d->IsKind(STANDARD_TYPE(Geom2d_BSplineCurve))
2090 && (cf < aFirst || cl > aLast)) {
2091 //pdn avoiding problems with segment in Bnd_Box
2092 gac.Load(c2d);
2093 }
2094 else
2095 gac.Load(c2d,cf,cl);
2096 BndLib_Add2dCurve::Add(gac,::Precision::Confusion(),box);
2097 boxes.Bind(newE2,box);
2098 }
2099 return Standard_True;
2100 }
2101 return Standard_False;
2102}
2103
2104
2105//=======================================================================
2106//function : FixIntersectingWires
2107//purpose :
2108//=======================================================================
2109
2110Standard_Boolean ShapeFix_Face::FixIntersectingWires()
2111{
2112 ShapeFix_IntersectionTool ITool(Context(),Precision(),MaxTolerance());
2113 return ITool.FixIntersectingWires(myFace);
2114}
2115
2116
2117//=======================================================================
2118//function : FixWiresTwoCoincEdges
2119//purpose :
2120//=======================================================================
2121
2122Standard_Boolean ShapeFix_Face::FixWiresTwoCoincEdges()
2123{
2124 if ( ! Context().IsNull() ) {
2125 TopoDS_Shape S = Context()->Apply ( myFace );
2126 myFace = TopoDS::Face ( S );
2127 }
2128
2129 TopAbs_Orientation ori = myFace.Orientation();
2130 TopoDS_Shape emptyCopied = myFace.EmptyCopied();
2131 TopoDS_Face face = TopoDS::Face (emptyCopied);
2132 face.Orientation(TopAbs_FORWARD);
2133 Standard_Integer nbWires = 0;
2134 BRep_Builder B;
2135
2136 for (TopoDS_Iterator it (myFace, Standard_False); it.More(); it.Next()) {
2137 if(it.Value().ShapeType() != TopAbs_WIRE ||
2138 (it.Value().Orientation() != TopAbs_FORWARD && it.Value().Orientation() != TopAbs_REVERSED)) {
2139 continue;
2140 }
2141 nbWires++;
2142 }
2143 if(nbWires<2) return Standard_False;
2144 Standard_Boolean isFixed = Standard_False;
2145 for (TopoDS_Iterator wi (myFace, Standard_False); wi.More(); wi.Next()) {
2146 if(wi.Value().ShapeType() != TopAbs_WIRE ||
2147 (wi.Value().Orientation() != TopAbs_FORWARD && wi.Value().Orientation() != TopAbs_REVERSED)) {
2148 B.Add(face,wi.Value());
2149 continue;
2150 }
2151 TopoDS_Wire wire = TopoDS::Wire ( wi.Value() );
2152 Handle(ShapeExtend_WireData) sewd = new ShapeExtend_WireData(wire);
2153 if(sewd->NbEdges()==2) {
2154 TopoDS_Edge E1 = sewd->Edge(1);
2155 TopoDS_Edge E2 = sewd->Edge(2);
2156 E1.Orientation(TopAbs_FORWARD);
2157 E2.Orientation(TopAbs_FORWARD);
2158 if( !(E1==E2) ) {
2159 B.Add(face,wire);
2160 }
2161 else isFixed = Standard_True;
2162 }
2163 else {
2164 B.Add(face,wire);
2165 }
2166 }
2167 if(isFixed) {
2168 face.Orientation(ori);
2169 if ( ! Context().IsNull() ) Context()->Replace ( myFace, face );
2170 myFace = face;
2171 }
2172
2173 return isFixed;
2174}
2175
2176
2177//=======================================================================
2178//function : FixSplitFace
2179//purpose :
2180//=======================================================================
2181
2182Standard_Boolean ShapeFix_Face::FixSplitFace(const TopTools_DataMapOfShapeListOfShape &MapWires)
2183{
2184 BRep_Builder B;
2185 TopTools_SequenceOfShape faces;
2186 TopoDS_Shape S = myFace;
2187 if ( ! Context().IsNull() )
2188 S = Context()->Apply ( myFace );
2189 Standard_Integer NbWires=0, NbWiresNew=0;
2190 for(TopoDS_Iterator iter(S,Standard_False); iter.More(); iter.Next()) {
2191 if(iter.Value().ShapeType() != TopAbs_WIRE ||
2192 (iter.Value().Orientation() != TopAbs_FORWARD && iter.Value().Orientation() != TopAbs_REVERSED))
2193 continue;
2194 TopoDS_Wire wire = TopoDS::Wire ( iter.Value() );
2195 NbWires++;
2196 if(MapWires.IsBound(wire)) {
2197 // if wire not closed --> stop split and return false
2198 Handle(ShapeExtend_WireData) sewd = new ShapeExtend_WireData(wire);
2199 TopoDS_Edge E1 = sewd->Edge(1);
2200 TopoDS_Edge E2 = sewd->Edge(sewd->NbEdges());
2201 TopoDS_Vertex V1,V2;
2202 ShapeAnalysis_Edge sae;
2203 V1=sae.FirstVertex(E1);
2204 V2=sae.LastVertex(E2);
2205 if(!V1.IsSame(V2)) {
2206 cout<<"wire not closed --> stop split"<<endl;
2207 return Standard_False;
2208 }
2209 // create face
2210 TopoDS_Shape emptyCopied = S.EmptyCopied();
2211 TopoDS_Face tmpFace = TopoDS::Face(emptyCopied);
2212 tmpFace.Orientation ( TopAbs_FORWARD );
2213 B.Add(tmpFace,wire);
2214 NbWiresNew++;
2215 const TopTools_ListOfShape& IntWires = MapWires.Find(wire);
2216 TopTools_ListIteratorOfListOfShape liter(IntWires);
2217 for( ; liter.More(); liter.Next()) {
2218 B.Add(tmpFace,liter.Value());
2219 NbWiresNew++;
2220 }
2221 if(!myFwd) tmpFace.Orientation(TopAbs_REVERSED);
2222 faces.Append(tmpFace);
2223 }
2224 }
2225
2226 if(NbWires!=NbWiresNew) return Standard_False;
2227
2228 if(faces.Length()>1) {
2229 TopoDS_Compound Comp;
2230 B.MakeCompound(Comp);
2231 for(Standard_Integer i=1; i<=faces.Length(); i++ )
2232 B.Add(Comp,faces(i));
2233 myResult = Comp;
2234 Context()->Replace ( myFace, myResult );
2235 for (TopExp_Explorer exp ( myResult, TopAbs_FACE ); exp.More(); exp.Next() ) {
2236 myFace = TopoDS::Face ( exp.Current() );
2237 BRepTools::Update(myFace);
2238 }
2239 return Standard_True;
2240 }
2241
2242 return Standard_False;
2243}