Logo Search packages:      
Sourcecode: opencascade version File versions  Download package

Standard_Boolean ShapeFix_Wireframe::MergeSmallEdges ( TopTools_MapOfShape &  theSmallEdges,
TopTools_DataMapOfShapeListOfShape &  theEdgeToFaces,
TopTools_DataMapOfShapeListOfShape &  theFaceWithSmall,
TopTools_MapOfShape &  theMultyEdges,
const Standard_Boolean  theModeDrop = Standard_False,
const Standard_Real  theLimitAngle = -1 
)

Auxiliary tool for FixSmallEdges which merges small edges.
If theModeDrop is equal to Standard_True then small edges,
which cannot be connected with adjacent edges are dropped.
Otherwise they are kept.
theLimitAngle specifies maximum allowed tangency
discontinuity between adjacent edges.
If theLimitAngle is equal to -1, this angle is not taken into account.

Definition at line 577 of file ShapeFix_Wireframe.cxx.

References TopoDS_Builder::Add(), gp_Vec::Angle(), Precision::Angular(), ShapeAnalysis_Wire::CheckConnected(), ShapeAnalysis_Wire::CheckSmall(), Precision::Confusion(), ShapeFix_Root::Context(), ShapeAnalysis_TransferParametersProj::CopyNMVertex(), TopExp_Explorer::Current(), ShapeAnalysis_Edge::Curve3d(), gp_Pnt::Distance(), TopoDS_Shape::EmptyCopied(), ShapeExtend::EncodeStatus(), ShapeAnalysis_Edge::FirstVertex(), ShapeAnalysis_Wire::Init(), TopoDS_Iterator::Initialize(), TopoDS_Shape::IsNull(), TopoDS_Shape::IsSame(), ShapeAnalysis_Wire::LastCheckStatus(), ShapeAnalysis_Edge::LastVertex(), ShapeAnalysis_Wire::Load(), TopoDS_Iterator::More(), TopExp_Explorer::More(), ShapeAnalysis_Wire::NbEdges(), TopExp_Explorer::Next(), TopoDS_Iterator::Next(), TopoDS_Shape::Nullify(), TopoDS_Shape::Orientation(), TopoDS_Shape::Oriented(), ShapeFix_Root::Precision(), gp_Vec::Reverse(), ShapeFix::SameParameter(), ShapeAnalysis_Wire::SetPrecision(), gp_Vec::SquareMagnitude(), StatusSmallEdges(), and TopoDS_Iterator::Value().

Referenced by FixSmallEdges().

{
  Standard_Boolean aModLimitAngle = (theLimitAngle >-1.0 || myLimitAngle > -1.0);
  Standard_Real aLimitAngle = Max(theLimitAngle,myLimitAngle);
  
  Standard_Boolean aModeDrop = theModeDrop || myModeDrop;
  TopTools_DataMapOfShapeShape theNewVertices;
  if (!theSmallEdges.IsEmpty()) 
  {
    
    Handle(ShapeFix_Wire) SFW = new ShapeFix_Wire;
    SFW->SetContext(Context());
    ShapeAnalysis_Edge SAE;
    TopoDS_Edge edge1, edge2, edge3;
    // Iterate on map of faces with small edges
    TopExp_Explorer anExpf2(myShape,TopAbs_FACE);
    for (; anExpf2.More(); anExpf2.Next()) 
    {
      if (theFaceWithSmall.IsBound(anExpf2.Current())) 
      {
      if (theFaceWithSmall(anExpf2.Current()).Extent()) 
        {
        //smh#8
        TopoDS_Shape tmpShape = Context()->Apply(anExpf2.Current());
        TopoDS_Face facet = TopoDS::Face(tmpShape);
        if(!facet.IsSame(anExpf2.Current())) 
          {  //gka
          TopExp_Explorer aExpEdge(anExpf2.Current(),TopAbs_EDGE);
          for( ; aExpEdge.More(); aExpEdge.Next()) 
            {
            TopoDS_Shape newEdge;
            Standard_Integer stat = Context()->Status(aExpEdge.Current(),newEdge,Standard_True);
            if(stat > 0 ) 
              {
            if(theSmallEdges.Contains(aExpEdge.Current())) 
                {
              theSmallEdges.Remove(aExpEdge.Current());
              theSmallEdges.Add(newEdge);
            }
            if(theEdgeToFaces.IsBound(aExpEdge.Current())) 
                {
              TopTools_ListOfShape aListFaces;
              aListFaces = theEdgeToFaces.Find(aExpEdge.Current());
              theEdgeToFaces.UnBind(aExpEdge.Current());
              theEdgeToFaces.Bind(newEdge,aListFaces);
              
            }
            }
          }
        }
          TopoDS_Face face = facet;
        //if (face.Orientation()==TopAbs_REVERSED) 
          //  face = TopoDS::Face(facet.Oriented(TopAbs_FORWARD));
        for (TopoDS_Iterator itw(face); itw.More(); itw.Next()) 
          {
            if(itw.Value().ShapeType() != TopAbs_WIRE) continue;
          TopoDS_Wire aWire = TopoDS::Wire(itw.Value());
            if (face.Orientation()==TopAbs_REVERSED) 
              face = TopoDS::Face(facet.Oriented(TopAbs_FORWARD));
          Handle(ShapeExtend_WireData) aswd = new ShapeExtend_WireData(aWire,Standard_True,Standard_False);
          //SFW->Load(aWire);
          SFW->Load(aswd);
          SFW->FixReorder();
          Standard_Integer prev, next, index = 1;
          
          while (index <= SFW->WireData()->NbEdges() && SFW->NbEdges()>1) 
            {
            prev = (index==1)? SFW->WireData()->NbEdges() : index-1;
            next = (index==SFW->WireData()->NbEdges())? 1 : index+1;
            edge1 = SFW->WireData()->Edge(prev);
            edge2 = SFW->WireData()->Edge(index);
            edge3 = SFW->WireData()->Edge(next);
              
              //gka protection against joining seem edge 
              if(edge2.IsSame(edge1) || edge2.IsSame(edge3)) 
              {
              //if(BRep_Tool::IsClosed(edge2,face)) { 
                index++;
                continue;
              }
               
              Standard_Boolean isSeam = SFW->WireData()->IsSeam(index);
              Standard_Boolean isSeam1 = SFW->WireData()->IsSeam(prev);
              Standard_Boolean isSeam2 = SFW->WireData()->IsSeam(next);
            if (theSmallEdges.Contains(edge2)) 
              {
            // Middle edge is small - choose a pair of edges to join
                Standard_Boolean IsAnyJoin = (edge1.IsSame(edge3));
            Standard_Boolean take_next = IsAnyJoin; //Standard_False;
            Standard_Boolean isLimAngle = Standard_False;
            Handle(Geom_Curve) C1, C2, C3;
            Standard_Real aux, last1, first2, last2, first3;
            Standard_Real Ang1 = 0., Ang2 =0.;
            if (SAE.Curve3d(edge1,C1,aux,last1) &&
                SAE.Curve3d(edge2,C2,first2,last2) &&
                SAE.Curve3d(edge3,C3,first3,aux)) 
                {
              // Compare angles between edges
              //Standard_Real Ang1, Ang2;
              gp_Vec Vec1, Vec2; gp_Pnt P;
              C1->D1(last1,P,Vec1);
              C2->D1(first2,P,Vec2);
              if ( edge1.Orientation() == TopAbs_REVERSED ) Vec1.Reverse();
              if ( edge2.Orientation() == TopAbs_REVERSED ) Vec2.Reverse();
              Standard_Real tol2 = Precision::Confusion() * Precision::Confusion();
              if ( Vec1.SquareMagnitude() < tol2 ||
                   Vec2.SquareMagnitude() < tol2 ) Ang1 = PI/2.;
              else Ang1 = Abs(Vec1.Angle(Vec2));
              C2->D1(last2,P,Vec1);
              C3->D1(first3,P,Vec2);
              if ( edge2.Orientation() == TopAbs_REVERSED ) Vec1.Reverse();
              if ( edge3.Orientation() == TopAbs_REVERSED ) Vec2.Reverse();
              if ( Vec1.SquareMagnitude() < tol2 ||
                   Vec2.SquareMagnitude() < tol2 ) Ang2 = PI/2.;
              else Ang2 = Abs(Vec1.Angle(Vec2));
              //isLimAngle = (theLimitAngle != -1 && Min(Ang1,Ang2) > theLimitAngle);  
              //take_next = (Ang2<Ang1);
              //if (take_next) { edge1 = edge2; edge2 = edge3; }
            }
            //if(theLimitAngle != -1 && Ang1 > theLimitAngle && Ang2 >theLimitAngle) {
            //  index++; continue;
            //}
                
            // Check if edges lay on the same faces
            if(theMultyEdges.Contains(edge1) || theMultyEdges.Contains(edge2)) 
                { //??????
              index++;
              continue;
            }
            TopTools_ListOfShape theList1,theList2,theList3;
            if(theEdgeToFaces.IsBound(edge1))
              theList1 = theEdgeToFaces(edge1);
            if(theEdgeToFaces.IsBound(edge2))
              theList2 = theEdgeToFaces(edge2);
            if(theEdgeToFaces.IsBound(edge3))
              theList3 = theEdgeToFaces(edge3);
            Standard_Boolean same_set = Standard_False;
                
                //gka protection against joining seem edges with other edges
            Standard_Boolean same_set1 = (theList1.Extent()==theList2.Extent() && 
                                              ((!isSeam && !isSeam1)|| (isSeam && isSeam1))); //gka
            Standard_Boolean same_set2 = (theList3.Extent()==theList2.Extent() && 
                                              ((!isSeam && !isSeam2)|| (isSeam && isSeam2)));
            TopTools_MapOfShape theSetOfFaces;
                for (TopTools_ListIteratorOfListOfShape itf1(theList2);
                     itf1.More(); itf1.Next())
                  theSetOfFaces.Add(itf1.Value());
            if (same_set1) 
                {
              // Add all faces of the first edge to the current set
              for (TopTools_ListIteratorOfListOfShape itf2(theList1);
                   (itf2.More() && same_set1); itf2.Next())
                same_set1 = theSetOfFaces.Contains(itf2.Value());
            }
            if (same_set2) 
                {
              // Add all faces of the first edge to the current set
              for (TopTools_ListIteratorOfListOfShape itf2(theList3);
                   (itf2.More() && same_set2); itf2.Next())
                same_set2 = theSetOfFaces.Contains(itf2.Value());
            }
            if(same_set1 && same_set2) 
                {
              same_set = Standard_True;
                  if(fabs(Ang2-Ang1) >Precision::Angular())
                    take_next = (Ang2<Ang1);
              if (take_next) 
                  { 
                    edge1 = edge2; edge2 = edge3;
                  }
              isLimAngle = (aModLimitAngle && Min(Ang1,Ang2) > aLimitAngle);
            }
            else if(same_set1 && !same_set2) 
                {
              isLimAngle = (aModLimitAngle && Ang1 > aLimitAngle);
              same_set = Standard_True;
            }
            else if(!same_set1 && same_set2) 
                {
              same_set = Standard_True;
              isLimAngle = (aModLimitAngle && Ang2 > aLimitAngle);
              edge1 = edge2; edge2 = edge3;
              take_next = Standard_True;
            }
            if (same_set && !isLimAngle ) 
                {
              // Merge current pair of edges
                   //gka protection against crossing seem on second face
                  Standard_Boolean isNeedJoin = Standard_True;//Standard_False;
                  for(TopTools_ListIteratorOfListOfShape aItF(theList2); aItF.More() && isNeedJoin; aItF.Next()) 
                  { 
                    if(aItF.Value().IsSame(anExpf2.Current())) continue;
                    TopoDS_Shape aF = Context()->Apply(aItF.Value());
                    //aF = aF.Oriented(TopAbs_FORWARD);
                    for(TopoDS_Iterator aIw(aF); aIw.More(); aIw.Next()) 
                    {
                      if(aIw.Value().ShapeType() != TopAbs_WIRE) continue;
                      TopoDS_Wire wt = TopoDS::Wire(aIw.Value());
                      Handle(ShapeFix_Wire) SFW1 = new ShapeFix_Wire;
                      SFW1->Load(wt);
                      SFW1->FixReorder();
                      Handle(ShapeExtend_WireData) atmpswd = SFW1->WireData();
                      Standard_Integer ind1 = atmpswd->Index(edge1);
                      Standard_Integer ind2 = atmpswd->Index(edge2);
                      if(ind1 && ind2) 
                      {
                        isNeedJoin = ((ind1 -ind2) ==1 || (ind2 == atmpswd->NbEdges() && ind1 ==1));
                        break;
                      }
                    }
                  }
                  Standard_Boolean ReplaceFirst = Standard_True;
                  if(isNeedJoin) 
                  {
                    
                    TopTools_ListOfShape aListF;
                    for(TopTools_ListIteratorOfListOfShape aItlF(theList2); aItlF.More(); aItlF.Next()) 
                    {
                      TopoDS_Shape tmpF = Context()->Apply(aItlF.Value());
                      aListF.Append(tmpF);
                    }
                    ReplaceFirst = JoinEdges(edge1,edge2,edge3,aListF);
                  }
                  else edge3 = TopoDS_Edge();
              if (edge3.IsNull()) 
                  {
                index++;
                myStatusSmallEdges |= ShapeExtend::EncodeStatus( ShapeExtend_FAIL1 );
              }
              else 
                  {
                // Record vertex replacements in the map
                TopoDS_Vertex oldV1 = SAE.FirstVertex(edge3),
                              oldV2 = SAE.LastVertex(edge3);
                if (!theNewVertices.IsBound(oldV1))
//smh#8
                    {
                      TopoDS_Shape emptyCopiedV1 = oldV1.EmptyCopied();
                      theNewVertices.Bind(oldV1,TopoDS::Vertex(emptyCopiedV1));
                    }
                if (!oldV1.IsSame(oldV2))
                  if (!theNewVertices.IsBound(oldV2))
//smh#8
                      {
                        TopoDS_Shape emptyCopiedV2 = oldV2.EmptyCopied();
                        theNewVertices.Bind(oldV2,TopoDS::Vertex(emptyCopiedV2));
                      }
                
                //To keep NM vertices belonging initial edges
                TopoDS_Iterator aItv(edge1,Standard_False);
                for( ; aItv.More(); aItv.Next()) {
                  if(aItv.Value().Orientation() == TopAbs_INTERNAL ||
                   aItv.Value().Orientation() == TopAbs_EXTERNAL) {
                  TopoDS_Vertex aOldV = TopoDS::Vertex(aItv.Value());
                  TopoDS_Vertex anewV =  ShapeAnalysis_TransferParametersProj::CopyNMVertex(aOldV,edge3,edge1);
                  BRep_Builder aB;
                  aB.Add(edge3,anewV);
                  Context()->Replace(aOldV,anewV);
                  }
                }
                  
                for(aItv.Initialize(edge2,Standard_False) ; aItv.More(); aItv.Next()) {
                  if(aItv.Value().Orientation() == TopAbs_INTERNAL ||
                   aItv.Value().Orientation() == TopAbs_EXTERNAL){
                  BRep_Builder aB;
                  TopoDS_Vertex aOldV = TopoDS::Vertex(aItv.Value());
                  TopoDS_Vertex anewV =  ShapeAnalysis_TransferParametersProj::CopyNMVertex(aOldV,edge3,edge2);
                  aB.Add(edge3,anewV);
                  Context()->Replace(aOldV,anewV);
                  }
                }
              
                // Check for small resulting edge
                Standard_Boolean newsmall = Standard_False;
                ShapeAnalysis_Wire SAW;
                SAW.Init(SFW->WireData(),face,Precision());
                // Make changes in WireData and Context
                    if(ReplaceFirst) 
                    {
                      Context()->Replace(edge1,edge3);
                      Context()->Remove(edge2);
                    }
                    else 
                    {
                      Context()->Replace(edge2,edge3);
                      Context()->Remove(edge1);
                    }
                if (take_next) 
                    {
                  SFW->WireData()->Set(edge3,next);
                  newsmall = SAW.CheckSmall(next,Precision());
                }
                else 
                    {
                  SFW->WireData()->Set(edge3,prev);
                  newsmall = SAW.CheckSmall(prev,Precision());
                }
                SFW->WireData()->Remove(index);
                // Process changes in maps
                TopTools_ListOfShape theList;
                theList.Append(theList2);
                theEdgeToFaces.UnBind(edge1);
                theEdgeToFaces.UnBind(edge2);
                theEdgeToFaces.Bind(edge3,theList);
                if (theSmallEdges.Contains(edge1)) theSmallEdges.Remove(edge1);
                if (theSmallEdges.Contains(edge2)) theSmallEdges.Remove(edge2);
                if (newsmall) theSmallEdges.Add(edge3);
                for (TopTools_ListIteratorOfListOfShape itlf(theList);
                   itlf.More(); itlf.Next()) 
                    {
                  TopoDS_Shape curface = itlf.Value();
                  if (theFaceWithSmall.IsBound(curface)) 
                      {
                  TopTools_ListOfShape& theEdges = theFaceWithSmall(curface);
                  if (newsmall) theEdges.Append(edge3);
                  TopTools_ListIteratorOfListOfShape ite(theEdges);
                  while (ite.More()) 
                        {
                    TopoDS_Shape iedge = ite.Value();
                    if (iedge.IsSame(edge1) || iedge.IsSame(edge2))
                      theEdges.Remove(ite);
                    else ite.Next();
                  }
                  // Remove face without small edges from the map
                  if (!theEdges.Extent()) theFaceWithSmall.UnBind(curface);
                  }
                }
                myStatusSmallEdges |= ShapeExtend::EncodeStatus( ShapeExtend_DONE1 );
              }
            }
            else if(aModeDrop) 
                { //gka
              Handle(ShapeExtend_WireData) tempWire = new ShapeExtend_WireData();
              ShapeAnalysis_Wire tempSaw;
              tempWire->Add(SFW->Wire());
              TopoDS_Edge remedge;
              if (take_next) 
                remedge = edge1;
              else  remedge = edge2;
              tempWire->Remove (index );
              tempSaw.Load(tempWire);
              Standard_Integer newindex = (index <= tempSaw.NbEdges() ? index : 1);
              tempSaw.CheckConnected(newindex,Precision());
              if(!tempSaw.LastCheckStatus(ShapeExtend_FAIL)) 
                  {
                SFW->WireData()->Remove (index );
                TopoDS_Edge tmpedge1 = tempWire->Edge(newindex);
                TopoDS_Edge tmpedge2 = tempWire->Edge(newindex == 1 ? tempSaw.NbEdges() : (newindex- 1));
                TopTools_ListOfShape aL1;
                if(theEdgeToFaces.IsBound(tmpedge1))
                   aL1 = theEdgeToFaces.Find(tmpedge1);
                TopTools_ListOfShape aL2;
                if(theEdgeToFaces.IsBound(tmpedge2))  
                  aL2= theEdgeToFaces.Find(tmpedge2);                               
                SFW->FixConnected(newindex <= SFW->NbEdges() ? newindex : 1,Precision());
                SFW->FixDegenerated(newindex <= SFW->NbEdges() ? newindex : 1);
                    TopoDS_Shape aTmpShape = Context()->Apply(tmpedge1); //for porting
                TopoDS_Edge anewedge1 = TopoDS::Edge(aTmpShape);
                    aTmpShape = Context()->Apply(tmpedge2);
                TopoDS_Edge anewedge2 = TopoDS::Edge(aTmpShape); 
                Context()->Remove(remedge);
                if (theSmallEdges.Contains(remedge)) 
                  theSmallEdges.Remove(remedge);
                theEdgeToFaces.UnBind(remedge);
                theEdgeToFaces.UnBind(tmpedge1);
                theEdgeToFaces.UnBind(tmpedge2);
                theEdgeToFaces.Bind(anewedge1,aL1);
                theEdgeToFaces.Bind(anewedge2,aL2);
                if (theSmallEdges.Contains(tmpedge1)) 
                    {
                  theSmallEdges.Remove(tmpedge1);
                  theSmallEdges.Add(anewedge1);
                  for (TopTools_ListIteratorOfListOfShape itlf(aL1);
                   itlf.More(); itlf.Next()) 
                      {
                  TopoDS_Shape curface = itlf.Value();
                  TopTools_ListOfShape& theEdges = theFaceWithSmall(curface);
                  TopTools_ListIteratorOfListOfShape ite(theEdges);
                  while (ite.More()) 
                        {
                    TopoDS_Shape iedge = ite.Value();
                    if (iedge.IsSame(tmpedge1)) 
                          {
                      theEdges.Remove(ite);
                      theEdges.Append(anewedge1);
                    }
                    else ite.Next();
                  }
                  }
                }
                if (theSmallEdges.Contains(tmpedge2)) 
                    {
                  theSmallEdges.Remove(tmpedge2);
                  theSmallEdges.Add(anewedge2);
                  for (TopTools_ListIteratorOfListOfShape itlf(aL2);
                   itlf.More(); itlf.Next()) 
                      {
                  TopoDS_Shape curface = itlf.Value();
                  TopTools_ListOfShape& theEdges = theFaceWithSmall(curface);
                  TopTools_ListIteratorOfListOfShape ite(theEdges);
                  while (ite.More()) 
                        {
                    TopoDS_Shape iedge = ite.Value();
                    if (iedge.IsSame(tmpedge2)) 
                          {
                      theEdges.Remove(ite);
                      theEdges.Append(anewedge2);
                    }
                    else ite.Next();
                  }
                  }
                }
                myStatusSmallEdges |= ShapeExtend::EncodeStatus( ShapeExtend_DONE3 );
              }
              else index++;
            }
            else 
                {
                  //gka protection aginst removing circles
                  TopoDS_Edge ed = (take_next ? edge1 : edge2);
                  ShapeAnalysis_Edge sae;
                  Handle(Geom_Curve) c3d;
                  Standard_Real f1,l1;
                  if(sae.Curve3d(ed,c3d,f1,l1,Standard_False)) 
                  {
                    gp_Pnt p1,p2,p3;
                    c3d->D0(f1,p1);
                    c3d->D0(l1,p2);
                    c3d->D0((f1 +l1)*0.5,p3);
                    
                    if(p1.Distance(p3) > p1.Distance(p2)) 
                    {
                      index++;
                      continue;
                    }
                  }
              if (take_next && theList2.Extent()== 1)  
                  { //gka
                  TopoDS_Vertex V1 = SAE.FirstVertex(edge1),
                             V2 = SAE.LastVertex(edge1);
                  if(V1.IsSame(V2)) 
                      {
                  SFW->WireData()->Remove (index );
                  Context()->Remove(edge1);
                  if (theSmallEdges.Contains(edge1)) theSmallEdges.Remove(edge1);
                  theEdgeToFaces.UnBind(edge1);
                  myStatusSmallEdges |= ShapeExtend::EncodeStatus( ShapeExtend_DONE2 );
                  }
                  else index++;
                }
                else if( !take_next && theList2.Extent()== 1) 
                    {
                  TopoDS_Vertex V1 = SAE.FirstVertex(edge2),
                  V2 = SAE.LastVertex(edge2);
                  if(V1.IsSame(V2)) 
                      {
                  SFW->WireData()->Remove (index );
                  Context()->Remove(edge2);
                  if (theSmallEdges.Contains(edge2)) theSmallEdges.Remove(edge2);
                  theEdgeToFaces.UnBind(edge2);
                  myStatusSmallEdges |= ShapeExtend::EncodeStatus( ShapeExtend_DONE2 );
                  }
                  else index++;
                }
                else index++; 
            }
            }
            else index++;
          }
          if (SFW->NbEdges() == 1 && aModeDrop) 
            {
            edge1 = SFW->WireData()->Edge(1);
            if (theSmallEdges.Contains(edge1)) 
              {
            SFW->WireData()->Remove(1);
            Context()->Remove(edge1);
            theSmallEdges.Remove(edge1);
            theEdgeToFaces.UnBind(edge1);
            Context()->Remove(aWire);
            myStatusSmallEdges |= ShapeExtend::EncodeStatus( ShapeExtend_DONE2 );
            }
          }
          else 
            {
              SFW->FixConnected();
              Context()->Replace(aWire,SFW->Wire());  
            }
        }
          face.Orientation(facet.Orientation());
        TopoDS_Shape anewShape = Context()->Apply(face);
        TopoDS_Iterator aIter(anewShape);
        if(!aIter.More())
          Context()->Remove(anewShape);
      }
      }
    }

// enk block
// Iterate on map of wires which not lie on faces 
    for (TopExp_Explorer expw1( myShape, TopAbs_WIRE, TopAbs_FACE); expw1.More(); expw1.Next()) 
    {
          TopoDS_Wire aWire = TopoDS::Wire(expw1.Current());
          SFW->Load(aWire);
          SFW->FixReorder();
          Standard_Integer prev, next, index = 1;
          while (index <= SFW->NbEdges() && SFW->NbEdges()>1) 
            {
            prev = (index==1)? SFW->NbEdges() : index-1;
            next = (index==SFW->NbEdges())? 1 : index+1;
            edge1 = SFW->WireData()->Edge(prev);
            edge2 = SFW->WireData()->Edge(index);
            edge3 = SFW->WireData()->Edge(next);
              
              //gka protection against joining seem edge 
              if(edge2.IsSame(edge1) || edge2.IsSame(edge3)) 
              {
              //if(BRep_Tool::IsClosed(edge2,face)) { 
                index++;
                continue;
              }
               
              Standard_Boolean isSeam = SFW->WireData()->IsSeam(index);
              Standard_Boolean isSeam1 = SFW->WireData()->IsSeam(prev);
              Standard_Boolean isSeam2 = SFW->WireData()->IsSeam(next);
            if (theSmallEdges.Contains(edge2)) 
              {
            // Middle edge is small - choose a pair of edges to join
                Standard_Boolean IsAnyJoin = (edge1.IsSame(edge3));
            Standard_Boolean take_next = IsAnyJoin; //Standard_False;
            Standard_Boolean isLimAngle = Standard_False;
            Handle(Geom_Curve) C1, C2, C3;
            Standard_Real aux, last1, first2, last2, first3;
            Standard_Real Ang1 = 0., Ang2 =0.;
            if (SAE.Curve3d(edge1,C1,aux,last1) &&
                SAE.Curve3d(edge2,C2,first2,last2) &&
                SAE.Curve3d(edge3,C3,first3,aux)) 
                {
              // Compare angles between edges
              //Standard_Real Ang1, Ang2;
              gp_Vec Vec1, Vec2; gp_Pnt P;
              C1->D1(last1,P,Vec1);
              C2->D1(first2,P,Vec2);
              if ( edge1.Orientation() == TopAbs_REVERSED ) Vec1.Reverse();
              if ( edge2.Orientation() == TopAbs_REVERSED ) Vec2.Reverse();
              Standard_Real tol2 = Precision::Confusion() * Precision::Confusion();
              if ( Vec1.SquareMagnitude() < tol2 ||
                   Vec2.SquareMagnitude() < tol2 ) Ang1 = PI/2.;
              else Ang1 = Abs(Vec1.Angle(Vec2));
              C2->D1(last2,P,Vec1);
              C3->D1(first3,P,Vec2);
              if ( edge2.Orientation() == TopAbs_REVERSED ) Vec1.Reverse();
              if ( edge3.Orientation() == TopAbs_REVERSED ) Vec2.Reverse();
              if ( Vec1.SquareMagnitude() < tol2 ||
                   Vec2.SquareMagnitude() < tol2 ) Ang2 = PI/2.;
              else Ang2 = Abs(Vec1.Angle(Vec2));
              //isLimAngle = (theLimitAngle != -1 && Min(Ang1,Ang2) > theLimitAngle);  
              //take_next = (Ang2<Ang1);
              //if (take_next) { edge1 = edge2; edge2 = edge3; }
            }
            //if(theLimitAngle != -1 && Ang1 > theLimitAngle && Ang2 >theLimitAngle) {
            //  index++; continue;
            //}
                
            // Check if edges lay on the same faces
            if(theMultyEdges.Contains(edge1) || theMultyEdges.Contains(edge2)) 
                { //??????
              index++;
              continue;
            }
            TopTools_ListOfShape theList1,theList2,theList3;
            if(theEdgeToFaces.IsBound(edge1))
              theList1 = theEdgeToFaces(edge1);
            if(theEdgeToFaces.IsBound(edge2))
              theList2 = theEdgeToFaces(edge2);
            if(theEdgeToFaces.IsBound(edge3))
              theList3 = theEdgeToFaces(edge3);
            Standard_Boolean same_set = Standard_False;
                
                //gka protection against joining seem edges with other edges
            Standard_Boolean same_set1 = (theList1.Extent()==theList2.Extent() && 
                                              ((!isSeam && !isSeam1)|| (isSeam && isSeam1))); //gka
            Standard_Boolean same_set2 = (theList3.Extent()==theList2.Extent() && 
                                              ((!isSeam && !isSeam2)|| (isSeam && isSeam2)));
            TopTools_MapOfShape theSetOfFaces;
                for (TopTools_ListIteratorOfListOfShape itf1(theList2);
                     itf1.More(); itf1.Next())
                  theSetOfFaces.Add(itf1.Value());
            if (same_set1) 
                {
              // Add all faces of the first edge to the current set
              for (TopTools_ListIteratorOfListOfShape itf2(theList1);
                   (itf2.More() && same_set1); itf2.Next())
                same_set1 = theSetOfFaces.Contains(itf2.Value());
            }
            if (same_set2) 
                {
              // Add all faces of the first edge to the current set
              for (TopTools_ListIteratorOfListOfShape itf2(theList3);
                   (itf2.More() && same_set2); itf2.Next())
                same_set2 = theSetOfFaces.Contains(itf2.Value());
            }
            if(same_set1 && same_set2) 
                {
              same_set = Standard_True;
                  if(fabs(Ang2-Ang1) >Precision::Angular())
                    take_next = (Ang2<Ang1);
              if (take_next) 
                  { 
                    edge1 = edge2; edge2 = edge3;
                  }
              isLimAngle = (aModLimitAngle && Min(Ang1,Ang2) > aLimitAngle);
            }
            else if(same_set1 && !same_set2) 
                {
              isLimAngle = (aModLimitAngle && Ang1 > aLimitAngle);
              same_set = Standard_True;
            }
            else if(!same_set1 && same_set2) 
                {
              same_set = Standard_True;
              isLimAngle = (aModLimitAngle && Ang2 > aLimitAngle);
              edge1 = edge2; edge2 = edge3;
              take_next = Standard_True;
            }
            if (same_set && !isLimAngle ) 
                {
              // Merge current pair of edges
                   //gka protection against crossing seem on second face
                  Standard_Boolean isNeedJoin = Standard_True;//Standard_False;
                  for(TopTools_ListIteratorOfListOfShape aItF(theList2); aItF.More() && isNeedJoin; aItF.Next()) 
                  { 
                    if(aItF.Value().IsSame(anExpf2.Current())) continue;
                    TopoDS_Shape aF = Context()->Apply(aItF.Value());
                    //aF = aF.Oriented(TopAbs_FORWARD);
                    for(TopoDS_Iterator aIw(aF); aIw.More(); aIw.Next()) 
                    {
                      if(aIw.Value().ShapeType() != TopAbs_WIRE) continue;
                      TopoDS_Wire wt = TopoDS::Wire(aIw.Value());
                      Handle(ShapeFix_Wire) SFW1 = new ShapeFix_Wire;
                      SFW1->Load(wt);
                      SFW1->FixReorder();
                      Handle(ShapeExtend_WireData) atmpswd = SFW1->WireData();
                      Standard_Integer ind1 = atmpswd->Index(edge1);
                      Standard_Integer ind2 = atmpswd->Index(edge2);
                      if(ind1 && ind2) 
                      {
                        isNeedJoin = ((ind1 -ind2) ==1 || (ind2 == atmpswd->NbEdges() && ind1 ==1));
                        break;
                      }
                    }
                  }
                  Standard_Boolean ReplaceFirst = Standard_True;
                  if(isNeedJoin) 
                  {
                    
                    TopTools_ListOfShape aListF;
                    for(TopTools_ListIteratorOfListOfShape aItlF(theList2); aItlF.More(); aItlF.Next()) 
                    {
                      TopoDS_Shape tmpF = Context()->Apply(aItlF.Value());
                      aListF.Append(tmpF);
                    }
                    ReplaceFirst = JoinEdges(edge1,edge2,edge3,aListF);
                  }
                  else edge3 = TopoDS_Edge();
              if (edge3.IsNull()) 
                  {
                index++;
                myStatusSmallEdges |= ShapeExtend::EncodeStatus( ShapeExtend_FAIL1 );
              }
              else 
                  {
                // Record vertex replacements in the map
                TopoDS_Vertex oldV1 = SAE.FirstVertex(edge3),
                              oldV2 = SAE.LastVertex(edge3);
                if (!theNewVertices.IsBound(oldV1))
//smh#8
                    {
                      TopoDS_Shape emptyCopiedV1 = oldV1.EmptyCopied();
                      theNewVertices.Bind(oldV1,TopoDS::Vertex(emptyCopiedV1));
                    }
                if (!oldV1.IsSame(oldV2))
                  if (!theNewVertices.IsBound(oldV2))
//smh#8
                      {
                        TopoDS_Shape emptyCopiedV2 = oldV2.EmptyCopied();
                        theNewVertices.Bind(oldV2,TopoDS::Vertex(emptyCopiedV2));
                      }
                //To keep NM vertices belonging initial edges
                TopoDS_Iterator aItv(edge1,Standard_False);
                for( ; aItv.More(); aItv.Next()) {
                  if(aItv.Value().Orientation() == TopAbs_INTERNAL ||
                   aItv.Value().Orientation() == TopAbs_EXTERNAL) {
                  BRep_Builder aB;
                  TopoDS_Vertex aOldV = TopoDS::Vertex(aItv.Value());
                  TopoDS_Vertex anewV =  ShapeAnalysis_TransferParametersProj::CopyNMVertex(aOldV,edge3,edge1);
                  aB.Add(edge3,anewV);
                  Context()->Replace(aOldV,anewV);
                  }
                }
                  
                for(aItv.Initialize(edge2,Standard_False) ; aItv.More(); aItv.Next()) {
                  if(aItv.Value().Orientation() == TopAbs_INTERNAL ||
                   aItv.Value().Orientation() == TopAbs_EXTERNAL){
                  BRep_Builder aB;
                  TopoDS_Vertex aOldV = TopoDS::Vertex(aItv.Value());
                  TopoDS_Vertex anewV =  ShapeAnalysis_TransferParametersProj::CopyNMVertex(aOldV,edge3,edge2);
                  aB.Add(edge3,anewV);
                  Context()->Replace(aOldV,anewV);
                  }
                }
                // Check for small resulting edge
                Standard_Boolean newsmall = Standard_False;
                ShapeAnalysis_Wire SAW;
                SAW.Load(SFW->WireData());
                    SAW.SetPrecision(Precision());
                // Make changes in WireData and Context
                    if(ReplaceFirst) 
                    {
                      Context()->Replace(edge1,edge3);
                      Context()->Remove(edge2);
                    }
                    else 
                    {
                      Context()->Replace(edge2,edge3);
                      Context()->Remove(edge1);
                    }
                if (take_next) 
                    {
                  SFW->WireData()->Set(edge3,next);
                  newsmall = SAW.CheckSmall(next,Precision());
                }
                else 
                    {
                  SFW->WireData()->Set(edge3,prev);
                  newsmall = SAW.CheckSmall(prev,Precision());
                }
                SFW->WireData()->Remove(index);
                // Process changes in maps
                TopTools_ListOfShape theList;
                theList.Append(theList2);
                theEdgeToFaces.UnBind(edge1);
                theEdgeToFaces.UnBind(edge2);
                theEdgeToFaces.Bind(edge3,theList);
                if (theSmallEdges.Contains(edge1)) theSmallEdges.Remove(edge1);
                if (theSmallEdges.Contains(edge2)) theSmallEdges.Remove(edge2);
                if (newsmall) theSmallEdges.Add(edge3);
                for (TopTools_ListIteratorOfListOfShape itlf(theList);
                   itlf.More(); itlf.Next()) 
                    {
                  TopoDS_Shape curface = itlf.Value();
                  if (theFaceWithSmall.IsBound(curface)) 
                      {
                  TopTools_ListOfShape& theEdges = theFaceWithSmall(curface);
                  if (newsmall) theEdges.Append(edge3);
                  TopTools_ListIteratorOfListOfShape ite(theEdges);
                  while (ite.More()) 
                        {
                    TopoDS_Shape iedge = ite.Value();
                    if (iedge.IsSame(edge1) || iedge.IsSame(edge2))
                      theEdges.Remove(ite);
                    else ite.Next();
                  }
                  // Remove face without small edges from the map
                  if (!theEdges.Extent()) theFaceWithSmall.UnBind(curface);
                  }
                }
                myStatusSmallEdges |= ShapeExtend::EncodeStatus( ShapeExtend_DONE1 );
              }
            }
            else if(aModeDrop) 
                { //gka
              Handle(ShapeExtend_WireData) tempWire = new ShapeExtend_WireData();
              ShapeAnalysis_Wire tempSaw;
              tempWire->Add(SFW->Wire());
              TopoDS_Edge remedge;
              if (take_next) 
                remedge = edge1;
              else  remedge = edge2;
              tempWire->Remove (index );
              tempSaw.Load(tempWire);
              Standard_Integer newindex = (index <= tempSaw.NbEdges() ? index : 1);
              tempSaw.CheckConnected(newindex,Precision());
              if(!tempSaw.LastCheckStatus(ShapeExtend_FAIL)) 
                  {
                SFW->WireData()->Remove (index );
                TopoDS_Edge tmpedge1 = tempWire->Edge(newindex);
                TopoDS_Edge tmpedge2 = tempWire->Edge(newindex == 1 ? tempSaw.NbEdges() : (newindex- 1));
                TopTools_ListOfShape aL1;
                if(theEdgeToFaces.IsBound(tmpedge1))
                   aL1 = theEdgeToFaces.Find(tmpedge1);
                TopTools_ListOfShape aL2;
                if(theEdgeToFaces.IsBound(tmpedge2))  
                  aL2= theEdgeToFaces.Find(tmpedge2);                               
                SFW->FixConnected(newindex <= SFW->NbEdges() ? newindex : 1,Precision());
                SFW->FixDegenerated(newindex <= SFW->NbEdges() ? newindex : 1);
                    TopoDS_Shape aTmpShape = Context()->Apply(tmpedge1); //for porting
                TopoDS_Edge anewedge1 = TopoDS::Edge(aTmpShape);
                    aTmpShape = Context()->Apply(tmpedge2);
                TopoDS_Edge anewedge2 = TopoDS::Edge(aTmpShape); 
                Context()->Remove(remedge);
                if (theSmallEdges.Contains(remedge)) 
                  theSmallEdges.Remove(remedge);
                theEdgeToFaces.UnBind(remedge);
                theEdgeToFaces.UnBind(tmpedge1);
                theEdgeToFaces.UnBind(tmpedge2);
                theEdgeToFaces.Bind(anewedge1,aL1);
                theEdgeToFaces.Bind(anewedge2,aL2);
                if (theSmallEdges.Contains(tmpedge1)) 
                    {
                  theSmallEdges.Remove(tmpedge1);
                  theSmallEdges.Add(anewedge1);
                  for (TopTools_ListIteratorOfListOfShape itlf(aL1);
                   itlf.More(); itlf.Next()) 
                      {
                  TopoDS_Shape curface = itlf.Value();
                  TopTools_ListOfShape& theEdges = theFaceWithSmall(curface);
                  TopTools_ListIteratorOfListOfShape ite(theEdges);
                  while (ite.More()) 
                        {
                    TopoDS_Shape iedge = ite.Value();
                    if (iedge.IsSame(tmpedge1)) 
                          {
                      theEdges.Remove(ite);
                      theEdges.Append(anewedge1);
                    }
                    else ite.Next();
                  }
                  }
                }
                if (theSmallEdges.Contains(tmpedge2)) 
                    {
                  theSmallEdges.Remove(tmpedge2);
                  theSmallEdges.Add(anewedge2);
                  for (TopTools_ListIteratorOfListOfShape itlf(aL2);
                   itlf.More(); itlf.Next()) 
                      {
                  TopoDS_Shape curface = itlf.Value();
                  TopTools_ListOfShape& theEdges = theFaceWithSmall(curface);
                  TopTools_ListIteratorOfListOfShape ite(theEdges);
                  while (ite.More()) 
                        {
                    TopoDS_Shape iedge = ite.Value();
                    if (iedge.IsSame(tmpedge2)) 
                          {
                      theEdges.Remove(ite);
                      theEdges.Append(anewedge2);
                    }
                    else ite.Next();
                  }
                  }
                }
                myStatusSmallEdges |= ShapeExtend::EncodeStatus( ShapeExtend_DONE3 );
              }
              else index++;
            }
            else 
                {
                  //gka protection aginst removing circles
                  TopoDS_Edge ed = (take_next ? edge1 : edge2);
                  ShapeAnalysis_Edge sae;
                  Handle(Geom_Curve) c3d;
                  Standard_Real f1,l1;
                  if(sae.Curve3d(ed,c3d,f1,l1,Standard_False)) 
                  {
                    gp_Pnt p1,p2,p3;
                    c3d->D0(f1,p1);
                    c3d->D0(l1,p2);
                    c3d->D0((f1 +l1)*0.5,p3);
                    
                    if(p1.Distance(p3) > p1.Distance(p2)) 
                    {
                      index++;
                      continue;
                    }
                  }
              if (take_next && theList2.Extent()== 1)  
                  { //gka
                  TopoDS_Vertex V1 = SAE.FirstVertex(edge1),
                             V2 = SAE.LastVertex(edge1);
                  if(V1.IsSame(V2)) 
                      {
                  SFW->WireData()->Remove (index );
                  Context()->Remove(edge1);
                  if (theSmallEdges.Contains(edge1)) theSmallEdges.Remove(edge1);
                  theEdgeToFaces.UnBind(edge1);
                  myStatusSmallEdges |= ShapeExtend::EncodeStatus( ShapeExtend_DONE2 );
                  }
                  else index++;
                }
                else if( !take_next && theList2.Extent()== 1) 
                    {
                  TopoDS_Vertex V1 = SAE.FirstVertex(edge2),
                  V2 = SAE.LastVertex(edge2);
                  if(V1.IsSame(V2)) 
                      {
                  SFW->WireData()->Remove (index );
                  Context()->Remove(edge2);
                  if (theSmallEdges.Contains(edge2)) theSmallEdges.Remove(edge2);
                  theEdgeToFaces.UnBind(edge2);
                  myStatusSmallEdges |= ShapeExtend::EncodeStatus( ShapeExtend_DONE2 );
                  }
                  else index++;
                }
                else index++; 
            }
            }
            else index++;
          }
          if (SFW->NbEdges() == 1 && aModeDrop) 
            {
            edge1 = SFW->WireData()->Edge(1);
            if (theSmallEdges.Contains(edge1)) 
              {
            SFW->WireData()->Remove(1);
            Context()->Remove(edge1);
            theSmallEdges.Remove(edge1);
            theEdgeToFaces.UnBind(edge1);
            Context()->Remove(aWire);
            myStatusSmallEdges |= ShapeExtend::EncodeStatus( ShapeExtend_DONE2 );
            }
          }
          else 
            {
              SFW->FixConnected();
              Context()->Replace(aWire,SFW->Wire());  
            }
          }
// end enk block      
    // Record vertex replacements in context
    for (TopTools_DataMapIteratorOfDataMapOfShapeShape itv(theNewVertices);
         itv.More(); itv.Next())  Context()->Replace(itv.Key(),itv.Value());
  
    TopoDS_Shape shape = myShape;
    myShape.Nullify();
    myShape = Context()->Apply(shape);
  
    ShapeFix::SameParameter(myShape,Standard_False);
    
    return StatusSmallEdges( ShapeExtend_DONE );
  }

  return Standard_False;
}


Generated by  Doxygen 1.6.0   Back to index