Curve validation is done in a common ancestor of App and GUI

Curve validation is done in a common ancestor class of Surface::BSurf
and SurfaceGui::CmdSurfaceBSurf
This commit is contained in:
balazs-bamer
2015-02-16 16:08:27 +01:00
committed by wmayer
parent e47e22e395
commit dd6775e0f2
3 changed files with 159 additions and 114 deletions

View File

@@ -34,6 +34,7 @@
#include <Geom_BoundedSurface.hxx>
#include <BRepBuilderAPI_MakeFace.hxx>
#include <TopExp_Explorer.hxx>
#include <BRep_Tool.hxx>
#endif
#include <Base/Exception.h>
@@ -43,6 +44,99 @@
using namespace Surface;
void ShapeValidator::initValidator(void)
{
willBezier = willBSpline = false;
edgeCount = 0;
}
// shows error message if the shape is not an edge
bool ShapeValidator::checkEdge(const TopoDS_Shape& shape)
{
if (shape.IsNull() || shape.ShapeType() != TopAbs_EDGE)
{
Standard_Failure::Raise("Shape is not an 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
Standard_Failure::Raise("Mixing Bezier and non-Bezier curves is not allowed.");
return false;
}
// we will create b-spline surface
willBSpline = true;
}
else
{
// this one is Bezier
if(willBSpline) {
// already found the other type, fail
Standard_Failure::Raise("Mixing Bezier and non-Bezier curves is not allowed.");
return false;
}
// we will create Bezier surface
willBezier = true;
}
edgeCount++;
return true;
}
void ShapeValidator::checkAndAdd(const TopoDS_Shape &shape, Handle(ShapeExtend_WireData) *aWD)
{
if(!checkEdge(shape))
{
return;
}
if(aWD != NULL)
{
BRepBuilderAPI_Copy copier(shape);
// make a copy of the shape and the underlying geometry to avoid to affect the input shapes
(*aWD)->Add(TopoDS::Edge(copier.Shape()));
}
}
void ShapeValidator::checkAndAdd(const Part::TopoShape &ts, const char *subName, Handle(ShapeExtend_WireData) *aWD)
{
try {
// unwrap the wire
if((!ts._Shape.IsNull()) && ts._Shape.ShapeType() == TopAbs_WIRE)
{
TopoDS_Wire wire = TopoDS::Wire(ts._Shape);
for (TopExp_Explorer wireExplorer (wire, TopAbs_EDGE); wireExplorer.More(); wireExplorer.Next())
{
checkAndAdd(wireExplorer.Current(), aWD);
}
}
else
{
if(subName != NULL && *subName != 0)
{
//we want only the subshape which is linked
checkAndAdd(ts.getSubShape(subName), aWD);
}
else
{
checkAndAdd(ts._Shape, aWD);
}
}
}
catch(Standard_Failure) { // any OCC exception means an unappropriate shape in the selection
Standard_Failure::Raise("Wrong shape type.");
return;
}
}
PROPERTY_SOURCE(Surface::BSurf, Part::Feature)
const char* BSurf::FillTypeEnums[] = {"Invalid", "Sretched", "Coons", "Curved", NULL};
@@ -90,8 +184,7 @@ void BSurf::getWire(TopoDS_Wire& aWire)
return;
}
BRepBuilderAPI_Copy copier;
edgeCount = 0;
initValidator();
for(int i = 0; i < boundaryListSize; i++)
{
App::PropertyLinkSubList::SubSet set = BoundaryList[i];
@@ -99,35 +192,7 @@ void BSurf::getWire(TopoDS_Wire& aWire)
if(set.obj->getTypeId().isDerivedFrom(Part::Feature::getClassTypeId())) {
const Part::TopoShape &ts = static_cast<Part::Feature*>(set.obj)->Shape.getShape();
if((!ts._Shape.IsNull()) && 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
{
//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.IsNull()) && 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
}
}
checkAndAdd(ts, set.sub, &aWD);
}
else{Standard_Failure::Raise("Curve not from Part::Feature");return;}
}

View File

@@ -25,6 +25,7 @@
#define FEATUREBSURF_H
#include <GeomFill_FillingStyle.hxx>
#include <ShapeExtend_WireData.hxx>
#include <App/PropertyStandard.h>
#include <App/PropertyUnits.h>
@@ -36,8 +37,21 @@ class Handle_Geom_BoundedSurface;
namespace Surface
{
class ShapeValidator
{
protected:
bool willBezier;
bool willBSpline;
int edgeCount;
void initValidator(void);
bool checkEdge(const TopoDS_Shape& shape);
void checkAndAdd(const TopoDS_Shape &shape, Handle(ShapeExtend_WireData) *aWD = NULL);
void checkAndAdd(const Part::TopoShape &ts, const char *subName, Handle(ShapeExtend_WireData) *aWire = NULL);
};
class BSurf : public Part::Feature
class BSurf : public Part::Feature, public ShapeValidator
{
PROPERTY_HEADER(Surface::BSurf);
@@ -61,9 +75,6 @@ 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

@@ -37,7 +37,6 @@
#include <Geom_BSplineCurve.hxx>
#include <TopExp_Explorer.hxx>
#include <TopoDS.hxx>
#include <BRep_Tool.hxx>
#include <Inventor/events/SoMouseButtonEvent.h>
#endif
@@ -150,7 +149,7 @@ void CmdSurfaceCut::activated(int iMsg)
// Bezier and BSpline surfaces
//===========================================================================
//DEF_STD_CMD_A(CmdSurfaceBSurf);
class CmdSurfaceBSurf : public Gui::Command
class CmdSurfaceBSurf : public Gui::Command, public Surface::ShapeValidator
{
public:
CmdSurfaceBSurf();
@@ -158,12 +157,9 @@ public:
virtual const char* className() const
{ return "CmdSurfaceBSurf"; }
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);
void showError(const char *msg);
virtual void activated(int iMsg);
};
@@ -178,93 +174,24 @@ 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() > 4) {
long size = Sel.size();
if(size < 1 || 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()))) {
return false;
}
Part::TopoShape ts = static_cast<Part::Feature*>((*it).pObject)->Shape.getShape();
try {
// make sure the main shape type is edge or wire
if((!ts._Shape.IsNull()) && ts._Shape.ShapeType() == TopAbs_WIRE)
{
TopoDS_Wire wire = TopoDS::Wire(ts._Shape);
for (TopExp_Explorer wireExplorer (wire, TopAbs_EDGE); wireExplorer.More(); wireExplorer.Next())
{
if(!isEdge(wireExplorer.Current()))
{
return false;
}
}
}
else
{
TopoDS_Shape shape = ts.getSubShape("Edge1");
if(!isEdge(shape))
{
return false;
}
}
}
catch(Standard_Failure) { // any OCC exception means an unappropriate shape in the selection
return false;
}
}
return edgeCount >= 2 && edgeCount <= 4;
return true;
}
void CmdSurfaceBSurf::createSurface(const char *surfaceNamePrefix, const char *commandName, const char *pythonAddCommand)
{
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();
@@ -294,9 +221,51 @@ void CmdSurfaceBSurf::createSurface(const char *surfaceNamePrefix, const char *c
updateActive();
}
void CmdSurfaceBSurf::showError(const char *msg)
{
QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Error"),
QObject::tr(msg));
}
void CmdSurfaceBSurf::activated(int iMsg)
{
// check wich was activated and perfom it clearing the flag
initValidator();
std::vector<Gui::SelectionSingleton::SelObj> Sel = getSelection().getSelection();
if (Sel.size() > 4) {
showError("Too many selected objects.");
return;
}
for (std::vector<Gui::SelectionSingleton::SelObj>::iterator it = Sel.begin(); it != Sel.end(); ++it)
{
Gui::SelectionSingleton::SelObj selObj = *it;
if(!(selObj.pObject->getTypeId().isDerivedFrom(Part::Feature::getClassTypeId()))) {
showError("Selected object is not a feature.");
return;
}
Part::TopoShape ts = static_cast<Part::Feature*>(selObj.pObject)->Shape.getShape();
try {
checkAndAdd(ts, selObj.SubName);
}
catch(Standard_Failure sf) {
showError(sf.GetMessageString());
return;
}
}
switch(edgeCount) {
case 2:
QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Warning"),
QObject::tr("Surfaces with two edges may fail for some fill types."));
break;
case 3: // no message
case 4:
break;
default:
showError("This tool requires 2, 3 or 4 curves.");
return;
}
// check wich was activated and perfom and clearing the flag
if(willBezier)
{
createSurface("BezierSurface", "Create Bezier surface", "FreeCAD.ActiveDocument.addObject(\"Surface::BezSurf\",\"%s\")");