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 |
63 | IMPLEMENT_STANDARD_RTTIEXT(ShapeFix_FixSmallFace,ShapeFix_Root) |
64 | |
42cf5bc1 |
65 | //#include <GeomLProp_SLProps.hxx> |
66 | //#include <TColStd_Array2OfReal.hxx> |
67 | //#include <TColStd_Array1OfReal.hxx> |
7fd59977 |
68 | ShapeFix_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 | |
766 | Standard_Boolean ShapeFix_FixSmallFace::FixPinFace (TopoDS_Face& /*F*/) |
767 | { |
768 | return Standard_True; |
769 | } |