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