Skip to content

Commit

Permalink
Path.Area added coplanar check parameter
Browse files Browse the repository at this point in the history
  • Loading branch information
realthunder committed Jan 19, 2017
1 parent 36423f2 commit 1517418
Show file tree
Hide file tree
Showing 3 changed files with 126 additions and 45 deletions.
151 changes: 109 additions & 42 deletions src/Mod/Path/App/Area.cpp
Expand Up @@ -111,29 +111,58 @@ Area::~Area() {
}

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;
myTrsf.SetTransformation(GeomAdaptor_Surface(
planeFinder.Surface()).Plane().Position());
clean();
}

void Area::add(CArea &area, const TopoDS_Shape &shape, const gp_Trsf *trsf,
double deflection, CArea *areaOpen, bool to_edges, bool reorder)
bool Area::isCoplanar(const TopoDS_Shape &s1, const TopoDS_Shape &s2) {
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;

int skipped = 0;
for (TopExp_Explorer it(shape, TopAbs_FACE); it.More(); it.Next()) {
haveShape = true;
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())
add(area,TopoDS::Wire(it.Current()),trsf,deflection);
}

if(haveShape) return;
if(haveShape) return skipped;

CArea _area;
CArea _areaOpen;

for (TopExp_Explorer it(shape, TopAbs_WIRE); it.More(); it.Next()) {
haveShape = true;
const TopoDS_Wire &wire = TopoDS::Wire(it.Current());
if(plane && !isCoplanar(wire,*plane)) {
++skipped;
if(force_coplanar) continue;
}
if(BRep_Tool::IsClosed(wire))
add(_area,wire,trsf,deflection);
else if(to_edges) {
Expand All @@ -146,6 +175,10 @@ void Area::add(CArea &area, const TopoDS_Shape &shape, const gp_Trsf *trsf,

if(!haveShape) {
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(
TopoDS::Edge(it.Current())).Wire(),trsf,deflection);
}
Expand All @@ -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);
else
area.m_curves.splice(area.m_curves.end(),_areaOpen.m_curves);
return skipped;
}

void Area::add(CArea &area, const TopoDS_Wire& wire,
Expand Down Expand Up @@ -227,16 +261,16 @@ void Area::clean(bool deleteShapes) {
myArea = NULL;
delete myAreaOpen;
myAreaOpen = NULL;
if(deleteShapes)
if(deleteShapes){
myShapePlane.Nullify();
myShapes.clear();
myHaveFace = false;
}
}

void Area::add(const TopoDS_Shape &shape,short op) {
#define AREA_SRC_OP(_v) op
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();
if(myShapes.empty())
Operation = ClipperLib::ctUnion;
Expand All @@ -258,8 +292,14 @@ void Area::addToBuild(CArea &area, const TopoDS_Shape &shape) {
TopExp_Explorer it(shape, TopAbs_FACE);
myHaveFace = it.More();
}
const TopoDS_Shape *plane;
if(myParams.Coplanar == CoplanarNone)
plane = NULL;
else
plane = myWorkPlane.IsNull()?&myShapePlane:&myWorkPlane;
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);
if(areaOpen.m_curves.size()) {
if(&area == myArea || myParams.OpenMode == OpenModeNone)
Expand All @@ -278,48 +318,75 @@ void Area::build() {
#define AREA_SRC(_v) myParams._v
PARAM_ENUM_CONVERT(AREA_SRC,,PARAM_ENUM_EXCEPT,AREA_PARAMS_CLIPPER_FILL);

TopoDS_Builder builder;
TopoDS_Compound comp;
builder.MakeCompound(comp);
if(!myWorkPlane.IsNull())
builder.Add(comp,myWorkPlane);
else {
for(const Shape &s : myShapes)
builder.Add(comp, s.shape);
}
BRepLib_FindSurface planeFinder(comp,-1,Standard_True);
if (!planeFinder.Found())
throw Base::ValueError("shapes are not coplanar");
if(myWorkPlane.IsNull()) {
myShapePlane.Nullify();
for(const Shape &s : myShapes) {
bool haveFace = false;
for(TopExp_Explorer it(s.shape, TopAbs_FACE); it.More(); it.Next()) {
haveFace = true;
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(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;
}

myTrsf.SetTransformation(GeomAdaptor_Surface(
planeFinder.Surface()).Plane().Position());
if(myShapePlane.IsNull())
throw Base::ValueError("shapes are not planar");
}

myArea = new CArea();
myAreaOpen = new CArea();
try {
myArea = new CArea();
myAreaOpen = new CArea();

CAreaConfig conf(myParams);
CArea areaClip;
CAreaConfig conf(myParams);
CArea areaClip;

mySkippedShapes = 0;
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;
bool pending = false;
for(const Shape &s : myShapes) {
if(op!=s.op) {
if(pending){
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(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);

}catch(...) {
clean();
throw;
}
myArea->m_curves.splice(myArea->m_curves.end(),myAreaOpen->m_curves);
}

TopoDS_Shape Area::toShape(CArea &area, short fill) {
Expand Down
17 changes: 14 additions & 3 deletions src/Mod/Path/App/Area.h
Expand Up @@ -109,9 +109,11 @@ class PathExport Area: public Base::BaseClass {
CArea *myAreaOpen;
gp_Trsf myTrsf;
AreaParams myParams;
TopoDS_Shape myShapePlane;
TopoDS_Shape myWorkPlane;
TopoDS_Shape myShape;
bool myHaveFace;
int mySkippedShapes;

/** Called internally to combine children shapes for further processing */
void build();
Expand Down Expand Up @@ -205,7 +207,7 @@ class PathExport Area: public Base::BaseClass {
* \arg \c deflection: for defecting non circular curves
* */
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
*
Expand All @@ -214,13 +216,20 @@ class PathExport Area: public Base::BaseClass {
* \arg \c trsf: optional transform matrix to transform the wire shape into
* XY0 plane.
* \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
* curves are added to \c area
* \arg \c to_edges: separate open wires to individual edges
* \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,
double deflection=0.01,CArea *areaOpen=NULL, bool to_edges=false, bool reorder=true);
static int add(CArea &area, const TopoDS_Shape &shape, const gp_Trsf *trsf=NULL,
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
*
Expand All @@ -231,6 +240,8 @@ class PathExport Area: public Base::BaseClass {
* */
static TopoDS_Shape toShape(const CArea &area, bool fill,
const gp_Trsf *trsf=NULL);

static bool isCoplanar(const TopoDS_Shape &s1, const TopoDS_Shape &s2);
};

} //namespace Path
Expand Down
3 changes: 3 additions & 0 deletions src/Mod/Path/App/AreaParams.h
Expand Up @@ -48,6 +48,9 @@
#define AREA_PARAMS_BASE \
((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)))\
((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."))\
((enum,open_mode,OpenMode,0,"Specify how to handle open wires.\n"\
"'None' means combin without openeration.\n"\
Expand Down

0 comments on commit 1517418

Please sign in to comment.