Files
create/src/Mod/Path/App/Area.h

258 lines
8.8 KiB
C++

/****************************************************************************
* 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 <TopoDS.hxx>
#include <gp_Pln.hxx>
#include <gp_Circ.hxx>
#include <gp_GTrsf.hxx>
#include "AreaParams.h"
class CArea;
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_CONF)
return true;
}
bool operator!=(const AreaParams &other) const {
return !(*this == other);
}
AreaParams();
};
/** 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 {
/** Stores current libarea settings */
PARAM_DECLARE(PARAM_FNAME,AREA_PARAMS_CAREA)
/** Stores user defined setting */
CAreaParams params;
/** 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();
protected:
struct Shape {
short op;
TopoDS_Shape shape;
Shape(short opCode, const TopoDS_Shape &s)
:op(opCode)
,shape(s)
{}
};
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;
/** 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();
public:
/** Declare all parameters defined in #AREA_PARAMS_ALL as member variable */
PARAM_ENUM_DECLARE(AREA_PARAMS_ALL)
Area(const AreaParams *params = NULL);
virtual ~Area();
/** Set a working plane
*
* If no working plane are set, Area will try to find a working plane from
* all the added children shapes. The purpose of this function is in case
* the child shapes are all colinear edges
*
* \arg \c shape: a shape defining a working plane
*/
void setPlane(const TopoDS_Shape &shape);
/** 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, 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, PARAM_ARGS_DEF(PARAM_FARG,AREA_PARAMS_POCKET));
/** Config this Area object */
void setParams(const AreaParams &params);
/** 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 */
TopoDS_Shape getShape(int index);
/** 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 defecting non circular curves
* */
static void add(CArea &area, const TopoDS_Wire &wire,
const gp_Trsf *trsf=NULL, double deflection=0.01);
/** 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 reorder: reorder closed wires for wire only shape
*
* \return Returns the number of non coplaner. Planar testing only happens
* if \c plane is supplied
* */
static int add(CArea &area, const TopoDS_Shape &shape, const gp_Trsf *trsf=NULL,
double deflection=0.01,const TopoDS_Shape *plane = NULL,
bool force_coplanar=true, CArea *areaOpen=NULL, bool to_edges=false,
bool reorder=true);
/** Convert curves in CArea into an OCC shape
*
* \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);
static bool isCoplanar(const TopoDS_Shape &s1, const TopoDS_Shape &s2);
};
} //namespace Path
#endif //PATH_AREA_H