1 //:j6 abv 7 Dec 98: ProSTEP TR10 r0601_id.stp #57676 & #58586:
2 // in FixIntersectingEdges, do not cut edges because of influence on adjacent faces
3 // pdn 17.12.98: shifting whole wire in FixShifted
4 //:k3 abv 24 Dec 98: BUC50070 #26682 and #30087: removing self-int loops on pcurves
5 // pdn 30.12.98: PRO10366 #210: shifting pcurve between two singularities
6 // pdn 05.01.98: renaming method FixLittle to FixSmall
7 //:l0 abv 10.01.99: remove unused code
8 //:n2 abv 22.01.99: ma-test5.igs: IGES read (pref3d): remove degen edge with no pcurve
9 //:o4 abv 17.02.99: r0301_db.stp #53082: using parameter isClosed in CheckOrder
10 //:p4 abv 23.02.99: PRO9234 #15720: update UV points of edges after shifting pcurves
11 //#67 rln 01.03.99 S4135: ims010.igs treatment of Geom_SphericalSurface together with V-closed surfaces
12 //:p7 abv 10.03.99 PRO18206: using method IsDegenerated() to detect singularity in FixLacking
13 //:r0 abv 19.03.99 PRO7226.stp #489490: remove degenerated edges if several
14 //#78 rln 12.03.99 S4135: checking spatial closure with Precision
15 //#79 rln 15.03.99 S4135: bmarkmdl.igs: check for gap before shifting on singularities
16 // pdn 17.03.99 S4135: implemented fixing not adjacent intersection
17 //#86 rln 22.03.99 S4135: repeat of fix self-intersection if it was fixed just before
18 //%15 pdn 06.04.99 CTS18546-2: fix of self-intersection is repeated while fixed
19 //#3 smh 01.04.99 S4163: Overflow
20 //#4 szv S4163: optimization
21 //:r7 abv 12.04.99 S4136: FixLk: extend cases of adding degenerated edge
22 //:r8 abv 12.04.99 PRO10107.stp #2241: try increasing tolerance of edge for fix IE
23 //:s2 abv 21.04.99 S4136, PRO7978.igs: FixLacking extended to be able to bend pcurves
24 //szv#9:S4244:19Aug99 Methods FixGaps3d and FixGaps2d were introduced
25 //#15 smh 03.04.2000 PRO19800. Checking degenerated point on a surface of revolution.
26 // sln 25.09.2001 checking order of 3d and 2d representation curves
27 // van 19.10.2001 fix of non-adjacent self-intersection corrected to agree with BRepCheck
28 // skl 07.03.2002 fix for bug OCC180
29 // skl 15.05.2002 for OCC208 (if few edges have reference to
30 // one pcurve we make replace pcurve)
31 // PTV 26.06.2002 Remove regressions after fix OCC450
33 #include <ShapeFix_Wire.ixx>
35 #include <Standard_ErrorHandler.hxx>
36 #include <Standard_Failure.hxx>
37 #include <TColStd_Array1OfReal.hxx>
38 #include <TColStd_Array1OfInteger.hxx>
39 #include <Precision.hxx>
41 #include <Geom_Curve.hxx>
42 #include <Geom_TrimmedCurve.hxx>
43 #include <Geom_BSplineCurve.hxx>
44 #include <Geom_SphericalSurface.hxx> //S4135
45 #include <Geom_SurfaceOfRevolution.hxx>
46 #include <GeomAdaptor_Curve.hxx>
47 #include <GeomAdaptor_HSurface.hxx>
48 #include <GeomAdaptor_Surface.hxx>
49 #include <GeomConvert_CompCurveToBSplineCurve.hxx>
50 #include <GeomAPI.hxx>
52 #include <Geom2d_Curve.hxx>
53 #include <Geom2d_TrimmedCurve.hxx>
54 #include <Geom2d_Line.hxx>
55 #include <Geom2d_BSplineCurve.hxx>
56 #include <Geom2dAdaptor_Curve.hxx>
57 #include <Geom2dConvert.hxx>
59 #include <Bnd_Box2d.hxx>
60 #include <Bnd_Array1OfBox2d.hxx>
61 #include <BndLib_Add2dCurve.hxx>
62 #include <IntRes2d_SequenceOfIntersectionPoint.hxx>
63 #include <IntRes2d_IntersectionPoint.hxx>
64 #include <TColgp_Array1OfPnt.hxx>
65 #include <TColgp_SequenceOfPnt.hxx>
69 #include <TopoDS_Vertex.hxx>
70 #include <TopoDS_Edge.hxx>
71 #include <TopTools_Array1OfShape.hxx>
72 #include <TopTools_HSequenceOfShape.hxx>
73 #include <TopExp_Explorer.hxx>
75 #include <BRep_Tool.hxx>
76 #include <BRep_Builder.hxx>
77 #include <BRep_ListIteratorOfListOfCurveRepresentation.hxx>
78 #include <BRep_TEdge.hxx>
79 #include <BRep_GCurve.hxx>
80 #include <BRepBuilderAPI_MakeEdge.hxx>
81 #include <BRepBuilderAPI_MakeVertex.hxx>
82 #include <BRepTools.hxx>
84 #include <Message_Msg.hxx>
85 #include <ShapeExtend.hxx>
86 #include <ShapeBuild_Edge.hxx>
87 #include <ShapeBuild_Vertex.hxx>
88 #include <ShapeBuild_ReShape.hxx>
89 #include <ShapeAnalysis_Curve.hxx>
90 #include <ShapeAnalysis_Edge.hxx>
91 #include <ShapeAnalysis_Surface.hxx>
92 #include <ShapeAnalysis.hxx>
93 #include <ShapeConstruct_ProjectCurveOnSurface.hxx>
94 #include <ShapeAnalysis_TransferParametersProj.hxx>
95 #include <Geom_Plane.hxx>
96 #include <Geom_OffsetCurve.hxx>
98 #include <TColStd_HSequenceOfReal.hxx>
99 #include <Handle_Geom2dAdaptor_HCurve.hxx>
100 #include <Adaptor3d_CurveOnSurface.hxx>
101 #include <Geom2dAdaptor_HCurve.hxx>
102 #include <GeomAPI_ProjectPointOnCurve.hxx>
104 #include <ShapeAnalysis_TransferParameters.hxx>
105 #include <ShapeFix.hxx>
106 #include <ShapeFix_IntersectionTool.hxx>
107 #include <ShapeFix_SplitTool.hxx>
110 //#######################################################################
111 // Constructors, initializations, modes, querying
112 //#######################################################################
114 //=======================================================================
115 //function : ShapeFix_Wire
117 //=======================================================================
119 ShapeFix_Wire::ShapeFix_Wire()
121 myFixEdge = new ShapeFix_Edge;
122 myAnalyzer = new ShapeAnalysis_Wire;
125 myStatusRemovedSegment = Standard_False;
128 //=======================================================================
129 //function : ShapeFix_Wire
131 //=======================================================================
133 ShapeFix_Wire::ShapeFix_Wire (const TopoDS_Wire& wire,
134 const TopoDS_Face &face, const Standard_Real prec)
136 myFixEdge = new ShapeFix_Edge;
137 myAnalyzer = new ShapeAnalysis_Wire;
139 SetMaxTolerance ( prec );
140 myStatusRemovedSegment = Standard_False;
141 Init ( wire, face, prec );
144 //=======================================================================
145 //function : SetPrecision
147 //=======================================================================
149 void ShapeFix_Wire::SetPrecision (const Standard_Real prec)
151 ShapeFix_Root::SetPrecision ( prec );
152 myAnalyzer->SetPrecision ( prec );
155 //=======================================================================
156 //function : ClearModes
158 //=======================================================================
160 void ShapeFix_Wire::ClearModes()
162 myTopoMode = Standard_False;
163 myGeomMode = Standard_True;
164 myClosedMode = Standard_True;
165 myPreference2d = Standard_True;
166 myFixGapsByRanges = Standard_False;
168 myRemoveLoopMode = -1;
170 myFixReversed2dMode = -1;
171 myFixRemovePCurveMode = -1;
172 myFixRemoveCurve3dMode = -1;
173 myFixAddPCurveMode = -1;
174 myFixAddCurve3dMode = -1;
176 myFixShiftedMode = -1;
177 myFixSameParameterMode = -1;
178 myFixVertexToleranceMode = -1;
180 myFixNotchedEdgesMode = -1;
181 myFixSelfIntersectingEdgeMode = -1;
182 myFixIntersectingEdgesMode = -1;
183 myFixNonAdjacentIntersectingEdgesMode = -1;
185 myFixReorderMode = -1;
187 myFixConnectedMode = -1;
188 myFixEdgeCurvesMode = -1;
189 myFixDegeneratedMode = -1;
190 myFixSelfIntersectionMode = -1;
191 myFixLackingMode = -1;
192 myFixGaps3dMode = -1;
193 myFixGaps2dMode = -1;
196 //=======================================================================
197 //function : ClearStatuses
199 //=======================================================================
201 void ShapeFix_Wire::ClearStatuses()
203 Standard_Integer emptyStatus = ShapeExtend::EncodeStatus ( ShapeExtend_OK );
205 myLastFixStatus = emptyStatus;
207 myStatusReorder = emptyStatus;
208 myStatusSmall = emptyStatus;
209 myStatusConnected = emptyStatus;
210 myStatusEdgeCurves = emptyStatus;
211 myStatusDegenerated = emptyStatus;
212 myStatusSelfIntersection = emptyStatus;
213 myStatusLacking = emptyStatus;
214 myStatusGaps3d = emptyStatus; //szv#9:S4244:19Aug99 new method introduced
215 myStatusGaps2d = emptyStatus; //szv#9:S4244:19Aug99 new method introduced
216 myStatusClosed = emptyStatus;
219 //=======================================================================
222 //=======================================================================
224 void ShapeFix_Wire::Init (const TopoDS_Wire& wire,
225 const TopoDS_Face &face, const Standard_Real prec)
229 SetPrecision ( prec );
232 //=======================================================================
235 //=======================================================================
237 void ShapeFix_Wire::Init (const Handle(ShapeAnalysis_Wire)& saw)
242 // SetPrecision ( saw.Precision() );
245 //=======================================================================
248 //=======================================================================
250 void ShapeFix_Wire::Load (const TopoDS_Wire& wire)
254 TopoDS_Wire W = wire;
255 if ( ! Context().IsNull() ) {
256 TopoDS_Shape S = Context()->Apply ( wire );
257 W = TopoDS::Wire ( S );
260 myAnalyzer->Load ( W );
264 //=======================================================================
267 //=======================================================================
269 void ShapeFix_Wire::Load (const Handle(ShapeExtend_WireData)& sbwd)
272 myAnalyzer->Load ( sbwd );
273 if ( ! Context().IsNull() ) UpdateWire();
277 //=======================================================================
280 //=======================================================================
282 Standard_Integer ShapeFix_Wire::NbEdges() const
284 Handle(ShapeExtend_WireData) sbwd = myAnalyzer->WireData();
285 return sbwd.IsNull() ? 0 : sbwd->NbEdges();
288 //#######################################################################
289 // Fixing methods of API level
290 //#######################################################################
292 //=======================================================================
294 //purpose : This method performs all the available fixes.
295 // If some fix is turned on or off explicitly by the flag,
296 // it is called or not depending on that flag
297 // Else (i.e. if flag is default) fix is called depending on the
298 // situation: default is True, but some fixes are not called or
299 // are limited if order of edges in the wire is not OK
300 //=======================================================================
302 Standard_Boolean ShapeFix_Wire::Perform()
305 if ( ! IsLoaded() ) return Standard_False;
308 Standard_Integer Fixed = Standard_False;
310 // FixReorder is first, because as a rule wire is required to be ordered
311 // We shall analyze the order of edges in the wire and set appropriate
312 // status even if FixReorder should not be called (if it is forbidden)
314 ShapeAnalysis_WireOrder sawo;
315 Standard_Boolean ReorderOK = ( myAnalyzer->CheckOrder ( sawo, myClosedMode ) ==0 );
316 if ( NeedFix ( myFixReorderMode, ! ReorderOK ) ) {
317 if(FixReorder()) Fixed = Standard_True;
318 ReorderOK = ! StatusReorder ( ShapeExtend_FAIL );
321 // FixSmall is allowed to change topology only if mode is set and FixReorder
323 if ( NeedFix ( myFixSmallMode, myTopoMode ) ) {
324 if ( FixSmall ( ! myTopoMode || ! ReorderOK, MinTolerance() ) ) {
325 Fixed = Standard_True;
326 // retry reorder if necessary (after FixSmall it can work better)
327 if ( NeedFix ( myFixReorderMode, ! ReorderOK ) ) {
329 ReorderOK = ! StatusReorder ( ShapeExtend_FAIL );
334 if ( NeedFix ( myFixConnectedMode, ReorderOK ) ) {
335 if ( FixConnected() ) Fixed = Standard_True;
338 if ( NeedFix ( myFixEdgeCurvesMode ) ) {
339 Standard_Integer savFixShiftedMode = myFixShiftedMode;
340 // turn out FixShifted if reorder not done
341 if ( myFixShiftedMode == -1 && ! ReorderOK ) myFixShiftedMode = 0;
342 if ( FixEdgeCurves() ) Fixed = Standard_True;
343 myFixShiftedMode = savFixShiftedMode;
346 if ( NeedFix ( myFixDegeneratedMode ) ) {
347 if ( FixDegenerated() ) Fixed = Standard_True; // ?? if ! ReorderOK ??
350 //pdn - temporary to test
351 if ( NeedFix ( myFixNotchedEdgesMode, ReorderOK ) ) {
352 Fixed |= FixNotchedEdges();
353 if(Fixed) FixShifted(); //skl 07.03.2002 for OCC180
356 if ( NeedFix ( myFixSelfIntersectionMode, myClosedMode ) ) {
357 Standard_Integer savFixIntersectingEdgesMode = myFixIntersectingEdgesMode;
358 // switch off FixIntEdges if reorder not done
359 if ( myFixIntersectingEdgesMode == -1 && ! ReorderOK )
360 myFixIntersectingEdgesMode = 0;
361 if ( FixSelfIntersection() ) Fixed = Standard_True;
363 myFixIntersectingEdgesMode = savFixIntersectingEdgesMode;
366 if ( NeedFix ( myFixLackingMode, ReorderOK ) ) {
367 if ( FixLacking() ) Fixed = Standard_True;
370 // TEMPORARILY without special mode !!!
371 Handle(ShapeExtend_WireData) sbwd = WireData();
372 for (Standard_Integer iedge = 1; iedge <= sbwd->NbEdges(); iedge++)
373 if ( myFixEdge->FixVertexTolerance (sbwd->Edge (iedge)) )
374 Fixed = Standard_True;
379 //=======================================================================
380 //function : FixReorder
382 //=======================================================================
384 Standard_Boolean ShapeFix_Wire::FixReorder()
386 myStatusReorder = ShapeExtend::EncodeStatus ( ShapeExtend_OK );
387 if ( ! IsLoaded() ) return Standard_False;
390 ShapeAnalysis_WireOrder sawo;
391 myAnalyzer->CheckOrder ( sawo, myClosedMode, Standard_True );
393 //:abv revolCuts.sat -23: in case of bi-periodic surface check case
394 // of reversed wire specifically. This is necessary because degenerated
395 // cases are possible when direct evaluation will give bad result.
396 Standard_Boolean isReorder = Standard_False;
397 if ( sawo.Status() != 0 &&
398 ! myAnalyzer->Surface().IsNull() &&
399 myAnalyzer->Surface()->Surface()->IsUPeriodic() &&
400 myAnalyzer->Surface()->Surface()->IsVPeriodic() ) {
401 Handle(ShapeExtend_WireData) sbwd2 = new ShapeExtend_WireData;
402 for ( Standard_Integer i=WireData()->NbEdges(); i >=1; i-- )
403 sbwd2->Add ( WireData()->Edge(i) );
404 ShapeAnalysis_WireOrder sawo2;
405 ShapeAnalysis_Wire analyzer2 ( sbwd2, myAnalyzer->Face(), Precision() );
406 analyzer2.CheckOrder ( sawo2, myClosedMode, Standard_True );
407 if ( ( sawo2.Status() >=0 && sawo2.Status() < sawo.Status() ) ||
408 ( sawo.Status() <0 && sawo2.Status() > sawo.Status() ) ) {
409 WireData()->Init ( sbwd2 );
411 isReorder = Standard_True;
417 if ( LastFixStatus ( ShapeExtend_FAIL ) )
418 myStatusReorder |= ShapeExtend::EncodeStatus ( LastFixStatus ( ShapeExtend_FAIL1 ) ?
419 ShapeExtend_FAIL1 : ShapeExtend_FAIL2 );
420 if ( ! LastFixStatus ( ShapeExtend_DONE )&& !isReorder ) return Standard_False;
422 myStatusReorder |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE1 );
423 if ( sawo.Status() ==2 || sawo.Status() ==-2 )
424 myStatusReorder |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE2 );
425 if ( sawo.Status() <0 )
426 myStatusReorder |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE3 );
427 return Standard_True;
430 //=======================================================================
431 //function : FixSmall
433 //=======================================================================
435 Standard_Integer ShapeFix_Wire::FixSmall (const Standard_Boolean lockvtx,
436 const Standard_Real precsmall)
438 myStatusSmall = ShapeExtend::EncodeStatus ( ShapeExtend_OK );
439 if ( ! IsLoaded() ) return Standard_False;
441 for ( Standard_Integer i = NbEdges(); i >0; i-- ) {
442 FixSmall ( i, lockvtx, precsmall );
443 myStatusSmall |= myLastFixStatus;
446 return StatusSmall ( ShapeExtend_DONE );
450 //=======================================================================
451 //function : FixConnected
453 //=======================================================================
455 Standard_Boolean ShapeFix_Wire::FixConnected (const Standard_Real prec)
457 myStatusConnected = ShapeExtend::EncodeStatus ( ShapeExtend_OK );
458 if ( ! IsLoaded() ) return Standard_False;
460 Standard_Integer stop = ( myClosedMode ? 0 : 1 );
461 for ( Standard_Integer i = NbEdges(); i > stop; i-- ) {
462 FixConnected ( i, prec );
463 myStatusConnected |= myLastFixStatus;
466 return StatusConnected ( ShapeExtend_DONE );
469 //=======================================================================
470 //function : FixEdgeCurves
472 //=======================================================================
474 Standard_Boolean ShapeFix_Wire::FixEdgeCurves()
476 myStatusEdgeCurves = ShapeExtend::EncodeStatus ( ShapeExtend_OK );
477 if ( ! IsLoaded() ) return Standard_False;
478 Standard_Boolean isReady = IsReady();
480 Handle(ShapeExtend_WireData) sbwd = WireData();
481 Standard_Integer i, nb = sbwd->NbEdges();
482 TopoDS_Face face = Face();
483 Handle(ShapeFix_Edge) theAdvFixEdge = Handle(ShapeFix_Edge)::DownCast(myFixEdge);
484 if (theAdvFixEdge.IsNull()) myFixReversed2dMode = Standard_False;
486 // fix revesred 2d / 3d curves
487 if ( isReady && NeedFix ( myFixReversed2dMode ) ) {
488 for ( i=1; i <= nb; i++ ) {
489 theAdvFixEdge->FixReversed2d ( sbwd->Edge(i), face );
490 if ( theAdvFixEdge->Status ( ShapeExtend_DONE ) )
491 myStatusEdgeCurves |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE1 );
492 if ( theAdvFixEdge->Status ( ShapeExtend_FAIL ) )
493 myStatusEdgeCurves |= ShapeExtend::EncodeStatus ( ShapeExtend_FAIL1 );
497 // add / remove pcurve
498 if ( isReady && NeedFix ( myFixRemovePCurveMode, Standard_False ) ) {
499 for ( i=1; i <= nb; i++ ) {
500 myFixEdge->FixRemovePCurve ( sbwd->Edge(i), face );
501 if ( myFixEdge->Status ( ShapeExtend_DONE ) )
502 myStatusEdgeCurves |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE2 );
503 if ( myFixEdge->Status ( ShapeExtend_FAIL ) )
504 myStatusEdgeCurves |= ShapeExtend::EncodeStatus ( ShapeExtend_FAIL2 );
508 if ( isReady && NeedFix ( myFixAddPCurveMode ) ) {
509 Standard_Integer overdegen = 0; //:c0
510 for ( i=1; i <= nb; i++ ) {
511 myFixEdge->FixAddPCurve ( sbwd->Edge(i), face, sbwd->IsSeam(i),
512 myAnalyzer->Surface(), Precision() );
513 if ( myFixEdge->Status ( ShapeExtend_DONE ) )
514 myStatusEdgeCurves |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE3 );
515 if ( myFixEdge->Status ( ShapeExtend_FAIL ) )
516 myStatusEdgeCurves |= ShapeExtend::EncodeStatus ( ShapeExtend_FAIL3 );
518 //if ( !sbwd->IsSeam(i) && myFixEdge->Status ( ShapeExtend_DONE2 )
519 // && BRep_Tool::SameParameter(sbwd->Edge(i)) ) {
520 if ( !sbwd->IsSeam(i) && myFixEdge->Status ( ShapeExtend_DONE2 ) ) {
521 // abv 24 Feb 00: trj3_s1-ac-214.stp #1631 etc.: try to split the edge in singularity
522 if ( ! Context().IsNull() ) {
524 TopoDS_Edge E = sbwd->Edge ( i );
525 ShapeAnalysis_Curve SAC;
527 Handle(Geom_Curve) C = BRep_Tool::Curve ( E, a, b );
528 Handle(ShapeAnalysis_Surface) S = myAnalyzer->Surface();
529 Standard_Integer nbs = S->NbSingularities(MinTolerance());
530 GeomAdaptor_Curve GAC ( C, a, b );
531 TColStd_SequenceOfReal seq;
532 for (Standard_Integer j=1; j <= nbs; j++) {
536 Standard_Real par1, par2, split;
537 Standard_Boolean tmpUIsoDeg;
538 S->Singularity (j, Preci, P3d, pd1, pd2, par1, par2, tmpUIsoDeg);
539 if ( SAC.Project ( GAC, P3d, MinTolerance(), pr, split, Standard_True ) < Max(Preci,MinTolerance()) ) {
540 if ( split - a > ::Precision::PConfusion() &&
541 b - split > ::Precision::PConfusion() ) {
543 for ( k=1; k <= seq.Length(); k++ ) {
544 if ( split < seq(k)-::Precision::PConfusion() ) {
545 seq.InsertBefore ( k, split );
548 else if ( split < seq(k)+::Precision::PConfusion() ) break;
550 if ( k > seq.Length() ) seq.Append ( split );
554 if ( seq.Length() >0 ) { // supposed that edge is SP
556 cout << "Edge going over singularity detected; splitted" << endl;
558 Standard_Boolean isFwd = ( E.Orientation() == TopAbs_FORWARD );
559 E.Orientation ( TopAbs_FORWARD );
561 //if( BRep_Tool::SameParameter(sbwd->Edge(i)) )
562 // sbe.RemovePCurve ( E, face );
564 //10.04.2003 skl for using trimmed lines as pcurves
565 ShapeAnalysis_Edge sae;
566 if( BRep_Tool::SameParameter(sbwd->Edge(i)) )
567 sbe.RemovePCurve ( E, face );
569 if(sae.HasPCurve(E,face)) {
570 Handle(Geom2d_Curve) C2d;
571 Standard_Real fp2d,lp2d;
572 if(sae.PCurve(E,face,C2d,fp2d,lp2d)) {
573 if( !C2d->IsKind(STANDARD_TYPE(Geom2d_TrimmedCurve)) )
574 sbe.RemovePCurve(E,face);
579 // myFixEdge->FixSameParameter ( E ); // to ensure SameRange & SP
581 TopoDS_Vertex V1, V2, V;
582 //ShapeAnalysis_Edge sae;
583 V1 = sae.FirstVertex ( E );
584 V2 = sae.LastVertex ( E );
585 Handle(ShapeExtend_WireData) sw = new ShapeExtend_WireData;
586 for ( Standard_Integer k=0; k <= seq.Length(); k++ ) {
587 Standard_Real split = ( k < seq.Length() ? seq(k+1) : b );
588 if ( k < seq.Length() )
589 B.MakeVertex ( V, C->Value(split), BRep_Tool::Tolerance(E) );
591 TopoDS_Edge edge = sbe.CopyReplaceVertices ( E, V1, V );
592 if( BRep_Tool::SameParameter(sbwd->Edge(i)) ) {
593 //TopoDS_Edge edge = sbe.CopyReplaceVertices ( E, V1, V );
594 B.Range ( edge, a, split );
598 //TopoDS_Edge edge = sbe.CopyReplaceVertices(sbwd->Edge(i),V1,V);
599 Handle(ShapeAnalysis_TransferParameters) sftp =
600 new ShapeAnalysis_TransferParameters(E,face);
601 sftp->TransferRange(edge, a, split, Standard_False);
610 E.Orientation ( TopAbs_REVERSED );
612 Context()->Replace ( E, sw->Wire() );
614 nb = sbwd->NbEdges();
624 //:c0 abv 20 Feb 98: treat case of curve going over degenerated pole and seam
625 if ( overdegen && myAnalyzer->Surface()->IsUClosed(Precision()) ) {
627 Standard_Real URange, SUF, SUL, SVF, SVL;
628 myAnalyzer->Surface()->Bounds(SUF, SUL, SVF, SVL);
629 URange = (Abs(SUL - SUF));
631 ShapeAnalysis_Edge sae;
633 for ( k = 1; k <= nb; k++) {
634 Standard_Real cf, cl;
635 Handle(Geom2d_Curve) c2d;
636 if ( ! sae.PCurve ( sbwd->Edge(k), face, c2d, cf, cl, Standard_True ) ) break;
637 vec += c2d->Value(cl).XY() - c2d->Value(cf).XY();
639 if ( k > nb && Abs ( Abs ( vec.X() ) - URange ) < 0.1 * URange ) {
640 sbe.RemovePCurve (sbwd->Edge ( overdegen ), face);
641 myFixEdge->Projector()->AdjustOverDegenMode() = Standard_False;
642 myFixEdge->FixAddPCurve ( sbwd->Edge(overdegen), face, sbwd->IsSeam(overdegen), myAnalyzer->Surface(), Precision());
645 cout << "Edge going over singularity detected; pcurve adjusted" << endl;
650 // add / remove pcurve
651 if ( isReady && NeedFix ( myFixRemoveCurve3dMode, Standard_False ) ) {
652 for ( i=1; i <= nb; i++ ) {
653 myFixEdge->FixRemoveCurve3d ( sbwd->Edge(i) );
654 if ( myFixEdge->Status ( ShapeExtend_DONE ) )
655 myStatusEdgeCurves |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE4 );
656 if ( myFixEdge->Status ( ShapeExtend_FAIL ) )
657 myStatusEdgeCurves |= ShapeExtend::EncodeStatus ( ShapeExtend_FAIL4 );
660 if ( NeedFix ( myFixAddCurve3dMode ) ) {
661 for ( i=1; i <= nb; i++ ) {
662 myFixEdge->FixAddCurve3d ( sbwd->Edge(i) );
663 if ( myFixEdge->Status ( ShapeExtend_DONE ) )
664 myStatusEdgeCurves |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE5 );
665 if ( myFixEdge->Status ( ShapeExtend_FAIL ) ) {
666 //:abv 29.08.01: Spatial_firex_lofting.sat: if 3d curve cannot
667 // be built because edge has no pcurves either, remove that edge
668 Handle(Geom2d_Curve) C;
669 Handle(Geom_Surface) S;
671 Standard_Real first, last;
672 BRep_Tool::CurveOnSurface ( sbwd->Edge(i), C, S, L, first, last );
675 SendWarning ( sbwd->Edge ( i ), Message_Msg ( "FixWire.FixCurve3d.Removed" ) );// Incomplete edge (with no pcurves or 3d curve) removed
676 sbwd->Remove ( i-- );
678 myStatusEdgeCurves |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE5 );
680 myStatusEdgeCurves |= ShapeExtend::EncodeStatus ( ShapeExtend_FAIL5 );
686 if ( isReady && NeedFix ( myFixSeamMode, Standard_False ) ) {
687 for ( i=1; i <= nb; i++ ) {
689 if ( LastFixStatus ( ShapeExtend_DONE ) )
690 myStatusEdgeCurves |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE6 );
691 if ( LastFixStatus ( ShapeExtend_FAIL ) )
692 myStatusEdgeCurves |= ShapeExtend::EncodeStatus ( ShapeExtend_FAIL6 );
697 if ( isReady && NeedFix ( myFixShiftedMode ) ) {
699 if ( LastFixStatus ( ShapeExtend_DONE ) )
700 myStatusEdgeCurves |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE7 );
701 if ( LastFixStatus ( ShapeExtend_FAIL ) )
702 myStatusEdgeCurves |= ShapeExtend::EncodeStatus ( ShapeExtend_FAIL7 );
705 // fix same parameter
706 if ( isReady && NeedFix ( myFixSameParameterMode ) ) {
707 for ( i=1; i <= nb; i++ ) {
708 // skl 28.10.2004 for OCC6366 - check SameRange
709 ShapeAnalysis_Edge sae;
710 Standard_Real First, Last;
711 Handle(Geom_Curve) tmpc3d = BRep_Tool::Curve(sbwd->Edge(i), First, Last);
712 if(sae.HasPCurve(sbwd->Edge(i),face)) {
713 Handle(Geom2d_Curve) C2d;
714 Standard_Real fp2d,lp2d;
715 if(sae.PCurve(sbwd->Edge(i),face,C2d,fp2d,lp2d)) {
716 if( fabs(First-fp2d)>Precision::PConfusion() ||
717 fabs(Last-fp2d)>Precision::PConfusion() ) {
719 B.SameRange(sbwd->Edge(i),Standard_False);
723 myFixEdge->FixSameParameter ( sbwd->Edge(i) );
724 if ( myFixEdge->Status ( ShapeExtend_DONE ) )
725 myStatusEdgeCurves |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE8 );
726 if ( myFixEdge->Status ( ShapeExtend_FAIL ) )
727 myStatusEdgeCurves |= ShapeExtend::EncodeStatus ( ShapeExtend_FAIL8 );
731 //:abv 10.06.02: porting C40 -> dev (CC670-12608.stp): moved from Perform()
732 // Update with face is needed for plane surfaces (w/o stored pcurves)
733 if ( NeedFix ( myFixVertexToleranceMode ) ) {
734 for ( i=1; i <= nb; i++) {
735 myFixEdge->FixVertexTolerance (sbwd->Edge (i), face);
736 if ( myFixEdge->Status ( ShapeExtend_DONE ) )
737 myStatusEdgeCurves |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE8 );
738 if ( myFixEdge->Status ( ShapeExtend_FAIL ) )
739 myStatusEdgeCurves |= ShapeExtend::EncodeStatus ( ShapeExtend_FAIL8 );
743 return StatusEdgeCurves ( ShapeExtend_DONE );
746 //=======================================================================
747 //function : FixDegenerated
749 //=======================================================================
751 Standard_Boolean ShapeFix_Wire::FixDegenerated()
753 myStatusDegenerated = ShapeExtend::EncodeStatus ( ShapeExtend_OK );
754 if ( ! IsReady() ) return Standard_False;
756 // if ( ! myAnalyzer->Surface()->HasSingularities ( Precision() ) ) return;
758 Standard_Integer lastcoded = -1, prevcoded = 0;
759 Standard_Integer stop = ( myClosedMode ? 0 : 1 );
760 for ( Standard_Integer i = NbEdges(); i > stop; i-- ) {
761 FixDegenerated ( i );
762 myStatusDegenerated |= myLastFixStatus;
763 //:r0 abv 19 Mar 99: PRO7226.stp #489490: remove duplicated degenerated edges
764 Standard_Integer coded = ( LastFixStatus ( ShapeExtend_DONE2 ) ? 1 : 0 );
765 if ( lastcoded ==-1 ) lastcoded = coded;
766 if ( coded && ( prevcoded || ( i ==1 && lastcoded ) ) && NbEdges() >1 ) {
767 Handle(ShapeExtend_WireData) sbwd = WireData();
770 if ( ! prevcoded ) i = NbEdges();
771 B.Degenerated ( sbwd->Edge ( i++ ), Standard_False );
774 else prevcoded = coded;
777 return StatusDegenerated ( ShapeExtend_DONE );
781 //=======================================================================
782 //function : FixSelfIntersection
783 //purpose : Applies FixSelfIntersectingEdge and FixIntersectingEdges
784 // and removes wrong edges
785 //=======================================================================
787 Standard_Boolean ShapeFix_Wire::FixSelfIntersection()
789 myStatusSelfIntersection = ShapeExtend::EncodeStatus ( ShapeExtend_OK );
790 if ( ! IsReady() ) return Standard_False;
792 Handle(ShapeExtend_WireData) sbwd = WireData();
793 Standard_Integer nb = sbwd->NbEdges();
795 if ( NeedFix ( myFixSelfIntersectingEdgeMode ) ) {
796 if (myRemoveLoopMode<1)
797 for ( Standard_Integer num=1; num <=nb; num++ )
799 FixSelfIntersectingEdge ( num );
800 myStatusSelfIntersection |= myLastFixStatus;
802 else if (myRemoveLoopMode==1)
804 for ( Standard_Integer num=1; num <=nb; num++ )
806 FixSelfIntersectingEdge ( num );
807 myStatusSelfIntersection |= myLastFixStatus;
808 if(nb<sbwd->NbEdges()) num--;
809 nb = sbwd->NbEdges();
811 FixClosed(Precision());
815 if ( NeedFix ( myFixIntersectingEdgesMode ) ) {
816 Standard_Integer num = ( myClosedMode ? 1 : 2 );
817 for ( ; nb >1 && num <= nb; num++ ) {
818 FixIntersectingEdges ( num );
819 if ( LastFixStatus ( ShapeExtend_FAIL1 ) )
820 myStatusSelfIntersection |= ShapeExtend::EncodeStatus ( ShapeExtend_FAIL1 );
821 if ( LastFixStatus ( ShapeExtend_FAIL2 ) )
822 myStatusSelfIntersection |= ShapeExtend::EncodeStatus ( ShapeExtend_FAIL2 );
823 if ( ! LastFixStatus ( ShapeExtend_DONE ) ) continue;
825 if ( LastFixStatus ( ShapeExtend_DONE1 ) )
826 myStatusSelfIntersection |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE1 );
827 if ( LastFixStatus ( ShapeExtend_DONE2 ) )
828 myStatusSelfIntersection |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE2 );
829 if(LastFixStatus (ShapeExtend_DONE6))
830 myStatusSelfIntersection |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE6 );
832 if ( ! myTopoMode || nb < 3 ) {
833 //#86 rln 22.03.99 sim2.igs, entity 4292: After fixing of self-intersecting
834 //BRepCheck finds one more self-intersection not found by ShapeAnalysis
835 //%15 pdn 06.04.99 repeat until fixed CTS18546-2 entity 777
836 //FixIntersectingEdges ( num );
837 if ( LastFixStatus ( ShapeExtend_DONE7 ) ) num--;
841 if ( LastFixStatus ( ShapeExtend_DONE4 ) ) sbwd->Remove ( num );
842 if ( LastFixStatus ( ShapeExtend_DONE3 ) ) sbwd->Remove ( num >1 ? num-1 : nb+num-1 );
843 if ( LastFixStatus ( ShapeExtend_DONE4 ) ||
844 LastFixStatus ( ShapeExtend_DONE3 ) ) {
845 myStatusSelfIntersection |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE3 );
846 num = ( myClosedMode ? 1 : 2 );
847 nb = sbwd->NbEdges();
849 cout << "Warning: ShapeFix_Wire::FixSelfIntersection: Edge removed" << endl;
854 //%15 pdn 06.04.99 repeat until fixed CTS18546-2 entity 777
855 //FixIntersectingEdges ( num );
856 if ( LastFixStatus ( ShapeExtend_DONE7 ) ) num--;
861 //pdn 17.03.99 S4135 to avoid regression fixing not adjacent intersection
862 if ( NeedFix ( myFixNonAdjacentIntersectingEdgesMode ) ) {
864 ShapeFix_IntersectionTool ITool(Context(),Precision());
865 Standard_Integer NbSplit=0, NbCut=0,NbRemoved=0;
866 if(ITool.FixSelfIntersectWire(sbwd,myAnalyzer->Face(),NbSplit,NbCut,NbRemoved)) {
867 myStatusSelfIntersection |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE5 );//gka 06.09.04
869 if( NbSplit>0 || NbRemoved>0 ) {
870 if(NbRemoved>0) myStatusRemovedSegment = Standard_True;
871 //Load(sbwd); commented by skl 29.12.2004 for OCC7624, instead this
872 // string inserted following three strings:
873 myAnalyzer->Load ( sbwd );
874 if ( ! Context().IsNull() ) UpdateWire();
878 if (StatusSelfIntersection (ShapeExtend_DONE5))
879 cout<<"Warning: ShapeFix_Wire::FixIntersection: Non-adjacent intersection fixed (split-"
880 <<NbSplit<<", cut-"<<NbCut<<", removed-"<<NbRemoved<<")"<<endl;
884 Bnd_Array1OfBox2d boxes(1,nb);
886 const Handle(Geom_Surface)& S = BRep_Tool::Surface(Face(), L);
887 Handle(Geom2d_Curve) c2d;
889 ShapeAnalysis_Edge sae;
890 for(Standard_Integer i = 1; i <= nb; i++){
891 TopoDS_Edge E = sbwd->Edge (i);
892 if(sae.PCurve (E,S,L,c2d,cf,cl,Standard_False)) {
894 Geom2dAdaptor_Curve gac;
895 Standard_Real aFirst = c2d->FirstParameter();
896 Standard_Real aLast = c2d->LastParameter();
897 if(c2d->IsKind(STANDARD_TYPE(Geom2d_BSplineCurve))
898 && (cf < aFirst || cl > aLast)) {
899 //pdn avoiding problems with segment in Bnd_Box
904 BndLib_Add2dCurve::Add(gac,::Precision::Confusion(),box);
909 Standard_Boolean isFail = Standard_False, isDone = Standard_False;
910 for(Standard_Integer num1 = 1; num1 < nb-1; num1++) {
911 Standard_Integer fin = (num1 == 1 ? nb-1 : nb);
912 for(Standard_Integer num2 = num1+2; num2 <= fin; num2++)
913 if(!boxes(num1).IsOut(boxes(num2))){
914 FixIntersectingEdges (num1, num2);
915 isFail |= LastFixStatus ( ShapeExtend_FAIL1 );
916 isDone |= LastFixStatus ( ShapeExtend_DONE1 );
921 myStatusSelfIntersection |= ShapeExtend::EncodeStatus ( ShapeExtend_FAIL3 );
923 myStatusSelfIntersection |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE5 );
925 if (StatusSelfIntersection (ShapeExtend_DONE5))
926 cout << "Warning: ShapeFix_Wire::FixSelfIntersection: Non ajacent intersection fixed" << endl;
931 return StatusSelfIntersection ( ShapeExtend_DONE );
935 //=======================================================================
936 //function : FixLacking
938 //=======================================================================
940 Standard_Boolean ShapeFix_Wire::FixLacking ( const Standard_Boolean force )
942 myStatusLacking = ShapeExtend::EncodeStatus ( ShapeExtend_OK );
943 if ( ! IsReady() ) return Standard_False;
945 Standard_Integer start = ( myClosedMode ? 1 : 2 );
946 for ( Standard_Integer i = start; i <= NbEdges(); i++ ) {
947 FixLacking ( i, force );
948 myStatusLacking |= myLastFixStatus;
951 return StatusLacking ( ShapeExtend_DONE );
955 //=======================================================================
956 //function : FixClosed
958 //=======================================================================
960 Standard_Boolean ShapeFix_Wire::FixClosed (const Standard_Real prec)
962 myStatusClosed = ShapeExtend::EncodeStatus ( ShapeExtend_OK );
963 if ( ! IsLoaded() || NbEdges() <1 ) return Standard_False;
965 FixConnected ( 1, prec );
966 if ( LastFixStatus ( ShapeExtend_DONE ) )
967 myStatusClosed |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE1 );
968 if ( LastFixStatus ( ShapeExtend_FAIL ) )
969 myStatusClosed |= ShapeExtend::EncodeStatus ( ShapeExtend_FAIL1 );
971 FixDegenerated ( 1 );
972 if ( LastFixStatus ( ShapeExtend_DONE ) )
973 myStatusClosed |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE2 );
974 if ( LastFixStatus ( ShapeExtend_FAIL ) )
975 myStatusClosed |= ShapeExtend::EncodeStatus ( ShapeExtend_FAIL2 );
978 if ( LastFixStatus ( ShapeExtend_DONE ) )
979 myStatusClosed |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE3 );
980 if ( LastFixStatus ( ShapeExtend_FAIL ) )
981 myStatusClosed |= ShapeExtend::EncodeStatus ( ShapeExtend_FAIL3 );
983 return StatusClosed ( ShapeExtend_DONE );
987 //#######################################################################
988 // Fixing methods of advanced level
989 //#######################################################################
991 //=======================================================================
992 //function : FixReorder
994 //=======================================================================
996 Standard_Boolean ShapeFix_Wire::FixReorder (const ShapeAnalysis_WireOrder& wi)
998 myLastFixStatus = ShapeExtend::EncodeStatus ( ShapeExtend_OK );
999 if ( ! IsLoaded() ) return Standard_False;
1001 Standard_Integer status = wi.Status();
1002 if ( status ==0 ) return Standard_False;
1003 if ( status <=-10 ) {
1004 myLastFixStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_FAIL1 );
1005 return Standard_False;
1008 Handle(ShapeExtend_WireData) sbwd = WireData();
1009 Standard_Integer i, nb = sbwd->NbEdges();
1010 if ( nb != wi.NbEdges() ) {
1011 myLastFixStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_FAIL2 );
1012 return Standard_False;
1014 // D abord on protege
1015 for (i = 1; i <= nb; i ++) {
1016 if ( wi.Ordered(i) == 0 ) {
1017 myLastFixStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_FAIL3 );
1018 return Standard_False;
1022 Handle(TopTools_HSequenceOfShape) newedges = new TopTools_HSequenceOfShape();
1023 for ( i=1; i <= nb; i++ )
1024 newedges->Append ( sbwd->Edge ( wi.Ordered(i) ) );
1025 for ( i=1; i <= nb; i++ )
1026 sbwd->Set ( TopoDS::Edge ( newedges->Value(i) ), i );
1028 myLastFixStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE1 );
1029 return Standard_True;
1033 //=======================================================================
1034 //function : FixSmall
1036 //=======================================================================
1038 Standard_Boolean ShapeFix_Wire::FixSmall (const Standard_Integer num,
1039 const Standard_Boolean lockvtx,
1040 const Standard_Real precsmall)
1042 myLastFixStatus = ShapeExtend::EncodeStatus ( ShapeExtend_OK );
1043 if ( ! IsLoaded() || NbEdges() <=1 ) return Standard_False;
1046 Handle(ShapeAnalysis_Wire) theAdvAnalyzer = Handle(ShapeAnalysis_Wire)::DownCast(myAnalyzer);
1047 if (theAdvAnalyzer.IsNull()) return Standard_False;
1048 Standard_Integer n = ( num >0 ? num : NbEdges() );
1049 theAdvAnalyzer->CheckSmall ( n, precsmall );
1050 if ( theAdvAnalyzer->LastCheckStatus ( ShapeExtend_FAIL ) ) {
1051 myLastFixStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_FAIL1 );
1052 //:n2 return Standard_False;
1055 if ( ! theAdvAnalyzer->LastCheckStatus ( ShapeExtend_DONE ) ) return Standard_False;
1057 // OUI cette edge est NULLE
1059 if ( theAdvAnalyzer->LastCheckStatus ( ShapeExtend_DONE2 ) ) {
1060 // edge is small, but vertices are not the same..
1061 if ( lockvtx || ! myTopoMode ) {
1062 myLastFixStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_FAIL2 );
1063 return Standard_False;
1065 myLastFixStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE2 );
1067 else myLastFixStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE1 );
1069 // action: remove edge
1070 if ( ! Context().IsNull() )
1071 Context()->Remove(WireData()->Edge(n));
1072 SendWarning ( WireData()->Edge ( n ), Message_Msg ( "FixAdvWire.FixSmall.MSG0" ) ); //Small edge(s) removed
1073 WireData()->Remove ( n );
1075 // call FixConnected in the case if vertices of the small edge were not the same
1076 if ( LastFixStatus ( ShapeExtend_DONE2 ) ) {
1077 Standard_Integer savLastFixStatus = myLastFixStatus;
1078 //#43 rln 20.11.98 S4054 CTS18544 entity 21734 removing last edge
1079 FixConnected ( n <= NbEdges() ? n : 1, precsmall );
1080 if ( LastFixStatus ( ShapeExtend_FAIL ) )
1081 savLastFixStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_FAIL3 );
1082 myLastFixStatus = savLastFixStatus;
1085 return Standard_True;
1089 //=======================================================================
1090 //function : FixConnected
1092 //=======================================================================
1094 Standard_Boolean ShapeFix_Wire::FixConnected (const Standard_Integer num,
1095 const Standard_Real prec)
1097 myLastFixStatus = ShapeExtend::EncodeStatus ( ShapeExtend_OK );
1098 if ( ! IsLoaded() || NbEdges() <=0 ) return Standard_False;
1102 myAnalyzer->CheckConnected ( num, prec < 0 ? MaxTolerance() : prec );
1103 if ( myAnalyzer->LastCheckStatus ( ShapeExtend_FAIL ) ) {
1104 myLastFixStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_FAIL1 );
1106 if ( ! myAnalyzer->LastCheckStatus ( ShapeExtend_DONE ) ) return Standard_False;
1108 // action: replacing vertex
1110 Handle(ShapeExtend_WireData) sbwd = WireData();
1111 Standard_Integer n2 = ( num >0 ? num : sbwd->NbEdges() );
1112 Standard_Integer n1 = ( n2 >1 ? n2-1 : sbwd->NbEdges() );
1113 TopoDS_Edge E1 = sbwd->Edge(n1);
1114 TopoDS_Edge E2 = sbwd->Edge(n2);
1116 ShapeAnalysis_Edge sae;
1117 TopoDS_Vertex V1 = sae.LastVertex (E1);
1118 TopoDS_Vertex V2 = sae.FirstVertex (E2);
1121 if ( myAnalyzer->LastCheckStatus ( ShapeExtend_DONE1 ) ) { // absolutely confused
1122 myLastFixStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE1 );
1123 //#40 rln 18.11.98 S4054 BUC60035 entity 2393 (2-nd sub-curve is edge with the same vertex)
1124 if ( V2.IsSame ( sae.LastVertex (E2) ) ) {
1126 if ( ! Context().IsNull() )
1127 Context()->Replace ( V1, V.Oriented(V1.Orientation()) );
1131 if ( ! Context().IsNull() )
1132 Context()->Replace ( V2, V.Oriented(V2.Orientation()) );
1135 else { // on moyenne ...
1136 if ( myAnalyzer->LastCheckStatus ( ShapeExtend_DONE2 ) )
1137 myLastFixStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE2 );
1138 else myLastFixStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE3 );
1139 ShapeBuild_Vertex sbv;
1140 V = sbv.CombineVertex ( V1, V2, 1.0001 );
1141 if ( ! Context().IsNull() ) {
1142 Context()->Replace ( V1, V.Oriented(V1.Orientation()) );
1143 Context()->Replace ( V2, V.Oriented(V2.Orientation()) );
1147 // replace vertices to a new one
1148 ShapeBuild_Edge sbe;
1149 if ( sbwd->NbEdges() <2 ) {
1150 if(E2.Free() && myTopoMode) {
1152 B.Remove(E2,sae.FirstVertex(E2));
1153 B.Remove(E2,sae.LastVertex(E2));
1154 B.Add(E2,V.Oriented(TopAbs_FORWARD));
1155 B.Add(E2,V.Oriented(TopAbs_REVERSED));
1158 TopoDS_Edge tmpE = sbe.CopyReplaceVertices ( E2, V, V );
1159 sbwd->Set ( tmpE, n2 );
1160 if ( ! Context().IsNull() ) Context()->Replace(E2,tmpE);
1164 if(E2.Free() &&E1.Free() && myTopoMode) {
1166 B.Remove(E2,sae.FirstVertex(E2));
1167 B.Add(E2,V.Oriented(TopAbs_FORWARD));
1168 if ( ! myAnalyzer->LastCheckStatus ( ShapeExtend_DONE1 ) ||
1169 sae.FirstVertex (E2).IsSame (sae.LastVertex (E2)) ) {
1170 B.Remove(E1,sae.LastVertex(E1));
1171 B.Add(E1,V.Oriented(TopAbs_REVERSED));
1175 TopoDS_Edge tmpE2 = sbe.CopyReplaceVertices ( E2, V, TopoDS_Vertex() );
1176 sbwd->Set ( tmpE2, n2 );
1177 if ( ! Context().IsNull() ) Context()->Replace(E2,tmpE2);
1178 if ( ! myAnalyzer->LastCheckStatus ( ShapeExtend_DONE1 ) ||
1179 sae.FirstVertex (E2).IsSame (sae.LastVertex (E2)) ) {
1180 TopoDS_Edge tmpE1 = sbe.CopyReplaceVertices ( E1, TopoDS_Vertex(), V );
1181 sbwd->Set (tmpE1, n1 );
1182 if ( ! Context().IsNull() ) Context()->Replace(E1,tmpE1);
1186 if ( ! Context().IsNull() ) UpdateWire();
1188 return Standard_True;
1192 //=======================================================================
1193 //function : FixSeam
1195 //=======================================================================
1197 Standard_Boolean ShapeFix_Wire::FixSeam (const Standard_Integer num)
1199 myLastFixStatus = ShapeExtend::EncodeStatus ( ShapeExtend_OK );
1200 if ( ! IsReady() ) return Standard_False;
1202 Handle(Geom2d_Curve) C1, C2;
1203 Standard_Real cf, cl;
1204 if ( ! myAnalyzer->CheckSeam (num, C1, C2, cf, cl) ) return Standard_False;
1207 TopoDS_Edge E = WireData()->Edge ( num >0 ? num : NbEdges() );
1208 B.UpdateEdge (E, C2,C1, Face(), 0.); //:S4136: BRep_Tool::Tolerance(E)
1209 B.Range (E, Face(),cf,cl);
1210 myLastFixStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE1 );
1212 return Standard_True;
1215 //=======================================================================
1216 //function : FixShifted
1217 //purpose : fix parametric curves which may be shifted
1218 // to whole parametric range of closed surface as result of recomputing
1219 // from 3d representation.
1220 // This can be a curve on a seam or near it.
1221 // This function is to be called before FixDegenerated.
1222 // LIMITATION: this function cannot fix cases when, e.g., closed wire is
1223 // composed of two meridians of the sphere and one of them is seam.
1224 // NOTE: wire is supposed to be closed and sorted !
1225 //=======================================================================
1227 //:p4 abv 23.02.99: PRO9234 #15720: update UV points of edge
1228 static void UpdateEdgeUVPoints (TopoDS_Edge &E, const TopoDS_Face &F)
1230 Standard_Real first, last;
1231 BRep_Tool::Range ( E, F, first, last );
1232 BRep_Builder().Range ( E, F, first, last );
1236 //=======================================================================
1237 //function : FixShifted
1239 //=======================================================================
1241 Standard_Boolean ShapeFix_Wire::FixShifted()
1243 myLastFixStatus = ShapeExtend::EncodeStatus ( ShapeExtend_OK );
1244 if ( ! IsReady() ) return Standard_False;
1246 Handle(ShapeAnalysis_Surface) surf = myAnalyzer->Surface();
1247 //#78 rln 12.03.99 S4135: checking spatial closure with Precision
1248 Standard_Boolean uclosed = surf->IsUClosed(Precision());
1249 Standard_Boolean vclosed = surf->IsVClosed(Precision()) || surf->Surface()->IsKind (STANDARD_TYPE(Geom_SphericalSurface));
1250 //#67 rln 01.03.99 S4135: ims010.igs entity D11900 (2D contour is 2*PI higher than V range [-pi/2,p/2])
1252 // PTV 26.06.2002 begin
1253 // CTS18546-2.igs entity 2222: base curve is periodic and 2dcurve is shifted
1254 Standard_Boolean IsVCrvClosed = Standard_False;
1255 Standard_Real VRange = 1.;
1256 if (surf->Surface()->IsKind (STANDARD_TYPE(Geom_SurfaceOfRevolution))) {
1257 Handle(Geom_SurfaceOfRevolution) aSurOfRev = Handle(Geom_SurfaceOfRevolution)::DownCast(surf->Surface());
1258 Handle(Geom_Curve) aBaseCrv = aSurOfRev->BasisCurve();
1259 while ( (aBaseCrv->IsKind(STANDARD_TYPE(Geom_OffsetCurve))) ||
1260 (aBaseCrv->IsKind(STANDARD_TYPE(Geom_TrimmedCurve))) ) {
1261 if (aBaseCrv->IsKind(STANDARD_TYPE(Geom_OffsetCurve)))
1262 aBaseCrv = Handle(Geom_OffsetCurve)::DownCast(aBaseCrv)->BasisCurve();
1263 if (aBaseCrv->IsKind(STANDARD_TYPE(Geom_TrimmedCurve)))
1264 aBaseCrv = Handle(Geom_TrimmedCurve)::DownCast(aBaseCrv)->BasisCurve();
1266 if (aBaseCrv->IsPeriodic()) {
1267 vclosed = Standard_True;
1268 VRange = aBaseCrv->Period();
1269 IsVCrvClosed = Standard_True;
1271 cout << "Warning: ShapeFix_Wire::FixShifted set vclosed True for Surface of Revolution" << endl;
1275 // PTV 26.06.2002 end
1276 if ( ! uclosed && ! vclosed ) return Standard_False;
1278 Standard_Real URange, /*VRange,*/ SUF, SUL, SVF, SVL;
1279 surf->Surface()->Bounds ( SUF, SUL, SVF, SVL );
1280 Standard_Real SUMid, SVMid;
1281 SUMid = 0.5*(SUF+SUL);
1282 SVMid = 0.5*(SVF+SVL);
1283 if (uclosed) URange = Abs ( SUL - SUF );
1284 else URange = RealLast();
1286 if (vclosed) VRange = Abs ( SVL - SVF );
1287 else VRange = RealLast();
1288 Standard_Real UTol = 0.2 * URange, VTol = 0.2 * VRange;
1290 Handle(ShapeExtend_WireData) sbwdOring = WireData();
1291 ShapeAnalysis_Edge sae;
1292 Handle(ShapeExtend_WireData) sbwd = new ShapeExtend_WireData;
1293 for ( Standard_Integer i=1; i <= sbwdOring->NbEdges(); i++ ) {
1294 TopoDS_Edge E1 = sbwdOring->Edge ( i );
1295 if ( BRep_Tool::Degenerated(E1) && !sae.HasPCurve(E1,Face()))
1301 ShapeBuild_Edge sbe;
1302 Standard_Integer nb = sbwd->NbEdges();
1303 Standard_Boolean end = (nb == 0), degstop = Standard_False;;
1304 Standard_Integer stop = nb;
1305 Standard_Integer degn2 = 0;
1307 //pdn 17.12.98 r0901_ec 38237 to shift wire at 0
1309 //GeomAdaptor_Surface& GAS = myAnalyzer->Surface()->Adaptor3d()->ChangeSurface(); //SK
1311 for ( Standard_Integer n2=1, n1=nb; ! end; n1 = n2++ ) {
1312 if ( n2 > nb ) n2 = 1;
1313 if ( n2 == stop ) end = Standard_True;
1315 TopoDS_Edge E1 = sbwd->Edge ( n1 );
1316 TopoDS_Edge E2 = sbwd->Edge ( n2 );
1318 if ( BRep_Tool::Degenerated(E1) || BRep_Tool::Degenerated(E2) ) {
1319 if ( ! degstop ) { stop = n2; degstop = Standard_True; }
1323 TopoDS_Vertex V = sae.FirstVertex ( E2 );
1324 gp_Pnt p = BRep_Tool::Pnt ( V );
1326 Standard_Real a1, b1, a2, b2;
1327 Handle(Geom2d_Curve) c2d1, c2d2;
1329 //:abv 29.08.01: torCuts.sat: distinguish degeneration by U and by V;
1330 // only corresponding move is prohibited
1331 // Standard_Boolean isDeg = surf->IsDegenerated ( p, Max ( Precision(), BRep_Tool::Tolerance(V) ) );
1332 Standard_Integer isDeg = 0;
1333 gp_Pnt2d degP1, degP2;
1334 Standard_Real degT1, degT2;
1335 if ( surf->DegeneratedValues ( p, Max ( Precision(), BRep_Tool::Tolerance(V) ),
1336 degP1, degP2, degT1, degT2 ) )
1337 isDeg = ( Abs ( degP1.X() - degP2.X() ) > Abs ( degP1.Y() - degP2.Y() ) ? 1 : 2 );
1339 // abv 23 Feb 00: UKI60107-6 210: additional check for near-degenerated case
1340 //smh#15 PRO19800. Check if the surface is surface of revolution.
1341 if (surf->Surface()->IsKind (STANDARD_TYPE(Geom_SurfaceOfRevolution))) {
1342 if ( ! isDeg && ! vclosed ) {
1343 if ( c2d1.IsNull() && ! sae.PCurve ( E1, Face(), c2d1, a1, b1, Standard_True ) ) continue;
1344 gp_Pnt2d p1 ( SUF, c2d1->Value(b1).Y() );
1345 gp_Pnt2d p2 ( SUL, c2d1->Value(b1).Y() );
1346 if ( surf->IsDegenerated ( p1, p2, MaxTolerance(), 10 ) &&
1347 ! 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
1350 if ( ! isDeg && ! uclosed ) {
1351 if ( c2d1.IsNull() && ! sae.PCurve ( E1, Face(), c2d1, a1, b1, Standard_True ) ) continue;
1352 gp_Pnt2d p1 ( c2d1->Value(b1).X(), SVF );
1353 gp_Pnt2d p2 ( c2d1->Value(b1).X(), SVL );
1354 if ( surf->IsDegenerated ( p1, p2, MaxTolerance(), 10 ) &&
1355 ! 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
1361 if ( ! degstop ) { stop = n2; degstop = Standard_True; }
1362 if ( ! degn2 ) { degn2 = n2; pdeg = p; }
1363 else if ( pdeg.SquareDistance(p) < Precision()*Precision() ) {
1365 // if ( stop < n2 ) { stop = n2; degstop = Standard_True; }
1368 Standard_Real ax1, bx1, ax2, bx2;
1369 Handle(Geom2d_Curve) cx1, cx2;
1370 if ( ( c2d1.IsNull() && ! sae.PCurve ( E1, Face(), c2d1, a1, b1, Standard_True ) ) ||
1371 ( c2d2.IsNull() && ! sae.PCurve ( E2, Face(), c2d2, a2, b2, Standard_True ) ) ||
1372 ! sae.PCurve ( sbwd->Edge ( degn2 >1 ? degn2-1 : nb ), Face(), cx1, ax1, bx1, Standard_True ) ||
1373 ! sae.PCurve ( sbwd->Edge ( degn2 ), Face(), cx2, ax2, bx2, Standard_True ) ) {
1374 myLastFixStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_FAIL1 );
1377 gp_Pnt2d pd1 = cx1->Value ( bx1 );
1378 gp_Pnt2d pd2 = cx2->Value ( ax2 );
1379 gp_Pnt2d pn1 = c2d1->Value ( b1 );
1380 gp_Pnt2d pn2 = c2d2->Value ( a2 );
1381 gp_Vec2d x(0.,0.); // shift vector
1382 Standard_Real period;
1383 if ( uclosed ) { x.SetX ( 1. ); period = URange; }
1384 else { x.SetY ( 1. ); period = VRange; }
1385 Standard_Real rot1 = ( pn1.XY() - pd2.XY() ) ^ x.XY();
1386 Standard_Real rot2 = ( pd1.XY() - pn2.XY() ) ^ x.XY();
1387 Standard_Real scld = ( pd2.XY() - pd1.XY() ) * x.XY();
1388 Standard_Real scln = ( pn2.XY() - pn1.XY() ) * x.XY();
1389 if ( rot1 * rot2 < -::Precision::PConfusion() &&
1390 scld * scln < -::Precision::PConfusion() &&
1391 Abs ( scln ) > 0.1 * period && Abs ( scld ) > 0.1 * period &&
1392 rot1 * scld > ::Precision::PConfusion() &&
1393 rot2 * scln > ::Precision::PConfusion() ) {
1394 // abv 02 Mar 00: trying more sophisticated analysis (ie_exhaust-A.stp #37520)
1395 Standard_Real sign = ( rot2 >0 ? 1. : -1. );
1396 Standard_Real deep1 = Min ( sign * ( pn2.XY() * x.XY() ),
1397 Min ( sign * ( pd1.XY() * x.XY() ),
1398 Min ( sign * ( c2d2->Value(b2 ).XY() * x.XY() ),
1399 Min ( sign * ( cx1->Value(ax1).XY() * x.XY() ),
1400 Min ( sign * ( c2d2->Value(0.5*(a2 +b2 )).XY() * x.XY() ),
1401 sign * ( cx1->Value(0.5*(ax1+bx1)).XY() * x.XY() ) ) ) ) ) );
1402 Standard_Real deep2 = Max ( sign * ( pn1.XY() * x.XY() ),
1403 Max ( sign * ( pd2.XY() * x.XY() ),
1404 Max ( sign * ( c2d1->Value(a1 ).XY() * x.XY() ),
1405 Max ( sign * ( cx2->Value(bx2).XY() * x.XY() ),
1406 Max ( sign * ( c2d1->Value(0.5*(a1 +b1 )).XY() * x.XY() ),
1407 sign * ( cx2->Value(0.5*(ax2+bx2)).XY() * x.XY() ) ) ) ) ) );
1408 Standard_Real deep = deep2 - deep1; // estimated current size of wire by x
1409 // pdn 30 Oct 00: trying correct period [0,period] (trj5_k1-tc-203.stp #4698)
1410 Standard_Real dx = ShapeAnalysis::AdjustToPeriod ( deep, ::Precision::PConfusion(), period+::Precision::PConfusion());
1411 x *= ( scld >0 ? -dx : dx );
1412 // x *= ( Abs(scld-scln) > 1.5 * period ? 2. : 1. ) *
1413 // ( scld >0 ? -period : period );
1415 Shift.SetTranslation ( x );
1416 for ( Standard_Integer k=degn2; ; k++ ) {
1417 if ( k > nb ) k = 1;
1418 if ( k == n2 ) break;
1419 TopoDS_Edge edge = sbwd->Edge ( k );
1420 if ( ! sae.PCurve ( edge, Face(), cx1, ax1, bx1, Standard_True ) ) continue;
1421 //cx1->Transform ( Shift );
1422 // skl 15.05.2002 for OCC208 (if few edges have reference to one pcurve)
1423 Handle(Geom2d_Curve) cx1new = Handle(Geom2d_Curve)::DownCast(cx1->Transformed(Shift));
1424 sbe.ReplacePCurve(edge,cx1new,Face());
1425 UpdateEdgeUVPoints ( edge, Face() );
1427 myLastFixStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE1 );
1429 cout << "Info: ShapeFix_Wire::FixShifted(): bi - meridian case fixed" << endl;
1432 // degn2 = n2; pdeg = p; // ie_exhaust-A.stp #37520
1436 // pdn to fix half sphere
1437 TopoDS_Vertex VE = sae.LastVertex ( E2 );
1438 gp_Pnt pe = BRep_Tool::Pnt ( VE );
1439 //pdn is second vertex on singular point ?
1440 if ( surf->IsDegenerated ( pe, Max ( Precision(), BRep_Tool::Tolerance(V) ) ) ) {
1441 if ( ( c2d1.IsNull() && ! sae.PCurve ( E1, Face(), c2d1, a1, b1, Standard_True ) ) ||
1442 ( c2d2.IsNull() && ! sae.PCurve ( E2, Face(), c2d2, a2, b2, Standard_True ) ) ) {
1443 myLastFixStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_FAIL1 );
1446 gp_Pnt2d p2d1 = c2d1->Value ( b1 ), p2f = c2d2->Value ( a2 ), p2l = c2d2->Value ( b2 );
1447 Standard_Real pres2 = ::Precision::PConfusion();
1448 Standard_Real du = 0.,dv = 0.;
1449 //#79 rln 15.03.99 S4135: bmarkmdl.igs entity 633 (incorrectly oriented contour) check for gap
1450 if(uclosed&&(Abs(p2f.X()-p2l.X())<pres2)&&Abs(p2d1.X()-p2f.X())>GAS.UResolution(Precision())) {
1451 if((Abs(p2f.X()-SUF)<pres2)&&(p2f.Y()<p2l.Y()))
1453 if((Abs(p2f.X()-SUL)<pres2)&&(p2f.Y()>p2l.Y()))
1456 if(vclosed&&(Abs(p2f.Y()-p2l.Y())<pres2)&&Abs(p2d1.Y()-p2f.Y())>GAS.VResolution(Precision())) {
1457 if((Abs(p2f.Y()-SVF)<pres2)&&(p2f.X()>p2l.X()))
1459 if((Abs(p2f.Y()-SVL)<pres2)&&(p2f.X()<p2l.X()))
1462 if ( du ==0. && dv == 0. ) continue;
1463 myLastFixStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE1 );
1465 Shift.SetTranslation ( gp_Vec2d ( du, dv ) );
1466 c2d2->Transform ( Shift );
1467 UpdateEdgeUVPoints ( E2, Face() );//rln 15.03.99 syntax correction :E1
1470 //:abv 29.08.01: torCuts.sat: continue;
1473 if ( ( c2d1.IsNull() && ! sae.PCurve ( E1, Face(), c2d1, a1, b1, Standard_True ) ) ||
1474 ( c2d2.IsNull() && ! sae.PCurve ( E2, Face(), c2d2, a2, b2, Standard_True ) ) ) {
1475 myLastFixStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_FAIL1 );
1478 gp_Pnt2d p2d1 = c2d1->Value ( b1 );
1479 gp_Pnt2d p2d2 = c2d2->Value ( a2 );
1482 Standard_Real du=0., dv=0.;
1483 if ( uclosed && isDeg != 1 ) {
1484 Standard_Real dx = Abs ( p2d2.X() - p2d1.X() );
1485 if ( dx > URange - UTol )
1486 du = ShapeAnalysis::AdjustByPeriod ( p2d2.X(), p2d1.X(), URange );
1487 else if ( dx > UTol && stop == nb ) stop = n2; //:abv 29.08.01: torCuts2.stp
1489 if ( vclosed && isDeg != 2 ) {
1490 Standard_Real dy = Abs ( p2d2.Y() - p2d1.Y() );
1491 if ( dy > VRange - VTol )
1492 dv = ShapeAnalysis::AdjustByPeriod ( p2d2.Y(), p2d1.Y(), VRange );
1493 else if ( dy > VTol && stop == nb ) stop = n2;
1495 if ( du ==0. && dv == 0. ) continue;
1497 myLastFixStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE1 );
1499 Shift.SetTranslation ( gp_Vec2d ( du, dv ) );
1500 //c2d2->Transform ( Shift );
1501 // skl 15.05.2002 for OCC208 (if few edges have reference to one pcurve)
1502 Handle(Geom2d_Curve) c2d2new = Handle(Geom2d_Curve)::DownCast(c2d2->Transformed(Shift));
1503 sbe.ReplacePCurve(E2,c2d2new,Face());
1504 UpdateEdgeUVPoints ( E2, Face() );
1506 if ( box.IsVoid() ) return Standard_False; //#3 smh 01.04.99. S4163: Overflow, when box is void.
1508 Standard_Real umin, vmin, umax, vmax;
1509 box.Get ( umin, vmin, umax, vmax );
1510 if ( Abs ( umin + umax - SUF - SUL ) < URange &&
1511 Abs ( vmin + vmax - SVF - SVL ) < VRange &&
1512 ! LastFixStatus ( ShapeExtend_DONE ) ) return Standard_False;
1515 Standard_Integer n; // svv Jan11 2000 : porting on DEC
1516 for ( n=1; n <= nb; n++ ) {
1518 Handle(Geom2d_Curve) c2d;
1519 if ( ! sae.PCurve ( sbwd->Edge(n), Face(), c2d, a, b, Standard_True ) ) continue;
1520 box.Add ( c2d->Value ( a ) );
1521 box.Add ( c2d->Value ( 0.5 * ( a + b ) ) );
1523 box.Get ( umin, vmin, umax, vmax );
1525 Standard_Real du=0., dv=0.;
1528 Standard_Real umid = 0.5 * ( umin + umax );
1529 // du = ShapeAnalysis::AdjustToPeriod(umid, SUF, SUL);
1530 // PTV 26.06.2002 xloop torus-apple iges face mode
1531 du = ShapeAnalysis::AdjustByPeriod(umid, SUMid, URange);
1534 Standard_Real vmid = 0.5 * ( vmin + vmax );
1535 // dv = ShapeAnalysis::AdjustToPeriod(vmid, SVF, SVL);
1536 // PTV 26.06.2002 xloop torus-apple iges face mode
1537 dv = ShapeAnalysis::AdjustByPeriod(vmid, SVMid, VRange);
1540 if ( du ==0. && dv == 0. ) return Standard_True;
1542 myLastFixStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE2 );
1545 Shift.SetTranslation ( gp_Vec2d ( du, dv ) );
1547 for ( n=1; n <= sbwdOring->NbEdges(); n++ ) {
1549 Handle(Geom2d_Curve) c2d;
1550 TopoDS_Edge ed = sbwdOring->Edge(n);
1551 if ( ! sae.PCurve ( ed, Face(), c2d, a, b, Standard_True ) ) continue;
1552 // skl 15.05.2002 for OCC208 (if few edges have reference to one pcurve)
1553 Handle(Geom2d_Curve) c2d2 = Handle(Geom2d_Curve)::DownCast(c2d->Transformed(Shift));
1554 sbe.ReplacePCurve(ed,c2d2,Face());
1555 UpdateEdgeUVPoints ( ed, Face() );
1557 return Standard_True;
1560 //=======================================================================
1561 //function : FixDegenerated
1563 //=======================================================================
1565 Standard_Boolean ShapeFix_Wire::FixDegenerated (const Standard_Integer num)
1567 myLastFixStatus = ShapeExtend::EncodeStatus ( ShapeExtend_OK );
1568 if ( ! IsReady() ) return Standard_False;
1571 gp_Pnt2d p2d1, p2d2;
1572 myAnalyzer->CheckDegenerated ( num, p2d1, p2d2 );
1573 if ( myAnalyzer->LastCheckStatus ( ShapeExtend_FAIL1 ) ) {
1574 myLastFixStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_FAIL1 );
1576 //: abv 29.08.01: torHalf2.sat: if edge was encoded as degenerated but
1577 // has no pcurve and no singularity is found at that point, remove it
1578 if ( myAnalyzer->LastCheckStatus ( ShapeExtend_FAIL2 ) ) {
1579 WireData()->Remove ( num );
1580 myLastFixStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE3 );
1581 return Standard_True;
1583 if ( ! myAnalyzer->LastCheckStatus ( ShapeExtend_DONE ) ) return Standard_False;
1585 // action: create degenerated edge and insert it (or replace)
1587 gp_Vec2d vect2d ( p2d1, p2d2 );
1588 gp_Dir2d dir2d ( vect2d );
1589 Handle(Geom2d_Line) line2d = new Geom2d_Line ( p2d1, dir2d );
1591 TopoDS_Edge degEdge;
1593 B.MakeEdge ( degEdge );
1594 B.Degenerated ( degEdge, Standard_True );
1595 B.UpdateEdge ( degEdge, line2d, Face(), ::Precision::Confusion() );
1596 B.Range ( degEdge, Face(), 0., vect2d.Magnitude() );
1598 Handle(ShapeExtend_WireData) sbwd = WireData();
1599 Standard_Integer n2 = ( num >0 ? num : sbwd->NbEdges() );
1600 Standard_Integer n1 = ( n2 >1 ? n2-1 : sbwd->NbEdges() );
1602 Standard_Boolean lack = myAnalyzer->LastCheckStatus ( ShapeExtend_DONE1 );
1603 Standard_Integer n3 = ( lack ? n2 : ( n2 < sbwd->NbEdges() ? n2+1 : 1 ) );
1605 ShapeAnalysis_Edge sae;
1606 TopoDS_Vertex V1 = sae.LastVertex ( sbwd->Edge ( n1 ) );
1607 TopoDS_Vertex V2 = sae.FirstVertex ( sbwd->Edge ( n3 ) );
1609 V1.Orientation(TopAbs_FORWARD);
1610 V2.Orientation(TopAbs_REVERSED);
1613 degEdge.Orientation(TopAbs_FORWARD);
1616 sbwd->Add ( degEdge, n2 );
1617 myLastFixStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE1 );
1620 sbwd->Set ( degEdge, n2 );
1621 myLastFixStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE2 );
1624 // commented to avoid extra messages
1625 // SendWarning ( degEdge, Message_Msg ( "FixWire.FixDegenerated.MSG0" ) );// Degenerated edge(s) detected
1627 return Standard_True;
1630 //=======================================================================
1631 //function : FixSelfIntersectingEdge
1632 //purpose : Tests edge for self-intersection and updates tolerance of vertex
1633 // if intersection is found
1634 // Returns True if tolerance was increased
1635 //=======================================================================
1637 // Create edge on basis of E with new pcurve and call FixSP
1638 // Return resulting tolerance and modified pcurve
1639 static Standard_Boolean TryNewPCurve (const TopoDS_Edge &E, const TopoDS_Face &face,
1640 Handle(Geom2d_Curve) &c2d,
1641 Standard_Real &first,
1642 Standard_Real &last,
1646 Handle(Geom_Curve) crv = BRep_Tool::Curve ( E, f, l );
1647 if ( crv.IsNull() ) return Standard_False;
1649 // make temp edge and compute tolerance
1650 BRepBuilderAPI_MakeEdge mkedge ( crv, f, l );
1652 ShapeBuild_Edge SBE; //skl 17.07.2001
1653 SBE.SetRange3d(mkedge,f,l); //skl 17.07.2001
1655 if ( ! mkedge.IsDone() ) return Standard_False;
1657 TopoDS_Edge edge = mkedge;
1659 B.UpdateEdge ( edge, c2d, face, 0. );
1660 B.Range ( edge, face, first, last );
1661 B.SameRange ( edge, Standard_False );
1662 // no call to BRepLib: B.SameParameter ( edge, Standard_False );
1664 Handle(ShapeFix_Edge) sfe = new ShapeFix_Edge;
1665 sfe->FixSameParameter ( edge );
1666 c2d = BRep_Tool::CurveOnSurface ( edge, face, first, last );
1667 tol = BRep_Tool::Tolerance ( edge );
1668 return Standard_True;
1671 //:k3 abv 24 Dec 98: BUC50070 #26682 and #30087:
1672 // Try to cut out the loop on the pcurve and make new pcurve by concatenating
1674 // If result is not SameParameter with prec, does nothing and returns False
1675 // Warning: resulting pcurve will be C0
1677 //=======================================================================
1678 //function : howMuchPCurves
1680 //=======================================================================
1681 static Standard_Integer howMuchPCurves (const TopoDS_Edge &E)
1683 Standard_Integer count = 0;
1684 BRep_ListIteratorOfListOfCurveRepresentation itcr
1685 ((*((Handle(BRep_TEdge)*)&E.TShape()))->ChangeCurves());
1687 while (itcr.More()) {
1688 const Handle(BRep_CurveRepresentation)& cr = itcr.Value();
1689 if ( cr->IsCurveOnSurface() )
1698 //=======================================================================
1699 //function : RemoveLoop
1701 //=======================================================================
1702 static Standard_Boolean RemoveLoop (TopoDS_Edge &E, const TopoDS_Face &face,
1703 const IntRes2d_IntersectionPoint &IP,
1704 const Standard_Real tolfact,
1705 const Standard_Real prec,
1706 const Standard_Boolean RemoveLoop3d)
1708 Standard_Boolean loopRemoved3d;
1709 if ( BRep_Tool::IsClosed ( E, face ) ) return Standard_False;
1712 Handle(Geom_Curve) crv = BRep_Tool::Curve ( E, f, l );
1714 Standard_Real t1 = IP.ParamOnFirst();
1715 Standard_Real t2 = IP.ParamOnSecond();
1716 if ( t1 > t2 ) { Standard_Real t = t1; t1 = t2; t2 = t; }
1718 ShapeAnalysis_Edge sae;
1720 Handle(Geom2d_Curve) c2d;
1721 if ( ! sae.PCurve ( E, face, c2d, a, b, Standard_False ) )
1722 return Standard_False;
1725 cout << "Cut Loop: params (" << t1 << ", " << t2;
1727 GeomAdaptor_Curve GAC ( crv, f, l );
1728 Standard_Real dt = tolfact * GAC.Resolution(prec);
1729 t1 -= dt; //1e-3;//::Precision::PConfusion();
1730 t2 += dt; //1e-3;//::Precision::PConfusion();
1732 cout << ") -> (" << t1 << ", " << t2 << ")" << endl;
1735 if ( t1 <= a || t2 >= b ) { // should not be so, but to be sure ..
1736 return Standard_False;
1739 // direct construction causes error on osf system.
1746 Handle(Geom_Plane) aPlaneSurf = Handle(Geom_Plane)::DownCast( BRep_Tool::Surface(face) );
1747 Handle(Geom_Curve) pcurve3d = crv;
1748 if ( !aPlaneSurf.IsNull() ) {
1749 Pln = aPlaneSurf->Pln();
1752 pcurve3d = GeomAPI::To3d ( c2d, Pln );
1755 //Handle(Geom_Curve) pcurve3d = GeomAPI::To3d ( c2d, Pln );
1756 Handle(Geom_TrimmedCurve) trim = new Geom_TrimmedCurve (pcurve3d, a, t1);
1757 GeomConvert_CompCurveToBSplineCurve connect ( trim );
1759 // null-length segment patch instead of loop
1760 TColgp_Array1OfPnt Poles(1,2);
1761 TColStd_Array1OfReal Knots(1,2);
1762 TColStd_Array1OfInteger Mults(1,2);
1764 Poles.SetValue(1,trim->Value(t1));
1765 Knots.SetValue(1,t1);
1766 Mults.SetValue(1,2);
1768 trim = new Geom_TrimmedCurve (pcurve3d, t2, b);
1769 Poles.SetValue(2,trim->Value(t2));
1770 Knots.SetValue(2,t2);
1771 Mults.SetValue(2,2);
1773 Handle(Geom_BSplineCurve) patch = new Geom_BSplineCurve ( Poles, Knots, Mults, 1 );
1774 if ( ! connect.Add (patch, ::Precision::PConfusion(), Standard_True, Standard_False) )
1775 return Standard_False;
1778 if ( ! connect.Add (trim, ::Precision::PConfusion(), Standard_True, Standard_False) )
1779 return Standard_False;
1781 // keep created 3d curve
1782 Handle(Geom_Curve) aNew3dCrv = connect.BSplineCurve();
1785 Handle(Geom2d_Curve) bs = GeomAPI::To2d ( aNew3dCrv, Pln );
1786 if ( bs.IsNull() ) return Standard_False;
1788 // make temp edge and compute tolerance
1791 if(!RemoveLoop3d) { // old variant (not remove loop 3d)
1792 Standard_Real newtol=0;
1794 Standard_Integer nbC2d = howMuchPCurves( E );
1795 if ( nbC2d <= 1 && !aPlaneSurf.IsNull() )
1796 B.UpdateEdge ( E, bs, face, 0 );
1798 if ( ! TryNewPCurve ( E, face, bs, a, b, newtol ) ) return Standard_False;
1800 Standard_Real tol = BRep_Tool::Tolerance ( E );
1802 cout << "Cut Loop: tol orig " << tol << ", prec " << prec << ", new tol " << newtol << endl;
1804 if ( newtol > Max ( prec, tol ) ) return Standard_False;
1805 //:s2 bs = BRep_Tool::CurveOnSurface ( edge, face, a, b );
1806 if ( Abs ( a - f ) > ::Precision::PConfusion() || // smth strange, cancel
1807 Abs ( b - l ) > ::Precision::PConfusion() ) return Standard_False;
1809 if ( !aPlaneSurf.IsNull() ) {
1810 B.UpdateEdge ( E, aNew3dCrv, Max (newtol, tol) );
1812 if ( ! TryNewPCurve ( E, face, bs, a, b, newtol ) ) return Standard_False;
1814 B.UpdateEdge ( E, bs, face, newtol );
1815 B.UpdateVertex ( sae.FirstVertex ( E ), newtol );
1816 B.UpdateVertex ( sae.LastVertex ( E ), newtol );
1817 return Standard_True;
1822 Handle(Geom_Surface) S = BRep_Tool::Surface(face, L);
1823 Handle(Geom2dAdaptor_HCurve) AC = new Geom2dAdaptor_HCurve(c2d);
1824 Handle(GeomAdaptor_HSurface) AS = new GeomAdaptor_HSurface(S);
1826 Adaptor3d_CurveOnSurface ACS(AC,AS);
1827 gp_Pnt P1(ACS.Value(t1));
1828 gp_Pnt P2(ACS.Value(t2));
1829 gp_Pnt pcurPnt((P1.X()+P2.X())/2,(P1.Y()+P2.Y())/2,(P1.Z()+P2.Z())/2);
1831 ShapeAnalysis_TransferParametersProj SFTP(E,face);
1832 Handle(TColStd_HSequenceOfReal) Seq2d = new TColStd_HSequenceOfReal;
1835 Seq2d->Append((t1+t2)/2);
1836 Handle(TColStd_HSequenceOfReal) Seq3d = new TColStd_HSequenceOfReal;
1837 Seq3d->Append(SFTP.Perform(Seq2d,Standard_False));
1839 Standard_Real dist1 = pcurPnt.Distance(crv->Value(Seq3d->Value(1)));// correting Seq3d already project
1840 Standard_Real dist2 = pcurPnt.Distance(crv->Value(Seq3d->Value(2)));
1841 Standard_Real dist3 = pcurPnt.Distance(crv->Value(Seq3d->Value(3)));
1842 Standard_Real ftrim,ltrim;
1843 if(dist3>Max(dist1,dist2)) {
1844 loopRemoved3d = Standard_False;
1847 loopRemoved3d = Standard_True;
1850 Handle(Geom_Curve) bs1;
1852 if (!loopRemoved3d) {
1853 // create new 3d curve
1854 ftrim = Seq3d->Value(1);
1855 ltrim = Seq3d->Value(2);
1858 Handle(Geom_TrimmedCurve) trim1 = new Geom_TrimmedCurve (crv, f, ftrim);
1859 GeomConvert_CompCurveToBSplineCurve connect1 ( trim1 );
1860 TColgp_Array1OfPnt Poles1(1,2);
1861 TColStd_Array1OfReal Knots1(1,2);
1862 TColStd_Array1OfInteger Mults1(1,2);
1864 Poles1.SetValue(1,trim1->Value(ftrim));
1865 Knots1.SetValue(1,ftrim);
1866 Mults1.SetValue(1,2);
1868 trim1 = new Geom_TrimmedCurve (crv, ltrim, l);
1869 Poles1.SetValue(2,trim1->Value(ltrim));
1870 Knots1.SetValue(2,ltrim);
1871 Mults1.SetValue(2,2);
1873 // create b-spline curve
1874 Handle(Geom_BSplineCurve) patch1 = new Geom_BSplineCurve ( Poles1, Knots1, Mults1, 1 );
1876 if ( ! connect1.Add (patch1, ::Precision::PConfusion(), Standard_True, Standard_False) )
1877 return Standard_False;
1880 if ( ! connect1.Add (trim1, ::Precision::PConfusion(), Standard_True, Standard_False) )
1881 return Standard_False;
1883 bs1 = connect1.BSplineCurve();
1886 return Standard_False;
1888 // Standard_Real oldtol = BRep_Tool::Tolerance ( E );
1891 B.UpdateEdge ( E, bs1, L, 0. );
1892 B.UpdateEdge ( E, bs, face, 0. );
1893 B.Range ( E, face, f, l );
1894 B.SameRange ( E, Standard_False );
1896 Handle(ShapeFix_Edge) sfe = new ShapeFix_Edge;
1897 sfe->FixSameParameter ( E );
1899 return Standard_True;
1902 //=======================================================================
1903 //function : RemoveLoop
1905 //=======================================================================
1906 static Standard_Boolean RemoveLoop (TopoDS_Edge &E, const TopoDS_Face &face,
1907 const IntRes2d_IntersectionPoint &IP2d,
1912 cout<<"Info: ShapeFix_Wire::FixSelfIntersection : Try insert vertex"<<endl;
1915 if ( BRep_Tool::IsClosed ( E, face ) ) return Standard_False;
1918 Handle(Geom_Curve) crv = BRep_Tool::Curve ( E, f, l );
1920 Standard_Real t1 = IP2d.ParamOnFirst();
1921 Standard_Real t2 = IP2d.ParamOnSecond();
1925 Standard_Real t = t1; t1 = t2; t2 = t;
1928 ShapeAnalysis_Edge sae;
1930 // define vertexes Vfirst , Vlast, Vmid
1931 TopoDS_Vertex Vfirst,Vlast,Vmid;
1932 // initialize Vfirst and Vlast
1933 Vfirst = sae.FirstVertex(E);
1934 Vlast = sae.LastVertex(E);
1936 // find a 2d curve and parameters from edge E
1938 Handle (Geom2d_Curve) c2d;
1939 if ( ! sae.PCurve ( E, face, c2d, a, b, Standard_False ) )
1940 return Standard_False;
1942 // first segment for 2d curve
1943 Handle(Geom2d_TrimmedCurve) trim1;
1944 if( (t1-a)>Precision::PConfusion() )
1945 trim1 = new Geom2d_TrimmedCurve (c2d, a, t1);
1946 // second segment for 2d curve
1947 Handle(Geom2d_TrimmedCurve) trim2 = new Geom2d_TrimmedCurve (c2d, t2, b);
1949 // if ( trim1.IsNull() || trim2.IsNull() )
1951 return Standard_False;
1954 Handle (Geom_Surface) S = BRep_Tool::Surface(face, L);
1955 Handle (Geom2dAdaptor_HCurve) AC = new Geom2dAdaptor_HCurve(c2d);
1956 Handle (GeomAdaptor_HSurface) AS = new GeomAdaptor_HSurface(S);
1958 Adaptor3d_CurveOnSurface ACS(AC,AS);
1959 gp_Pnt P1(ACS.Value(t1));
1960 gp_Pnt P2(ACS.Value(t2));
1961 gp_Pnt pcurPnt((P1.X()+P2.X())/2,(P1.Y()+P2.Y())/2,(P1.Z()+P2.Z())/2);
1963 // transfer parameters from pcurve to 3d curve
1964 ShapeAnalysis_TransferParametersProj SFTP(E,face);
1965 Handle (TColStd_HSequenceOfReal) Seq2d = new TColStd_HSequenceOfReal;
1968 Seq2d->Append((t1+t2)/2);
1969 Handle (TColStd_HSequenceOfReal) Seq3d = new TColStd_HSequenceOfReal;
1970 Seq3d->Append(SFTP.Perform(Seq2d,Standard_False));
1972 Standard_Real dist1 = pcurPnt.Distance(crv->Value(Seq3d->Value(1)));// correting Seq3d already project
1973 Standard_Real dist2 = pcurPnt.Distance(crv->Value(Seq3d->Value(2)));
1974 Standard_Real dist3 = pcurPnt.Distance(crv->Value(Seq3d->Value(3)));
1975 Standard_Real ftrim,ltrim;
1976 if ( dist3 > Max(dist1, dist2)) { // is loop in 3d
1977 ftrim = Seq3d->Value(1);
1978 ltrim = Seq3d->Value(2);
1980 else { // not loop in 3d
1981 ftrim = Seq3d->Value(3);
1982 ltrim = Seq3d->Value(3);
1985 // ftrim = Seq3d->Value(1);
1986 // ltrim = Seq3d->Value(2);
1988 // trim for 3d curve 'crv' with parameters from 'f' to 'l'
1989 Handle(Geom_TrimmedCurve) trim3;
1991 trim3 = new Geom_TrimmedCurve (crv, f, ftrim);
1992 // second segment for 3d curve
1993 Handle(Geom_TrimmedCurve) trim4 = new Geom_TrimmedCurve (crv, ltrim, l);
1995 // if ( trim3.IsNull() || trim4.IsNull() )
1997 return Standard_False;
1999 // create a point for middle vertex
2000 gp_Pnt pnt1 = crv->Value(ftrim);
2001 gp_Pnt pnt2 = crv->Value(ltrim);
2002 gp_Pnt Pmid((pnt1.X()+pnt2.X())/2,(pnt1.Y()+pnt2.Y())/2,(pnt1.Z()+pnt2.Z())/2);
2006 // create new copies for E1 and E2
2008 E1=TopoDS::Edge(E.EmptyCopied());
2009 E2=TopoDS::Edge(E.EmptyCopied());
2011 // initialize middle vertex Vmid
2013 B.MakeVertex(Vmid, pnt2, 0.);
2015 B.MakeVertex(Vmid, Pmid, 0.);
2017 ShapeBuild_Edge sbe;
2019 // replace verteces for new edges E1 and E2
2020 if (E.Orientation()== TopAbs_FORWARD)
2023 E1=sbe.CopyReplaceVertices(E1,Vfirst,Vmid);
2024 E2=sbe.CopyReplaceVertices(E2,Vmid, Vlast);
2029 E1=sbe.CopyReplaceVertices(E1,Vmid, Vlast);
2030 E2=sbe.CopyReplaceVertices(E2,Vfirst, Vmid);
2033 // Update edges by 2d and 3d curves
2034 Handle(ShapeFix_Edge) mySfe = new ShapeFix_Edge;
2036 B.UpdateEdge(E1, trim1, face, 0.);
2037 B.UpdateEdge(E1, trim3, 0.);
2038 B.Range(E1, f, ftrim);
2039 B.SameRange(E1,Standard_False);
2040 // B.SameParameter(E1,Standard_False);
2041 mySfe->FixSameParameter(E1);
2042 mySfe->FixVertexTolerance(E1);
2044 B.UpdateEdge(E2, trim2, face, 0.);
2045 B.UpdateEdge(E2, trim4, 0.);
2046 B.Range ( E2,ltrim,l );
2047 B.SameRange(E2, Standard_False );
2048 // B.SameParameter(E2, Standard_False);
2049 mySfe->FixSameParameter(E2);
2050 mySfe->FixVertexTolerance(E2);
2052 return Standard_True;
2056 //=======================================================================
2057 //function : FixSelfIntersectingEdge
2059 //=======================================================================
2061 Standard_Boolean ShapeFix_Wire::FixSelfIntersectingEdge (const Standard_Integer num)
2063 myLastFixStatus = ShapeExtend::EncodeStatus ( ShapeExtend_OK );
2064 if ( ! IsReady() ) return Standard_False;
2067 IntRes2d_SequenceOfIntersectionPoint points2d;
2068 TColgp_SequenceOfPnt points3d;
2069 Handle(ShapeAnalysis_Wire) theAdvAnalyzer = Handle(ShapeAnalysis_Wire)::DownCast(myAnalyzer);
2070 if (theAdvAnalyzer.IsNull()) return Standard_False;
2071 theAdvAnalyzer->CheckSelfIntersectingEdge ( num, points2d, points3d );
2072 if ( theAdvAnalyzer->LastCheckStatus ( ShapeExtend_FAIL ) ) {
2073 myLastFixStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_FAIL1 );
2075 if ( ! theAdvAnalyzer->LastCheckStatus ( ShapeExtend_DONE ) ) return Standard_False;
2077 // action: increase tolerance of vertex
2079 TopoDS_Edge E = WireData()->Edge ( num >0 ? num : NbEdges() );
2081 ShapeAnalysis_Edge sae;
2082 TopoDS_Vertex V1 = sae.FirstVertex ( E );
2083 TopoDS_Vertex V2 = sae.LastVertex ( E );
2084 Standard_Real tol1 = BRep_Tool::Tolerance ( V1 );
2085 Standard_Real tol2 = BRep_Tool::Tolerance ( V2 );
2086 gp_Pnt pnt1 = BRep_Tool::Pnt ( V1 );
2087 gp_Pnt pnt2 = BRep_Tool::Pnt ( V2 );
2089 // cycle is to verify fix in case of RemoveLoop
2090 Standard_Real tolfact = 0.1; // factor for shifting by parameter in RemoveLoop
2091 Standard_Real f2d, l2d;
2092 Handle(Geom2d_Curve) c2d;
2093 Standard_Real newtol=0.; // = Precision();
2095 if (myRemoveLoopMode<1) {
2096 for ( Standard_Integer iter=0; iter < 30; iter++ ) {
2097 Standard_Boolean loopRemoved = Standard_False;;
2098 Standard_Real prevFirst = 0 , prevLast = 0;
2099 for ( Standard_Integer i=1; i<=points2d.Length(); i++ ) {
2100 gp_Pnt pint = points3d.Value(i);
2101 Standard_Real dist21 = pnt1.SquareDistance ( pint );
2102 Standard_Real dist22 = pnt2.SquareDistance ( pint );
2103 if ( dist21 < tol1 * tol1 || dist22 < tol2 * tol2 ) continue;
2104 newtol = 1.001 * Sqrt ( Min ( dist21, dist22 ) ); //:f8
2106 //:k3 abv 24 Dec 98: BUC50070 #26682 and #30087: try to remove loop
2109 sae.PCurve ( E, Face(), c2d, f2d, l2d, Standard_False );
2110 Standard_Real firstpar = points2d.Value(i).ParamOnFirst();
2111 Standard_Real lastpar = points2d.Value(i).ParamOnSecond();
2112 if(firstpar > prevFirst && lastpar < prevLast) continue;
2113 if ( RemoveLoop (E, Face(), points2d.Value(i), tolfact,
2114 Min( MaxTolerance(), Max(newtol,Precision()) ),
2115 myRemoveLoopMode==0 ) ) {
2116 myLastFixStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE4 );
2117 loopRemoved = Standard_True;
2118 prevFirst = firstpar;
2120 continue; // repeat of fix on that edge required (to be done by caller)
2123 if ( newtol < MaxTolerance() ) {
2124 myLastFixStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE1 );
2126 if ( dist21 < dist22 ) B.UpdateVertex ( V1, tol1 = newtol );
2127 else B.UpdateVertex ( V2, tol2 = newtol );
2129 else myLastFixStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_FAIL2 );
2132 // after RemoveLoop, check that self-intersection disappeared
2133 if ( loopRemoved ) {
2134 IntRes2d_SequenceOfIntersectionPoint pnts2d;
2135 TColgp_SequenceOfPnt pnts3d;
2136 theAdvAnalyzer->CheckSelfIntersectingEdge ( num, pnts2d, pnts3d );
2137 if ( ! theAdvAnalyzer->LastCheckStatus ( ShapeExtend_DONE ) ) break;
2138 //points3d.Append(pnts3d);
2139 //points2d.Append(pnts2d);
2143 B.UpdateEdge ( E, c2d, Face(), 0. );
2144 B.Range ( E, Face(), f2d, l2d );
2145 //newtol+=Precision();
2153 //===============================================
2154 // RemoveLoopMode = 1 , insert vertex
2155 //===============================================
2156 if (myRemoveLoopMode == 1) {
2157 // after fixing will be nb+1 edges
2158 Standard_Boolean loopRemoved;
2159 // create a sequence of resulting edges
2160 Handle (TopTools_HSequenceOfShape) TTSS = new TopTools_HSequenceOfShape;
2163 loopRemoved = Standard_False;
2164 //:k3 abv 24 Dec 98: BUC50070 #26682 and #30087: try to remove loop
2167 sae.PCurve ( E, Face(), c2d, f2d, l2d, Standard_False );
2169 if ( RemoveLoop (E, Face(), points2d.Value(1),E1,E2) ) {
2170 myLastFixStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE4 );
2171 loopRemoved = Standard_True;
2174 newtol = Max(BRep_Tool::Tolerance(E1),BRep_Tool::Tolerance(E2));
2177 newtol = BRep_Tool::Tolerance(E2);
2183 if ( newtol > MaxTolerance() )
2184 myLastFixStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_FAIL2 );
2186 ShapeExtend_WireData sewd;
2187 for (Standard_Integer i=1 ; i <= TTSS->Length(); i++) {
2188 sewd.Add(TopoDS::Edge(TTSS->Value(i)));
2190 if (! Context().IsNull()) {
2191 Context()->Replace ( E, sewd.Wire() );
2195 WireData()->Remove(num >0 ? num : NbEdges());
2196 WireData()->Add(sewd.Wire(), num >0 ? num : NbEdges());
2199 myLastFixStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE8 );
2203 if ( LastFixStatus ( ShapeExtend_DONE ) && ! myShape.IsNull() ) {
2204 SendWarning ( E, Message_Msg ( "FixAdvWire.FixIntersection.MSG5" ) );// Edge was self-intersecting, corrected
2207 return LastFixStatus ( ShapeExtend_DONE );
2211 //=======================================================================
2212 //function : ComputeLocalDeviation
2213 //purpose : auxilary
2214 //=======================================================================
2215 static Standard_Real ComputeLocalDeviation (const TopoDS_Edge &edge,
2216 const gp_Pnt &pint,const gp_Pnt &pnt,
2217 Standard_Real f, Standard_Real l,
2218 const TopoDS_Face &face )
2220 ShapeAnalysis_Edge sae;
2221 Handle(Geom_Curve) c3d;
2223 if ( ! sae.Curve3d ( edge, c3d, a, b, Standard_False ) ) return RealLast();
2225 gp_Lin line ( pint, gp_Vec ( pint, pnt ) );
2227 Handle(Geom2d_Curve) Crv;
2228 Standard_Real fp,lp;
2229 if ( sae.PCurve(edge,face,Crv,fp,lp,Standard_False) ) {
2230 if(Crv->IsKind(STANDARD_TYPE(Geom2d_TrimmedCurve))) {
2231 Handle(Geom2d_TrimmedCurve) tc = Handle(Geom2d_TrimmedCurve)::DownCast(Crv);
2232 if(tc->BasisCurve()->IsKind(STANDARD_TYPE(Geom2d_Line))) {
2233 f = a + (f-fp)*(b-a)/(lp-fp);
2234 l = a + (l-fp)*(b-a)/(lp-fp);
2239 const Standard_Integer NSEG = 10;
2240 Standard_Real step = ( l - f ) / NSEG;
2241 Standard_Real dev = 0.;
2242 for ( Standard_Integer i=1; i < NSEG; i++ ) {
2243 gp_Pnt p = c3d->Value ( f + i * step );
2244 Standard_Real d = line.Distance ( p );
2245 if ( dev < d ) dev = d;
2250 //=======================================================================
2251 //function : FixIntersectingEdges
2253 //=======================================================================
2255 Standard_Boolean ShapeFix_Wire::FixIntersectingEdges (const Standard_Integer num)
2257 myLastFixStatus = ShapeExtend::EncodeStatus ( ShapeExtend_OK );
2258 if ( ! IsReady() || NbEdges() <2 ) return Standard_False;
2261 IntRes2d_SequenceOfIntersectionPoint points2d;
2262 TColgp_SequenceOfPnt points3d;
2263 TColStd_SequenceOfReal errors;
2264 Handle(ShapeAnalysis_Wire) theAdvAnalyzer = Handle(ShapeAnalysis_Wire)::DownCast(myAnalyzer);
2265 if (theAdvAnalyzer.IsNull()) return Standard_False;
2266 theAdvAnalyzer->CheckIntersectingEdges ( num, points2d, points3d, errors );
2267 if ( theAdvAnalyzer->LastCheckStatus ( ShapeExtend_FAIL ) ) {
2268 myLastFixStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_FAIL1 );
2270 if ( ! theAdvAnalyzer->LastCheckStatus ( ShapeExtend_DONE ) ) return Standard_False;
2272 //rln 03/02/98: CSR#BUC50004 entity 56 (to avoid later inserting lacking edge)
2273 //:l0 Standard_Boolean isLacking = myAnalyzer->CheckLacking ( num );
2275 // action: increase tolerance of vertex
2277 Handle(ShapeExtend_WireData) sbwd = WireData();
2278 Standard_Integer n2 = ( num >0 ? num : sbwd->NbEdges() );
2279 Standard_Integer n1 = ( n2 >1 ? n2-1 : sbwd->NbEdges() );
2280 TopoDS_Edge E1 = sbwd->Edge(n1);
2281 TopoDS_Edge E2 = sbwd->Edge(n2);
2282 Standard_Boolean isForward1 = ( E1.Orientation() == TopAbs_FORWARD );
2283 Standard_Boolean isForward2 = ( E2.Orientation() == TopAbs_FORWARD );
2284 Standard_Real a1, b1, a2, b2;
2285 BRep_Tool::Range ( E1, Face(), a1, b1 );
2286 BRep_Tool::Range ( E2, Face(), a2, b2 );
2288 ShapeAnalysis_Edge sae;
2289 TopoDS_Vertex Vp = sae.FirstVertex ( E1 );
2290 TopoDS_Vertex V1 = sae.LastVertex ( E1 );
2291 TopoDS_Vertex V2 = sae.FirstVertex ( E2 );
2292 TopoDS_Vertex Vn = sae.LastVertex ( E2 );
2294 Standard_Real tol = BRep_Tool::Tolerance ( V1 );
2295 gp_Pnt pnt = BRep_Tool::Pnt ( V1 );
2297 Standard_Real prevRange1 = RealLast(), prevRange2 = RealLast();
2298 Standard_Boolean cutEdge1 = Standard_False, cutEdge2 = Standard_False;
2299 Standard_Boolean IsCutLine = Standard_False;
2303 Standard_Integer nb = points3d.Length();
2304 for ( Standard_Integer i=1; i <= nb; i++ ) {
2305 const IntRes2d_IntersectionPoint &IP = points2d.Value(i);
2306 Standard_Real param1 = ( num ==1 ? IP.ParamOnSecond() : IP.ParamOnFirst() );
2307 Standard_Real param2 = ( num ==1 ? IP.ParamOnFirst() : IP.ParamOnSecond() );
2309 Standard_Real newRange1 = Abs ( ( isForward1 ? a1 : b1 ) - param1 );
2310 Standard_Real newRange2 = Abs ( ( isForward2 ? b2 : a2 ) - param2 );
2311 if ( newRange1 > prevRange1 && newRange2 > prevRange2 ) continue;
2313 gp_Pnt pint = points3d.Value(i);
2314 Standard_Real rad = errors.Value(i);
2315 Standard_Real newtol = 1.0001 * ( pnt.Distance ( pint ) + rad );
2317 // GeomAdaptor_Surface& Ads = myAnalyzer->Surface()->Adaptor3d()->ChangeSurface();
2319 //:r8 abv 12 Apr 99: try increasing tolerance of edge
2320 if ( ! myTopoMode && newtol > tol ) {
2321 Standard_Real te1 = rad + ComputeLocalDeviation (E1, pint, pnt,
2322 param1, ( isForward1 ? b1 : a1 ), Face() );
2323 Standard_Real te2 = rad + ComputeLocalDeviation (E2, pint, pnt,
2324 ( isForward2 ? a2 : b2 ), param2, Face() );
2325 Standard_Real maxte = Max ( te1, te2 );
2326 if ( maxte < MaxTolerance() && maxte < newtol ) {
2327 if ( BRep_Tool::Tolerance(E1) < te1 || BRep_Tool::Tolerance(E2) < te2 ) {
2329 // cout << "Warning: ShapeFix_Wire::FixIE: edges tolerance increased: (" <<
2330 // te1 << ", " << te2 << ") / " << newtol << endl;
2332 B.UpdateEdge ( E1, 1.000001 * te1 );
2333 B.UpdateVertex ( sae.FirstVertex ( E1 ), 1.000001 * te1 );
2334 B.UpdateVertex ( sae.LastVertex ( E1 ), 1.000001 * te1 );
2335 B.UpdateEdge ( E2, 1.000001 * te2 );
2336 B.UpdateVertex ( sae.FirstVertex ( E2 ), 1.000001 * te2 );
2337 B.UpdateVertex ( sae.LastVertex ( E2 ), 1.000001 * te2 );
2338 myLastFixStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE6 );
2340 newtol = 1.000001 * maxte;
2344 if ( myTopoMode || newtol <= MaxTolerance() ) {
2345 prevRange1 = newRange1;
2346 prevRange2 = newRange2;
2347 Standard_Boolean locMayEdit = myTopoMode;
2348 if ( myTopoMode ) { //:j6 abv 7 Dec 98: ProSTEP TR10 r0601_id.stp #57676 & #58586: do not cut edges because of influence on adjacent faces
2349 ShapeFix_SplitTool aTool;
2350 //if ( ! ShapeFix::CutEdge ( E1, ( isForward1 ? a1 : b1 ), param1, Face(), IsCutLine ) ) {
2351 if ( ! aTool.CutEdge ( E1, ( isForward1 ? a1 : b1 ), param1, Face(), IsCutLine ) ) {
2352 if ( V1.IsSame ( Vp ) )
2353 myLastFixStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE3 );
2354 else locMayEdit = Standard_False;
2356 else cutEdge1 = Standard_True; //:h4
2357 //if ( ! ShapeFix::CutEdge ( E2, ( isForward2 ? b2 : a2 ), param2, Face(), IsCutLine ) ) {
2358 if ( ! aTool.CutEdge ( E2, ( isForward2 ? b2 : a2 ), param2, Face(), IsCutLine ) ) {
2359 if ( V2.IsSame ( Vn ) )
2360 myLastFixStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE4 );
2361 else locMayEdit = Standard_False;
2363 else cutEdge2 = Standard_True; //:h4
2366 newRange1 <= prevRange1 && newRange2 <= prevRange2 && //rln 09/01/98
2367 BRep_Tool::SameParameter ( E1 ) &&
2368 BRep_Tool::SameParameter ( E2 ) ) {
2369 myLastFixStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE2 );
2372 myLastFixStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE1 );
2376 else if(IsCutLine) {
2377 myLastFixStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE2 );
2380 myLastFixStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE1 );
2384 else { // else increase tolerance
2385 if (tol < newtol) { //rln 07.04.99 CCI60005-brep.igs
2386 myLastFixStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE1 );
2391 else myLastFixStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_FAIL2 );
2394 if ( ! LastFixStatus ( ShapeExtend_DONE ) ) return Standard_False;
2396 B.UpdateVertex ( V1, pnt, tol );
2397 B.UpdateVertex ( V2, pnt, tol );
2399 //:h4: make edges SP (after all cuts: t4mug.stp #3730+#6460)
2400 if ( cutEdge1 ) myFixEdge->FixSameParameter ( E1 );
2401 if ( cutEdge2 && !IsCutLine ) myFixEdge->FixSameParameter ( E2 );
2402 if ( cutEdge1 || cutEdge2 ) {
2403 myLastFixStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE7 );
2405 if ( ! myShape.IsNull() ) {
2406 SendWarning ( Message_Msg ( "FixAdvWire.FixIntersection.MSG10" ) );// Edges were intersecting, corrected
2408 return Standard_True;
2411 //=======================================================================
2412 //function : FixIntersectingEdges
2414 //=======================================================================
2415 //pdn 17.03.99 fixing non ajacent intersection by increasing tolerance of vertex
2417 Standard_Boolean ShapeFix_Wire::FixIntersectingEdges (const Standard_Integer num1,
2418 const Standard_Integer num2)
2420 myLastFixStatus = ShapeExtend::EncodeStatus ( ShapeExtend_OK );
2421 if ( !IsReady() ) return Standard_False;
2422 IntRes2d_SequenceOfIntersectionPoint points2d;
2423 TColgp_SequenceOfPnt points3d;
2424 TColStd_SequenceOfReal errors;
2425 Handle(ShapeAnalysis_Wire) theAdvAnalyzer = Handle(ShapeAnalysis_Wire)::DownCast(myAnalyzer);
2426 if (theAdvAnalyzer.IsNull()) return Standard_False;
2427 theAdvAnalyzer->CheckIntersectingEdges ( num1, num2, points2d, points3d, errors);
2428 if ( theAdvAnalyzer->LastCheckStatus ( ShapeExtend_FAIL ) ) {
2429 myLastFixStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_FAIL1 );
2431 if ( ! theAdvAnalyzer->LastCheckStatus ( ShapeExtend_DONE ) ) return Standard_False;
2432 TColgp_Array1OfPnt vertexPoints(1,4);
2433 TColStd_Array1OfReal vertexTolers(1,4);
2434 TColStd_Array1OfReal newTolers(1,4);
2435 TopTools_Array1OfShape vertices(1,4);
2438 Handle(ShapeExtend_WireData) sbwd = WireData();
2439 Standard_Integer n2 = ( num1 >0 ? num1 : sbwd->NbEdges() );
2440 Standard_Integer n1 = ( num2 >1 ? num2 : sbwd->NbEdges() );
2441 if(n1==n2) return Standard_False;
2443 TopoDS_Edge edge1 = sbwd->Edge(n1);
2444 TopoDS_Edge edge2 = sbwd->Edge(n2);
2446 ShapeAnalysis_Edge sae;
2447 vertices(1) = sae.FirstVertex(edge1);
2448 vertices(2) = sae.LastVertex(edge1);
2449 vertices(3) = sae.FirstVertex(edge2);
2450 vertices(4) = sae.LastVertex(edge2);
2452 Standard_Integer i; // svv Jan11 2000 : porting on DEC
2453 for (i = 1; i <=4; i++) {
2454 vertexPoints(i) = BRep_Tool::Pnt(TopoDS::Vertex(vertices(i)));
2455 vertexTolers(i) = BRep_Tool::Tolerance(TopoDS::Vertex(vertices(i)));
2458 Standard_Real aNewTolEdge1 = 0.0, aNewTolEdge2 = 0.0;
2459 Standard_Integer nb = points3d.Length();
2460 for ( i=1; i <= nb; i++ ) {
2461 gp_Pnt pint = points3d.Value(i);
2463 // searching for the nearest vertexies to the intersection point
2464 Standard_Real aVtx1Param=0., aVtx2Param=0.;
2465 Standard_Integer aVC1, aVC2;
2466 Standard_Real aMinDist = RealLast();
2467 gp_Pnt aNearestVertex;
2468 Standard_Real aNecessaryVtxTole = 0.0;
2469 for(aVC1 = 1; aVC1 <= 2; aVC1++) {
2470 for(aVC2 = 3; aVC2 <= 4; aVC2++) {
2472 Standard_Real aVtxIPDist = pint.Distance(vertexPoints(aVC1));
2473 Standard_Real aVtxVtxDist = vertexPoints(aVC1).Distance(vertexPoints(aVC2));
2474 if(aMinDist > aVtxIPDist && aVtxIPDist > aVtxVtxDist) {
2475 aNecessaryVtxTole = aVtxVtxDist;
2476 aNearestVertex = vertexPoints(aVC1);
2477 aMinDist = aVtxIPDist;
2478 aVtx1Param = BRep_Tool::Parameter(TopoDS::Vertex(vertices(aVC1)),edge1);
2479 aVtx2Param = BRep_Tool::Parameter(TopoDS::Vertex(vertices(aVC2)),edge2);
2484 // calculation of necessary tolerances of edges
2485 const IntRes2d_IntersectionPoint &IP = points2d.Value(i);
2486 Standard_Real param1 = IP.ParamOnFirst();
2487 Standard_Real param2 = IP.ParamOnSecond();
2488 Handle(Geom_Curve) aCurve1, aCurve2;
2490 TopLoc_Location L1, L2;
2491 aCurve1 = BRep_Tool::Curve(edge1, L1, f, l);
2492 aCurve2 = BRep_Tool::Curve(edge2, L2, f, l);
2494 // if aMinDist lower than resolution than the intersection point lyes inside the vertex
2495 if(aMinDist < gp::Resolution())
2498 Standard_Real aMaxEdgeTol1 = 0.0, aMaxEdgeTol2 = 0.0;
2499 if(aMinDist < RealLast() && !aCurve1.IsNull() && !aCurve2.IsNull())
2501 gp_Lin aLig(aNearestVertex, gp_Vec(aNearestVertex, pint));
2502 Standard_Integer aPointsC;
2503 Standard_Real du1 = 0.05*(param1 - aVtx1Param);
2504 Standard_Real du2 = 0.05*(param2 - aVtx2Param);
2505 Standard_Real tole1=BRep_Tool::Tolerance(edge1);
2506 Standard_Real tole2=BRep_Tool::Tolerance(edge2);
2507 for(aPointsC = 2; aPointsC < 19; aPointsC++)
2509 Standard_Real u = aVtx1Param + aPointsC * du1;
2510 gp_Pnt P1 = aCurve1->Value(u);
2511 P1.Transform(L1.Transformation());
2512 Standard_Real d1 = aLig.Distance(P1) * 2.0000001;
2513 if(d1 > tole1 && d1 > aMaxEdgeTol1)
2516 u = aVtx2Param + aPointsC * du2;
2517 gp_Pnt P2 = aCurve2->Value(u);
2518 P2.Transform(L2.Transformation());
2519 Standard_Real d2 = aLig.Distance(P2) * 2.0000001;
2520 if(d2 > tole2 && d2 > aMaxEdgeTol2)
2523 if(aMaxEdgeTol1 == 0.0 && aMaxEdgeTol2 == 0.0) continue;
2524 // if the vertexies are far than tolerances so
2525 // we do not need to increase edge tolerance
2526 if(aNecessaryVtxTole > Max(aMaxEdgeTol1, tole1) ||
2527 aNecessaryVtxTole > Max(aMaxEdgeTol2, tole2))
2534 Standard_Real rad = errors.Value(i);
2535 Standard_Real finTol = RealLast();
2536 Standard_Integer rank=1;
2537 for(Standard_Integer j=1; j<=4; j++) {
2538 Standard_Real newtol = 1.0001 * ( pint.Distance (vertexPoints(j)) + rad );
2544 if(finTol <= MaxTolerance()) {
2545 myLastFixStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE1);
2546 if(newTolers(rank) < finTol)
2548 if(Max(aMaxEdgeTol1, aMaxEdgeTol2) < finTol && (aMaxEdgeTol1 > 0 || aMaxEdgeTol2 > 0))
2550 aNewTolEdge1 = Max(aNewTolEdge1, aMaxEdgeTol1);
2551 aNewTolEdge2 = Max(aNewTolEdge2, aMaxEdgeTol2);
2555 newTolers(rank) = finTol;
2559 myLastFixStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_FAIL2 );
2564 // update of tolerances of edges
2565 if(aNewTolEdge1 > 0)
2567 for(i = 1; i <= 2; i++)
2568 if(aNewTolEdge1 > Max(vertexTolers(i), newTolers(i)))
2569 newTolers(i) = aNewTolEdge1;
2570 B.UpdateEdge(edge1, aNewTolEdge1);
2572 if(aNewTolEdge2 > 0)
2574 for(i = 3; i <= 4; i++)
2575 if(aNewTolEdge2 > Max(vertexTolers(i), newTolers(i)))
2576 newTolers(i) = aNewTolEdge2;
2577 B.UpdateEdge(edge2, aNewTolEdge2);
2580 // update of tolerances of vertexies
2581 for(i = 1; i <=4; i++)
2582 if(newTolers(i)>0) B.UpdateVertex(TopoDS::Vertex(vertices(i)),newTolers(i));
2584 if ( ! myShape.IsNull() ) {
2585 SendWarning ( Message_Msg ( "FixAdvWire.FixIntersection.MSG10" ) );// Edges were intersecting, corrected
2587 return Standard_True;
2590 //=======================================================================
2591 //function : FixLacking
2592 //purpose : Test if two adjucent edges are disconnected in 2d (while connected
2593 // in 3d), and in that case either increase tolerance of the vertex or
2594 // add a new edge (straight in 2d space), in order to close wire in 2d.
2595 // Returns True if edge was added or tolerance was increased.
2596 //NOTE : Is to be run after FixDegenerated
2597 //Algorithm: 1. Compute the 2d gap between edges and calculate a tolerance
2598 // which should have vertex in order to comprise the gap
2599 // (using GeomAdaptor_Surface); computed value is inctol
2600 // 2. If inctol < tol of vertex, return False (everything is OK)
2601 // 3. If inctol < Precision, just increase tolerance of vertex to inctol
2602 // 4. Else (if both edges are not degenerated) try to add new edge
2603 // with straight pcurve (in order to close the gap):
2604 // a) if flag MayEdit is False
2605 // 1. if inctol < MaxTolerance, increase tolerance of vertex to inctol
2606 // 2. else try to add degenerated edge (check that middle point of
2607 // that pcurveis inside the vertex)
2608 // b) if MayEdit is True
2609 // 1. try to replace big vertex with two new small vertices
2610 // connected by new edge. This is made if there is a 3d space
2611 // between ends of adjacent edges.
2612 // 2. if inctol < MaxTolerance, increase tolerance of vertex to inctol
2613 // 3. else add either degenerated or closed edge (if middle point
2614 // of a pcurve of a new edge is inside the vertex, then
2615 // degenerated edge is added, else new edge is closed).
2616 // 5. If new edge cannot be added, but inctol < MaxTolerance,
2617 // when increase tolerance of vertex to a value of inctol
2618 //Short list of some internal variables:
2619 // tol - tolerance of vertex
2620 // tol2d - tolerance in parametric space of the surface corresponding to 2*tol
2621 // dist2d - distance between ends of pcurves of edges (2d)
2622 // inctol - tolerance required for vertex to close 2d gap (=tol*dist2d/tol2d)
2623 // tol1, tol2 - tolerances of edges, tol0 = tol1 + tol2
2624 // p3d1, p3d2 - ends of 3d curves of edges
2625 //=======================================================================
2626 //:h2 abv 28 May 98: merged modifications by abv 22 Apr 98, gka 27 May 98
2627 // and pdn 25 May 98 concerning lacking closed or degenerated edges
2628 // Example files: r0501_pe #107813, UKI60107-6 250, UKI60107-3 1577.
2630 //:s2 abv 21 Apr 99: add functionality for bending pcurve
2631 static Standard_Boolean TryBendingPCurve (const TopoDS_Edge &E, const TopoDS_Face &face,
2632 const gp_Pnt2d p2d, const Standard_Boolean end,
2633 Handle(Geom2d_Curve) &c2d,
2634 Standard_Real &first, Standard_Real &last,
2637 ShapeAnalysis_Edge sae;
2638 if ( ! sae.PCurve ( E, face, c2d, first, last, Standard_False ) ) return Standard_False;
2643 Handle(Geom2d_BSplineCurve) bs;
2644 if ( c2d->IsKind(STANDARD_TYPE(Geom2d_BSplineCurve)) )
2645 bs = Handle(Geom2d_BSplineCurve)::DownCast(c2d->Copy());
2646 else // if ( c2d->IsKind(STANDARD_TYPE(Geom2d_Line)) )
2648 Handle(Geom2d_TrimmedCurve) trim = new Geom2d_TrimmedCurve ( c2d, first, last );
2649 bs = Geom2dConvert::CurveToBSplineCurve ( trim );
2651 if ( bs.IsNull() ) return Standard_False;
2653 Standard_Real par = ( end ? last : first );
2654 if ( fabs ( bs->FirstParameter() - par ) < ::Precision::PConfusion() &&
2655 bs->Multiplicity(1) > bs->Degree() ) bs->SetPole ( 1, p2d );
2656 else if ( fabs ( bs->LastParameter() - par ) < ::Precision::PConfusion() &&
2657 bs->Multiplicity(bs->NbKnots()) > bs->Degree() ) bs->SetPole ( bs->NbPoles(), p2d );
2659 bs->Segment ( first, last );
2660 if (fabs ( bs->FirstParameter() - par ) < ::Precision::PConfusion() &&
2661 bs->Multiplicity(1) > bs->Degree()) bs->SetPole ( 1, p2d );
2662 else if (fabs ( bs->LastParameter() - par ) < ::Precision::PConfusion() &&
2663 bs->Multiplicity(bs->NbKnots()) > bs->Degree()) bs->SetPole ( bs->NbPoles(), p2d );
2664 else return Standard_False;
2668 catch ( Standard_Failure ) {
2670 cout << "Warning: ShapeFix_Wire::FixLacking: Exception in Geom2d_BSplineCurve::Segment()" << endl;
2672 return Standard_False;
2676 if ( ! TryNewPCurve ( E, face, c2d, first, last, tol ) ) return Standard_False;
2677 return Standard_True;
2681 //=======================================================================
2682 //function : FixLacking
2684 //=======================================================================
2686 Standard_Boolean ShapeFix_Wire::FixLacking (const Standard_Integer num,
2687 const Standard_Boolean force)
2689 myLastFixStatus = ShapeExtend::EncodeStatus ( ShapeExtend_OK );
2690 if ( ! IsReady() ) return Standard_False;
2693 // First phase: analysis whether the problem (gap) exists
2694 gp_Pnt2d p2d1, p2d2;
2695 Handle(ShapeAnalysis_Wire)::DownCast(myAnalyzer)->CheckLacking ( num, ( force ? Precision() : 0. ), p2d1, p2d2 );
2696 if ( myAnalyzer->LastCheckStatus ( ShapeExtend_FAIL ) ) {
2697 myLastFixStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_FAIL1 );
2699 if ( ! myAnalyzer->LastCheckStatus ( ShapeExtend_DONE ) ) return Standard_False;
2702 // Second phase: collection of data necessary for further analysis
2704 Handle(ShapeExtend_WireData) sbwd = WireData();
2705 Standard_Integer n2 = ( num >0 ? num : sbwd->NbEdges() );
2706 Standard_Integer n1 = ( n2 >1 ? n2-1 : sbwd->NbEdges() );
2707 TopoDS_Edge E1 = sbwd->Edge(n1);
2708 TopoDS_Edge E2 = sbwd->Edge(n2);
2710 ShapeAnalysis_Edge sae;
2711 TopoDS_Vertex V1 = sae.LastVertex ( E1 );
2712 TopoDS_Vertex V2 = sae.FirstVertex ( E2 );
2713 Standard_Real tol = Max ( BRep_Tool::Tolerance ( V1 ), BRep_Tool::Tolerance ( V2 ) );
2715 Standard_Real Prec = Precision();
2716 Standard_Real dist2d = myAnalyzer->MaxDistance2d();
2717 Standard_Real inctol = myAnalyzer->MaxDistance3d();
2719 TopoDS_Face face = myAnalyzer->Face();
2720 Handle(ShapeAnalysis_Surface) surf = myAnalyzer->Surface();
2723 Standard_Real tol1=::Precision::Confusion(), tol2=::Precision::Confusion(); //SK
2726 //:s2 abv 21 Apr 99: Speculation: try bending pcurves
2727 Standard_Real bendtol1, bendtol2;
2728 Handle(Geom2d_Curve) bendc1, bendc2;
2729 Standard_Real bendf1, bendl1, bendf2, bendl2;
2730 if ( myGeomMode && ! BRep_Tool::IsClosed(E1,face) && ! BRep_Tool::IsClosed(E2,face) ) {
2731 gp_Pnt2d p2d = 0.5 * ( p2d1.XY() + p2d2.XY() );
2732 Standard_Boolean ok1 = TryBendingPCurve (E1, face, p2d, E1.Orientation() == TopAbs_FORWARD,
2733 bendc1, bendf1, bendl1, bendtol1);
2734 Standard_Boolean ok2 = TryBendingPCurve (E2, face, p2d, E2.Orientation() == TopAbs_REVERSED,
2735 bendc2, bendf2, bendl2, bendtol2);
2736 if ( ok1 && ! ok2 ) {
2737 bendtol2 = BRep_Tool::Tolerance(E2);
2738 ok1 = TryBendingPCurve (E1, face, p2d2, E1.Orientation() == TopAbs_FORWARD,
2739 bendc1, bendf1, bendl1, bendtol1);
2741 else if ( ! ok1 && ok2 ) {
2742 bendtol1 = BRep_Tool::Tolerance(E1);
2743 ok2 = TryBendingPCurve (E2, face, p2d1, E2.Orientation() == TopAbs_FORWARD,
2744 bendc2, bendf2, bendl2, bendtol2);
2746 if ( ! ok1 && ! ok2 ) bendc1.Nullify();
2750 // Third phase: analyse how to fix the problem
2752 // selector of solutions
2753 Standard_Boolean doIncrease = Standard_False; // increase tolerance
2754 Standard_Boolean doAddLong = Standard_False; // add long 3d edge in replacement of a vertex
2755 Standard_Boolean doAddClosed = Standard_False; // add closed 3d edge
2756 Standard_Boolean doAddDegen = Standard_False; // add degenerated edge
2757 Standard_Boolean doBend = Standard_False; //:s2 bend pcurves
2759 // if bending is OK with existing tolerances of edges, take it
2760 if ( ! bendc1.IsNull() && ! bendc2.IsNull() &&
2761 ( ( bendtol1 < BRep_Tool::Tolerance(E1) &&
2762 bendtol2 < BRep_Tool::Tolerance(E2) ) ||
2763 ( inctol < Prec && bendtol1 < inctol && bendtol2 < inctol ) ) )
2764 doBend = Standard_True;
2766 // is it OK just to increase tolerance (to a value less than preci)?
2767 else if ( inctol < Prec ) doIncrease = Standard_True;
2769 // If increase is not OK or force, try to find other solutions (adding edge)
2770 else if ( ! BRep_Tool::Degenerated ( E2 ) && ! BRep_Tool::Degenerated ( E1 ) ) {
2772 // analyze the 3d space btw edges: is it enough to add long 3d edge?
2774 Handle(Geom_Curve) c3d;
2776 if ( ! sae.Curve3d ( E1, c3d, a, b, Standard_True ) ) { // cannot work
2777 myLastFixStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_FAIL1 );
2778 return Standard_False;
2780 p3d1 = c3d->Value ( b );
2781 Standard_Real dist2d3d1 = p3d1.Distance ( surf->Value ( p2d1 ) );
2782 if ( ! sae.Curve3d ( E2, c3d, a, b, Standard_True ) ) { // cannot work
2783 myLastFixStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_FAIL1 );
2784 return Standard_False;
2786 p3d2 = c3d->Value ( a );
2787 Standard_Real dist2d3d2 = p3d2.Distance ( surf->Value ( p2d2 ) );
2789 tol1 = Max ( BRep_Tool::Tolerance ( E1 ), dist2d3d1 );
2790 tol2 = Max ( BRep_Tool::Tolerance ( E2 ), dist2d3d2 );
2791 //:c5 Standard_Real tol0 = Max ( tol1 + tol2, thepreci );
2792 Standard_Real tol0 = tol1 + tol2; //:c5 abv 26 Feb 98: CTS17806 #44418
2793 Standard_Real dist3d2 = p3d1.SquareDistance ( p3d2 );
2795 // is it OK to add a long 3d edge?
2796 if ( ! myAnalyzer->LastCheckStatus ( ShapeExtend_DONE2 ) && //:81 abv 20 Jan 98: don`t add back-going edges (zigzags)
2797 dist3d2 > 1.25 * tol0 * tol0 &&
2798 ( force || dist3d2 > Prec * Prec || inctol > MaxTolerance() ) ) {
2799 doAddLong = Standard_True;
2803 //:h6 abv 25 Jun 98: BUC40132 6361: try to increase tol up to MaxTol if not add
2804 if ( ! doAddLong && inctol < MaxTolerance() &&
2805 ! myAnalyzer->Surface()->IsDegenerated ( p2d1, p2d2, 2.*tol, 10. ) ) { //:p7
2806 if ( ! bendc1.IsNull() && ! bendc2.IsNull() &&
2807 bendtol1 < inctol && bendtol2 < inctol ) doBend = Standard_True;
2808 else doIncrease = Standard_True;
2812 // else try to add either degenerated or closed edge
2813 if ( ! doAddLong ) {
2814 gp_Pnt pV = 0.5 * ( BRep_Tool::Pnt(V1).XYZ() + BRep_Tool::Pnt(V2).XYZ() );
2815 gp_Pnt pm = myAnalyzer->Surface()->Value ( 0.5 * ( p2d1.XY() + p2d2.XY() ) );
2817 Standard_Real dist = pV.Distance ( pm );
2818 if ( dist <= tol ) doAddDegen = Standard_True;
2819 else if ( myTopoMode ) doAddClosed = Standard_True;
2820 else if ( dist <= MaxTolerance() ) { //:r7 abv 12 Apr 99: t3d_opt.stp #14245 after S4136
2821 doAddDegen = Standard_True;
2822 doIncrease = Standard_True;
2828 else if ( !BRep_Tool::Degenerated(E2) && BRep_Tool::Degenerated(E1) ) {
2829 // create new degenerated edge and replace E1 to new edge
2831 else if ( BRep_Tool::Degenerated(E2) && !BRep_Tool::Degenerated(E1) ) {
2832 // create new degenerated edge and replace E2 to new edge
2836 // Third phase - do the fixes
2840 if ( doAddLong || doAddDegen || doAddClosed ) {
2842 // construct new vertices
2843 TopoDS_Vertex newV1, newV2;
2845 newV1 = BRepBuilderAPI_MakeVertex ( p3d1 );
2847 newV2 = BRepBuilderAPI_MakeVertex ( p3d2 );
2848 B.UpdateVertex ( newV1, 1.001 * tol1 );
2849 B.UpdateVertex ( newV2, 1.001 * tol2 );
2858 B.MakeEdge ( edge );
2859 if ( doAddDegen ) B.Degenerated ( edge, Standard_True ); // sln: do it before adding curve
2860 gp_Vec2d v12 ( p2d1, p2d2 );
2861 Handle(Geom2d_Line) theLine2d = new Geom2d_Line ( p2d1, gp_Dir2d ( v12 ) );
2862 B.UpdateEdge ( edge, theLine2d, face, ::Precision::Confusion() );
2863 B.Range ( edge, face, 0, dist2d );
2864 B.Add ( edge, newV1.Oriented ( TopAbs_FORWARD ) );
2865 B.Add ( edge, newV2.Oriented ( TopAbs_REVERSED ) );
2866 ShapeBuild_Edge sbe;
2867 if ( ! doAddDegen && ! sbe.BuildCurve3d ( edge ) ) {
2868 myLastFixStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_FAIL3 );
2869 return Standard_False;
2872 // if long edge is added, replace vertices of adjacent edges
2875 // replace 1st edge (n1==n2 - special case: wire consists of one edge)
2876 TopoDS_Edge edge1 = sbe.CopyReplaceVertices ( E1,
2877 ( n1 == n2 ? newV2 : TopoDS_Vertex() ), newV1 );
2878 sbwd->Set ( edge1, n1 );
2879 if ( ! Context().IsNull() ) {
2880 Context()->Replace ( E1, edge1 );
2881 // actually, this will occur only in context of single face
2882 // hence, recording to ReShape is rather for tracking modifications
2883 // than for keeping sharing
2884 Context()->Replace ( V1, newV1.Oriented ( V1.Orientation() ) );
2885 if ( ! V1.IsSame ( V2 ) ) {
2886 Context()->Replace ( V2, newV2.Oriented ( V2.Orientation() ) );
2891 TopoDS_Edge edge2 = sbe.CopyReplaceVertices ( E2, newV2, TopoDS_Vertex() );
2892 sbwd->Set ( edge2, n2 );
2893 if ( ! Context().IsNull() ) Context()->Replace ( E2, edge2 );
2895 if ( ! Context().IsNull() ) UpdateWire();
2900 myLastFixStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE3 );
2902 cout << "Warning: ShapeFix_Wire::FixLacking: degenerated edge added" << endl;
2905 else if ( ! doAddLong ) {
2906 myLastFixStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE4 );
2908 sbwd->Add ( edge, n2 );
2909 myLastFixStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE2 );
2912 // else try to increase tol up to MaxTol
2913 else if ( inctol > tol && inctol < MaxTolerance() ) {
2914 if ( ! bendc1.IsNull() && ! bendc2.IsNull() &&
2915 bendtol1 < inctol && bendtol2 < inctol ) doBend = Standard_True;
2916 else doIncrease = Standard_True;
2920 if ( doBend ) { //:s2 abv 21 Apr 99
2921 B.UpdateEdge ( E1, bendc1, face, bendtol1 );
2922 B.Range ( E1, face, bendf1, bendl1 );
2923 B.UpdateEdge ( E2, bendc2, face, bendtol2 );
2924 B.Range ( E2, face, bendf2, bendl2 );
2925 B.UpdateVertex ( sae.FirstVertex(E1), bendtol1 );
2926 B.UpdateVertex ( sae.LastVertex(E1), bendtol1 );
2927 B.UpdateVertex ( sae.FirstVertex(E2), bendtol2 );
2928 B.UpdateVertex ( sae.LastVertex(E2), bendtol2 );
2929 myLastFixStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE5 );
2930 //:s3 abv 22 Apr 99: PRO7187 #11534: self-intersection not detected unitil curve is bent (!)
2931 FixSelfIntersectingEdge ( n1 );
2932 FixSelfIntersectingEdge ( n2 );
2933 FixIntersectingEdges ( n2 ); //skl 24.04.2003 for OCC58
2935 cout << "Info: ShapeFix_Wire::FixLacking: Bending pcurves" << endl;
2937 myLastFixStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE5 );
2940 // increase vertex tolerance
2942 B.UpdateVertex ( V1, 1.001 * inctol );
2943 B.UpdateVertex ( V2, 1.001 * inctol );
2944 myLastFixStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE1 );
2947 if ( LastFixStatus ( ShapeExtend_DONE ) ) return Standard_True;
2949 myLastFixStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_FAIL2 );
2950 return Standard_False;
2953 //=======================================================================
2954 //function : FixNotchedEdges
2956 //=======================================================================
2958 Standard_Boolean ShapeFix_Wire::FixNotchedEdges()
2960 myLastFixStatus = ShapeExtend::EncodeStatus ( ShapeExtend_OK );
2961 if ( ! IsReady() ) return Standard_False;
2963 Handle(ShapeAnalysis_Wire) theAdvAnalyzer = Handle(ShapeAnalysis_Wire)::DownCast(myAnalyzer);
2964 TopoDS_Face face = Face();
2965 if ( ! Context().IsNull() ) UpdateWire();
2966 Handle(ShapeExtend_WireData) sewd = WireData();
2968 for (Standard_Integer i = 1; i <= NbEdges() && NbEdges() > 2; i++) {
2969 Standard_Real param;
2970 Standard_Integer toRemove;
2971 if(theAdvAnalyzer->CheckNotchedEdges(i,toRemove,param,MinTolerance())){
2972 Standard_Integer n2 = (i > 0) ? i : NbEdges();
2973 Standard_Integer n1 = (n2 > 1) ? n2-1 : NbEdges();
2974 Standard_Boolean isRemoveFirst = (n1==toRemove);
2975 Standard_Integer toSplit = (n2==toRemove ? n1 : n2);
2976 TopoDS_Edge splitE = sewd->Edge ( toSplit );
2977 ShapeAnalysis_Edge sae;
2978 Handle(Geom2d_Curve) c2d;
2980 sae.PCurve ( splitE, face, c2d, a, b, Standard_True );
2981 Standard_Real ppar = (isRemoveFirst ? b : a);
2982 ShapeBuild_Edge sbe;
2983 TopAbs_Orientation orient = splitE.Orientation();
2984 if ( Abs(param - ppar) > ::Precision::PConfusion() ) {
2985 //pdn perform splitting of the edge and adding to wire
2987 //pdn check if it is necessary
2988 if( Abs((isRemoveFirst ? a : b)-param) < ::Precision::PConfusion() ) {
2992 Handle(ShapeAnalysis_TransferParametersProj) transferParameters =
2993 new ShapeAnalysis_TransferParametersProj;
2994 transferParameters->SetMaxTolerance(MaxTolerance());
2995 transferParameters->Init(splitE,face);
2996 Standard_Real first, last;
3007 B.MakeVertex(Vnew,Analyzer()->Surface()->Value(c2d->Value(param)),::Precision::Confusion());
3008 TopoDS_Edge wE = splitE;
3009 wE.Orientation ( TopAbs_FORWARD );
3010 TopoDS_Shape aTmpShape = Vnew.Oriented(TopAbs_REVERSED); //for porting
3011 TopoDS_Edge newE1 = sbe.CopyReplaceVertices ( wE, sae.FirstVertex(wE), TopoDS::Vertex(aTmpShape) );
3012 sbe.CopyPCurves ( newE1, wE );
3013 transferParameters->TransferRange(newE1,first,param,Standard_True);
3014 B.SameRange(newE1,Standard_False);
3015 B.SameParameter(newE1,Standard_False);
3016 aTmpShape = Vnew.Oriented(TopAbs_FORWARD);
3017 TopoDS_Edge newE2 = sbe.CopyReplaceVertices ( wE, TopoDS::Vertex(aTmpShape),sae.LastVertex(wE) );
3018 sbe.CopyPCurves ( newE2, wE );
3019 transferParameters->TransferRange(newE2,param,last,Standard_True);
3020 B.SameRange(newE2,Standard_False);
3021 B.SameParameter(newE2,Standard_False);
3023 if ( !Context().IsNull() ) {
3028 Context()->Replace ( wE, wire );
3031 newE1.Orientation(orient);
3032 newE2.Orientation(orient);
3033 if (orient==TopAbs_REVERSED){ TopoDS_Edge tmp = newE2; newE2 = newE1; newE1=tmp;}
3035 Standard_Boolean isRemoveLast = ((n1==NbEdges())&&(n2==1));
3036 sewd->Set ( newE1, toSplit);
3037 sewd->Add ( newE2, (toSplit==NbEdges() ? 0 : toSplit+1));
3039 FixDummySeam(isRemoveLast ? NbEdges() : toRemove);
3040 myLastFixStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE2 );
3046 if(!Context().IsNull()) //skl 07.03.2002 for OCC180
3048 myLastFixStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE1 );
3051 myStatusNotches = myLastFixStatus;
3052 return LastFixStatus ( ShapeExtend_DONE );
3055 //=======================================================================
3056 //function : FixDummySeam
3058 //=======================================================================
3060 static void CopyReversePcurves(const TopoDS_Edge& toedge,
3061 const TopoDS_Edge& fromedge,
3062 const Standard_Boolean reverse)
3064 TopLoc_Location fromLoc = fromedge.Location();
3065 TopLoc_Location toLoc = toedge.Location();
3066 for (BRep_ListIteratorOfListOfCurveRepresentation fromitcr
3067 ((*((Handle(BRep_TEdge)*)&fromedge.TShape()))->ChangeCurves()); fromitcr.More(); fromitcr.Next()) {
3068 Handle(BRep_GCurve) fromGC = Handle(BRep_GCurve)::DownCast(fromitcr.Value());
3069 if ( fromGC.IsNull() ) continue;
3070 if ( fromGC->IsCurveOnSurface() ) {
3071 Handle(Geom_Surface) surface = fromGC->Surface();
3072 TopLoc_Location L = fromGC->Location();
3073 Standard_Boolean found = Standard_False;
3074 BRep_ListOfCurveRepresentation& tolist = (*((Handle(BRep_TEdge)*)&toedge.TShape()))->ChangeCurves();
3075 Handle(BRep_GCurve) toGC;
3076 for (BRep_ListIteratorOfListOfCurveRepresentation toitcr (tolist); toitcr.More() && !found; toitcr.Next()) {
3077 toGC = Handle(BRep_GCurve)::DownCast(toitcr.Value());
3078 if ( toGC.IsNull() || !toGC->IsCurveOnSurface() ||
3079 surface != toGC->Surface() || L != toGC->Location() ) continue;
3080 found = Standard_True;
3084 Standard_Real fp = fromGC->First();
3085 Standard_Real lp = fromGC->Last();
3086 toGC = Handle(BRep_GCurve)::DownCast(fromGC->Copy());
3087 tolist.Append (toGC);
3088 Handle(Geom2d_Curve) pcurve = Handle(Geom2d_Curve)::DownCast( fromGC->PCurve()->Copy() );
3090 fp = pcurve->ReversedParameter(fp);
3091 lp = pcurve->ReversedParameter(lp);
3093 Standard_Real tmp = fp;
3097 //bug OCC209 invalid location of pcurve in the edge after copying
3098 TopLoc_Location newLoc = (fromLoc*L).Predivided(toLoc);
3099 toGC->SetRange(fp,lp);
3100 toGC->PCurve(pcurve);
3101 toGC->Location(newLoc);
3102 if ( fromGC->IsCurveOnClosedSurface() ) {
3103 pcurve = fromGC->PCurve2();
3104 toGC->PCurve2(Handle(Geom2d_Curve)::DownCast(pcurve->Copy()));
3111 //=======================================================================
3112 //function : HasNewPCurves
3114 //=======================================================================
3115 // Note: This function temporarily not used, because adress to it in
3116 // function FixDummySeam() (see below line 2472) not used too
3118 //static Standard_Boolean HasNewPCurves(const TopoDS_Edge& toedge,
3119 // const TopoDS_Edge& fromedge)
3122 // for (BRep_ListIteratorOfListOfCurveRepresentation fromitcr
3123 // ((*((Handle(BRep_TEdge)*)&fromedge.TShape()))->ChangeCurves()); fromitcr.More(); fromitcr.Next()) {
3124 // Handle(BRep_GCurve) fromGC = Handle(BRep_GCurve)::DownCast(fromitcr.Value());
3125 // if ( fromGC.IsNull() ) continue;
3126 // if ( fromGC->IsCurveOnSurface() ) {
3127 // Handle(Geom_Surface) surface = fromGC->Surface();
3128 // TopLoc_Location L = fromGC->Location();
3129 // Standard_Boolean found = Standard_False;
3130 // BRep_ListOfCurveRepresentation& tolist = (*((Handle(BRep_TEdge)*)&toedge.TShape()))->ChangeCurves();
3131 // Handle(BRep_GCurve) toGC;
3132 // for (BRep_ListIteratorOfListOfCurveRepresentation toitcr (tolist); toitcr.More() && !found; toitcr.Next()) {
3133 // toGC = Handle(BRep_GCurve)::DownCast(toitcr.Value());
3134 // if ( toGC.IsNull() || !toGC->IsCurveOnSurface() ||
3135 // surface != toGC->Surface() || L != toGC->Location() ) continue;
3136 // found = Standard_True;
3140 // return Standard_True;
3143 // return Standard_False;
3146 //=======================================================================
3147 //function : FixDummySeam
3149 //=======================================================================
3151 void ShapeFix_Wire::FixDummySeam(const Standard_Integer num)
3153 ShapeAnalysis_Edge sae;
3154 ShapeBuild_Edge sbe;
3155 ShapeBuild_Vertex sbv;
3156 Standard_Integer num1 = (num == NbEdges()) ? 1 : num+1;
3157 Handle(ShapeExtend_WireData) sewd = WireData();
3158 TopoDS_Edge E1 = sewd->Edge(num), E2 = sewd->Edge(num1);
3159 TopoDS_Vertex V1 = sae.FirstVertex(E1), V2 = sae.LastVertex(E2);
3160 TopoDS_Vertex Vm = sbv.CombineVertex ( V1, V2, 1.0001 );
3162 //pnd defining if new pcurves exists
3163 //pdn Temporary not removed
3164 // Standard_Boolean toRemove = !(HasNewPCurves(E1,E2)||HasNewPCurves(E2,E1));
3165 Standard_Boolean toRemove = Standard_False;
3167 //creating new edge with pcurves and new vertex
3168 TopoDS_Vertex Vs = sae.FirstVertex(E2);
3169 if ( Vs.IsSame ( V1 ) || Vs.IsSame ( V2 ) ) Vs = Vm;
3170 TopoDS_Edge newEdge = sbe.CopyReplaceVertices ( E2, Vs, Vm );
3171 CopyReversePcurves(newEdge,E1,E1.Orientation()==E2.Orientation());
3173 B.SameRange(newEdge,Standard_False);
3174 B.SameParameter(newEdge,Standard_False);
3176 if ( !Context().IsNull() ) {
3178 Context()->Remove ( E2 );
3179 Context()->Remove ( E1 );
3182 Context()->Replace ( E2, newEdge );
3183 Context()->Replace ( E1, newEdge.Reversed());
3185 Context()->Replace ( V1, Vm.Oriented(V1.Orientation()) );
3186 Context()->Replace ( V2, Vm.Oriented(V2.Orientation()) );
3189 Standard_Integer next = ( num1 == NbEdges()) ? 1 : num1+1;
3190 Standard_Integer prev = ( num > 1) ? num-1 : NbEdges();
3191 TopoDS_Edge prevE = sewd->Edge(prev), nextE = sewd->Edge(next);
3193 TopoDS_Edge tmpE1=sbe.CopyReplaceVertices( prevE, TopoDS_Vertex(), Vm);
3194 sewd->Set ( tmpE1,prev );
3195 if ( !Context().IsNull() ) Context()->Replace ( prevE, tmpE1);
3197 tmpE1 = sbe.CopyReplaceVertices ( nextE, Vm, TopoDS_Vertex());
3198 sewd->Set ( tmpE1,next );
3199 if ( !Context().IsNull() ) Context()->Replace ( nextE, tmpE1);
3201 //removing edges from wire
3202 Standard_Integer n1, n2;
3204 n1 = num; n2 = num1;
3206 n1 = num1; n2 = num;
3212 //=======================================================================
3213 //function : UpdateWire
3215 //=======================================================================
3217 void ShapeFix_Wire::UpdateWire ()
3219 Handle(ShapeExtend_WireData) sbwd = WireData();
3220 for ( Standard_Integer i=1; i <= sbwd->NbEdges(); i++ ) {
3221 TopoDS_Edge E = sbwd->Edge(i);
3222 TopoDS_Shape S = Context()->Apply ( E );
3223 if ( S == E ) continue;
3224 for ( TopExp_Explorer exp(S,TopAbs_EDGE); exp.More(); exp.Next() )
3225 sbwd->Add ( exp.Current(), i++ );
3226 sbwd->Remove ( i-- );