Merge pull request #3433 from dubstar-04/fixes/toolbit-simulation
[Path] - Fixes/toolbit simulation
This commit is contained in:
@@ -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)
|
||||
|
||||
@@ -33,7 +33,6 @@
|
||||
#include <Base/Console.h>
|
||||
|
||||
#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)
|
||||
|
||||
@@ -31,7 +31,6 @@
|
||||
#include <TopoDS.hxx>
|
||||
#include <TopoDS_Shape.hxx>
|
||||
#include <Mod/Path/App/Command.h>
|
||||
#include <Mod/Path/App/Tooltable.h>
|
||||
#include <Mod/Part/App/TopoShape.h>
|
||||
#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:
|
||||
|
||||
@@ -23,12 +23,10 @@ Create a path simulator object\n</UserDocu>
|
||||
Start a simulation process on a box shape stock with given resolution\n</UserDocu>
|
||||
</Documentation>
|
||||
</Methode>
|
||||
<Methode Name="SetCurrentTool">
|
||||
<Methode Name="SetToolShape">
|
||||
<Documentation>
|
||||
<UserDocu>
|
||||
SetCurrentTool(tool):\n
|
||||
Set the current Path Tool for the subsequent simulator operations.\n
|
||||
</UserDocu>
|
||||
<UserDocu>SetToolShape(shape):\n
|
||||
Set the shape of the tool to be used for simulation\n</UserDocu>
|
||||
</Documentation>
|
||||
</Methode>
|
||||
<Methode Name="GetResultMesh">
|
||||
|
||||
@@ -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<Path::ToolPy*>(pObjTool)->getToolPtr());
|
||||
const TopoDS_Shape& toolShape = static_cast<Part::TopoShapePy*>(pObjToolShape)->getTopoShapePtr()->getShape();
|
||||
sim->SetToolShape(toolShape, resolution);
|
||||
Py_IncRef(Py_None);
|
||||
return Py_None;
|
||||
}
|
||||
|
||||
@@ -21,6 +21,11 @@
|
||||
***************************************************************************/
|
||||
|
||||
#include "PreCompiled.h"
|
||||
#include <Base/Console.h>
|
||||
|
||||
#include <BRepCheck_Analyzer.hxx>
|
||||
#include <BRepClass3d_SolidClassifier.hxx>
|
||||
#include <gp_Pnt.hxx>
|
||||
|
||||
#ifndef _PreComp_
|
||||
# include <algorithm>
|
||||
@@ -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<std::chrono::microseconds>(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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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 <class T>
|
||||
@@ -131,7 +136,6 @@ private:
|
||||
int height;
|
||||
};
|
||||
|
||||
|
||||
class cStock
|
||||
{
|
||||
public:
|
||||
|
||||
Reference in New Issue
Block a user