1 // Created on: 2000-01-21
2 // Created by: data exchange team
3 // Copyright (c) 2000-2014 OPEN CASCADE SAS
4 //
5 // This file is part of Open CASCADE Technology software library.
6 //
7 // This library is free software; you can redistribute it and/or modify it under
8 // the terms of the GNU Lesser General Public License version 2.1 as published
9 // by the Free Software Foundation, with special exception defined in the file
10 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
11 // distribution for complete text of the license and disclaimer of any warranty.
12 //
13 // Alternatively, this file may be used under the terms of Open CASCADE
14 // commercial license or contractual agreement.
15
16 #include <ShapeFix.hxx>
17 //:k2 abv 16.12.98: eliminating code duplication
18 //pdn 18.12.98: checking deviation for SP edges
19 //: abv 22.02.99: method FillFace() removed since PRO13123 is fixed
20 //szv#4 S4163
21 //szv#9:S4244:19Aug99: Added method FixWireGaps
22 //szv#10:S4244:23Aug99: Added method FixFaceGaps
23
24 #include <BRep_Builder.hxx>
25 #include <BRep_Tool.hxx>
26
27 #include <Geom2d_Curve.hxx>
28 #include <Geom_Curve.hxx>
29
30 #include <Precision.hxx>
31
32 #include <Standard_Failure.hxx>
33
34 #include <TopExp_Explorer.hxx>
35 #include <TopLoc_Location.hxx>
36 #include <TopoDS.hxx>
37 #include <TopoDS_Edge.hxx>
38 #include <TopoDS_Face.hxx>
39 #include <Geom_Surface.hxx>
40
41 //:i2
42 #include <gp_Pnt.hxx>
43 #include <Geom_Plane.hxx>
44 #include <ShapeFix_Edge.hxx>
45 #include <Geom2dAdaptor_Curve.hxx>
46 #include <Adaptor3d_CurveOnSurface.hxx>
47 #include <Geom_RectangularTrimmedSurface.hxx>
48 #include <ShapeAnalysis_Surface.hxx>
49
50 #include <ShapeFix_Edge.hxx>
51 #include <ShapeFix_Shape.hxx>
52 #include <ShapeFix_Wire.hxx>
53 #include <ShapeFix_Face.hxx>
54 #include <TopoDS_Iterator.hxx>
55 #include <GeomAdaptor_Surface.hxx>
56 #include <TopTools_MapOfShape.hxx>
57 #include <BRepLib.hxx>
58
59 #include <ShapeAnalysis_Edge.hxx>
60 #include <ShapeBuild_Edge.hxx>
61 #include <TopoDS_Vertex.hxx>
62 #include <ShapeBuild_ReShape.hxx>
63 #include <TColgp_SequenceOfPnt.hxx>
64 #include <TopTools_ListOfShape.hxx>
65 #include <TopTools_ListIteratorOfListOfShape.hxx>
66 #include <TopTools_SequenceOfShape.hxx>
67 #include <TopTools_IndexedDataMapOfShapeListOfShape.hxx>
68 #include <TopExp.hxx>
69
70 #include <Message_ProgressScope.hxx>
71 #include <Message_Msg.hxx>
72 #include <ShapeExtend_BasicMsgRegistrator.hxx>
73
74 //=======================================================================
75 //function : SameParameter
76 //purpose :
77 //=======================================================================
78
SameParameter(const TopoDS_Shape & shape,const Standard_Boolean enforce,const Standard_Real preci,const Message_ProgressRange & theProgress,const Handle (ShapeExtend_BasicMsgRegistrator)& theMsgReg)79 Standard_Boolean ShapeFix::SameParameter(const TopoDS_Shape& shape,
80 const Standard_Boolean enforce,
81 const Standard_Real preci,
82 const Message_ProgressRange& theProgress,
83 const Handle(ShapeExtend_BasicMsgRegistrator)& theMsgReg)
84 {
85 // Calculate number of edges
86 Standard_Integer aNbEdges = 0;
87 for ( TopExp_Explorer anEdgeExp(shape, TopAbs_EDGE); anEdgeExp.More(); anEdgeExp.Next() )
88 ++aNbEdges;
89
90 // Calculate number of faces
91 Standard_Integer aNbFaces = 0;
92 for ( TopExp_Explorer anEdgeExp(shape, TopAbs_FACE); anEdgeExp.More(); anEdgeExp.Next() )
93 ++aNbFaces;
94
95 TopTools_IndexedDataMapOfShapeListOfShape aMapEF;
96 TopExp::MapShapesAndAncestors(shape, TopAbs_EDGE, TopAbs_FACE, aMapEF);
97
98 BRep_Builder B;
99 //Standard_Integer nbexcp = 0;
100 Standard_Integer nbfail = 0, numedge = 0;
101 Standard_Boolean status = Standard_True;
102 Standard_Real tol = preci;
103 Standard_Boolean iatol = (tol > 0);
104 Handle(ShapeFix_Edge) sfe = new ShapeFix_Edge;
105 TopExp_Explorer ex(shape,TopAbs_EDGE);
106 Message_Msg doneMsg("FixEdge.SameParameter.MSG0");
107
108 // Start progress scope (no need to check if progress exists -- it is safe)
109 Message_ProgressScope aPSForSameParam(theProgress, "Fixing same parameter problem", 2);
110
111 {
112 // Start progress scope (no need to check if progress exists -- it is safe)
113 Message_ProgressScope aPS (aPSForSameParam.Next(), "Fixing edge", aNbEdges);
114
115 while ( ex.More() )
116 {
117 TopoDS_Edge E;
118 while ( ex.More() && aPS.More() )
119 {
120 numedge ++;
121 int ierr = 0;
122 TopLoc_Location loc;
123 E = TopoDS::Edge (ex.Current());
124 ex.Next();
125
126 if (!iatol)
127 tol = BRep_Tool::Tolerance (E);
128 if (enforce)
129 {
130 B.SameRange (E,Standard_False);
131 B.SameParameter (E,Standard_False);
132 }
133
134 TopTools_ListOfShape aListOfFaces;
135 aMapEF.FindFromKey(E, aListOfFaces);
136 if (aListOfFaces.Extent() != 0)
137 {
138 TopTools_ListOfShape::Iterator aListOfFacesIt(aListOfFaces);
139 for ( ; aListOfFacesIt.More() ; aListOfFacesIt.Next())
140 {
141 TopoDS_Face aF = TopoDS::Face( aListOfFacesIt.Value() );
142 sfe->FixSameParameter (E, aF);
143 }
144 }
145 else
146 {
147 sfe->FixSameParameter (E); // K2-SEP97
148 }
149
150 if (!BRep_Tool::SameParameter (E)) { ierr = 1; nbfail ++; }
151
152 if (ierr)
153 {
154 status = Standard_False;
155 B.SameRange (E,Standard_False);
156 B.SameParameter (E,Standard_False);
157 }
158 else if ( !theMsgReg.IsNull() && !sfe->Status( ShapeExtend_OK ) )
159 {
160 theMsgReg->Send( E, doneMsg, Message_Warning );
161 }
162
163 // Complete step in current progress scope
164 aPS.Next();
165 } // -- end while
166
167 // Halt algorithm in case of user's abort
168 if ( !aPS.More() )
169 return Standard_False;
170 }
171
172 }
173
174 {
175 // Start progress scope (no need to check if progress exists -- it is safe)
176 Message_ProgressScope aPS (aPSForSameParam.Next(), "Update tolerances", aNbFaces);
177
178 //:i2 abv 21 Aug 98: ProSTEP TR8 Motor.rle face 710:
179 // Update tolerance of edges on planes (no pcurves are stored)
180 for ( TopExp_Explorer exp ( shape, TopAbs_FACE ); exp.More() && aPS.More(); exp.Next(), aPS.Next() )
181 {
182 TopoDS_Face face = TopoDS::Face ( exp.Current() );
183 Handle(Geom_Surface) Surf = BRep_Tool::Surface ( face );
184
185 Handle(Geom_Plane) plane = Handle(Geom_Plane)::DownCast ( Surf );
186 if ( plane.IsNull() ) {
187 Handle(Geom_RectangularTrimmedSurface) GRTS =
188 Handle(Geom_RectangularTrimmedSurface)::DownCast ( Surf );
189 if ( ! GRTS.IsNull() )
190 plane = Handle(Geom_Plane)::DownCast ( GRTS->BasisSurface() );
191 if ( plane.IsNull() )
192 continue;
193 }
194
195 Handle(GeomAdaptor_Surface) AS = new GeomAdaptor_Surface ( plane );
196 for ( TopExp_Explorer ed ( face, TopAbs_EDGE ); ed.More(); ed.Next() ) {
197 TopoDS_Edge edge = TopoDS::Edge ( ed.Current() );
198 Standard_Real f, l;
199 Handle(Geom_Curve) crv = BRep_Tool::Curve ( edge, f, l );
200 if ( crv.IsNull() )
201 continue;
202
203 Handle(Geom2d_Curve) c2d = BRep_Tool::CurveOnSurface ( edge, face, f, l );
204 if ( c2d.IsNull() ) continue;
205 Handle(Geom2dAdaptor_Curve) GHPC = new Geom2dAdaptor_Curve ( c2d, f, l );
206 Adaptor3d_CurveOnSurface ACS(GHPC,AS);
207
208 Standard_Real tol0 = BRep_Tool::Tolerance(edge);
209 tol = tol0;
210 Standard_Real tol2 = tol*tol;
211 Standard_Boolean isChanged = Standard_False;
212 const Standard_Integer NCONTROL = 23;
213 for ( Standard_Integer i = 0; i < NCONTROL; i++ )
214 {
215 Standard_Real par = ( f * ( NCONTROL - 1 - i ) + l * i ) / ( NCONTROL - 1 );
216 gp_Pnt pnt = crv->Value ( par );
217 gp_Pnt prj = ACS.Value( par );
218 Standard_Real dist = pnt.SquareDistance(prj);
219 if ( tol2 < dist )
220 {
221 tol2 = dist;
222 isChanged = Standard_True;
223 }
224 }
225 if ( isChanged )
226 {
227 tol = 1.00005 * sqrt(tol2); // coeff: see trj3_pm1-ct-203.stp #19681, edge 10
228 if ( tol >= tol0 )
229 {
230 B.UpdateEdge ( edge, tol );
231 for ( TopoDS_Iterator itV(edge); itV.More(); itV.Next() )
232 {
233 TopoDS_Shape S = itV.Value();
234 B.UpdateVertex ( TopoDS::Vertex ( S ), tol );
235 }
236 }
237 }
238 }
239 }
240 // Halt algorithm in case of user's abort
241 if (!aPS.More())
242 return Standard_False;
243 }
244
245 if (!status) {
246 #ifdef OCCT_DEBUG
247 std::cout<<"** SameParameter not complete. On "<<numedge<<" Edges:";
248 if (nbfail > 0) std::cout<<" "<<nbfail<<" Failed";
249 std::cout<<std::endl;
250 #endif
251 }
252 return status;
253 }
254
255
256 //=======================================================================
257 //function : EncodeRegularity
258 //purpose :
259 //=======================================================================
260
EncodeRegularity(const TopoDS_Shape & shape,const Standard_Real tolang)261 void ShapeFix::EncodeRegularity (const TopoDS_Shape& shape,
262 const Standard_Real tolang)
263 {
264 BRepLib::EncodeRegularity(shape, tolang);
265 }
266
267
268 //=======================================================================
269 //function : RemoveSmallEdges
270 //purpose :
271 //=======================================================================
272
RemoveSmallEdges(TopoDS_Shape & Shape,const Standard_Real Tolerance,Handle (ShapeBuild_ReShape)& context)273 TopoDS_Shape ShapeFix::RemoveSmallEdges (TopoDS_Shape& Shape,
274 const Standard_Real Tolerance,
275 Handle(ShapeBuild_ReShape)& context)
276 {
277 Handle(ShapeFix_Shape) sfs = new ShapeFix_Shape;
278 sfs->Init(Shape);
279 sfs->SetPrecision(Tolerance);
280 sfs->FixFaceTool()->FixMissingSeamMode() = Standard_False;
281 sfs->FixFaceTool()->FixOrientationMode() = Standard_False;
282 sfs->FixFaceTool()->FixSmallAreaWireMode() = Standard_False;
283 sfs->FixWireTool()->ModifyTopologyMode() = Standard_True;
284 //sfs.FixWireTool().FixReorderMode() = Standard_False;
285 sfs->FixWireTool()->FixConnectedMode() = Standard_False;
286 sfs->FixWireTool()->FixEdgeCurvesMode() = Standard_False;
287 sfs->FixWireTool()->FixDegeneratedMode() = Standard_False;
288 sfs->FixWireTool()->FixSelfIntersectionMode() = Standard_False;
289 sfs->FixWireTool()->FixLackingMode() = Standard_False;
290 sfs->FixWireTool()->FixSmallMode() = Standard_True;
291 sfs->Perform();
292 TopoDS_Shape result = sfs->Shape();
293 context = sfs->Context();
294 return result;
295 }
296
297
298 //=======================================================================
299 //function : ReplaceVertex
300 //purpose : auxiliary for FixVertexPosition
301 //=======================================================================
ReplaceVertex(const TopoDS_Edge & theEdge,const gp_Pnt theP,const Standard_Boolean theFwd)302 static TopoDS_Edge ReplaceVertex(const TopoDS_Edge& theEdge,
303 const gp_Pnt theP,
304 const Standard_Boolean theFwd)
305 {
306 TopoDS_Vertex aNewVertex;
307 BRep_Builder aB;
308 aB.MakeVertex(aNewVertex,theP,Precision::Confusion());
309 TopoDS_Vertex aV1,aV2;
310 if(theFwd) {
311 aV1 = aNewVertex;
312 aV1.Orientation( TopAbs_FORWARD);
313 }
314 else {
315 aV2 = aNewVertex;
316 aV2.Orientation( TopAbs_REVERSED);
317 }
318 ShapeBuild_Edge aSbe;
319 TopoDS_Edge e1 = theEdge;
320 TopAbs_Orientation Ori = e1.Orientation();
321 e1.Orientation(TopAbs_FORWARD);
322 TopoDS_Edge aNewEdge = aSbe.CopyReplaceVertices(e1,aV1,aV2);
323 aNewEdge.Orientation(Ori);
324 return aNewEdge;
325 }
326
327
328 //=======================================================================
329 //function : getNearPoint
330 //purpose : auxiliary for FixVertexPosition
331 //=======================================================================
getNearPoint(const TColgp_SequenceOfPnt & aSeq1,const TColgp_SequenceOfPnt & aSeq2,gp_XYZ & acent)332 static Standard_Real getNearPoint(const TColgp_SequenceOfPnt& aSeq1,
333 const TColgp_SequenceOfPnt& aSeq2,
334 gp_XYZ& acent)
335 {
336 Standard_Integer i =1;
337 Standard_Integer ind1 =0,ind2 =0;
338 Standard_Real mindist =RealLast();
339 for( ; i <= aSeq1.Length(); i++) {
340 gp_Pnt p1 = aSeq1.Value(i);
341 Standard_Integer j=1;
342 for( ; j <= aSeq2.Length(); j++) {
343 gp_Pnt p2 = aSeq2.Value(j);
344 Standard_Real d = p1.Distance(p2);
345 if(fabs(d -mindist ) <= Precision::Confusion())
346 continue;
347 if(d < mindist) {
348 mindist = d;
349 ind1 =i;
350 ind2 = j;
351 }
352
353 }
354 }
355 if(ind1 && ind2)
356 acent = (aSeq1.Value(ind1).XYZ() + aSeq2.Value(ind2).XYZ())/2.0;
357 return mindist;
358 }
359
360
361 //=======================================================================
362 //function : getNearestEdges
363 //purpose : auxiliary for FixVertexPosition
364 //=======================================================================
getNearestEdges(TopTools_ListOfShape & theLEdges,const TopoDS_Vertex theVert,TopTools_SequenceOfShape & theSuitEdges,TopTools_SequenceOfShape & theRejectEdges,const Standard_Real theTolerance,gp_XYZ & thecentersuit,gp_XYZ & thecenterreject)365 static Standard_Boolean getNearestEdges(TopTools_ListOfShape& theLEdges,
366 const TopoDS_Vertex theVert,
367 TopTools_SequenceOfShape& theSuitEdges,
368 TopTools_SequenceOfShape& theRejectEdges,
369 const Standard_Real theTolerance,
370 gp_XYZ& thecentersuit,
371 gp_XYZ& thecenterreject)
372 {
373 if(theLEdges.IsEmpty())
374 return Standard_False;
375 TopTools_MapOfShape aMapEdges;
376
377 TopTools_ListOfShape atempList;
378 atempList= theLEdges;
379 TopTools_ListIteratorOfListOfShape alIter(atempList);
380
381 TopoDS_Edge aEdge1 = TopoDS::Edge(alIter.Value());
382 TopoDS_Vertex aVert11,aVert12;
383 TopExp::Vertices(aEdge1, aVert11,aVert12 );
384 aMapEdges.Add(aEdge1);
385 Standard_Real aFirst1,aLast1;
386 Handle(Geom_Curve) aCurve1 = BRep_Tool::Curve(aEdge1,aFirst1,aLast1);
387 gp_Pnt p11;
388 gp_Pnt p12;
389 Standard_Boolean isFirst1 = theVert.IsSame(aVert11);
390 Standard_Boolean isSame1 = aVert11.IsSame(aVert12);
391 if( !aCurve1.IsNull()) {
392 if(isFirst1)
393 p11 = aCurve1->Value(aFirst1);
394 else if(!isSame1)
395 p11 = aCurve1->Value(aLast1);
396 if(isSame1)
397 p12 = aCurve1->Value(aLast1);
398 }
399 else return Standard_False;
400 alIter.Next();
401 TopTools_SequenceOfShape aseqreject;
402 TopTools_SequenceOfShape aseqsuit;
403
404 Standard_Integer anumLoop =0;
405 for( ; alIter.More(); ) {
406 TopoDS_Edge aEdge = TopoDS::Edge(alIter.Value());
407 if( aMapEdges.Contains(aEdge)) {
408 atempList.Remove(alIter);
409 continue;
410 }
411
412 TopoDS_Vertex aVert1,aVert2;
413 TopExp::Vertices(aEdge, aVert1,aVert2 );
414 Standard_Real isFirst = theVert.IsSame(aVert1);
415 Standard_Boolean isSame = aVert1.IsSame(aVert2);
416
417 Standard_Boolean isLoop = ((aVert1.IsSame(aVert11) && aVert2.IsSame(aVert12)) ||
418 (aVert1.IsSame(aVert12) && aVert2.IsSame(aVert11)));
419 if(isLoop /*&& !aseqsuit.Length()*/ && (atempList.Extent() >anumLoop)) {
420 atempList.Append(aEdge);
421 atempList.Remove(alIter);
422 anumLoop++;
423 continue;
424 }
425 aMapEdges.Add(aEdge);
426 Standard_Real aFirst,aLast;
427 Handle(Geom_Curve) aCurve = BRep_Tool::Curve(aEdge,aFirst,aLast);
428 if( !aCurve.IsNull()) {
429 gp_Pnt p1;
430 gp_Pnt p2;
431 if(isFirst)
432 p1 = aCurve->Value(aFirst);
433 else
434 p1 = aCurve->Value(aLast);
435 if(isSame)
436 p2 = aCurve->Value(aLast);
437 Standard_Real aMinDist = RealLast();
438 gp_XYZ acent;
439 if(!isSame && ! isSame1) {
440 aMinDist = p1.Distance(p11);
441 acent = (p1.XYZ() + p11.XYZ())/2.0;
442 }
443 else {
444 TColgp_SequenceOfPnt aSeq1;
445 TColgp_SequenceOfPnt aSeq2;
446 aSeq1.Append(p11);
447 if(isSame1)
448 aSeq1.Append(p12);
449 aSeq2.Append(p1);
450 if(isSame)
451 aSeq2.Append(p2);
452 aMinDist = getNearPoint(aSeq1,aSeq2,acent);
453 }
454
455 if(aMinDist > theTolerance) {
456 if(!aseqreject.Length())
457 thecenterreject = acent;
458 aseqreject.Append(aEdge);
459 }
460 else {
461 if(!aseqsuit.Length()) {
462 thecentersuit = acent;
463 aseqsuit.Append(aEdge);
464 }
465 else if(!isSame1)
466 aseqsuit.Append(aEdge);
467 else if((thecentersuit - acent).Modulus() < theTolerance)
468 aseqsuit.Append(aEdge);
469 else
470 aseqreject.Append(aEdge);
471 }
472
473 }
474 atempList.Remove(alIter);
475 }
476
477 Standard_Boolean isDone = (!aseqsuit.IsEmpty() || !aseqreject.IsEmpty());
478 if(isDone) {
479 if(aseqsuit.IsEmpty()) {
480 theRejectEdges.Append(aEdge1);
481 theLEdges.RemoveFirst();
482
483 getNearestEdges(theLEdges,theVert,theSuitEdges,theRejectEdges,
484 theTolerance,thecentersuit,thecenterreject);
485 }
486 else {
487 theSuitEdges.Append(aEdge1);
488 theSuitEdges.Append(aseqsuit);
489 theRejectEdges.Append(aseqreject);
490 }
491 }
492 else
493 theRejectEdges.Append(aEdge1);
494
495 return isDone;
496 }
497
498
499 //=======================================================================
500 //function : FixVertexPosition
501 //purpose :
502 //=======================================================================
503
FixVertexPosition(TopoDS_Shape & theshape,const Standard_Real theTolerance,const Handle (ShapeBuild_ReShape)& thecontext)504 Standard_Boolean ShapeFix::FixVertexPosition(TopoDS_Shape& theshape,
505 const Standard_Real theTolerance,
506 const Handle(ShapeBuild_ReShape)& thecontext)
507 {
508 TopTools_IndexedDataMapOfShapeListOfShape aMapVertEdges;
509 TopExp_Explorer aExp1(theshape,TopAbs_EDGE);
510 for( ; aExp1.More(); aExp1.Next()) {
511 TopoDS_Shape aVert1;
512 Standard_Integer nV =1;
513 TopoDS_Iterator aExp3(aExp1.Current());
514 for( ; aExp3.More(); aExp3.Next(),nV++) {
515 TopoDS_Shape aVert = aExp3.Value();
516 if(nV ==1)
517 aVert1 = aVert;
518 else if(aVert1.IsSame(aVert))
519 continue;
520 if(aMapVertEdges.Contains(aVert))
521 aMapVertEdges.ChangeFromKey(aVert).Append(aExp1.Current());
522 else {
523 TopTools_ListOfShape alEdges;
524 alEdges.Append(aExp1.Current());
525 aMapVertEdges.Add(aVert,alEdges);
526 }
527 }
528 }
529 Standard_Boolean isDone = Standard_False;
530 Standard_Integer i=1;
531 for( ; i <= aMapVertEdges.Extent(); i++) {
532 TopoDS_Vertex aVert = TopoDS::Vertex(aMapVertEdges.FindKey(i));
533 Standard_Real aTolVert = BRep_Tool::Tolerance(aVert);
534 if(aTolVert <= theTolerance)
535 continue;
536
537 BRep_Builder aB1;
538 aB1.UpdateVertex(aVert,theTolerance);
539 gp_Pnt aPvert = BRep_Tool::Pnt(aVert);
540 gp_XYZ acenter(aPvert.XYZ()), acenterreject(aPvert.XYZ());
541
542 TopTools_SequenceOfShape aSuitEdges;
543 TopTools_SequenceOfShape aRejectEdges;
544 TopTools_ListOfShape aledges;
545 aledges= aMapVertEdges.FindFromIndex(i);
546 if(aledges.Extent() ==1)
547 continue;
548 //if tolerance of vertex is more than specified tolerance
549 // check distance between curves and vertex
550
551 if(!getNearestEdges(aledges,aVert,aSuitEdges,aRejectEdges,theTolerance,acenter,acenterreject))
552 continue;
553
554 //update vertex by nearest point
555 Standard_Boolean isAdd = Standard_False;
556 Standard_Integer k =1;
557 for( ; k <= aSuitEdges.Length(); k++) {
558
559 TopoDS_Edge aEdgeOld = TopoDS::Edge(aSuitEdges.Value(k));
560 TopoDS_Vertex aVert1,aVert2;
561 TopExp::Vertices(aEdgeOld, aVert1,aVert2 );
562
563 Standard_Boolean isFirst = (aVert1.IsSame(aVert));
564 Standard_Boolean isLast = (aVert2.IsSame(aVert));
565 if(!isFirst && !isLast)
566 continue;
567 Standard_Real aFirst,aLast;
568 Handle(Geom_Curve) aCurve;
569 TopoDS_Edge aEdge = TopoDS::Edge(thecontext->Apply(aEdgeOld));
570
571 TopoDS_Vertex aVert1n,aVert2n;
572 TopExp::Vertices(aEdge, aVert1n,aVert2n );
573 aCurve = BRep_Tool::Curve(aEdge,aFirst,aLast);
574 if( !aCurve.IsNull()) {
575 gp_Pnt p1 = aCurve->Value(aFirst);
576 gp_Pnt p2 = aCurve->Value(aLast);
577
578 //if distance between ends of curve more than specified tolerance
579 //but vertices are the same that one of the vertex will be replaced.
580
581 Standard_Boolean isReplace = (aVert1n.IsSame(aVert2n) && p1.Distance(p2) >theTolerance);
582
583 //Standard_Real dd1 = (acenter - p1.XYZ()).Modulus();
584 //Standard_Real dd2 = (acenter - p2.XYZ()).Modulus();
585 if(isFirst) {
586 if( k>2) {
587 acenter += p1.XYZ();
588 acenter /= 2.0;
589 }
590 if(isReplace) {
591 TopoDS_Edge enew;
592 if(p1.Distance(acenter) < p2.Distance(acenter))
593 enew = ReplaceVertex(aEdge,p2,Standard_False);
594 else
595 enew = ReplaceVertex(aEdge,p1,Standard_True);
596 thecontext->Replace(aEdge,enew);
597 isDone = Standard_True;
598 }
599 }
600 else {
601 if( k>2) {
602 acenter += p2.XYZ();
603 acenter /= 2.0;
604 }
605 if(isReplace) {
606 TopoDS_Edge enew;
607 if(p1.Distance(acenter) < p2.Distance(acenter))
608 enew = ReplaceVertex(aEdge,p2,Standard_False);
609 else
610 enew = ReplaceVertex(aEdge,p1,Standard_True);
611 thecontext->Replace(aEdge,enew);
612 isDone = Standard_True;
613 }
614 }
615
616
617
618 isAdd = Standard_True;
619
620 }
621 }
622
623
624 if(isAdd && aPvert.Distance(acenter) > theTolerance)
625 {
626
627 BRep_Builder aB;
628
629 // aB.UpdateVertex(aVert,Precision::Confusion());
630 //else {
631 isDone = Standard_True;
632 TopoDS_Vertex aNewVertex;
633 aB.MakeVertex(aNewVertex,acenter,Precision::Confusion());
634 aNewVertex.Orientation(aVert.Orientation());
635 thecontext->Replace(aVert,aNewVertex);
636
637 }
638
639 for( k =1; k <= aRejectEdges.Length(); k++) {
640 TopoDS_Edge aEdgeOld = TopoDS::Edge( aRejectEdges.Value(k));
641 TopoDS_Vertex aVert1,aVert2;
642 TopExp::Vertices(aEdgeOld, aVert1,aVert2 );
643
644 Standard_Boolean isFirst = (aVert1.IsSame(aVert));
645 Standard_Boolean isLast = (aVert2.IsSame(aVert));
646 if(!isFirst && !isLast)
647 continue;
648 Standard_Boolean isSame = aVert1.IsSame(aVert2);
649 Handle(Geom_Curve) aCurve;
650 TopoDS_Edge aEdge = TopoDS::Edge(thecontext->Apply(aEdgeOld));
651
652 TopoDS_Vertex aVert1n,aVert2n;
653 TopExp::Vertices(aEdge, aVert1n,aVert2n );
654
655 Standard_Real aFirst,aLast;
656 aCurve = BRep_Tool::Curve(aEdge,aFirst,aLast);
657 if( !aCurve.IsNull()) {
658 gp_Pnt p1 = aCurve->Value(aFirst);
659 gp_Pnt p2 = aCurve->Value(aLast);
660 TopoDS_Edge enew;
661 if(isFirst) {
662 enew = ReplaceVertex(aEdge,p1,Standard_True);
663 if(isSame)
664 enew = ReplaceVertex(enew,p2,Standard_False);
665 }
666 else {
667 enew = ReplaceVertex(aEdge,p2,Standard_False);
668 if(isSame)
669 enew = ReplaceVertex(enew ,p1,Standard_True);
670 }
671
672 thecontext->Replace(aEdge,enew);
673 isDone = Standard_True;
674
675
676 }
677
678 }
679 }
680 if(isDone)
681 theshape = thecontext->Apply(theshape);
682 return isDone;
683 }
684
685
686 //=======================================================================
687 //function : LeastEdgeSize
688 //purpose :
689 //=======================================================================
690
LeastEdgeSize(TopoDS_Shape & theShape)691 Standard_Real ShapeFix::LeastEdgeSize(TopoDS_Shape& theShape)
692 {
693 Standard_Real aRes = RealLast();
694 for(TopExp_Explorer exp(theShape,TopAbs_EDGE); exp.More(); exp.Next()) {
695 TopoDS_Edge edge = TopoDS::Edge ( exp.Current() );
696 Standard_Real first,last;
697 Handle(Geom_Curve) c3d = BRep_Tool::Curve(edge, first, last);
698 if(!c3d.IsNull()) {
699 Bnd_Box bb;
700 bb.Add(c3d->Value(first));
701 bb.Add(c3d->Value(last));
702 bb.Add(c3d->Value((last+first)/2.));
703 Standard_Real x1,x2,y1,y2,z1,z2,size;
704 bb.Get(x1,y1,z1,x2,y2,z2);
705 size = (x2-x1)*(x2-x1) + (y2-y1)*(y2-y1) + (z2-z1)*(z2-z1);
706 if(size<aRes) aRes = size;
707 }
708 }
709 aRes = sqrt(aRes);
710 return aRes;
711 }
712