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