diff --git a/src/Mod/Path/PathScripts/PathSimulatorGui.py b/src/Mod/Path/PathScripts/PathSimulatorGui.py
index 428dcc394c..0045d5ed61 100644
--- a/src/Mod/Path/PathScripts/PathSimulatorGui.py
+++ b/src/Mod/Path/PathScripts/PathSimulatorGui.py
@@ -125,13 +125,21 @@ class PathSimulation:
except Exception:
self.tool = None
- # if hasattr(self.operation, "ToolController"):
- # self.tool = self.operation.ToolController.Tool
if (self.tool is not None):
- toolProf = self.CreateToolProfile(self.tool, Vector(0, 1, 0), Vector(0, 0, 0), float(self.tool.Diameter) / 2.0)
- self.cutTool.Shape = Part.makeSolid(toolProf.revolve(Vector(0, 0, 0), Vector(0, 0, 1)))
+ if isinstance(self.tool, Path.Tool):
+ # handle legacy tools
+ toolProf = self.CreateToolProfile(self.tool, Vector(0, 1, 0), Vector(0, 0, 0), float(self.tool.Diameter) / 2.0)
+ self.cutTool.Shape = Part.makeSolid(toolProf.revolve(Vector(0, 0, 0), Vector(0, 0, 1)))
+ else:
+ # handle tool bits
+ self.cutTool.Shape = self.tool.Shape
+
+ if not self.cutTool.Shape.isValid() or self.cutTool.Shape.isNull():
+ self.EndSimulation()
+ raise RuntimeError("Path Simulation: Error in tool geometry - {}".format(self.tool.Name))
+
self.cutTool.ViewObject.show()
- self.voxSim.SetCurrentTool(self.tool)
+ self.voxSim.SetToolShape(self.cutTool.Shape, 0.05 * self.accuracy)
self.icmd = 0
self.curpos = FreeCAD.Placement(self.initialPos, self.stdrot)
# self.cutTool.Placement = FreeCAD.Placement(self.curpos, self.stdrot)
diff --git a/src/Mod/Path/PathSimulator/App/PathSim.cpp b/src/Mod/Path/PathSimulator/App/PathSim.cpp
index 64afa13f67..621efe5b99 100644
--- a/src/Mod/Path/PathSimulator/App/PathSim.cpp
+++ b/src/Mod/Path/PathSimulator/App/PathSim.cpp
@@ -33,7 +33,6 @@
#include
#include "PathSim.h"
-//#include "VolSim.h"
using namespace Base;
using namespace PathSimulator;
@@ -54,69 +53,15 @@ PathSim::~PathSim()
delete m_tool;
}
-
void PathSim::BeginSimulation(Part::TopoShape * stock, float resolution)
{
Base::BoundBox3d bbox = stock->getBoundBox();
m_stock = new cStock(bbox.MinX, bbox.MinY, bbox.MinZ, bbox.LengthX(), bbox.LengthY(), bbox.LengthZ(), resolution);
}
-void PathSim::SetCurrentTool(Tool * tool)
+void PathSim::SetToolShape(const TopoDS_Shape& toolShape, float resolution)
{
- cSimTool::Type tp = cSimTool::FLAT;
- float angle = 180;
- switch (tool->Type)
- {
- case Tool::BALLENDMILL:
- tp = cSimTool::ROUND;
- break;
-
- case Tool::CHAMFERMILL:
- tp = cSimTool::CHAMFER;
- angle = tool->CuttingEdgeAngle;
- break;
-
- case Tool::UNDEFINED:
- case Tool::DRILL:
- tp = cSimTool::CHAMFER;
- angle = tool->CuttingEdgeAngle;
- if (angle > 180)
- {
- angle = 180;
- }
- break;
- case Tool::CENTERDRILL:
- tp = cSimTool::CHAMFER;
- angle = tool->CuttingEdgeAngle;
- if (angle > 180)
- {
- angle = 180;
- }
- break;
- case Tool::COUNTERSINK:
- case Tool::COUNTERBORE:
- case Tool::REAMER:
- case Tool::TAP:
- case Tool::ENDMILL:
- tp = cSimTool::FLAT;
- angle = 180;
- break;
- case Tool::SLOTCUTTER:
- case Tool::CORNERROUND:
- case Tool::ENGRAVER:
- tp = cSimTool::CHAMFER;
- angle = tool->CuttingEdgeAngle;
- if (angle > 180)
- {
- angle = 180;
- }
- break;
- default:
- tp = cSimTool::FLAT;
- angle = 180;
- break;
- }
- m_tool = new cSimTool(tp, tool->Diameter / 2.0, angle);
+ m_tool = new cSimTool(toolShape, resolution);
}
Base::Placement * PathSim::ApplyCommand(Base::Placement * pos, Command * cmd)
diff --git a/src/Mod/Path/PathSimulator/App/PathSim.h b/src/Mod/Path/PathSimulator/App/PathSim.h
index 5ad93dbb99..90be142766 100644
--- a/src/Mod/Path/PathSimulator/App/PathSim.h
+++ b/src/Mod/Path/PathSimulator/App/PathSim.h
@@ -31,7 +31,6 @@
#include
#include
#include
-#include
#include
#include "VolSim.h"
@@ -51,7 +50,7 @@ namespace PathSimulator
~PathSim();
void BeginSimulation(Part::TopoShape * stock, float resolution);
- void SetCurrentTool(Tool * tool);
+ void SetToolShape(const TopoDS_Shape& toolShape, float resolution);
Base::Placement * ApplyCommand(Base::Placement * pos, Command * cmd);
public:
diff --git a/src/Mod/Path/PathSimulator/App/PathSimPy.xml b/src/Mod/Path/PathSimulator/App/PathSimPy.xml
index 1449f5b20e..7225318f21 100644
--- a/src/Mod/Path/PathSimulator/App/PathSimPy.xml
+++ b/src/Mod/Path/PathSimulator/App/PathSimPy.xml
@@ -23,12 +23,10 @@ Create a path simulator object\n
Start a simulation process on a box shape stock with given resolution\n
-
+
-
- SetCurrentTool(tool):\n
- Set the current Path Tool for the subsequent simulator operations.\n
-
+ SetToolShape(shape):\n
+Set the shape of the tool to be used for simulation\n
diff --git a/src/Mod/Path/PathSimulator/App/PathSimPyImp.cpp b/src/Mod/Path/PathSimulator/App/PathSimPyImp.cpp
index eaec6d454a..708cc4b9a1 100644
--- a/src/Mod/Path/PathSimulator/App/PathSimPyImp.cpp
+++ b/src/Mod/Path/PathSimulator/App/PathSimPyImp.cpp
@@ -69,13 +69,15 @@ PyObject* PathSimPy::BeginSimulation(PyObject * args, PyObject * kwds)
return Py_None;
}
-PyObject* PathSimPy::SetCurrentTool(PyObject * args)
+PyObject* PathSimPy::SetToolShape(PyObject * args)
{
- PyObject *pObjTool;
- if (!PyArg_ParseTuple(args, "O!", &(Path::ToolPy::Type), &pObjTool))
+ PyObject *pObjToolShape;
+ float resolution;
+ if (!PyArg_ParseTuple(args, "O!f", &(Part::TopoShapePy::Type), &pObjToolShape, &resolution))
return 0;
PathSim *sim = getPathSimPtr();
- sim->SetCurrentTool(static_cast(pObjTool)->getToolPtr());
+ const TopoDS_Shape& toolShape = static_cast(pObjToolShape)->getTopoShapePtr()->getShape();
+ sim->SetToolShape(toolShape, resolution);
Py_IncRef(Py_None);
return Py_None;
}
diff --git a/src/Mod/Path/PathSimulator/App/VolSim.cpp b/src/Mod/Path/PathSimulator/App/VolSim.cpp
index 2ba4450586..bc46e76b47 100644
--- a/src/Mod/Path/PathSimulator/App/VolSim.cpp
+++ b/src/Mod/Path/PathSimulator/App/VolSim.cpp
@@ -21,6 +21,11 @@
***************************************************************************/
#include "PreCompiled.h"
+#include
+
+#include
+#include
+#include
#ifndef _PreComp_
# include
@@ -712,41 +717,98 @@ void Point3D::UpdateCmd(Path::Command & cmd)
//************************************************************************************************************
// Simulation tool
//************************************************************************************************************
-float cSimTool::GetToolProfileAt(float pos) // pos is -1..1 location along the radius of the tool (0 is center)
-{
- switch (type)
- {
- case FLAT:
- return 0;
+cSimTool::cSimTool(const TopoDS_Shape& toolShape, float res){
- case CHAMFER:
- {
- if (pos < 0) return -chamRatio * pos;
- return chamRatio * pos;
+ BRepCheck_Analyzer aChecker(toolShape);
+ bool shapeIsValid = aChecker.IsValid() ? true : false;
+
+ if(!shapeIsValid){
+ throw Base::RuntimeError("Path Simulation: Error in tool geometry");
}
- case ROUND:
- pos *= radius;
- return radius - sqrt(dradius - pos * pos);
- break;
+ Bnd_Box boundBox;
+ BRepBndLib::Add(toolShape, boundBox);
+
+ boundBox.SetGap(0.0);
+ Standard_Real xMin, yMin, zMin, xMax, yMax, zMax;
+ boundBox.Get(xMin, yMin, zMin, xMax, yMax, zMax);
+ radius = (xMax - xMin) / 2;
+ length = zMax - zMin;
+
+ Base::Vector3d pnt;
+ pnt.x = 0;
+ pnt.y = 0;
+ pnt.z = 0;
+
+ int radValue = (int)(radius / res) + 1;
+
+ // Measure the performance of the profile extraction
+ //auto start = std::chrono::high_resolution_clock::now();
+
+ for (int x = 0; x < radValue; x++)
+ {
+ // find the face of the tool by checking z points accross the
+ // radius to see if the point is inside the shape
+ pnt.x = x * res;
+ bool inside = isInside(toolShape, pnt, res);
+
+ // move down until the point is outside the shape
+ while(inside && std::abs(pnt.z) < length ){
+ pnt.z -= res;
+ inside = isInside(toolShape, pnt, res);
+ }
+
+ // move up until the point is first inside the shape and record the position
+ while (!inside && pnt.z < length)
+ {
+ pnt.z += res;
+ inside = isInside(toolShape, pnt, res);
+
+ if (inside){
+ toolShapePoint shapePoint;
+ shapePoint.radiusPos = pnt.x;
+ shapePoint.heightPos = pnt.z;
+ m_toolShape.push_back(shapePoint);
+ break;
+ }
+ }
}
- return 0;
+
+ // Report the performance of the profile extraction
+ //auto stop = std::chrono::high_resolution_clock::now();
+ //auto duration = std::chrono::duration_cast(stop - start);
+ //Base::Console().Log("cSimTool::cSimTool - Tool Profile Extraction Took: %i ms\n", duration.count() / 1000);
+
}
-void cSimTool::InitTool() // pos is 0..1 location along the radius of the tool
+float cSimTool::GetToolProfileAt(float pos) // pos is -1..1 location along the radius of the tool (0 is center)
{
- switch (type)
- {
- case CHAMFER:
- chamRatio = radius * tan((90.0 - tipAngle / 2) * 3.1415926535 / 180);
- break;
+ try{
+ float radPos = std::abs(pos) * radius;
+ toolShapePoint test; test.radiusPos = radPos;
+ auto it = std::lower_bound(m_toolShape.begin(), m_toolShape.end(), test, toolShapePoint::less_than());
+ return it->heightPos;
+ }catch(...){
+ return 0;
+ }
+}
- case ROUND:
- dradius = radius * radius;
- break;
+bool cSimTool::isInside(const TopoDS_Shape& toolShape, Base::Vector3d pnt, float res)
+{
+ bool checkFace = true;
+ TopAbs_State stateIn = TopAbs_IN;
- case FLAT:
- break;
+ try {
+ BRepClass3d_SolidClassifier solidClassifier(toolShape);
+ gp_Pnt vertex = gp_Pnt(pnt.x, pnt.y, pnt.z);
+ solidClassifier.Perform(vertex, res);
+ bool inside = (solidClassifier.State() == stateIn);
+ if (checkFace && solidClassifier.IsOnAFace()){
+ inside = true;
+ }
+ return inside;
+ }catch (...) {
+ return false;
}
}
diff --git a/src/Mod/Path/PathSimulator/App/VolSim.h b/src/Mod/Path/PathSimulator/App/VolSim.h
index 39fb371adf..0487db7eb2 100644
--- a/src/Mod/Path/PathSimulator/App/VolSim.h
+++ b/src/Mod/Path/PathSimulator/App/VolSim.h
@@ -34,6 +34,18 @@
#define SIM_TESSEL_TOP 1
#define SIM_TESSEL_BOT 2
#define SIM_WALK_RES 0.6 // step size in pixel units (to make sure all pixels in the path are visited)
+
+struct toolShapePoint {
+ float radiusPos;
+ float heightPos;
+
+ struct less_than{
+ bool operator()(const toolShapePoint &a, const toolShapePoint &b){
+ return a.radiusPos < b.radiusPos;
+ }
+ };
+};
+
struct Point3D
{
Point3D() : x(0), y(0), z(0), sina(0), cosa(0) {}
@@ -88,22 +100,15 @@ struct cLineSegment
class cSimTool
{
public:
- enum Type {
- FLAT = 0,
- CHAMFER,
- ROUND
- };
- cSimTool() : type(FLAT), radius(0), tipAngle(0), dradius(0), chamRatio(0) {}
- cSimTool(Type t, float rad, float tipang = 180) : type(t), radius(rad), tipAngle(tipang) { InitTool(); }
+ cSimTool(const TopoDS_Shape& toolShape, float res);
~cSimTool() {}
- void InitTool();
- Type type;
- float radius;
- float tipAngle;
- float dradius;
- float chamRatio;
float GetToolProfileAt(float pos);
+ bool isInside(const TopoDS_Shape& toolShape, Base::Vector3d pnt, float res);
+
+ std::vector< toolShapePoint > m_toolShape;
+ float radius;
+ float length;
};
template
@@ -131,7 +136,6 @@ private:
int height;
};
-
class cStock
{
public: