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