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