1 // Created on: 1999-08-24
2 // Created by: Sergei ZERTCHANINOV
3 // Copyright (c) 1999 Matra Datavision
4 // Copyright (c) 1999-2012 OPEN CASCADE SAS
6 // The content of this file is subject to the Open CASCADE Technology Public
7 // License Version 6.5 (the "License"). You may not use the content of this file
8 // except in compliance with the License. Please obtain a copy of the License
9 // at http://www.opencascade.org and read it completely before using this file.
11 // The Initial Developer of the Original Code is Open CASCADE S.A.S., having its
12 // main offices at: 1, place des Freres Montgolfier, 78280 Guyancourt, France.
14 // The Original Code and all software distributed under the License is
15 // distributed on an "AS IS" basis, without warranty of any kind, and the
16 // Initial Developer hereby disclaims all such warranties, including without
17 // limitation, any warranties of merchantability, fitness for a particular
18 // purpose or non-infringement. Please see the License for the specific terms
19 // and conditions governing the rights and limitations under the License.
22 #include <ShapeFix_Wireframe.ixx>
24 #include <Standard_Failure.hxx>
25 #include <Standard_ErrorHandler.hxx>
27 //#include <Geom2dConvert_CompCurveToBSplineCurve.hxx>
28 #include <ShapeBuild_ReShape.hxx>
29 #include <TopTools_DataMapOfShapeShape.hxx>
30 #include <TopoDS_Compound.hxx>
31 #include <BRep_Builder.hxx>
32 #include <TopoDS_Iterator.hxx>
33 #include <ShapeFix_Wire.hxx>
34 #include <TopoDS_Face.hxx>
35 #include <TopExp_Explorer.hxx>
37 #include <ShapeFix.hxx>
38 #include <ShapeFix_Edge.hxx>
39 #include <ShapeConstruct_Curve.hxx>
40 #include <TopoDS_Edge.hxx>
41 #include <TopoDS_Vertex.hxx>
42 #include <ShapeAnalysis_Edge.hxx>
43 #include <Geom_Curve.hxx>
44 #include <Geom_BSplineCurve.hxx>
46 #include <GeomConvert_CompCurveToBSplineCurve.hxx>
47 #include <BRep_Tool.hxx>
48 #include <TopTools_ListIteratorOfListOfShape.hxx>
49 #include <Geom2d_Curve.hxx>
50 #include <Geom2d_BSplineCurve.hxx>
52 #include <GeomAPI.hxx>
53 #include <TopTools_ListOfShape.hxx>
54 #include <TopTools_MapOfShape.hxx>
55 #include <TopTools_DataMapOfShapeListOfShape.hxx>
56 #include <TopTools_DataMapOfShapeInteger.hxx>
57 #include <TopTools_DataMapIteratorOfDataMapOfShapeShape.hxx>
58 #include <ShapeConstruct.hxx>
59 #include <ShapeBuild_Edge.hxx>
60 #include <ShapeAnalysis_TransferParametersProj.hxx>
62 //=======================================================================
63 //function : ShapeFix_Wireframe
65 //=======================================================================
67 ShapeFix_Wireframe::ShapeFix_Wireframe()
70 myModeDrop = Standard_False;
74 //=======================================================================
75 //function : ShapeFix_Wireframe
77 //=======================================================================
79 ShapeFix_Wireframe::ShapeFix_Wireframe(const TopoDS_Shape& shape)
83 myModeDrop = Standard_False;
87 //=======================================================================
88 //function : ClearStatuses
90 //=======================================================================
92 void ShapeFix_Wireframe::ClearStatuses()
94 Standard_Integer emptyStatus = ShapeExtend::EncodeStatus( ShapeExtend_OK );
96 myStatusWireGaps = emptyStatus;
97 myStatusSmallEdges = emptyStatus;
100 //=======================================================================
103 //=======================================================================
105 void ShapeFix_Wireframe::Load(const TopoDS_Shape& shape)
111 //=======================================================================
112 //function : FixWireGaps
114 //=======================================================================
116 Standard_Boolean ShapeFix_Wireframe::FixWireGaps()
118 myStatusWireGaps = ShapeExtend::EncodeStatus( ShapeExtend_OK );
119 if (myShape.IsNull()) return Standard_False;
121 if (Context().IsNull()) SetContext(new ShapeBuild_ReShape);
124 TopoDS_Shape shape = myShape;
126 myShape = Context()->Apply(shape);
129 Standard_Real prec = (Precision()>0.)? Precision() : Precision::Confusion();
130 TopTools_DataMapOfShapeShape cont;
131 if ( myShape.ShapeType() == TopAbs_COMPOUND )
133 Standard_Boolean locModified = Standard_False;
136 B.MakeCompound ( C );
137 TopoDS_Shape savShape = myShape;
138 for ( TopoDS_Iterator it(savShape); it.More(); it.Next() )
140 TopoDS_Shape shape1 = it.Value();
141 TopLoc_Location L = shape1.Location(),nullLoc;
142 shape1.Location ( nullLoc );
144 if ( cont.IsBound ( shape1 ) )
146 res = cont.Find ( shape1 ).Oriented ( shape1.Orientation() );
153 cont.Bind(myShape,res);
155 if ( ! res.IsSame ( shape1 ) ) locModified = Standard_True;
162 C.Orientation(savShape.Orientation());
163 Context()->Replace(savShape,C);
165 myShape = Context()->Apply(savShape);
166 return StatusWireGaps(ShapeExtend_DONE);
168 Handle(ShapeFix_Wire) sfw = new ShapeFix_Wire;
169 sfw->SetContext(Context());
170 sfw->SetPrecision(prec);
173 for (TopExp_Explorer anExpf1(myShape,TopAbs_FACE); anExpf1.More(); anExpf1.Next())
176 TopoDS_Shape tmpF = Context()->Apply(anExpf1.Current());
177 face = TopoDS::Face(tmpF);
178 if (face.Orientation()==TopAbs_REVERSED) face.Orientation(TopAbs_FORWARD);
179 for (TopoDS_Iterator itw(face); itw.More(); itw.Next())
181 if(itw.Value().ShapeType() != TopAbs_WIRE)
184 TopoDS_Shape tmpW = Context()->Apply(itw.Value());
185 sfw->Init(TopoDS::Wire(tmpW), face, prec);
188 if (sfw->StatusGaps3d(ShapeExtend_DONE))
189 myStatusWireGaps |= ShapeExtend::EncodeStatus( ShapeExtend_DONE1 );
190 if (sfw->StatusGaps3d(ShapeExtend_FAIL))
191 myStatusWireGaps |= ShapeExtend::EncodeStatus( ShapeExtend_FAIL1 );
193 if (sfw->StatusGaps2d(ShapeExtend_DONE))
194 myStatusWireGaps |= ShapeExtend::EncodeStatus( ShapeExtend_DONE2 );
195 if (sfw->StatusGaps2d(ShapeExtend_FAIL))
196 myStatusWireGaps |= ShapeExtend::EncodeStatus( ShapeExtend_FAIL2 );
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 );
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;
402 //=======================================================================
403 //function : FixSmallEdges
405 //=======================================================================
407 Standard_Boolean ShapeFix_Wireframe::FixSmallEdges()
409 myStatusSmallEdges = ShapeExtend::EncodeStatus( ShapeExtend_OK );
410 if (myShape.IsNull()) return Standard_False;
412 if (Context().IsNull()) SetContext(new ShapeBuild_ReShape);
415 TopoDS_Shape shape = myShape;
417 myShape = Context()->Apply(shape);
419 TopTools_DataMapOfShapeShape cont;
420 if ( myShape.ShapeType() == TopAbs_COMPOUND )
422 Standard_Boolean locModified = Standard_False;
425 B.MakeCompound ( C );
426 TopoDS_Shape savShape = myShape;
427 for ( TopoDS_Iterator it(savShape); it.More(); it.Next() )
429 TopoDS_Shape shape1 = it.Value();
430 TopLoc_Location L = shape1.Location(),nullLoc;
431 shape1.Location ( nullLoc );
433 if ( cont.IsBound ( shape1 ) )
435 res = cont.Find ( shape1 ).Oriented ( shape1.Orientation() );
442 cont.Bind(myShape,res);
444 if ( ! res.IsSame ( shape1 ) ) locModified = Standard_True;
451 C.Orientation(savShape.Orientation());
452 Context()->Replace(savShape,C);
454 myShape = Context()->Apply(savShape);
455 return StatusSmallEdges( ShapeExtend_DONE );
457 TopTools_MapOfShape theSmallEdges, theMultyEdges;
458 TopTools_DataMapOfShapeListOfShape theEdgeToFaces,theFaceWithSmall;
459 CheckSmallEdges ( theSmallEdges,theEdgeToFaces,theFaceWithSmall, theMultyEdges);
460 MergeSmallEdges ( theSmallEdges,theEdgeToFaces,theFaceWithSmall, theMultyEdges);
461 return StatusSmallEdges( ShapeExtend_DONE );
464 //=======================================================================
465 //function : CheckSmallEdges
467 //=======================================================================
468 #include <BRepBuilderAPI_MakeFace.hxx>
469 #include <TopExp.hxx>
470 #include <TopTools_IndexedDataMapOfShapeListOfShape.hxx>
471 Standard_Boolean ShapeFix_Wireframe::CheckSmallEdges(TopTools_MapOfShape& theSmallEdges,
472 TopTools_DataMapOfShapeListOfShape& theEdgeToFaces,
473 TopTools_DataMapOfShapeListOfShape& theFaceWithSmall,
474 TopTools_MapOfShape& theMultyEdges)
478 ShapeAnalysis_Wire SAW;
480 for (TopExp_Explorer anExpf1(myShape,TopAbs_FACE); anExpf1.More(); anExpf1.Next())
482 TopTools_ListOfShape theEdgeList;
483 TopoDS_Face facet = TopoDS::Face(anExpf1.Current());
485 if (facet.Orientation()==TopAbs_REVERSED) face = TopoDS::Face(facet.Oriented(TopAbs_FORWARD));
486 for (TopoDS_Iterator itw(face); itw.More(); itw.Next())
488 if(itw.Value().ShapeType() != TopAbs_WIRE)
490 TopoDS_Wire aW = TopoDS::Wire(itw.Value());
491 Handle(ShapeExtend_WireData) aswd = new ShapeExtend_WireData(aW,Standard_True,Standard_False);
492 SAW.Init(aswd,face,Precision());
493 // pnd protection on seam edges
494 TopTools_DataMapOfShapeInteger EdgeMap;
496 for (i=1; i<=SAW.NbEdges(); i++)
498 edge = SAW.WireData()->Edge(i);
499 if (EdgeMap.IsBound(edge))
500 EdgeMap.ChangeFind(edge)++;
502 EdgeMap.Bind(edge,1);
505 for ( i=1; i<=SAW.NbEdges(); i++)
507 edge = SAW.WireData()->Edge(i);
508 if(EdgeMap.Find(edge)!=1)
510 if(!SAW.WireData()->IsSeam(i))
511 theMultyEdges.Add(edge);
514 // Append current face to the list
515 if (theEdgeToFaces.IsBound(edge))
517 theEdgeToFaces(edge).Append(facet);
521 TopTools_ListOfShape theFaceList;
522 theFaceList.Append(facet);
523 theEdgeToFaces.Bind(edge,theFaceList);
525 // Check if current edge is small
526 if (theSmallEdges.Contains(edge)) theEdgeList.Append(edge);
527 else if (SAW.CheckSmall(i,Precision()))
529 theSmallEdges.Add(edge);
530 theEdgeList.Append(edge);
534 // Add current face to the map if has small edges
535 if (theEdgeList.Extent()) theFaceWithSmall.Bind(facet,theEdgeList);
538 //========================================================================
540 // Purpose: Analizing of shape for small edges , if edge don't lie on face
541 //========================================================================
542 for (TopExp_Explorer expw1(myShape,TopAbs_WIRE,TopAbs_FACE); expw1.More(); expw1.Next())
544 SAW.SetPrecision(Precision());
545 TopTools_DataMapOfShapeInteger EdgeMap;
547 TopoDS_Wire theWire=TopoDS::Wire(expw1.Current());
548 TopTools_ListOfShape theEdgeList;
552 return Standard_False;
554 for (i=1; i<=SAW.NbEdges(); i++)
556 edge = SAW.WireData()->Edge(i);
557 if (EdgeMap.IsBound(edge))
558 EdgeMap.ChangeFind(edge)++;
560 EdgeMap.Bind(edge,1);
563 for ( i=1; i<=SAW.NbEdges(); i++)
565 edge = SAW.WireData()->Edge(i);
566 if(EdgeMap.Find(edge)!=1)
568 if(!SAW.WireData()->IsSeam(i))
569 theMultyEdges.Add(edge);
573 // Check if current edge is small
574 if (theSmallEdges.Contains(edge)) theEdgeList.Append(edge);
575 else if (SAW.CheckSmall(i,Precision()))
577 theSmallEdges.Add(edge);
578 theEdgeList.Append(edge);
583 return (!theSmallEdges.IsEmpty());
587 //=======================================================================
588 //function : MergeSmallEdges
590 //=======================================================================
592 Standard_Boolean ShapeFix_Wireframe::MergeSmallEdges(TopTools_MapOfShape& theSmallEdges,
593 TopTools_DataMapOfShapeListOfShape& theEdgeToFaces,
594 TopTools_DataMapOfShapeListOfShape& theFaceWithSmall,
595 TopTools_MapOfShape& theMultyEdges,
596 const Standard_Boolean theModeDrop,
597 const Standard_Real theLimitAngle)
599 Standard_Boolean aModLimitAngle = (theLimitAngle >-1.0 || myLimitAngle > -1.0);
600 Standard_Real aLimitAngle = Max(theLimitAngle,myLimitAngle);
602 Standard_Boolean aModeDrop = theModeDrop || myModeDrop;
603 TopTools_DataMapOfShapeShape theNewVertices;
604 if (!theSmallEdges.IsEmpty())
607 Handle(ShapeFix_Wire) SFW = new ShapeFix_Wire;
608 SFW->SetContext(Context());
609 ShapeAnalysis_Edge SAE;
610 TopoDS_Edge edge1, edge2, edge3;
611 // Iterate on map of faces with small edges
612 TopExp_Explorer anExpf2(myShape,TopAbs_FACE);
613 for (; anExpf2.More(); anExpf2.Next())
615 if (theFaceWithSmall.IsBound(anExpf2.Current()))
617 if (theFaceWithSmall(anExpf2.Current()).Extent())
620 TopoDS_Shape tmpShape = Context()->Apply(anExpf2.Current());
621 TopoDS_Face facet = TopoDS::Face(tmpShape);
622 if(!facet.IsSame(anExpf2.Current()))
624 TopExp_Explorer aExpEdge(anExpf2.Current(),TopAbs_EDGE);
625 for( ; aExpEdge.More(); aExpEdge.Next())
627 TopoDS_Shape newEdge;
628 Standard_Integer stat = Context()->Status(aExpEdge.Current(),newEdge,Standard_True);
631 if(theSmallEdges.Contains(aExpEdge.Current()))
633 theSmallEdges.Remove(aExpEdge.Current());
634 theSmallEdges.Add(newEdge);
636 if(theEdgeToFaces.IsBound(aExpEdge.Current()))
638 TopTools_ListOfShape aListFaces;
639 aListFaces = theEdgeToFaces.Find(aExpEdge.Current());
640 theEdgeToFaces.UnBind(aExpEdge.Current());
641 theEdgeToFaces.Bind(newEdge,aListFaces);
647 TopoDS_Face face = facet;
648 //if (face.Orientation()==TopAbs_REVERSED)
649 // face = TopoDS::Face(facet.Oriented(TopAbs_FORWARD));
650 for (TopoDS_Iterator itw(face); itw.More(); itw.Next())
652 if(itw.Value().ShapeType() != TopAbs_WIRE) continue;
653 TopoDS_Wire aWire = TopoDS::Wire(itw.Value());
654 if (face.Orientation()==TopAbs_REVERSED)
655 face = TopoDS::Face(facet.Oriented(TopAbs_FORWARD));
656 Handle(ShapeExtend_WireData) aswd = new ShapeExtend_WireData(aWire,Standard_True,Standard_False);
660 Standard_Integer prev, next, index = 1;
662 while (index <= SFW->WireData()->NbEdges() && SFW->NbEdges()>1)
664 prev = (index==1)? SFW->WireData()->NbEdges() : index-1;
665 next = (index==SFW->WireData()->NbEdges())? 1 : index+1;
666 edge1 = SFW->WireData()->Edge(prev);
667 edge2 = SFW->WireData()->Edge(index);
668 edge3 = SFW->WireData()->Edge(next);
670 //gka protection against joining seem edge
671 if(edge2.IsSame(edge1) || edge2.IsSame(edge3))
673 //if(BRep_Tool::IsClosed(edge2,face)) {
678 Standard_Boolean isSeam = SFW->WireData()->IsSeam(index);
679 Standard_Boolean isSeam1 = SFW->WireData()->IsSeam(prev);
680 Standard_Boolean isSeam2 = SFW->WireData()->IsSeam(next);
681 if (theSmallEdges.Contains(edge2))
683 // Middle edge is small - choose a pair of edges to join
684 Standard_Boolean IsAnyJoin = (edge1.IsSame(edge3));
685 Standard_Boolean take_next = IsAnyJoin; //Standard_False;
686 Standard_Boolean isLimAngle = Standard_False;
687 Handle(Geom_Curve) C1, C2, C3;
688 Standard_Real aux, last1, first2, last2, first3;
689 Standard_Real Ang1 = 0., Ang2 =0.;
690 if (SAE.Curve3d(edge1,C1,aux,last1) &&
691 SAE.Curve3d(edge2,C2,first2,last2) &&
692 SAE.Curve3d(edge3,C3,first3,aux))
694 // Compare angles between edges
695 //Standard_Real Ang1, Ang2;
696 gp_Vec Vec1, Vec2; gp_Pnt P;
697 C1->D1(last1,P,Vec1);
698 C2->D1(first2,P,Vec2);
699 if ( edge1.Orientation() == TopAbs_REVERSED ) Vec1.Reverse();
700 if ( edge2.Orientation() == TopAbs_REVERSED ) Vec2.Reverse();
701 Standard_Real tol2 = Precision::SquareConfusion();
702 if ( Vec1.SquareMagnitude() < tol2 ||
703 Vec2.SquareMagnitude() < tol2 ) Ang1 = M_PI/2.;
704 else Ang1 = Abs(Vec1.Angle(Vec2));
705 C2->D1(last2,P,Vec1);
706 C3->D1(first3,P,Vec2);
707 if ( edge2.Orientation() == TopAbs_REVERSED ) Vec1.Reverse();
708 if ( edge3.Orientation() == TopAbs_REVERSED ) Vec2.Reverse();
709 if ( Vec1.SquareMagnitude() < tol2 ||
710 Vec2.SquareMagnitude() < tol2 ) Ang2 = M_PI/2.;
711 else Ang2 = Abs(Vec1.Angle(Vec2));
712 //isLimAngle = (theLimitAngle != -1 && Min(Ang1,Ang2) > theLimitAngle);
713 //take_next = (Ang2<Ang1);
714 //if (take_next) { edge1 = edge2; edge2 = edge3; }
716 //if(theLimitAngle != -1 && Ang1 > theLimitAngle && Ang2 >theLimitAngle) {
717 // index++; continue;
720 // Check if edges lay on the same faces
721 if(theMultyEdges.Contains(edge1) || theMultyEdges.Contains(edge2))
726 TopTools_ListOfShape theList1,theList2,theList3;
727 if(theEdgeToFaces.IsBound(edge1))
728 theList1 = theEdgeToFaces(edge1);
729 if(theEdgeToFaces.IsBound(edge2))
730 theList2 = theEdgeToFaces(edge2);
731 if(theEdgeToFaces.IsBound(edge3))
732 theList3 = theEdgeToFaces(edge3);
733 Standard_Boolean same_set = Standard_False;
735 //gka protection against joining seem edges with other edges
736 Standard_Boolean same_set1 = (theList1.Extent()==theList2.Extent() &&
737 ((!isSeam && !isSeam1)|| (isSeam && isSeam1))); //gka
738 Standard_Boolean same_set2 = (theList3.Extent()==theList2.Extent() &&
739 ((!isSeam && !isSeam2)|| (isSeam && isSeam2)));
740 TopTools_MapOfShape theSetOfFaces;
741 for (TopTools_ListIteratorOfListOfShape itf1(theList2);
742 itf1.More(); itf1.Next())
743 theSetOfFaces.Add(itf1.Value());
746 // Add all faces of the first edge to the current set
747 for (TopTools_ListIteratorOfListOfShape itf2(theList1);
748 (itf2.More() && same_set1); itf2.Next())
749 same_set1 = theSetOfFaces.Contains(itf2.Value());
753 // Add all faces of the first edge to the current set
754 for (TopTools_ListIteratorOfListOfShape itf2(theList3);
755 (itf2.More() && same_set2); itf2.Next())
756 same_set2 = theSetOfFaces.Contains(itf2.Value());
758 if(same_set1 && same_set2)
760 same_set = Standard_True;
761 if(fabs(Ang2-Ang1) >Precision::Angular())
762 take_next = (Ang2<Ang1);
765 edge1 = edge2; edge2 = edge3;
767 isLimAngle = (aModLimitAngle && Min(Ang1,Ang2) > aLimitAngle);
769 else if(same_set1 && !same_set2)
771 isLimAngle = (aModLimitAngle && Ang1 > aLimitAngle);
772 same_set = Standard_True;
774 else if(!same_set1 && same_set2)
776 same_set = Standard_True;
777 isLimAngle = (aModLimitAngle && Ang2 > aLimitAngle);
778 edge1 = edge2; edge2 = edge3;
779 take_next = Standard_True;
781 if (same_set && !isLimAngle )
783 // Merge current pair of edges
784 //gka protection against crossing seem on second face
785 Standard_Boolean isNeedJoin = Standard_True;//Standard_False;
786 for(TopTools_ListIteratorOfListOfShape aItF(theList2); aItF.More() && isNeedJoin; aItF.Next())
788 if(aItF.Value().IsSame(anExpf2.Current())) continue;
789 TopoDS_Shape aF = Context()->Apply(aItF.Value());
790 //aF = aF.Oriented(TopAbs_FORWARD);
791 for(TopoDS_Iterator aIw(aF); aIw.More(); aIw.Next())
793 if(aIw.Value().ShapeType() != TopAbs_WIRE) continue;
794 TopoDS_Wire wt = TopoDS::Wire(aIw.Value());
795 Handle(ShapeFix_Wire) SFW1 = new ShapeFix_Wire;
798 Handle(ShapeExtend_WireData) atmpswd = SFW1->WireData();
799 Standard_Integer ind1 = atmpswd->Index(edge1);
800 Standard_Integer ind2 = atmpswd->Index(edge2);
803 isNeedJoin = ((ind1 -ind2) ==1 || (ind2 == atmpswd->NbEdges() && ind1 ==1));
808 Standard_Boolean ReplaceFirst = Standard_True;
812 TopTools_ListOfShape aListF;
813 for(TopTools_ListIteratorOfListOfShape aItlF(theList2); aItlF.More(); aItlF.Next())
815 TopoDS_Shape tmpF = Context()->Apply(aItlF.Value());
818 ReplaceFirst = JoinEdges(edge1,edge2,edge3,aListF);
820 else edge3 = TopoDS_Edge();
824 myStatusSmallEdges |= ShapeExtend::EncodeStatus( ShapeExtend_FAIL1 );
828 // Record vertex replacements in the map
829 TopoDS_Vertex oldV1 = SAE.FirstVertex(edge3),
830 oldV2 = SAE.LastVertex(edge3);
831 if (!theNewVertices.IsBound(oldV1))
834 TopoDS_Shape emptyCopiedV1 = oldV1.EmptyCopied();
835 theNewVertices.Bind(oldV1,TopoDS::Vertex(emptyCopiedV1));
837 if (!oldV1.IsSame(oldV2))
838 if (!theNewVertices.IsBound(oldV2))
841 TopoDS_Shape emptyCopiedV2 = oldV2.EmptyCopied();
842 theNewVertices.Bind(oldV2,TopoDS::Vertex(emptyCopiedV2));
845 //To keep NM vertices belonging initial edges
846 TopoDS_Iterator aItv(edge1,Standard_False);
847 for( ; aItv.More(); aItv.Next()) {
848 if(aItv.Value().Orientation() == TopAbs_INTERNAL ||
849 aItv.Value().Orientation() == TopAbs_EXTERNAL) {
850 TopoDS_Vertex aOldV = TopoDS::Vertex(aItv.Value());
851 TopoDS_Vertex anewV = ShapeAnalysis_TransferParametersProj::CopyNMVertex(aOldV,edge3,edge1);
854 Context()->Replace(aOldV,anewV);
858 for(aItv.Initialize(edge2,Standard_False) ; aItv.More(); aItv.Next()) {
859 if(aItv.Value().Orientation() == TopAbs_INTERNAL ||
860 aItv.Value().Orientation() == TopAbs_EXTERNAL){
862 TopoDS_Vertex aOldV = TopoDS::Vertex(aItv.Value());
863 TopoDS_Vertex anewV = ShapeAnalysis_TransferParametersProj::CopyNMVertex(aOldV,edge3,edge2);
865 Context()->Replace(aOldV,anewV);
869 // Check for small resulting edge
870 Standard_Boolean newsmall = Standard_False;
871 ShapeAnalysis_Wire SAW;
872 SAW.Init(SFW->WireData(),face,Precision());
873 // Make changes in WireData and Context
876 Context()->Replace(edge1,edge3);
877 Context()->Remove(edge2);
881 Context()->Replace(edge2,edge3);
882 Context()->Remove(edge1);
886 SFW->WireData()->Set(edge3,next);
887 newsmall = SAW.CheckSmall(next,Precision());
891 SFW->WireData()->Set(edge3,prev);
892 newsmall = SAW.CheckSmall(prev,Precision());
894 SFW->WireData()->Remove(index);
895 // Process changes in maps
896 TopTools_ListOfShape theList;
897 theList.Append(theList2);
898 theEdgeToFaces.UnBind(edge1);
899 theEdgeToFaces.UnBind(edge2);
900 theEdgeToFaces.Bind(edge3,theList);
901 if (theSmallEdges.Contains(edge1)) theSmallEdges.Remove(edge1);
902 if (theSmallEdges.Contains(edge2)) theSmallEdges.Remove(edge2);
903 if (newsmall) theSmallEdges.Add(edge3);
904 for (TopTools_ListIteratorOfListOfShape itlf(theList);
905 itlf.More(); itlf.Next())
907 TopoDS_Shape curface = itlf.Value();
908 if (theFaceWithSmall.IsBound(curface))
910 TopTools_ListOfShape& theEdges = theFaceWithSmall(curface);
911 if (newsmall) theEdges.Append(edge3);
912 TopTools_ListIteratorOfListOfShape ite(theEdges);
915 TopoDS_Shape iedge = ite.Value();
916 if (iedge.IsSame(edge1) || iedge.IsSame(edge2))
917 theEdges.Remove(ite);
920 // Remove face without small edges from the map
921 if (!theEdges.Extent()) theFaceWithSmall.UnBind(curface);
924 myStatusSmallEdges |= ShapeExtend::EncodeStatus( ShapeExtend_DONE1 );
929 Handle(ShapeExtend_WireData) tempWire = new ShapeExtend_WireData();
930 ShapeAnalysis_Wire tempSaw;
931 tempWire->Add(SFW->Wire());
935 else remedge = edge2;
936 tempWire->Remove (index );
937 tempSaw.Load(tempWire);
938 Standard_Integer newindex = (index <= tempSaw.NbEdges() ? index : 1);
939 tempSaw.CheckConnected(newindex,Precision());
940 if(!tempSaw.LastCheckStatus(ShapeExtend_FAIL))
942 SFW->WireData()->Remove (index );
943 TopoDS_Edge tmpedge1 = tempWire->Edge(newindex);
944 TopoDS_Edge tmpedge2 = tempWire->Edge(newindex == 1 ? tempSaw.NbEdges() : (newindex- 1));
945 TopTools_ListOfShape aL1;
946 if(theEdgeToFaces.IsBound(tmpedge1))
947 aL1 = theEdgeToFaces.Find(tmpedge1);
948 TopTools_ListOfShape aL2;
949 if(theEdgeToFaces.IsBound(tmpedge2))
950 aL2= theEdgeToFaces.Find(tmpedge2);
951 SFW->FixConnected(newindex <= SFW->NbEdges() ? newindex : 1,Precision());
952 SFW->FixDegenerated(newindex <= SFW->NbEdges() ? newindex : 1);
953 TopoDS_Shape aTmpShape = Context()->Apply(tmpedge1); //for porting
954 TopoDS_Edge anewedge1 = TopoDS::Edge(aTmpShape);
955 aTmpShape = Context()->Apply(tmpedge2);
956 TopoDS_Edge anewedge2 = TopoDS::Edge(aTmpShape);
957 Context()->Remove(remedge);
958 if (theSmallEdges.Contains(remedge))
959 theSmallEdges.Remove(remedge);
960 theEdgeToFaces.UnBind(remedge);
961 theEdgeToFaces.UnBind(tmpedge1);
962 theEdgeToFaces.UnBind(tmpedge2);
963 theEdgeToFaces.Bind(anewedge1,aL1);
964 theEdgeToFaces.Bind(anewedge2,aL2);
965 if (theSmallEdges.Contains(tmpedge1))
967 theSmallEdges.Remove(tmpedge1);
968 theSmallEdges.Add(anewedge1);
969 for (TopTools_ListIteratorOfListOfShape itlf(aL1);
970 itlf.More(); itlf.Next())
972 TopoDS_Shape curface = itlf.Value();
973 TopTools_ListOfShape& theEdges = theFaceWithSmall(curface);
974 TopTools_ListIteratorOfListOfShape ite(theEdges);
977 TopoDS_Shape iedge = ite.Value();
978 if (iedge.IsSame(tmpedge1))
980 theEdges.Remove(ite);
981 theEdges.Append(anewedge1);
987 if (theSmallEdges.Contains(tmpedge2))
989 theSmallEdges.Remove(tmpedge2);
990 theSmallEdges.Add(anewedge2);
991 for (TopTools_ListIteratorOfListOfShape itlf(aL2);
992 itlf.More(); itlf.Next())
994 TopoDS_Shape curface = itlf.Value();
995 TopTools_ListOfShape& theEdges = theFaceWithSmall(curface);
996 TopTools_ListIteratorOfListOfShape ite(theEdges);
999 TopoDS_Shape iedge = ite.Value();
1000 if (iedge.IsSame(tmpedge2))
1002 theEdges.Remove(ite);
1003 theEdges.Append(anewedge2);
1009 myStatusSmallEdges |= ShapeExtend::EncodeStatus( ShapeExtend_DONE3 );
1015 //gka protection aginst removing circles
1016 TopoDS_Edge ed = (take_next ? edge1 : edge2);
1017 ShapeAnalysis_Edge sae;
1018 Handle(Geom_Curve) c3d;
1019 Standard_Real f1,l1;
1020 if(sae.Curve3d(ed,c3d,f1,l1,Standard_False))
1025 c3d->D0((f1 +l1)*0.5,p3);
1027 if(p1.Distance(p3) > p1.Distance(p2))
1033 if (take_next && theList2.Extent()== 1)
1035 TopoDS_Vertex V1 = SAE.FirstVertex(edge1),
1036 V2 = SAE.LastVertex(edge1);
1039 SFW->WireData()->Remove (index );
1040 Context()->Remove(edge1);
1041 if (theSmallEdges.Contains(edge1)) theSmallEdges.Remove(edge1);
1042 theEdgeToFaces.UnBind(edge1);
1043 myStatusSmallEdges |= ShapeExtend::EncodeStatus( ShapeExtend_DONE2 );
1047 else if( !take_next && theList2.Extent()== 1)
1049 TopoDS_Vertex V1 = SAE.FirstVertex(edge2),
1050 V2 = SAE.LastVertex(edge2);
1053 SFW->WireData()->Remove (index );
1054 Context()->Remove(edge2);
1055 if (theSmallEdges.Contains(edge2)) theSmallEdges.Remove(edge2);
1056 theEdgeToFaces.UnBind(edge2);
1057 myStatusSmallEdges |= ShapeExtend::EncodeStatus( ShapeExtend_DONE2 );
1066 if (SFW->NbEdges() == 1 && aModeDrop)
1068 edge1 = SFW->WireData()->Edge(1);
1069 if (theSmallEdges.Contains(edge1))
1071 SFW->WireData()->Remove(1);
1072 Context()->Remove(edge1);
1073 theSmallEdges.Remove(edge1);
1074 theEdgeToFaces.UnBind(edge1);
1075 Context()->Remove(aWire);
1076 myStatusSmallEdges |= ShapeExtend::EncodeStatus( ShapeExtend_DONE2 );
1081 SFW->FixConnected();
1082 Context()->Replace(aWire,SFW->Wire());
1085 face.Orientation(facet.Orientation());
1086 TopoDS_Shape anewShape = Context()->Apply(face);
1087 TopoDS_Iterator aIter(anewShape);
1089 Context()->Remove(anewShape);
1095 // Iterate on map of wires which not lie on faces
1096 for (TopExp_Explorer expw1( myShape, TopAbs_WIRE, TopAbs_FACE); expw1.More(); expw1.Next())
1098 TopoDS_Wire aWire = TopoDS::Wire(expw1.Current());
1101 Standard_Integer prev, next, index = 1;
1102 while (index <= SFW->NbEdges() && SFW->NbEdges()>1)
1104 prev = (index==1)? SFW->NbEdges() : index-1;
1105 next = (index==SFW->NbEdges())? 1 : index+1;
1106 edge1 = SFW->WireData()->Edge(prev);
1107 edge2 = SFW->WireData()->Edge(index);
1108 edge3 = SFW->WireData()->Edge(next);
1110 //gka protection against joining seem edge
1111 if(edge2.IsSame(edge1) || edge2.IsSame(edge3))
1113 //if(BRep_Tool::IsClosed(edge2,face)) {
1118 Standard_Boolean isSeam = SFW->WireData()->IsSeam(index);
1119 Standard_Boolean isSeam1 = SFW->WireData()->IsSeam(prev);
1120 Standard_Boolean isSeam2 = SFW->WireData()->IsSeam(next);
1121 if (theSmallEdges.Contains(edge2))
1123 // Middle edge is small - choose a pair of edges to join
1124 Standard_Boolean IsAnyJoin = (edge1.IsSame(edge3));
1125 Standard_Boolean take_next = IsAnyJoin; //Standard_False;
1126 Standard_Boolean isLimAngle = Standard_False;
1127 Handle(Geom_Curve) C1, C2, C3;
1128 Standard_Real aux, last1, first2, last2, first3;
1129 Standard_Real Ang1 = 0., Ang2 =0.;
1130 if (SAE.Curve3d(edge1,C1,aux,last1) &&
1131 SAE.Curve3d(edge2,C2,first2,last2) &&
1132 SAE.Curve3d(edge3,C3,first3,aux))
1134 // Compare angles between edges
1135 //Standard_Real Ang1, Ang2;
1136 gp_Vec Vec1, Vec2; gp_Pnt P;
1137 C1->D1(last1,P,Vec1);
1138 C2->D1(first2,P,Vec2);
1139 if ( edge1.Orientation() == TopAbs_REVERSED ) Vec1.Reverse();
1140 if ( edge2.Orientation() == TopAbs_REVERSED ) Vec2.Reverse();
1141 Standard_Real tol2 = Precision::SquareConfusion();
1142 if ( Vec1.SquareMagnitude() < tol2 ||
1143 Vec2.SquareMagnitude() < tol2 ) Ang1 = M_PI/2.;
1144 else Ang1 = Abs(Vec1.Angle(Vec2));
1145 C2->D1(last2,P,Vec1);
1146 C3->D1(first3,P,Vec2);
1147 if ( edge2.Orientation() == TopAbs_REVERSED ) Vec1.Reverse();
1148 if ( edge3.Orientation() == TopAbs_REVERSED ) Vec2.Reverse();
1149 if ( Vec1.SquareMagnitude() < tol2 ||
1150 Vec2.SquareMagnitude() < tol2 ) Ang2 = M_PI/2.;
1151 else Ang2 = Abs(Vec1.Angle(Vec2));
1152 //isLimAngle = (theLimitAngle != -1 && Min(Ang1,Ang2) > theLimitAngle);
1153 //take_next = (Ang2<Ang1);
1154 //if (take_next) { edge1 = edge2; edge2 = edge3; }
1156 //if(theLimitAngle != -1 && Ang1 > theLimitAngle && Ang2 >theLimitAngle) {
1157 // index++; continue;
1160 // Check if edges lay on the same faces
1161 if(theMultyEdges.Contains(edge1) || theMultyEdges.Contains(edge2))
1166 TopTools_ListOfShape theList1,theList2,theList3;
1167 if(theEdgeToFaces.IsBound(edge1))
1168 theList1 = theEdgeToFaces(edge1);
1169 if(theEdgeToFaces.IsBound(edge2))
1170 theList2 = theEdgeToFaces(edge2);
1171 if(theEdgeToFaces.IsBound(edge3))
1172 theList3 = theEdgeToFaces(edge3);
1173 Standard_Boolean same_set = Standard_False;
1175 //gka protection against joining seem edges with other edges
1176 Standard_Boolean same_set1 = (theList1.Extent()==theList2.Extent() &&
1177 ((!isSeam && !isSeam1)|| (isSeam && isSeam1))); //gka
1178 Standard_Boolean same_set2 = (theList3.Extent()==theList2.Extent() &&
1179 ((!isSeam && !isSeam2)|| (isSeam && isSeam2)));
1180 TopTools_MapOfShape theSetOfFaces;
1181 for (TopTools_ListIteratorOfListOfShape itf1(theList2);
1182 itf1.More(); itf1.Next())
1183 theSetOfFaces.Add(itf1.Value());
1186 // Add all faces of the first edge to the current set
1187 for (TopTools_ListIteratorOfListOfShape itf2(theList1);
1188 (itf2.More() && same_set1); itf2.Next())
1189 same_set1 = theSetOfFaces.Contains(itf2.Value());
1193 // Add all faces of the first edge to the current set
1194 for (TopTools_ListIteratorOfListOfShape itf2(theList3);
1195 (itf2.More() && same_set2); itf2.Next())
1196 same_set2 = theSetOfFaces.Contains(itf2.Value());
1198 if(same_set1 && same_set2)
1200 same_set = Standard_True;
1201 if(fabs(Ang2-Ang1) >Precision::Angular())
1202 take_next = (Ang2<Ang1);
1205 edge1 = edge2; edge2 = edge3;
1207 isLimAngle = (aModLimitAngle && Min(Ang1,Ang2) > aLimitAngle);
1209 else if(same_set1 && !same_set2)
1211 isLimAngle = (aModLimitAngle && Ang1 > aLimitAngle);
1212 same_set = Standard_True;
1214 else if(!same_set1 && same_set2)
1216 same_set = Standard_True;
1217 isLimAngle = (aModLimitAngle && Ang2 > aLimitAngle);
1218 edge1 = edge2; edge2 = edge3;
1219 take_next = Standard_True;
1221 if (same_set && !isLimAngle )
1223 // Merge current pair of edges
1224 //gka protection against crossing seem on second face
1225 Standard_Boolean isNeedJoin = Standard_True;//Standard_False;
1226 for(TopTools_ListIteratorOfListOfShape aItF(theList2); aItF.More() && isNeedJoin; aItF.Next())
1228 if(aItF.Value().IsSame(anExpf2.Current())) continue;
1229 TopoDS_Shape aF = Context()->Apply(aItF.Value());
1230 //aF = aF.Oriented(TopAbs_FORWARD);
1231 for(TopoDS_Iterator aIw(aF); aIw.More(); aIw.Next())
1233 if(aIw.Value().ShapeType() != TopAbs_WIRE) continue;
1234 TopoDS_Wire wt = TopoDS::Wire(aIw.Value());
1235 Handle(ShapeFix_Wire) SFW1 = new ShapeFix_Wire;
1238 Handle(ShapeExtend_WireData) atmpswd = SFW1->WireData();
1239 Standard_Integer ind1 = atmpswd->Index(edge1);
1240 Standard_Integer ind2 = atmpswd->Index(edge2);
1243 isNeedJoin = ((ind1 -ind2) ==1 || (ind2 == atmpswd->NbEdges() && ind1 ==1));
1248 Standard_Boolean ReplaceFirst = Standard_True;
1252 TopTools_ListOfShape aListF;
1253 for(TopTools_ListIteratorOfListOfShape aItlF(theList2); aItlF.More(); aItlF.Next())
1255 TopoDS_Shape tmpF = Context()->Apply(aItlF.Value());
1256 aListF.Append(tmpF);
1258 ReplaceFirst = JoinEdges(edge1,edge2,edge3,aListF);
1260 else edge3 = TopoDS_Edge();
1264 myStatusSmallEdges |= ShapeExtend::EncodeStatus( ShapeExtend_FAIL1 );
1268 // Record vertex replacements in the map
1269 TopoDS_Vertex oldV1 = SAE.FirstVertex(edge3),
1270 oldV2 = SAE.LastVertex(edge3);
1271 if (!theNewVertices.IsBound(oldV1))
1274 TopoDS_Shape emptyCopiedV1 = oldV1.EmptyCopied();
1275 theNewVertices.Bind(oldV1,TopoDS::Vertex(emptyCopiedV1));
1277 if (!oldV1.IsSame(oldV2))
1278 if (!theNewVertices.IsBound(oldV2))
1281 TopoDS_Shape emptyCopiedV2 = oldV2.EmptyCopied();
1282 theNewVertices.Bind(oldV2,TopoDS::Vertex(emptyCopiedV2));
1284 //To keep NM vertices belonging initial edges
1285 TopoDS_Iterator aItv(edge1,Standard_False);
1286 for( ; aItv.More(); aItv.Next()) {
1287 if(aItv.Value().Orientation() == TopAbs_INTERNAL ||
1288 aItv.Value().Orientation() == TopAbs_EXTERNAL) {
1290 TopoDS_Vertex aOldV = TopoDS::Vertex(aItv.Value());
1291 TopoDS_Vertex anewV = ShapeAnalysis_TransferParametersProj::CopyNMVertex(aOldV,edge3,edge1);
1292 aB.Add(edge3,anewV);
1293 Context()->Replace(aOldV,anewV);
1297 for(aItv.Initialize(edge2,Standard_False) ; aItv.More(); aItv.Next()) {
1298 if(aItv.Value().Orientation() == TopAbs_INTERNAL ||
1299 aItv.Value().Orientation() == TopAbs_EXTERNAL){
1301 TopoDS_Vertex aOldV = TopoDS::Vertex(aItv.Value());
1302 TopoDS_Vertex anewV = ShapeAnalysis_TransferParametersProj::CopyNMVertex(aOldV,edge3,edge2);
1303 aB.Add(edge3,anewV);
1304 Context()->Replace(aOldV,anewV);
1307 // Check for small resulting edge
1308 Standard_Boolean newsmall = Standard_False;
1309 ShapeAnalysis_Wire SAW;
1310 SAW.Load(SFW->WireData());
1311 SAW.SetPrecision(Precision());
1312 // Make changes in WireData and Context
1315 Context()->Replace(edge1,edge3);
1316 Context()->Remove(edge2);
1320 Context()->Replace(edge2,edge3);
1321 Context()->Remove(edge1);
1325 SFW->WireData()->Set(edge3,next);
1326 newsmall = SAW.CheckSmall(next,Precision());
1330 SFW->WireData()->Set(edge3,prev);
1331 newsmall = SAW.CheckSmall(prev,Precision());
1333 SFW->WireData()->Remove(index);
1334 // Process changes in maps
1335 TopTools_ListOfShape theList;
1336 theList.Append(theList2);
1337 theEdgeToFaces.UnBind(edge1);
1338 theEdgeToFaces.UnBind(edge2);
1339 theEdgeToFaces.Bind(edge3,theList);
1340 if (theSmallEdges.Contains(edge1)) theSmallEdges.Remove(edge1);
1341 if (theSmallEdges.Contains(edge2)) theSmallEdges.Remove(edge2);
1342 if (newsmall) theSmallEdges.Add(edge3);
1343 for (TopTools_ListIteratorOfListOfShape itlf(theList);
1344 itlf.More(); itlf.Next())
1346 TopoDS_Shape curface = itlf.Value();
1347 if (theFaceWithSmall.IsBound(curface))
1349 TopTools_ListOfShape& theEdges = theFaceWithSmall(curface);
1350 if (newsmall) theEdges.Append(edge3);
1351 TopTools_ListIteratorOfListOfShape ite(theEdges);
1354 TopoDS_Shape iedge = ite.Value();
1355 if (iedge.IsSame(edge1) || iedge.IsSame(edge2))
1356 theEdges.Remove(ite);
1359 // Remove face without small edges from the map
1360 if (!theEdges.Extent()) theFaceWithSmall.UnBind(curface);
1363 myStatusSmallEdges |= ShapeExtend::EncodeStatus( ShapeExtend_DONE1 );
1368 Handle(ShapeExtend_WireData) tempWire = new ShapeExtend_WireData();
1369 ShapeAnalysis_Wire tempSaw;
1370 tempWire->Add(SFW->Wire());
1371 TopoDS_Edge remedge;
1374 else remedge = edge2;
1375 tempWire->Remove (index );
1376 tempSaw.Load(tempWire);
1377 Standard_Integer newindex = (index <= tempSaw.NbEdges() ? index : 1);
1378 tempSaw.CheckConnected(newindex,Precision());
1379 if(!tempSaw.LastCheckStatus(ShapeExtend_FAIL))
1381 SFW->WireData()->Remove (index );
1382 TopoDS_Edge tmpedge1 = tempWire->Edge(newindex);
1383 TopoDS_Edge tmpedge2 = tempWire->Edge(newindex == 1 ? tempSaw.NbEdges() : (newindex- 1));
1384 TopTools_ListOfShape aL1;
1385 if(theEdgeToFaces.IsBound(tmpedge1))
1386 aL1 = theEdgeToFaces.Find(tmpedge1);
1387 TopTools_ListOfShape aL2;
1388 if(theEdgeToFaces.IsBound(tmpedge2))
1389 aL2= theEdgeToFaces.Find(tmpedge2);
1390 SFW->FixConnected(newindex <= SFW->NbEdges() ? newindex : 1,Precision());
1391 SFW->FixDegenerated(newindex <= SFW->NbEdges() ? newindex : 1);
1392 TopoDS_Shape aTmpShape = Context()->Apply(tmpedge1); //for porting
1393 TopoDS_Edge anewedge1 = TopoDS::Edge(aTmpShape);
1394 aTmpShape = Context()->Apply(tmpedge2);
1395 TopoDS_Edge anewedge2 = TopoDS::Edge(aTmpShape);
1396 Context()->Remove(remedge);
1397 if (theSmallEdges.Contains(remedge))
1398 theSmallEdges.Remove(remedge);
1399 theEdgeToFaces.UnBind(remedge);
1400 theEdgeToFaces.UnBind(tmpedge1);
1401 theEdgeToFaces.UnBind(tmpedge2);
1402 theEdgeToFaces.Bind(anewedge1,aL1);
1403 theEdgeToFaces.Bind(anewedge2,aL2);
1404 if (theSmallEdges.Contains(tmpedge1))
1406 theSmallEdges.Remove(tmpedge1);
1407 theSmallEdges.Add(anewedge1);
1408 for (TopTools_ListIteratorOfListOfShape itlf(aL1);
1409 itlf.More(); itlf.Next())
1411 TopoDS_Shape curface = itlf.Value();
1412 TopTools_ListOfShape& theEdges = theFaceWithSmall(curface);
1413 TopTools_ListIteratorOfListOfShape ite(theEdges);
1416 TopoDS_Shape iedge = ite.Value();
1417 if (iedge.IsSame(tmpedge1))
1419 theEdges.Remove(ite);
1420 theEdges.Append(anewedge1);
1426 if (theSmallEdges.Contains(tmpedge2))
1428 theSmallEdges.Remove(tmpedge2);
1429 theSmallEdges.Add(anewedge2);
1430 for (TopTools_ListIteratorOfListOfShape itlf(aL2);
1431 itlf.More(); itlf.Next())
1433 TopoDS_Shape curface = itlf.Value();
1434 TopTools_ListOfShape& theEdges = theFaceWithSmall(curface);
1435 TopTools_ListIteratorOfListOfShape ite(theEdges);
1438 TopoDS_Shape iedge = ite.Value();
1439 if (iedge.IsSame(tmpedge2))
1441 theEdges.Remove(ite);
1442 theEdges.Append(anewedge2);
1448 myStatusSmallEdges |= ShapeExtend::EncodeStatus( ShapeExtend_DONE3 );
1454 //gka protection aginst removing circles
1455 TopoDS_Edge ed = (take_next ? edge1 : edge2);
1456 ShapeAnalysis_Edge sae;
1457 Handle(Geom_Curve) c3d;
1458 Standard_Real f1,l1;
1459 if(sae.Curve3d(ed,c3d,f1,l1,Standard_False))
1464 c3d->D0((f1 +l1)*0.5,p3);
1466 if(p1.Distance(p3) > p1.Distance(p2))
1472 if (take_next && theList2.Extent()== 1)
1474 TopoDS_Vertex V1 = SAE.FirstVertex(edge1),
1475 V2 = SAE.LastVertex(edge1);
1478 SFW->WireData()->Remove (index );
1479 Context()->Remove(edge1);
1480 if (theSmallEdges.Contains(edge1)) theSmallEdges.Remove(edge1);
1481 theEdgeToFaces.UnBind(edge1);
1482 myStatusSmallEdges |= ShapeExtend::EncodeStatus( ShapeExtend_DONE2 );
1486 else if( !take_next && theList2.Extent()== 1)
1488 TopoDS_Vertex V1 = SAE.FirstVertex(edge2),
1489 V2 = SAE.LastVertex(edge2);
1492 SFW->WireData()->Remove (index );
1493 Context()->Remove(edge2);
1494 if (theSmallEdges.Contains(edge2)) theSmallEdges.Remove(edge2);
1495 theEdgeToFaces.UnBind(edge2);
1496 myStatusSmallEdges |= ShapeExtend::EncodeStatus( ShapeExtend_DONE2 );
1505 if (SFW->NbEdges() == 1 && aModeDrop)
1507 edge1 = SFW->WireData()->Edge(1);
1508 if (theSmallEdges.Contains(edge1))
1510 SFW->WireData()->Remove(1);
1511 Context()->Remove(edge1);
1512 theSmallEdges.Remove(edge1);
1513 theEdgeToFaces.UnBind(edge1);
1514 Context()->Remove(aWire);
1515 myStatusSmallEdges |= ShapeExtend::EncodeStatus( ShapeExtend_DONE2 );
1520 SFW->FixConnected();
1521 Context()->Replace(aWire,SFW->Wire());
1525 // Record vertex replacements in context
1526 for (TopTools_DataMapIteratorOfDataMapOfShapeShape itv(theNewVertices);
1527 itv.More(); itv.Next()) Context()->Replace(itv.Key(),itv.Value());
1529 TopoDS_Shape shape = myShape;
1531 myShape = Context()->Apply(shape);
1533 ShapeFix::SameParameter(myShape,Standard_False);
1535 return StatusSmallEdges( ShapeExtend_DONE );
1538 return Standard_False;