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.
18 #include <BRep_Builder.hxx>
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>
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>
37 #include <ShapeFix_Wire.hxx>
38 #include <ShapeFix_Wireframe.hxx>
39 #include <Standard_ErrorHandler.hxx>
40 #include <Standard_Failure.hxx>
41 #include <Standard_Type.hxx>
42 #include <TopExp_Explorer.hxx>
44 #include <TopoDS_Compound.hxx>
45 #include <TopoDS_Edge.hxx>
46 #include <TopoDS_Face.hxx>
47 #include <TopoDS_Iterator.hxx>
48 #include <TopoDS_Shape.hxx>
49 #include <TopoDS_Vertex.hxx>
50 #include <TopTools_DataMapIteratorOfDataMapOfShapeShape.hxx>
51 #include <TopTools_DataMapOfShapeInteger.hxx>
52 #include <TopTools_DataMapOfShapeListOfShape.hxx>
53 #include <TopTools_DataMapOfShapeShape.hxx>
54 #include <TopTools_ListIteratorOfListOfShape.hxx>
55 #include <TopTools_ListOfShape.hxx>
56 #include <TopTools_MapOfShape.hxx>
58 IMPLEMENT_STANDARD_RTTIEXT(ShapeFix_Wireframe,ShapeFix_Root)
60 //#include <Geom2dConvert_CompCurveToBSplineCurve.hxx>
61 //=======================================================================
62 //function : ShapeFix_Wireframe
64 //=======================================================================
65 ShapeFix_Wireframe::ShapeFix_Wireframe()
68 myModeDrop = Standard_False;
72 //=======================================================================
73 //function : ShapeFix_Wireframe
75 //=======================================================================
77 ShapeFix_Wireframe::ShapeFix_Wireframe(const TopoDS_Shape& shape)
81 myModeDrop = Standard_False;
85 //=======================================================================
86 //function : ClearStatuses
88 //=======================================================================
90 void ShapeFix_Wireframe::ClearStatuses()
92 Standard_Integer emptyStatus = ShapeExtend::EncodeStatus( ShapeExtend_OK );
94 myStatusWireGaps = emptyStatus;
95 myStatusSmallEdges = emptyStatus;
98 //=======================================================================
101 //=======================================================================
103 void ShapeFix_Wireframe::Load(const TopoDS_Shape& shape)
109 //=======================================================================
110 //function : FixWireGaps
112 //=======================================================================
114 Standard_Boolean ShapeFix_Wireframe::FixWireGaps()
116 myStatusWireGaps = ShapeExtend::EncodeStatus( ShapeExtend_OK );
117 if (myShape.IsNull()) return Standard_False;
119 if (Context().IsNull()) SetContext(new ShapeBuild_ReShape);
122 TopoDS_Shape shape = myShape;
124 myShape = Context()->Apply(shape);
127 Standard_Real prec = (Precision()>0.)? Precision() : Precision::Confusion();
128 TopTools_DataMapOfShapeShape cont;
129 if ( myShape.ShapeType() == TopAbs_COMPOUND )
131 Standard_Boolean locModified = Standard_False;
134 B.MakeCompound ( C );
135 TopoDS_Shape savShape = myShape;
136 for ( TopoDS_Iterator it(savShape); it.More(); it.Next() )
138 TopoDS_Shape shape1 = it.Value();
139 TopLoc_Location L = shape1.Location(),nullLoc;
140 shape1.Location ( nullLoc );
142 if ( cont.IsBound ( shape1 ) )
144 res = cont.Find ( shape1 ).Oriented ( shape1.Orientation() );
151 cont.Bind(myShape,res);
153 if ( ! res.IsSame ( shape1 ) ) locModified = Standard_True;
160 C.Orientation(savShape.Orientation());
161 Context()->Replace(savShape,C);
163 myShape = Context()->Apply(savShape);
164 return StatusWireGaps(ShapeExtend_DONE);
166 Handle(ShapeFix_Wire) sfw = new ShapeFix_Wire;
167 sfw->SetContext(Context());
168 sfw->SetPrecision(prec);
171 for (TopExp_Explorer anExpf1(myShape,TopAbs_FACE); anExpf1.More(); anExpf1.Next())
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())
179 if(itw.Value().ShapeType() != TopAbs_WIRE)
182 TopoDS_Shape tmpW = Context()->Apply(itw.Value());
183 sfw->Init(TopoDS::Wire(tmpW), face, prec);
186 if (sfw->StatusGaps3d(ShapeExtend_DONE))
187 myStatusWireGaps |= ShapeExtend::EncodeStatus( ShapeExtend_DONE1 );
188 if (sfw->StatusGaps3d(ShapeExtend_FAIL))
189 myStatusWireGaps |= ShapeExtend::EncodeStatus( ShapeExtend_FAIL1 );
191 if (sfw->StatusGaps2d(ShapeExtend_DONE))
192 myStatusWireGaps |= ShapeExtend::EncodeStatus( ShapeExtend_DONE2 );
193 if (sfw->StatusGaps2d(ShapeExtend_FAIL))
194 myStatusWireGaps |= ShapeExtend::EncodeStatus( ShapeExtend_FAIL2 );
195 if (sfw->StatusGaps3d(ShapeExtend_DONE) || sfw->StatusGaps2d(ShapeExtend_DONE))
196 SendWarning( itw.Value(), Message_Msg( "FixWireframe.FixFixWireGaps.MSG0" ));
200 //============================================================
202 //Purpose: This block fixing a 3d wire which not lie on plane
204 //============================================================
205 for (TopExp_Explorer expw(myShape,TopAbs_WIRE,TopAbs_FACE); expw.More(); expw.Next())
207 TopoDS_Shape tmpW = Context()->Apply(expw.Current());
208 sfw->Load(TopoDS::Wire(tmpW));
209 sfw->SetPrecision(prec);
212 if (sfw->StatusGaps3d(ShapeExtend_DONE))
213 myStatusWireGaps |= ShapeExtend::EncodeStatus( ShapeExtend_DONE1 );
214 if (sfw->StatusGaps3d(ShapeExtend_FAIL))
215 myStatusWireGaps |= ShapeExtend::EncodeStatus( ShapeExtend_FAIL1 );
216 if (sfw->StatusGaps3d(ShapeExtend_DONE))
217 SendWarning( expw.Current(), Message_Msg( "FixWireframe.FixFixWireGaps.MSG0" ));
219 //End Part1========================================================
221 if (StatusWireGaps(ShapeExtend_DONE))
224 myShape = Context()->Apply(myShape);
226 ShapeFix::SameParameter(myShape,Standard_False);
229 Handle(ShapeFix_Edge) sfe = new ShapeFix_Edge;
230 for (TopExp_Explorer anExpf2(myShape,TopAbs_FACE); anExpf2.More(); anExpf2.Next())
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())
236 if(itw.Value().ShapeType() != TopAbs_WIRE)
238 wire = TopoDS::Wire(itw.Value());
239 sfw->Init(wire, face, prec);
241 sfw->FixSelfIntersection();
242 for (TopoDS_Iterator ite(wire); ite.More(); ite.Next())
243 sfe->FixVertexTolerance(TopoDS::Edge(ite.Value()));
248 for (TopExp_Explorer expw2(myShape,TopAbs_WIRE,TopAbs_FACE); expw2.More(); expw2.Next())
250 wire = TopoDS::Wire(expw2.Current());
252 sfw->SetPrecision(prec);
254 sfw->FixSelfIntersection();
255 for (TopoDS_Iterator ite(wire); ite.More(); ite.Next())
256 sfe->FixVertexTolerance(TopoDS::Edge(ite.Value()));
261 return Standard_True;
264 return Standard_False;
267 //=======================================================================
268 //function : JoinEdges (static)
269 //purpose : used in FixSmallEdges
270 //=======================================================================
272 static Standard_Boolean JoinEdges(const TopoDS_Edge& E1,
273 const TopoDS_Edge& E2,
275 const TopTools_ListOfShape& faces)
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;
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);
289 Standard_Boolean isSame = (V11.IsSame(V12) || V22.IsSame(V21));
292 Standard_Real cf1,cf2,cl1,cl2,first1,first2,last1,last2;
293 newedge.Orientation(TopAbs_FORWARD);
297 if(!sae.Curve3d(E1,c3d1,cf1,cl1,Standard_False )) return ReplaceFirst;
298 if(!sae.Curve3d(E2,c3d2,cf2,cl2,Standard_False )) return ReplaceFirst;
301 B.Add(newedge,V11.Oriented(TopAbs_FORWARD));
302 B.Add(newedge,V22.Oriented(TopAbs_REVERSED));
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))
309 // if(isRev1 || isRev2)
310 if(!isSame && (isRev1 || isRev2))
312 ReplaceFirst = (!isRev1);
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)
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);
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);
338 for(TopTools_ListIteratorOfListOfShape iter(faces); iter.More(); iter.Next())
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;
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))
349 if(ismanifold && (!isSame && (isRev12 || isRev22)))
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;
362 // dealing with seams: the same again
363 if(sae.IsSeam(E1,face) && sae.IsSeam(E2,face))
365 Handle(Geom2d_Curve) c2d12,c2d22;
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 );
374 Handle(Geom2d_Curve) C2dRes2;
375 if(!ShapeConstruct::JoinCurves(c2d12,c2d22,OrEdge1,OrEdge2,first1, last1,first2, last2,C2dRes2,isRev12,isRev22,isSame))
377 if(!isSame && (isRev1 || isRev2))
379 B.UpdateEdge(newedge,C2dRes,C2dRes2,face,0);
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);
386 newedge.Orientation(ReplaceFirst ? OrEdge1 :OrEdge2 );
388 B.SameRange(newedge,Standard_False);
393 catch ( Standard_Failure const& anException) {
395 cout<<"Error: ShapeFix_Wireframe::FixSmallEdges: JoinEdges: Exception in GeomConvert_CompCurveToBSplineCurve: ";
396 anException.Print(cout); cout<<endl;
403 //=======================================================================
404 //function : FixSmallEdges
406 //=======================================================================
408 Standard_Boolean ShapeFix_Wireframe::FixSmallEdges()
410 myStatusSmallEdges = ShapeExtend::EncodeStatus( ShapeExtend_OK );
411 if (myShape.IsNull()) return Standard_False;
413 if (Context().IsNull()) SetContext(new ShapeBuild_ReShape);
416 TopoDS_Shape shape = myShape;
418 myShape = Context()->Apply(shape);
420 TopTools_DataMapOfShapeShape cont;
421 if ( myShape.ShapeType() == TopAbs_COMPOUND )
423 Standard_Boolean locModified = Standard_False;
426 B.MakeCompound ( C );
427 TopoDS_Shape savShape = myShape;
428 for ( TopoDS_Iterator it(savShape); it.More(); it.Next() )
430 TopoDS_Shape shape1 = it.Value();
431 TopLoc_Location L = shape1.Location(),nullLoc;
432 shape1.Location ( nullLoc );
434 if ( cont.IsBound ( shape1 ) )
436 res = cont.Find ( shape1 ).Oriented ( shape1.Orientation() );
443 cont.Bind(myShape,res);
445 if ( ! res.IsSame ( shape1 ) ) locModified = Standard_True;
447 //check if resulting shape if not empty
457 C.Orientation(savShape.Orientation());
458 Context()->Replace(savShape,C);
460 myShape = Context()->Apply(savShape);
461 return StatusSmallEdges( ShapeExtend_DONE );
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 );
470 //=======================================================================
471 //function : CheckSmallEdges
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)
484 ShapeAnalysis_Wire SAW;
486 for (TopExp_Explorer anExpf1(myShape,TopAbs_FACE); anExpf1.More(); anExpf1.Next())
488 TopTools_ListOfShape theEdgeList;
489 TopoDS_Face facet = TopoDS::Face(anExpf1.Current());
491 if (facet.Orientation()==TopAbs_REVERSED) face = TopoDS::Face(facet.Oriented(TopAbs_FORWARD));
492 for (TopoDS_Iterator itw(face); itw.More(); itw.Next())
494 if(itw.Value().ShapeType() != TopAbs_WIRE)
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;
502 for (i=1; i<=SAW.NbEdges(); i++)
504 edge = SAW.WireData()->Edge(i);
505 if (EdgeMap.IsBound(edge))
506 EdgeMap.ChangeFind(edge)++;
508 EdgeMap.Bind(edge,1);
511 for ( i=1; i<=SAW.NbEdges(); i++)
513 edge = SAW.WireData()->Edge(i);
514 if(EdgeMap.Find(edge)!=1)
516 if(!SAW.WireData()->IsSeam(i))
517 theMultyEdges.Add(edge);
520 // Append current face to the list
521 if (theEdgeToFaces.IsBound(edge))
523 theEdgeToFaces(edge).Append(facet);
527 TopTools_ListOfShape theFaceList;
528 theFaceList.Append(facet);
529 theEdgeToFaces.Bind(edge,theFaceList);
531 // Check if current edge is small
532 if (theSmallEdges.Contains(edge)) theEdgeList.Append(edge);
533 else if (SAW.CheckSmall(i,Precision()))
535 theSmallEdges.Add(edge);
536 theEdgeList.Append(edge);
540 // Add current face to the map if has small edges
541 if (theEdgeList.Extent()) theFaceWithSmall.Bind(facet,theEdgeList);
544 //========================================================================
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())
550 SAW.SetPrecision(Precision());
551 TopTools_DataMapOfShapeInteger EdgeMap;
553 TopoDS_Wire theWire=TopoDS::Wire(expw1.Current());
554 TopTools_ListOfShape theEdgeList;
558 return Standard_False;
560 for (i=1; i<=SAW.NbEdges(); i++)
562 edge = SAW.WireData()->Edge(i);
563 if (EdgeMap.IsBound(edge))
564 EdgeMap.ChangeFind(edge)++;
566 EdgeMap.Bind(edge,1);
569 for ( i=1; i<=SAW.NbEdges(); i++)
571 edge = SAW.WireData()->Edge(i);
572 if(EdgeMap.Find(edge)!=1)
574 if(!SAW.WireData()->IsSeam(i))
575 theMultyEdges.Add(edge);
579 // Check if current edge is small
580 if (theSmallEdges.Contains(edge)) theEdgeList.Append(edge);
581 else if (SAW.CheckSmall(i,Precision()))
583 theSmallEdges.Add(edge);
584 theEdgeList.Append(edge);
589 return (!theSmallEdges.IsEmpty());
593 //=======================================================================
594 //function : MergeSmallEdges
596 //=======================================================================
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)
605 Standard_Boolean aModLimitAngle = (theLimitAngle >-1.0 || myLimitAngle > -1.0);
606 Standard_Real aLimitAngle = Max(theLimitAngle,myLimitAngle);
608 Standard_Boolean aModeDrop = theModeDrop || myModeDrop;
609 TopTools_DataMapOfShapeShape theNewVertices;
610 if (!theSmallEdges.IsEmpty())
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())
621 if (theFaceWithSmall.IsBound(anExpf2.Current()))
623 if (theFaceWithSmall(anExpf2.Current()).Extent())
626 TopoDS_Shape tmpShape = Context()->Apply(anExpf2.Current());
627 TopoDS_Face facet = TopoDS::Face(tmpShape);
628 if(!facet.IsSame(anExpf2.Current()))
630 TopExp_Explorer aExpEdge(anExpf2.Current(),TopAbs_EDGE);
631 for( ; aExpEdge.More(); aExpEdge.Next())
633 TopoDS_Shape newEdge;
634 Standard_Integer stat = Context()->Status(aExpEdge.Current(),newEdge,Standard_True);
637 if(theSmallEdges.Contains(aExpEdge.Current()))
639 theSmallEdges.Remove(aExpEdge.Current());
640 theSmallEdges.Add(newEdge);
642 if(theEdgeToFaces.IsBound(aExpEdge.Current()))
644 TopTools_ListOfShape aListFaces;
645 aListFaces = theEdgeToFaces.Find(aExpEdge.Current());
646 theEdgeToFaces.UnBind(aExpEdge.Current());
647 theEdgeToFaces.Bind(newEdge,aListFaces);
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())
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);
666 Standard_Integer prev, next, index = 1;
668 while (index <= SFW->WireData()->NbEdges() && SFW->NbEdges()>1)
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);
676 //gka protection against joining seem edge
677 if(edge2.IsSame(edge1) || edge2.IsSame(edge3))
679 //if(BRep_Tool::IsClosed(edge2,face)) {
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))
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))
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();
707 Standard_Real tol2 = Precision::SquareConfusion();
708 if ( Vec1.SquareMagnitude() < tol2 ||
709 Vec2.SquareMagnitude() < tol2 ) Ang1 = M_PI/2.;
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 ||
716 Vec2.SquareMagnitude() < tol2 ) Ang2 = M_PI/2.;
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; }
722 //if(theLimitAngle != -1 && Ang1 > theLimitAngle && Ang2 >theLimitAngle) {
723 // index++; continue;
726 // Check if edges lay on the same faces
727 if(theMultyEdges.Contains(edge1) || theMultyEdges.Contains(edge2))
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;
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());
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());
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());
764 if(same_set1 && same_set2)
766 same_set = Standard_True;
767 if(fabs(Ang2-Ang1) >Precision::Angular())
768 take_next = (Ang2<Ang1);
771 edge1 = edge2; edge2 = edge3;
773 isLimAngle = (aModLimitAngle && Min(Ang1,Ang2) > aLimitAngle);
775 else if(same_set1 && !same_set2)
777 isLimAngle = (aModLimitAngle && Ang1 > aLimitAngle);
778 same_set = Standard_True;
780 else if(!same_set1 && same_set2)
782 same_set = Standard_True;
783 isLimAngle = (aModLimitAngle && Ang2 > aLimitAngle);
784 edge1 = edge2; edge2 = edge3;
785 take_next = Standard_True;
787 if (same_set && !isLimAngle )
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())
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())
799 if(aIw.Value().ShapeType() != TopAbs_WIRE) continue;
800 TopoDS_Wire wt = TopoDS::Wire(aIw.Value());
801 Handle(ShapeFix_Wire) SFW1 = new ShapeFix_Wire;
804 Handle(ShapeExtend_WireData) atmpswd = SFW1->WireData();
805 Standard_Integer ind1 = atmpswd->Index(edge1);
806 Standard_Integer ind2 = atmpswd->Index(edge2);
809 isNeedJoin = ((ind1 -ind2) ==1 || (ind2 == atmpswd->NbEdges() && ind1 ==1));
814 Standard_Boolean ReplaceFirst = Standard_True;
818 TopTools_ListOfShape aListF;
819 for(TopTools_ListIteratorOfListOfShape aItlF(theList2); aItlF.More(); aItlF.Next())
821 TopoDS_Shape tmpF = Context()->Apply(aItlF.Value());
824 ReplaceFirst = JoinEdges(edge1,edge2,edge3,aListF);
826 else edge3 = TopoDS_Edge();
830 myStatusSmallEdges |= ShapeExtend::EncodeStatus( ShapeExtend_FAIL1 );
834 // Record vertex replacements in the map
835 TopoDS_Vertex oldV1 = SAE.FirstVertex(edge3),
836 oldV2 = SAE.LastVertex(edge3);
837 if (!theNewVertices.IsBound(oldV1))
840 TopoDS_Shape emptyCopiedV1 = oldV1.EmptyCopied();
841 theNewVertices.Bind(oldV1,TopoDS::Vertex(emptyCopiedV1));
843 if (!oldV1.IsSame(oldV2))
844 if (!theNewVertices.IsBound(oldV2))
847 TopoDS_Shape emptyCopiedV2 = oldV2.EmptyCopied();
848 theNewVertices.Bind(oldV2,TopoDS::Vertex(emptyCopiedV2));
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);
860 Context()->Replace(aOldV,anewV);
864 for(aItv.Initialize(edge2,Standard_False) ; aItv.More(); aItv.Next()) {
865 if(aItv.Value().Orientation() == TopAbs_INTERNAL ||
866 aItv.Value().Orientation() == TopAbs_EXTERNAL){
868 TopoDS_Vertex aOldV = TopoDS::Vertex(aItv.Value());
869 TopoDS_Vertex anewV = ShapeAnalysis_TransferParametersProj::CopyNMVertex(aOldV,edge3,edge2);
871 Context()->Replace(aOldV,anewV);
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
882 Context()->Replace(edge1,edge3);
883 Context()->Remove(edge2);
884 SendWarning( edge2, Message_Msg("FixWireframe.FixSmallEdges.MSG0"));
888 Context()->Replace(edge2,edge3);
889 Context()->Remove(edge1);
890 SendWarning( edge1, Message_Msg("FixWireframe.FixSmallEdges.MSG0"));
894 SFW->WireData()->Set(edge3,next);
895 newsmall = SAW.CheckSmall(next,Precision());
899 SFW->WireData()->Set(edge3,prev);
900 newsmall = SAW.CheckSmall(prev,Precision());
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())
915 TopoDS_Shape curface = itlf.Value();
916 if (theFaceWithSmall.IsBound(curface))
918 TopTools_ListOfShape& theEdges = theFaceWithSmall(curface);
919 if (newsmall) theEdges.Append(edge3);
920 TopTools_ListIteratorOfListOfShape ite(theEdges);
923 TopoDS_Shape iedge = ite.Value();
924 if (iedge.IsSame(edge1) || iedge.IsSame(edge2))
925 theEdges.Remove(ite);
928 // Remove face without small edges from the map
929 if (!theEdges.Extent()) theFaceWithSmall.UnBind(curface);
932 myStatusSmallEdges |= ShapeExtend::EncodeStatus( ShapeExtend_DONE1 );
937 Handle(ShapeExtend_WireData) tempWire = new ShapeExtend_WireData();
938 ShapeAnalysis_Wire tempSaw;
939 tempWire->Add(SFW->Wire());
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))
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);
966 SendWarning( remedge, Message_Msg("FixWireframe.FixSmallEdges.MSG0"));
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))
976 theSmallEdges.Remove(tmpedge1);
977 theSmallEdges.Add(anewedge1);
978 for (TopTools_ListIteratorOfListOfShape itlf(aL1);
979 itlf.More(); itlf.Next())
981 TopoDS_Shape curface = itlf.Value();
982 TopTools_ListOfShape& theEdges = theFaceWithSmall(curface);
983 TopTools_ListIteratorOfListOfShape ite(theEdges);
986 TopoDS_Shape iedge = ite.Value();
987 if (iedge.IsSame(tmpedge1))
989 theEdges.Remove(ite);
990 theEdges.Append(anewedge1);
996 if (theSmallEdges.Contains(tmpedge2))
998 theSmallEdges.Remove(tmpedge2);
999 theSmallEdges.Add(anewedge2);
1000 for (TopTools_ListIteratorOfListOfShape itlf(aL2);
1001 itlf.More(); itlf.Next())
1003 TopoDS_Shape curface = itlf.Value();
1004 TopTools_ListOfShape& theEdges = theFaceWithSmall(curface);
1005 TopTools_ListIteratorOfListOfShape ite(theEdges);
1008 TopoDS_Shape iedge = ite.Value();
1009 if (iedge.IsSame(tmpedge2))
1011 theEdges.Remove(ite);
1012 theEdges.Append(anewedge2);
1018 myStatusSmallEdges |= ShapeExtend::EncodeStatus( ShapeExtend_DONE3 );
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))
1034 c3d->D0((f1 +l1)*0.5,p3);
1036 if(p1.Distance(p3) > p1.Distance(p2))
1042 if (take_next && theList2.Extent()== 1)
1044 TopoDS_Vertex V1 = SAE.FirstVertex(edge1),
1045 V2 = SAE.LastVertex(edge1);
1048 SFW->WireData()->Remove (index );
1049 Context()->Remove(edge1);
1050 SendWarning( edge1, Message_Msg("FixWireframe.FixSmallEdges.MSG0"));
1051 if (theSmallEdges.Contains(edge1)) theSmallEdges.Remove(edge1);
1052 theEdgeToFaces.UnBind(edge1);
1053 myStatusSmallEdges |= ShapeExtend::EncodeStatus( ShapeExtend_DONE2 );
1057 else if( !take_next && theList2.Extent()== 1)
1059 TopoDS_Vertex V1 = SAE.FirstVertex(edge2),
1060 V2 = SAE.LastVertex(edge2);
1063 SFW->WireData()->Remove (index );
1064 Context()->Remove(edge2);
1065 SendWarning( edge2, Message_Msg("FixWireframe.FixSmallEdges.MSG0"));
1066 if (theSmallEdges.Contains(edge2)) theSmallEdges.Remove(edge2);
1067 theEdgeToFaces.UnBind(edge2);
1068 myStatusSmallEdges |= ShapeExtend::EncodeStatus( ShapeExtend_DONE2 );
1077 if (SFW->NbEdges() == 1 && aModeDrop)
1079 edge1 = SFW->WireData()->Edge(1);
1080 if (theSmallEdges.Contains(edge1))
1082 SFW->WireData()->Remove(1);
1083 Context()->Remove(edge1);
1084 SendWarning( edge1, Message_Msg("FixWireframe.FixSmallEdges.MSG0"));
1085 theSmallEdges.Remove(edge1);
1086 theEdgeToFaces.UnBind(edge1);
1087 Context()->Remove(aWire);
1088 SendWarning( aWire, Message_Msg("FixWireframe.FixSmallEdges.MSG1"));
1089 myStatusSmallEdges |= ShapeExtend::EncodeStatus( ShapeExtend_DONE2 );
1094 SFW->FixConnected();
1095 Context()->Replace(aWire,SFW->Wire());
1098 face.Orientation(facet.Orientation());
1099 TopoDS_Shape anewShape = Context()->Apply(face);
1100 TopoDS_Iterator aIter(anewShape);
1102 Context()->Remove(anewShape);
1103 SendWarning( face, Message_Msg("FixWireframe.FixSmallEdges.MSG2"));
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())
1113 TopoDS_Wire aWire = TopoDS::Wire(expw1.Current());
1116 Standard_Integer prev, next, index = 1;
1117 while (index <= SFW->NbEdges() && SFW->NbEdges()>1)
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);
1125 //gka protection against joining seem edge
1126 if(edge2.IsSame(edge1) || edge2.IsSame(edge3))
1128 //if(BRep_Tool::IsClosed(edge2,face)) {
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))
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))
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();
1156 Standard_Real tol2 = Precision::SquareConfusion();
1157 if ( Vec1.SquareMagnitude() < tol2 ||
1158 Vec2.SquareMagnitude() < tol2 ) Ang1 = M_PI/2.;
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 ||
1165 Vec2.SquareMagnitude() < tol2 ) Ang2 = M_PI/2.;
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; }
1171 //if(theLimitAngle != -1 && Ang1 > theLimitAngle && Ang2 >theLimitAngle) {
1172 // index++; continue;
1175 // Check if edges lay on the same faces
1176 if(theMultyEdges.Contains(edge1) || theMultyEdges.Contains(edge2))
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;
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());
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());
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());
1213 if(same_set1 && same_set2)
1215 same_set = Standard_True;
1216 if(fabs(Ang2-Ang1) >Precision::Angular())
1217 take_next = (Ang2<Ang1);
1220 edge1 = edge2; edge2 = edge3;
1222 isLimAngle = (aModLimitAngle && Min(Ang1,Ang2) > aLimitAngle);
1224 else if(same_set1 && !same_set2)
1226 isLimAngle = (aModLimitAngle && Ang1 > aLimitAngle);
1227 same_set = Standard_True;
1229 else if(!same_set1 && same_set2)
1231 same_set = Standard_True;
1232 isLimAngle = (aModLimitAngle && Ang2 > aLimitAngle);
1233 edge1 = edge2; edge2 = edge3;
1234 take_next = Standard_True;
1236 if (same_set && !isLimAngle )
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())
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())
1248 if(aIw.Value().ShapeType() != TopAbs_WIRE) continue;
1249 TopoDS_Wire wt = TopoDS::Wire(aIw.Value());
1250 Handle(ShapeFix_Wire) SFW1 = new ShapeFix_Wire;
1253 Handle(ShapeExtend_WireData) atmpswd = SFW1->WireData();
1254 Standard_Integer ind1 = atmpswd->Index(edge1);
1255 Standard_Integer ind2 = atmpswd->Index(edge2);
1258 isNeedJoin = ((ind1 -ind2) ==1 || (ind2 == atmpswd->NbEdges() && ind1 ==1));
1263 Standard_Boolean ReplaceFirst = Standard_True;
1267 TopTools_ListOfShape aListF;
1268 for(TopTools_ListIteratorOfListOfShape aItlF(theList2); aItlF.More(); aItlF.Next())
1270 TopoDS_Shape tmpF = Context()->Apply(aItlF.Value());
1271 aListF.Append(tmpF);
1273 ReplaceFirst = JoinEdges(edge1,edge2,edge3,aListF);
1275 else edge3 = TopoDS_Edge();
1279 myStatusSmallEdges |= ShapeExtend::EncodeStatus( ShapeExtend_FAIL1 );
1283 // Record vertex replacements in the map
1284 TopoDS_Vertex oldV1 = SAE.FirstVertex(edge3),
1285 oldV2 = SAE.LastVertex(edge3);
1286 if (!theNewVertices.IsBound(oldV1))
1289 TopoDS_Shape emptyCopiedV1 = oldV1.EmptyCopied();
1290 theNewVertices.Bind(oldV1,TopoDS::Vertex(emptyCopiedV1));
1292 if (!oldV1.IsSame(oldV2))
1293 if (!theNewVertices.IsBound(oldV2))
1296 TopoDS_Shape emptyCopiedV2 = oldV2.EmptyCopied();
1297 theNewVertices.Bind(oldV2,TopoDS::Vertex(emptyCopiedV2));
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) {
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);
1312 for(aItv.Initialize(edge2,Standard_False) ; aItv.More(); aItv.Next()) {
1313 if(aItv.Value().Orientation() == TopAbs_INTERNAL ||
1314 aItv.Value().Orientation() == TopAbs_EXTERNAL){
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);
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
1330 Context()->Replace(edge1,edge3);
1331 Context()->Remove(edge2);
1332 SendWarning( edge2, Message_Msg("FixWireframe.FixSmallEdges.MSG0"));
1336 Context()->Replace(edge2,edge3);
1337 Context()->Remove(edge1);
1338 SendWarning( edge1, Message_Msg("FixWireframe.FixSmallEdges.MSG0"));
1342 SFW->WireData()->Set(edge3,next);
1343 newsmall = SAW.CheckSmall(next,Precision());
1347 SFW->WireData()->Set(edge3,prev);
1348 newsmall = SAW.CheckSmall(prev,Precision());
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())
1363 TopoDS_Shape curface = itlf.Value();
1364 if (theFaceWithSmall.IsBound(curface))
1366 TopTools_ListOfShape& theEdges = theFaceWithSmall(curface);
1367 if (newsmall) theEdges.Append(edge3);
1368 TopTools_ListIteratorOfListOfShape ite(theEdges);
1371 TopoDS_Shape iedge = ite.Value();
1372 if (iedge.IsSame(edge1) || iedge.IsSame(edge2))
1373 theEdges.Remove(ite);
1376 // Remove face without small edges from the map
1377 if (!theEdges.Extent()) theFaceWithSmall.UnBind(curface);
1380 myStatusSmallEdges |= ShapeExtend::EncodeStatus( ShapeExtend_DONE1 );
1385 Handle(ShapeExtend_WireData) tempWire = new ShapeExtend_WireData();
1386 ShapeAnalysis_Wire tempSaw;
1387 tempWire->Add(SFW->Wire());
1388 TopoDS_Edge remedge;
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))
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);
1414 SendWarning( remedge, Message_Msg("FixWireframe.FixSmallEdges.MSG0"));
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))
1424 theSmallEdges.Remove(tmpedge1);
1425 theSmallEdges.Add(anewedge1);
1426 for (TopTools_ListIteratorOfListOfShape itlf(aL1);
1427 itlf.More(); itlf.Next())
1429 TopoDS_Shape curface = itlf.Value();
1430 TopTools_ListOfShape& theEdges = theFaceWithSmall(curface);
1431 TopTools_ListIteratorOfListOfShape ite(theEdges);
1434 TopoDS_Shape iedge = ite.Value();
1435 if (iedge.IsSame(tmpedge1))
1437 theEdges.Remove(ite);
1438 theEdges.Append(anewedge1);
1444 if (theSmallEdges.Contains(tmpedge2))
1446 theSmallEdges.Remove(tmpedge2);
1447 theSmallEdges.Add(anewedge2);
1448 for (TopTools_ListIteratorOfListOfShape itlf(aL2);
1449 itlf.More(); itlf.Next())
1451 TopoDS_Shape curface = itlf.Value();
1452 TopTools_ListOfShape& theEdges = theFaceWithSmall(curface);
1453 TopTools_ListIteratorOfListOfShape ite(theEdges);
1456 TopoDS_Shape iedge = ite.Value();
1457 if (iedge.IsSame(tmpedge2))
1459 theEdges.Remove(ite);
1460 theEdges.Append(anewedge2);
1466 myStatusSmallEdges |= ShapeExtend::EncodeStatus( ShapeExtend_DONE3 );
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))
1482 c3d->D0((f1 +l1)*0.5,p3);
1484 if(p1.Distance(p3) > p1.Distance(p2))
1490 if (take_next && theList2.Extent()== 1)
1492 TopoDS_Vertex V1 = SAE.FirstVertex(edge1),
1493 V2 = SAE.LastVertex(edge1);
1496 SFW->WireData()->Remove (index );
1497 Context()->Remove(edge1);
1498 SendWarning( edge1, Message_Msg("FixWireframe.FixSmallEdges.MSG0"));
1499 if (theSmallEdges.Contains(edge1)) theSmallEdges.Remove(edge1);
1500 theEdgeToFaces.UnBind(edge1);
1501 myStatusSmallEdges |= ShapeExtend::EncodeStatus( ShapeExtend_DONE2 );
1505 else if( !take_next && theList2.Extent()== 1)
1507 TopoDS_Vertex V1 = SAE.FirstVertex(edge2),
1508 V2 = SAE.LastVertex(edge2);
1511 SFW->WireData()->Remove (index );
1512 Context()->Remove(edge2);
1513 SendWarning( edge2, Message_Msg("FixWireframe.FixSmallEdges.MSG0"));
1514 if (theSmallEdges.Contains(edge2)) theSmallEdges.Remove(edge2);
1515 theEdgeToFaces.UnBind(edge2);
1516 myStatusSmallEdges |= ShapeExtend::EncodeStatus( ShapeExtend_DONE2 );
1525 if (SFW->NbEdges() == 1 && aModeDrop)
1527 edge1 = SFW->WireData()->Edge(1);
1528 if (theSmallEdges.Contains(edge1))
1530 SFW->WireData()->Remove(1);
1531 Context()->Remove(edge1);
1532 SendWarning( edge1, Message_Msg("FixWireframe.FixSmallEdges.MSG0"));
1533 theSmallEdges.Remove(edge1);
1534 theEdgeToFaces.UnBind(edge1);
1535 Context()->Remove(aWire);
1536 SendWarning( aWire, Message_Msg("FixWireframe.FixSmallEdges.MSG1"));
1537 myStatusSmallEdges |= ShapeExtend::EncodeStatus( ShapeExtend_DONE2 );
1542 SFW->FixConnected();
1543 Context()->Replace(aWire,SFW->Wire());
1547 // Record vertex replacements in context
1548 for (TopTools_DataMapIteratorOfDataMapOfShapeShape itv(theNewVertices);
1549 itv.More(); itv.Next()) Context()->Replace(itv.Key(),itv.Value());
1551 TopoDS_Shape shape = myShape;
1553 myShape = Context()->Apply(shape);
1555 ShapeFix::SameParameter(myShape,Standard_False);
1557 return StatusSmallEdges( ShapeExtend_DONE );
1560 return Standard_False;