b311480e |
1 | // Created on: 1999-08-24 |
2 | // Created by: Sergei ZERTCHANINOV |
3 | // Copyright (c) 1999 Matra Datavision |
973c2be1 |
4 | // Copyright (c) 1999-2014 OPEN CASCADE SAS |
b311480e |
5 | // |
973c2be1 |
6 | // This file is part of Open CASCADE Technology software library. |
b311480e |
7 | // |
d5f74e42 |
8 | // This library is free software; you can redistribute it and/or modify it under |
9 | // the terms of the GNU Lesser General Public License version 2.1 as published |
973c2be1 |
10 | // by the Free Software Foundation, with special exception defined in the file |
11 | // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT |
12 | // distribution for complete text of the license and disclaimer of any warranty. |
b311480e |
13 | // |
973c2be1 |
14 | // Alternatively, this file may be used under the terms of Open CASCADE |
15 | // commercial license or contractual agreement. |
7fd59977 |
16 | |
7fd59977 |
17 | |
7fd59977 |
18 | #include <BRep_Builder.hxx> |
42cf5bc1 |
19 | #include <BRep_Tool.hxx> |
20 | #include <Geom2d_BSplineCurve.hxx> |
21 | #include <Geom2d_Curve.hxx> |
22 | #include <Geom_BSplineCurve.hxx> |
23 | #include <Geom_Curve.hxx> |
24 | #include <GeomAPI.hxx> |
25 | #include <GeomConvert_CompCurveToBSplineCurve.hxx> |
26 | #include <gp_Pln.hxx> |
27 | #include <gp_Pnt.hxx> |
28 | #include <Message_Msg.hxx> |
29 | #include <ShapeAnalysis_Edge.hxx> |
30 | #include <ShapeAnalysis_TransferParametersProj.hxx> |
31 | #include <ShapeBuild_Edge.hxx> |
32 | #include <ShapeBuild_ReShape.hxx> |
33 | #include <ShapeConstruct.hxx> |
34 | #include <ShapeConstruct_Curve.hxx> |
35 | #include <ShapeFix.hxx> |
36 | #include <ShapeFix_Edge.hxx> |
7fd59977 |
37 | #include <ShapeFix_Wire.hxx> |
42cf5bc1 |
38 | #include <ShapeFix_Wireframe.hxx> |
39 | #include <Standard_ErrorHandler.hxx> |
40 | #include <Standard_Failure.hxx> |
41 | #include <Standard_Type.hxx> |
7fd59977 |
42 | #include <TopExp_Explorer.hxx> |
43 | #include <TopoDS.hxx> |
42cf5bc1 |
44 | #include <TopoDS_Compound.hxx> |
7fd59977 |
45 | #include <TopoDS_Edge.hxx> |
42cf5bc1 |
46 | #include <TopoDS_Face.hxx> |
47 | #include <TopoDS_Iterator.hxx> |
48 | #include <TopoDS_Shape.hxx> |
7fd59977 |
49 | #include <TopoDS_Vertex.hxx> |
42cf5bc1 |
50 | #include <TopTools_DataMapIteratorOfDataMapOfShapeShape.hxx> |
51 | #include <TopTools_DataMapOfShapeInteger.hxx> |
52 | #include <TopTools_DataMapOfShapeListOfShape.hxx> |
53 | #include <TopTools_DataMapOfShapeShape.hxx> |
7fd59977 |
54 | #include <TopTools_ListIteratorOfListOfShape.hxx> |
7fd59977 |
55 | #include <TopTools_ListOfShape.hxx> |
56 | #include <TopTools_MapOfShape.hxx> |
7fd59977 |
57 | |
92efcf78 |
58 | IMPLEMENT_STANDARD_RTTIEXT(ShapeFix_Wireframe,ShapeFix_Root) |
59 | |
42cf5bc1 |
60 | //#include <Geom2dConvert_CompCurveToBSplineCurve.hxx> |
7fd59977 |
61 | //======================================================================= |
62 | //function : ShapeFix_Wireframe |
63 | //purpose : |
64 | //======================================================================= |
7fd59977 |
65 | ShapeFix_Wireframe::ShapeFix_Wireframe() |
66 | { |
67 | ClearStatuses(); |
68 | myModeDrop = Standard_False; |
69 | myLimitAngle = -1; |
70 | } |
71 | |
72 | //======================================================================= |
73 | //function : ShapeFix_Wireframe |
74 | //purpose : |
75 | //======================================================================= |
76 | |
77 | ShapeFix_Wireframe::ShapeFix_Wireframe(const TopoDS_Shape& shape) |
78 | { |
79 | ClearStatuses(); |
80 | myShape = shape; |
81 | myModeDrop = Standard_False; |
82 | myLimitAngle = -1; |
83 | } |
84 | |
85 | //======================================================================= |
86 | //function : ClearStatuses |
87 | //purpose : |
88 | //======================================================================= |
89 | |
90 | void ShapeFix_Wireframe::ClearStatuses() |
91 | { |
92 | Standard_Integer emptyStatus = ShapeExtend::EncodeStatus( ShapeExtend_OK ); |
93 | |
94 | myStatusWireGaps = emptyStatus; |
95 | myStatusSmallEdges = emptyStatus; |
96 | } |
97 | |
98 | //======================================================================= |
99 | //function : Load |
100 | //purpose : |
101 | //======================================================================= |
102 | |
103 | void ShapeFix_Wireframe::Load(const TopoDS_Shape& shape) |
104 | { |
105 | ClearStatuses(); |
106 | myShape = shape; |
107 | } |
108 | |
109 | //======================================================================= |
110 | //function : FixWireGaps |
111 | //purpose : |
112 | //======================================================================= |
113 | |
114 | Standard_Boolean ShapeFix_Wireframe::FixWireGaps() |
115 | { |
116 | myStatusWireGaps = ShapeExtend::EncodeStatus( ShapeExtend_OK ); |
117 | if (myShape.IsNull()) return Standard_False; |
118 | |
119 | if (Context().IsNull()) SetContext(new ShapeBuild_ReShape); |
120 | else |
121 | { |
122 | TopoDS_Shape shape = myShape; |
123 | myShape.Nullify(); |
124 | myShape = Context()->Apply(shape); |
125 | } |
126 | |
127 | Standard_Real prec = (Precision()>0.)? Precision() : Precision::Confusion(); |
128 | TopTools_DataMapOfShapeShape cont; |
129 | if ( myShape.ShapeType() == TopAbs_COMPOUND ) |
130 | { |
131 | Standard_Boolean locModified = Standard_False; |
132 | TopoDS_Compound C; |
133 | BRep_Builder B; |
134 | B.MakeCompound ( C ); |
135 | TopoDS_Shape savShape = myShape; |
136 | for ( TopoDS_Iterator it(savShape); it.More(); it.Next() ) |
137 | { |
138 | TopoDS_Shape shape1 = it.Value(); |
139 | TopLoc_Location L = shape1.Location(),nullLoc; |
140 | shape1.Location ( nullLoc ); |
141 | TopoDS_Shape res; |
142 | if ( cont.IsBound ( shape1 ) ) |
143 | { |
144 | res = cont.Find ( shape1 ).Oriented ( shape1.Orientation() ); |
145 | } |
146 | else |
147 | { |
148 | myShape = shape1; |
149 | FixWireGaps(); |
150 | res = Shape(); |
151 | cont.Bind(myShape,res); |
152 | } |
153 | if ( ! res.IsSame ( shape1 ) ) locModified = Standard_True; |
154 | res.Location ( L ); |
155 | B.Add ( C, res ); |
156 | |
157 | } |
158 | if (locModified ) |
159 | { |
160 | C.Orientation(savShape.Orientation()); |
161 | Context()->Replace(savShape,C); |
162 | } |
163 | myShape = Context()->Apply(savShape); |
164 | return StatusWireGaps(ShapeExtend_DONE); |
165 | } |
166 | Handle(ShapeFix_Wire) sfw = new ShapeFix_Wire; |
167 | sfw->SetContext(Context()); |
168 | sfw->SetPrecision(prec); |
169 | |
170 | TopoDS_Face face; |
171 | for (TopExp_Explorer anExpf1(myShape,TopAbs_FACE); anExpf1.More(); anExpf1.Next()) |
172 | { |
173 | //smh#8 |
174 | TopoDS_Shape tmpF = Context()->Apply(anExpf1.Current()); |
175 | face = TopoDS::Face(tmpF); |
176 | if (face.Orientation()==TopAbs_REVERSED) face.Orientation(TopAbs_FORWARD); |
177 | for (TopoDS_Iterator itw(face); itw.More(); itw.Next()) |
178 | { |
179 | if(itw.Value().ShapeType() != TopAbs_WIRE) |
180 | continue; |
181 | //smh#8 |
182 | TopoDS_Shape tmpW = Context()->Apply(itw.Value()); |
183 | sfw->Init(TopoDS::Wire(tmpW), face, prec); |
184 | sfw->FixReorder(); |
185 | sfw->FixGaps3d(); |
186 | if (sfw->StatusGaps3d(ShapeExtend_DONE)) |
187 | myStatusWireGaps |= ShapeExtend::EncodeStatus( ShapeExtend_DONE1 ); |
188 | if (sfw->StatusGaps3d(ShapeExtend_FAIL)) |
189 | myStatusWireGaps |= ShapeExtend::EncodeStatus( ShapeExtend_FAIL1 ); |
190 | sfw->FixGaps2d(); |
191 | if (sfw->StatusGaps2d(ShapeExtend_DONE)) |
192 | myStatusWireGaps |= ShapeExtend::EncodeStatus( ShapeExtend_DONE2 ); |
193 | if (sfw->StatusGaps2d(ShapeExtend_FAIL)) |
194 | myStatusWireGaps |= ShapeExtend::EncodeStatus( ShapeExtend_FAIL2 ); |
da2db6a7 |
195 | if (sfw->StatusGaps3d(ShapeExtend_DONE) || sfw->StatusGaps2d(ShapeExtend_DONE)) |
196 | SendWarning( itw.Value(), Message_Msg( "FixWireframe.FixFixWireGaps.MSG0" )); |
7fd59977 |
197 | } |
198 | } |
199 | |
200 | //============================================================ |
201 | //Author : enk |
202 | //Purpose: This block fixing a 3d wire which not lie on plane |
203 | // Part 1 |
204 | //============================================================ |
205 | for (TopExp_Explorer expw(myShape,TopAbs_WIRE,TopAbs_FACE); expw.More(); expw.Next()) |
206 | { |
207 | TopoDS_Shape tmpW = Context()->Apply(expw.Current()); |
208 | sfw->Load(TopoDS::Wire(tmpW)); |
209 | sfw->SetPrecision(prec); |
210 | sfw->FixReorder(); |
211 | sfw->FixGaps3d(); |
212 | if (sfw->StatusGaps3d(ShapeExtend_DONE)) |
213 | myStatusWireGaps |= ShapeExtend::EncodeStatus( ShapeExtend_DONE1 ); |
214 | if (sfw->StatusGaps3d(ShapeExtend_FAIL)) |
215 | myStatusWireGaps |= ShapeExtend::EncodeStatus( ShapeExtend_FAIL1 ); |
da2db6a7 |
216 | if (sfw->StatusGaps3d(ShapeExtend_DONE)) |
217 | SendWarning( expw.Current(), Message_Msg( "FixWireframe.FixFixWireGaps.MSG0" )); |
7fd59977 |
218 | } |
219 | //End Part1======================================================== |
220 | |
221 | if (StatusWireGaps(ShapeExtend_DONE)) |
222 | { |
223 | |
224 | myShape = Context()->Apply(myShape); |
225 | |
226 | ShapeFix::SameParameter(myShape,Standard_False); |
227 | |
228 | TopoDS_Wire wire; |
229 | Handle(ShapeFix_Edge) sfe = new ShapeFix_Edge; |
230 | for (TopExp_Explorer anExpf2(myShape,TopAbs_FACE); anExpf2.More(); anExpf2.Next()) |
231 | { |
232 | face = TopoDS::Face(anExpf2.Current()); |
233 | if (face.Orientation()==TopAbs_REVERSED) face.Orientation(TopAbs_FORWARD); |
234 | for (TopoDS_Iterator itw(face); itw.More(); itw.Next()) |
235 | { |
236 | if(itw.Value().ShapeType() != TopAbs_WIRE) |
237 | continue; |
238 | wire = TopoDS::Wire(itw.Value()); |
239 | sfw->Init(wire, face, prec); |
240 | sfw->FixReorder(); |
241 | sfw->FixSelfIntersection(); |
242 | for (TopoDS_Iterator ite(wire); ite.More(); ite.Next()) |
243 | sfe->FixVertexTolerance(TopoDS::Edge(ite.Value())); |
244 | } |
245 | } |
246 | |
247 | // enk Part 2 |
248 | for (TopExp_Explorer expw2(myShape,TopAbs_WIRE,TopAbs_FACE); expw2.More(); expw2.Next()) |
249 | { |
250 | wire = TopoDS::Wire(expw2.Current()); |
251 | sfw->Load(wire); |
252 | sfw->SetPrecision(prec); |
253 | sfw->FixReorder(); |
254 | sfw->FixSelfIntersection(); |
255 | for (TopoDS_Iterator ite(wire); ite.More(); ite.Next()) |
256 | sfe->FixVertexTolerance(TopoDS::Edge(ite.Value())); |
257 | |
258 | } |
259 | // End Part 2 |
260 | |
261 | return Standard_True; |
262 | } |
263 | |
264 | return Standard_False; |
265 | } |
266 | |
267 | //======================================================================= |
268 | //function : JoinEdges (static) |
269 | //purpose : used in FixSmallEdges |
270 | //======================================================================= |
271 | |
272 | static Standard_Boolean JoinEdges(const TopoDS_Edge& E1, |
273 | const TopoDS_Edge& E2, |
274 | TopoDS_Edge& E3, |
275 | const TopTools_ListOfShape& faces) |
276 | { |
277 | Standard_Boolean ReplaceFirst = Standard_True; |
278 | ShapeAnalysis_Edge sae; |
279 | Handle(Geom_Curve) c3d1,c3d2; |
280 | Handle(Geom2d_Curve) c2d1,c2d2; //TopTools |
281 | TopoDS_Edge newedge,newedge1; |
282 | E3 = newedge1; |
283 | TopoDS_Vertex V11 = sae.FirstVertex(E1); |
284 | TopoDS_Vertex V12 = sae.LastVertex(E1); |
285 | TopoDS_Vertex V21 = sae.FirstVertex(E2); |
286 | TopoDS_Vertex V22 = sae.LastVertex(E2); |
287 | |
288 | |
289 | Standard_Boolean isSame = (V11.IsSame(V12) || V22.IsSame(V21)); |
290 | BRep_Builder B; |
291 | B.MakeEdge(newedge); |
292 | Standard_Real cf1,cf2,cl1,cl2,first1,first2,last1,last2; |
293 | newedge.Orientation(TopAbs_FORWARD); |
294 | try |
295 | { |
296 | OCC_CATCH_SIGNALS |
297 | if(!sae.Curve3d(E1,c3d1,cf1,cl1,Standard_False )) return ReplaceFirst; |
298 | if(!sae.Curve3d(E2,c3d2,cf2,cl2,Standard_False )) return ReplaceFirst; |
299 | |
300 | |
301 | B.Add(newedge,V11.Oriented(TopAbs_FORWARD)); |
302 | B.Add(newedge,V22.Oriented(TopAbs_REVERSED)); |
303 | |
304 | Handle(Geom_Curve) CRes; |
305 | Standard_Boolean isRev1,isRev2; |
306 | // Standard_Real newf,newl; |
307 | if(!ShapeConstruct::JoinCurves(c3d1,c3d2,E1.Orientation(),E2.Orientation(),cf1, cl1,cf2, cl2,CRes,isRev1,isRev2)) |
308 | return ReplaceFirst; |
309 | // if(isRev1 || isRev2) |
310 | if(!isSame && (isRev1 || isRev2)) |
311 | return ReplaceFirst; |
312 | ReplaceFirst = (!isRev1); |
313 | |
314 | Standard_Real newf = cf1; |
315 | Standard_Real newl = cl1 + cl2 - cf2; |
316 | TopAbs_Orientation OrEdge1 = E1.Orientation(); |
317 | TopAbs_Orientation OrEdge2 = E2.Orientation(); |
318 | Standard_Boolean ismanifold =(OrEdge1 == TopAbs_FORWARD || OrEdge1 == TopAbs_REVERSED); |
319 | Standard_Boolean ismanifold2 = (OrEdge2 == TopAbs_FORWARD || OrEdge2 == TopAbs_REVERSED); |
320 | if(ismanifold != ismanifold2) |
321 | return ReplaceFirst; |
322 | |
323 | if(ismanifold) { |
324 | |
325 | OrEdge1 = ( (!isRev1 && E1.Orientation() == TopAbs_FORWARD) || |
326 | (isRev1 && E1.Orientation() == TopAbs_REVERSED) ? TopAbs_FORWARD :TopAbs_REVERSED); |
327 | OrEdge2 = ( (!isRev2 && E2.Orientation() == TopAbs_FORWARD) || |
328 | (isRev2 && E2.Orientation() == TopAbs_REVERSED) ? TopAbs_FORWARD :TopAbs_REVERSED); |
329 | } |
330 | B.UpdateEdge(newedge,CRes,Max(BRep_Tool::Tolerance(E1),BRep_Tool::Tolerance(E2))); |
331 | Standard_Real fp= CRes->FirstParameter(); |
332 | Standard_Real lp= CRes->LastParameter(); |
333 | if(fp > newf) newf = fp; |
334 | if(lp < newl) newl = lp; |
335 | B.Range(newedge,newf,newl); |
336 | |
337 | //merging pcurves |
338 | for(TopTools_ListIteratorOfListOfShape iter(faces); iter.More(); iter.Next()) |
339 | { |
340 | TopoDS_Face face = TopoDS::Face(iter.Value()); |
341 | if(!sae.PCurve ( E1, face, c2d1, first1, last1, Standard_False )) return ReplaceFirst; |
342 | if(!sae.PCurve ( E2, face, c2d2, first2, last2, Standard_False )) return ReplaceFirst; |
343 | |
344 | Handle(Geom2d_Curve) C2dRes; |
345 | Standard_Boolean isRev12,isRev22; |
346 | if(!ShapeConstruct::JoinCurves(c2d1,c2d2,OrEdge1,OrEdge2,first1, last1,first2, last2,C2dRes,isRev12,isRev22,isSame)) |
347 | return ReplaceFirst; |
348 | |
349 | if(ismanifold && (!isSame && (isRev12 || isRev22))) |
350 | return ReplaceFirst; |
351 | |
352 | if(isRev12) |
353 | ReplaceFirst = Standard_False; |
354 | Standard_Real fp2d = C2dRes->FirstParameter(); |
355 | Standard_Real lp2d = C2dRes->LastParameter(); |
356 | //B.UpdateEdge(newedge,C2dRes,face,0); |
357 | Standard_Real newf1 = first1; |
358 | Standard_Real newl1 = last1 + (last2 - first2); |
359 | if(fp2d > newf1) newf1 = fp2d; |
360 | if(lp2d < newl1) newl1 = lp2d; |
361 | |
362 | // dealing with seams: the same again |
363 | if(sae.IsSeam(E1,face) && sae.IsSeam(E2,face)) |
364 | { |
365 | Handle(Geom2d_Curve) c2d12,c2d22; |
366 | //smh#8 |
367 | TopoDS_Shape tmpE1 = E1.Reversed(), |
368 | tmpE2 = E2.Reversed(); |
369 | TopoDS_Edge E1t = TopoDS::Edge(tmpE1); |
370 | TopoDS_Edge E2t = TopoDS::Edge(tmpE2); |
371 | sae.PCurve ( E1t, face, c2d12, first1, last1, Standard_False ); |
372 | sae.PCurve ( E2t, face, c2d22, first2, last2, Standard_False ); |
373 | |
374 | Handle(Geom2d_Curve) C2dRes2; |
375 | if(!ShapeConstruct::JoinCurves(c2d12,c2d22,OrEdge1,OrEdge2,first1, last1,first2, last2,C2dRes2,isRev12,isRev22,isSame)) |
376 | return ReplaceFirst; |
377 | if(!isSame && (isRev1 || isRev2)) |
378 | return ReplaceFirst; |
379 | B.UpdateEdge(newedge,C2dRes,C2dRes2,face,0); |
380 | } |
381 | else if(sae.IsSeam(E1,face) || sae.IsSeam(E2,face)) return ReplaceFirst; |
382 | else if(!sae.IsSeam(E1,face) && !sae.IsSeam(E2,face)) |
383 | B.UpdateEdge(newedge,C2dRes,face,0); |
384 | B.Range(newedge,face,newf1,newl1); |
385 | if(!ismanifold) |
386 | newedge.Orientation(ReplaceFirst ? OrEdge1 :OrEdge2 ); |
387 | } |
388 | B.SameRange(newedge,Standard_False); |
389 | |
390 | E3 = newedge; |
391 | return ReplaceFirst; |
392 | } |
9775fa61 |
393 | catch ( Standard_Failure const& anException) { |
0797d9d3 |
394 | #ifdef OCCT_DEBUG |
7fd59977 |
395 | cout<<"Error: ShapeFix_Wireframe::FixSmallEdges: JoinEdges: Exception in GeomConvert_CompCurveToBSplineCurve: "; |
9775fa61 |
396 | anException.Print(cout); cout<<endl; |
7fd59977 |
397 | #endif |
9775fa61 |
398 | (void)anException; |
7fd59977 |
399 | return ReplaceFirst; |
400 | } |
7fd59977 |
401 | } |
402 | |
403 | //======================================================================= |
404 | //function : FixSmallEdges |
405 | //purpose : |
406 | //======================================================================= |
407 | |
408 | Standard_Boolean ShapeFix_Wireframe::FixSmallEdges() |
409 | { |
410 | myStatusSmallEdges = ShapeExtend::EncodeStatus( ShapeExtend_OK ); |
411 | if (myShape.IsNull()) return Standard_False; |
412 | |
413 | if (Context().IsNull()) SetContext(new ShapeBuild_ReShape); |
414 | else |
415 | { |
416 | TopoDS_Shape shape = myShape; |
417 | myShape.Nullify(); |
418 | myShape = Context()->Apply(shape); |
419 | } |
420 | TopTools_DataMapOfShapeShape cont; |
421 | if ( myShape.ShapeType() == TopAbs_COMPOUND ) |
422 | { |
423 | Standard_Boolean locModified = Standard_False; |
424 | TopoDS_Compound C; |
425 | BRep_Builder B; |
426 | B.MakeCompound ( C ); |
427 | TopoDS_Shape savShape = myShape; |
428 | for ( TopoDS_Iterator it(savShape); it.More(); it.Next() ) |
429 | { |
430 | TopoDS_Shape shape1 = it.Value(); |
431 | TopLoc_Location L = shape1.Location(),nullLoc; |
432 | shape1.Location ( nullLoc ); |
433 | TopoDS_Shape res; |
434 | if ( cont.IsBound ( shape1 ) ) |
435 | { |
c6037065 |
436 | res = cont.Find ( shape1 ).Oriented ( shape1.Orientation() ); |
7fd59977 |
437 | } |
438 | else |
439 | { |
c6037065 |
440 | myShape = shape1; |
441 | FixSmallEdges(); |
442 | res = Shape(); |
443 | cont.Bind(myShape,res); |
7fd59977 |
444 | } |
445 | if ( ! res.IsSame ( shape1 ) ) locModified = Standard_True; |
c6037065 |
446 | |
447 | //check if resulting shape if not empty |
448 | if( res.IsNull()) |
449 | continue; |
450 | |
7fd59977 |
451 | res.Location ( L ); |
452 | B.Add ( C, res ); |
453 | |
454 | } |
455 | if (locModified ) |
456 | { |
457 | C.Orientation(savShape.Orientation()); |
458 | Context()->Replace(savShape,C); |
459 | } |
460 | myShape = Context()->Apply(savShape); |
461 | return StatusSmallEdges( ShapeExtend_DONE ); |
462 | } |
463 | TopTools_MapOfShape theSmallEdges, theMultyEdges; |
464 | TopTools_DataMapOfShapeListOfShape theEdgeToFaces,theFaceWithSmall; |
465 | CheckSmallEdges ( theSmallEdges,theEdgeToFaces,theFaceWithSmall, theMultyEdges); |
466 | MergeSmallEdges ( theSmallEdges,theEdgeToFaces,theFaceWithSmall, theMultyEdges); |
467 | return StatusSmallEdges( ShapeExtend_DONE ); |
468 | } |
469 | |
470 | //======================================================================= |
471 | //function : CheckSmallEdges |
472 | //purpose : |
473 | //======================================================================= |
474 | #include <BRepBuilderAPI_MakeFace.hxx> |
475 | #include <TopExp.hxx> |
476 | #include <TopTools_IndexedDataMapOfShapeListOfShape.hxx> |
477 | Standard_Boolean ShapeFix_Wireframe::CheckSmallEdges(TopTools_MapOfShape& theSmallEdges, |
478 | TopTools_DataMapOfShapeListOfShape& theEdgeToFaces, |
479 | TopTools_DataMapOfShapeListOfShape& theFaceWithSmall, |
480 | TopTools_MapOfShape& theMultyEdges) |
481 | { |
482 | TopoDS_Face face; |
483 | TopoDS_Edge edge; |
484 | ShapeAnalysis_Wire SAW; |
485 | |
486 | for (TopExp_Explorer anExpf1(myShape,TopAbs_FACE); anExpf1.More(); anExpf1.Next()) |
487 | { |
488 | TopTools_ListOfShape theEdgeList; |
489 | TopoDS_Face facet = TopoDS::Face(anExpf1.Current()); |
490 | face = facet; |
491 | if (facet.Orientation()==TopAbs_REVERSED) face = TopoDS::Face(facet.Oriented(TopAbs_FORWARD)); |
492 | for (TopoDS_Iterator itw(face); itw.More(); itw.Next()) |
493 | { |
494 | if(itw.Value().ShapeType() != TopAbs_WIRE) |
495 | continue; |
496 | TopoDS_Wire aW = TopoDS::Wire(itw.Value()); |
497 | Handle(ShapeExtend_WireData) aswd = new ShapeExtend_WireData(aW,Standard_True,Standard_False); |
498 | SAW.Init(aswd,face,Precision()); |
499 | // pnd protection on seam edges |
500 | TopTools_DataMapOfShapeInteger EdgeMap; |
501 | Standard_Integer i; |
502 | for (i=1; i<=SAW.NbEdges(); i++) |
503 | { |
504 | edge = SAW.WireData()->Edge(i); |
505 | if (EdgeMap.IsBound(edge)) |
506 | EdgeMap.ChangeFind(edge)++; |
507 | else |
508 | EdgeMap.Bind(edge,1); |
509 | } |
510 | |
511 | for ( i=1; i<=SAW.NbEdges(); i++) |
512 | { |
513 | edge = SAW.WireData()->Edge(i); |
514 | if(EdgeMap.Find(edge)!=1) |
515 | { |
516 | if(!SAW.WireData()->IsSeam(i)) |
517 | theMultyEdges.Add(edge); |
518 | continue; |
519 | } |
520 | // Append current face to the list |
521 | if (theEdgeToFaces.IsBound(edge)) |
522 | { |
523 | theEdgeToFaces(edge).Append(facet); |
524 | } |
525 | else |
526 | { |
527 | TopTools_ListOfShape theFaceList; |
528 | theFaceList.Append(facet); |
529 | theEdgeToFaces.Bind(edge,theFaceList); |
530 | } |
531 | // Check if current edge is small |
532 | if (theSmallEdges.Contains(edge)) theEdgeList.Append(edge); |
533 | else if (SAW.CheckSmall(i,Precision())) |
534 | { |
535 | theSmallEdges.Add(edge); |
536 | theEdgeList.Append(edge); |
537 | } |
538 | } |
539 | } |
540 | // Add current face to the map if has small edges |
541 | if (theEdgeList.Extent()) theFaceWithSmall.Bind(facet,theEdgeList); |
542 | } |
543 | |
544 | //======================================================================== |
545 | // Author : enk |
546 | // Purpose: Analizing of shape for small edges , if edge don't lie on face |
547 | //======================================================================== |
548 | for (TopExp_Explorer expw1(myShape,TopAbs_WIRE,TopAbs_FACE); expw1.More(); expw1.Next()) |
549 | { |
550 | SAW.SetPrecision(Precision()); |
551 | TopTools_DataMapOfShapeInteger EdgeMap; |
552 | Standard_Integer i; |
553 | TopoDS_Wire theWire=TopoDS::Wire(expw1.Current()); |
554 | TopTools_ListOfShape theEdgeList; |
555 | SAW.Load(theWire); |
556 | if (!SAW.IsLoaded()) |
557 | { |
558 | return Standard_False; |
559 | } |
560 | for (i=1; i<=SAW.NbEdges(); i++) |
561 | { |
562 | edge = SAW.WireData()->Edge(i); |
563 | if (EdgeMap.IsBound(edge)) |
564 | EdgeMap.ChangeFind(edge)++; |
565 | else |
566 | EdgeMap.Bind(edge,1); |
567 | } |
568 | |
569 | for ( i=1; i<=SAW.NbEdges(); i++) |
570 | { |
571 | edge = SAW.WireData()->Edge(i); |
572 | if(EdgeMap.Find(edge)!=1) |
573 | { |
574 | if(!SAW.WireData()->IsSeam(i)) |
575 | theMultyEdges.Add(edge); |
576 | continue; |
577 | } |
578 | |
579 | // Check if current edge is small |
580 | if (theSmallEdges.Contains(edge)) theEdgeList.Append(edge); |
581 | else if (SAW.CheckSmall(i,Precision())) |
582 | { |
583 | theSmallEdges.Add(edge); |
584 | theEdgeList.Append(edge); |
585 | } |
586 | } |
587 | |
588 | } |
589 | return (!theSmallEdges.IsEmpty()); |
590 | |
591 | } |
592 | |
593 | //======================================================================= |
594 | //function : MergeSmallEdges |
595 | //purpose : |
596 | //======================================================================= |
597 | |
598 | Standard_Boolean ShapeFix_Wireframe::MergeSmallEdges(TopTools_MapOfShape& theSmallEdges, |
599 | TopTools_DataMapOfShapeListOfShape& theEdgeToFaces, |
600 | TopTools_DataMapOfShapeListOfShape& theFaceWithSmall, |
601 | TopTools_MapOfShape& theMultyEdges, |
602 | const Standard_Boolean theModeDrop, |
603 | const Standard_Real theLimitAngle) |
604 | { |
605 | Standard_Boolean aModLimitAngle = (theLimitAngle >-1.0 || myLimitAngle > -1.0); |
606 | Standard_Real aLimitAngle = Max(theLimitAngle,myLimitAngle); |
607 | |
608 | Standard_Boolean aModeDrop = theModeDrop || myModeDrop; |
609 | TopTools_DataMapOfShapeShape theNewVertices; |
610 | if (!theSmallEdges.IsEmpty()) |
611 | { |
612 | |
613 | Handle(ShapeFix_Wire) SFW = new ShapeFix_Wire; |
614 | SFW->SetContext(Context()); |
615 | ShapeAnalysis_Edge SAE; |
616 | TopoDS_Edge edge1, edge2, edge3; |
617 | // Iterate on map of faces with small edges |
618 | TopExp_Explorer anExpf2(myShape,TopAbs_FACE); |
619 | for (; anExpf2.More(); anExpf2.Next()) |
620 | { |
621 | if (theFaceWithSmall.IsBound(anExpf2.Current())) |
622 | { |
623 | if (theFaceWithSmall(anExpf2.Current()).Extent()) |
624 | { |
625 | //smh#8 |
626 | TopoDS_Shape tmpShape = Context()->Apply(anExpf2.Current()); |
627 | TopoDS_Face facet = TopoDS::Face(tmpShape); |
628 | if(!facet.IsSame(anExpf2.Current())) |
629 | { //gka |
630 | TopExp_Explorer aExpEdge(anExpf2.Current(),TopAbs_EDGE); |
631 | for( ; aExpEdge.More(); aExpEdge.Next()) |
632 | { |
633 | TopoDS_Shape newEdge; |
634 | Standard_Integer stat = Context()->Status(aExpEdge.Current(),newEdge,Standard_True); |
635 | if(stat > 0 ) |
636 | { |
637 | if(theSmallEdges.Contains(aExpEdge.Current())) |
638 | { |
639 | theSmallEdges.Remove(aExpEdge.Current()); |
640 | theSmallEdges.Add(newEdge); |
641 | } |
642 | if(theEdgeToFaces.IsBound(aExpEdge.Current())) |
643 | { |
644 | TopTools_ListOfShape aListFaces; |
645 | aListFaces = theEdgeToFaces.Find(aExpEdge.Current()); |
646 | theEdgeToFaces.UnBind(aExpEdge.Current()); |
647 | theEdgeToFaces.Bind(newEdge,aListFaces); |
648 | |
649 | } |
650 | } |
651 | } |
652 | } |
653 | TopoDS_Face face = facet; |
654 | //if (face.Orientation()==TopAbs_REVERSED) |
655 | // face = TopoDS::Face(facet.Oriented(TopAbs_FORWARD)); |
656 | for (TopoDS_Iterator itw(face); itw.More(); itw.Next()) |
657 | { |
658 | if(itw.Value().ShapeType() != TopAbs_WIRE) continue; |
659 | TopoDS_Wire aWire = TopoDS::Wire(itw.Value()); |
660 | if (face.Orientation()==TopAbs_REVERSED) |
661 | face = TopoDS::Face(facet.Oriented(TopAbs_FORWARD)); |
662 | Handle(ShapeExtend_WireData) aswd = new ShapeExtend_WireData(aWire,Standard_True,Standard_False); |
663 | //SFW->Load(aWire); |
664 | SFW->Load(aswd); |
665 | SFW->FixReorder(); |
666 | Standard_Integer prev, next, index = 1; |
667 | |
668 | while (index <= SFW->WireData()->NbEdges() && SFW->NbEdges()>1) |
669 | { |
670 | prev = (index==1)? SFW->WireData()->NbEdges() : index-1; |
671 | next = (index==SFW->WireData()->NbEdges())? 1 : index+1; |
672 | edge1 = SFW->WireData()->Edge(prev); |
673 | edge2 = SFW->WireData()->Edge(index); |
674 | edge3 = SFW->WireData()->Edge(next); |
675 | |
676 | //gka protection against joining seem edge |
677 | if(edge2.IsSame(edge1) || edge2.IsSame(edge3)) |
678 | { |
679 | //if(BRep_Tool::IsClosed(edge2,face)) { |
680 | index++; |
681 | continue; |
682 | } |
683 | |
684 | Standard_Boolean isSeam = SFW->WireData()->IsSeam(index); |
685 | Standard_Boolean isSeam1 = SFW->WireData()->IsSeam(prev); |
686 | Standard_Boolean isSeam2 = SFW->WireData()->IsSeam(next); |
687 | if (theSmallEdges.Contains(edge2)) |
688 | { |
689 | // Middle edge is small - choose a pair of edges to join |
690 | Standard_Boolean IsAnyJoin = (edge1.IsSame(edge3)); |
691 | Standard_Boolean take_next = IsAnyJoin; //Standard_False; |
692 | Standard_Boolean isLimAngle = Standard_False; |
693 | Handle(Geom_Curve) C1, C2, C3; |
694 | Standard_Real aux, last1, first2, last2, first3; |
695 | Standard_Real Ang1 = 0., Ang2 =0.; |
696 | if (SAE.Curve3d(edge1,C1,aux,last1) && |
697 | SAE.Curve3d(edge2,C2,first2,last2) && |
698 | SAE.Curve3d(edge3,C3,first3,aux)) |
699 | { |
700 | // Compare angles between edges |
701 | //Standard_Real Ang1, Ang2; |
702 | gp_Vec Vec1, Vec2; gp_Pnt P; |
703 | C1->D1(last1,P,Vec1); |
704 | C2->D1(first2,P,Vec2); |
705 | if ( edge1.Orientation() == TopAbs_REVERSED ) Vec1.Reverse(); |
706 | if ( edge2.Orientation() == TopAbs_REVERSED ) Vec2.Reverse(); |
08cd2f6b |
707 | Standard_Real tol2 = Precision::SquareConfusion(); |
7fd59977 |
708 | if ( Vec1.SquareMagnitude() < tol2 || |
c6541a0c |
709 | Vec2.SquareMagnitude() < tol2 ) Ang1 = M_PI/2.; |
7fd59977 |
710 | else Ang1 = Abs(Vec1.Angle(Vec2)); |
711 | C2->D1(last2,P,Vec1); |
712 | C3->D1(first3,P,Vec2); |
713 | if ( edge2.Orientation() == TopAbs_REVERSED ) Vec1.Reverse(); |
714 | if ( edge3.Orientation() == TopAbs_REVERSED ) Vec2.Reverse(); |
715 | if ( Vec1.SquareMagnitude() < tol2 || |
c6541a0c |
716 | Vec2.SquareMagnitude() < tol2 ) Ang2 = M_PI/2.; |
7fd59977 |
717 | else Ang2 = Abs(Vec1.Angle(Vec2)); |
718 | //isLimAngle = (theLimitAngle != -1 && Min(Ang1,Ang2) > theLimitAngle); |
719 | //take_next = (Ang2<Ang1); |
720 | //if (take_next) { edge1 = edge2; edge2 = edge3; } |
721 | } |
722 | //if(theLimitAngle != -1 && Ang1 > theLimitAngle && Ang2 >theLimitAngle) { |
723 | // index++; continue; |
724 | //} |
725 | |
726 | // Check if edges lay on the same faces |
727 | if(theMultyEdges.Contains(edge1) || theMultyEdges.Contains(edge2)) |
728 | { //?????? |
729 | index++; |
730 | continue; |
731 | } |
732 | TopTools_ListOfShape theList1,theList2,theList3; |
733 | if(theEdgeToFaces.IsBound(edge1)) |
734 | theList1 = theEdgeToFaces(edge1); |
735 | if(theEdgeToFaces.IsBound(edge2)) |
736 | theList2 = theEdgeToFaces(edge2); |
737 | if(theEdgeToFaces.IsBound(edge3)) |
738 | theList3 = theEdgeToFaces(edge3); |
739 | Standard_Boolean same_set = Standard_False; |
740 | |
741 | //gka protection against joining seem edges with other edges |
742 | Standard_Boolean same_set1 = (theList1.Extent()==theList2.Extent() && |
743 | ((!isSeam && !isSeam1)|| (isSeam && isSeam1))); //gka |
744 | Standard_Boolean same_set2 = (theList3.Extent()==theList2.Extent() && |
745 | ((!isSeam && !isSeam2)|| (isSeam && isSeam2))); |
746 | TopTools_MapOfShape theSetOfFaces; |
747 | for (TopTools_ListIteratorOfListOfShape itf1(theList2); |
748 | itf1.More(); itf1.Next()) |
749 | theSetOfFaces.Add(itf1.Value()); |
750 | if (same_set1) |
751 | { |
752 | // Add all faces of the first edge to the current set |
753 | for (TopTools_ListIteratorOfListOfShape itf2(theList1); |
754 | (itf2.More() && same_set1); itf2.Next()) |
755 | same_set1 = theSetOfFaces.Contains(itf2.Value()); |
756 | } |
757 | if (same_set2) |
758 | { |
759 | // Add all faces of the first edge to the current set |
760 | for (TopTools_ListIteratorOfListOfShape itf2(theList3); |
761 | (itf2.More() && same_set2); itf2.Next()) |
762 | same_set2 = theSetOfFaces.Contains(itf2.Value()); |
763 | } |
764 | if(same_set1 && same_set2) |
765 | { |
766 | same_set = Standard_True; |
767 | if(fabs(Ang2-Ang1) >Precision::Angular()) |
768 | take_next = (Ang2<Ang1); |
769 | if (take_next) |
770 | { |
771 | edge1 = edge2; edge2 = edge3; |
772 | } |
773 | isLimAngle = (aModLimitAngle && Min(Ang1,Ang2) > aLimitAngle); |
774 | } |
775 | else if(same_set1 && !same_set2) |
776 | { |
777 | isLimAngle = (aModLimitAngle && Ang1 > aLimitAngle); |
778 | same_set = Standard_True; |
779 | } |
780 | else if(!same_set1 && same_set2) |
781 | { |
782 | same_set = Standard_True; |
783 | isLimAngle = (aModLimitAngle && Ang2 > aLimitAngle); |
784 | edge1 = edge2; edge2 = edge3; |
785 | take_next = Standard_True; |
786 | } |
787 | if (same_set && !isLimAngle ) |
788 | { |
789 | // Merge current pair of edges |
790 | //gka protection against crossing seem on second face |
791 | Standard_Boolean isNeedJoin = Standard_True;//Standard_False; |
792 | for(TopTools_ListIteratorOfListOfShape aItF(theList2); aItF.More() && isNeedJoin; aItF.Next()) |
793 | { |
794 | if(aItF.Value().IsSame(anExpf2.Current())) continue; |
795 | TopoDS_Shape aF = Context()->Apply(aItF.Value()); |
796 | //aF = aF.Oriented(TopAbs_FORWARD); |
797 | for(TopoDS_Iterator aIw(aF); aIw.More(); aIw.Next()) |
798 | { |
799 | if(aIw.Value().ShapeType() != TopAbs_WIRE) continue; |
800 | TopoDS_Wire wt = TopoDS::Wire(aIw.Value()); |
801 | Handle(ShapeFix_Wire) SFW1 = new ShapeFix_Wire; |
802 | SFW1->Load(wt); |
803 | SFW1->FixReorder(); |
804 | Handle(ShapeExtend_WireData) atmpswd = SFW1->WireData(); |
805 | Standard_Integer ind1 = atmpswd->Index(edge1); |
806 | Standard_Integer ind2 = atmpswd->Index(edge2); |
807 | if(ind1 && ind2) |
808 | { |
809 | isNeedJoin = ((ind1 -ind2) ==1 || (ind2 == atmpswd->NbEdges() && ind1 ==1)); |
810 | break; |
811 | } |
812 | } |
813 | } |
814 | Standard_Boolean ReplaceFirst = Standard_True; |
815 | if(isNeedJoin) |
816 | { |
817 | |
818 | TopTools_ListOfShape aListF; |
819 | for(TopTools_ListIteratorOfListOfShape aItlF(theList2); aItlF.More(); aItlF.Next()) |
820 | { |
821 | TopoDS_Shape tmpF = Context()->Apply(aItlF.Value()); |
822 | aListF.Append(tmpF); |
823 | } |
824 | ReplaceFirst = JoinEdges(edge1,edge2,edge3,aListF); |
825 | } |
826 | else edge3 = TopoDS_Edge(); |
827 | if (edge3.IsNull()) |
828 | { |
829 | index++; |
830 | myStatusSmallEdges |= ShapeExtend::EncodeStatus( ShapeExtend_FAIL1 ); |
831 | } |
832 | else |
833 | { |
834 | // Record vertex replacements in the map |
835 | TopoDS_Vertex oldV1 = SAE.FirstVertex(edge3), |
836 | oldV2 = SAE.LastVertex(edge3); |
837 | if (!theNewVertices.IsBound(oldV1)) |
838 | //smh#8 |
839 | { |
840 | TopoDS_Shape emptyCopiedV1 = oldV1.EmptyCopied(); |
841 | theNewVertices.Bind(oldV1,TopoDS::Vertex(emptyCopiedV1)); |
842 | } |
843 | if (!oldV1.IsSame(oldV2)) |
844 | if (!theNewVertices.IsBound(oldV2)) |
845 | //smh#8 |
846 | { |
847 | TopoDS_Shape emptyCopiedV2 = oldV2.EmptyCopied(); |
848 | theNewVertices.Bind(oldV2,TopoDS::Vertex(emptyCopiedV2)); |
849 | } |
850 | |
851 | //To keep NM vertices belonging initial edges |
852 | TopoDS_Iterator aItv(edge1,Standard_False); |
853 | for( ; aItv.More(); aItv.Next()) { |
854 | if(aItv.Value().Orientation() == TopAbs_INTERNAL || |
855 | aItv.Value().Orientation() == TopAbs_EXTERNAL) { |
856 | TopoDS_Vertex aOldV = TopoDS::Vertex(aItv.Value()); |
857 | TopoDS_Vertex anewV = ShapeAnalysis_TransferParametersProj::CopyNMVertex(aOldV,edge3,edge1); |
858 | BRep_Builder aB; |
859 | aB.Add(edge3,anewV); |
860 | Context()->Replace(aOldV,anewV); |
861 | } |
862 | } |
863 | |
864 | for(aItv.Initialize(edge2,Standard_False) ; aItv.More(); aItv.Next()) { |
865 | if(aItv.Value().Orientation() == TopAbs_INTERNAL || |
866 | aItv.Value().Orientation() == TopAbs_EXTERNAL){ |
867 | BRep_Builder aB; |
868 | TopoDS_Vertex aOldV = TopoDS::Vertex(aItv.Value()); |
869 | TopoDS_Vertex anewV = ShapeAnalysis_TransferParametersProj::CopyNMVertex(aOldV,edge3,edge2); |
870 | aB.Add(edge3,anewV); |
871 | Context()->Replace(aOldV,anewV); |
872 | } |
873 | } |
874 | |
875 | // Check for small resulting edge |
876 | Standard_Boolean newsmall = Standard_False; |
877 | ShapeAnalysis_Wire SAW; |
878 | SAW.Init(SFW->WireData(),face,Precision()); |
879 | // Make changes in WireData and Context |
880 | if(ReplaceFirst) |
881 | { |
882 | Context()->Replace(edge1,edge3); |
883 | Context()->Remove(edge2); |
da2db6a7 |
884 | SendWarning( edge2, Message_Msg("FixWireframe.FixSmallEdges.MSG0")); |
7fd59977 |
885 | } |
886 | else |
887 | { |
888 | Context()->Replace(edge2,edge3); |
889 | Context()->Remove(edge1); |
da2db6a7 |
890 | SendWarning( edge1, Message_Msg("FixWireframe.FixSmallEdges.MSG0")); |
7fd59977 |
891 | } |
892 | if (take_next) |
893 | { |
894 | SFW->WireData()->Set(edge3,next); |
895 | newsmall = SAW.CheckSmall(next,Precision()); |
896 | } |
897 | else |
898 | { |
899 | SFW->WireData()->Set(edge3,prev); |
900 | newsmall = SAW.CheckSmall(prev,Precision()); |
901 | } |
902 | SFW->WireData()->Remove(index); |
903 | // Process changes in maps |
904 | TopTools_ListOfShape theList; |
905 | theList.Append(theList2); |
906 | theEdgeToFaces.UnBind(edge1); |
907 | theEdgeToFaces.UnBind(edge2); |
908 | theEdgeToFaces.Bind(edge3,theList); |
909 | if (theSmallEdges.Contains(edge1)) theSmallEdges.Remove(edge1); |
910 | if (theSmallEdges.Contains(edge2)) theSmallEdges.Remove(edge2); |
911 | if (newsmall) theSmallEdges.Add(edge3); |
912 | for (TopTools_ListIteratorOfListOfShape itlf(theList); |
913 | itlf.More(); itlf.Next()) |
914 | { |
915 | TopoDS_Shape curface = itlf.Value(); |
916 | if (theFaceWithSmall.IsBound(curface)) |
917 | { |
918 | TopTools_ListOfShape& theEdges = theFaceWithSmall(curface); |
919 | if (newsmall) theEdges.Append(edge3); |
920 | TopTools_ListIteratorOfListOfShape ite(theEdges); |
921 | while (ite.More()) |
922 | { |
923 | TopoDS_Shape iedge = ite.Value(); |
924 | if (iedge.IsSame(edge1) || iedge.IsSame(edge2)) |
925 | theEdges.Remove(ite); |
926 | else ite.Next(); |
927 | } |
928 | // Remove face without small edges from the map |
929 | if (!theEdges.Extent()) theFaceWithSmall.UnBind(curface); |
930 | } |
931 | } |
932 | myStatusSmallEdges |= ShapeExtend::EncodeStatus( ShapeExtend_DONE1 ); |
933 | } |
934 | } |
935 | else if(aModeDrop) |
936 | { //gka |
937 | Handle(ShapeExtend_WireData) tempWire = new ShapeExtend_WireData(); |
938 | ShapeAnalysis_Wire tempSaw; |
939 | tempWire->Add(SFW->Wire()); |
940 | TopoDS_Edge remedge; |
941 | if (take_next) |
942 | remedge = edge1; |
943 | else remedge = edge2; |
944 | tempWire->Remove (index ); |
945 | tempSaw.Load(tempWire); |
946 | Standard_Integer newindex = (index <= tempSaw.NbEdges() ? index : 1); |
947 | tempSaw.CheckConnected(newindex,Precision()); |
948 | if(!tempSaw.LastCheckStatus(ShapeExtend_FAIL)) |
949 | { |
950 | SFW->WireData()->Remove (index ); |
951 | TopoDS_Edge tmpedge1 = tempWire->Edge(newindex); |
952 | TopoDS_Edge tmpedge2 = tempWire->Edge(newindex == 1 ? tempSaw.NbEdges() : (newindex- 1)); |
953 | TopTools_ListOfShape aL1; |
954 | if(theEdgeToFaces.IsBound(tmpedge1)) |
955 | aL1 = theEdgeToFaces.Find(tmpedge1); |
956 | TopTools_ListOfShape aL2; |
957 | if(theEdgeToFaces.IsBound(tmpedge2)) |
958 | aL2= theEdgeToFaces.Find(tmpedge2); |
959 | SFW->FixConnected(newindex <= SFW->NbEdges() ? newindex : 1,Precision()); |
960 | SFW->FixDegenerated(newindex <= SFW->NbEdges() ? newindex : 1); |
961 | TopoDS_Shape aTmpShape = Context()->Apply(tmpedge1); //for porting |
962 | TopoDS_Edge anewedge1 = TopoDS::Edge(aTmpShape); |
963 | aTmpShape = Context()->Apply(tmpedge2); |
964 | TopoDS_Edge anewedge2 = TopoDS::Edge(aTmpShape); |
965 | Context()->Remove(remedge); |
da2db6a7 |
966 | SendWarning( remedge, Message_Msg("FixWireframe.FixSmallEdges.MSG0")); |
7fd59977 |
967 | if (theSmallEdges.Contains(remedge)) |
968 | theSmallEdges.Remove(remedge); |
969 | theEdgeToFaces.UnBind(remedge); |
970 | theEdgeToFaces.UnBind(tmpedge1); |
971 | theEdgeToFaces.UnBind(tmpedge2); |
972 | theEdgeToFaces.Bind(anewedge1,aL1); |
973 | theEdgeToFaces.Bind(anewedge2,aL2); |
974 | if (theSmallEdges.Contains(tmpedge1)) |
975 | { |
976 | theSmallEdges.Remove(tmpedge1); |
977 | theSmallEdges.Add(anewedge1); |
978 | for (TopTools_ListIteratorOfListOfShape itlf(aL1); |
979 | itlf.More(); itlf.Next()) |
980 | { |
981 | TopoDS_Shape curface = itlf.Value(); |
982 | TopTools_ListOfShape& theEdges = theFaceWithSmall(curface); |
983 | TopTools_ListIteratorOfListOfShape ite(theEdges); |
984 | while (ite.More()) |
985 | { |
986 | TopoDS_Shape iedge = ite.Value(); |
987 | if (iedge.IsSame(tmpedge1)) |
988 | { |
989 | theEdges.Remove(ite); |
990 | theEdges.Append(anewedge1); |
991 | } |
992 | else ite.Next(); |
993 | } |
994 | } |
995 | } |
996 | if (theSmallEdges.Contains(tmpedge2)) |
997 | { |
998 | theSmallEdges.Remove(tmpedge2); |
999 | theSmallEdges.Add(anewedge2); |
1000 | for (TopTools_ListIteratorOfListOfShape itlf(aL2); |
1001 | itlf.More(); itlf.Next()) |
1002 | { |
1003 | TopoDS_Shape curface = itlf.Value(); |
1004 | TopTools_ListOfShape& theEdges = theFaceWithSmall(curface); |
1005 | TopTools_ListIteratorOfListOfShape ite(theEdges); |
1006 | while (ite.More()) |
1007 | { |
1008 | TopoDS_Shape iedge = ite.Value(); |
1009 | if (iedge.IsSame(tmpedge2)) |
1010 | { |
1011 | theEdges.Remove(ite); |
1012 | theEdges.Append(anewedge2); |
1013 | } |
1014 | else ite.Next(); |
1015 | } |
1016 | } |
1017 | } |
1018 | myStatusSmallEdges |= ShapeExtend::EncodeStatus( ShapeExtend_DONE3 ); |
1019 | } |
1020 | else index++; |
1021 | } |
1022 | else |
1023 | { |
1024 | //gka protection aginst removing circles |
1025 | TopoDS_Edge ed = (take_next ? edge1 : edge2); |
1026 | ShapeAnalysis_Edge sae; |
1027 | Handle(Geom_Curve) c3d; |
1028 | Standard_Real f1,l1; |
1029 | if(sae.Curve3d(ed,c3d,f1,l1,Standard_False)) |
1030 | { |
1031 | gp_Pnt p1,p2,p3; |
1032 | c3d->D0(f1,p1); |
1033 | c3d->D0(l1,p2); |
1034 | c3d->D0((f1 +l1)*0.5,p3); |
1035 | |
1036 | if(p1.Distance(p3) > p1.Distance(p2)) |
1037 | { |
1038 | index++; |
1039 | continue; |
1040 | } |
1041 | } |
1042 | if (take_next && theList2.Extent()== 1) |
1043 | { //gka |
1044 | TopoDS_Vertex V1 = SAE.FirstVertex(edge1), |
1045 | V2 = SAE.LastVertex(edge1); |
1046 | if(V1.IsSame(V2)) |
1047 | { |
1048 | SFW->WireData()->Remove (index ); |
1049 | Context()->Remove(edge1); |
da2db6a7 |
1050 | SendWarning( edge1, Message_Msg("FixWireframe.FixSmallEdges.MSG0")); |
7fd59977 |
1051 | if (theSmallEdges.Contains(edge1)) theSmallEdges.Remove(edge1); |
1052 | theEdgeToFaces.UnBind(edge1); |
1053 | myStatusSmallEdges |= ShapeExtend::EncodeStatus( ShapeExtend_DONE2 ); |
1054 | } |
1055 | else index++; |
1056 | } |
1057 | else if( !take_next && theList2.Extent()== 1) |
1058 | { |
1059 | TopoDS_Vertex V1 = SAE.FirstVertex(edge2), |
1060 | V2 = SAE.LastVertex(edge2); |
1061 | if(V1.IsSame(V2)) |
1062 | { |
1063 | SFW->WireData()->Remove (index ); |
1064 | Context()->Remove(edge2); |
da2db6a7 |
1065 | SendWarning( edge2, Message_Msg("FixWireframe.FixSmallEdges.MSG0")); |
7fd59977 |
1066 | if (theSmallEdges.Contains(edge2)) theSmallEdges.Remove(edge2); |
1067 | theEdgeToFaces.UnBind(edge2); |
1068 | myStatusSmallEdges |= ShapeExtend::EncodeStatus( ShapeExtend_DONE2 ); |
1069 | } |
1070 | else index++; |
1071 | } |
1072 | else index++; |
1073 | } |
1074 | } |
1075 | else index++; |
1076 | } |
1077 | if (SFW->NbEdges() == 1 && aModeDrop) |
1078 | { |
1079 | edge1 = SFW->WireData()->Edge(1); |
1080 | if (theSmallEdges.Contains(edge1)) |
1081 | { |
1082 | SFW->WireData()->Remove(1); |
1083 | Context()->Remove(edge1); |
da2db6a7 |
1084 | SendWarning( edge1, Message_Msg("FixWireframe.FixSmallEdges.MSG0")); |
7fd59977 |
1085 | theSmallEdges.Remove(edge1); |
1086 | theEdgeToFaces.UnBind(edge1); |
1087 | Context()->Remove(aWire); |
da2db6a7 |
1088 | SendWarning( aWire, Message_Msg("FixWireframe.FixSmallEdges.MSG1")); |
7fd59977 |
1089 | myStatusSmallEdges |= ShapeExtend::EncodeStatus( ShapeExtend_DONE2 ); |
1090 | } |
1091 | } |
1092 | else |
1093 | { |
1094 | SFW->FixConnected(); |
1095 | Context()->Replace(aWire,SFW->Wire()); |
1096 | } |
1097 | } |
1098 | face.Orientation(facet.Orientation()); |
1099 | TopoDS_Shape anewShape = Context()->Apply(face); |
1100 | TopoDS_Iterator aIter(anewShape); |
da2db6a7 |
1101 | if(!aIter.More()) { |
7fd59977 |
1102 | Context()->Remove(anewShape); |
da2db6a7 |
1103 | SendWarning( face, Message_Msg("FixWireframe.FixSmallEdges.MSG2")); |
1104 | } |
7fd59977 |
1105 | } |
1106 | } |
1107 | } |
1108 | |
1109 | // enk block |
1110 | // Iterate on map of wires which not lie on faces |
1111 | for (TopExp_Explorer expw1( myShape, TopAbs_WIRE, TopAbs_FACE); expw1.More(); expw1.Next()) |
1112 | { |
1113 | TopoDS_Wire aWire = TopoDS::Wire(expw1.Current()); |
1114 | SFW->Load(aWire); |
1115 | SFW->FixReorder(); |
1116 | Standard_Integer prev, next, index = 1; |
1117 | while (index <= SFW->NbEdges() && SFW->NbEdges()>1) |
1118 | { |
1119 | prev = (index==1)? SFW->NbEdges() : index-1; |
1120 | next = (index==SFW->NbEdges())? 1 : index+1; |
1121 | edge1 = SFW->WireData()->Edge(prev); |
1122 | edge2 = SFW->WireData()->Edge(index); |
1123 | edge3 = SFW->WireData()->Edge(next); |
1124 | |
1125 | //gka protection against joining seem edge |
1126 | if(edge2.IsSame(edge1) || edge2.IsSame(edge3)) |
1127 | { |
1128 | //if(BRep_Tool::IsClosed(edge2,face)) { |
1129 | index++; |
1130 | continue; |
1131 | } |
1132 | |
1133 | Standard_Boolean isSeam = SFW->WireData()->IsSeam(index); |
1134 | Standard_Boolean isSeam1 = SFW->WireData()->IsSeam(prev); |
1135 | Standard_Boolean isSeam2 = SFW->WireData()->IsSeam(next); |
1136 | if (theSmallEdges.Contains(edge2)) |
1137 | { |
1138 | // Middle edge is small - choose a pair of edges to join |
1139 | Standard_Boolean IsAnyJoin = (edge1.IsSame(edge3)); |
1140 | Standard_Boolean take_next = IsAnyJoin; //Standard_False; |
1141 | Standard_Boolean isLimAngle = Standard_False; |
1142 | Handle(Geom_Curve) C1, C2, C3; |
1143 | Standard_Real aux, last1, first2, last2, first3; |
1144 | Standard_Real Ang1 = 0., Ang2 =0.; |
1145 | if (SAE.Curve3d(edge1,C1,aux,last1) && |
1146 | SAE.Curve3d(edge2,C2,first2,last2) && |
1147 | SAE.Curve3d(edge3,C3,first3,aux)) |
1148 | { |
1149 | // Compare angles between edges |
1150 | //Standard_Real Ang1, Ang2; |
1151 | gp_Vec Vec1, Vec2; gp_Pnt P; |
1152 | C1->D1(last1,P,Vec1); |
1153 | C2->D1(first2,P,Vec2); |
1154 | if ( edge1.Orientation() == TopAbs_REVERSED ) Vec1.Reverse(); |
1155 | if ( edge2.Orientation() == TopAbs_REVERSED ) Vec2.Reverse(); |
08cd2f6b |
1156 | Standard_Real tol2 = Precision::SquareConfusion(); |
7fd59977 |
1157 | if ( Vec1.SquareMagnitude() < tol2 || |
c6541a0c |
1158 | Vec2.SquareMagnitude() < tol2 ) Ang1 = M_PI/2.; |
7fd59977 |
1159 | else Ang1 = Abs(Vec1.Angle(Vec2)); |
1160 | C2->D1(last2,P,Vec1); |
1161 | C3->D1(first3,P,Vec2); |
1162 | if ( edge2.Orientation() == TopAbs_REVERSED ) Vec1.Reverse(); |
1163 | if ( edge3.Orientation() == TopAbs_REVERSED ) Vec2.Reverse(); |
1164 | if ( Vec1.SquareMagnitude() < tol2 || |
c6541a0c |
1165 | Vec2.SquareMagnitude() < tol2 ) Ang2 = M_PI/2.; |
7fd59977 |
1166 | else Ang2 = Abs(Vec1.Angle(Vec2)); |
1167 | //isLimAngle = (theLimitAngle != -1 && Min(Ang1,Ang2) > theLimitAngle); |
1168 | //take_next = (Ang2<Ang1); |
1169 | //if (take_next) { edge1 = edge2; edge2 = edge3; } |
1170 | } |
1171 | //if(theLimitAngle != -1 && Ang1 > theLimitAngle && Ang2 >theLimitAngle) { |
1172 | // index++; continue; |
1173 | //} |
1174 | |
1175 | // Check if edges lay on the same faces |
1176 | if(theMultyEdges.Contains(edge1) || theMultyEdges.Contains(edge2)) |
1177 | { //?????? |
1178 | index++; |
1179 | continue; |
1180 | } |
1181 | TopTools_ListOfShape theList1,theList2,theList3; |
1182 | if(theEdgeToFaces.IsBound(edge1)) |
1183 | theList1 = theEdgeToFaces(edge1); |
1184 | if(theEdgeToFaces.IsBound(edge2)) |
1185 | theList2 = theEdgeToFaces(edge2); |
1186 | if(theEdgeToFaces.IsBound(edge3)) |
1187 | theList3 = theEdgeToFaces(edge3); |
1188 | Standard_Boolean same_set = Standard_False; |
1189 | |
1190 | //gka protection against joining seem edges with other edges |
1191 | Standard_Boolean same_set1 = (theList1.Extent()==theList2.Extent() && |
1192 | ((!isSeam && !isSeam1)|| (isSeam && isSeam1))); //gka |
1193 | Standard_Boolean same_set2 = (theList3.Extent()==theList2.Extent() && |
1194 | ((!isSeam && !isSeam2)|| (isSeam && isSeam2))); |
1195 | TopTools_MapOfShape theSetOfFaces; |
1196 | for (TopTools_ListIteratorOfListOfShape itf1(theList2); |
1197 | itf1.More(); itf1.Next()) |
1198 | theSetOfFaces.Add(itf1.Value()); |
1199 | if (same_set1) |
1200 | { |
1201 | // Add all faces of the first edge to the current set |
1202 | for (TopTools_ListIteratorOfListOfShape itf2(theList1); |
1203 | (itf2.More() && same_set1); itf2.Next()) |
1204 | same_set1 = theSetOfFaces.Contains(itf2.Value()); |
1205 | } |
1206 | if (same_set2) |
1207 | { |
1208 | // Add all faces of the first edge to the current set |
1209 | for (TopTools_ListIteratorOfListOfShape itf2(theList3); |
1210 | (itf2.More() && same_set2); itf2.Next()) |
1211 | same_set2 = theSetOfFaces.Contains(itf2.Value()); |
1212 | } |
1213 | if(same_set1 && same_set2) |
1214 | { |
1215 | same_set = Standard_True; |
1216 | if(fabs(Ang2-Ang1) >Precision::Angular()) |
1217 | take_next = (Ang2<Ang1); |
1218 | if (take_next) |
1219 | { |
1220 | edge1 = edge2; edge2 = edge3; |
1221 | } |
1222 | isLimAngle = (aModLimitAngle && Min(Ang1,Ang2) > aLimitAngle); |
1223 | } |
1224 | else if(same_set1 && !same_set2) |
1225 | { |
1226 | isLimAngle = (aModLimitAngle && Ang1 > aLimitAngle); |
1227 | same_set = Standard_True; |
1228 | } |
1229 | else if(!same_set1 && same_set2) |
1230 | { |
1231 | same_set = Standard_True; |
1232 | isLimAngle = (aModLimitAngle && Ang2 > aLimitAngle); |
1233 | edge1 = edge2; edge2 = edge3; |
1234 | take_next = Standard_True; |
1235 | } |
1236 | if (same_set && !isLimAngle ) |
1237 | { |
1238 | // Merge current pair of edges |
1239 | //gka protection against crossing seem on second face |
1240 | Standard_Boolean isNeedJoin = Standard_True;//Standard_False; |
1241 | for(TopTools_ListIteratorOfListOfShape aItF(theList2); aItF.More() && isNeedJoin; aItF.Next()) |
1242 | { |
1243 | if(aItF.Value().IsSame(anExpf2.Current())) continue; |
1244 | TopoDS_Shape aF = Context()->Apply(aItF.Value()); |
1245 | //aF = aF.Oriented(TopAbs_FORWARD); |
1246 | for(TopoDS_Iterator aIw(aF); aIw.More(); aIw.Next()) |
1247 | { |
1248 | if(aIw.Value().ShapeType() != TopAbs_WIRE) continue; |
1249 | TopoDS_Wire wt = TopoDS::Wire(aIw.Value()); |
1250 | Handle(ShapeFix_Wire) SFW1 = new ShapeFix_Wire; |
1251 | SFW1->Load(wt); |
1252 | SFW1->FixReorder(); |
1253 | Handle(ShapeExtend_WireData) atmpswd = SFW1->WireData(); |
1254 | Standard_Integer ind1 = atmpswd->Index(edge1); |
1255 | Standard_Integer ind2 = atmpswd->Index(edge2); |
1256 | if(ind1 && ind2) |
1257 | { |
1258 | isNeedJoin = ((ind1 -ind2) ==1 || (ind2 == atmpswd->NbEdges() && ind1 ==1)); |
1259 | break; |
1260 | } |
1261 | } |
1262 | } |
1263 | Standard_Boolean ReplaceFirst = Standard_True; |
1264 | if(isNeedJoin) |
1265 | { |
1266 | |
1267 | TopTools_ListOfShape aListF; |
1268 | for(TopTools_ListIteratorOfListOfShape aItlF(theList2); aItlF.More(); aItlF.Next()) |
1269 | { |
1270 | TopoDS_Shape tmpF = Context()->Apply(aItlF.Value()); |
1271 | aListF.Append(tmpF); |
1272 | } |
1273 | ReplaceFirst = JoinEdges(edge1,edge2,edge3,aListF); |
1274 | } |
1275 | else edge3 = TopoDS_Edge(); |
1276 | if (edge3.IsNull()) |
1277 | { |
1278 | index++; |
1279 | myStatusSmallEdges |= ShapeExtend::EncodeStatus( ShapeExtend_FAIL1 ); |
1280 | } |
1281 | else |
1282 | { |
1283 | // Record vertex replacements in the map |
1284 | TopoDS_Vertex oldV1 = SAE.FirstVertex(edge3), |
1285 | oldV2 = SAE.LastVertex(edge3); |
1286 | if (!theNewVertices.IsBound(oldV1)) |
1287 | //smh#8 |
1288 | { |
1289 | TopoDS_Shape emptyCopiedV1 = oldV1.EmptyCopied(); |
1290 | theNewVertices.Bind(oldV1,TopoDS::Vertex(emptyCopiedV1)); |
1291 | } |
1292 | if (!oldV1.IsSame(oldV2)) |
1293 | if (!theNewVertices.IsBound(oldV2)) |
1294 | //smh#8 |
1295 | { |
1296 | TopoDS_Shape emptyCopiedV2 = oldV2.EmptyCopied(); |
1297 | theNewVertices.Bind(oldV2,TopoDS::Vertex(emptyCopiedV2)); |
1298 | } |
1299 | //To keep NM vertices belonging initial edges |
1300 | TopoDS_Iterator aItv(edge1,Standard_False); |
1301 | for( ; aItv.More(); aItv.Next()) { |
1302 | if(aItv.Value().Orientation() == TopAbs_INTERNAL || |
1303 | aItv.Value().Orientation() == TopAbs_EXTERNAL) { |
1304 | BRep_Builder aB; |
1305 | TopoDS_Vertex aOldV = TopoDS::Vertex(aItv.Value()); |
1306 | TopoDS_Vertex anewV = ShapeAnalysis_TransferParametersProj::CopyNMVertex(aOldV,edge3,edge1); |
1307 | aB.Add(edge3,anewV); |
1308 | Context()->Replace(aOldV,anewV); |
1309 | } |
1310 | } |
1311 | |
1312 | for(aItv.Initialize(edge2,Standard_False) ; aItv.More(); aItv.Next()) { |
1313 | if(aItv.Value().Orientation() == TopAbs_INTERNAL || |
1314 | aItv.Value().Orientation() == TopAbs_EXTERNAL){ |
1315 | BRep_Builder aB; |
1316 | TopoDS_Vertex aOldV = TopoDS::Vertex(aItv.Value()); |
1317 | TopoDS_Vertex anewV = ShapeAnalysis_TransferParametersProj::CopyNMVertex(aOldV,edge3,edge2); |
1318 | aB.Add(edge3,anewV); |
1319 | Context()->Replace(aOldV,anewV); |
1320 | } |
1321 | } |
1322 | // Check for small resulting edge |
1323 | Standard_Boolean newsmall = Standard_False; |
1324 | ShapeAnalysis_Wire SAW; |
1325 | SAW.Load(SFW->WireData()); |
1326 | SAW.SetPrecision(Precision()); |
1327 | // Make changes in WireData and Context |
1328 | if(ReplaceFirst) |
1329 | { |
1330 | Context()->Replace(edge1,edge3); |
1331 | Context()->Remove(edge2); |
da2db6a7 |
1332 | SendWarning( edge2, Message_Msg("FixWireframe.FixSmallEdges.MSG0")); |
7fd59977 |
1333 | } |
1334 | else |
1335 | { |
1336 | Context()->Replace(edge2,edge3); |
1337 | Context()->Remove(edge1); |
da2db6a7 |
1338 | SendWarning( edge1, Message_Msg("FixWireframe.FixSmallEdges.MSG0")); |
7fd59977 |
1339 | } |
1340 | if (take_next) |
1341 | { |
1342 | SFW->WireData()->Set(edge3,next); |
1343 | newsmall = SAW.CheckSmall(next,Precision()); |
1344 | } |
1345 | else |
1346 | { |
1347 | SFW->WireData()->Set(edge3,prev); |
1348 | newsmall = SAW.CheckSmall(prev,Precision()); |
1349 | } |
1350 | SFW->WireData()->Remove(index); |
1351 | // Process changes in maps |
1352 | TopTools_ListOfShape theList; |
1353 | theList.Append(theList2); |
1354 | theEdgeToFaces.UnBind(edge1); |
1355 | theEdgeToFaces.UnBind(edge2); |
1356 | theEdgeToFaces.Bind(edge3,theList); |
1357 | if (theSmallEdges.Contains(edge1)) theSmallEdges.Remove(edge1); |
1358 | if (theSmallEdges.Contains(edge2)) theSmallEdges.Remove(edge2); |
1359 | if (newsmall) theSmallEdges.Add(edge3); |
1360 | for (TopTools_ListIteratorOfListOfShape itlf(theList); |
1361 | itlf.More(); itlf.Next()) |
1362 | { |
1363 | TopoDS_Shape curface = itlf.Value(); |
1364 | if (theFaceWithSmall.IsBound(curface)) |
1365 | { |
1366 | TopTools_ListOfShape& theEdges = theFaceWithSmall(curface); |
1367 | if (newsmall) theEdges.Append(edge3); |
1368 | TopTools_ListIteratorOfListOfShape ite(theEdges); |
1369 | while (ite.More()) |
1370 | { |
1371 | TopoDS_Shape iedge = ite.Value(); |
1372 | if (iedge.IsSame(edge1) || iedge.IsSame(edge2)) |
1373 | theEdges.Remove(ite); |
1374 | else ite.Next(); |
1375 | } |
1376 | // Remove face without small edges from the map |
1377 | if (!theEdges.Extent()) theFaceWithSmall.UnBind(curface); |
1378 | } |
1379 | } |
1380 | myStatusSmallEdges |= ShapeExtend::EncodeStatus( ShapeExtend_DONE1 ); |
1381 | } |
1382 | } |
1383 | else if(aModeDrop) |
1384 | { //gka |
1385 | Handle(ShapeExtend_WireData) tempWire = new ShapeExtend_WireData(); |
1386 | ShapeAnalysis_Wire tempSaw; |
1387 | tempWire->Add(SFW->Wire()); |
1388 | TopoDS_Edge remedge; |
1389 | if (take_next) |
1390 | remedge = edge1; |
1391 | else remedge = edge2; |
1392 | tempWire->Remove (index ); |
1393 | tempSaw.Load(tempWire); |
1394 | Standard_Integer newindex = (index <= tempSaw.NbEdges() ? index : 1); |
1395 | tempSaw.CheckConnected(newindex,Precision()); |
1396 | if(!tempSaw.LastCheckStatus(ShapeExtend_FAIL)) |
1397 | { |
1398 | SFW->WireData()->Remove (index ); |
1399 | TopoDS_Edge tmpedge1 = tempWire->Edge(newindex); |
1400 | TopoDS_Edge tmpedge2 = tempWire->Edge(newindex == 1 ? tempSaw.NbEdges() : (newindex- 1)); |
1401 | TopTools_ListOfShape aL1; |
1402 | if(theEdgeToFaces.IsBound(tmpedge1)) |
1403 | aL1 = theEdgeToFaces.Find(tmpedge1); |
1404 | TopTools_ListOfShape aL2; |
1405 | if(theEdgeToFaces.IsBound(tmpedge2)) |
1406 | aL2= theEdgeToFaces.Find(tmpedge2); |
1407 | SFW->FixConnected(newindex <= SFW->NbEdges() ? newindex : 1,Precision()); |
1408 | SFW->FixDegenerated(newindex <= SFW->NbEdges() ? newindex : 1); |
1409 | TopoDS_Shape aTmpShape = Context()->Apply(tmpedge1); //for porting |
1410 | TopoDS_Edge anewedge1 = TopoDS::Edge(aTmpShape); |
1411 | aTmpShape = Context()->Apply(tmpedge2); |
1412 | TopoDS_Edge anewedge2 = TopoDS::Edge(aTmpShape); |
1413 | Context()->Remove(remedge); |
da2db6a7 |
1414 | SendWarning( remedge, Message_Msg("FixWireframe.FixSmallEdges.MSG0")); |
7fd59977 |
1415 | if (theSmallEdges.Contains(remedge)) |
1416 | theSmallEdges.Remove(remedge); |
1417 | theEdgeToFaces.UnBind(remedge); |
1418 | theEdgeToFaces.UnBind(tmpedge1); |
1419 | theEdgeToFaces.UnBind(tmpedge2); |
1420 | theEdgeToFaces.Bind(anewedge1,aL1); |
1421 | theEdgeToFaces.Bind(anewedge2,aL2); |
1422 | if (theSmallEdges.Contains(tmpedge1)) |
1423 | { |
1424 | theSmallEdges.Remove(tmpedge1); |
1425 | theSmallEdges.Add(anewedge1); |
1426 | for (TopTools_ListIteratorOfListOfShape itlf(aL1); |
1427 | itlf.More(); itlf.Next()) |
1428 | { |
1429 | TopoDS_Shape curface = itlf.Value(); |
1430 | TopTools_ListOfShape& theEdges = theFaceWithSmall(curface); |
1431 | TopTools_ListIteratorOfListOfShape ite(theEdges); |
1432 | while (ite.More()) |
1433 | { |
1434 | TopoDS_Shape iedge = ite.Value(); |
1435 | if (iedge.IsSame(tmpedge1)) |
1436 | { |
1437 | theEdges.Remove(ite); |
1438 | theEdges.Append(anewedge1); |
1439 | } |
1440 | else ite.Next(); |
1441 | } |
1442 | } |
1443 | } |
1444 | if (theSmallEdges.Contains(tmpedge2)) |
1445 | { |
1446 | theSmallEdges.Remove(tmpedge2); |
1447 | theSmallEdges.Add(anewedge2); |
1448 | for (TopTools_ListIteratorOfListOfShape itlf(aL2); |
1449 | itlf.More(); itlf.Next()) |
1450 | { |
1451 | TopoDS_Shape curface = itlf.Value(); |
1452 | TopTools_ListOfShape& theEdges = theFaceWithSmall(curface); |
1453 | TopTools_ListIteratorOfListOfShape ite(theEdges); |
1454 | while (ite.More()) |
1455 | { |
1456 | TopoDS_Shape iedge = ite.Value(); |
1457 | if (iedge.IsSame(tmpedge2)) |
1458 | { |
1459 | theEdges.Remove(ite); |
1460 | theEdges.Append(anewedge2); |
1461 | } |
1462 | else ite.Next(); |
1463 | } |
1464 | } |
1465 | } |
1466 | myStatusSmallEdges |= ShapeExtend::EncodeStatus( ShapeExtend_DONE3 ); |
1467 | } |
1468 | else index++; |
1469 | } |
1470 | else |
1471 | { |
1472 | //gka protection aginst removing circles |
1473 | TopoDS_Edge ed = (take_next ? edge1 : edge2); |
1474 | ShapeAnalysis_Edge sae; |
1475 | Handle(Geom_Curve) c3d; |
1476 | Standard_Real f1,l1; |
1477 | if(sae.Curve3d(ed,c3d,f1,l1,Standard_False)) |
1478 | { |
1479 | gp_Pnt p1,p2,p3; |
1480 | c3d->D0(f1,p1); |
1481 | c3d->D0(l1,p2); |
1482 | c3d->D0((f1 +l1)*0.5,p3); |
1483 | |
1484 | if(p1.Distance(p3) > p1.Distance(p2)) |
1485 | { |
1486 | index++; |
1487 | continue; |
1488 | } |
1489 | } |
1490 | if (take_next && theList2.Extent()== 1) |
1491 | { //gka |
1492 | TopoDS_Vertex V1 = SAE.FirstVertex(edge1), |
1493 | V2 = SAE.LastVertex(edge1); |
1494 | if(V1.IsSame(V2)) |
1495 | { |
1496 | SFW->WireData()->Remove (index ); |
1497 | Context()->Remove(edge1); |
da2db6a7 |
1498 | SendWarning( edge1, Message_Msg("FixWireframe.FixSmallEdges.MSG0")); |
7fd59977 |
1499 | if (theSmallEdges.Contains(edge1)) theSmallEdges.Remove(edge1); |
1500 | theEdgeToFaces.UnBind(edge1); |
1501 | myStatusSmallEdges |= ShapeExtend::EncodeStatus( ShapeExtend_DONE2 ); |
1502 | } |
1503 | else index++; |
1504 | } |
1505 | else if( !take_next && theList2.Extent()== 1) |
1506 | { |
1507 | TopoDS_Vertex V1 = SAE.FirstVertex(edge2), |
1508 | V2 = SAE.LastVertex(edge2); |
1509 | if(V1.IsSame(V2)) |
1510 | { |
1511 | SFW->WireData()->Remove (index ); |
1512 | Context()->Remove(edge2); |
da2db6a7 |
1513 | SendWarning( edge2, Message_Msg("FixWireframe.FixSmallEdges.MSG0")); |
7fd59977 |
1514 | if (theSmallEdges.Contains(edge2)) theSmallEdges.Remove(edge2); |
1515 | theEdgeToFaces.UnBind(edge2); |
1516 | myStatusSmallEdges |= ShapeExtend::EncodeStatus( ShapeExtend_DONE2 ); |
1517 | } |
1518 | else index++; |
1519 | } |
1520 | else index++; |
1521 | } |
1522 | } |
1523 | else index++; |
1524 | } |
1525 | if (SFW->NbEdges() == 1 && aModeDrop) |
1526 | { |
1527 | edge1 = SFW->WireData()->Edge(1); |
1528 | if (theSmallEdges.Contains(edge1)) |
1529 | { |
1530 | SFW->WireData()->Remove(1); |
1531 | Context()->Remove(edge1); |
da2db6a7 |
1532 | SendWarning( edge1, Message_Msg("FixWireframe.FixSmallEdges.MSG0")); |
7fd59977 |
1533 | theSmallEdges.Remove(edge1); |
1534 | theEdgeToFaces.UnBind(edge1); |
1535 | Context()->Remove(aWire); |
da2db6a7 |
1536 | SendWarning( aWire, Message_Msg("FixWireframe.FixSmallEdges.MSG1")); |
7fd59977 |
1537 | myStatusSmallEdges |= ShapeExtend::EncodeStatus( ShapeExtend_DONE2 ); |
1538 | } |
1539 | } |
1540 | else |
1541 | { |
1542 | SFW->FixConnected(); |
1543 | Context()->Replace(aWire,SFW->Wire()); |
1544 | } |
1545 | } |
1546 | // end enk block |
1547 | // Record vertex replacements in context |
1548 | for (TopTools_DataMapIteratorOfDataMapOfShapeShape itv(theNewVertices); |
1549 | itv.More(); itv.Next()) Context()->Replace(itv.Key(),itv.Value()); |
1550 | |
1551 | TopoDS_Shape shape = myShape; |
1552 | myShape.Nullify(); |
1553 | myShape = Context()->Apply(shape); |
1554 | |
1555 | ShapeFix::SameParameter(myShape,Standard_False); |
1556 | |
1557 | return StatusSmallEdges( ShapeExtend_DONE ); |
1558 | } |
1559 | |
1560 | return Standard_False; |
1561 | } |