Merge pull request #460 from realthunder/PathArea

Added Path.Area and Path::FeatureArea
This commit is contained in:
wwmayer
2017-02-04 11:36:21 +01:00
committed by GitHub
43 changed files with 7871 additions and 218 deletions

View File

@@ -98,6 +98,13 @@ if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_COMPILER_IS_CLANGXX)
endif()
endif(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_COMPILER_IS_CLANGXX)
if(CMAKE_COMPILER_IS_CLANGXX)
# older boost.preprocessor turn off variadics for clang
add_definitions(-DBOOST_PP_VARIADICS=1)
message(STATUS "Force BOOST_PP_VARIADICS=1 for clang")
endif()
# ================================================================================
# Output directories for install target

View File

@@ -147,7 +147,7 @@ struct EdgePoints {
TopoDS_Edge edge;
};
static std::list<TopoDS_Edge> sort_Edges(double tol3d, std::list<TopoDS_Edge>& edges)
PartExport std::list<TopoDS_Edge> sort_Edges(double tol3d, std::list<TopoDS_Edge>& edges)
{
tol3d = tol3d * tol3d;
std::list<EdgePoints> edge_points;

View File

@@ -105,7 +105,9 @@ PyObject* Curve2dPy::reverse(PyObject * args)
return 0;
}
namespace Part {
extern Py::Object shape2pyshape(const TopoDS_Shape &shape);
}
PyObject* Curve2dPy::toShape(PyObject *args)
{

View File

@@ -157,8 +157,9 @@ int TopoShapePy::PyInit(PyObject* args, PyObject*)
return 0;
}
namespace Part {
//common code.. maybe put somewhere else?
Py::Object shape2pyshape(const TopoDS_Shape &shape)
PartExport Py::Object shape2pyshape(const TopoDS_Shape &shape)
{
PyObject* ret = 0;
if (!shape.IsNull()) {
@@ -204,6 +205,7 @@ Py::Object shape2pyshape(const TopoDS_Shape &shape)
return Py::asObject(ret);
}
} //namespace Part
PyObject* TopoShapePy::copy(PyObject *args)
{

View File

@@ -42,6 +42,8 @@
#include "PropertyTooltable.h"
#include "FeaturePathCompound.h"
#include "FeaturePathShape.h"
#include "AreaPy.h"
#include "FeatureArea.h"
namespace Path {
extern PyObject* initModule();
@@ -50,15 +52,24 @@ extern PyObject* initModule();
/* Python entry */
PyMOD_INIT_FUNC(Path)
{
// load dependent module
try {
Base::Interpreter().runString("import Part");
}
catch(const Base::Exception& e) {
PyErr_SetString(PyExc_ImportError, e.what());
return;
}
PyObject* pathModule = Path::initModule();
Base::Console().Log("Loading Path module... done\n");
// Add Types to module
Base::Interpreter().addType(&Path::CommandPy ::Type, pathModule, "Command");
Base::Interpreter().addType(&Path::PathPy ::Type, pathModule, "Path");
Base::Interpreter().addType(&Path::ToolPy ::Type, pathModule, "Tool");
Base::Interpreter().addType(&Path::TooltablePy ::Type, pathModule, "Tooltable");
Base::Interpreter().addType(&Path::AreaPy ::Type, pathModule, "Area");
// NOTE: To finish the initialization of our own type objects we must
// call PyType_Ready, otherwise we run into a segmentation fault, later on.
@@ -75,6 +86,11 @@ PyMOD_INIT_FUNC(Path)
Path::FeatureCompoundPython ::init();
Path::FeatureShape ::init();
Path::FeatureShapePython ::init();
Path::Area ::init();
Path::FeatureArea ::init();
Path::FeatureAreaPython ::init();
Path::FeatureAreaView ::init();
Path::FeatureAreaViewPython ::init();
PyMOD_Return(pathModule);
}

View File

@@ -37,6 +37,7 @@
#include <App/DocumentObjectPy.h>
#include <App/Application.h>
#include <Mod/Part/App/OCCError.h>
#include <Mod/Part/App/TopoShape.h>
#include <Mod/Part/App/TopoShapePy.h>
#include <TopoDS.hxx>
@@ -57,7 +58,45 @@
#include "Path.h"
#include "FeaturePath.h"
#include "FeaturePathCompound.h"
#include "Area.h"
#define PATH_CATCH catch (Standard_Failure &e) \
{ \
std::string str; \
Standard_CString msg = e.GetMessageString(); \
str += typeid(e).name(); \
str += " "; \
if (msg) {str += msg;} \
else {str += "No OCCT Exception Message";} \
Base::Console().Error(str.c_str()); \
PyErr_SetString(Part::PartExceptionOCCError,str.c_str()); \
} \
catch(Base::Exception &e) \
{ \
std::string str; \
str += "FreeCAD exception thrown ("; \
str += e.what(); \
str += ")"; \
e.ReportException(); \
PyErr_SetString(Base::BaseExceptionFreeCADError,str.c_str());\
} \
catch(std::exception &e) \
{ \
std::string str; \
str += "STL exception thrown ("; \
str += e.what(); \
str += ")"; \
Base::Console().Error(str.c_str()); \
PyErr_SetString(Base::BaseExceptionFreeCADError,str.c_str());\
} \
catch(const char *e) \
{ \
PyErr_SetString(Base::BaseExceptionFreeCADError,e); \
} throw Py::Exception();
namespace Part {
extern PartExport Py::Object shape2pyshape(const TopoDS_Shape &shape);
}
namespace Path {
class Module : public Py::ExtensionModule<Module>
@@ -79,6 +118,23 @@ public:
add_varargs_method("fromShape",&Module::fromShape,
"fromShape(Shape): Returns a Path object from a Part Shape"
);
add_keyword_method("fromShapes",&Module::fromShapes,
"fromShapes(shapes, start=Vector(), " PARAM_PY_ARGS_DOC(ARG,AREA_PARAMS_PATH) ", key=value...)\n"
"\nReturns a Path object from a list of shapes\n"
"\n* shapes: input list of shapes.\n"
"\n* start (Vector()): optional start position.\n"
PARAM_PY_DOC(ARG, AREA_PARAMS_PATH)
"\n* <key>: any key supported by Path.Area, see Path.Area.getParamDesc() for description"
);
add_keyword_method("sortWires",&Module::sortWires,
"sortWires(shapes, start=Vector(), " PARAM_PY_ARGS_DOC(ARG,AREA_PARAMS_SORT) ", key=value...)\n"
"\nReturns (wires,end), where 'wires' is sorted accross Z value and with optimized travel distance,\n"
"and 'end' is the ending position of the whole wires\n"
"\n* shapes: input shape list\n"
"\n* start (Vector()): optional start position.\n"
PARAM_PY_DOC(ARG, AREA_PARAMS_SORT)
"\n* <key>: any key supported by Path.Area, see Path.Area.getParamDesc() for description"
);
initialize("This module is the Path module."); // register with Python
}
@@ -261,7 +317,115 @@ private:
throw Py::RuntimeError(e.what());
}
}
Py::Object fromShapes(const Py::Tuple& args, const Py::Dict &kwds)
{
PARAM_PY_DECLARE_INIT(PARAM_FARG,AREA_PARAMS_PATH)
PARAM_PY_DECLARE_INIT(PARAM_FNAME,AREA_PARAMS_CONF)
PyObject *pShapes=NULL;
PyObject *start=NULL;
static char* kwd_list[] = {"shapes", "start",
PARAM_FIELD_STRINGS(ARG,AREA_PARAMS_PATH),
PARAM_FIELD_STRINGS(NAME,AREA_PARAMS_CONF), NULL};
if (!PyArg_ParseTupleAndKeywords(args.ptr(), kwds.ptr(),
"O|O!" PARAM_PY_KWDS(AREA_PARAMS_PATH) PARAM_PY_KWDS(AREA_PARAMS_CONF),
kwd_list, &pShapes, &(Base::VectorPy::Type), &start,
PARAM_REF(PARAM_FARG,AREA_PARAMS_PATH),
PARAM_REF(PARAM_FNAME,AREA_PARAMS_CONF)))
throw Py::Exception();
std::list<TopoDS_Shape> shapes;
if (PyObject_TypeCheck(pShapes, &(Part::TopoShapePy::Type)))
shapes.push_back(static_cast<Part::TopoShapePy*>(pShapes)->getTopoShapePtr()->getShape());
else if (PyObject_TypeCheck(pShapes, &(PyList_Type)) ||
PyObject_TypeCheck(pShapes, &(PyTuple_Type)))
{
Py::Sequence shapeSeq(pShapes);
for (Py::Sequence::iterator it = shapeSeq.begin(); it != shapeSeq.end(); ++it) {
PyObject* item = (*it).ptr();
if(!PyObject_TypeCheck(item, &(Part::TopoShapePy::Type))) {
PyErr_SetString(PyExc_TypeError, "non-shape object in sequence");
throw Py::Exception();
}
shapes.push_back(static_cast<Part::TopoShapePy*>(item)->getTopoShapePtr()->getShape());
}
}
#define AREA_GET(_param) \
params.PARAM_FNAME(_param) = \
PARAM_TYPED(PARAM_CAST_PY_,_param)(PARAM_FNAME(_param));
AreaParams params;
PARAM_FOREACH(AREA_GET,AREA_PARAMS_CONF)
gp_Pnt pstart;
if(start) {
Base::Vector3d vec = static_cast<Base::VectorPy*>(start)->value();
pstart.SetCoord(vec.x, vec.y, vec.z);
}
try {
std::unique_ptr<Toolpath> path(new Toolpath);
Area::toPath(*path,shapes,&params, &pstart, NULL,
PARAM_PY_FIELDS(PARAM_FARG,AREA_PARAMS_PATH));
return Py::asObject(new PathPy(path.release()));
} PATH_CATCH
}
Py::Object sortWires(const Py::Tuple& args, const Py::Dict &kwds)
{
PARAM_PY_DECLARE_INIT(PARAM_FARG,AREA_PARAMS_SORT)
PARAM_PY_DECLARE_INIT(PARAM_FNAME,AREA_PARAMS_CONF)
PyObject *pShapes=NULL;
PyObject *start=NULL;
static char* kwd_list[] = {"shapes", "start",
PARAM_FIELD_STRINGS(ARG,AREA_PARAMS_SORT),
PARAM_FIELD_STRINGS(NAME,AREA_PARAMS_CONF), NULL};
if (!PyArg_ParseTupleAndKeywords(args.ptr(), kwds.ptr(),
"O|O!" PARAM_PY_KWDS(AREA_PARAMS_SORT) PARAM_PY_KWDS(AREA_PARAMS_CONF),
kwd_list, &pShapes, &(Base::VectorPy::Type), &start,
PARAM_REF(PARAM_FARG,AREA_PARAMS_SORT),
PARAM_REF(PARAM_FNAME,AREA_PARAMS_CONF)))
throw Py::Exception();
std::list<TopoDS_Shape> shapes;
if (PyObject_TypeCheck(pShapes, &(Part::TopoShapePy::Type)))
shapes.push_back(static_cast<Part::TopoShapePy*>(pShapes)->getTopoShapePtr()->getShape());
else if (PyObject_TypeCheck(pShapes, &(PyList_Type)) ||
PyObject_TypeCheck(pShapes, &(PyTuple_Type))) {
Py::Sequence shapeSeq(pShapes);
for (Py::Sequence::iterator it = shapeSeq.begin(); it != shapeSeq.end(); ++it) {
PyObject* item = (*it).ptr();
if(!PyObject_TypeCheck(item, &(Part::TopoShapePy::Type))) {
PyErr_SetString(PyExc_TypeError, "non-shape object in sequence");
throw Py::Exception();
}
shapes.push_back(static_cast<Part::TopoShapePy*>(item)->getTopoShapePtr()->getShape());
}
}
AreaParams params;
PARAM_FOREACH(AREA_GET,AREA_PARAMS_CONF)
gp_Pnt pstart,pend;
if(start) {
Base::Vector3d vec = static_cast<Base::VectorPy*>(start)->value();
pstart.SetCoord(vec.x, vec.y, vec.z);
}
try {
std::list<TopoDS_Shape> wires = Area::sortWires(shapes,&params,&pstart,
&pend, PARAM_PY_FIELDS(PARAM_FARG,AREA_PARAMS_SORT));
PyObject *list = PyList_New(0);
for(auto &wire : wires)
PyList_Append(list,Py::new_reference_to(
Part::shape2pyshape(TopoDS::Wire(wire))));
PyObject *ret = PyTuple_New(2);
PyTuple_SetItem(ret,0,list);
PyTuple_SetItem(ret,1,new Base::VectorPy(
Base::Vector3d(pend.X(),pend.Y(),pend.Z())));
return Py::asObject(ret);
} PATH_CATCH
}
};
PyObject* initModule()

1860
src/Mod/Path/App/Area.cpp Normal file

File diff suppressed because it is too large Load Diff

465
src/Mod/Path/App/Area.h Normal file
View File

@@ -0,0 +1,465 @@
/****************************************************************************
* Copyright (c) 2017 Zheng, Lei (realthunder) <realthunder.dev@gmail.com>*
* *
* This file is part of the FreeCAD CAx development system. *
* *
* This library is free software; you can redistribute it and/or *
* modify it under the terms of the GNU Library General Public *
* License as published by the Free Software Foundation; either *
* version 2 of the License, or (at your option) any later version. *
* *
* This library is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU Library General Public License for more details. *
* *
* You should have received a copy of the GNU Library General Public *
* License along with this library; see the file COPYING.LIB. If not, *
* write to the Free Software Foundation, Inc., 59 Temple Place, *
* Suite 330, Boston, MA 02111-1307, USA *
* *
****************************************************************************/
#ifndef PATH_AREA_H
#define PATH_AREA_H
#include <QApplication>
#include <chrono>
#include <memory>
#include <vector>
#include <list>
#include <TopoDS.hxx>
#include <gp_Pln.hxx>
#include <gp_Circ.hxx>
#include <gp_GTrsf.hxx>
#include <Base/Console.h>
#include "Path.h"
#include "AreaParams.h"
#define _AREA_LOG(_l,_msg) do {\
if(Area::_l##Enabled()){\
std::stringstream str;\
str << "Path.Area: " << _msg;\
Base::Console()._l("%s\n",str.str().c_str());\
}\
qApp->sendPostedEvents();\
if(Area::aborting()) {\
Area::abort(false);\
throw Base::AbortException("operation aborted");\
}\
}while(0)
#define AREA_LOG(_msg) _AREA_LOG(Log,_msg)
#define AREA_WARN(_msg) _AREA_LOG(Warning,_msg)
#define AREA_ERR(_msg) _AREA_LOG(Error,_msg)
#define AREA_PT(_pt) '('<<(_pt).X()<<", " << (_pt).Y()<<", " << (_pt).Z()<<')'
#define AREA_PT2(_pt) '('<<(_pt).x<<", " << (_pt).y<<')'
#define AREA_TRACE(_msg) do{\
if(Area::TraceEnabled()) AREA_LOG('('<<__LINE__<<"): " <<_msg);\
}while(0)
#define AREA_TIME_ENABLE
#ifdef AREA_TIME_ENABLE
#define TIME_UNIT duration<double>
#define TIME_CLOCK high_resolution_clock
#define TIME_POINT std::chrono::TIME_CLOCK::time_point
#define TIME_INIT(_t) \
auto _t=std::chrono::TIME_CLOCK::now()
#define TIME_INIT2(_t1,_t2) TIME_INIT(_t1),_t2=_t1
#define TIME_INIT3(_t1,_t2,_t3) TIME_INIT(_t1),_t2=_t1,_t3=_t1
#define _DURATION_PRINT(_l,_d,_msg) \
AREA_##_l(_msg<< " time: " << _d.count()<<'s');
#define DURATION_PRINT(_d,_msg) _DURATION_PRINT(LOG,_d,_msg)
#define TIME_PRINT(_t,_msg) \
DURATION_PRINT(Path::getDuration(_t),_msg);
#define TIME_TRACE(_t,_msg) \
_DURATION_PRINT(TRACE,Path::getDuration(_t),_msg);
#define DURATION_INIT(_d) \
std::chrono::TIME_UNIT _d(0)
#define DURATION_INIT2(_d1,_d2) DURATION_INIT(_d1),_d2(0)
namespace Path {
inline std::chrono::TIME_UNIT getDuration(TIME_POINT &t)
{
auto tnow = std::chrono::TIME_CLOCK::now();
auto d = std::chrono::duration_cast<std::chrono::TIME_UNIT>(tnow-t);
t = tnow;
return d;
}
}
#define DURATION_PLUS(_d,_t) _d += Path::getDuration(_t)
#else
#define TIME_INIT(...) do{}while(0)
#define TIME_INIT2(...) do{}while(0)
#define TIME_INIT3(...) do{}while(0)
#define TIME_PRINT(...) do{}while(0)
#define DURATION_PRINT(...) do{}while(0)
#define DURATION_INIT(...) do{}while(0)
#define DURATION_INIT2(...) do{}while(0)
#define DURATION_PLUS(...) do{}while(0)
#endif
class CArea;
class CCurve;
namespace Path
{
/** Store libarea algorithm configuration */
struct PathExport CAreaParams {
PARAM_DECLARE(PARAM_FNAME,AREA_PARAMS_CAREA)
CAreaParams();
};
/** Store all Area configurations */
struct PathExport AreaParams: CAreaParams {
PARAM_DECLARE(PARAM_FNAME,AREA_PARAMS_AREA)
bool operator==(const AreaParams &other) const {
#define AREA_COMPARE(_param) \
if(PARAM_FIELD(NAME,_param)!=other.PARAM_FIELD(NAME,_param)) return false;
PARAM_FOREACH(AREA_COMPARE,AREA_PARAMS_CAREA)
PARAM_FOREACH(AREA_COMPARE,AREA_PARAMS_AREA)
return true;
}
bool operator!=(const AreaParams &other) const {
return !(*this == other);
}
AreaParams();
};
struct PathExport AreaStaticParams: AreaParams {
PARAM_DECLARE(PARAM_FNAME,AREA_PARAMS_EXTRA_CONF);
AreaStaticParams();
};
/** libarea configurator
*
* It is kind of troublesome with the fact that libarea uses static variables to
* config its algorithm. CAreaConfig makes it easy to safely customize libarea.
*/
struct PathExport CAreaConfig {
/** For saving current libarea settings */
PARAM_DECLARE(PARAM_FNAME,AREA_PARAMS_CAREA)
/** The constructor automatically saves current setting and apply user defined ones
*
* \arg \c p user defined configurations
* \arg \c noFitArgs if true, will override and disable arc fitting. Because
* arc unfiting and fitting is lossy. And repeatedly perform these operation
* may cause shape deformation. So it is best to delay arc fitting until the
* final step*/
CAreaConfig(const CAreaParams &p, bool noFitArcs=true);
/** The destructor restores the setting, and thus exception safe. */
~CAreaConfig();
};
/** Base class for FreeCAD wrapping of libarea */
class PathExport Area: public Base::BaseClass {
TYPESYSTEM_HEADER();
public:
struct Shape {
short op;
TopoDS_Shape shape;
Shape(short opCode, const TopoDS_Shape &s)
:op(opCode)
,shape(s)
{}
};
protected:
std::list<Shape> myShapes;
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;
static bool s_aborting;
static AreaStaticParams s_params;
/** Called internally to combine children shapes for further processing */
void build();
/** Called by build() to add children shape
*
* Mainly for checking if there is any faces for auto fill*/
void addToBuild(CArea &area, const TopoDS_Shape &shape);
/** Called internally to obtain the combained children shapes */
TopoDS_Shape toShape(CArea &area, short fill);
/** 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();
void explode(const TopoDS_Shape &shape);
bool isBuilt() const;
TopoDS_Shape findPlane(const TopoDS_Shape &shape, gp_Trsf &trsf);
public:
/** Declare all parameters defined in #AREA_PARAMS_ALL as member variable */
PARAM_ENUM_DECLARE(AREA_PARAMS_ALL)
Area(const AreaParams *params = NULL);
Area(const Area &other, bool deep_copy=true);
virtual ~Area();
/** Set a working plane
*
* \arg \c shape: a shape defining a working plane.
*
* The supplied shape does not need to be planar. Area will try to find planar
* sub-shape (face, wire or edge). If more than one planar sub-shape is found,
* it will prefer the top plane parallel to XY0 plane.
*
* If no working plane are set, Area will try to find a working plane from
* the added children shape using the same algorithm
*/
void setPlane(const TopoDS_Shape &shape);
/** Return the current active workplane
*
* \arg \c trsf: optional return of a transformation matrix that will bring the
* found plane to XY0 plane.
*
* If no workplane is set using setPlane(), the active workplane is derived from
* the added children shapes using the same algorithm empolyed by setPlane().
*/
TopoDS_Shape getPlane(gp_Trsf *trsf = NULL);
/** Add a child shape with given operation code
*
* No validation is done at this point. Exception will be thrown when asking
* for output shape, if any of the children shapes is not valid or not
* coplanar
*
* \arg \c shape: the child shape
* \arg \c op: operation code, see #AREA_PARAMS_OPCODE
*/
void add(const TopoDS_Shape &shape,PARAM_ARGS_DEF(PARAM_FARG,AREA_PARAMS_OPCODE));
/** Generate an offset of the combined shape
*
* See #AREA_PARAMS_OFFSET for description of the arguments.
* 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(int index=-1, 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(int index=-1, PARAM_ARGS_DEF(PARAM_FARG,AREA_PARAMS_POCKET));
std::vector<std::shared_ptr<Area> > makeSections(
PARAM_ARGS_DEF(PARAM_FARG,AREA_PARAMS_SECTION_EXTRA),
const std::vector<double> &_heights = std::vector<double>(),
const TopoDS_Shape &plane = TopoDS_Shape());
/** Config this Area object */
void setParams(const AreaParams &params);
const std::list<Shape> getChildren() const {
return myShapes;
}
/** Get the current configuration */
const AreaParams &getParams() const {
return myParams;
}
/** Clean internal caches
*
* The combained shapes is cached internally to make other operation more
* efficient, such as makeOffset() and makePocket()
*
* \arg \c deleteShapes: if true, delete all children shapes.
*/
void clean(bool deleteShapes=false);
/** Get the combined shape
* \arg \c index: index of the section, -1 for all sections. No effect on
* non-sectioned area.
*/
TopoDS_Shape getShape(int index=-1);
/** Return the number of sections */
std::size_t getSectionCount() {
build();
return mySections.size();
}
/** Add a OCC wire shape to CArea
*
* \arg \c area: output converted curved object to here
* \arg \c wire: input wire object
* \arg \c trsf: optional transform matrix to transform the wire shape into
* XY0 plane.
* \arg \c deflection: for discretizing non circular curves
* \arg \c to_edges: if true, discretize all curves, and insert as open
* line segments
* */
static void add(CArea &area, const TopoDS_Wire &wire, const gp_Trsf *trsf=NULL,
double deflection=0.01, bool to_edges=false);
/** Output a list or sorted wire with minimize traval distance
*
* \arg \c index: index of the section, -1 for all sections. No effect on
* non-sectioned area.
* \arg \c count: number of the sections to return, <=0 for all sections
* after \c index. No effect on non-sectioned area.
* \arg \c pstart: optional start point
* \arg \c pend: optional output containing the ending point of the returned
* wires
* \arg \c allow_Break: whether allow to break open wires
*
* See #AREA_PARAMS_SORT for other arguments
*
* \return sorted wires
* */
std::list<TopoDS_Shape> sortWires(int index=-1, int count=0,
const gp_Pnt *pstart=NULL, gp_Pnt *pend=NULL,
PARAM_ARGS_DEF(PARAM_FARG,AREA_PARAMS_SORT));
/** Add a OCC generic shape to CArea
*
* \arg \c area: output converted curved object to here
* \arg \c shape: input shape object
* \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 reorient: reorient closed wires for wire only shape
*
* \return Returns the number of non coplaner. Planar testing only happens
* if \c plane is supplied
* */
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 reorient=true);
/** Convert curves in CArea into an OCC shape
*
* \arg \c area: input area object
* \arg \c fill: if true, create a face object from the wires
* \arg \c trsf: optional transform matrix to transform the shape back into
* its original position.
* */
static TopoDS_Shape toShape(const CArea &area, bool fill,
const gp_Trsf *trsf=NULL);
/** Convert a single curve into an OCC wire
*
* \arg \c curve: input curve object
* \arg \c trsf: optional transform matrix to transform the shape back into
* its original position.
* */
static TopoDS_Wire toShape(const CCurve &curve, const gp_Trsf *trsf=NULL);
/** Check if two OCC shape is coplanar */
static bool isCoplanar(const TopoDS_Shape &s1, const TopoDS_Shape &s2);
/** Group shapes by their plane, and return a list of sorted wires
*
* The output wires is ordered by its occupied plane, and sorted to
* minimize traval distance
*
* \arg \c shapes: input list of shapes.
* \arg \c params: optional Area parameters for the Area object internally
* used for sorting
* \arg \c pstart: optional start point
* \arg \c pend: optional output containing the ending point of the returned
*
* See #AREA_PARAMS_SORT for other arguments
*
* \return sorted wires
*/
static std::list<TopoDS_Shape> sortWires(const std::list<TopoDS_Shape> &shapes,
const AreaParams *params = NULL, const gp_Pnt *pstart=NULL,
gp_Pnt *pend=NULL, PARAM_ARGS_DEF(PARAM_FARG,AREA_PARAMS_SORT));
/** Convert a list of wires to gcode
*
* \arg \c path: output toolpath
* \arg \c shapes: input list of shapes
* \arg \c params: optional Area parameters for the Area object internally
* used for sorting
* \arg \c pstart: output start point,
* \arg \c pend: optional output containing the ending point of the returned
*
* See #AREA_PARAMS_PATH for other arguments
*/
static void toPath(Toolpath &path, const std::list<TopoDS_Shape> &shapes,
const AreaParams *params=NULL, const gp_Pnt *pstart=NULL, gp_Pnt *pend=NULL,
PARAM_ARGS_DEF(PARAM_FARG,AREA_PARAMS_PATH));
PARAM_ENUM_DECLARE(AREA_PARAMS_PATH)
static void abort(bool aborting);
static bool aborting();
static void setDefaultParams(const AreaStaticParams &params);
static const AreaStaticParams &getDefaultParams();
#define AREA_LOG_CHECK_DECLARE(_1,_2,_elem) \
static bool BOOST_PP_CAT(_elem,Enabled)();
BOOST_PP_SEQ_FOR_EACH(AREA_LOG_CHECK_DECLARE,_,AREA_PARAM_LOG_LEVEL)
PARAM_ENUM_DECLARE(AREA_PARAMS_LOG_LEVEL)
};
} //namespace Path
#endif //PATH_AREA_H

View File

@@ -0,0 +1,223 @@
/****************************************************************************
* Copyright (c) 2017 Zheng, Lei (realthunder) <realthunder.dev@gmail.com>*
* *
* This file is part of the FreeCAD CAx development system. *
* *
* This library is free software; you can redistribute it and/or *
* modify it under the terms of the GNU Library General Public *
* License as published by the Free Software Foundation; either *
* version 2 of the License, or (at your option) any later version. *
* *
* This library is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU Library General Public License for more details. *
* *
* You should have received a copy of the GNU Library General Public *
* License along with this library; see the file COPYING.LIB. If not, *
* write to the Free Software Foundation, Inc., 59 Temple Place, *
* Suite 330, Boston, MA 02111-1307, USA *
* *
****************************************************************************/
#ifndef PATH_AreaParams_H
#define PATH_AreaParams_H
// deifne this to enable offset algo selection
// #define AREA_OFFSET_ALGO
/** \file
* Parameters definition for Path::Area and its companion
* See \ref ParamPage "here" for details of parameter definition.
*/
#include "ParamsHelper.h"
/** clipper fill type */
#define AREA_CLIPPER_FILL_TYPE \
(NonZero)(EvenOdd)(Positive)(Negative),(ClipperLib::PolyFillType,ClipperLib::pft)
/** Paramerters of clipper fill types */
#define AREA_PARAMS_CLIPPER_FILL \
((enum2,subject_fill,SubjectFill,0,\
"ClipperLib subject fill type. \nSee https://goo.gl/5pYQQP",AREA_CLIPPER_FILL_TYPE))\
((enum2,clip_fill,ClipFill,0,\
"ClipperLib clip fill type. \nSee https://goo.gl/5pYQQP",AREA_CLIPPER_FILL_TYPE))
/** Deflection parameter */
#define AREA_PARAMS_DEFLECTION \
((double,deflection,Deflection,0.01,\
"Deflection for non circular curve discretization. It also also used for\n"\
"discretizing circular wires when you 'Explode' the shape for wire operations"))
/** Base parameters */
#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. 'Force' will discard non coplaner shapes,\n"\
"but 'Check' only gives warning.",(None)(Check)(Force)))\
((bool,reorient,Reorient,true,\
"Re-orient closed wires in wire only shapes so that inner wires become holes."))\
((bool,explode,Explode,false,\
"If true, Area will explode the first shape into disconnected open edges, \n"\
"with all curves discretized, so that later operations like 'Difference' \n"\
"behave like wire cutting. Without exploding, 'Difference' in ClipperLib\n"\
"behave like face cutting."))\
((enum,open_mode,OpenMode,0,\
"Specify how to handle open wires. 'None' means combin without openeration.\n"\
"'Edges' means separate to edges before Union. ClipperLib seems to have an.\n"\
"urge to close open wires.",(None)(Union)(Edges)))\
AREA_PARAMS_DEFLECTION \
AREA_PARAMS_CLIPPER_FILL
#define AREA_PARAMS_FIT_ARCS \
((bool,fit_arcs,FitArcs,true,"Enable arc fitting"))
/** libarea algorithm option parameters */
#define AREA_PARAMS_CAREA \
((double,tolerance,Tolerance,Precision::Confusion(),"Point coincidence tolerance"))\
AREA_PARAMS_FIT_ARCS \
((bool,clipper_simple,Simplify,false,\
"Simplify polygons after operation. See https://goo.gl/Mh9XK1"))\
((double,clipper_clean_distance,CleanDistance,0.0,\
"Clean polygon smaller than this distance. See https://goo.gl/jox3JY"))\
((double,accuracy,Accuracy,0.01,"Arc fitting accuracy"))\
((double,units,Unit,1.0,"Scaling factor for convertion to inch"))\
((short,min_arc_points,MinArcPoints,4,"Minimum segments for arc discretization"))\
((short,max_arc_points,MaxArcPoints,100,"Maximum segments for arc discretization"))\
((double,clipper_scale,ClipperScale,10000.0,\
"ClipperLib operate on intergers. This is the scale factor to convert\n"\
"floating points."))
/** Pocket parameters
*
* These parameters cooresponds to CAreaPocketParams in libarea
* */
#define AREA_PARAMS_POCKET \
((enum,mode,PocketMode,0,"Selects the pocket toolpath pattern",(None)(ZigZag)(Offset)(Spiral)(ZigZagOffset)))\
((double,tool_radius,ToolRadius,1.0,"Tool radius for pocketing"))\
((double,extra_offset,PocketExtraOffset,0.0,"Extra offset for pocketing"))\
((double,stepover,PocketStepover,0.0,"Cutter diameter to step over on each pass. If =0, use ToolRadius."))\
((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 \
((enum,op,Operation,0,"Boolean operation.\n"\
"For the first four operations, see https://goo.gl/Gj8RUu.\n"\
"'Compound' means no operation, normally used to do Area.sortWires().",\
(Union)(Difference)(Intersection)(Xor)(Compound)))
/** Offset parameters */
#define AREA_PARAMS_OFFSET \
((double,offset,Offset,0.0,"Offset value, positive for expansion, negative for shrinking"))\
((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"))
#define AREA_PARAMS_SECTION_EXTRA \
((enum,mode,SectionMode,2,"Section offset coordinate mode.\n"\
"'Absolute' means the absolute Z height to start section.\n"\
"'BoundBox' means relative Z height to the bounding box of all the children shape. Only\n"\
"positive value is allowed, which specifies the offset below the top Z of the bounding box.\n"\
"Note that OCC has trouble getting the minimumi bounding box of some solids, particually\n"\
"those with non-planar surface.\n"\
"'Workplane' means relative to workplane.",\
(Absolute)(BoundBox)(Workplane)))
/** 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"))\
AREA_PARAMS_SECTION_EXTRA
#ifdef AREA_OFFSET_ALGO
# define AREA_PARAMS_OFFSET_ALGO \
((enum,algo,Algo,0,"Offset algorithm type",(Clipper)(libarea)))
#else
# define AREA_PARAMS_OFFSET_ALGO
#endif
/** Offset configuration parameters */
#define AREA_PARAMS_OFFSET_CONF \
AREA_PARAMS_OFFSET_ALGO \
((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",\
(OpenRound)(ClosedPolygon)(ClosedLine)(OpenSquare)(OpenButt),(ClipperLib::EndType,ClipperLib::et)))\
((double,miter_limit,MiterLimit,2.0,"Miter limit for joint type Miter. See https://goo.gl/K8xX9h"))\
((double,round_precision,RoundPreceision,0.0,\
"Round joint precision. If =0, it defaults to Accuracy. \nSee https://goo.gl/4odfQh"))
#define AREA_PARAMS_MIN_DIST \
((double, min_dist, MinDistance, 0.0, \
"minimum distance for the generated new wires. Wires maybe broken if the\n"\
"algorithm see fits. Set to zero to disable wire breaking."))
/** Area wire sorting parameters */
#define AREA_PARAMS_SORT \
((enum, sort_mode, SortMode, 1, "Wire sorting mode to optimize travel distance.\n"\
"'2D5' explode shapes into wires, and groups the shapes by its plane. The 'start' position\n"\
"chooses the first plane to start. The algorithm will then sort within the plane and then\n"\
"move on to the next nearest plane.\n"\
"'3D' makes no assumption of planarity. The sorting is done across 3D space\n",\
(None)(2D5)(3D)))\
AREA_PARAMS_MIN_DIST
/** Area path generation parameters */
#define AREA_PARAMS_PATH \
AREA_PARAMS_SORT \
((double, threshold, RetractThreshold, 0.0,\
"If two wire's end points are separated within this threshold, they are consider\n"\
"as connected. You may want to set this to the tool diameter to keep the tool down."))\
((double, height, RetractHeight, 0.0,"Tool retraction absolute height"))\
((double, clearance, Clearance, 0.0,\
"When return from last retraction, this gives the pause height relative to the Z\n"\
"value of the next move"))\
((double,segmentation,Segmentation,0.0,\
"Break long curves into segments of this length. One use case is for PCB autolevel,\n"\
"so that more correction points can be inserted"))
#define AREA_PARAMS_PATH_EXTRA \
AREA_PARAMS_DEFLECTION \
AREA_PARAMS_FIT_ARCS
#define AREA_PARAMS_PATH_CONF \
AREA_PARAMS_PATH \
AREA_PARAMS_PATH_EXTRA
/** 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_AREA
/** Group of all Area parameters */
#define AREA_PARAMS_ALL \
AREA_PARAMS_CONF \
AREA_PARAMS_OPCODE
#define AREA_PARAM_LOG_LEVEL (Error)(Warning)(Log)(Trace)
#define AREA_PARAMS_LOG_LEVEL \
((enum, log_level, LogLevel, 1, "Area log level", AREA_PARAM_LOG_LEVEL))
#define AREA_PARAMS_EXTRA_CONF \
AREA_PARAMS_LOG_LEVEL
#define AREA_PARAMS_STATIC_CONF \
AREA_PARAMS_CONF \
AREA_PARAMS_EXTRA_CONF
#endif //PATH_AreaParam_H

114
src/Mod/Path/App/AreaPy.xml Normal file
View File

@@ -0,0 +1,114 @@
<?xml version="1.0" encoding="UTF-8"?>
<GenerateModel xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="generateMetaModel_Module.xsd">
<PythonExport
Father="BaseClassPy"
Name="AreaPy"
Twin="Area"
TwinPointer="Area"
Include="Mod/Path/App/Area.h"
Namespace="Path"
FatherInclude="Base/BaseClassPy.h"
FatherNamespace="Base"
Constructor="true"
Delete="true">
<Documentation>
<Author Licence="LGPL" Name="Zheng, Lei" EMail="realthunder.dev@gmail.com" />
<UserDocu>FreeCAD python wrapper of libarea\n
Path.Area(key=value ...)\n
The constuctor accepts the same parameters as setParams(...) to configure the object
All arguments are optional.</UserDocu>
</Documentation>
<Methode Name="add" Keyword='true'>
<Documentation>
<UserDocu></UserDocu>
</Documentation>
</Methode>
<Methode Name="setPlane">
<Documentation>
<UserDocu>setPlane(shape): Set the working plane.\n
The supplied shape does not need to be planar. Area will try to find planar
sub-shape (face, wire or edge). If more than one planar sub-shape is found, it
will prefer the top plane parallel to XY0 plane. If no working plane are set,
Area will try to find a working plane from the added children shape using the
same algorithm</UserDocu>
</Documentation>
</Methode>
<Methode Name="getShape" Keyword='true'>
<Documentation>
<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'>
<Documentation>
<UserDocu></UserDocu>
</Documentation>
</Methode>
<Methode Name="makePocket" Keyword='true'>
<Documentation>
<UserDocu></UserDocu>
</Documentation>
</Methode>
<Methode Name="makeSections" Keyword="true">
<Documentation>
<UserDocu></UserDocu>
</Documentation>
</Methode>
<Methode Name="setParams" Keyword="true">
<Documentation>
<UserDocu></UserDocu>
</Documentation>
</Methode>
<Methode Name="setDefaultParams" Keyword="true">
<Documentation>
<UserDocu></UserDocu>
</Documentation>
</Methode>
<Methode Name="getDefaultParams">
<Documentation>
<UserDocu></UserDocu>
</Documentation>
</Methode>
<Methode Name="getParamsDesc" Keyword="true">
<Documentation>
<UserDocu>getParamsDesc(as_string=True): Returns a list of supported parameters and their descriptions.\n
* as_string: if False, then return a dictionary of documents of all supported parameters.
</UserDocu>
</Documentation>
</Methode>
<Methode Name="sortWires" Keyword="true">
<Documentation>
<UserDocu></UserDocu>
</Documentation>
</Methode>
<Methode Name="getParams">
<Documentation>
<UserDocu>Get current algorithm parameters as a dictionary.</UserDocu>
</Documentation>
</Methode>
<Methode Name="abort" Keyword="true">
<Documentation>
<UserDocu></UserDocu>
</Documentation>
</Methode>
<Attribute Name="Sections" ReadOnly="true">
<Documentation>
<UserDocu>List of sections in this area.</UserDocu>
</Documentation>
<Parameter Name="Sections" Type="List"/>
</Attribute>
<Attribute Name="Workplane" ReadOnly="true">
<Documentation>
<UserDocu>The current workplane. If no plane is set, it is derived from the added shapes.</UserDocu>
</Documentation>
<Parameter Name="Workplane" Type="Object"/>
</Attribute>
<Attribute Name="Shapes" ReadOnly="true">
<Documentation>
<UserDocu>A list of tuple: [(shape,op), ...] containing the added shapes together with their operation code</UserDocu>
</Documentation>
<Parameter Name="Shapes" Type="List"/>
</Attribute>
</PythonExport>
</GenerateModel>

View File

@@ -0,0 +1,495 @@
/****************************************************************************
* Copyright (c) 2017 Zheng, Lei (realthunder) <realthunder.dev@gmail.com>*
* *
* This file is part of the FreeCAD CAx development system. *
* *
* This library is free software; you can redistribute it and/or *
* modify it under the terms of the GNU Library General Public *
* License as published by the Free Software Foundation; either *
* version 2 of the License, or (at your option) any later version. *
* *
* This library is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU Library General Public License for more details. *
* *
* You should have received a copy of the GNU Library General Public *
* License along with this library; see the file COPYING.LIB. If not, *
* write to the Free Software Foundation, Inc., 59 Temple Place, *
* Suite 330, Boston, MA 02111-1307, USA *
* *
****************************************************************************/
#include "PreCompiled.h"
#include <Mod/Part/App/TopoShapePy.h>
#include <Base/VectorPy.h>
#include "Area.h"
// inclusion of the generated files (generated out of AreaPy.xml)
#include "AreaPy.h"
#include "AreaPy.cpp"
static PyObject * areaAbort(PyObject *, PyObject *args, PyObject *kwd) {
static char *kwlist[] = {"aborting", NULL};
PyObject *pObj = Py_True;
if (!PyArg_ParseTupleAndKeywords(args,kwd,"|O",kwlist,&pObj))
return 0;
Area::abort(PyObject_IsTrue(pObj));
return Py_None;
}
static PyObject * areaSetParams(PyObject *, PyObject *args, PyObject *kwd) {
static char *kwlist[] = {PARAM_FIELD_STRINGS(NAME,AREA_PARAMS_STATIC_CONF),NULL};
//Declare variables defined in the NAME field of the CONF parameter list
PARAM_PY_DECLARE(PARAM_FNAME,AREA_PARAMS_STATIC_CONF);
AreaStaticParams params = Area::getDefaultParams();
#define AREA_SET(_param) \
PARAM_FNAME(_param) = \
PARAM_TYPED(PARAM_PY_CAST_,_param)(params.PARAM_FNAME(_param));
//populate the CONF variables with params
PARAM_FOREACH(AREA_SET,AREA_PARAMS_STATIC_CONF)
//Parse arguments to overwrite CONF variables
if (!PyArg_ParseTupleAndKeywords(args, kwd,
"|" PARAM_PY_KWDS(AREA_PARAMS_STATIC_CONF), kwlist,
PARAM_REF(PARAM_FNAME,AREA_PARAMS_STATIC_CONF)))
return 0;
#define AREA_GET(_param) \
params.PARAM_FNAME(_param) = \
PARAM_TYPED(PARAM_CAST_PY_,_param)(PARAM_FNAME(_param));
//populate 'params' with the CONF variables
PARAM_FOREACH(AREA_GET,AREA_PARAMS_STATIC_CONF)
Area::setDefaultParams(params);
return Py_None;
}
static PyObject* areaGetParams(PyObject *, PyObject *args) {
if (!PyArg_ParseTuple(args, ""))
return 0;
const AreaStaticParams &params = Area::getDefaultParams();
PyObject *dict = PyDict_New();
#define AREA_SRC(_param) params.PARAM_FNAME(_param)
PARAM_PY_DICT_SET_VALUE(dict,NAME,AREA_SRC,AREA_PARAMS_STATIC_CONF)
return dict;
}
static const PyMethodDef areaOverrides[] = {
{
"setParams",NULL,0,
"setParam(key=value...): Set algorithm parameters. You can call getParamsDesc() to \n"
"get a list of supported parameters and their descriptions.\n"
PARAM_PY_DOC(NAME,AREA_PARAMS_CONF)
},
{
"add",NULL,0,
"add((shape...)," PARAM_PY_ARGS_DOC(ARG,AREA_PARAMS_OPCODE) "):\n"
"Add TopoShape(s) with given operation code\n"
PARAM_PY_DOC(ARG,AREA_PARAMS_OPCODE)
"\nThe first shape's wires will be unioned together regardless of the op code given\n"
"(except for 'Compound'). Subsequent shape's wire will be combined using the op code.\n"
"All shape wires shall be coplanar, and are used to determine a working plane for face\n"
"making and offseting. You can call setPlane() to supply a reference shape to determin\n"
"the workplane in case the added shapes are all colinear lines.\n",
},
{
"makeOffset",NULL,0,
"makeOffset(index=-1, " PARAM_PY_ARGS_DOC(ARG,AREA_PARAMS_OFFSET) "):\n"
"Make an 2D offset 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_OFFSET),
},
{
"makePocket",NULL,0,
"makePocket(index=-1, " 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),
},
{
"makeSections",NULL,0,
"makeSections(" PARAM_PY_ARGS_DOC(ARG,AREA_PARAMS_SECTION_EXTRA) ", heights=[], plane=None):\n"
"Make a list of area holding the sectioned children shapes on given heights\n"
PARAM_PY_DOC(ARG,AREA_PARAMS_SECTION_EXTRA)
"\n* heights ([]): a list of section heights, the meaning of the value is determined by 'mode'.\n"
"If not specified, the current SectionCount, and SectionOffset of this Area is used.\n"
"\n* plane (None): optional shape to specify a section plane. If not give, the current workplane\n"
"of this Area is used.",
},
{
"sortWires",NULL,0,
"sortWires(index=-1, count=0, start=Vector(), allow_break=False, " PARAM_PY_ARGS_DOC(ARG,AREA_PARAMS_SORT) "):\n"
"Returns a tuple (wires,end): sorted wires with minimized travel distance, and the endpoint\n"
"of the wires.\n"
"\n* index (-1): the index of the section. -1 means all sections. No effect on planar shape.\n"
"\n* count (0): the number of sections to return. <=0 means all sections starting from index.\n"
"\n* start (Vector()): a vector specifies the start point.\n"
PARAM_PY_DOC(ARG,AREA_PARAMS_SORT),
},
{
"setDefaultParams",(PyCFunction)areaSetParams, METH_VARARGS|METH_KEYWORDS|METH_STATIC,
"setDefaultParams(" PARAM_PY_ARGS_DOC(NAME,AREA_PARAMS_EXTRA_CONF) ", key=value...):\n"
"Static method to set the default parameters of all following Path.Area, plus the following\n"
"additional parameters.\n"
PARAM_PY_DOC(NAME,AREA_PARAMS_EXTRA_CONF)
},
{
"getDefaultParams",(PyCFunction)areaGetParams, METH_VARARGS|METH_STATIC,
"getDefaultParams(): Static method to return the current default parameters."
},
{
"abort",(PyCFunction)areaAbort, METH_VARARGS|METH_KEYWORDS|METH_STATIC,
"abort(aborting=True): Static method to abort any ongoing operation\n"
"\nTo ensure no stray abortion is left in the previous operaion, it is advised to manually clear\n"
"the aborting flag by calling abort(False) before starting a new operation.",
},
};
struct AreaPyModifier {
AreaPyModifier() {
for(auto &method : Path::AreaPy::Methods) {
if(!method.ml_name) continue;
for(auto &entry : areaOverrides) {
if(std::strcmp(method.ml_name,entry.ml_name)==0) {
if(entry.ml_doc)
method.ml_doc = entry.ml_doc;
if(entry.ml_meth)
method.ml_meth = entry.ml_meth;
if(entry.ml_flags)
method.ml_flags = entry.ml_flags;
break;
}
}
}
}
};
static AreaPyModifier mod;
namespace Part {
extern PartExport Py::Object shape2pyshape(const TopoDS_Shape &shape);
}
using namespace Path;
// returns a string which represents the object e.g. when printed in python
std::string AreaPy::representation(void) const
{
std::stringstream str;
str << "<Area object at " << getAreaPtr() << ">";
return str.str();
}
PyObject *AreaPy::PyMake(struct _typeobject *, PyObject *args, PyObject *kwd) // Python wrapper
{
std::unique_ptr<AreaPy> ret(new AreaPy(new Area));
if(!ret->setParams(args,kwd))
return 0;
return ret.release();
}
// constructor method
int AreaPy::PyInit(PyObject* , PyObject* )
{
return 0;
}
PyObject* AreaPy::setPlane(PyObject *args) {
PyObject *pcObj;
if (!PyArg_ParseTuple(args, "O!", &(Part::TopoShapePy::Type), &pcObj))
return 0;
#define GET_TOPOSHAPE(_p) static_cast<Part::TopoShapePy*>(_p)->getTopoShapePtr()->getShape()
getAreaPtr()->setPlane(GET_TOPOSHAPE(pcObj));
Py_INCREF(this);
return this;
}
PyObject* AreaPy::getShape(PyObject *args, PyObject *keywds)
{
PyObject *pcObj = Py_False;
short index=-1;
static char *kwlist[] = {"index","rebuild", NULL};
if (!PyArg_ParseTupleAndKeywords(args, keywds,"|hO",kwlist,&pcObj))
return 0;
if(PyObject_IsTrue(pcObj))
getAreaPtr()->clean();
return Py::new_reference_to(Part::shape2pyshape(getAreaPtr()->getShape(index)));
}
PyObject* AreaPy::sortWires(PyObject *args, PyObject *keywds){
PARAM_PY_DECLARE_INIT(PARAM_FARG,AREA_PARAMS_SORT)
short index = -1;
short count = 0;
PyObject *start = NULL;
static char *kwlist[] = {"index","count","start",
PARAM_FIELD_STRINGS(ARG,AREA_PARAMS_SORT), NULL};
if (!PyArg_ParseTupleAndKeywords(args, keywds,
"|hhO!" PARAM_PY_KWDS(AREA_PARAMS_SORT),
kwlist,&index,&count,&(Base::VectorPy::Type),&start,
PARAM_REF(PARAM_FARG,AREA_PARAMS_SORT)))
return 0;
gp_Pnt pstart,pend;
if(start) {
Base::Vector3d vec = static_cast<Base::VectorPy*>(start)->value();
pstart.SetCoord(vec.x, vec.y, vec.z);
}
std::list<TopoDS_Shape> wires = getAreaPtr()->sortWires(
index,count,&pstart,&pend,
PARAM_PY_FIELDS(PARAM_FARG,AREA_PARAMS_SORT));
PyObject *list = PyList_New(0);
for(auto &wire : wires)
PyList_Append(list,Py::new_reference_to(
Part::shape2pyshape(TopoDS::Wire(wire))));
PyObject *ret = PyTuple_New(2);
PyTuple_SetItem(ret,0,list);
PyTuple_SetItem(ret,1,new Base::VectorPy(
Base::Vector3d(pend.X(),pend.Y(),pend.Z())));
return ret;
}
PyObject* AreaPy::add(PyObject *args, PyObject *keywds)
{
PARAM_PY_DECLARE_INIT(PARAM_FARG,AREA_PARAMS_OPCODE)
PyObject *pcObj;
//Strangely, PyArg_ParseTupleAndKeywords requires all arguments to be keyword based,
//even non-optional ones? That doesn't make sense in python. Seems only in python 3
//they added '$' to address that issue.
static char *kwlist[] = {"shape",PARAM_FIELD_STRINGS(ARG,AREA_PARAMS_OPCODE), NULL};
if (!PyArg_ParseTupleAndKeywords(args, keywds,
"O|" PARAM_PY_KWDS(AREA_PARAMS_OPCODE),
kwlist,&pcObj,PARAM_REF(PARAM_FARG,AREA_PARAMS_OPCODE)))
return 0;
if (PyObject_TypeCheck(pcObj, &(Part::TopoShapePy::Type))) {
getAreaPtr()->add(GET_TOPOSHAPE(pcObj),op);
Py_INCREF(this);
return this;
} else if (PyObject_TypeCheck(pcObj, &(PyList_Type)) ||
PyObject_TypeCheck(pcObj, &(PyTuple_Type))) {
Py::Sequence shapeSeq(pcObj);
for (Py::Sequence::iterator it = shapeSeq.begin(); it != shapeSeq.end(); ++it) {
PyObject* item = (*it).ptr();
if(!PyObject_TypeCheck(item, &(Part::TopoShapePy::Type))) {
PyErr_SetString(PyExc_TypeError, "non-shape object in sequence");
return 0;
}
}
for (Py::Sequence::iterator it = shapeSeq.begin(); it != shapeSeq.end(); ++it){
PyObject* item = (*it).ptr();
getAreaPtr()->add(GET_TOPOSHAPE(item),
PARAM_PY_FIELDS(PARAM_FARG,AREA_PARAMS_OPCODE));
}
Py_INCREF(this);
return this;
}
PyErr_SetString(PyExc_TypeError, "shape must be 'TopoShape' or list of 'TopoShape'");
return 0;
}
PyObject* AreaPy::makeOffset(PyObject *args, PyObject *keywds)
{
//Generate a keyword string defined in the ARG field of OFFSET parameter list
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(PARAM_FARG,AREA_PARAMS_OFFSET)
//Parse arguments to overwrite the defaults
if (!PyArg_ParseTupleAndKeywords(args, keywds,
"|h" PARAM_PY_KWDS(AREA_PARAMS_OFFSET), kwlist,
&index,PARAM_REF(PARAM_FARG,AREA_PARAMS_OFFSET)))
return 0;
//Expand the variable as function call arguments
TopoDS_Shape resultShape = getAreaPtr()->makeOffset(index,
PARAM_PY_FIELDS(PARAM_FARG,AREA_PARAMS_OFFSET));
return Py::new_reference_to(Part::shape2pyshape(resultShape));
}
PyObject* AreaPy::makePocket(PyObject *args, PyObject *keywds)
{
static char *kwlist[] = {"index",PARAM_FIELD_STRINGS(ARG,AREA_PARAMS_POCKET), NULL};
short index = -1;
PARAM_PY_DECLARE_INIT(PARAM_FARG,AREA_PARAMS_POCKET)
//Override pocket mode default
mode = Area::PocketModeZigZagOffset;
if (!PyArg_ParseTupleAndKeywords(args, keywds,
"|h" PARAM_PY_KWDS(AREA_PARAMS_POCKET), kwlist,
&index,PARAM_REF(PARAM_FARG,AREA_PARAMS_POCKET)))
return 0;
TopoDS_Shape resultShape = getAreaPtr()->makePocket(index,
PARAM_PY_FIELDS(PARAM_FARG,AREA_PARAMS_POCKET));
return Py::new_reference_to(Part::shape2pyshape(resultShape));
}
PyObject* AreaPy::makeSections(PyObject *args, PyObject *keywds)
{
static char *kwlist[] = {PARAM_FIELD_STRINGS(ARG,AREA_PARAMS_SECTION_EXTRA),
"heights", "plane", NULL};
PyObject *heights = NULL;
PyObject *plane = NULL;
PARAM_PY_DECLARE_INIT(PARAM_FARG,AREA_PARAMS_SECTION_EXTRA)
if (!PyArg_ParseTupleAndKeywords(args, keywds,
"|" PARAM_PY_KWDS(AREA_PARAMS_SECTION_EXTRA) "OO!", kwlist,
PARAM_REF(PARAM_FARG,AREA_PARAMS_SECTION_EXTRA),
&heights, &(Part::TopoShapePy::Type), &plane))
return 0;
std::vector<double> h;
if(heights) {
if (PyObject_TypeCheck(heights, &(PyFloat_Type)))
h.push_back(PyFloat_AsDouble(heights));
else if (PyObject_TypeCheck(heights, &(PyList_Type)) ||
PyObject_TypeCheck(heights, &(PyTuple_Type))) {
Py::Sequence shapeSeq(heights);
h.reserve(shapeSeq.size());
for (Py::Sequence::iterator it = shapeSeq.begin(); it != shapeSeq.end(); ++it) {
PyObject* item = (*it).ptr();
if(!PyObject_TypeCheck(item, &(PyFloat_Type))) {
PyErr_SetString(PyExc_TypeError, "heights must only contain float type");
return 0;
}
h.push_back(PyFloat_AsDouble(item));
}
}else{
PyErr_SetString(PyExc_TypeError, "heights must be of type float or list/tuple of float");
return 0;
}
}
std::vector<std::shared_ptr<Area> > sections = getAreaPtr()->makeSections(
PARAM_PY_FIELDS(PARAM_FARG,AREA_PARAMS_SECTION_EXTRA),
h,plane?GET_TOPOSHAPE(plane):TopoDS_Shape());
Py::List ret;
for(auto &area : sections)
ret.append(Py::asObject(new AreaPy(new Area(*area,false))));
return Py::new_reference_to(ret);
}
PyObject* AreaPy::setDefaultParams(PyObject *, PyObject *)
{
return 0;
}
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(PARAM_FNAME,AREA_PARAMS_CONF);
AreaParams params = getAreaPtr()->getParams();
//populate the CONF variables with params
PARAM_FOREACH(AREA_SET,AREA_PARAMS_CONF)
//Parse arguments to overwrite CONF variables
if (!PyArg_ParseTupleAndKeywords(args, keywds,
"|" PARAM_PY_KWDS(AREA_PARAMS_CONF), kwlist,
PARAM_REF(PARAM_FNAME,AREA_PARAMS_CONF)))
return 0;
//populate 'params' with the CONF variables
PARAM_FOREACH(AREA_GET,AREA_PARAMS_CONF)
getAreaPtr()->setParams(params);
Py_INCREF(this);
return this;
}
PyObject* AreaPy::getParams(PyObject *args)
{
if (!PyArg_ParseTuple(args, ""))
return 0;
const AreaParams &params =getAreaPtr()->getParams();
PyObject *dict = PyDict_New();
PARAM_PY_DICT_SET_VALUE(dict,NAME,AREA_SRC,AREA_PARAMS_CONF)
return dict;
}
PyObject* AreaPy::getDefaultParams(PyObject *)
{
return 0;
}
PyObject* AreaPy::abort(PyObject *, PyObject *) {
return 0;
}
PyObject* AreaPy::getParamsDesc(PyObject *args, PyObject *keywds)
{
PyObject *pcObj = Py_True;
static char *kwlist[] = {"as_string", NULL};
if (!PyArg_ParseTupleAndKeywords(args, keywds,"|O",kwlist,&pcObj))
return 0;
if(PyObject_IsTrue(pcObj))
return PyString_FromString(PARAM_PY_DOC(NAME,AREA_PARAMS_CONF));
PyObject *dict = PyDict_New();
PARAM_PY_DICT_SET_DOC(dict,NAME,AREA_PARAMS_CONF)
return dict;
}
Py::List AreaPy::getSections(void) const {
Py::List ret;
Area *area = getAreaPtr();
for(size_t i=0,count=area->getSectionCount(); i<count;++i)
ret.append(Part::shape2pyshape(getAreaPtr()->getShape(i)));
return ret;
}
Py::List AreaPy::getShapes(void) const {
Py::List ret;
Area *area = getAreaPtr();
const std::list<Area::Shape> &shapes = area->getChildren();
for(auto &s : shapes)
ret.append(Py::TupleN(Part::shape2pyshape(s.shape),Py::Int(s.op)));
return ret;
}
Py::Object AreaPy::getWorkplane(void) const {
return Part::shape2pyshape(getAreaPtr()->getPlane());
}
// custom attributes get/set
PyObject *AreaPy::getCustomAttributes(const char* /*attr*/) const
{
return 0;
}
int AreaPy::setCustomAttributes(const char* /*attr*/, PyObject* /*obj*/)
{
return 0;
}

View File

@@ -22,6 +22,7 @@ link_directories(${OCC_LIBRARY_DIR})
set(Path_LIBS
# Robot
Part
area-native
FreeCADApp
)
@@ -30,6 +31,8 @@ generate_from_xml(PathPy)
generate_from_xml(ToolPy)
generate_from_xml(TooltablePy)
generate_from_xml(FeaturePathCompoundPy)
generate_from_xml(AreaPy)
generate_from_xml(FeatureAreaPy)
SET(Python_SRCS
CommandPy.xml
@@ -41,6 +44,10 @@ SET(Python_SRCS
TooltablePyImp.cpp
FeaturePathCompoundPy.xml
FeaturePathCompoundPyImp.cpp
AreaPy.xml
AreaPyImp.cpp
FeatureAreaPy.xml
FeatureAreaPyImp.cpp
)
SET(Mod_SRCS
@@ -67,6 +74,12 @@ SET(Path_SRCS
FeaturePathCompound.h
FeaturePathShape.cpp
FeaturePathShape.h
Area.cpp
Area.h
AreaParams.h
ParamsHelper.h
FeatureArea.cpp
FeatureArea.h
${Mod_SRCS}
${Python_SRCS}
)

View File

@@ -0,0 +1,247 @@
/****************************************************************************
* Copyright (c) 2017 Zheng, Lei (realthunder) <realthunder.dev@gmail.com>*
* *
* This file is part of the FreeCAD CAx development system. *
* *
* This library is free software; you can redistribute it and/or *
* modify it under the terms of the GNU Library General Public *
* License as published by the Free Software Foundation; either *
* version 2 of the License, or (at your option) any later version. *
* *
* This library is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU Library General Public License for more details. *
* *
* You should have received a copy of the GNU Library General Public *
* License along with this library; see the file COPYING.LIB. If not, *
* write to the Free Software Foundation, Inc., 59 Temple Place, *
* Suite 330, Boston, MA 02111-1307, USA *
* *
****************************************************************************/
#include "PreCompiled.h"
#ifndef _PreComp_
#endif
#include <BRep_Builder.hxx>
#include <TopoDS_Compound.hxx>
#include "FeatureArea.h"
#include "FeatureAreaPy.h"
#include <App/DocumentObjectPy.h>
#include <Base/Placement.h>
#include <Mod/Part/App/PartFeature.h>
using namespace Path;
PROPERTY_SOURCE(Path::FeatureArea, Part::Feature)
PARAM_ENUM_STRING_DECLARE(static const char *Enums,AREA_PARAMS_ALL)
FeatureArea::FeatureArea()
:myBuild(false)
{
ADD_PROPERTY(Sources,(0));
ADD_PROPERTY(WorkPlane,(TopoDS_Shape()));
PARAM_PROP_ADD("Area",AREA_PARAMS_OPCODE);
PARAM_PROP_ADD("Area",AREA_PARAMS_BASE);
PARAM_PROP_ADD("Offset",AREA_PARAMS_OFFSET);
PARAM_PROP_ADD("Offset", AREA_PARAMS_OFFSET_CONF);
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("libarea",AREA_PARAMS_CAREA);
PARAM_PROP_SET_ENUM(Enums,AREA_PARAMS_ALL);
PocketMode.setValue((long)0);
}
FeatureArea::~FeatureArea()
{
}
Area &FeatureArea::getArea() {
if(!myBuild)
execute();
return myArea;
}
App::DocumentObjectExecReturn *FeatureArea::execute(void)
{
std::vector<App::DocumentObject*> links = Sources.getValues();
if (links.empty())
return new App::DocumentObjectExecReturn("No shapes linked");
for (std::vector<App::DocumentObject*>::iterator it = links.begin(); it != links.end(); ++it) {
if (!(*it && (*it)->isDerivedFrom(Part::Feature::getClassTypeId())))
return new App::DocumentObjectExecReturn("Linked object is not a Part object (has no Shape).");
TopoDS_Shape shape = static_cast<Part::Feature*>(*it)->Shape.getShape().getShape();
if (shape.IsNull())
return new App::DocumentObjectExecReturn("Linked shape object is empty");
}
TIME_INIT(t);
myBuild = true;
AreaParams params;
#define AREA_PROP_GET(_param) \
params.PARAM_FNAME(_param) = PARAM_FNAME(_param).getValue();
PARAM_FOREACH(AREA_PROP_GET,AREA_PARAMS_CONF)
myArea.clean(true);
myArea.setParams(params);
TopoDS_Shape workPlane = WorkPlane.getShape().getShape();
myArea.setPlane(workPlane);
for (std::vector<App::DocumentObject*>::iterator it = links.begin(); it != links.end(); ++it) {
myArea.add(static_cast<Part::Feature*>(*it)->Shape.getShape().getShape(),
PARAM_PROP_ARGS(AREA_PARAMS_OPCODE));
}
myShapes.clear();
if(myArea.getSectionCount()==0)
myShapes.push_back(myArea.getShape(-1));
else {
myShapes.reserve(myArea.getSectionCount());
for(int i=0;i<(int)myArea.getSectionCount();++i)
myShapes.push_back(myArea.getShape(i));
}
if(myShapes.empty())
Shape.setValue(TopoDS_Shape());
else if(myShapes.size()==1)
Shape.setValue(myShapes.front());
else{
BRep_Builder builder;
TopoDS_Compound compound;
builder.MakeCompound(compound);
for(auto &shape : myShapes)
builder.Add(compound,shape);
Shape.setValue(compound);
}
TIME_PRINT(t,"feature execute");
return Part::Feature::execute();
}
const std::vector<TopoDS_Shape> &FeatureArea::getShapes() {
getArea();
return myShapes;
}
short FeatureArea::mustExecute(void) const
{
if (Sources.isTouched())
return 1;
if (WorkPlane.isTouched())
return 1;
PARAM_PROP_TOUCHED(AREA_PARAMS_ALL)
return Part::Feature::mustExecute();
}
PyObject *FeatureArea::getPyObject()
{
if (PythonObject.is(Py::_None())){
// ref counter is set to 1
PythonObject = Py::Object(new FeatureAreaPy(this),true);
}
return Py::new_reference_to(PythonObject);
}
// FeatureAreaView -------------------------------------------------------------
//
PROPERTY_SOURCE(Path::FeatureAreaView, Part::Feature)
FeatureAreaView::FeatureAreaView()
{
ADD_PROPERTY(Source,(0));
ADD_PROPERTY_TYPE(SectionIndex,(0),"Section",App::Prop_None,"The start index of the section to show, negative value for reverse index from bottom");
ADD_PROPERTY_TYPE(SectionCount,(1),"Section",App::Prop_None,"Number of sections to show, 0 to show all section starting from SectionIndex");
}
std::list<TopoDS_Shape> FeatureAreaView::getShapes() {
std::list<TopoDS_Shape> shapes;
App::DocumentObject* pObj = Source.getValue();
if (!pObj) return shapes;
if(!pObj->isDerivedFrom(FeatureArea::getClassTypeId()))
return shapes;
auto all_shapes = static_cast<FeatureArea*>(pObj)->getShapes();
if(all_shapes.empty())
return shapes;
int index=SectionIndex.getValue(),count=SectionCount.getValue();
if(index<0) {
index += ((int)all_shapes.size());
if(index<0) return shapes;
if(count<=0 || index+1-count<0) {
count = index+1;
index = 0;
}else
index -= count-1;
}else if(index >= (int)all_shapes.size())
return shapes;
if(count<=0) count = all_shapes.size();
count += index;
if(count>(int)all_shapes.size())
count = all_shapes.size();
for(int i=index;i<count;++i)
shapes.push_back(all_shapes[i]);
return std::move(shapes);
}
App::DocumentObjectExecReturn *FeatureAreaView::execute(void)
{
App::DocumentObject* pObj = Source.getValue();
if (!pObj)
return new App::DocumentObjectExecReturn("No shape linked");
if(!pObj->isDerivedFrom(FeatureArea::getClassTypeId()))
return new App::DocumentObjectExecReturn("Linked object is not a FeatureArea");
std::list<TopoDS_Shape> shapes = getShapes();
if(shapes.empty())
Shape.setValue(TopoDS_Shape());
else if(shapes.size()==1) {
Shape.setValue(shapes.front());
}else{
BRep_Builder builder;
TopoDS_Compound compound;
builder.MakeCompound(compound);
for(auto &shape : shapes)
builder.Add(compound,shape);
Shape.setValue(compound);
}
return Part::Feature::execute();
}
// Python feature ---------------------------------------------------------
namespace App {
/// @cond DOXERR
PROPERTY_SOURCE_TEMPLATE(Path::FeatureAreaPython, Path::FeatureArea)
PROPERTY_SOURCE_TEMPLATE(Path::FeatureAreaViewPython, Path::FeatureAreaView)
template<> const char* Path::FeatureAreaPython::getViewProviderName(void) const {
return "PathGui::ViewProviderAreaPython";
}
template<> const char* Path::FeatureAreaViewPython::getViewProviderName(void) const {
return "PathGui::ViewProviderAreaViewPython";
}
/// @endcond
// explicit template instantiation
template class PathExport FeaturePythonT<Path::FeatureArea>;
}

View File

@@ -0,0 +1,96 @@
/****************************************************************************
* Copyright (c) 2017 Zheng, Lei (realthunder) <realthunder.dev@gmail.com>*
* *
* This file is part of the FreeCAD CAx development system. *
* *
* This library is free software; you can redistribute it and/or *
* modify it under the terms of the GNU Library General Public *
* License as published by the Free Software Foundation; either *
* version 2 of the License, or (at your option) any later version. *
* *
* This library is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU Library General Public License for more details. *
* *
* You should have received a copy of the GNU Library General Public *
* License along with this library; see the file COPYING.LIB. If not, *
* write to the Free Software Foundation, Inc., 59 Temple Place, *
* Suite 330, Boston, MA 02111-1307, USA *
* *
****************************************************************************/
#ifndef PATH_FeatureArea_H
#define PATH_FeatureArea_H
#include <App/DocumentObject.h>
#include <App/GeoFeature.h>
#include <App/PropertyFile.h>
#include <App/PropertyGeo.h>
#include <App/FeaturePython.h>
#include "Mod/Part/App/PartFeature.h"
#include "Area.h"
namespace Path
{
class PathExport FeatureArea : public Part::Feature
{
PROPERTY_HEADER(Path::FeatureArea);
public:
/// Constructor
FeatureArea(void);
virtual ~FeatureArea();
Area &getArea();
const std::vector<TopoDS_Shape> &getShapes();
/// returns the type name of the ViewProvider
virtual const char* getViewProviderName(void) const {
return "PathGui::ViewProviderArea";
}
virtual App::DocumentObjectExecReturn *execute(void);
virtual short mustExecute(void) const;
virtual PyObject *getPyObject(void);
App::PropertyLinkList Sources;
Part::PropertyPartShape WorkPlane;
PARAM_PROP_DECLARE(AREA_PARAMS_ALL)
private:
bool myBuild;
Area myArea;
std::vector<TopoDS_Shape> myShapes;
};
typedef App::FeaturePythonT<FeatureArea> FeatureAreaPython;
class PathExport FeatureAreaView : public Part::Feature
{
PROPERTY_HEADER(Path::FeatureAreaView);
public:
/// Constructor
FeatureAreaView(void);
std::list<TopoDS_Shape> getShapes();
virtual const char* getViewProviderName(void) const {
return "PathGui::ViewProviderAreaView";
}
virtual App::DocumentObjectExecReturn *execute(void);
App::PropertyLink Source;
App::PropertyInteger SectionIndex;
App::PropertyInteger SectionCount;
};
typedef App::FeaturePythonT<FeatureAreaView> FeatureAreaViewPython;
} //namespace Path
#endif // PATH_FeaturePath_H

View File

@@ -0,0 +1,30 @@
<?xml version="1.0" encoding="UTF-8"?>
<GenerateModel xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="generateMetaModel_Module.xsd">
<PythonExport
Father="DocumentObjectPy"
Name="FeatureAreaPy"
Twin="FeatureArea"
TwinPointer="FeatureArea"
Include="Mod/Path/App/FeatureArea.h"
Namespace="Path"
FatherInclude="App/DocumentObjectPy.h"
FatherNamespace="App">
<Documentation>
<Author Licence="LGPL" Name="Zheng, Lei" EMail="realthunder.dev@gmail.com" />
<UserDocu>This class handles Path Area features</UserDocu>
</Documentation>
<Methode Name="getArea">
<Documentation>
<UserDocu>Return a copy of the encapsulated Python Area object.</UserDocu>
</Documentation>
</Methode>
<Methode Name="setParams" Keyword="true">
<Documentation>
<UserDocu>setParams(key=value...): Convenient function to configure this feature.\n
Same usage as Path.Area.setParams(). This function stores the parameters in the properties.</UserDocu>
</Documentation>
</Methode>
<CustomAttributes />
</PythonExport>
</GenerateModel>

View File

@@ -0,0 +1,93 @@
/****************************************************************************
* Copyright (c) 2017 Zheng, Lei (realthunder) <realthunder.dev@gmail.com>*
* *
* This file is part of the FreeCAD CAx development system. *
* *
* This library is free software; you can redistribute it and/or *
* modify it under the terms of the GNU Library General Public *
* License as published by the Free Software Foundation; either *
* version 2 of the License, or (at your option) any later version. *
* *
* This library is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU Library General Public License for more details. *
* *
* You should have received a copy of the GNU Library General Public *
* License along with this library; see the file COPYING.LIB. If not, *
* write to the Free Software Foundation, Inc., 59 Temple Place, *
* Suite 330, Boston, MA 02111-1307, USA *
* *
****************************************************************************/
#include "PreCompiled.h"
#include <CXX/Objects.hxx>
#include "FeatureArea.h"
// inclusion of the generated files (generated out of FeatureAreaPy.xml)
#include "FeatureAreaPy.h"
#include "FeatureAreaPy.cpp"
#include "AreaPy.h"
using namespace Path;
// returns a string which represent the object e.g. when printed in python
std::string FeatureAreaPy::representation(void) const
{
return std::string("<Path::FeatureArea>");
}
PyObject* FeatureAreaPy::getArea(PyObject *args)
{
if (!PyArg_ParseTuple(args, ""))
return NULL;
return new AreaPy(new Area(getFeatureAreaPtr()->getArea()));
}
PyObject* FeatureAreaPy::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(PARAM_FNAME,AREA_PARAMS_CONF);
FeatureArea *feature = getFeatureAreaPtr();
#define AREA_SET(_param) \
PARAM_FNAME(_param) = \
PARAM_TYPED(PARAM_PY_CAST_,_param)(feature->PARAM_FNAME(_param).getValue());
//populate the CONF variables with values in properties
PARAM_FOREACH(AREA_SET,AREA_PARAMS_CONF)
//Parse arguments to overwrite CONF variables
if (!PyArg_ParseTupleAndKeywords(args, keywds,
"|" PARAM_PY_KWDS(AREA_PARAMS_CONF), kwlist,
PARAM_REF(PARAM_FNAME,AREA_PARAMS_CONF)))
Py_Error(Base::BaseExceptionFreeCADError,
"Wrong parameters, call getParamsDesc() to get supported params");
#define AREA_GET(_param) \
feature->PARAM_FNAME(_param).setValue(\
PARAM_TYPED(PARAM_CAST_PY_,_param)(PARAM_FNAME(_param)));
//populate properties with the CONF variables
PARAM_FOREACH(AREA_GET,AREA_PARAMS_CONF)
return Py_None;
}
PyObject *FeatureAreaPy::getCustomAttributes(const char* /*attr*/) const
{
return 0;
}
int FeatureAreaPy::setCustomAttributes(const char* /*attr*/, PyObject* /*obj*/)
{
return 0;
}

View File

@@ -19,7 +19,9 @@
* Suite 330, Boston, MA 02111-1307, USA *
* *
***************************************************************************/
/*
* Copyright (c) 2017 Zheng, Lei <realthunder.dev@gmail.com>
*/
#include "PreCompiled.h"
@@ -32,101 +34,66 @@
#include <App/DocumentObjectPy.h>
#include <Base/Placement.h>
#include <Mod/Part/App/TopoShape.h>
#include <Mod/Part/App/PartFeature.h>
#include <TopoDS.hxx>
#include <TopoDS_Shape.hxx>
#include <TopoDS_Edge.hxx>
#include <TopoDS_Vertex.hxx>
#include <TopoDS_Iterator.hxx>
#include <TopExp_Explorer.hxx>
#include <gp_Lin.hxx>
#include <BRep_Tool.hxx>
#include <BRepAdaptor_CompCurve.hxx>
#include <BRepAdaptor_HCompCurve.hxx>
#include <Approx_Curve3d.hxx>
#include <BRepAdaptor_HCurve.hxx>
#include <Standard_Failure.hxx>
#include <Standard_Version.hxx>
#include <BRepBuilderAPI_MakeWire.hxx>
#include "FeatureArea.h"
using namespace Path;
PROPERTY_SOURCE(Path::FeatureShape, Path::Feature)
PARAM_ENUM_STRING_DECLARE(static const char *Enums,AREA_PARAMS_PATH)
FeatureShape::FeatureShape()
{
ADD_PROPERTY_TYPE(Shape,(TopoDS_Shape()),"Path",App::Prop_None,"The shape data of this feature");
ADD_PROPERTY(Sources,(0));
ADD_PROPERTY_TYPE(StartPoint,(Base::Vector3d()),"Path",App::Prop_None,"Path start position");
PARAM_PROP_ADD("Path",AREA_PARAMS_PATH_CONF);
PARAM_PROP_SET_ENUM(Enums,AREA_PARAMS_PATH_CONF);
}
FeatureShape::~FeatureShape()
{
}
short FeatureShape::mustExecute(void) const
{
return Path::Feature::mustExecute();
}
App::DocumentObjectExecReturn *FeatureShape::execute(void)
{
TopoDS_Shape shape = Shape.getValue();
if (!shape.IsNull()) {
if (shape.ShapeType() == TopAbs_WIRE) {
Path::Toolpath result;
bool first = true;
Base::Placement last;
TopExp_Explorer ExpEdges (shape,TopAbs_EDGE);
while (ExpEdges.More()) {
const TopoDS_Edge& edge = TopoDS::Edge(ExpEdges.Current());
TopExp_Explorer ExpVerts(edge,TopAbs_VERTEX);
bool vfirst = true;
while (ExpVerts.More()) {
const TopoDS_Vertex& vert = TopoDS::Vertex(ExpVerts.Current());
gp_Pnt pnt = BRep_Tool::Pnt(vert);
Base::Placement tpl;
tpl.setPosition(Base::Vector3d(pnt.X(),pnt.Y(),pnt.Z()));
if (first) {
// add first point as a G0 move
Path::Command cmd;
std::ostringstream ctxt;
ctxt << "G0 X" << tpl.getPosition().x << " Y" << tpl.getPosition().y << " Z" << tpl.getPosition().z;
cmd.setFromGCode(ctxt.str());
result.addCommand(cmd);
first = false;
vfirst = false;
} else {
if (vfirst)
vfirst = false;
else {
Path::Command cmd;
cmd.setFromPlacement(tpl);
// write arc data if needed
BRepAdaptor_Curve adapt(edge);
if (adapt.GetType() == GeomAbs_Circle) {
gp_Circ circ = adapt.Circle();
gp_Pnt c = circ.Location();
bool clockwise = false;
gp_Dir n = circ.Axis().Direction();
if (n.Z() < 0)
clockwise = true;
Base::Vector3d center = Base::Vector3d(c.X(),c.Y(),c.Z());
// center coords must be relative to last point
center -= last.getPosition();
cmd.setCenter(center,clockwise);
}
result.addCommand(cmd);
}
}
ExpVerts.Next();
last = tpl;
}
ExpEdges.Next();
}
Path.setValue(result);
}
Toolpath path;
std::vector<App::DocumentObject*> links = Sources.getValues();
if (links.empty()) {
Path.setValue(path);
return new App::DocumentObjectExecReturn("No shapes linked");
}
const Base::Vector3d &v = StartPoint.getValue();
gp_Pnt pstart(v.x,v.y,v.z);
std::list<TopoDS_Shape> shapes;
for (std::vector<App::DocumentObject*>::iterator it = links.begin(); it != links.end(); ++it) {
if (!(*it && (*it)->isDerivedFrom(Part::Feature::getClassTypeId())))
continue;
const TopoDS_Shape &shape = static_cast<Part::Feature*>(*it)->Shape.getShape().getShape();
if (shape.IsNull())
continue;
shapes.push_back(shape);
}
AreaParams params;
#define AREA_PROP_GET(_param) \
params.PARAM_FNAME(_param) = PARAM_FNAME(_param).getValue();
PARAM_FOREACH(AREA_PROP_GET,AREA_PARAMS_PATH_EXTRA)
Area::toPath(path,shapes,&params,&pstart,NULL,PARAM_PROP_ARGS(AREA_PARAMS_PATH));
Path.setValue(path);
return App::DocumentObject::StdReturn;
}

View File

@@ -19,6 +19,9 @@
* Suite 330, Boston, MA 02111-1307, USA *
* *
***************************************************************************/
/*
* Copyright (c) 2017 Zheng, Lei <realthunder.dev@gmail.com>
*/
#ifndef PATH_FeaturePathShape_H
@@ -26,14 +29,13 @@
#include <App/DocumentObject.h>
#include <App/GeoFeature.h>
#include <App/PropertyFile.h>
#include <App/PropertyGeo.h>
#include <App/FeaturePython.h>
#include "Mod/Part/App/PropertyTopoShape.h"
#include "Path.h"
#include "PropertyPath.h"
#include "FeaturePath.h"
#include "Area.h"
namespace Path
{
@@ -47,12 +49,14 @@ public:
FeatureShape(void);
virtual ~FeatureShape();
Part::PropertyPartShape Shape;
// Part::PropertyPartShape Shape;
App::PropertyLinkList Sources;
App::PropertyVector StartPoint;
PARAM_PROP_DECLARE(AREA_PARAMS_PATH_CONF)
//@{
/// recalculate the feature
virtual App::DocumentObjectExecReturn *execute(void);
virtual short mustExecute(void) const;
//@}
/// returns the type name of the ViewProvider

File diff suppressed because it is too large Load Diff

View File

@@ -23,10 +23,10 @@
#ifndef PATH_Path_H
#define PATH_Path_H
#include "Command.h"
#include "Command.h"
//#include "Mod/Robot/App/kdl_cp/path_composite.hpp"
//#include "Mod/Robot/App/kdl_cp/frames_io.hpp"
//#include "Mod/Robot/App/kdl_cp/frames_io.hpp"
#include <Base/Persistence.h>
#include <Base/Vector3D.h>

View File

@@ -35,6 +35,7 @@
#include "DlgSettingsPathColor.h"
#include "ViewProviderPathCompound.h"
#include "ViewProviderPathShape.h"
#include "ViewProviderArea.h"
// use a different name to CreateCommand()
void CreatePathCommands(void);
@@ -77,6 +78,10 @@ PyMOD_INIT_FUNC(PathGui)
PathGui::ViewProviderPathCompoundPython ::init();
PathGui::ViewProviderPathShape ::init();
PathGui::ViewProviderPathPython ::init();
PathGui::ViewProviderArea ::init();
PathGui::ViewProviderAreaPython ::init();
PathGui::ViewProviderAreaView ::init();
PathGui::ViewProviderAreaViewPython ::init();
// add resources and reloads the translators
loadPathResource();

View File

@@ -81,6 +81,8 @@ SET(PathGui_SRCS_ViewProvider
ViewProviderPathCompound.h
ViewProviderPathShape.cpp
ViewProviderPathShape.h
ViewProviderArea.cpp
ViewProviderArea.h
)
SOURCE_GROUP("ViewProvider" FILES ${PathGui_SRCS_ViewProvider})

View File

@@ -25,6 +25,8 @@
#ifndef _PreComp_
#endif
#include <TopExp_Explorer.hxx>
#include <Base/Console.h>
#include <App/Application.h>
#include <Gui/Application.h>
@@ -39,6 +41,183 @@
#include <Mod/Path/App/FeaturePathCompound.h>
#include <Mod/Path/App/FeaturePathShape.h>
#include <Mod/Part/App/PartFeature.h>
#include <Mod/Path/App/FeatureArea.h>
// Path Area #####################################################################################################
DEF_STD_CMD_A(CmdPathArea)
CmdPathArea::CmdPathArea()
:Command("Path_Area")
{
sAppModule = "Path";
sGroup = QT_TR_NOOP("Path");
sMenuText = QT_TR_NOOP("Area");
sToolTipText = QT_TR_NOOP("Creates a feature area from selected objects");
sWhatsThis = "Path_Area";
sStatusTip = sToolTipText;
sPixmap = "Path-Area";
sAccel = "P,A";
}
void CmdPathArea::activated(int iMsg)
{
Q_UNUSED(iMsg);
std::list<std::string> cmds;
std::ostringstream sources;
std::string areaName;
bool addView = true;
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(addView && areaName.size()) addView = false;
if(subnames.empty()) {
if(addView && pcObj->getTypeId().isDerivedFrom(Path::FeatureArea::getClassTypeId()))
areaName = pcObj->getNameInDocument();
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;
}
std::ostringstream subname;
subname << pcObj->getNameInDocument() << '_' << name;
std::string sub_fname = getUniqueObjectName(subname.str().c_str());
std::ostringstream cmd;
cmd << "FreeCAD.activeDocument().addObject('Part::Feature','" << sub_fname <<
"').Shape = PathCommands.findShape(FreeCAD.activeDocument()." <<
pcObj->getNameInDocument() << ".Shape,'" << name << "'";
if(!name.compare(0,4,"Edge"))
cmd << ",'Wires'";
cmd << ')';
cmds.push_back(cmd.str());
sources << "FreeCAD.activeDocument()." << sub_fname << ",";
}
}
if(addView && areaName.size()) {
std::string FeatName = getUniqueObjectName("FeatureAreaView");
openCommand("Create Path Area View");
doCommand(Doc,"FreeCAD.activeDocument().addObject('Path::FeatureAreaView','%s')",FeatName.c_str());
doCommand(Doc,"FreeCAD.activeDocument().%s.Source = FreeCAD.activeDocument().%s",
FeatName.c_str(),areaName.c_str());
commitCommand();
updateActive();
return;
}
std::string FeatName = getUniqueObjectName("FeatureArea");
openCommand("Create Path Area");
doCommand(Doc,"import PathCommands");
for(const std::string &cmd : cmds)
doCommand(Doc,cmd.c_str());
doCommand(Doc,"FreeCAD.activeDocument().addObject('Path::FeatureArea','%s')",FeatName.c_str());
doCommand(Doc,"FreeCAD.activeDocument().%s.Sources = [ %s ]",FeatName.c_str(),sources.str().c_str());
commitCommand();
updateActive();
}
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;
}
std::ostringstream subname;
subname << planeSubname << ",'" << name << "','Wires'";
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,"import PathCommands");
doCommand(Doc,"FreeCAD.activeDocument().%s.WorkPlane = PathCommands.findShape("
"FreeCAD.activeDocument().%s)", areaName.c_str(),planeSubname.c_str());
doCommand(Doc,"FreeCAD.activeDocument().%s.ViewObject.Visibility = True",areaName.c_str());
commitCommand();
updateActive();
}
bool CmdPathAreaWorkplane::isActive(void)
{
return !getSelection().getSelectionEx(NULL, Path::FeatureArea::getClassTypeId()).empty();
}
// Path compound #####################################################################################################
@@ -95,7 +274,6 @@ bool CmdPathCompound::isActive(void)
return hasActiveDocument();
}
// Path Shape #####################################################################################################
@@ -117,24 +295,48 @@ CmdPathShape::CmdPathShape()
void CmdPathShape::activated(int iMsg)
{
Q_UNUSED(iMsg);
std::vector<Gui::SelectionSingleton::SelObj> Sel = getSelection().getSelection();
if (Sel.size() == 1) {
if (Sel[0].pObject->getTypeId().isDerivedFrom(Part::Feature::getClassTypeId())) {
Part::Feature *pcPartObject = static_cast<Part::Feature*>(Sel[0].pObject);
std::string FeatName = getUniqueObjectName("PathShape");
openCommand("Create Path Compound");
doCommand(Doc,"FreeCAD.activeDocument().addObject('Path::FeatureShape','%s')",FeatName.c_str());
doCommand(Doc,"FreeCAD.activeDocument().%s.Shape = FreeCAD.activeDocument().%s.Shape.copy()",FeatName.c_str(),pcPartObject->getNameInDocument());
commitCommand();
updateActive();
} else {
Base::Console().Error("Exactly one shape object must be selected\n");
return;
std::list<std::string> cmds;
std::ostringstream sources;
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().Warning("Ignored shape %s %s\n",
pcObj->getNameInDocument(), name.c_str());
continue;
}
std::ostringstream subname;
subname << pcObj->getNameInDocument() << '_' << name;
std::string sub_fname = getUniqueObjectName(subname.str().c_str());
std::ostringstream cmd;
cmd << "FreeCAD.activeDocument().addObject('Part::Feature','" << sub_fname <<
"').Shape = PathCommands.findShape(FreeCAD.activeDocument()." <<
pcObj->getNameInDocument() << ".Shape,'" << name << "'";
if(!name.compare(0,4,"Edge"))
cmd << ",'Wires'";
cmd << ')';
cmds.push_back(cmd.str());
sources << "FreeCAD.activeDocument()." << sub_fname << ",";
}
} else {
Base::Console().Error("Exactly one shape object must be selected\n");
return;
}
std::string FeatName = getUniqueObjectName("PathShape");
openCommand("Create Path Shape");
doCommand(Doc,"import PathCommands");
for(const std::string &cmd : cmds)
doCommand(Doc,cmd.c_str());
doCommand(Doc,"FreeCAD.activeDocument().addObject('Path::FeatureShape','%s')",FeatName.c_str());
doCommand(Doc,"FreeCAD.activeDocument().%s.Sources = [ %s ]",FeatName.c_str(),sources.str().c_str());
commitCommand();
updateActive();
}
bool CmdPathShape::isActive(void)
@@ -149,4 +351,6 @@ void CreatePathCommands(void)
Gui::CommandManager &rcCmdMgr = Gui::Application::Instance->commandManager();
rcCmdMgr.addCommand(new CmdPathCompound());
rcCmdMgr.addCommand(new CmdPathShape());
rcCmdMgr.addCommand(new CmdPathArea());
rcCmdMgr.addCommand(new CmdPathAreaWorkplane());
}

View File

@@ -46,6 +46,9 @@
<file>icons/Path-ToolChange.svg</file>
<file>icons/Path-Toolpath.svg</file>
<file>icons/Path-ToolTable.svg</file>
<file>icons/Path-Area.svg</file>
<file>icons/Path-Area-View.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>

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 24 KiB

View 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

View File

@@ -0,0 +1,648 @@
<?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.svg">
<defs
id="defs2818">
<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>
</defs>
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="11"
inkscape:cx="25.031078"
inkscape:cy="28.81298"
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" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 22 KiB

View File

@@ -0,0 +1,197 @@
/****************************************************************************
* Copyright (c) 2017 Zheng, Lei (realthunder) <realthunder.dev@gmail.com>*
* *
* This file is part of the FreeCAD CAx development system. *
* *
* This library is free software; you can redistribute it and/or *
* modify it under the terms of the GNU Library General Public *
* License as published by the Free Software Foundation; either *
* version 2 of the License, or (at your option) any later version. *
* *
* This library is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU Library General Public License for more details. *
* *
* You should have received a copy of the GNU Library General Public *
* License along with this library; see the file COPYING.LIB. If not, *
* write to the Free Software Foundation, Inc., 59 Temple Place, *
* Suite 330, Boston, MA 02111-1307, USA *
* *
****************************************************************************/
#include "PreCompiled.h"
#ifndef _PreComp_
#endif
#include <Gui/Application.h>
#include <Mod/Path/App/FeatureArea.h>
#include "ViewProviderArea.h"
using namespace PathGui;
PROPERTY_SOURCE(PathGui::ViewProviderArea, PartGui::ViewProviderPlaneParametric)
ViewProviderArea::ViewProviderArea()
{
sPixmap = "Path-Area.svg";
}
ViewProviderArea::~ViewProviderArea()
{
}
std::vector<App::DocumentObject*> ViewProviderArea::claimChildren(void) const
{
return std::vector<App::DocumentObject*>(
static_cast<Path::FeatureArea*>(getObject())->Sources.getValues());
}
bool ViewProviderArea::canDragObjects() const
{
return true;
}
bool ViewProviderArea::canDragObject(App::DocumentObject* obj) const
{
return obj && obj->getTypeId().isDerivedFrom(Part::Feature::getClassTypeId());
}
void ViewProviderArea::dragObject(App::DocumentObject* obj)
{
Path::FeatureArea* area = static_cast<Path::FeatureArea*>(getObject());
std::vector<App::DocumentObject*> sources = area->Sources.getValues();
for (std::vector<App::DocumentObject*>::iterator it = sources.begin(); it != sources.end(); ++it) {
if (*it == obj) {
sources.erase(it);
area->Sources.setValues(sources);
break;
}
}
}
bool ViewProviderArea::canDropObjects() const
{
return true;
}
bool ViewProviderArea::canDropObject(App::DocumentObject* obj) const
{
return canDragObject(obj);
}
void ViewProviderArea::dropObject(App::DocumentObject* obj)
{
Path::FeatureArea* area = static_cast<Path::FeatureArea*>(getObject());
std::vector<App::DocumentObject*> sources = area->Sources.getValues();
sources.push_back(obj);
area->Sources.setValues(sources);
}
void ViewProviderArea::updateData(const App::Property* prop)
{
PartGui::ViewProviderPart::updateData(prop);
if (prop->getTypeId() == App::PropertyLinkList::getClassTypeId()) {
std::vector<App::DocumentObject*> pShapes = static_cast<const App::PropertyLinkList*>(prop)->getValues();
for (std::vector<App::DocumentObject*>::iterator it = pShapes.begin(); it != pShapes.end(); ++it) {
if (*it)
Gui::Application::Instance->hideViewProvider(*it);
}
}
}
bool ViewProviderArea::onDelete(const std::vector<std::string> &)
{
// get the input shapes
Path::FeatureArea* area = static_cast<Path::FeatureArea*>(getObject());
std::vector<App::DocumentObject*> pShapes =area->Sources.getValues();
for (std::vector<App::DocumentObject*>::iterator it = pShapes.begin(); it != pShapes.end(); ++it) {
if (*it)
Gui::Application::Instance->showViewProvider(*it);
}
return true;
}
// Python object -----------------------------------------------------------------------
PROPERTY_SOURCE(PathGui::ViewProviderAreaView, PartGui::ViewProviderPlaneParametric)
ViewProviderAreaView::ViewProviderAreaView()
{
sPixmap = "Path-Area-View.svg";
}
ViewProviderAreaView::~ViewProviderAreaView()
{
}
std::vector<App::DocumentObject*> ViewProviderAreaView::claimChildren(void) const
{
std::vector<App::DocumentObject*> ret;
Path::FeatureAreaView* feature = static_cast<Path::FeatureAreaView*>(getObject());
if(feature->Source.getValue())
ret.push_back(feature->Source.getValue());
return ret;
}
bool ViewProviderAreaView::canDragObjects() const
{
return true;
}
bool ViewProviderAreaView::canDragObject(App::DocumentObject* obj) const
{
return obj && obj->getTypeId().isDerivedFrom(Path::FeatureArea::getClassTypeId());
}
void ViewProviderAreaView::dragObject(App::DocumentObject* )
{
Path::FeatureAreaView* feature = static_cast<Path::FeatureAreaView*>(getObject());
feature->Source.setValue(NULL);
}
bool ViewProviderAreaView::canDropObjects() const
{
return true;
}
bool ViewProviderAreaView::canDropObject(App::DocumentObject* obj) const
{
return canDragObject(obj);
}
void ViewProviderAreaView::dropObject(App::DocumentObject* obj)
{
Path::FeatureAreaView* feature = static_cast<Path::FeatureAreaView*>(getObject());
feature->Source.setValue(obj);
}
void ViewProviderAreaView::updateData(const App::Property* prop)
{
PartGui::ViewProviderPlaneParametric::updateData(prop);
if (prop->getTypeId() == App::PropertyLink::getClassTypeId())
Gui::Application::Instance->hideViewProvider(
static_cast<const App::PropertyLink*>(prop)->getValue());
}
bool ViewProviderAreaView::onDelete(const std::vector<std::string> &)
{
Path::FeatureAreaView* feature = static_cast<Path::FeatureAreaView*>(getObject());
Gui::Application::Instance->showViewProvider(feature->Source.getValue());
return true;
}
// Python object -----------------------------------------------------------------------
namespace Gui {
/// @cond DOXERR
PROPERTY_SOURCE_TEMPLATE(PathGui::ViewProviderAreaPython, PathGui::ViewProviderArea)
PROPERTY_SOURCE_TEMPLATE(PathGui::ViewProviderAreaViewPython, PathGui::ViewProviderAreaView)
/// @endcond
// explicit template instantiation
template class PathGuiExport ViewProviderPythonFeatureT<PathGui::ViewProviderArea>;
template class PathGuiExport ViewProviderPythonFeatureT<PathGui::ViewProviderAreaView>;
}

View File

@@ -0,0 +1,83 @@
/****************************************************************************
* Copyright (c) 2017 Zheng, Lei (realthunder) <realthunder.dev@gmail.com>*
* *
* This file is part of the FreeCAD CAx development system. *
* *
* This library is free software; you can redistribute it and/or *
* modify it under the terms of the GNU Library General Public *
* License as published by the Free Software Foundation; either *
* version 2 of the License, or (at your option) any later version. *
* *
* This library is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU Library General Public License for more details. *
* *
* You should have received a copy of the GNU Library General Public *
* License along with this library; see the file COPYING.LIB. If not, *
* write to the Free Software Foundation, Inc., 59 Temple Place, *
* Suite 330, Boston, MA 02111-1307, USA *
* *
****************************************************************************/
#ifndef PATH_ViewProviderArea_H
#define PATH_ViewProviderArea_H
#include <Gui/ViewProviderPythonFeature.h>
#include <Mod/Part/Gui/ViewProviderPlaneParametric.h>
namespace PathGui
{
class PathGuiExport ViewProviderArea : public PartGui::ViewProviderPlaneParametric
{
PROPERTY_HEADER(PathGui::ViewProviderArea);
public:
ViewProviderArea();
virtual ~ViewProviderArea();
/// grouping handling
virtual std::vector<App::DocumentObject*> claimChildren(void) const;
virtual void updateData(const App::Property*);
virtual bool onDelete(const std::vector<std::string> &);
/// drag and drop
virtual bool canDragObjects() const;
virtual bool canDragObject(App::DocumentObject*) const;
virtual void dragObject(App::DocumentObject*);
virtual bool canDropObjects() const;
virtual bool canDropObject(App::DocumentObject*) const;
virtual void dropObject(App::DocumentObject*);
};
typedef Gui::ViewProviderPythonFeatureT<ViewProviderArea> ViewProviderAreaPython;
class PathGuiExport ViewProviderAreaView : public PartGui::ViewProviderPlaneParametric
{
PROPERTY_HEADER(PathGui::ViewProviderAreaView);
public:
ViewProviderAreaView();
virtual ~ViewProviderAreaView();
virtual std::vector<App::DocumentObject*> claimChildren(void) const;
virtual void updateData(const App::Property*);
virtual bool onDelete(const std::vector<std::string> &);
/// drag and drop
virtual bool canDragObjects() const;
virtual bool canDragObject(App::DocumentObject*) const;
virtual void dragObject(App::DocumentObject*);
virtual bool canDropObjects() const;
virtual bool canDropObject(App::DocumentObject*) const;
virtual void dropObject(App::DocumentObject*);
};
typedef Gui::ViewProviderPythonFeatureT<ViewProviderAreaView> ViewProviderAreaViewPython;
} //namespace PathGui
#endif // PATH_ViewProviderArea_H

View File

@@ -26,8 +26,11 @@
#ifndef _PreComp_
#endif
#include "ViewProviderPathShape.h"
#include <Gui/BitmapFactory.h>
#include <Gui/Application.h>
#include <Mod/Part/App/PartFeature.h>
#include <Mod/Path/App/FeaturePathShape.h>
#include "ViewProviderPathShape.h"
using namespace Gui;
using namespace PathGui;
@@ -38,3 +41,74 @@ QIcon ViewProviderPathShape::getIcon() const
{
return Gui::BitmapFactory().pixmap("Path-Shape");
}
std::vector<App::DocumentObject*> ViewProviderPathShape::claimChildren(void) const
{
return std::vector<App::DocumentObject*>(
static_cast<Path::FeatureShape*>(getObject())->Sources.getValues());
}
bool ViewProviderPathShape::canDragObjects() const
{
return true;
}
bool ViewProviderPathShape::canDragObject(App::DocumentObject* obj) const
{
return obj && obj->getTypeId().isDerivedFrom(Part::Feature::getClassTypeId());
}
void ViewProviderPathShape::dragObject(App::DocumentObject* obj)
{
Path::FeatureShape *feature = static_cast<Path::FeatureShape*>(getObject());
std::vector<App::DocumentObject*> sources = feature->Sources.getValues();
for (std::vector<App::DocumentObject*>::iterator it = sources.begin(); it != sources.end(); ++it) {
if (*it == obj) {
sources.erase(it);
feature->Sources.setValues(sources);
break;
}
}
}
bool ViewProviderPathShape::canDropObjects() const
{
return true;
}
bool ViewProviderPathShape::canDropObject(App::DocumentObject* obj) const
{
return canDragObject(obj);
}
void ViewProviderPathShape::dropObject(App::DocumentObject* obj)
{
Path::FeatureShape *feature = static_cast<Path::FeatureShape*>(getObject());
std::vector<App::DocumentObject*> sources = feature->Sources.getValues();
sources.push_back(obj);
feature->Sources.setValues(sources);
}
void ViewProviderPathShape::updateData(const App::Property* prop)
{
PathGui::ViewProviderPath::updateData(prop);
if (prop->getTypeId() == App::PropertyLinkList::getClassTypeId()) {
std::vector<App::DocumentObject*> pShapes = static_cast<const App::PropertyLinkList*>(prop)->getValues();
for (std::vector<App::DocumentObject*>::iterator it = pShapes.begin(); it != pShapes.end(); ++it) {
if (*it)
Gui::Application::Instance->hideViewProvider(*it);
}
}
}
bool ViewProviderPathShape::onDelete(const std::vector<std::string> &)
{
// get the input shapes
Path::FeatureShape *feature = static_cast<Path::FeatureShape*>(getObject());
std::vector<App::DocumentObject*> pShapes =feature->Sources.getValues();
for (std::vector<App::DocumentObject*>::iterator it = pShapes.begin(); it != pShapes.end(); ++it) {
if (*it)
Gui::Application::Instance->showViewProvider(*it);
}
return true;
}

View File

@@ -34,6 +34,19 @@ class PathGuiExport ViewProviderPathShape: public ViewProviderPath
PROPERTY_HEADER(PathGui::ViewProviderPathShape);
public:
/// grouping handling
virtual std::vector<App::DocumentObject*> claimChildren(void) const;
virtual void updateData(const App::Property*);
virtual bool onDelete(const std::vector<std::string> &);
/// drag and drop
virtual bool canDragObjects() const;
virtual bool canDragObject(App::DocumentObject*) const;
virtual void dragObject(App::DocumentObject*);
virtual bool canDropObjects() const;
virtual bool canDropObject(App::DocumentObject*) const;
virtual void dropObject(App::DocumentObject*);
QIcon getIcon(void) const;
};

View File

@@ -81,12 +81,12 @@ class PathWorkbench (Workbench):
# build commands list
projcmdlist = ["Path_Job", "Path_Post", "Path_Inspect", "Path_Sanity"]
toolcmdlist = ["Path_ToolLibraryEdit", "Path_LoadTool"]
prepcmdlist = ["Path_Plane", "Path_Fixture", "Path_ToolLenOffset", "Path_Comment", "Path_Stop", "Path_FaceProfile", "Path_FacePocket", "Path_Custom", "Path_FromShape"]
prepcmdlist = ["Path_Plane", "Path_Fixture", "Path_ToolLenOffset", "Path_Comment", "Path_Stop", "Path_FaceProfile", "Path_FacePocket", "Path_Custom", "Path_Shape"]
twodopcmdlist = ["Path_Contour", "Path_Profile", "Path_Profile_Edges", "Path_Pocket", "Path_Drilling", "Path_Engrave", "Path_MillFace", "Path_Helix"]
threedopcmdlist = ["Path_Surfacing"]
modcmdlist = ["Path_Copy", "Path_CompoundExtended", "Path_Array", "Path_SimpleCopy" ]
dressupcmdlist = ["PathDressup_Dogbone", "PathDressup_DragKnife", "PathDressup_HoldingTags"]
extracmdlist = ["Path_SelectLoop"]
extracmdlist = ["Path_SelectLoop", "Path_Shape", "Path_Area", "Path_Area_Workplane"]
#modcmdmore = ["Path_Hop",]
#remotecmdlist = ["Path_Remote"]

View File

@@ -78,3 +78,28 @@ class _CommandSelectLoop:
if FreeCAD.GuiUp:
FreeCADGui.addCommand('Path_SelectLoop',_CommandSelectLoop())
def findShape(shape,subname=None,subtype=None):
'''To find a higher oder shape containing the subshape with subname.
E.g. to find the wire containing 'Edge1' in shape,
findShape(shape,'Edge1','Wires')
'''
if not subname:
return shape
ret = shape.getElement(subname)
if not subtype or not ret or ret.isNull():
return ret;
if subname.startswith('Face'):
tp = 'Faces'
elif subname.startswith('Edge'):
tp = 'Edges'
elif subname.startswith('Vertex'):
tp = 'Vertex'
else:
return ret
for obj in getattr(shape,subtype):
for sobj in getattr(obj,tp):
if sobj.isEqual(ret):
return obj
return ret

View File

@@ -10,7 +10,11 @@
double CArea::m_accuracy = 0.01;
double CArea::m_units = 1.0;
bool CArea::m_clipper_simple = false;
double CArea::m_clipper_clean_distance = 0.0;
bool CArea::m_fit_arcs = true;
int CArea::m_min_arc_points = 4;
int CArea::m_max_arc_points = 100;
double CArea::m_single_area_processing_length = 0.0;
double CArea::m_processing_done = 0.0;
bool CArea::m_please_abort = false;
@@ -20,6 +24,24 @@ bool CArea::m_set_processing_length_in_split = false;
double CArea::m_after_MakeOffsets_length = 0.0;
//static const double PI = 3.1415926535897932;
#define _CAREA_PARAM_DEFINE(_class,_type,_name) \
_type CArea::get_##_name() {return _class::_name;}\
void CArea::set_##_name(_type _name) {_class::_name = _name;}
#define CAREA_PARAM_DEFINE(_type,_name) \
_type CArea::get_##_name() {return m_##_name;}\
void CArea::set_##_name(_type _name) {m_##_name = _name;}
_CAREA_PARAM_DEFINE(Point,double,tolerance);
CAREA_PARAM_DEFINE(bool,fit_arcs)
CAREA_PARAM_DEFINE(bool,clipper_simple);
CAREA_PARAM_DEFINE(double,clipper_clean_distance);
CAREA_PARAM_DEFINE(double,accuracy);
CAREA_PARAM_DEFINE(double,units);
CAREA_PARAM_DEFINE(short,min_arc_points);
CAREA_PARAM_DEFINE(short,max_arc_points);
CAREA_PARAM_DEFINE(double,clipper_scale);
void CArea::append(const CCurve& curve)
{
m_curves.push_back(curve);
@@ -51,6 +73,75 @@ Point CArea::NearestPoint(const Point& p)const
return best_point;
}
void CArea::ChangeStartToNearest(const Point *point, double min_dist)
{
for(std::list<CCurve>::iterator It=m_curves.begin(),ItNext=It;
It != m_curves.end(); It=ItNext)
{
++ItNext;
if(It->m_vertices.size()<=1)
m_curves.erase(It);
}
if(m_curves.empty()) return;
std::list<CCurve> curves;
Point p;
if(point) p =*point;
if(min_dist < Point::tolerance)
min_dist = Point::tolerance;
while(m_curves.size()) {
std::list<CCurve>::iterator It=m_curves.begin();
std::list<CCurve>::iterator ItBest=It++;
Point best_point = ItBest->NearestPoint(p);
double best_dist = p.dist(best_point);
for(; It != m_curves.end(); ++It)
{
const CCurve& curve = *It;
Point near_point;
double dist;
if(min_dist>Point::tolerance && !curve.IsClosed()) {
double d1 = curve.m_vertices.front().m_p.dist(p);
double d2 = curve.m_vertices.back().m_p.dist(p);
if(d1<d2) {
dist = d1;
near_point = curve.m_vertices.front().m_p;
}else{
dist = d2;
near_point = curve.m_vertices.back().m_p;
}
}else{
near_point = curve.NearestPoint(p);
dist = near_point.dist(p);
}
if(dist < best_dist)
{
best_dist = dist;
best_point = near_point;
ItBest = It;
}
}
if(ItBest->IsClosed()) {
ItBest->ChangeStart(best_point);
}else{
double dfront = ItBest->m_vertices.front().m_p.dist(best_point);
double dback = ItBest->m_vertices.back().m_p.dist(best_point);
if(min_dist>Point::tolerance && dfront>min_dist && dback>min_dist) {
ItBest->Break(best_point);
m_curves.push_back(*ItBest);
m_curves.back().ChangeEnd(best_point);
ItBest->ChangeStart(best_point);
}else if(dfront>dback)
ItBest->Reverse();
}
curves.splice(curves.end(),m_curves,ItBest);
p = curves.back().m_vertices.back().m_p;
}
m_curves.splice(m_curves.end(),curves);
}
void CArea::GetBox(CBox2D &box)
{
for(std::list<CCurve>::iterator It = m_curves.begin(); It != m_curves.end(); It++)
@@ -70,17 +161,22 @@ void CArea::Reorder()
// returns 1, if the curves are overlapping
CAreaOrderer ao;
for(std::list<CCurve>::iterator It = m_curves.begin(); It != m_curves.end(); It++)
for(std::list<CCurve>::iterator It = m_curves.begin(), ItNext=It; It != m_curves.end(); It=ItNext)
{
++ItNext;
CCurve& curve = *It;
ao.Insert(&curve);
if(!It->IsClosed())
continue;
ao.Insert(make_shared<CCurve>(curve));
if(m_set_processing_length_in_split)
{
CArea::m_processing_done += (m_split_processing_length / m_curves.size());
}
m_curves.erase(It);
}
*this = ao.ResultArea();
if(ao.m_top_level)
ao.m_top_level->GetArea(*this);
}
class ZigZag

View File

@@ -7,6 +7,7 @@
#define AREA_HEADER
#include "Curve.h"
#include "clipper.hpp"
enum PocketMode
{
@@ -42,7 +43,11 @@ public:
std::list<CCurve> m_curves;
static double m_accuracy;
static double m_units; // 1.0 for mm, 25.4 for inches. All points are multiplied by this before going to the engine
static bool m_clipper_simple;
static double m_clipper_clean_distance;
static bool m_fit_arcs;
static int m_min_arc_points;
static int m_max_arc_points;
static double m_processing_done; // 0.0 to 100.0, set inside MakeOnePocketCurve
static double m_single_area_processing_length;
static double m_after_MakeOffsets_length;
@@ -50,6 +55,7 @@ public:
static double m_split_processing_length;
static bool m_set_processing_length_in_split;
static bool m_please_abort; // the user sets this from another thread, to tell MakeOnePocketCurve to finish with no result.
static double m_clipper_scale;
void append(const CCurve& curve);
void Subtract(const CArea& a2);
@@ -58,6 +64,11 @@ public:
static CArea UniteCurves(std::list<CCurve> &curves);
void Xor(const CArea& a2);
void Offset(double inwards_value);
void OffsetWithClipper(double offset,
ClipperLib::JoinType joinType=ClipperLib::jtRound,
ClipperLib::EndType endType=ClipperLib::etOpenRound,
double miterLimit = 5.0,
double roundPrecision = 0.0);
void Thicken(double value);
void FitArcs();
unsigned int num_curves(){return static_cast<int>(m_curves.size());}
@@ -73,6 +84,30 @@ public:
void SpanIntersections(const Span& span, std::list<Point> &pts)const;
void CurveIntersections(const CCurve& curve, std::list<Point> &pts)const;
void InsideCurves(const CCurve& curve, std::list<CCurve> &curves_inside)const;
void ChangeStartToNearest(const Point *pstart=NULL, double min_dist=1.0);
//Avoid outside direct accessing static member variable because of Windows DLL issue
#define CAREA_PARAM_DECLARE(_type,_name) \
static _type get_##_name();\
static void set_##_name(_type _name);
CAREA_PARAM_DECLARE(double,tolerance);
CAREA_PARAM_DECLARE(bool,fit_arcs)
CAREA_PARAM_DECLARE(bool,clipper_simple);
CAREA_PARAM_DECLARE(double,clipper_clean_distance);
CAREA_PARAM_DECLARE(double,accuracy);
CAREA_PARAM_DECLARE(double,units);
CAREA_PARAM_DECLARE(short,min_arc_points);
CAREA_PARAM_DECLARE(short,max_arc_points);
CAREA_PARAM_DECLARE(double,clipper_scale);
// Following functions is add to operate on possible open curves
void PopulateClipper(ClipperLib::Clipper &c, ClipperLib::PolyType type) const;
void Clip(ClipperLib::ClipType op,
const CArea *a,
ClipperLib::PolyFillType subjFillType = ClipperLib::pftEvenOdd,
ClipperLib::PolyFillType clipFillType = ClipperLib::pftEvenOdd);
};
enum eOverlapType

View File

@@ -12,7 +12,7 @@ using namespace ClipperLib;
bool CArea::HolesLinked(){ return false; }
//static const double PI = 3.1415926535897932;
static double Clipper4Factor = 10000.0;
double CArea::m_clipper_scale = 10000.0;
class DoubleAreaPoint
{
@@ -20,8 +20,8 @@ public:
double X, Y;
DoubleAreaPoint(double x, double y){X = x; Y = y;}
DoubleAreaPoint(const IntPoint& p){X = (double)(p.X) / Clipper4Factor; Y = (double)(p.Y) / Clipper4Factor;}
IntPoint int_point(){return IntPoint((long64)(X * Clipper4Factor), (long64)(Y * Clipper4Factor));}
DoubleAreaPoint(const IntPoint& p){X = (double)(p.X) / CArea::m_clipper_scale; Y = (double)(p.Y) / CArea::m_clipper_scale;}
IntPoint int_point(){return IntPoint((long64)(X * CArea::m_clipper_scale), (long64)(Y * CArea::m_clipper_scale));}
};
static std::list<DoubleAreaPoint> pts_for_AddVertex;
@@ -81,10 +81,10 @@ static void AddVertex(const CVertex& vertex, const CVertex* prev_vertex)
else
Segments=(int)ceil(-phit/dphi);
if (Segments < 1)
Segments=1;
if (Segments > 100)
Segments=100;
if (Segments < CArea::m_min_arc_points)
Segments = CArea::m_min_arc_points;
if (Segments > CArea::m_max_arc_points)
Segments=CArea::m_max_arc_points;
dphi=phit/(Segments);
@@ -139,6 +139,7 @@ static void MakeLoop(const DoubleAreaPoint &pt0, const DoubleAreaPoint &pt1, con
static void OffsetWithLoops(const TPolyPolygon &pp, TPolyPolygon &pp_new, double inwards_value)
{
Clipper c;
c.StrictlySimple(CArea::m_clipper_simple);
bool inwards = (inwards_value > 0);
bool reverse = false;
@@ -251,6 +252,7 @@ static void MakeObround(const Point &pt0, const CVertex &vt1, double radius)
static void OffsetSpansWithObrounds(const CArea& area, TPolyPolygon &pp_new, double radius)
{
Clipper c;
c.StrictlySimple(CArea::m_clipper_simple);
for(std::list<CCurve>::const_iterator It = area.m_curves.begin(); It != area.m_curves.end(); It++)
@@ -296,48 +298,14 @@ static void OffsetSpansWithObrounds(const CArea& area, TPolyPolygon &pp_new, dou
}
}
static void MakePolyPoly( const CArea& area, TPolyPolygon &pp, bool reverse = true ){
pp.clear();
for(std::list<CCurve>::const_iterator It = area.m_curves.begin(); It != area.m_curves.end(); It++)
{
pts_for_AddVertex.clear();
const CCurve& curve = *It;
const CVertex* prev_vertex = NULL;
for(std::list<CVertex>::const_iterator It2 = curve.m_vertices.begin(); It2 != curve.m_vertices.end(); It2++)
{
const CVertex& vertex = *It2;
if(prev_vertex)AddVertex(vertex, prev_vertex);
prev_vertex = &vertex;
}
TPolygon p;
p.resize(pts_for_AddVertex.size());
if(reverse)
{
std::size_t i = pts_for_AddVertex.size() - 1;// clipper wants them the opposite way to CArea
for(std::list<DoubleAreaPoint>::iterator It = pts_for_AddVertex.begin(); It != pts_for_AddVertex.end(); It++, i--)
{
p[i] = It->int_point();
}
}
else
{
unsigned int i = 0;
for(std::list<DoubleAreaPoint>::iterator It = pts_for_AddVertex.begin(); It != pts_for_AddVertex.end(); It++, i++)
{
p[i] = It->int_point();
}
}
pp.push_back(p);
}
}
static void MakePoly(const CCurve& curve, TPolygon &p)
static void MakePoly(const CCurve& curve, TPolygon &p, bool reverse = false)
{
pts_for_AddVertex.clear();
const CVertex* prev_vertex = NULL;
if(!curve.m_vertices.size()) return;
if(!curve.IsClosed()) AddVertex(curve.m_vertices.front(),NULL);
for (std::list<CVertex>::const_iterator It2 = curve.m_vertices.begin(); It2 != curve.m_vertices.end(); It2++)
{
const CVertex& vertex = *It2;
@@ -346,6 +314,15 @@ static void MakePoly(const CCurve& curve, TPolygon &p)
}
p.resize(pts_for_AddVertex.size());
if(reverse)
{
std::size_t i = pts_for_AddVertex.size() - 1;// clipper wants them the opposite way to CArea
for(std::list<DoubleAreaPoint>::iterator It = pts_for_AddVertex.begin(); It != pts_for_AddVertex.end(); It++, i--)
{
p[i] = It->int_point();
}
}
else
{
unsigned int i = 0;
for (std::list<DoubleAreaPoint>::iterator It = pts_for_AddVertex.begin(); It != pts_for_AddVertex.end(); It++, i++)
@@ -355,8 +332,21 @@ static void MakePoly(const CCurve& curve, TPolygon &p)
}
}
static void SetFromResult( CCurve& curve, const TPolygon& p, bool reverse = true )
static void MakePolyPoly( const CArea& area, TPolyPolygon &pp, bool reverse = true ){
pp.clear();
for(std::list<CCurve>::const_iterator It = area.m_curves.begin(); It != area.m_curves.end(); It++)
{
pp.push_back(TPolygon());
MakePoly(*It,pp.back(),reverse);
}
}
static void SetFromResult( CCurve& curve, TPolygon& p, bool reverse = true )
{
if(CArea::m_clipper_clean_distance >= Point::tolerance)
CleanPolygon(p,CArea::m_clipper_clean_distance);
for(unsigned int j = 0; j < p.size(); j++)
{
const IntPoint &pt = p[j];
@@ -372,14 +362,14 @@ static void SetFromResult( CCurve& curve, const TPolygon& p, bool reverse = true
if(CArea::m_fit_arcs)curve.FitArcs();
}
static void SetFromResult( CArea& area, const TPolyPolygon& pp, bool reverse = true )
static void SetFromResult( CArea& area, TPolyPolygon& pp, bool reverse = true )
{
// delete existing geometry
area.m_curves.clear();
for(unsigned int i = 0; i < pp.size(); i++)
{
const TPolygon& p = pp[i];
TPolygon& p = pp[i];
area.m_curves.push_back(CCurve());
CCurve &curve = area.m_curves.back();
@@ -390,6 +380,7 @@ static void SetFromResult( CArea& area, const TPolyPolygon& pp, bool reverse = t
void CArea::Subtract(const CArea& a2)
{
Clipper c;
c.StrictlySimple(CArea::m_clipper_simple);
TPolyPolygon pp1, pp2;
MakePolyPoly(*this, pp1);
MakePolyPoly(a2, pp2);
@@ -403,6 +394,7 @@ void CArea::Subtract(const CArea& a2)
void CArea::Intersect(const CArea& a2)
{
Clipper c;
c.StrictlySimple(CArea::m_clipper_simple);
TPolyPolygon pp1, pp2;
MakePolyPoly(*this, pp1);
MakePolyPoly(a2, pp2);
@@ -416,6 +408,7 @@ void CArea::Intersect(const CArea& a2)
void CArea::Union(const CArea& a2)
{
Clipper c;
c.StrictlySimple(CArea::m_clipper_simple);
TPolyPolygon pp1, pp2;
MakePolyPoly(*this, pp1);
MakePolyPoly(a2, pp2);
@@ -430,6 +423,7 @@ void CArea::Union(const CArea& a2)
CArea CArea::UniteCurves(std::list<CCurve> &curves)
{
Clipper c;
c.StrictlySimple(CArea::m_clipper_simple);
TPolyPolygon pp;
@@ -452,6 +446,7 @@ CArea CArea::UniteCurves(std::list<CCurve> &curves)
void CArea::Xor(const CArea& a2)
{
Clipper c;
c.StrictlySimple(CArea::m_clipper_simple);
TPolyPolygon pp1, pp2;
MakePolyPoly(*this, pp1);
MakePolyPoly(a2, pp2);
@@ -471,6 +466,73 @@ void CArea::Offset(double inwards_value)
this->Reorder();
}
void CArea::PopulateClipper(Clipper &c, PolyType type) const
{
int skipped = 0;
for (std::list<CCurve>::const_iterator It = m_curves.begin(); It != m_curves.end(); It++)
{
const CCurve &curve = *It;
bool closed = curve.IsClosed();
if(!closed) {
if(type == ptClip){
++skipped;
continue;
}
}
TPolygon p;
MakePoly(curve, p, false);
c.AddPath(p, type, closed);
}
if(skipped)
std::cout << "libarea: warning skipped " << skipped << " open wires" << std::endl;
}
void CArea::Clip(ClipType op, const CArea *a,
PolyFillType subjFillType,
PolyFillType clipFillType)
{
Clipper c;
c.StrictlySimple(CArea::m_clipper_simple);
PopulateClipper(c,ptSubject);
if(a) a->PopulateClipper(c,ptClip);
PolyTree tree;
c.Execute(op, tree, subjFillType,clipFillType);
TPolyPolygon solution;
PolyTreeToPaths(tree,solution);
SetFromResult(*this, solution);
}
void CArea::OffsetWithClipper(double offset,
JoinType joinType/* =jtRound */,
EndType endType/* =etOpenRound */,
double miterLimit/* = 5.0 */,
double roundPrecision/* = 0.0 */)
{
offset *= m_units*m_clipper_scale;
if(roundPrecision == 0.0) {
// Clipper roundPrecision definition: https://goo.gl/4odfQh
double dphi=acos(1.0-m_accuracy*m_clipper_scale/fabs(offset));
int Segments=(int)ceil(PI/dphi);
if (Segments < 2*CArea::m_min_arc_points)
Segments = 2*CArea::m_min_arc_points;
if (Segments > CArea::m_max_arc_points)
Segments=CArea::m_max_arc_points;
dphi = PI/Segments;
roundPrecision = (1.0-cos(dphi))*fabs(offset);
}else
roundPrecision *= m_clipper_scale;
ClipperOffset clipper(miterLimit,roundPrecision);
TPolyPolygon pp, pp2;
MakePolyPoly(*this, pp, false);
int i=0;
for(const CCurve &c : m_curves)
clipper.AddPath(pp[i++],joinType,c.IsClosed()?etClosedPolygon:endType);
clipper.Execute(pp2,(long64)(offset));
SetFromResult(*this, pp2, false);
this->Reorder();
}
void CArea::Thicken(double value)
{
TPolyPolygon pp;

View File

@@ -30,29 +30,27 @@ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "AreaOrderer.h"
#include "Area.h"
using namespace std;
CAreaOrderer* CInnerCurves::area_orderer = NULL;
CInnerCurves::CInnerCurves(CInnerCurves* pOuter, const CCurve* curve)
CInnerCurves::CInnerCurves(shared_ptr<CInnerCurves> pOuter, shared_ptr<CCurve> curve)
:m_pOuter(pOuter)
,m_curve(curve)
{
m_pOuter = pOuter;
m_curve = curve;
m_unite_area = NULL;
}
CInnerCurves::~CInnerCurves()
{
delete m_unite_area;
}
void CInnerCurves::Insert(const CCurve* pcurve)
void CInnerCurves::Insert(shared_ptr<CCurve> pcurve)
{
std::list<CInnerCurves*> outside_of_these;
std::list<CInnerCurves*> crossing_these;
std::list<shared_ptr<CInnerCurves> > outside_of_these;
std::list<shared_ptr<CInnerCurves> > crossing_these;
// check all inner curves
for(std::set<CInnerCurves*>::iterator It = m_inner_curves.begin(); It != m_inner_curves.end(); It++)
{
CInnerCurves* c = *It;
for(shared_ptr<CInnerCurves> c : m_inner_curves) {
switch(GetOverlapType(*pcurve, *(c->m_curve)))
{
@@ -75,28 +73,24 @@ void CInnerCurves::Insert(const CCurve* pcurve)
}
// add as a new inner
CInnerCurves* new_item = new CInnerCurves(this, pcurve);
shared_ptr<CInnerCurves> new_item(new CInnerCurves(shared_from_this(), pcurve));
this->m_inner_curves.insert(new_item);
for(std::list<CInnerCurves*>::iterator It = outside_of_these.begin(); It != outside_of_these.end(); It++)
{
for(shared_ptr<CInnerCurves> c : outside_of_these) {
// move items
CInnerCurves* c = *It;
c->m_pOuter = new_item;
new_item->m_inner_curves.insert(c);
this->m_inner_curves.erase(c);
}
for(std::list<CInnerCurves*>::iterator It = crossing_these.begin(); It != crossing_these.end(); It++)
{
for(shared_ptr<CInnerCurves> c : crossing_these) {
// unite these
CInnerCurves* c = *It;
new_item->Unite(c);
this->m_inner_curves.erase(c);
}
}
void CInnerCurves::GetArea(CArea &area, bool outside, bool use_curve)const
void CInnerCurves::GetArea(CArea &area, bool outside, bool use_curve)
{
if(use_curve && m_curve)
{
@@ -104,11 +98,9 @@ void CInnerCurves::GetArea(CArea &area, bool outside, bool use_curve)const
outside = !outside;
}
std::list<const CInnerCurves*> do_after;
std::list<shared_ptr<CInnerCurves> > do_after;
for(std::set<CInnerCurves*>::const_iterator It = m_inner_curves.begin(); It != m_inner_curves.end(); It++)
{
const CInnerCurves* c = *It;
for(shared_ptr<CInnerCurves> c: m_inner_curves) {
area.m_curves.push_back(*c->m_curve);
if(!outside)area.m_curves.back().Reverse();
@@ -116,20 +108,16 @@ void CInnerCurves::GetArea(CArea &area, bool outside, bool use_curve)const
else do_after.push_back(c);
}
for(std::list<const CInnerCurves*>::iterator It = do_after.begin(); It != do_after.end(); It++)
{
const CInnerCurves* c = *It;
for(shared_ptr<CInnerCurves> c : do_after)
c->GetArea(area, !outside, false);
}
}
void CInnerCurves::Unite(const CInnerCurves* c)
void CInnerCurves::Unite(shared_ptr<CInnerCurves> c)
{
// unite all the curves in c, with this one
CArea* new_area = new CArea();
shared_ptr<CArea> new_area(new CArea());
new_area->m_curves.push_back(*m_curve);
delete m_unite_area;
m_unite_area = new_area;
m_unite_area = new_area;
CArea a2;
c->GetArea(a2);
@@ -140,21 +128,21 @@ void CInnerCurves::Unite(const CInnerCurves* c)
{
CCurve &curve = *It;
if(It == m_unite_area->m_curves.begin())
m_curve = &curve;
m_curve = make_shared<CCurve>(curve);
else
{
if(curve.IsClockwise())curve.Reverse();
Insert(&curve);
Insert(shared_ptr<CCurve>(new CCurve(curve)));
}
}
}
CAreaOrderer::CAreaOrderer()
:m_top_level(make_shared<CInnerCurves>())
{
m_top_level = new CInnerCurves(NULL, NULL);
}
void CAreaOrderer::Insert(CCurve* pcurve)
void CAreaOrderer::Insert(shared_ptr<CCurve> pcurve)
{
CInnerCurves::area_orderer = this;

View File

@@ -28,6 +28,7 @@ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#pragma once
#include <memory>
#include <list>
#include <set>
@@ -36,30 +37,31 @@ class CCurve;
class CAreaOrderer;
class CInnerCurves
class CInnerCurves: public std::enable_shared_from_this<CInnerCurves>
{
CInnerCurves* m_pOuter;
const CCurve* m_curve; // always empty if top level
std::set<CInnerCurves*> m_inner_curves;
CArea *m_unite_area; // new curves made by uniting are stored here
std::shared_ptr<CInnerCurves> m_pOuter;
std::shared_ptr<CCurve> m_curve; // always empty if top level
std::set<std::shared_ptr<CInnerCurves> > m_inner_curves;
std::shared_ptr<CArea> m_unite_area; // new curves made by uniting are stored here
public:
static CAreaOrderer* area_orderer;
CInnerCurves(CInnerCurves* pOuter, const CCurve* curve);
CInnerCurves(std::shared_ptr<CInnerCurves> pOuter, std::shared_ptr<CCurve> curve);
CInnerCurves(){}
~CInnerCurves();
void Insert(const CCurve* pcurve);
void GetArea(CArea &area, bool outside = true, bool use_curve = true)const;
void Unite(const CInnerCurves* c);
void Insert(std::shared_ptr<CCurve> pcurve);
void GetArea(CArea &area, bool outside = true, bool use_curve = true);
void Unite(std::shared_ptr<CInnerCurves> c);
};
class CAreaOrderer
{
public:
CInnerCurves* m_top_level;
std::shared_ptr<CInnerCurves> m_top_level;
CAreaOrderer();
void Insert(CCurve* pcurve);
void Insert(std::shared_ptr<CCurve> pcurve);
CArea ResultArea()const;
};
};

View File

@@ -65,37 +65,52 @@ file(GLOB headers "${CMAKE_CURRENT_SOURCE_DIR}/*.h")
# this makes the Python module
add_library(
area
MODULE
area-native
SHARED
${AREA_SRC_COMMON}
${AREA_SRC_CLIPPER}
${PYAREA_SRC}
)
add_library(
area
MODULE
${PYAREA_SRC}
)
if(MSVC)
set(area_LIBS
${Boost_LIBRARIES}
${PYTHON_LIBRARIES}
set(area_native_LIBS
debug MSVCRTD.LIB
debug MSVCPRTD.LIB
optimized MSVCRT.LIB
optimized MSVCPRT.LIB
)
elseif(MINGW)
set(area_LIBS
${Boost_LIBRARIES}
${PYTHON_LIBRARIES}
${area_native_LIBS}
)
elseif(MINGW)
set(area_native_LIBS
Rpcrt4.lib
)
set(area_LIBS
${Boost_LIBRARIES}
${PYTHON_LIBRARIES}
${area_native_LIBS}
)
else(MSVC)
set(area_native_LIBS
)
set(area_LIBS
${Boost_LIBRARIES}
${PYTHON_LIBRARIES}
)
endif(MSVC)
target_link_libraries(area ${area_LIBS})
target_link_libraries(area-native ${area_native_LIBS})
SET_BIN_DIR(area-native area-native)
target_link_libraries(area area-native ${area_LIBS} ${area_native_LIBS})
SET_BIN_DIR(area area)
SET_PYTHON_PREFIX_SUFFIX(area)
@@ -108,8 +123,20 @@ execute_process(
message(STATUS "area module (for Path Workbench) will be installed to: " ${CMAKE_INSTALL_LIBDIR})
if(WIN32)
set_target_properties(area-native PROPERTIES WINDOWS_EXPORT_ALL_SYMBOLS TRUE)
INSTALL(TARGETS area-native
RUNTIME DESTINATION bin
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
)
else(WIN32)
INSTALL(TARGETS area-native
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
)
endif(WIN32)
# this installs the python library
install(
TARGETS area
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
DESTINATION ${CMAKE_INSTALL_LIBDIR}
)

View File

@@ -13,6 +13,12 @@ double Point::tolerance = 0.001;
//static const double PI = 3.1415926535897932; duplicated in kurve/geometry.h
//This function is moved from header here to solve windows DLL not export
//static variable problem
bool Point::operator==(const Point& p)const{
return fabs(x-p.x)<tolerance && fabs(y-p.y)<tolerance;
}
double Point::length()const
{
return sqrt( x*x + y*y );

View File

@@ -48,7 +48,7 @@ public:
const Point operator-(const Point& p)const{return Point(x - p.x, y - p.y);}
const Point operator*(double d)const{return Point(x * d, y * d);}
const Point operator/(double d)const{return Point(x / d, y / d);}
bool operator==(const Point& p)const{return fabs(x-p.x)<tolerance && fabs(y-p.y)<tolerance;}
bool operator==(const Point& p)const;
bool operator!=(const Point &p)const{ return !(*this == p);}
double dist(const Point &p)const{double dx = p.x - x; double dy = p.y - y; return sqrt(dx*dx + dy*dy);}
double length()const;

View File

@@ -80,8 +80,8 @@ static void print_curve(const CCurve& c)
for(std::list<CVertex>::const_iterator It = c.m_vertices.begin(); It != c.m_vertices.end(); It++, i++)
{
const CVertex& vertex = *It;
printf("vertex %d type = %d, x = %g, y = %g", i+1, vertex.m_type, vertex.m_p.x / CArea::m_units, vertex.m_p.y / CArea::m_units);
if(vertex.m_type)printf(", xc = %g, yc = %g", vertex.m_c.x / CArea::m_units, vertex.m_c.y / CArea::m_units);
printf("vertex %d type = %d, x = %g, y = %g", i+1, vertex.m_type, vertex.m_p.x / CArea::get_units(), vertex.m_p.y / CArea::get_units());
if(vertex.m_type)printf(", xc = %g, yc = %g", vertex.m_c.x / CArea::get_units(), vertex.m_c.y / CArea::get_units());
printf("\n");
}
}
@@ -112,12 +112,12 @@ static CVertex LastVertex(const CCurve& curve)
static void set_units(double units)
{
CArea::m_units = units;
CArea::set_units(units);
}
static double get_units()
{
return CArea::m_units;
return CArea::get_units();
}
static bool holes_linked()

View File

@@ -44,7 +44,7 @@
//#define use_xyz
//use_lines: Enables line clipping. Adds a very minor cost to performance.
//#define use_lines
#define use_lines
//use_deprecated: Enables temporary support for the obsolete functions
//#define use_deprecated