//=======================================================================
//function : IsInternalFace
//purpose  : 
//=======================================================================
  Standard_Boolean GEOMAlgo_Tools3D::IsInternalFace(const TopoDS_Face& theFace,
                                                   const TopoDS_Solid& theSolid,
                                                   const TopTools_IndexedDataMapOfShapeListOfShape& theMEF,
                                                   const Standard_Real theTol,
                                                   IntTools_Context& theContext)
{
  Standard_Boolean bRet;
  Standard_Integer aNbF;
  TopoDS_Edge aEL;
  TopExp_Explorer aExp;
  TopTools_ListIteratorOfListOfShape aItF;
  //
  bRet=Standard_False;
  //
  // 1 Try to find an edge from theFace in theMEF
  aExp.Init(theFace, TopAbs_EDGE);
  for(; aExp.More(); aExp.Next()) {
    const TopoDS_Edge& aE=TopoDS::Edge(aExp.Current());
    if (!theMEF.Contains(aE)) {
      continue;
    }
    // 
    const TopTools_ListOfShape& aLF=theMEF.FindFromKey(aE);
    aNbF=aLF.Extent();
    if (!aNbF) {
      return bRet; // it can not be so
    }
    else if (aNbF==1) {
      // aE is internal edge on aLF.First()
      const TopoDS_Face& aF1=TopoDS::Face(aLF.First());
      bRet=GEOMAlgo_Tools3D::IsInternalFace(theFace, aE, aF1, aF1, theContext);
      return bRet;
    }
    else if (aNbF==2) {
      const TopoDS_Face& aF1=TopoDS::Face(aLF.First());
      const TopoDS_Face& aF2=TopoDS::Face(aLF.Last());
      //
      if (aF2.IsSame(aF1) && BRep_Tool::IsClosed(aE, aF1)) {
        // treat as it was for 1 face
        bRet=GEOMAlgo_Tools3D::IsInternalFace(theFace, aE, aF1, aF2, theContext);
        return bRet;
      }
    }
    if (aNbF%2) {
      return bRet; // it can not be so
    }
    else { // aNbF=2,4,6,8,...
      bRet=GEOMAlgo_Tools3D::IsInternalFace(theFace, aE, aLF, theContext);
      return bRet;
    }
  }//for(; aExp.More(); aExp.Next()) {
  //
  //========================================
  // 2. Classify face using classifier
  //
  TopAbs_State aState;
  TopTools_IndexedMapOfShape aBounds;
  //
  aState=GEOMAlgo_Tools3D::ComputeState(theFace, theSolid, theTol, aBounds, theContext);
  bRet=(aState==TopAbs_IN);
  //
  return bRet;
}
//=======================================================================
//function :IsSplitToReverse
//purpose  : 
//=======================================================================
  Standard_Boolean GEOMAlgo_Tools3D::IsSplitToReverse(const TopoDS_Face& theFSp,
                                                     const TopoDS_Face& theFSr,
                                                     IntTools_Context& theContext)
{
  Standard_Boolean bRet, bFound, bInFace;
  Standard_Real aT1, aT2, aT, aU, aV, aScPr;
  gp_Pnt aPFSp, aPFSr;
  gp_Dir aDNFSp;
  gp_Vec aD1U, aD1V;
  Handle(Geom_Surface) aSr, aSp;
  TopAbs_Orientation aOrSr, aOrSp;
  TopExp_Explorer anExp;
  TopoDS_Edge aESp;
  //
  bRet=Standard_False;
  //
  aSr=BRep_Tool::Surface(theFSr);
  aSp=BRep_Tool::Surface(theFSp);
  if (aSr==aSp) {
    aOrSr=theFSr.Orientation();
    aOrSp=theFSp.Orientation();
    bRet=(aOrSr!=aOrSp);
    return bRet;
  }
  //
  bFound=Standard_False;
  anExp.Init(theFSp, TopAbs_EDGE);
  for (; anExp.More(); anExp.Next()) {
    aESp=TopoDS::Edge(anExp.Current());
    if (!BRep_Tool::Degenerated(aESp)) {
      if (!BRep_Tool::IsClosed(aESp, theFSp)) {
        bFound=!bFound;
        break;
      }
    }
  }
  if (!bFound) {
    return bRet;
  }
  //
  BRep_Tool::Range(aESp, aT1, aT2);
  aT=BOPTools_Tools2D::IntermediatePoint(aT1, aT2);
  BOPTools_Tools3D::GetApproxNormalToFaceOnEdge(aESp, theFSp, aT, aPFSp, aDNFSp);
  //
  // Parts of theContext.ComputeVS(..) 
  GeomAPI_ProjectPointOnSurf& aProjector=theContext.ProjPS(theFSr);
  aProjector.Perform(aPFSp);
  if (!aProjector.IsDone()) {
    return bRet;
  }
  //
  aProjector.LowerDistanceParameters(aU, aV);
  gp_Pnt2d aP2D(aU, aV);
  bInFace=theContext.IsPointInFace (theFSr, aP2D);
  if (!bInFace) {
    return bRet;
  }
  //
  aSr->D1(aU, aV, aPFSr, aD1U, aD1V);
  gp_Dir aDD1U(aD1U); 
  gp_Dir aDD1V(aD1V);
  gp_Dir aDNFSr=aDD1U^aDD1V; 
  if (theFSr.Orientation()==TopAbs_REVERSED){
    aDNFSr.Reverse();
  }
  //
  aScPr=aDNFSp*aDNFSr;
  bRet=(aScPr<0.);
  //
  return bRet;
}
//=======================================================================
// function: BuildSplitFaces
// purpose: 
//=======================================================================
  void GEOMAlgo_Builder::BuildSplitFaces()
{
  const NMTDS_ShapesDataStructure& aDS=*myPaveFiller->DS();
  NMTTools_PaveFiller* pPF=myPaveFiller;
  NMTDS_InterfPool* pIP=pPF->IP();
  BOPTools_CArray1OfSSInterference& aFFs=pIP->SSInterferences();
  IntTools_Context& aCtx= pPF->ChangeContext();
  //
  Standard_Boolean bToReverse, bIsClosed, bIsDegenerated;
  Standard_Integer i, aNb, aNbF, nF;
  TopTools_MapOfShape aMFence;
  TColStd_IndexedMapOfInteger aMFP;
  TopExp_Explorer anExp;
  TopoDS_Face aFF;
  TopoDS_Edge aSp, aEE;
  TopTools_ListIteratorOfListOfShape aIt;
  TopAbs_Orientation anOriF, anOriE;
  //
  mySplitFaces.Clear();
  //
  // 1. Select Faces to process (MFP)
  aNb=aDS.NumberOfShapesOfTheObject();
  for (i=1; i<=aNb; ++i) {
    const TopoDS_Shape& aF=aDS.Shape(i);
    if (aF.ShapeType()!=TopAbs_FACE) {
      continue;
    }
    if (!aMFence.Add(aF)) {
      continue;
    }
    //
    if (myInParts.Contains(aF)) {
      aMFP.Add(i);
      continue;
    }
    //
    anExp.Init(aF, TopAbs_EDGE);
    for (; anExp.More(); anExp.Next()) {
      const TopoDS_Shape& aE=anExp.Current();
      if (myImages.HasImage(aE)) {
	aMFP.Add(i);
	break;
      }
    }
    //
    //===
    {
      Standard_Integer aNbFFs, aNbSE, j, n1, n2;
      //
      aNbFFs=aFFs.Extent();
      for (j=1; j<=aNbFFs; ++j) {
	BOPTools_SSInterference& aFFj=aFFs(j);
	aFFj.Indices(n1, n2);
	if (!(n1==i || n2==i)) {
	  continue;
	}
	//
	const TColStd_ListOfInteger& aLSE=aFFj.SharedEdges();
	aNbSE=aLSE.Extent();
	if (aNbSE) {
	  aMFP.Add(i);
          break;
	}
      }
    }
    //===
    //
  }// for (i=1; i<=aNb; ++i)
  //
  // 2. ProcessFaces
  aNbF=aMFP.Extent();
  for (i=1; i<=aNbF; ++i) {
    nF=aMFP(i);
    const TopoDS_Face& aF=TopoDS::Face(aDS.Shape(nF));
    anOriF=aF.Orientation();
    aFF=aF;
    aFF.Orientation(TopAbs_FORWARD);
    //
    aMFence.Clear();
    //
    // 2.1. Fill WES 
    GEOMAlgo_WireEdgeSet aWES;
    aWES.SetFace(aFF);
    //
    //  2.1.1. Add Split parts
    anExp.Init(aFF, TopAbs_EDGE);
    for (; anExp.More(); anExp.Next()) {
      const TopoDS_Edge& aE=TopoDS::Edge(anExp.Current());
      anOriE=aE.Orientation();
      //
      if (!myImages.HasImage(aE)) {
	if (anOriE==TopAbs_INTERNAL) {
	  aEE=aE;
	  aEE.Orientation(TopAbs_FORWARD);
	  aWES.AddStartElement(aEE);
	  aEE.Orientation(TopAbs_REVERSED);
	  aWES.AddStartElement(aEE);
	}
	else {
	  aWES.AddStartElement(aE);
	}
	continue;
      }
      //
      bIsDegenerated=BRep_Tool::Degenerated(aE);
      bIsClosed=BRep_Tool::IsClosed(aE, aF);
      //
      const TopTools_ListOfShape& aLIE=myImages.Image(aE);
      aIt.Initialize(aLIE);
      for (; aIt.More(); aIt.Next()) {
	aSp=TopoDS::Edge(aIt.Value());
	//
	if (bIsDegenerated) {
	  aSp.Orientation(anOriE);
	  aWES.AddStartElement(aSp);
	  continue;
	}
	//
	if (anOriE==TopAbs_INTERNAL) {
	  aSp.Orientation(TopAbs_FORWARD);
	  aWES.AddStartElement(aSp);
	  aSp.Orientation(TopAbs_REVERSED);
	  aWES.AddStartElement(aSp);
	  continue;
	}
	//
	if (bIsClosed){
	  if (aMFence.Add(aSp)) {
	    //
	    if (!BRep_Tool::IsClosed(aSp, aF)){
	      BOPTools_Tools3D::DoSplitSEAMOnFace(aSp, aF);
	    }
	    //
	    aSp.Orientation(TopAbs_FORWARD);
	    aWES.AddStartElement(aSp);
	    aSp.Orientation(TopAbs_REVERSED);
	    aWES.AddStartElement(aSp);
	  }
	  continue;
	}// if (aMFence.Add(aSp))
	//
	aSp.Orientation(anOriE);
	bToReverse=BOPTools_Tools3D::IsSplitToReverse1(aSp, aE, (Handle_IntTools_Context&)aCtx);
	if (bToReverse) {
	  aSp.Reverse();
	}
	aWES.AddStartElement(aSp);
      }// for (; aIt.More(); aIt.Next()) {
    }// for (; anExp.More(); anExp.Next()) {
    //
    // 2.1.2. Add In2D Parts
    if (myInParts.Contains(aF)) {
      const TopTools_ListOfShape& aLE=myInParts.FindFromKey(aF);
      aIt.Initialize(aLE);
      for (; aIt.More(); aIt.Next()) {
	aSp=TopoDS::Edge(aIt.Value());
	//
	aSp.Orientation(TopAbs_FORWARD);
	aWES.AddStartElement(aSp);
	//
	aSp.Orientation(TopAbs_REVERSED);
	aWES.AddStartElement(aSp);
      }
    }
    //
    // 2.2. Build images Faces
    TopTools_ListOfShape aLFR;
    GEOMAlgo_ShapeSet aS1, aS2;
    //
    const TopTools_ListOfShape& aSE=aWES.StartElements();
    aS1.Add(aSE);
    aS2.Add(aFF, TopAbs_EDGE);
    if (aS1.IsEqual(aS2)) {
      aLFR.Append(aF);
    }
    else {
    GEOMAlgo_BuilderFace aBF;
    //
    aBF.SetFace(aFF);
    aBF.SetContext((Handle_IntTools_Context&)aCtx);
    /*
    {
      TopoDS_Compound aCx;
      BRep_Builder aBBx;
      TopTools_ListIteratorOfListOfShape aItx;
      //
      aBBx.MakeCompound(aCx);
      aBBx.Add(aCx, aFF);
      aItx.Initialize(aSE);
      for (; aItx.More(); aItx.Next()) {
	TopoDS_Shape& aEx=aItx.Value();
	aBBx.Add(aCx, aEx);
      }
      int a=0;
    }
    */
    aBF.SetShapes(aSE);
      // <-DEB
    aBF.Perform();
    //
    const TopTools_ListOfShape& aLF=aBF.Areas();
    aIt.Initialize(aLF);
    for (; aIt.More(); aIt.Next()) {
      TopoDS_Shape& aFR=aIt.Value();
      if (anOriF==TopAbs_REVERSED) {
	aFR.Orientation(TopAbs_REVERSED);
      }
      aLFR.Append(aFR);
    }
    }
    //
    // 2.3. Collect draft images Faces
    mySplitFaces.Bind(aF, aLFR);
  }//for (i=1; i<=aNbF; ++i)
}
//=================================================================================
// function: BuildResult
// purpose:
//=================================================================================
void GEOMAlgo_ShellSolid::BuildResult()
{
  Standard_Boolean bIsTouchCase;
  Standard_Integer i, j, nF1, nF2, aNbFFs, aNbS, aNbCurves, nSp, iRank1;
  Standard_Integer nE, nF, aNbPB, iBeg, iEnd;
  BooleanOperations_StateOfShape aState;
  TopExp_Explorer anExp;
  TopAbs_ShapeEnum aType;
  gp_Pnt2d aP2D;
  gp_Pnt aP3D;
  //
  const BooleanOperations_ShapesDataStructure& aDS=myDSFiller->DS();
  const BOPTools_InterferencePool& anInterfPool=myDSFiller->InterfPool();
  BOPTools_InterferencePool* pInterfPool=(BOPTools_InterferencePool*) &anInterfPool;
  BOPTools_CArray1OfSSInterference& aFFs=pInterfPool->SSInterferences();
  const BOPTools_PaveFiller& aPaveFiller=myDSFiller->PaveFiller();
  const BOPTools_SplitShapesPool& aSplitShapesPool=aPaveFiller.SplitShapesPool();
  //
  // 1. process pf non-interferring faces
  iBeg=1;
  iEnd=aDS.NumberOfShapesOfTheObject();
  if (myRank==2) {
    iBeg=iEnd+1;
    iEnd=aDS.NumberOfSourceShapes();
  }
  //
  for (i=iBeg; i<=iEnd; ++i) {
    aType=aDS.GetShapeType(i);
    if (aType!=TopAbs_FACE) {
      continue;
    }
    //
    const TopoDS_Face& aF1=TopoDS::Face(aDS.Shape(i));
    aState=aDS.GetState(i);
    if (aState==BooleanOperations_IN) {
      myLSIN.Append(aF1);
    }
    else if (aState==BooleanOperations_OUT) {
      myLSOUT.Append(aF1);
    }
  }
  //
  // 2. process pf interferred faces
  aNbFFs=aFFs.Extent();
  for (i=1; i<=aNbFFs; ++i) {
    BOPTools_SSInterference& aFFi=aFFs(i);
    //
    nF1=aFFi.Index1();
    nF2=aFFi.Index2();
    iRank1=aDS.Rank(nF1);
    nF=(iRank1==myRank) ? nF1 : nF2;
    const TopoDS_Face& aF1=TopoDS::Face(aDS.Shape(nF));
    //
    bIsTouchCase=aFFi.IsTangentFaces();
    //
    if (bIsTouchCase) {
      myLSON.Append(aF1);
      continue;
    }
    //
    // Has section edges ?
    aNbS=0;
    BOPTools_SequenceOfCurves& aBCurves=aFFi.Curves();
    aNbCurves=aBCurves.Length();
    for (j=1; j<=aNbCurves; j++) {
      BOPTools_Curve& aBC=aBCurves(j);
      const BOPTools_ListOfPaveBlock& aSectEdges=aBC.NewPaveBlocks();
      aNbS=aSectEdges.Extent();
      if (aNbS) {
        break;
      }
    }
    //
    if (aNbS) { // it has
      continue;
    }
    //
    anExp.Init(aF1, TopAbs_EDGE);
    for (; anExp.More(); anExp.Next()) {
      const TopoDS_Edge& aE=TopoDS::Edge(anExp.Current());
      if (BRep_Tool::Degenerated(aE)) {
        continue;
      }
      //
      nE=aDS.ShapeIndex(aE, myRank);
      const BOPTools_ListOfPaveBlock& aLPB=aSplitShapesPool(aDS.RefEdge(nE));
      aNbPB=aLPB.Extent();
      //
      if (aNbPB<2) {
        nSp=nE;
        if (aNbPB) {
          const BOPTools_PaveBlock& aPB=aLPB.First();
          nSp=aPB.Edge();
        }
        /*const TopoDS_Shape& aSp=*/aDS.Shape(nSp);
        //
        aState=aDS.GetState(nSp);
        if (aState==BooleanOperations_IN) {
          myLSIN.Append(aF1);
        }
        else if (aState==BooleanOperations_OUT) {
          myLSOUT.Append(aF1);
        }
        else if (aState==BooleanOperations_ON) {
          Standard_Real aTol;
          TopAbs_State aSt;
          //
          //const TopoDS_Face& aF2=TopoDS::Face(aDS.Shape((iRank1==myRank)? nF2 : nF1));
          //aTol=BRep_Tool::Tolerance(aF2);
          aTol=1.e-7;
          //
          BOPTools_Tools3D::PointNearEdge(aE, aF1, aP2D, aP3D);
          const TopoDS_Solid& aRefSolid=(myRank==1) ?
            TopoDS::Solid(aDS.Tool()) : TopoDS::Solid(aDS.Object());
          //
          BOPTools_PaveFiller* pPF=(BOPTools_PaveFiller*)& aPaveFiller;
          const Handle(IntTools_Context)& aCtx=pPF->Context();
          //
          BRepClass3d_SolidClassifier& aSC=aCtx->SolidClassifier(aRefSolid);
          aSC.Perform(aP3D, aTol);
          aSt=aSC.State();
          if (aSt==TopAbs_IN) {
            myLSIN.Append(aF1);
          }
          else if (aSt==TopAbs_OUT) {
            myLSOUT.Append(aF1);
          }
        }
        break;
      } // if (aNbPB<2) {
    } //for (; anExp.More(); anExp.Next())
Beispiel #5
0
int
EG_loadModel(egObject *context, int bflg, const char *name, 
             egObject **model)
{
  int          i, j, stat, outLevel, len, nattr, egads = 0;
  egObject     *omodel, *aobj;
  TopoDS_Shape source;
  egadsModel   *mshape = NULL;
  FILE         *fp;
  
  *model = NULL;
  if (context == NULL)               return EGADS_NULLOBJ;
  if (context->magicnumber != MAGIC) return EGADS_NOTOBJ;
  if (context->oclass != CONTXT)     return EGADS_NOTCNTX;
  outLevel = EG_outLevel(context);
  
  if (name == NULL) {
    if (outLevel > 0)
      printf(" EGADS Warning: NULL Filename (EG_loadModel)!\n");
    return EGADS_NONAME;
  }
  
  /* does file exist? */

  fp = fopen(name, "r");
  if (fp == NULL) {
    if (outLevel > 0)
      printf(" EGADS Warning: File %s Not Found (EG_loadModel)!\n", name);
    return EGADS_NOTFOUND;
  }
  fclose(fp);
  
  /* find extension */
  
  len = strlen(name);
  for (i = len-1; i > 0; i--)
    if (name[i] == '.') break;
  if (i == 0) {
    if (outLevel > 0)
      printf(" EGADS Warning: No Extension in %s (EG_loadModel)!\n", name);
    return EGADS_NODATA;
  }
  
  if ((strcasecmp(&name[i],".step") == 0) || 
      (strcasecmp(&name[i],".stp") == 0)) {

    /* STEP files */

    STEPControl_Reader aReader;
    IFSelect_ReturnStatus status = aReader.ReadFile(name);
    if (status != IFSelect_RetDone) {
      if (outLevel > 0)
        printf(" EGADS Error: STEP Read of %s = %d (EG_loadModel)!\n", 
               name, status);
      return EGADS_NOLOAD;
    }

    // inspect the root transfers
    if (outLevel > 2)
      aReader.PrintCheckLoad(Standard_False, IFSelect_ItemsByEntity);

    int nroot = aReader.NbRootsForTransfer();
    if (outLevel > 1)
      printf(" EGADS Info: %s Entries = %d\n", name, nroot);

    for (i = 1; i <= nroot; i++) {
      Standard_Boolean ok = aReader.TransferRoot(i);
      if ((!ok) && (outLevel > 0))
        printf(" EGADS Warning: Transfer %d/%d is not OK!\n", i, nroot);
    }

    int nbs = aReader.NbShapes();
    if (nbs <= 0) {
      if (outLevel > 0)
        printf(" EGADS Error: %s has No Shapes (EG_loadModel)!\n", 
               name);
      return EGADS_NOLOAD;
    }
    if (outLevel > 1)    
      printf(" EGADS Info: %s has %d Shape(s)\n", name, nbs);

    TopoDS_Compound compound;
    BRep_Builder    builder3D;
    builder3D.MakeCompound(compound);
    for (i = 1; i <= nbs; i++) {
      TopoDS_Shape aShape = aReader.Shape(i);
      builder3D.Add(compound, aShape);
    }
    source = compound;
    
  } else if ((strcasecmp(&name[i],".iges") == 0) || 
             (strcasecmp(&name[i],".igs") == 0)) {
             
    /* IGES files */
    
    IGESControl_Reader iReader;
    Standard_Integer stats = iReader.ReadFile(name);
    if (stats != IFSelect_RetDone) {
      if (outLevel > 0)
        printf(" EGADS Error: IGES Read of %s = %d (EG_loadModel)!\n", 
               name, stats);
      return EGADS_NOLOAD;
    }
    iReader.TransferRoots();

    int nbs = iReader.NbShapes();
    if (nbs <= 0) {
      if (outLevel > 0)
        printf(" EGADS Error: %s has No Shapes (EG_loadModel)!\n", 
               name);
      return EGADS_NOLOAD;
    }
    if (outLevel > 1)    
      printf(" EGADS Info: %s has %d Shape(s)\n", name, nbs);

    TopoDS_Compound compound;
    BRep_Builder    builder3D;
    builder3D.MakeCompound(compound);
    for (i = 1; i <= nbs; i++) {
      TopoDS_Shape aShape = iReader.Shape(i);
      builder3D.Add(compound, aShape);
    }
    source = compound;

  } else if ((strcasecmp(&name[i],".brep") == 0) ||
             (strcasecmp(&name[i],".egads") == 0)) {
  
    /* Native OCC file */
    if (strcasecmp(&name[i],".egads") == 0) egads = 1;

    BRep_Builder builder;
    if (!BRepTools::Read(source, name, builder)) {
      if (outLevel > 0)
        printf(" EGADS Warning: Read Error on %s (EG_loadModel)!\n", name);
      return EGADS_NOLOAD;
    }

  } else {
    if (outLevel > 0)
      printf(" EGADS Warning: Extension in %s Not Supported (EG_loadModel)!\n",
             name);
    return EGADS_NODATA;
  }
  
  int nWire  = 0;
  int nFace  = 0;
  int nSheet = 0;
  int nSolid = 0;
  
  TopExp_Explorer Exp;
  for (Exp.Init(source, TopAbs_WIRE,  TopAbs_FACE);
       Exp.More(); Exp.Next()) nWire++;
  for (Exp.Init(source, TopAbs_FACE,  TopAbs_SHELL);
       Exp.More(); Exp.Next()) nFace++;
  for (Exp.Init(source, TopAbs_SHELL, TopAbs_SOLID);
       Exp.More(); Exp.Next()) nSheet++;
  for (Exp.Init(source, TopAbs_SOLID); Exp.More(); Exp.Next()) nSolid++;

  if (outLevel > 1)
    printf("\n EGADS Info: %s has %d Solids, %d Sheets, %d Faces and %d Wires\n",
           name, nSolid, nSheet, nFace, nWire);
           
  int nBody = nWire+nFace+nSheet+nSolid;
  if (nBody == 0) {
    source.Nullify();
    if (outLevel > 0)
      printf(" EGADS Warning: Nothing found in %s (EG_loadModel)!\n", name);
    return EGADS_NODATA;
  }
  
  mshape = new egadsModel;
  mshape->shape  = source;
  mshape->nbody  = nBody;
  mshape->bodies = new egObject*[nBody];
  for (i = 0; i < nBody; i++) {
    stat = EG_makeObject(context, &mshape->bodies[i]);
    if (stat != EGADS_SUCCESS) {
      for (int j = 0; j < i; j++) {
        egObject  *obj   = mshape->bodies[j];
        egadsBody *pbody = (egadsBody *) obj->blind;
        delete pbody;
        EG_deleteObject(mshape->bodies[j]);
      }
      delete [] mshape->bodies;
      delete mshape;
      return stat;
    }
    egObject  *pobj    = mshape->bodies[i];
    egadsBody *pbody   = new egadsBody;
    pbody->nodes.objs  = NULL;
    pbody->edges.objs  = NULL;
    pbody->loops.objs  = NULL;
    pbody->faces.objs  = NULL;
    pbody->shells.objs = NULL;
    pbody->senses      = NULL;
    pobj->blind        = pbody;
  }
  
  i = 0;
  for (Exp.Init(mshape->shape, TopAbs_WIRE,  TopAbs_FACE); 
       Exp.More(); Exp.Next()) {
    egObject  *obj   = mshape->bodies[i++];
    egadsBody *pbody = (egadsBody *) obj->blind;
    pbody->shape     = Exp.Current();
  }
  for (Exp.Init(mshape->shape, TopAbs_FACE,  TopAbs_SHELL);
       Exp.More(); Exp.Next()) {
    egObject  *obj   = mshape->bodies[i++];
    egadsBody *pbody = (egadsBody *) obj->blind;
    pbody->shape     = Exp.Current();
  }
  for (Exp.Init(mshape->shape, TopAbs_SHELL, TopAbs_SOLID);
       Exp.More(); Exp.Next()) {
    egObject  *obj   = mshape->bodies[i++];
    egadsBody *pbody = (egadsBody *) obj->blind;
    pbody->shape     = Exp.Current();
  }
  for (Exp.Init(mshape->shape, TopAbs_SOLID); Exp.More(); Exp.Next()) {
    egObject  *obj   = mshape->bodies[i++];
    egadsBody *pbody = (egadsBody *) obj->blind;
    pbody->shape     = Exp.Current();
  }
  
  stat = EG_makeObject(context, &omodel);
  if (stat != EGADS_SUCCESS) {
    source.Nullify();
    for (i = 0; i < nBody; i++) {
      egObject  *obj   = mshape->bodies[i];
      egadsBody *pbody = (egadsBody *) obj->blind;
      delete pbody;
      EG_deleteObject(mshape->bodies[i]);
    }
    delete [] mshape->bodies;
    delete mshape;
    return stat;
  }
  omodel->oclass = MODEL;
  omodel->blind  = mshape;
  EG_referenceObject(omodel, context);
  
  for (i = 0; i < nBody; i++) {
    egObject  *pobj  = mshape->bodies[i];
    egadsBody *pbody = (egadsBody *) pobj->blind;
    pobj->topObj     = omodel;
    if (((bflg&1) == 0) && (egads == 0)) EG_splitPeriodics(pbody);
    stat = EG_traverseBody(context, i, pobj, omodel, pbody);
    if (stat != EGADS_SUCCESS) {
      mshape->nbody = i;
      EG_destroyTopology(omodel);
      delete [] mshape->bodies;
      delete mshape;
      return stat;
    }
  }

  *model = omodel;
  if (egads == 0) return EGADS_SUCCESS;

  /* get the attributes from the EGADS files */
  
  fp = fopen(name, "r");
  if (fp == NULL) {
    printf(" EGADS Info: Cannot reOpen %s (EG_loadModel)!\n", name);
    return EGADS_SUCCESS;
  }
  char line[81];
  for (;;) {
    line[0] = line[1] = ' ';
    if (fgets(line, 81, fp) == NULL) break;
    if ((line[0] == '#') && (line[1] == '#')) break;
  }
  
  // got the header
  if ((line[0] == '#') && (line[1] == '#')) {
    if (outLevel > 1) printf(" Header = %s\n", line);
    // get number of model attributes
    fscanf(fp, "%d", &nattr);
    if (nattr != 0) EG_readAttrs(omodel, nattr, fp);
    for (i = 0; i < nBody; i++) {
      int otype,  oindex;
      int rsolid, rshell, rface, rloop, redge, rnode;
      int nsolid, nshell, nface, nloop, nedge, nnode;

      fscanf(fp, " %d %d %d %d %d %d %d", &rsolid, &rshell, 
             &rface, &rloop, &redge, &rnode, &nattr);
      if (outLevel > 2)
        printf(" read = %d %d %d %d %d %d %d\n", rsolid, rshell, 
               rface, rloop, redge, rnode, nattr);
      egObject  *pobj  = mshape->bodies[i];
      egadsBody *pbody = (egadsBody *) pobj->blind;
      nnode  = pbody->nodes.map.Extent();
      nedge  = pbody->edges.map.Extent();
      nloop  = pbody->loops.map.Extent();
      nface  = pbody->faces.map.Extent();
      nshell = pbody->shells.map.Extent();
      nsolid = 0;
      if (pobj->mtype == SOLIDBODY) nsolid = 1;
      if ((nnode != rnode) || (nedge  != redge)  || (nloop  != rloop) ||
          (nface != rface) || (nshell != rshell) || (nsolid != rsolid)) {
        printf(" EGADS Info: %d %d, %d %d, %d %d, %d %d, %d %d, %d %d",
               nnode, rnode, nedge,  redge,  nloop,  rloop,
               nface, rface, nshell, rshell, nsolid, rsolid);
        printf("  MisMatch on Attributes (EG_loadModel)!\n");
        fclose(fp);
        return EGADS_SUCCESS;
      }
      // got the correct body -- transfer the attributes
      if (nattr != 0) EG_readAttrs(pobj, nattr, fp);
      for (;;)  {
        j = fscanf(fp, "%d %d %d\n", &otype, &oindex, &nattr);
        if (outLevel > 2)
          printf(" %d:  attr header = %d %d %d\n", 
                 j, otype, oindex, nattr);
        if (j     != 3) break;
        if (otype == 0) break;
        if (otype == 1) {
          aobj = pbody->shells.objs[oindex];
        } else if (otype == 2) {
          aobj = pbody->faces.objs[oindex];
        } else if (otype == 3) {
          aobj = pbody->loops.objs[oindex];
        } else if (otype == 4) {
          aobj = pbody->edges.objs[oindex];
        } else {
          aobj = pbody->nodes.objs[oindex];
        }
        EG_readAttrs(aobj, nattr, fp);
      }
    }
  } else {
    printf(" EGADS Info: EGADS Header not found in %s (EG_loadModel)!\n", 
           name);
    return EGADS_SUCCESS;
  }
  
  fclose(fp);
  return EGADS_SUCCESS;
}
//=======================================================================
//function : Execute
//purpose  :
//======================================================================= 
Standard_Integer GEOMImpl_MeasureDriver::Execute(TFunction_Logbook& log) const
{
  if (Label().IsNull()) return 0;    
  Handle(GEOM_Function) aFunction = GEOM_Function::GetFunction(Label());

  GEOMImpl_IMeasure aCI (aFunction);
  Standard_Integer aType = aFunction->GetType();

  TopoDS_Shape aShape;

  if (aType == CDG_MEASURE)
  {
    Handle(GEOM_Function) aRefBase = aCI.GetBase();
    TopoDS_Shape aShapeBase = aRefBase->GetValue();
    if (aShapeBase.IsNull()) {
      Standard_NullObject::Raise("Shape for centre of mass calculation is null");
    }

    gp_Ax3 aPos = GEOMImpl_IMeasureOperations::GetPosition(aShapeBase);
    gp_Pnt aCenterMass = aPos.Location();
    aShape = BRepBuilderAPI_MakeVertex(aCenterMass).Shape();
  }
  else if (aType == VERTEX_BY_INDEX)
  {
    Handle(GEOM_Function) aRefBase = aCI.GetBase();
    TopoDS_Shape aShapeBase = aRefBase->GetValue();
    if (aShapeBase.IsNull()) {
      Standard_NullObject::Raise("Shape for centre of mass calculation is null");
    }

    int index = aCI.GetIndex();
    gp_Pnt aVertex;

    if (aShapeBase.ShapeType() == TopAbs_VERTEX) {
      if ( index != 1 )
        Standard_NullObject::Raise("Vertex index is out of range");
      else
        aVertex = BRep_Tool::Pnt(TopoDS::Vertex(aShapeBase));
    } else if (aShapeBase.ShapeType() == TopAbs_EDGE) {
      TopoDS_Vertex aV1, aV2;
      TopoDS_Edge anEdgeE = TopoDS::Edge(aShapeBase);
      
      TopExp::Vertices(anEdgeE, aV1, aV2);
      gp_Pnt aP1 = BRep_Tool::Pnt(aV1);
      gp_Pnt aP2 = BRep_Tool::Pnt(aV2);

      if (index < 0 || index > 1)
        Standard_NullObject::Raise("Vertex index is out of range");

      if ( ( anEdgeE.Orientation() == TopAbs_FORWARD && index == 0 ) ||
           ( anEdgeE.Orientation() == TopAbs_REVERSED && index == 1 ) )
        aVertex = aP1;
      else
      aVertex = aP2;
    } else if (aShapeBase.ShapeType() == TopAbs_WIRE) {
      TopTools_IndexedMapOfShape anEdgeShapes;
      TopTools_IndexedMapOfShape aVertexShapes;
      TopoDS_Vertex aV1, aV2;
      TopoDS_Wire aWire = TopoDS::Wire(aShapeBase);
      TopExp_Explorer exp (aWire, TopAbs_EDGE);
      for (; exp.More(); exp.Next()) {
        anEdgeShapes.Add(exp.Current());
        TopoDS_Edge E = TopoDS::Edge(exp.Current());
        TopExp::Vertices(E, aV1, aV2);
        if ( aVertexShapes.Extent() == 0)
          aVertexShapes.Add(aV1);
        if ( !aV1.IsSame( aVertexShapes(aVertexShapes.Extent()) ) )
          aVertexShapes.Add(aV1);
        if ( !aV2.IsSame( aVertexShapes(aVertexShapes.Extent()) ) )
          aVertexShapes.Add(aV2);
      }

      if (index < 0 || index > aVertexShapes.Extent())
        Standard_NullObject::Raise("Vertex index is out of range");

      if (aWire.Orientation() == TopAbs_FORWARD)
        aVertex = BRep_Tool::Pnt(TopoDS::Vertex(aVertexShapes(index+1)));
      else
        aVertex = BRep_Tool::Pnt(TopoDS::Vertex(aVertexShapes(aVertexShapes.Extent() - index)));
    } else {
      Standard_NullObject::Raise("Shape for vertex calculation is not an edge or wire");
    }

    aShape = BRepBuilderAPI_MakeVertex(aVertex).Shape();
  }
  else if (aType == VECTOR_FACE_NORMALE)
  {
    // Face
    Handle(GEOM_Function) aRefBase = aCI.GetBase();
    TopoDS_Shape aShapeBase = aRefBase->GetValue();
    if (aShapeBase.IsNull()) {
      Standard_NullObject::Raise("Face for normale calculation is null");
    }
    if (aShapeBase.ShapeType() != TopAbs_FACE) {
      Standard_NullObject::Raise("Shape for normale calculation is not a face");
    }
    TopoDS_Face aFace = TopoDS::Face(aShapeBase);

    // Point
    gp_Pnt p1 (0,0,0);

    Handle(GEOM_Function) aPntFunc = aCI.GetPoint();
    if (!aPntFunc.IsNull())
    {
      TopoDS_Shape anOptPnt = aPntFunc->GetValue();
      if (anOptPnt.IsNull())
        Standard_NullObject::Raise("Invalid shape given for point argument");
      p1 = BRep_Tool::Pnt(TopoDS::Vertex(anOptPnt));
    }
    else
    {
      gp_Ax3 aPos = GEOMImpl_IMeasureOperations::GetPosition(aFace);
      p1 = aPos.Location();
    }

    // Point parameters on surface
    Handle(Geom_Surface) aSurf = BRep_Tool::Surface(aFace);
    Handle(ShapeAnalysis_Surface) aSurfAna = new ShapeAnalysis_Surface (aSurf);
    gp_Pnt2d pUV = aSurfAna->ValueOfUV(p1, Precision::Confusion());

    // Normal direction
    gp_Vec Vec1,Vec2;
    BRepAdaptor_Surface SF (aFace);
    SF.D1(pUV.X(), pUV.Y(), p1, Vec1, Vec2);
    if (Vec1.Magnitude() < Precision::Confusion()) {
      gp_Vec tmpV;
      gp_Pnt tmpP;
      SF.D1(pUV.X(), pUV.Y()-0.1, tmpP, Vec1, tmpV);
    }
    else if (Vec2.Magnitude() < Precision::Confusion()) {
      gp_Vec tmpV;
      gp_Pnt tmpP;
      SF.D1(pUV.X()-0.1, pUV.Y(), tmpP, tmpV, Vec2);
    }

    gp_Vec V = Vec1.Crossed(Vec2);
    Standard_Real mod = V.Magnitude();
    if (mod < Precision::Confusion())
      Standard_NullObject::Raise("Normal vector of a face has null magnitude");

    // Set length of normal vector to average radius of curvature
    Standard_Real radius = 0.0;
    GeomLProp_SLProps aProperties (aSurf, pUV.X(), pUV.Y(), 2, Precision::Confusion());
    if (aProperties.IsCurvatureDefined()) {
      Standard_Real radius1 = Abs(aProperties.MinCurvature());
      Standard_Real radius2 = Abs(aProperties.MaxCurvature());
      if (Abs(radius1) > Precision::Confusion()) {
        radius = 1.0 / radius1;
        if (Abs(radius2) > Precision::Confusion()) {
          radius = (radius + 1.0 / radius2) / 2.0;
        }
      }
      else {
        if (Abs(radius2) > Precision::Confusion()) {
          radius = 1.0 / radius2;
        }
      }
    }

    // Set length of normal vector to average dimension of the face
    // (only if average radius of curvature is not appropriate)
    if (radius < Precision::Confusion()) {
        Bnd_Box B;
        Standard_Real Xmin, Xmax, Ymin, Ymax, Zmin, Zmax;
        BRepBndLib::Add(aFace, B);
        B.Get(Xmin, Ymin, Zmin, Xmax, Ymax, Zmax);
        radius = ((Xmax - Xmin) + (Ymax - Ymin) + (Zmax - Zmin)) / 3.0;
    }

    if (radius < Precision::Confusion())
      radius = 1.0;

    V *= radius / mod;

    // consider the face orientation
    if (aFace.Orientation() == TopAbs_REVERSED ||
        aFace.Orientation() == TopAbs_INTERNAL) {
      V = - V;
    }

    // Edge
    gp_Pnt p2 = p1.Translated(V);
    BRepBuilderAPI_MakeEdge aBuilder (p1, p2);
    if (!aBuilder.IsDone())
      Standard_NullObject::Raise("Vector construction failed");
    aShape = aBuilder.Shape();
  }
  else {
  }

  if (aShape.IsNull()) return 0;

  aFunction->SetValue(aShape);

  log.SetTouched(Label()); 

  return 1;
}
Beispiel #7
0
void PovTools::writeShape(std::ostream &out, const char *PartName,
                          const TopoDS_Shape& Shape, float fMeshDeviation)
{
    Base::Console().Log("Meshing with Deviation: %f\n",fMeshDeviation);

    TopExp_Explorer ex;
    BRepMesh_IncrementalMesh MESH(Shape,fMeshDeviation);


    // counting faces and start sequencer
    int l = 1;
    for (ex.Init(Shape, TopAbs_FACE); ex.More(); ex.Next(),l++) {}
    Base::SequencerLauncher seq("Writing file", l);

    // write the file
    out <<  "// Written by FreeCAD http://www.freecadweb.org/" << endl;
    l = 1;
    for (ex.Init(Shape, TopAbs_FACE); ex.More(); ex.Next(),l++) {

        // get the shape and mesh it
        const TopoDS_Face& aFace = TopoDS::Face(ex.Current());

        // this block mesh the face and transfers it in a C array of vertices and face indexes
        Standard_Integer nbNodesInFace,nbTriInFace;
        gp_Vec* vertices=0;
        gp_Vec* vertexnormals=0;
        long* cons=0;

        transferToArray(aFace,&vertices,&vertexnormals,&cons,nbNodesInFace,nbTriInFace);

        if (!vertices) break;
        // writing per face header
        out << "// face number" << l << " +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++" << endl
        << "#declare " << PartName << l << " = mesh2{" << endl
        << "  vertex_vectors {" << endl
        << "    " << nbNodesInFace << "," << endl;
        // writing vertices
        for (int i=0; i < nbNodesInFace; i++) {
            out << "    <" << vertices[i].X() << ","
            << vertices[i].Z() << ","
            << vertices[i].Y() << ">,"
            << endl;
        }
        out << "  }" << endl
        // writing per vertex normals
        << "  normal_vectors {" << endl
        << "    " << nbNodesInFace << "," << endl;
        for (int j=0; j < nbNodesInFace; j++) {
            out << "    <" << vertexnormals[j].X() << ","
            << vertexnormals[j].Z() << ","
            << vertexnormals[j].Y() << ">,"
            << endl;
        }

        out << "  }" << endl
        // writing triangle indices
        << "  face_indices {" << endl
        << "    " << nbTriInFace << "," << endl;
        for (int k=0; k < nbTriInFace; k++) {
            out << "    <" << cons[3*k] << ","<< cons[3*k+2] << ","<< cons[3*k+1] << ">," << endl;
        }
        // end of face
        out << "  }" << endl
        << "} // end of Face"<< l << endl << endl;

        delete [] vertexnormals;
        delete [] vertices;
        delete [] cons;

        seq.next();

    } // end of face loop


    out << endl << endl << "// Declare all together +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++" << endl
    << "#declare " << PartName << " = union {" << endl;
    for (int i=1; i < l; i++) {
        out << "mesh2{ " << PartName << i << "}" << endl;
    }
    out << "}" << endl;
}
Beispiel #8
0
App::DocumentObjectExecReturn *Pipe::execute(void)
{
    
    std::vector<TopoDS_Wire> wires;
    try {
        wires = getProfileWires();
    } catch (const Base::Exception& e) {
        return new App::DocumentObjectExecReturn(e.what());
    }
    
    TopoDS_Shape sketchshape = getVerifiedFace();
    if (sketchshape.IsNull())
        return new App::DocumentObjectExecReturn("Pipe: No valid sketch or face as first section");
    else {
        //TODO: currently we only allow planar faces. the reason for this is that with other faces in front, we could 
        //not use the current simulate approach and build the start and end face from the wires. As the shell 
        //beginns always at the spine and not the profile, the sketchshape cannot be used directly as front face. 
        //We would need a method to translate the frontshape to match the shell starting position somehow...
        TopoDS_Face face = TopoDS::Face(sketchshape);
        BRepAdaptor_Surface adapt(face);
        if(adapt.GetType() != GeomAbs_Plane)
            return new App::DocumentObjectExecReturn("Pipe: Only planar faces supportet");
    }

    // if the Base property has a valid shape, fuse the pipe into it
    TopoDS_Shape base;
    try {
        base = getBaseShape();
    } catch (const Base::Exception&) {
        base = TopoDS_Shape();
    }
 
    try {
        //setup the location
        this->positionByPrevious();
        TopLoc_Location invObjLoc = this->getLocation().Inverted();
        if(!base.IsNull())
            base.Move(invObjLoc);
        
        //build the paths
        App::DocumentObject* spine = Spine.getValue();
        if (!(spine && spine->getTypeId().isDerivedFrom(Part::Feature::getClassTypeId())))
            return new App::DocumentObjectExecReturn("No spine linked.");
        std::vector<std::string> subedge = Spine.getSubValues();
        TopoDS_Shape path;
        const Part::TopoShape& shape = static_cast<Part::Feature*>(spine)->Shape.getValue();
        buildPipePath(shape, subedge, path);
        path.Move(invObjLoc);
        
        
        TopoDS_Shape auxpath;
        if(Mode.getValue()==3) {
            App::DocumentObject* auxspine = AuxillerySpine.getValue();
            if (!(auxspine && auxspine->getTypeId().isDerivedFrom(Part::Feature::getClassTypeId())))
                return new App::DocumentObjectExecReturn("No auxillery spine linked.");
            std::vector<std::string> auxsubedge = AuxillerySpine.getSubValues();
            TopoDS_Shape path;
            const Part::TopoShape& auxshape = static_cast<Part::Feature*>(auxspine)->Shape.getValue();
            buildPipePath(auxshape, auxsubedge, auxpath);
            auxpath.Move(invObjLoc);
        }        
        
        //build up multisections
        auto multisections = Sections.getValues();
        std::vector<std::vector<TopoDS_Wire>> wiresections;
        for(TopoDS_Wire& wire : wires)
            wiresections.push_back(std::vector<TopoDS_Wire>(1, wire));
        //maybe we need a sacling law
        Handle(Law_Function) scalinglaw;
        
        //see if we shall use multiple sections
        if(Transformation.getValue() == 1) {
            
            //TODO: we need to order the sections to prevent occ from crahsing, as makepieshell connects
            //the sections in the order of adding            
                
            for(App::DocumentObject* obj : multisections) {
                if(!obj->isDerivedFrom(Part::Feature::getClassTypeId()))
                    return  new App::DocumentObjectExecReturn("All sections need to be part features");
                
                TopExp_Explorer ex;
                size_t i=0;
                for (ex.Init(static_cast<Part::Feature*>(obj)->Shape.getValue(), TopAbs_WIRE); ex.More(); ex.Next()) {
                    wiresections[i].push_back(TopoDS::Wire(ex.Current()));
                    if(i>=wiresections.size())
                        return new App::DocumentObjectExecReturn("Multisections need to have the same amount of inner wires as the base section");
                    
                    ++i;
                }
                if(i<wiresections.size())
                        return new App::DocumentObjectExecReturn("Multisections need to have the same amount of inner wires as the base section");
                
            }
        }
        /*//build the law functions instead
        else if(Transformation.getValue() == 2) {
            if(ScalingData.getValues().size()<1)
                return new App::DocumentObjectExecReturn("No valid data given for liinear scaling mode");
            
            Handle(Law_Linear) lin = new Law_Linear();
            lin->Set(0,1,1,ScalingData[0].x);
            
            scalinglaw = lin;
        }
        else if(Transformation.getValue() == 3) {
            if(ScalingData.getValues().size()<1)
                return new App::DocumentObjectExecReturn("No valid data given for S-shape scaling mode");
            
            Handle(Law_S) s = new Law_S();
            s->Set(0,1,ScalingData[0].y, 1, ScalingData[0].x, ScalingData[0].z);
            
            scalinglaw = s;
        }*/
        
        //build all shells
        std::vector<TopoDS_Shape> shells;
        std::vector<TopoDS_Wire> frontwires, backwires;
        for(std::vector<TopoDS_Wire>& wires : wiresections) {
            
            BRepOffsetAPI_MakePipeShell mkPS(TopoDS::Wire(path));
            setupAlgorithm(mkPS, auxpath);
            
            if(!scalinglaw) {
                for(TopoDS_Wire& wire : wires) {
                    wire.Move(invObjLoc);
                    mkPS.Add(wire);
                }
            }
            else {
                for(TopoDS_Wire& wire : wires)  {
                    wire.Move(invObjLoc);
                    mkPS.SetLaw(wire, scalinglaw);
                }
            }

            if (!mkPS.IsReady())
                return new App::DocumentObjectExecReturn("pipe could not be build");
            
            //build the shell use simulate to get the top and bottom wires in an easy way
            shells.push_back(mkPS.Shape());
            TopTools_ListOfShape sim;
            mkPS.Simulate(2, sim);
            frontwires.push_back(TopoDS::Wire(sim.First()));
            backwires.push_back(TopoDS::Wire(sim.Last()));            
        }
        
        //build the top and bottom face, sew the shell and build the final solid
        TopoDS_Shape front = makeFace(frontwires);
        TopoDS_Shape back  = makeFace(backwires);
        
        BRepBuilderAPI_Sewing sewer;
        sewer.SetTolerance(Precision::Confusion());
        sewer.Add(front);
        sewer.Add(back);
        for(TopoDS_Shape& s : shells)
            sewer.Add(s);      
        
        sewer.Perform();
        
        //build the solid
        BRepBuilderAPI_MakeSolid mkSolid;
        mkSolid.Add(TopoDS::Shell(sewer.SewedShape()));
        if(!mkSolid.IsDone())
            return new App::DocumentObjectExecReturn("Result is not a solid");
        
        TopoDS_Shape result = mkSolid.Shape();
        BRepClass3d_SolidClassifier SC(result);
        SC.PerformInfinitePoint(Precision::Confusion());
        if ( SC.State() == TopAbs_IN) {
            result.Reverse();
        }
        
        //result.Move(invObjLoc);
        AddSubShape.setValue(result);
        
        if(base.IsNull()) {
            Shape.setValue(getSolid(result));
            return App::DocumentObject::StdReturn;
        }
        
        if(getAddSubType() == FeatureAddSub::Additive) {
                        
            BRepAlgoAPI_Fuse mkFuse(base, result);
            if (!mkFuse.IsDone())
                return new App::DocumentObjectExecReturn("Adding the pipe failed");
            // we have to get the solids (fuse sometimes creates compounds)
            TopoDS_Shape boolOp = this->getSolid(mkFuse.Shape());
            // lets check if the result is a solid
            if (boolOp.IsNull())
                return new App::DocumentObjectExecReturn("Resulting shape is not a solid");
            
            boolOp = refineShapeIfActive(boolOp);
            Shape.setValue(getSolid(boolOp));
        }
        else if(getAddSubType() == FeatureAddSub::Subtractive) {
            
            BRepAlgoAPI_Cut mkCut(base, result);
            if (!mkCut.IsDone())
                return new App::DocumentObjectExecReturn("Subtracting the pipe failed");
            // we have to get the solids (fuse sometimes creates compounds)
            TopoDS_Shape boolOp = this->getSolid(mkCut.Shape());
            // lets check if the result is a solid
            if (boolOp.IsNull())
                return new App::DocumentObjectExecReturn("Resulting shape is not a solid");
            
            boolOp = refineShapeIfActive(boolOp);
            Shape.setValue(getSolid(boolOp));
        }
        
        return App::DocumentObject::StdReturn;
        
        return ProfileBased::execute();   
    }
    catch (Standard_Failure) {
        Handle_Standard_Failure e = Standard_Failure::Caught();
        return new App::DocumentObjectExecReturn(e->GetMessageString());
    }
    catch (...) {
        return new App::DocumentObjectExecReturn("A fatal error occurred when making the pipe");
    }
}
const bool SketchBased::checkLineCrossesFace(const gp_Lin &line, const TopoDS_Face &face)
{
#if 1
    BRepBuilderAPI_MakeEdge mkEdge(line);
    TopoDS_Wire wire = ShapeAnalysis::OuterWire(face);
    BRepExtrema_DistShapeShape distss(wire, mkEdge.Shape(), Precision::Confusion());
    if (distss.IsDone()) {
        if (distss.Value() > Precision::Confusion())
            return false;
        // build up map vertex->edge
        TopTools_IndexedDataMapOfShapeListOfShape vertex2Edge;
        TopExp::MapShapesAndAncestors(wire, TopAbs_VERTEX, TopAbs_EDGE, vertex2Edge);

        for (Standard_Integer i=1; i<= distss.NbSolution(); i++) {
            if (distss.PointOnShape1(i).Distance(distss.PointOnShape2(i)) > Precision::Confusion())
                continue;
            BRepExtrema_SupportType type = distss.SupportTypeShape1(i);
            if (type == BRepExtrema_IsOnEdge) {
                TopoDS_Edge edge = TopoDS::Edge(distss.SupportOnShape1(i));
                BRepAdaptor_Curve adapt(edge);
                // create a plane (pnt,dir) that goes through the intersection point and is built of
                // the vectors of the sketch normal and the rotation axis
                const gp_Dir& normal = BRepAdaptor_Surface(face).Plane().Axis().Direction();
                gp_Dir dir = line.Direction().Crossed(normal);
                gp_Pnt pnt = distss.PointOnShape1(i);

                Standard_Real t;
                distss.ParOnEdgeS1(i, t);
                gp_Pnt p_eps1 = adapt.Value(std::max<double>(adapt.FirstParameter(), t-10*Precision::Confusion()));
                gp_Pnt p_eps2 = adapt.Value(std::min<double>(adapt.LastParameter(), t+10*Precision::Confusion()));

                // now check if we get a change in the sign of the distances
                Standard_Real dist_p_eps1_pnt = gp_Vec(p_eps1, pnt).Dot(gp_Vec(dir));
                Standard_Real dist_p_eps2_pnt = gp_Vec(p_eps2, pnt).Dot(gp_Vec(dir));
                // distance to the plane must be noticable
                if (fabs(dist_p_eps1_pnt) > 5*Precision::Confusion() &&
                    fabs(dist_p_eps2_pnt) > 5*Precision::Confusion()) {
                    if (dist_p_eps1_pnt * dist_p_eps2_pnt < 0)
                        return true;
                }
            }
            else if (type == BRepExtrema_IsVertex) {
                // for a vertex check the two adjacent edges if there is a change of sign
                TopoDS_Vertex vertex = TopoDS::Vertex(distss.SupportOnShape1(i));
                const TopTools_ListOfShape& edges = vertex2Edge.FindFromKey(vertex);
                if (edges.Extent() == 2) {
                    // create a plane (pnt,dir) that goes through the intersection point and is built of
                    // the vectors of the sketch normal and the rotation axis
                    BRepAdaptor_Surface adapt(face);
                    const gp_Dir& normal = adapt.Plane().Axis().Direction();
                    gp_Dir dir = line.Direction().Crossed(normal);
                    gp_Pnt pnt = distss.PointOnShape1(i);

                    // from the first edge get a point next to the intersection point
                    const TopoDS_Edge& edge1 = TopoDS::Edge(edges.First());
                    BRepAdaptor_Curve adapt1(edge1);
                    Standard_Real dist1 = adapt1.Value(adapt1.FirstParameter()).SquareDistance(pnt);
                    Standard_Real dist2 = adapt1.Value(adapt1.LastParameter()).SquareDistance(pnt);
                    gp_Pnt p_eps1;
                    if (dist1 < dist2)
                        p_eps1 = adapt1.Value(adapt1.FirstParameter() + 2*Precision::Confusion());
                    else
                        p_eps1 = adapt1.Value(adapt1.LastParameter() - 2*Precision::Confusion());

                    // from the second edge get a point next to the intersection point
                    const TopoDS_Edge& edge2 = TopoDS::Edge(edges.Last());
                    BRepAdaptor_Curve adapt2(edge2);
                    Standard_Real dist3 = adapt2.Value(adapt2.FirstParameter()).SquareDistance(pnt);
                    Standard_Real dist4 = adapt2.Value(adapt2.LastParameter()).SquareDistance(pnt);
                    gp_Pnt p_eps2;
                    if (dist3 < dist4)
                        p_eps2 = adapt2.Value(adapt2.FirstParameter() + 2*Precision::Confusion());
                    else
                        p_eps2 = adapt2.Value(adapt2.LastParameter() - 2*Precision::Confusion());

                    // now check if we get a change in the sign of the distances
                    Standard_Real dist_p_eps1_pnt = gp_Vec(p_eps1, pnt).Dot(gp_Vec(dir));
                    Standard_Real dist_p_eps2_pnt = gp_Vec(p_eps2, pnt).Dot(gp_Vec(dir));
                    // distance to the plane must be noticable
                    if (fabs(dist_p_eps1_pnt) > Precision::Confusion() &&
                        fabs(dist_p_eps2_pnt) > Precision::Confusion()) {
                        if (dist_p_eps1_pnt * dist_p_eps2_pnt < 0)
                            return true;
                    }
                }
            }
        }
    }

    return false;
#else
    // This is not as easy as it looks, because a distance of zero might be OK if
    // the axis touches the sketchshape in in a linear edge or a vertex
    // Note: This algorithm does not catch cases where the sketchshape touches the
    // axis in two or more points
    // Note: And it only works on closed outer wires
    TopoDS_Wire outerWire = ShapeAnalysis::OuterWire(face);
    BRepBuilderAPI_MakeEdge mkEdge(line);
    if (!mkEdge.IsDone())
        throw Base::Exception("Revolve: Unexpected OCE failure");
    BRepAdaptor_Curve axis(TopoDS::Edge(mkEdge.Shape()));

    TopExp_Explorer ex;
    int intersections = 0;
    std::vector<gp_Pnt> intersectionpoints;

    // Note: We need to look at evey edge separately to catch coincident lines
    for (ex.Init(outerWire, TopAbs_EDGE); ex.More(); ex.Next()) {
        BRepAdaptor_Curve edge(TopoDS::Edge(ex.Current()));
        Extrema_ExtCC intersector(axis, edge);

        if (intersector.IsDone()) {
            for (int i = 1; i <= intersector.NbExt(); i++) {


#if OCC_VERSION_HEX >= 0x060500
                if (intersector.SquareDistance(i) < Precision::Confusion()) {
#else
                if (intersector.Value(i) < Precision::Confusion()) {
#endif
                    if (intersector.IsParallel()) {
                        // A line that is coincident with the axis produces three intersections
                        // 1 with the line itself and 2 with the adjacent edges
                        intersections -= 2;
                    } else {
                        Extrema_POnCurv p1, p2;
                        intersector.Points(i, p1, p2);
                        intersectionpoints.push_back(p1.Value());
                        intersections++;
                    }
                }
            }
        }
    }

    // Note: We might check this inside the loop but then we have to rely on TopExp_Explorer
    // returning the wire's edges in adjacent order (because of the coincident line checking)
    if (intersections > 1) {
        // Check that we don't touch the sketchface just in two identical vertices
        if ((intersectionpoints.size() == 2) &&
            (intersectionpoints[0].IsEqual(intersectionpoints[1], Precision::Confusion())))
            return false;
        else
            return true;
    }

    return false;
#endif
}

void SketchBased::remapSupportShape(const TopoDS_Shape& newShape)
{
    TopTools_IndexedMapOfShape faceMap;
    TopExp::MapShapes(newShape, TopAbs_FACE, faceMap);

    // here we must reset the placement otherwise the geometric matching doesn't work
    Part::TopoShape shape = this->Shape.getValue();
    shape._Shape.Location(TopLoc_Location());

    std::vector<App::DocumentObject*> refs = this->getInList();
    for (std::vector<App::DocumentObject*>::iterator it = refs.begin(); it != refs.end(); ++it) {
        std::vector<App::Property*> props;
        (*it)->getPropertyList(props);
        for (std::vector<App::Property*>::iterator jt = props.begin(); jt != props.end(); ++jt) {
            if (!(*jt)->isDerivedFrom(App::PropertyLinkSub::getClassTypeId()))
                continue;
            App::PropertyLinkSub* link = static_cast<App::PropertyLinkSub*>(*jt);
            if (link->getValue() != this)
                continue;
            std::vector<std::string> subValues = link->getSubValues();
            std::vector<std::string> newSubValues;

            for (std::vector<std::string>::iterator it = subValues.begin(); it != subValues.end(); ++it) {
                std::string shapetype;
                if (it->size() > 4 && it->substr(0,4) == "Face") {
                    shapetype = "Face";
                }
                else if (it->size() > 4 && it->substr(0,4) == "Edge") {
                    shapetype = "Edge";
                }
                else if (it->size() > 6 && it->substr(0,6) == "Vertex") {
                    shapetype = "Vertex";
                }
                else {
                    newSubValues.push_back(*it);
                    continue;
                }

                bool success = false;
                TopoDS_Shape element;
                try {
                    element = shape.getSubShape(it->c_str());
                }
                catch (Standard_Failure) {
                    // This shape doesn't even exist, so no chance to do some tests
                    newSubValues.push_back(*it);
                    continue;
                }
                try {
                    // as very first test check if old face and new face are parallel planes
                    TopoDS_Shape newElement = Part::TopoShape(newShape).getSubShape(it->c_str());
                    if (isParallelPlane(element, newElement)) {
                        newSubValues.push_back(*it);
                        success = true;
                    }
                }
                catch (Standard_Failure) {
                }
                // try an exact matching
                if (!success) {
                    for (int i=1; i<faceMap.Extent(); i++) {
                        if (isQuasiEqual(element, faceMap.FindKey(i))) {
                            std::stringstream str;
                            str << shapetype << i;
                            newSubValues.push_back(str.str());
                            success = true;
                            break;
                        }
                    }
                }
                // if an exact matching fails then try to compare only the geometries
                if (!success) {
                    for (int i=1; i<faceMap.Extent(); i++) {
                        if (isEqualGeometry(element, faceMap.FindKey(i))) {
                            std::stringstream str;
                            str << shapetype << i;
                            newSubValues.push_back(str.str());
                            success = true;
                            break;
                        }
                    }
                }

                // the new shape couldn't be found so keep the old sub-name
                if (!success)
                    newSubValues.push_back(*it);
            }

            link->setValue(this, newSubValues);
        }
    }
}
//=======================================================================
// function: Perform
// purpose: 
//=======================================================================
  void GEOMAlgo_WireSplitter::Perform()
{
  myErrorStatus=2;
  myNothingToDo=Standard_True;

  Standard_Integer index, i, aNb, aCntIn, aCntOut;
  Standard_Boolean anIsIn;
  Standard_Real anAngle;
  
  BOP_ListOfEdgeInfo emptyInfo;
  TopTools_ListIteratorOfListOfShape anItList;
  //
  // 1.Filling mySmartMap
  mySmartMap.Clear();

  anItList.Initialize(myEdges);
  for (; anItList.More(); anItList.Next()) {
    const TopoDS_Edge& anEdge = TopoDS::Edge(anItList.Value());
    //
    if (!BOPTools_Tools2D::HasCurveOnSurface (anEdge, myFace)) {
      continue;
    }
    //
    TopExp_Explorer anExpVerts (anEdge, TopAbs_VERTEX);
    for (; anExpVerts.More(); anExpVerts.Next()) {
      const TopoDS_Shape& aVertex= anExpVerts.Current();

      index = mySmartMap.FindIndex(aVertex);
      if (!index) {
	index=mySmartMap.Add(aVertex, emptyInfo);
      }
      
      BOP_ListOfEdgeInfo& aListOfEInfo=mySmartMap(index);

      BOP_EdgeInfo aEInfo;
      aEInfo.SetEdge(anEdge);
      
      TopAbs_Orientation anOr=aVertex.Orientation();

      if (anOr==TopAbs_FORWARD) {
	aEInfo.SetInFlag(Standard_False);
      }

      else if (anOr==TopAbs_REVERSED) {
	aEInfo.SetInFlag(Standard_True);
      }

      aListOfEInfo.Append(aEInfo);
    }
  }
  //
  aNb=mySmartMap.Extent();
  //
  // 2. myNothingToDo 
  myNothingToDo=Standard_True;
  
  for (i=1; i<=aNb; i++) {
    aCntIn=0;
    aCntOut=0;
    const BOP_ListOfEdgeInfo& aLEInfo= mySmartMap(i);
    BOP_ListIteratorOfListOfEdgeInfo anIt(aLEInfo);
    for (; anIt.More(); anIt.Next()) {
      const BOP_EdgeInfo& anEdgeInfo=anIt.Value();
      anIsIn=anEdgeInfo.IsIn();
      if (anIsIn) {
	aCntIn++;
      }
      else {
	aCntOut++;
      }
    }
    if (aCntIn!=1 || aCntOut!=1) {
      myNothingToDo=Standard_False;
      break;
    }
  }
  //
  // Each vertex has one edge In and one - Out. Good. But it is not enought
  // to consider that nothing to do with this. We must check edges on TShape
  // coinsidence. If there are such edges there is something to do with.
  // 
  if (myNothingToDo) {
    Standard_Integer aNbE, aNbMapEE;
    TopTools_IndexedDataMapOfShapeListOfShape aMapEE;
    aNbE=myEdges.Extent();
    
    anItList.Initialize(myEdges);
    for (; anItList.More(); anItList.Next()) {
      const TopoDS_Shape& aE = anItList.Value();
      
      if (!aMapEE.Contains(aE)) {
	TopTools_ListOfShape aLEx;
	aLEx.Append(aE);
	aMapEE.Add(aE, aLEx);
      }
      else {
	TopTools_ListOfShape& aLEx=aMapEE.ChangeFromKey(aE);
	aLEx.Append(aE);
      }
    }
    
    Standard_Boolean bFlag;
    bFlag=Standard_True;
    aNbMapEE=aMapEE.Extent();
    for (i=1; i<=aNbMapEE; i++) {
      const TopTools_ListOfShape& aLEx=aMapEE(i);
      aNbE=aLEx.Extent();
      if (aNbE==1) {
	// usual case
	continue;
      }
      else if (aNbE==2){
	const TopoDS_Shape& aE1=aLEx.First();
	const TopoDS_Shape& aE2=aLEx.Last();
	if (aE1.IsSame(aE2)) {
	  bFlag=Standard_False;
	  break;
	}
      }
      else {
	bFlag=Standard_False;
	break;
      }
    }
    myNothingToDo=myNothingToDo && bFlag;
  }
  // 
  //
  if (myNothingToDo) {
    myErrorStatus=0;
    return;
  }
  //
  // 3. Angles in mySmartMap
  BRepAdaptor_Surface aBAS(myFace);
  const GeomAdaptor_Surface& aGAS=aBAS.Surface();
  for (i=1; i<=aNb; i++) {
    const TopoDS_Vertex& aV=TopoDS::Vertex (mySmartMap.FindKey(i));
    const BOP_ListOfEdgeInfo& aLEInfo= mySmartMap(i);

    BOP_ListIteratorOfListOfEdgeInfo anIt(aLEInfo);
    for (; anIt.More(); anIt.Next()) {
      BOP_EdgeInfo& anEdgeInfo=anIt.Value();
      const TopoDS_Edge& aE=anEdgeInfo.Edge();
      //
      TopoDS_Vertex aVV=aV;
      //
      anIsIn=anEdgeInfo.IsIn();
      if (anIsIn) {
	//
	aVV.Orientation(TopAbs_REVERSED);
	anAngle=Angle2D (aVV, aE, myFace, aGAS, Standard_True);
      }
      // 
      else { // OUT
	//
	aVV.Orientation(TopAbs_FORWARD);
	anAngle=Angle2D (aVV, aE, myFace, aGAS, Standard_False);
      }
      anEdgeInfo.SetAngle(anAngle);
      
    }
  }
  //
  // 4. Do
  //
  Standard_Boolean anIsOut, anIsNotPassed;
  
  TopTools_SequenceOfShape aLS, aVertVa;
  TColgp_SequenceOfPnt2d aCoordVa;
  
  BOP_ListIteratorOfListOfEdgeInfo anIt;

  for (i=1; i<=aNb; i++) {
    const TopoDS_Vertex aVa=TopoDS::Vertex (mySmartMap.FindKey(i));
    const BOP_ListOfEdgeInfo& aLEInfo=mySmartMap(i);
    
    anIt.Initialize(aLEInfo);
    for (; anIt.More(); anIt.Next()) {
      BOP_EdgeInfo& anEdgeInfo=anIt.Value();
      const TopoDS_Edge& aEOuta=anEdgeInfo.Edge();
      
      anIsOut=!anEdgeInfo.IsIn();
      anIsNotPassed=!anEdgeInfo.Passed();
      
      if (anIsOut && anIsNotPassed) {
	//
	aLS.Clear();
	aVertVa.Clear();
	aCoordVa.Clear();
	//
	Path(aGAS, myFace, aVa, aEOuta, anEdgeInfo, aLS, 
	     aVertVa, aCoordVa, myShapes, mySmartMap);
      }
    }
  }
  //
  {
    Standard_Integer aNbV, aNbE;
    TopoDS_Vertex aV1, aV2;
    BOPTColStd_ListOfListOfShape aShapes;
    BOPTColStd_ListIteratorOfListOfListOfShape anItW(myShapes);
    
    for (; anItW.More(); anItW.Next()) {
      TopTools_IndexedMapOfShape aMV, aME;
      const TopTools_ListOfShape& aLE=anItW.Value();
      TopTools_ListIteratorOfListOfShape anItE(aLE);
      for (; anItE.More(); anItE.Next()) {
	const TopoDS_Edge& aE=TopoDS::Edge(anItE.Value());
	aME.Add(aE);
	TopExp::Vertices(aE, aV1, aV2);
	aMV.Add(aV1);
	aMV.Add(aV2);
      }
      aNbV=aMV.Extent();
      aNbE=aME.Extent();
      if (aNbV<=aNbE) {
	aShapes.Append(aLE);
      }
    }
    //
    myShapes.Clear();
    anItW.Initialize(aShapes);
    for (; anItW.More(); anItW.Next()) {
      const TopTools_ListOfShape& aLE=anItW.Value();
      myShapes.Append(aLE);
    }
  }
  //
  myErrorStatus=0;
}
void SketchBased::getUpToFace(TopoDS_Face& upToFace,
                              const TopoDS_Shape& support,
                              const TopoDS_Face& supportface,
                              const TopoDS_Shape& sketchshape,
                              const std::string& method,
                              const gp_Dir& dir)
{
    if ((method == "UpToLast") || (method == "UpToFirst")) {
        // Check for valid support object
        if (support.IsNull())
            throw Base::Exception("SketchBased: Up to face: No support in Sketch!");

        std::vector<Part::cutFaces> cfaces = Part::findAllFacesCutBy(support, sketchshape, dir);
        if (cfaces.empty())
            throw Base::Exception("SketchBased: Up to face: No faces found in this direction");

        // Find nearest/furthest face
        std::vector<Part::cutFaces>::const_iterator it, it_near, it_far;
        it_near = it_far = cfaces.begin();
        for (it = cfaces.begin(); it != cfaces.end(); it++)
            if (it->distsq > it_far->distsq)
                it_far = it;
            else if (it->distsq < it_near->distsq)
                it_near = it;
        upToFace = (method == "UpToLast" ? it_far->face : it_near->face);
    }

    // Remove the limits of the upToFace so that the extrusion works even if sketchshape is larger
    // than the upToFace
    bool remove_limits = false;
    TopExp_Explorer Ex;
    for (Ex.Init(sketchshape,TopAbs_FACE); Ex.More(); Ex.Next()) {
        // Get outermost wire of sketch face
        TopoDS_Face sketchface = TopoDS::Face(Ex.Current());
        TopoDS_Wire outerWire = ShapeAnalysis::OuterWire(sketchface);
        if (!checkWireInsideFace(outerWire, upToFace, dir)) {
            remove_limits = true;
            break;
        }
    }

    if (remove_limits) {
        // Note: Using an unlimited face every time gives unnecessary failures for concave faces
        TopLoc_Location loc = upToFace.Location();
        BRepAdaptor_Surface adapt(upToFace, Standard_False);
        BRepBuilderAPI_MakeFace mkFace(adapt.Surface().Surface()
#if OCC_VERSION_HEX >= 0x060502
              , Precision::Confusion()
#endif
        );
        if (!mkFace.IsDone())
            throw Base::Exception("SketchBased: Up To Face: Failed to create unlimited face");
        upToFace = TopoDS::Face(mkFace.Shape());
        upToFace.Location(loc);
    }

    // Check that the upToFace does not intersect the sketch face and
    // is not parallel to the extrusion direction (for simplicity, supportface is used instead of sketchshape)
    BRepAdaptor_Surface adapt1(TopoDS::Face(supportface));
    BRepAdaptor_Surface adapt2(TopoDS::Face(upToFace));

    if (adapt2.GetType() == GeomAbs_Plane) {
        if (adapt1.Plane().Axis().IsNormal(adapt2.Plane().Axis(), Precision::Confusion()))
            throw Base::Exception("SketchBased: Up to face: Must not be parallel to extrusion direction!");
    }

    // We must measure from sketchshape, not supportface, here
    BRepExtrema_DistShapeShape distSS(sketchshape, upToFace);
    if (distSS.Value() < Precision::Confusion())
        throw Base::Exception("SketchBased: Up to face: Must not intersect sketch!");

}
Beispiel #12
0
int OCCFace::boolean(OCCSolid *tool, BoolOpType op) {
    try {
        TopoDS_Shape shape;
        switch (op) {
            case BOOL_CUT:
            {
                BRepAlgoAPI_Cut CU (this->getShape(), tool->getShape());
                if (!CU.IsDone())
                    Standard_ConstructionError::Raise("operation failed");
                shape = CU.Shape();
                break;
            }
            case BOOL_COMMON:
            {
                BRepAlgoAPI_Common CO (this->getShape(), tool->getShape());
                if (!CO.IsDone())
                    Standard_ConstructionError::Raise("operation failed");
                shape = CO.Shape();
                break;
            }
            default:
                Standard_ConstructionError::Raise("unknown operation");
                break;
        }
        // extract single face or single shell
        int idx = 0;
        TopExp_Explorer exBO;
        for (exBO.Init(shape, TopAbs_SHELL); exBO.More(); exBO.Next()) {
            if (idx > 0) {
                Standard_ConstructionError::Raise("multiple object in result");
            }
            const TopoDS_Shape& cur = exBO.Current();
            this->setShape(cur);
            idx++;
        }
        if (idx == 0) {
            idx = 0;
            for (exBO.Init(shape, TopAbs_FACE); exBO.More(); exBO.Next()) {
                if (idx > 0) {
                    Standard_ConstructionError::Raise("multiple object in result");
                }
                const TopoDS_Shape& cur = exBO.Current();
                this->setShape(cur);
                idx++;
            }
        }
        if (idx == 0)
            StdFail_NotDone::Raise("no results from boolean operation");;
        this->setShape(shape);
        
        // possible fix shape
        if (!this->fixShape())
            StdFail_NotDone::Raise("Shapes not valid");
        
    } catch(Standard_Failure &err) {
        Handle_Standard_Failure e = Standard_Failure::Caught();
        const Standard_CString msg = e->GetMessageString();
        if (msg != NULL && strlen(msg) > 1) {
            setErrorMessage(msg);
        } else {
            setErrorMessage("Failed in boolean operation");
        }
        return 0;
    }
    return 1;
}
Beispiel #13
0
int
EG_saveModel(const egObject *model, const char *name)
{
  int         i, len, outLevel;
  egadsModel *mshape;
  FILE        *fp;
  
  if (model == NULL)               return EGADS_NULLOBJ;
  if (model->magicnumber != MAGIC) return EGADS_NOTOBJ;
  if (model->oclass != MODEL)      return EGADS_NOTMODEL;
  outLevel = EG_outLevel(model);

  if (name == NULL) {
    if (outLevel > 0)
      printf(" EGADS Warning: NULL Filename (EG_saveModel)!\n");
    return EGADS_NONAME;
  }
  
  /* does file exist? */

  fp = fopen(name, "r");
  if (fp != NULL) {
    if (outLevel > 0)
      printf(" EGADS Warning: File %s Exists (EG_saveModel)!\n", name);
    fclose(fp);
    return EGADS_NOTFOUND;
  }
  
  /* find extension */
  
  len = strlen(name);
  for (i = len-1; i > 0; i--)
    if (name[i] == '.') break;
  if (i == 0) {
    if (outLevel > 0)
      printf(" EGADS Warning: No Extension in %s (EG_saveModel)!\n", name);
    return EGADS_NODATA;
  }
  
  mshape = (egadsModel *) model->blind;
  
  if ((strcasecmp(&name[i],".step") == 0) || 
      (strcasecmp(&name[i],".stp") == 0)) {

    /* STEP files */
    
    STEPControl_Writer aWriter;
    TopExp_Explorer Exp;
    const STEPControl_StepModelType aVal = STEPControl_AsIs;
    for (Exp.Init(mshape->shape, TopAbs_WIRE,  TopAbs_FACE);
         Exp.More(); Exp.Next()) aWriter.Transfer(Exp.Current(), aVal);
    for (Exp.Init(mshape->shape, TopAbs_FACE,  TopAbs_SHELL);
         Exp.More(); Exp.Next()) aWriter.Transfer(Exp.Current(), aVal);
    for (Exp.Init(mshape->shape, TopAbs_SHELL, TopAbs_SOLID);
         Exp.More(); Exp.Next()) aWriter.Transfer(Exp.Current(), aVal);
    for (Exp.Init(mshape->shape, TopAbs_SOLID); 
         Exp.More(); Exp.Next()) aWriter.Transfer(Exp.Current(), aVal);	
  
    if (!aWriter.Write(name)) {
      printf(" EGADS Warning: STEP Write Error (EG_saveModel)!\n");
      return EGADS_WRITERR;
    }
    
  } else if ((strcasecmp(&name[i],".iges") == 0) || 
             (strcasecmp(&name[i],".igs") == 0)) {
             
    /* IGES files */

    try {
      IGESControl_Controller::Init();
      IGESControl_Writer iWrite;
      TopExp_Explorer Exp;
      for (Exp.Init(mshape->shape, TopAbs_WIRE,  TopAbs_FACE);
           Exp.More(); Exp.Next()) iWrite.AddShape(Exp.Current());
      for (Exp.Init(mshape->shape, TopAbs_FACE,  TopAbs_SHELL);
           Exp.More(); Exp.Next()) iWrite.AddShape(Exp.Current());
      for (Exp.Init(mshape->shape, TopAbs_SHELL, TopAbs_SOLID);
           Exp.More(); Exp.Next()) iWrite.AddShape(Exp.Current());
      for (Exp.Init(mshape->shape, TopAbs_SOLID); 
           Exp.More(); Exp.Next()) iWrite.AddShape(Exp.Current());

      iWrite.ComputeModel();
      if (!iWrite.Write(name)) {
        printf(" EGADS Warning: IGES Write Error (EG_saveModel)!\n");
        return EGADS_WRITERR;
      }
    }
    catch (...)
    {
      printf(" EGADS Warning: Internal IGES Write Error (EG_saveModel)!\n");
      return EGADS_WRITERR;
    }

  } else if ((strcasecmp(&name[i],".brep") == 0) ||
             (strcasecmp(&name[i],".egads") == 0)) {
  
    /* Native OCC file or our filetype */

    if (!BRepTools::Write(mshape->shape, name)) {
      printf(" EGADS Warning: OCC Write Error (EG_saveModel)!\n");
      return EGADS_WRITERR;
    }
    if (strcasecmp(&name[i],".brep") == 0) return EGADS_SUCCESS;
    
    /* append the attributes -- output in the read order */
    
    FILE *fp = fopen(name, "a");
    if (fp == NULL) {
      printf(" EGADS Warning: EGADS Open Error (EG_saveModel)!\n");
      return EGADS_WRITERR;
    }
    fprintf(fp, "\n##EGADS HEADER FILE-REV 1 ##\n");
    /* write model attributes */
    EG_writeAttrs(model, fp);
    TopExp_Explorer Exp;
    for (Exp.Init(mshape->shape, TopAbs_WIRE,  TopAbs_FACE); 
         Exp.More(); Exp.Next()) {
      TopoDS_Shape shape = Exp.Current();
      for (i = 0; i < mshape->nbody; i++) {
        egObject  *obj   = mshape->bodies[i];
        egadsBody *pbody = (egadsBody *) obj->blind;
        if (shape.IsSame(pbody->shape)) {
          EG_writeAttrs(obj, fp);
          break;
        }
      }
    }
    for (Exp.Init(mshape->shape, TopAbs_FACE,  TopAbs_SHELL);
         Exp.More(); Exp.Next()) {
      TopoDS_Shape shape = Exp.Current();
      for (i = 0; i < mshape->nbody; i++) {
        egObject  *obj   = mshape->bodies[i];
        egadsBody *pbody = (egadsBody *) obj->blind;
        if (shape.IsSame(pbody->shape)) {
          EG_writeAttrs(obj, fp);
          break;
        }
      }
    }
    for (Exp.Init(mshape->shape, TopAbs_SHELL, TopAbs_SOLID);
         Exp.More(); Exp.Next()) {
      TopoDS_Shape shape = Exp.Current();
      for (i = 0; i < mshape->nbody; i++) {
        egObject  *obj   = mshape->bodies[i];
        egadsBody *pbody = (egadsBody *) obj->blind;
        if (shape.IsSame(pbody->shape)) {
          EG_writeAttrs(obj, fp);
          break;
        }
      }
    }
    for (Exp.Init(mshape->shape, TopAbs_SOLID); Exp.More(); Exp.Next()) {
      TopoDS_Shape shape = Exp.Current();
      for (i = 0; i < mshape->nbody; i++) {
        egObject  *obj   = mshape->bodies[i];
        egadsBody *pbody = (egadsBody *) obj->blind;
        if (shape.IsSame(pbody->shape)) {
          EG_writeAttrs(obj, fp);
          break;
        }
      }
    }
   
   fclose(fp);

  } else {
    if (outLevel > 0)
      printf(" EGADS Warning: Extension in %s Not Supported (EG_saveModel)!\n",
             name);
    return EGADS_NODATA;
  }

  return EGADS_SUCCESS;
}
Beispiel #14
0
//=======================================================================
// function: MakeConnexityBlock.
// purpose: 
//=======================================================================
  void GEOMAlgo_Tools3D::MakeConnexityBlock (const TopTools_ListOfShape& theLFIn,
                                             const TopTools_IndexedMapOfShape& theMEAvoid,
                                             TopTools_ListOfShape& theLCB)
{
  Standard_Integer  aNbF, aNbAdd1;
  TopExp_Explorer aExp;
  TopTools_IndexedDataMapOfShapeListOfShape aMEF;
  TopTools_MapIteratorOfMapOfShape aItM, aItM1;
  TopTools_MapOfShape aMCB, aMAdd, aMAdd1;
  TopTools_ListIteratorOfListOfShape aIt;
  //
  // 1. aMEF
  aNbF=theLFIn.Extent();
  aIt.Initialize(theLFIn);
  for (; aIt.More(); aIt.Next()) {
    const TopoDS_Shape& aF=aIt.Value();      
    TopExp::MapShapesAndAncestors(aF, TopAbs_EDGE, TopAbs_FACE, aMEF);
  }
  //
  // 2. aMCB
  const TopoDS_Shape& aF1=theLFIn.First();
  aMAdd.Add(aF1);
  //
  while(1) {
    aMAdd1.Clear();
    aItM.Initialize(aMAdd);
    for (; aItM.More(); aItM.Next()) {
      const TopoDS_Shape& aF=aItM.Key();
      //
      //aMAdd1.Clear();
      aExp.Init(aF, TopAbs_EDGE);
      for (; aExp.More(); aExp.Next()) {
        const TopoDS_Shape& aE=aExp.Current();
        if (theMEAvoid.Contains(aE)){
          continue;
        }
        //
        const TopTools_ListOfShape& aLF=aMEF.FindFromKey(aE);
        aIt.Initialize(aLF);
        for (; aIt.More(); aIt.Next()) {
          const TopoDS_Shape& aFx=aIt.Value();
          if (aFx.IsSame(aF)) {
            continue;
          }
          if (aMCB.Contains(aFx)) {
            continue;
          }
          aMAdd1.Add(aFx);
        }
      }//for (; aExp.More(); aExp.Next()){
      aMCB.Add(aF);
    }// for (; aItM.More(); aItM.Next()) {
    //
    aNbAdd1=aMAdd1.Extent();
    if (!aNbAdd1) {
      break;
    }
    //
    aMAdd.Clear();
    aItM1.Initialize(aMAdd1);
    for (; aItM1.More(); aItM1.Next()) {
      const TopoDS_Shape& aFAdd=aItM1.Key();
      aMAdd.Add(aFAdd);
    }
    //
  }//while(1) {
  
  //
  aNbF=aMCB.Extent();
  aItM.Initialize(aMCB);
  for (; aItM.More(); aItM.Next()) {
    const TopoDS_Shape& aF=aItM.Key();
    theLCB.Append(aF);
  }
}
App::DocumentObjectExecReturn *FeatureShape::execute(void)
{
    TopoDS_Shape shape = Shape.getValue();
    if (!shape.IsNull()) {
        if (shape.ShapeType() == TopAbs_WIRE) {
            Path::Toolpath result;
            bool first = true;
            Base::Placement last;
            
            TopExp_Explorer ExpEdges (shape,TopAbs_EDGE);
            while (ExpEdges.More()) {
                const TopoDS_Edge& edge = TopoDS::Edge(ExpEdges.Current());
                TopExp_Explorer ExpVerts(edge,TopAbs_VERTEX);
                bool vfirst = true;
                while (ExpVerts.More()) {
                    const TopoDS_Vertex& vert = TopoDS::Vertex(ExpVerts.Current());
                    gp_Pnt pnt = BRep_Tool::Pnt(vert);
                    Base::Placement tpl;
                    tpl.setPosition(Base::Vector3d(pnt.X(),pnt.Y(),pnt.Z()));
                    if (first) {
                        // add first point as a G0 move
                        Path::Command cmd;
                        std::ostringstream ctxt;
                        ctxt << "G0 X" << tpl.getPosition().x << " Y" << tpl.getPosition().y << " Z" << tpl.getPosition().z;
                        cmd.setFromGCode(ctxt.str());
                        result.addCommand(cmd);
                        first = false;
                        vfirst = false;
                    } else {
                        if (vfirst)
                            vfirst = false;
                        else {
                            Path::Command cmd;
                            cmd.setFromPlacement(tpl);
                
                            // write arc data if needed
                            BRepAdaptor_Curve adapt(edge);
                            if (adapt.GetType() == GeomAbs_Circle) {
                                gp_Circ circ = adapt.Circle();
                                gp_Pnt c = circ.Location();
                                bool clockwise = false;
                                gp_Dir n = circ.Axis().Direction();
                                if (n.Z() < 0)
                                    clockwise = true;
                                Base::Vector3d center = Base::Vector3d(c.X(),c.Y(),c.Z());
                                // center coords must be relative to last point
                                center -= last.getPosition();
                                cmd.setCenter(center,clockwise);
                            }
                            result.addCommand(cmd);
                        }
                    }
                    ExpVerts.Next();
                    last = tpl;
                }
                ExpEdges.Next();
            }
            
            Path.setValue(result);
        }
    }
    return App::DocumentObject::StdReturn;
}
Beispiel #16
0
//=======================================================================
//function : GetEdgeNearPoint
//purpose  :
//=======================================================================
TopoDS_Shape GEOMUtils::GetEdgeNearPoint (const TopoDS_Shape& theShape,
                                          const TopoDS_Vertex& thePoint)
{
  TopoDS_Shape aResult;

  // 1. Explode the shape on edges
  TopTools_MapOfShape mapShape;
  Standard_Integer nbEdges = 0;
  TopExp_Explorer exp (theShape, TopAbs_EDGE);
  for (; exp.More(); exp.Next()) {
    if (mapShape.Add(exp.Current())) {
      nbEdges++;
    }
  }

  if (nbEdges == 0)
    Standard_NullObject::Raise("Given shape contains no edges");

  mapShape.Clear();
  Standard_Integer ind = 1;
  TopTools_Array1OfShape anEdges (1, nbEdges);
  TColStd_Array1OfReal aDistances (1, nbEdges);
  for (exp.Init(theShape, TopAbs_EDGE); exp.More(); exp.Next()) {
    if (mapShape.Add(exp.Current())) {
      TopoDS_Shape anEdge = exp.Current();
      anEdges(ind) = anEdge;

      // 2. Classify the point relatively each edge
      BRepExtrema_DistShapeShape aDistTool (thePoint, anEdges(ind));
      if (!aDistTool.IsDone())
        Standard_ConstructionError::Raise("Cannot find a distance from the given point to one of edges");

      aDistances(ind) = aDistTool.Value();
      ind++;
    }
  }

  // 3. Define edge, having minimum distance to the point
  Standard_Real nearest = RealLast(), nbFound = 0;
  Standard_Real prec = Precision::Confusion();
  for (ind = 1; ind <= nbEdges; ind++) {
    if (Abs(aDistances(ind) - nearest) < prec) {
      nbFound++;
    }
    else if (aDistances(ind) < nearest) {
      nearest = aDistances(ind);
      aResult = anEdges(ind);
      nbFound = 1;
    }
    else {
    }
  }
  if (nbFound > 1) {
    Standard_ConstructionError::Raise("Multiple edges near the given point are found");
  }
  else if (nbFound == 0) {
    Standard_ConstructionError::Raise("There are no edges near the given point");
  }
  else {
  }

  return aResult;
}
Beispiel #17
0
// create the PCB (board only) model using the current outlines and drill holes
bool PCBMODEL::CreatePCB()
{
    if( m_hasPCB )
    {
        if( m_pcb_label.IsNull() )
            return false;

        return true;
    }

    if( m_curves.empty() || m_mincurve == m_curves.end() )
    {
        m_hasPCB = true;
        std::ostringstream ostr;
#ifdef __WXDEBUG__
        ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
#endif /* __WXDEBUG */
        ostr << "  * no valid board outline\n";
        wxLogMessage( "%s", ostr.str().c_str() );
        return false;
    }

    m_hasPCB = true;    // whether or not operations fail we note that CreatePCB has been invoked
    TopoDS_Shape board;
    OUTLINE oln;    // loop to assemble (represents PCB outline and cutouts)
    oln.SetMinSqDistance( m_minDistance2 );
    oln.AddSegment( *m_mincurve );
    m_curves.erase( m_mincurve );

    while( !m_curves.empty() )
    {
        if( oln.IsClosed() )
        {
            if( board.IsNull() )
            {
                if( !oln.MakeShape( board, m_thickness ) )
                {
                    std::ostringstream ostr;
#ifdef __WXDEBUG__
                    ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
#endif /* __WXDEBUG */
                    ostr << "  * could not create board extrusion\n";
                    wxLogMessage( "%s", ostr.str().c_str() );

                    return false;
                }
            }
            else
            {
                TopoDS_Shape hole;

                if( oln.MakeShape( hole, m_thickness ) )
                {
                    m_cutouts.push_back( hole );
                }
                else
                {
                    std::ostringstream ostr;
#ifdef __WXDEBUG__
                    ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
#endif /* __WXDEBUG */
                    ostr << "  * could not create board cutout\n";
                    wxLogMessage( "%s", ostr.str().c_str() );
                }
            }

            oln.Clear();

            if( !m_curves.empty() )
            {
                oln.AddSegment( m_curves.front() );
                m_curves.pop_front();
            }

            continue;
        }

        std::list< KICADCURVE >::iterator sC = m_curves.begin();
        std::list< KICADCURVE >::iterator eC = m_curves.end();

        while( sC != eC )
        {
            if( oln.AddSegment( *sC ) )
            {
                m_curves.erase( sC );
                break;
            }

            ++sC;
        }

        if( sC == eC && !oln.m_curves.empty() )
        {
            std::ostringstream ostr;
#ifdef __WXDEBUG__
            ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
#endif /* __WXDEBUG */
            ostr << "  * could not close outline (dropping outline data with " << oln.m_curves.size() << " segments)\n";

            for( const auto& c : oln.m_curves )
                ostr << "    + " << c.Describe() << "\n";

            wxLogMessage( "%s", ostr.str().c_str() );
            oln.Clear();

            if( !m_curves.empty() )
            {
                oln.AddSegment( m_curves.front() );
                m_curves.pop_front();
            }
        }
    }

    if( oln.IsClosed() )
    {
        if( board.IsNull() )
        {
            if( !oln.MakeShape( board, m_thickness ) )
            {
                std::ostringstream ostr;
#ifdef __WXDEBUG__
                ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
#endif /* __WXDEBUG */
                ostr << "  * could not create board extrusion\n";
                wxLogMessage( "%s", ostr.str().c_str() );
                return false;
            }
        }
        else
        {
            TopoDS_Shape hole;

            if( oln.MakeShape( hole, m_thickness ) )
            {
                m_cutouts.push_back( hole );
            }
            else
            {
                std::ostringstream ostr;
#ifdef __WXDEBUG__
                ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
#endif /* __WXDEBUG */
                ostr << "  * could not create board cutout\n";
                wxLogMessage( "%s", ostr.str().c_str() );
            }
        }
    }

    // subtract cutouts (if any)
    for( auto i : m_cutouts )
        board = BRepAlgoAPI_Cut( board, i );

    // push the board to the data structure
    m_pcb_label = m_assy->AddComponent( m_assy_label, board );

    if( m_pcb_label.IsNull() )
        return false;

    // color the PCB
    Handle(XCAFDoc_ColorTool) color =
        XCAFDoc_DocumentTool::ColorTool( m_doc->Main () );
    Quantity_Color pcb_green( 0.06, 0.4, 0.06, Quantity_TOC_RGB );
    color->SetColor( m_pcb_label, pcb_green, XCAFDoc_ColorSurf );

    TopExp_Explorer topex;
    topex.Init( m_assy->GetShape( m_pcb_label ), TopAbs_SOLID );

    while( topex.More() )
    {
        color->SetColor( topex.Current(), pcb_green, XCAFDoc_ColorSurf );
        topex.Next();
    }

#if ( defined OCC_VERSION_HEX ) && ( OCC_VERSION_HEX > 0x070101 )
    m_assy->UpdateAssemblies();
#endif
    return true;
}
void MeshAlgos::LoftOnCurve(MeshCore::MeshKernel &ResultMesh, const TopoDS_Shape &Shape, const std::vector<Base::Vector3f> &poly, const Base::Vector3f & up, float MaxSize)
{
  TopExp_Explorer Ex;
  Standard_Real fBegin, fEnd;
  std::vector<MeshGeomFacet> cVAry;
  std::map<TopoDS_Vertex,std::vector<Base::Vector3f>,_VertexCompare> ConnectMap;

  for (Ex.Init(Shape, TopAbs_EDGE); Ex.More(); Ex.Next())
  {
    // get the edge and the belonging Vertexes
    TopoDS_Edge Edge = (TopoDS_Edge&)Ex.Current();
    TopoDS_Vertex V1, V2;
    TopExp::Vertices(Edge, V1, V2);
    bool bBegin = false,bEnd = false;
    // geting the geometric curve and the interval
    GeomLProp_CLProps prop(BRep_Tool::Curve(Edge,fBegin,fEnd),1,0.0000000001);
    int res = int((fEnd - fBegin)/MaxSize);
    // do at least 2 segments
    if(res < 2) 
      res = 2;
    gp_Dir Tangent;

    std::vector<Base::Vector3f> prePoint(poly.size());
    std::vector<Base::Vector3f> actPoint(poly.size());
    
    // checking if there is already a end to conect
    if(ConnectMap.find(V1) != ConnectMap.end() ){
      bBegin = true;
      prePoint = ConnectMap[V1];
    }
    
    if(ConnectMap.find(V2) != ConnectMap.end() )
      bEnd = true;

    for (long i = 0; i < res; i++)
    {

      // get point and tangent at the position, up is fix for the moment
      prop.SetParameter(fBegin + ((fEnd - fBegin) * float(i)) / float(res-1));
      prop.Tangent(Tangent);
      Base::Vector3f Tng((float)Tangent.X(),
                         (float)Tangent.Y(),
                         (float)Tangent.Z());
      Base::Vector3f Ptn((float)prop.Value().X(),
                         (float)prop.Value().Y(),
                         (float)prop.Value().Z());
      Base::Vector3f Up (up);
      // normalize and calc the third vector of the plane coordinatesystem
      Tng.Normalize(); 
      Up.Normalize();
      Base::Vector3f Third(Tng%Up);

//      Base::Console().Log("Pos: %f %f %f \n",Ptn.x,Ptn.y,Ptn.z);

      unsigned int l=0;
      std::vector<Base::Vector3f>::const_iterator It;

      // got through the profile
      for(It=poly.begin();It!=poly.end();++It,l++)
        actPoint[l] = ((Third*It->x)+(Up*It->y)+(Tng*It->z)+Ptn);

      if(i == res-1 && !bEnd)
        // remeber the last row to conect to a otger edge with the same vertex
        ConnectMap[V2] = actPoint;

      if(i==1 && bBegin)
        // using the end of an other edge as start 
        prePoint = ConnectMap[V1];

      if(i==0 && !bBegin)
          // remember the first row for conection to a edge with the same vertex
          ConnectMap[V1] = actPoint;

      if(i ) // not the first row or somthing to conect to
      {
        for(l=0;l<actPoint.size();l++)
        {
          if(l) // not first point in row 
          {
            if(i == res-1 && bEnd) // if last row and a end to conect
              actPoint = ConnectMap[V2];

            Base::Vector3f p1 = prePoint[l-1],
                     p2 = actPoint[l-1],
                     p3 = prePoint[l],
                     p4 = actPoint[l];

            cVAry.push_back(MeshGeomFacet(p1,p2,p3));
            cVAry.push_back(MeshGeomFacet(p3,p2,p4));
          }
        }
      }

      prePoint = actPoint;
    }
  }

  ResultMesh.AddFacets(cVAry);

}
//=======================================================================
//function : Execute
//purpose  :
//=======================================================================
Standard_Integer GEOMImpl_ChamferDriver::Execute(TFunction_Logbook& log) const
{
  if (Label().IsNull()) return 0;
  Handle(GEOM_Function) aFunction = GEOM_Function::GetFunction(Label());

  GEOMImpl_IChamfer aCI (aFunction);
  Standard_Integer aType = aFunction->GetType();

  TopoDS_Shape aShape;

  Handle(GEOM_Function) aRefShape = aCI.GetShape();
  TopoDS_Shape aShapeBase = aRefShape->GetValue();



  if (aType == CHAMFER_SHAPE_EDGES_2D)
  {
	BRepFilletAPI_MakeFillet2d fill;
	TopoDS_Face aFace;

	Standard_Boolean aWireFlag = Standard_False;
	
	if (aShapeBase.ShapeType() == TopAbs_FACE)
		aFace = TopoDS::Face(aShapeBase);
	else if (aShapeBase.ShapeType() == TopAbs_WIRE)
	{
		TopoDS_Wire aWire = TopoDS::Wire(aShapeBase);
		BRepBuilderAPI_MakeFace aMF(aWire);
		aMF.Build();
		if (!aMF.IsDone()) {
			StdFail_NotDone::Raise("Cannot build initial face from given wire");
		}
		aFace = aMF.Face();
		aWireFlag = Standard_True;
	}
	else
		StdFail_NotDone::Raise("Base shape is neither a face or a wire !");

	fill.Init(aFace);

	double aD1_2D = aCI.GetD1();
	double aD2_2D = aCI.GetD2();

	TopoDS_Shape aShapeFace1, aShapeFace2;

	if (GEOMImpl_ILocalOperations::GetSubShape(aShapeBase, aCI.Get2DEdge1(), aShapeFace1) &&
		GEOMImpl_ILocalOperations::GetSubShape(aShapeBase, aCI.Get2DEdge2(), aShapeFace2))
	{
		fill.AddChamfer(TopoDS::Edge(aShapeFace1), TopoDS::Edge(aShapeFace2), aD1_2D, aD2_2D);
	}
	else
		StdFail_NotDone::Raise("Cannot get 2d egde from sub-shape index!");

	fill.Build();
	if (!fill.IsDone()) {
		StdFail_NotDone::Raise("Chamfer can not be computed on the given shape with the given parameters");
	}
	if (aWireFlag)
	{
		BRepBuilderAPI_MakeWire MW;
		TopExp_Explorer exp (fill.Shape(), TopAbs_EDGE);
		for (; exp.More(); exp.Next())
			MW.Add(TopoDS::Edge(exp.Current()));
		MW.Build();
		if (!MW.IsDone())
			StdFail_NotDone::Raise("Resulting wire cannot be built");
			
		aShape = MW.Shape();
	}
	else
		aShape = fill.Shape();
  }
  else
  {
	  // Check the shape type. It have to be shell
	  // or solid, or compsolid, or compound of these shapes.
	  if (!isGoodForChamfer(aShapeBase)) {
		StdFail_NotDone::Raise
		  ("Wrong shape. Must be shell or solid, or compsolid or compound of these shapes");
	  }

	  BRepFilletAPI_MakeChamfer fill (aShapeBase);

	  if (aType == CHAMFER_SHAPE_ALL) {
		// symmetric chamfer on all edges
		double aD = aCI.GetD();
		TopTools_IndexedDataMapOfShapeListOfShape M;
		GEOMImpl_Block6Explorer::MapShapesAndAncestors(aShapeBase, TopAbs_EDGE, TopAbs_FACE, M);
		for (int i = 1; i <= M.Extent(); i++) {
		  TopoDS_Edge E = TopoDS::Edge(M.FindKey(i));
		  TopoDS_Face F = TopoDS::Face(M.FindFromIndex(i).First());
		  if (!BRepTools::IsReallyClosed(E, F) &&
			  !BRep_Tool::Degenerated(E) &&
			  M.FindFromIndex(i).Extent() == 2)
			fill.Add(aD, E, F);
		}
	  }else if (aType == CHAMFER_SHAPE_EDGE || aType == CHAMFER_SHAPE_EDGE_AD) {
		// chamfer on edges, common to two faces, with D1 on the first face

		TopoDS_Shape aFace1, aFace2;
		if (GEOMImpl_ILocalOperations::GetSubShape(aShapeBase, aCI.GetFace1(), aFace1) &&
			GEOMImpl_ILocalOperations::GetSubShape(aShapeBase, aCI.GetFace2(), aFace2))
		  {
		TopoDS_Face F = TopoDS::Face(aFace1);

		// fill map of edges of the second face
		TopTools_MapOfShape aMap;
		TopExp_Explorer Exp2 (aFace2, TopAbs_EDGE);
		for (; Exp2.More(); Exp2.Next()) {
		  aMap.Add(Exp2.Current());
		}
	
		// find edges of the first face, common with the second face
		TopExp_Explorer Exp (aFace1, TopAbs_EDGE);
		for (; Exp.More(); Exp.Next()) {
		  if (aMap.Contains(Exp.Current())) {
			TopoDS_Edge E = TopoDS::Edge(Exp.Current());
			if (!BRepTools::IsReallyClosed(E, F) && !BRep_Tool::Degenerated(E))
			  {
			if ( aType == CHAMFER_SHAPE_EDGE )
			  {
				double aD1 = aCI.GetD1();
				double aD2 = aCI.GetD2();
				fill.Add(aD1, aD2, E, F);
			  }
			else
			  {
				double aD = aCI.GetD();
				double anAngle = aCI.GetAngle();
				if ( (anAngle > 0) && (anAngle < (Standard_PI/2)) )
				  fill.AddDA(aD, anAngle, E, F);
			  }
			  }
		  }
		}
		  }
	  }
	  else if (aType == CHAMFER_SHAPE_FACES || aType == CHAMFER_SHAPE_FACES_AD) {
		// chamfer on all edges of the selected faces, with D1 on the selected face
		// (on first selected face, if the edge belongs to two selected faces)

		int aLen = aCI.GetLength();
		int ind = 1;
		TopTools_MapOfShape aMap;
		TopTools_IndexedDataMapOfShapeListOfShape M;
		GEOMImpl_Block6Explorer::MapShapesAndAncestors(aShapeBase, TopAbs_EDGE, TopAbs_FACE, M);
		for (; ind <= aLen; ind++)
		{
		  TopoDS_Shape aShapeFace;
		  if (GEOMImpl_ILocalOperations::GetSubShape(aShapeBase, aCI.GetFace(ind), aShapeFace))
		{
		  TopoDS_Face F = TopoDS::Face(aShapeFace);
		  TopExp_Explorer Exp (F, TopAbs_EDGE);
		  for (; Exp.More(); Exp.Next()) {
			if (!aMap.Contains(Exp.Current()))
			  {
			TopoDS_Edge E = TopoDS::Edge(Exp.Current());
			if (!BRepTools::IsReallyClosed(E, F) &&
				!BRep_Tool::Degenerated(E) &&
				M.FindFromKey(E).Extent() == 2)
			  if (aType == CHAMFER_SHAPE_FACES)
				{
				  double aD1 = aCI.GetD1();
				  double aD2 = aCI.GetD2();
				  fill.Add(aD1, aD2, E, F);
				}
			  else
				{
				  double aD = aCI.GetD();
				  double anAngle = aCI.GetAngle();
				  if ( (anAngle > 0) && (anAngle < (Standard_PI/2)) )
				fill.AddDA(aD, anAngle, E, F);
				}
			  }
		  }
		}
		}
	  }
	else if (aType == CHAMFER_SHAPE_EDGES || aType == CHAMFER_SHAPE_EDGES_AD)
	  {
		// chamfer on selected edges with lenght param D1 & D2.

		int aLen = aCI.GetLength();
		int ind = 1;
		TopTools_MapOfShape aMap;
		TopTools_IndexedDataMapOfShapeListOfShape M;
		GEOMImpl_Block6Explorer::MapShapesAndAncestors(aShapeBase, TopAbs_EDGE, TopAbs_FACE, M);
		for (; ind <= aLen; ind++)
		{
		  TopoDS_Shape aShapeEdge;
		  if (GEOMImpl_ILocalOperations::GetSubShape(aShapeBase, aCI.GetEdge(ind), aShapeEdge))
		{
		  TopoDS_Edge E = TopoDS::Edge(aShapeEdge);
		  const TopTools_ListOfShape& aFacesList = M.FindFromKey(E);
		  TopoDS_Face F = TopoDS::Face( aFacesList.First() );
		  if (aType == CHAMFER_SHAPE_EDGES)
			{
			  double aD1 = aCI.GetD1();
			  double aD2 = aCI.GetD2();
			  fill.Add(aD1, aD2, E, F);
			}
		  else
			{
			  double aD = aCI.GetD();
			  double anAngle = aCI.GetAngle();
			  if ( (anAngle > 0) && (anAngle < (Standard_PI/2)) )
			fill.AddDA(aD, anAngle, E, F);
			}
		}
		}
	  }
	  else {
	  }

	  fill.Build();
	  if (!fill.IsDone()) {
		StdFail_NotDone::Raise("Chamfer can not be computed on the given shape with the given parameters");
	  }
	  aShape = fill.Shape();
  }

  if (aShape.IsNull()) return 0;

  // Check shape validity
  BRepCheck_Analyzer ana (aShape, false);
  if (!ana.IsValid()) {
  	// 08.07.2008 added by skl during fixing bug 19761 from Mantis
	ShapeFix_ShapeTolerance aSFT;
	aSFT.LimitTolerance(aShape, Precision::Confusion(),
						Precision::Confusion(), TopAbs_SHAPE);
	Handle(ShapeFix_Shape) aSfs = new ShapeFix_Shape(aShape);
	aSfs->Perform();
	aShape = aSfs->Shape();

    // fix SameParameter flag
    BRepLib::SameParameter(aShape, 1.E-5, Standard_True);

	ana.Init(aShape);
	if (!ana.IsValid()) {
	  Standard_CString anErrStr("Chamfer algorithm has produced an invalid shape result");
	  #ifdef THROW_ON_INVALID_SH
		Standard_ConstructionError::Raise(anErrStr);
	  #else
		MESSAGE(anErrStr);
		//further processing can be performed here
		//...
		//in case of failure of automatic treatment
		//mark the corresponding GEOM_Object as problematic
		TDF_Label aLabel = aFunction->GetOwnerEntry();
		if (!aLabel.IsRoot()) {
		  Handle(GEOM_Object) aMainObj = GEOM_Object::GetObject(aLabel);
		  if (!aMainObj.IsNull())
			aMainObj->SetDirty(Standard_True);
		}
	  #endif
	}
  }

  aFunction->SetValue(aShape);

  log.SetTouched(Label());

  return 1;
}