Path.Area: added support for solid
* Path.Area/FeatureArea can now section solid shapes. * Added command to select workplane for FeatureArea * Generalized ParamsHelper
This commit is contained in:
parent
eb0f89f477
commit
c0ba9700aa
|
@ -51,6 +51,10 @@
|
|||
#include <gp_GTrsf.hxx>
|
||||
#include <Standard_Version.hxx>
|
||||
#include <GCPnts_UniformDeflection.hxx>
|
||||
#include <BRepBndLib.hxx>
|
||||
#include <BRepLib_MakeFace.hxx>
|
||||
#include <Bnd_Box.hxx>
|
||||
#include <BRepAlgoAPI_Section.hxx>
|
||||
|
||||
#include <Base/Exception.h>
|
||||
#include <Base/Tools.h>
|
||||
|
@ -64,11 +68,11 @@
|
|||
using namespace Path;
|
||||
|
||||
CAreaParams::CAreaParams()
|
||||
:PARAM_INIT(NAME,AREA_PARAMS_CAREA)
|
||||
:PARAM_INIT(PARAM_FNAME,AREA_PARAMS_CAREA)
|
||||
{}
|
||||
|
||||
AreaParams::AreaParams()
|
||||
:PARAM_INIT(NAME,AREA_PARAMS_BASE)
|
||||
:PARAM_INIT(PARAM_FNAME,AREA_PARAMS_AREA)
|
||||
{}
|
||||
|
||||
CAreaConfig::CAreaConfig(const CAreaParams &p, bool noFitArcs)
|
||||
|
@ -98,9 +102,9 @@ CAreaConfig::~CAreaConfig() {
|
|||
TYPESYSTEM_SOURCE(Path::Area, Base::BaseClass);
|
||||
|
||||
Area::Area(const AreaParams *params)
|
||||
:myArea(NULL)
|
||||
,myAreaOpen(NULL)
|
||||
,myHaveFace(false)
|
||||
:myHaveFace(false)
|
||||
,myHaveSolid(false)
|
||||
,myShapeDone(false)
|
||||
{
|
||||
if(params)
|
||||
setParams(*params);
|
||||
|
@ -256,35 +260,51 @@ void Area::add(CArea &area, const TopoDS_Wire& wire,
|
|||
|
||||
|
||||
void Area::clean(bool deleteShapes) {
|
||||
myShapeDone = false;
|
||||
mySections.clear();
|
||||
myShape.Nullify();
|
||||
delete myArea;
|
||||
myArea = NULL;
|
||||
delete myAreaOpen;
|
||||
myAreaOpen = NULL;
|
||||
myArea.reset();
|
||||
myAreaOpen.reset();
|
||||
if(deleteShapes){
|
||||
myShapePlane.Nullify();
|
||||
myShapes.clear();
|
||||
myHaveFace = false;
|
||||
myHaveSolid = 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);
|
||||
#define AREA_SRC_OP(_param) op
|
||||
PARAM_ENUM_CONVERT(AREA_SRC_OP,PARAM_FNAME,PARAM_ENUM_EXCEPT,AREA_PARAMS_OPCODE);
|
||||
Q_UNUSED(Operation);
|
||||
|
||||
bool haveSolid = false;
|
||||
for(TopExp_Explorer it(shape, TopAbs_SOLID);it.More();) {
|
||||
haveSolid = true;
|
||||
break;
|
||||
}
|
||||
//TODO: shall we support Shells?
|
||||
if((!haveSolid && myHaveSolid) ||
|
||||
(haveSolid && !myHaveSolid && !myShapes.empty()))
|
||||
throw Base::ValueError("mixing solid and planar shapes is not allowed");
|
||||
|
||||
myHaveSolid = haveSolid;
|
||||
|
||||
clean();
|
||||
if(myShapes.empty())
|
||||
Operation = ClipperLib::ctUnion;
|
||||
myShapes.push_back(Shape((short)Operation,shape));
|
||||
op = OperationUnion;
|
||||
myShapes.push_back(Shape(op,shape));
|
||||
}
|
||||
|
||||
|
||||
void Area::setParams(const AreaParams ¶ms) {
|
||||
#define AREA_SRC2(_v) params._v
|
||||
#define AREA_SRC2(_param) params.PARAM_FNAME(_param)
|
||||
// Validate all enum type of parameters
|
||||
PARAM_ENUM_CHECK(AREA_SRC2,PARAM_ENUM_EXCEPT,AREA_PARAMS_CONF);
|
||||
if(params!=myParams)
|
||||
if(params!=myParams) {
|
||||
clean();
|
||||
myParams = params;
|
||||
myParams = params;
|
||||
}
|
||||
}
|
||||
|
||||
void Area::addToBuild(CArea &area, const TopoDS_Shape &shape) {
|
||||
|
@ -299,24 +319,28 @@ void Area::addToBuild(CArea &area, const TopoDS_Shape &shape) {
|
|||
plane = myWorkPlane.IsNull()?&myShapePlane:&myWorkPlane;
|
||||
CArea areaOpen;
|
||||
mySkippedShapes += add(area,shape,&myTrsf,myParams.Deflection,plane,
|
||||
myParams.Coplanar==CoplanarForce,&areaOpen,
|
||||
myHaveSolid||myParams.Coplanar==CoplanarForce,&areaOpen,
|
||||
myParams.OpenMode==OpenModeEdges,myParams.Reorder);
|
||||
if(areaOpen.m_curves.size()) {
|
||||
if(&area == myArea || myParams.OpenMode == OpenModeNone)
|
||||
if(&area == myArea.get() || myParams.OpenMode == OpenModeNone)
|
||||
myAreaOpen->m_curves.splice(myAreaOpen->m_curves.end(),areaOpen.m_curves);
|
||||
else
|
||||
Base::Console().Warning("open wires discarded in clipping shapes\n");
|
||||
}
|
||||
}
|
||||
|
||||
namespace Part {
|
||||
extern PartExport std::list<TopoDS_Edge> sort_Edges(double tol3d, std::list<TopoDS_Edge>& edges);
|
||||
}
|
||||
|
||||
void Area::build() {
|
||||
if(myArea) return;
|
||||
if(myArea || mySections.size()) return;
|
||||
|
||||
if(myShapes.empty())
|
||||
throw Base::ValueError("Null shape");
|
||||
|
||||
#define AREA_SRC(_v) myParams._v
|
||||
PARAM_ENUM_CONVERT(AREA_SRC,,PARAM_ENUM_EXCEPT,AREA_PARAMS_CLIPPER_FILL);
|
||||
#define AREA_SRC(_param) myParams.PARAM_FNAME(_param)
|
||||
PARAM_ENUM_CONVERT(AREA_SRC,PARAM_FNAME,PARAM_ENUM_EXCEPT,AREA_PARAMS_CLIPPER_FILL);
|
||||
|
||||
if(myWorkPlane.IsNull()) {
|
||||
myShapePlane.Nullify();
|
||||
|
@ -350,36 +374,139 @@ void Area::build() {
|
|||
throw Base::ValueError("shapes are not planar");
|
||||
}
|
||||
|
||||
if(myHaveSolid && myParams.SectionCount) {
|
||||
|
||||
if(myParams.SectionOffset < 0)
|
||||
throw Base::ValueError("invalid section offset");
|
||||
if(myParams.SectionCount>1 && myParams.Stepdown<Precision::Confusion())
|
||||
throw Base::ValueError("invalid stepdown");
|
||||
|
||||
TopLoc_Location loc(myTrsf);
|
||||
Bnd_Box bounds;
|
||||
for(const Shape &s : myShapes)
|
||||
BRepBndLib::Add(s.shape.Moved(loc), bounds);
|
||||
|
||||
bounds.SetGap(0.0);
|
||||
Standard_Real xMin, yMin, zMin, xMax, yMax, zMax;
|
||||
bounds.Get(xMin, yMin, zMin, xMax, yMax, zMax);
|
||||
|
||||
zMax -= myParams.SectionOffset;
|
||||
if(zMax <= zMin)
|
||||
throw Base::ValueError("section offset too big");
|
||||
|
||||
int error = 0;
|
||||
int count = myParams.SectionCount;
|
||||
if(count<0 || count*myParams.Stepdown > zMax-zMin)
|
||||
count = ceil((zMax-zMin)/myParams.Stepdown);
|
||||
for(int i=0;i<count;++i,zMax-=myParams.Stepdown) {
|
||||
if(zMax < zMin) zMax = zMin;
|
||||
|
||||
// gp_Pnt p1(xMax,yMin,zMax);
|
||||
// gp_Pnt p2(xMax,yMax,zMax);
|
||||
// gp_Pnt p3(xMin,yMax,zMax);
|
||||
// gp_Pnt p4(xMin,yMin,zMax);
|
||||
// mkWire.Add(BRepBuilderAPI_MakeEdge(p1,p2).Edge());
|
||||
// mkWire.Add(BRepBuilderAPI_MakeEdge(p2,p3).Edge());
|
||||
// mkWire.Add(BRepBuilderAPI_MakeEdge(p3,p4).Edge());
|
||||
// mkWire.Add(BRepBuilderAPI_MakeEdge(p4,p1).Edge());
|
||||
gp_Pln pln(gp_Pnt(0,0,zMax),gp_Dir(0,0,1));
|
||||
BRepLib_MakeFace mkFace(pln,xMin,xMax,yMin,yMax);
|
||||
const TopoDS_Shape &face = mkFace.Face();
|
||||
|
||||
shared_ptr<Area> area(new Area(&myParams));
|
||||
area->setPlane(face);
|
||||
for(const Shape &s : myShapes) {
|
||||
BRep_Builder builder;
|
||||
TopoDS_Compound comp;
|
||||
builder.MakeCompound(comp);
|
||||
for(TopExp_Explorer it(s.shape, TopAbs_SOLID); it.More(); it.Next()) {
|
||||
BRepAlgoAPI_Section section(it.Current().Moved(loc),face);
|
||||
if(!section.IsDone()) {
|
||||
++error;
|
||||
continue;
|
||||
}
|
||||
const TopoDS_Shape &shape = section.Shape();
|
||||
if(shape.IsNull()) continue;
|
||||
|
||||
Part::FaceMakerBullseye mkFace;
|
||||
mkFace.setPlane(pln);
|
||||
|
||||
std::list<TopoDS_Edge> edges;
|
||||
for(TopExp_Explorer it(shape, TopAbs_EDGE); it.More(); it.Next())
|
||||
edges.push_back(TopoDS::Edge(it.Current()));
|
||||
bool open = false;
|
||||
std::list<TopoDS_Wire> wires;
|
||||
while(edges.size()) {
|
||||
const std::list<TopoDS_Edge> sorted =
|
||||
Part::sort_Edges(Precision::Confusion(),edges);
|
||||
BRepBuilderAPI_MakeWire mkWire;
|
||||
for(const TopoDS_Edge &e : sorted)
|
||||
mkWire.Add(e);
|
||||
const TopoDS_Wire &wire = mkWire.Wire();
|
||||
if(!BRep_Tool::IsClosed(wire))
|
||||
open = true;
|
||||
wires.push_back(wire);
|
||||
}
|
||||
if(!open) {
|
||||
for(const TopoDS_Wire &wire : wires)
|
||||
mkFace.addWire(wire);
|
||||
try {
|
||||
mkFace.Build();
|
||||
if (mkFace.Shape().IsNull())
|
||||
continue;
|
||||
builder.Add(comp,mkFace.Shape());
|
||||
continue;
|
||||
}catch (Base::Exception &e){
|
||||
Base::Console().Warning("FaceMakerBullseye failed: %s\n", e.what());
|
||||
}
|
||||
}
|
||||
//Shouldn't have any open wire, so count as error
|
||||
++error;
|
||||
for(const TopoDS_Wire &wire : wires)
|
||||
builder.Add(comp,wire);
|
||||
}
|
||||
if(comp.IsNull()) continue;
|
||||
area->add(comp,s.op);
|
||||
}
|
||||
mySections.push_back(area);
|
||||
}
|
||||
if(error)
|
||||
Base::Console().Warning("Some errors occured during operation\n");
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
myArea = new CArea();
|
||||
myAreaOpen = new CArea();
|
||||
myArea.reset(new CArea());
|
||||
myAreaOpen.reset(new CArea());
|
||||
|
||||
CAreaConfig conf(myParams);
|
||||
CArea areaClip;
|
||||
|
||||
mySkippedShapes = 0;
|
||||
short op = ClipperLib::ctUnion;
|
||||
short op = OperationUnion;
|
||||
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);
|
||||
PARAM_ENUM_CONVERT(AREA_SRC_OP,PARAM_FNAME,PARAM_ENUM_EXCEPT,AREA_PARAMS_OPCODE);
|
||||
myArea->Clip(Operation,&areaClip,SubjectFill,ClipFill);
|
||||
areaClip.m_curves.clear();
|
||||
op=s.op;
|
||||
}
|
||||
addToBuild(op==ClipperLib::ctUnion?*myArea:areaClip,s.shape);
|
||||
addToBuild(op==OperationUnion?*myArea:areaClip,s.shape);
|
||||
pending = true;
|
||||
}
|
||||
if(mySkippedShapes)
|
||||
if(mySkippedShapes && !myHaveSolid)
|
||||
Base::Console().Warning("%s %d non coplanar shapes\n",
|
||||
myParams.Coplanar==CoplanarForce?"Skipped":"Found",mySkippedShapes);
|
||||
|
||||
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);
|
||||
PARAM_ENUM_CONVERT(AREA_SRC_OP,PARAM_FNAME,PARAM_ENUM_EXCEPT,AREA_PARAMS_OPCODE);
|
||||
myArea->Clip(Operation,&areaClip,SubjectFill,ClipFill);
|
||||
}
|
||||
myArea->m_curves.splice(myArea->m_curves.end(),myAreaOpen->m_curves);
|
||||
|
||||
|
@ -403,7 +530,7 @@ TopoDS_Shape Area::toShape(CArea &area, short fill) {
|
|||
bFill = false;
|
||||
}
|
||||
if(myParams.FitArcs) {
|
||||
if(&area == myArea) {
|
||||
if(&area == myArea.get()) {
|
||||
CArea copy(area);
|
||||
copy.FitArcs();
|
||||
return toShape(copy,bFill,&trsf);
|
||||
|
@ -413,47 +540,132 @@ TopoDS_Shape Area::toShape(CArea &area, short fill) {
|
|||
return toShape(area,bFill,&trsf);
|
||||
}
|
||||
|
||||
const TopoDS_Shape &Area::getShape() {
|
||||
if(myShape.IsNull()) {
|
||||
build();
|
||||
CAreaConfig conf(myParams);
|
||||
myShape = toShape(*myArea,myParams.Fill);
|
||||
}
|
||||
return myShape;
|
||||
}
|
||||
#define AREA_SECTION(_op,_index,...) do {\
|
||||
if(mySections.size()) {\
|
||||
if(_index>=(int)mySections.size())\
|
||||
throw Base::ValueError("index out of bound");\
|
||||
TopLoc_Location loc(myTrsf.Inverted());\
|
||||
if(_index<0) {\
|
||||
BRep_Builder builder;\
|
||||
TopoDS_Compound compound;\
|
||||
builder.MakeCompound(compound);\
|
||||
for(shared_ptr<Area> area : mySections)\
|
||||
builder.Add(compound,area->_op(-1, ## __VA_ARGS__).Moved(loc));\
|
||||
return compound;\
|
||||
}\
|
||||
return mySections[_index]->_op(-1, ## __VA_ARGS__).Moved(loc);\
|
||||
}\
|
||||
}while(0)
|
||||
|
||||
TopoDS_Shape Area::getShape(int index) {
|
||||
build();
|
||||
AREA_SECTION(getShape,index);
|
||||
|
||||
if(myShapeDone) return myShape;
|
||||
|
||||
CAreaConfig conf(myParams);
|
||||
|
||||
#define AREA_MY(_param) myParams.PARAM_FNAME(_param)
|
||||
|
||||
// if no offset or thicken, try pocket
|
||||
if(fabs(myParams.Offset) < Precision::Confusion() && !myParams.Thicken) {
|
||||
if(myParams.PocketMode == PocketModeNone) {
|
||||
myShape = toShape(*myArea,myParams.Fill);
|
||||
myShapeDone = true;
|
||||
return myShape;
|
||||
}
|
||||
myShape = makePocket(-1,PARAM_FIELDS(AREA_MY,AREA_PARAMS_POCKET));
|
||||
myShapeDone = true;
|
||||
return myShape;
|
||||
}
|
||||
|
||||
// if no pocket, do offset or thicken
|
||||
if(myParams.PocketMode == PocketModeNone){
|
||||
myShape = makeOffset(-1,PARAM_FIELDS(AREA_MY,AREA_PARAMS_OFFSET));
|
||||
myShapeDone = true;
|
||||
return myShape;
|
||||
}
|
||||
|
||||
// do offset first, then pocket the inner most offseted shape
|
||||
std::list<shared_ptr<CArea> > areas;
|
||||
makeOffset(areas,PARAM_FIELDS(AREA_MY,AREA_PARAMS_OFFSET));
|
||||
|
||||
if(areas.empty())
|
||||
areas.push_back(make_shared<CArea>(*myArea));
|
||||
|
||||
Area areaPocket(&myParams);
|
||||
bool front = true;
|
||||
if(areas.size()>1) {
|
||||
double step = myParams.Stepover;
|
||||
if(fabs(step)<Precision::Confusion())
|
||||
step = myParams.Offset;
|
||||
front = step>0;
|
||||
}
|
||||
|
||||
// for pocketing, we discard the outer most offset wire in order to achieve
|
||||
// the effect of offseting shape first than pocket, where the actual offset
|
||||
// path is not wanted. For extra outline profiling, add extra_offset
|
||||
if(front) {
|
||||
areaPocket.add(toShape(*areas.front(),myParams.Fill));
|
||||
areas.pop_back();
|
||||
}else{
|
||||
areaPocket.add(toShape(*areas.back(),myParams.Fill));
|
||||
areas.pop_front();
|
||||
}
|
||||
|
||||
TopoDS_Shape Area::makeOffset(PARAM_ARGS(ARG,AREA_PARAMS_OFFSET)) {
|
||||
std::list<TopoDS_Shape> shapes;
|
||||
makeOffset(shapes,PARAM_FIELDS(ARG,AREA_PARAMS_OFFSET));
|
||||
if(shapes.empty())
|
||||
return TopoDS_Shape();
|
||||
if(shapes.size()==1)
|
||||
return shapes.front();
|
||||
BRep_Builder builder;
|
||||
TopoDS_Compound compound;
|
||||
builder.MakeCompound(compound);
|
||||
for(const TopoDS_Shape &s : shapes)
|
||||
builder.Add(compound,s);
|
||||
|
||||
short fill = myParams.Thicken?FillFace:FillNone;
|
||||
for(shared_ptr<CArea> area : areas) {
|
||||
if(myParams.Thicken)
|
||||
area->Thicken(myParams.ToolRadius);
|
||||
builder.Add(compound,toShape(*area,fill));
|
||||
}
|
||||
builder.Add(compound,areaPocket.makePocket(
|
||||
-1,PARAM_FIELDS(AREA_MY,AREA_PARAMS_POCKET)));
|
||||
myShape = compound;
|
||||
myShapeDone = true;
|
||||
return myShape;
|
||||
}
|
||||
|
||||
TopoDS_Shape Area::makeOffset(int index,PARAM_ARGS(PARAM_FARG,AREA_PARAMS_OFFSET)) {
|
||||
build();
|
||||
AREA_SECTION(makeOffset,index,PARAM_FIELDS(PARAM_FARG,AREA_PARAMS_OFFSET));
|
||||
|
||||
std::list<shared_ptr<CArea> > areas;
|
||||
makeOffset(areas,PARAM_FIELDS(PARAM_FARG,AREA_PARAMS_OFFSET));
|
||||
if(areas.empty()) {
|
||||
if(myParams.Thicken && myParams.ToolRadius>Precision::Confusion()) {
|
||||
CArea area(*myArea);
|
||||
area.Thicken(myParams.ToolRadius);
|
||||
return toShape(area,FillFace);
|
||||
}
|
||||
return TopoDS_Shape();
|
||||
}
|
||||
BRep_Builder builder;
|
||||
TopoDS_Compound compound;
|
||||
builder.MakeCompound(compound);
|
||||
for(shared_ptr<CArea> area : areas) {
|
||||
short fill;
|
||||
if(myParams.Thicken && myParams.ToolRadius>Precision::Confusion()) {
|
||||
area->Thicken(myParams.ToolRadius);
|
||||
fill = FillFace;
|
||||
}else if(areas.size()==1)
|
||||
fill = myParams.Fill;
|
||||
else
|
||||
fill = FillNone;
|
||||
builder.Add(compound,toShape(*area,fill));
|
||||
}
|
||||
return compound;
|
||||
}
|
||||
|
||||
void Area::makeOffset(std::list<TopoDS_Shape> &shapes,
|
||||
PARAM_ARGS(ARG,AREA_PARAMS_OFFSET))
|
||||
void Area::makeOffset(list<shared_ptr<CArea> > &areas,
|
||||
PARAM_ARGS(PARAM_FARG,AREA_PARAMS_OFFSET))
|
||||
{
|
||||
if(fabs(offset)<Precision::Confusion()){
|
||||
shapes.push_back(getShape());
|
||||
if(fabs(offset)<Precision::Confusion())
|
||||
return;
|
||||
}
|
||||
|
||||
build();
|
||||
CAreaConfig conf(myParams);
|
||||
|
||||
if(myParams.Thicken) {
|
||||
CArea area(*myArea);
|
||||
area.Thicken(fabs(offset));
|
||||
shapes.push_back(toShape(area,myParams.Fill));
|
||||
return;
|
||||
}
|
||||
|
||||
long count = 1;
|
||||
if(extra_pass) {
|
||||
|
@ -469,13 +681,14 @@ void Area::makeOffset(std::list<TopoDS_Shape> &shapes,
|
|||
}
|
||||
}
|
||||
|
||||
PARAM_ENUM_CONVERT(AREA_SRC,,PARAM_ENUM_EXCEPT,AREA_PARAMS_OFFSET_CONF);
|
||||
PARAM_ENUM_CONVERT(AREA_SRC,PARAM_FNAME,PARAM_ENUM_EXCEPT,AREA_PARAMS_OFFSET_CONF);
|
||||
#ifdef AREA_OFFSET_ALGO
|
||||
PARAM_ENUM_CONVERT(AREA_SRC,,PARAM_ENUM_EXCEPT,AREA_PARAMS_CLIPPER_FILL);
|
||||
PARAM_ENUM_CONVERT(AREA_SRC,PARAM_FNAME,PARAM_ENUM_EXCEPT,AREA_PARAMS_CLIPPER_FILL);
|
||||
#endif
|
||||
|
||||
for(int i=0;count<0||i<count;++i,offset+=stepover) {
|
||||
CArea area;
|
||||
areas.push_back(make_shared<CArea>());
|
||||
CArea &area = *areas.back();
|
||||
CArea areaOpen;
|
||||
#ifdef AREA_OFFSET_ALGO
|
||||
if(myParams.Algo == Area::Algolibarea) {
|
||||
|
@ -512,16 +725,10 @@ void Area::makeOffset(std::list<TopoDS_Shape> &shapes,
|
|||
|
||||
if(area.m_curves.empty())
|
||||
return;
|
||||
|
||||
if(count == 1) {
|
||||
shapes.push_back(toShape(area,myParams.Fill));
|
||||
return;
|
||||
}
|
||||
shapes.push_back(toShape(area,Area::FillNone));
|
||||
}
|
||||
}
|
||||
|
||||
TopoDS_Shape Area::makePocket(PARAM_ARGS(ARG,AREA_PARAMS_POCKET)) {
|
||||
TopoDS_Shape Area::makePocket(int index, PARAM_ARGS(PARAM_FARG,AREA_PARAMS_POCKET)) {
|
||||
if(tool_radius < Precision::Confusion())
|
||||
throw Base::ValueError("tool radius too small");
|
||||
|
||||
|
@ -534,6 +741,9 @@ TopoDS_Shape Area::makePocket(PARAM_ARGS(ARG,AREA_PARAMS_POCKET)) {
|
|||
if(mode == Area::PocketModeNone)
|
||||
return TopoDS_Shape();
|
||||
|
||||
build();
|
||||
AREA_SECTION(makePocket,index,PARAM_FIELDS(PARAM_FARG,AREA_PARAMS_POCKET));
|
||||
|
||||
PocketMode pm;
|
||||
switch(mode) {
|
||||
case Area::PocketModeZigZag:
|
||||
|
@ -543,11 +753,11 @@ TopoDS_Shape Area::makePocket(PARAM_ARGS(ARG,AREA_PARAMS_POCKET)) {
|
|||
pm = SpiralPocketMode;
|
||||
break;
|
||||
case Area::PocketModeOffset: {
|
||||
PARAM_DECLARE_INIT(NAME,AREA_PARAMS_OFFSET);
|
||||
PARAM_DECLARE_INIT(PARAM_FNAME,AREA_PARAMS_OFFSET);
|
||||
Offset = -tool_radius-extra_offset;
|
||||
ExtraPass = -1;
|
||||
Stepover = -stepover;
|
||||
return makeOffset(PARAM_FIELDS(NAME,AREA_PARAMS_OFFSET));
|
||||
return makeOffset(index,PARAM_FIELDS(PARAM_FNAME,AREA_PARAMS_OFFSET));
|
||||
}case Area::PocketModeZigZagOffset:
|
||||
pm = ZigZagThenSingleOffsetPocketMode;
|
||||
break;
|
||||
|
@ -564,7 +774,12 @@ TopoDS_Shape Area::makePocket(PARAM_ARGS(ARG,AREA_PARAMS_POCKET)) {
|
|||
// reorder before input, otherwise nothing is shown.
|
||||
in.Reorder();
|
||||
in.MakePocketToolpath(out.m_curves,params);
|
||||
return toShape(out,FillNone);
|
||||
|
||||
if(myParams.Thicken){
|
||||
out.Thicken(tool_radius);
|
||||
return toShape(out,FillFace);
|
||||
}else
|
||||
return toShape(out,FillNone);
|
||||
}
|
||||
|
||||
static inline bool IsLeft(const gp_Pnt &a, const gp_Pnt &b, const gp_Pnt &c) {
|
||||
|
|
|
@ -37,15 +37,14 @@ namespace Path
|
|||
|
||||
/** Store libarea algorithm configuration */
|
||||
struct PathExport CAreaParams {
|
||||
PARAM_DECLARE(NAME,AREA_PARAMS_CAREA)
|
||||
PARAM_DECLARE(PARAM_FNAME,AREA_PARAMS_CAREA)
|
||||
CAreaParams();
|
||||
};
|
||||
|
||||
/** Store all Area configurations */
|
||||
struct PathExport AreaParams: CAreaParams {
|
||||
|
||||
PARAM_DECLARE(NAME,AREA_PARAMS_BASE)
|
||||
PARAM_DECLARE(NAME,AREA_PARAMS_OFFSET_CONF)
|
||||
PARAM_DECLARE(PARAM_FNAME,AREA_PARAMS_AREA)
|
||||
|
||||
bool operator==(const AreaParams &other) const {
|
||||
#define AREA_COMPARE(_param) \
|
||||
|
@ -68,7 +67,7 @@ struct PathExport AreaParams: CAreaParams {
|
|||
struct PathExport CAreaConfig {
|
||||
|
||||
/** Stores current libarea settings */
|
||||
PARAM_DECLARE(NAME,AREA_PARAMS_CAREA)
|
||||
PARAM_DECLARE(PARAM_FNAME,AREA_PARAMS_CAREA)
|
||||
|
||||
/** Stores user defined setting */
|
||||
CAreaParams params;
|
||||
|
@ -105,14 +104,17 @@ protected:
|
|||
};
|
||||
|
||||
std::list<Shape> myShapes;
|
||||
CArea *myArea;
|
||||
CArea *myAreaOpen;
|
||||
std::unique_ptr<CArea> myArea;
|
||||
std::unique_ptr<CArea> myAreaOpen;
|
||||
gp_Trsf myTrsf;
|
||||
AreaParams myParams;
|
||||
TopoDS_Shape myShapePlane;
|
||||
TopoDS_Shape myWorkPlane;
|
||||
TopoDS_Shape myShape;
|
||||
std::vector<std::shared_ptr<Area> > mySections;
|
||||
bool myHaveFace;
|
||||
bool myHaveSolid;
|
||||
bool myShapeDone;
|
||||
int mySkippedShapes;
|
||||
|
||||
/** Called internally to combine children shapes for further processing */
|
||||
|
@ -126,7 +128,19 @@ protected:
|
|||
/** Called internally to obtain the combained children shapes */
|
||||
TopoDS_Shape toShape(CArea &area, short fill);
|
||||
|
||||
public:
|
||||
/** Obtain a list of offseted areas
|
||||
*
|
||||
* See #AREA_PARAMS_OFFSET for description of the arguments.
|
||||
*/
|
||||
void makeOffset(std::list<std::shared_ptr<CArea> > &areas,
|
||||
PARAM_ARGS_DEF(PARAM_FARG,AREA_PARAMS_OFFSET));
|
||||
|
||||
/** Make a pocket of the combined shape
|
||||
*
|
||||
* User #AREA_PARAMS_POCKET setting in myParams.
|
||||
*/
|
||||
TopoDS_Shape makePocket();
|
||||
|
||||
/** Declare all parameters defined in #AREA_PARAMS_ALL as member variable */
|
||||
PARAM_ENUM_DECLARE(AREA_PARAMS_ALL)
|
||||
|
||||
|
@ -153,7 +167,8 @@ public:
|
|||
* \arg \c shape: the child shape
|
||||
* \arg \c op: operation code, see #AREA_PARAMS_OPCODE
|
||||
*/
|
||||
void add(const TopoDS_Shape &shape,PARAM_ARGS_DEF(ARG,AREA_PARAMS_OPCODE));
|
||||
void add(const TopoDS_Shape &shape,PARAM_ARGS_DEF(PARAM_FARG,AREA_PARAMS_OPCODE));
|
||||
|
||||
|
||||
/** Generate an offset of the combined shape
|
||||
*
|
||||
|
@ -161,20 +176,13 @@ public:
|
|||
* If more than one offset is requested, a compound shape is return
|
||||
* containing all offset shapes as wires regardless of \c Fill setting.
|
||||
*/
|
||||
TopoDS_Shape makeOffset(PARAM_ARGS_DEF(ARG,AREA_PARAMS_OFFSET));
|
||||
|
||||
/** Obtain a list of offset shapes of the combined shape,
|
||||
*
|
||||
* See #AREA_PARAMS_OFFSET for description of the arguments.
|
||||
*/
|
||||
void makeOffset(std::list<TopoDS_Shape> &shapes,
|
||||
PARAM_ARGS_DEF(ARG,AREA_PARAMS_OFFSET));
|
||||
TopoDS_Shape makeOffset(int index, PARAM_ARGS_DEF(PARAM_FARG,AREA_PARAMS_OFFSET));
|
||||
|
||||
/** Make a pocket of the combined shape
|
||||
*
|
||||
* See #AREA_PARAMS_POCKET for description of the arguments.
|
||||
*/
|
||||
TopoDS_Shape makePocket(PARAM_ARGS_DEF(ARG,AREA_PARAMS_POCKET));
|
||||
TopoDS_Shape makePocket(int index, PARAM_ARGS_DEF(PARAM_FARG,AREA_PARAMS_POCKET));
|
||||
|
||||
|
||||
/** Config this Area object */
|
||||
|
@ -196,7 +204,7 @@ public:
|
|||
void clean(bool deleteShapes=false);
|
||||
|
||||
/** Get the combined shape */
|
||||
const TopoDS_Shape &getShape();
|
||||
TopoDS_Shape getShape(int index);
|
||||
|
||||
/** Add a OCC wire shape to CArea
|
||||
*
|
||||
|
|
|
@ -86,6 +86,9 @@
|
|||
((bool,from_center,FromCenter,true,"Start pocketing from center"))\
|
||||
((double,zig_angle,ZigAngle,45,"Zig angle in degree"))
|
||||
|
||||
#define AREA_PARAMS_POCKET_CONF \
|
||||
((bool,thicken,Thicken,false,"Thicken the resulting wires with ToolRadius"))
|
||||
|
||||
/** Operation code */
|
||||
#define AREA_PARAMS_OPCODE \
|
||||
((enum2,op,Operation,0,"Boolean operation",\
|
||||
|
@ -97,6 +100,12 @@
|
|||
((long,extra_pass,ExtraPass,0,"Number of extra offset pass to generate."))\
|
||||
((double,stepover,Stepover,0.0,"Cutter diameter to step over on each pass. If =0, use Offset"))
|
||||
|
||||
/** Section parameters */
|
||||
#define AREA_PARAMS_SECTION \
|
||||
((long,count,SectionCount,0,"Number of sections to generate. -1 means full sections."))\
|
||||
((double,stepdown,Stepdown,1.0,"Step down distance for each section"))\
|
||||
((double,offset,SectionOffset,0.0,"Offset for the first section"))
|
||||
|
||||
#ifdef AREA_OFFSET_ALGO
|
||||
# define AREA_PARAMS_OFFSET_ALGO \
|
||||
((enum,algo,Algo,0,"Offset algorithm type",(Clipper)(libarea)))
|
||||
|
@ -107,7 +116,6 @@
|
|||
/** Offset configuration parameters */
|
||||
#define AREA_PARAMS_OFFSET_CONF \
|
||||
AREA_PARAMS_OFFSET_ALGO \
|
||||
((bool,thicken,Thicken,false,"Thicken the resulting wires with Offset"))\
|
||||
((enum2,join_type,JoinType,0,"ClipperOffset join type. \nSee https://goo.gl/4odfQh",\
|
||||
(Round)(Square)(Miter),(ClipperLib::JoinType,ClipperLib::jt)))\
|
||||
((enum2,end_type,EndType,0,"\nClipperOffset end type. See https://goo.gl/tj7gkX",\
|
||||
|
@ -116,17 +124,23 @@
|
|||
((double,round_precision,RoundPreceision,0.0,\
|
||||
"Round joint precision. If =0, it defaults to Accuracy. \nSee https://goo.gl/4odfQh"))
|
||||
|
||||
/** Group of all Area configuration parameters except CArea's*/
|
||||
#define AREA_PARAMS_AREA \
|
||||
AREA_PARAMS_BASE \
|
||||
AREA_PARAMS_OFFSET \
|
||||
AREA_PARAMS_OFFSET_CONF \
|
||||
AREA_PARAMS_POCKET \
|
||||
AREA_PARAMS_POCKET_CONF \
|
||||
AREA_PARAMS_SECTION
|
||||
|
||||
/** Group of all Area configuration parameters */
|
||||
#define AREA_PARAMS_CONF \
|
||||
AREA_PARAMS_CAREA \
|
||||
AREA_PARAMS_BASE \
|
||||
AREA_PARAMS_OFFSET_CONF
|
||||
AREA_PARAMS_AREA
|
||||
|
||||
/** Group of all Area parameters */
|
||||
#define AREA_PARAMS_ALL \
|
||||
AREA_PARAMS_CONF \
|
||||
AREA_PARAMS_OPCODE \
|
||||
AREA_PARAMS_OFFSET \
|
||||
AREA_PARAMS_POCKET
|
||||
AREA_PARAMS_OPCODE
|
||||
|
||||
#endif //PATH_AreaParam_H
|
||||
|
|
|
@ -26,9 +26,11 @@
|
|||
any operation</UserDocu>
|
||||
</Documentation>
|
||||
</Methode>
|
||||
<Methode Name="toShape" Keyword='true'>
|
||||
<Methode Name="getShape" Keyword='true'>
|
||||
<Documentation>
|
||||
<UserDocu>toShape(rebuild=False): Return the resulting shape</UserDocu>
|
||||
<UserDocu>getShape(index=-1,rebuild=False): Return the resulting shape\n
|
||||
\n* index (-1): the index of the section. -1 means all sections. No effect on planar shape.\n
|
||||
\n* rebuild: clean the internal cache and rebuild</UserDocu>
|
||||
</Documentation>
|
||||
</Methode>
|
||||
<Methode Name="makeOffset" Keyword='true'>
|
||||
|
|
|
@ -65,6 +65,7 @@ static const AreaDoc myDocs[] = {
|
|||
"makeOffset",
|
||||
|
||||
"makeOffset(" PARAM_PY_ARGS_DOC(ARG,AREA_PARAMS_OFFSET) "):\n"
|
||||
"\n* index (-1): the index of the section. -1 means all sections. No effect on planar shape.\n"
|
||||
"Make an 2D offset of the shape.\n"
|
||||
PARAM_PY_DOC(ARG,AREA_PARAMS_OFFSET),
|
||||
},
|
||||
|
@ -73,6 +74,7 @@ static const AreaDoc myDocs[] = {
|
|||
|
||||
"makePocket(" PARAM_PY_ARGS_DOC(ARG,AREA_PARAMS_POCKET) "):\n"
|
||||
"Generate pocket toolpath of the shape.\n"
|
||||
"\n* index (-1): the index of the section. -1 means all sections. No effect on planar shape.\n"
|
||||
PARAM_PY_DOC(ARG,AREA_PARAMS_POCKET),
|
||||
},
|
||||
};
|
||||
|
@ -94,7 +96,7 @@ struct AreaPyDoc {
|
|||
static AreaPyDoc doc;
|
||||
|
||||
namespace Part {
|
||||
extern Py::Object shape2pyshape(const TopoDS_Shape &shape);
|
||||
extern PartExport Py::Object shape2pyshape(const TopoDS_Shape &shape);
|
||||
}
|
||||
|
||||
using namespace Path;
|
||||
|
@ -128,29 +130,30 @@ PyObject* AreaPy::setPlane(PyObject *args) {
|
|||
return Py_None;
|
||||
}
|
||||
|
||||
PyObject* AreaPy::toShape(PyObject *args, PyObject *keywds)
|
||||
PyObject* AreaPy::getShape(PyObject *args, PyObject *keywds)
|
||||
{
|
||||
PyObject *pcObj = Py_True;
|
||||
static char *kwlist[] = {"rebuild", NULL};
|
||||
if (!PyArg_ParseTupleAndKeywords(args, keywds,"|O",kwlist,&pcObj))
|
||||
short index=-1;
|
||||
static char *kwlist[] = {"index","rebuild", NULL};
|
||||
if (!PyArg_ParseTupleAndKeywords(args, keywds,"|hO",kwlist,&pcObj))
|
||||
Py_Error(Base::BaseExceptionFreeCADError, "This method accepts no argument");
|
||||
|
||||
try {
|
||||
if(PyObject_IsTrue(pcObj))
|
||||
getAreaPtr()->clean(true);
|
||||
return Py::new_reference_to(Part::shape2pyshape(getAreaPtr()->getShape()));
|
||||
return Py::new_reference_to(Part::shape2pyshape(getAreaPtr()->getShape(index)));
|
||||
}
|
||||
PY_CATCH_OCC;
|
||||
}
|
||||
|
||||
PyObject* AreaPy::add(PyObject *args, PyObject *keywds)
|
||||
{
|
||||
PARAM_PY_DECLARE_INIT(ARG,AREA_PARAMS_OPCODE)
|
||||
PARAM_PY_DECLARE_INIT(PARAM_FARG,AREA_PARAMS_OPCODE)
|
||||
PyObject *pcObj;
|
||||
static char *kwlist[] = {PARAM_FIELD_STRINGS(ARG,AREA_PARAMS_OPCODE), NULL};
|
||||
if (!PyArg_ParseTupleAndKeywords(args, keywds,
|
||||
"O|" PARAM_PY_KWDS(AREA_PARAMS_OPCODE),
|
||||
kwlist,&pcObj,PARAM_REF(ARG,AREA_PARAMS_OPCODE)))
|
||||
kwlist,&pcObj,PARAM_REF(PARAM_FARG,AREA_PARAMS_OPCODE)))
|
||||
Py_Error(Base::BaseExceptionFreeCADError, "Wrong parameters");
|
||||
|
||||
if (PyObject_TypeCheck(pcObj, &(Part::TopoShapePy::Type))) {
|
||||
|
@ -168,7 +171,7 @@ PyObject* AreaPy::add(PyObject *args, PyObject *keywds)
|
|||
for (Py::Sequence::iterator it = shapeSeq.begin(); it != shapeSeq.end(); ++it){
|
||||
PyObject* item = (*it).ptr();
|
||||
getAreaPtr()->add(GET_TOPOSHAPE(item),
|
||||
PARAM_PY_FIELDS(ARG,AREA_PARAMS_OPCODE));
|
||||
PARAM_PY_FIELDS(PARAM_FARG,AREA_PARAMS_OPCODE));
|
||||
}
|
||||
return Py_None;
|
||||
}
|
||||
|
@ -176,22 +179,23 @@ PyObject* AreaPy::add(PyObject *args, PyObject *keywds)
|
|||
PyObject* AreaPy::makeOffset(PyObject *args, PyObject *keywds)
|
||||
{
|
||||
//Generate a keyword string defined in the ARG field of OFFSET parameter list
|
||||
static char *kwlist[] = {PARAM_FIELD_STRINGS(ARG,AREA_PARAMS_OFFSET), NULL};
|
||||
static char *kwlist[] = {"index",PARAM_FIELD_STRINGS(ARG,AREA_PARAMS_OFFSET), NULL};
|
||||
short index = -1;
|
||||
|
||||
//Declare variables defined in the ARG field of the OFFSET parameter list with
|
||||
//initialization to defaults
|
||||
PARAM_PY_DECLARE_INIT(ARG,AREA_PARAMS_OFFSET)
|
||||
PARAM_PY_DECLARE_INIT(PARAM_FARG,AREA_PARAMS_OFFSET)
|
||||
|
||||
//Parse arguments to overwrite the defaults
|
||||
if (!PyArg_ParseTupleAndKeywords(args, keywds,
|
||||
"|" PARAM_PY_KWDS(AREA_PARAMS_OFFSET), kwlist,
|
||||
PARAM_REF(ARG,AREA_PARAMS_OFFSET)))
|
||||
"|h" PARAM_PY_KWDS(AREA_PARAMS_OFFSET), kwlist,
|
||||
&index,PARAM_REF(PARAM_FARG,AREA_PARAMS_OFFSET)))
|
||||
Py_Error(Base::BaseExceptionFreeCADError, "Wrong parameters");
|
||||
|
||||
try {
|
||||
//Expand the variable as function call arguments
|
||||
TopoDS_Shape resultShape = getAreaPtr()->makeOffset(
|
||||
PARAM_PY_FIELDS(ARG,AREA_PARAMS_OFFSET));
|
||||
TopoDS_Shape resultShape = getAreaPtr()->makeOffset(index,
|
||||
PARAM_PY_FIELDS(PARAM_FARG,AREA_PARAMS_OFFSET));
|
||||
return Py::new_reference_to(Part::shape2pyshape(resultShape));
|
||||
}
|
||||
PY_CATCH_OCC;
|
||||
|
@ -199,18 +203,19 @@ PyObject* AreaPy::makeOffset(PyObject *args, PyObject *keywds)
|
|||
|
||||
PyObject* AreaPy::makePocket(PyObject *args, PyObject *keywds)
|
||||
{
|
||||
static char *kwlist[] = {PARAM_FIELD_STRINGS(ARG,AREA_PARAMS_POCKET), NULL};
|
||||
static char *kwlist[] = {"index",PARAM_FIELD_STRINGS(ARG,AREA_PARAMS_POCKET), NULL};
|
||||
short index = -1;
|
||||
|
||||
PARAM_PY_DECLARE_INIT(ARG,AREA_PARAMS_POCKET)
|
||||
PARAM_PY_DECLARE_INIT(PARAM_FARG,AREA_PARAMS_POCKET)
|
||||
|
||||
if (!PyArg_ParseTupleAndKeywords(args, keywds,
|
||||
"|" PARAM_PY_KWDS(AREA_PARAMS_POCKET), kwlist,
|
||||
PARAM_REF(ARG,AREA_PARAMS_POCKET)))
|
||||
"|h" PARAM_PY_KWDS(AREA_PARAMS_POCKET), kwlist,
|
||||
&index,PARAM_REF(PARAM_FARG,AREA_PARAMS_POCKET)))
|
||||
Py_Error(Base::BaseExceptionFreeCADError, "Wrong parameters");
|
||||
|
||||
try {
|
||||
TopoDS_Shape resultShape = getAreaPtr()->makePocket(
|
||||
PARAM_PY_FIELDS(ARG,AREA_PARAMS_POCKET));
|
||||
TopoDS_Shape resultShape = getAreaPtr()->makePocket(index,
|
||||
PARAM_PY_FIELDS(PARAM_FARG,AREA_PARAMS_POCKET));
|
||||
return Py::new_reference_to(Part::shape2pyshape(resultShape));
|
||||
}
|
||||
PY_CATCH_OCC;
|
||||
|
@ -222,7 +227,7 @@ PyObject* AreaPy::setParams(PyObject *args, PyObject *keywds)
|
|||
static char *kwlist[] = {PARAM_FIELD_STRINGS(NAME,AREA_PARAMS_CONF),NULL};
|
||||
|
||||
//Declare variables defined in the NAME field of the CONF parameter list
|
||||
PARAM_PY_DECLARE(NAME,AREA_PARAMS_CONF);
|
||||
PARAM_PY_DECLARE(PARAM_FNAME,AREA_PARAMS_CONF);
|
||||
|
||||
AreaParams params = getAreaPtr()->getParams();
|
||||
|
||||
|
@ -235,7 +240,7 @@ PyObject* AreaPy::setParams(PyObject *args, PyObject *keywds)
|
|||
//Parse arguments to overwrite CONF variables
|
||||
if (!PyArg_ParseTupleAndKeywords(args, keywds,
|
||||
"|" PARAM_PY_KWDS(AREA_PARAMS_CONF), kwlist,
|
||||
PARAM_REF(NAME,AREA_PARAMS_CONF)))
|
||||
PARAM_REF(PARAM_FNAME,AREA_PARAMS_CONF)))
|
||||
Py_Error(Base::BaseExceptionFreeCADError,
|
||||
"Wrong parameters, call getParamsDesc() to get supported params");
|
||||
|
||||
|
@ -257,8 +262,8 @@ PyObject* AreaPy::getParams(PyObject *args)
|
|||
const AreaParams ¶ms =getAreaPtr()->getParams();
|
||||
|
||||
PyObject *dict = PyDict_New();
|
||||
#define AREA_SRC(_v) params._v
|
||||
PARAM_PY_DICT_SET_VALUE(dict,AREA_SRC,AREA_PARAMS_CONF)
|
||||
#define AREA_SRC(_param) params.PARAM_FNAME(_param)
|
||||
PARAM_PY_DICT_SET_VALUE(dict,NAME,AREA_SRC,AREA_PARAMS_CONF)
|
||||
return dict;
|
||||
}
|
||||
|
||||
|
@ -273,7 +278,7 @@ PyObject* AreaPy::getParamsDesc(PyObject *args, PyObject *keywds)
|
|||
return PyString_FromString(PARAM_PY_DOC(NAME,AREA_PARAMS_CONF));
|
||||
|
||||
PyObject *dict = PyDict_New();
|
||||
PARAM_PY_DICT_SET_DOC(dict,AREA_PARAMS_CONF)
|
||||
PARAM_PY_DICT_SET_DOC(dict,NAME,AREA_PARAMS_CONF)
|
||||
return dict;
|
||||
}
|
||||
|
||||
|
|
|
@ -48,6 +48,8 @@ FeatureArea::FeatureArea()
|
|||
PARAM_PROP_ADD("Area",AREA_PARAMS_BASE);
|
||||
PARAM_PROP_ADD("Offset",AREA_PARAMS_OFFSET);
|
||||
PARAM_PROP_ADD("Pocket",AREA_PARAMS_POCKET);
|
||||
PARAM_PROP_ADD("Pocket",AREA_PARAMS_POCKET_CONF);
|
||||
PARAM_PROP_ADD("Section",AREA_PARAMS_SECTION);
|
||||
PARAM_PROP_ADD("Offset Settings", AREA_PARAMS_OFFSET_CONF);
|
||||
PARAM_PROP_ADD("libarea Settings",AREA_PARAMS_CAREA);
|
||||
|
||||
|
@ -77,7 +79,6 @@ App::DocumentObjectExecReturn *FeatureArea::execute(void)
|
|||
|
||||
#define AREA_PROP_GET(_param) \
|
||||
params.PARAM_FNAME(_param) = PARAM_FNAME(_param).getValue();
|
||||
|
||||
PARAM_FOREACH(AREA_PROP_GET,AREA_PARAMS_CONF)
|
||||
|
||||
Area area(¶ms);
|
||||
|
@ -86,45 +87,12 @@ App::DocumentObjectExecReturn *FeatureArea::execute(void)
|
|||
if(!workPlane.IsNull())
|
||||
area.setPlane(workPlane);
|
||||
|
||||
area.clean(true);
|
||||
for (std::vector<App::DocumentObject*>::iterator it = links.begin(); it != links.end(); ++it) {
|
||||
area.add(static_cast<Part::Feature*>(*it)->Shape.getShape().getShape(),
|
||||
PARAM_PROP_ARGS(AREA_PARAMS_OPCODE));
|
||||
}
|
||||
|
||||
std::list<TopoDS_Shape> shapes;
|
||||
if(fabs(Offset.getValue())>Precision::Confusion())
|
||||
area.makeOffset(shapes,PARAM_PROP_ARGS(AREA_PARAMS_OFFSET));
|
||||
|
||||
if(PocketMode.getValue()) {
|
||||
Area areaPocket(¶ms);
|
||||
if(shapes.empty())
|
||||
areaPocket.add(area.getShape());
|
||||
else{
|
||||
bool front = true;
|
||||
if(shapes.size()>1) {
|
||||
double step = Stepover.getValue();
|
||||
if(fabs(step)<Precision::Confusion())
|
||||
step = Offset.getValue();
|
||||
front = step>0;
|
||||
}
|
||||
areaPocket.add(front?shapes.front():shapes.back());
|
||||
}
|
||||
shapes.push_back(areaPocket.makePocket(PARAM_PROP_ARGS(AREA_PARAMS_POCKET)));
|
||||
}
|
||||
|
||||
if(shapes.empty())
|
||||
this->Shape.setValue(area.getShape());
|
||||
else if(shapes.size()==1)
|
||||
this->Shape.setValue(shapes.front());
|
||||
else {
|
||||
BRep_Builder builder;
|
||||
TopoDS_Compound compound;
|
||||
builder.MakeCompound(compound);
|
||||
for(const TopoDS_Shape &s : shapes)
|
||||
builder.Add(compound,s);
|
||||
this->Shape.setValue(compound);
|
||||
}
|
||||
this->Shape.setValue(area.getShape(-1));
|
||||
return Part::Feature::execute();
|
||||
}
|
||||
|
||||
|
|
|
@ -315,42 +315,52 @@
|
|||
|
||||
|
||||
/** Helper for #PARAM_DECLARE */
|
||||
#define PARAM_DECLARE_(_1,_field,_param) \
|
||||
PARAM_TYPE(_param) PARAM_FIELD(_field,_param);
|
||||
#define PARAM_DECLARE_(_1,_src,_param) \
|
||||
PARAM_TYPE(_param) _src(_param);
|
||||
|
||||
/**
|
||||
* Delcares parameters using the given field as name
|
||||
*
|
||||
* \arg \c _field: specifies the \ref ParamField "field" to use as name
|
||||
* \arg \c _src: \anchor ParamSrc Macro to generate source variable. The
|
||||
* signature must be <tt>_src(_param)<\tt>, where \c _param is the tuple
|
||||
* defining the parameter. You pass any of the \ref ParamAccessor "parameter
|
||||
* accessors" to directly access the field. Or, supply your own macro to append
|
||||
* any prefix as you like. For example:
|
||||
* \code{.unparsed}
|
||||
* #define MY_SRC(_param) BOOST_PP_CAT(my,PARAM_FNAME(_param))
|
||||
* ->
|
||||
* my##<name>
|
||||
* \endcode
|
||||
*
|
||||
* Expands to:
|
||||
* \code{.unparsed}
|
||||
* type1 _field1;type2 _field2; ...
|
||||
* type1 _src(_param1);type2 _src(_param2); ...
|
||||
* \endcode
|
||||
* \ingroup ParamCommon
|
||||
*/
|
||||
#define PARAM_DECLARE(_field,_seq) \
|
||||
BOOST_PP_SEQ_FOR_EACH(PARAM_DECLARE_,_field,_seq)
|
||||
#define PARAM_DECLARE(_src,_seq) \
|
||||
BOOST_PP_SEQ_FOR_EACH(PARAM_DECLARE_,_src,_seq)
|
||||
|
||||
|
||||
/** Helper for #PARAM_DECLARE_INIT */
|
||||
#define PARAM_DECLARE_INIT_(_1,_field,_param) \
|
||||
PARAM_TYPE(_param) PARAM_FIELD(_field,_param) = PARAM_FDEF(_param);
|
||||
#define PARAM_DECLARE_INIT_(_1,_src,_param) \
|
||||
PARAM_TYPE(_param) _src(_param) = PARAM_FDEF(_param);
|
||||
|
||||
/**
|
||||
* Delcares parameters with initialization to default using the given field as
|
||||
* name
|
||||
*
|
||||
* \arg \c _field: \ref ParamField "field" to use as name
|
||||
* \arg \c _src: macro to generate source field. See \ref ParamSrc "here" for
|
||||
* more details
|
||||
*
|
||||
* Expands to:
|
||||
* \code{.unparsed}
|
||||
* type1 _field1=_def1;type2 _field2=_def2; ...
|
||||
* type1 _src(_param1)=_def1;type2 _src(_param2)=_def2; ...
|
||||
* \endcode
|
||||
* \ingroup ParamCommon
|
||||
*/
|
||||
#define PARAM_DECLARE_INIT(_field,_seq) \
|
||||
BOOST_PP_SEQ_FOR_EACH(PARAM_DECLARE_INIT_,_field,_seq)
|
||||
#define PARAM_DECLARE_INIT(_src,_seq) \
|
||||
BOOST_PP_SEQ_FOR_EACH(PARAM_DECLARE_INIT_,_src,_seq)
|
||||
|
||||
|
||||
#define PARAM_ENUM_DECLARE_enum_(_1,_name,_i,_elem) \
|
||||
|
@ -394,8 +404,7 @@
|
|||
|
||||
#define PARAM_ENUM_CONVERT_enum_(_dst,_name,_prefix,_elem) \
|
||||
case BOOST_PP_CAT(_name,_elem):\
|
||||
_dst(_name) = \
|
||||
BOOST_PP_CAT(_prefix,_elem);\
|
||||
_dst = BOOST_PP_CAT(_prefix,_elem);\
|
||||
break;
|
||||
|
||||
#define PARAM_ENUM_CONVERT__(_1,_args,_i,_elem) \
|
||||
|
@ -418,10 +427,10 @@
|
|||
* i.e. not double but single parathesis
|
||||
*/
|
||||
#define PARAM_ENUM_CONVERT_SINGLE(_src,_dst,_default,_param) \
|
||||
PARAM_FENUM_TYPE(_param) _dst(PARAM_FNAME(_param));\
|
||||
switch(_src(PARAM_FNAME(_param))) {\
|
||||
PARAM_FENUM_TYPE(_param) _dst(_param);\
|
||||
switch(_src(_param)) {\
|
||||
BOOST_PP_SEQ_FOR_EACH_I(PARAM_ENUM_CONVERT__,\
|
||||
(_dst,PARAM_FNAME(_param),PARAM_FENUM_PREFIX(_param)),PARAM_FSEQ(_param))\
|
||||
(_dst(_param),PARAM_FNAME(_param),PARAM_FENUM_PREFIX(_param)),PARAM_FSEQ(_param))\
|
||||
default: \
|
||||
_default(_param);\
|
||||
}
|
||||
|
@ -441,11 +450,12 @@
|
|||
*
|
||||
* \ingroup ParamEnumHelper
|
||||
*
|
||||
* \arg \c _src: Optional macro to generate source variable. The signature must
|
||||
* be <tt>_src(_name)<\tt>, where \c _name will be the parameters \a name field.
|
||||
* In case you just want \c _name as the source variable name, you can simply
|
||||
* omit this argument, because newer C++ preprocessor allows empty argument.
|
||||
* \arg \c _dst: Optional macro to generate destination variable. Same as above.
|
||||
* \arg \c _src: Macro to generate source variable. The signature must be
|
||||
* <tt>_src(_param)<\tt>, where \c _param is the tuple defining the parameter.
|
||||
* You pass any of the \ref ParamAccessor "parameter accessors" to directly
|
||||
* access the field. Or, supply your own macro to append any prefix as you
|
||||
* like.
|
||||
* \arg \c _dst: Same as above.
|
||||
* \arg \c _default: A macro to call for invalid value. Signature should be
|
||||
* <tt>_default(_param)<\tt>, where \c _param is the parameter definition. You
|
||||
* can use #PARAM_ENUM_EXCEPT to throw Base::ValueError exception in FreeCAD
|
||||
|
@ -457,12 +467,12 @@
|
|||
* ((enum,test1,Test1,0,"it's a test",(Foo)(Bar),(MyEnum1,myEnum1)) \
|
||||
* ((enum,test2,Test2,0,"it's a test",(Foo)(Bar),(MyEnum2,myEnum2)))
|
||||
*
|
||||
* #define MY_DST(_v) BOOST_PP_CAT(my,_v)
|
||||
* #define MY_DST(_param) BOOST_PP_CAT(my,PARAM_FNAME(_param))
|
||||
* \code{.unparsed}
|
||||
*
|
||||
* calling (note that the \c _src macro is omitted)
|
||||
* calling
|
||||
* \code{.unparsed}
|
||||
* PARAM_ENUM_CONVERT(,MY_DST,My,PARAM_ENUM_EXCEP,MY_PARAM_TEST)
|
||||
* PARAM_ENUM_CONVERT(PARAM_FNAME,MY_DST,My,PARAM_ENUM_EXCEP,MY_PARAM_TEST)
|
||||
* \code{.unparsed}
|
||||
*
|
||||
* expands to
|
||||
|
@ -514,7 +524,7 @@
|
|||
_param)
|
||||
|
||||
#define PARAM_ENUM_CHECK_SINGLE(_src,_default,_param) \
|
||||
switch(_src(PARAM_FNAME(_param))) {\
|
||||
switch(_src(_param)) {\
|
||||
BOOST_PP_SEQ_FOR_EACH_I(PARAM_ENUM_CHECK_enum_,\
|
||||
PARAM_FNAME(_param),PARAM_FSEQ(_param))\
|
||||
default: \
|
||||
|
@ -528,10 +538,11 @@
|
|||
*
|
||||
* \ingroup ParamEnumHelper
|
||||
*
|
||||
* \arg \c _src: Optional macro to generate source variable. The signature must
|
||||
* be <tt>_src(_name)<\tt>, where \c _name will be the parameters \a name field.
|
||||
* In case you just want \c _name as the source variable name, you can simply
|
||||
* omit this argument, because newer C++ preprocessor allows empty argument.
|
||||
* \arg \c _src: Macro to generate source variable. The signature must be
|
||||
* <tt>_src(_param)<\tt>, where \c _param is the tuple defining the parameter.
|
||||
* You pass any of the \ref ParamAccessor "parameter accessors" to directly
|
||||
* access the field. Or, supply your own macro to append any prefix as you
|
||||
* like.
|
||||
*
|
||||
* \arg \c _default: A macro to call for invalid value. Signature should be
|
||||
* <tt>_default(_param)<\tt>, where \c _param is the parameter definition. You
|
||||
|
@ -574,57 +585,86 @@
|
|||
|
||||
|
||||
/** Helper for #PARAM_INIT */
|
||||
#define PARAM_INIT_(_,_field,_i,_param) \
|
||||
BOOST_PP_COMMA_IF(_i) PARAM_FIELD(_field,_param)(PARAM_FDEF(_param))
|
||||
#define PARAM_INIT_(_,_src,_i,_param) \
|
||||
BOOST_PP_COMMA_IF(_i) _src(_param)(PARAM_FDEF(_param))
|
||||
|
||||
/** Constructor initialization
|
||||
*
|
||||
* \arg \c _field: specifies the \ref ParamField "field" to use as name
|
||||
* \arg \c _src: macro to generate source field. See \ref ParamSrc "here" for
|
||||
* more details
|
||||
*
|
||||
* Expand to,
|
||||
* \code{.unparsed}
|
||||
* field1(def1), field2(def2)...
|
||||
* _src(_param1)(def1), _src(_param1)(def2)...
|
||||
* \endcode
|
||||
* \ingroup ParamCommon
|
||||
*/
|
||||
#define PARAM_INIT(_field,_seq) \
|
||||
BOOST_PP_SEQ_FOR_EACH_I(PARAM_INIT_,_field,_seq)
|
||||
#define PARAM_INIT(_src,_seq) \
|
||||
BOOST_PP_SEQ_FOR_EACH_I(PARAM_INIT_,_src,_seq)
|
||||
|
||||
|
||||
/** Helper for #PARAM_OP */
|
||||
#define PARAM_OP_(_,_args,_param) \
|
||||
BOOST_PP_TUPLE_ELEM(0,_args)(_param) BOOST_PP_TUPLE_ELEM(1,_args) \
|
||||
BOOST_PP_TUPLE_ELEM(2,_args)(_param);
|
||||
|
||||
/** Perform operation on two instance of each parameter in a sequence
|
||||
*
|
||||
* \arg \c _src: Macro to generate source variable. The signature must be
|
||||
* <tt>_src(_param)<\tt>, where \c _param is the tuple defining the parameter.
|
||||
* You pass any of the \ref ParamAccessor "parameter accessors" to directly
|
||||
* access the field. Or, supply your own macro to append any prefix as you
|
||||
* like.
|
||||
* \arg \c _op: a boolean operator
|
||||
* \arg \c _dst: Same as \c _src above.
|
||||
*
|
||||
* Expands to:
|
||||
* \code{.unparsed}
|
||||
* _src(_param1) _op _src(_param2);
|
||||
* \endcode
|
||||
*
|
||||
* \ingroup ParamCommon
|
||||
*/
|
||||
#define PARAM_OP(_src,_op,_dst,_seq) \
|
||||
BOOST_PP_SEQ_FOR_EACH(PARAM_COPY_,(_src,_op,_dst),_seq)
|
||||
|
||||
|
||||
/** Helper for #PARAM_ARGS_DEF */
|
||||
#define PARAM_ARGS_DEF_(_,_field,_i,_param) \
|
||||
BOOST_PP_COMMA_IF(_i) PARAM_TYPE(_param) PARAM_FIELD(_field,_param)=PARAM_FDEF(_param)
|
||||
#define PARAM_ARGS_DEF_(_,_src,_i,_param) \
|
||||
BOOST_PP_COMMA_IF(_i) PARAM_TYPE(_param) _src(_param)=PARAM_FDEF(_param)
|
||||
|
||||
/** Delcare the parameters as function argument list with defaults.
|
||||
*
|
||||
* \arg \c _field: specifies the \ref ParamField "field" to use as name
|
||||
* \arg \c _src: macro to generate source field. See \ref ParamSrc "here" for
|
||||
* more details
|
||||
*
|
||||
* Expand to:
|
||||
* \code{.unparsed}
|
||||
* type1 field1=def1, type2 field2=def2 ...
|
||||
* type1 _src(_param1)=def1, type2 _src(_param1)=def2 ...
|
||||
* \endcode
|
||||
* \ingroup ParamCommon
|
||||
*/
|
||||
#define PARAM_ARGS_DEF(_field,_seq) \
|
||||
BOOST_PP_SEQ_FOR_EACH_I(PARAM_ARGS_DEF_,_field,_seq)
|
||||
#define PARAM_ARGS_DEF(_src,_seq) \
|
||||
BOOST_PP_SEQ_FOR_EACH_I(PARAM_ARGS_DEF_,_src,_seq)
|
||||
|
||||
|
||||
/** Helper for #PARAM_ARGS */
|
||||
#define PARAM_ARGS_(_,_field,_i,_param) \
|
||||
BOOST_PP_COMMA_IF(_i) PARAM_TYPE(_param) PARAM_FIELD(_field,_param)
|
||||
#define PARAM_ARGS_(_,_src,_i,_param) \
|
||||
BOOST_PP_COMMA_IF(_i) PARAM_TYPE(_param) _src(_param)
|
||||
|
||||
/** Delcare the parameters as function argument list without defaults.
|
||||
*
|
||||
* \arg \c _field: specifies the \ref ParamField "field" to use as name
|
||||
* \arg \c _src: macro to generate source field. See \ref ParamSrc "here" for
|
||||
* more details
|
||||
*
|
||||
* Expand to:
|
||||
* \code{.unparsed}
|
||||
* type1 field1, type2 field2 ...
|
||||
* type1 _src(_param1), type2 _src(_param2) ...
|
||||
* \endcode
|
||||
* \ingroup ParamCommon
|
||||
*/
|
||||
#define PARAM_ARGS(_field,_seq) \
|
||||
BOOST_PP_SEQ_FOR_EACH_I(PARAM_ARGS_,_field,_seq)
|
||||
#define PARAM_ARGS(_src,_seq) \
|
||||
BOOST_PP_SEQ_FOR_EACH_I(PARAM_ARGS_,_src,_seq)
|
||||
|
||||
|
||||
/** \defgroup ParamPy Python helper
|
||||
|
@ -685,19 +725,22 @@
|
|||
|
||||
|
||||
/** Helper for #PARAM_FIELDS */
|
||||
#define PARAM_FIELDS_(_1,_field,_i,_param) \
|
||||
BOOST_PP_COMMA_IF(_i) PARAM_FIELD(_field,_param)
|
||||
#define PARAM_FIELDS_(_1,_src,_i,_param) \
|
||||
BOOST_PP_COMMA_IF(_i) _src(_param)
|
||||
|
||||
/** Expand to a list of the given field in the parameter sequence
|
||||
*
|
||||
* For example, PARAM_FIELDS(ARG, _seq) expands to:
|
||||
* \arg \c _src: macro to generate source field. See \ref ParamSrc "here" for
|
||||
* more details
|
||||
*
|
||||
* For example, PARAM_FIELDS(PARAM_FARG, _seq) expands to:
|
||||
* \code{.unparsed}
|
||||
* arg1,arg2 ...
|
||||
* \endcode
|
||||
* \ingroup ParamCommon ParamPy
|
||||
*/
|
||||
#define PARAM_FIELDS(_field,_seq) \
|
||||
BOOST_PP_SEQ_FOR_EACH_I(PARAM_FIELDS_,_field,_seq)
|
||||
#define PARAM_FIELDS(_src,_seq) \
|
||||
BOOST_PP_SEQ_FOR_EACH_I(PARAM_FIELDS_,_src,_seq)
|
||||
|
||||
|
||||
#define PARAM_PY_CAST_short(_v) (_v)
|
||||
|
@ -716,16 +759,19 @@
|
|||
|
||||
|
||||
/** Helper for #PARAM_PY_FIELDS */
|
||||
#define PARAM_PY_FIELDS_(_1,_field,_i,_param) \
|
||||
BOOST_PP_COMMA_IF(_i) PARAM_TYPED(PARAM_CAST_PY_,_param)(PARAM_FIELD(_field,_param))
|
||||
#define PARAM_PY_FIELDS_(_1,_src,_i,_param) \
|
||||
BOOST_PP_COMMA_IF(_i) PARAM_TYPED(PARAM_CAST_PY_,_param)(_src(_param))
|
||||
|
||||
/** Expand to a list of the given field in the sequence
|
||||
/** Expand to a comma separated list of the given field in the sequence
|
||||
*
|
||||
* \arg \c _src: macro to generate source field. See \ref ParamSrc "here" for
|
||||
* more details
|
||||
*
|
||||
* The field will be casted from python C to C type
|
||||
* \ingroup ParamCommon ParamPy
|
||||
*/
|
||||
#define PARAM_PY_FIELDS(_field,_seq) \
|
||||
BOOST_PP_SEQ_FOR_EACH_I(PARAM_PY_FIELDS_,_field,_seq)
|
||||
#define PARAM_PY_FIELDS(_src,_seq) \
|
||||
BOOST_PP_SEQ_FOR_EACH_I(PARAM_PY_FIELDS_,_src,_seq)
|
||||
|
||||
|
||||
/** Helper for #PARAM_FIELD_STRINGS */
|
||||
|
@ -733,7 +779,7 @@
|
|||
BOOST_PP_COMMA_IF(_i) PARAM_FIELD_STR(_field,_param)
|
||||
|
||||
/** Expand to a list of stringified fields
|
||||
* \ingroup ParamCommon ParamPy
|
||||
* \ingroup ParamStringizer ParamPy
|
||||
*/
|
||||
#define PARAM_FIELD_STRINGS(_field,_seq) \
|
||||
BOOST_PP_SEQ_FOR_EACH_I(PARAM_FIELD_STRINGS_,_field,_seq)
|
||||
|
@ -764,14 +810,14 @@
|
|||
#define PARAM_PY_TYPE_enum2 short
|
||||
|
||||
/** Helper for #PARAM_PY_DECLARE */
|
||||
#define PARAM_PY_DECLARE_(_1,_field,_param) \
|
||||
PARAM_TYPED(PARAM_PY_TYPE_,_param) PARAM_FIELD(_field,_param);
|
||||
#define PARAM_PY_DECLARE_(_1,_src,_param) \
|
||||
PARAM_TYPED(PARAM_PY_TYPE_,_param) _src(_param);
|
||||
|
||||
/** Declare field variables for Python C type without initialization
|
||||
* \ingroup ParamPy
|
||||
*/
|
||||
#define PARAM_PY_DECLARE(_field,_seq) \
|
||||
BOOST_PP_SEQ_FOR_EACH(PARAM_PY_DECLARE_,_field,_seq)
|
||||
#define PARAM_PY_DECLARE(_src,_seq) \
|
||||
BOOST_PP_SEQ_FOR_EACH(PARAM_PY_DECLARE_,_src,_seq)
|
||||
|
||||
#define PARAM_PY_INIT_short(_v) _v
|
||||
#define PARAM_PY_INIT_long(_v) _v
|
||||
|
@ -781,31 +827,34 @@
|
|||
#define PARAM_PY_INIT_enum2(_v) _v
|
||||
|
||||
/** Helper for #PARAM_PY_DECLARE_INIT */
|
||||
#define PARAM_PY_DECLARE_INIT_(_1,_field,_param) \
|
||||
PARAM_TYPED(PARAM_PY_TYPE_,_param) PARAM_FIELD(_field,_param) = \
|
||||
#define PARAM_PY_DECLARE_INIT_(_1,_src,_param) \
|
||||
PARAM_TYPED(PARAM_PY_TYPE_,_param) _src(_param) = \
|
||||
PARAM_TYPED(PARAM_PY_INIT_,_param)(PARAM_FDEF(_param));
|
||||
|
||||
/** Declare field variables of Python c type with initialization to default
|
||||
* \ingroup ParamPy
|
||||
*/
|
||||
#define PARAM_PY_DECLARE_INIT(_field,_seq) \
|
||||
BOOST_PP_SEQ_FOR_EACH(PARAM_PY_DECLARE_INIT_,_field,_seq)
|
||||
#define PARAM_PY_DECLARE_INIT(_src,_seq) \
|
||||
BOOST_PP_SEQ_FOR_EACH(PARAM_PY_DECLARE_INIT_,_src,_seq)
|
||||
|
||||
|
||||
/** Helper for #PARAM_REF */
|
||||
#define PARAM_REF_(_1,_field,_i,_param) \
|
||||
BOOST_PP_COMMA_IF(_i) &PARAM_FIELD(_field,_param)
|
||||
#define PARAM_REF_(_1,_src,_i,_param) \
|
||||
BOOST_PP_COMMA_IF(_i) &_src(_param)
|
||||
|
||||
/** Generate a list of field references
|
||||
*
|
||||
* \arg \c _src: macro to generate source field. See \ref ParamSrc "here" for
|
||||
*
|
||||
* more details
|
||||
* Expand to:
|
||||
* \code{.unparsed}
|
||||
* &_field1, &_field2 ...
|
||||
* &_src(_param1), &_src(_param1) ...
|
||||
* \endcode
|
||||
* \ingroup ParamPy
|
||||
*/
|
||||
#define PARAM_REF(_field,_seq) \
|
||||
BOOST_PP_SEQ_FOR_EACH_I(PARAM_REF_,_field,_seq)
|
||||
#define PARAM_REF(_src,_seq) \
|
||||
BOOST_PP_SEQ_FOR_EACH_I(PARAM_REF_,_src,_seq)
|
||||
|
||||
|
||||
#define PARAM_CAST_PYOBJ_short(_v) PyInt_FromLong(_v)
|
||||
|
@ -816,35 +865,36 @@
|
|||
#define PARAM_CAST_PYOBJ_enum2 PARAM_CAST_PYOBJ_short
|
||||
|
||||
|
||||
/** Stringize field to a Python string */
|
||||
#define PARAM_PY_STRINGIZE(_field,_param) \
|
||||
/** Stringize field to a Python string
|
||||
* \ingroup ParamPy ParamStringizer
|
||||
*/
|
||||
#define PARAM_PY_STR(_field,_param) \
|
||||
PyString_FromString(PARAM_FIELD_STR(_field,_param))
|
||||
|
||||
/** Helper for #PARAM_PY_DICT_SET_VALUE */
|
||||
#define PARAM_PY_DICT_SET_VALUE_(_1,_args,_param) \
|
||||
PyDict_SetItem(BOOST_PP_TUPLE_ELEM(0,_args), \
|
||||
PARAM_PY_STRINGIZE(NAME,_param),\
|
||||
PARAM_PY_STR(BOOST_PP_TUPLE_ELEM(1,_args),_param),\
|
||||
PARAM_TYPED(PARAM_CAST_PYOBJ_,_param)(\
|
||||
BOOST_PP_TUPLE_ELEM(1,_args)(PARAM_FIELD(NAME,_param))));
|
||||
BOOST_PP_TUPLE_ELEM(2,_args)(_param)));
|
||||
|
||||
/** Populate a Python dict with a structure variable
|
||||
*
|
||||
* \arg \c _dict: the Python dictionary object
|
||||
* \arg \c _src: Optional macro to generate source variable. The signature must
|
||||
* be <tt>_src(_name)<\tt>, where \c _name will be the parameters \a name field.
|
||||
* In case you just want \c _name as the source variable name, you can simply
|
||||
* omit this argument, because newer C++ preprocessor allows empty argument.
|
||||
* \arg \c _field: specifies the \ref ParamField "field" to use as key
|
||||
* \arg \c _src: macro to generate source field. See \ref ParamSrc "here" for
|
||||
* more details
|
||||
*
|
||||
* Roughly translated to:
|
||||
* \code{.unparsed}
|
||||
* PyDict_SetItem(_dict,#name1,_src(name1));
|
||||
* PyDict_SetItem(_dict,#name2,_src(name2));
|
||||
* PyDict_SetItem(_dict,#_field1,_src(_param));
|
||||
* PyDict_SetItem(_dict,#_field2,_src(_param));
|
||||
* ...
|
||||
* \endcode
|
||||
* \ingroup ParamPy
|
||||
*/
|
||||
#define PARAM_PY_DICT_SET_VALUE(_dict,_src,_seq) \
|
||||
BOOST_PP_SEQ_FOR_EACH(PARAM_PY_DICT_SET_VALUE_,(_dict,_src),_seq)
|
||||
#define PARAM_PY_DICT_SET_VALUE(_dict,_field,_src,_seq) \
|
||||
BOOST_PP_SEQ_FOR_EACH(PARAM_PY_DICT_SET_VALUE_,(_dict,_field,_src),_seq)
|
||||
|
||||
|
||||
#define PARAM_PY_DICT_DOC_enum_(_i,_elem) \
|
||||
|
@ -868,22 +918,26 @@
|
|||
#define PARAM_PY_DICT_DOC_enum2 PARAM_PY_DICT_DOC_enum
|
||||
|
||||
/** Helper for #PARAM_PY_DICT_SET_DOC */
|
||||
#define PARAM_PY_DICT_SET_DOC_(_1,_dict,_param) \
|
||||
PyDict_SetItem(_dict, PARAM_PY_STRINGIZE(NAME,_param),\
|
||||
PyString_FromString(PARAM_TYPED(PARAM_PY_DICT_DOC_,_param)(_param)));
|
||||
#define PARAM_PY_DICT_SET_DOC_(_1,_args,_param) \
|
||||
PyDict_SetItem(BOOST_PP_TUPLE_ELEM(0,_args), \
|
||||
PARAM_PY_STR(BOOST_PP_TUPLE_ELEM(1,_args),_param),\
|
||||
PyString_FromString(PARAM_TYPED(PARAM_PY_DICT_DOC_,_param)(_param)));
|
||||
|
||||
/** Populate a Python dict with the doc field of the parameter sequence
|
||||
*
|
||||
* \arg \c _dict: the Python dictionary object
|
||||
* \arg \c _field: specifies the \ref ParamField "field" to use as key
|
||||
*
|
||||
* Roughly translated to:
|
||||
* \code{.unparsed}
|
||||
* PyDict_SetItem(_dict,#name1,doc1);
|
||||
* PyDict_SetItem(_dict,#name2,doc2);
|
||||
* PyDict_SetItem(_dict,#_field1,doc1);
|
||||
* PyDict_SetItem(_dict,#_field1,doc2);
|
||||
* ...
|
||||
* \endcode
|
||||
* \ingroup ParamDoc
|
||||
*/
|
||||
#define PARAM_PY_DICT_SET_DOC(_dict,_seq) \
|
||||
BOOST_PP_SEQ_FOR_EACH(PARAM_PY_DICT_SET_DOC_,_dict,_seq)
|
||||
#define PARAM_PY_DICT_SET_DOC(_dict,_field,_seq) \
|
||||
BOOST_PP_SEQ_FOR_EACH(PARAM_PY_DICT_SET_DOC_,(_dict,_field),_seq)
|
||||
|
||||
|
||||
/** \defgroup ParamProperty Property Macros
|
||||
|
|
|
@ -66,44 +66,37 @@ CmdPathArea::CmdPathArea()
|
|||
void CmdPathArea::activated(int iMsg)
|
||||
{
|
||||
Q_UNUSED(iMsg);
|
||||
std::vector<Gui::SelectionObject> Sel =
|
||||
getSelection().getSelectionEx(NULL, Part::Feature::getClassTypeId());
|
||||
std::list<std::string> cmds;
|
||||
std::ostringstream sources;
|
||||
if (Sel.size() > 0) {
|
||||
for(const Gui::SelectionObject &selObj : Sel) {
|
||||
const Part::Feature *pcObj = static_cast<const Part::Feature*>(selObj.getObject());
|
||||
if(selObj.getSubNames().empty()) {
|
||||
const TopoDS_Shape &shape = pcObj->Shape.getShape().getShape();
|
||||
TopExp_Explorer it(shape, TopAbs_SHELL);
|
||||
if(it.More()) {
|
||||
Base::Console().Error("Selected shape is not 2D\n");
|
||||
return;
|
||||
}
|
||||
sources << "FreeCAD.activeDocument()." << pcObj->getNameInDocument() << ",";
|
||||
continue;
|
||||
for(const Gui::SelectionObject &selObj :
|
||||
getSelection().getSelectionEx(NULL, Part::Feature::getClassTypeId()))
|
||||
{
|
||||
const Part::Feature *pcObj = static_cast<const Part::Feature*>(selObj.getObject());
|
||||
const std::vector<std::string> &subnames = selObj.getSubNames();
|
||||
if(subnames.empty()) {
|
||||
sources << "FreeCAD.activeDocument()." << pcObj->getNameInDocument() << ",";
|
||||
continue;
|
||||
}
|
||||
for(const std::string &name : subnames) {
|
||||
if(!name.compare(0,4,"Face") &&
|
||||
!name.compare(0,4,"Edge"))
|
||||
{
|
||||
Base::Console().Error("Selected shape is not 2D\n");
|
||||
return;
|
||||
}
|
||||
|
||||
for(const std::string &name : selObj.getSubNames()) {
|
||||
if(!name.compare(0,4,"Face") &&
|
||||
!name.compare(0,4,"Edge"))
|
||||
{
|
||||
Base::Console().Error("Selected shape is not 2D\n");
|
||||
return;
|
||||
}
|
||||
int index = atoi(name.substr(4).c_str());
|
||||
|
||||
int index = atoi(name.substr(4).c_str());
|
||||
std::ostringstream subname;
|
||||
subname << pcObj->getNameInDocument() << '_' << name;
|
||||
std::string sub_fname = getUniqueObjectName(subname.str().c_str());
|
||||
|
||||
std::ostringstream subname;
|
||||
subname << pcObj->getNameInDocument() << '_' << name;
|
||||
std::string sub_fname = getUniqueObjectName(subname.str().c_str());
|
||||
|
||||
std::ostringstream cmd;
|
||||
cmd << "FreeCAD.activeDocument().addObject('Path::Feature','" << sub_fname << "').Shape = " <<
|
||||
pcObj->getNameInDocument() << '.' << name.substr(0,4) << '[' << index-1 << ']';
|
||||
cmds.push_back(cmd.str());
|
||||
sources << "FreeCAD.activeDocument()." << sub_fname << ",";
|
||||
}
|
||||
std::ostringstream cmd;
|
||||
cmd << "FreeCAD.activeDocument().addObject('Part::Feature','" << sub_fname <<
|
||||
"').Shape = FreeCAD.activeDocument()." << pcObj->getNameInDocument() << ".Shape." <<
|
||||
name.substr(0,4) << "s[" << index-1 << ']';
|
||||
cmds.push_back(cmd.str());
|
||||
sources << "FreeCAD.activeDocument()." << sub_fname << ",";
|
||||
}
|
||||
}
|
||||
std::string FeatName = getUniqueObjectName("FeatureArea");
|
||||
|
@ -121,6 +114,101 @@ bool CmdPathArea::isActive(void)
|
|||
return hasActiveDocument();
|
||||
}
|
||||
|
||||
|
||||
DEF_STD_CMD_A(CmdPathAreaWorkplane)
|
||||
|
||||
CmdPathAreaWorkplane::CmdPathAreaWorkplane()
|
||||
:Command("Path_Area_Workplane")
|
||||
{
|
||||
sAppModule = "Path";
|
||||
sGroup = QT_TR_NOOP("Path");
|
||||
sMenuText = QT_TR_NOOP("Area workplane");
|
||||
sToolTipText = QT_TR_NOOP("Select a workplane for a FeatureArea");
|
||||
sWhatsThis = "Path_Area_Workplane";
|
||||
sStatusTip = sToolTipText;
|
||||
sPixmap = "Path-Area-Workplane";
|
||||
sAccel = "P,W";
|
||||
|
||||
}
|
||||
|
||||
void CmdPathAreaWorkplane::activated(int iMsg)
|
||||
{
|
||||
Q_UNUSED(iMsg);
|
||||
|
||||
std::string areaName;
|
||||
std::string planeSubname;
|
||||
std::string planeName;
|
||||
|
||||
for(Gui::SelectionObject &selObj :
|
||||
getSelection().getSelectionEx(NULL, Part::Feature::getClassTypeId()))
|
||||
{
|
||||
const std::vector<std::string> &subnames = selObj.getSubNames();
|
||||
if(subnames.size()>1) {
|
||||
Base::Console().Error("Please select one sub shape object for plane only\n");
|
||||
return;
|
||||
}
|
||||
const Part::Feature *pcObj = static_cast<Part::Feature*>(selObj.getObject());
|
||||
if(subnames.empty()) {
|
||||
if(pcObj->getTypeId().isDerivedFrom(Path::FeatureArea::getClassTypeId())) {
|
||||
if(areaName.size()){
|
||||
Base::Console().Error("Please select one FeatureArea only\n");
|
||||
return;
|
||||
}
|
||||
areaName = pcObj->getNameInDocument();
|
||||
continue;
|
||||
}
|
||||
for (TopExp_Explorer it(pcObj->Shape.getShape().getShape(), TopAbs_SHELL); it.More(); it.Next()) {
|
||||
Base::Console().Error("Selected shape is not 2D\n");
|
||||
return;
|
||||
}
|
||||
}
|
||||
if(planeName.size()){
|
||||
Base::Console().Error("Please select one shape object for plane only\n");
|
||||
return;
|
||||
}else{
|
||||
planeSubname = planeName = pcObj->getNameInDocument();
|
||||
planeSubname += ".Shape";
|
||||
}
|
||||
|
||||
for(const std::string &name : subnames) {
|
||||
if(!name.compare(0,4,"Face") &&
|
||||
!name.compare(0,4,"Edge"))
|
||||
{
|
||||
Base::Console().Error("Selected shape is not 2D\n");
|
||||
return;
|
||||
}
|
||||
|
||||
int index = atoi(name.substr(4).c_str());
|
||||
|
||||
std::ostringstream subname;
|
||||
subname << planeSubname << '.' << name.substr(0,4) << "s[" << index-1 << ']';
|
||||
planeSubname = subname.str();
|
||||
}
|
||||
}
|
||||
if(areaName.empty()) {
|
||||
Base::Console().Error("Please select one FeatureArea\n");
|
||||
return;
|
||||
}
|
||||
if(planeName.empty()) {
|
||||
Base::Console().Error("Please select one shape object\n");
|
||||
return;
|
||||
}
|
||||
|
||||
openCommand("Select Workplane for Path Area");
|
||||
doCommand(Doc,"FreeCAD.activeDocument().%s.WorkPlane = FreeCAD.activeDocument().%s",
|
||||
areaName.c_str(),planeSubname.c_str());
|
||||
doCommand(Doc,"FreeCAD.activeDocument().%s.ViewObject.Visibility = True",areaName.c_str());
|
||||
// doCommand(Doc,"FreeCAD.activeDocument().%s.ViewObject.Visibility = False",planeName.c_str());
|
||||
commitCommand();
|
||||
updateActive();
|
||||
}
|
||||
|
||||
bool CmdPathAreaWorkplane::isActive(void)
|
||||
{
|
||||
return !getSelection().getSelectionEx(NULL, Path::FeatureArea::getClassTypeId()).empty();
|
||||
}
|
||||
|
||||
|
||||
// Path compound #####################################################################################################
|
||||
|
||||
|
||||
|
@ -229,4 +317,5 @@ void CreatePathCommands(void)
|
|||
rcCmdMgr.addCommand(new CmdPathCompound());
|
||||
rcCmdMgr.addCommand(new CmdPathShape());
|
||||
rcCmdMgr.addCommand(new CmdPathArea());
|
||||
rcCmdMgr.addCommand(new CmdPathAreaWorkplane());
|
||||
}
|
||||
|
|
|
@ -47,6 +47,7 @@
|
|||
<file>icons/Path-Toolpath.svg</file>
|
||||
<file>icons/Path-ToolTable.svg</file>
|
||||
<file>icons/Path-Area.svg</file>
|
||||
<file>icons/Path-Area-Workplane.svg</file>
|
||||
<file>icons/preferences-path.svg</file>
|
||||
<file>panels/ContourEdit.ui</file>
|
||||
<file>panels/DlgJobChooser.ui</file>
|
||||
|
|
676
src/Mod/Path/Gui/Resources/icons/Path-Area-Workplane.svg
Normal file
676
src/Mod/Path/Gui/Resources/icons/Path-Area-Workplane.svg
Normal file
|
@ -0,0 +1,676 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
width="64px"
|
||||
height="64px"
|
||||
id="svg2816"
|
||||
version="1.1"
|
||||
inkscape:version="0.91 r13725"
|
||||
sodipodi:docname="Path-Area-Workplane.svg">
|
||||
<defs
|
||||
id="defs2818">
|
||||
<linearGradient
|
||||
id="linearGradient4022-3"
|
||||
inkscape:collect="always">
|
||||
<stop
|
||||
id="stop4316"
|
||||
offset="0"
|
||||
style="stop-color:#ff0000;stop-opacity:1" />
|
||||
<stop
|
||||
id="stop4318"
|
||||
offset="1"
|
||||
style="stop-color:#ff8080;stop-opacity:1" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
id="linearGradient4066">
|
||||
<stop
|
||||
style="stop-color:#4e9a06;stop-opacity:1"
|
||||
offset="0"
|
||||
id="stop4068" />
|
||||
<stop
|
||||
style="stop-color:#8ae234;stop-opacity:1"
|
||||
offset="1"
|
||||
id="stop4070" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
id="linearGradient4022">
|
||||
<stop
|
||||
style="stop-color:#204a87;stop-opacity:1"
|
||||
offset="0"
|
||||
id="stop4024" />
|
||||
<stop
|
||||
style="stop-color:#729fcf;stop-opacity:1"
|
||||
offset="1"
|
||||
id="stop4026" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="linearGradient4513">
|
||||
<stop
|
||||
style="stop-color:#ffffff;stop-opacity:1;"
|
||||
offset="0"
|
||||
id="stop4515" />
|
||||
<stop
|
||||
style="stop-color:#999999;stop-opacity:1;"
|
||||
offset="1"
|
||||
id="stop4517" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="linearGradient3681">
|
||||
<stop
|
||||
id="stop3697"
|
||||
offset="0"
|
||||
style="stop-color:#fff110;stop-opacity:1;" />
|
||||
<stop
|
||||
style="stop-color:#cf7008;stop-opacity:1;"
|
||||
offset="1"
|
||||
id="stop3685" />
|
||||
</linearGradient>
|
||||
<inkscape:perspective
|
||||
sodipodi:type="inkscape:persp3d"
|
||||
inkscape:vp_x="0 : 32 : 1"
|
||||
inkscape:vp_y="0 : 1000 : 0"
|
||||
inkscape:vp_z="64 : 32 : 1"
|
||||
inkscape:persp3d-origin="32 : 21.333333 : 1"
|
||||
id="perspective2824" />
|
||||
<inkscape:perspective
|
||||
id="perspective3622"
|
||||
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
|
||||
inkscape:vp_z="1 : 0.5 : 1"
|
||||
inkscape:vp_y="0 : 1000 : 0"
|
||||
inkscape:vp_x="0 : 0.5 : 1"
|
||||
sodipodi:type="inkscape:persp3d" />
|
||||
<inkscape:perspective
|
||||
id="perspective3622-9"
|
||||
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
|
||||
inkscape:vp_z="1 : 0.5 : 1"
|
||||
inkscape:vp_y="0 : 1000 : 0"
|
||||
inkscape:vp_x="0 : 0.5 : 1"
|
||||
sodipodi:type="inkscape:persp3d" />
|
||||
<inkscape:perspective
|
||||
id="perspective3653"
|
||||
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
|
||||
inkscape:vp_z="1 : 0.5 : 1"
|
||||
inkscape:vp_y="0 : 1000 : 0"
|
||||
inkscape:vp_x="0 : 0.5 : 1"
|
||||
sodipodi:type="inkscape:persp3d" />
|
||||
<inkscape:perspective
|
||||
id="perspective3675"
|
||||
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
|
||||
inkscape:vp_z="1 : 0.5 : 1"
|
||||
inkscape:vp_y="0 : 1000 : 0"
|
||||
inkscape:vp_x="0 : 0.5 : 1"
|
||||
sodipodi:type="inkscape:persp3d" />
|
||||
<inkscape:perspective
|
||||
id="perspective3697"
|
||||
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
|
||||
inkscape:vp_z="1 : 0.5 : 1"
|
||||
inkscape:vp_y="0 : 1000 : 0"
|
||||
inkscape:vp_x="0 : 0.5 : 1"
|
||||
sodipodi:type="inkscape:persp3d" />
|
||||
<inkscape:perspective
|
||||
id="perspective3720"
|
||||
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
|
||||
inkscape:vp_z="1 : 0.5 : 1"
|
||||
inkscape:vp_y="0 : 1000 : 0"
|
||||
inkscape:vp_x="0 : 0.5 : 1"
|
||||
sodipodi:type="inkscape:persp3d" />
|
||||
<inkscape:perspective
|
||||
id="perspective3742"
|
||||
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
|
||||
inkscape:vp_z="1 : 0.5 : 1"
|
||||
inkscape:vp_y="0 : 1000 : 0"
|
||||
inkscape:vp_x="0 : 0.5 : 1"
|
||||
sodipodi:type="inkscape:persp3d" />
|
||||
<inkscape:perspective
|
||||
id="perspective3764"
|
||||
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
|
||||
inkscape:vp_z="1 : 0.5 : 1"
|
||||
inkscape:vp_y="0 : 1000 : 0"
|
||||
inkscape:vp_x="0 : 0.5 : 1"
|
||||
sodipodi:type="inkscape:persp3d" />
|
||||
<inkscape:perspective
|
||||
id="perspective3785"
|
||||
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
|
||||
inkscape:vp_z="1 : 0.5 : 1"
|
||||
inkscape:vp_y="0 : 1000 : 0"
|
||||
inkscape:vp_x="0 : 0.5 : 1"
|
||||
sodipodi:type="inkscape:persp3d" />
|
||||
<inkscape:perspective
|
||||
id="perspective3806"
|
||||
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
|
||||
inkscape:vp_z="1 : 0.5 : 1"
|
||||
inkscape:vp_y="0 : 1000 : 0"
|
||||
inkscape:vp_x="0 : 0.5 : 1"
|
||||
sodipodi:type="inkscape:persp3d" />
|
||||
<inkscape:perspective
|
||||
id="perspective3806-3"
|
||||
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
|
||||
inkscape:vp_z="1 : 0.5 : 1"
|
||||
inkscape:vp_y="0 : 1000 : 0"
|
||||
inkscape:vp_x="0 : 0.5 : 1"
|
||||
sodipodi:type="inkscape:persp3d" />
|
||||
<inkscape:perspective
|
||||
id="perspective3835"
|
||||
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
|
||||
inkscape:vp_z="1 : 0.5 : 1"
|
||||
inkscape:vp_y="0 : 1000 : 0"
|
||||
inkscape:vp_x="0 : 0.5 : 1"
|
||||
sodipodi:type="inkscape:persp3d" />
|
||||
<inkscape:perspective
|
||||
id="perspective3614"
|
||||
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
|
||||
inkscape:vp_z="1 : 0.5 : 1"
|
||||
inkscape:vp_y="0 : 1000 : 0"
|
||||
inkscape:vp_x="0 : 0.5 : 1"
|
||||
sodipodi:type="inkscape:persp3d" />
|
||||
<inkscape:perspective
|
||||
id="perspective3614-8"
|
||||
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
|
||||
inkscape:vp_z="1 : 0.5 : 1"
|
||||
inkscape:vp_y="0 : 1000 : 0"
|
||||
inkscape:vp_x="0 : 0.5 : 1"
|
||||
sodipodi:type="inkscape:persp3d" />
|
||||
<inkscape:perspective
|
||||
id="perspective3643"
|
||||
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
|
||||
inkscape:vp_z="1 : 0.5 : 1"
|
||||
inkscape:vp_y="0 : 1000 : 0"
|
||||
inkscape:vp_x="0 : 0.5 : 1"
|
||||
sodipodi:type="inkscape:persp3d" />
|
||||
<inkscape:perspective
|
||||
id="perspective3643-3"
|
||||
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
|
||||
inkscape:vp_z="1 : 0.5 : 1"
|
||||
inkscape:vp_y="0 : 1000 : 0"
|
||||
inkscape:vp_x="0 : 0.5 : 1"
|
||||
sodipodi:type="inkscape:persp3d" />
|
||||
<inkscape:perspective
|
||||
id="perspective3672"
|
||||
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
|
||||
inkscape:vp_z="1 : 0.5 : 1"
|
||||
inkscape:vp_y="0 : 1000 : 0"
|
||||
inkscape:vp_x="0 : 0.5 : 1"
|
||||
sodipodi:type="inkscape:persp3d" />
|
||||
<inkscape:perspective
|
||||
id="perspective3672-5"
|
||||
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
|
||||
inkscape:vp_z="1 : 0.5 : 1"
|
||||
inkscape:vp_y="0 : 1000 : 0"
|
||||
inkscape:vp_x="0 : 0.5 : 1"
|
||||
sodipodi:type="inkscape:persp3d" />
|
||||
<inkscape:perspective
|
||||
id="perspective3701"
|
||||
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
|
||||
inkscape:vp_z="1 : 0.5 : 1"
|
||||
inkscape:vp_y="0 : 1000 : 0"
|
||||
inkscape:vp_x="0 : 0.5 : 1"
|
||||
sodipodi:type="inkscape:persp3d" />
|
||||
<inkscape:perspective
|
||||
id="perspective3701-8"
|
||||
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
|
||||
inkscape:vp_z="1 : 0.5 : 1"
|
||||
inkscape:vp_y="0 : 1000 : 0"
|
||||
inkscape:vp_x="0 : 0.5 : 1"
|
||||
sodipodi:type="inkscape:persp3d" />
|
||||
<inkscape:perspective
|
||||
id="perspective3746"
|
||||
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
|
||||
inkscape:vp_z="1 : 0.5 : 1"
|
||||
inkscape:vp_y="0 : 1000 : 0"
|
||||
inkscape:vp_x="0 : 0.5 : 1"
|
||||
sodipodi:type="inkscape:persp3d" />
|
||||
<pattern
|
||||
patternTransform="matrix(0.67643728,-0.81829155,2.4578314,1.8844554,-26.450606,18.294947)"
|
||||
id="pattern5231"
|
||||
xlink:href="#Strips1_1-4"
|
||||
inkscape:collect="always" />
|
||||
<inkscape:perspective
|
||||
id="perspective5224"
|
||||
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
|
||||
inkscape:vp_z="1 : 0.5 : 1"
|
||||
inkscape:vp_y="0 : 1000 : 0"
|
||||
inkscape:vp_x="0 : 0.5 : 1"
|
||||
sodipodi:type="inkscape:persp3d" />
|
||||
<pattern
|
||||
inkscape:stockid="Stripes 1:1"
|
||||
id="Strips1_1-4"
|
||||
patternTransform="matrix(0.66772843,-1.0037085,2.4261878,2.3114548,3.4760987,3.534923)"
|
||||
height="1"
|
||||
width="2"
|
||||
patternUnits="userSpaceOnUse"
|
||||
inkscape:collect="always">
|
||||
<rect
|
||||
id="rect4483-4"
|
||||
height="2"
|
||||
width="1"
|
||||
y="-0.5"
|
||||
x="0"
|
||||
style="fill:black;stroke:none" />
|
||||
</pattern>
|
||||
<inkscape:perspective
|
||||
id="perspective5224-9"
|
||||
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
|
||||
inkscape:vp_z="1 : 0.5 : 1"
|
||||
inkscape:vp_y="0 : 1000 : 0"
|
||||
inkscape:vp_x="0 : 0.5 : 1"
|
||||
sodipodi:type="inkscape:persp3d" />
|
||||
<pattern
|
||||
patternTransform="matrix(0.66772843,-1.0037085,2.4261878,2.3114548,39.618381,8.9692804)"
|
||||
id="pattern5231-4"
|
||||
xlink:href="#Strips1_1-6"
|
||||
inkscape:collect="always" />
|
||||
<inkscape:perspective
|
||||
id="perspective5224-3"
|
||||
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
|
||||
inkscape:vp_z="1 : 0.5 : 1"
|
||||
inkscape:vp_y="0 : 1000 : 0"
|
||||
inkscape:vp_x="0 : 0.5 : 1"
|
||||
sodipodi:type="inkscape:persp3d" />
|
||||
<pattern
|
||||
inkscape:stockid="Stripes 1:1"
|
||||
id="Strips1_1-6"
|
||||
patternTransform="matrix(0.66772843,-1.0037085,2.4261878,2.3114548,3.4760987,3.534923)"
|
||||
height="1"
|
||||
width="2"
|
||||
patternUnits="userSpaceOnUse"
|
||||
inkscape:collect="always">
|
||||
<rect
|
||||
id="rect4483-0"
|
||||
height="2"
|
||||
width="1"
|
||||
y="-0.5"
|
||||
x="0"
|
||||
style="fill:black;stroke:none" />
|
||||
</pattern>
|
||||
<pattern
|
||||
patternTransform="matrix(0.66513382,-1.0631299,2.4167603,2.4482973,-49.762569,2.9546807)"
|
||||
id="pattern5296"
|
||||
xlink:href="#pattern5231-3"
|
||||
inkscape:collect="always" />
|
||||
<inkscape:perspective
|
||||
id="perspective5288"
|
||||
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
|
||||
inkscape:vp_z="1 : 0.5 : 1"
|
||||
inkscape:vp_y="0 : 1000 : 0"
|
||||
inkscape:vp_x="0 : 0.5 : 1"
|
||||
sodipodi:type="inkscape:persp3d" />
|
||||
<pattern
|
||||
patternTransform="matrix(0.66772843,-1.0037085,2.4261878,2.3114548,-26.336284,10.887197)"
|
||||
id="pattern5231-3"
|
||||
xlink:href="#Strips1_1-4-3"
|
||||
inkscape:collect="always" />
|
||||
<pattern
|
||||
inkscape:stockid="Stripes 1:1"
|
||||
id="Strips1_1-4-3"
|
||||
patternTransform="matrix(0.66772843,-1.0037085,2.4261878,2.3114548,3.4760987,3.534923)"
|
||||
height="1"
|
||||
width="2"
|
||||
patternUnits="userSpaceOnUse"
|
||||
inkscape:collect="always">
|
||||
<rect
|
||||
id="rect4483-4-6"
|
||||
height="2"
|
||||
width="1"
|
||||
y="-0.5"
|
||||
x="0"
|
||||
style="fill:black;stroke:none" />
|
||||
</pattern>
|
||||
<pattern
|
||||
patternTransform="matrix(0.42844886,-0.62155849,1.5567667,1.431396,27.948414,13.306456)"
|
||||
id="pattern5330"
|
||||
xlink:href="#Strips1_1-9"
|
||||
inkscape:collect="always" />
|
||||
<inkscape:perspective
|
||||
id="perspective5323"
|
||||
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
|
||||
inkscape:vp_z="1 : 0.5 : 1"
|
||||
inkscape:vp_y="0 : 1000 : 0"
|
||||
inkscape:vp_x="0 : 0.5 : 1"
|
||||
sodipodi:type="inkscape:persp3d" />
|
||||
<pattern
|
||||
inkscape:stockid="Stripes 1:1"
|
||||
id="Strips1_1-9"
|
||||
patternTransform="matrix(0.66772843,-1.0037085,2.4261878,2.3114548,3.4760987,3.534923)"
|
||||
height="1"
|
||||
width="2"
|
||||
patternUnits="userSpaceOnUse"
|
||||
inkscape:collect="always">
|
||||
<rect
|
||||
id="rect4483-3"
|
||||
height="2"
|
||||
width="1"
|
||||
y="-0.5"
|
||||
x="0"
|
||||
style="fill:black;stroke:none" />
|
||||
</pattern>
|
||||
<inkscape:perspective
|
||||
id="perspective5361"
|
||||
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
|
||||
inkscape:vp_z="1 : 0.5 : 1"
|
||||
inkscape:vp_y="0 : 1000 : 0"
|
||||
inkscape:vp_x="0 : 0.5 : 1"
|
||||
sodipodi:type="inkscape:persp3d" />
|
||||
<inkscape:perspective
|
||||
id="perspective5383"
|
||||
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
|
||||
inkscape:vp_z="1 : 0.5 : 1"
|
||||
inkscape:vp_y="0 : 1000 : 0"
|
||||
inkscape:vp_x="0 : 0.5 : 1"
|
||||
sodipodi:type="inkscape:persp3d" />
|
||||
<inkscape:perspective
|
||||
id="perspective5411"
|
||||
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
|
||||
inkscape:vp_z="1 : 0.5 : 1"
|
||||
inkscape:vp_y="0 : 1000 : 0"
|
||||
inkscape:vp_x="0 : 0.5 : 1"
|
||||
sodipodi:type="inkscape:persp3d" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient3681"
|
||||
id="linearGradient3687"
|
||||
x1="37.89756"
|
||||
y1="41.087898"
|
||||
x2="4.0605712"
|
||||
y2="40.168594"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="translate(127.27273,-51.272729)" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient3681"
|
||||
id="linearGradient3695"
|
||||
x1="37.894287"
|
||||
y1="40.484772"
|
||||
x2="59.811455"
|
||||
y2="43.558987"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="translate(127.27273,-51.272729)" />
|
||||
<linearGradient
|
||||
id="linearGradient3681-3">
|
||||
<stop
|
||||
id="stop3697-3"
|
||||
offset="0"
|
||||
style="stop-color:#fff110;stop-opacity:1;" />
|
||||
<stop
|
||||
style="stop-color:#cf7008;stop-opacity:1;"
|
||||
offset="1"
|
||||
id="stop3685-4" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
y2="43.558987"
|
||||
x2="59.811455"
|
||||
y1="40.484772"
|
||||
x1="37.894287"
|
||||
gradientTransform="translate(-37.00068,-20.487365)"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
id="linearGradient3608"
|
||||
xlink:href="#linearGradient3681-3"
|
||||
inkscape:collect="always" />
|
||||
<linearGradient
|
||||
id="linearGradient4513-2">
|
||||
<stop
|
||||
style="stop-color:#ffffff;stop-opacity:1;"
|
||||
offset="0"
|
||||
id="stop4515-2" />
|
||||
<stop
|
||||
style="stop-color:#999999;stop-opacity:1;"
|
||||
offset="1"
|
||||
id="stop4517-4" />
|
||||
</linearGradient>
|
||||
<radialGradient
|
||||
r="23.634638"
|
||||
fy="7.9319997"
|
||||
fx="32.151962"
|
||||
cy="7.9319997"
|
||||
cx="32.151962"
|
||||
gradientTransform="matrix(1,0,0,1.1841158,-8.5173246,-3.4097568)"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
id="radialGradient4538"
|
||||
xlink:href="#linearGradient4513-2"
|
||||
inkscape:collect="always" />
|
||||
<linearGradient
|
||||
id="linearGradient4513-1">
|
||||
<stop
|
||||
style="stop-color:#ffffff;stop-opacity:1;"
|
||||
offset="0"
|
||||
id="stop4515-8" />
|
||||
<stop
|
||||
style="stop-color:#999999;stop-opacity:1;"
|
||||
offset="1"
|
||||
id="stop4517-6" />
|
||||
</linearGradient>
|
||||
<radialGradient
|
||||
r="23.634638"
|
||||
fy="7.9319997"
|
||||
fx="32.151962"
|
||||
cy="7.9319997"
|
||||
cx="32.151962"
|
||||
gradientTransform="matrix(1,0,0,1.1841158,-8.5173246,-3.4097568)"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
id="radialGradient4538-6"
|
||||
xlink:href="#linearGradient4513-1"
|
||||
inkscape:collect="always" />
|
||||
<linearGradient
|
||||
id="linearGradient4513-1-3">
|
||||
<stop
|
||||
style="stop-color:#ffffff;stop-opacity:1;"
|
||||
offset="0"
|
||||
id="stop4515-8-7" />
|
||||
<stop
|
||||
style="stop-color:#999999;stop-opacity:1;"
|
||||
offset="1"
|
||||
id="stop4517-6-5" />
|
||||
</linearGradient>
|
||||
<radialGradient
|
||||
r="23.634638"
|
||||
fy="35.869175"
|
||||
fx="32.151962"
|
||||
cy="35.869175"
|
||||
cx="32.151962"
|
||||
gradientTransform="matrix(0.39497909,0,0,1.1841158,-2.716491,-26.067007)"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
id="radialGradient3069"
|
||||
xlink:href="#linearGradient4513-1-3"
|
||||
inkscape:collect="always" />
|
||||
<linearGradient
|
||||
id="linearGradient4513-1-2">
|
||||
<stop
|
||||
style="stop-color:#ffffff;stop-opacity:1;"
|
||||
offset="0"
|
||||
id="stop4515-8-6" />
|
||||
<stop
|
||||
style="stop-color:#999999;stop-opacity:1;"
|
||||
offset="1"
|
||||
id="stop4517-6-6" />
|
||||
</linearGradient>
|
||||
<radialGradient
|
||||
r="23.634638"
|
||||
fy="35.869175"
|
||||
fx="32.151962"
|
||||
cy="35.869175"
|
||||
cx="32.151962"
|
||||
gradientTransform="matrix(0.39497909,0,0,1.1841158,-2.716491,-26.067007)"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
id="radialGradient3102"
|
||||
xlink:href="#linearGradient4513-1-2"
|
||||
inkscape:collect="always" />
|
||||
<radialGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient4513-1"
|
||||
id="radialGradient3132"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(0.39497909,0,0,1.1841158,64.952609,-7.0541574)"
|
||||
cx="32.151962"
|
||||
cy="27.950663"
|
||||
fx="32.151962"
|
||||
fy="27.950663"
|
||||
r="23.634638" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient4022"
|
||||
id="linearGradient4028"
|
||||
x1="36.538239"
|
||||
y1="45.928013"
|
||||
x2="36.804447"
|
||||
y2="23.332739"
|
||||
gradientUnits="userSpaceOnUse" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient4066"
|
||||
id="linearGradient4072"
|
||||
x1="41.610756"
|
||||
y1="59.853931"
|
||||
x2="32.101425"
|
||||
y2="10.99928"
|
||||
gradientUnits="userSpaceOnUse" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient4031"
|
||||
id="linearGradient4055"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="translate(71.494719,-3.1982556)"
|
||||
x1="30.000002"
|
||||
y1="14"
|
||||
x2="36"
|
||||
y2="54.227272" />
|
||||
<linearGradient
|
||||
id="linearGradient4031">
|
||||
<stop
|
||||
id="stop4033"
|
||||
offset="0"
|
||||
style="stop-color:#d3d7cf;stop-opacity:1" />
|
||||
<stop
|
||||
id="stop4035"
|
||||
offset="1"
|
||||
style="stop-color:#888a85;stop-opacity:1" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
gradientTransform="matrix(1.2000004,0,0,1.2000004,-14.000047,-24.000012)"
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient4022-3"
|
||||
id="linearGradient4028-3"
|
||||
x1="36.538239"
|
||||
y1="45.928013"
|
||||
x2="36.804447"
|
||||
y2="23.332739"
|
||||
gradientUnits="userSpaceOnUse" />
|
||||
</defs>
|
||||
<sodipodi:namedview
|
||||
id="base"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="3.8890873"
|
||||
inkscape:cx="21.739458"
|
||||
inkscape:cy="37.036095"
|
||||
inkscape:current-layer="layer1"
|
||||
showgrid="true"
|
||||
inkscape:document-units="px"
|
||||
inkscape:grid-bbox="true"
|
||||
inkscape:snap-bbox="true"
|
||||
inkscape:bbox-paths="true"
|
||||
inkscape:bbox-nodes="true"
|
||||
inkscape:snap-bbox-edge-midpoints="true"
|
||||
inkscape:snap-bbox-midpoints="true"
|
||||
inkscape:object-paths="true"
|
||||
inkscape:object-nodes="true"
|
||||
inkscape:window-width="1375"
|
||||
inkscape:window-height="876"
|
||||
inkscape:window-x="65"
|
||||
inkscape:window-y="24"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:snap-global="true">
|
||||
<inkscape:grid
|
||||
type="xygrid"
|
||||
id="grid3234"
|
||||
empspacing="2"
|
||||
visible="true"
|
||||
enabled="true"
|
||||
snapvisiblegridlinesonly="true" />
|
||||
</sodipodi:namedview>
|
||||
<metadata
|
||||
id="metadata2821">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title></dc:title>
|
||||
<dc:title>Path-FaceProfile</dc:title>
|
||||
<dc:date>2016-01-19</dc:date>
|
||||
<dc:relation>http://www.freecadweb.org/wiki/index.php?title=Artwork</dc:relation>
|
||||
<dc:publisher>
|
||||
<cc:Agent>
|
||||
<dc:title>FreeCAD</dc:title>
|
||||
</cc:Agent>
|
||||
</dc:publisher>
|
||||
<dc:identifier>FreeCAD/src/Mod/Path/Gui/Resources/icons/Path-</dc:identifier>
|
||||
<dc:rights>
|
||||
<cc:Agent>
|
||||
<dc:title>FreeCAD LGPL2+</dc:title>
|
||||
</cc:Agent>
|
||||
</dc:rights>
|
||||
<cc:license>https://www.gnu.org/copyleft/lesser.html</cc:license>
|
||||
<dc:contributor>
|
||||
<cc:Agent>
|
||||
<dc:title>[agryson] Alexander Gryson</dc:title>
|
||||
</cc:Agent>
|
||||
</dc:contributor>
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g
|
||||
id="layer1"
|
||||
inkscape:label="Layer 1"
|
||||
inkscape:groupmode="layer">
|
||||
<path
|
||||
style="color:#000000;fill:url(#linearGradient4028);fill-opacity:1;fill-rule:nonzero;stroke:#0b1521;stroke-width:2;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
|
||||
d="M 33,21 17,45 41,49 53,33 49,23 z"
|
||||
id="rect3083"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="cccccc" />
|
||||
<path
|
||||
style="color:#000000;fill:none;stroke:#172a04;stroke-width:8;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
|
||||
d="M 50,13 39,11 c -4,-1 -5.171573,-1.4142136 -8,0 -2,1 -3,2 -5,5 L 7,46 c -3,4 -1,7 3,8 l 28,4 c 5,1 9,-2 12,-6 l 4,-5"
|
||||
id="rect3083-0"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="ccscccccc" />
|
||||
<path
|
||||
style="color:#000000;fill:none;stroke:#729fcf;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
|
||||
d="M 33.965909,23.113636 20.349931,43.571429 40.140486,46.839294 50.710729,32.691101 47.57301,24.842851 z"
|
||||
id="rect3083-3"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="cccccc" />
|
||||
<path
|
||||
style="color:#000000;fill:none;stroke:url(#linearGradient4072);stroke-width:4;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
|
||||
d="M 50,13 39,11 c -4,-1 -5.171573,-1.414214 -8,0 -2,1 -3,2 -5,5 L 7,46 c -3,4 -1,7 3,8 l 28,4 c 5,1 9,-2 12,-6 l 4,-5"
|
||||
id="rect3083-0-6"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="ccscccccc" />
|
||||
<path
|
||||
style="color:#000000;fill:none;stroke:#8ae234;stroke-width:2;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
|
||||
d="M 50.064283,12 38.517882,9.919647 c -4,-1.0000001 -5.171573,-1.4142141 -8,0 -2,1 -3,2 -5,5 l -19.0000003,30 c -2.9999999,4 -1,7 2.9999998,8 l 28.0000005,4 c 5,1 9,-2 12,-6 L 53,46"
|
||||
id="rect3083-0-6-7"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="ccscccccc" />
|
||||
<path
|
||||
style="color:#000000;display:inline;overflow:visible;visibility:visible;opacity:0.84799978;fill:url(#linearGradient4028-3);fill-opacity:1.0;fill-rule:nonzero;stroke:#0b1521;stroke-width:2.40000081;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;enable-background:accumulate"
|
||||
d="M 25.599966,1.1999953 6.3999597,30.000005 35.199969,34.800007 49.599974,15.600001 44.799972,3.5999961 Z"
|
||||
id="rect3083-5"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="cccccc" />
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 23 KiB |
|
@ -86,7 +86,7 @@ class PathWorkbench (Workbench):
|
|||
threedopcmdlist = ["Path_Surfacing"]
|
||||
modcmdlist = ["Path_Copy", "Path_CompoundExtended", "Path_Array", "Path_SimpleCopy" ]
|
||||
dressupcmdlist = ["PathDressup_Dogbone", "PathDressup_DragKnife", "PathDressup_HoldingTags"]
|
||||
extracmdlist = ["Path_SelectLoop", "Path_Area"]
|
||||
extracmdlist = ["Path_SelectLoop", "Path_Area", "Path_Area_Workplane"]
|
||||
#modcmdmore = ["Path_Hop",]
|
||||
#remotecmdlist = ["Path_Remote"]
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user