//=======================================================================
//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;
}
Example #2
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;
}
Example #3
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(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(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(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");
    }
}
Example #4
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;
}
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;
}
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!");

}
Example #9
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;
}
Example #10
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;
}
Example #11
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_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;
}