Correction of OCCT for ACIS22398
[occt.git] / src / ShapeFix / ShapeFix_Wire.cxx
CommitLineData
7fd59977 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
32
33#include <ShapeFix_Wire.ixx>
34
35#include <Standard_ErrorHandler.hxx>
36#include <Standard_Failure.hxx>
37#include <TColStd_Array1OfReal.hxx>
38#include <TColStd_Array1OfInteger.hxx>
39#include <Precision.hxx>
40
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>
51
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>
58
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>
66#include <gp_Pln.hxx>
67
68#include <TopoDS.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>
74
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>
83
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>
97
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>
103
104#include <ShapeAnalysis_TransferParameters.hxx>
105#include <ShapeFix.hxx>
106#include <ShapeFix_IntersectionTool.hxx>
107#include <ShapeFix_SplitTool.hxx>
108
109
110//#######################################################################
111// Constructors, initializations, modes, querying
112//#######################################################################
113
114//=======================================================================
115//function : ShapeFix_Wire
116//purpose :
117//=======================================================================
118
119ShapeFix_Wire::ShapeFix_Wire()
120{
121 myFixEdge = new ShapeFix_Edge;
122 myAnalyzer = new ShapeAnalysis_Wire;
123 ClearModes();
124 ClearStatuses();
125 myStatusRemovedSegment = Standard_False;
126}
127
128//=======================================================================
129//function : ShapeFix_Wire
130//purpose :
131//=======================================================================
132
133ShapeFix_Wire::ShapeFix_Wire (const TopoDS_Wire& wire,
134 const TopoDS_Face &face, const Standard_Real prec)
135{
136 myFixEdge = new ShapeFix_Edge;
137 myAnalyzer = new ShapeAnalysis_Wire;
138 ClearModes();
139 SetMaxTolerance ( prec );
140 myStatusRemovedSegment = Standard_False;
141 Init ( wire, face, prec );
142}
143
144//=======================================================================
145//function : SetPrecision
146//purpose :
147//=======================================================================
148
149void ShapeFix_Wire::SetPrecision (const Standard_Real prec)
150{
151 ShapeFix_Root::SetPrecision ( prec );
152 myAnalyzer->SetPrecision ( prec );
153}
154
155//=======================================================================
156//function : ClearModes
157//purpose :
158//=======================================================================
159
160void ShapeFix_Wire::ClearModes()
161{
162 myTopoMode = Standard_False;
163 myGeomMode = Standard_True;
164 myClosedMode = Standard_True;
165 myPreference2d = Standard_True;
166 myFixGapsByRanges = Standard_False;
167
168 myRemoveLoopMode = -1;
169
170 myFixReversed2dMode = -1;
171 myFixRemovePCurveMode = -1;
172 myFixRemoveCurve3dMode = -1;
173 myFixAddPCurveMode = -1;
174 myFixAddCurve3dMode = -1;
175 myFixSeamMode = -1;
176 myFixShiftedMode = -1;
177 myFixSameParameterMode = -1;
178 myFixVertexToleranceMode = -1;
179
180 myFixNotchedEdgesMode = -1;
181 myFixSelfIntersectingEdgeMode = -1;
182 myFixIntersectingEdgesMode = -1;
183 myFixNonAdjacentIntersectingEdgesMode = -1;
184
185 myFixReorderMode = -1;
186 myFixSmallMode = -1;
187 myFixConnectedMode = -1;
188 myFixEdgeCurvesMode = -1;
189 myFixDegeneratedMode = -1;
190 myFixSelfIntersectionMode = -1;
191 myFixLackingMode = -1;
192 myFixGaps3dMode = -1;
193 myFixGaps2dMode = -1;
194}
195
196//=======================================================================
197//function : ClearStatuses
198//purpose :
199//=======================================================================
200
201void ShapeFix_Wire::ClearStatuses()
202{
203 Standard_Integer emptyStatus = ShapeExtend::EncodeStatus ( ShapeExtend_OK );
204
205 myLastFixStatus = emptyStatus;
206
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;
217}
218
219//=======================================================================
220//function : Init
221//purpose :
222//=======================================================================
223
224void ShapeFix_Wire::Init (const TopoDS_Wire& wire,
225 const TopoDS_Face &face, const Standard_Real prec)
226{
227 Load ( wire );
228 SetFace ( face );
229 SetPrecision ( prec );
230}
231
232//=======================================================================
233//function : Init
234//purpose :
235//=======================================================================
236
237void ShapeFix_Wire::Init (const Handle(ShapeAnalysis_Wire)& saw)
238{
239 ClearStatuses();
240 myAnalyzer = saw;
241 myShape.Nullify();
242// SetPrecision ( saw.Precision() );
243}
244
245//=======================================================================
246//function : Load
247//purpose :
248//=======================================================================
249
250void ShapeFix_Wire::Load (const TopoDS_Wire& wire)
251{
252 ClearStatuses();
253
254 TopoDS_Wire W = wire;
255 if ( ! Context().IsNull() ) {
256 TopoDS_Shape S = Context()->Apply ( wire );
257 W = TopoDS::Wire ( S );
258 }
259
260 myAnalyzer->Load ( W );
261 myShape = wire;
262}
263
264//=======================================================================
265//function : Load
266//purpose :
267//=======================================================================
268
269void ShapeFix_Wire::Load (const Handle(ShapeExtend_WireData)& sbwd)
270{
271 ClearStatuses();
272 myAnalyzer->Load ( sbwd );
273 if ( ! Context().IsNull() ) UpdateWire();
274 myShape.Nullify();
275}
276
277//=======================================================================
278//function : NbEdges
279//purpose :
280//=======================================================================
281
282Standard_Integer ShapeFix_Wire::NbEdges() const
283{
284 Handle(ShapeExtend_WireData) sbwd = myAnalyzer->WireData();
285 return sbwd.IsNull() ? 0 : sbwd->NbEdges();
286}
287
288//#######################################################################
289// Fixing methods of API level
290//#######################################################################
291
292//=======================================================================
293//function : Perform
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//=======================================================================
301
302Standard_Boolean ShapeFix_Wire::Perform()
303{
304 ClearStatuses();
305 if ( ! IsLoaded() ) return Standard_False;
306
307
308 Standard_Integer Fixed = Standard_False;
309
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)
313
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 );
319 }
320
321 // FixSmall is allowed to change topology only if mode is set and FixReorder
322 // did not failed
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 ) ) {
328 FixReorder();
329 ReorderOK = ! StatusReorder ( ShapeExtend_FAIL );
330 }
331 }
332 }
333
334 if ( NeedFix ( myFixConnectedMode, ReorderOK ) ) {
335 if ( FixConnected() ) Fixed = Standard_True;
336 }
337
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;
344 }
345
346 if ( NeedFix ( myFixDegeneratedMode ) ) {
347 if ( FixDegenerated() ) Fixed = Standard_True; // ?? if ! ReorderOK ??
348 }
349
350 //pdn - temporary to test
351 if ( NeedFix ( myFixNotchedEdgesMode, ReorderOK ) ) {
352 Fixed |= FixNotchedEdges();
353 if(Fixed) FixShifted(); //skl 07.03.2002 for OCC180
354 }
355
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;
362 FixReorder();
363 myFixIntersectingEdgesMode = savFixIntersectingEdgesMode;
364 }
365
366 if ( NeedFix ( myFixLackingMode, ReorderOK ) ) {
367 if ( FixLacking() ) Fixed = Standard_True;
368 }
369
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;
375
376 return Fixed;
377}
378
379//=======================================================================
380//function : FixReorder
381//purpose :
382//=======================================================================
383
384Standard_Boolean ShapeFix_Wire::FixReorder()
385{
386 myStatusReorder = ShapeExtend::EncodeStatus ( ShapeExtend_OK );
387 if ( ! IsLoaded() ) return Standard_False;
388
389 // fix in 3d
390 ShapeAnalysis_WireOrder sawo;
391 myAnalyzer->CheckOrder ( sawo, myClosedMode, Standard_True );
392
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 );
410 sawo = sawo2;
411 isReorder = Standard_True;
412 }
413 }
414
415 FixReorder ( sawo );
416
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;
421
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;
428}
429
430//=======================================================================
431//function : FixSmall
432//purpose :
433//=======================================================================
434
435Standard_Integer ShapeFix_Wire::FixSmall (const Standard_Boolean lockvtx,
436 const Standard_Real precsmall)
437{
438 myStatusSmall = ShapeExtend::EncodeStatus ( ShapeExtend_OK );
439 if ( ! IsLoaded() ) return Standard_False;
440
441 for ( Standard_Integer i = NbEdges(); i >0; i-- ) {
442 FixSmall ( i, lockvtx, precsmall );
443 myStatusSmall |= myLastFixStatus;
444 }
445
446 if ( StatusSmall ( ShapeExtend_DONE ) && ! myShape.IsNull() ) {
447 SendWarning (Message_Msg ("FixAdvWire.FixSmall.MSG0"));//Small edge(s) removed
448 }
449 return StatusSmall ( ShapeExtend_DONE );
450
451}
452
453//=======================================================================
454//function : FixConnected
455//purpose :
456//=======================================================================
457
458Standard_Boolean ShapeFix_Wire::FixConnected (const Standard_Real prec)
459{
460 myStatusConnected = ShapeExtend::EncodeStatus ( ShapeExtend_OK );
461 if ( ! IsLoaded() ) return Standard_False;
462
463 Standard_Integer stop = ( myClosedMode ? 0 : 1 );
464 for ( Standard_Integer i = NbEdges(); i > stop; i-- ) {
465 FixConnected ( i, prec );
466 myStatusConnected |= myLastFixStatus;
467 }
468
469 return StatusConnected ( ShapeExtend_DONE );
470}
471
472//=======================================================================
473//function : FixEdgeCurves
474//purpose :
475//=======================================================================
476
477Standard_Boolean ShapeFix_Wire::FixEdgeCurves()
478{
479 myStatusEdgeCurves = ShapeExtend::EncodeStatus ( ShapeExtend_OK );
480 if ( ! IsLoaded() ) return Standard_False;
481 Standard_Boolean isReady = IsReady();
482
483 Handle(ShapeExtend_WireData) sbwd = WireData();
484 Standard_Integer i, nb = sbwd->NbEdges();
485 TopoDS_Face face = Face();
486 Handle(ShapeFix_Edge) theAdvFixEdge = Handle(ShapeFix_Edge)::DownCast(myFixEdge);
487 if (theAdvFixEdge.IsNull()) myFixReversed2dMode = Standard_False;
488
489 // fix revesred 2d / 3d curves
490 if ( isReady && NeedFix ( myFixReversed2dMode ) ) {
491 for ( i=1; i <= nb; i++ ) {
492 theAdvFixEdge->FixReversed2d ( sbwd->Edge(i), face );
493 if ( theAdvFixEdge->Status ( ShapeExtend_DONE ) )
494 myStatusEdgeCurves |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE1 );
495 if ( theAdvFixEdge->Status ( ShapeExtend_FAIL ) )
496 myStatusEdgeCurves |= ShapeExtend::EncodeStatus ( ShapeExtend_FAIL1 );
497 }
498 }
499
500 // add / remove pcurve
501 if ( isReady && NeedFix ( myFixRemovePCurveMode, Standard_False ) ) {
502 for ( i=1; i <= nb; i++ ) {
503 myFixEdge->FixRemovePCurve ( sbwd->Edge(i), face );
504 if ( myFixEdge->Status ( ShapeExtend_DONE ) )
505 myStatusEdgeCurves |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE2 );
506 if ( myFixEdge->Status ( ShapeExtend_FAIL ) )
507 myStatusEdgeCurves |= ShapeExtend::EncodeStatus ( ShapeExtend_FAIL2 );
508 }
509 }
510
511 if ( isReady && NeedFix ( myFixAddPCurveMode ) ) {
512 Standard_Integer overdegen = 0; //:c0
513 for ( i=1; i <= nb; i++ ) {
514 myFixEdge->FixAddPCurve ( sbwd->Edge(i), face, sbwd->IsSeam(i),
515 myAnalyzer->Surface(), Precision() );
516 if ( myFixEdge->Status ( ShapeExtend_DONE ) )
517 myStatusEdgeCurves |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE3 );
518 if ( myFixEdge->Status ( ShapeExtend_FAIL ) )
519 myStatusEdgeCurves |= ShapeExtend::EncodeStatus ( ShapeExtend_FAIL3 );
520
521 //if ( !sbwd->IsSeam(i) && myFixEdge->Status ( ShapeExtend_DONE2 )
522 // && BRep_Tool::SameParameter(sbwd->Edge(i)) ) {
523 if ( !sbwd->IsSeam(i) && myFixEdge->Status ( ShapeExtend_DONE2 ) ) {
524 // abv 24 Feb 00: trj3_s1-ac-214.stp #1631 etc.: try to split the edge in singularity
525 if ( ! Context().IsNull() ) {
526 ShapeBuild_Edge sbe;
527 TopoDS_Edge E = sbwd->Edge ( i );
528 ShapeAnalysis_Curve SAC;
529 Standard_Real a, b;
530 Handle(Geom_Curve) C = BRep_Tool::Curve ( E, a, b );
531 Handle(ShapeAnalysis_Surface) S = myAnalyzer->Surface();
532 Standard_Integer nbs = S->NbSingularities(MinTolerance());
533 GeomAdaptor_Curve GAC ( C, a, b );
534 TColStd_SequenceOfReal seq;
535 for (Standard_Integer j=1; j <= nbs; j++) {
536 Standard_Real Preci;
537 gp_Pnt2d pd1, pd2;
538 gp_Pnt P3d, pr;
539 Standard_Real par1, par2, split;
540 Standard_Boolean tmpUIsoDeg;
541 S->Singularity (j, Preci, P3d, pd1, pd2, par1, par2, tmpUIsoDeg);
542 if ( SAC.Project ( GAC, P3d, MinTolerance(), pr, split, Standard_True ) < Max(Preci,MinTolerance()) ) {
543 if ( split - a > ::Precision::PConfusion() &&
544 b - split > ::Precision::PConfusion() ) {
545 Standard_Integer k;
546 for ( k=1; k <= seq.Length(); k++ ) {
547 if ( split < seq(k)-::Precision::PConfusion() ) {
548 seq.InsertBefore ( k, split );
549 break;
550 }
551 else if ( split < seq(k)+::Precision::PConfusion() ) break;
552 }
553 if ( k > seq.Length() ) seq.Append ( split );
554 }
555 }
556 }
557 if ( seq.Length() >0 ) { // supposed that edge is SP
558#ifdef DEB
559 cout << "Edge going over singularity detected; splitted" << endl;
560#endif
561 Standard_Boolean isFwd = ( E.Orientation() == TopAbs_FORWARD );
562 E.Orientation ( TopAbs_FORWARD );
563
564 //if( BRep_Tool::SameParameter(sbwd->Edge(i)) )
565 // sbe.RemovePCurve ( E, face );
566
567 //10.04.2003 skl for using trimmed lines as pcurves
568 ShapeAnalysis_Edge sae;
569 if( BRep_Tool::SameParameter(sbwd->Edge(i)) )
570 sbe.RemovePCurve ( E, face );
571 else {
572 if(sae.HasPCurve(E,face)) {
573 Handle(Geom2d_Curve) C2d;
574 Standard_Real fp2d,lp2d;
575 if(sae.PCurve(E,face,C2d,fp2d,lp2d)) {
576 if( !C2d->IsKind(STANDARD_TYPE(Geom2d_TrimmedCurve)) )
577 sbe.RemovePCurve(E,face);
578 }
579 }
580 }
581
582// myFixEdge->FixSameParameter ( E ); // to ensure SameRange & SP
583 BRep_Builder B;
584 TopoDS_Vertex V1, V2, V;
585 //ShapeAnalysis_Edge sae;
586 V1 = sae.FirstVertex ( E );
587 V2 = sae.LastVertex ( E );
588 Handle(ShapeExtend_WireData) sw = new ShapeExtend_WireData;
589 for ( Standard_Integer k=0; k <= seq.Length(); k++ ) {
590 Standard_Real split = ( k < seq.Length() ? seq(k+1) : b );
591 if ( k < seq.Length() )
592 B.MakeVertex ( V, C->Value(split), BRep_Tool::Tolerance(E) );
593 else V = V2;
594 TopoDS_Edge edge = sbe.CopyReplaceVertices ( E, V1, V );
595 if( BRep_Tool::SameParameter(sbwd->Edge(i)) ) {
596 //TopoDS_Edge edge = sbe.CopyReplaceVertices ( E, V1, V );
597 B.Range ( edge, a, split );
598 sw->Add ( edge );
599 }
600 else {
601 //TopoDS_Edge edge = sbe.CopyReplaceVertices(sbwd->Edge(i),V1,V);
602 Handle(ShapeAnalysis_TransferParameters) sftp =
603 new ShapeAnalysis_TransferParameters(E,face);
604 sftp->TransferRange(edge, a, split, Standard_False);
605 sw->Add(edge);
606 }
607 //sw->Add(edge);
608 a = split;
609 V1 = V;
610 }
611 if ( ! isFwd ) {
612 sw->Reverse();
613 E.Orientation ( TopAbs_REVERSED );
614 }
615 Context()->Replace ( E, sw->Wire() );
616 UpdateWire();
617 nb = sbwd->NbEdges();
618 i--;
619 continue;
620 }
621 }
622
623 overdegen = i;
624 }
625 }
626
627 //:c0 abv 20 Feb 98: treat case of curve going over degenerated pole and seam
628 if ( overdegen && myAnalyzer->Surface()->IsUClosed(Precision()) ) {
629 ShapeBuild_Edge sbe;
630 Standard_Real URange, SUF, SUL, SVF, SVL;
631 myAnalyzer->Surface()->Bounds(SUF, SUL, SVF, SVL);
632 URange = (Abs(SUL - SUF));
633 gp_XY vec(0,0);
634 ShapeAnalysis_Edge sae;
635 Standard_Integer k;
636 for ( k = 1; k <= nb; k++) {
637 Standard_Real cf, cl;
638 Handle(Geom2d_Curve) c2d;
639 if ( ! sae.PCurve ( sbwd->Edge(k), face, c2d, cf, cl, Standard_True ) ) break;
640 vec += c2d->Value(cl).XY() - c2d->Value(cf).XY();
641 }
642 if ( k > nb && Abs ( Abs ( vec.X() ) - URange ) < 0.1 * URange ) {
643 sbe.RemovePCurve (sbwd->Edge ( overdegen ), face);
644 myFixEdge->Projector()->AdjustOverDegenMode() = Standard_False;
645 myFixEdge->FixAddPCurve ( sbwd->Edge(overdegen), face, sbwd->IsSeam(overdegen), myAnalyzer->Surface(), Precision());
646 }
647#ifdef DEB
648 cout << "Edge going over singularity detected; pcurve adjusted" << endl;
649#endif
650 }
651 }
652
653 // add / remove pcurve
654 if ( isReady && NeedFix ( myFixRemoveCurve3dMode, Standard_False ) ) {
655 for ( i=1; i <= nb; i++ ) {
656 myFixEdge->FixRemoveCurve3d ( sbwd->Edge(i) );
657 if ( myFixEdge->Status ( ShapeExtend_DONE ) )
658 myStatusEdgeCurves |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE4 );
659 if ( myFixEdge->Status ( ShapeExtend_FAIL ) )
660 myStatusEdgeCurves |= ShapeExtend::EncodeStatus ( ShapeExtend_FAIL4 );
661 }
662 }
663 if ( NeedFix ( myFixAddCurve3dMode ) ) {
664 for ( i=1; i <= nb; i++ ) {
665 myFixEdge->FixAddCurve3d ( sbwd->Edge(i) );
666 if ( myFixEdge->Status ( ShapeExtend_DONE ) )
667 myStatusEdgeCurves |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE5 );
668 if ( myFixEdge->Status ( ShapeExtend_FAIL ) ) {
669 //:abv 29.08.01: Spatial_firex_lofting.sat: if 3d curve cannot
670 // be built because edge has no pcurves either, remove that edge
671 Handle(Geom2d_Curve) C;
672 Handle(Geom_Surface) S;
673 TopLoc_Location L;
674 Standard_Real first, last;
675 BRep_Tool::CurveOnSurface ( sbwd->Edge(i), C, S, L, first, last );
676 if ( C.IsNull() ) {
677 sbwd->Remove ( i-- );
678 nb--;
679 myStatusEdgeCurves |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE5 );
680 if ( ! myShape.IsNull() )
681 SendWarning (Message_Msg ("FixWire.FixCurve3d.Removed")); // Incomplete edge (with no pcurves or 3d curve) removed
682 }
683 myStatusEdgeCurves |= ShapeExtend::EncodeStatus ( ShapeExtend_FAIL5 );
684 }
685 }
686 }
687
688 // fix seam
689 if ( isReady && NeedFix ( myFixSeamMode, Standard_False ) ) {
690 for ( i=1; i <= nb; i++ ) {
691 FixSeam ( i );
692 if ( LastFixStatus ( ShapeExtend_DONE ) )
693 myStatusEdgeCurves |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE6 );
694 if ( LastFixStatus ( ShapeExtend_FAIL ) )
695 myStatusEdgeCurves |= ShapeExtend::EncodeStatus ( ShapeExtend_FAIL6 );
696 }
697 }
698
699 // fix shifted
700 if ( isReady && NeedFix ( myFixShiftedMode ) ) {
701 FixShifted();
702 if ( LastFixStatus ( ShapeExtend_DONE ) )
703 myStatusEdgeCurves |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE7 );
704 if ( LastFixStatus ( ShapeExtend_FAIL ) )
705 myStatusEdgeCurves |= ShapeExtend::EncodeStatus ( ShapeExtend_FAIL7 );
706 }
707
708 // fix same parameter
709 if ( isReady && NeedFix ( myFixSameParameterMode ) ) {
710 for ( i=1; i <= nb; i++ ) {
711 // skl 28.10.2004 for OCC6366 - check SameRange
712 ShapeAnalysis_Edge sae;
713 Standard_Real First, Last;
714 Handle(Geom_Curve) tmpc3d = BRep_Tool::Curve(sbwd->Edge(i), First, Last);
715 if(sae.HasPCurve(sbwd->Edge(i),face)) {
716 Handle(Geom2d_Curve) C2d;
717 Standard_Real fp2d,lp2d;
718 if(sae.PCurve(sbwd->Edge(i),face,C2d,fp2d,lp2d)) {
719 if( fabs(First-fp2d)>Precision::PConfusion() ||
720 fabs(Last-fp2d)>Precision::PConfusion() ) {
721 BRep_Builder B;
722 B.SameRange(sbwd->Edge(i),Standard_False);
723 }
724 }
725 }
726 myFixEdge->FixSameParameter ( sbwd->Edge(i) );
727 if ( myFixEdge->Status ( ShapeExtend_DONE ) )
728 myStatusEdgeCurves |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE8 );
729 if ( myFixEdge->Status ( ShapeExtend_FAIL ) )
730 myStatusEdgeCurves |= ShapeExtend::EncodeStatus ( ShapeExtend_FAIL8 );
731 }
732 }
733
734 //:abv 10.06.02: porting C40 -> dev (CC670-12608.stp): moved from Perform()
735 // Update with face is needed for plane surfaces (w/o stored pcurves)
736 if ( NeedFix ( myFixVertexToleranceMode ) ) {
737 for ( i=1; i <= nb; i++) {
738 myFixEdge->FixVertexTolerance (sbwd->Edge (i), face);
739 if ( myFixEdge->Status ( ShapeExtend_DONE ) )
740 myStatusEdgeCurves |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE8 );
741 if ( myFixEdge->Status ( ShapeExtend_FAIL ) )
742 myStatusEdgeCurves |= ShapeExtend::EncodeStatus ( ShapeExtend_FAIL8 );
743 }
744 }
745
746 return StatusEdgeCurves ( ShapeExtend_DONE );
747}
748
749//=======================================================================
750//function : FixDegenerated
751//purpose :
752//=======================================================================
753
754Standard_Boolean ShapeFix_Wire::FixDegenerated()
755{
756 myStatusDegenerated = ShapeExtend::EncodeStatus ( ShapeExtend_OK );
757 if ( ! IsReady() ) return Standard_False;
758
759// if ( ! myAnalyzer->Surface()->HasSingularities ( Precision() ) ) return;
760
761 Standard_Integer lastcoded = -1, prevcoded = 0;
762 Standard_Integer stop = ( myClosedMode ? 0 : 1 );
763 for ( Standard_Integer i = NbEdges(); i > stop; i-- ) {
764 FixDegenerated ( i );
765 myStatusDegenerated |= myLastFixStatus;
766 //:r0 abv 19 Mar 99: PRO7226.stp #489490: remove duplicated degenerated edges
767 Standard_Integer coded = ( LastFixStatus ( ShapeExtend_DONE2 ) ? 1 : 0 );
768 if ( lastcoded ==-1 ) lastcoded = coded;
769 if ( coded && ( prevcoded || ( i ==1 && lastcoded ) ) && NbEdges() >1 ) {
770 Handle(ShapeExtend_WireData) sbwd = WireData();
771 BRep_Builder B;
772 sbwd->Remove ( i );
773 if ( ! prevcoded ) i = NbEdges();
774 B.Degenerated ( sbwd->Edge ( i++ ), Standard_False );
775 prevcoded = 0;
776 }
777 else prevcoded = coded;
778 }
779
780 if ( StatusDegenerated ( ShapeExtend_DONE ) && ! myShape.IsNull() ) {
781 SendWarning (Message_Msg ("FixWire.FixDegenerated.MSG0")); //Degenerated edge(s) detected
782 }
783
784 return StatusDegenerated ( ShapeExtend_DONE );
785}
786
787
788//=======================================================================
789//function : FixSelfIntersection
790//purpose : Applies FixSelfIntersectingEdge and FixIntersectingEdges
791// and removes wrong edges
792//=======================================================================
793
794Standard_Boolean ShapeFix_Wire::FixSelfIntersection()
795{
796 myStatusSelfIntersection = ShapeExtend::EncodeStatus ( ShapeExtend_OK );
797 if ( ! IsReady() ) return Standard_False;
798
799 Handle(ShapeExtend_WireData) sbwd = WireData();
800 Standard_Integer nb = sbwd->NbEdges();
801
802 if ( NeedFix ( myFixSelfIntersectingEdgeMode ) ) {
803 if (myRemoveLoopMode<1)
804 for ( Standard_Integer num=1; num <=nb; num++ )
805 {
806 FixSelfIntersectingEdge ( num );
807 myStatusSelfIntersection |= myLastFixStatus;
808 }
809 else if (myRemoveLoopMode==1)
810 {
811 for ( Standard_Integer num=1; num <=nb; num++ )
812 {
813 FixSelfIntersectingEdge ( num );
814 myStatusSelfIntersection |= myLastFixStatus;
815 if(nb<sbwd->NbEdges()) num--;
816 nb = sbwd->NbEdges();
817 }
818 FixClosed(Precision());
819 }
820 }
821
822 if ( NeedFix ( myFixIntersectingEdgesMode ) ) {
823 Standard_Integer num = ( myClosedMode ? 1 : 2 );
824 for ( ; nb >1 && num <= nb; num++ ) {
825 FixIntersectingEdges ( num );
826 if ( LastFixStatus ( ShapeExtend_FAIL1 ) )
827 myStatusSelfIntersection |= ShapeExtend::EncodeStatus ( ShapeExtend_FAIL1 );
828 if ( LastFixStatus ( ShapeExtend_FAIL2 ) )
829 myStatusSelfIntersection |= ShapeExtend::EncodeStatus ( ShapeExtend_FAIL2 );
830 if ( ! LastFixStatus ( ShapeExtend_DONE ) ) continue;
831
832 if ( LastFixStatus ( ShapeExtend_DONE1 ) )
833 myStatusSelfIntersection |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE1 );
834 if ( LastFixStatus ( ShapeExtend_DONE2 ) )
835 myStatusSelfIntersection |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE2 );
836 if(LastFixStatus (ShapeExtend_DONE6))
837 myStatusSelfIntersection |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE6 );
838
839 if ( ! myTopoMode || nb < 3 ) {
840 //#86 rln 22.03.99 sim2.igs, entity 4292: After fixing of self-intersecting
841 //BRepCheck finds one more self-intersection not found by ShapeAnalysis
842 //%15 pdn 06.04.99 repeat until fixed CTS18546-2 entity 777
843 //FixIntersectingEdges ( num );
844 if ( LastFixStatus ( ShapeExtend_DONE7 ) ) num--;
845 continue;
846 }
847
848 if ( LastFixStatus ( ShapeExtend_DONE4 ) ) sbwd->Remove ( num );
849 if ( LastFixStatus ( ShapeExtend_DONE3 ) ) sbwd->Remove ( num >1 ? num-1 : nb+num-1 );
850 if ( LastFixStatus ( ShapeExtend_DONE4 ) ||
851 LastFixStatus ( ShapeExtend_DONE3 ) ) {
852 myStatusSelfIntersection |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE3 );
853 num = ( myClosedMode ? 1 : 2 );
854 nb = sbwd->NbEdges();
855#ifdef DEB
856 cout << "Warning: ShapeFix_Wire::FixSelfIntersection: Edge removed" << endl;
857#endif
858 }
859 else {
860 //#86 rln 22.03.99
861 //%15 pdn 06.04.99 repeat until fixed CTS18546-2 entity 777
862 //FixIntersectingEdges ( num );
863 if ( LastFixStatus ( ShapeExtend_DONE7 ) ) num--;
864 }
865 }
866 }
867
868 //pdn 17.03.99 S4135 to avoid regression fixing not adjacent intersection
869 if ( NeedFix ( myFixNonAdjacentIntersectingEdgesMode ) ) {
870
871 ShapeFix_IntersectionTool ITool(Context(),Precision());
872 Standard_Integer NbSplit=0, NbCut=0,NbRemoved=0;
873 if(ITool.FixSelfIntersectWire(sbwd,myAnalyzer->Face(),NbSplit,NbCut,NbRemoved)) {
874 myStatusSelfIntersection |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE5 );//gka 06.09.04
875 }
876 if( NbSplit>0 || NbRemoved>0 ) {
877 if(NbRemoved>0) myStatusRemovedSegment = Standard_True;
878 //Load(sbwd); commented by skl 29.12.2004 for OCC7624, instead this
879 // string inserted following three strings:
880 myAnalyzer->Load ( sbwd );
881 if ( ! Context().IsNull() ) UpdateWire();
882 myShape.Nullify();
883 }
884#ifdef DEB
885 if (StatusSelfIntersection (ShapeExtend_DONE5))
886 cout<<"Warning: ShapeFix_Wire::FixIntersection: Non-adjacent intersection fixed (split-"
887 <<NbSplit<<", cut-"<<NbCut<<", removed-"<<NbRemoved<<")"<<endl;
888#endif
889
890/*
891 Bnd_Array1OfBox2d boxes(1,nb);
892 TopLoc_Location L;
893 const Handle(Geom_Surface)& S = BRep_Tool::Surface(Face(), L);
894 Handle(Geom2d_Curve) c2d;
895 Standard_Real cf,cl;
896 ShapeAnalysis_Edge sae;
897 for(Standard_Integer i = 1; i <= nb; i++){
898 TopoDS_Edge E = sbwd->Edge (i);
899 if(sae.PCurve (E,S,L,c2d,cf,cl,Standard_False)) {
900 Bnd_Box2d box;
901 Geom2dAdaptor_Curve gac;
902 Standard_Real aFirst = c2d->FirstParameter();
903 Standard_Real aLast = c2d->LastParameter();
904 if(c2d->IsKind(STANDARD_TYPE(Geom2d_BSplineCurve))
905 && (cf < aFirst || cl > aLast)) {
906 //pdn avoiding problems with segment in Bnd_Box
907 gac.Load(c2d);
908 }
909 else
910 gac.Load(c2d,cf,cl);
911 BndLib_Add2dCurve::Add(gac,::Precision::Confusion(),box);
912 boxes(i) = box;
913 }
914 }
915
916 Standard_Boolean isFail = Standard_False, isDone = Standard_False;
917 for(Standard_Integer num1 = 1; num1 < nb-1; num1++) {
918 Standard_Integer fin = (num1 == 1 ? nb-1 : nb);
919 for(Standard_Integer num2 = num1+2; num2 <= fin; num2++)
920 if(!boxes(num1).IsOut(boxes(num2))){
921 FixIntersectingEdges (num1, num2);
922 isFail |= LastFixStatus ( ShapeExtend_FAIL1 );
923 isDone |= LastFixStatus ( ShapeExtend_DONE1 );
924 }
925 }
926
927 if(isFail)
928 myStatusSelfIntersection |= ShapeExtend::EncodeStatus ( ShapeExtend_FAIL3 );
929 if(isDone)
930 myStatusSelfIntersection |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE5 );
931#ifdef DEB
932 if (StatusSelfIntersection (ShapeExtend_DONE5))
933 cout << "Warning: ShapeFix_Wire::FixSelfIntersection: Non ajacent intersection fixed" << endl;
934#endif
935*/
936 }
937
938 if ( StatusSelfIntersection ( ShapeExtend_DONE ) && ! myShape.IsNull() ) {
939 SendWarning (Message_Msg ("FixAdvWire.FixIntersection.MSG0")); // Self-intersection corrected
940 }
941 return StatusSelfIntersection ( ShapeExtend_DONE );
942}
943
944
945//=======================================================================
946//function : FixLacking
947//purpose :
948//=======================================================================
949
950Standard_Boolean ShapeFix_Wire::FixLacking ( const Standard_Boolean force )
951{
952 myStatusLacking = ShapeExtend::EncodeStatus ( ShapeExtend_OK );
953 if ( ! IsReady() ) return Standard_False;
954
955 Standard_Integer start = ( myClosedMode ? 1 : 2 );
956 for ( Standard_Integer i = start; i <= NbEdges(); i++ ) {
957 FixLacking ( i, force );
958 myStatusLacking |= myLastFixStatus;
959 }
960
961 return StatusLacking ( ShapeExtend_DONE );
962}
963
964
965//=======================================================================
966//function : FixClosed
967//purpose :
968//=======================================================================
969
970Standard_Boolean ShapeFix_Wire::FixClosed (const Standard_Real prec)
971{
972 myStatusClosed = ShapeExtend::EncodeStatus ( ShapeExtend_OK );
973 if ( ! IsLoaded() || NbEdges() <1 ) return Standard_False;
974
975 FixConnected ( 1, prec );
976 if ( LastFixStatus ( ShapeExtend_DONE ) )
977 myStatusClosed |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE1 );
978 if ( LastFixStatus ( ShapeExtend_FAIL ) )
979 myStatusClosed |= ShapeExtend::EncodeStatus ( ShapeExtend_FAIL1 );
980
981 FixDegenerated ( 1 );
982 if ( LastFixStatus ( ShapeExtend_DONE ) )
983 myStatusClosed |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE2 );
984 if ( LastFixStatus ( ShapeExtend_FAIL ) )
985 myStatusClosed |= ShapeExtend::EncodeStatus ( ShapeExtend_FAIL2 );
986
987 FixLacking ( 1 );
988 if ( LastFixStatus ( ShapeExtend_DONE ) )
989 myStatusClosed |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE3 );
990 if ( LastFixStatus ( ShapeExtend_FAIL ) )
991 myStatusClosed |= ShapeExtend::EncodeStatus ( ShapeExtend_FAIL3 );
992
993 return StatusClosed ( ShapeExtend_DONE );
994}
995
996
997//#######################################################################
998// Fixing methods of advanced level
999//#######################################################################
1000
1001//=======================================================================
1002//function : FixReorder
1003//purpose :
1004//=======================================================================
1005
1006Standard_Boolean ShapeFix_Wire::FixReorder (const ShapeAnalysis_WireOrder& wi)
1007{
1008 myLastFixStatus = ShapeExtend::EncodeStatus ( ShapeExtend_OK );
1009 if ( ! IsLoaded() ) return Standard_False;
1010
1011 Standard_Integer status = wi.Status();
1012 if ( status ==0 ) return Standard_False;
1013 if ( status <=-10 ) {
1014 myLastFixStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_FAIL1 );
1015 return Standard_False;
1016 }
1017
1018 Handle(ShapeExtend_WireData) sbwd = WireData();
1019 Standard_Integer i, nb = sbwd->NbEdges();
1020 if ( nb != wi.NbEdges() ) {
1021 myLastFixStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_FAIL2 );
1022 return Standard_False;
1023 }
1024 // D abord on protege
1025 for (i = 1; i <= nb; i ++) {
1026 if ( wi.Ordered(i) == 0 ) {
1027 myLastFixStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_FAIL3 );
1028 return Standard_False;
1029 }
1030 }
1031
1032 Handle(TopTools_HSequenceOfShape) newedges = new TopTools_HSequenceOfShape();
1033 for ( i=1; i <= nb; i++ )
1034 newedges->Append ( sbwd->Edge ( wi.Ordered(i) ) );
1035 for ( i=1; i <= nb; i++ )
1036 sbwd->Set ( TopoDS::Edge ( newedges->Value(i) ), i );
1037
1038 myLastFixStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE1 );
1039 return Standard_True;
1040}
1041
1042
1043//=======================================================================
1044//function : FixSmall
1045//purpose :
1046//=======================================================================
1047
1048Standard_Boolean ShapeFix_Wire::FixSmall (const Standard_Integer num,
1049 const Standard_Boolean lockvtx,
1050 const Standard_Real precsmall)
1051{
1052 myLastFixStatus = ShapeExtend::EncodeStatus ( ShapeExtend_OK );
1053 if ( ! IsLoaded() || NbEdges() <=1 ) return Standard_False;
1054
1055 // analysis:
1056 Handle(ShapeAnalysis_Wire) theAdvAnalyzer = Handle(ShapeAnalysis_Wire)::DownCast(myAnalyzer);
1057 if (theAdvAnalyzer.IsNull()) return Standard_False;
1058 Standard_Integer n = ( num >0 ? num : NbEdges() );
1059 theAdvAnalyzer->CheckSmall ( n, precsmall );
1060 if ( theAdvAnalyzer->LastCheckStatus ( ShapeExtend_FAIL ) ) {
1061 myLastFixStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_FAIL1 );
1062//:n2 return Standard_False;
1063 }
1064
1065 if ( ! theAdvAnalyzer->LastCheckStatus ( ShapeExtend_DONE ) ) return Standard_False;
1066
1067 // OUI cette edge est NULLE
1068
1069 if ( theAdvAnalyzer->LastCheckStatus ( ShapeExtend_DONE2 ) ) {
1070 // edge is small, but vertices are not the same..
1071 if ( lockvtx || ! myTopoMode ) {
1072 myLastFixStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_FAIL2 );
1073 return Standard_False;
1074 }
1075 myLastFixStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE2 );
1076 }
1077 else myLastFixStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE1 );
1078
1079 // action: remove edge
1080 if ( ! Context().IsNull() ) Context()->Remove(WireData()->Edge(n));
1081 WireData()->Remove ( n );
1082
1083 // call FixConnected in the case if vertices of the small edge were not the same
1084 if ( LastFixStatus ( ShapeExtend_DONE2 ) ) {
1085 Standard_Integer savLastFixStatus = myLastFixStatus;
1086 //#43 rln 20.11.98 S4054 CTS18544 entity 21734 removing last edge
1087 FixConnected ( n <= NbEdges() ? n : 1, precsmall );
1088 if ( LastFixStatus ( ShapeExtend_FAIL ) )
1089 savLastFixStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_FAIL3 );
1090 myLastFixStatus = savLastFixStatus;
1091 }
1092
1093 if ( ! myShape.IsNull() ) {
1094 Message_Msg MSG ("FixAdvWire.FixSmall.MSG0"); //Small edge %d removed
1095 MSG.Arg (n);
1096 SendWarning (MSG);
1097 }
1098 return Standard_True;
1099}
1100
1101
1102//=======================================================================
1103//function : FixConnected
1104//purpose :
1105//=======================================================================
1106
1107Standard_Boolean ShapeFix_Wire::FixConnected (const Standard_Integer num,
1108 const Standard_Real prec)
1109{
1110 myLastFixStatus = ShapeExtend::EncodeStatus ( ShapeExtend_OK );
1111 if ( ! IsLoaded() || NbEdges() <=0 ) return Standard_False;
1112
1113 // analysis
1114
1115 myAnalyzer->CheckConnected ( num, prec < 0 ? MaxTolerance() : prec );
1116 if ( myAnalyzer->LastCheckStatus ( ShapeExtend_FAIL ) ) {
1117 myLastFixStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_FAIL1 );
1118 }
1119 if ( ! myAnalyzer->LastCheckStatus ( ShapeExtend_DONE ) ) return Standard_False;
1120
1121 // action: replacing vertex
1122
1123 Handle(ShapeExtend_WireData) sbwd = WireData();
1124 Standard_Integer n2 = ( num >0 ? num : sbwd->NbEdges() );
1125 Standard_Integer n1 = ( n2 >1 ? n2-1 : sbwd->NbEdges() );
1126 TopoDS_Edge E1 = sbwd->Edge(n1);
1127 TopoDS_Edge E2 = sbwd->Edge(n2);
1128
1129 ShapeAnalysis_Edge sae;
1130 TopoDS_Vertex V1 = sae.LastVertex (E1);
1131 TopoDS_Vertex V2 = sae.FirstVertex (E2);
1132 TopoDS_Vertex V;
1133
1134 if ( myAnalyzer->LastCheckStatus ( ShapeExtend_DONE1 ) ) { // absolutely confused
1135 myLastFixStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE1 );
1136 //#40 rln 18.11.98 S4054 BUC60035 entity 2393 (2-nd sub-curve is edge with the same vertex)
1137 if ( V2.IsSame ( sae.LastVertex (E2) ) ) {
1138 V = V2;
1139 if ( ! Context().IsNull() )
1140 Context()->Replace ( V1, V.Oriented(V1.Orientation()) );
1141 }
1142 else {
1143 V = V1;
1144 if ( ! Context().IsNull() )
1145 Context()->Replace ( V2, V.Oriented(V2.Orientation()) );
1146 }
1147 }
1148 else { // on moyenne ...
1149 if ( myAnalyzer->LastCheckStatus ( ShapeExtend_DONE2 ) )
1150 myLastFixStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE2 );
1151 else myLastFixStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE3 );
1152 ShapeBuild_Vertex sbv;
1153 V = sbv.CombineVertex ( V1, V2, 1.0001 );
1154 if ( ! Context().IsNull() ) {
1155 Context()->Replace ( V1, V.Oriented(V1.Orientation()) );
1156 Context()->Replace ( V2, V.Oriented(V2.Orientation()) );
1157 }
1158 }
1159
1160 // replace vertices to a new one
1161 ShapeBuild_Edge sbe;
1162 if ( sbwd->NbEdges() <2 ) {
1163 if(E2.Free() && myTopoMode) {
1164 BRep_Builder B;
1165 B.Remove(E2,sae.FirstVertex(E2));
1166 B.Remove(E2,sae.LastVertex(E2));
1167 B.Add(E2,V.Oriented(TopAbs_FORWARD));
1168 B.Add(E2,V.Oriented(TopAbs_REVERSED));
1169 }
1170 else {
1171 TopoDS_Edge tmpE = sbe.CopyReplaceVertices ( E2, V, V );
1172 sbwd->Set ( tmpE, n2 );
1173 if ( ! Context().IsNull() ) Context()->Replace(E2,tmpE);
1174 }
1175 }
1176 else {
1177 if(E2.Free() &&E1.Free() && myTopoMode) {
1178 BRep_Builder B;
1179 B.Remove(E2,sae.FirstVertex(E2));
1180 B.Add(E2,V.Oriented(TopAbs_FORWARD));
1181 if ( ! myAnalyzer->LastCheckStatus ( ShapeExtend_DONE1 ) ||
1182 sae.FirstVertex (E2).IsSame (sae.LastVertex (E2)) ) {
1183 B.Remove(E1,sae.LastVertex(E1));
1184 B.Add(E1,V.Oriented(TopAbs_REVERSED));
1185 }
1186 }
1187 else {
1188 TopoDS_Edge tmpE2 = sbe.CopyReplaceVertices ( E2, V, TopoDS_Vertex() );
1189 sbwd->Set ( tmpE2, n2 );
1190 if ( ! Context().IsNull() ) Context()->Replace(E2,tmpE2);
1191 if ( ! myAnalyzer->LastCheckStatus ( ShapeExtend_DONE1 ) ||
1192 sae.FirstVertex (E2).IsSame (sae.LastVertex (E2)) ) {
1193 TopoDS_Edge tmpE1 = sbe.CopyReplaceVertices ( E1, TopoDS_Vertex(), V );
1194 sbwd->Set (tmpE1, n1 );
1195 if ( ! Context().IsNull() ) Context()->Replace(E1,tmpE1);
1196 }
1197 }
1198 }
1199 if ( ! Context().IsNull() ) UpdateWire();
1200
1201 return Standard_True;
1202}
1203
1204
1205//=======================================================================
1206//function : FixSeam
1207//purpose :
1208//=======================================================================
1209
1210Standard_Boolean ShapeFix_Wire::FixSeam (const Standard_Integer num)
1211{
1212 myLastFixStatus = ShapeExtend::EncodeStatus ( ShapeExtend_OK );
1213 if ( ! IsReady() ) return Standard_False;
1214
1215 Handle(Geom2d_Curve) C1, C2;
1216 Standard_Real cf, cl;
1217 if ( ! myAnalyzer->CheckSeam (num, C1, C2, cf, cl) ) return Standard_False;
1218
1219 BRep_Builder B;
1220 TopoDS_Edge E = WireData()->Edge ( num >0 ? num : NbEdges() );
1221 B.UpdateEdge (E, C2,C1, Face(), 0.); //:S4136: BRep_Tool::Tolerance(E)
1222 B.Range (E, Face(),cf,cl);
1223 myLastFixStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE1 );
1224
1225 return Standard_True;
1226}
1227
1228//=======================================================================
1229//function : FixShifted
1230//purpose : fix parametric curves which may be shifted
1231// to whole parametric range of closed surface as result of recomputing
1232// from 3d representation.
1233// This can be a curve on a seam or near it.
1234// This function is to be called before FixDegenerated.
1235// LIMITATION: this function cannot fix cases when, e.g., closed wire is
1236// composed of two meridians of the sphere and one of them is seam.
1237// NOTE: wire is supposed to be closed and sorted !
1238//=======================================================================
1239
1240//:p4 abv 23.02.99: PRO9234 #15720: update UV points of edge
1241static void UpdateEdgeUVPoints (TopoDS_Edge &E, const TopoDS_Face &F)
1242{
1243 Standard_Real first, last;
1244 BRep_Tool::Range ( E, F, first, last );
1245 BRep_Builder().Range ( E, F, first, last );
1246}
1247
1248
1249//=======================================================================
1250//function : FixShifted
1251//purpose :
1252//=======================================================================
1253
1254Standard_Boolean ShapeFix_Wire::FixShifted()
1255{
1256 myLastFixStatus = ShapeExtend::EncodeStatus ( ShapeExtend_OK );
1257 if ( ! IsReady() ) return Standard_False;
1258
1259 Handle(ShapeAnalysis_Surface) surf = myAnalyzer->Surface();
1260 //#78 rln 12.03.99 S4135: checking spatial closure with Precision
1261 Standard_Boolean uclosed = surf->IsUClosed(Precision());
1262 Standard_Boolean vclosed = surf->IsVClosed(Precision()) || surf->Surface()->IsKind (STANDARD_TYPE(Geom_SphericalSurface));
1263 //#67 rln 01.03.99 S4135: ims010.igs entity D11900 (2D contour is 2*PI higher than V range [-pi/2,p/2])
1264
1265 // PTV 26.06.2002 begin
1266 // CTS18546-2.igs entity 2222: base curve is periodic and 2dcurve is shifted
1267 Standard_Boolean IsVCrvClosed = Standard_False;
1268 Standard_Real VRange = 1.;
1269 if (surf->Surface()->IsKind (STANDARD_TYPE(Geom_SurfaceOfRevolution))) {
1270 Handle(Geom_SurfaceOfRevolution) aSurOfRev = Handle(Geom_SurfaceOfRevolution)::DownCast(surf->Surface());
1271 Handle(Geom_Curve) aBaseCrv = aSurOfRev->BasisCurve();
1272 while ( (aBaseCrv->IsKind(STANDARD_TYPE(Geom_OffsetCurve))) ||
1273 (aBaseCrv->IsKind(STANDARD_TYPE(Geom_TrimmedCurve))) ) {
1274 if (aBaseCrv->IsKind(STANDARD_TYPE(Geom_OffsetCurve)))
1275 aBaseCrv = Handle(Geom_OffsetCurve)::DownCast(aBaseCrv)->BasisCurve();
1276 if (aBaseCrv->IsKind(STANDARD_TYPE(Geom_TrimmedCurve)))
1277 aBaseCrv = Handle(Geom_TrimmedCurve)::DownCast(aBaseCrv)->BasisCurve();
1278 }
1279 if (aBaseCrv->IsPeriodic()) {
1280 vclosed = Standard_True;
1281 VRange = aBaseCrv->Period();
1282 IsVCrvClosed = Standard_True;
1283#ifdef DEB
1284 cout << "Warning: ShapeFix_Wire::FixShifted set vclosed True for Surface of Revolution" << endl;
1285#endif
1286 }
1287 }
1288 // PTV 26.06.2002 end
1289 if ( ! uclosed && ! vclosed ) return Standard_False;
1290
1291 Standard_Real URange, /*VRange,*/ SUF, SUL, SVF, SVL;
1292 surf->Surface()->Bounds ( SUF, SUL, SVF, SVL );
1293 Standard_Real SUMid, SVMid;
1294 SUMid = 0.5*(SUF+SUL);
1295 SVMid = 0.5*(SVF+SVL);
1296 if (uclosed) URange = Abs ( SUL - SUF );
1297 else URange = RealLast();
1298 if (!IsVCrvClosed)
1299 if (vclosed) VRange = Abs ( SVL - SVF );
1300 else VRange = RealLast();
1301 Standard_Real UTol = 0.2 * URange, VTol = 0.2 * VRange;
1302
1303 Handle(ShapeExtend_WireData) sbwdOring = WireData();
1304 ShapeAnalysis_Edge sae;
1305 Handle(ShapeExtend_WireData) sbwd = new ShapeExtend_WireData;
1306 for ( Standard_Integer i=1; i <= sbwdOring->NbEdges(); i++ ) {
1307 TopoDS_Edge E1 = sbwdOring->Edge ( i );
1308 if ( BRep_Tool::Degenerated(E1) && !sae.HasPCurve(E1,Face()))
1309 continue;
1310
1311 sbwd->Add(E1);
1312 }
1313
1314 ShapeBuild_Edge sbe;
1315 Standard_Integer nb = sbwd->NbEdges();
1316 Standard_Boolean end = (nb == 0), degstop = Standard_False;;
1317 Standard_Integer stop = nb;
1318 Standard_Integer degn2 = 0;
1319 gp_Pnt pdeg;
1320 //pdn 17.12.98 r0901_ec 38237 to shift wire at 0
1321
1322 //GeomAdaptor_Surface& GAS = myAnalyzer->Surface()->Adaptor3d()->ChangeSurface(); //SK
1323 Bnd_Box2d box;
1324 for ( Standard_Integer n2=1, n1=nb; ! end; n1 = n2++ ) {
1325 if ( n2 > nb ) n2 = 1;
1326 if ( n2 == stop ) end = Standard_True;
1327
1328 TopoDS_Edge E1 = sbwd->Edge ( n1 );
1329 TopoDS_Edge E2 = sbwd->Edge ( n2 );
1330
1331 if ( BRep_Tool::Degenerated(E1) || BRep_Tool::Degenerated(E2) ) {
1332 if ( ! degstop ) { stop = n2; degstop = Standard_True; }
1333 continue;
1334 }
1335
1336 TopoDS_Vertex V = sae.FirstVertex ( E2 );
1337 gp_Pnt p = BRep_Tool::Pnt ( V );
1338
1339 Standard_Real a1, b1, a2, b2;
1340 Handle(Geom2d_Curve) c2d1, c2d2;
1341
1342 //:abv 29.08.01: torCuts.sat: distinguish degeneration by U and by V;
1343 // only corresponding move is prohibited
1344// Standard_Boolean isDeg = surf->IsDegenerated ( p, Max ( Precision(), BRep_Tool::Tolerance(V) ) );
1345 Standard_Integer isDeg = 0;
1346 gp_Pnt2d degP1, degP2;
1347 Standard_Real degT1, degT2;
1348 if ( surf->DegeneratedValues ( p, Max ( Precision(), BRep_Tool::Tolerance(V) ),
1349 degP1, degP2, degT1, degT2 ) )
1350 isDeg = ( Abs ( degP1.X() - degP2.X() ) > Abs ( degP1.Y() - degP2.Y() ) ? 1 : 2 );
1351
1352 // abv 23 Feb 00: UKI60107-6 210: additional check for near-degenerated case
1353 //smh#15 PRO19800. Check if the surface is surface of revolution.
1354 if (surf->Surface()->IsKind (STANDARD_TYPE(Geom_SurfaceOfRevolution))) {
1355 if ( ! isDeg && ! vclosed ) {
1356 if ( c2d1.IsNull() && ! sae.PCurve ( E1, Face(), c2d1, a1, b1, Standard_True ) ) continue;
1357 gp_Pnt2d p1 ( SUF, c2d1->Value(b1).Y() );
1358 gp_Pnt2d p2 ( SUL, c2d1->Value(b1).Y() );
1359 if ( surf->IsDegenerated ( p1, p2, MaxTolerance(), 10 ) &&
1360 ! 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 isDeg = 1;
1362 }
1363 if ( ! isDeg && ! uclosed ) {
1364 if ( c2d1.IsNull() && ! sae.PCurve ( E1, Face(), c2d1, a1, b1, Standard_True ) ) continue;
1365 gp_Pnt2d p1 ( c2d1->Value(b1).X(), SVF );
1366 gp_Pnt2d p2 ( c2d1->Value(b1).X(), SVL );
1367 if ( surf->IsDegenerated ( p1, p2, MaxTolerance(), 10 ) &&
1368 ! 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
1369 isDeg = 2;
1370 }
1371 }
1372
1373 if ( isDeg ) {
1374 if ( ! degstop ) { stop = n2; degstop = Standard_True; }
1375 if ( ! degn2 ) { degn2 = n2; pdeg = p; }
1376 else if ( pdeg.SquareDistance(p) < Precision()*Precision() ) {
1377 degn2 = n2;
1378// if ( stop < n2 ) { stop = n2; degstop = Standard_True; }
1379 }
1380 else {
1381 Standard_Real ax1, bx1, ax2, bx2;
1382 Handle(Geom2d_Curve) cx1, cx2;
1383 if ( ( c2d1.IsNull() && ! sae.PCurve ( E1, Face(), c2d1, a1, b1, Standard_True ) ) ||
1384 ( c2d2.IsNull() && ! sae.PCurve ( E2, Face(), c2d2, a2, b2, Standard_True ) ) ||
1385 ! sae.PCurve ( sbwd->Edge ( degn2 >1 ? degn2-1 : nb ), Face(), cx1, ax1, bx1, Standard_True ) ||
1386 ! sae.PCurve ( sbwd->Edge ( degn2 ), Face(), cx2, ax2, bx2, Standard_True ) ) {
1387 myLastFixStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_FAIL1 );
1388 continue;
1389 }
1390 gp_Pnt2d pd1 = cx1->Value ( bx1 );
1391 gp_Pnt2d pd2 = cx2->Value ( ax2 );
1392 gp_Pnt2d pn1 = c2d1->Value ( b1 );
1393 gp_Pnt2d pn2 = c2d2->Value ( a2 );
1394 gp_Vec2d x(0.,0.); // shift vector
1395 Standard_Real period;
1396 if ( uclosed ) { x.SetX ( 1. ); period = URange; }
1397 else { x.SetY ( 1. ); period = VRange; }
1398 Standard_Real rot1 = ( pn1.XY() - pd2.XY() ) ^ x.XY();
1399 Standard_Real rot2 = ( pd1.XY() - pn2.XY() ) ^ x.XY();
1400 Standard_Real scld = ( pd2.XY() - pd1.XY() ) * x.XY();
1401 Standard_Real scln = ( pn2.XY() - pn1.XY() ) * x.XY();
1402 if ( rot1 * rot2 < -::Precision::PConfusion() &&
1403 scld * scln < -::Precision::PConfusion() &&
1404 Abs ( scln ) > 0.1 * period && Abs ( scld ) > 0.1 * period &&
1405 rot1 * scld > ::Precision::PConfusion() &&
1406 rot2 * scln > ::Precision::PConfusion() ) {
1407 // abv 02 Mar 00: trying more sophisticated analysis (ie_exhaust-A.stp #37520)
1408 Standard_Real sign = ( rot2 >0 ? 1. : -1. );
1409 Standard_Real deep1 = Min ( sign * ( pn2.XY() * x.XY() ),
1410 Min ( sign * ( pd1.XY() * x.XY() ),
1411 Min ( sign * ( c2d2->Value(b2 ).XY() * x.XY() ),
1412 Min ( sign * ( cx1->Value(ax1).XY() * x.XY() ),
1413 Min ( sign * ( c2d2->Value(0.5*(a2 +b2 )).XY() * x.XY() ),
1414 sign * ( cx1->Value(0.5*(ax1+bx1)).XY() * x.XY() ) ) ) ) ) );
1415 Standard_Real deep2 = Max ( sign * ( pn1.XY() * x.XY() ),
1416 Max ( sign * ( pd2.XY() * x.XY() ),
1417 Max ( sign * ( c2d1->Value(a1 ).XY() * x.XY() ),
1418 Max ( sign * ( cx2->Value(bx2).XY() * x.XY() ),
1419 Max ( sign * ( c2d1->Value(0.5*(a1 +b1 )).XY() * x.XY() ),
1420 sign * ( cx2->Value(0.5*(ax2+bx2)).XY() * x.XY() ) ) ) ) ) );
1421 Standard_Real deep = deep2 - deep1; // estimated current size of wire by x
1422 // pdn 30 Oct 00: trying correct period [0,period] (trj5_k1-tc-203.stp #4698)
1423 Standard_Real dx = ShapeAnalysis::AdjustToPeriod ( deep, ::Precision::PConfusion(), period+::Precision::PConfusion());
1424 x *= ( scld >0 ? -dx : dx );
1425// x *= ( Abs(scld-scln) > 1.5 * period ? 2. : 1. ) *
1426// ( scld >0 ? -period : period );
1427 gp_Trsf2d Shift;
1428 Shift.SetTranslation ( x );
1429 for ( Standard_Integer k=degn2; ; k++ ) {
1430 if ( k > nb ) k = 1;
1431 if ( k == n2 ) break;
1432 TopoDS_Edge edge = sbwd->Edge ( k );
1433 if ( ! sae.PCurve ( edge, Face(), cx1, ax1, bx1, Standard_True ) ) continue;
1434 //cx1->Transform ( Shift );
1435 // skl 15.05.2002 for OCC208 (if few edges have reference to one pcurve)
1436 Handle(Geom2d_Curve) cx1new = Handle(Geom2d_Curve)::DownCast(cx1->Transformed(Shift));
1437 sbe.ReplacePCurve(edge,cx1new,Face());
1438 UpdateEdgeUVPoints ( edge, Face() );
1439 }
1440 myLastFixStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE1 );
1441#ifdef DEB
1442 cout << "Info: ShapeFix_Wire::FixShifted(): bi - meridian case fixed" << endl;
1443#endif
1444 }
1445// degn2 = n2; pdeg = p; // ie_exhaust-A.stp #37520
1446 continue;
1447 }
1448/*
1449 // pdn to fix half sphere
1450 TopoDS_Vertex VE = sae.LastVertex ( E2 );
1451 gp_Pnt pe = BRep_Tool::Pnt ( VE );
1452 //pdn is second vertex on singular point ?
1453 if ( surf->IsDegenerated ( pe, Max ( Precision(), BRep_Tool::Tolerance(V) ) ) ) {
1454 if ( ( c2d1.IsNull() && ! sae.PCurve ( E1, Face(), c2d1, a1, b1, Standard_True ) ) ||
1455 ( c2d2.IsNull() && ! sae.PCurve ( E2, Face(), c2d2, a2, b2, Standard_True ) ) ) {
1456 myLastFixStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_FAIL1 );
1457 continue;
1458 }
1459 gp_Pnt2d p2d1 = c2d1->Value ( b1 ), p2f = c2d2->Value ( a2 ), p2l = c2d2->Value ( b2 );
1460 Standard_Real pres2 = ::Precision::PConfusion();
1461 Standard_Real du = 0.,dv = 0.;
1462 //#79 rln 15.03.99 S4135: bmarkmdl.igs entity 633 (incorrectly oriented contour) check for gap
1463 if(uclosed&&(Abs(p2f.X()-p2l.X())<pres2)&&Abs(p2d1.X()-p2f.X())>GAS.UResolution(Precision())) {
1464 if((Abs(p2f.X()-SUF)<pres2)&&(p2f.Y()<p2l.Y()))
1465 du = URange;
1466 if((Abs(p2f.X()-SUL)<pres2)&&(p2f.Y()>p2l.Y()))
1467 du = -URange;
1468 }
1469 if(vclosed&&(Abs(p2f.Y()-p2l.Y())<pres2)&&Abs(p2d1.Y()-p2f.Y())>GAS.VResolution(Precision())) {
1470 if((Abs(p2f.Y()-SVF)<pres2)&&(p2f.X()>p2l.X()))
1471 dv = VRange;
1472 if((Abs(p2f.Y()-SVL)<pres2)&&(p2f.X()<p2l.X()))
1473 dv = -VRange;
1474 }
1475 if ( du ==0. && dv == 0. ) continue;
1476 myLastFixStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE1 );
1477 gp_Trsf2d Shift;
1478 Shift.SetTranslation ( gp_Vec2d ( du, dv ) );
1479 c2d2->Transform ( Shift );
1480 UpdateEdgeUVPoints ( E2, Face() );//rln 15.03.99 syntax correction :E1
1481 }
1482*/
1483//:abv 29.08.01: torCuts.sat: continue;
1484 }
1485
1486 if ( ( c2d1.IsNull() && ! sae.PCurve ( E1, Face(), c2d1, a1, b1, Standard_True ) ) ||
1487 ( c2d2.IsNull() && ! sae.PCurve ( E2, Face(), c2d2, a2, b2, Standard_True ) ) ) {
1488 myLastFixStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_FAIL1 );
1489 continue;
1490 }
1491 gp_Pnt2d p2d1 = c2d1->Value ( b1 );
1492 gp_Pnt2d p2d2 = c2d2->Value ( a2 );
1493 box.Add ( p2d1 );
1494
1495 Standard_Real du=0., dv=0.;
1496 if ( uclosed && isDeg != 1 ) {
1497 Standard_Real dx = Abs ( p2d2.X() - p2d1.X() );
1498 if ( dx > URange - UTol )
1499 du = ShapeAnalysis::AdjustByPeriod ( p2d2.X(), p2d1.X(), URange );
1500 else if ( dx > UTol && stop == nb ) stop = n2; //:abv 29.08.01: torCuts2.stp
1501 }
1502 if ( vclosed && isDeg != 2 ) {
1503 Standard_Real dy = Abs ( p2d2.Y() - p2d1.Y() );
1504 if ( dy > VRange - VTol )
1505 dv = ShapeAnalysis::AdjustByPeriod ( p2d2.Y(), p2d1.Y(), VRange );
1506 else if ( dy > VTol && stop == nb ) stop = n2;
1507 }
1508 if ( du ==0. && dv == 0. ) continue;
1509
1510 myLastFixStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE1 );
1511 gp_Trsf2d Shift;
1512 Shift.SetTranslation ( gp_Vec2d ( du, dv ) );
1513 //c2d2->Transform ( Shift );
1514 // skl 15.05.2002 for OCC208 (if few edges have reference to one pcurve)
1515 Handle(Geom2d_Curve) c2d2new = Handle(Geom2d_Curve)::DownCast(c2d2->Transformed(Shift));
1516 sbe.ReplacePCurve(E2,c2d2new,Face());
1517 UpdateEdgeUVPoints ( E2, Face() );
1518 }
1519 if ( box.IsVoid() ) return Standard_False; //#3 smh 01.04.99. S4163: Overflow, when box is void.
1520
1521 Standard_Real umin, vmin, umax, vmax;
1522 box.Get ( umin, vmin, umax, vmax );
1523 if ( Abs ( umin + umax - SUF - SUL ) < URange &&
1524 Abs ( vmin + vmax - SVF - SVL ) < VRange &&
1525 ! LastFixStatus ( ShapeExtend_DONE ) ) return Standard_False;
1526
1527 box.SetVoid();
1528 Standard_Integer n; // svv Jan11 2000 : porting on DEC
1529 for ( n=1; n <= nb; n++ ) {
1530 Standard_Real a, b;
1531 Handle(Geom2d_Curve) c2d;
1532 if ( ! sae.PCurve ( sbwd->Edge(n), Face(), c2d, a, b, Standard_True ) ) continue;
1533 box.Add ( c2d->Value ( a ) );
1534 box.Add ( c2d->Value ( 0.5 * ( a + b ) ) );
1535 }
1536 box.Get ( umin, vmin, umax, vmax );
1537
1538 Standard_Real du=0., dv=0.;
1539
1540 if ( uclosed ) {
1541 Standard_Real umid = 0.5 * ( umin + umax );
1542// du = ShapeAnalysis::AdjustToPeriod(umid, SUF, SUL);
1543 // PTV 26.06.2002 xloop torus-apple iges face mode
1544 du = ShapeAnalysis::AdjustByPeriod(umid, SUMid, URange);
1545 }
1546 if ( vclosed ) {
1547 Standard_Real vmid = 0.5 * ( vmin + vmax );
1548// dv = ShapeAnalysis::AdjustToPeriod(vmid, SVF, SVL);
1549 // PTV 26.06.2002 xloop torus-apple iges face mode
1550 dv = ShapeAnalysis::AdjustByPeriod(vmid, SVMid, VRange);
1551 }
1552
1553 if ( du ==0. && dv == 0. ) return Standard_True;
1554
1555 myLastFixStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE2 );
1556
1557 gp_Trsf2d Shift;
1558 Shift.SetTranslation ( gp_Vec2d ( du, dv ) );
1559
1560 for ( n=1; n <= sbwdOring->NbEdges(); n++ ) {
1561 Standard_Real a, b;
1562 Handle(Geom2d_Curve) c2d;
1563 TopoDS_Edge ed = sbwdOring->Edge(n);
1564 if ( ! sae.PCurve ( ed, Face(), c2d, a, b, Standard_True ) ) continue;
1565 // skl 15.05.2002 for OCC208 (if few edges have reference to one pcurve)
1566 Handle(Geom2d_Curve) c2d2 = Handle(Geom2d_Curve)::DownCast(c2d->Transformed(Shift));
1567 sbe.ReplacePCurve(ed,c2d2,Face());
1568 UpdateEdgeUVPoints ( ed, Face() );
1569 }
1570 return Standard_True;
1571}
1572
1573//=======================================================================
1574//function : FixDegenerated
1575//purpose :
1576//=======================================================================
1577
1578Standard_Boolean ShapeFix_Wire::FixDegenerated (const Standard_Integer num)
1579{
1580 myLastFixStatus = ShapeExtend::EncodeStatus ( ShapeExtend_OK );
1581 if ( ! IsReady() ) return Standard_False;
1582
1583 // analysis
1584 gp_Pnt2d p2d1, p2d2;
1585 myAnalyzer->CheckDegenerated ( num, p2d1, p2d2 );
1586 if ( myAnalyzer->LastCheckStatus ( ShapeExtend_FAIL1 ) ) {
1587 myLastFixStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_FAIL1 );
1588 }
1589 //: abv 29.08.01: torHalf2.sat: if edge was encoded as degenerated but
1590 // has no pcurve and no singularity is found at that point, remove it
1591 if ( myAnalyzer->LastCheckStatus ( ShapeExtend_FAIL2 ) ) {
1592 WireData()->Remove ( num );
1593 myLastFixStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE3 );
1594 return Standard_True;
1595 }
1596 if ( ! myAnalyzer->LastCheckStatus ( ShapeExtend_DONE ) ) return Standard_False;
1597
1598 // action: create degenerated edge and insert it (or replace)
1599
1600 gp_Vec2d vect2d ( p2d1, p2d2 );
1601 gp_Dir2d dir2d ( vect2d );
1602 Handle(Geom2d_Line) line2d = new Geom2d_Line ( p2d1, dir2d );
1603
1604 TopoDS_Edge degEdge;
1605 BRep_Builder B;
1606 B.MakeEdge ( degEdge );
1607 B.Degenerated ( degEdge, Standard_True );
1608 B.UpdateEdge ( degEdge, line2d, Face(), ::Precision::Confusion() );
1609 B.Range ( degEdge, Face(), 0., vect2d.Magnitude() );
1610
1611 Handle(ShapeExtend_WireData) sbwd = WireData();
1612 Standard_Integer n2 = ( num >0 ? num : sbwd->NbEdges() );
1613 Standard_Integer n1 = ( n2 >1 ? n2-1 : sbwd->NbEdges() );
1614
1615 Standard_Boolean lack = myAnalyzer->LastCheckStatus ( ShapeExtend_DONE1 );
1616 Standard_Integer n3 = ( lack ? n2 : ( n2 < sbwd->NbEdges() ? n2+1 : 1 ) );
1617
1618 ShapeAnalysis_Edge sae;
1619 TopoDS_Vertex V1 = sae.LastVertex ( sbwd->Edge ( n1 ) );
1620 TopoDS_Vertex V2 = sae.FirstVertex ( sbwd->Edge ( n3 ) );
1621
1622 V1.Orientation(TopAbs_FORWARD);
1623 V2.Orientation(TopAbs_REVERSED);
1624 B.Add(degEdge,V1);
1625 B.Add(degEdge,V2);
1626 degEdge.Orientation(TopAbs_FORWARD);
1627
1628 if ( lack ) {
1629 sbwd->Add ( degEdge, n2 );
1630 myLastFixStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE1 );
1631 }
1632 else {
1633 sbwd->Set ( degEdge, n2 );
1634 myLastFixStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE2 );
1635 }
1636//: abv 28.08.01 - commented to avoid extra messages
1637// Message_Msg MSG ("FixWire.FixDegenerated.MSG5"); //Degenerated edge %d detected
1638// MSG.Arg (n2);
1639// SendWarning (MSG);
1640 return Standard_True;
1641}
1642
1643//=======================================================================
1644//function : FixSelfIntersectingEdge
1645//purpose : Tests edge for self-intersection and updates tolerance of vertex
1646// if intersection is found
1647// Returns True if tolerance was increased
1648//=======================================================================
1649
1650// Create edge on basis of E with new pcurve and call FixSP
1651// Return resulting tolerance and modified pcurve
1652static Standard_Boolean TryNewPCurve (const TopoDS_Edge &E, const TopoDS_Face &face,
1653 Handle(Geom2d_Curve) &c2d,
1654 Standard_Real &first,
1655 Standard_Real &last,
1656 Standard_Real &tol)
1657{
1658 Standard_Real f, l;
1659 Handle(Geom_Curve) crv = BRep_Tool::Curve ( E, f, l );
1660 if ( crv.IsNull() ) return Standard_False;
1661
1662 // make temp edge and compute tolerance
1663 BRepBuilderAPI_MakeEdge mkedge ( crv, f, l );
1664
1665 ShapeBuild_Edge SBE; //skl 17.07.2001
1666 SBE.SetRange3d(mkedge,f,l); //skl 17.07.2001
1667
1668 if ( ! mkedge.IsDone() ) return Standard_False;
1669
1670 TopoDS_Edge edge = mkedge;
1671 BRep_Builder B;
1672 B.UpdateEdge ( edge, c2d, face, 0. );
1673 B.Range ( edge, face, first, last );
1674 B.SameRange ( edge, Standard_False );
1675// no call to BRepLib: B.SameParameter ( edge, Standard_False );
1676
1677 Handle(ShapeFix_Edge) sfe = new ShapeFix_Edge;
1678 sfe->FixSameParameter ( edge );
1679 c2d = BRep_Tool::CurveOnSurface ( edge, face, first, last );
1680 tol = BRep_Tool::Tolerance ( edge );
1681 return Standard_True;
1682}
1683
1684//:k3 abv 24 Dec 98: BUC50070 #26682 and #30087:
1685// Try to cut out the loop on the pcurve and make new pcurve by concatenating
1686// the parts.
1687// If result is not SameParameter with prec, does nothing and returns False
1688// Warning: resulting pcurve will be C0
1689
1690//=======================================================================
1691//function : howMuchPCurves
1692//purpose : OCC901
1693//=======================================================================
1694static Standard_Integer howMuchPCurves (const TopoDS_Edge &E)
1695{
1696 Standard_Integer count = 0;
1697 BRep_ListIteratorOfListOfCurveRepresentation itcr
1698 ((*((Handle(BRep_TEdge)*)&E.TShape()))->ChangeCurves());
1699
1700 while (itcr.More()) {
1701 const Handle(BRep_CurveRepresentation)& cr = itcr.Value();
1702 if ( cr->IsCurveOnSurface() )
1703 count++;
1704 itcr.Next();
1705 }
1706
1707 return count;
1708}
1709
1710
1711//=======================================================================
1712//function : RemoveLoop
1713//purpose :
1714//=======================================================================
1715static Standard_Boolean RemoveLoop (TopoDS_Edge &E, const TopoDS_Face &face,
1716 const IntRes2d_IntersectionPoint &IP,
1717 const Standard_Real tolfact,
1718 const Standard_Real prec,
1719 const Standard_Boolean RemoveLoop3d)
1720{
1721 Standard_Boolean loopRemoved3d;
1722 if ( BRep_Tool::IsClosed ( E, face ) ) return Standard_False;
1723
1724 Standard_Real f, l;
1725 Handle(Geom_Curve) crv = BRep_Tool::Curve ( E, f, l );
1726
1727 Standard_Real t1 = IP.ParamOnFirst();
1728 Standard_Real t2 = IP.ParamOnSecond();
1729 if ( t1 > t2 ) { Standard_Real t = t1; t1 = t2; t2 = t; }
1730
1731 ShapeAnalysis_Edge sae;
1732 Standard_Real a, b;
1733 Handle(Geom2d_Curve) c2d;
1734 if ( ! sae.PCurve ( E, face, c2d, a, b, Standard_False ) )
1735 return Standard_False;
1736
1737#ifdef DEB
1738 cout << "Cut Loop: params (" << t1 << ", " << t2;
1739#endif
1740 GeomAdaptor_Curve GAC ( crv, f, l );
1741 Standard_Real dt = tolfact * GAC.Resolution(prec);
1742 t1 -= dt; //1e-3;//::Precision::PConfusion();
1743 t2 += dt; //1e-3;//::Precision::PConfusion();
1744#ifdef DEB
1745 cout << ") -> (" << t1 << ", " << t2 << ")" << endl;
1746#endif
1747
1748 if ( t1 <= a || t2 >= b ) { // should not be so, but to be sure ..
1749 return Standard_False;
1750 }
1751
1752 // direct construction causes error on osf system.
1753 gp_Pnt p(0,0,0);
1754 gp_Dir d(0,0,1);
1755 gp_Ax3 ax(p, d);
1756 gp_Pln Pln (ax);
1757
1758 // PTV OCC884
1759 Handle(Geom_Plane) aPlaneSurf = Handle(Geom_Plane)::DownCast( BRep_Tool::Surface(face) );
1760 Handle(Geom_Curve) pcurve3d = crv;
1761 if ( !aPlaneSurf.IsNull() ) {
1762 Pln = aPlaneSurf->Pln();
1763 }
1764 else
1765 pcurve3d = GeomAPI::To3d ( c2d, Pln );
1766
1767 // first segment
1768 //Handle(Geom_Curve) pcurve3d = GeomAPI::To3d ( c2d, Pln );
1769 Handle(Geom_TrimmedCurve) trim = new Geom_TrimmedCurve (pcurve3d, a, t1);
1770 GeomConvert_CompCurveToBSplineCurve connect ( trim );
1771
1772 // null-length segment patch instead of loop
1773 TColgp_Array1OfPnt Poles(1,2);
1774 TColStd_Array1OfReal Knots(1,2);
1775 TColStd_Array1OfInteger Mults(1,2);
1776
1777 Poles.SetValue(1,trim->Value(t1));
1778 Knots.SetValue(1,t1);
1779 Mults.SetValue(1,2);
1780
1781 trim = new Geom_TrimmedCurve (pcurve3d, t2, b);
1782 Poles.SetValue(2,trim->Value(t2));
1783 Knots.SetValue(2,t2);
1784 Mults.SetValue(2,2);
1785
1786 Handle(Geom_BSplineCurve) patch = new Geom_BSplineCurve ( Poles, Knots, Mults, 1 );
1787 if ( ! connect.Add (patch, ::Precision::PConfusion(), Standard_True, Standard_False) )
1788 return Standard_False;
1789
1790 // last segment
1791 if ( ! connect.Add (trim, ::Precision::PConfusion(), Standard_True, Standard_False) )
1792 return Standard_False;
1793 // PTV OCC884
1794 // keep created 3d curve
1795 Handle(Geom_Curve) aNew3dCrv = connect.BSplineCurve();
1796
1797
1798 Handle(Geom2d_Curve) bs = GeomAPI::To2d ( aNew3dCrv, Pln );
1799 if ( bs.IsNull() ) return Standard_False;
1800
1801 // make temp edge and compute tolerance
1802 BRep_Builder B;
1803
1804 if(!RemoveLoop3d) { // old variant (not remove loop 3d)
1805 Standard_Real newtol=0;
1806 // OCC901
1807 Standard_Integer nbC2d = howMuchPCurves( E );
1808 if ( nbC2d <= 1 && !aPlaneSurf.IsNull() )
1809 B.UpdateEdge ( E, bs, face, 0 );
1810 else
1811 if ( ! TryNewPCurve ( E, face, bs, a, b, newtol ) ) return Standard_False;
1812
1813 Standard_Real tol = BRep_Tool::Tolerance ( E );
1814#ifdef DEB
1815 cout << "Cut Loop: tol orig " << tol << ", prec " << prec << ", new tol " << newtol << endl;
1816#endif
1817 if ( newtol > Max ( prec, tol ) ) return Standard_False;
1818 //:s2 bs = BRep_Tool::CurveOnSurface ( edge, face, a, b );
1819 if ( Abs ( a - f ) > ::Precision::PConfusion() || // smth strange, cancel
1820 Abs ( b - l ) > ::Precision::PConfusion() ) return Standard_False;
1821 // PTV OCC884
1822 if ( !aPlaneSurf.IsNull() ) {
1823 B.UpdateEdge ( E, aNew3dCrv, Max (newtol, tol) );
1824 // OCC901
1825 if ( ! TryNewPCurve ( E, face, bs, a, b, newtol ) ) return Standard_False;
1826 }
1827 B.UpdateEdge ( E, bs, face, newtol );
1828 B.UpdateVertex ( sae.FirstVertex ( E ), newtol );
1829 B.UpdateVertex ( sae.LastVertex ( E ), newtol );
1830 return Standard_True;
1831 }
1832
1833 //:q1
1834 TopLoc_Location L;
1835 Handle(Geom_Surface) S = BRep_Tool::Surface(face, L);
1836 Handle(Geom2dAdaptor_HCurve) AC = new Geom2dAdaptor_HCurve(c2d);
1837 Handle(GeomAdaptor_HSurface) AS = new GeomAdaptor_HSurface(S);
1838
1839 Adaptor3d_CurveOnSurface ACS(AC,AS);
1840 gp_Pnt P1(ACS.Value(t1));
1841 gp_Pnt P2(ACS.Value(t2));
1842 gp_Pnt pcurPnt((P1.X()+P2.X())/2,(P1.Y()+P2.Y())/2,(P1.Z()+P2.Z())/2);
1843
1844 ShapeAnalysis_TransferParametersProj SFTP(E,face);
1845 Handle(TColStd_HSequenceOfReal) Seq2d = new TColStd_HSequenceOfReal;
1846 Seq2d->Append(t1);
1847 Seq2d->Append(t2);
1848 Seq2d->Append((t1+t2)/2);
1849 Handle(TColStd_HSequenceOfReal) Seq3d = new TColStd_HSequenceOfReal;
1850 Seq3d->Append(SFTP.Perform(Seq2d,Standard_False));
1851
1852 Standard_Real dist1 = pcurPnt.Distance(crv->Value(Seq3d->Value(1)));// correting Seq3d already project
1853 Standard_Real dist2 = pcurPnt.Distance(crv->Value(Seq3d->Value(2)));
1854 Standard_Real dist3 = pcurPnt.Distance(crv->Value(Seq3d->Value(3)));
1855 Standard_Real ftrim,ltrim;
1856 if(dist3>Max(dist1,dist2)) {
1857 loopRemoved3d = Standard_False;
1858 }
1859 else {
1860 loopRemoved3d = Standard_True;
1861 }
1862
1863 Handle(Geom_Curve) bs1;
1864
1865 if (!loopRemoved3d) {
1866 // create new 3d curve
1867 ftrim = Seq3d->Value(1);
1868 ltrim = Seq3d->Value(2);
1869 ftrim-=dt;
1870 ltrim+=dt;
1871 Handle(Geom_TrimmedCurve) trim1 = new Geom_TrimmedCurve (crv, f, ftrim);
1872 GeomConvert_CompCurveToBSplineCurve connect1 ( trim1 );
1873 TColgp_Array1OfPnt Poles1(1,2);
1874 TColStd_Array1OfReal Knots1(1,2);
1875 TColStd_Array1OfInteger Mults1(1,2);
1876
1877 Poles1.SetValue(1,trim1->Value(ftrim));
1878 Knots1.SetValue(1,ftrim);
1879 Mults1.SetValue(1,2);
1880
1881 trim1 = new Geom_TrimmedCurve (crv, ltrim, l);
1882 Poles1.SetValue(2,trim1->Value(ltrim));
1883 Knots1.SetValue(2,ltrim);
1884 Mults1.SetValue(2,2);
1885
1886 // create b-spline curve
1887 Handle(Geom_BSplineCurve) patch1 = new Geom_BSplineCurve ( Poles1, Knots1, Mults1, 1 );
1888
1889 if ( ! connect1.Add (patch1, ::Precision::PConfusion(), Standard_True, Standard_False) )
1890 return Standard_False;
1891
1892 // last segment
1893 if ( ! connect1.Add (trim1, ::Precision::PConfusion(), Standard_True, Standard_False) )
1894 return Standard_False;
1895
1896 bs1 = connect1.BSplineCurve();
1897
1898 if ( bs1.IsNull() )
1899 return Standard_False;
1900 }
1901// Standard_Real oldtol = BRep_Tool::Tolerance ( E );
1902
1903 if (!loopRemoved3d)
1904 B.UpdateEdge ( E, bs1, L, 0. );
1905 B.UpdateEdge ( E, bs, face, 0. );
1906 B.Range ( E, face, f, l );
1907 B.SameRange ( E, Standard_False );
1908
1909 Handle(ShapeFix_Edge) sfe = new ShapeFix_Edge;
1910 sfe->FixSameParameter ( E );
1911
1912 return Standard_True;
1913}
1914
1915//=======================================================================
1916//function : RemoveLoop
1917//purpose :
1918//=======================================================================
1919static Standard_Boolean RemoveLoop (TopoDS_Edge &E, const TopoDS_Face &face,
1920 const IntRes2d_IntersectionPoint &IP2d,
1921 TopoDS_Edge &E1,
1922 TopoDS_Edge &E2)
1923{
1924#ifdef DEB
1925 cout<<"Info: ShapeFix_Wire::FixSelfIntersection : Try insert vertex"<<endl;
1926#endif
1927
1928 if ( BRep_Tool::IsClosed ( E, face ) ) return Standard_False;
1929
1930 Standard_Real f, l;
1931 Handle(Geom_Curve) crv = BRep_Tool::Curve ( E, f, l );
1932
1933 Standard_Real t1 = IP2d.ParamOnFirst();
1934 Standard_Real t2 = IP2d.ParamOnSecond();
1935
1936 if ( t1 > t2 )
1937 {
1938 Standard_Real t = t1; t1 = t2; t2 = t;
1939 }
1940
1941 ShapeAnalysis_Edge sae;
1942
1943 // define vertexes Vfirst , Vlast, Vmid
1944 TopoDS_Vertex Vfirst,Vlast,Vmid;
1945 // initialize Vfirst and Vlast
1946 Vfirst = sae.FirstVertex(E);
1947 Vlast = sae.LastVertex(E);
1948
1949 // find a 2d curve and parameters from edge E
1950 Standard_Real a, b;
1951 Handle (Geom2d_Curve) c2d;
1952 if ( ! sae.PCurve ( E, face, c2d, a, b, Standard_False ) )
1953 return Standard_False;
1954
1955 // first segment for 2d curve
1956 Handle(Geom2d_TrimmedCurve) trim1;
1957 if( (t1-a)>Precision::PConfusion() )
1958 trim1 = new Geom2d_TrimmedCurve (c2d, a, t1);
1959 // second segment for 2d curve
1960 Handle(Geom2d_TrimmedCurve) trim2 = new Geom2d_TrimmedCurve (c2d, t2, b);
1961
1962// if ( trim1.IsNull() || trim2.IsNull() )
1963 if(trim2.IsNull())
1964 return Standard_False;
1965
1966 TopLoc_Location L;
1967 Handle (Geom_Surface) S = BRep_Tool::Surface(face, L);
1968 Handle (Geom2dAdaptor_HCurve) AC = new Geom2dAdaptor_HCurve(c2d);
1969 Handle (GeomAdaptor_HSurface) AS = new GeomAdaptor_HSurface(S);
1970
1971 Adaptor3d_CurveOnSurface ACS(AC,AS);
1972 gp_Pnt P1(ACS.Value(t1));
1973 gp_Pnt P2(ACS.Value(t2));
1974 gp_Pnt pcurPnt((P1.X()+P2.X())/2,(P1.Y()+P2.Y())/2,(P1.Z()+P2.Z())/2);
1975
1976 // transfer parameters from pcurve to 3d curve
1977 ShapeAnalysis_TransferParametersProj SFTP(E,face);
1978 Handle (TColStd_HSequenceOfReal) Seq2d = new TColStd_HSequenceOfReal;
1979 Seq2d->Append(t1);
1980 Seq2d->Append(t2);
1981 Seq2d->Append((t1+t2)/2);
1982 Handle (TColStd_HSequenceOfReal) Seq3d = new TColStd_HSequenceOfReal;
1983 Seq3d->Append(SFTP.Perform(Seq2d,Standard_False));
1984
1985 Standard_Real dist1 = pcurPnt.Distance(crv->Value(Seq3d->Value(1)));// correting Seq3d already project
1986 Standard_Real dist2 = pcurPnt.Distance(crv->Value(Seq3d->Value(2)));
1987 Standard_Real dist3 = pcurPnt.Distance(crv->Value(Seq3d->Value(3)));
1988 Standard_Real ftrim,ltrim;
1989 if ( dist3 > Max(dist1, dist2)) { // is loop in 3d
1990 ftrim = Seq3d->Value(1);
1991 ltrim = Seq3d->Value(2);
1992 }
1993 else { // not loop in 3d
1994 ftrim = Seq3d->Value(3);
1995 ltrim = Seq3d->Value(3);
1996 }
1997
1998// ftrim = Seq3d->Value(1);
1999// ltrim = Seq3d->Value(2);
2000
2001 // trim for 3d curve 'crv' with parameters from 'f' to 'l'
2002 Handle(Geom_TrimmedCurve) trim3;
2003 if(!trim1.IsNull())
2004 trim3 = new Geom_TrimmedCurve (crv, f, ftrim);
2005 // second segment for 3d curve
2006 Handle(Geom_TrimmedCurve) trim4 = new Geom_TrimmedCurve (crv, ltrim, l);
2007
2008// if ( trim3.IsNull() || trim4.IsNull() )
2009 if(trim4.IsNull())
2010 return Standard_False;
2011
2012 // create a point for middle vertex
2013 gp_Pnt pnt1 = crv->Value(ftrim);
2014 gp_Pnt pnt2 = crv->Value(ltrim);
2015 gp_Pnt Pmid((pnt1.X()+pnt2.X())/2,(pnt1.Y()+pnt2.Y())/2,(pnt1.Z()+pnt2.Z())/2);
2016
2017 BRep_Builder B;
2018
2019 // create new copies for E1 and E2
2020 if(!trim1.IsNull())
2021 E1=TopoDS::Edge(E.EmptyCopied());
2022 E2=TopoDS::Edge(E.EmptyCopied());
2023
2024 // initialize middle vertex Vmid
2025 if(trim1.IsNull())
2026 B.MakeVertex(Vmid, pnt2, 0.);
2027 else
2028 B.MakeVertex(Vmid, Pmid, 0.);
2029
2030 ShapeBuild_Edge sbe;
2031
2032 // replace verteces for new edges E1 and E2
2033 if (E.Orientation()== TopAbs_FORWARD)
2034 {
2035 if(!E1.IsNull())
2036 E1=sbe.CopyReplaceVertices(E1,Vfirst,Vmid);
2037 E2=sbe.CopyReplaceVertices(E2,Vmid, Vlast);
2038 }
2039 else
2040 {
2041 if(!E1.IsNull())
2042 E1=sbe.CopyReplaceVertices(E1,Vmid, Vlast);
2043 E2=sbe.CopyReplaceVertices(E2,Vfirst, Vmid);
2044 }
2045
2046 // Update edges by 2d and 3d curves
2047 Handle(ShapeFix_Edge) mySfe = new ShapeFix_Edge;
2048 if(!E1.IsNull()) {
2049 B.UpdateEdge(E1, trim1, face, 0.);
2050 B.UpdateEdge(E1, trim3, 0.);
2051 B.Range(E1, f, ftrim);
2052 B.SameRange(E1,Standard_False);
2053// B.SameParameter(E1,Standard_False);
2054 mySfe->FixSameParameter(E1);
2055 mySfe->FixVertexTolerance(E1);
2056 }
2057 B.UpdateEdge(E2, trim2, face, 0.);
2058 B.UpdateEdge(E2, trim4, 0.);
2059 B.Range ( E2,ltrim,l );
2060 B.SameRange(E2, Standard_False );
2061// B.SameParameter(E2, Standard_False);
2062 mySfe->FixSameParameter(E2);
2063 mySfe->FixVertexTolerance(E2);
2064
2065 return Standard_True;
2066}
2067
2068
2069//=======================================================================
2070//function : FixSelfIntersectingEdge
2071//purpose :
2072//=======================================================================
2073
2074Standard_Boolean ShapeFix_Wire::FixSelfIntersectingEdge (const Standard_Integer num)
2075{
2076 myLastFixStatus = ShapeExtend::EncodeStatus ( ShapeExtend_OK );
2077 if ( ! IsReady() ) return Standard_False;
2078
2079 // analysis
2080 IntRes2d_SequenceOfIntersectionPoint points2d;
2081 TColgp_SequenceOfPnt points3d;
2082 Handle(ShapeAnalysis_Wire) theAdvAnalyzer = Handle(ShapeAnalysis_Wire)::DownCast(myAnalyzer);
2083 if (theAdvAnalyzer.IsNull()) return Standard_False;
2084 theAdvAnalyzer->CheckSelfIntersectingEdge ( num, points2d, points3d );
2085 if ( theAdvAnalyzer->LastCheckStatus ( ShapeExtend_FAIL ) ) {
2086 myLastFixStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_FAIL1 );
2087 }
2088 if ( ! theAdvAnalyzer->LastCheckStatus ( ShapeExtend_DONE ) ) return Standard_False;
2089
2090 // action: increase tolerance of vertex
2091
2092 TopoDS_Edge E = WireData()->Edge ( num >0 ? num : NbEdges() );
2093
2094 ShapeAnalysis_Edge sae;
2095 TopoDS_Vertex V1 = sae.FirstVertex ( E );
2096 TopoDS_Vertex V2 = sae.LastVertex ( E );
2097 Standard_Real tol1 = BRep_Tool::Tolerance ( V1 );
2098 Standard_Real tol2 = BRep_Tool::Tolerance ( V2 );
2099 gp_Pnt pnt1 = BRep_Tool::Pnt ( V1 );
2100 gp_Pnt pnt2 = BRep_Tool::Pnt ( V2 );
2101
2102 // cycle is to verify fix in case of RemoveLoop
2103 Standard_Real tolfact = 0.1; // factor for shifting by parameter in RemoveLoop
2104 Standard_Real f2d, l2d;
2105 Handle(Geom2d_Curve) c2d;
2106 Standard_Real newtol=0.; // = Precision();
2107
2108 if (myRemoveLoopMode<1) {
2109 for ( Standard_Integer iter=0; iter < 30; iter++ ) {
2110 Standard_Boolean loopRemoved = Standard_False;;
2111 Standard_Real prevFirst = 0 , prevLast = 0;
2112 for ( Standard_Integer i=1; i<=points2d.Length(); i++ ) {
2113 gp_Pnt pint = points3d.Value(i);
2114 Standard_Real dist21 = pnt1.SquareDistance ( pint );
2115 Standard_Real dist22 = pnt2.SquareDistance ( pint );
2116 if ( dist21 < tol1 * tol1 || dist22 < tol2 * tol2 ) continue;
2117 newtol = 1.001 * Sqrt ( Min ( dist21, dist22 ) ); //:f8
2118
2119 //:k3 abv 24 Dec 98: BUC50070 #26682 and #30087: try to remove loop
2120 if ( myGeomMode ) {
2121 if ( c2d.IsNull() )
2122 sae.PCurve ( E, Face(), c2d, f2d, l2d, Standard_False );
2123 Standard_Real firstpar = points2d.Value(i).ParamOnFirst();
2124 Standard_Real lastpar = points2d.Value(i).ParamOnSecond();
2125 if(firstpar > prevFirst && lastpar < prevLast) continue;
2126 if ( RemoveLoop (E, Face(), points2d.Value(i), tolfact,
2127 Min( MaxTolerance(), Max(newtol,Precision()) ),
2128 myRemoveLoopMode==0 ) ) {
2129 myLastFixStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE4 );
2130 loopRemoved = Standard_True;
2131 prevFirst = firstpar;
2132 prevLast = lastpar;
2133 continue; // repeat of fix on that edge required (to be done by caller)
2134 }
2135 }
2136 if ( newtol < MaxTolerance() ) {
2137 myLastFixStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE1 );
2138 BRep_Builder B;
2139 if ( dist21 < dist22 ) B.UpdateVertex ( V1, tol1 = newtol );
2140 else B.UpdateVertex ( V2, tol2 = newtol );
2141 }
2142 else myLastFixStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_FAIL2 );
2143 }
2144
2145 // after RemoveLoop, check that self-intersection disappeared
2146 if ( loopRemoved ) {
2147 IntRes2d_SequenceOfIntersectionPoint pnts2d;
2148 TColgp_SequenceOfPnt pnts3d;
2149 theAdvAnalyzer->CheckSelfIntersectingEdge ( num, pnts2d, pnts3d );
2150 if ( ! theAdvAnalyzer->LastCheckStatus ( ShapeExtend_DONE ) ) break;
2151 //points3d.Append(pnts3d);
2152 //points2d.Append(pnts2d);
2153 points3d = pnts3d;
2154 points2d = pnts2d;
2155 BRep_Builder B;
2156 B.UpdateEdge ( E, c2d, Face(), 0. );
2157 B.Range ( E, Face(), f2d, l2d );
2158 //newtol+=Precision();
2159 }
2160 else {
2161 break;
2162 }
2163 }
2164 }
2165
2166 //===============================================
2167 // RemoveLoopMode = 1 , insert vertex
2168 //===============================================
2169 if (myRemoveLoopMode == 1) {
2170 // after fixing will be nb+1 edges
2171 Standard_Boolean loopRemoved;
2172 // create a sequence of resulting edges
2173 Handle (TopTools_HSequenceOfShape) TTSS = new TopTools_HSequenceOfShape;
2174 TopoDS_Edge E2;
2175
2176 loopRemoved = Standard_False;
2177 //:k3 abv 24 Dec 98: BUC50070 #26682 and #30087: try to remove loop
2178 if ( myGeomMode ) {
2179 if ( c2d.IsNull() )
2180 sae.PCurve ( E, Face(), c2d, f2d, l2d, Standard_False );
2181 TopoDS_Edge E1;
2182 if ( RemoveLoop (E, Face(), points2d.Value(1),E1,E2) ) {
2183 myLastFixStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE4 );
2184 loopRemoved = Standard_True;
2185 if(!E1.IsNull()) {
2186 TTSS->Append(E1);
2187 newtol = Max(BRep_Tool::Tolerance(E1),BRep_Tool::Tolerance(E2));
2188 }
2189 else
2190 newtol = BRep_Tool::Tolerance(E2);
2191 }
2192 }
2193
2194 TTSS->Append(E2);
2195
2196 if ( newtol > MaxTolerance() )
2197 myLastFixStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_FAIL2 );
2198
2199 ShapeExtend_WireData sewd;
2200 for (Standard_Integer i=1 ; i <= TTSS->Length(); i++) {
2201 sewd.Add(TopoDS::Edge(TTSS->Value(i)));
2202 }
2203 if (! Context().IsNull()) {
2204 Context()->Replace ( E, sewd.Wire() );
2205 UpdateWire();
2206 }
2207 else {
2208 WireData()->Remove(num >0 ? num : NbEdges());
2209 WireData()->Add(sewd.Wire(), num >0 ? num : NbEdges());
2210 }
2211 if (loopRemoved)
2212 myLastFixStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE8 );
2213
2214 }
2215
2216 if ( LastFixStatus ( ShapeExtend_DONE ) && ! myShape.IsNull() ) {
2217 Message_Msg MSG ("FixAdvWire.FixIntersection.MSG5"); //Edge %d was self-intersecting, corrected
2218 MSG.Arg (num);
2219 SendWarning (MSG);
2220 }
2221
2222 return LastFixStatus ( ShapeExtend_DONE );
2223}
2224
2225
2226//=======================================================================
2227//function : ComputeLocalDeviation
2228//purpose : auxilary
2229//=======================================================================
2230static Standard_Real ComputeLocalDeviation (const TopoDS_Edge &edge,
2231 const gp_Pnt &pint,const gp_Pnt &pnt,
2232 Standard_Real f, Standard_Real l,
2233 const TopoDS_Face &face )
2234{
2235 ShapeAnalysis_Edge sae;
2236 Handle(Geom_Curve) c3d;
2237 Standard_Real a, b;
2238 if ( ! sae.Curve3d ( edge, c3d, a, b, Standard_False ) ) return RealLast();
2239
2240 gp_Lin line ( pint, gp_Vec ( pint, pnt ) );
2241
2242 Handle(Geom2d_Curve) Crv;
2243 Standard_Real fp,lp;
2244 if ( sae.PCurve(edge,face,Crv,fp,lp,Standard_False) ) {
2245 if(Crv->IsKind(STANDARD_TYPE(Geom2d_TrimmedCurve))) {
2246 Handle(Geom2d_TrimmedCurve) tc = Handle(Geom2d_TrimmedCurve)::DownCast(Crv);
2247 if(tc->BasisCurve()->IsKind(STANDARD_TYPE(Geom2d_Line))) {
2248 f = a + (f-fp)*(b-a)/(lp-fp);
2249 l = a + (l-fp)*(b-a)/(lp-fp);
2250 }
2251 }
2252 }
2253
2254 const Standard_Integer NSEG = 10;
2255 Standard_Real step = ( l - f ) / NSEG;
2256 Standard_Real dev = 0.;
2257 for ( Standard_Integer i=1; i < NSEG; i++ ) {
2258 gp_Pnt p = c3d->Value ( f + i * step );
2259 Standard_Real d = line.Distance ( p );
2260 if ( dev < d ) dev = d;
2261 }
2262 return dev;
2263}
2264
2265//=======================================================================
2266//function : FixIntersectingEdges
2267//purpose :
2268//=======================================================================
2269
2270Standard_Boolean ShapeFix_Wire::FixIntersectingEdges (const Standard_Integer num)
2271{
2272 myLastFixStatus = ShapeExtend::EncodeStatus ( ShapeExtend_OK );
2273 if ( ! IsReady() || NbEdges() <2 ) return Standard_False;
2274
2275 // analysis
2276 IntRes2d_SequenceOfIntersectionPoint points2d;
2277 TColgp_SequenceOfPnt points3d;
2278 TColStd_SequenceOfReal errors;
2279 Handle(ShapeAnalysis_Wire) theAdvAnalyzer = Handle(ShapeAnalysis_Wire)::DownCast(myAnalyzer);
2280 if (theAdvAnalyzer.IsNull()) return Standard_False;
2281 theAdvAnalyzer->CheckIntersectingEdges ( num, points2d, points3d, errors );
2282 if ( theAdvAnalyzer->LastCheckStatus ( ShapeExtend_FAIL ) ) {
2283 myLastFixStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_FAIL1 );
2284 }
2285 if ( ! theAdvAnalyzer->LastCheckStatus ( ShapeExtend_DONE ) ) return Standard_False;
2286
2287 //rln 03/02/98: CSR#BUC50004 entity 56 (to avoid later inserting lacking edge)
2288 //:l0 Standard_Boolean isLacking = myAnalyzer->CheckLacking ( num );
2289
2290 // action: increase tolerance of vertex
2291
2292 Handle(ShapeExtend_WireData) sbwd = WireData();
2293 Standard_Integer n2 = ( num >0 ? num : sbwd->NbEdges() );
2294 Standard_Integer n1 = ( n2 >1 ? n2-1 : sbwd->NbEdges() );
2295 TopoDS_Edge E1 = sbwd->Edge(n1);
2296 TopoDS_Edge E2 = sbwd->Edge(n2);
2297 Standard_Boolean isForward1 = ( E1.Orientation() == TopAbs_FORWARD );
2298 Standard_Boolean isForward2 = ( E2.Orientation() == TopAbs_FORWARD );
2299 Standard_Real a1, b1, a2, b2;
2300 BRep_Tool::Range ( E1, Face(), a1, b1 );
2301 BRep_Tool::Range ( E2, Face(), a2, b2 );
2302
2303 ShapeAnalysis_Edge sae;
2304 TopoDS_Vertex Vp = sae.FirstVertex ( E1 );
2305 TopoDS_Vertex V1 = sae.LastVertex ( E1 );
2306 TopoDS_Vertex V2 = sae.FirstVertex ( E2 );
2307 TopoDS_Vertex Vn = sae.LastVertex ( E2 );
2308
2309 Standard_Real tol = BRep_Tool::Tolerance ( V1 );
2310 gp_Pnt pnt = BRep_Tool::Pnt ( V1 );
2311
2312 Standard_Real prevRange1 = RealLast(), prevRange2 = RealLast();
2313 Standard_Boolean cutEdge1 = Standard_False, cutEdge2 = Standard_False;
2314 Standard_Boolean IsCutLine = Standard_False;
2315
2316 BRep_Builder B;
2317
2318 Standard_Integer nb = points3d.Length();
2319 for ( Standard_Integer i=1; i <= nb; i++ ) {
2320 const IntRes2d_IntersectionPoint &IP = points2d.Value(i);
2321 Standard_Real param1 = ( num ==1 ? IP.ParamOnSecond() : IP.ParamOnFirst() );
2322 Standard_Real param2 = ( num ==1 ? IP.ParamOnFirst() : IP.ParamOnSecond() );
2323
2324 Standard_Real newRange1 = Abs ( ( isForward1 ? a1 : b1 ) - param1 );
2325 Standard_Real newRange2 = Abs ( ( isForward2 ? b2 : a2 ) - param2 );
2326 if ( newRange1 > prevRange1 && newRange2 > prevRange2 ) continue;
2327
2328 gp_Pnt pint = points3d.Value(i);
2329 Standard_Real rad = errors.Value(i);
2330 Standard_Real newtol = 1.0001 * ( pnt.Distance ( pint ) + rad );
2331
2332// GeomAdaptor_Surface& Ads = myAnalyzer->Surface()->Adaptor3d()->ChangeSurface();
2333
2334 //:r8 abv 12 Apr 99: try increasing tolerance of edge
2335 if ( ! myTopoMode && newtol > tol ) {
2336 Standard_Real te1 = rad + ComputeLocalDeviation (E1, pint, pnt,
2337 param1, ( isForward1 ? b1 : a1 ), Face() );
2338 Standard_Real te2 = rad + ComputeLocalDeviation (E2, pint, pnt,
2339 ( isForward2 ? a2 : b2 ), param2, Face() );
2340 Standard_Real maxte = Max ( te1, te2 );
2341 if ( maxte < MaxTolerance() && maxte < newtol ) {
2342 if ( BRep_Tool::Tolerance(E1) < te1 || BRep_Tool::Tolerance(E2) < te2 ) {
2343//#ifdef DEB
2344// cout << "Warning: ShapeFix_Wire::FixIE: edges tolerance increased: (" <<
2345// te1 << ", " << te2 << ") / " << newtol << endl;
2346//#endif
2347 B.UpdateEdge ( E1, 1.000001 * te1 );
2348 B.UpdateVertex ( sae.FirstVertex ( E1 ), 1.000001 * te1 );
2349 B.UpdateVertex ( sae.LastVertex ( E1 ), 1.000001 * te1 );
2350 B.UpdateEdge ( E2, 1.000001 * te2 );
2351 B.UpdateVertex ( sae.FirstVertex ( E2 ), 1.000001 * te2 );
2352 B.UpdateVertex ( sae.LastVertex ( E2 ), 1.000001 * te2 );
2353 myLastFixStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE6 );
2354 }
2355 newtol = 1.000001 * maxte;
2356 }
2357 }
2358
2359 if ( myTopoMode || newtol <= MaxTolerance() ) {
2360 prevRange1 = newRange1;
2361 prevRange2 = newRange2;
2362 Standard_Boolean locMayEdit = myTopoMode;
2363 if ( myTopoMode ) { //:j6 abv 7 Dec 98: ProSTEP TR10 r0601_id.stp #57676 & #58586: do not cut edges because of influence on adjacent faces
2364 ShapeFix_SplitTool aTool;
2365 //if ( ! ShapeFix::CutEdge ( E1, ( isForward1 ? a1 : b1 ), param1, Face(), IsCutLine ) ) {
2366 if ( ! aTool.CutEdge ( E1, ( isForward1 ? a1 : b1 ), param1, Face(), IsCutLine ) ) {
2367 if ( V1.IsSame ( Vp ) )
2368 myLastFixStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE3 );
2369 else locMayEdit = Standard_False;
2370 }
2371 else cutEdge1 = Standard_True; //:h4
2372 //if ( ! ShapeFix::CutEdge ( E2, ( isForward2 ? b2 : a2 ), param2, Face(), IsCutLine ) ) {
2373 if ( ! aTool.CutEdge ( E2, ( isForward2 ? b2 : a2 ), param2, Face(), IsCutLine ) ) {
2374 if ( V2.IsSame ( Vn ) )
2375 myLastFixStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE4 );
2376 else locMayEdit = Standard_False;
2377 }
2378 else cutEdge2 = Standard_True; //:h4
2379 }
2380 if ( locMayEdit &&
2381 newRange1 <= prevRange1 && newRange2 <= prevRange2 && //rln 09/01/98
2382 BRep_Tool::SameParameter ( E1 ) &&
2383 BRep_Tool::SameParameter ( E2 ) ) {
2384 myLastFixStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE2 );
2385 pnt = pint;
2386 if ( tol <= rad ) {
2387 myLastFixStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE1 );
2388 tol = 1.001 * rad;
2389 }
2390 }
2391 else if(IsCutLine) {
2392 myLastFixStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE2 );
2393 pnt = pint;
2394 if ( tol <= rad ) {
2395 myLastFixStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE1 );
2396 tol = 1.001 * rad;
2397 }
2398 }
2399 else { // else increase tolerance
2400 if (tol < newtol) { //rln 07.04.99 CCI60005-brep.igs
2401 myLastFixStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE1 );
2402 tol = newtol;
2403 }
2404 }
2405 }
2406 else myLastFixStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_FAIL2 );
2407 }
2408
2409 if ( ! LastFixStatus ( ShapeExtend_DONE ) ) return Standard_False;
2410
2411 B.UpdateVertex ( V1, pnt, tol );
2412 B.UpdateVertex ( V2, pnt, tol );
2413
2414 //:h4: make edges SP (after all cuts: t4mug.stp #3730+#6460)
2415 if ( cutEdge1 ) myFixEdge->FixSameParameter ( E1 );
2416 if ( cutEdge2 && !IsCutLine ) myFixEdge->FixSameParameter ( E2 );
2417 if ( cutEdge1 || cutEdge2 ) {
2418 myLastFixStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE7 );
2419 }
2420 if ( ! myShape.IsNull() ) {
2421 Message_Msg MSG ("FixAdvWire.FixIntersection.MSG10"); //Edges %d and %d were intersecting, corrected
2422 MSG.Arg (n1);
2423 MSG.Arg (n2);
2424 SendWarning (MSG);
2425 }
2426 return Standard_True;
2427}
2428
2429//=======================================================================
2430//function : FixIntersectingEdges
2431//purpose :
2432//=======================================================================
2433//pdn 17.03.99 fixing non ajacent intersection by increasing tolerance of vertex
2434
2435Standard_Boolean ShapeFix_Wire::FixIntersectingEdges (const Standard_Integer num1,
2436 const Standard_Integer num2)
2437{
2438 myLastFixStatus = ShapeExtend::EncodeStatus ( ShapeExtend_OK );
2439 if ( !IsReady() ) return Standard_False;
2440 IntRes2d_SequenceOfIntersectionPoint points2d;
2441 TColgp_SequenceOfPnt points3d;
2442 TColStd_SequenceOfReal errors;
2443 Handle(ShapeAnalysis_Wire) theAdvAnalyzer = Handle(ShapeAnalysis_Wire)::DownCast(myAnalyzer);
2444 if (theAdvAnalyzer.IsNull()) return Standard_False;
2445 theAdvAnalyzer->CheckIntersectingEdges ( num1, num2, points2d, points3d, errors);
2446 if ( theAdvAnalyzer->LastCheckStatus ( ShapeExtend_FAIL ) ) {
2447 myLastFixStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_FAIL1 );
2448 }
2449 if ( ! theAdvAnalyzer->LastCheckStatus ( ShapeExtend_DONE ) ) return Standard_False;
2450 TColgp_Array1OfPnt vertexPoints(1,4);
2451 TColStd_Array1OfReal vertexTolers(1,4);
2452 TColStd_Array1OfReal newTolers(1,4);
2453 TopTools_Array1OfShape vertices(1,4);
2454 newTolers.Init(0);
2455
2456 Handle(ShapeExtend_WireData) sbwd = WireData();
2457 Standard_Integer n2 = ( num1 >0 ? num1 : sbwd->NbEdges() );
2458 Standard_Integer n1 = ( num2 >1 ? num2 : sbwd->NbEdges() );
2459 if(n1==n2) return Standard_False;
2460
2461 TopoDS_Edge edge1 = sbwd->Edge(n1);
2462 TopoDS_Edge edge2 = sbwd->Edge(n2);
2463
2464 ShapeAnalysis_Edge sae;
2465 vertices(1) = sae.FirstVertex(edge1);
2466 vertices(2) = sae.LastVertex(edge1);
2467 vertices(3) = sae.FirstVertex(edge2);
2468 vertices(4) = sae.LastVertex(edge2);
2469
2470 Standard_Integer i; // svv Jan11 2000 : porting on DEC
2471 for (i = 1; i <=4; i++) {
2472 vertexPoints(i) = BRep_Tool::Pnt(TopoDS::Vertex(vertices(i)));
2473 vertexTolers(i) = BRep_Tool::Tolerance(TopoDS::Vertex(vertices(i)));
2474 }
2475
2476 Standard_Real aNewTolEdge1 = 0.0, aNewTolEdge2 = 0.0;
2477 Standard_Integer nb = points3d.Length();
2478 for ( i=1; i <= nb; i++ ) {
2479 gp_Pnt pint = points3d.Value(i);
2480
2481 // searching for the nearest vertexies to the intersection point
2482 Standard_Real aVtx1Param=0., aVtx2Param=0.;
2483 Standard_Integer aVC1, aVC2;
2484 Standard_Real aMinDist = RealLast();
2485 gp_Pnt aNearestVertex;
2486 Standard_Real aNecessaryVtxTole = 0.0;
2487 for(aVC1 = 1; aVC1 <= 2; aVC1++) {
2488 for(aVC2 = 3; aVC2 <= 4; aVC2++) {
2489
2490 Standard_Real aVtxIPDist = pint.Distance(vertexPoints(aVC1));
2491 Standard_Real aVtxVtxDist = vertexPoints(aVC1).Distance(vertexPoints(aVC2));
2492 if(aMinDist > aVtxIPDist && aVtxIPDist > aVtxVtxDist) {
2493 aNecessaryVtxTole = aVtxVtxDist;
2494 aNearestVertex = vertexPoints(aVC1);
2495 aMinDist = aVtxIPDist;
2496 aVtx1Param = BRep_Tool::Parameter(TopoDS::Vertex(vertices(aVC1)),edge1);
2497 aVtx2Param = BRep_Tool::Parameter(TopoDS::Vertex(vertices(aVC2)),edge2);
2498 }
2499 }
2500 }
2501
2502 // calculation of necessary tolerances of edges
2503 const IntRes2d_IntersectionPoint &IP = points2d.Value(i);
2504 Standard_Real param1 = IP.ParamOnFirst();
2505 Standard_Real param2 = IP.ParamOnSecond();
2506 Handle(Geom_Curve) aCurve1, aCurve2;
2507 Standard_Real f,l;
2508 TopLoc_Location L1, L2;
2509 aCurve1 = BRep_Tool::Curve(edge1, L1, f, l);
2510 aCurve2 = BRep_Tool::Curve(edge2, L2, f, l);
2511
2512 // if aMinDist lower than resolution than the intersection point lyes inside the vertex
2513 if(aMinDist < gp::Resolution())
2514 continue;
2515
2516 Standard_Real aMaxEdgeTol1 = 0.0, aMaxEdgeTol2 = 0.0;
2517 if(aMinDist < RealLast() && !aCurve1.IsNull() && !aCurve2.IsNull())
2518 {
2519 gp_Lin aLig(aNearestVertex, gp_Vec(aNearestVertex, pint));
2520 Standard_Integer aPointsC;
2521 Standard_Real du1 = 0.05*(param1 - aVtx1Param);
2522 Standard_Real du2 = 0.05*(param2 - aVtx2Param);
2523 Standard_Real tole1=BRep_Tool::Tolerance(edge1);
2524 Standard_Real tole2=BRep_Tool::Tolerance(edge2);
2525 for(aPointsC = 2; aPointsC < 19; aPointsC++)
2526 {
2527 Standard_Real u = aVtx1Param + aPointsC * du1;
2528 gp_Pnt P1 = aCurve1->Value(u);
2529 P1.Transform(L1.Transformation());
2530 Standard_Real d1 = aLig.Distance(P1) * 2.0000001;
2531 if(d1 > tole1 && d1 > aMaxEdgeTol1)
2532 aMaxEdgeTol1 = d1;
2533
2534 u = aVtx2Param + aPointsC * du2;
2535 gp_Pnt P2 = aCurve2->Value(u);
2536 P2.Transform(L2.Transformation());
2537 Standard_Real d2 = aLig.Distance(P2) * 2.0000001;
2538 if(d2 > tole2 && d2 > aMaxEdgeTol2)
2539 aMaxEdgeTol2 = d2;
2540 }
2541 if(aMaxEdgeTol1 == 0.0 && aMaxEdgeTol2 == 0.0) continue;
2542 // if the vertexies are far than tolerances so
2543 // we do not need to increase edge tolerance
2544 if(aNecessaryVtxTole > Max(aMaxEdgeTol1, tole1) ||
2545 aNecessaryVtxTole > Max(aMaxEdgeTol2, tole2))
2546 {
2547 aMaxEdgeTol1 = 0.0;
2548 aMaxEdgeTol2 = 0.0;
2549 }
2550 }
2551
2552 Standard_Real rad = errors.Value(i);
2553 Standard_Real finTol = RealLast();
2554 Standard_Integer rank=1;
2555 for(Standard_Integer j=1; j<=4; j++) {
2556 Standard_Real newtol = 1.0001 * ( pint.Distance (vertexPoints(j)) + rad );
2557 if(newtol<finTol) {
2558 rank = j;
2559 finTol = newtol;
2560 }
2561 }
2562 if(finTol <= MaxTolerance()) {
2563 myLastFixStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE1);
2564 if(newTolers(rank) < finTol)
2565 {
2566 if(Max(aMaxEdgeTol1, aMaxEdgeTol2) < finTol && (aMaxEdgeTol1 > 0 || aMaxEdgeTol2 > 0))
2567 {
2568 aNewTolEdge1 = Max(aNewTolEdge1, aMaxEdgeTol1);
2569 aNewTolEdge2 = Max(aNewTolEdge2, aMaxEdgeTol2);
2570 }
2571 else
2572 {
2573 newTolers(rank) = finTol;
2574 }
2575 }
2576 } else {
2577 myLastFixStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_FAIL2 );
2578 }
2579 }
2580
2581 BRep_Builder B;
2582 // update of tolerances of edges
2583 if(aNewTolEdge1 > 0)
2584 {
2585 for(i = 1; i <= 2; i++)
2586 if(aNewTolEdge1 > Max(vertexTolers(i), newTolers(i)))
2587 newTolers(i) = aNewTolEdge1;
2588 B.UpdateEdge(edge1, aNewTolEdge1);
2589 }
2590 if(aNewTolEdge2 > 0)
2591 {
2592 for(i = 3; i <= 4; i++)
2593 if(aNewTolEdge2 > Max(vertexTolers(i), newTolers(i)))
2594 newTolers(i) = aNewTolEdge2;
2595 B.UpdateEdge(edge2, aNewTolEdge2);
2596 }
2597
2598 // update of tolerances of vertexies
2599 for(i = 1; i <=4; i++)
2600 if(newTolers(i)>0) B.UpdateVertex(TopoDS::Vertex(vertices(i)),newTolers(i));
2601
2602 if ( ! myShape.IsNull() ) {
2603 Message_Msg MSG ("FixAdvWire.FixIntersection.MSG10"); //Edges %d and %d were intersecting, corrected
2604 MSG.Arg (n1);
2605 MSG.Arg (n2);
2606 SendWarning (MSG);
2607 }
2608 return Standard_True;
2609}
2610
2611//=======================================================================
2612//function : FixLacking
2613//purpose : Test if two adjucent edges are disconnected in 2d (while connected
2614// in 3d), and in that case either increase tolerance of the vertex or
2615// add a new edge (straight in 2d space), in order to close wire in 2d.
2616// Returns True if edge was added or tolerance was increased.
2617//NOTE : Is to be run after FixDegenerated
2618//Algorithm: 1. Compute the 2d gap between edges and calculate a tolerance
2619// which should have vertex in order to comprise the gap
2620// (using GeomAdaptor_Surface); computed value is inctol
2621// 2. If inctol < tol of vertex, return False (everything is OK)
2622// 3. If inctol < Precision, just increase tolerance of vertex to inctol
2623// 4. Else (if both edges are not degenerated) try to add new edge
2624// with straight pcurve (in order to close the gap):
2625// a) if flag MayEdit is False
2626// 1. if inctol < MaxTolerance, increase tolerance of vertex to inctol
2627// 2. else try to add degenerated edge (check that middle point of
2628// that pcurveis inside the vertex)
2629// b) if MayEdit is True
2630// 1. try to replace big vertex with two new small vertices
2631// connected by new edge. This is made if there is a 3d space
2632// between ends of adjacent edges.
2633// 2. if inctol < MaxTolerance, increase tolerance of vertex to inctol
2634// 3. else add either degenerated or closed edge (if middle point
2635// of a pcurve of a new edge is inside the vertex, then
2636// degenerated edge is added, else new edge is closed).
2637// 5. If new edge cannot be added, but inctol < MaxTolerance,
2638// when increase tolerance of vertex to a value of inctol
2639//Short list of some internal variables:
2640// tol - tolerance of vertex
2641// tol2d - tolerance in parametric space of the surface corresponding to 2*tol
2642// dist2d - distance between ends of pcurves of edges (2d)
2643// inctol - tolerance required for vertex to close 2d gap (=tol*dist2d/tol2d)
2644// tol1, tol2 - tolerances of edges, tol0 = tol1 + tol2
2645// p3d1, p3d2 - ends of 3d curves of edges
2646//=======================================================================
2647//:h2 abv 28 May 98: merged modifications by abv 22 Apr 98, gka 27 May 98
2648// and pdn 25 May 98 concerning lacking closed or degenerated edges
2649// Example files: r0501_pe #107813, UKI60107-6 250, UKI60107-3 1577.
2650
2651//:s2 abv 21 Apr 99: add functionality for bending pcurve
2652static Standard_Boolean TryBendingPCurve (const TopoDS_Edge &E, const TopoDS_Face &face,
2653 const gp_Pnt2d p2d, const Standard_Boolean end,
2654 Handle(Geom2d_Curve) &c2d,
2655 Standard_Real &first, Standard_Real &last,
2656 Standard_Real &tol)
2657{
2658 ShapeAnalysis_Edge sae;
2659 if ( ! sae.PCurve ( E, face, c2d, first, last, Standard_False ) ) return Standard_False;
2660
2661 {
2662 try {
2663 OCC_CATCH_SIGNALS
2664 Handle(Geom2d_BSplineCurve) bs;
2665 if ( c2d->IsKind(STANDARD_TYPE(Geom2d_BSplineCurve)) )
2666 bs = Handle(Geom2d_BSplineCurve)::DownCast(c2d->Copy());
2667 else // if ( c2d->IsKind(STANDARD_TYPE(Geom2d_Line)) )
2668 {
2669 Handle(Geom2d_TrimmedCurve) trim = new Geom2d_TrimmedCurve ( c2d, first, last );
2670 bs = Geom2dConvert::CurveToBSplineCurve ( trim );
2671 }
2672 if ( bs.IsNull() ) return Standard_False;
2673
2674 Standard_Real par = ( end ? last : first );
2675 if ( fabs ( bs->FirstParameter() - par ) < ::Precision::PConfusion() &&
2676 bs->Multiplicity(1) > bs->Degree() ) bs->SetPole ( 1, p2d );
2677 else if ( fabs ( bs->LastParameter() - par ) < ::Precision::PConfusion() &&
2678 bs->Multiplicity(bs->NbKnots()) > bs->Degree() ) bs->SetPole ( bs->NbPoles(), p2d );
2679 else {
2680 bs->Segment ( first, last );
2681 if (fabs ( bs->FirstParameter() - par ) < ::Precision::PConfusion() &&
2682 bs->Multiplicity(1) > bs->Degree()) bs->SetPole ( 1, p2d );
2683 else if (fabs ( bs->LastParameter() - par ) < ::Precision::PConfusion() &&
2684 bs->Multiplicity(bs->NbKnots()) > bs->Degree()) bs->SetPole ( bs->NbPoles(), p2d );
2685 else return Standard_False;
2686 }
2687 c2d = bs;
2688 }
2689 catch ( Standard_Failure ) {
2690#ifdef DEB
2691 cout << "Warning: ShapeFix_Wire::FixLacking: Exception in Geom2d_BSplineCurve::Segment()" << endl;
2692#endif
2693 return Standard_False;
2694 }
2695 }
2696
2697 if ( ! TryNewPCurve ( E, face, c2d, first, last, tol ) ) return Standard_False;
2698 return Standard_True;
2699}
2700
2701
2702//=======================================================================
2703//function : FixLacking
2704//purpose :
2705//=======================================================================
2706
2707Standard_Boolean ShapeFix_Wire::FixLacking (const Standard_Integer num,
2708 const Standard_Boolean force)
2709{
2710 myLastFixStatus = ShapeExtend::EncodeStatus ( ShapeExtend_OK );
2711 if ( ! IsReady() ) return Standard_False;
2712
2713 //=============
2714 // First phase: analysis whether the problem (gap) exists
2715 gp_Pnt2d p2d1, p2d2;
2716 Handle(ShapeAnalysis_Wire)::DownCast(myAnalyzer)->CheckLacking ( num, ( force ? Precision() : 0. ), p2d1, p2d2 );
2717 if ( myAnalyzer->LastCheckStatus ( ShapeExtend_FAIL ) ) {
2718 myLastFixStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_FAIL1 );
2719 }
2720 if ( ! myAnalyzer->LastCheckStatus ( ShapeExtend_DONE ) ) return Standard_False;
2721
2722 //=============
2723 // Second phase: collection of data necessary for further analysis
2724
2725 Handle(ShapeExtend_WireData) sbwd = WireData();
2726 Standard_Integer n2 = ( num >0 ? num : sbwd->NbEdges() );
2727 Standard_Integer n1 = ( n2 >1 ? n2-1 : sbwd->NbEdges() );
2728 TopoDS_Edge E1 = sbwd->Edge(n1);
2729 TopoDS_Edge E2 = sbwd->Edge(n2);
2730
2731 ShapeAnalysis_Edge sae;
2732 TopoDS_Vertex V1 = sae.LastVertex ( E1 );
2733 TopoDS_Vertex V2 = sae.FirstVertex ( E2 );
2734 Standard_Real tol = Max ( BRep_Tool::Tolerance ( V1 ), BRep_Tool::Tolerance ( V2 ) );
2735
2736 Standard_Real Prec = Precision();
2737 Standard_Real dist2d = myAnalyzer->MaxDistance2d();
2738 Standard_Real inctol = myAnalyzer->MaxDistance3d();
2739
2740 TopoDS_Face face = myAnalyzer->Face();
2741 Handle(ShapeAnalysis_Surface) surf = myAnalyzer->Surface();
2742
2743 gp_Pnt p3d1, p3d2;
2744 Standard_Real tol1=::Precision::Confusion(), tol2=::Precision::Confusion(); //SK
2745
2746 //=============
2747 //:s2 abv 21 Apr 99: Speculation: try bending pcurves
2748 Standard_Real bendtol1, bendtol2;
2749 Handle(Geom2d_Curve) bendc1, bendc2;
2750 Standard_Real bendf1, bendl1, bendf2, bendl2;
2751 if ( myGeomMode && ! BRep_Tool::IsClosed(E1,face) && ! BRep_Tool::IsClosed(E2,face) ) {
2752 gp_Pnt2d p2d = 0.5 * ( p2d1.XY() + p2d2.XY() );
2753 Standard_Boolean ok1 = TryBendingPCurve (E1, face, p2d, E1.Orientation() == TopAbs_FORWARD,
2754 bendc1, bendf1, bendl1, bendtol1);
2755 Standard_Boolean ok2 = TryBendingPCurve (E2, face, p2d, E2.Orientation() == TopAbs_REVERSED,
2756 bendc2, bendf2, bendl2, bendtol2);
2757 if ( ok1 && ! ok2 ) {
2758 bendtol2 = BRep_Tool::Tolerance(E2);
2759 ok1 = TryBendingPCurve (E1, face, p2d2, E1.Orientation() == TopAbs_FORWARD,
2760 bendc1, bendf1, bendl1, bendtol1);
2761 }
2762 else if ( ! ok1 && ok2 ) {
2763 bendtol1 = BRep_Tool::Tolerance(E1);
2764 ok2 = TryBendingPCurve (E2, face, p2d1, E2.Orientation() == TopAbs_FORWARD,
2765 bendc2, bendf2, bendl2, bendtol2);
2766 }
2767 if ( ! ok1 && ! ok2 ) bendc1.Nullify();
2768 }
2769
2770 //=============
2771 // Third phase: analyse how to fix the problem
2772
2773 // selector of solutions
2774 Standard_Boolean doIncrease = Standard_False; // increase tolerance
2775 Standard_Boolean doAddLong = Standard_False; // add long 3d edge in replacement of a vertex
2776 Standard_Boolean doAddClosed = Standard_False; // add closed 3d edge
2777 Standard_Boolean doAddDegen = Standard_False; // add degenerated edge
2778 Standard_Boolean doBend = Standard_False; //:s2 bend pcurves
2779
2780 // if bending is OK with existing tolerances of edges, take it
2781 if ( ! bendc1.IsNull() && ! bendc2.IsNull() &&
2782 ( ( bendtol1 < BRep_Tool::Tolerance(E1) &&
2783 bendtol2 < BRep_Tool::Tolerance(E2) ) ||
2784 ( inctol < Prec && bendtol1 < inctol && bendtol2 < inctol ) ) )
2785 doBend = Standard_True;
2786
2787 // is it OK just to increase tolerance (to a value less than preci)?
2788 else if ( inctol < Prec ) doIncrease = Standard_True;
2789
2790 // If increase is not OK or force, try to find other solutions (adding edge)
2791 else if ( ! BRep_Tool::Degenerated ( E2 ) && ! BRep_Tool::Degenerated ( E1 ) ) {
2792
2793 // analyze the 3d space btw edges: is it enough to add long 3d edge?
2794 if ( myTopoMode ) {
2795 Handle(Geom_Curve) c3d;
2796 Standard_Real a, b;
2797 if ( ! sae.Curve3d ( E1, c3d, a, b, Standard_True ) ) { // cannot work
2798 myLastFixStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_FAIL1 );
2799 return Standard_False;
2800 }
2801 p3d1 = c3d->Value ( b );
2802 Standard_Real dist2d3d1 = p3d1.Distance ( surf->Value ( p2d1 ) );
2803 if ( ! sae.Curve3d ( E2, c3d, a, b, Standard_True ) ) { // cannot work
2804 myLastFixStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_FAIL1 );
2805 return Standard_False;
2806 }
2807 p3d2 = c3d->Value ( a );
2808 Standard_Real dist2d3d2 = p3d2.Distance ( surf->Value ( p2d2 ) );
2809
2810 tol1 = Max ( BRep_Tool::Tolerance ( E1 ), dist2d3d1 );
2811 tol2 = Max ( BRep_Tool::Tolerance ( E2 ), dist2d3d2 );
2812 //:c5 Standard_Real tol0 = Max ( tol1 + tol2, thepreci );
2813 Standard_Real tol0 = tol1 + tol2; //:c5 abv 26 Feb 98: CTS17806 #44418
2814 Standard_Real dist3d2 = p3d1.SquareDistance ( p3d2 );
2815
2816 // is it OK to add a long 3d edge?
2817 if ( ! myAnalyzer->LastCheckStatus ( ShapeExtend_DONE2 ) && //:81 abv 20 Jan 98: don`t add back-going edges (zigzags)
2818 dist3d2 > 1.25 * tol0 * tol0 &&
2819 ( force || dist3d2 > Prec * Prec || inctol > MaxTolerance() ) ) {
2820 doAddLong = Standard_True;
2821 }
2822 }
2823
2824 //:h6 abv 25 Jun 98: BUC40132 6361: try to increase tol up to MaxTol if not add
2825 if ( ! doAddLong && inctol < MaxTolerance() &&
2826 ! myAnalyzer->Surface()->IsDegenerated ( p2d1, p2d2, 2.*tol, 10. ) ) { //:p7
2827 if ( ! bendc1.IsNull() && ! bendc2.IsNull() &&
2828 bendtol1 < inctol && bendtol2 < inctol ) doBend = Standard_True;
2829 else doIncrease = Standard_True;
2830 }
2831 else
2832
2833 // else try to add either degenerated or closed edge
2834 if ( ! doAddLong ) {
2835 gp_Pnt pV = 0.5 * ( BRep_Tool::Pnt(V1).XYZ() + BRep_Tool::Pnt(V2).XYZ() );
2836 gp_Pnt pm = myAnalyzer->Surface()->Value ( 0.5 * ( p2d1.XY() + p2d2.XY() ) );
2837
2838 Standard_Real dist = pV.Distance ( pm );
2839 if ( dist <= tol ) doAddDegen = Standard_True;
2840 else if ( myTopoMode ) doAddClosed = Standard_True;
2841 else if ( dist <= MaxTolerance() ) { //:r7 abv 12 Apr 99: t3d_opt.stp #14245 after S4136
2842 doAddDegen = Standard_True;
2843 doIncrease = Standard_True;
2844 inctol = dist;
2845 }
2846 }
2847 }
2848
2849 else if ( !BRep_Tool::Degenerated(E2) && BRep_Tool::Degenerated(E1) ) {
2850 // create new degenerated edge and replace E1 to new edge
2851 }
2852 else if ( BRep_Tool::Degenerated(E2) && !BRep_Tool::Degenerated(E1) ) {
2853 // create new degenerated edge and replace E2 to new edge
2854 }
2855
2856 //=============
2857 // Third phase - do the fixes
2858 BRep_Builder B;
2859
2860 // add edge
2861 if ( doAddLong || doAddDegen || doAddClosed ) {
2862
2863 // construct new vertices
2864 TopoDS_Vertex newV1, newV2;
2865 if ( doAddLong ) {
2866 newV1 = BRepBuilderAPI_MakeVertex ( p3d1 );
2867 newV1.Reverse();
2868 newV2 = BRepBuilderAPI_MakeVertex ( p3d2 );
2869 B.UpdateVertex ( newV1, 1.001 * tol1 );
2870 B.UpdateVertex ( newV2, 1.001 * tol2 );
2871 }
2872 else {
2873 newV1 = V1;
2874 newV2 = V2;
2875 }
2876
2877 // prepare new edge
2878 TopoDS_Edge edge;
2879 B.MakeEdge ( edge );
2880 if ( doAddDegen ) B.Degenerated ( edge, Standard_True ); // sln: do it before adding curve
2881 gp_Vec2d v12 ( p2d1, p2d2 );
2882 Handle(Geom2d_Line) theLine2d = new Geom2d_Line ( p2d1, gp_Dir2d ( v12 ) );
2883 B.UpdateEdge ( edge, theLine2d, face, ::Precision::Confusion() );
2884 B.Range ( edge, face, 0, dist2d );
2885 B.Add ( edge, newV1.Oriented ( TopAbs_FORWARD ) );
2886 B.Add ( edge, newV2.Oriented ( TopAbs_REVERSED ) );
2887 ShapeBuild_Edge sbe;
2888 if ( ! doAddDegen && ! sbe.BuildCurve3d ( edge ) ) {
2889 myLastFixStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_FAIL3 );
2890 return Standard_False;
2891 }
2892
2893 // if long edge is added, replace vertices of adjacent edges
2894 if ( doAddLong ) {
2895
2896 // replace 1st edge (n1==n2 - special case: wire consists of one edge)
2897 TopoDS_Edge edge1 = sbe.CopyReplaceVertices ( E1,
2898 ( n1 == n2 ? newV2 : TopoDS_Vertex() ), newV1 );
2899 sbwd->Set ( edge1, n1 );
2900 if ( ! Context().IsNull() ) {
2901 Context()->Replace ( E1, edge1 );
2902 // actually, this will occur only in context of single face
2903 // hence, recording to ReShape is rather for tracking modifications
2904 // than for keeping sharing
2905 Context()->Replace ( V1, newV1.Oriented ( V1.Orientation() ) );
2906 if ( ! V1.IsSame ( V2 ) ) {
2907 Context()->Replace ( V2, newV2.Oriented ( V2.Orientation() ) );
2908 }
2909 }
2910 // replace 2nd edge
2911 if ( n1 != n2 ) {
2912 TopoDS_Edge edge2 = sbe.CopyReplaceVertices ( E2, newV2, TopoDS_Vertex() );
2913 sbwd->Set ( edge2, n2 );
2914 if ( ! Context().IsNull() ) Context()->Replace ( E2, edge2 );
2915 }
2916 if ( ! Context().IsNull() ) UpdateWire();
2917 }
2918
2919 // insert new edge
2920 if ( doAddDegen ) {
2921 myLastFixStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE3 );
2922#ifdef DEB
2923 cout << "Warning: ShapeFix_Wire::FixLacking: degenerated edge added" << endl;
2924#endif
2925 }
2926 else if ( ! doAddLong ) {
2927 myLastFixStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE4 );
2928 }
2929 sbwd->Add ( edge, n2 );
2930 myLastFixStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE2 );
2931 }
2932
2933 // else try to increase tol up to MaxTol
2934 else if ( inctol > tol && inctol < MaxTolerance() ) {
2935 if ( ! bendc1.IsNull() && ! bendc2.IsNull() &&
2936 bendtol1 < inctol && bendtol2 < inctol ) doBend = Standard_True;
2937 else doIncrease = Standard_True;
2938 }
2939
2940 // bend pcurves
2941 if ( doBend ) { //:s2 abv 21 Apr 99
2942 B.UpdateEdge ( E1, bendc1, face, bendtol1 );
2943 B.Range ( E1, face, bendf1, bendl1 );
2944 B.UpdateEdge ( E2, bendc2, face, bendtol2 );
2945 B.Range ( E2, face, bendf2, bendl2 );
2946 B.UpdateVertex ( sae.FirstVertex(E1), bendtol1 );
2947 B.UpdateVertex ( sae.LastVertex(E1), bendtol1 );
2948 B.UpdateVertex ( sae.FirstVertex(E2), bendtol2 );
2949 B.UpdateVertex ( sae.LastVertex(E2), bendtol2 );
2950 myLastFixStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE5 );
2951 //:s3 abv 22 Apr 99: PRO7187 #11534: self-intersection not detected unitil curve is bent (!)
2952 FixSelfIntersectingEdge ( n1 );
2953 FixSelfIntersectingEdge ( n2 );
2954 FixIntersectingEdges ( n2 ); //skl 24.04.2003 for OCC58
2955#ifdef DEB
2956 cout << "Info: ShapeFix_Wire::FixLacking: Bending pcurves" << endl;
2957#endif
2958 myLastFixStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE5 );
2959 }
2960
2961 // increase vertex tolerance
2962 if ( doIncrease ) {
2963 B.UpdateVertex ( V1, 1.001 * inctol );
2964 B.UpdateVertex ( V2, 1.001 * inctol );
2965 myLastFixStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE1 );
2966 }
2967
2968 if ( LastFixStatus ( ShapeExtend_DONE ) ) return Standard_True;
2969
2970 myLastFixStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_FAIL2 );
2971 return Standard_False;
2972}
2973
2974//=======================================================================
2975//function : FixNotchedEdges
2976//purpose :
2977//=======================================================================
2978
2979Standard_Boolean ShapeFix_Wire::FixNotchedEdges()
2980{
2981 myLastFixStatus = ShapeExtend::EncodeStatus ( ShapeExtend_OK );
2982 if ( ! IsReady() ) return Standard_False;
2983
2984 Handle(ShapeAnalysis_Wire) theAdvAnalyzer = Handle(ShapeAnalysis_Wire)::DownCast(myAnalyzer);
2985 TopoDS_Face face = Face();
2986 if ( ! Context().IsNull() ) UpdateWire();
2987 Handle(ShapeExtend_WireData) sewd = WireData();
2988
ba9cc08b 2989 for (Standard_Integer i = 1; i <= NbEdges() && NbEdges() > 2; i++) {
7fd59977 2990 Standard_Real param;
2991 Standard_Integer toRemove;
2992 if(theAdvAnalyzer->CheckNotchedEdges(i,toRemove,param,MinTolerance())){
2993 Standard_Integer n2 = (i > 0) ? i : NbEdges();
2994 Standard_Integer n1 = (n2 > 1) ? n2-1 : NbEdges();
2995 Standard_Boolean isRemoveFirst = (n1==toRemove);
2996 Standard_Integer toSplit = (n2==toRemove ? n1 : n2);
2997 TopoDS_Edge splitE = sewd->Edge ( toSplit );
2998 ShapeAnalysis_Edge sae;
2999 Handle(Geom2d_Curve) c2d;
3000 Standard_Real a, b;
3001 sae.PCurve ( splitE, face, c2d, a, b, Standard_True );
3002 Standard_Real ppar = (isRemoveFirst ? b : a);
3003 ShapeBuild_Edge sbe;
3004 TopAbs_Orientation orient = splitE.Orientation();
3005 if ( Abs(param - ppar) > ::Precision::PConfusion() ) {
3006 //pdn perform splitting of the edge and adding to wire
3007
3008 //pdn check if it is necessary
3009 if( Abs((isRemoveFirst ? a : b)-param) < ::Precision::PConfusion() ) {
3010 continue;
3011 }
3012
3013 Handle(ShapeAnalysis_TransferParametersProj) transferParameters =
3014 new ShapeAnalysis_TransferParametersProj;
3015 transferParameters->SetMaxTolerance(MaxTolerance());
3016 transferParameters->Init(splitE,face);
3017 Standard_Real first, last;
3018 if (a < b ) {
3019 first = a;
3020 last = b;
3021 }
3022 else {
3023 first = b;
3024 last = a;
3025 }
3026 TopoDS_Vertex Vnew;
3027 BRep_Builder B;
3028 B.MakeVertex(Vnew,Analyzer()->Surface()->Value(c2d->Value(param)),::Precision::Confusion());
3029 TopoDS_Edge wE = splitE;
3030 wE.Orientation ( TopAbs_FORWARD );
3031 TopoDS_Shape aTmpShape = Vnew.Oriented(TopAbs_REVERSED); //for porting
3032 TopoDS_Edge newE1 = sbe.CopyReplaceVertices ( wE, sae.FirstVertex(wE), TopoDS::Vertex(aTmpShape) );
3033 sbe.CopyPCurves ( newE1, wE );
3034 transferParameters->TransferRange(newE1,first,param,Standard_True);
3035 B.SameRange(newE1,Standard_False);
3036 B.SameParameter(newE1,Standard_False);
3037 aTmpShape = Vnew.Oriented(TopAbs_FORWARD);
3038 TopoDS_Edge newE2 = sbe.CopyReplaceVertices ( wE, TopoDS::Vertex(aTmpShape),sae.LastVertex(wE) );
3039 sbe.CopyPCurves ( newE2, wE );
3040 transferParameters->TransferRange(newE2,param,last,Standard_True);
3041 B.SameRange(newE2,Standard_False);
3042 B.SameParameter(newE2,Standard_False);
3043
3044 if ( !Context().IsNull() ) {
3045 TopoDS_Wire wire;
3046 B.MakeWire(wire);
3047 B.Add(wire,newE1);
3048 B.Add(wire,newE2);
3049 Context()->Replace ( wE, wire );
3050 }
3051
3052 newE1.Orientation(orient);
3053 newE2.Orientation(orient);
3054 if (orient==TopAbs_REVERSED){ TopoDS_Edge tmp = newE2; newE2 = newE1; newE1=tmp;}
3055
3056 Standard_Boolean isRemoveLast = ((n1==NbEdges())&&(n2==1));
3057 sewd->Set ( newE1, toSplit);
3058 sewd->Add ( newE2, (toSplit==NbEdges() ? 0 : toSplit+1));
3059
3060 FixDummySeam(isRemoveLast ? NbEdges() : toRemove);
3061 myLastFixStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE2 );
3062 }
3063 else
3064 FixDummySeam(n1);
3065
3066 i--;
3067 if(!Context().IsNull()) //skl 07.03.2002 for OCC180
3068 UpdateWire();
3069 myLastFixStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE1 );
3070 }
3071 }
3072 myStatusNotches = myLastFixStatus;
3073 return LastFixStatus ( ShapeExtend_DONE );
3074}
3075
3076//=======================================================================
3077//function : FixDummySeam
3078//purpose :
3079//=======================================================================
3080
3081static void CopyReversePcurves(const TopoDS_Edge& toedge,
3082 const TopoDS_Edge& fromedge,
3083 const Standard_Boolean reverse)
3084{
3085 TopLoc_Location fromLoc = fromedge.Location();
3086 TopLoc_Location toLoc = toedge.Location();
3087 for (BRep_ListIteratorOfListOfCurveRepresentation fromitcr
3088 ((*((Handle(BRep_TEdge)*)&fromedge.TShape()))->ChangeCurves()); fromitcr.More(); fromitcr.Next()) {
3089 Handle(BRep_GCurve) fromGC = Handle(BRep_GCurve)::DownCast(fromitcr.Value());
3090 if ( fromGC.IsNull() ) continue;
3091 if ( fromGC->IsCurveOnSurface() ) {
3092 Handle(Geom_Surface) surface = fromGC->Surface();
3093 TopLoc_Location L = fromGC->Location();
3094 Standard_Boolean found = Standard_False;
3095 BRep_ListOfCurveRepresentation& tolist = (*((Handle(BRep_TEdge)*)&toedge.TShape()))->ChangeCurves();
3096 Handle(BRep_GCurve) toGC;
3097 for (BRep_ListIteratorOfListOfCurveRepresentation toitcr (tolist); toitcr.More() && !found; toitcr.Next()) {
3098 toGC = Handle(BRep_GCurve)::DownCast(toitcr.Value());
3099 if ( toGC.IsNull() || !toGC->IsCurveOnSurface() ||
3100 surface != toGC->Surface() || L != toGC->Location() ) continue;
3101 found = Standard_True;
3102 break;
3103 }
3104 if (!found) {
3105 Standard_Real fp = fromGC->First();
3106 Standard_Real lp = fromGC->Last();
3107 toGC = Handle(BRep_GCurve)::DownCast(fromGC->Copy());
3108 tolist.Append (toGC);
3109 Handle(Geom2d_Curve) pcurve = Handle(Geom2d_Curve)::DownCast( fromGC->PCurve()->Copy() );
3110 if (reverse) {
3111 fp = pcurve->ReversedParameter(fp);
3112 lp = pcurve->ReversedParameter(lp);
3113 pcurve->Reverse();
3114 Standard_Real tmp = fp;
3115 fp = lp;
3116 lp = tmp;
3117 }
3118 //bug OCC209 invalid location of pcurve in the edge after copying
3119 TopLoc_Location newLoc = (fromLoc*L).Predivided(toLoc);
3120 toGC->SetRange(fp,lp);
3121 toGC->PCurve(pcurve);
3122 toGC->Location(newLoc);
3123 if ( fromGC->IsCurveOnClosedSurface() ) {
3124 pcurve = fromGC->PCurve2();
3125 toGC->PCurve2(Handle(Geom2d_Curve)::DownCast(pcurve->Copy()));
3126 }
3127 }
3128 }
3129 }
3130}
3131
3132//=======================================================================
3133//function : HasNewPCurves
3134//purpose :
3135//=======================================================================
3136// Note: This function temporarily not used, because adress to it in
3137// function FixDummySeam() (see below line 2472) not used too
3138//
3139//static Standard_Boolean HasNewPCurves(const TopoDS_Edge& toedge,
3140// const TopoDS_Edge& fromedge)
3141//
3142//{
3143// for (BRep_ListIteratorOfListOfCurveRepresentation fromitcr
3144// ((*((Handle(BRep_TEdge)*)&fromedge.TShape()))->ChangeCurves()); fromitcr.More(); fromitcr.Next()) {
3145// Handle(BRep_GCurve) fromGC = Handle(BRep_GCurve)::DownCast(fromitcr.Value());
3146// if ( fromGC.IsNull() ) continue;
3147// if ( fromGC->IsCurveOnSurface() ) {
3148// Handle(Geom_Surface) surface = fromGC->Surface();
3149// TopLoc_Location L = fromGC->Location();
3150// Standard_Boolean found = Standard_False;
3151// BRep_ListOfCurveRepresentation& tolist = (*((Handle(BRep_TEdge)*)&toedge.TShape()))->ChangeCurves();
3152// Handle(BRep_GCurve) toGC;
3153// for (BRep_ListIteratorOfListOfCurveRepresentation toitcr (tolist); toitcr.More() && !found; toitcr.Next()) {
3154// toGC = Handle(BRep_GCurve)::DownCast(toitcr.Value());
3155// if ( toGC.IsNull() || !toGC->IsCurveOnSurface() ||
3156// surface != toGC->Surface() || L != toGC->Location() ) continue;
3157// found = Standard_True;
3158// break;
3159// }
3160// if (!found)
3161// return Standard_True;
3162// }
3163// }
3164// return Standard_False;
3165//}
3166
3167//=======================================================================
3168//function : FixDummySeam
3169//purpose :
3170//=======================================================================
3171
3172void ShapeFix_Wire::FixDummySeam(const Standard_Integer num)
3173{
3174 ShapeAnalysis_Edge sae;
3175 ShapeBuild_Edge sbe;
3176 ShapeBuild_Vertex sbv;
3177 Standard_Integer num1 = (num == NbEdges()) ? 1 : num+1;
3178 Handle(ShapeExtend_WireData) sewd = WireData();
3179 TopoDS_Edge E1 = sewd->Edge(num), E2 = sewd->Edge(num1);
3180 TopoDS_Vertex V1 = sae.FirstVertex(E1), V2 = sae.LastVertex(E2);
3181 TopoDS_Vertex Vm = sbv.CombineVertex ( V1, V2, 1.0001 );
3182
3183 //pnd defining if new pcurves exists
3184 //pdn Temporary not removed
3185// Standard_Boolean toRemove = !(HasNewPCurves(E1,E2)||HasNewPCurves(E2,E1));
3186 Standard_Boolean toRemove = Standard_False;
3187
3188 //creating new edge with pcurves and new vertex
3189 TopoDS_Vertex Vs = sae.FirstVertex(E2);
3190 if ( Vs.IsSame ( V1 ) || Vs.IsSame ( V2 ) ) Vs = Vm;
3191 TopoDS_Edge newEdge = sbe.CopyReplaceVertices ( E2, Vs, Vm );
3192 CopyReversePcurves(newEdge,E1,E1.Orientation()==E2.Orientation());
3193 BRep_Builder B;
3194 B.SameRange(newEdge,Standard_False);
3195 B.SameParameter(newEdge,Standard_False);
3196
3197 if ( !Context().IsNull() ) {
3198 if (toRemove) {
3199 Context()->Remove ( E2 );
3200 Context()->Remove ( E1 );
3201 }
3202 else {
3203 Context()->Replace ( E2, newEdge );
3204 Context()->Replace ( E1, newEdge.Reversed());
3205 }
3206 Context()->Replace ( V1, Vm.Oriented(V1.Orientation()) );
3207 Context()->Replace ( V2, Vm.Oriented(V2.Orientation()) );
3208 }
3209
3210 Standard_Integer next = ( num1 == NbEdges()) ? 1 : num1+1;
3211 Standard_Integer prev = ( num > 1) ? num-1 : NbEdges();
3212 TopoDS_Edge prevE = sewd->Edge(prev), nextE = sewd->Edge(next);
3213
3214 TopoDS_Edge tmpE1=sbe.CopyReplaceVertices( prevE, TopoDS_Vertex(), Vm);
3215 sewd->Set ( tmpE1,prev );
3216 if ( !Context().IsNull() ) Context()->Replace ( prevE, tmpE1);
3217
3218 tmpE1 = sbe.CopyReplaceVertices ( nextE, Vm, TopoDS_Vertex());
3219 sewd->Set ( tmpE1,next );
3220 if ( !Context().IsNull() ) Context()->Replace ( nextE, tmpE1);
3221
3222 //removing edges from wire
3223 Standard_Integer n1, n2;
3224 if ( num < num1 ) {
3225 n1 = num; n2 = num1;
3226 } else {
3227 n1 = num1; n2 = num;
3228 }
3229 sewd->Remove(n2);
3230 sewd->Remove(n1);
3231}
3232
3233//=======================================================================
3234//function : UpdateWire
3235//purpose :
3236//=======================================================================
3237
3238void ShapeFix_Wire::UpdateWire ()
3239{
3240 Handle(ShapeExtend_WireData) sbwd = WireData();
3241 for ( Standard_Integer i=1; i <= sbwd->NbEdges(); i++ ) {
3242 TopoDS_Edge E = sbwd->Edge(i);
3243 TopoDS_Shape S = Context()->Apply ( E );
3244 if ( S == E ) continue;
3245 for ( TopExp_Explorer exp(S,TopAbs_EDGE); exp.More(); exp.Next() )
3246 sbwd->Add ( exp.Current(), i++ );
3247 sbwd->Remove ( i-- );
3248 }
3249}