1 // Created on: 1999-08-24
2 // Created by: Sergei ZERTCHANINOV
3 // Copyright (c) 1999 Matra Datavision
4 // Copyright (c) 1999-2014 OPEN CASCADE SAS
6 // This file is part of Open CASCADE Technology software library.
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
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.
14 // Alternatively, this file may be used under the terms of Open CASCADE
15 // commercial license or contractual agreement.
17 #include <ShapeFix_Wireframe.ixx>
19 #include <Standard_Failure.hxx>
20 #include <Standard_ErrorHandler.hxx>
22 //#include <Geom2dConvert_CompCurveToBSplineCurve.hxx>
23 #include <ShapeBuild_ReShape.hxx>
24 #include <TopTools_DataMapOfShapeShape.hxx>
25 #include <TopoDS_Compound.hxx>
26 #include <BRep_Builder.hxx>
27 #include <TopoDS_Iterator.hxx>
28 #include <ShapeFix_Wire.hxx>
29 #include <TopoDS_Face.hxx>
30 #include <TopExp_Explorer.hxx>
32 #include <ShapeFix.hxx>
33 #include <ShapeFix_Edge.hxx>
34 #include <ShapeConstruct_Curve.hxx>
35 #include <TopoDS_Edge.hxx>
36 #include <TopoDS_Vertex.hxx>
37 #include <ShapeAnalysis_Edge.hxx>
38 #include <Geom_Curve.hxx>
39 #include <Geom_BSplineCurve.hxx>
41 #include <GeomConvert_CompCurveToBSplineCurve.hxx>
42 #include <BRep_Tool.hxx>
43 #include <TopTools_ListIteratorOfListOfShape.hxx>
44 #include <Geom2d_Curve.hxx>
45 #include <Geom2d_BSplineCurve.hxx>
47 #include <GeomAPI.hxx>
48 #include <TopTools_ListOfShape.hxx>
49 #include <TopTools_MapOfShape.hxx>
50 #include <TopTools_DataMapOfShapeListOfShape.hxx>
51 #include <TopTools_DataMapOfShapeInteger.hxx>
52 #include <TopTools_DataMapIteratorOfDataMapOfShapeShape.hxx>
53 #include <ShapeConstruct.hxx>
54 #include <ShapeBuild_Edge.hxx>
55 #include <ShapeAnalysis_TransferParametersProj.hxx>
56 #include <Message_Msg.hxx>
58 //=======================================================================
59 //function : ShapeFix_Wireframe
61 //=======================================================================
63 ShapeFix_Wireframe::ShapeFix_Wireframe()
66 myModeDrop = Standard_False;
70 //=======================================================================
71 //function : ShapeFix_Wireframe
73 //=======================================================================
75 ShapeFix_Wireframe::ShapeFix_Wireframe(const TopoDS_Shape& shape)
79 myModeDrop = Standard_False;
83 //=======================================================================
84 //function : ClearStatuses
86 //=======================================================================
88 void ShapeFix_Wireframe::ClearStatuses()
90 Standard_Integer emptyStatus = ShapeExtend::EncodeStatus( ShapeExtend_OK );
92 myStatusWireGaps = emptyStatus;
93 myStatusSmallEdges = emptyStatus;
96 //=======================================================================
99 //=======================================================================
101 void ShapeFix_Wireframe::Load(const TopoDS_Shape& shape)
107 //=======================================================================
108 //function : FixWireGaps
110 //=======================================================================
112 Standard_Boolean ShapeFix_Wireframe::FixWireGaps()
114 myStatusWireGaps = ShapeExtend::EncodeStatus( ShapeExtend_OK );
115 if (myShape.IsNull()) return Standard_False;
117 if (Context().IsNull()) SetContext(new ShapeBuild_ReShape);
120 TopoDS_Shape shape = myShape;
122 myShape = Context()->Apply(shape);
125 Standard_Real prec = (Precision()>0.)? Precision() : Precision::Confusion();
126 TopTools_DataMapOfShapeShape cont;
127 if ( myShape.ShapeType() == TopAbs_COMPOUND )
129 Standard_Boolean locModified = Standard_False;
132 B.MakeCompound ( C );
133 TopoDS_Shape savShape = myShape;
134 for ( TopoDS_Iterator it(savShape); it.More(); it.Next() )
136 TopoDS_Shape shape1 = it.Value();
137 TopLoc_Location L = shape1.Location(),nullLoc;
138 shape1.Location ( nullLoc );
140 if ( cont.IsBound ( shape1 ) )
142 res = cont.Find ( shape1 ).Oriented ( shape1.Orientation() );
149 cont.Bind(myShape,res);
151 if ( ! res.IsSame ( shape1 ) ) locModified = Standard_True;
158 C.Orientation(savShape.Orientation());
159 Context()->Replace(savShape,C);
161 myShape = Context()->Apply(savShape);
162 return StatusWireGaps(ShapeExtend_DONE);
164 Handle(ShapeFix_Wire) sfw = new ShapeFix_Wire;
165 sfw->SetContext(Context());
166 sfw->SetPrecision(prec);
169 for (TopExp_Explorer anExpf1(myShape,TopAbs_FACE); anExpf1.More(); anExpf1.Next())
172 TopoDS_Shape tmpF = Context()->Apply(anExpf1.Current());
173 face = TopoDS::Face(tmpF);
174 if (face.Orientation()==TopAbs_REVERSED) face.Orientation(TopAbs_FORWARD);
175 for (TopoDS_Iterator itw(face); itw.More(); itw.Next())
177 if(itw.Value().ShapeType() != TopAbs_WIRE)
180 TopoDS_Shape tmpW = Context()->Apply(itw.Value());
181 sfw->Init(TopoDS::Wire(tmpW), face, prec);
184 if (sfw->StatusGaps3d(ShapeExtend_DONE))
185 myStatusWireGaps |= ShapeExtend::EncodeStatus( ShapeExtend_DONE1 );
186 if (sfw->StatusGaps3d(ShapeExtend_FAIL))
187 myStatusWireGaps |= ShapeExtend::EncodeStatus( ShapeExtend_FAIL1 );
189 if (sfw->StatusGaps2d(ShapeExtend_DONE))
190 myStatusWireGaps |= ShapeExtend::EncodeStatus( ShapeExtend_DONE2 );
191 if (sfw->StatusGaps2d(ShapeExtend_FAIL))
192 myStatusWireGaps |= ShapeExtend::EncodeStatus( ShapeExtend_FAIL2 );
193 if (sfw->StatusGaps3d(ShapeExtend_DONE) || sfw->StatusGaps2d(ShapeExtend_DONE))
194 SendWarning( itw.Value(), Message_Msg( "FixWireframe.FixFixWireGaps.MSG0" ));
198 //============================================================
200 //Purpose: This block fixing a 3d wire which not lie on plane
202 //============================================================
203 for (TopExp_Explorer expw(myShape,TopAbs_WIRE,TopAbs_FACE); expw.More(); expw.Next())
205 TopoDS_Shape tmpW = Context()->Apply(expw.Current());
206 sfw->Load(TopoDS::Wire(tmpW));
207 sfw->SetPrecision(prec);
210 if (sfw->StatusGaps3d(ShapeExtend_DONE))
211 myStatusWireGaps |= ShapeExtend::EncodeStatus( ShapeExtend_DONE1 );
212 if (sfw->StatusGaps3d(ShapeExtend_FAIL))
213 myStatusWireGaps |= ShapeExtend::EncodeStatus( ShapeExtend_FAIL1 );
214 if (sfw->StatusGaps3d(ShapeExtend_DONE))
215 SendWarning( expw.Current(), Message_Msg( "FixWireframe.FixFixWireGaps.MSG0" ));
217 //End Part1========================================================
219 if (StatusWireGaps(ShapeExtend_DONE))
222 myShape = Context()->Apply(myShape);
224 ShapeFix::SameParameter(myShape,Standard_False);
227 Handle(ShapeFix_Edge) sfe = new ShapeFix_Edge;
228 for (TopExp_Explorer anExpf2(myShape,TopAbs_FACE); anExpf2.More(); anExpf2.Next())
230 face = TopoDS::Face(anExpf2.Current());
231 if (face.Orientation()==TopAbs_REVERSED) face.Orientation(TopAbs_FORWARD);
232 for (TopoDS_Iterator itw(face); itw.More(); itw.Next())
234 if(itw.Value().ShapeType() != TopAbs_WIRE)
236 wire = TopoDS::Wire(itw.Value());
237 sfw->Init(wire, face, prec);
239 sfw->FixSelfIntersection();
240 for (TopoDS_Iterator ite(wire); ite.More(); ite.Next())
241 sfe->FixVertexTolerance(TopoDS::Edge(ite.Value()));
246 for (TopExp_Explorer expw2(myShape,TopAbs_WIRE,TopAbs_FACE); expw2.More(); expw2.Next())
248 wire = TopoDS::Wire(expw2.Current());
250 sfw->SetPrecision(prec);
252 sfw->FixSelfIntersection();
253 for (TopoDS_Iterator ite(wire); ite.More(); ite.Next())
254 sfe->FixVertexTolerance(TopoDS::Edge(ite.Value()));
259 return Standard_True;
262 return Standard_False;
265 //=======================================================================
266 //function : JoinEdges (static)
267 //purpose : used in FixSmallEdges
268 //=======================================================================
270 static Standard_Boolean JoinEdges(const TopoDS_Edge& E1,
271 const TopoDS_Edge& E2,
273 const TopTools_ListOfShape& faces)
275 Standard_Boolean ReplaceFirst = Standard_True;
276 ShapeAnalysis_Edge sae;
277 Handle(Geom_Curve) c3d1,c3d2;
278 Handle(Geom2d_Curve) c2d1,c2d2; //TopTools
279 TopoDS_Edge newedge,newedge1;
281 TopoDS_Vertex V11 = sae.FirstVertex(E1);
282 TopoDS_Vertex V12 = sae.LastVertex(E1);
283 TopoDS_Vertex V21 = sae.FirstVertex(E2);
284 TopoDS_Vertex V22 = sae.LastVertex(E2);
287 Standard_Boolean isSame = (V11.IsSame(V12) || V22.IsSame(V21));
290 Standard_Real cf1,cf2,cl1,cl2,first1,first2,last1,last2;
291 newedge.Orientation(TopAbs_FORWARD);
295 if(!sae.Curve3d(E1,c3d1,cf1,cl1,Standard_False )) return ReplaceFirst;
296 if(!sae.Curve3d(E2,c3d2,cf2,cl2,Standard_False )) return ReplaceFirst;
299 B.Add(newedge,V11.Oriented(TopAbs_FORWARD));
300 B.Add(newedge,V22.Oriented(TopAbs_REVERSED));
302 Handle(Geom_Curve) CRes;
303 Standard_Boolean isRev1,isRev2;
304 // Standard_Real newf,newl;
305 if(!ShapeConstruct::JoinCurves(c3d1,c3d2,E1.Orientation(),E2.Orientation(),cf1, cl1,cf2, cl2,CRes,isRev1,isRev2))
307 // if(isRev1 || isRev2)
308 if(!isSame && (isRev1 || isRev2))
310 ReplaceFirst = (!isRev1);
312 Standard_Real newf = cf1;
313 Standard_Real newl = cl1 + cl2 - cf2;
314 TopAbs_Orientation OrEdge1 = E1.Orientation();
315 TopAbs_Orientation OrEdge2 = E2.Orientation();
316 Standard_Boolean ismanifold =(OrEdge1 == TopAbs_FORWARD || OrEdge1 == TopAbs_REVERSED);
317 Standard_Boolean ismanifold2 = (OrEdge2 == TopAbs_FORWARD || OrEdge2 == TopAbs_REVERSED);
318 if(ismanifold != ismanifold2)
323 OrEdge1 = ( (!isRev1 && E1.Orientation() == TopAbs_FORWARD) ||
324 (isRev1 && E1.Orientation() == TopAbs_REVERSED) ? TopAbs_FORWARD :TopAbs_REVERSED);
325 OrEdge2 = ( (!isRev2 && E2.Orientation() == TopAbs_FORWARD) ||
326 (isRev2 && E2.Orientation() == TopAbs_REVERSED) ? TopAbs_FORWARD :TopAbs_REVERSED);
328 B.UpdateEdge(newedge,CRes,Max(BRep_Tool::Tolerance(E1),BRep_Tool::Tolerance(E2)));
329 Standard_Real fp= CRes->FirstParameter();
330 Standard_Real lp= CRes->LastParameter();
331 if(fp > newf) newf = fp;
332 if(lp < newl) newl = lp;
333 B.Range(newedge,newf,newl);
336 for(TopTools_ListIteratorOfListOfShape iter(faces); iter.More(); iter.Next())
338 TopoDS_Face face = TopoDS::Face(iter.Value());
339 if(!sae.PCurve ( E1, face, c2d1, first1, last1, Standard_False )) return ReplaceFirst;
340 if(!sae.PCurve ( E2, face, c2d2, first2, last2, Standard_False )) return ReplaceFirst;
342 Handle(Geom2d_Curve) C2dRes;
343 Standard_Boolean isRev12,isRev22;
344 if(!ShapeConstruct::JoinCurves(c2d1,c2d2,OrEdge1,OrEdge2,first1, last1,first2, last2,C2dRes,isRev12,isRev22,isSame))
347 if(ismanifold && (!isSame && (isRev12 || isRev22)))
351 ReplaceFirst = Standard_False;
352 Standard_Real fp2d = C2dRes->FirstParameter();
353 Standard_Real lp2d = C2dRes->LastParameter();
354 //B.UpdateEdge(newedge,C2dRes,face,0);
355 Standard_Real newf1 = first1;
356 Standard_Real newl1 = last1 + (last2 - first2);
357 if(fp2d > newf1) newf1 = fp2d;
358 if(lp2d < newl1) newl1 = lp2d;
360 // dealing with seams: the same again
361 if(sae.IsSeam(E1,face) && sae.IsSeam(E2,face))
363 Handle(Geom2d_Curve) c2d12,c2d22;
365 TopoDS_Shape tmpE1 = E1.Reversed(),
366 tmpE2 = E2.Reversed();
367 TopoDS_Edge E1t = TopoDS::Edge(tmpE1);
368 TopoDS_Edge E2t = TopoDS::Edge(tmpE2);
369 sae.PCurve ( E1t, face, c2d12, first1, last1, Standard_False );
370 sae.PCurve ( E2t, face, c2d22, first2, last2, Standard_False );
372 Handle(Geom2d_Curve) C2dRes2;
373 if(!ShapeConstruct::JoinCurves(c2d12,c2d22,OrEdge1,OrEdge2,first1, last1,first2, last2,C2dRes2,isRev12,isRev22,isSame))
375 if(!isSame && (isRev1 || isRev2))
377 B.UpdateEdge(newedge,C2dRes,C2dRes2,face,0);
379 else if(sae.IsSeam(E1,face) || sae.IsSeam(E2,face)) return ReplaceFirst;
380 else if(!sae.IsSeam(E1,face) && !sae.IsSeam(E2,face))
381 B.UpdateEdge(newedge,C2dRes,face,0);
382 B.Range(newedge,face,newf1,newl1);
384 newedge.Orientation(ReplaceFirst ? OrEdge1 :OrEdge2 );
386 B.SameRange(newedge,Standard_False);
391 catch ( Standard_Failure )
394 cout<<"Error: ShapeFix_Wireframe::FixSmallEdges: JoinEdges: Exception in GeomConvert_CompCurveToBSplineCurve: ";
395 Standard_Failure::Caught()->Print(cout); cout<<endl;
401 //=======================================================================
402 //function : FixSmallEdges
404 //=======================================================================
406 Standard_Boolean ShapeFix_Wireframe::FixSmallEdges()
408 myStatusSmallEdges = ShapeExtend::EncodeStatus( ShapeExtend_OK );
409 if (myShape.IsNull()) return Standard_False;
411 if (Context().IsNull()) SetContext(new ShapeBuild_ReShape);
414 TopoDS_Shape shape = myShape;
416 myShape = Context()->Apply(shape);
418 TopTools_DataMapOfShapeShape cont;
419 if ( myShape.ShapeType() == TopAbs_COMPOUND )
421 Standard_Boolean locModified = Standard_False;
424 B.MakeCompound ( C );
425 TopoDS_Shape savShape = myShape;
426 for ( TopoDS_Iterator it(savShape); it.More(); it.Next() )
428 TopoDS_Shape shape1 = it.Value();
429 TopLoc_Location L = shape1.Location(),nullLoc;
430 shape1.Location ( nullLoc );
432 if ( cont.IsBound ( shape1 ) )
434 res = cont.Find ( shape1 ).Oriented ( shape1.Orientation() );
441 cont.Bind(myShape,res);
443 if ( ! res.IsSame ( shape1 ) ) locModified = Standard_True;
445 //check if resulting shape if not empty
455 C.Orientation(savShape.Orientation());
456 Context()->Replace(savShape,C);
458 myShape = Context()->Apply(savShape);
459 return StatusSmallEdges( ShapeExtend_DONE );
461 TopTools_MapOfShape theSmallEdges, theMultyEdges;
462 TopTools_DataMapOfShapeListOfShape theEdgeToFaces,theFaceWithSmall;
463 CheckSmallEdges ( theSmallEdges,theEdgeToFaces,theFaceWithSmall, theMultyEdges);
464 MergeSmallEdges ( theSmallEdges,theEdgeToFaces,theFaceWithSmall, theMultyEdges);
465 return StatusSmallEdges( ShapeExtend_DONE );
468 //=======================================================================
469 //function : CheckSmallEdges
471 //=======================================================================
472 #include <BRepBuilderAPI_MakeFace.hxx>
473 #include <TopExp.hxx>
474 #include <TopTools_IndexedDataMapOfShapeListOfShape.hxx>
475 Standard_Boolean ShapeFix_Wireframe::CheckSmallEdges(TopTools_MapOfShape& theSmallEdges,
476 TopTools_DataMapOfShapeListOfShape& theEdgeToFaces,
477 TopTools_DataMapOfShapeListOfShape& theFaceWithSmall,
478 TopTools_MapOfShape& theMultyEdges)
482 ShapeAnalysis_Wire SAW;
484 for (TopExp_Explorer anExpf1(myShape,TopAbs_FACE); anExpf1.More(); anExpf1.Next())
486 TopTools_ListOfShape theEdgeList;
487 TopoDS_Face facet = TopoDS::Face(anExpf1.Current());
489 if (facet.Orientation()==TopAbs_REVERSED) face = TopoDS::Face(facet.Oriented(TopAbs_FORWARD));
490 for (TopoDS_Iterator itw(face); itw.More(); itw.Next())
492 if(itw.Value().ShapeType() != TopAbs_WIRE)
494 TopoDS_Wire aW = TopoDS::Wire(itw.Value());
495 Handle(ShapeExtend_WireData) aswd = new ShapeExtend_WireData(aW,Standard_True,Standard_False);
496 SAW.Init(aswd,face,Precision());
497 // pnd protection on seam edges
498 TopTools_DataMapOfShapeInteger EdgeMap;
500 for (i=1; i<=SAW.NbEdges(); i++)
502 edge = SAW.WireData()->Edge(i);
503 if (EdgeMap.IsBound(edge))
504 EdgeMap.ChangeFind(edge)++;
506 EdgeMap.Bind(edge,1);
509 for ( i=1; i<=SAW.NbEdges(); i++)
511 edge = SAW.WireData()->Edge(i);
512 if(EdgeMap.Find(edge)!=1)
514 if(!SAW.WireData()->IsSeam(i))
515 theMultyEdges.Add(edge);
518 // Append current face to the list
519 if (theEdgeToFaces.IsBound(edge))
521 theEdgeToFaces(edge).Append(facet);
525 TopTools_ListOfShape theFaceList;
526 theFaceList.Append(facet);
527 theEdgeToFaces.Bind(edge,theFaceList);
529 // Check if current edge is small
530 if (theSmallEdges.Contains(edge)) theEdgeList.Append(edge);
531 else if (SAW.CheckSmall(i,Precision()))
533 theSmallEdges.Add(edge);
534 theEdgeList.Append(edge);
538 // Add current face to the map if has small edges
539 if (theEdgeList.Extent()) theFaceWithSmall.Bind(facet,theEdgeList);
542 //========================================================================
544 // Purpose: Analizing of shape for small edges , if edge don't lie on face
545 //========================================================================
546 for (TopExp_Explorer expw1(myShape,TopAbs_WIRE,TopAbs_FACE); expw1.More(); expw1.Next())
548 SAW.SetPrecision(Precision());
549 TopTools_DataMapOfShapeInteger EdgeMap;
551 TopoDS_Wire theWire=TopoDS::Wire(expw1.Current());
552 TopTools_ListOfShape theEdgeList;
556 return Standard_False;
558 for (i=1; i<=SAW.NbEdges(); i++)
560 edge = SAW.WireData()->Edge(i);
561 if (EdgeMap.IsBound(edge))
562 EdgeMap.ChangeFind(edge)++;
564 EdgeMap.Bind(edge,1);
567 for ( i=1; i<=SAW.NbEdges(); i++)
569 edge = SAW.WireData()->Edge(i);
570 if(EdgeMap.Find(edge)!=1)
572 if(!SAW.WireData()->IsSeam(i))
573 theMultyEdges.Add(edge);
577 // Check if current edge is small
578 if (theSmallEdges.Contains(edge)) theEdgeList.Append(edge);
579 else if (SAW.CheckSmall(i,Precision()))
581 theSmallEdges.Add(edge);
582 theEdgeList.Append(edge);
587 return (!theSmallEdges.IsEmpty());
591 //=======================================================================
592 //function : MergeSmallEdges
594 //=======================================================================
596 Standard_Boolean ShapeFix_Wireframe::MergeSmallEdges(TopTools_MapOfShape& theSmallEdges,
597 TopTools_DataMapOfShapeListOfShape& theEdgeToFaces,
598 TopTools_DataMapOfShapeListOfShape& theFaceWithSmall,
599 TopTools_MapOfShape& theMultyEdges,
600 const Standard_Boolean theModeDrop,
601 const Standard_Real theLimitAngle)
603 Standard_Boolean aModLimitAngle = (theLimitAngle >-1.0 || myLimitAngle > -1.0);
604 Standard_Real aLimitAngle = Max(theLimitAngle,myLimitAngle);
606 Standard_Boolean aModeDrop = theModeDrop || myModeDrop;
607 TopTools_DataMapOfShapeShape theNewVertices;
608 if (!theSmallEdges.IsEmpty())
611 Handle(ShapeFix_Wire) SFW = new ShapeFix_Wire;
612 SFW->SetContext(Context());
613 ShapeAnalysis_Edge SAE;
614 TopoDS_Edge edge1, edge2, edge3;
615 // Iterate on map of faces with small edges
616 TopExp_Explorer anExpf2(myShape,TopAbs_FACE);
617 for (; anExpf2.More(); anExpf2.Next())
619 if (theFaceWithSmall.IsBound(anExpf2.Current()))
621 if (theFaceWithSmall(anExpf2.Current()).Extent())
624 TopoDS_Shape tmpShape = Context()->Apply(anExpf2.Current());
625 TopoDS_Face facet = TopoDS::Face(tmpShape);
626 if(!facet.IsSame(anExpf2.Current()))
628 TopExp_Explorer aExpEdge(anExpf2.Current(),TopAbs_EDGE);
629 for( ; aExpEdge.More(); aExpEdge.Next())
631 TopoDS_Shape newEdge;
632 Standard_Integer stat = Context()->Status(aExpEdge.Current(),newEdge,Standard_True);
635 if(theSmallEdges.Contains(aExpEdge.Current()))
637 theSmallEdges.Remove(aExpEdge.Current());
638 theSmallEdges.Add(newEdge);
640 if(theEdgeToFaces.IsBound(aExpEdge.Current()))
642 TopTools_ListOfShape aListFaces;
643 aListFaces = theEdgeToFaces.Find(aExpEdge.Current());
644 theEdgeToFaces.UnBind(aExpEdge.Current());
645 theEdgeToFaces.Bind(newEdge,aListFaces);
651 TopoDS_Face face = facet;
652 //if (face.Orientation()==TopAbs_REVERSED)
653 // face = TopoDS::Face(facet.Oriented(TopAbs_FORWARD));
654 for (TopoDS_Iterator itw(face); itw.More(); itw.Next())
656 if(itw.Value().ShapeType() != TopAbs_WIRE) continue;
657 TopoDS_Wire aWire = TopoDS::Wire(itw.Value());
658 if (face.Orientation()==TopAbs_REVERSED)
659 face = TopoDS::Face(facet.Oriented(TopAbs_FORWARD));
660 Handle(ShapeExtend_WireData) aswd = new ShapeExtend_WireData(aWire,Standard_True,Standard_False);
664 Standard_Integer prev, next, index = 1;
666 while (index <= SFW->WireData()->NbEdges() && SFW->NbEdges()>1)
668 prev = (index==1)? SFW->WireData()->NbEdges() : index-1;
669 next = (index==SFW->WireData()->NbEdges())? 1 : index+1;
670 edge1 = SFW->WireData()->Edge(prev);
671 edge2 = SFW->WireData()->Edge(index);
672 edge3 = SFW->WireData()->Edge(next);
674 //gka protection against joining seem edge
675 if(edge2.IsSame(edge1) || edge2.IsSame(edge3))
677 //if(BRep_Tool::IsClosed(edge2,face)) {
682 Standard_Boolean isSeam = SFW->WireData()->IsSeam(index);
683 Standard_Boolean isSeam1 = SFW->WireData()->IsSeam(prev);
684 Standard_Boolean isSeam2 = SFW->WireData()->IsSeam(next);
685 if (theSmallEdges.Contains(edge2))
687 // Middle edge is small - choose a pair of edges to join
688 Standard_Boolean IsAnyJoin = (edge1.IsSame(edge3));
689 Standard_Boolean take_next = IsAnyJoin; //Standard_False;
690 Standard_Boolean isLimAngle = Standard_False;
691 Handle(Geom_Curve) C1, C2, C3;
692 Standard_Real aux, last1, first2, last2, first3;
693 Standard_Real Ang1 = 0., Ang2 =0.;
694 if (SAE.Curve3d(edge1,C1,aux,last1) &&
695 SAE.Curve3d(edge2,C2,first2,last2) &&
696 SAE.Curve3d(edge3,C3,first3,aux))
698 // Compare angles between edges
699 //Standard_Real Ang1, Ang2;
700 gp_Vec Vec1, Vec2; gp_Pnt P;
701 C1->D1(last1,P,Vec1);
702 C2->D1(first2,P,Vec2);
703 if ( edge1.Orientation() == TopAbs_REVERSED ) Vec1.Reverse();
704 if ( edge2.Orientation() == TopAbs_REVERSED ) Vec2.Reverse();
705 Standard_Real tol2 = Precision::SquareConfusion();
706 if ( Vec1.SquareMagnitude() < tol2 ||
707 Vec2.SquareMagnitude() < tol2 ) Ang1 = M_PI/2.;
708 else Ang1 = Abs(Vec1.Angle(Vec2));
709 C2->D1(last2,P,Vec1);
710 C3->D1(first3,P,Vec2);
711 if ( edge2.Orientation() == TopAbs_REVERSED ) Vec1.Reverse();
712 if ( edge3.Orientation() == TopAbs_REVERSED ) Vec2.Reverse();
713 if ( Vec1.SquareMagnitude() < tol2 ||
714 Vec2.SquareMagnitude() < tol2 ) Ang2 = M_PI/2.;
715 else Ang2 = Abs(Vec1.Angle(Vec2));
716 //isLimAngle = (theLimitAngle != -1 && Min(Ang1,Ang2) > theLimitAngle);
717 //take_next = (Ang2<Ang1);
718 //if (take_next) { edge1 = edge2; edge2 = edge3; }
720 //if(theLimitAngle != -1 && Ang1 > theLimitAngle && Ang2 >theLimitAngle) {
721 // index++; continue;
724 // Check if edges lay on the same faces
725 if(theMultyEdges.Contains(edge1) || theMultyEdges.Contains(edge2))
730 TopTools_ListOfShape theList1,theList2,theList3;
731 if(theEdgeToFaces.IsBound(edge1))
732 theList1 = theEdgeToFaces(edge1);
733 if(theEdgeToFaces.IsBound(edge2))
734 theList2 = theEdgeToFaces(edge2);
735 if(theEdgeToFaces.IsBound(edge3))
736 theList3 = theEdgeToFaces(edge3);
737 Standard_Boolean same_set = Standard_False;
739 //gka protection against joining seem edges with other edges
740 Standard_Boolean same_set1 = (theList1.Extent()==theList2.Extent() &&
741 ((!isSeam && !isSeam1)|| (isSeam && isSeam1))); //gka
742 Standard_Boolean same_set2 = (theList3.Extent()==theList2.Extent() &&
743 ((!isSeam && !isSeam2)|| (isSeam && isSeam2)));
744 TopTools_MapOfShape theSetOfFaces;
745 for (TopTools_ListIteratorOfListOfShape itf1(theList2);
746 itf1.More(); itf1.Next())
747 theSetOfFaces.Add(itf1.Value());
750 // Add all faces of the first edge to the current set
751 for (TopTools_ListIteratorOfListOfShape itf2(theList1);
752 (itf2.More() && same_set1); itf2.Next())
753 same_set1 = theSetOfFaces.Contains(itf2.Value());
757 // Add all faces of the first edge to the current set
758 for (TopTools_ListIteratorOfListOfShape itf2(theList3);
759 (itf2.More() && same_set2); itf2.Next())
760 same_set2 = theSetOfFaces.Contains(itf2.Value());
762 if(same_set1 && same_set2)
764 same_set = Standard_True;
765 if(fabs(Ang2-Ang1) >Precision::Angular())
766 take_next = (Ang2<Ang1);
769 edge1 = edge2; edge2 = edge3;
771 isLimAngle = (aModLimitAngle && Min(Ang1,Ang2) > aLimitAngle);
773 else if(same_set1 && !same_set2)
775 isLimAngle = (aModLimitAngle && Ang1 > aLimitAngle);
776 same_set = Standard_True;
778 else if(!same_set1 && same_set2)
780 same_set = Standard_True;
781 isLimAngle = (aModLimitAngle && Ang2 > aLimitAngle);
782 edge1 = edge2; edge2 = edge3;
783 take_next = Standard_True;
785 if (same_set && !isLimAngle )
787 // Merge current pair of edges
788 //gka protection against crossing seem on second face
789 Standard_Boolean isNeedJoin = Standard_True;//Standard_False;
790 for(TopTools_ListIteratorOfListOfShape aItF(theList2); aItF.More() && isNeedJoin; aItF.Next())
792 if(aItF.Value().IsSame(anExpf2.Current())) continue;
793 TopoDS_Shape aF = Context()->Apply(aItF.Value());
794 //aF = aF.Oriented(TopAbs_FORWARD);
795 for(TopoDS_Iterator aIw(aF); aIw.More(); aIw.Next())
797 if(aIw.Value().ShapeType() != TopAbs_WIRE) continue;
798 TopoDS_Wire wt = TopoDS::Wire(aIw.Value());
799 Handle(ShapeFix_Wire) SFW1 = new ShapeFix_Wire;
802 Handle(ShapeExtend_WireData) atmpswd = SFW1->WireData();
803 Standard_Integer ind1 = atmpswd->Index(edge1);
804 Standard_Integer ind2 = atmpswd->Index(edge2);
807 isNeedJoin = ((ind1 -ind2) ==1 || (ind2 == atmpswd->NbEdges() && ind1 ==1));
812 Standard_Boolean ReplaceFirst = Standard_True;
816 TopTools_ListOfShape aListF;
817 for(TopTools_ListIteratorOfListOfShape aItlF(theList2); aItlF.More(); aItlF.Next())
819 TopoDS_Shape tmpF = Context()->Apply(aItlF.Value());
822 ReplaceFirst = JoinEdges(edge1,edge2,edge3,aListF);
824 else edge3 = TopoDS_Edge();
828 myStatusSmallEdges |= ShapeExtend::EncodeStatus( ShapeExtend_FAIL1 );
832 // Record vertex replacements in the map
833 TopoDS_Vertex oldV1 = SAE.FirstVertex(edge3),
834 oldV2 = SAE.LastVertex(edge3);
835 if (!theNewVertices.IsBound(oldV1))
838 TopoDS_Shape emptyCopiedV1 = oldV1.EmptyCopied();
839 theNewVertices.Bind(oldV1,TopoDS::Vertex(emptyCopiedV1));
841 if (!oldV1.IsSame(oldV2))
842 if (!theNewVertices.IsBound(oldV2))
845 TopoDS_Shape emptyCopiedV2 = oldV2.EmptyCopied();
846 theNewVertices.Bind(oldV2,TopoDS::Vertex(emptyCopiedV2));
849 //To keep NM vertices belonging initial edges
850 TopoDS_Iterator aItv(edge1,Standard_False);
851 for( ; aItv.More(); aItv.Next()) {
852 if(aItv.Value().Orientation() == TopAbs_INTERNAL ||
853 aItv.Value().Orientation() == TopAbs_EXTERNAL) {
854 TopoDS_Vertex aOldV = TopoDS::Vertex(aItv.Value());
855 TopoDS_Vertex anewV = ShapeAnalysis_TransferParametersProj::CopyNMVertex(aOldV,edge3,edge1);
858 Context()->Replace(aOldV,anewV);
862 for(aItv.Initialize(edge2,Standard_False) ; aItv.More(); aItv.Next()) {
863 if(aItv.Value().Orientation() == TopAbs_INTERNAL ||
864 aItv.Value().Orientation() == TopAbs_EXTERNAL){
866 TopoDS_Vertex aOldV = TopoDS::Vertex(aItv.Value());
867 TopoDS_Vertex anewV = ShapeAnalysis_TransferParametersProj::CopyNMVertex(aOldV,edge3,edge2);
869 Context()->Replace(aOldV,anewV);
873 // Check for small resulting edge
874 Standard_Boolean newsmall = Standard_False;
875 ShapeAnalysis_Wire SAW;
876 SAW.Init(SFW->WireData(),face,Precision());
877 // Make changes in WireData and Context
880 Context()->Replace(edge1,edge3);
881 Context()->Remove(edge2);
882 SendWarning( edge2, Message_Msg("FixWireframe.FixSmallEdges.MSG0"));
886 Context()->Replace(edge2,edge3);
887 Context()->Remove(edge1);
888 SendWarning( edge1, Message_Msg("FixWireframe.FixSmallEdges.MSG0"));
892 SFW->WireData()->Set(edge3,next);
893 newsmall = SAW.CheckSmall(next,Precision());
897 SFW->WireData()->Set(edge3,prev);
898 newsmall = SAW.CheckSmall(prev,Precision());
900 SFW->WireData()->Remove(index);
901 // Process changes in maps
902 TopTools_ListOfShape theList;
903 theList.Append(theList2);
904 theEdgeToFaces.UnBind(edge1);
905 theEdgeToFaces.UnBind(edge2);
906 theEdgeToFaces.Bind(edge3,theList);
907 if (theSmallEdges.Contains(edge1)) theSmallEdges.Remove(edge1);
908 if (theSmallEdges.Contains(edge2)) theSmallEdges.Remove(edge2);
909 if (newsmall) theSmallEdges.Add(edge3);
910 for (TopTools_ListIteratorOfListOfShape itlf(theList);
911 itlf.More(); itlf.Next())
913 TopoDS_Shape curface = itlf.Value();
914 if (theFaceWithSmall.IsBound(curface))
916 TopTools_ListOfShape& theEdges = theFaceWithSmall(curface);
917 if (newsmall) theEdges.Append(edge3);
918 TopTools_ListIteratorOfListOfShape ite(theEdges);
921 TopoDS_Shape iedge = ite.Value();
922 if (iedge.IsSame(edge1) || iedge.IsSame(edge2))
923 theEdges.Remove(ite);
926 // Remove face without small edges from the map
927 if (!theEdges.Extent()) theFaceWithSmall.UnBind(curface);
930 myStatusSmallEdges |= ShapeExtend::EncodeStatus( ShapeExtend_DONE1 );
935 Handle(ShapeExtend_WireData) tempWire = new ShapeExtend_WireData();
936 ShapeAnalysis_Wire tempSaw;
937 tempWire->Add(SFW->Wire());
941 else remedge = edge2;
942 tempWire->Remove (index );
943 tempSaw.Load(tempWire);
944 Standard_Integer newindex = (index <= tempSaw.NbEdges() ? index : 1);
945 tempSaw.CheckConnected(newindex,Precision());
946 if(!tempSaw.LastCheckStatus(ShapeExtend_FAIL))
948 SFW->WireData()->Remove (index );
949 TopoDS_Edge tmpedge1 = tempWire->Edge(newindex);
950 TopoDS_Edge tmpedge2 = tempWire->Edge(newindex == 1 ? tempSaw.NbEdges() : (newindex- 1));
951 TopTools_ListOfShape aL1;
952 if(theEdgeToFaces.IsBound(tmpedge1))
953 aL1 = theEdgeToFaces.Find(tmpedge1);
954 TopTools_ListOfShape aL2;
955 if(theEdgeToFaces.IsBound(tmpedge2))
956 aL2= theEdgeToFaces.Find(tmpedge2);
957 SFW->FixConnected(newindex <= SFW->NbEdges() ? newindex : 1,Precision());
958 SFW->FixDegenerated(newindex <= SFW->NbEdges() ? newindex : 1);
959 TopoDS_Shape aTmpShape = Context()->Apply(tmpedge1); //for porting
960 TopoDS_Edge anewedge1 = TopoDS::Edge(aTmpShape);
961 aTmpShape = Context()->Apply(tmpedge2);
962 TopoDS_Edge anewedge2 = TopoDS::Edge(aTmpShape);
963 Context()->Remove(remedge);
964 SendWarning( remedge, Message_Msg("FixWireframe.FixSmallEdges.MSG0"));
965 if (theSmallEdges.Contains(remedge))
966 theSmallEdges.Remove(remedge);
967 theEdgeToFaces.UnBind(remedge);
968 theEdgeToFaces.UnBind(tmpedge1);
969 theEdgeToFaces.UnBind(tmpedge2);
970 theEdgeToFaces.Bind(anewedge1,aL1);
971 theEdgeToFaces.Bind(anewedge2,aL2);
972 if (theSmallEdges.Contains(tmpedge1))
974 theSmallEdges.Remove(tmpedge1);
975 theSmallEdges.Add(anewedge1);
976 for (TopTools_ListIteratorOfListOfShape itlf(aL1);
977 itlf.More(); itlf.Next())
979 TopoDS_Shape curface = itlf.Value();
980 TopTools_ListOfShape& theEdges = theFaceWithSmall(curface);
981 TopTools_ListIteratorOfListOfShape ite(theEdges);
984 TopoDS_Shape iedge = ite.Value();
985 if (iedge.IsSame(tmpedge1))
987 theEdges.Remove(ite);
988 theEdges.Append(anewedge1);
994 if (theSmallEdges.Contains(tmpedge2))
996 theSmallEdges.Remove(tmpedge2);
997 theSmallEdges.Add(anewedge2);
998 for (TopTools_ListIteratorOfListOfShape itlf(aL2);
999 itlf.More(); itlf.Next())
1001 TopoDS_Shape curface = itlf.Value();
1002 TopTools_ListOfShape& theEdges = theFaceWithSmall(curface);
1003 TopTools_ListIteratorOfListOfShape ite(theEdges);
1006 TopoDS_Shape iedge = ite.Value();
1007 if (iedge.IsSame(tmpedge2))
1009 theEdges.Remove(ite);
1010 theEdges.Append(anewedge2);
1016 myStatusSmallEdges |= ShapeExtend::EncodeStatus( ShapeExtend_DONE3 );
1022 //gka protection aginst removing circles
1023 TopoDS_Edge ed = (take_next ? edge1 : edge2);
1024 ShapeAnalysis_Edge sae;
1025 Handle(Geom_Curve) c3d;
1026 Standard_Real f1,l1;
1027 if(sae.Curve3d(ed,c3d,f1,l1,Standard_False))
1032 c3d->D0((f1 +l1)*0.5,p3);
1034 if(p1.Distance(p3) > p1.Distance(p2))
1040 if (take_next && theList2.Extent()== 1)
1042 TopoDS_Vertex V1 = SAE.FirstVertex(edge1),
1043 V2 = SAE.LastVertex(edge1);
1046 SFW->WireData()->Remove (index );
1047 Context()->Remove(edge1);
1048 SendWarning( edge1, Message_Msg("FixWireframe.FixSmallEdges.MSG0"));
1049 if (theSmallEdges.Contains(edge1)) theSmallEdges.Remove(edge1);
1050 theEdgeToFaces.UnBind(edge1);
1051 myStatusSmallEdges |= ShapeExtend::EncodeStatus( ShapeExtend_DONE2 );
1055 else if( !take_next && theList2.Extent()== 1)
1057 TopoDS_Vertex V1 = SAE.FirstVertex(edge2),
1058 V2 = SAE.LastVertex(edge2);
1061 SFW->WireData()->Remove (index );
1062 Context()->Remove(edge2);
1063 SendWarning( edge2, Message_Msg("FixWireframe.FixSmallEdges.MSG0"));
1064 if (theSmallEdges.Contains(edge2)) theSmallEdges.Remove(edge2);
1065 theEdgeToFaces.UnBind(edge2);
1066 myStatusSmallEdges |= ShapeExtend::EncodeStatus( ShapeExtend_DONE2 );
1075 if (SFW->NbEdges() == 1 && aModeDrop)
1077 edge1 = SFW->WireData()->Edge(1);
1078 if (theSmallEdges.Contains(edge1))
1080 SFW->WireData()->Remove(1);
1081 Context()->Remove(edge1);
1082 SendWarning( edge1, Message_Msg("FixWireframe.FixSmallEdges.MSG0"));
1083 theSmallEdges.Remove(edge1);
1084 theEdgeToFaces.UnBind(edge1);
1085 Context()->Remove(aWire);
1086 SendWarning( aWire, Message_Msg("FixWireframe.FixSmallEdges.MSG1"));
1087 myStatusSmallEdges |= ShapeExtend::EncodeStatus( ShapeExtend_DONE2 );
1092 SFW->FixConnected();
1093 Context()->Replace(aWire,SFW->Wire());
1096 face.Orientation(facet.Orientation());
1097 TopoDS_Shape anewShape = Context()->Apply(face);
1098 TopoDS_Iterator aIter(anewShape);
1100 Context()->Remove(anewShape);
1101 SendWarning( face, Message_Msg("FixWireframe.FixSmallEdges.MSG2"));
1108 // Iterate on map of wires which not lie on faces
1109 for (TopExp_Explorer expw1( myShape, TopAbs_WIRE, TopAbs_FACE); expw1.More(); expw1.Next())
1111 TopoDS_Wire aWire = TopoDS::Wire(expw1.Current());
1114 Standard_Integer prev, next, index = 1;
1115 while (index <= SFW->NbEdges() && SFW->NbEdges()>1)
1117 prev = (index==1)? SFW->NbEdges() : index-1;
1118 next = (index==SFW->NbEdges())? 1 : index+1;
1119 edge1 = SFW->WireData()->Edge(prev);
1120 edge2 = SFW->WireData()->Edge(index);
1121 edge3 = SFW->WireData()->Edge(next);
1123 //gka protection against joining seem edge
1124 if(edge2.IsSame(edge1) || edge2.IsSame(edge3))
1126 //if(BRep_Tool::IsClosed(edge2,face)) {
1131 Standard_Boolean isSeam = SFW->WireData()->IsSeam(index);
1132 Standard_Boolean isSeam1 = SFW->WireData()->IsSeam(prev);
1133 Standard_Boolean isSeam2 = SFW->WireData()->IsSeam(next);
1134 if (theSmallEdges.Contains(edge2))
1136 // Middle edge is small - choose a pair of edges to join
1137 Standard_Boolean IsAnyJoin = (edge1.IsSame(edge3));
1138 Standard_Boolean take_next = IsAnyJoin; //Standard_False;
1139 Standard_Boolean isLimAngle = Standard_False;
1140 Handle(Geom_Curve) C1, C2, C3;
1141 Standard_Real aux, last1, first2, last2, first3;
1142 Standard_Real Ang1 = 0., Ang2 =0.;
1143 if (SAE.Curve3d(edge1,C1,aux,last1) &&
1144 SAE.Curve3d(edge2,C2,first2,last2) &&
1145 SAE.Curve3d(edge3,C3,first3,aux))
1147 // Compare angles between edges
1148 //Standard_Real Ang1, Ang2;
1149 gp_Vec Vec1, Vec2; gp_Pnt P;
1150 C1->D1(last1,P,Vec1);
1151 C2->D1(first2,P,Vec2);
1152 if ( edge1.Orientation() == TopAbs_REVERSED ) Vec1.Reverse();
1153 if ( edge2.Orientation() == TopAbs_REVERSED ) Vec2.Reverse();
1154 Standard_Real tol2 = Precision::SquareConfusion();
1155 if ( Vec1.SquareMagnitude() < tol2 ||
1156 Vec2.SquareMagnitude() < tol2 ) Ang1 = M_PI/2.;
1157 else Ang1 = Abs(Vec1.Angle(Vec2));
1158 C2->D1(last2,P,Vec1);
1159 C3->D1(first3,P,Vec2);
1160 if ( edge2.Orientation() == TopAbs_REVERSED ) Vec1.Reverse();
1161 if ( edge3.Orientation() == TopAbs_REVERSED ) Vec2.Reverse();
1162 if ( Vec1.SquareMagnitude() < tol2 ||
1163 Vec2.SquareMagnitude() < tol2 ) Ang2 = M_PI/2.;
1164 else Ang2 = Abs(Vec1.Angle(Vec2));
1165 //isLimAngle = (theLimitAngle != -1 && Min(Ang1,Ang2) > theLimitAngle);
1166 //take_next = (Ang2<Ang1);
1167 //if (take_next) { edge1 = edge2; edge2 = edge3; }
1169 //if(theLimitAngle != -1 && Ang1 > theLimitAngle && Ang2 >theLimitAngle) {
1170 // index++; continue;
1173 // Check if edges lay on the same faces
1174 if(theMultyEdges.Contains(edge1) || theMultyEdges.Contains(edge2))
1179 TopTools_ListOfShape theList1,theList2,theList3;
1180 if(theEdgeToFaces.IsBound(edge1))
1181 theList1 = theEdgeToFaces(edge1);
1182 if(theEdgeToFaces.IsBound(edge2))
1183 theList2 = theEdgeToFaces(edge2);
1184 if(theEdgeToFaces.IsBound(edge3))
1185 theList3 = theEdgeToFaces(edge3);
1186 Standard_Boolean same_set = Standard_False;
1188 //gka protection against joining seem edges with other edges
1189 Standard_Boolean same_set1 = (theList1.Extent()==theList2.Extent() &&
1190 ((!isSeam && !isSeam1)|| (isSeam && isSeam1))); //gka
1191 Standard_Boolean same_set2 = (theList3.Extent()==theList2.Extent() &&
1192 ((!isSeam && !isSeam2)|| (isSeam && isSeam2)));
1193 TopTools_MapOfShape theSetOfFaces;
1194 for (TopTools_ListIteratorOfListOfShape itf1(theList2);
1195 itf1.More(); itf1.Next())
1196 theSetOfFaces.Add(itf1.Value());
1199 // Add all faces of the first edge to the current set
1200 for (TopTools_ListIteratorOfListOfShape itf2(theList1);
1201 (itf2.More() && same_set1); itf2.Next())
1202 same_set1 = theSetOfFaces.Contains(itf2.Value());
1206 // Add all faces of the first edge to the current set
1207 for (TopTools_ListIteratorOfListOfShape itf2(theList3);
1208 (itf2.More() && same_set2); itf2.Next())
1209 same_set2 = theSetOfFaces.Contains(itf2.Value());
1211 if(same_set1 && same_set2)
1213 same_set = Standard_True;
1214 if(fabs(Ang2-Ang1) >Precision::Angular())
1215 take_next = (Ang2<Ang1);
1218 edge1 = edge2; edge2 = edge3;
1220 isLimAngle = (aModLimitAngle && Min(Ang1,Ang2) > aLimitAngle);
1222 else if(same_set1 && !same_set2)
1224 isLimAngle = (aModLimitAngle && Ang1 > aLimitAngle);
1225 same_set = Standard_True;
1227 else if(!same_set1 && same_set2)
1229 same_set = Standard_True;
1230 isLimAngle = (aModLimitAngle && Ang2 > aLimitAngle);
1231 edge1 = edge2; edge2 = edge3;
1232 take_next = Standard_True;
1234 if (same_set && !isLimAngle )
1236 // Merge current pair of edges
1237 //gka protection against crossing seem on second face
1238 Standard_Boolean isNeedJoin = Standard_True;//Standard_False;
1239 for(TopTools_ListIteratorOfListOfShape aItF(theList2); aItF.More() && isNeedJoin; aItF.Next())
1241 if(aItF.Value().IsSame(anExpf2.Current())) continue;
1242 TopoDS_Shape aF = Context()->Apply(aItF.Value());
1243 //aF = aF.Oriented(TopAbs_FORWARD);
1244 for(TopoDS_Iterator aIw(aF); aIw.More(); aIw.Next())
1246 if(aIw.Value().ShapeType() != TopAbs_WIRE) continue;
1247 TopoDS_Wire wt = TopoDS::Wire(aIw.Value());
1248 Handle(ShapeFix_Wire) SFW1 = new ShapeFix_Wire;
1251 Handle(ShapeExtend_WireData) atmpswd = SFW1->WireData();
1252 Standard_Integer ind1 = atmpswd->Index(edge1);
1253 Standard_Integer ind2 = atmpswd->Index(edge2);
1256 isNeedJoin = ((ind1 -ind2) ==1 || (ind2 == atmpswd->NbEdges() && ind1 ==1));
1261 Standard_Boolean ReplaceFirst = Standard_True;
1265 TopTools_ListOfShape aListF;
1266 for(TopTools_ListIteratorOfListOfShape aItlF(theList2); aItlF.More(); aItlF.Next())
1268 TopoDS_Shape tmpF = Context()->Apply(aItlF.Value());
1269 aListF.Append(tmpF);
1271 ReplaceFirst = JoinEdges(edge1,edge2,edge3,aListF);
1273 else edge3 = TopoDS_Edge();
1277 myStatusSmallEdges |= ShapeExtend::EncodeStatus( ShapeExtend_FAIL1 );
1281 // Record vertex replacements in the map
1282 TopoDS_Vertex oldV1 = SAE.FirstVertex(edge3),
1283 oldV2 = SAE.LastVertex(edge3);
1284 if (!theNewVertices.IsBound(oldV1))
1287 TopoDS_Shape emptyCopiedV1 = oldV1.EmptyCopied();
1288 theNewVertices.Bind(oldV1,TopoDS::Vertex(emptyCopiedV1));
1290 if (!oldV1.IsSame(oldV2))
1291 if (!theNewVertices.IsBound(oldV2))
1294 TopoDS_Shape emptyCopiedV2 = oldV2.EmptyCopied();
1295 theNewVertices.Bind(oldV2,TopoDS::Vertex(emptyCopiedV2));
1297 //To keep NM vertices belonging initial edges
1298 TopoDS_Iterator aItv(edge1,Standard_False);
1299 for( ; aItv.More(); aItv.Next()) {
1300 if(aItv.Value().Orientation() == TopAbs_INTERNAL ||
1301 aItv.Value().Orientation() == TopAbs_EXTERNAL) {
1303 TopoDS_Vertex aOldV = TopoDS::Vertex(aItv.Value());
1304 TopoDS_Vertex anewV = ShapeAnalysis_TransferParametersProj::CopyNMVertex(aOldV,edge3,edge1);
1305 aB.Add(edge3,anewV);
1306 Context()->Replace(aOldV,anewV);
1310 for(aItv.Initialize(edge2,Standard_False) ; aItv.More(); aItv.Next()) {
1311 if(aItv.Value().Orientation() == TopAbs_INTERNAL ||
1312 aItv.Value().Orientation() == TopAbs_EXTERNAL){
1314 TopoDS_Vertex aOldV = TopoDS::Vertex(aItv.Value());
1315 TopoDS_Vertex anewV = ShapeAnalysis_TransferParametersProj::CopyNMVertex(aOldV,edge3,edge2);
1316 aB.Add(edge3,anewV);
1317 Context()->Replace(aOldV,anewV);
1320 // Check for small resulting edge
1321 Standard_Boolean newsmall = Standard_False;
1322 ShapeAnalysis_Wire SAW;
1323 SAW.Load(SFW->WireData());
1324 SAW.SetPrecision(Precision());
1325 // Make changes in WireData and Context
1328 Context()->Replace(edge1,edge3);
1329 Context()->Remove(edge2);
1330 SendWarning( edge2, Message_Msg("FixWireframe.FixSmallEdges.MSG0"));
1334 Context()->Replace(edge2,edge3);
1335 Context()->Remove(edge1);
1336 SendWarning( edge1, Message_Msg("FixWireframe.FixSmallEdges.MSG0"));
1340 SFW->WireData()->Set(edge3,next);
1341 newsmall = SAW.CheckSmall(next,Precision());
1345 SFW->WireData()->Set(edge3,prev);
1346 newsmall = SAW.CheckSmall(prev,Precision());
1348 SFW->WireData()->Remove(index);
1349 // Process changes in maps
1350 TopTools_ListOfShape theList;
1351 theList.Append(theList2);
1352 theEdgeToFaces.UnBind(edge1);
1353 theEdgeToFaces.UnBind(edge2);
1354 theEdgeToFaces.Bind(edge3,theList);
1355 if (theSmallEdges.Contains(edge1)) theSmallEdges.Remove(edge1);
1356 if (theSmallEdges.Contains(edge2)) theSmallEdges.Remove(edge2);
1357 if (newsmall) theSmallEdges.Add(edge3);
1358 for (TopTools_ListIteratorOfListOfShape itlf(theList);
1359 itlf.More(); itlf.Next())
1361 TopoDS_Shape curface = itlf.Value();
1362 if (theFaceWithSmall.IsBound(curface))
1364 TopTools_ListOfShape& theEdges = theFaceWithSmall(curface);
1365 if (newsmall) theEdges.Append(edge3);
1366 TopTools_ListIteratorOfListOfShape ite(theEdges);
1369 TopoDS_Shape iedge = ite.Value();
1370 if (iedge.IsSame(edge1) || iedge.IsSame(edge2))
1371 theEdges.Remove(ite);
1374 // Remove face without small edges from the map
1375 if (!theEdges.Extent()) theFaceWithSmall.UnBind(curface);
1378 myStatusSmallEdges |= ShapeExtend::EncodeStatus( ShapeExtend_DONE1 );
1383 Handle(ShapeExtend_WireData) tempWire = new ShapeExtend_WireData();
1384 ShapeAnalysis_Wire tempSaw;
1385 tempWire->Add(SFW->Wire());
1386 TopoDS_Edge remedge;
1389 else remedge = edge2;
1390 tempWire->Remove (index );
1391 tempSaw.Load(tempWire);
1392 Standard_Integer newindex = (index <= tempSaw.NbEdges() ? index : 1);
1393 tempSaw.CheckConnected(newindex,Precision());
1394 if(!tempSaw.LastCheckStatus(ShapeExtend_FAIL))
1396 SFW->WireData()->Remove (index );
1397 TopoDS_Edge tmpedge1 = tempWire->Edge(newindex);
1398 TopoDS_Edge tmpedge2 = tempWire->Edge(newindex == 1 ? tempSaw.NbEdges() : (newindex- 1));
1399 TopTools_ListOfShape aL1;
1400 if(theEdgeToFaces.IsBound(tmpedge1))
1401 aL1 = theEdgeToFaces.Find(tmpedge1);
1402 TopTools_ListOfShape aL2;
1403 if(theEdgeToFaces.IsBound(tmpedge2))
1404 aL2= theEdgeToFaces.Find(tmpedge2);
1405 SFW->FixConnected(newindex <= SFW->NbEdges() ? newindex : 1,Precision());
1406 SFW->FixDegenerated(newindex <= SFW->NbEdges() ? newindex : 1);
1407 TopoDS_Shape aTmpShape = Context()->Apply(tmpedge1); //for porting
1408 TopoDS_Edge anewedge1 = TopoDS::Edge(aTmpShape);
1409 aTmpShape = Context()->Apply(tmpedge2);
1410 TopoDS_Edge anewedge2 = TopoDS::Edge(aTmpShape);
1411 Context()->Remove(remedge);
1412 SendWarning( remedge, Message_Msg("FixWireframe.FixSmallEdges.MSG0"));
1413 if (theSmallEdges.Contains(remedge))
1414 theSmallEdges.Remove(remedge);
1415 theEdgeToFaces.UnBind(remedge);
1416 theEdgeToFaces.UnBind(tmpedge1);
1417 theEdgeToFaces.UnBind(tmpedge2);
1418 theEdgeToFaces.Bind(anewedge1,aL1);
1419 theEdgeToFaces.Bind(anewedge2,aL2);
1420 if (theSmallEdges.Contains(tmpedge1))
1422 theSmallEdges.Remove(tmpedge1);
1423 theSmallEdges.Add(anewedge1);
1424 for (TopTools_ListIteratorOfListOfShape itlf(aL1);
1425 itlf.More(); itlf.Next())
1427 TopoDS_Shape curface = itlf.Value();
1428 TopTools_ListOfShape& theEdges = theFaceWithSmall(curface);
1429 TopTools_ListIteratorOfListOfShape ite(theEdges);
1432 TopoDS_Shape iedge = ite.Value();
1433 if (iedge.IsSame(tmpedge1))
1435 theEdges.Remove(ite);
1436 theEdges.Append(anewedge1);
1442 if (theSmallEdges.Contains(tmpedge2))
1444 theSmallEdges.Remove(tmpedge2);
1445 theSmallEdges.Add(anewedge2);
1446 for (TopTools_ListIteratorOfListOfShape itlf(aL2);
1447 itlf.More(); itlf.Next())
1449 TopoDS_Shape curface = itlf.Value();
1450 TopTools_ListOfShape& theEdges = theFaceWithSmall(curface);
1451 TopTools_ListIteratorOfListOfShape ite(theEdges);
1454 TopoDS_Shape iedge = ite.Value();
1455 if (iedge.IsSame(tmpedge2))
1457 theEdges.Remove(ite);
1458 theEdges.Append(anewedge2);
1464 myStatusSmallEdges |= ShapeExtend::EncodeStatus( ShapeExtend_DONE3 );
1470 //gka protection aginst removing circles
1471 TopoDS_Edge ed = (take_next ? edge1 : edge2);
1472 ShapeAnalysis_Edge sae;
1473 Handle(Geom_Curve) c3d;
1474 Standard_Real f1,l1;
1475 if(sae.Curve3d(ed,c3d,f1,l1,Standard_False))
1480 c3d->D0((f1 +l1)*0.5,p3);
1482 if(p1.Distance(p3) > p1.Distance(p2))
1488 if (take_next && theList2.Extent()== 1)
1490 TopoDS_Vertex V1 = SAE.FirstVertex(edge1),
1491 V2 = SAE.LastVertex(edge1);
1494 SFW->WireData()->Remove (index );
1495 Context()->Remove(edge1);
1496 SendWarning( edge1, Message_Msg("FixWireframe.FixSmallEdges.MSG0"));
1497 if (theSmallEdges.Contains(edge1)) theSmallEdges.Remove(edge1);
1498 theEdgeToFaces.UnBind(edge1);
1499 myStatusSmallEdges |= ShapeExtend::EncodeStatus( ShapeExtend_DONE2 );
1503 else if( !take_next && theList2.Extent()== 1)
1505 TopoDS_Vertex V1 = SAE.FirstVertex(edge2),
1506 V2 = SAE.LastVertex(edge2);
1509 SFW->WireData()->Remove (index );
1510 Context()->Remove(edge2);
1511 SendWarning( edge2, Message_Msg("FixWireframe.FixSmallEdges.MSG0"));
1512 if (theSmallEdges.Contains(edge2)) theSmallEdges.Remove(edge2);
1513 theEdgeToFaces.UnBind(edge2);
1514 myStatusSmallEdges |= ShapeExtend::EncodeStatus( ShapeExtend_DONE2 );
1523 if (SFW->NbEdges() == 1 && aModeDrop)
1525 edge1 = SFW->WireData()->Edge(1);
1526 if (theSmallEdges.Contains(edge1))
1528 SFW->WireData()->Remove(1);
1529 Context()->Remove(edge1);
1530 SendWarning( edge1, Message_Msg("FixWireframe.FixSmallEdges.MSG0"));
1531 theSmallEdges.Remove(edge1);
1532 theEdgeToFaces.UnBind(edge1);
1533 Context()->Remove(aWire);
1534 SendWarning( aWire, Message_Msg("FixWireframe.FixSmallEdges.MSG1"));
1535 myStatusSmallEdges |= ShapeExtend::EncodeStatus( ShapeExtend_DONE2 );
1540 SFW->FixConnected();
1541 Context()->Replace(aWire,SFW->Wire());
1545 // Record vertex replacements in context
1546 for (TopTools_DataMapIteratorOfDataMapOfShapeShape itv(theNewVertices);
1547 itv.More(); itv.Next()) Context()->Replace(itv.Key(),itv.Value());
1549 TopoDS_Shape shape = myShape;
1551 myShape = Context()->Apply(shape);
1553 ShapeFix::SameParameter(myShape,Standard_False);
1555 return StatusSmallEdges( ShapeExtend_DONE );
1558 return Standard_False;