0030895: Coding Rules - specify std namespace explicitly for std::cout and streams
[occt.git] / src / ShapeFix / ShapeFix_FixSmallFace.cxx
CommitLineData
973c2be1 1// Copyright (c) 1999-2014 OPEN CASCADE SAS
b311480e 2//
973c2be1 3// This file is part of Open CASCADE Technology software library.
b311480e 4//
d5f74e42 5// This library is free software; you can redistribute it and/or modify it under
6// the terms of the GNU Lesser General Public License version 2.1 as published
973c2be1 7// by the Free Software Foundation, with special exception defined in the file
8// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
9// distribution for complete text of the license and disclaimer of any warranty.
b311480e 10//
973c2be1 11// Alternatively, this file may be used under the terms of Open CASCADE
12// commercial license or contractual agreement.
b311480e 13
7fd59977 14
42cf5bc1 15#include <BRep_Builder.hxx>
16#include <BRep_Tool.hxx>
17#include <BRepLib.hxx>
18#include <BRepTools.hxx>
19#include <ElCLib.hxx>
20#include <Geom2d_Curve.hxx>
21#include <Geom_BezierSurface.hxx>
22#include <Geom_BSplineSurface.hxx>
7fd59977 23#include <Geom_Curve.hxx>
42cf5bc1 24#include <Geom_ElementarySurface.hxx>
25#include <Geom_Line.hxx>
7fd59977 26#include <Geom_Surface.hxx>
42cf5bc1 27#include <Geom_TrimmedCurve.hxx>
28#include <GeomAdaptor_Curve.hxx>
7fd59977 29#include <GeomAdaptor_Surface.hxx>
42cf5bc1 30#include <GeomLib.hxx>
7fd59977 31#include <gp_Dir.hxx>
32#include <gp_Vec.hxx>
42cf5bc1 33#include <Message_Msg.hxx>
34#include <Poly_Polygon3D.hxx>
35#include <Precision.hxx>
36#include <ShapeAnalysis_Curve.hxx>
37#include <ShapeAnalysis_DataMapOfShapeListOfReal.hxx>
7fd59977 38#include <ShapeBuild_ReShape.hxx>
7fd59977 39#include <ShapeFix_Edge.hxx>
7fd59977 40#include <ShapeFix_Face.hxx>
42cf5bc1 41#include <ShapeFix_FixSmallFace.hxx>
7fd59977 42#include <ShapeFix_Shape.hxx>
42cf5bc1 43#include <ShapeFix_Wire.hxx>
44#include <Standard_Type.hxx>
45#include <TColgp_Array1OfPnt.hxx>
46#include <TColgp_Array2OfPnt.hxx>
47#include <TColgp_SequenceOfXYZ.hxx>
48#include <TopExp.hxx>
7fd59977 49#include <TopExp_Explorer.hxx>
42cf5bc1 50#include <TopoDS.hxx>
51#include <TopoDS_Builder.hxx>
7fd59977 52#include <TopoDS_Compound.hxx>
42cf5bc1 53#include <TopoDS_Edge.hxx>
54#include <TopoDS_Face.hxx>
7fd59977 55#include <TopoDS_Iterator.hxx>
42cf5bc1 56#include <TopoDS_Shape.hxx>
57#include <TopoDS_Shell.hxx>
58#include <TopoDS_Vertex.hxx>
59#include <TopoDS_Wire.hxx>
60#include <TopTools_Array1OfShape.hxx>
61#include <TopTools_DataMapOfShapeListOfShape.hxx>
b311480e 62
92efcf78 63IMPLEMENT_STANDARD_RTTIEXT(ShapeFix_FixSmallFace,ShapeFix_Root)
64
42cf5bc1 65//#include <GeomLProp_SLProps.hxx>
66//#include <TColStd_Array2OfReal.hxx>
67//#include <TColStd_Array1OfReal.hxx>
7fd59977 68ShapeFix_FixSmallFace::ShapeFix_FixSmallFace()
69{
70 myStatus = ShapeExtend::EncodeStatus ( ShapeExtend_OK );
71 SetPrecision(Precision::Confusion());
72
73}
74
75 void ShapeFix_FixSmallFace::Init(const TopoDS_Shape& S)
76{
77 myShape = S;
78 if ( Context().IsNull() )
79 SetContext ( new ShapeBuild_ReShape );
80 myResult = myShape;
81 Context()->Apply(myShape);
82}
83
84
85 void ShapeFix_FixSmallFace::Perform()
86{
87 FixSpotFace();
88 FixStripFace();
89}
90
91 TopoDS_Shape ShapeFix_FixSmallFace::FixSpotFace()
92{
93
94 // gp_Pnt spot;
95 // Standard_Real spotol;
96 Standard_Boolean done = Standard_False;
97 TopAbs_ShapeEnum st = myShape.ShapeType();
98 if (st == TopAbs_COMPOUND || st == TopAbs_COMPSOLID || st == TopAbs_SOLID || st == TopAbs_SHELL || st == TopAbs_FACE) {
99 for (TopExp_Explorer itf (myShape,TopAbs_FACE); itf.More(); itf.Next()) {
100//smh#8
101 TopoDS_Shape tmpFace = Context()->Apply(itf.Current());
102 TopoDS_Face F = TopoDS::Face (tmpFace);
103 if(F.IsNull()) continue;
104 if (myAnalyzer.CheckSpotFace (F,Precision()))
105 {
106 ReplaceVerticesInCaseOfSpot(F,Precision());
107 RemoveFacesInCaseOfSpot(F);
108 myStatus = ShapeExtend::EncodeStatus ( ShapeExtend_DONE1 );
109 done = Standard_True;
110 }
111 }
112 myShape = Context()->Apply(myShape);
113 Handle(ShapeFix_Wire) sfw = new ShapeFix_Wire;
114 if (done)
115 {
116 if (myShape.IsNull()) return myShape;
117 /*ShapeFix_Wire sfw;
118 sfw.SetContext(Context());
119 sfw.SetPrecision(Precision::Confusion());
120 if (myShape.IsNull()) return myShape;
121 for (TopExp_Explorer itfw (myShape,TopAbs_FACE); itfw.More(); itfw.Next()) {
122 for (TopExp_Explorer itw (myShape,TopAbs_WIRE); itw.More(); itw.Next()) {
123 TopoDS_Wire w = TopoDS::Wire(itw.Current());
124 sfw.Init(w, TopoDS::Face(itfw.Current()), Precision::Confusion());
125 sfw->FixNotchedEdgesMode() = 0;
126 if(sfw.Perform())
127 Context()->Replace(w, sfw.Wire());
128 }
129 }*/
130 myShape = FixShape();
131 }
132
133 //myShape = Context()->Apply(myShape);
134 myResult = myShape;
135 }
136 return myShape;
137}
138
139 Standard_Boolean ShapeFix_FixSmallFace::ReplaceVerticesInCaseOfSpot(TopoDS_Face& F,const Standard_Real /*tol*/) const
140{
141
142 TColgp_SequenceOfXYZ thePositions;
143 gp_XYZ thePosition;
144 BRep_Builder theBuilder;
145 Standard_Real theMaxDev;
146 Standard_Real theMaxTol = 0.0;
147 thePositions.Clear();
148 gp_Pnt thePoint;
149//smh#8
150 TopoDS_Shape tmpFace = Context()->Apply(F);
151 F = TopoDS::Face(tmpFace);
152 // gka Mar2000 Protection against faces without wires
153 // but they occur due to bugs in the algorithm itself, it needs to be fixed
154 Standard_Boolean isWir = Standard_False;
155 for(TopoDS_Iterator itw(F,Standard_False) ; itw.More();itw.Next()) {
156 if(itw.Value().ShapeType() != TopAbs_WIRE)
157 continue;
158 TopoDS_Wire w1 = TopoDS::Wire(itw.Value());
159 if (!w1.IsNull()) {isWir = Standard_True; break;}
160 }
161 if(!isWir) return Standard_True;
162 //Accumulating positions and maximal vertex tolerance
163 for (TopExp_Explorer iter_vertex(F,TopAbs_VERTEX); iter_vertex.More(); iter_vertex.Next()) {
164 TopoDS_Vertex V = TopoDS::Vertex (iter_vertex.Current());
165 thePoint = BRep_Tool::Pnt(V);
166 if (theMaxTol <= (BRep_Tool::Tolerance(V))) theMaxTol = BRep_Tool::Tolerance(V);
167 thePositions.Append(thePoint.XYZ());
168 }
169 //Calculate common vertex position
170 thePosition = gp_XYZ(0.,0.,0.);
171 Standard_Integer theNbPos = thePositions.Length();
172 Standard_Integer i; // svv Jan11 2000 : porting on DEC
173 for ( i = 1; i <= theNbPos; i++ ) thePosition += thePositions.Value(i);
174 if ( theNbPos > 1 ) thePosition /= theNbPos;
175
176 // Calculate maximal deviation
177 theMaxDev = 0.;
178 for ( i = 1; i <= theNbPos; i++ ) {
179 Standard_Real theDeviation = (thePosition-thePositions.Value(i)).Modulus();
180 if ( theDeviation > theMaxDev ) theMaxDev = theDeviation;
181 }
182 theMaxDev *= 1.00001;
183
184 //Cretate new vertex with mean point
185 TopoDS_Vertex theSharedVertex;
186 theBuilder.MakeVertex(theSharedVertex);
187 theBuilder.UpdateVertex( theSharedVertex, gp_Pnt(thePosition), theMaxDev+theMaxTol/2 );
188 //Use external tolerance
189// if (tol!=-1.0) theBuilder.UpdateVertex( theSharedVertex, tol);
190 //Replacing all vertices in the face by new one
191 TopoDS_Vertex theNewVertex;
192 for ( TopExp_Explorer iter_vert(F,TopAbs_VERTEX); iter_vert.More(); iter_vert.Next()) {
193 TopoDS_Vertex V = TopoDS::Vertex (iter_vert.Current());
194 if (V.Orientation()==TopAbs_FORWARD)
195//smh#8
196 {
197 TopoDS_Shape tmpVertexFwd = theSharedVertex.Oriented(TopAbs_FORWARD);
198 theNewVertex = TopoDS::Vertex(tmpVertexFwd);
199 }
200 else
201//smh#8
202 {
203 TopoDS_Shape tmpVertexRev = theSharedVertex.Oriented(TopAbs_REVERSED);
204 theNewVertex = TopoDS::Vertex(tmpVertexRev);
205 }
206 Context()->Replace(V, theNewVertex);
207 }
208 return Standard_True;
209}
210
211 Standard_Boolean ShapeFix_FixSmallFace::RemoveFacesInCaseOfSpot(const TopoDS_Face& F) const
212{
213 for ( TopExp_Explorer iter_vert(F,TopAbs_EDGE); iter_vert.More(); iter_vert.Next()) {
214 TopoDS_Edge Ed = TopoDS::Edge (iter_vert.Current());
215 Context()->Remove(Ed);
216 }
217 Context()->Remove(F);
da2db6a7 218 SendWarning( F, Message_Msg( "FixAdvFace.FixSpotFace.MSG0" ));
7fd59977 219 return Standard_True;
220
221
222}
223
224 TopoDS_Shape ShapeFix_FixSmallFace::FixStripFace(const Standard_Boolean wasdone)
225{
226 if(myShape.IsNull()) return myShape;
227 TopAbs_ShapeEnum st = myShape.ShapeType();
228 // BRep_Builder theBuilder;
229 Standard_Boolean done = wasdone;
230 if (st == TopAbs_COMPOUND || st == TopAbs_COMPSOLID ||st == TopAbs_SOLID || st == TopAbs_SHELL || st == TopAbs_FACE) {
231 for (TopExp_Explorer itf (myShape,TopAbs_FACE); itf.More(); itf.Next()) {
232 TopoDS_Face F = TopoDS::Face (itf.Current());
233//smh#8
234 TopoDS_Shape tmpFace = Context()->Apply(F);
235 F= TopoDS::Face(tmpFace);
236 if(F.IsNull()) continue;
237 // Standard_Real dmax = 1;
238 TopoDS_Edge E1,E2;
239 if (myAnalyzer.CheckStripFace (F, E1,E2,Precision()))
240 {
241 if(ReplaceInCaseOfStrip(F,E1,E2, Precision()))
242 RemoveFacesInCaseOfStrip(F);
243 myStatus = ShapeExtend::EncodeStatus ( ShapeExtend_DONE2 );
244 done = Standard_True;
245 }
246 }
247 myShape = Context()->Apply(myShape);
248 //Particular case of empty shell
249 if (!myShape.IsNull())
250 {
251 for (TopExp_Explorer exp_s (myShape,TopAbs_SHELL); exp_s.More(); exp_s.Next()) {
252 TopoDS_Shell Sh = TopoDS::Shell (exp_s.Current());
253 TopExp_Explorer ex_sh(Sh,TopAbs_FACE);
254 if (!ex_sh.More()) { Context()->Remove(Sh);
04232180 255// std::cout << "Empty shell was removed" << std::endl;
7fd59977 256 }
257 }
258 myShape = Context()->Apply(myShape);
259 //Fixing of missing pcurves on new edges, if thay were inserted
260 if (done)
261 {
262 if (myShape.IsNull()) return myShape;
263 TopoDS_Shape theResult;
264 myShape = FixShape();
265 //myShape = Context()->Apply(myShape);
266 myResult = myShape;
267 }
268
269 }
270 }
271 return myShape;
272
273}
274
275 Standard_Boolean ShapeFix_FixSmallFace::ReplaceInCaseOfStrip(TopoDS_Face& F,TopoDS_Edge& E1,TopoDS_Edge& E2, const Standard_Real tol) const
276{
277 if(E1.IsNull() || E2.IsNull()) return Standard_False;
278 TopoDS_Edge theSharedEdge;
279 TopoDS_Face F1,F2;
280//smh#8
281 TopoDS_Shape tmpFace = Context()->Apply(F);
282 F= TopoDS::Face(tmpFace);
283 for(TopExp_Explorer expf(myShape,TopAbs_FACE); expf.More(); expf.Next()) {
284//smh#8
285 TopoDS_Shape tmpShape = Context()->Apply(expf.Current());
286 TopoDS_Face tempF = TopoDS::Face (tmpShape);
287 if(tempF.IsNull() || tempF.IsSame(F)) continue;
288 for(TopExp_Explorer expe(tempF,TopAbs_EDGE); expe.More(); expe.Next()) {
289 TopoDS_Edge tempE = TopoDS::Edge (expe.Current());
290 if(tempE.IsSame(E1)) F1 = tempF;
291 if(tempE.IsSame(E2)) F2 = tempF;
292 if(!F1.IsNull()) break; // && !F2.IsNull()) break;
293 }
294 }
295
296 //Compute shared edge for this face
297 if(F1.IsNull() && F2.IsNull()) return Standard_True;
298 TopoDS_Edge E1tmp = E1;
299 TopoDS_Edge E2tmp = E2;
300 if(F1.IsNull()) {
301 E1tmp = E2;
302 E2tmp = E1;
303 F1 = F2;
304 }
305 theSharedEdge = ComputeSharedEdgeForStripFace(F, E1tmp, E2tmp, F1, tol);
306 //Replace two long edges by new one
307 if (theSharedEdge.IsNull()) return Standard_False;
308 if (E1.Orientation()==TopAbs_REVERSED) {
309 Context()->Replace(E1tmp, theSharedEdge.Oriented(TopAbs_REVERSED));
310 if(F.Orientation() == F1.Orientation())
311 Context()->Replace(E2tmp, theSharedEdge);
312 else
313 Context()->Replace(E2tmp, theSharedEdge.Oriented(TopAbs_REVERSED));
314 }
315 else
316 {
317 Context()->Replace(E1tmp, theSharedEdge);
318 if(F.Orientation() == F1.Orientation())
319 Context()->Replace(E2tmp, theSharedEdge.Oriented(TopAbs_REVERSED));
320 else
321 Context()->Replace(E2tmp, theSharedEdge);
322 }
323
324 //Remove short edges
325 for (TopExp_Explorer exp_e (F,TopAbs_EDGE); exp_e.More(); exp_e.Next()) {
326 TopoDS_Edge shortedge = TopoDS::Edge (exp_e.Current());
327 if (!shortedge.IsSame(E1tmp) && !shortedge.IsSame(E2tmp)) Context()->Remove(shortedge);
328 }
329
330 return Standard_True;
331}
332
333 Standard_Boolean ShapeFix_FixSmallFace::RemoveFacesInCaseOfStrip(const TopoDS_Face& F) const
334{
335 Context()->Remove(F);
da2db6a7 336 SendWarning( F, Message_Msg( "FixAdvFace.FixStripFace.MSG0" ));
7fd59977 337 return Standard_True;
338}
339
340 TopoDS_Edge ShapeFix_FixSmallFace::ComputeSharedEdgeForStripFace(const TopoDS_Face& /*F*/,const TopoDS_Edge& E1,const TopoDS_Edge& E2,const TopoDS_Face& F1,const Standard_Real tol) const
341{
342
343 BRep_Builder theBuilder;
344 //Compute deviation between two vertices and create new vertices
345 TopoDS_Edge theNewEdge;
346 TopoDS_Vertex V1,V2, V3, V4;
347 TopExp::Vertices (E1,V1,V2);
348 TopExp::Vertices (E2,V3,V4);
349 gp_Pnt p1, p2;
350 Standard_Real dev;
351 p1 = BRep_Tool::Pnt(V1);
352 p2 = BRep_Tool::Pnt(V3);
353 dev = p1.Distance(p2);
354 TopoDS_Vertex theFirstVer;
355 TopoDS_Vertex theSecondVer;
356 theBuilder.MakeVertex(theFirstVer);
357 theBuilder.MakeVertex(theSecondVer);
358 gp_XYZ thePosition;
359 TopoDS_Shape temp;
360
361 if ((dev<=BRep_Tool::Tolerance (V1)) || (dev<=BRep_Tool::Tolerance (V3)) || (dev<=tol)) {
362 if (V1.IsSame(V3))
363// #ifdef AIX CKY : applies to all platforms
364 theFirstVer = V1;
365// theFirstVer = TopoDS::Vertex(V1);
366
367 else {
368 dev = (dev/2)*1.0001;
369 thePosition = (p1.XYZ()+p2.XYZ())/2;
370 theBuilder.UpdateVertex(theFirstVer, gp_Pnt(thePosition), dev );
371 //if(Context()->Status(V1, temp) != 0) theFirstVer = TopoDS::Vertex (temp); //If this vertex already recorded in map
372 //else //take recorded vertex
373 // if(theRepVert->Status(V3, temp) != 0) theFirstVer = TopoDS::Vertex (temp);
374 if (V1.Orientation()==TopAbs_FORWARD) Context()->Replace(V1, theFirstVer.Oriented(TopAbs_FORWARD));
375 else Context()->Replace(V1, theFirstVer.Oriented(TopAbs_REVERSED));
376 if (V3.Orientation()==TopAbs_FORWARD) Context()->Replace(V3, theFirstVer.Oriented(TopAbs_FORWARD));
377 else Context()->Replace(V3, theFirstVer.Oriented(TopAbs_REVERSED));
378
379 }
380 if(V1.IsSame(V2) || V3.IsSame(V4))
381 theSecondVer = theFirstVer;
382 else {
383 if (!V2.IsSame(V4)) {
384 // #ifdef AIX CKY : applies to all platforms
385
386 p1 = BRep_Tool::Pnt(V2);
387 p2 = BRep_Tool::Pnt(V4);
388 dev = p1.Distance(p2);
389 thePosition = (p1.XYZ()+p2.XYZ())/2;
390 theBuilder.UpdateVertex(theSecondVer, gp_Pnt(thePosition), dev );
391 //if(theRepVert->Status(V2, temp) != 0) theSecondVer = TopoDS::Vertex (temp); //If this vertex already recorded in map
392 //else
393 // if(theRepVert->Status(V4, temp) != 0) theSecondVer = TopoDS::Vertex (temp);
394 }
395 else theSecondVer = V2;
396
397 }
398 if (!V2.IsSame(theSecondVer)) {
399 if (V2.Orientation()==TopAbs_FORWARD) Context()->Replace(V2, theSecondVer.Oriented(TopAbs_FORWARD));
400 else Context()->Replace(V2, theSecondVer.Oriented(TopAbs_REVERSED));
401 if (V4.Orientation()==TopAbs_FORWARD) Context()->Replace(V4, theSecondVer.Oriented(TopAbs_FORWARD));
402 else Context()->Replace(V4, theSecondVer.Oriented(TopAbs_REVERSED));
403 }
404 }
405 else {
406 p2 = BRep_Tool::Pnt(V4);
407 dev = p1.Distance(p2);
408 if ((dev<=BRep_Tool::Tolerance (V1)) || (dev<=BRep_Tool::Tolerance (V4)) || (dev<=tol)) {
409 if (V1.IsSame(V4))
410// #ifdef AIX CKY : applies to all platforms
411 theFirstVer = V1;
412// theFirstVer = TopoDS::Vertex(V1);
413
414 else {
415 dev = (dev/2)*1.0001;
416 thePosition = (p1.XYZ()+p2.XYZ())/2;
417 theBuilder.UpdateVertex(theFirstVer, gp_Pnt(thePosition), dev );
418 // if(theRepVert->Status(V1, temp) != 0) theFirstVer = TopoDS::Vertex (temp); //If this vertex already recorded in map
419 // else
420 // if(theRepVert->Status(V4, temp) != 0) theFirstVer = TopoDS::Vertex (temp);
421 if (V1.Orientation()==TopAbs_FORWARD) Context()->Replace(V1, theFirstVer.Oriented(TopAbs_FORWARD));
422 else Context()->Replace(V1, theFirstVer.Oriented(TopAbs_REVERSED));
423 if (V4.Orientation()==TopAbs_FORWARD) Context()->Replace(V4, theFirstVer.Oriented(TopAbs_FORWARD));
424 else Context()->Replace(V4, theFirstVer.Oriented(TopAbs_REVERSED));
425 }
426 if(V1.IsSame(V2) || V3.IsSame(V4))
427 theSecondVer = theFirstVer;
428 else {
429
430 if (!V2.IsSame(V3)) {
431 p1 = BRep_Tool::Pnt(V2);
432 p2 = BRep_Tool::Pnt(V3);
433 dev = p1.Distance(p2);
434 thePosition = (p1.XYZ()+p2.XYZ())/2;
435 theBuilder.UpdateVertex(theSecondVer, gp_Pnt(thePosition), dev );
436 }
437 else theSecondVer = V2;
438 }
439 // if(theRepVert->Status(V2, temp) != 0) theSecondVer = TopoDS::Vertex (temp); //If this vertex already recorded in map
440 // else
441 // if(theRepVert->Status(V3, temp) != 0) theSecondVer = TopoDS::Vertex (temp);
442 if (!V2.IsSame(theSecondVer)) {
443 if (V2.Orientation()==TopAbs_FORWARD) Context()->Replace(V2, theSecondVer.Oriented(TopAbs_FORWARD));
444 else Context()->Replace(V2, theSecondVer.Oriented(TopAbs_REVERSED));
445 if (V3.Orientation()==TopAbs_FORWARD) Context()->Replace(V3, theSecondVer.Oriented(TopAbs_FORWARD));
446 else Context()->Replace(V3, theSecondVer.Oriented(TopAbs_REVERSED));
447 }
448
449 }
450 else {
0797d9d3 451#ifdef OCCT_DEBUG
04232180 452 std::cout << "The face is not strip face" << std::endl;
7fd59977 453#endif
454 return theNewEdge;
455 }
456 }
457 if (theFirstVer.IsNull() || theSecondVer.IsNull()) return theNewEdge;
458 //Cretate new edge
459 theBuilder.MakeEdge(theNewEdge);
460 Standard_Real f, l, fp1, lp1/*, fp2, lp2*/;
461 TopLoc_Location loc;
462 Handle(Geom_Curve) the3dcurve;
463 the3dcurve = BRep_Tool::Curve(E1, f, l);
464 Handle(Geom2d_Curve) the2dcurve1, the2dcurve2, thenew1, thenew2;
465 if (!F1.IsNull())
466 {
467 the2dcurve1 = BRep_Tool::CurveOnSurface(E1, F1, fp1, lp1);
468 if(!the2dcurve1.IsNull() && fp1!=f && lp1!=l) GeomLib::SameRange(Precision::Confusion(), the2dcurve1, fp1, lp1, f, l, thenew1);
469 }
470
471 /* if (!F2.IsNull())
472 {
473 the2dcurve2 = BRep_Tool::CurveOnSurface(E2, F2, fp2, lp2);
474 if(!the2dcurve2.IsNull()) GeomLib::SameRange(Precision::Confusion(), the2dcurve2, fp2, lp2, f, l, thenew2);
475 }*/
476
477 Standard_Real maxdev;
478 if ((BRep_Tool::Tolerance(theFirstVer))<=(BRep_Tool::Tolerance(theSecondVer)))
479 maxdev = (BRep_Tool::Tolerance(theSecondVer));
480 else maxdev = (BRep_Tool::Tolerance(theFirstVer));
481 theBuilder.UpdateVertex(theFirstVer, maxdev);
482 theBuilder.UpdateVertex(theSecondVer, maxdev);
483 //Standard_Boolean IsFree = Standard_True;
484 theBuilder.SameParameter(theNewEdge, Standard_False);
485 the3dcurve = BRep_Tool::Curve(E1, f, l);
486 theBuilder.UpdateEdge(theNewEdge, the3dcurve, maxdev);
487 theBuilder.Range(theNewEdge, f, l);
488 if (!F1.IsNull() && !thenew1.IsNull())
489 {
490 theBuilder.UpdateEdge(theNewEdge, thenew1, F1, maxdev);
491 //IsFree = Standard_False;
492 }
493 /*if (!F2.IsNull() && !thenew2.IsNull())
494 {
495 theBuilder.UpdateEdge(theNewEdge, thenew2, F2, maxdev);
496 IsFree = Standard_False;
497 }*/
498 theBuilder.Add(theNewEdge, theFirstVer.Oriented(TopAbs_FORWARD));
499 theBuilder.Add(theNewEdge, theSecondVer.Oriented(TopAbs_REVERSED));
500 //Call fixsameparameter for computing distance between 3d and pcurves, if edge is not free
501// if (!IsFree)
502// {
503// ShapeFix_Edge sfe;
504// if (!F1.IsNull() && !thenew1.IsNull()) sfe.FixReversed2d(theNewEdge, F1);
505// if (!F2.IsNull() && !thenew2.IsNull()) sfe.FixReversed2d(theNewEdge, F2);
506// sfe.FixSameParameter(theNewEdge, maxdev);
507// }
508 return theNewEdge;
509
510
511}
512
513 TopoDS_Shape ShapeFix_FixSmallFace::FixSplitFace(const TopoDS_Shape& /*S*/)
514{
515 if (myShape.IsNull()) return myShape;
516 TopAbs_ShapeEnum st = myShape.ShapeType();
517 Standard_Boolean done = Standard_False;
518 TopoDS_Compound theSplittedFaces;
519 BRep_Builder theBuilder;
520 if (st == TopAbs_COMPOUND || st == TopAbs_COMPSOLID ||
521 st == TopAbs_SOLID || st == TopAbs_SHELL || st == TopAbs_FACE) {
522 for (TopExp_Explorer itf (myShape,TopAbs_FACE); itf.More(); itf.Next()) {
523 TopoDS_Face F = TopoDS::Face (itf.Current());
524 TopoDS_Compound CompSplittedFaces;
525 theBuilder.MakeCompound(CompSplittedFaces);
526 if(SplitOneFace(F, CompSplittedFaces)) {
527 done = Standard_True;
528 Context()->Replace(F, CompSplittedFaces);
529 }
530 }
531 }
532 if(done) myStatus = ShapeExtend::EncodeStatus ( ShapeExtend_DONE3 );
533 myShape = Context()->Apply(myShape);
534 myResult = myShape;
535 return myShape;
7fd59977 536}
537
538 Standard_Boolean ShapeFix_FixSmallFace::SplitOneFace(TopoDS_Face& F,TopoDS_Compound& theSplittedFaces)
539{
540 TopTools_DataMapOfShapeListOfShape MapEdges;
541 ShapeAnalysis_DataMapOfShapeListOfReal MapParam;
542 TopoDS_Compound theAllVert;
543 BRep_Builder theBuilder;
544 theBuilder.MakeCompound(theAllVert);
545//smh#8
546 TopoDS_Shape tmpShape = Context()->Apply(F);
547 F = TopoDS::Face(tmpShape);
548 if (myAnalyzer.CheckSplittingVertices(F,MapEdges,MapParam,theAllVert) != 0)
549 {
550 TopoDS_Wire tempwire;
551 //Take information about splitting vertices
552 if (theAllVert.IsNull()) return Standard_False;
553 //Standard_Integer i;
554 TopoDS_Vertex V;
555 TopExp_Explorer itc(theAllVert,TopAbs_VERTEX); V = TopoDS::Vertex (itc.Current());
556 if (V.IsNull()) return Standard_False;
557 gp_Pnt proj;
558 gp_Pnt vp = BRep_Tool::Pnt(V);
559 TopoDS_Vertex theNewVertex;
560 TopoDS_Edge E;
561 TopoDS_Edge theFirstEdge, theSecondEdge;
562
563 {
564 //If one vertex presents do splitting by two faces
565 ShapeAnalysis_Curve SAC;
566 for (TopExp_Explorer ite(F,TopAbs_EDGE); ite.More(); ite.Next()) {
567 E = TopoDS::Edge (ite.Current());
568 TopoDS_Vertex V1,V2;
569 TopExp::Vertices (E,V1,V2);
570 Standard_Real cf,cl;
571 Handle(Geom_Curve) C3D = BRep_Tool::Curve (E,cf,cl);
572 if (C3D.IsNull()) continue;
573 if (V.IsSame(V1) || V.IsSame(V2)) continue;
574 Standard_Real vt = BRep_Tool::Tolerance (V);
575 Standard_Real param;
576 Standard_Real dist = SAC.Project (C3D,vp,vt*10.,proj,param,cf,cl);
577 if (dist==0) continue; //Projection on same curve but on other edge ?
578 if ( dist <= vt )
579 {
580 theBuilder.MakeVertex(theNewVertex);
581 theBuilder.UpdateVertex(theNewVertex, proj, Precision::Confusion());
582 theBuilder.MakeEdge(theFirstEdge);
583 theBuilder.MakeEdge(theSecondEdge);
584 Standard_Real f, l;
585 Handle(Geom_Curve) the3dcurve = BRep_Tool::Curve(E, f, l);
586 theBuilder.UpdateEdge(theFirstEdge, the3dcurve,Precision::Confusion());
587 theBuilder.UpdateEdge(theSecondEdge, the3dcurve,Precision::Confusion());
588 if (V1.Orientation()==TopAbs_FORWARD)
589 {
590 theBuilder.Add(theFirstEdge, V1);
591 theBuilder.Add(theFirstEdge,theNewVertex.Oriented(TopAbs_REVERSED));
592 theBuilder.Add(theSecondEdge,theNewVertex.Oriented(TopAbs_FORWARD));
593 theBuilder.Add(theSecondEdge, V2);
594 }
595 else {
596 theBuilder.Add(theFirstEdge,V2);
597 theBuilder.Add(theFirstEdge,theNewVertex.Oriented(TopAbs_REVERSED));
598 theBuilder.Add(theSecondEdge,theNewVertex.Oriented(TopAbs_FORWARD));
599 theBuilder.Add(theSecondEdge, V1);
600 }
601 theBuilder.Range(theFirstEdge, cf, param);
602 theBuilder.Range(theSecondEdge, param, cl);
603 //Replace old edge by two new edges
604 TopoDS_Wire twoedges;
605 theBuilder.MakeWire(twoedges);
606 if (E.Orientation() == TopAbs_FORWARD)
607 {
608 theBuilder.Add(twoedges, theFirstEdge.Oriented(TopAbs_FORWARD));
609 theBuilder.Add(twoedges, theSecondEdge.Oriented(TopAbs_FORWARD));
610 }
611 else
612 {
613 theBuilder.Add(twoedges, theFirstEdge.Oriented(TopAbs_REVERSED));
614 theBuilder.Add(twoedges, theSecondEdge.Oriented(TopAbs_REVERSED));
615 }
616 Context()->Replace(E, twoedges);
617 break;
618 }
619 }
620 if (theNewVertex.IsNull()) return Standard_False;
621 //Create split edge
622 TopoDS_Edge theSplitEdge;
623 gp_Lin lin(vp, gp_Dir(gp_Vec( vp, proj)));
624 Standard_Real firstparam = ElCLib::Parameter(lin, vp);
625 Standard_Real lastparam = ElCLib::Parameter(lin, proj);
626 Handle(Geom_Line) L = new Geom_Line( vp, gp_Vec( vp, proj));
627 Handle(Geom_Curve) the3dc = L;
628 theBuilder.MakeEdge(theSplitEdge, the3dc, Precision::Confusion());
629 theBuilder.Add(theSplitEdge, V.Oriented(TopAbs_FORWARD));
630 theBuilder.Add(theSplitEdge, theNewVertex.Oriented(TopAbs_REVERSED));
631 theBuilder.Range(theSplitEdge, firstparam, lastparam);
632 //Add pcurve in new edge
633 Handle(ShapeFix_Edge) sfe = new ShapeFix_Edge;
634 sfe->FixAddPCurve(theSplitEdge, F, Standard_False);
635 //Reorder the wire
636 TopoDS_Wire wireonface;
637 //Inher loop is not support yet !!!
638 TopExp_Explorer itw(F,TopAbs_WIRE);
639 wireonface = TopoDS::Wire (itw.Current());
640 itw.Next();
641 if (itw.More()) return Standard_False; //if face contains more than one wire
642 Handle(ShapeFix_Wire) sfw = new ShapeFix_Wire;
643 sfw->Init(wireonface, F, Precision::Confusion());
644 sfw->FixReorder();
645 wireonface = sfw->Wire();
646
647 //Create two new wires
648 TopoDS_Wire w1, w2;
649 theBuilder.MakeWire(w1);
650 theBuilder.MakeWire(w2);
651 theBuilder.MakeWire(tempwire);
652 for (TopExp_Explorer itnew(wireonface, TopAbs_EDGE ); itnew.More(); itnew.Next())
653 {
654 TopoDS_Edge ce = TopoDS::Edge (itnew.Current());
655 if (ce.IsSame(E))
656 {
657 theBuilder.Remove(wireonface, ce);
658 theBuilder.Add(wireonface, theFirstEdge.Oriented(TopAbs_FORWARD));
659 theBuilder.Add(wireonface, theSecondEdge.Oriented(TopAbs_FORWARD));
660 }
661 }
662 sfw->Init(wireonface, F, Precision::Confusion());
663 sfw->FixReorder();
664 wireonface = sfw->Wire();
665
666 for (TopExp_Explorer itere(wireonface, TopAbs_EDGE); itere.More(); itere.Next())
667 {
668 TopoDS_Edge ce = TopoDS::Edge (itere.Current());
669 TopoDS_Vertex thecontrol;
670 if (ce.Orientation () == TopAbs_FORWARD) thecontrol = TopExp::LastVertex(ce);
671 else thecontrol = TopExp::FirstVertex(ce);
672 theBuilder.Add(w1, ce);
673 if (thecontrol.IsSame(V))
674 {
675 theBuilder.Add(w1, theSplitEdge.Oriented(TopAbs_FORWARD));
676 TopoDS_Wire wtemp = w1;
677 w1 = w2;
678 w2 = wtemp;
679 }
680 if (thecontrol.IsSame(theNewVertex))
681 {
682 theBuilder.Add(w1, theSplitEdge.Oriented(TopAbs_REVERSED));
683 TopoDS_Wire wtemp = w1;
684 w1 = w2;
685 w2 = wtemp;
686 }
687 }
688 if ( w1.IsNull()|| w2.IsNull() ) return Standard_False;
689 //Create two new faces and replace old one
690 TopoDS_Face F1;
691 TopoDS_Face F2;
692 theBuilder.MakeFace(F1, BRep_Tool::Surface(F), Precision::Confusion());
693 theBuilder.MakeFace(F2, BRep_Tool::Surface(F), Precision::Confusion());
694 theBuilder.Add(F1, w1);
695 theBuilder.Add(F2, w2);
696 TopoDS_Compound tf;
697 theBuilder.MakeCompound(tf);
698 theBuilder.Add(tf,F1);
699 theBuilder.Add(tf, F2);
700 //Call recursive spliteoneface() for each face
701 if(!SplitOneFace(F1, theSplittedFaces)) theBuilder.Add(theSplittedFaces, F1);
702 if(!SplitOneFace(F2, theSplittedFaces)) theBuilder.Add(theSplittedFaces, F2);
703 }
704 return Standard_True ;
705 }
706 return Standard_False ;
707}
708
7fd59977 709 TopoDS_Face ShapeFix_FixSmallFace::FixFace(const TopoDS_Face& F)
710{
711//smh#8
712 TopoDS_Shape emptyCopied = F.EmptyCopied();
713 TopoDS_Face theFixedFace = TopoDS::Face(emptyCopied);
714 // BRep_Builder theBuilder;
715
716 // Handle(ShapeFix_Wire) sfw = new ShapeFix_Wire;
717 // sfw->SetContext(Context());
718 // for (TopExp_Explorer exp_w (F,TopAbs_WIRE); exp_w.More(); exp_w.Next()) {
719 // TopoDS_Wire theCurWire = TopoDS::Wire (exp_w.Current());
720
721 // sfw->Init(theCurWire, F, Precision::Confusion());
722 // if(sfw->NbEdges() == 0) continue;
723 // sfw->FixNotchedEdgesMode() = 0;
724 // sfw->Perform();
725 // theCurWire = sfw->Wire();
726 // theBuilder.Add(theFixedFace, theCurWire);
727 // }
728 Handle(ShapeFix_Face) sff = new ShapeFix_Face;
729 sff->SetContext(Context());
730 sff->Init(F);
731 sff->Perform();
732 //sff->Init(theFixedFace);
733 //sff->FixOrientation();
734 theFixedFace = sff->Face();
735 return theFixedFace;
736}
737
738 TopoDS_Shape ShapeFix_FixSmallFace::FixShape()
739{
740 TopoDS_Shape FixSh;
741 if(myShape.IsNull()) return FixSh;
742 /*ShapeFix_Shape sfs;
743 sfs.SetContext(Context());
744
745 sfs.SetPrecision(Precision::Confusion());
746 sfs.Init(myShape);
747 sfs.Perform();
748 FixSh = sfs.Shape();*/
749 for(TopExp_Explorer expf(myShape,TopAbs_FACE) ; expf.More(); expf.Next()) {
750 TopoDS_Face F = TopoDS::Face(expf.Current());
751//smh#8
752 TopoDS_Shape tmpFace = Context()->Apply(F);
753 F= TopoDS::Face(tmpFace);
754 TopoDS_Face newF = FixFace(F);
755 Context()->Replace(F,newF);
756 }
757 FixSh = Context()->Apply(myShape);
758 return FixSh;
759
760}
761 TopoDS_Shape ShapeFix_FixSmallFace::Shape()
762{
763 return myShape;
764}
765
766Standard_Boolean ShapeFix_FixSmallFace::FixPinFace (TopoDS_Face& /*F*/)
767{
768 return Standard_True;
769}