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