add feature loft

This commit is contained in:
Stefan Tröger 2015-06-03 07:47:05 +02:00
parent f4a5bf6acd
commit c82e4117e9
5 changed files with 320 additions and 6 deletions

View File

@ -55,6 +55,7 @@
#include "DatumCS.h"
#include "FeatureThickness.h"
#include "FeaturePipe.h"
#include "FeatureLoft.h"
namespace PartDesign {
extern PyObject* initModule();
@ -105,6 +106,9 @@ PyMODINIT_FUNC init_PartDesign()
PartDesign::Pipe ::init();
PartDesign::AdditivePipe ::init();
PartDesign::SubtractivePipe ::init();
PartDesign::Loft ::init();
PartDesign::AdditiveLoft ::init();
PartDesign::SubtractiveLoft ::init();
PartDesign::Plane ::init();
PartDesign::Line ::init();
PartDesign::Point ::init();

View File

@ -102,6 +102,8 @@ SET(FeaturesSketchBased_SRCS
FeaturePrimitive.cpp
FeaturePipe.h
FeaturePipe.cpp
FeatureLoft.h
FeatureLoft.cpp
)
SOURCE_GROUP("SketchBasedFeatures" FILES ${FeaturesSketchBased_SRCS})

View File

@ -0,0 +1,234 @@
/***************************************************************************
* Copyright (c) 2015 Stefan Tröger <stefantroeger@gmx.net> *
* *
* This file is part of the FreeCAD CAx development system. *
* *
* This library is free software; you can redistribute it and/or *
* modify it under the terms of the GNU Library General Public *
* License as published by the Free Software Foundation; either *
* version 2 of the License, or (at your option) any later version. *
* *
* This library is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU Library General Public License for more details. *
* *
* You should have received a copy of the GNU Library General Public *
* License along with this library; see the file COPYING.LIB. If not, *
* write to the Free Software Foundation, Inc., 59 Temple Place, *
* Suite 330, Boston, MA 02111-1307, USA *
* *
***************************************************************************/
#include "PreCompiled.h"
#ifndef _PreComp_
# include <TopoDS_Solid.hxx>
# include <TopoDS_Wire.hxx>
# include <TopExp_Explorer.hxx>
# include <BRepAlgoAPI_Fuse.hxx>
# include <BRepAlgoAPI_Common.hxx>
#include <BRepOffsetAPI_ThruSections.hxx>
#include <BRepBuilderAPI_Sewing.hxx>
#include <BRepBuilderAPI_MakeSolid.hxx>
#include <BRepClass3d_SolidClassifier.hxx>
#include <BRepAlgoAPI_Cut.hxx>
#include <TopoDS.hxx>
#include <Precision.hxx>
#endif
#include <Base/Exception.h>
#include <Base/Placement.h>
#include <Base/Console.h>
#include <Base/Reader.h>
#include <App/Document.h>
//#include "Body.h"
#include "FeatureLoft.h"
using namespace PartDesign;
PROPERTY_SOURCE(PartDesign::Loft, PartDesign::SketchBased)
Loft::Loft()
{
ADD_PROPERTY_TYPE(Sections,(0),"Loft",App::Prop_None,"List of sections");
Sections.setSize(0);
ADD_PROPERTY_TYPE(Ruled,(false),"Loft",App::Prop_None,"Create ruled surface");
ADD_PROPERTY_TYPE(Closed,(false),"Loft",App::Prop_None,"Close Last to First Profile");
}
short Loft::mustExecute() const
{
if (Sections.isTouched())
return 1;
if (Ruled.isTouched())
return 1;
if (Closed.isTouched())
return 1;
return SketchBased::mustExecute();
}
App::DocumentObjectExecReturn *Loft::execute(void)
{
Part::Part2DObject* sketch = 0;
std::vector<TopoDS_Wire> wires;
try {
sketch = getVerifiedSketch();
wires = getSketchWires();
} catch (const Base::Exception& e) {
return new App::DocumentObjectExecReturn(e.what());
}
TopoDS_Shape sketchshape = makeFace(wires);
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->positionBySketch();
TopLoc_Location invObjLoc = this->getLocation().Inverted();
if(!base.IsNull())
base.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));
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;
int 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("Sections need to have the same amount of inner wires as the base section");
++i;
}
if(i<wiresections.size())
return new App::DocumentObjectExecReturn("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)
mkTS.AddWire(wire);
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 = makeFace(wires);
std::vector<TopoDS_Wire> backwires;
for(std::vector<TopoDS_Wire>& wires : wiresections)
backwires.push_back(wires.back());
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 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("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 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("Resulting shape is not a solid");
boolOp = refineShapeIfActive(boolOp);
Shape.setValue(boolOp);
}
return App::DocumentObject::StdReturn;
return SketchBased::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 loft");
}
}
PROPERTY_SOURCE(PartDesign::AdditiveLoft, PartDesign::Loft)
AdditiveLoft::AdditiveLoft() {
addSubType = Additive;
}
PROPERTY_SOURCE(PartDesign::SubtractiveLoft, PartDesign::Loft)
SubtractiveLoft::SubtractiveLoft() {
addSubType = Subtractive;
}

View File

@ -0,0 +1,79 @@
/***************************************************************************
* Copyright (c) 2015 Stefan Tröger <stefantroeger@gmx.net> *
* *
* This file is part of the FreeCAD CAx development system. *
* *
* This library is free software; you can redistribute it and/or *
* modify it under the terms of the GNU Library General Public *
* License as published by the Free Software Foundation; either *
* version 2 of the License, or (at your option) any later version. *
* *
* This library is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU Library General Public License for more details. *
* *
* You should have received a copy of the GNU Library General Public *
* License along with this library; see the file COPYING.LIB. If not, *
* write to the Free Software Foundation, Inc., 59 Temple Place, *
* Suite 330, Boston, MA 02111-1307, USA *
* *
***************************************************************************/
#ifndef PARTDESIGN_Loft_H
#define PARTDESIGN_Loft_H
#include <App/PropertyUnits.h>
#include <App/PropertyStandard.h>
#include <App/PropertyUnits.h>
#include "FeatureSketchBased.h"
namespace PartDesign
{
class PartDesignExport Loft : public SketchBased
{
PROPERTY_HEADER(PartDesign::Loft);
public:
Loft();
App::PropertyLinkList Sections;
App::PropertyBool Ruled;
App::PropertyBool Closed;
/** @name methods override feature */
//@{
App::DocumentObjectExecReturn *execute(void);
short mustExecute() const;
/// returns the type name of the view provider
const char* getViewProviderName(void) const {
return "PartDesignGui::ViewProviderLoft";
}
//@}
private:
//static const char* TypeEnums[];
//static const char* SideEnums[];
};
class PartDesignExport AdditiveLoft : public Loft {
PROPERTY_HEADER(PartDesign::AdditiveLoft);
public:
AdditiveLoft();
};
class PartDesignExport SubtractiveLoft : public Loft {
PROPERTY_HEADER(PartDesign::SubtractiveLoft);
public:
SubtractiveLoft();
};
} //namespace PartDesign
#endif // PART_Loft_H

View File

@ -278,12 +278,7 @@ App::DocumentObjectExecReturn *Pipe::execute(void)
}
if(getAddSubType() == FeatureAddSub::Additive) {
auto* b = getDocument()->addObject("Part::Feature", "base");
static_cast<Part::Feature*>(b)->Shape.setValue(base);
b = getDocument()->addObject("Part::Feature", "pipe");
static_cast<Part::Feature*>(b)->Shape.setValue(result);
BRepAlgoAPI_Fuse mkFuse(base, result);
if (!mkFuse.IsDone())
return new App::DocumentObjectExecReturn("Adding the pipe failed");