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