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:
@@ -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 © = 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;}
|
||||
}
|
||||
|
||||
@@ -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[];
|
||||
};
|
||||
|
||||
@@ -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\")");
|
||||
|
||||
Reference in New Issue
Block a user