// constructor method
int TopoShapeSolidPy::PyInit(PyObject* args, PyObject* /*kwd*/)
{
    PyObject *obj;
    if (!PyArg_ParseTuple(args, "O!", &(TopoShapePy::Type), &obj))
        return -1;

    try {
        BRepBuilderAPI_MakeSolid mkSolid;
        const TopoDS_Shape& shape = static_cast<TopoShapePy*>(obj)
            ->getTopoShapePtr()->_Shape;
        TopExp_Explorer anExp (shape, TopAbs_SHELL);
        int count=0;
        for (; anExp.More(); anExp.Next()) {
            ++count;
            mkSolid.Add(TopoDS::Shell(anExp.Current()));
        }

        if (count == 0)
            Standard_Failure::Raise("No shells found in shape");

        TopoDS_Solid solid = mkSolid.Solid();
        BRepLib::OrientClosedSolid(solid);
        getTopoShapePtr()->_Shape = solid;
    }
    catch (Standard_Failure) {
        PyErr_SetString(PartExceptionOCCError, "creation of solid failed");
        return -1;
    }

    return 0;
}
// constructor method
int TopoShapeSolidPy::PyInit(PyObject* args, PyObject* /*kwd*/)
{
    PyObject *obj;
    if (!PyArg_ParseTuple(args, "O!", &(TopoShapePy::Type), &obj))
        return -1;

    try {
        const TopoDS_Shape& shape = static_cast<TopoShapePy*>(obj)
            ->getTopoShapePtr()->getShape();
        //first, if we were given a compsolid, try making a solid out of it
        TopExp_Explorer CSExp (shape, TopAbs_COMPSOLID);
        TopoDS_CompSolid compsolid;
        int count=0;
        for (; CSExp.More(); CSExp.Next()) {
            ++count;
            compsolid = TopoDS::CompSolid(CSExp.Current());
            if (count > 1)
                break;
        }
        if (count == 0) {
            //no compsolids. Get shells...
            BRepBuilderAPI_MakeSolid mkSolid;
            TopExp_Explorer anExp (shape, TopAbs_SHELL);
            count=0;
            for (; anExp.More(); anExp.Next()) {
                ++count;
                mkSolid.Add(TopoDS::Shell(anExp.Current()));
            }

            if (count == 0)//no shells?
                Standard_Failure::Raise("No shells or compsolids found in shape");

            TopoDS_Solid solid = mkSolid.Solid();
            BRepLib::OrientClosedSolid(solid);
            getTopoShapePtr()->setShape(solid);
        } else if (count == 1) {
            BRepBuilderAPI_MakeSolid mkSolid(compsolid);
            TopoDS_Solid solid = mkSolid.Solid();
            getTopoShapePtr()->setShape(solid);
        } else if (count > 1) {
            Standard_Failure::Raise("Only one compsolid can be accepted. Provided shape has more than one compsolid.");
        }

    }
    catch (Standard_Failure err) {
        std::stringstream errmsg;
        errmsg << "Creation of solid failed: " << err.GetMessageString();
        PyErr_SetString(PartExceptionOCCError, errmsg.str().c_str());
        return -1;
    }

    return 0;
}
App::DocumentObjectExecReturn *Wedge::execute(void)
{
    double xmin = Xmin.getValue();
    double ymin = Ymin.getValue();
    double zmin = Zmin.getValue();
    double z2min = Z2min.getValue();
    double x2min = X2min.getValue();
    double xmax = Xmax.getValue();
    double ymax = Ymax.getValue();
    double zmax = Zmax.getValue();
    double z2max = Z2max.getValue();
    double x2max = X2max.getValue();


    double dx = xmax-xmin;
    double dy = ymax-ymin;
    double dz = zmax-zmin;
    double dz2 = z2max-z2min;
    double dx2 = x2max-x2min;

    if (dx < Precision::Confusion())
        return new App::DocumentObjectExecReturn("delta x of wedge too small");

    if (dy < Precision::Confusion())
        return new App::DocumentObjectExecReturn("delta y of wedge too small");

    if (dz < Precision::Confusion())
        return new App::DocumentObjectExecReturn("delta z of wedge too small");

    if (dz2 < 0)
        return new App::DocumentObjectExecReturn("delta z2 of wedge is negative");

    if (dx2 < 0)
        return new App::DocumentObjectExecReturn("delta x2 of wedge is negative");

    try {
        gp_Pnt pnt(0.0,0.0,0.0);
        gp_Dir dir(0.0,0.0,1.0);
        BRepPrim_Wedge mkWedge(gp_Ax2(pnt,dir),
            xmin, ymin, zmin, z2min, x2min,
            xmax, ymax, zmax, z2max, x2max);
        BRepBuilderAPI_MakeSolid mkSolid;
        mkSolid.Add(mkWedge.Shell());
        this->Shape.setValue(mkSolid.Solid());
    }
    catch (Standard_Failure) {
        Handle_Standard_Failure e = Standard_Failure::Caught();
        return new App::DocumentObjectExecReturn(e->GetMessageString());
    }

    return App::DocumentObject::StdReturn;
}
示例#4
0
/// This is the actual fusing
void CFuseShapes::DoFuse()
{
    if (!_parent) {
        throw tigl::CTiglError("Null pointer for parent shape in CFuseShapes", TIGL_NULL_POINTER);
    }

    BRepBuilderAPI_Sewing shellMaker;

    _trimmedChilds.clear();
    ListPNamedShape::const_iterator childIter;

    TrimOperation childTrim  = EXCLUDE;
    TrimOperation parentTrim = EXCLUDE;

    // trim the childs with the parent and vice versa
    _trimmedParent = _parent->DeepCopy();
    for (childIter = _childs.begin(); childIter != _childs.end(); ++childIter) {
        const PNamedShape child = *childIter;
        if (!child) {
            continue;
        }

#ifdef DEBUG_BOP
        clock_t start, stop;
        start = clock();
#endif
        BOPCol_ListOfShape aLS;
        aLS.Append(_trimmedParent->Shape());
        aLS.Append(child->Shape());
        BOPAlgo_PaveFiller DSFill;
        DSFill.SetArguments(aLS);
        DSFill.Perform();
#ifdef DEBUG_BOP
        stop = clock();
        printf("dsfiller [ms]: %f\n", (stop-start)/(double)CLOCKS_PER_SEC * 1000.);

        start = clock();
#endif
        // calculate intersection
        // Todo: make a new BOP out of this
        TopoDS_Shape intersection = BRepAlgoAPI_Section(_trimmedParent->Shape(), child->Shape(), DSFill);
        PNamedShape intersectionShape(new CNamedShape(intersection, std::string("INT" + std::string(_parent->Name()) + child->Name()).c_str()));
        intersectionShape->SetShortName(std::string("INT" + std::string(_parent->ShortName()) + child->ShortName()).c_str());
        _intersections.push_back(intersectionShape);

#ifdef DEBUG_BOP
        stop = clock();
        printf("intersection [ms]: %f\n", (stop-start)/(double)CLOCKS_PER_SEC * 1000.);

        start = clock();
#endif
        _trimmedParent = CTrimShape(_trimmedParent, child, DSFill, parentTrim);

#ifdef DEBUG_BOP
        stop = clock();
        printf("parent split [ms]: %f\n", (stop-start)/(double)CLOCKS_PER_SEC * 1000.);

        start = clock();
#endif
        PNamedShape trimmedChild = CTrimShape(child, _parent, DSFill, childTrim);
        _trimmedChilds.push_back(trimmedChild);

#ifdef DEBUG_BOP
        stop = clock();
        printf("child split [ms]: %f\n", (stop-start)/(double)CLOCKS_PER_SEC * 1000.);
#endif
    } // trimming

    // add trimmed child faces to result
    for (childIter = _trimmedChilds.begin(); childIter != _trimmedChilds.end(); ++childIter) {
        shellMaker.Add((*childIter)->Shape());
    }

    // add trimmed parent faces to result
    shellMaker.Add(_trimmedParent->Shape());
    shellMaker.Perform();

    // make a solid out of the face collection
    TopoDS_Shape shell = shellMaker.SewedShape();


    BRepSewingToBRepBuilderShapeAdapter sewerAdapter(shellMaker);

    // map names to shell
    PNamedShape resultShell(new CNamedShape(shell, "BOP_FUSE"));
    for (childIter = _trimmedChilds.begin(); childIter != _trimmedChilds.end(); ++childIter) {
        const PNamedShape child = *childIter;
        PNamedShape tmpshape(new CNamedShape(*child));
        tmpshape->SetShape(shellMaker.ModifiedSubShape(child->Shape()));
        CBooleanOperTools::MapFaceNamesAfterBOP(sewerAdapter, tmpshape, resultShell);
    }
    PNamedShape tmpshape(new CNamedShape(*_trimmedParent));
    tmpshape->SetShape(shellMaker.ModifiedSubShape(_trimmedParent->Shape()));
    CBooleanOperTools::MapFaceNamesAfterBOP(sewerAdapter, tmpshape, resultShell);

    // map names to solid
    BRepBuilderAPI_MakeSolid solidmaker;
    TopTools_IndexedMapOfShape shellMap;
    TopExp::MapShapes(resultShell->Shape(), TopAbs_SHELL, shellMap);
    for (int ishell = 1; ishell <= shellMap.Extent(); ++ishell) {
        const TopoDS_Shell& shell = TopoDS::Shell(shellMap(ishell));
        solidmaker.Add(shell);
    }

    PNamedShape result(new CNamedShape(solidmaker.Solid(), resultShell->Name()));
    CBooleanOperTools::MapFaceNamesAfterBOP(solidmaker, resultShell, result);

    _resultshape = result;
}
App::DocumentObjectExecReturn *Loft::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("Loft: Creating a face from sketch failed");

    // 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 up multisections
        auto multisections = Sections.getValues();
        if(multisections.empty())
            return new App::DocumentObjectExecReturn("Loft: At least one section is needed");
        
        std::vector<std::vector<TopoDS_Wire>> wiresections;
        for(TopoDS_Wire& wire : wires)
            wiresections.push_back(std::vector<TopoDS_Wire>(1, wire));
                
        for(App::DocumentObject* obj : multisections) {
            if(!obj->isDerivedFrom(Part::Feature::getClassTypeId()))
                return  new App::DocumentObjectExecReturn("Loft: 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(), ++i) {
                if(i>=wiresections.size())
                    return new App::DocumentObjectExecReturn("Loft: Sections need to have the same amount of inner wires as the base section");
                wiresections[i].push_back(TopoDS::Wire(ex.Current()));
            }
            if(i<wiresections.size())
                    return new App::DocumentObjectExecReturn("Loft: Sections need to have the same amount of inner wires as the base section");
            
        }
        
        //build all shells
        std::vector<TopoDS_Shape> shells;
        for(std::vector<TopoDS_Wire>& wires : wiresections) {
            
            BRepOffsetAPI_ThruSections mkTS(false, Ruled.getValue(), Precision::Confusion());

            for(TopoDS_Wire& wire : wires)   {
                 wire.Move(invObjLoc);
                 mkTS.AddWire(wire);
            }

            mkTS.Build();
            if (!mkTS.IsDone())
                return new App::DocumentObjectExecReturn("Loft could not be build");
            
            //build the shell use simulate to get the top and bottom wires in an easy way
            shells.push_back(mkTS.Shape());
        }
        
        //build the top and bottom face, sew the shell and build the final solid
        TopoDS_Shape front = getVerifiedFace();
        front.Move(invObjLoc);
        std::vector<TopoDS_Wire> backwires;
        for(std::vector<TopoDS_Wire>& wires : wiresections)
            backwires.push_back(wires.back());
        
        TopoDS_Shape back = Part::FaceMakerCheese::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("Loft: 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();
        }

        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("Loft: Adding the loft 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("Loft: 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("Loft: Subtracting the loft 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("Loft: Resulting shape is not a solid");
            
            boolOp = refineShapeIfActive(boolOp);
            Shape.setValue(getSolid(boolOp));
        }
        
        return App::DocumentObject::StdReturn;
    }
    catch (Standard_Failure) {
        Handle_Standard_Failure e = Standard_Failure::Caught();
        return new App::DocumentObjectExecReturn(e->GetMessageString());
    }
    catch (...) {
        return new App::DocumentObjectExecReturn("Loft: A fatal error occurred when making the loft");
    }
}
void Part::BRepBuilderAPI_RefineModel::Build()
{
    if (myShape.IsNull())
        Standard_Failure::Raise("Cannot remove splitter from empty shape");

    if (myShape.ShapeType() == TopAbs_SOLID) {
        const TopoDS_Solid &solid = TopoDS::Solid(myShape);
        BRepBuilderAPI_MakeSolid mkSolid;
        TopExp_Explorer it;
        for (it.Init(solid, TopAbs_SHELL); it.More(); it.Next()) {
            const TopoDS_Shell &currentShell = TopoDS::Shell(it.Current());
            ModelRefine::FaceUniter uniter(currentShell);
            if (uniter.process()) {
                if (uniter.isModified()) {
                    const TopoDS_Shell &newShell = uniter.getShell();
                    mkSolid.Add(newShell);
                    LogModifications(uniter);
                }
                else {
                    mkSolid.Add(currentShell);
                }
            }
            else {
                Standard_Failure::Raise("Removing splitter failed");
            }
        }
        myShape = mkSolid.Solid();
    }
    else if (myShape.ShapeType() == TopAbs_SHELL) {
        const TopoDS_Shell& shell = TopoDS::Shell(myShape);
        ModelRefine::FaceUniter uniter(shell);
        if (uniter.process()) {
            // TODO: Why not check for uniter.isModified()?
            myShape = uniter.getShell();
            LogModifications(uniter);
        }
        else {
            Standard_Failure::Raise("Removing splitter failed");
        }
    }
    else if (myShape.ShapeType() == TopAbs_COMPOUND) {
        BRep_Builder builder;
        TopoDS_Compound comp;
        builder.MakeCompound(comp);

        TopExp_Explorer xp;
        // solids
        for (xp.Init(myShape, TopAbs_SOLID); xp.More(); xp.Next()) {
            const TopoDS_Solid &solid = TopoDS::Solid(xp.Current());
            BRepTools_ReShape reshape;
            TopExp_Explorer it;
            for (it.Init(solid, TopAbs_SHELL); it.More(); it.Next()) {
                const TopoDS_Shell &currentShell = TopoDS::Shell(it.Current());
                ModelRefine::FaceUniter uniter(currentShell);
                if (uniter.process()) {
                    if (uniter.isModified()) {
                        const TopoDS_Shell &newShell = uniter.getShell();
                        reshape.Replace(currentShell, newShell);
                        LogModifications(uniter);
                    }
                }
            }
            builder.Add(comp, reshape.Apply(solid));
        }
        // free shells
        for (xp.Init(myShape, TopAbs_SHELL, TopAbs_SOLID); xp.More(); xp.Next()) {
            const TopoDS_Shell& shell = TopoDS::Shell(xp.Current());
            ModelRefine::FaceUniter uniter(shell);
            if (uniter.process()) {
                builder.Add(comp, uniter.getShell());
                LogModifications(uniter);
            }
        }
        // the rest
        for (xp.Init(myShape, TopAbs_FACE, TopAbs_SHELL); xp.More(); xp.Next()) {
            if (!xp.Current().IsNull())
                builder.Add(comp, xp.Current());
        }
        for (xp.Init(myShape, TopAbs_WIRE, TopAbs_FACE); xp.More(); xp.Next()) {
            if (!xp.Current().IsNull())
                builder.Add(comp, xp.Current());
        }
        for (xp.Init(myShape, TopAbs_EDGE, TopAbs_WIRE); xp.More(); xp.Next()) {
            if (!xp.Current().IsNull())
                builder.Add(comp, xp.Current());
        }
        for (xp.Init(myShape, TopAbs_VERTEX, TopAbs_EDGE); xp.More(); xp.Next()) {
            if (!xp.Current().IsNull())
                builder.Add(comp, xp.Current());
        }

        myShape = comp;
    }

    Done();
}
示例#7
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");
    }
}