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