Path.Area added coplanar check parameter

This commit is contained in:
Zheng, Lei 2017-01-20 02:36:59 +08:00
parent 36423f24de
commit 1517418ba0
3 changed files with 125 additions and 44 deletions

View File

@ -111,22 +111,47 @@ Area::~Area() {
} }
void Area::setPlane(const TopoDS_Shape &shape) { void Area::setPlane(const TopoDS_Shape &shape) {
if(shape.IsNull()) {
myWorkPlane.Nullify();
return;
}
BRepLib_FindSurface planeFinder(shape,-1,Standard_True);
if (!planeFinder.Found())
throw Base::ValueError("shape is not coplanar");
myWorkPlane = shape; myWorkPlane = shape;
myTrsf.SetTransformation(GeomAdaptor_Surface(
planeFinder.Surface()).Plane().Position());
clean();
} }
void Area::add(CArea &area, const TopoDS_Shape &shape, const gp_Trsf *trsf, bool Area::isCoplanar(const TopoDS_Shape &s1, const TopoDS_Shape &s2) {
double deflection, CArea *areaOpen, bool to_edges, bool reorder) TopoDS_Builder builder;
TopoDS_Compound comp;
builder.MakeCompound(comp);
builder.Add(comp,s1);
builder.Add(comp,s2);
BRepLib_FindSurface planeFinder(comp,-1,Standard_True);
return planeFinder.Found();
}
int Area::add(CArea &area, const TopoDS_Shape &shape, const gp_Trsf *trsf,
double deflection, const TopoDS_Shape *plane, bool force_coplanar,
CArea *areaOpen, bool to_edges, bool reorder)
{ {
bool haveShape = false; bool haveShape = false;
int skipped = 0;
for (TopExp_Explorer it(shape, TopAbs_FACE); it.More(); it.Next()) { for (TopExp_Explorer it(shape, TopAbs_FACE); it.More(); it.Next()) {
haveShape = true; haveShape = true;
const TopoDS_Face &face = TopoDS::Face(it.Current()); const TopoDS_Face &face = TopoDS::Face(it.Current());
if(plane && !isCoplanar(face,*plane)) {
++skipped;
if(force_coplanar) continue;
}
for (TopExp_Explorer it(face, TopAbs_WIRE); it.More(); it.Next()) for (TopExp_Explorer it(face, TopAbs_WIRE); it.More(); it.Next())
add(area,TopoDS::Wire(it.Current()),trsf,deflection); add(area,TopoDS::Wire(it.Current()),trsf,deflection);
} }
if(haveShape) return; if(haveShape) return skipped;
CArea _area; CArea _area;
CArea _areaOpen; CArea _areaOpen;
@ -134,6 +159,10 @@ void Area::add(CArea &area, const TopoDS_Shape &shape, const gp_Trsf *trsf,
for (TopExp_Explorer it(shape, TopAbs_WIRE); it.More(); it.Next()) { for (TopExp_Explorer it(shape, TopAbs_WIRE); it.More(); it.Next()) {
haveShape = true; haveShape = true;
const TopoDS_Wire &wire = TopoDS::Wire(it.Current()); const TopoDS_Wire &wire = TopoDS::Wire(it.Current());
if(plane && !isCoplanar(wire,*plane)) {
++skipped;
if(force_coplanar) continue;
}
if(BRep_Tool::IsClosed(wire)) if(BRep_Tool::IsClosed(wire))
add(_area,wire,trsf,deflection); add(_area,wire,trsf,deflection);
else if(to_edges) { else if(to_edges) {
@ -146,6 +175,10 @@ void Area::add(CArea &area, const TopoDS_Shape &shape, const gp_Trsf *trsf,
if(!haveShape) { if(!haveShape) {
for (TopExp_Explorer it(shape, TopAbs_EDGE); it.More(); it.Next()) { for (TopExp_Explorer it(shape, TopAbs_EDGE); it.More(); it.Next()) {
if(plane && !isCoplanar(it.Current(),*plane)) {
++skipped;
if(force_coplanar) continue;
}
add(_areaOpen,BRepBuilderAPI_MakeWire( add(_areaOpen,BRepBuilderAPI_MakeWire(
TopoDS::Edge(it.Current())).Wire(),trsf,deflection); TopoDS::Edge(it.Current())).Wire(),trsf,deflection);
} }
@ -158,6 +191,7 @@ void Area::add(CArea &area, const TopoDS_Shape &shape, const gp_Trsf *trsf,
areaOpen->m_curves.splice(areaOpen->m_curves.end(),_areaOpen.m_curves); areaOpen->m_curves.splice(areaOpen->m_curves.end(),_areaOpen.m_curves);
else else
area.m_curves.splice(area.m_curves.end(),_areaOpen.m_curves); area.m_curves.splice(area.m_curves.end(),_areaOpen.m_curves);
return skipped;
} }
void Area::add(CArea &area, const TopoDS_Wire& wire, void Area::add(CArea &area, const TopoDS_Wire& wire,
@ -227,16 +261,16 @@ void Area::clean(bool deleteShapes) {
myArea = NULL; myArea = NULL;
delete myAreaOpen; delete myAreaOpen;
myAreaOpen = NULL; myAreaOpen = NULL;
if(deleteShapes) if(deleteShapes){
myShapePlane.Nullify();
myShapes.clear(); myShapes.clear();
myHaveFace = false;
}
} }
void Area::add(const TopoDS_Shape &shape,short op) { void Area::add(const TopoDS_Shape &shape,short op) {
#define AREA_SRC_OP(_v) op #define AREA_SRC_OP(_v) op
PARAM_ENUM_CONVERT(AREA_SRC_OP,,PARAM_ENUM_EXCEPT,AREA_PARAMS_OPCODE); PARAM_ENUM_CONVERT(AREA_SRC_OP,,PARAM_ENUM_EXCEPT,AREA_PARAMS_OPCODE);
TopExp_Explorer it(shape, TopAbs_SHELL);
if(it.More())
throw Base::ValueError("not a 2D shape");
clean(); clean();
if(myShapes.empty()) if(myShapes.empty())
Operation = ClipperLib::ctUnion; Operation = ClipperLib::ctUnion;
@ -258,8 +292,14 @@ void Area::addToBuild(CArea &area, const TopoDS_Shape &shape) {
TopExp_Explorer it(shape, TopAbs_FACE); TopExp_Explorer it(shape, TopAbs_FACE);
myHaveFace = it.More(); myHaveFace = it.More();
} }
const TopoDS_Shape *plane;
if(myParams.Coplanar == CoplanarNone)
plane = NULL;
else
plane = myWorkPlane.IsNull()?&myShapePlane:&myWorkPlane;
CArea areaOpen; CArea areaOpen;
add(area,shape,&myTrsf,myParams.Deflection,&areaOpen, mySkippedShapes += add(area,shape,&myTrsf,myParams.Deflection,plane,
myParams.Coplanar==CoplanarForce,&areaOpen,
myParams.OpenMode==OpenModeEdges,myParams.Reorder); myParams.OpenMode==OpenModeEdges,myParams.Reorder);
if(areaOpen.m_curves.size()) { if(areaOpen.m_curves.size()) {
if(&area == myArea || myParams.OpenMode == OpenModeNone) if(&area == myArea || myParams.OpenMode == OpenModeNone)
@ -278,48 +318,75 @@ void Area::build() {
#define AREA_SRC(_v) myParams._v #define AREA_SRC(_v) myParams._v
PARAM_ENUM_CONVERT(AREA_SRC,,PARAM_ENUM_EXCEPT,AREA_PARAMS_CLIPPER_FILL); PARAM_ENUM_CONVERT(AREA_SRC,,PARAM_ENUM_EXCEPT,AREA_PARAMS_CLIPPER_FILL);
TopoDS_Builder builder; if(myWorkPlane.IsNull()) {
TopoDS_Compound comp; myShapePlane.Nullify();
builder.MakeCompound(comp); for(const Shape &s : myShapes) {
if(!myWorkPlane.IsNull()) bool haveFace = false;
builder.Add(comp,myWorkPlane); for(TopExp_Explorer it(s.shape, TopAbs_FACE); it.More(); it.Next()) {
else { haveFace = true;
for(const Shape &s : myShapes) BRepLib_FindSurface planeFinder(it.Current(),-1,Standard_True);
builder.Add(comp, s.shape); if (!planeFinder.Found())
continue;
myShapePlane = it.Current();
myTrsf.SetTransformation(GeomAdaptor_Surface(
planeFinder.Surface()).Plane().Position());
break;
}
if(!myShapePlane.IsNull()) break;
if(haveFace) continue;
for(TopExp_Explorer it(s.shape, TopAbs_WIRE); it.More(); it.Next()) {
BRepLib_FindSurface planeFinder(it.Current(),-1,Standard_True);
if (!planeFinder.Found())
continue;
myShapePlane = it.Current();
myTrsf.SetTransformation(GeomAdaptor_Surface(
planeFinder.Surface()).Plane().Position());
break;
}
if(!myShapePlane.IsNull()) break;
}
if(myShapePlane.IsNull())
throw Base::ValueError("shapes are not planar");
} }
BRepLib_FindSurface planeFinder(comp,-1,Standard_True);
if (!planeFinder.Found())
throw Base::ValueError("shapes are not coplanar");
myTrsf.SetTransformation(GeomAdaptor_Surface( try {
planeFinder.Surface()).Plane().Position()); myArea = new CArea();
myAreaOpen = new CArea();
myArea = new CArea(); CAreaConfig conf(myParams);
myAreaOpen = new CArea(); CArea areaClip;
CAreaConfig conf(myParams); mySkippedShapes = 0;
CArea areaClip; short op = ClipperLib::ctUnion;
bool pending = false;
for(const Shape &s : myShapes) {
if(op!=s.op) {
if(myParams.OpenMode!=OpenModeNone)
myArea->m_curves.splice(myArea->m_curves.end(),myAreaOpen->m_curves);
pending = false;
myArea->Clip((ClipperLib::ClipType)op,&areaClip,SubjectFill,ClipFill);
areaClip.m_curves.clear();
op=s.op;
}
addToBuild(op==ClipperLib::ctUnion?*myArea:areaClip,s.shape);
pending = true;
}
if(mySkippedShapes)
Base::Console().Warning("%s %d non coplanar shapes\n",
myParams.Coplanar==CoplanarForce?"Skipped":"Found",mySkippedShapes);
short op = ClipperLib::ctUnion; if(pending){
bool pending = false;
for(const Shape &s : myShapes) {
if(op!=s.op) {
if(myParams.OpenMode!=OpenModeNone) if(myParams.OpenMode!=OpenModeNone)
myArea->m_curves.splice(myArea->m_curves.end(),myAreaOpen->m_curves); myArea->m_curves.splice(myArea->m_curves.end(),myAreaOpen->m_curves);
pending = false;
myArea->Clip((ClipperLib::ClipType)op,&areaClip,SubjectFill,ClipFill); myArea->Clip((ClipperLib::ClipType)op,&areaClip,SubjectFill,ClipFill);
areaClip.m_curves.clear();
op=s.op;
} }
addToBuild(op==ClipperLib::ctUnion?*myArea:areaClip,s.shape); myArea->m_curves.splice(myArea->m_curves.end(),myAreaOpen->m_curves);
pending = true;
}catch(...) {
clean();
throw;
} }
if(pending){
if(myParams.OpenMode!=OpenModeNone)
myArea->m_curves.splice(myArea->m_curves.end(),myAreaOpen->m_curves);
myArea->Clip((ClipperLib::ClipType)op,&areaClip,SubjectFill,ClipFill);
}
myArea->m_curves.splice(myArea->m_curves.end(),myAreaOpen->m_curves);
} }
TopoDS_Shape Area::toShape(CArea &area, short fill) { TopoDS_Shape Area::toShape(CArea &area, short fill) {

View File

@ -109,9 +109,11 @@ protected:
CArea *myAreaOpen; CArea *myAreaOpen;
gp_Trsf myTrsf; gp_Trsf myTrsf;
AreaParams myParams; AreaParams myParams;
TopoDS_Shape myShapePlane;
TopoDS_Shape myWorkPlane; TopoDS_Shape myWorkPlane;
TopoDS_Shape myShape; TopoDS_Shape myShape;
bool myHaveFace; bool myHaveFace;
int mySkippedShapes;
/** Called internally to combine children shapes for further processing */ /** Called internally to combine children shapes for further processing */
void build(); void build();
@ -205,7 +207,7 @@ public:
* \arg \c deflection: for defecting non circular curves * \arg \c deflection: for defecting non circular curves
* */ * */
static void add(CArea &area, const TopoDS_Wire &wire, static void add(CArea &area, const TopoDS_Wire &wire,
const gp_Trsf *trsf=NULL,double deflection=0.01); const gp_Trsf *trsf=NULL, double deflection=0.01);
/** Add a OCC generic shape to CArea /** Add a OCC generic shape to CArea
* *
@ -214,13 +216,20 @@ public:
* \arg \c trsf: optional transform matrix to transform the wire shape into * \arg \c trsf: optional transform matrix to transform the wire shape into
* XY0 plane. * XY0 plane.
* \arg \c deflection: for defecting non circular curves * \arg \c deflection: for defecting non circular curves
* \arg \c plane: a shape for testing coplanar
* \arg \c force_coplaner: if true, discard non-coplanar shapes.
* \arg \c areaOpen: for collecting open curves. If not supplied, open * \arg \c areaOpen: for collecting open curves. If not supplied, open
* curves are added to \c area * curves are added to \c area
* \arg \c to_edges: separate open wires to individual edges * \arg \c to_edges: separate open wires to individual edges
* \arg \c reorder: reorder closed wires for wire only shape * \arg \c reorder: reorder closed wires for wire only shape
*
* \return Returns the number of non coplaner. Planar testing only happens
* if \c plane is supplied
* */ * */
static void add(CArea &area, const TopoDS_Shape &shape, const gp_Trsf *trsf=NULL, static int add(CArea &area, const TopoDS_Shape &shape, const gp_Trsf *trsf=NULL,
double deflection=0.01,CArea *areaOpen=NULL, bool to_edges=false, bool reorder=true); double deflection=0.01,const TopoDS_Shape *plane = NULL,
bool force_coplanar=true, CArea *areaOpen=NULL, bool to_edges=false,
bool reorder=true);
/** Convert curves in CArea into an OCC shape /** Convert curves in CArea into an OCC shape
* *
@ -231,6 +240,8 @@ public:
* */ * */
static TopoDS_Shape toShape(const CArea &area, bool fill, static TopoDS_Shape toShape(const CArea &area, bool fill,
const gp_Trsf *trsf=NULL); const gp_Trsf *trsf=NULL);
static bool isCoplanar(const TopoDS_Shape &s1, const TopoDS_Shape &s2);
}; };
} //namespace Path } //namespace Path

View File

@ -48,6 +48,9 @@
#define AREA_PARAMS_BASE \ #define AREA_PARAMS_BASE \
((enum,fill,Fill,2,"Fill the output wires to make a face. \n"\ ((enum,fill,Fill,2,"Fill the output wires to make a face. \n"\
"Auto means make a face if any of the children has a face.",(None)(Face)(Auto)))\ "Auto means make a face if any of the children has a face.",(None)(Face)(Auto)))\
((enum,coplanar,Coplanar,2,"Specifies the way to check coplanar.\n"\
"'Force' will discard non coplaner shapes, but 'Check' only gives warning.",\
(None)(Check)(Force)))\
((bool,reorder,Reorder,false,"Re-orient closed wires in wire only shapes so that inner wires become holes."))\ ((bool,reorder,Reorder,false,"Re-orient closed wires in wire only shapes so that inner wires become holes."))\
((enum,open_mode,OpenMode,0,"Specify how to handle open wires.\n"\ ((enum,open_mode,OpenMode,0,"Specify how to handle open wires.\n"\
"'None' means combin without openeration.\n"\ "'None' means combin without openeration.\n"\