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