1 // Copyright (c) 1999-2014 OPEN CASCADE SAS
3 // This file is part of Open CASCADE Technology software library.
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
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.
11 // Alternatively, this file may be used under the terms of Open CASCADE
12 // commercial license or contractual agreement.
14 //:j6 abv 7 Dec 98: ProSTEP TR10 r0601_id.stp #57676 & #58586:
15 // in FixIntersectingEdges, do not cut edges because of influence on adjacent faces
16 // pdn 17.12.98: shifting whole wire in FixShifted
17 //:k3 abv 24 Dec 98: BUC50070 #26682 and #30087: removing self-int loops on pcurves
18 // pdn 30.12.98: PRO10366 #210: shifting pcurve between two singularities
19 // pdn 05.01.98: renaming method FixLittle to FixSmall
20 //:l0 abv 10.01.99: remove unused code
21 //:n2 abv 22.01.99: ma-test5.igs: IGES read (pref3d): remove degen edge with no pcurve
22 //:o4 abv 17.02.99: r0301_db.stp #53082: using parameter isClosed in CheckOrder
23 //:p4 abv 23.02.99: PRO9234 #15720: update UV points of edges after shifting pcurves
24 //#67 rln 01.03.99 S4135: ims010.igs treatment of Geom_SphericalSurface together with V-closed surfaces
25 //:p7 abv 10.03.99 PRO18206: using method IsDegenerated() to detect singularity in FixLacking
26 //:r0 abv 19.03.99 PRO7226.stp #489490: remove degenerated edges if several
27 //#78 rln 12.03.99 S4135: checking spatial closure with Precision
28 //#79 rln 15.03.99 S4135: bmarkmdl.igs: check for gap before shifting on singularities
29 // pdn 17.03.99 S4135: implemented fixing not adjacent intersection
30 //#86 rln 22.03.99 S4135: repeat of fix self-intersection if it was fixed just before
31 //%15 pdn 06.04.99 CTS18546-2: fix of self-intersection is repeated while fixed
32 //#3 smh 01.04.99 S4163: Overflow
33 //#4 szv S4163: optimization
34 //:r7 abv 12.04.99 S4136: FixLk: extend cases of adding degenerated edge
35 //:r8 abv 12.04.99 PRO10107.stp #2241: try increasing tolerance of edge for fix IE
36 //:s2 abv 21.04.99 S4136, PRO7978.igs: FixLacking extended to be able to bend pcurves
37 //szv#9:S4244:19Aug99 Methods FixGaps3d and FixGaps2d were introduced
38 //#15 smh 03.04.2000 PRO19800. Checking degenerated point on a surface of revolution.
39 // sln 25.09.2001 checking order of 3d and 2d representation curves
40 // van 19.10.2001 fix of non-adjacent self-intersection corrected to agree with BRepCheck
41 // skl 07.03.2002 fix for bug OCC180
42 // skl 15.05.2002 for OCC208 (if few edges have reference to
43 // one pcurve we make replace pcurve)
44 // PTV 26.06.2002 Remove regressions after fix OCC450
46 #include <Adaptor3d_CurveOnSurface.hxx>
47 #include <Bnd_Array1OfBox2d.hxx>
48 #include <Bnd_Box2d.hxx>
49 #include <BndLib_Add2dCurve.hxx>
50 #include <BRep_Builder.hxx>
51 #include <BRep_GCurve.hxx>
52 #include <BRep_ListIteratorOfListOfCurveRepresentation.hxx>
53 #include <BRep_TEdge.hxx>
54 #include <BRep_Tool.hxx>
55 #include <BRepBuilderAPI_MakeEdge.hxx>
56 #include <BRepBuilderAPI_MakeVertex.hxx>
57 #include <BRepTools.hxx>
58 #include <Geom2d_BSplineCurve.hxx>
59 #include <Geom2d_Curve.hxx>
60 #include <Geom2d_Line.hxx>
61 #include <Geom2d_TrimmedCurve.hxx>
62 #include <Geom2dAdaptor_Curve.hxx>
63 #include <Geom2dAdaptor_HCurve.hxx>
64 #include <Geom2dConvert.hxx>
65 #include <Geom_BSplineCurve.hxx>
66 #include <Geom_Curve.hxx>
67 #include <Geom_OffsetCurve.hxx>
68 #include <Geom_Plane.hxx>
69 #include <Geom_SphericalSurface.hxx>
70 #include <Geom_Surface.hxx>
71 #include <Geom_SurfaceOfRevolution.hxx>
72 #include <Geom_TrimmedCurve.hxx>
73 #include <GeomAdaptor_Curve.hxx>
74 #include <GeomAdaptor_HSurface.hxx>
75 #include <GeomAdaptor_Surface.hxx>
76 #include <GeomAPI.hxx>
77 #include <GeomAPI_ProjectPointOnCurve.hxx>
78 #include <GeomConvert_CompCurveToBSplineCurve.hxx>
80 #include <IntRes2d_IntersectionPoint.hxx>
81 #include <IntRes2d_SequenceOfIntersectionPoint.hxx>
82 #include <Message_Msg.hxx>
83 #include <Precision.hxx>
84 #include <ShapeAnalysis.hxx>
85 #include <ShapeAnalysis_Curve.hxx>
86 #include <ShapeAnalysis_Edge.hxx>
87 #include <ShapeAnalysis_Surface.hxx>
88 #include <ShapeAnalysis_TransferParameters.hxx>
89 #include <ShapeAnalysis_TransferParametersProj.hxx>
90 #include <ShapeAnalysis_Wire.hxx>
91 #include <ShapeAnalysis_WireOrder.hxx>
92 #include <ShapeBuild_Edge.hxx>
93 #include <ShapeBuild_ReShape.hxx>
94 #include <ShapeBuild_Vertex.hxx>
95 #include <ShapeConstruct_ProjectCurveOnSurface.hxx>
96 #include <ShapeExtend.hxx>
97 #include <ShapeExtend_WireData.hxx>
98 #include <ShapeFix.hxx>
99 #include <ShapeFix_Edge.hxx>
100 #include <ShapeFix_IntersectionTool.hxx>
101 #include <ShapeFix_SplitTool.hxx>
102 #include <ShapeFix_Wire.hxx>
103 #include <Standard_ErrorHandler.hxx>
104 #include <Standard_Failure.hxx>
105 #include <Standard_Type.hxx>
106 #include <TColgp_Array1OfPnt.hxx>
107 #include <TColgp_SequenceOfPnt.hxx>
108 #include <TColStd_Array1OfInteger.hxx>
109 #include <TColStd_Array1OfReal.hxx>
110 #include <TColStd_HSequenceOfReal.hxx>
111 #include <TopExp_Explorer.hxx>
112 #include <TopLoc_Location.hxx>
113 #include <TopoDS.hxx>
114 #include <TopoDS_Edge.hxx>
115 #include <TopoDS_Face.hxx>
116 #include <TopoDS_Vertex.hxx>
117 #include <TopoDS_Wire.hxx>
118 #include <TopTools_Array1OfShape.hxx>
119 #include <TopTools_HSequenceOfShape.hxx>
121 IMPLEMENT_STANDARD_RTTIEXT(ShapeFix_Wire,ShapeFix_Root)
124 //#######################################################################
125 // Constructors, initializations, modes, querying
126 //#######################################################################
127 //=======================================================================
128 //function : ShapeFix_Wire
130 //=======================================================================
131 ShapeFix_Wire::ShapeFix_Wire() : myMaxTailAngleSine(0), myMaxTailWidth(-1)
133 myFixEdge = new ShapeFix_Edge;
134 myAnalyzer = new ShapeAnalysis_Wire;
137 myStatusRemovedSegment = Standard_False;
140 //=======================================================================
141 //function : ShapeFix_Wire
143 //=======================================================================
145 ShapeFix_Wire::ShapeFix_Wire (
146 const TopoDS_Wire& wire,
147 const TopoDS_Face &face,
148 const Standard_Real prec) : myMaxTailAngleSine(0), myMaxTailWidth(-1)
150 myFixEdge = new ShapeFix_Edge;
151 myAnalyzer = new ShapeAnalysis_Wire;
153 SetMaxTolerance ( prec );
154 myStatusRemovedSegment = Standard_False;
155 Init ( wire, face, prec );
158 //=======================================================================
159 //function : SetPrecision
161 //=======================================================================
163 void ShapeFix_Wire::SetPrecision (const Standard_Real prec)
165 ShapeFix_Root::SetPrecision ( prec );
166 myAnalyzer->SetPrecision ( prec );
169 //=======================================================================
170 //function : SetMaxTailAngle
172 //=======================================================================
173 void ShapeFix_Wire::SetMaxTailAngle(const Standard_Real theMaxTailAngle)
175 myMaxTailAngleSine = Sin(theMaxTailAngle);
176 myMaxTailAngleSine = (myMaxTailAngleSine >= 0) ? myMaxTailAngleSine : 0;
179 //=======================================================================
180 //function : SetMaxTailWidth
182 //=======================================================================
183 void ShapeFix_Wire::SetMaxTailWidth(const Standard_Real theMaxTailWidth)
185 myMaxTailWidth = theMaxTailWidth;
188 //=======================================================================
189 //function : ClearModes
191 //=======================================================================
193 void ShapeFix_Wire::ClearModes()
195 myTopoMode = Standard_False;
196 myGeomMode = Standard_True;
197 myClosedMode = Standard_True;
198 myPreference2d = Standard_True;
199 myFixGapsByRanges = Standard_False;
201 myRemoveLoopMode = -1;
203 myFixReversed2dMode = -1;
204 myFixRemovePCurveMode = -1;
205 myFixRemoveCurve3dMode = -1;
206 myFixAddPCurveMode = -1;
207 myFixAddCurve3dMode = -1;
209 myFixShiftedMode = -1;
210 myFixSameParameterMode = -1;
211 myFixVertexToleranceMode = -1;
213 myFixNotchedEdgesMode = -1;
214 myFixSelfIntersectingEdgeMode = -1;
215 myFixIntersectingEdgesMode = -1;
216 myFixNonAdjacentIntersectingEdgesMode = -1;
219 myFixReorderMode = -1;
221 myFixConnectedMode = -1;
222 myFixEdgeCurvesMode = -1;
223 myFixDegeneratedMode = -1;
224 myFixSelfIntersectionMode = -1;
225 myFixLackingMode = -1;
226 myFixGaps3dMode = -1;
227 myFixGaps2dMode = -1;
230 //=======================================================================
231 //function : ClearStatuses
233 //=======================================================================
235 void ShapeFix_Wire::ClearStatuses()
237 Standard_Integer emptyStatus = ShapeExtend::EncodeStatus ( ShapeExtend_OK );
239 myLastFixStatus = emptyStatus;
241 myStatusReorder = emptyStatus;
242 myStatusSmall = emptyStatus;
243 myStatusConnected = emptyStatus;
244 myStatusEdgeCurves = emptyStatus;
245 myStatusDegenerated = emptyStatus;
246 myStatusSelfIntersection = emptyStatus;
247 myStatusLacking = emptyStatus;
248 myStatusGaps3d = emptyStatus; //szv#9:S4244:19Aug99 new method introduced
249 myStatusGaps2d = emptyStatus; //szv#9:S4244:19Aug99 new method introduced
250 myStatusClosed = emptyStatus;
251 myStatusNotches = emptyStatus;
252 myStatusFixTails = emptyStatus;
255 //=======================================================================
258 //=======================================================================
260 void ShapeFix_Wire::Init (const TopoDS_Wire& wire,
261 const TopoDS_Face &face, const Standard_Real prec)
265 SetPrecision ( prec );
268 //=======================================================================
271 //=======================================================================
273 void ShapeFix_Wire::Init (const Handle(ShapeAnalysis_Wire)& saw)
278 // SetPrecision ( saw.Precision() );
281 //=======================================================================
284 //=======================================================================
286 void ShapeFix_Wire::Load (const TopoDS_Wire& wire)
290 TopoDS_Wire W = wire;
291 if ( ! Context().IsNull() ) {
292 TopoDS_Shape S = Context()->Apply ( wire );
293 W = TopoDS::Wire ( S );
296 myAnalyzer->Load ( W );
300 //=======================================================================
303 //=======================================================================
305 void ShapeFix_Wire::Load (const Handle(ShapeExtend_WireData)& sbwd)
308 myAnalyzer->Load ( sbwd );
309 if ( ! Context().IsNull() ) UpdateWire();
313 //=======================================================================
316 //=======================================================================
318 Standard_Integer ShapeFix_Wire::NbEdges() const
320 Handle(ShapeExtend_WireData) sbwd = myAnalyzer->WireData();
321 return sbwd.IsNull() ? 0 : sbwd->NbEdges();
324 //#######################################################################
325 // Fixing methods of API level
326 //#######################################################################
328 //=======================================================================
330 //purpose : This method performs all the available fixes.
331 // If some fix is turned on or off explicitly by the flag,
332 // it is called or not depending on that flag
333 // Else (i.e. if flag is default) fix is called depending on the
334 // situation: default is True, but some fixes are not called or
335 // are limited if order of edges in the wire is not OK
336 //=======================================================================
338 Standard_Boolean ShapeFix_Wire::Perform()
341 if ( ! IsLoaded() ) return Standard_False;
343 if ( !Context().IsNull() )
344 myFixEdge->SetContext( Context() );
346 Standard_Boolean Fixed = Standard_False;
348 // FixReorder is first, because as a rule wire is required to be ordered
349 // We shall analyze the order of edges in the wire and set appropriate
350 // status even if FixReorder should not be called (if it is forbidden)
352 ShapeAnalysis_WireOrder sawo;
353 Standard_Boolean ReorderOK = ( myAnalyzer->CheckOrder ( sawo, myClosedMode ) ==0 );
354 if ( NeedFix ( myFixReorderMode, ! ReorderOK ) ) {
355 if(FixReorder()) Fixed = Standard_True;
356 ReorderOK = ! StatusReorder ( ShapeExtend_FAIL );
359 // FixSmall is allowed to change topology only if mode is set and FixReorder
361 if ( NeedFix ( myFixSmallMode, myTopoMode ) ) {
362 if ( FixSmall ( ! myTopoMode || ! ReorderOK, MinTolerance() ) ) {
363 Fixed = Standard_True;
364 // retry reorder if necessary (after FixSmall it can work better)
365 if ( NeedFix ( myFixReorderMode, ! ReorderOK ) ) {
367 ReorderOK = ! StatusReorder ( ShapeExtend_FAIL );
372 if ( NeedFix ( myFixConnectedMode, ReorderOK ) ) {
373 if ( FixConnected() ) Fixed = Standard_True;
376 if ( NeedFix ( myFixEdgeCurvesMode ) ) {
377 Standard_Integer savFixShiftedMode = myFixShiftedMode;
378 // turn out FixShifted if reorder not done
379 if ( myFixShiftedMode == -1 && ! ReorderOK ) myFixShiftedMode = 0;
380 if ( FixEdgeCurves() ) Fixed = Standard_True;
381 myFixShiftedMode = savFixShiftedMode;
384 if ( NeedFix ( myFixDegeneratedMode ) ) {
385 if ( FixDegenerated() ) Fixed = Standard_True; // ?? if ! ReorderOK ??
388 //pdn - temporary to test
389 if (myFixTailMode <= 0 && NeedFix(myFixNotchedEdgesMode, ReorderOK))
391 Fixed |= FixNotchedEdges();
392 if(Fixed) FixShifted(); //skl 07.03.2002 for OCC180
395 if (myFixTailMode != 0)
404 if ( NeedFix ( myFixSelfIntersectionMode, myClosedMode ) ) {
405 Standard_Integer savFixIntersectingEdgesMode = myFixIntersectingEdgesMode;
406 // switch off FixIntEdges if reorder not done
407 if ( myFixIntersectingEdgesMode == -1 && ! ReorderOK )
408 myFixIntersectingEdgesMode = 0;
409 if ( FixSelfIntersection() ) Fixed = Standard_True;
411 myFixIntersectingEdgesMode = savFixIntersectingEdgesMode;
414 if ( NeedFix ( myFixLackingMode, ReorderOK ) ) {
415 if ( FixLacking() ) Fixed = Standard_True;
418 // TEMPORARILY without special mode !!!
419 Handle(ShapeExtend_WireData) sbwd = WireData();
420 for (Standard_Integer iedge = 1; iedge <= sbwd->NbEdges(); iedge++)
421 if ( myFixEdge->FixVertexTolerance (sbwd->Edge (iedge), Face()) )
423 Fixed = Standard_True;
426 if ( !Context().IsNull() )
432 //=======================================================================
433 //function : FixReorder
435 //=======================================================================
437 Standard_Boolean ShapeFix_Wire::FixReorder()
439 myStatusReorder = ShapeExtend::EncodeStatus ( ShapeExtend_OK );
440 if ( ! IsLoaded() ) return Standard_False;
443 ShapeAnalysis_WireOrder sawo;
444 myAnalyzer->CheckOrder ( sawo, myClosedMode, Standard_True );
446 //:abv revolCuts.sat -23: in case of bi-periodic surface check case
447 // of reversed wire specifically. This is necessary because degenerated
448 // cases are possible when direct evaluation will give bad result.
449 Standard_Boolean isReorder = Standard_False;
450 if ( sawo.Status() != 0 &&
451 ! myAnalyzer->Surface().IsNull() &&
452 myAnalyzer->Surface()->Surface()->IsUPeriodic() &&
453 myAnalyzer->Surface()->Surface()->IsVPeriodic() ) {
454 Handle(ShapeExtend_WireData) sbwd2 = new ShapeExtend_WireData;
455 for ( Standard_Integer i=WireData()->NbEdges(); i >=1; i-- )
456 sbwd2->Add ( WireData()->Edge(i) );
457 ShapeAnalysis_WireOrder sawo2;
458 ShapeAnalysis_Wire analyzer2 ( sbwd2, myAnalyzer->Face(), Precision() );
459 analyzer2.CheckOrder ( sawo2, myClosedMode, Standard_True );
460 if ( ( sawo2.Status() >=0 && sawo2.Status() < sawo.Status() ) ||
461 ( sawo.Status() <0 && sawo2.Status() > sawo.Status() ) ) {
462 WireData()->Init ( sbwd2 );
464 isReorder = Standard_True;
470 if ( LastFixStatus ( ShapeExtend_FAIL ) )
471 myStatusReorder |= ShapeExtend::EncodeStatus ( LastFixStatus ( ShapeExtend_FAIL1 ) ?
472 ShapeExtend_FAIL1 : ShapeExtend_FAIL2 );
473 if ( ! LastFixStatus ( ShapeExtend_DONE )&& !isReorder ) return Standard_False;
475 myStatusReorder |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE1 );
476 if ( sawo.Status() ==2 || sawo.Status() ==-2 )
477 myStatusReorder |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE2 );
478 if ( sawo.Status() <0 )
479 myStatusReorder |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE3 );
480 if ( sawo.Status() == 3)
481 myStatusReorder |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE5 );//only shifted
482 return Standard_True;
485 //=======================================================================
486 //function : FixSmall
488 //=======================================================================
490 Standard_Integer ShapeFix_Wire::FixSmall (const Standard_Boolean lockvtx,
491 const Standard_Real precsmall)
493 myStatusSmall = ShapeExtend::EncodeStatus ( ShapeExtend_OK );
494 if ( ! IsLoaded() ) return Standard_False;
496 for ( Standard_Integer i = NbEdges(); i >0; i-- ) {
497 FixSmall ( i, lockvtx, precsmall );
498 myStatusSmall |= myLastFixStatus;
501 return StatusSmall ( ShapeExtend_DONE );
505 //=======================================================================
506 //function : FixConnected
508 //=======================================================================
510 Standard_Boolean ShapeFix_Wire::FixConnected (const Standard_Real prec)
512 myStatusConnected = ShapeExtend::EncodeStatus ( ShapeExtend_OK );
513 if ( ! IsLoaded() ) return Standard_False;
515 Standard_Integer stop = ( myClosedMode ? 0 : 1 );
516 for ( Standard_Integer i = NbEdges(); i > stop; i-- ) {
517 FixConnected ( i, prec );
518 myStatusConnected |= myLastFixStatus;
521 return StatusConnected ( ShapeExtend_DONE );
524 //=======================================================================
525 //function : FixEdgeCurves
527 //=======================================================================
529 Standard_Boolean ShapeFix_Wire::FixEdgeCurves()
531 myStatusEdgeCurves = ShapeExtend::EncodeStatus ( ShapeExtend_OK );
532 if ( ! IsLoaded() ) return Standard_False;
533 Standard_Boolean isReady = IsReady();
535 Handle(ShapeExtend_WireData) sbwd = WireData();
536 Standard_Integer i, nb = sbwd->NbEdges();
537 TopoDS_Face face = Face();
538 Handle(ShapeFix_Edge) theAdvFixEdge = myFixEdge;
539 if (theAdvFixEdge.IsNull()) myFixReversed2dMode = Standard_False;
541 // fix revesred 2d / 3d curves
542 if ( isReady && NeedFix ( myFixReversed2dMode ) ) {
543 for ( i=1; i <= nb; i++ ) {
544 theAdvFixEdge->FixReversed2d ( sbwd->Edge(i), face );
545 if ( theAdvFixEdge->Status ( ShapeExtend_DONE ) )
546 myStatusEdgeCurves |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE1 );
547 if ( theAdvFixEdge->Status ( ShapeExtend_FAIL ) )
548 myStatusEdgeCurves |= ShapeExtend::EncodeStatus ( ShapeExtend_FAIL1 );
552 // add / remove pcurve
553 if ( isReady && NeedFix ( myFixRemovePCurveMode, Standard_False ) ) {
554 for ( i=1; i <= nb; i++ ) {
555 myFixEdge->FixRemovePCurve ( sbwd->Edge(i), face );
556 if ( myFixEdge->Status ( ShapeExtend_DONE ) )
557 myStatusEdgeCurves |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE2 );
558 if ( myFixEdge->Status ( ShapeExtend_FAIL ) )
559 myStatusEdgeCurves |= ShapeExtend::EncodeStatus ( ShapeExtend_FAIL2 );
563 if ( isReady && NeedFix ( myFixAddPCurveMode ) ) {
564 Standard_Integer overdegen = 0; //:c0
565 for ( i=1; i <= nb; i++ ) {
566 myFixEdge->FixAddPCurve ( sbwd->Edge(i), face, sbwd->IsSeam(i),
567 myAnalyzer->Surface(), Precision() );
568 if ( myFixEdge->Status ( ShapeExtend_DONE ) )
569 myStatusEdgeCurves |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE3 );
570 if ( myFixEdge->Status ( ShapeExtend_FAIL ) )
571 myStatusEdgeCurves |= ShapeExtend::EncodeStatus ( ShapeExtend_FAIL3 );
573 //if ( !sbwd->IsSeam(i) && myFixEdge->Status ( ShapeExtend_DONE2 )
574 // && BRep_Tool::SameParameter(sbwd->Edge(i)) ) {
575 if ( !sbwd->IsSeam(i) && myFixEdge->Status ( ShapeExtend_DONE2 ) ) {
576 // abv 24 Feb 00: trj3_s1-ac-214.stp #1631 etc.: try to split the edge in singularity
577 if ( ! Context().IsNull() ) {
579 TopoDS_Edge E = sbwd->Edge ( i );
580 ShapeAnalysis_Curve SAC;
582 Handle(Geom_Curve) C = BRep_Tool::Curve ( E, a, b );
583 Handle(ShapeAnalysis_Surface) S = myAnalyzer->Surface();
584 Standard_Integer nbs = S->NbSingularities(MinTolerance());
585 GeomAdaptor_Curve GAC ( C, a, b );
586 TColStd_SequenceOfReal seq;
587 for (Standard_Integer j=1; j <= nbs; j++) {
591 Standard_Real par1, par2, split;
592 Standard_Boolean tmpUIsoDeg;
593 S->Singularity (j, Preci, P3d, pd1, pd2, par1, par2, tmpUIsoDeg);
594 if ( SAC.Project ( GAC, P3d, MinTolerance(), pr, split, Standard_True ) < Max(Preci,MinTolerance()) ) {
595 if ( split - a > ::Precision::PConfusion() &&
596 b - split > ::Precision::PConfusion() ) {
598 for ( k=1; k <= seq.Length(); k++ ) {
599 if ( split < seq(k)-::Precision::PConfusion() ) {
600 seq.InsertBefore ( k, split );
603 else if ( split < seq(k)+::Precision::PConfusion() ) break;
605 if ( k > seq.Length() ) seq.Append ( split );
609 if ( seq.Length() >0 ) { // supposed that edge is SP
611 cout << "Edge going over singularity detected; splitted" << endl;
613 Standard_Boolean isFwd = ( E.Orientation() == TopAbs_FORWARD );
614 E.Orientation ( TopAbs_FORWARD );
616 //if( BRep_Tool::SameParameter(sbwd->Edge(i)) )
617 // sbe.RemovePCurve ( E, face );
619 //10.04.2003 skl for using trimmed lines as pcurves
620 ShapeAnalysis_Edge sae;
621 if( BRep_Tool::SameParameter(sbwd->Edge(i)) )
622 sbe.RemovePCurve ( E, face );
624 if(sae.HasPCurve(E,face)) {
625 Handle(Geom2d_Curve) C2d;
626 Standard_Real fp2d,lp2d;
627 if(sae.PCurve(E,face,C2d,fp2d,lp2d)) {
628 if( !C2d->IsKind(STANDARD_TYPE(Geom2d_TrimmedCurve)) )
629 sbe.RemovePCurve(E,face);
634 // myFixEdge->FixSameParameter ( E ); // to ensure SameRange & SP
636 TopoDS_Vertex V1, V2, V;
637 //ShapeAnalysis_Edge sae;
638 V1 = sae.FirstVertex ( E );
639 V2 = sae.LastVertex ( E );
641 Handle(ShapeExtend_WireData) sw = new ShapeExtend_WireData;
642 for ( Standard_Integer k=0; k <= seq.Length(); k++ )
644 Standard_Real split = ( k < seq.Length() ? seq(k+1) : b );
645 if ( k < seq.Length() )
647 B.MakeVertex ( V, C->Value(split), BRep_Tool::Tolerance(E) );
648 //try increase tolerance before splitting
649 Standard_Real aDist = BRep_Tool::Pnt(V1).Distance(BRep_Tool::Pnt(V));
650 if (aDist < BRep_Tool::Tolerance(V1) * 1.01) {
651 B.UpdateVertex(V1, Max(aDist, BRep_Tool::Tolerance(V1)));
658 aDist = BRep_Tool::Pnt(V2).Distance(BRep_Tool::Pnt(V));
659 if (aDist < BRep_Tool::Tolerance(V2) * 1.01) {
660 B.UpdateVertex(V, Max(aDist, BRep_Tool::Tolerance(V2)));
672 TopoDS_Edge edge = sbe.CopyReplaceVertices ( E, V1, V );
673 if( BRep_Tool::SameParameter(sbwd->Edge(i)) ) {
674 //TopoDS_Edge edge = sbe.CopyReplaceVertices ( E, V1, V );
675 B.Range ( edge, a, split );
679 //TopoDS_Edge edge = sbe.CopyReplaceVertices(sbwd->Edge(i),V1,V);
680 Handle(ShapeAnalysis_TransferParameters) sftp =
681 new ShapeAnalysis_TransferParameters(E,face);
682 sftp->TransferRange(edge, a, split, Standard_False);
691 E.Orientation ( TopAbs_REVERSED );
693 Context()->Replace ( E, sw->Wire() );
695 nb = sbwd->NbEdges();
705 //:c0 abv 20 Feb 98: treat case of curve going over degenerated pole and seam
706 if ( overdegen && myAnalyzer->Surface()->IsUClosed(Precision()) ) {
708 Standard_Real URange, SUF, SUL, SVF, SVL;
709 myAnalyzer->Surface()->Bounds(SUF, SUL, SVF, SVL);
710 URange = (Abs(SUL - SUF));
712 ShapeAnalysis_Edge sae;
714 for ( k = 1; k <= nb; k++) {
715 Standard_Real cf, cl;
716 Handle(Geom2d_Curve) c2d;
717 if ( ! sae.PCurve ( sbwd->Edge(k), face, c2d, cf, cl, Standard_True ) ) break;
718 vec += c2d->Value(cl).XY() - c2d->Value(cf).XY();
720 if ( k > nb && Abs ( Abs ( vec.X() ) - URange ) < 0.1 * URange ) {
721 sbe.RemovePCurve (sbwd->Edge ( overdegen ), face);
722 myFixEdge->Projector()->AdjustOverDegenMode() = Standard_False;
723 myFixEdge->FixAddPCurve ( sbwd->Edge(overdegen), face, sbwd->IsSeam(overdegen), myAnalyzer->Surface(), Precision());
726 cout << "Edge going over singularity detected; pcurve adjusted" << endl;
731 // add / remove pcurve
732 if ( isReady && NeedFix ( myFixRemoveCurve3dMode, Standard_False ) ) {
733 for ( i=1; i <= nb; i++ ) {
734 myFixEdge->FixRemoveCurve3d ( sbwd->Edge(i) );
735 if ( myFixEdge->Status ( ShapeExtend_DONE ) )
736 myStatusEdgeCurves |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE4 );
737 if ( myFixEdge->Status ( ShapeExtend_FAIL ) )
738 myStatusEdgeCurves |= ShapeExtend::EncodeStatus ( ShapeExtend_FAIL4 );
741 if ( NeedFix ( myFixAddCurve3dMode ) ) {
742 for ( i=1; i <= nb; i++ ) {
743 myFixEdge->FixAddCurve3d ( sbwd->Edge(i) );
744 if ( myFixEdge->Status ( ShapeExtend_DONE ) )
745 myStatusEdgeCurves |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE5 );
746 if ( myFixEdge->Status ( ShapeExtend_FAIL ) ) {
747 //:abv 29.08.01: Spatial_firex_lofting.sat: if 3d curve cannot
748 // be built because edge has no pcurves either, remove that edge
749 Handle(Geom2d_Curve) C;
750 Handle(Geom_Surface) S;
752 Standard_Real first = 0., last = 0.;
753 BRep_Tool::CurveOnSurface ( sbwd->Edge(i), C, S, L, first, last );
754 if ( C.IsNull() || Abs (last - first) < Precision::PConfusion())
756 SendWarning ( sbwd->Edge ( i ), Message_Msg ( "FixWire.FixCurve3d.Removed" ) );// Incomplete edge (with no pcurves or 3d curve) removed
757 sbwd->Remove ( i-- );
759 myStatusEdgeCurves |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE5 );
760 FixConnected (i + 1, Precision());
762 myStatusEdgeCurves |= ShapeExtend::EncodeStatus ( ShapeExtend_FAIL5 );
768 if ( isReady && NeedFix ( myFixSeamMode, Standard_False ) ) {
769 for ( i=1; i <= nb; i++ ) {
771 if ( LastFixStatus ( ShapeExtend_DONE ) )
772 myStatusEdgeCurves |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE6 );
773 if ( LastFixStatus ( ShapeExtend_FAIL ) )
774 myStatusEdgeCurves |= ShapeExtend::EncodeStatus ( ShapeExtend_FAIL6 );
779 if ( isReady && NeedFix ( myFixShiftedMode ) ) {
781 if ( LastFixStatus ( ShapeExtend_DONE ) )
782 myStatusEdgeCurves |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE7 );
783 if ( LastFixStatus ( ShapeExtend_FAIL ) )
784 myStatusEdgeCurves |= ShapeExtend::EncodeStatus ( ShapeExtend_FAIL7 );
787 // fix same parameter
788 if ( isReady && NeedFix ( myFixSameParameterMode ) ){
789 for ( i=1; i <= nb; i++ ) {
790 // skl 28.10.2004 for OCC6366 - check SameRange
791 ShapeAnalysis_Edge sae;
792 Standard_Real First, Last;
793 Handle(Geom_Curve) tmpc3d = BRep_Tool::Curve(sbwd->Edge(i), First, Last);
794 if(sae.HasPCurve(sbwd->Edge(i),face)) {
795 Handle(Geom2d_Curve) C2d;
796 Standard_Real fp2d,lp2d;
797 if(sae.PCurve(sbwd->Edge(i),face,C2d,fp2d,lp2d, Standard_False)) {
798 if( fabs(First-fp2d)>Precision::PConfusion() ||
799 fabs(Last-lp2d)>Precision::PConfusion() )
802 B.SameRange(sbwd->Edge(i),Standard_False);
804 else if(!sae.CheckPCurveRange(First, Last, C2d))
808 const Handle(Geom_Surface)& S = BRep_Tool::Surface(face, L);
809 ShapeBuild_Edge().RemovePCurve (sbwd->Edge(i), S, L);
810 myFixEdge->FixAddPCurve ( sbwd->Edge(i), face, sbwd->IsSeam(i),
811 myAnalyzer->Surface(), Precision() );
812 if ( myFixEdge->Status ( ShapeExtend_DONE ) )
813 myStatusEdgeCurves |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE3 );
814 if ( myFixEdge->Status ( ShapeExtend_FAIL ) )
815 myStatusEdgeCurves |= ShapeExtend::EncodeStatus ( ShapeExtend_FAIL3 );
819 myFixEdge->FixSameParameter ( sbwd->Edge(i), Face());
820 if ( myFixEdge->Status ( ShapeExtend_DONE ) )
821 myStatusEdgeCurves |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE8 );
822 if ( myFixEdge->Status ( ShapeExtend_FAIL ) )
823 myStatusEdgeCurves |= ShapeExtend::EncodeStatus ( ShapeExtend_FAIL8 );
827 //:abv 10.06.02: porting C40 -> dev (CC670-12608.stp): moved from Perform()
828 // Update with face is needed for plane surfaces (w/o stored pcurves)
829 if ( NeedFix ( myFixVertexToleranceMode ) )
831 for ( i=1; i <= nb; i++)
833 myFixEdge->FixVertexTolerance (sbwd->Edge (i), Face());
834 if ( myFixEdge->Status ( ShapeExtend_DONE ) )
835 myStatusEdgeCurves |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE8 );
836 if ( myFixEdge->Status ( ShapeExtend_FAIL ) )
837 myStatusEdgeCurves |= ShapeExtend::EncodeStatus ( ShapeExtend_FAIL8 );
839 if (!Context().IsNull() )
844 return StatusEdgeCurves ( ShapeExtend_DONE );
847 //=======================================================================
848 //function : FixDegenerated
850 //=======================================================================
852 Standard_Boolean ShapeFix_Wire::FixDegenerated()
854 myStatusDegenerated = ShapeExtend::EncodeStatus ( ShapeExtend_OK );
855 if ( ! IsReady() ) return Standard_False;
857 // if ( ! myAnalyzer->Surface()->HasSingularities ( Precision() ) ) return;
859 Standard_Integer lastcoded = -1, prevcoded = 0;
860 Standard_Integer stop = ( myClosedMode ? 0 : 1 );
861 for ( Standard_Integer i = NbEdges(); i > stop; i-- ) {
862 FixDegenerated ( i );
863 myStatusDegenerated |= myLastFixStatus;
864 //:r0 abv 19 Mar 99: PRO7226.stp #489490: remove duplicated degenerated edges
865 Standard_Integer coded = ( LastFixStatus ( ShapeExtend_DONE2 ) ? 1 : 0 );
866 if ( lastcoded ==-1 ) lastcoded = coded;
867 if ( coded && ( prevcoded || ( i ==1 && lastcoded ) ) && NbEdges() >1 ) {
868 Handle(ShapeExtend_WireData) sbwd = WireData();
871 if ( ! prevcoded ) i = NbEdges();
872 B.Degenerated ( sbwd->Edge ( i++ ), Standard_False );
875 else prevcoded = coded;
878 return StatusDegenerated ( ShapeExtend_DONE );
882 //=======================================================================
883 //function : FixSelfIntersection
884 //purpose : Applies FixSelfIntersectingEdge and FixIntersectingEdges
885 // and removes wrong edges
886 //=======================================================================
888 Standard_Boolean ShapeFix_Wire::FixSelfIntersection()
890 myStatusSelfIntersection = ShapeExtend::EncodeStatus ( ShapeExtend_OK );
891 if ( ! IsReady() ) return Standard_False;
893 Handle(ShapeExtend_WireData) sbwd = WireData();
894 Standard_Integer nb = sbwd->NbEdges();
896 if ( NeedFix ( myFixSelfIntersectingEdgeMode ) ) {
897 if (myRemoveLoopMode<1)
898 for ( Standard_Integer num=1; num <=nb; num++ )
900 FixSelfIntersectingEdge ( num );
901 myStatusSelfIntersection |= myLastFixStatus;
903 else if (myRemoveLoopMode==1)
905 for ( Standard_Integer num=1; num <=nb; num++ )
907 FixSelfIntersectingEdge ( num );
908 myStatusSelfIntersection |= myLastFixStatus;
909 if(nb<sbwd->NbEdges()) num--;
910 nb = sbwd->NbEdges();
912 FixClosed(Precision());
916 if ( NeedFix ( myFixIntersectingEdgesMode ) )
918 Standard_Integer num = ( myClosedMode ? 1 : 2 );
919 for ( ; nb >1 && num <= nb; num++ )
921 FixIntersectingEdges ( num );
922 if ( LastFixStatus ( ShapeExtend_FAIL1 ) )
923 myStatusSelfIntersection |= ShapeExtend::EncodeStatus ( ShapeExtend_FAIL1 );
924 if ( LastFixStatus ( ShapeExtend_FAIL2 ) )
925 myStatusSelfIntersection |= ShapeExtend::EncodeStatus ( ShapeExtend_FAIL2 );
926 if ( ! LastFixStatus ( ShapeExtend_DONE ) ) continue;
928 if ( LastFixStatus ( ShapeExtend_DONE1 ) )
929 myStatusSelfIntersection |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE1 );
930 if ( LastFixStatus ( ShapeExtend_DONE2 ) )
931 myStatusSelfIntersection |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE2 );
932 if(LastFixStatus (ShapeExtend_DONE6))
933 myStatusSelfIntersection |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE6 );
935 if ( /*! myTopoMode ||*/ nb < 3 )
937 //#86 rln 22.03.99 sim2.igs, entity 4292: After fixing of self-intersecting
938 //BRepCheck finds one more self-intersection not found by ShapeAnalysis
939 //%15 pdn 06.04.99 repeat until fixed CTS18546-2 entity 777
941 // if the tolerance was modified we should recheck the result, if it was enough
942 if ( LastFixStatus ( ShapeExtend_DONE7 ) ) //num--;
943 FixIntersectingEdges ( num );
947 if ( LastFixStatus ( ShapeExtend_DONE4 ) ) sbwd->Remove ( num );
948 if ( LastFixStatus ( ShapeExtend_DONE3 ) ) sbwd->Remove ( num >1 ? num-1 : nb+num-1 );
949 if ( LastFixStatus ( ShapeExtend_DONE4 ) ||
950 LastFixStatus ( ShapeExtend_DONE3 ) )
952 myStatusSelfIntersection |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE3 );
953 num = ( myClosedMode ? 1 : 2 );
954 nb = sbwd->NbEdges();
956 cout << "Warning: ShapeFix_Wire::FixSelfIntersection: Edge removed" << endl;
962 //%15 pdn 06.04.99 repeat until fixed CTS18546-2 entity 777
963 FixIntersectingEdges ( num );
964 /*if ( LastFixStatus ( ShapeExtend_DONE7 ) )*/
965 // Always revisit the fixed edge
969 if ( !Context().IsNull())
974 //pdn 17.03.99 S4135 to avoid regression fixing not adjacent intersection
975 if ( NeedFix ( myFixNonAdjacentIntersectingEdgesMode ) ) {
977 ShapeFix_IntersectionTool ITool(Context(),Precision());
978 Standard_Integer NbSplit=0, NbCut=0,NbRemoved=0;
979 if(ITool.FixSelfIntersectWire(sbwd,myAnalyzer->Face(),NbSplit,NbCut,NbRemoved)) {
980 myStatusSelfIntersection |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE5 );//gka 06.09.04
982 if( NbSplit>0 || NbRemoved>0 ) {
983 if(NbRemoved>0) myStatusRemovedSegment = Standard_True;
984 //Load(sbwd); commented by skl 29.12.2004 for OCC7624, instead this
985 // string inserted following three strings:
986 myAnalyzer->Load ( sbwd );
987 if ( ! Context().IsNull() ) UpdateWire();
991 if (StatusSelfIntersection (ShapeExtend_DONE5))
992 cout<<"Warning: ShapeFix_Wire::FixIntersection: Non-adjacent intersection fixed (split-"
993 <<NbSplit<<", cut-"<<NbCut<<", removed-"<<NbRemoved<<")"<<endl;
997 Bnd_Array1OfBox2d boxes(1,nb);
999 const Handle(Geom_Surface)& S = BRep_Tool::Surface(Face(), L);
1000 Handle(Geom2d_Curve) c2d;
1001 Standard_Real cf,cl;
1002 ShapeAnalysis_Edge sae;
1003 for(Standard_Integer i = 1; i <= nb; i++){
1004 TopoDS_Edge E = sbwd->Edge (i);
1005 if(sae.PCurve (E,S,L,c2d,cf,cl,Standard_False)) {
1007 Geom2dAdaptor_Curve gac;
1008 Standard_Real aFirst = c2d->FirstParameter();
1009 Standard_Real aLast = c2d->LastParameter();
1010 if(c2d->IsKind(STANDARD_TYPE(Geom2d_BSplineCurve))
1011 && (cf < aFirst || cl > aLast)) {
1012 //pdn avoiding problems with segment in Bnd_Box
1016 gac.Load(c2d,cf,cl);
1017 BndLib_Add2dCurve::Add(gac,::Precision::Confusion(),box);
1022 Standard_Boolean isFail = Standard_False, isDone = Standard_False;
1023 for(Standard_Integer num1 = 1; num1 < nb-1; num1++) {
1024 Standard_Integer fin = (num1 == 1 ? nb-1 : nb);
1025 for(Standard_Integer num2 = num1+2; num2 <= fin; num2++)
1026 if(!boxes(num1).IsOut(boxes(num2))){
1027 FixIntersectingEdges (num1, num2);
1028 isFail |= LastFixStatus ( ShapeExtend_FAIL1 );
1029 isDone |= LastFixStatus ( ShapeExtend_DONE1 );
1034 myStatusSelfIntersection |= ShapeExtend::EncodeStatus ( ShapeExtend_FAIL3 );
1036 myStatusSelfIntersection |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE5 );
1038 if (StatusSelfIntersection (ShapeExtend_DONE5))
1039 cout << "Warning: ShapeFix_Wire::FixSelfIntersection: Non ajacent intersection fixed" << endl;
1044 return StatusSelfIntersection ( ShapeExtend_DONE );
1048 //=======================================================================
1049 //function : FixLacking
1051 //=======================================================================
1053 Standard_Boolean ShapeFix_Wire::FixLacking ( const Standard_Boolean force )
1055 myStatusLacking = ShapeExtend::EncodeStatus ( ShapeExtend_OK );
1056 if ( ! IsReady() ) return Standard_False;
1058 Standard_Integer start = ( myClosedMode ? 1 : 2 );
1059 for ( Standard_Integer i = start; i <= NbEdges(); i++ ) {
1060 FixLacking ( i, force );
1061 myStatusLacking |= myLastFixStatus;
1064 return StatusLacking ( ShapeExtend_DONE );
1068 //=======================================================================
1069 //function : FixClosed
1071 //=======================================================================
1073 Standard_Boolean ShapeFix_Wire::FixClosed (const Standard_Real prec)
1075 myStatusClosed = ShapeExtend::EncodeStatus ( ShapeExtend_OK );
1076 if ( ! IsLoaded() || NbEdges() <1 ) return Standard_False;
1078 FixConnected ( 1, prec );
1079 if ( LastFixStatus ( ShapeExtend_DONE ) )
1080 myStatusClosed |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE1 );
1081 if ( LastFixStatus ( ShapeExtend_FAIL ) )
1082 myStatusClosed |= ShapeExtend::EncodeStatus ( ShapeExtend_FAIL1 );
1084 FixDegenerated ( 1 );
1085 if ( LastFixStatus ( ShapeExtend_DONE ) )
1086 myStatusClosed |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE2 );
1087 if ( LastFixStatus ( ShapeExtend_FAIL ) )
1088 myStatusClosed |= ShapeExtend::EncodeStatus ( ShapeExtend_FAIL2 );
1091 if ( LastFixStatus ( ShapeExtend_DONE ) )
1092 myStatusClosed |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE3 );
1093 if ( LastFixStatus ( ShapeExtend_FAIL ) )
1094 myStatusClosed |= ShapeExtend::EncodeStatus ( ShapeExtend_FAIL3 );
1096 return StatusClosed ( ShapeExtend_DONE );
1100 //#######################################################################
1101 // Fixing methods of advanced level
1102 //#######################################################################
1104 //=======================================================================
1105 //function : FixReorder
1107 //=======================================================================
1109 Standard_Boolean ShapeFix_Wire::FixReorder (const ShapeAnalysis_WireOrder& wi)
1111 myLastFixStatus = ShapeExtend::EncodeStatus ( ShapeExtend_OK );
1112 if ( ! IsLoaded() ) return Standard_False;
1114 Standard_Integer status = wi.Status();
1115 if ( status ==0 ) return Standard_False;
1116 if ( status <=-10 ) {
1117 myLastFixStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_FAIL1 );
1118 return Standard_False;
1121 Handle(ShapeExtend_WireData) sbwd = WireData();
1122 Standard_Integer i, nb = sbwd->NbEdges();
1123 if ( nb != wi.NbEdges() ) {
1124 myLastFixStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_FAIL2 );
1125 return Standard_False;
1127 // D abord on protege
1128 for (i = 1; i <= nb; i ++) {
1129 if ( wi.Ordered(i) == 0 ) {
1130 myLastFixStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_FAIL3 );
1131 return Standard_False;
1135 Handle(TopTools_HSequenceOfShape) newedges = new TopTools_HSequenceOfShape();
1136 for ( i=1; i <= nb; i++ )
1137 newedges->Append ( sbwd->Edge ( wi.Ordered(i) ) );
1138 for ( i=1; i <= nb; i++ )
1139 sbwd->Set ( TopoDS::Edge ( newedges->Value(i) ), i );
1141 myLastFixStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE1 );
1142 return Standard_True;
1146 //=======================================================================
1147 //function : FixSmall
1149 //=======================================================================
1151 Standard_Boolean ShapeFix_Wire::FixSmall (const Standard_Integer num,
1152 const Standard_Boolean lockvtx,
1153 const Standard_Real precsmall)
1155 myLastFixStatus = ShapeExtend::EncodeStatus ( ShapeExtend_OK );
1156 if ( ! IsLoaded() || NbEdges() <=1 ) return Standard_False;
1159 Handle(ShapeAnalysis_Wire) theAdvAnalyzer = myAnalyzer;
1160 if (theAdvAnalyzer.IsNull()) return Standard_False;
1161 Standard_Integer n = ( num >0 ? num : NbEdges() );
1162 theAdvAnalyzer->CheckSmall ( n, precsmall );
1163 if ( theAdvAnalyzer->LastCheckStatus ( ShapeExtend_FAIL ) ) {
1164 myLastFixStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_FAIL1 );
1165 //:n2 return Standard_False;
1168 if ( ! theAdvAnalyzer->LastCheckStatus ( ShapeExtend_DONE ) ) return Standard_False;
1170 // OUI cette edge est NULLE
1172 if ( theAdvAnalyzer->LastCheckStatus ( ShapeExtend_DONE2 ) ) {
1173 // edge is small, but vertices are not the same..
1174 if ( lockvtx || ! myTopoMode ) {
1175 myLastFixStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_FAIL2 );
1176 return Standard_False;
1178 myLastFixStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE2 );
1180 else myLastFixStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE1 );
1182 // action: remove edge
1183 if ( ! Context().IsNull() )
1184 Context()->Remove(WireData()->Edge(n));
1185 SendWarning ( WireData()->Edge ( n ), Message_Msg ( "FixAdvWire.FixSmall.MSG0" ) ); //Small edge(s) removed
1186 WireData()->Remove ( n );
1188 // call FixConnected in the case if vertices of the small edge were not the same
1189 if ( LastFixStatus ( ShapeExtend_DONE2 ) ) {
1190 Standard_Integer savLastFixStatus = myLastFixStatus;
1191 //#43 rln 20.11.98 S4054 CTS18544 entity 21734 removing last edge
1192 FixConnected ( n <= NbEdges() ? n : 1, precsmall );
1193 if ( LastFixStatus ( ShapeExtend_FAIL ) )
1194 savLastFixStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_FAIL3 );
1195 myLastFixStatus = savLastFixStatus;
1198 return Standard_True;
1202 //=======================================================================
1203 //function : FixConnected
1205 //=======================================================================
1207 Standard_Boolean ShapeFix_Wire::FixConnected (const Standard_Integer num,
1208 const Standard_Real prec)
1210 myLastFixStatus = ShapeExtend::EncodeStatus ( ShapeExtend_OK );
1211 if ( ! IsLoaded() || NbEdges() <=0 ) return Standard_False;
1215 myAnalyzer->CheckConnected ( num, prec < 0 ? MaxTolerance() : prec );
1216 if ( myAnalyzer->LastCheckStatus ( ShapeExtend_FAIL ) ) {
1217 myLastFixStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_FAIL1 );
1219 if ( ! myAnalyzer->LastCheckStatus ( ShapeExtend_DONE ) ) return Standard_False;
1221 // action: replacing vertex
1223 Handle(ShapeExtend_WireData) sbwd = WireData();
1224 Standard_Integer n2 = ( num >0 ? num : sbwd->NbEdges() );
1225 Standard_Integer n1 = ( n2 >1 ? n2-1 : sbwd->NbEdges() );
1226 TopoDS_Edge E1 = sbwd->Edge(n1);
1227 TopoDS_Edge E2 = sbwd->Edge(n2);
1229 ShapeAnalysis_Edge sae;
1230 TopoDS_Vertex V1 = sae.LastVertex (E1);
1231 TopoDS_Vertex V2 = sae.FirstVertex (E2);
1234 if ( myAnalyzer->LastCheckStatus ( ShapeExtend_DONE1 ) ) { // absolutely confused
1235 myLastFixStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE1 );
1236 //#40 rln 18.11.98 S4054 BUC60035 entity 2393 (2-nd sub-curve is edge with the same vertex)
1237 if ( V2.IsSame ( sae.LastVertex (E2) ) ) {
1239 if ( ! Context().IsNull() )
1240 Context()->Replace ( V1, V.Oriented(V1.Orientation()) );
1244 if ( ! Context().IsNull() )
1245 Context()->Replace ( V2, V.Oriented(V2.Orientation()) );
1248 else { // on moyenne ...
1249 if ( myAnalyzer->LastCheckStatus ( ShapeExtend_DONE2 ) )
1250 myLastFixStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE2 );
1251 else myLastFixStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE3 );
1252 ShapeBuild_Vertex sbv;
1253 V = sbv.CombineVertex ( V1, V2, 1.0001 );
1254 if ( ! Context().IsNull() ) {
1255 Context()->Replace ( V1, V.Oriented(V1.Orientation()) );
1256 Context()->Replace ( V2, V.Oriented(V2.Orientation()) );
1260 // replace vertices to a new one
1261 ShapeBuild_Edge sbe;
1262 if ( sbwd->NbEdges() <2 ) {
1263 if(E2.Free() && myTopoMode) {
1265 B.Remove(E2,sae.FirstVertex(E2));
1266 B.Remove(E2,sae.LastVertex(E2));
1267 B.Add(E2,V.Oriented(TopAbs_FORWARD));
1268 B.Add(E2,V.Oriented(TopAbs_REVERSED));
1271 TopoDS_Edge tmpE = sbe.CopyReplaceVertices ( E2, V, V );
1272 sbwd->Set ( tmpE, n2 );
1273 if ( ! Context().IsNull() ) Context()->Replace(E2,tmpE);
1277 if(E2.Free() &&E1.Free() && myTopoMode) {
1279 B.Remove(E2,sae.FirstVertex(E2));
1280 B.Add(E2,V.Oriented(TopAbs_FORWARD));
1281 if ( ! myAnalyzer->LastCheckStatus ( ShapeExtend_DONE1 ) ||
1282 sae.FirstVertex (E2).IsSame (sae.LastVertex (E2)) ) {
1283 B.Remove(E1,sae.LastVertex(E1));
1284 B.Add(E1,V.Oriented(TopAbs_REVERSED));
1288 TopoDS_Edge tmpE2 = sbe.CopyReplaceVertices ( E2, V, TopoDS_Vertex() );
1289 sbwd->Set ( tmpE2, n2 );
1290 if ( ! Context().IsNull() ) Context()->Replace(E2,tmpE2);
1291 if ( ! myAnalyzer->LastCheckStatus ( ShapeExtend_DONE1 ) ||
1292 sae.FirstVertex (E2).IsSame (sae.LastVertex (E2)) ) {
1293 TopoDS_Edge tmpE1 = sbe.CopyReplaceVertices ( E1, TopoDS_Vertex(), V );
1294 sbwd->Set (tmpE1, n1 );
1295 if ( ! Context().IsNull() ) Context()->Replace(E1,tmpE1);
1299 if ( ! Context().IsNull() ) UpdateWire();
1301 return Standard_True;
1305 //=======================================================================
1306 //function : FixSeam
1308 //=======================================================================
1310 Standard_Boolean ShapeFix_Wire::FixSeam (const Standard_Integer num)
1312 myLastFixStatus = ShapeExtend::EncodeStatus ( ShapeExtend_OK );
1313 if ( ! IsReady() ) return Standard_False;
1315 Handle(Geom2d_Curve) C1, C2;
1316 Standard_Real cf, cl;
1317 if ( ! myAnalyzer->CheckSeam (num, C1, C2, cf, cl) ) return Standard_False;
1320 TopoDS_Edge E = WireData()->Edge ( num >0 ? num : NbEdges() );
1321 B.UpdateEdge (E, C2,C1, Face(), 0.); //:S4136: BRep_Tool::Tolerance(E)
1322 B.Range (E, Face(),cf,cl);
1323 myLastFixStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE1 );
1325 return Standard_True;
1328 //=======================================================================
1329 //function : FixShifted
1330 //purpose : fix parametric curves which may be shifted
1331 // to whole parametric range of closed surface as result of recomputing
1332 // from 3d representation.
1333 // This can be a curve on a seam or near it.
1334 // This function is to be called before FixDegenerated.
1335 // LIMITATION: this function cannot fix cases when, e.g., closed wire is
1336 // composed of two meridians of the sphere and one of them is seam.
1337 // NOTE: wire is supposed to be closed and sorted !
1338 //=======================================================================
1340 //:p4 abv 23.02.99: PRO9234 #15720: update UV points of edge
1341 static void UpdateEdgeUVPoints (TopoDS_Edge &E, const TopoDS_Face &F)
1343 Standard_Real first, last;
1344 BRep_Tool::Range ( E, F, first, last );
1345 BRep_Builder().Range ( E, F, first, last );
1349 //=======================================================================
1350 //function : FixShifted
1352 //=======================================================================
1354 Standard_Boolean ShapeFix_Wire::FixShifted()
1356 myLastFixStatus = ShapeExtend::EncodeStatus ( ShapeExtend_OK );
1357 if ( ! IsReady() ) return Standard_False;
1359 Handle(ShapeAnalysis_Surface) surf = myAnalyzer->Surface();
1360 //#78 rln 12.03.99 S4135: checking spatial closure with Precision
1361 Standard_Boolean uclosed = surf->IsUClosed(Precision());
1362 Standard_Boolean vclosed = surf->IsVClosed(Precision()) || surf->Surface()->IsKind (STANDARD_TYPE(Geom_SphericalSurface));
1363 //#67 rln 01.03.99 S4135: ims010.igs entity D11900 (2D contour is 2*PI higher than V range [-pi/2,p/2])
1365 // PTV 26.06.2002 begin
1366 // CTS18546-2.igs entity 2222: base curve is periodic and 2dcurve is shifted
1367 Standard_Boolean IsVCrvClosed = Standard_False;
1368 Standard_Real VRange = 1.;
1369 if (surf->Surface()->IsKind (STANDARD_TYPE(Geom_SurfaceOfRevolution))) {
1370 Handle(Geom_SurfaceOfRevolution) aSurOfRev = Handle(Geom_SurfaceOfRevolution)::DownCast(surf->Surface());
1371 Handle(Geom_Curve) aBaseCrv = aSurOfRev->BasisCurve();
1372 while ( (aBaseCrv->IsKind(STANDARD_TYPE(Geom_OffsetCurve))) ||
1373 (aBaseCrv->IsKind(STANDARD_TYPE(Geom_TrimmedCurve))) ) {
1374 if (aBaseCrv->IsKind(STANDARD_TYPE(Geom_OffsetCurve)))
1375 aBaseCrv = Handle(Geom_OffsetCurve)::DownCast(aBaseCrv)->BasisCurve();
1376 if (aBaseCrv->IsKind(STANDARD_TYPE(Geom_TrimmedCurve)))
1377 aBaseCrv = Handle(Geom_TrimmedCurve)::DownCast(aBaseCrv)->BasisCurve();
1379 if (aBaseCrv->IsPeriodic()) {
1380 vclosed = Standard_True;
1381 VRange = aBaseCrv->Period();
1382 IsVCrvClosed = Standard_True;
1384 cout << "Warning: ShapeFix_Wire::FixShifted set vclosed True for Surface of Revolution" << endl;
1388 // PTV 26.06.2002 end
1389 if ( ! uclosed && ! vclosed ) return Standard_False;
1391 Standard_Real URange, /*VRange,*/ SUF, SUL, SVF, SVL;
1392 surf->Surface()->Bounds ( SUF, SUL, SVF, SVL );
1393 Standard_Real SUMid, SVMid;
1394 SUMid = 0.5*(SUF+SUL);
1395 SVMid = 0.5*(SVF+SVL);
1396 if (uclosed) URange = Abs ( SUL - SUF );
1397 else URange = RealLast();
1398 if (!IsVCrvClosed) {
1399 if (vclosed) VRange = Abs ( SVL - SVF );
1400 else VRange = RealLast();
1402 Standard_Real UTol = 0.2 * URange, VTol = 0.2 * VRange;
1404 Handle(ShapeExtend_WireData) sbwdOring = WireData();
1405 ShapeAnalysis_Edge sae;
1406 Handle(ShapeExtend_WireData) sbwd = new ShapeExtend_WireData;
1407 for ( Standard_Integer i=1; i <= sbwdOring->NbEdges(); i++ ) {
1408 TopoDS_Edge E1 = sbwdOring->Edge ( i );
1409 if ( BRep_Tool::Degenerated(E1) && !sae.HasPCurve(E1,Face()))
1415 ShapeBuild_Edge sbe;
1416 Standard_Integer nb = sbwd->NbEdges();
1417 Standard_Boolean end = (nb == 0), degstop = Standard_False;;
1418 Standard_Integer stop = nb;
1419 Standard_Integer degn2 = 0;
1421 //pdn 17.12.98 r0901_ec 38237 to shift wire at 0
1423 //GeomAdaptor_Surface& GAS = myAnalyzer->Surface()->Adaptor3d()->ChangeSurface(); //SK
1425 for ( Standard_Integer n2=1, n1=nb; ! end; n1 = n2++ ) {
1426 if ( n2 > nb ) n2 = 1;
1427 if ( n2 == stop ) end = Standard_True;
1429 TopoDS_Edge E1 = sbwd->Edge ( n1 );
1430 TopoDS_Edge E2 = sbwd->Edge ( n2 );
1432 if ( BRep_Tool::Degenerated(E1) || BRep_Tool::Degenerated(E2) )
1437 degstop = Standard_True;
1442 TopoDS_Vertex V = sae.FirstVertex ( E2 );
1446 gp_Pnt p = BRep_Tool::Pnt ( V );
1448 Standard_Real a1 = 0., b1 = 0., a2 = 0., b2 = 0.;
1449 Handle(Geom2d_Curve) c2d1, c2d2;
1451 //:abv 29.08.01: torCuts.sat: distinguish degeneration by U and by V;
1452 // only corresponding move is prohibited
1453 // Standard_Boolean isDeg = surf->IsDegenerated ( p, Max ( Precision(), BRep_Tool::Tolerance(V) ) );
1454 Standard_Integer isDeg = 0;
1455 gp_Pnt2d degP1, degP2;
1456 Standard_Real degT1, degT2;
1457 if ( surf->DegeneratedValues ( p, Max ( Precision(), BRep_Tool::Tolerance(V) ),
1458 degP1, degP2, degT1, degT2 ) )
1459 isDeg = ( Abs ( degP1.X() - degP2.X() ) > Abs ( degP1.Y() - degP2.Y() ) ? 1 : 2 );
1461 // abv 23 Feb 00: UKI60107-6 210: additional check for near-degenerated case
1462 //smh#15 PRO19800. Check if the surface is surface of revolution.
1463 if (surf->Surface()->IsKind (STANDARD_TYPE(Geom_SurfaceOfRevolution))) {
1464 if ( ! isDeg && ! vclosed ) {
1465 if ( c2d1.IsNull() && ! sae.PCurve ( E1, Face(), c2d1, a1, b1, Standard_True ) ) continue;
1466 gp_Pnt2d p1 ( SUF, c2d1->Value(b1).Y() );
1467 gp_Pnt2d p2 ( SUL, c2d1->Value(b1).Y() );
1468 if ( surf->IsDegenerated ( p1, p2, MaxTolerance(), 10 ) &&
1469 ! surf->IsDegenerated ( c2d1->Value(a1), c2d1->Value(b1), MaxTolerance(), 10 ) ) // abv 31.07.00: trj4_pm1-ec-214.stp #31274: still allow work if edge already exists
1472 if ( ! isDeg && ! uclosed ) {
1473 if ( c2d1.IsNull() && ! sae.PCurve ( E1, Face(), c2d1, a1, b1, Standard_True ) ) continue;
1474 gp_Pnt2d p1 ( c2d1->Value(b1).X(), SVF );
1475 gp_Pnt2d p2 ( c2d1->Value(b1).X(), SVL );
1476 if ( surf->IsDegenerated ( p1, p2, MaxTolerance(), 10 ) &&
1477 ! surf->IsDegenerated ( c2d1->Value(a1), c2d1->Value(b1), MaxTolerance(), 10 ) ) // abv 31.07.00: trj4_pm1-ec-214.stp #31274: still allow work if edge already exists
1487 degstop = Standard_True;
1497 if ( pdeg.SquareDistance(p) < Precision() * Precision() )
1500 //if ( stop < n2 ) { stop = n2; degstop = Standard_True; }
1504 Standard_Real ax1 = 0., bx1 = 0., ax2 = 0., bx2 = 0.;
1505 Handle(Geom2d_Curve) cx1, cx2;
1506 if ( ( c2d1.IsNull() && ! sae.PCurve ( E1, Face(), c2d1, a1, b1, Standard_True ) ) ||
1507 ( c2d2.IsNull() && ! sae.PCurve ( E2, Face(), c2d2, a2, b2, Standard_True ) ) ||
1508 ! sae.PCurve ( sbwd->Edge ( degn2 >1 ? degn2-1 : nb ), Face(), cx1, ax1, bx1, Standard_True ) ||
1509 ! sae.PCurve ( sbwd->Edge ( degn2 ), Face(), cx2, ax2, bx2, Standard_True ) )
1511 myLastFixStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_FAIL1 );
1514 gp_Pnt2d pd1 = cx1->Value ( bx1 );
1515 gp_Pnt2d pd2 = cx2->Value ( ax2 );
1516 gp_Pnt2d pn1 = c2d1->Value ( b1 );
1517 gp_Pnt2d pn2 = c2d2->Value ( a2 );
1518 gp_Vec2d x(0.,0.); // shift vector
1519 Standard_Real period;
1520 if ( uclosed ) { x.SetX ( 1. ); period = URange; }
1521 else { x.SetY ( 1. ); period = VRange; }
1522 Standard_Real rot1 = ( pn1.XY() - pd2.XY() ) ^ x.XY();
1523 Standard_Real rot2 = ( pd1.XY() - pn2.XY() ) ^ x.XY();
1524 Standard_Real scld = ( pd2.XY() - pd1.XY() ) * x.XY();
1525 Standard_Real scln = ( pn2.XY() - pn1.XY() ) * x.XY();
1526 if ( rot1 * rot2 < -::Precision::PConfusion() &&
1527 scld * scln < -::Precision::PConfusion() &&
1528 Abs ( scln ) > 0.1 * period && Abs ( scld ) > 0.1 * period &&
1529 rot1 * scld > ::Precision::PConfusion() &&
1530 rot2 * scln > ::Precision::PConfusion() )
1532 // abv 02 Mar 00: trying more sophisticated analysis (ie_exhaust-A.stp #37520)
1533 Standard_Real sign = ( rot2 >0 ? 1. : -1. );
1534 Standard_Real deep1 = Min ( sign * ( pn2.XY() * x.XY() ),
1535 Min ( sign * ( pd1.XY() * x.XY() ),
1536 Min ( sign * ( c2d2->Value(b2 ).XY() * x.XY() ),
1537 Min ( sign * ( cx1->Value(ax1).XY() * x.XY() ),
1538 Min ( sign * ( c2d2->Value(0.5*(a2 +b2 )).XY() * x.XY() ),
1539 sign * ( cx1->Value(0.5*(ax1+bx1)).XY() * x.XY() ) ) ) ) ) );
1540 Standard_Real deep2 = Max ( sign * ( pn1.XY() * x.XY() ),
1541 Max ( sign * ( pd2.XY() * x.XY() ),
1542 Max ( sign * ( c2d1->Value(a1 ).XY() * x.XY() ),
1543 Max ( sign * ( cx2->Value(bx2).XY() * x.XY() ),
1544 Max ( sign * ( c2d1->Value(0.5*(a1 +b1 )).XY() * x.XY() ),
1545 sign * ( cx2->Value(0.5*(ax2+bx2)).XY() * x.XY() ) ) ) ) ) );
1546 Standard_Real deep = deep2 - deep1; // estimated current size of wire by x
1547 // pdn 30 Oct 00: trying correct period [0,period] (trj5_k1-tc-203.stp #4698)
1548 Standard_Real dx = ShapeAnalysis::AdjustToPeriod ( deep, ::Precision::PConfusion(), period+::Precision::PConfusion());
1549 x *= ( scld >0 ? -dx : dx );
1550 //x *= ( Abs(scld-scln) > 1.5 * period ? 2. : 1. ) *
1551 // ( scld >0 ? -period : period );
1553 Shift.SetTranslation ( x );
1554 for ( Standard_Integer k=degn2; ; k++ )
1556 if ( k > nb ) k = 1;
1557 if ( k == n2 ) break;
1558 TopoDS_Edge edge = sbwd->Edge ( k );
1559 if ( ! sae.PCurve ( edge, Face(), cx1, ax1, bx1, Standard_True ) ) continue;
1560 //cx1->Transform ( Shift );
1561 // skl 15.05.2002 for OCC208 (if few edges have reference to one pcurve)
1562 Handle(Geom2d_Curve) cx1new = Handle(Geom2d_Curve)::DownCast(cx1->Transformed(Shift));
1563 sbe.ReplacePCurve(edge,cx1new,Face());
1564 UpdateEdgeUVPoints ( edge, Face() );
1566 myLastFixStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE1 );
1568 cout << "Info: ShapeFix_Wire::FixShifted(): bi - meridian case fixed" << endl;
1572 //degn2 = n2; pdeg = p; // ie_exhaust-A.stp #37520
1576 // pdn to fix half sphere
1577 TopoDS_Vertex VE = sae.LastVertex ( E2 );
1578 gp_Pnt pe = BRep_Tool::Pnt ( VE );
1579 //pdn is second vertex on singular point ?
1580 if ( surf->IsDegenerated ( pe, Max ( Precision(), BRep_Tool::Tolerance(V) ) ) ) {
1581 if ( ( c2d1.IsNull() && ! sae.PCurve ( E1, Face(), c2d1, a1, b1, Standard_True ) ) ||
1582 ( c2d2.IsNull() && ! sae.PCurve ( E2, Face(), c2d2, a2, b2, Standard_True ) ) ) {
1583 myLastFixStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_FAIL1 );
1586 gp_Pnt2d p2d1 = c2d1->Value ( b1 ), p2f = c2d2->Value ( a2 ), p2l = c2d2->Value ( b2 );
1587 Standard_Real pres2 = ::Precision::PConfusion();
1588 Standard_Real du = 0.,dv = 0.;
1589 //#79 rln 15.03.99 S4135: bmarkmdl.igs entity 633 (incorrectly oriented contour) check for gap
1590 if(uclosed&&(Abs(p2f.X()-p2l.X())<pres2)&&Abs(p2d1.X()-p2f.X())>GAS.UResolution(Precision())) {
1591 if((Abs(p2f.X()-SUF)<pres2)&&(p2f.Y()<p2l.Y()))
1593 if((Abs(p2f.X()-SUL)<pres2)&&(p2f.Y()>p2l.Y()))
1596 if(vclosed&&(Abs(p2f.Y()-p2l.Y())<pres2)&&Abs(p2d1.Y()-p2f.Y())>GAS.VResolution(Precision())) {
1597 if((Abs(p2f.Y()-SVF)<pres2)&&(p2f.X()>p2l.X()))
1599 if((Abs(p2f.Y()-SVL)<pres2)&&(p2f.X()<p2l.X()))
1602 if ( du ==0. && dv == 0. ) continue;
1603 myLastFixStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE1 );
1605 Shift.SetTranslation ( gp_Vec2d ( du, dv ) );
1606 c2d2->Transform ( Shift );
1607 UpdateEdgeUVPoints ( E2, Face() );//rln 15.03.99 syntax correction :E1
1610 //:abv 29.08.01: torCuts.sat: continue;
1613 if ( ( c2d1.IsNull() && ! sae.PCurve ( E1, Face(), c2d1, a1, b1, Standard_True ) ) ||
1614 ( c2d2.IsNull() && ! sae.PCurve ( E2, Face(), c2d2, a2, b2, Standard_True ) ) ) {
1615 myLastFixStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_FAIL1 );
1618 gp_Pnt2d p2d1 = c2d1->Value ( b1 );
1619 gp_Pnt2d p2d2 = c2d2->Value ( a2 );
1622 Standard_Real du=0., dv=0.;
1623 if ( uclosed && isDeg != 1 ) {
1624 Standard_Real dx = Abs ( p2d2.X() - p2d1.X() );
1625 if ( dx > URange - UTol )
1626 du = ShapeAnalysis::AdjustByPeriod ( p2d2.X(), p2d1.X(), URange );
1627 else if ( dx > UTol && stop == nb ) stop = n2; //:abv 29.08.01: torCuts2.stp
1629 if ( vclosed && isDeg != 2 ) {
1630 Standard_Real dy = Abs ( p2d2.Y() - p2d1.Y() );
1631 if ( dy > VRange - VTol )
1632 dv = ShapeAnalysis::AdjustByPeriod ( p2d2.Y(), p2d1.Y(), VRange );
1633 else if ( dy > VTol && stop == nb ) stop = n2;
1635 if ( du ==0. && dv == 0. ) continue;
1637 myLastFixStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE1 );
1639 Shift.SetTranslation ( gp_Vec2d ( du, dv ) );
1640 //c2d2->Transform ( Shift );
1641 // skl 15.05.2002 for OCC208 (if few edges have reference to one pcurve)
1642 Handle(Geom2d_Curve) c2d2new = Handle(Geom2d_Curve)::DownCast(c2d2->Transformed(Shift));
1643 sbe.ReplacePCurve(E2,c2d2new,Face());
1644 UpdateEdgeUVPoints ( E2, Face() );
1646 if ( box.IsVoid() ) return Standard_False; //#3 smh 01.04.99. S4163: Overflow, when box is void.
1648 Standard_Real umin, vmin, umax, vmax;
1649 box.Get ( umin, vmin, umax, vmax );
1650 if ( Abs ( umin + umax - SUF - SUL ) < URange &&
1651 Abs ( vmin + vmax - SVF - SVL ) < VRange &&
1652 ! LastFixStatus ( ShapeExtend_DONE ) ) return Standard_False;
1655 Standard_Integer n; // svv Jan11 2000 : porting on DEC
1656 for ( n=1; n <= nb; n++ ) {
1658 Handle(Geom2d_Curve) c2d;
1659 if ( ! sae.PCurve ( sbwd->Edge(n), Face(), c2d, a, b, Standard_True ) ) continue;
1660 box.Add ( c2d->Value ( a ) );
1661 box.Add ( c2d->Value ( 0.5 * ( a + b ) ) );
1663 box.Get ( umin, vmin, umax, vmax );
1665 Standard_Real du=0., dv=0.;
1668 Standard_Real umid = 0.5 * ( umin + umax );
1669 // du = ShapeAnalysis::AdjustToPeriod(umid, SUF, SUL);
1670 // PTV 26.06.2002 xloop torus-apple iges face mode
1671 du = ShapeAnalysis::AdjustByPeriod(umid, SUMid, URange);
1674 Standard_Real vmid = 0.5 * ( vmin + vmax );
1675 // dv = ShapeAnalysis::AdjustToPeriod(vmid, SVF, SVL);
1676 // PTV 26.06.2002 xloop torus-apple iges face mode
1677 dv = ShapeAnalysis::AdjustByPeriod(vmid, SVMid, VRange);
1680 if ( du ==0. && dv == 0. ) return Standard_True;
1682 myLastFixStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE2 );
1685 Shift.SetTranslation ( gp_Vec2d ( du, dv ) );
1687 for ( n=1; n <= sbwdOring->NbEdges(); n++ ) {
1689 Handle(Geom2d_Curve) c2d;
1690 TopoDS_Edge ed = sbwdOring->Edge(n);
1691 if ( ! sae.PCurve ( ed, Face(), c2d, a, b, Standard_True ) ) continue;
1692 // skl 15.05.2002 for OCC208 (if few edges have reference to one pcurve)
1693 Handle(Geom2d_Curve) c2d2 = Handle(Geom2d_Curve)::DownCast(c2d->Transformed(Shift));
1694 sbe.ReplacePCurve(ed,c2d2,Face());
1695 UpdateEdgeUVPoints ( ed, Face() );
1697 return Standard_True;
1700 //=======================================================================
1701 //function : FixDegenerated
1703 //=======================================================================
1705 Standard_Boolean ShapeFix_Wire::FixDegenerated (const Standard_Integer num)
1707 myLastFixStatus = ShapeExtend::EncodeStatus ( ShapeExtend_OK );
1708 if ( ! IsReady() ) return Standard_False;
1711 gp_Pnt2d p2d1, p2d2;
1712 myAnalyzer->CheckDegenerated ( num, p2d1, p2d2 );
1713 if ( myAnalyzer->LastCheckStatus ( ShapeExtend_FAIL1 ) ) {
1714 myLastFixStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_FAIL1 );
1716 //: abv 29.08.01: torHalf2.sat: if edge was encoded as degenerated but
1717 // has no pcurve and no singularity is found at that point, remove it
1718 if ( myAnalyzer->LastCheckStatus ( ShapeExtend_FAIL2 ) ) {
1719 WireData()->Remove ( num );
1720 myLastFixStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE3 );
1721 return Standard_True;
1723 if ( ! myAnalyzer->LastCheckStatus ( ShapeExtend_DONE ) ) return Standard_False;
1725 // action: create degenerated edge and insert it (or replace)
1727 gp_Vec2d vect2d ( p2d1, p2d2 );
1728 gp_Dir2d dir2d ( vect2d );
1729 Handle(Geom2d_Line) line2d = new Geom2d_Line ( p2d1, dir2d );
1731 TopoDS_Edge degEdge;
1733 B.MakeEdge ( degEdge );
1734 B.Degenerated ( degEdge, Standard_True );
1735 B.UpdateEdge ( degEdge, line2d, Face(), ::Precision::Confusion() );
1736 B.Range ( degEdge, Face(), 0., vect2d.Magnitude() );
1738 Handle(ShapeExtend_WireData) sbwd = WireData();
1739 Standard_Integer n2 = ( num >0 ? num : sbwd->NbEdges() );
1740 Standard_Integer n1 = ( n2 >1 ? n2-1 : sbwd->NbEdges() );
1742 Standard_Boolean lack = myAnalyzer->LastCheckStatus ( ShapeExtend_DONE1 );
1743 Standard_Integer n3 = ( lack ? n2 : ( n2 < sbwd->NbEdges() ? n2+1 : 1 ) );
1745 ShapeAnalysis_Edge sae;
1746 TopoDS_Vertex V1 = sae.LastVertex ( sbwd->Edge ( n1 ) );
1747 TopoDS_Vertex V2 = sae.FirstVertex ( sbwd->Edge ( n3 ) );
1749 V1.Orientation(TopAbs_FORWARD);
1750 V2.Orientation(TopAbs_REVERSED);
1753 degEdge.Orientation(TopAbs_FORWARD);
1756 sbwd->Add ( degEdge, n2 );
1757 myLastFixStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE1 );
1760 sbwd->Set ( degEdge, n2 );
1761 myLastFixStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE2 );
1764 // commented to avoid extra messages
1765 // SendWarning ( degEdge, Message_Msg ( "FixWire.FixDegenerated.MSG0" ) );// Degenerated edge(s) detected
1767 return Standard_True;
1770 //=======================================================================
1771 //function : FixSelfIntersectingEdge
1772 //purpose : Tests edge for self-intersection and updates tolerance of vertex
1773 // if intersection is found
1774 // Returns True if tolerance was increased
1775 //=======================================================================
1777 // Create edge on basis of E with new pcurve and call FixSP
1778 // Return resulting tolerance and modified pcurve
1779 static Standard_Boolean TryNewPCurve (const TopoDS_Edge &E, const TopoDS_Face &face,
1780 Handle(Geom2d_Curve) &c2d,
1781 Standard_Real &first,
1782 Standard_Real &last,
1786 Handle(Geom_Curve) crv = BRep_Tool::Curve ( E, f, l );
1787 if ( crv.IsNull() ) return Standard_False;
1789 // make temp edge and compute tolerance
1790 BRepBuilderAPI_MakeEdge mkedge ( crv, f, l );
1792 ShapeBuild_Edge SBE; //skl 17.07.2001
1793 SBE.SetRange3d(mkedge,f,l); //skl 17.07.2001
1795 if ( ! mkedge.IsDone() ) return Standard_False;
1797 TopoDS_Edge edge = mkedge;
1799 B.UpdateEdge ( edge, c2d, face, 0. );
1800 B.Range ( edge, face, first, last );
1801 B.SameRange ( edge, Standard_False );
1802 // no call to BRepLib: B.SameParameter ( edge, Standard_False );
1804 Handle(ShapeFix_Edge) sfe = new ShapeFix_Edge;
1805 sfe->FixSameParameter ( edge, face );
1806 c2d = BRep_Tool::CurveOnSurface ( edge, face, first, last );
1807 tol = BRep_Tool::Tolerance ( edge );
1808 return Standard_True;
1811 //:k3 abv 24 Dec 98: BUC50070 #26682 and #30087:
1812 // Try to cut out the loop on the pcurve and make new pcurve by concatenating
1814 // If result is not SameParameter with prec, does nothing and returns False
1815 // Warning: resulting pcurve will be C0
1817 //=======================================================================
1818 //function : howMuchPCurves
1820 //=======================================================================
1821 static Standard_Integer howMuchPCurves (const TopoDS_Edge &E)
1823 Standard_Integer count = 0;
1824 BRep_ListIteratorOfListOfCurveRepresentation itcr
1825 ((*((Handle(BRep_TEdge)*)&E.TShape()))->ChangeCurves());
1827 while (itcr.More()) {
1828 const Handle(BRep_CurveRepresentation)& cr = itcr.Value();
1829 if ( cr->IsCurveOnSurface() )
1838 //=======================================================================
1839 //function : RemoveLoop
1841 //=======================================================================
1842 static Standard_Boolean RemoveLoop (TopoDS_Edge &E, const TopoDS_Face &face,
1843 const IntRes2d_IntersectionPoint &IP,
1844 const Standard_Real tolfact,
1845 const Standard_Real prec,
1846 const Standard_Boolean RemoveLoop3d)
1848 Standard_Boolean loopRemoved3d;
1849 if ( BRep_Tool::IsClosed ( E, face ) ) return Standard_False;
1852 Handle(Geom_Curve) crv = BRep_Tool::Curve ( E, f, l );
1854 Standard_Real t1 = IP.ParamOnFirst();
1855 Standard_Real t2 = IP.ParamOnSecond();
1856 if ( t1 > t2 ) { Standard_Real t = t1; t1 = t2; t2 = t; }
1858 ShapeAnalysis_Edge sae;
1860 Handle(Geom2d_Curve) c2d;
1861 if ( ! sae.PCurve ( E, face, c2d, a, b, Standard_False ) )
1862 return Standard_False;
1865 cout << "Cut Loop: params (" << t1 << ", " << t2;
1867 GeomAdaptor_Curve GAC ( crv, f, l );
1868 Standard_Real dt = tolfact * GAC.Resolution(prec);
1869 t1 -= dt; //1e-3;//::Precision::PConfusion();
1870 t2 += dt; //1e-3;//::Precision::PConfusion();
1872 cout << ") -> (" << t1 << ", " << t2 << ")" << endl;
1875 if ( t1 <= a || t2 >= b ) { // should not be so, but to be sure ..
1876 return Standard_False;
1879 // direct construction causes error on osf system.
1886 Handle(Geom_Plane) aPlaneSurf = Handle(Geom_Plane)::DownCast( BRep_Tool::Surface(face) );
1887 Handle(Geom_Curve) pcurve3d = crv;
1888 if ( !aPlaneSurf.IsNull() ) {
1889 Pln = aPlaneSurf->Pln();
1892 pcurve3d = GeomAPI::To3d ( c2d, Pln );
1895 //Handle(Geom_Curve) pcurve3d = GeomAPI::To3d ( c2d, Pln );
1896 Handle(Geom_TrimmedCurve) trim = new Geom_TrimmedCurve (pcurve3d, a, t1);
1897 GeomConvert_CompCurveToBSplineCurve connect ( trim );
1899 // null-length segment patch instead of loop
1900 TColgp_Array1OfPnt Poles(1,2);
1901 TColStd_Array1OfReal Knots(1,2);
1902 TColStd_Array1OfInteger Mults(1,2);
1904 Poles.SetValue(1,trim->Value(t1));
1905 Knots.SetValue(1,t1);
1906 Mults.SetValue(1,2);
1908 trim = new Geom_TrimmedCurve (pcurve3d, t2, b);
1909 Poles.SetValue(2,trim->Value(t2));
1910 Knots.SetValue(2,t2);
1911 Mults.SetValue(2,2);
1913 Handle(Geom_BSplineCurve) patch = new Geom_BSplineCurve ( Poles, Knots, Mults, 1 );
1914 if ( ! connect.Add (patch, ::Precision::PConfusion(), Standard_True, Standard_False) )
1915 return Standard_False;
1918 if ( ! connect.Add (trim, ::Precision::PConfusion(), Standard_True, Standard_False) )
1919 return Standard_False;
1921 // keep created 3d curve
1922 Handle(Geom_Curve) aNew3dCrv = connect.BSplineCurve();
1925 Handle(Geom2d_Curve) bs = GeomAPI::To2d ( aNew3dCrv, Pln );
1926 if ( bs.IsNull() ) return Standard_False;
1928 // make temp edge and compute tolerance
1931 if(!RemoveLoop3d) { // old variant (not remove loop 3d)
1932 Standard_Real newtol=0;
1934 Standard_Integer nbC2d = howMuchPCurves( E );
1935 if ( nbC2d <= 1 && !aPlaneSurf.IsNull() )
1936 B.UpdateEdge ( E, bs, face, 0 );
1938 if ( ! TryNewPCurve ( E, face, bs, a, b, newtol ) ) return Standard_False;
1940 Standard_Real tol = BRep_Tool::Tolerance ( E );
1942 cout << "Cut Loop: tol orig " << tol << ", prec " << prec << ", new tol " << newtol << endl;
1944 if ( newtol > Max ( prec, tol ) ) return Standard_False;
1945 //:s2 bs = BRep_Tool::CurveOnSurface ( edge, face, a, b );
1946 if ( Abs ( a - f ) > ::Precision::PConfusion() || // smth strange, cancel
1947 Abs ( b - l ) > ::Precision::PConfusion() ) return Standard_False;
1949 if ( !aPlaneSurf.IsNull() ) {
1950 B.UpdateEdge ( E, aNew3dCrv, Max (newtol, tol) );
1952 if ( ! TryNewPCurve ( E, face, bs, a, b, newtol ) ) return Standard_False;
1954 B.UpdateEdge ( E, bs, face, newtol );
1955 B.UpdateVertex ( sae.FirstVertex ( E ), newtol );
1956 B.UpdateVertex ( sae.LastVertex ( E ), newtol );
1957 return Standard_True;
1962 Handle(Geom_Surface) S = BRep_Tool::Surface(face, L);
1963 Handle(Geom2dAdaptor_HCurve) AC = new Geom2dAdaptor_HCurve(c2d);
1964 Handle(GeomAdaptor_HSurface) AS = new GeomAdaptor_HSurface(S);
1966 Adaptor3d_CurveOnSurface ACS(AC,AS);
1967 gp_Pnt P1(ACS.Value(t1));
1968 gp_Pnt P2(ACS.Value(t2));
1969 gp_Pnt pcurPnt((P1.X()+P2.X())/2,(P1.Y()+P2.Y())/2,(P1.Z()+P2.Z())/2);
1971 ShapeAnalysis_TransferParametersProj SFTP(E,face);
1972 Handle(TColStd_HSequenceOfReal) Seq2d = new TColStd_HSequenceOfReal;
1975 Seq2d->Append((t1+t2)/2);
1976 Handle(TColStd_HSequenceOfReal) Seq3d = SFTP.Perform(Seq2d,Standard_False);
1978 Standard_Real dist1 = pcurPnt.Distance(crv->Value(Seq3d->Value(1)));// correting Seq3d already project
1979 Standard_Real dist2 = pcurPnt.Distance(crv->Value(Seq3d->Value(2)));
1980 Standard_Real dist3 = pcurPnt.Distance(crv->Value(Seq3d->Value(3)));
1981 Standard_Real ftrim,ltrim;
1982 if(dist3>Max(dist1,dist2)) {
1983 loopRemoved3d = Standard_False;
1986 loopRemoved3d = Standard_True;
1989 Handle(Geom_Curve) bs1;
1991 if (!loopRemoved3d) {
1992 // create new 3d curve
1993 ftrim = Seq3d->Value(1);
1994 ltrim = Seq3d->Value(2);
1997 Handle(Geom_TrimmedCurve) trim1 = new Geom_TrimmedCurve (crv, f, ftrim);
1998 GeomConvert_CompCurveToBSplineCurve connect1 ( trim1 );
1999 TColgp_Array1OfPnt Poles1(1,2);
2000 TColStd_Array1OfReal Knots1(1,2);
2001 TColStd_Array1OfInteger Mults1(1,2);
2003 Poles1.SetValue(1,trim1->Value(ftrim));
2004 Knots1.SetValue(1,ftrim);
2005 Mults1.SetValue(1,2);
2007 trim1 = new Geom_TrimmedCurve (crv, ltrim, l);
2008 Poles1.SetValue(2,trim1->Value(ltrim));
2009 Knots1.SetValue(2,ltrim);
2010 Mults1.SetValue(2,2);
2012 // create b-spline curve
2013 Handle(Geom_BSplineCurve) patch1 = new Geom_BSplineCurve ( Poles1, Knots1, Mults1, 1 );
2015 if ( ! connect1.Add (patch1, ::Precision::PConfusion(), Standard_True, Standard_False) )
2016 return Standard_False;
2019 if ( ! connect1.Add (trim1, ::Precision::PConfusion(), Standard_True, Standard_False) )
2020 return Standard_False;
2022 bs1 = connect1.BSplineCurve();
2025 return Standard_False;
2027 // Standard_Real oldtol = BRep_Tool::Tolerance ( E );
2030 B.UpdateEdge ( E, bs1, L, 0. );
2031 B.UpdateEdge ( E, bs, face, 0. );
2032 B.Range ( E, face, f, l );
2033 B.SameRange ( E, Standard_False );
2035 Handle(ShapeFix_Edge) sfe = new ShapeFix_Edge;
2036 sfe->FixSameParameter ( E );
2038 return Standard_True;
2041 //=======================================================================
2042 //function : RemoveLoop
2044 //=======================================================================
2045 static Standard_Boolean RemoveLoop (TopoDS_Edge &E, const TopoDS_Face &face,
2046 const IntRes2d_IntersectionPoint &IP2d,
2051 cout<<"Info: ShapeFix_Wire::FixSelfIntersection : Try insert vertex"<<endl;
2054 if ( BRep_Tool::IsClosed ( E, face ) ) return Standard_False;
2057 Handle(Geom_Curve) crv = BRep_Tool::Curve ( E, f, l );
2059 Standard_Real t1 = IP2d.ParamOnFirst();
2060 Standard_Real t2 = IP2d.ParamOnSecond();
2064 Standard_Real t = t1; t1 = t2; t2 = t;
2067 ShapeAnalysis_Edge sae;
2069 // define vertexes Vfirst , Vlast, Vmid
2070 TopoDS_Vertex Vfirst,Vlast,Vmid;
2071 // initialize Vfirst and Vlast
2072 Vfirst = sae.FirstVertex(E);
2073 Vlast = sae.LastVertex(E);
2075 // find a 2d curve and parameters from edge E
2077 Handle (Geom2d_Curve) c2d;
2078 if ( ! sae.PCurve ( E, face, c2d, a, b, Standard_False ) )
2079 return Standard_False;
2081 // first segment for 2d curve
2082 Handle(Geom2d_TrimmedCurve) trim1;
2083 if( (t1-a)>Precision::PConfusion() )
2084 trim1 = new Geom2d_TrimmedCurve (c2d, a, t1);
2085 // second segment for 2d curve
2086 Handle(Geom2d_TrimmedCurve) trim2 = new Geom2d_TrimmedCurve (c2d, t2, b);
2088 // if ( trim1.IsNull() || trim2.IsNull() )
2090 return Standard_False;
2093 Handle (Geom_Surface) S = BRep_Tool::Surface(face, L);
2094 Handle (Geom2dAdaptor_HCurve) AC = new Geom2dAdaptor_HCurve(c2d);
2095 Handle (GeomAdaptor_HSurface) AS = new GeomAdaptor_HSurface(S);
2097 Adaptor3d_CurveOnSurface ACS(AC,AS);
2098 gp_Pnt P1(ACS.Value(t1));
2099 gp_Pnt P2(ACS.Value(t2));
2100 gp_Pnt pcurPnt((P1.X()+P2.X())/2,(P1.Y()+P2.Y())/2,(P1.Z()+P2.Z())/2);
2102 // transfer parameters from pcurve to 3d curve
2103 ShapeAnalysis_TransferParametersProj SFTP(E,face);
2104 Handle (TColStd_HSequenceOfReal) Seq2d = new TColStd_HSequenceOfReal;
2107 Seq2d->Append((t1+t2)/2);
2108 Handle (TColStd_HSequenceOfReal) Seq3d = SFTP.Perform(Seq2d,Standard_False);
2110 Standard_Real dist1 = pcurPnt.Distance(crv->Value(Seq3d->Value(1)));// correting Seq3d already project
2111 Standard_Real dist2 = pcurPnt.Distance(crv->Value(Seq3d->Value(2)));
2112 Standard_Real dist3 = pcurPnt.Distance(crv->Value(Seq3d->Value(3)));
2113 Standard_Real ftrim,ltrim;
2114 if ( dist3 > Max(dist1, dist2)) { // is loop in 3d
2115 ftrim = Seq3d->Value(1);
2116 ltrim = Seq3d->Value(2);
2118 else { // not loop in 3d
2119 ftrim = Seq3d->Value(3);
2120 ltrim = Seq3d->Value(3);
2123 // ftrim = Seq3d->Value(1);
2124 // ltrim = Seq3d->Value(2);
2126 // trim for 3d curve 'crv' with parameters from 'f' to 'l'
2127 Handle(Geom_TrimmedCurve) trim3;
2129 trim3 = new Geom_TrimmedCurve (crv, f, ftrim);
2130 // second segment for 3d curve
2131 Handle(Geom_TrimmedCurve) trim4 = new Geom_TrimmedCurve (crv, ltrim, l);
2133 // if ( trim3.IsNull() || trim4.IsNull() )
2135 return Standard_False;
2137 // create a point for middle vertex
2138 gp_Pnt pnt1 = crv->Value(ftrim);
2139 gp_Pnt pnt2 = crv->Value(ltrim);
2140 gp_Pnt Pmid((pnt1.X()+pnt2.X())/2,(pnt1.Y()+pnt2.Y())/2,(pnt1.Z()+pnt2.Z())/2);
2144 // create new copies for E1 and E2
2146 E1=TopoDS::Edge(E.EmptyCopied());
2147 E2=TopoDS::Edge(E.EmptyCopied());
2149 // initialize middle vertex Vmid
2151 B.MakeVertex(Vmid, pnt2, 0.);
2153 B.MakeVertex(Vmid, Pmid, 0.);
2155 ShapeBuild_Edge sbe;
2157 // replace verteces for new edges E1 and E2
2158 if (E.Orientation()== TopAbs_FORWARD)
2161 E1=sbe.CopyReplaceVertices(E1,Vfirst,Vmid);
2162 E2=sbe.CopyReplaceVertices(E2,Vmid, Vlast);
2167 E1=sbe.CopyReplaceVertices(E1,Vmid, Vlast);
2168 E2=sbe.CopyReplaceVertices(E2,Vfirst, Vmid);
2171 // Update edges by 2d and 3d curves
2172 Handle(ShapeFix_Edge) mySfe = new ShapeFix_Edge;
2174 B.UpdateEdge(E1, trim1, face, 0.);
2175 B.UpdateEdge(E1, trim3, 0.);
2176 B.Range(E1, f, ftrim);
2177 B.SameRange(E1,Standard_False);
2178 // B.SameParameter(E1,Standard_False);
2179 mySfe->FixSameParameter(E1);
2180 mySfe->FixVertexTolerance(E1);
2182 B.UpdateEdge(E2, trim2, face, 0.);
2183 B.UpdateEdge(E2, trim4, 0.);
2184 B.Range ( E2,ltrim,l );
2185 B.SameRange(E2, Standard_False );
2186 // B.SameParameter(E2, Standard_False);
2187 mySfe->FixSameParameter(E2);
2188 mySfe->FixVertexTolerance(E2);
2190 return Standard_True;
2194 //=======================================================================
2195 //function : FixSelfIntersectingEdge
2197 //=======================================================================
2199 Standard_Boolean ShapeFix_Wire::FixSelfIntersectingEdge (const Standard_Integer num)
2201 myLastFixStatus = ShapeExtend::EncodeStatus ( ShapeExtend_OK );
2202 if ( ! IsReady() ) return Standard_False;
2205 IntRes2d_SequenceOfIntersectionPoint points2d;
2206 TColgp_SequenceOfPnt points3d;
2207 Handle(ShapeAnalysis_Wire) theAdvAnalyzer = myAnalyzer;
2208 if (theAdvAnalyzer.IsNull()) return Standard_False;
2209 theAdvAnalyzer->CheckSelfIntersectingEdge ( num, points2d, points3d );
2210 if ( theAdvAnalyzer->LastCheckStatus ( ShapeExtend_FAIL ) ) {
2211 myLastFixStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_FAIL1 );
2213 if ( ! theAdvAnalyzer->LastCheckStatus ( ShapeExtend_DONE ) ) return Standard_False;
2215 // action: increase tolerance of vertex
2217 TopoDS_Edge E = WireData()->Edge ( num >0 ? num : NbEdges() );
2219 ShapeAnalysis_Edge sae;
2220 TopoDS_Vertex V1 = sae.FirstVertex ( E );
2221 TopoDS_Vertex V2 = sae.LastVertex ( E );
2222 Standard_Real tol1 = BRep_Tool::Tolerance ( V1 );
2223 Standard_Real tol2 = BRep_Tool::Tolerance ( V2 );
2224 gp_Pnt pnt1 = BRep_Tool::Pnt ( V1 );
2225 gp_Pnt pnt2 = BRep_Tool::Pnt ( V2 );
2227 // cycle is to verify fix in case of RemoveLoop
2228 Standard_Real tolfact = 0.1; // factor for shifting by parameter in RemoveLoop
2229 Standard_Real f2d = 0., l2d = 0.;
2230 Handle(Geom2d_Curve) c2d;
2231 Standard_Real newtol=0.; // = Precision();
2233 if (myRemoveLoopMode<1) {
2234 for ( Standard_Integer iter=0; iter < 30; iter++ ) {
2235 Standard_Boolean loopRemoved = Standard_False;;
2236 Standard_Real prevFirst = 0 , prevLast = 0;
2237 for ( Standard_Integer i=1; i<=points2d.Length(); i++ ) {
2238 gp_Pnt pint = points3d.Value(i);
2239 Standard_Real dist21 = pnt1.SquareDistance ( pint );
2240 Standard_Real dist22 = pnt2.SquareDistance ( pint );
2241 if ( dist21 < tol1 * tol1 || dist22 < tol2 * tol2 ) continue;
2242 newtol = 1.001 * Sqrt ( Min ( dist21, dist22 ) ); //:f8
2244 //:k3 abv 24 Dec 98: BUC50070 #26682 and #30087: try to remove loop
2247 sae.PCurve ( E, Face(), c2d, f2d, l2d, Standard_False );
2248 Standard_Real firstpar = points2d.Value(i).ParamOnFirst();
2249 Standard_Real lastpar = points2d.Value(i).ParamOnSecond();
2250 if(firstpar > prevFirst && lastpar < prevLast) continue;
2251 if ( RemoveLoop (E, Face(), points2d.Value(i), tolfact,
2252 Min( MaxTolerance(), Max(newtol,Precision()) ),
2253 myRemoveLoopMode==0 ) ) {
2254 myLastFixStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE4 );
2255 loopRemoved = Standard_True;
2256 prevFirst = firstpar;
2258 continue; // repeat of fix on that edge required (to be done by caller)
2261 if ( newtol < MaxTolerance() ) {
2262 myLastFixStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE1 );
2264 if ( dist21 < dist22 ) B.UpdateVertex ( V1, tol1 = newtol );
2265 else B.UpdateVertex ( V2, tol2 = newtol );
2267 else myLastFixStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_FAIL2 );
2270 // after RemoveLoop, check that self-intersection disappeared
2271 if ( loopRemoved ) {
2272 IntRes2d_SequenceOfIntersectionPoint pnts2d;
2273 TColgp_SequenceOfPnt pnts3d;
2274 theAdvAnalyzer->CheckSelfIntersectingEdge ( num, pnts2d, pnts3d );
2275 if ( ! theAdvAnalyzer->LastCheckStatus ( ShapeExtend_DONE ) ) break;
2276 //points3d.Append(pnts3d);
2277 //points2d.Append(pnts2d);
2281 B.UpdateEdge ( E, c2d, Face(), 0. );
2282 B.Range ( E, Face(), f2d, l2d );
2283 //newtol+=Precision();
2291 //===============================================
2292 // RemoveLoopMode = 1 , insert vertex
2293 //===============================================
2294 if (myRemoveLoopMode == 1) {
2295 // after fixing will be nb+1 edges
2296 Standard_Boolean loopRemoved;
2297 // create a sequence of resulting edges
2298 Handle (TopTools_HSequenceOfShape) TTSS = new TopTools_HSequenceOfShape;
2301 loopRemoved = Standard_False;
2302 //:k3 abv 24 Dec 98: BUC50070 #26682 and #30087: try to remove loop
2305 sae.PCurve ( E, Face(), c2d, f2d, l2d, Standard_False );
2307 if ( RemoveLoop (E, Face(), points2d.Value(1),E1,E2) ) {
2308 myLastFixStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE4 );
2309 loopRemoved = Standard_True;
2312 newtol = Max(BRep_Tool::Tolerance(E1),BRep_Tool::Tolerance(E2));
2315 newtol = BRep_Tool::Tolerance(E2);
2321 if ( newtol > MaxTolerance() )
2322 myLastFixStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_FAIL2 );
2324 ShapeExtend_WireData sewd;
2325 for (Standard_Integer i=1 ; i <= TTSS->Length(); i++) {
2326 sewd.Add(TopoDS::Edge(TTSS->Value(i)));
2328 if (! Context().IsNull()) {
2329 Context()->Replace ( E, sewd.Wire() );
2333 WireData()->Remove(num >0 ? num : NbEdges());
2334 WireData()->Add(sewd.Wire(), num >0 ? num : NbEdges());
2337 myLastFixStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE8 );
2341 if ( LastFixStatus ( ShapeExtend_DONE ) && ! myShape.IsNull() ) {
2342 SendWarning ( E, Message_Msg ( "FixAdvWire.FixIntersection.MSG5" ) );// Edge was self-intersecting, corrected
2345 return LastFixStatus ( ShapeExtend_DONE );
2349 //=======================================================================
2350 //function : ComputeLocalDeviation
2351 //purpose : auxilary
2352 //=======================================================================
2353 static Standard_Real ComputeLocalDeviation (const TopoDS_Edge &edge,
2354 const gp_Pnt &pint,const gp_Pnt &pnt,
2355 Standard_Real f, Standard_Real l,
2356 const TopoDS_Face &face )
2358 ShapeAnalysis_Edge sae;
2359 Handle(Geom_Curve) c3d;
2361 if ( ! sae.Curve3d ( edge, c3d, a, b, Standard_False ) ) return RealLast();
2363 gp_Lin line ( pint, gp_Vec ( pint, pnt ) );
2365 Handle(Geom2d_Curve) Crv;
2366 Standard_Real fp,lp;
2367 if ( sae.PCurve(edge,face,Crv,fp,lp,Standard_False) ) {
2368 if(Crv->IsKind(STANDARD_TYPE(Geom2d_TrimmedCurve))) {
2369 Handle(Geom2d_TrimmedCurve) tc = Handle(Geom2d_TrimmedCurve)::DownCast(Crv);
2370 if(tc->BasisCurve()->IsKind(STANDARD_TYPE(Geom2d_Line))) {
2371 f = a + (f-fp)*(b-a)/(lp-fp);
2372 l = a + (l-fp)*(b-a)/(lp-fp);
2377 const Standard_Integer NSEG = 10;
2378 Standard_Real step = ( l - f ) / NSEG;
2379 Standard_Real dev = 0.;
2380 for ( Standard_Integer i=1; i < NSEG; i++ ) {
2381 gp_Pnt p = c3d->Value ( f + i * step );
2382 Standard_Real d = line.Distance ( p );
2383 if ( dev < d ) dev = d;
2388 //=======================================================================
2389 //function : FixIntersectingEdges
2391 //=======================================================================
2393 Standard_Boolean ShapeFix_Wire::FixIntersectingEdges (const Standard_Integer num)
2395 myLastFixStatus = ShapeExtend::EncodeStatus ( ShapeExtend_OK );
2396 if ( ! IsReady() || NbEdges() <2 ) return Standard_False;
2399 IntRes2d_SequenceOfIntersectionPoint points2d;
2400 TColgp_SequenceOfPnt points3d;
2401 TColStd_SequenceOfReal errors;
2402 Handle(ShapeAnalysis_Wire) theAdvAnalyzer = myAnalyzer;
2403 if (theAdvAnalyzer.IsNull()) return Standard_False;
2404 theAdvAnalyzer->CheckIntersectingEdges ( num, points2d, points3d, errors );
2405 if ( theAdvAnalyzer->LastCheckStatus ( ShapeExtend_FAIL ) ) {
2406 myLastFixStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_FAIL1 );
2408 if ( ! theAdvAnalyzer->LastCheckStatus ( ShapeExtend_DONE ) ) return Standard_False;
2410 //rln 03/02/98: CSR#BUC50004 entity 56 (to avoid later inserting lacking edge)
2411 //:l0 Standard_Boolean isLacking = myAnalyzer->CheckLacking ( num );
2413 // action: increase tolerance of vertex
2415 Handle(ShapeExtend_WireData) sbwd = WireData();
2416 Standard_Integer n2 = ( num >0 ? num : sbwd->NbEdges() );
2417 Standard_Integer n1 = ( n2 >1 ? n2-1 : sbwd->NbEdges() );
2418 TopoDS_Edge E1 = sbwd->Edge(n1);
2419 TopoDS_Edge E2 = sbwd->Edge(n2);
2420 if ( !Context().IsNull() )
2422 E1 = TopoDS::Edge(Context()->Apply(sbwd->Edge(n1)));
2423 E2 = TopoDS::Edge(Context()->Apply(sbwd->Edge(n2)));
2426 Standard_Boolean isForward1 = ( E1.Orientation() == TopAbs_FORWARD );
2427 Standard_Boolean isForward2 = ( E2.Orientation() == TopAbs_FORWARD );
2428 Standard_Real a1, b1, a2, b2;
2429 BRep_Tool::Range ( E1, Face(), a1, b1 );
2430 BRep_Tool::Range ( E2, Face(), a2, b2 );
2432 ShapeAnalysis_Edge sae;
2433 TopoDS_Vertex Vp = sae.FirstVertex ( E1 );
2434 TopoDS_Vertex V1 = sae.LastVertex ( E1 );
2435 TopoDS_Vertex V2 = sae.FirstVertex ( E2 );
2436 TopoDS_Vertex Vn = sae.LastVertex ( E2 );
2438 Standard_Real tol = BRep_Tool::Tolerance ( V1 );
2439 gp_Pnt pnt = BRep_Tool::Pnt ( V1 );
2441 Standard_Real prevRange1 = RealLast(), prevRange2 = RealLast();
2442 Standard_Boolean cutEdge1 = Standard_False, cutEdge2 = Standard_False;
2443 Standard_Boolean IsCutLine = Standard_False;
2444 Standard_Boolean isChangedEdge = Standard_False;
2448 Standard_Integer nb = points3d.Length();
2449 for ( Standard_Integer i=1; i <= nb; i++ ) {
2450 const IntRes2d_IntersectionPoint &IP = points2d.Value(i);
2451 Standard_Real param1 = ( num ==1 ? IP.ParamOnSecond() : IP.ParamOnFirst() );
2452 Standard_Real param2 = ( num ==1 ? IP.ParamOnFirst() : IP.ParamOnSecond() );
2454 Standard_Real newRange1 = Abs ( ( isForward1 ? a1 : b1 ) - param1 );
2455 Standard_Real newRange2 = Abs ( ( isForward2 ? b2 : a2 ) - param2 );
2456 if ( newRange1 > prevRange1 && newRange2 > prevRange2 ) continue;
2458 gp_Pnt pint = points3d.Value(i);
2459 Standard_Real rad = errors.Value(i);
2460 Standard_Real newtol = 1.0001 * ( pnt.Distance ( pint ) + rad );
2462 //GeomAdaptor_Surface& Ads = myAnalyzer->Surface()->Adaptor3d()->ChangeSurface();
2464 //:r8 abv 12 Apr 99: try increasing tolerance of edge
2466 Standard_Boolean locMayEdit = myTopoMode;
2467 // Always try to modify the tolerance firstly as a better solution
2468 if ( /*! myTopoMode &&*/ newtol > tol )
2470 Standard_Real te1 = rad + ComputeLocalDeviation (E1, pint, pnt,
2471 param1, ( isForward1 ? b1 : a1 ), Face() );
2472 Standard_Real te2 = rad + ComputeLocalDeviation (E2, pint, pnt,
2473 ( isForward2 ? a2 : b2 ), param2, Face() );
2474 Standard_Real maxte = Max ( te1, te2 );
2475 if ( maxte < MaxTolerance() && maxte < newtol )
2477 if ( BRep_Tool::Tolerance(E1) < te1 || BRep_Tool::Tolerance(E2) < te2 )
2480 cout << "Warning: ShapeFix_Wire::FixIE: edges tolerance increased: (" <<
2481 te1 << ", " << te2 << ") / " << newtol << endl;
2484 // Make copy of edges.
2485 if (!Context().IsNull())
2487 isChangedEdge = Standard_True; // To avoid double copying of vertexes.
2489 // Intersection point of two base edges.
2490 ShapeBuild_Edge aSBE;
2491 TopoDS_Vertex VV1 = Context()->CopyVertex(V1);
2493 TopoDS_Vertex VVp = Vp;
2494 TopoDS_Vertex VVn = Vn;
2497 // Should modify only one vertex.
2498 VVp = Context()->CopyVertex(Vp);
2503 VVp = Context()->CopyVertex(Vp);
2504 VVn = Context()->CopyVertex(Vn);
2507 TopoDS_Edge EE1 = aSBE.CopyReplaceVertices(E1, VVp, VV1);
2508 TopoDS_Edge EE2 = aSBE.CopyReplaceVertices(E2, VV1, VVn);
2510 Context()->Replace(E1, EE1);
2511 Context()->Replace(E2, EE2);
2514 E1 = sbwd->Edge(n1);
2515 E2 = sbwd->Edge(n2);
2516 Vp = sae.FirstVertex ( E1 );
2517 V1 = sae.LastVertex ( E1 );
2518 V2 = sae.FirstVertex ( E2 );
2519 Vn = sae.LastVertex ( E2 );
2522 B.UpdateEdge ( E1, 1.000001 * te1 );
2523 B.UpdateVertex ( sae.FirstVertex ( E1 ), 1.000001 * te1 );
2524 B.UpdateVertex ( sae.LastVertex ( E1 ), 1.000001 * te1 );
2525 B.UpdateEdge ( E2, 1.000001 * te2 );
2526 B.UpdateVertex ( sae.FirstVertex ( E2 ), 1.000001 * te2 );
2527 B.UpdateVertex ( sae.LastVertex ( E2 ), 1.000001 * te2 );
2529 myLastFixStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE6 );
2530 locMayEdit = Standard_False;
2532 newtol = 1.000001 * maxte;
2536 if ( locMayEdit || newtol <= MaxTolerance() )
2538 prevRange1 = newRange1;
2539 prevRange2 = newRange2;
2542 newtol = 1.0001 * ( pnt.Distance ( pint ) + rad );
2543 //:j6 abv 7 Dec 98: ProSTEP TR10 r0601_id.stp #57676 & #58586: do not cut edges because of influence on adjacent faces
2544 ShapeFix_SplitTool aTool;
2546 if ( ! aTool.CutEdge ( E1, ( isForward1 ? a1 : b1 ), param1, Face(), IsCutLine ) ) {
2547 if ( V1.IsSame ( Vp ) )
2548 myLastFixStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE3 );
2549 else locMayEdit = Standard_False;
2551 else cutEdge1 = Standard_True; //:h4
2553 if ( ! aTool.CutEdge ( E2, ( isForward2 ? b2 : a2 ), param2, Face(), IsCutLine ) ) {
2554 if ( V2.IsSame ( Vn ) )
2555 myLastFixStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE4 );
2556 else locMayEdit = Standard_False;
2558 else cutEdge2 = Standard_True; //:h4
2562 newRange1 <= prevRange1 && newRange2 <= prevRange2 && //rln 09/01/98
2563 BRep_Tool::SameParameter ( E1 ) &&
2564 BRep_Tool::SameParameter ( E2 ) )
2566 myLastFixStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE2 );
2569 myLastFixStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE1 );
2577 myLastFixStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE2 );
2580 myLastFixStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE1 );
2585 { // else increase tolerance
2587 { //rln 07.04.99 CCI60005-brep.igs
2588 myLastFixStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE1 );
2596 myLastFixStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_FAIL2 );
2600 if ( ! LastFixStatus ( ShapeExtend_DONE ) ) return Standard_False;
2604 B.UpdateVertex ( V1, pnt, tol );
2605 B.UpdateVertex ( V2, pnt, tol );
2609 if ( !Context().IsNull() )
2613 Context()->CopyVertex(V1, pnt, tol);
2617 Context()->CopyVertex(V1, pnt, tol);
2618 Context()->CopyVertex(V2, pnt, tol);
2623 B.UpdateVertex ( V1, pnt, tol );
2624 B.UpdateVertex ( V2, pnt, tol );
2628 //:h4: make edges SP (after all cuts: t4mug.stp #3730+#6460)
2631 if ( !Context().IsNull() )
2632 E1 = TopoDS::Edge(Context()->Apply(E1));
2633 myFixEdge->FixSameParameter ( E1 );
2635 if ( cutEdge2 && !IsCutLine )
2637 if ( !Context().IsNull() )
2638 E2 = TopoDS::Edge(Context()->Apply(E2));
2639 myFixEdge->FixSameParameter ( E2 );
2641 if ( cutEdge1 || cutEdge2 ) {
2642 myLastFixStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE7 );
2644 if ( ! myShape.IsNull() ) {
2645 SendWarning ( Message_Msg ( "FixAdvWire.FixIntersection.MSG10" ) );// Edges were intersecting, corrected
2647 return Standard_True;
2650 //=======================================================================
2651 //function : FixIntersectingEdges
2653 //=======================================================================
2654 //pdn 17.03.99 fixing non ajacent intersection by increasing tolerance of vertex
2656 Standard_Boolean ShapeFix_Wire::FixIntersectingEdges (const Standard_Integer num1,
2657 const Standard_Integer num2)
2659 myLastFixStatus = ShapeExtend::EncodeStatus ( ShapeExtend_OK );
2660 if ( !IsReady() ) return Standard_False;
2661 IntRes2d_SequenceOfIntersectionPoint points2d;
2662 TColgp_SequenceOfPnt points3d;
2663 TColStd_SequenceOfReal errors;
2664 Handle(ShapeAnalysis_Wire) theAdvAnalyzer = myAnalyzer;
2665 if (theAdvAnalyzer.IsNull()) return Standard_False;
2666 theAdvAnalyzer->CheckIntersectingEdges ( num1, num2, points2d, points3d, errors);
2667 if ( theAdvAnalyzer->LastCheckStatus ( ShapeExtend_FAIL ) ) {
2668 myLastFixStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_FAIL1 );
2670 if ( ! theAdvAnalyzer->LastCheckStatus ( ShapeExtend_DONE ) ) return Standard_False;
2671 TColgp_Array1OfPnt vertexPoints(1,4);
2672 TColStd_Array1OfReal vertexTolers(1,4);
2673 TColStd_Array1OfReal newTolers(1,4);
2674 TopTools_Array1OfShape vertices(1,4);
2677 Handle(ShapeExtend_WireData) sbwd = WireData();
2678 Standard_Integer n2 = ( num1 >0 ? num1 : sbwd->NbEdges() );
2679 Standard_Integer n1 = ( num2 >1 ? num2 : sbwd->NbEdges() );
2680 if(n1==n2) return Standard_False;
2682 TopoDS_Edge edge1 = sbwd->Edge(n1);
2683 TopoDS_Edge edge2 = sbwd->Edge(n2);
2685 ShapeAnalysis_Edge sae;
2686 vertices(1) = sae.FirstVertex(edge1);
2687 vertices(2) = sae.LastVertex(edge1);
2688 vertices(3) = sae.FirstVertex(edge2);
2689 vertices(4) = sae.LastVertex(edge2);
2691 Standard_Integer i; // svv Jan11 2000 : porting on DEC
2692 for (i = 1; i <=4; i++) {
2693 vertexPoints(i) = BRep_Tool::Pnt(TopoDS::Vertex(vertices(i)));
2694 vertexTolers(i) = BRep_Tool::Tolerance(TopoDS::Vertex(vertices(i)));
2697 Standard_Real aNewTolEdge1 = 0.0, aNewTolEdge2 = 0.0;
2698 Standard_Integer nb = points3d.Length();
2699 for ( i=1; i <= nb; i++ ) {
2700 gp_Pnt pint = points3d.Value(i);
2702 // searching for the nearest vertexies to the intersection point
2703 Standard_Real aVtx1Param=0., aVtx2Param=0.;
2704 Standard_Integer aVC1, aVC2;
2705 Standard_Real aMinDist = RealLast();
2706 gp_Pnt aNearestVertex;
2707 Standard_Real aNecessaryVtxTole = 0.0;
2708 for(aVC1 = 1; aVC1 <= 2; aVC1++) {
2709 for(aVC2 = 3; aVC2 <= 4; aVC2++) {
2711 Standard_Real aVtxIPDist = pint.Distance(vertexPoints(aVC1));
2712 Standard_Real aVtxVtxDist = vertexPoints(aVC1).Distance(vertexPoints(aVC2));
2713 if(aMinDist > aVtxIPDist && aVtxIPDist > aVtxVtxDist) {
2714 aNecessaryVtxTole = aVtxVtxDist;
2715 aNearestVertex = vertexPoints(aVC1);
2716 aMinDist = aVtxIPDist;
2717 aVtx1Param = BRep_Tool::Parameter(TopoDS::Vertex(vertices(aVC1)),edge1);
2718 aVtx2Param = BRep_Tool::Parameter(TopoDS::Vertex(vertices(aVC2)),edge2);
2723 // calculation of necessary tolerances of edges
2724 const IntRes2d_IntersectionPoint &IP = points2d.Value(i);
2725 Standard_Real param1 = IP.ParamOnFirst();
2726 Standard_Real param2 = IP.ParamOnSecond();
2727 Handle(Geom_Curve) aCurve1, aCurve2;
2729 TopLoc_Location L1, L2;
2730 aCurve1 = BRep_Tool::Curve(edge1, L1, f, l);
2731 aCurve2 = BRep_Tool::Curve(edge2, L2, f, l);
2733 // if aMinDist lower than resolution than the intersection point lyes inside the vertex
2734 if(aMinDist < gp::Resolution())
2737 Standard_Real aMaxEdgeTol1 = 0.0, aMaxEdgeTol2 = 0.0;
2738 if(aMinDist < RealLast() && !aCurve1.IsNull() && !aCurve2.IsNull())
2740 gp_Lin aLig(aNearestVertex, gp_Vec(aNearestVertex, pint));
2741 Standard_Integer aPointsC;
2742 Standard_Real du1 = 0.05*(param1 - aVtx1Param);
2743 Standard_Real du2 = 0.05*(param2 - aVtx2Param);
2744 Standard_Real tole1=BRep_Tool::Tolerance(edge1);
2745 Standard_Real tole2=BRep_Tool::Tolerance(edge2);
2746 for(aPointsC = 2; aPointsC < 19; aPointsC++)
2748 Standard_Real u = aVtx1Param + aPointsC * du1;
2749 gp_Pnt P1 = aCurve1->Value(u);
2750 P1.Transform(L1.Transformation());
2751 Standard_Real d1 = aLig.Distance(P1) * 2.0000001;
2752 if(d1 > tole1 && d1 > aMaxEdgeTol1)
2755 u = aVtx2Param + aPointsC * du2;
2756 gp_Pnt P2 = aCurve2->Value(u);
2757 P2.Transform(L2.Transformation());
2758 Standard_Real d2 = aLig.Distance(P2) * 2.0000001;
2759 if(d2 > tole2 && d2 > aMaxEdgeTol2)
2762 if(aMaxEdgeTol1 == 0.0 && aMaxEdgeTol2 == 0.0) continue;
2763 // if the vertexies are far than tolerances so
2764 // we do not need to increase edge tolerance
2765 if(aNecessaryVtxTole > Max(aMaxEdgeTol1, tole1) ||
2766 aNecessaryVtxTole > Max(aMaxEdgeTol2, tole2))
2773 Standard_Real rad = errors.Value(i);
2774 Standard_Real finTol = RealLast();
2775 Standard_Integer rank=1;
2776 for(Standard_Integer j=1; j<=4; j++) {
2777 Standard_Real newtol = 1.0001 * ( pint.Distance (vertexPoints(j)) + rad );
2783 if(finTol <= MaxTolerance()) {
2784 myLastFixStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE1);
2785 if(newTolers(rank) < finTol)
2787 if(Max(aMaxEdgeTol1, aMaxEdgeTol2) < finTol && (aMaxEdgeTol1 > 0 || aMaxEdgeTol2 > 0))
2789 aNewTolEdge1 = Max(aNewTolEdge1, aMaxEdgeTol1);
2790 aNewTolEdge2 = Max(aNewTolEdge2, aMaxEdgeTol2);
2794 newTolers(rank) = finTol;
2798 myLastFixStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_FAIL2 );
2803 // update of tolerances of edges
2804 if(aNewTolEdge1 > 0)
2806 for(i = 1; i <= 2; i++)
2807 if(aNewTolEdge1 > Max(vertexTolers(i), newTolers(i)))
2808 newTolers(i) = aNewTolEdge1;
2809 B.UpdateEdge(edge1, aNewTolEdge1);
2811 if(aNewTolEdge2 > 0)
2813 for(i = 3; i <= 4; i++)
2814 if(aNewTolEdge2 > Max(vertexTolers(i), newTolers(i)))
2815 newTolers(i) = aNewTolEdge2;
2816 B.UpdateEdge(edge2, aNewTolEdge2);
2819 // update of tolerances of vertexies
2820 for(i = 1; i <=4; i++)
2821 if(newTolers(i)>0) B.UpdateVertex(TopoDS::Vertex(vertices(i)),newTolers(i));
2823 if ( ! myShape.IsNull() ) {
2824 SendWarning ( Message_Msg ( "FixAdvWire.FixIntersection.MSG10" ) );// Edges were intersecting, corrected
2826 return Standard_True;
2829 //=======================================================================
2830 //function : FixLacking
2831 //purpose : Test if two adjucent edges are disconnected in 2d (while connected
2832 // in 3d), and in that case either increase tolerance of the vertex or
2833 // add a new edge (straight in 2d space), in order to close wire in 2d.
2834 // Returns True if edge was added or tolerance was increased.
2835 //NOTE : Is to be run after FixDegenerated
2836 //Algorithm: 1. Compute the 2d gap between edges and calculate a tolerance
2837 // which should have vertex in order to comprise the gap
2838 // (using GeomAdaptor_Surface); computed value is inctol
2839 // 2. If inctol < tol of vertex, return False (everything is OK)
2840 // 3. If inctol < Precision, just increase tolerance of vertex to inctol
2841 // 4. Else (if both edges are not degenerated) try to add new edge
2842 // with straight pcurve (in order to close the gap):
2843 // a) if flag MayEdit is False
2844 // 1. if inctol < MaxTolerance, increase tolerance of vertex to inctol
2845 // 2. else try to add degenerated edge (check that middle point of
2846 // that pcurveis inside the vertex)
2847 // b) if MayEdit is True
2848 // 1. try to replace big vertex with two new small vertices
2849 // connected by new edge. This is made if there is a 3d space
2850 // between ends of adjacent edges.
2851 // 2. if inctol < MaxTolerance, increase tolerance of vertex to inctol
2852 // 3. else add either degenerated or closed edge (if middle point
2853 // of a pcurve of a new edge is inside the vertex, then
2854 // degenerated edge is added, else new edge is closed).
2855 // 5. If new edge cannot be added, but inctol < MaxTolerance,
2856 // when increase tolerance of vertex to a value of inctol
2857 //Short list of some internal variables:
2858 // tol - tolerance of vertex
2859 // tol2d - tolerance in parametric space of the surface corresponding to 2*tol
2860 // dist2d - distance between ends of pcurves of edges (2d)
2861 // inctol - tolerance required for vertex to close 2d gap (=tol*dist2d/tol2d)
2862 // tol1, tol2 - tolerances of edges, tol0 = tol1 + tol2
2863 // p3d1, p3d2 - ends of 3d curves of edges
2864 //=======================================================================
2865 //:h2 abv 28 May 98: merged modifications by abv 22 Apr 98, gka 27 May 98
2866 // and pdn 25 May 98 concerning lacking closed or degenerated edges
2867 // Example files: r0501_pe #107813, UKI60107-6 250, UKI60107-3 1577.
2869 //:s2 abv 21 Apr 99: add functionality for bending pcurve
2870 static Standard_Boolean TryBendingPCurve (const TopoDS_Edge &E, const TopoDS_Face &face,
2871 const gp_Pnt2d p2d, const Standard_Boolean end,
2872 Handle(Geom2d_Curve) &c2d,
2873 Standard_Real &first, Standard_Real &last,
2876 ShapeAnalysis_Edge sae;
2877 if ( ! sae.PCurve ( E, face, c2d, first, last, Standard_False ) ) return Standard_False;
2882 Handle(Geom2d_BSplineCurve) bs;
2883 if ( c2d->IsKind(STANDARD_TYPE(Geom2d_BSplineCurve)) )
2884 bs = Handle(Geom2d_BSplineCurve)::DownCast(c2d->Copy());
2885 else // if ( c2d->IsKind(STANDARD_TYPE(Geom2d_Line)) )
2887 Handle(Geom2d_TrimmedCurve) trim = new Geom2d_TrimmedCurve ( c2d, first, last );
2888 bs = Geom2dConvert::CurveToBSplineCurve ( trim );
2890 if ( bs.IsNull() ) return Standard_False;
2892 Standard_Real par = ( end ? last : first );
2893 if ( fabs ( bs->FirstParameter() - par ) < ::Precision::PConfusion() &&
2894 bs->Multiplicity(1) > bs->Degree() ) bs->SetPole ( 1, p2d );
2895 else if ( fabs ( bs->LastParameter() - par ) < ::Precision::PConfusion() &&
2896 bs->Multiplicity(bs->NbKnots()) > bs->Degree() ) bs->SetPole ( bs->NbPoles(), p2d );
2898 bs->Segment ( first, last );
2899 if (fabs ( bs->FirstParameter() - par ) < ::Precision::PConfusion() &&
2900 bs->Multiplicity(1) > bs->Degree()) bs->SetPole ( 1, p2d );
2901 else if (fabs ( bs->LastParameter() - par ) < ::Precision::PConfusion() &&
2902 bs->Multiplicity(bs->NbKnots()) > bs->Degree()) bs->SetPole ( bs->NbPoles(), p2d );
2903 else return Standard_False;
2907 if ( ! TryNewPCurve ( E, face, c2d, first, last, tol ) ) return Standard_False;
2909 catch ( Standard_Failure ) {
2911 cout << "Warning: ShapeFix_Wire::FixLacking: Exception in Geom2d_BSplineCurve::Segment()" << endl;
2913 return Standard_False;
2917 return Standard_True;
2921 //=======================================================================
2922 //function : FixLacking
2924 //=======================================================================
2926 Standard_Boolean ShapeFix_Wire::FixLacking (const Standard_Integer num,
2927 const Standard_Boolean force)
2929 myLastFixStatus = ShapeExtend::EncodeStatus ( ShapeExtend_OK );
2930 if ( ! IsReady() ) return Standard_False;
2933 // First phase: analysis whether the problem (gap) exists
2934 gp_Pnt2d p2d1, p2d2;
2935 myAnalyzer->CheckLacking ( num, ( force ? Precision() : 0. ), p2d1, p2d2 );
2936 if ( myAnalyzer->LastCheckStatus ( ShapeExtend_FAIL ) ) {
2937 myLastFixStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_FAIL1 );
2939 if ( ! myAnalyzer->LastCheckStatus ( ShapeExtend_DONE ) ) return Standard_False;
2942 // Second phase: collection of data necessary for further analysis
2944 Handle(ShapeExtend_WireData) sbwd = WireData();
2945 Standard_Integer n2 = ( num >0 ? num : sbwd->NbEdges() );
2946 Standard_Integer n1 = ( n2 >1 ? n2-1 : sbwd->NbEdges() );
2947 TopoDS_Edge E1 = sbwd->Edge(n1);
2948 TopoDS_Edge E2 = sbwd->Edge(n2);
2950 ShapeAnalysis_Edge sae;
2951 TopoDS_Vertex V1 = sae.LastVertex ( E1 );
2952 TopoDS_Vertex V2 = sae.FirstVertex ( E2 );
2953 Standard_Real tol = Max ( BRep_Tool::Tolerance ( V1 ), BRep_Tool::Tolerance ( V2 ) );
2955 Standard_Real Prec = Precision();
2956 Standard_Real dist2d = myAnalyzer->MaxDistance2d();
2957 Standard_Real inctol = myAnalyzer->MaxDistance3d();
2959 TopoDS_Face face = myAnalyzer->Face();
2960 Handle(ShapeAnalysis_Surface) surf = myAnalyzer->Surface();
2963 Standard_Real tol1=::Precision::Confusion(), tol2=::Precision::Confusion(); //SK
2966 //:s2 abv 21 Apr 99: Speculation: try bending pcurves
2967 Standard_Real bendtol1 = 0., bendtol2 = 0.;
2968 Handle(Geom2d_Curve) bendc1, bendc2;
2969 Standard_Real bendf1 = 0., bendl1 = 0., bendf2 = 0., bendl2 = 0.;
2970 if ( myGeomMode && ! BRep_Tool::IsClosed(E1,face) && ! BRep_Tool::IsClosed(E2,face) ) {
2971 gp_Pnt2d p2d = 0.5 * ( p2d1.XY() + p2d2.XY() );
2972 Standard_Boolean ok1 = TryBendingPCurve (E1, face, p2d, E1.Orientation() == TopAbs_FORWARD,
2973 bendc1, bendf1, bendl1, bendtol1);
2974 Standard_Boolean ok2 = TryBendingPCurve (E2, face, p2d, E2.Orientation() == TopAbs_REVERSED,
2975 bendc2, bendf2, bendl2, bendtol2);
2976 if ( ok1 && ! ok2 ) {
2977 bendtol2 = BRep_Tool::Tolerance(E2);
2978 ok1 = TryBendingPCurve (E1, face, p2d2, E1.Orientation() == TopAbs_FORWARD,
2979 bendc1, bendf1, bendl1, bendtol1);
2981 else if ( ! ok1 && ok2 ) {
2982 bendtol1 = BRep_Tool::Tolerance(E1);
2983 ok2 = TryBendingPCurve (E2, face, p2d1, E2.Orientation() == TopAbs_FORWARD,
2984 bendc2, bendf2, bendl2, bendtol2);
2986 if ( ! ok1 && ! ok2 ) bendc1.Nullify();
2990 // Third phase: analyse how to fix the problem
2992 // selector of solutions
2993 Standard_Boolean doIncrease = Standard_False; // increase tolerance
2994 Standard_Boolean doAddLong = Standard_False; // add long 3d edge in replacement of a vertex
2995 Standard_Boolean doAddClosed = Standard_False; // add closed 3d edge
2996 Standard_Boolean doAddDegen = Standard_False; // add degenerated edge
2997 Standard_Boolean doBend = Standard_False; //:s2 bend pcurves
2999 // if bending is OK with existing tolerances of edges, take it
3000 if ( ! bendc1.IsNull() && ! bendc2.IsNull() &&
3001 ( ( bendtol1 < BRep_Tool::Tolerance(E1) &&
3002 bendtol2 < BRep_Tool::Tolerance(E2) ) ||
3003 ( inctol < Prec && bendtol1 < inctol && bendtol2 < inctol ) ) )
3004 doBend = Standard_True;
3006 // is it OK just to increase tolerance (to a value less than preci)?
3007 else if ( inctol < Prec ) doIncrease = Standard_True;
3009 // If increase is not OK or force, try to find other solutions (adding edge)
3010 else if ( ! BRep_Tool::Degenerated ( E2 ) && ! BRep_Tool::Degenerated ( E1 ) ) {
3012 // analyze the 3d space btw edges: is it enough to add long 3d edge?
3014 Handle(Geom_Curve) c3d;
3016 if ( ! sae.Curve3d ( E1, c3d, a, b, Standard_True ) ) { // cannot work
3017 myLastFixStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_FAIL1 );
3018 return Standard_False;
3020 p3d1 = c3d->Value ( b );
3021 Standard_Real dist2d3d1 = p3d1.Distance ( surf->Value ( p2d1 ) );
3022 if ( ! sae.Curve3d ( E2, c3d, a, b, Standard_True ) ) { // cannot work
3023 myLastFixStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_FAIL1 );
3024 return Standard_False;
3026 p3d2 = c3d->Value ( a );
3027 Standard_Real dist2d3d2 = p3d2.Distance ( surf->Value ( p2d2 ) );
3029 tol1 = Max ( BRep_Tool::Tolerance ( E1 ), dist2d3d1 );
3030 tol2 = Max ( BRep_Tool::Tolerance ( E2 ), dist2d3d2 );
3031 //:c5 Standard_Real tol0 = Max ( tol1 + tol2, thepreci );
3032 Standard_Real tol0 = tol1 + tol2; //:c5 abv 26 Feb 98: CTS17806 #44418
3033 Standard_Real dist3d2 = p3d1.SquareDistance ( p3d2 );
3035 // is it OK to add a long 3d edge?
3036 if ( ! myAnalyzer->LastCheckStatus ( ShapeExtend_DONE2 ) && //:81 abv 20 Jan 98: don`t add back-going edges (zigzags)
3037 dist3d2 > 1.25 * tol0 * tol0 &&
3038 ( force || dist3d2 > Prec * Prec || inctol > MaxTolerance() ) ) {
3039 doAddLong = Standard_True;
3043 //:h6 abv 25 Jun 98: BUC40132 6361: try to increase tol up to MaxTol if not add
3044 if ( ! doAddLong && inctol < MaxTolerance() &&
3045 ! myAnalyzer->Surface()->IsDegenerated ( p2d1, p2d2, 2.*tol, 10. ) ) { //:p7
3046 if ( ! bendc1.IsNull() && ! bendc2.IsNull() &&
3047 bendtol1 < inctol && bendtol2 < inctol ) doBend = Standard_True;
3048 else doIncrease = Standard_True;
3052 // else try to add either degenerated or closed edge
3053 if ( ! doAddLong ) {
3054 gp_Pnt pV = 0.5 * ( BRep_Tool::Pnt(V1).XYZ() + BRep_Tool::Pnt(V2).XYZ() );
3055 gp_Pnt pm = myAnalyzer->Surface()->Value ( 0.5 * ( p2d1.XY() + p2d2.XY() ) );
3057 Standard_Real dist = pV.Distance ( pm );
3058 if ( dist <= tol ) doAddDegen = Standard_True;
3059 else if ( myTopoMode ) doAddClosed = Standard_True;
3060 else if ( dist <= MaxTolerance() ) { //:r7 abv 12 Apr 99: t3d_opt.stp #14245 after S4136
3061 doAddDegen = Standard_True;
3062 doIncrease = Standard_True;
3068 else if ( !BRep_Tool::Degenerated(E2) && BRep_Tool::Degenerated(E1) ) {
3069 // create new degenerated edge and replace E1 to new edge
3071 else if ( BRep_Tool::Degenerated(E2) && !BRep_Tool::Degenerated(E1) ) {
3072 // create new degenerated edge and replace E2 to new edge
3076 // Third phase - do the fixes
3080 if ( doAddLong || doAddDegen || doAddClosed ) {
3082 // construct new vertices
3083 TopoDS_Vertex newV1, newV2;
3085 newV1 = BRepBuilderAPI_MakeVertex ( p3d1 );
3087 newV2 = BRepBuilderAPI_MakeVertex ( p3d2 );
3088 B.UpdateVertex ( newV1, 1.001 * tol1 );
3089 B.UpdateVertex ( newV2, 1.001 * tol2 );
3098 B.MakeEdge ( edge );
3099 if ( doAddDegen ) B.Degenerated ( edge, Standard_True ); // sln: do it before adding curve
3100 gp_Vec2d v12 ( p2d1, p2d2 );
3101 Handle(Geom2d_Line) theLine2d = new Geom2d_Line ( p2d1, gp_Dir2d ( v12 ) );
3102 B.UpdateEdge ( edge, theLine2d, face, ::Precision::Confusion() );
3103 B.Range ( edge, face, 0, dist2d );
3104 B.Add ( edge, newV1.Oriented ( TopAbs_FORWARD ) );
3105 B.Add ( edge, newV2.Oriented ( TopAbs_REVERSED ) );
3106 ShapeBuild_Edge sbe;
3107 if ( ! doAddDegen && ! sbe.BuildCurve3d ( edge ) ) {
3108 myLastFixStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_FAIL3 );
3109 return Standard_False;
3112 // if long edge is added, replace vertices of adjacent edges
3115 // replace 1st edge (n1==n2 - special case: wire consists of one edge)
3116 TopoDS_Edge edge1 = sbe.CopyReplaceVertices ( E1,
3117 ( n1 == n2 ? newV2 : TopoDS_Vertex() ), newV1 );
3118 sbwd->Set ( edge1, n1 );
3119 if ( ! Context().IsNull() ) {
3120 Context()->Replace ( E1, edge1 );
3121 // actually, this will occur only in context of single face
3122 // hence, recording to ReShape is rather for tracking modifications
3123 // than for keeping sharing
3124 Context()->Replace ( V1, newV1.Oriented ( V1.Orientation() ) );
3125 if ( ! V1.IsSame ( V2 ) ) {
3126 Context()->Replace ( V2, newV2.Oriented ( V2.Orientation() ) );
3131 TopoDS_Edge edge2 = sbe.CopyReplaceVertices ( E2, newV2, TopoDS_Vertex() );
3132 sbwd->Set ( edge2, n2 );
3133 if ( ! Context().IsNull() ) Context()->Replace ( E2, edge2 );
3135 if ( ! Context().IsNull() ) UpdateWire();
3140 myLastFixStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE3 );
3142 cout << "Warning: ShapeFix_Wire::FixLacking: degenerated edge added" << endl;
3145 else if ( ! doAddLong ) {
3146 myLastFixStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE4 );
3148 sbwd->Add ( edge, n2 );
3149 myLastFixStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE2 );
3152 // else try to increase tol up to MaxTol
3153 else if ( inctol > tol && inctol < MaxTolerance() ) {
3154 if ( ! bendc1.IsNull() && ! bendc2.IsNull() &&
3155 bendtol1 < inctol && bendtol2 < inctol ) doBend = Standard_True;
3156 else doIncrease = Standard_True;
3160 if ( doBend ) { //:s2 abv 21 Apr 99
3161 B.UpdateEdge ( E1, bendc1, face, bendtol1 );
3162 B.Range ( E1, face, bendf1, bendl1 );
3163 B.UpdateEdge ( E2, bendc2, face, bendtol2 );
3164 B.Range ( E2, face, bendf2, bendl2 );
3165 B.UpdateVertex ( sae.FirstVertex(E1), bendtol1 );
3166 B.UpdateVertex ( sae.LastVertex(E1), bendtol1 );
3167 B.UpdateVertex ( sae.FirstVertex(E2), bendtol2 );
3168 B.UpdateVertex ( sae.LastVertex(E2), bendtol2 );
3169 myLastFixStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE5 );
3170 //:s3 abv 22 Apr 99: PRO7187 #11534: self-intersection not detected unitil curve is bent (!)
3171 FixSelfIntersectingEdge ( n1 );
3172 FixSelfIntersectingEdge ( n2 );
3173 FixIntersectingEdges ( n2 ); //skl 24.04.2003 for OCC58
3175 cout << "Info: ShapeFix_Wire::FixLacking: Bending pcurves" << endl;
3177 myLastFixStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE5 );
3180 // increase vertex tolerance
3182 B.UpdateVertex ( V1, 1.001 * inctol );
3183 B.UpdateVertex ( V2, 1.001 * inctol );
3184 myLastFixStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE1 );
3187 if ( LastFixStatus ( ShapeExtend_DONE ) ) return Standard_True;
3189 myLastFixStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_FAIL2 );
3190 return Standard_False;
3193 //=======================================================================
3194 //function : FixNotchedEdges
3196 //=======================================================================
3198 Standard_Boolean ShapeFix_Wire::FixNotchedEdges()
3200 myLastFixStatus = ShapeExtend::EncodeStatus ( ShapeExtend_OK );
3201 if ( ! IsReady() ) return Standard_False;
3203 Handle(ShapeAnalysis_Wire) theAdvAnalyzer = myAnalyzer;
3204 TopoDS_Face face = Face();
3205 if ( ! Context().IsNull() ) UpdateWire();
3206 Handle(ShapeExtend_WireData) sewd = WireData();
3208 for (Standard_Integer i = 1; i <= NbEdges() && NbEdges() > 2; i++) {
3209 Standard_Real param;
3210 Standard_Integer toRemove;
3211 if(theAdvAnalyzer->CheckNotchedEdges(i,toRemove,param,MinTolerance())){
3212 Standard_Integer n2 = (i > 0) ? i : NbEdges();
3213 Standard_Integer n1 = (n2 > 1) ? n2-1 : NbEdges();
3214 Standard_Boolean isRemoveFirst = (n1==toRemove);
3215 Standard_Integer toSplit = (n2==toRemove ? n1 : n2);
3216 TopoDS_Edge splitE = sewd->Edge ( toSplit );
3217 ShapeAnalysis_Edge sae;
3218 Handle(Geom2d_Curve) c2d;
3220 sae.PCurve ( splitE, face, c2d, a, b, Standard_True );
3221 Standard_Real ppar = (isRemoveFirst ? b : a);
3222 ShapeBuild_Edge sbe;
3223 TopAbs_Orientation orient = splitE.Orientation();
3224 if ( Abs(param - ppar) > ::Precision::PConfusion() ) {
3225 //pdn perform splitting of the edge and adding to wire
3227 //pdn check if it is necessary
3228 if( Abs((isRemoveFirst ? a : b)-param) < ::Precision::PConfusion() ) {
3232 Handle(ShapeAnalysis_TransferParametersProj) transferParameters =
3233 new ShapeAnalysis_TransferParametersProj;
3234 transferParameters->SetMaxTolerance(MaxTolerance());
3235 transferParameters->Init(splitE,face);
3236 Standard_Real first, last;
3247 B.MakeVertex(Vnew,Analyzer()->Surface()->Value(c2d->Value(param)),::Precision::Confusion());
3248 TopoDS_Edge wE = splitE;
3249 wE.Orientation ( TopAbs_FORWARD );
3250 TopoDS_Shape aTmpShape = Vnew.Oriented(TopAbs_REVERSED); //for porting
3251 TopoDS_Edge newE1 = sbe.CopyReplaceVertices ( wE, sae.FirstVertex(wE), TopoDS::Vertex(aTmpShape) );
3252 sbe.CopyPCurves ( newE1, wE );
3253 transferParameters->TransferRange(newE1,first,param,Standard_True);
3254 B.SameRange(newE1,Standard_False);
3255 B.SameParameter(newE1,Standard_False);
3256 aTmpShape = Vnew.Oriented(TopAbs_FORWARD);
3257 TopoDS_Edge newE2 = sbe.CopyReplaceVertices ( wE, TopoDS::Vertex(aTmpShape),sae.LastVertex(wE) );
3258 sbe.CopyPCurves ( newE2, wE );
3259 transferParameters->TransferRange(newE2,param,last,Standard_True);
3260 B.SameRange(newE2,Standard_False);
3261 B.SameParameter(newE2,Standard_False);
3263 if ( !Context().IsNull() ) {
3268 Context()->Replace ( wE, wire );
3271 newE1.Orientation(orient);
3272 newE2.Orientation(orient);
3273 if (orient==TopAbs_REVERSED){ TopoDS_Edge tmp = newE2; newE2 = newE1; newE1=tmp;}
3275 Standard_Boolean isRemoveLast = ((n1==NbEdges())&&(n2==1));
3276 sewd->Set ( newE1, toSplit);
3277 sewd->Add ( newE2, (toSplit==NbEdges() ? 0 : toSplit+1));
3279 FixDummySeam(isRemoveLast ? NbEdges() : toRemove);
3280 myLastFixStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE2 );
3285 // The seam edge is removed from the list. So, need to step back to avoid missing of edge processing
3290 if(!Context().IsNull()) //skl 07.03.2002 for OCC180
3292 myLastFixStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE1 );
3295 myStatusNotches = myLastFixStatus;
3296 return LastFixStatus ( ShapeExtend_DONE );
3299 //=======================================================================
3300 //function : FixDummySeam
3302 //=======================================================================
3304 static void CopyReversePcurves(const TopoDS_Edge& toedge,
3305 const TopoDS_Edge& fromedge,
3306 const Standard_Boolean reverse)
3308 TopLoc_Location fromLoc = fromedge.Location();
3309 TopLoc_Location toLoc = toedge.Location();
3310 for (BRep_ListIteratorOfListOfCurveRepresentation fromitcr
3311 ((*((Handle(BRep_TEdge)*)&fromedge.TShape()))->ChangeCurves()); fromitcr.More(); fromitcr.Next()) {
3312 Handle(BRep_GCurve) fromGC = Handle(BRep_GCurve)::DownCast(fromitcr.Value());
3313 if ( fromGC.IsNull() ) continue;
3314 if ( fromGC->IsCurveOnSurface() ) {
3315 Handle(Geom_Surface) surface = fromGC->Surface();
3316 TopLoc_Location L = fromGC->Location();
3317 Standard_Boolean found = Standard_False;
3318 BRep_ListOfCurveRepresentation& tolist = (*((Handle(BRep_TEdge)*)&toedge.TShape()))->ChangeCurves();
3319 Handle(BRep_GCurve) toGC;
3320 for (BRep_ListIteratorOfListOfCurveRepresentation toitcr (tolist); toitcr.More() && !found; toitcr.Next()) {
3321 toGC = Handle(BRep_GCurve)::DownCast(toitcr.Value());
3322 if ( toGC.IsNull() || !toGC->IsCurveOnSurface() ||
3323 surface != toGC->Surface() || L != toGC->Location() ) continue;
3324 found = Standard_True;
3328 Standard_Real fp = fromGC->First();
3329 Standard_Real lp = fromGC->Last();
3330 toGC = Handle(BRep_GCurve)::DownCast(fromGC->Copy());
3331 tolist.Append (toGC);
3332 Handle(Geom2d_Curve) pcurve = Handle(Geom2d_Curve)::DownCast( fromGC->PCurve()->Copy() );
3334 fp = pcurve->ReversedParameter(fp);
3335 lp = pcurve->ReversedParameter(lp);
3337 Standard_Real tmp = fp;
3341 //bug OCC209 invalid location of pcurve in the edge after copying
3342 TopLoc_Location newLoc = (fromLoc*L).Predivided(toLoc);
3343 toGC->SetRange(fp,lp);
3344 toGC->PCurve(pcurve);
3345 toGC->Location(newLoc);
3346 if ( fromGC->IsCurveOnClosedSurface() ) {
3347 pcurve = fromGC->PCurve2();
3348 toGC->PCurve2(Handle(Geom2d_Curve)::DownCast(pcurve->Copy()));
3355 //=======================================================================
3356 //function : HasNewPCurves
3358 //=======================================================================
3359 // Note: This function temporarily not used, because adress to it in
3360 // function FixDummySeam() (see below line 2472) not used too
3362 //static Standard_Boolean HasNewPCurves(const TopoDS_Edge& toedge,
3363 // const TopoDS_Edge& fromedge)
3366 // for (BRep_ListIteratorOfListOfCurveRepresentation fromitcr
3367 // ((*((Handle(BRep_TEdge)*)&fromedge.TShape()))->ChangeCurves()); fromitcr.More(); fromitcr.Next()) {
3368 // Handle(BRep_GCurve) fromGC = Handle(BRep_GCurve)::DownCast(fromitcr.Value());
3369 // if ( fromGC.IsNull() ) continue;
3370 // if ( fromGC->IsCurveOnSurface() ) {
3371 // Handle(Geom_Surface) surface = fromGC->Surface();
3372 // TopLoc_Location L = fromGC->Location();
3373 // Standard_Boolean found = Standard_False;
3374 // BRep_ListOfCurveRepresentation& tolist = (*((Handle(BRep_TEdge)*)&toedge.TShape()))->ChangeCurves();
3375 // Handle(BRep_GCurve) toGC;
3376 // for (BRep_ListIteratorOfListOfCurveRepresentation toitcr (tolist); toitcr.More() && !found; toitcr.Next()) {
3377 // toGC = Handle(BRep_GCurve)::DownCast(toitcr.Value());
3378 // if ( toGC.IsNull() || !toGC->IsCurveOnSurface() ||
3379 // surface != toGC->Surface() || L != toGC->Location() ) continue;
3380 // found = Standard_True;
3384 // return Standard_True;
3387 // return Standard_False;
3390 //=======================================================================
3391 //function : FixDummySeam
3393 //=======================================================================
3395 void ShapeFix_Wire::FixDummySeam(const Standard_Integer num)
3397 ShapeAnalysis_Edge sae;
3398 ShapeBuild_Edge sbe;
3399 ShapeBuild_Vertex sbv;
3400 Standard_Integer num1 = (num == NbEdges()) ? 1 : num+1;
3401 Handle(ShapeExtend_WireData) sewd = WireData();
3402 TopoDS_Edge E1 = sewd->Edge(num), E2 = sewd->Edge(num1);
3403 TopoDS_Vertex V1 = sae.FirstVertex(E1), V2 = sae.LastVertex(E2);
3404 TopoDS_Vertex Vm = sbv.CombineVertex ( V1, V2, 1.0001 );
3406 //pnd defining if new pcurves exists
3407 //pdn Temporary not removed
3408 // Standard_Boolean toRemove = !(HasNewPCurves(E1,E2)||HasNewPCurves(E2,E1));
3409 Standard_Boolean toRemove = Standard_False;
3411 //creating new edge with pcurves and new vertex
3412 TopoDS_Vertex Vs = sae.FirstVertex(E2);
3413 if ( Vs.IsSame ( V1 ) || Vs.IsSame ( V2 ) ) Vs = Vm;
3414 TopoDS_Edge newEdge = sbe.CopyReplaceVertices ( E2, Vs, Vm );
3415 CopyReversePcurves(newEdge,E1,E1.Orientation()==E2.Orientation());
3417 B.SameRange(newEdge,Standard_False);
3418 B.SameParameter(newEdge,Standard_False);
3420 if ( !Context().IsNull() ) {
3422 Context()->Remove ( E2 );
3423 Context()->Remove ( E1 );
3426 Context()->Replace ( E2, newEdge );
3427 Context()->Replace ( E1, newEdge.Reversed());
3429 Context()->Replace ( V1, Vm.Oriented(V1.Orientation()) );
3430 Context()->Replace ( V2, Vm.Oriented(V2.Orientation()) );
3433 Standard_Integer next = ( num1 == NbEdges()) ? 1 : num1+1;
3434 Standard_Integer prev = ( num > 1) ? num-1 : NbEdges();
3435 TopoDS_Edge prevE = sewd->Edge(prev), nextE = sewd->Edge(next);
3437 TopoDS_Edge tmpE1=sbe.CopyReplaceVertices( prevE, TopoDS_Vertex(), Vm);
3438 sewd->Set ( tmpE1,prev );
3439 if ( !Context().IsNull() ) Context()->Replace ( prevE, tmpE1);
3441 tmpE1 = sbe.CopyReplaceVertices ( nextE, Vm, TopoDS_Vertex());
3442 sewd->Set ( tmpE1,next );
3443 if ( !Context().IsNull() ) Context()->Replace ( nextE, tmpE1);
3445 //removing edges from wire
3446 Standard_Integer n1, n2;
3448 n1 = num; n2 = num1;
3450 n1 = num1; n2 = num;
3456 //=======================================================================
3457 //function : UpdateWire
3459 //=======================================================================
3461 void ShapeFix_Wire::UpdateWire ()
3463 Handle(ShapeExtend_WireData) sbwd = WireData();
3464 for ( Standard_Integer i=1; i <= sbwd->NbEdges(); i++ ) {
3465 TopoDS_Edge E = sbwd->Edge(i);
3466 TopoDS_Shape S = Context()->Apply ( E );
3467 if ( S == E ) continue;
3468 for ( TopExp_Explorer exp(S,TopAbs_EDGE); exp.More(); exp.Next() )
3469 sbwd->Add ( exp.Current(), i++ );
3470 sbwd->Remove ( i-- );
3474 //=======================================================================
3475 //function : FixTails
3477 //=======================================================================
3478 Standard_Boolean ShapeFix_Wire::FixTails()
3480 if (myMaxTailWidth < 0 || !IsReady())
3482 return Standard_False;
3485 myLastFixStatus = ShapeExtend::EncodeStatus(ShapeExtend_OK);
3486 if (!Context().IsNull())
3490 Handle(ShapeExtend_WireData) aSEWD = WireData();
3491 Standard_Integer aECount = NbEdges(), aENs[] = {aECount, 1};
3492 Standard_Boolean aCheckAngle = Standard_True;
3493 while (aECount >= 2 && aENs[1] <= aECount)
3495 const TopoDS_Edge aEs[] = {aSEWD->Edge(aENs[0]), aSEWD->Edge(aENs[1])};
3496 TopoDS_Edge aEParts[2][2];
3497 if (!myAnalyzer->CheckTail(aEs[0], aEs[1],
3498 aCheckAngle ? myMaxTailAngleSine : -1, myMaxTailWidth, MaxTolerance(),
3499 aEParts[0][0], aEParts[0][1], aEParts[1][0], aEParts[1][1]))
3501 aENs[0] = aENs[1]++;
3502 aCheckAngle = Standard_True;
3506 // Provide not less than 1 edge in the result wire.
3507 Standard_Integer aSplitCounts[] =
3508 {aEParts[0][1].IsNull() ? 0 : 1, aEParts[1][1].IsNull() ? 0 : 1};
3509 const Standard_Integer aRemoveCount =
3510 (aEParts[0][0].IsNull() ? 0 : 1) + (aEParts[1][0].IsNull() ? 0 : 1);
3511 if (aECount + aSplitCounts[0] + aSplitCounts[1] < 1 + aRemoveCount)
3513 aENs[0] = aENs[1]++;
3514 aCheckAngle = Standard_True;
3519 for (Standard_Integer aEI = 0; aEI < 2; ++aEI)
3521 if (aSplitCounts[aEI] == 0)
3526 // Replace the edge by the wire of its parts in the shape.
3527 const TopoDS_Edge aE = aEs[aEI];
3528 if (!Context().IsNull())
3531 BRep_Builder().MakeWire(aEWire);
3532 BRep_Builder().Add(aEWire, aEParts[aEI][0]);
3533 BRep_Builder().Add(aEWire, aEParts[aEI][1]);
3534 TopoDS_Edge aFE = TopoDS::Edge(aE.Oriented(TopAbs_FORWARD));
3535 Context()->Replace(aFE, aEWire);
3538 // Replace the edge by its parts in the edge wire.
3539 const TopAbs_Orientation aOrient = aE.Orientation();
3540 aEParts[aEI][0].Orientation(aOrient);
3541 aEParts[aEI][1].Orientation(aOrient);
3542 const Standard_Integer aFirstPI = (aOrient != TopAbs_REVERSED) ? 0 : 1;
3543 const Standard_Integer aAdd =
3544 (aEI == 0 || aENs[1] < aENs[0]) ? 0 : aSplitCounts[0];
3545 aSEWD->Set(aEParts[aEI][aFirstPI], aENs[aEI] + aAdd);
3546 aSEWD->Add(aEParts[aEI][1 - aFirstPI], aENs[aEI] + 1 + aAdd);
3550 if (aRemoveCount == 2)
3552 aCheckAngle = Standard_True;
3553 FixDummySeam(aENs[0] + aSplitCounts[0] +
3554 ((aENs[0] < aENs[1]) ? 0 : aSplitCounts[1]));
3555 if (!Context().IsNull())
3559 myLastFixStatus |= ShapeExtend::EncodeStatus(ShapeExtend_DONE);
3561 if (aSplitCounts[0] + aSplitCounts[1] == 2)
3563 aENs[0] = aENs[1]++;
3567 if (aSplitCounts[0] == aSplitCounts[1])
3580 aCheckAngle = Standard_False;
3585 if (aSplitCounts[0] != 0)
3587 aENs[0] = (aENs[0] <= aECount) ? aENs[0] : aECount;
3606 aCheckAngle = Standard_False;
3608 const Standard_Integer aRI = aEParts[0][0].IsNull() ? 1 : 0;
3609 if (aSplitCounts[aRI] != 0)
3626 aENs[0] = (aENs[1] > 1) ? aENs[0] : aECount;
3629 aSEWD->Remove(aENs[aRI] + ((aRI != 0 || aSplitCounts[0] == 0) ? 0 : 1));
3630 if (!Context().IsNull())
3632 Context()->Remove(aEs[aRI].Oriented(TopAbs_FORWARD));
3635 myLastFixStatus |= ShapeExtend::EncodeStatus(ShapeExtend_DONE);
3638 myStatusNotches = myLastFixStatus;
3639 return ShapeExtend::DecodeStatus(myLastFixStatus, ShapeExtend_DONE);