diff --git a/src/Mod/Path/Gui/Resources/panels/TaskPathSimulator.ui b/src/Mod/Path/Gui/Resources/panels/TaskPathSimulator.ui index 1b8734d1c8..d8ec9ab93e 100644 --- a/src/Mod/Path/Gui/Resources/panels/TaskPathSimulator.ui +++ b/src/Mod/Path/Gui/Resources/panels/TaskPathSimulator.ui @@ -187,10 +187,10 @@ 1 - 100 + 50 - 100 + 50 Qt::Horizontal diff --git a/src/Mod/Path/PathScripts/PathSimulatorGui.py b/src/Mod/Path/PathScripts/PathSimulatorGui.py index 3666e83b1b..466f970792 100644 --- a/src/Mod/Path/PathScripts/PathSimulatorGui.py +++ b/src/Mod/Path/PathScripts/PathSimulatorGui.py @@ -4,10 +4,12 @@ _filePath = os.path.dirname(os.path.abspath(__file__)) import FreeCAD import Path import Part +import Mesh import PathSimulator import math from FreeCAD import Vector, Base from PathScripts.PathGeom import PathGeom + if FreeCAD.GuiUp: import FreeCADGui from PySide import QtGui, QtCore @@ -43,7 +45,9 @@ class PathSimulation: QtCore.QObject.connect(self.timer, QtCore.SIGNAL("timeout()"), self.PerformCut) self.stdrot = FreeCAD.Rotation(Vector(0,0,1),0) self.iprogress = 0 - self.numCommands = 0; + self.numCommands = 0 + self.simperiod = 20 + self.accuracy = 0.1 def Connect(self, but, sig): QtCore.QObject.connect(but, QtCore.SIGNAL("clicked()"), sig) @@ -89,8 +93,11 @@ class PathSimulation: return 0 self.stock = self.job.Stock.Shape if (self.isVoxel): - self.voxSim.BeginSimulation(self.stock,0.5) - self.cutMaterial.Mesh = self.voxSim.GetResultMesh() + maxlen = self.stock.BoundBox.XLength + if (maxlen < self.stock.BoundBox.YLength): + maxlen = self.stock.BoundBox.YLength + self.voxSim.BeginSimulation(self.stock, 0.01 * self.accuracy * maxlen) + (self.cutMaterial.Mesh, self.cutMaterialIn.Mesh) = self.voxSim.GetResultMesh() else: self.cutMaterial.Shape = self.stock self.busy = False @@ -127,11 +134,16 @@ class PathSimulation: # Add cut material if self.isVoxel: self.cutMaterial = FreeCAD.ActiveDocument.addObject("Mesh::FeaturePython","CutMaterial") + self.cutMaterialIn = FreeCAD.ActiveDocument.addObject("Mesh::FeaturePython","CutMaterialIn") + self.cutMaterialIn.ViewObject.Proxy = 0 + self.cutMaterialIn.ViewObject.show() + self.cutMaterialIn.ViewObject.ShapeColor = (1.0, 0.85, 0.45, 0.0) else: self.cutMaterial = FreeCAD.ActiveDocument.addObject("Part::FeaturePython","CutMaterial") self.cutMaterial.Shape = self.job.Stock.Shape self.cutMaterial.ViewObject.Proxy = 0 self.cutMaterial.ViewObject.show() + self.cutMaterial.ViewObject.ShapeColor = (0.5, 0.25, 0.25, 0.0) # Add cut path solid for debug if self.debug: @@ -140,7 +152,7 @@ class PathSimulation: self.cutSolid.ViewObject.hide() self.SetupSimulation() - self.resetSimulation = False + self.resetSimulation = True FreeCAD.ActiveDocument.recompute() #self.dialog.show() @@ -212,7 +224,7 @@ class PathSimulation: self.curpos = self.voxSim.ApplyCommand(self.curpos, cmd) if not self.disableAnim: self.cutTool.Placement = self.curpos #FreeCAD.Placement(self.curpos, self.stdrot) - self.cutMaterial.Mesh = self.voxSim.GetResultMesh() + (self.cutMaterial.Mesh, self.cutMaterialIn.Mesh) = self.voxSim.GetResultMesh() self.icmd += 1 self.iprogress += 1 self.UpdateProgress() @@ -397,11 +409,16 @@ class PathSimulation: def onSpeedBarChange(self): form = self.taskForm.form + self.simperiod = 1000 / form.sliderSpeed.value() form.labelGPerSec.setText(str(form.sliderSpeed.value()) + " G/s") + #if (self.timer.isActive()): + self.timer.setInterval(self.simperiod) + def onAccuracyBarChange(self): form = self.taskForm.form - form.labelAccuracy.setText(str(1.1 - 0.1 * form.sliderAccuracy.value()) + "%") + self.accuracy = 1.1 - 0.1 * form.sliderAccuracy.value() + form.labelAccuracy.setText(str(self.accuracy) + "%") def GuiBusy(self, isBusy): form = self.taskForm.form @@ -435,11 +452,11 @@ class PathSimulation: def SimPlay(self): self.disableAnim = False self.GuiBusy(True) - self.timer.start(20) + self.timer.start(self.simperiod) def ViewShape(self): if self.isVoxel: - self.cutMaterial.Mesh = self.voxSim.GetResultMesh() + (self.cutMaterial.Mesh, self.cutMaterialIn.Mesh) = self.voxSim.GetResultMesh() else: self.cutMaterial.Shape = self.stock @@ -455,15 +472,26 @@ class PathSimulation: FreeCAD.ActiveDocument.removeObject(self.cutTool.Name) self.cutTool = None + def RemoveInnerMaterial(self): + if self.cutMaterialIn is not None: + if self.isVoxel and self.cutMaterial is not None: + mesh = Mesh.Mesh() + mesh.addMesh(self.cutMaterial.Mesh) + mesh.addMesh(self.cutMaterialIn.Mesh) + self.cutMaterial.Mesh = mesh + FreeCAD.ActiveDocument.removeObject(self.cutMaterialIn.Name) + self.cutMaterialIn = None + def RemoveMaterial(self): - if self.cutMaterial is None: - return - FreeCAD.ActiveDocument.removeObject(self.cutMaterial.Name) - self.cutMaterial = None + if self.cutMaterial is not None: + FreeCAD.ActiveDocument.removeObject(self.cutMaterial.Name) + self.cutMaterial = None + self.RemoveInnerMaterial() def accept(self): self.EndSimulation() + self.RemoveInnerMaterial() self.RemoveTool() def cancel(self): diff --git a/src/Mod/Path/PathSimulator/App/PathSimPyImp.cpp b/src/Mod/Path/PathSimulator/App/PathSimPyImp.cpp index c8da4261e4..33a01b7279 100644 --- a/src/Mod/Path/PathSimulator/App/PathSimPyImp.cpp +++ b/src/Mod/Path/PathSimulator/App/PathSimPyImp.cpp @@ -89,10 +89,15 @@ PyObject* PathSimPy::GetResultMesh(PyObject * args) return 0; cStock *stock = getPathSimPtr()->m_stock; - Mesh::MeshObject *mesh = new Mesh::MeshObject(); - Mesh::MeshPy *meshpy = new Mesh::MeshPy(mesh); - stock->Tesselate(*mesh); - return meshpy; + Mesh::MeshObject *meshOuter = new Mesh::MeshObject(); + Mesh::MeshPy *meshOuterpy = new Mesh::MeshPy(meshOuter); + Mesh::MeshObject *meshInner = new Mesh::MeshObject(); + Mesh::MeshPy *meshInnerpy = new Mesh::MeshPy(meshInner); + stock->Tesselate(*meshOuter, *meshInner); + PyObject *tuple = PyTuple_New(2); + PyTuple_SetItem(tuple, 0, meshOuterpy); + PyTuple_SetItem(tuple, 1, meshInnerpy); + return tuple; } diff --git a/src/Mod/Path/PathSimulator/App/VolSim.cpp b/src/Mod/Path/PathSimulator/App/VolSim.cpp index f885cf88b4..55465d718d 100644 --- a/src/Mod/Path/PathSimulator/App/VolSim.cpp +++ b/src/Mod/Path/PathSimulator/App/VolSim.cpp @@ -183,7 +183,10 @@ int cStock::TesselTop(int xp, int yp) Point3D pbr(xp + x_size, yp, z); Point3D ptl(xp, yp + y_size, z); Point3D ptr(xp + x_size, yp + y_size, z); - AddQuad(pbl, pbr, ptr, ptl); + if (abs(m_pz + m_lz - z) < SIM_EPSILON) + AddQuad(pbl, pbr, ptr, ptl, facetsOuter); + else + AddQuad(pbl, pbr, ptr, ptl, facetsInner); } if (farRect) @@ -324,7 +327,7 @@ int cStock::TesselBot(int xp, int yp) Point3D pbr(xp + x_size, yp, m_pz); Point3D ptl(xp, yp + y_size, m_pz); Point3D ptr(xp + x_size, yp + y_size, m_pz); - AddQuad(pbl, ptl, ptr, pbr); + AddQuad(pbl, ptl, ptr, pbr, facetsOuter); if (farRect) return -1; @@ -342,6 +345,10 @@ int cStock::TesselSidesX(int yp) if (yp > 0) lastz2 = std::max(m_stock[0][yp - 1], m_pz); + std::vector *facets = &facetsInner; + if (yp == 0 || yp == m_y) + facets = &facetsOuter; + //bool lastzclip = (lastz - m_pz) < m_res; int lastpoint = 0; for (int x = 1; x <= m_x; x++) @@ -361,7 +368,7 @@ int cStock::TesselSidesX(int yp) Point3D pbr(x, yp, lastz1); Point3D ptl(lastpoint, yp, lastz2); Point3D ptr(x, yp, lastz2); - AddQuad(pbl, ptl, ptr, pbr); + AddQuad(pbl, ptl, ptr, pbr, *facets); } lastz1 = newz1; lastz2 = newz2; @@ -379,6 +386,10 @@ int cStock::TesselSidesY(int xp) if (xp > 0) lastz2 = std::max(m_stock[xp - 1][0], m_pz); + std::vector *facets = &facetsInner; + if (xp == 0 || xp == m_x) + facets = &facetsOuter; + //bool lastzclip = (lastz - m_pz) < m_res; int lastpoint = 0; for (int y = 1; y <= m_y; y++) @@ -398,7 +409,7 @@ int cStock::TesselSidesY(int xp) Point3D pbl(xp, y, lastz1); Point3D ptr(xp, lastpoint, lastz2); Point3D ptl(xp, y, lastz2); - AddQuad(pbl, ptl, ptr, pbr); + AddQuad(pbl, ptl, ptr, pbr, *facets); } lastz1 = newz1; lastz2 = newz2; @@ -421,7 +432,7 @@ void cStock::SetFacetPoints(MeshCore::MeshGeomFacet & facet, Point3D & p1, Point facet.CalcNormal(); } -void cStock::AddQuad(Point3D & p1, Point3D & p2, Point3D & p3, Point3D & p4) +void cStock::AddQuad(Point3D & p1, Point3D & p2, Point3D & p3, Point3D & p4, std::vector & facets) { MeshCore::MeshGeomFacet facet; SetFacetPoints(facet, p1, p2, p3); @@ -430,14 +441,15 @@ void cStock::AddQuad(Point3D & p1, Point3D & p2, Point3D & p3, Point3D & p4) facets.push_back(facet); } -void cStock::Tesselate(Mesh::MeshObject & mesh) +void cStock::Tesselate(Mesh::MeshObject & meshOuter, Mesh::MeshObject & meshInner) { // reset attribs for (int y = 0; y < m_y; y++) for (int x = 0; x < m_x; x++) m_attr[x][y] = 0; - facets.clear(); + facetsOuter.clear(); + facetsInner.clear(); for (int y = 0; y < m_y; y++) { @@ -462,8 +474,10 @@ void cStock::Tesselate(Mesh::MeshObject & mesh) TesselSidesX(y); for (int x = 0; x <= m_x; x++) TesselSidesY(x); - mesh.addFacets(facets); - facets.clear(); + meshOuter.addFacets(facetsOuter); + meshInner.addFacets(facetsInner); + facetsOuter.clear(); + facetsInner.clear(); } diff --git a/src/Mod/Path/PathSimulator/App/VolSim.h b/src/Mod/Path/PathSimulator/App/VolSim.h index c3ce9e503a..5c55aedb10 100644 --- a/src/Mod/Path/PathSimulator/App/VolSim.h +++ b/src/Mod/Path/PathSimulator/App/VolSim.h @@ -85,36 +85,6 @@ struct cLineSegment float lenXY; }; -struct Model3D -{ - Model3D(float px, float py, float res) : pos_x(px), pos_y(py), resolution(res) {} - void SetFacetPoints(MeshCore::MeshGeomFacet & facet, Point3D & p1, Point3D & p2, Point3D & p3) - { - facet._aclPoints[0][0] = p1.x * resolution + pos_x; - facet._aclPoints[0][1] = p1.y * resolution + pos_y; - facet._aclPoints[0][2] = p1.z; - facet._aclPoints[1][0] = p2.x * resolution + pos_x; - facet._aclPoints[1][1] = p2.y * resolution + pos_y; - facet._aclPoints[1][2] = p2.z; - facet._aclPoints[2][0] = p3.x * resolution + pos_x; - facet._aclPoints[2][1] = p3.y * resolution + pos_y; - facet._aclPoints[2][2] = p3.z; - facet.CalcNormal(); - } - - inline void AddQuad(Point3D & p1, Point3D & p2, Point3D & p3, Point3D & p4) - { - MeshCore::MeshGeomFacet facet; - SetFacetPoints(facet, p1, p2, p3); - mesh.addFacet(facet); - SetFacetPoints(facet, p1, p3, p4); - mesh.addFacet(facet); - } - - float pos_x, pos_y, resolution; - Mesh::MeshObject mesh; -}; - class cSimTool { public: @@ -167,7 +137,7 @@ class cStock public: cStock(float px, float py, float pz, float lx, float ly, float lz, float res); ~cStock(); - void Tesselate(Mesh::MeshObject & mesh); + void Tesselate(Mesh::MeshObject & meshOuter, Mesh::MeshObject & meshInner); void CreatePocket(float x, float y, float rad, float height); void ApplyLinearTool(Point3D & p1, Point3D & p2, cSimTool &tool); void ApplyCircularTool(Point3D & p1, Point3D & p2, Point3D & cent, cSimTool &tool, bool isCCW); @@ -179,7 +149,7 @@ private: float FindRectTop(int & xp, int & yp, int & x_size, int & y_size, bool scanHoriz); void FindRectBot(int & xp, int & yp, int & x_size, int & y_size, bool scanHoriz); void SetFacetPoints(MeshCore::MeshGeomFacet & facet, Point3D & p1, Point3D & p2, Point3D & p3); - void AddQuad(Point3D & p1, Point3D & p2, Point3D & p3, Point3D & p4); + void AddQuad(Point3D & p1, Point3D & p2, Point3D & p3, Point3D & p4, std::vector & facets); int TesselTop(int x, int y); int TesselBot(int x, int y); int TesselSidesX(int yp); @@ -191,7 +161,8 @@ private: float m_res; // resoulution float m_plane; // stock plane height int m_x, m_y; // stock array size - std::vector facets; + std::vector facetsOuter; + std::vector facetsInner; }; class cVolSim