Back to index

salome-geom  6.5.0
Public Member Functions | Private Attributes
BlockFix_UnionFaces Class Reference

#include <BlockFix_UnionFaces.hxx>

List of all members.

Public Member Functions

void * operator new (size_t, void *anAddress)
void * operator new (size_t size)
void operator delete (void *anAddress)
Standard_EXPORT BlockFix_UnionFaces ()
Standard_EXPORT Standard_Real & GetTolerance ()
Standard_EXPORT Standard_Integer & GetOptimumNbFaces ()
Standard_EXPORT TopoDS_Shape Perform (const TopoDS_Shape &Shape)
virtual Standard_EXPORT
Standard_Boolean 
IsSameDomain (const TopoDS_Face &aFace, const TopoDS_Face &aChekedFace) const
virtual Standard_EXPORT void MovePCurves (TopoDS_Face &aTarget, const TopoDS_Face &aSource) const

Private Attributes

Standard_Real myTolerance
Standard_Integer myOptimumNbFaces

Detailed Description

Definition at line 42 of file BlockFix_UnionFaces.hxx.


Constructor & Destructor Documentation

Definition at line 108 of file BlockFix_UnionFaces.cxx.

  : myTolerance(Precision::Confusion()),
    myOptimumNbFaces(6)
{
}

Member Function Documentation

Definition at line 131 of file BlockFix_UnionFaces.cxx.

{
  return myOptimumNbFaces;
}

Here is the caller graph for this function:

Standard_Real & BlockFix_UnionFaces::GetTolerance ( )

Definition at line 120 of file BlockFix_UnionFaces.cxx.

{
  return myTolerance;
}

Here is the caller graph for this function:

Standard_Boolean BlockFix_UnionFaces::IsSameDomain ( const TopoDS_Face &  aFace,
const TopoDS_Face &  aChekedFace 
) const [virtual]

Definition at line 582 of file BlockFix_UnionFaces.cxx.

{
  //checking the same handles
  TopLoc_Location L1, L2;
  Handle(Geom_Surface) S1, S2;

  S1 = BRep_Tool::Surface(aFace,L1);
  S2 = BRep_Tool::Surface(aCheckedFace,L2);

  if (S1 == S2 && L1 == L2)
    return true;

  // planar and cylindrical cases (IMP 20052)
  Standard_Real aPrec = Precision::Confusion();

  S1 = BRep_Tool::Surface(aFace);
  S2 = BRep_Tool::Surface(aCheckedFace);

  S1 = ClearRts(S1);
  S2 = ClearRts(S2);

  //Handle(Geom_OffsetSurface) aGOFS1, aGOFS2;
  //aGOFS1 = Handle(Geom_OffsetSurface)::DownCast(S1);
  //aGOFS2 = Handle(Geom_OffsetSurface)::DownCast(S2);
  //if (!aGOFS1.IsNull()) S1 = aGOFS1->BasisSurface();
  //if (!aGOFS2.IsNull()) S2 = aGOFS2->BasisSurface();

  // case of two elementary surfaces: use OCCT tool
  // elementary surfaces: ConicalSurface, CylindricalSurface,
  //                      Plane, SphericalSurface and ToroidalSurface
  if (S1->IsKind(STANDARD_TYPE(Geom_ElementarySurface)) &&
      S2->IsKind(STANDARD_TYPE(Geom_ElementarySurface)))
  {
    Handle(GeomAdaptor_HSurface) aGA1 = new GeomAdaptor_HSurface(S1);
    Handle(GeomAdaptor_HSurface) aGA2 = new GeomAdaptor_HSurface(S2);

    Handle(BRepTopAdaptor_TopolTool) aTT1 = new BRepTopAdaptor_TopolTool();
    Handle(BRepTopAdaptor_TopolTool) aTT2 = new BRepTopAdaptor_TopolTool();

    try {
#if OCC_VERSION_LARGE > 0x06010000
      OCC_CATCH_SIGNALS;
#endif

#if OCC_VERSION_LARGE > 0x06040000 // Porting to OCCT6.5.1
      IntPatch_ImpImpIntersection anIIInt (aGA1, aTT1, aGA2, aTT2, aPrec, aPrec);
#else
      IntPatch_TheIIIntOfIntersection anIIInt (aGA1, aTT1, aGA2, aTT2, aPrec, aPrec);
#endif
      if (!anIIInt.IsDone() || anIIInt.IsEmpty())
        return false;

      return anIIInt.TangentFaces();
    }
    catch (Standard_Failure) {
      return false;
    }
  }

  // case of two planar surfaces:
  // all kinds of surfaces checked, including b-spline and bezier
  GeomLib_IsPlanarSurface aPlanarityChecker1 (S1, aPrec);
  if (aPlanarityChecker1.IsPlanar()) {
    GeomLib_IsPlanarSurface aPlanarityChecker2 (S2, aPrec);
    if (aPlanarityChecker2.IsPlanar()) {
      gp_Pln aPln1 = aPlanarityChecker1.Plan();
      gp_Pln aPln2 = aPlanarityChecker2.Plan();

      if (aPln1.Position().Direction().IsParallel(aPln2.Position().Direction(), aPrec) &&
          aPln1.Distance(aPln2) < aPrec) {
        return true;
      }
    }
  }

  // case of two cylindrical surfaces, at least one of which is a swept surface
  // swept surfaces: SurfaceOfLinearExtrusion, SurfaceOfRevolution
  if ((S1->IsKind(STANDARD_TYPE(Geom_CylindricalSurface)) ||
       S1->IsKind(STANDARD_TYPE(Geom_SweptSurface))) &&
      (S2->IsKind(STANDARD_TYPE(Geom_CylindricalSurface)) ||
       S2->IsKind(STANDARD_TYPE(Geom_SweptSurface))))
  {
    gp_Cylinder aCyl1, aCyl2;
    if (getCylinder(S1, aCyl1) && getCylinder(S2, aCyl2)) {
      if (fabs(aCyl1.Radius() - aCyl2.Radius()) < aPrec) {
        gp_Dir aDir1 = aCyl1.Position().Direction();
        gp_Dir aDir2 = aCyl2.Position().Direction();
        if (aDir1.IsParallel(aDir2, aPrec)) {
          gp_Pnt aLoc1 = aCyl1.Location();
          gp_Pnt aLoc2 = aCyl2.Location();
          gp_Vec aVec12 (aLoc1, aLoc2);
          if (aVec12.SquareMagnitude() < aPrec*aPrec ||
              aVec12.IsParallel(aDir1, aPrec)) {
            return true;
          }
        }
      }
    }
  }

  return false;
}

Here is the call graph for this function:

Here is the caller graph for this function:

void BlockFix_UnionFaces::MovePCurves ( TopoDS_Face &  aTarget,
const TopoDS_Face &  aSource 
) const [virtual]

Definition at line 692 of file BlockFix_UnionFaces.cxx.

{
  BRep_Builder B;
  for(TopExp_Explorer wexp(aSource,TopAbs_WIRE);wexp.More();wexp.Next()) {
    Handle(ShapeFix_Wire) sfw = new ShapeFix_Wire(TopoDS::Wire(wexp.Current()),
                                                  aTarget, Precision::Confusion());
    sfw->FixReorder();
    Standard_Boolean isReoredFailed = sfw->StatusReorder ( ShapeExtend_FAIL );
    sfw->FixEdgeCurves();
    if(isReoredFailed)
      continue;

    sfw->FixShifted();
    sfw->FixDegenerated();

    // remove degenerated edges from not degenerated points
    ShapeAnalysis_Edge sae;
    Handle(ShapeExtend_WireData) sewd = sfw->WireData();
    for(Standard_Integer i = 1; i<=sewd->NbEdges();i++) {
      TopoDS_Edge E = sewd->Edge(i);
      if(BRep_Tool::Degenerated(E)&&!sae.HasPCurve(E,aTarget)) {
        sewd->Remove(i);
        i--;
      }
    }

    TopoDS_Wire ResWire = sfw->Wire();
    B.Add(aTarget,ResWire);
  }
}

Here is the call graph for this function:

Here is the caller graph for this function:

void BlockFix_UnionFaces::operator delete ( void *  anAddress) [inline]

Definition at line 53 of file BlockFix_UnionFaces.hxx.

  {
    if (anAddress) Standard::Free((Standard_Address&)anAddress);
  }
void* BlockFix_UnionFaces::operator new ( size_t  ,
void *  anAddress 
) [inline]

Definition at line 45 of file BlockFix_UnionFaces.hxx.

  {
    return anAddress;
  }
void* BlockFix_UnionFaces::operator new ( size_t  size) [inline]

Definition at line 49 of file BlockFix_UnionFaces.hxx.

  {
    return Standard::Allocate(size);
  }
TopoDS_Shape BlockFix_UnionFaces::Perform ( const TopoDS_Shape &  Shape)

Definition at line 204 of file BlockFix_UnionFaces.cxx.

{
  Handle(ShapeBuild_ReShape) myContext = new ShapeBuild_ReShape;
  TopoDS_Shape aResShape = myContext->Apply(Shape);

  // processing each solid
  TopExp_Explorer exps;
  for (exps.Init(Shape, TopAbs_SOLID); exps.More(); exps.Next()) {
    TopoDS_Solid aSolid = TopoDS::Solid(exps.Current());

    // creating map of edge faces
    TopTools_IndexedDataMapOfShapeListOfShape aMapEdgeFaces;
    TopExp::MapShapesAndAncestors(aSolid, TopAbs_EDGE, TopAbs_FACE, aMapEdgeFaces);

    // map of processed shapes
    TopTools_MapOfShape aProcessed;

    Handle(ShapeBuild_ReShape) aContext = new ShapeBuild_ReShape;

    Standard_Integer NbModif = 0;
    Standard_Boolean hasFailed = Standard_False;
    Standard_Real tol = Min(Max(Precision::Confusion(), myTolerance/10.), 0.1);

    // count faces
    int nbf = 0;
    TopExp_Explorer exp;
    TopTools_MapOfShape mapF;
    for (exp.Init(aSolid, TopAbs_FACE); exp.More(); exp.Next()) {
      if (mapF.Add(exp.Current()))
        nbf++;
    }

    bool doUnion = ((myOptimumNbFaces == 0) ||
                    ((myOptimumNbFaces > 0) && (nbf > myOptimumNbFaces)));

    // processing each face
    mapF.Clear();
    for (exp.Init(aSolid, TopAbs_FACE); exp.More() && doUnion; exp.Next()) {
      TopoDS_Face aFace = TopoDS::Face(exp.Current().Oriented(TopAbs_FORWARD));

      if (aProcessed.Contains(aFace))
        continue;

      Standard_Integer dummy;
      TopTools_SequenceOfShape edges;
      AddOrdinaryEdges(edges,aFace,dummy);

      TopTools_SequenceOfShape faces;
      faces.Append(aFace);

      //surface and location to construct result
      TopLoc_Location aBaseLocation;
      Handle(Geom_Surface) aBaseSurface = BRep_Tool::Surface(aFace,aBaseLocation);
      aBaseSurface = ClearRts(aBaseSurface);

      // find adjacent faces to union
      Standard_Integer i;
      for (i = 1; i <= edges.Length(); i++) {
        TopoDS_Edge edge = TopoDS::Edge(edges(i));
        if (BRep_Tool::Degenerated(edge))
          continue;

        const TopTools_ListOfShape& aList = aMapEdgeFaces.FindFromKey(edge);
        TopTools_ListIteratorOfListOfShape anIter(aList);
        for (; anIter.More(); anIter.Next()) {
          TopoDS_Face anCheckedFace = TopoDS::Face(anIter.Value().Oriented(TopAbs_FORWARD));
          if (anCheckedFace.IsSame(aFace))
            continue;

          if (aProcessed.Contains(anCheckedFace))
            continue;

          if (IsSameDomain(aFace,anCheckedFace)) {

            if (aList.Extent() != 2) {
              // non mainfold case is not processed
              continue;
            }

            // replacing pcurves
            TopoDS_Face aMockUpFace;
            BRep_Builder B;
            B.MakeFace(aMockUpFace,aBaseSurface,aBaseLocation,0.);
            MovePCurves(aMockUpFace,anCheckedFace);

            if (AddOrdinaryEdges(edges,aMockUpFace,dummy)) {
              // sequence edges is modified
              i = dummy;
            }

            faces.Append(anCheckedFace);
            aProcessed.Add(anCheckedFace);
            break;
          }
        }
      }

      // all faces collected in the sequence. Perform union of faces
      if (faces.Length() > 1) {
        NbModif++;
        TopoDS_Face aResult;
        BRep_Builder B;
        B.MakeFace(aResult,aBaseSurface,aBaseLocation,0);
        Standard_Integer nbWires = 0;

        // connecting wires
        while (edges.Length()>0) {

          Standard_Boolean isEdge3d = Standard_False;
          nbWires++;
          TopTools_MapOfShape aVertices;
          TopoDS_Wire aWire;
          B.MakeWire(aWire);

          TopoDS_Edge anEdge = TopoDS::Edge(edges(1));
          edges.Remove(1);

          isEdge3d |= !BRep_Tool::Degenerated(anEdge);
          B.Add(aWire,anEdge);
          TopoDS_Vertex V1,V2;
          TopExp::Vertices(anEdge,V1,V2);
          aVertices.Add(V1);
          aVertices.Add(V2);

          Standard_Boolean isNewFound = Standard_False;
          do {
            isNewFound = Standard_False;
            for(Standard_Integer j = 1; j <= edges.Length(); j++) {
              anEdge = TopoDS::Edge(edges(j));
              TopExp::Vertices(anEdge,V1,V2);
              if(aVertices.Contains(V1) || aVertices.Contains(V2)) {
                isEdge3d |= !BRep_Tool::Degenerated(anEdge);
                aVertices.Add(V1);
                aVertices.Add(V2);
                B.Add(aWire,anEdge);
                edges.Remove(j);
                j--;
                isNewFound = Standard_True;
              }
            }
          } while (isNewFound);

          // sorting any type of edges
          aWire = TopoDS::Wire(aContext->Apply(aWire));

          TopoDS_Face tmpF = TopoDS::Face(aContext->Apply(faces(1).Oriented(TopAbs_FORWARD)));
          Handle(ShapeFix_Wire) sfw = new ShapeFix_Wire(aWire,tmpF,Precision::Confusion());
          sfw->FixReorder();
          Standard_Boolean isDegRemoved = Standard_False;
          if(!sfw->StatusReorder ( ShapeExtend_FAIL )) {
            // clear degenerated edges if at least one with 3d curve exist
            if(isEdge3d) {
              Handle(ShapeExtend_WireData) sewd = sfw->WireData();
              for(Standard_Integer j = 1; j<=sewd->NbEdges();j++) {
                TopoDS_Edge E = sewd->Edge(j);
                if(BRep_Tool::Degenerated(E)) {
                  sewd->Remove(j);
                  isDegRemoved = Standard_True;
                  j--;
                }
              }
            }
            sfw->FixShifted();
            if(isDegRemoved)
              sfw->FixDegenerated();
          }
          TopoDS_Wire aWireFixed = sfw->Wire();
          aContext->Replace(aWire,aWireFixed);
          // add resulting wire
          if(isEdge3d) {
            B.Add(aResult,aWireFixed);
          }
          else  {
            // sorting edges
            Handle(ShapeExtend_WireData) sbwd = sfw->WireData();
            Standard_Integer nbEdges = sbwd->NbEdges();
            // sort degenerated edges and create one edge instead of several ones
            ShapeAnalysis_WireOrder sawo(Standard_False, 0);
            ShapeAnalysis_Edge sae;
            Standard_Integer aLastEdge = nbEdges;
            for(Standard_Integer j = 1; j <= nbEdges; j++) {
              Standard_Real f,l;
              //smh protection on NULL pcurve
              Handle(Geom2d_Curve) c2d;
              if(!sae.PCurve(sbwd->Edge(j),tmpF,c2d,f,l)) {
                aLastEdge--;
                continue;
              }
              sawo.Add(c2d->Value(f).XY(),c2d->Value(l).XY());
            }
            sawo.Perform();

            // constructind one degenerative edge
            gp_XY aStart, anEnd, tmp;
            Standard_Integer nbFirst = sawo.Ordered(1);
            TopoDS_Edge anOrigE = TopoDS::Edge(sbwd->Edge(nbFirst).Oriented(TopAbs_FORWARD));
            ShapeBuild_Edge sbe;
            TopoDS_Vertex aDummyV;
            TopoDS_Edge E = sbe.CopyReplaceVertices(anOrigE,aDummyV,aDummyV);
            sawo.XY(nbFirst,aStart,tmp);
            sawo.XY(sawo.Ordered(aLastEdge),tmp,anEnd);

            gp_XY aVec = anEnd-aStart;
            Handle(Geom2d_Line) aLine = new Geom2d_Line(aStart,gp_Dir2d(anEnd-aStart));

            B.UpdateEdge(E,aLine,tmpF,0.);
            B.Range(E,tmpF,0.,aVec.Modulus());
            Handle(Geom_Curve) C3d;
            B.UpdateEdge(E,C3d,0.);
            B.Degenerated(E,Standard_True);
            TopoDS_Wire aW;
            B.MakeWire(aW);
            B.Add(aW,E);
            B.Add(aResult,aW);
          }
        }

        // perform substitution of face
        aContext->Replace(aContext->Apply(aFace),aResult);

        ShapeFix_Face sff (aResult);
        //Intializing by tolerances
        sff.SetPrecision(myTolerance);
        sff.SetMinTolerance(tol);
        sff.SetMaxTolerance(Max(1.,myTolerance*1000.));
        //Setting modes
        sff.FixOrientationMode() = 0;
        //sff.FixWireMode() = 0;
        sff.SetContext(aContext);
        // Applying the fixes
        sff.Perform();
        if(sff.Status(ShapeExtend_FAIL))
        hasFailed = Standard_True;

        // breaking down to several faces
        TopoDS_Shape theResult = aContext->Apply(aResult);
        for (TopExp_Explorer aFaceExp (theResult,TopAbs_FACE); aFaceExp.More(); aFaceExp.Next()) {
          TopoDS_Face aCurrent = TopoDS::Face(aFaceExp.Current().Oriented(TopAbs_FORWARD));
          Handle(TColGeom_HArray2OfSurface) grid = new TColGeom_HArray2OfSurface ( 1, 1, 1, 1 );
          grid->SetValue ( 1, 1, aBaseSurface );
          Handle(ShapeExtend_CompositeSurface) G = new ShapeExtend_CompositeSurface ( grid );
          ShapeFix_ComposeShell CompShell;
          CompShell.Init ( G, aBaseLocation, aCurrent, ::Precision::Confusion() );//myPrecision
          CompShell.SetContext( aContext );

          TopTools_SequenceOfShape parts;
          ShapeFix_SequenceOfWireSegment wires;
          for(TopExp_Explorer W_Exp(aCurrent,TopAbs_WIRE);W_Exp.More();W_Exp.Next()) {
            Handle(ShapeExtend_WireData) sbwd =
              new ShapeExtend_WireData ( TopoDS::Wire(W_Exp.Current() ));
            ShapeFix_WireSegment seg ( sbwd, TopAbs_REVERSED );
            wires.Append(seg);
          }

          CompShell.DispatchWires ( parts,wires );
          for (Standard_Integer j=1; j <= parts.Length(); j++ ) {
            ShapeFix_Face aFixOrient(TopoDS::Face(parts(j)));
            aFixOrient.SetContext(aContext);
            aFixOrient.FixOrientation();
          }

          TopoDS_Shape CompRes;
          if ( faces.Length() !=1 ) {
            TopoDS_Shell S;
            B.MakeShell ( S );
            for ( i=1; i <= parts.Length(); i++ )
              B.Add ( S, parts(i) );
            CompRes = S;
          }
          else CompRes = parts(1);

          aContext->Replace(aCurrent,CompRes);
        }

        // remove the remaining faces
        for(i = 2; i <= faces.Length(); i++)
          aContext->Remove(faces(i));
      }
    } // end processing each face

    //TopoDS_Shape aResult = Shape;
    if (NbModif > 0 && !hasFailed) {
      TopoDS_Shape aResult = aContext->Apply(aSolid);

      ShapeFix_Edge sfe;
      for (exp.Init(aResult,TopAbs_EDGE); exp.More(); exp.Next()) {
        TopoDS_Edge E = TopoDS::Edge(exp.Current());
        sfe.FixVertexTolerance (E);
        // ptv add fix same parameter
        sfe.FixSameParameter(E, myTolerance);
      }

      myContext->Replace(aSolid, aResult);
    }
    //else
    {
      for (exp.Init(aSolid, TopAbs_FACE); exp.More(); exp.Next()) {
        TopoDS_Face aFace = TopoDS::Face(exp.Current().Oriented(TopAbs_FORWARD));
        Handle(ShapeFix_Wire) sfw = new ShapeFix_Wire;
        sfw->SetContext(myContext);
        sfw->SetPrecision(myTolerance);
        sfw->SetMinTolerance(myTolerance);
        sfw->SetMaxTolerance(Max(1.,myTolerance*1000.));
        sfw->SetFace(aFace);
        for (TopoDS_Iterator iter (aFace,Standard_False); iter.More(); iter.Next()) {
          TopoDS_Wire wire = TopoDS::Wire(iter.Value());
          sfw->Load(wire);
          sfw->FixReorder();
          sfw->FixShifted();
        }
      }
    }
  } // end processing each solid

  aResShape = myContext->Apply(Shape);
  return aResShape;
}

Here is the call graph for this function:

Here is the caller graph for this function:


Member Data Documentation

Standard_Integer BlockFix_UnionFaces::myOptimumNbFaces [private]

Definition at line 87 of file BlockFix_UnionFaces.hxx.

Standard_Real BlockFix_UnionFaces::myTolerance [private]

Definition at line 86 of file BlockFix_UnionFaces.hxx.


The documentation for this class was generated from the following files: