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