allow wires as surface input

Now an arbitrary mixture of edges and wires can be used as input.
However, the total count of edges together with the wire members
can only be 2, 3 or 4.

For some reason, wires do not work in Python script:
test1.BoundaryList = [(Draft.upgrade([bs1a, bs2a]), 'Wire1')]
yields an empty BoundaryList
This commit is contained in:
balazs-bamer
2015-02-07 18:58:25 +01:00
committed by wmayer
parent 4e2eede777
commit ef27ba2c8a
5 changed files with 114 additions and 68 deletions

View File

@@ -107,10 +107,9 @@ App::DocumentObjectExecReturn *BSplineSurf::execute(void)
GeomFill_FillingStyle fstyle = getFillingStyle();
GeomFill_BSplineCurves aSurfBuilder; //Create Surface Builder
int ncrv = BoundaryList.getSize();
if(ncrv==2) {aSurfBuilder.Init(crvs[0], crvs[1], fstyle);}
else if(ncrv==3) {aSurfBuilder.Init(crvs[0], crvs[1], crvs[2], fstyle);}
else if(ncrv==4) {aSurfBuilder.Init(crvs[0], crvs[1], crvs[2], crvs[3], fstyle);}
if(edgeCount==2) {aSurfBuilder.Init(crvs[0], crvs[1], fstyle);}
else if(edgeCount==3) {aSurfBuilder.Init(crvs[0], crvs[1], crvs[2], fstyle);}
else if(edgeCount==4) {aSurfBuilder.Init(crvs[0], crvs[1], crvs[2], crvs[3], fstyle);}
createFace(aSurfBuilder.Surface());

View File

@@ -33,6 +33,7 @@
#include <GeomFill_BezierCurves.hxx>
#include <Geom_BoundedSurface.hxx>
#include <BRepBuilderAPI_MakeFace.hxx>
#include <TopExp_Explorer.hxx>
#endif
#include <Base/Exception.h>
@@ -82,43 +83,57 @@ void BSurf::getWire(TopoDS_Wire& aWire)
Handle(ShapeExtend_WireData) aWD = new ShapeExtend_WireData;
int boundaryListSize = BoundaryList.getSize();
if(boundaryListSize > 4 || boundaryListSize < 2)
if(boundaryListSize > 4) // if too many not even try
{
Standard_Failure::Raise("Only 2-4 curves are allowed");
return;
}
BRepBuilderAPI_Copy copier;
edgeCount = 0;
for(int i = 0; i < boundaryListSize; i++)
{
Part::TopoShape ts; //Curve TopoShape
TopoDS_Shape sub; //Curve TopoDS_Shape
TopoDS_Edge etmp; //Curve TopoDS_Edge
//Get Edge
App::PropertyLinkSubList::SubSet set = BoundaryList[i];
if(set.obj->getTypeId().isDerivedFrom(Part::Feature::getClassTypeId())) {
ts = static_cast<Part::Feature*>(set.obj)->Shape.getShape();
//we want only the subshape which is linked
sub = ts.getSubShape(set.sub);
// make a copy of the shape and the underlying geometry to avoid to affect the input shapes
BRepBuilderAPI_Copy copy(sub);
sub = copy.Shape();
if(sub.ShapeType() == TopAbs_EDGE) { //Check Shape type and assign edge
etmp = TopoDS::Edge(sub);
const Part::TopoShape &ts = static_cast<Part::Feature*>(set.obj)->Shape.getShape();
if(ts._Shape.ShapeType() == TopAbs_WIRE)
{
const TopoDS_Wire &wire = TopoDS::Wire(ts._Shape);
// resolve the wire, we need edges from now on
for (TopExp_Explorer wireExplorer (wire, TopAbs_EDGE); wireExplorer.More(); wireExplorer.Next())
{
// make a copy of the shape and the underlying geometry to avoid to affect the input shapes
copier.Perform(wireExplorer.Current());
aWD->Add(TopoDS::Edge(copier.Shape()));
edgeCount++;
}
}
else {
Standard_Failure::Raise("Curves must be type TopoDS_Edge");
return; //Raise exception
}
aWD->Add(etmp);
else
{
//we want only the subshape which is linked
const TopoDS_Shape &sub = ts.getSubShape(set.sub);
// make a copy of the shape and the underlying geometry to avoid to affect the input shapes
copier.Perform(sub);
const TopoDS_Shape &copy = copier.Shape();
if(copy.ShapeType() == TopAbs_EDGE) { //Check Shape type and assign edge
aWD->Add(TopoDS::Edge(copy));
edgeCount++;
}
else {
Standard_Failure::Raise("Curves must be of type TopoDS_Edge or TopoDS_Wire");
return; //Raise exception
}
}
}
else{Standard_Failure::Raise("Curve not from Part::Feature");return;}
}
if(edgeCount < 2 || edgeCount > 4)
{
Standard_Failure::Raise("Only 2-4 curves are allowed");
return;
}
//Reorder the curves and fix the wire if required

View File

@@ -61,6 +61,9 @@ protected:
// corrects the initially invalid fill type
void correcteInvalidFillType();
// number of edges is a result of calculating single and wire edges
int edgeCount;
private:
static const char* FillTypeEnums[];
};

View File

@@ -89,10 +89,9 @@ App::DocumentObjectExecReturn *BezSurf::execute(void)
GeomFill_FillingStyle fstyle = getFillingStyle();
GeomFill_BezierCurves aSurfBuilder; //Create Surface Builder
int ncrv = BoundaryList.getSize();
if(ncrv==2) {aSurfBuilder.Init(crvs[0], crvs[1], fstyle);}
else if(ncrv==3) {aSurfBuilder.Init(crvs[0], crvs[1], crvs[2], fstyle);}
else if(ncrv==4) {aSurfBuilder.Init(crvs[0], crvs[1], crvs[2], crvs[3], fstyle);}
if(edgeCount==2) {aSurfBuilder.Init(crvs[0], crvs[1], fstyle);}
else if(edgeCount==3) {aSurfBuilder.Init(crvs[0], crvs[1], crvs[2], fstyle);}
else if(edgeCount==4) {aSurfBuilder.Init(crvs[0], crvs[1], crvs[2], crvs[3], fstyle);}
createFace(aSurfBuilder.Surface());

View File

@@ -160,6 +160,8 @@ public:
protected:
bool willBezier;
bool willBSpline;
int edgeCount;
bool isEdge(const TopoDS_Shape& shape);
virtual bool isActive(void);
void createSurface(const char *surfaceNamePrefix, const char *commandName, const char *pythonAddCommand);
virtual void activated(int iMsg);
@@ -176,13 +178,51 @@ CmdSurfaceBSurf::CmdSurfaceBSurf() : Command("Surface_BSurf")
sPixmap = "BSplineSurf";
}
bool CmdSurfaceBSurf::isEdge(const TopoDS_Shape& shape)
{
if (shape.IsNull() || shape.ShapeType() != TopAbs_EDGE)
{
return false;
}
TopoDS_Edge etmp = TopoDS::Edge(shape); //Curve TopoDS_Edge
TopLoc_Location heloc; // this will be output
Standard_Real u0;// contains output
Standard_Real u1;// contains output
Handle_Geom_Curve c_geom = BRep_Tool::Curve(etmp,heloc,u0,u1); //The geometric curve
Handle_Geom_BezierCurve bez_geom = Handle_Geom_BezierCurve::DownCast(c_geom); //Try to get Bezier curve
if (bez_geom.IsNull())
{
// this one is not Bezier, we hope it can be converted into b-spline
if(willBezier) {
// already found the other type, fail
return false;
}
// we will create b-spline surface
willBSpline = true;
}
else
{
// this one is Bezier
if(willBSpline) {
// already found the other type, fail
return false;
}
// we will create Bezier surface
willBezier = true;
}
edgeCount++;
return true;
}
bool CmdSurfaceBSurf::isActive(void)
{
willBezier = willBSpline = false;
std::vector<Gui::SelectionSingleton::SelObj> Sel = getSelection().getSelection();
if (Sel.size() < 2 || Sel.size() > 4) {
if (Sel.size() > 4) {
return false;
}
// we need to count them inside wires, too
edgeCount = 0;
for (std::vector<Gui::SelectionSingleton::SelObj>::iterator it = Sel.begin(); it != Sel.end(); ++it)
{
if(!((*it).pObject->getTypeId().isDerivedFrom(Part::Feature::getClassTypeId()))) {
@@ -191,67 +231,57 @@ bool CmdSurfaceBSurf::isActive(void)
Part::TopoShape ts = static_cast<Part::Feature*>((*it).pObject)->Shape.getShape();
try {
// make sure the main shape type is edge or wire
TopAbs_ShapeEnum shapeType = ts._Shape.ShapeType();
if(shapeType != TopAbs_WIRE && shapeType != TopAbs_EDGE)
if(ts._Shape.ShapeType() == TopAbs_WIRE)
{
return false;
}
TopoDS_Shape shape = ts.getSubShape("Edge1");
if (shape.IsNull())
{
return false;
}
if(shape.ShapeType() != TopAbs_EDGE) { //Check Shape type and assign edge
return false;
}
TopoDS_Edge etmp = TopoDS::Edge(shape); //Curve TopoDS_Edge
TopLoc_Location heloc; // this will be output
Standard_Real u0;// contains output
Standard_Real u1;// contains output
Handle_Geom_Curve c_geom = BRep_Tool::Curve(etmp,heloc,u0,u1); //The geometric curve
Handle_Geom_BezierCurve bez_geom = Handle_Geom_BezierCurve::DownCast(c_geom); //Try to get Bezier curve
if (bez_geom.IsNull())
{
// this one is not Bezier, we hope it can be converted into b-spline
if(willBezier) {
// already found the other type, fail
return false;
TopoDS_Wire wire = TopoDS::Wire(ts._Shape);
for (TopExp_Explorer wireExplorer (wire, TopAbs_EDGE); wireExplorer.More(); wireExplorer.Next())
{
if(!isEdge(wireExplorer.Current()))
{
return false;
}
}
// we will create b-spline surface
willBSpline = true;
}
else
{
// this one is Bezier
if(willBSpline) {
// already found the other type, fail
TopoDS_Shape shape = ts.getSubShape("Edge1");
if(!isEdge(shape))
{
return false;
}
// we will create Bezier surface
willBezier = true;
}
}
catch(Standard_Failure) { // any OCC exception means an unappropriate shape in the selection
return false;
}
}
return true;
return edgeCount >= 2 && edgeCount <= 4;
}
void CmdSurfaceBSurf::createSurface(const char *surfaceNamePrefix, const char *commandName, const char *pythonAddCommand)
{
// we take the whole selection and require that all of its members are of the required curve
std::vector<Gui::SelectionObject> sel = getSelection().getSelectionEx(0);
if (sel.size() == 2) {
if (edgeCount == 2) {
QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Warning"),
QObject::tr("Surfaces with two edges may fail for some fill types."));
}
std::string FeatName = getUniqueObjectName(surfaceNamePrefix);
std::stringstream bspListCmd;
std::vector<Gui::SelectionSingleton::SelObj> Sel = getSelection().getSelection();
bspListCmd << "FreeCAD.ActiveDocument.ActiveObject.BoundaryList = [";
for (std::vector<Gui::SelectionObject>::iterator it = sel.begin(); it != sel.end(); ++it) {
bspListCmd << "(App.activeDocument()." << it->getFeatName() << ", \'Edge1\'),";
for (std::vector<Gui::SelectionSingleton::SelObj>::iterator it = Sel.begin(); it != Sel.end(); ++it)
{
Part::TopoShape ts = static_cast<Part::Feature*>((*it).pObject)->Shape.getShape();
bspListCmd << "(App.activeDocument()." << it->FeatName;
// if it is wire, add as wire
if(ts._Shape.ShapeType() == TopAbs_WIRE)
{
bspListCmd << ", \'Wire1\'),";
}
else
{
bspListCmd << ", \'Edge1\'),";
}
}
bspListCmd << "]";