PATH: Delete misplaced and unused files
This commit is contained in:
parent
207432c0bd
commit
84b3617c97
|
@ -67,7 +67,6 @@ class PathWorkbench (Workbench):
|
||||||
from PathScripts import PathSimpleCopy
|
from PathScripts import PathSimpleCopy
|
||||||
from PathScripts import PathEngrave
|
from PathScripts import PathEngrave
|
||||||
from PathScripts import PathSurface
|
from PathScripts import PathSurface
|
||||||
from PathScripts import PathRemote
|
|
||||||
from PathScripts import PathSanity
|
from PathScripts import PathSanity
|
||||||
from PathScripts import DragknifeDressup
|
from PathScripts import DragknifeDressup
|
||||||
from PathScripts import PathContour
|
from PathScripts import PathContour
|
||||||
|
|
|
@ -1,145 +0,0 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<ui version="4.0">
|
|
||||||
<class>Dialog</class>
|
|
||||||
<widget class="QDialog" name="Dialog">
|
|
||||||
<property name="geometry">
|
|
||||||
<rect>
|
|
||||||
<x>0</x>
|
|
||||||
<y>0</y>
|
|
||||||
<width>946</width>
|
|
||||||
<height>614</height>
|
|
||||||
</rect>
|
|
||||||
</property>
|
|
||||||
<property name="windowTitle">
|
|
||||||
<string>Dialog</string>
|
|
||||||
</property>
|
|
||||||
<layout class="QGridLayout" name="gridLayout">
|
|
||||||
<item row="1" column="1">
|
|
||||||
<widget class="QDialogButtonBox" name="buttonBox">
|
|
||||||
<property name="orientation">
|
|
||||||
<enum>Qt::Horizontal</enum>
|
|
||||||
</property>
|
|
||||||
<property name="standardButtons">
|
|
||||||
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="1" column="0">
|
|
||||||
<widget class="QCommandLinkButton" name="cmdAddTools">
|
|
||||||
<property name="text">
|
|
||||||
<string>Add Selected Tools to Project</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="0" column="0" colspan="2">
|
|
||||||
<widget class="QGroupBox" name="groupBox">
|
|
||||||
<property name="title">
|
|
||||||
<string>Tool Library</string>
|
|
||||||
</property>
|
|
||||||
<layout class="QGridLayout" name="gridLayout_2">
|
|
||||||
<item row="4" column="2">
|
|
||||||
<widget class="QPushButton" name="ButtonDelete">
|
|
||||||
<property name="text">
|
|
||||||
<string>Delete</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="0" column="3">
|
|
||||||
<widget class="QPushButton" name="ButtonImport">
|
|
||||||
<property name="text">
|
|
||||||
<string>Import...</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="4" column="3">
|
|
||||||
<widget class="QPushButton" name="ButtonUp">
|
|
||||||
<property name="text">
|
|
||||||
<string>Move up</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="4" column="0">
|
|
||||||
<widget class="QPushButton" name="ButtonAdd">
|
|
||||||
<property name="text">
|
|
||||||
<string>Add new List</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="4" column="4">
|
|
||||||
<widget class="QPushButton" name="ButtonDown">
|
|
||||||
<property name="text">
|
|
||||||
<string>Move down</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="4" column="1">
|
|
||||||
<widget class="QPushButton" name="ButtonNewTool">
|
|
||||||
<property name="text">
|
|
||||||
<string>New Tool</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="3" column="0">
|
|
||||||
<widget class="QListWidget" name="listWidget">
|
|
||||||
<property name="sizePolicy">
|
|
||||||
<sizepolicy hsizetype="Minimum" vsizetype="Expanding">
|
|
||||||
<horstretch>0</horstretch>
|
|
||||||
<verstretch>0</verstretch>
|
|
||||||
</sizepolicy>
|
|
||||||
</property>
|
|
||||||
<property name="acceptDrops">
|
|
||||||
<bool>true</bool>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="0" column="4">
|
|
||||||
<widget class="QPushButton" name="ButtonExport">
|
|
||||||
<property name="text">
|
|
||||||
<string>Export...</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="3" column="1" colspan="4">
|
|
||||||
<widget class="QTableView" name="ToolsList"/>
|
|
||||||
</item>
|
|
||||||
</layout>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
</layout>
|
|
||||||
</widget>
|
|
||||||
<resources/>
|
|
||||||
<connections>
|
|
||||||
<connection>
|
|
||||||
<sender>buttonBox</sender>
|
|
||||||
<signal>accepted()</signal>
|
|
||||||
<receiver>Dialog</receiver>
|
|
||||||
<slot>accept()</slot>
|
|
||||||
<hints>
|
|
||||||
<hint type="sourcelabel">
|
|
||||||
<x>248</x>
|
|
||||||
<y>254</y>
|
|
||||||
</hint>
|
|
||||||
<hint type="destinationlabel">
|
|
||||||
<x>157</x>
|
|
||||||
<y>274</y>
|
|
||||||
</hint>
|
|
||||||
</hints>
|
|
||||||
</connection>
|
|
||||||
<connection>
|
|
||||||
<sender>buttonBox</sender>
|
|
||||||
<signal>rejected()</signal>
|
|
||||||
<receiver>Dialog</receiver>
|
|
||||||
<slot>reject()</slot>
|
|
||||||
<hints>
|
|
||||||
<hint type="sourcelabel">
|
|
||||||
<x>316</x>
|
|
||||||
<y>260</y>
|
|
||||||
</hint>
|
|
||||||
<hint type="destinationlabel">
|
|
||||||
<x>286</x>
|
|
||||||
<y>274</y>
|
|
||||||
</hint>
|
|
||||||
</hints>
|
|
||||||
</connection>
|
|
||||||
</connections>
|
|
||||||
</ui>
|
|
|
@ -1,244 +0,0 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<ui version="4.0">
|
|
||||||
<class>Dialog</class>
|
|
||||||
<widget class="QDialog" name="Dialog">
|
|
||||||
<property name="geometry">
|
|
||||||
<rect>
|
|
||||||
<x>0</x>
|
|
||||||
<y>0</y>
|
|
||||||
<width>807</width>
|
|
||||||
<height>555</height>
|
|
||||||
</rect>
|
|
||||||
</property>
|
|
||||||
<property name="windowTitle">
|
|
||||||
<string>Dialog</string>
|
|
||||||
</property>
|
|
||||||
<layout class="QGridLayout" name="gridLayout">
|
|
||||||
<item row="0" column="1" colspan="2">
|
|
||||||
<widget class="QGroupBox" name="groupBox_2">
|
|
||||||
<property name="title">
|
|
||||||
<string>Tool Properties</string>
|
|
||||||
</property>
|
|
||||||
<layout class="QFormLayout" name="formLayout">
|
|
||||||
<property name="fieldGrowthPolicy">
|
|
||||||
<enum>QFormLayout::AllNonFixedFieldsGrow</enum>
|
|
||||||
</property>
|
|
||||||
<item row="0" column="0">
|
|
||||||
<widget class="QLabel" name="label">
|
|
||||||
<property name="text">
|
|
||||||
<string>Name</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="0" column="1">
|
|
||||||
<widget class="QLineEdit" name="NameField"/>
|
|
||||||
</item>
|
|
||||||
<item row="2" column="0">
|
|
||||||
<widget class="QLabel" name="label_2">
|
|
||||||
<property name="text">
|
|
||||||
<string>Type</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="2" column="1">
|
|
||||||
<widget class="QComboBox" name="TypeField"/>
|
|
||||||
</item>
|
|
||||||
<item row="4" column="0">
|
|
||||||
<widget class="QLabel" name="label_3">
|
|
||||||
<property name="text">
|
|
||||||
<string>Material</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="4" column="1">
|
|
||||||
<widget class="QComboBox" name="MaterialField"/>
|
|
||||||
</item>
|
|
||||||
<item row="6" column="0">
|
|
||||||
<widget class="QLabel" name="label_4">
|
|
||||||
<property name="text">
|
|
||||||
<string>Diameter</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="6" column="1">
|
|
||||||
<widget class="QDoubleSpinBox" name="DiameterField">
|
|
||||||
<property name="suffix">
|
|
||||||
<string>mm</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="8" column="0">
|
|
||||||
<widget class="QLabel" name="label_5">
|
|
||||||
<property name="text">
|
|
||||||
<string>Length Offset</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="8" column="1">
|
|
||||||
<widget class="QDoubleSpinBox" name="LengthOffsetField">
|
|
||||||
<property name="suffix">
|
|
||||||
<string>mm</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="12" column="0">
|
|
||||||
<widget class="QLabel" name="label_6">
|
|
||||||
<property name="text">
|
|
||||||
<string>Flat Radius</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="12" column="1">
|
|
||||||
<widget class="QDoubleSpinBox" name="FlatRadiusField">
|
|
||||||
<property name="suffix">
|
|
||||||
<string>mm</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="14" column="0">
|
|
||||||
<widget class="QLabel" name="label_7">
|
|
||||||
<property name="text">
|
|
||||||
<string>Corner Radius</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="14" column="1">
|
|
||||||
<widget class="QDoubleSpinBox" name="CornerRadiusField">
|
|
||||||
<property name="suffix">
|
|
||||||
<string>mm</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="16" column="0">
|
|
||||||
<widget class="QLabel" name="label_9">
|
|
||||||
<property name="text">
|
|
||||||
<string>Cutting Edge Angle</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="16" column="1">
|
|
||||||
<widget class="QDoubleSpinBox" name="CuttingEdgeAngleField">
|
|
||||||
<property name="suffix">
|
|
||||||
<string>°</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="18" column="0">
|
|
||||||
<widget class="QLabel" name="label_8">
|
|
||||||
<property name="text">
|
|
||||||
<string>Cutting Edge Height</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="18" column="1">
|
|
||||||
<widget class="QDoubleSpinBox" name="CuttingEdgeHeightField">
|
|
||||||
<property name="suffix">
|
|
||||||
<string>mm</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
</layout>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="1" column="2">
|
|
||||||
<widget class="QDialogButtonBox" name="buttonBox">
|
|
||||||
<property name="orientation">
|
|
||||||
<enum>Qt::Horizontal</enum>
|
|
||||||
</property>
|
|
||||||
<property name="standardButtons">
|
|
||||||
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="0" column="0">
|
|
||||||
<widget class="QGroupBox" name="groupBox">
|
|
||||||
<property name="title">
|
|
||||||
<string>Tool List</string>
|
|
||||||
</property>
|
|
||||||
<layout class="QGridLayout" name="gridLayout_2">
|
|
||||||
<item row="2" column="1">
|
|
||||||
<widget class="QPushButton" name="ButtonDelete">
|
|
||||||
<property name="text">
|
|
||||||
<string>Delete</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="2" column="2">
|
|
||||||
<widget class="QPushButton" name="ButtonUp">
|
|
||||||
<property name="text">
|
|
||||||
<string>Move up</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="0" column="0" colspan="2">
|
|
||||||
<widget class="QPushButton" name="ButtonImport">
|
|
||||||
<property name="text">
|
|
||||||
<string>Import...</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="0" column="2" colspan="2">
|
|
||||||
<widget class="QPushButton" name="ButtonExport">
|
|
||||||
<property name="text">
|
|
||||||
<string>Export...</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="2" column="0">
|
|
||||||
<widget class="QPushButton" name="ButtonAdd">
|
|
||||||
<property name="text">
|
|
||||||
<string>Add new</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="1" column="0" colspan="4">
|
|
||||||
<widget class="QTableView" name="ToolsList"/>
|
|
||||||
</item>
|
|
||||||
<item row="2" column="3">
|
|
||||||
<widget class="QPushButton" name="ButtonDown">
|
|
||||||
<property name="text">
|
|
||||||
<string>Move down</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
</layout>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
</layout>
|
|
||||||
</widget>
|
|
||||||
<resources/>
|
|
||||||
<connections>
|
|
||||||
<connection>
|
|
||||||
<sender>buttonBox</sender>
|
|
||||||
<signal>accepted()</signal>
|
|
||||||
<receiver>Dialog</receiver>
|
|
||||||
<slot>accept()</slot>
|
|
||||||
<hints>
|
|
||||||
<hint type="sourcelabel">
|
|
||||||
<x>248</x>
|
|
||||||
<y>254</y>
|
|
||||||
</hint>
|
|
||||||
<hint type="destinationlabel">
|
|
||||||
<x>157</x>
|
|
||||||
<y>274</y>
|
|
||||||
</hint>
|
|
||||||
</hints>
|
|
||||||
</connection>
|
|
||||||
<connection>
|
|
||||||
<sender>buttonBox</sender>
|
|
||||||
<signal>rejected()</signal>
|
|
||||||
<receiver>Dialog</receiver>
|
|
||||||
<slot>reject()</slot>
|
|
||||||
<hints>
|
|
||||||
<hint type="sourcelabel">
|
|
||||||
<x>316</x>
|
|
||||||
<y>260</y>
|
|
||||||
</hint>
|
|
||||||
<hint type="destinationlabel">
|
|
||||||
<x>286</x>
|
|
||||||
<y>274</y>
|
|
||||||
</hint>
|
|
||||||
</hints>
|
|
||||||
</connection>
|
|
||||||
</connections>
|
|
||||||
</ui>
|
|
|
@ -37,21 +37,21 @@ except AttributeError:
|
||||||
return QtGui.QApplication.translate(context, text, disambig)
|
return QtGui.QApplication.translate(context, text, disambig)
|
||||||
|
|
||||||
|
|
||||||
class OldHighlighter(QtGui.QSyntaxHighlighter):
|
# class OldHighlighter(QtGui.QSyntaxHighlighter):
|
||||||
|
|
||||||
def highlightBlock(self, text):
|
# def highlightBlock(self, text):
|
||||||
|
|
||||||
myClassFormat = QtGui.QTextCharFormat()
|
# myClassFormat = QtGui.QTextCharFormat()
|
||||||
myClassFormat.setFontWeight(QtGui.QFont.Bold)
|
# myClassFormat.setFontWeight(QtGui.QFont.Bold)
|
||||||
myClassFormat.setForeground(QtCore.Qt.green)
|
# myClassFormat.setForeground(QtCore.Qt.green)
|
||||||
# the regex pattern to be colored
|
# # the regex pattern to be colored
|
||||||
pattern = "(G.*?|M.*?)\\s"
|
# pattern = "(G.*?|M.*?)\\s"
|
||||||
expression = QtCore.QRegExp(pattern)
|
# expression = QtCore.QRegExp(pattern)
|
||||||
index = text.index(expression)
|
# index = text.index(expression)
|
||||||
while index >= 0:
|
# while index >= 0:
|
||||||
length = expression.matchedLength()
|
# length = expression.matchedLength()
|
||||||
setFormat(index, length, myClassFormat)
|
# setFormat(index, length, myClassFormat)
|
||||||
index = text.index(expression, index + length)
|
# index = text.index(expression, index + length)
|
||||||
|
|
||||||
|
|
||||||
class GCodeHighlighter(QtGui.QSyntaxHighlighter):
|
class GCodeHighlighter(QtGui.QSyntaxHighlighter):
|
||||||
|
|
|
@ -28,8 +28,6 @@ from PySide import QtCore, QtGui
|
||||||
from PathScripts.PathPostProcessor import PostProcessor
|
from PathScripts.PathPostProcessor import PostProcessor
|
||||||
from PathScripts.PathPreferences import PathPreferences
|
from PathScripts.PathPreferences import PathPreferences
|
||||||
import Draft
|
import Draft
|
||||||
import os
|
|
||||||
import glob
|
|
||||||
|
|
||||||
|
|
||||||
FreeCADGui = None
|
FreeCADGui = None
|
||||||
|
|
|
@ -22,16 +22,9 @@
|
||||||
# * *
|
# * *
|
||||||
# ***************************************************************************
|
# ***************************************************************************
|
||||||
'''PathKurveUtils - functions needed for using libarea (created by Dan Heeks) for making simple CNC profile paths '''
|
'''PathKurveUtils - functions needed for using libarea (created by Dan Heeks) for making simple CNC profile paths '''
|
||||||
import FreeCAD
|
|
||||||
from FreeCAD import Vector
|
|
||||||
import FreeCADGui as Gui
|
|
||||||
import Part
|
import Part
|
||||||
import DraftGeomUtils
|
|
||||||
import DraftVecUtils
|
|
||||||
from DraftGeomUtils import geomType
|
|
||||||
import math
|
import math
|
||||||
import area
|
import area
|
||||||
import Path
|
|
||||||
from PathScripts import PathUtils
|
from PathScripts import PathUtils
|
||||||
from nc.nc import *
|
from nc.nc import *
|
||||||
import PathScripts.nc.iso
|
import PathScripts.nc.iso
|
||||||
|
@ -209,7 +202,7 @@ def profile(curve, side_of_line, radius=1.0, vertfeed=0.0, horizfeed=0.0, offset
|
||||||
layer_count = int((start_depth - final_depth) / stepdown)
|
layer_count = int((start_depth - final_depth) / stepdown)
|
||||||
if layer_count * stepdown + 0.00001 < start_depth - final_depth:
|
if layer_count * stepdown + 0.00001 < start_depth - final_depth:
|
||||||
layer_count += 1
|
layer_count += 1
|
||||||
current_start_depth = start_depth
|
# current_start_depth = start_depth
|
||||||
prev_depth = start_depth
|
prev_depth = start_depth
|
||||||
for i in range(1, layer_count + 1):
|
for i in range(1, layer_count + 1):
|
||||||
if i == layer_count:
|
if i == layer_count:
|
||||||
|
@ -388,7 +381,7 @@ def profile2(curve, direction="on", radius=1.0, vertfeed=0.0,
|
||||||
# do multiple depths
|
# do multiple depths
|
||||||
depths = depthparams.get_depths()
|
depths = depthparams.get_depths()
|
||||||
|
|
||||||
current_start_depth = depthparams.start_depth
|
# current_start_depth = depthparams.start_depth
|
||||||
|
|
||||||
# tags
|
# tags
|
||||||
if len(tags) > 0:
|
if len(tags) > 0:
|
||||||
|
@ -532,7 +525,7 @@ class Tag:
|
||||||
|
|
||||||
height_above_depth = tag_top_depth - depth
|
height_above_depth = tag_top_depth - depth
|
||||||
ramp_width_at_depth = height_above_depth / math.tan(self.angle)
|
ramp_width_at_depth = height_above_depth / math.tan(self.angle)
|
||||||
cut_depth = start_depth - depth
|
# cut_depth = start_depth - depth
|
||||||
half_flat_top = radius + self.width / 2
|
half_flat_top = radius + self.width / 2
|
||||||
|
|
||||||
d = curve.PointToPerim(self.p)
|
d = curve.PointToPerim(self.p)
|
||||||
|
@ -574,7 +567,7 @@ class Tag:
|
||||||
def get_z_at_perim(self, current_perim, curve, radius, start_depth, depth, final_depth):
|
def get_z_at_perim(self, current_perim, curve, radius, start_depth, depth, final_depth):
|
||||||
# return the z for this position on the kurve ( specified by current_perim ), for this tag
|
# return the z for this position on the kurve ( specified by current_perim ), for this tag
|
||||||
# if the position is not within the tag, then depth is returned
|
# if the position is not within the tag, then depth is returned
|
||||||
cut_depth = start_depth - depth
|
# cut_depth = start_depth - depth
|
||||||
half_flat_top = radius + self.width / 2
|
half_flat_top = radius + self.width / 2
|
||||||
|
|
||||||
z = depth
|
z = depth
|
||||||
|
|
|
@ -224,7 +224,7 @@ class ObjectFace:
|
||||||
self.vertFeed = 100
|
self.vertFeed = 100
|
||||||
self.horizFeed = 100
|
self.horizFeed = 100
|
||||||
self.vertRapid = 100
|
self.vertRapid = 100
|
||||||
self.horiRrapid = 100
|
self.horizRrapid = 100
|
||||||
self.radius = 0.25
|
self.radius = 0.25
|
||||||
obj.ToolNumber = 0
|
obj.ToolNumber = 0
|
||||||
obj.ToolDescription = "UNDEFINED"
|
obj.ToolDescription = "UNDEFINED"
|
||||||
|
|
|
@ -1,478 +0,0 @@
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
|
|
||||||
# ***************************************************************************
|
|
||||||
# * *
|
|
||||||
# * Copyright (c) 2016 sliptonic <shopinthewoods@gmail.com> *
|
|
||||||
# * *
|
|
||||||
# * This program is free software; you can redistribute it and/or modify *
|
|
||||||
# * it under the terms of the GNU Lesser General Public License (LGPL) *
|
|
||||||
# * as published by the Free Software Foundation; either version 2 of *
|
|
||||||
# * the License, or (at your option) any later version. *
|
|
||||||
# * for detail see the LICENCE text file. *
|
|
||||||
# * *
|
|
||||||
# * This program 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 program; if not, write to the Free Software *
|
|
||||||
# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
|
|
||||||
# * USA *
|
|
||||||
# * *
|
|
||||||
# ***************************************************************************
|
|
||||||
|
|
||||||
import FreeCAD
|
|
||||||
import Path
|
|
||||||
from PathScripts import PathUtils
|
|
||||||
import urllib2
|
|
||||||
import json
|
|
||||||
|
|
||||||
if FreeCAD.GuiUp:
|
|
||||||
import FreeCADGui
|
|
||||||
from PySide import QtCore, QtGui
|
|
||||||
|
|
||||||
__title__ = "Path Remote Operation"
|
|
||||||
__author__ = "sliptonic (Brad Collette)"
|
|
||||||
__url__ = "http://www.freecadweb.org"
|
|
||||||
|
|
||||||
"""Path Remote processing object and FreeCAD command"""
|
|
||||||
|
|
||||||
# Qt tanslation handling
|
|
||||||
try:
|
|
||||||
_encoding = QtGui.QApplication.UnicodeUTF8
|
|
||||||
|
|
||||||
def translate(context, text, disambig=None):
|
|
||||||
return QtGui.QApplication.translate(context, text, disambig, _encoding)
|
|
||||||
except AttributeError:
|
|
||||||
def translate(context, text, disambig=None):
|
|
||||||
return QtGui.QApplication.translate(context, text, disambig)
|
|
||||||
|
|
||||||
|
|
||||||
class ObjectRemote:
|
|
||||||
|
|
||||||
def __init__(self, obj):
|
|
||||||
|
|
||||||
obj.addProperty("App::PropertyLinkSubList", "Base", "Path", QtCore.QT_TRANSLATE_NOOP("App::Property","The base geometry of this toolpath"))
|
|
||||||
obj.addProperty("App::PropertyBool", "Active", "Path", QtCore.QT_TRANSLATE_NOOP("App::Property","Make False, to prevent operation from generating code"))
|
|
||||||
obj.addProperty("App::PropertyString", "Comment", "Path", QtCore.QT_TRANSLATE_NOOP("App::Property","An optional comment for this profile"))
|
|
||||||
obj.addProperty("App::PropertyString", "UserLabel", "Path", QtCore.QT_TRANSLATE_NOOP("App::Property","User Assigned Label"))
|
|
||||||
|
|
||||||
obj.addProperty("App::PropertyString", "URL", "API", QtCore.QT_TRANSLATE_NOOP("App::Property","The Base URL of the remote path service"))
|
|
||||||
obj.addProperty("App::PropertyStringList", "proplist", "Path", QtCore.QT_TRANSLATE_NOOP("App::Property","list of remote properties"))
|
|
||||||
obj.setEditorMode('proplist', 2) # make this hidden
|
|
||||||
|
|
||||||
# Tool Properties
|
|
||||||
obj.addProperty("App::PropertyIntegerConstraint", "ToolNumber", "Tool",QtCore.QT_TRANSLATE_NOOP("App::Property","The tool number in use"))
|
|
||||||
obj.ToolNumber = (0, 0, 1000, 0)
|
|
||||||
obj.setEditorMode('ToolNumber', 1) # make this read only
|
|
||||||
obj.addProperty("App::PropertyString", "ToolDescription", "Tool", QtCore.QT_TRANSLATE_NOOP("App::Property","The description of the tool "))
|
|
||||||
obj.setEditorMode('ToolDescription', 1) # make this read onlyt
|
|
||||||
|
|
||||||
# Depth Properties
|
|
||||||
obj.addProperty("App::PropertyFloat", "ClearanceHeight", "Depth", QtCore.QT_TRANSLATE_NOOP("App::Property","The height needed to clear clamps and obstructions"))
|
|
||||||
obj.addProperty("App::PropertyFloat", "SafeHeight", "Depth", QtCore.QT_TRANSLATE_NOOP("App::Property","Rapid Safety Height between locations."))
|
|
||||||
obj.addProperty("App::PropertyFloatConstraint", "StepDown", "Step", QtCore.QT_TRANSLATE_NOOP("App::Property","Incremental Step Down of Tool"))
|
|
||||||
obj.StepDown = (0.0, 0.01, 100.0, 0.5)
|
|
||||||
obj.addProperty("App::PropertyFloat", "StartDepth", "Depth", QtCore.QT_TRANSLATE_NOOP("App::Property","Starting Depth of Tool- first cut depth in Z"))
|
|
||||||
obj.addProperty("App::PropertyFloat", "FinalDepth", "Depth", QtCore.QT_TRANSLATE_NOOP("App::Property","Final Depth of Tool- lowest value in Z"))
|
|
||||||
obj.addProperty("App::PropertyFloat", "FinishDepth", "Depth", QtCore.QT_TRANSLATE_NOOP("App::Property","Maximum material removed on final pass."))
|
|
||||||
|
|
||||||
obj.Proxy = self
|
|
||||||
|
|
||||||
def addbaseobject(self, obj, ss, sub=""):
|
|
||||||
baselist = obj.Base
|
|
||||||
if len(baselist) == 0: # When adding the first base object, guess at heights
|
|
||||||
try:
|
|
||||||
bb = ss.Shape.BoundBox # parent boundbox
|
|
||||||
subobj = ss.Shape.getElement(sub)
|
|
||||||
fbb = subobj.BoundBox # feature boundbox
|
|
||||||
obj.StartDepth = bb.ZMax
|
|
||||||
obj.ClearanceHeight = bb.ZMax + 5.0
|
|
||||||
obj.SafeHeight = bb.ZMax + 3.0
|
|
||||||
|
|
||||||
if fbb.ZMax < bb.ZMax:
|
|
||||||
obj.FinalDepth = fbb.ZMax
|
|
||||||
else:
|
|
||||||
obj.FinalDepth = bb.ZMin
|
|
||||||
except:
|
|
||||||
obj.StartDepth = 5.0
|
|
||||||
obj.ClearanceHeight = 10.0
|
|
||||||
obj.SafeHeight = 8.0
|
|
||||||
|
|
||||||
item = (ss, sub)
|
|
||||||
if item in baselist:
|
|
||||||
FreeCAD.Console.PrintWarning("this object already in the list" + "\n")
|
|
||||||
else:
|
|
||||||
baselist.append(item)
|
|
||||||
obj.Base = baselist
|
|
||||||
self.execute(obj)
|
|
||||||
|
|
||||||
def __getstate__(self):
|
|
||||||
return None
|
|
||||||
|
|
||||||
def __setstate__(self, state):
|
|
||||||
return None
|
|
||||||
|
|
||||||
def onChanged(self, obj, prop):
|
|
||||||
|
|
||||||
"'''Do something when a property has changed'''"
|
|
||||||
if prop == "URL":
|
|
||||||
url = obj.URL + "/api/v1.0/properties"
|
|
||||||
try:
|
|
||||||
response = urllib2.urlopen(url)
|
|
||||||
except:
|
|
||||||
print "service not defined or not responding"
|
|
||||||
print "len: " + str(len(obj.proplist))
|
|
||||||
if len(obj.proplist) != 0:
|
|
||||||
for prop in obj.proplist:
|
|
||||||
print "removing: " + str(prop)
|
|
||||||
obj.removeProperty(prop)
|
|
||||||
pl = obj.proplist
|
|
||||||
pl = []
|
|
||||||
obj.proplist = pl
|
|
||||||
return
|
|
||||||
|
|
||||||
data = json.load(response)
|
|
||||||
|
|
||||||
properties = data['properties']
|
|
||||||
for prop in obj.proplist:
|
|
||||||
print "removing: " + str(prop)
|
|
||||||
obj.removeProperty(prop)
|
|
||||||
|
|
||||||
pl = obj.proplist
|
|
||||||
pl = []
|
|
||||||
for prop in properties:
|
|
||||||
obj.addProperty(
|
|
||||||
prop['type'],
|
|
||||||
prop['propertyname'],
|
|
||||||
"Remote",
|
|
||||||
prop['description'])
|
|
||||||
pl.append(prop['propertyname'])
|
|
||||||
print "adding: " + str(prop)
|
|
||||||
obj.proplist = pl
|
|
||||||
|
|
||||||
if prop == "UserLabel":
|
|
||||||
obj.Label = obj.UserLabel + " :" + obj.ToolDescription
|
|
||||||
|
|
||||||
def execute(self, obj):
|
|
||||||
output = ""
|
|
||||||
if obj.Comment != "":
|
|
||||||
output += '(' + str(obj.Comment)+')\n'
|
|
||||||
|
|
||||||
toolLoad = PathUtils.getLastToolLoad(obj)
|
|
||||||
if toolLoad is None or toolLoad.ToolNumber == 0:
|
|
||||||
self.vertFeed = 100
|
|
||||||
self.horizFeed = 100
|
|
||||||
self.radius = 0.25
|
|
||||||
obj.ToolNumber = 0
|
|
||||||
obj.ToolDescription = "UNDEFINED"
|
|
||||||
else:
|
|
||||||
self.vertFeed = toolLoad.VertFeed.Value
|
|
||||||
self.horizFeed = toolLoad.HorizFeed.Value
|
|
||||||
tool = PathUtils.getTool(obj, toolLoad.ToolNumber)
|
|
||||||
self.radius = tool.Diameter/2
|
|
||||||
obj.ToolNumber = toolLoad.ToolNumber
|
|
||||||
obj.ToolDescription = toolLoad.Name
|
|
||||||
|
|
||||||
if obj.UserLabel == "":
|
|
||||||
obj.Label = obj.Name + " :" + obj.ToolDescription
|
|
||||||
else:
|
|
||||||
obj.Label = obj.UserLabel + " :" + obj.ToolDescription
|
|
||||||
|
|
||||||
output += "(remote gcode goes here)"
|
|
||||||
|
|
||||||
if obj.Active:
|
|
||||||
path = Path.Path(output)
|
|
||||||
obj.Path = path
|
|
||||||
obj.ViewObject.Visibility = True
|
|
||||||
|
|
||||||
else:
|
|
||||||
path = Path.Path("(inactive operation)")
|
|
||||||
obj.Path = path
|
|
||||||
obj.ViewObject.Visibility = False
|
|
||||||
|
|
||||||
|
|
||||||
class ViewProviderRemote:
|
|
||||||
def __init__(self, obj):
|
|
||||||
obj.Proxy = self
|
|
||||||
|
|
||||||
def __getstate__(self):
|
|
||||||
return None
|
|
||||||
|
|
||||||
def __setstate__(self, state):
|
|
||||||
return None
|
|
||||||
|
|
||||||
def getIcon(self):
|
|
||||||
return ":/icons/Path-Remote.svg"
|
|
||||||
|
|
||||||
def onChanged(self, obj, prop):
|
|
||||||
# this is executed when a property of the VIEW PROVIDER changes
|
|
||||||
pass
|
|
||||||
|
|
||||||
def updateData(self, obj, prop): # optional
|
|
||||||
# this is executed when a property of the APP OBJECT changes
|
|
||||||
pass
|
|
||||||
|
|
||||||
def setEdit(self, vobj, mode=0):
|
|
||||||
FreeCADGui.Control.closeDialog()
|
|
||||||
taskd = TaskPanel()
|
|
||||||
taskd.obj = vobj.Object
|
|
||||||
FreeCADGui.Control.showDialog(taskd)
|
|
||||||
taskd.setupUi()
|
|
||||||
return True
|
|
||||||
|
|
||||||
def unsetEdit(self, vobj, mode):
|
|
||||||
# this is executed when the user cancels or terminates edit mode
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
class _RefreshRemotePath:
|
|
||||||
def GetResources(self):
|
|
||||||
return {'Pixmap': 'Path-Refresh',
|
|
||||||
'MenuText': QtCore.QT_TRANSLATE_NOOP("Path_Remote", "Refresh Remote Path Data"),
|
|
||||||
'ToolTip': QtCore.QT_TRANSLATE_NOOP("Path_Remote", "Refresh Remote Path Data")}
|
|
||||||
|
|
||||||
def IsActive(self):
|
|
||||||
return FreeCAD.ActiveDocument is not None
|
|
||||||
|
|
||||||
def refresh(self):
|
|
||||||
obj = FreeCADGui.Selection.getSelection()[0]
|
|
||||||
values = {}
|
|
||||||
|
|
||||||
for i in obj.PropertiesList:
|
|
||||||
if obj.getGroupOfProperty(i) in ["Remote"]:
|
|
||||||
values.update({i: obj.getPropertyByName(i)})
|
|
||||||
|
|
||||||
if obj.getGroupOfProperty(i) in ["Depth"]:
|
|
||||||
print str(i)
|
|
||||||
values.update({i: obj.getPropertyByName(i)})
|
|
||||||
|
|
||||||
if obj.getGroupOfProperty(i) in ["Step"]:
|
|
||||||
values.update({i: obj.getPropertyByName(i)})
|
|
||||||
|
|
||||||
if obj.getGroupOfProperty(i) in ["Tool"]:
|
|
||||||
tool = PathUtils.getTool(obj, obj.ToolNumber)
|
|
||||||
if tool:
|
|
||||||
tradius = tool.Diameter/2
|
|
||||||
tlength = tool.LengthOffset
|
|
||||||
ttype = tool.ToolType
|
|
||||||
else:
|
|
||||||
tradius = 0.25
|
|
||||||
tlength = 1
|
|
||||||
ttype = "undefined"
|
|
||||||
|
|
||||||
values.update({"tool_diameter": tradius})
|
|
||||||
values.update({"tool_length": tlength})
|
|
||||||
values.update({"tool_type": ttype})
|
|
||||||
|
|
||||||
payload = json.dumps(values)
|
|
||||||
|
|
||||||
url = obj.URL + "/api/v1.0/path"
|
|
||||||
print url
|
|
||||||
try:
|
|
||||||
req = urllib2.Request(url)
|
|
||||||
req.add_header('Content-Type', 'application/json')
|
|
||||||
response = urllib2.urlopen(req, payload)
|
|
||||||
data = json.load(response)
|
|
||||||
except:
|
|
||||||
print "service not defined or not responding"
|
|
||||||
return
|
|
||||||
|
|
||||||
path = data['path']
|
|
||||||
output = ""
|
|
||||||
for command in path:
|
|
||||||
output += command['command']
|
|
||||||
path = Path.Path(output)
|
|
||||||
obj.Path = path
|
|
||||||
|
|
||||||
def Activated(self):
|
|
||||||
self.refresh()
|
|
||||||
|
|
||||||
|
|
||||||
class CommandPathRemote:
|
|
||||||
|
|
||||||
def GetResources(self):
|
|
||||||
return {'Pixmap': 'Path-Remote',
|
|
||||||
'MenuText': QtCore.QT_TRANSLATE_NOOP("Path_Remote", "Remote"),
|
|
||||||
'Accel': "P, R",
|
|
||||||
'ToolTip': QtCore.QT_TRANSLATE_NOOP("Path_Remote", "Request a Path from a remote cloud service")}
|
|
||||||
|
|
||||||
def IsActive(self):
|
|
||||||
if FreeCAD.ActiveDocument is not None:
|
|
||||||
for o in FreeCAD.ActiveDocument.Objects:
|
|
||||||
if o.Name[:3] == "Job":
|
|
||||||
return True
|
|
||||||
return False
|
|
||||||
|
|
||||||
def Activated(self):
|
|
||||||
ztop = 10.0
|
|
||||||
zbottom = 0.0
|
|
||||||
|
|
||||||
FreeCAD.ActiveDocument.openTransaction(translate("Path_Remote", "Create remote path operation"))
|
|
||||||
FreeCADGui.addModule("PathScripts.PathRemote")
|
|
||||||
FreeCADGui.doCommand('obj = FreeCAD.ActiveDocument.addObject("Path::FeaturePython", "Remote")')
|
|
||||||
FreeCADGui.doCommand('PathScripts.PathRemote.ObjectRemote(obj)')
|
|
||||||
FreeCADGui.doCommand('obj.Active = True')
|
|
||||||
FreeCADGui.doCommand('PathScripts.PathRemote.ViewProviderRemote(obj.ViewObject)')
|
|
||||||
FreeCADGui.doCommand('from PathScripts import PathUtils')
|
|
||||||
FreeCADGui.doCommand('obj.ClearanceHeight = ' + str(ztop + 2))
|
|
||||||
FreeCADGui.doCommand('obj.StartDepth = ' + str(ztop))
|
|
||||||
FreeCADGui.doCommand('obj.SafeHeight = ' + str(ztop + 2))
|
|
||||||
FreeCADGui.doCommand('obj.StepDown = ' + str((ztop-zbottom)/8))
|
|
||||||
|
|
||||||
FreeCADGui.doCommand('obj.FinalDepth=' + str(zbottom))
|
|
||||||
FreeCADGui.doCommand('PathScripts.PathUtils.addToJob(obj)')
|
|
||||||
|
|
||||||
FreeCAD.ActiveDocument.commitTransaction()
|
|
||||||
FreeCAD.ActiveDocument.recompute()
|
|
||||||
FreeCADGui.doCommand('obj.ViewObject.startEditing()')
|
|
||||||
|
|
||||||
|
|
||||||
class TaskPanel:
|
|
||||||
def __init__(self):
|
|
||||||
self.form = FreeCADGui.PySideUic.loadUi(":/panels/RemoteEdit.ui")
|
|
||||||
|
|
||||||
def accept(self):
|
|
||||||
self.getFields()
|
|
||||||
|
|
||||||
FreeCADGui.ActiveDocument.resetEdit()
|
|
||||||
FreeCADGui.Control.closeDialog()
|
|
||||||
FreeCAD.ActiveDocument.recompute()
|
|
||||||
FreeCADGui.Selection.removeObserver(self.s)
|
|
||||||
|
|
||||||
def reject(self):
|
|
||||||
FreeCADGui.Control.closeDialog()
|
|
||||||
FreeCAD.ActiveDocument.recompute()
|
|
||||||
FreeCADGui.Selection.removeObserver(self.s)
|
|
||||||
|
|
||||||
def getRemoteFields(self):
|
|
||||||
self.getFields()
|
|
||||||
self.obj.URL = self.form.remoteURL.text()
|
|
||||||
print "getRemote:320"
|
|
||||||
|
|
||||||
def getFields(self):
|
|
||||||
if self.obj:
|
|
||||||
if hasattr(self.obj, "StartDepth"):
|
|
||||||
self.obj.StartDepth = float(self.form.startDepth.text())
|
|
||||||
if hasattr(self.obj, "FinalDepth"):
|
|
||||||
self.obj.FinalDepth = float(self.form.finalDepth.text())
|
|
||||||
if hasattr(self.obj, "SafeHeight"):
|
|
||||||
self.obj.SafeHeight = float(self.form.safeHeight.text())
|
|
||||||
if hasattr(self.obj, "ClearanceHeight"):
|
|
||||||
self.obj.ClearanceHeight = float(self.form.clearanceHeight.text())
|
|
||||||
if hasattr(self.obj, "StepDown"):
|
|
||||||
self.obj.StepDown = float(self.form.stepDown.value())
|
|
||||||
|
|
||||||
self.obj.Proxy.execute(self.obj)
|
|
||||||
|
|
||||||
def open(self):
|
|
||||||
self.s = SelObserver()
|
|
||||||
FreeCADGui.Selection.addObserver(self.s)
|
|
||||||
|
|
||||||
def addBase(self):
|
|
||||||
# check that the selection contains exactly what we want
|
|
||||||
selection = FreeCADGui.Selection.getSelectionEx()
|
|
||||||
|
|
||||||
if not len(selection) >= 1:
|
|
||||||
FreeCAD.Console.PrintError(translate("PathProject", "Please select at least one suitable object\n"))
|
|
||||||
return
|
|
||||||
for s in selection:
|
|
||||||
if s.HasSubObjects:
|
|
||||||
for i in s.SubElementNames:
|
|
||||||
self.obj.Proxy.addbaseobject(self.obj, s.Object, i)
|
|
||||||
else:
|
|
||||||
self.obj.Proxy.addbaseobject(self.obj, s.Object)
|
|
||||||
|
|
||||||
self.setupUi() # defaults may have changed. Reload.
|
|
||||||
self.form.baseList.clear()
|
|
||||||
for i in self.obj.Base:
|
|
||||||
self.form.baseList.addItem(i[0].Name + "." + i[1])
|
|
||||||
|
|
||||||
def deleteBase(self):
|
|
||||||
dlist = self.form.baseList.selectedItems()
|
|
||||||
for d in dlist:
|
|
||||||
newlist = []
|
|
||||||
for i in self.obj.Base:
|
|
||||||
if not i[0].Name == d.text():
|
|
||||||
newlist.append(i)
|
|
||||||
self.obj.Base = newlist
|
|
||||||
self.form.baseList.takeItem(self.form.baseList.row(d))
|
|
||||||
self.obj.Proxy.execute(self.obj)
|
|
||||||
FreeCAD.ActiveDocument.recompute()
|
|
||||||
|
|
||||||
def itemActivated(self):
|
|
||||||
FreeCADGui.Selection.clearSelection()
|
|
||||||
slist = self.form.baseList.selectedItems()
|
|
||||||
for i in slist:
|
|
||||||
o = FreeCAD.ActiveDocument.getObject(i.text())
|
|
||||||
FreeCADGui.Selection.addSelection(o)
|
|
||||||
FreeCADGui.updateGui()
|
|
||||||
|
|
||||||
def reorderBase(self):
|
|
||||||
newlist = []
|
|
||||||
for i in range(self.form.baseList.count()):
|
|
||||||
s = self.form.baseList.item(i).text()
|
|
||||||
obj = FreeCAD.ActiveDocument.getObject(s)
|
|
||||||
newlist.append(obj)
|
|
||||||
self.obj.Base = newlist
|
|
||||||
self.obj.Proxy.execute(self.obj)
|
|
||||||
FreeCAD.ActiveDocument.recompute()
|
|
||||||
|
|
||||||
def getStandardButtons(self):
|
|
||||||
return int(QtGui.QDialogButtonBox.Ok)
|
|
||||||
|
|
||||||
def changeURL(self):
|
|
||||||
from urlparse import urlparse
|
|
||||||
t = self.form.remoteURL.text()
|
|
||||||
if t == '' and self.obj.URL != '': # if the url was deleted, cleanup.
|
|
||||||
self.obj.URL = ''
|
|
||||||
|
|
||||||
if urlparse(t).scheme != '' and t != self.obj.URL: # validate new url.
|
|
||||||
self.obj.URL = t
|
|
||||||
# next make sure the property fields reflect the current attached service
|
|
||||||
for p in self.obj.proplist:
|
|
||||||
print p
|
|
||||||
|
|
||||||
def setupUi(self):
|
|
||||||
self.form.startDepth.setText(str(self.obj.StartDepth))
|
|
||||||
self.form.finalDepth.setText(str(self.obj.FinalDepth))
|
|
||||||
self.form.safeHeight.setText(str(self.obj.SafeHeight))
|
|
||||||
self.form.clearanceHeight.setText(str(self.obj.ClearanceHeight))
|
|
||||||
self.form.remoteURL.setText(str(self.obj.URL))
|
|
||||||
|
|
||||||
for i in self.obj.Base:
|
|
||||||
self.form.baseList.addItem(i[0].Name)
|
|
||||||
|
|
||||||
# Connect Signals and Slots
|
|
||||||
self.form.startDepth.editingFinished.connect(self.getFields)
|
|
||||||
self.form.finalDepth.editingFinished.connect(self.getFields)
|
|
||||||
self.form.safeHeight.editingFinished.connect(self.getFields)
|
|
||||||
self.form.clearanceHeight.editingFinished.connect(self.getFields)
|
|
||||||
|
|
||||||
self.form.addBase.clicked.connect(self.addBase)
|
|
||||||
self.form.baseList.itemSelectionChanged.connect(self.itemActivated)
|
|
||||||
self.form.deleteBase.clicked.connect(self.deleteBase)
|
|
||||||
self.form.reorderBase.clicked.connect(self.reorderBase)
|
|
||||||
|
|
||||||
self.form.remoteURL.editingFinished.connect(self.changeURL)
|
|
||||||
|
|
||||||
|
|
||||||
class SelObserver:
|
|
||||||
def __init__(self):
|
|
||||||
import PathScripts.PathSelection as PST
|
|
||||||
|
|
||||||
def __del__(self):
|
|
||||||
import PathScripts.PathSelection as PST
|
|
||||||
PST.clear()
|
|
||||||
|
|
||||||
def addSelection(self, doc, obj, sub, pnt):
|
|
||||||
FreeCADGui.doCommand('Gui.Selection.addSelection(FreeCAD.ActiveDocument.' + obj + ')')
|
|
||||||
FreeCADGui.updateGui()
|
|
||||||
|
|
||||||
if FreeCAD.GuiUp:
|
|
||||||
# register the FreeCAD command
|
|
||||||
FreeCADGui.addCommand('Path_Remote', CommandPathRemote())
|
|
||||||
FreeCADGui.addCommand('Refresh_Path', _RefreshRemotePath())
|
|
||||||
|
|
||||||
FreeCAD.Console.PrintLog("Loading PathRemote... done\n")
|
|
|
@ -25,44 +25,44 @@
|
||||||
|
|
||||||
import FreeCAD
|
import FreeCAD
|
||||||
import FreeCADGui
|
import FreeCADGui
|
||||||
from FreeCAD import Vector
|
#from FreeCAD import Vector
|
||||||
|
|
||||||
|
|
||||||
def equals(p1, p2):
|
# def equals(p1, p2):
|
||||||
'''returns True if vertexes have same coordinates within precision amount of digits '''
|
# '''returns True if vertexes have same coordinates within precision amount of digits '''
|
||||||
precision = 12
|
# precision = 12
|
||||||
p = precision
|
# p = precision
|
||||||
u = Vector(p1.X, p1.Y, p1.Z)
|
# u = Vector(p1.X, p1.Y, p1.Z)
|
||||||
v = Vector(p2.X, p2.Y, p2.Z)
|
# v = Vector(p2.X, p2.Y, p2.Z)
|
||||||
vector = (u.sub(v))
|
# vector = (u.sub(v))
|
||||||
isNull = (round(vector.x, p) == 0 and round(vector.y, p) == 0 and round(vector.z, p) == 0)
|
# isNull = (round(vector.x, p) == 0 and round(vector.y, p) == 0 and round(vector.z, p) == 0)
|
||||||
return isNull
|
# return isNull
|
||||||
|
|
||||||
|
|
||||||
def segments(poly):
|
# def segments(poly):
|
||||||
''' A sequence of (x,y) numeric coordinates pairs '''
|
# ''' A sequence of (x,y) numeric coordinates pairs '''
|
||||||
return zip(poly, poly[1:] + [poly[0]])
|
# return zip(poly, poly[1:] + [poly[0]])
|
||||||
|
|
||||||
|
|
||||||
def check_clockwise(poly):
|
# def check_clockwise(poly):
|
||||||
'''
|
# '''
|
||||||
check_clockwise(poly) a function for returning a boolean if the selected wire is clockwise or counter clockwise
|
# check_clockwise(poly) a function for returning a boolean if the selected wire is clockwise or counter clockwise
|
||||||
based on point order. poly = [(x1,y1),(x2,y2),(x3,y3)]
|
# based on point order. poly = [(x1,y1),(x2,y2),(x3,y3)]
|
||||||
'''
|
# '''
|
||||||
clockwise = False
|
# clockwise = False
|
||||||
if (sum(x0*y1 - x1*y0 for ((x0, y0), (x1, y1)) in segments(poly))) < 0:
|
# if (sum(x0*y1 - x1*y0 for ((x0, y0), (x1, y1)) in segments(poly))) < 0:
|
||||||
clockwise = not clockwise
|
# clockwise = not clockwise
|
||||||
return clockwise
|
# return clockwise
|
||||||
|
|
||||||
|
|
||||||
class FGate:
|
# class FGate:
|
||||||
def allow(self, doc, obj, sub):
|
# def allow(self, doc, obj, sub):
|
||||||
return (sub[0:4] == 'Face')
|
# return (sub[0:4] == 'Face')
|
||||||
|
|
||||||
|
|
||||||
class VGate:
|
# class VGate:
|
||||||
def allow(self, doc, obj, sub):
|
# def allow(self, doc, obj, sub):
|
||||||
return (sub[0:6] == 'Vertex')
|
# return (sub[0:6] == 'Vertex')
|
||||||
|
|
||||||
|
|
||||||
class EGate:
|
class EGate:
|
||||||
|
@ -182,14 +182,14 @@ def contourselect():
|
||||||
FreeCADGui.Selection.addSelectionGate(CONTOURGate())
|
FreeCADGui.Selection.addSelectionGate(CONTOURGate())
|
||||||
FreeCAD.Console.PrintWarning("Contour Select Mode\n")
|
FreeCAD.Console.PrintWarning("Contour Select Mode\n")
|
||||||
|
|
||||||
def fselect():
|
# def fselect():
|
||||||
FreeCADGui.Selection.addSelectionGate(FGate())
|
# FreeCADGui.Selection.addSelectionGate(FGate())
|
||||||
FreeCAD.Console.PrintWarning("Face Select Mode\n")
|
# FreeCAD.Console.PrintWarning("Face Select Mode\n")
|
||||||
|
|
||||||
|
|
||||||
def vselect():
|
# def vselect():
|
||||||
FreeCADGui.Selection.addSelectionGate(VGate())
|
# FreeCADGui.Selection.addSelectionGate(VGate())
|
||||||
FreeCAD.Console.PrintWarning("Vertex Select Mode\n")
|
# FreeCAD.Console.PrintWarning("Vertex Select Mode\n")
|
||||||
|
|
||||||
|
|
||||||
def eselect():
|
def eselect():
|
||||||
|
|
|
@ -1,401 +0,0 @@
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
|
|
||||||
# ***************************************************************************
|
|
||||||
# * *
|
|
||||||
# * Copyright (c) 2016 sliptonic <shopinthewoods@gmail.com> *
|
|
||||||
# * *
|
|
||||||
# * This program is free software; you can redistribute it and/or modify *
|
|
||||||
# * it under the terms of the GNU Lesser General Public License (LGPL) *
|
|
||||||
# * as published by the Free Software Foundation; either version 2 of *
|
|
||||||
# * the License, or (at your option) any later version. *
|
|
||||||
# * for detail see the LICENCE text file. *
|
|
||||||
# * *
|
|
||||||
# * This program 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 program; if not, write to the Free Software *
|
|
||||||
# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
|
|
||||||
# * USA *
|
|
||||||
# * *
|
|
||||||
# ***************************************************************************
|
|
||||||
|
|
||||||
import FreeCAD
|
|
||||||
import Path
|
|
||||||
from PathScripts import PathUtils
|
|
||||||
|
|
||||||
if FreeCAD.GuiUp:
|
|
||||||
import FreeCADGui
|
|
||||||
from PySide import QtCore, QtGui
|
|
||||||
|
|
||||||
__title__ = "Path Surface Operation"
|
|
||||||
__author__ = "sliptonic (Brad Collette)"
|
|
||||||
__url__ = "http://www.freecadweb.org"
|
|
||||||
|
|
||||||
"""Path surface object and FreeCAD command"""
|
|
||||||
|
|
||||||
# Qt tanslation handling
|
|
||||||
try:
|
|
||||||
_encoding = QtGui.QApplication.UnicodeUTF8
|
|
||||||
|
|
||||||
def translate(context, text, disambig=None):
|
|
||||||
return QtGui.QApplication.translate(context, text, disambig, _encoding)
|
|
||||||
except AttributeError:
|
|
||||||
def translate(context, text, disambig=None):
|
|
||||||
return QtGui.QApplication.translate(context, text, disambig)
|
|
||||||
|
|
||||||
|
|
||||||
class ObjectStrategy:
|
|
||||||
|
|
||||||
def __init__(self, obj):
|
|
||||||
obj.addProperty("App::PropertyLinkSubList", "Base", "Path", "The base geometry of this toolpath")
|
|
||||||
obj.addProperty("App::PropertyBool", "Active", "Path", "Make False, to prevent operation from generating code")
|
|
||||||
obj.addProperty("App::PropertyString", "Comment", "Path", "An optional comment for this profile")
|
|
||||||
obj.addProperty("App::PropertyString", "UserLabel", "Path", "User Assigned Label")
|
|
||||||
|
|
||||||
obj.addProperty("App::PropertyEnumeration", "Algorithm", "Algorithm", "The library to use to generate the path")
|
|
||||||
obj.Algorithm = ['OCL Dropcutter', 'OCL Waterline']
|
|
||||||
|
|
||||||
# Tool Properties
|
|
||||||
obj.addProperty("App::PropertyIntegerConstraint", "ToolNumber", "Tool", "The tool number in use")
|
|
||||||
obj.ToolNumber = (0, 0, 1000, 0)
|
|
||||||
obj.setEditorMode('ToolNumber', 1) # make this read only
|
|
||||||
obj.addProperty("App::PropertyString", "ToolDescription", "Tool", "The description of the tool ")
|
|
||||||
obj.setEditorMode('ToolDescription', 1) # make this read onlyt
|
|
||||||
|
|
||||||
# Depth Properties
|
|
||||||
obj.addProperty("App::PropertyDistance", "ClearanceHeight", "Depth", "The height needed to clear clamps and obstructions")
|
|
||||||
obj.addProperty("App::PropertyDistance", "SafeHeight", "Depth", "Rapid Safety Height between locations.")
|
|
||||||
obj.addProperty("App::PropertyFloatConstraint", "StepDown", "Depth", "Incremental Step Down of Tool")
|
|
||||||
obj.StepDown = (0.0, 0.01, 100.0, 0.5)
|
|
||||||
obj.addProperty("App::PropertyDistance", "StartDepth", "Depth", "Starting Depth of Tool- first cut depth in Z")
|
|
||||||
obj.addProperty("App::PropertyDistance", "FinalDepth", "Depth", "Final Depth of Tool- lowest value in Z")
|
|
||||||
obj.addProperty("App::PropertyDistance", "FinishDepth", "Depth", "Maximum material removed on final pass.")
|
|
||||||
|
|
||||||
obj.Proxy = self
|
|
||||||
|
|
||||||
def addbase(self, obj, ss, sub=""):
|
|
||||||
baselist = obj.Base
|
|
||||||
if len(baselist) == 0: # When adding the first base object, guess at heights
|
|
||||||
try:
|
|
||||||
bb = ss.Shape.BoundBox # parent boundbox
|
|
||||||
subobj = ss.Shape.getElement(sub)
|
|
||||||
fbb = subobj.BoundBox # feature boundbox
|
|
||||||
obj.StartDepth = bb.ZMax
|
|
||||||
obj.ClearanceHeight = bb.ZMax + 5.0
|
|
||||||
obj.SafeHeight = bb.ZMax + 3.0
|
|
||||||
|
|
||||||
if fbb.ZMax < bb.ZMax:
|
|
||||||
obj.FinalDepth = fbb.ZMax
|
|
||||||
else:
|
|
||||||
obj.FinalDepth = bb.ZMin
|
|
||||||
except:
|
|
||||||
obj.StartDepth = 5.0
|
|
||||||
obj.ClearanceHeight = 10.0
|
|
||||||
obj.SafeHeight = 8.0
|
|
||||||
|
|
||||||
item = (ss, sub)
|
|
||||||
if item in baselist:
|
|
||||||
FreeCAD.Console.PrintWarning(
|
|
||||||
"this object already in the list" + "\n")
|
|
||||||
else:
|
|
||||||
baselist.append(item)
|
|
||||||
obj.Base = baselist
|
|
||||||
self.execute(obj)
|
|
||||||
|
|
||||||
def __getstate__(self):
|
|
||||||
return None
|
|
||||||
|
|
||||||
def __setstate__(self, state):
|
|
||||||
return None
|
|
||||||
|
|
||||||
def onChanged(self, obj, prop):
|
|
||||||
return None
|
|
||||||
|
|
||||||
def execute(self, obj):
|
|
||||||
output = ""
|
|
||||||
|
|
||||||
toolLoad = PathUtils.getLastToolLoad(obj)
|
|
||||||
if toolLoad is None or toolLoad.ToolNumber == 0:
|
|
||||||
self.vertFeed = 100
|
|
||||||
self.horizFeed = 100
|
|
||||||
self.vertRapid = 100
|
|
||||||
self.horizRapid = 100
|
|
||||||
self.radius = 0.25
|
|
||||||
obj.ToolNumber = 0
|
|
||||||
obj.ToolDescription = "UNDEFINED"
|
|
||||||
else:
|
|
||||||
self.vertFeed = toolLoad.VertFeed.Value
|
|
||||||
self.horizFeed = toolLoad.HorizFeed.Value
|
|
||||||
self.vertRapid = toolLoad.VertRapid.Value
|
|
||||||
self.horizRapid = toolLoad.HorizRapid.Value
|
|
||||||
tool = PathUtils.getTool(obj, toolLoad.ToolNumber)
|
|
||||||
if tool.Diameter == 0:
|
|
||||||
self.radius = 0.25
|
|
||||||
else:
|
|
||||||
self.radius = tool.Diameter/2
|
|
||||||
obj.ToolNumber = toolLoad.ToolNumber
|
|
||||||
obj.ToolDescription = toolLoad.Name
|
|
||||||
|
|
||||||
|
|
||||||
output += "(" + obj.Label + ")"
|
|
||||||
output += "(Compensated Tool Path. Diameter: " + str(self.radius * 2) + ")"
|
|
||||||
|
|
||||||
if obj.Active:
|
|
||||||
path = Path.Path(output)
|
|
||||||
obj.Path = path
|
|
||||||
obj.ViewObject.Visibility = True
|
|
||||||
|
|
||||||
else:
|
|
||||||
path = Path.Path("(inactive operation)")
|
|
||||||
obj.Path = path
|
|
||||||
obj.ViewObject.Visibility = False
|
|
||||||
|
|
||||||
class ViewProviderStrategy:
|
|
||||||
|
|
||||||
def __init__(self, obj): # mandatory
|
|
||||||
# obj.addProperty("App::PropertyFloat","SomePropertyName","PropertyGroup","Description of this property")
|
|
||||||
obj.Proxy = self
|
|
||||||
|
|
||||||
def __getstate__(self): # mandatory
|
|
||||||
return None
|
|
||||||
|
|
||||||
def __setstate__(self, state): # mandatory
|
|
||||||
return None
|
|
||||||
|
|
||||||
def getIcon(self): # optional
|
|
||||||
return ":/icons/Path-Surfacing.svg"
|
|
||||||
|
|
||||||
def onChanged(self, obj, prop): # optional
|
|
||||||
# this is executed when a property of the VIEW PROVIDER changes
|
|
||||||
pass
|
|
||||||
|
|
||||||
def updateData(self, obj, prop): # optional
|
|
||||||
# this is executed when a property of the APP OBJECT changes
|
|
||||||
pass
|
|
||||||
|
|
||||||
def setEdit(self, vobj, mode=0):
|
|
||||||
FreeCADGui.Control.closeDialog()
|
|
||||||
taskd = TaskPanel()
|
|
||||||
taskd.obj = vobj.Object
|
|
||||||
FreeCADGui.Control.showDialog(taskd)
|
|
||||||
taskd.setupUi()
|
|
||||||
return True
|
|
||||||
|
|
||||||
def unsetEdit(self, vobj, mode): # optional
|
|
||||||
# this is executed when the user cancels or terminates edit mode
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
class CommandPathStrategy:
|
|
||||||
|
|
||||||
def GetResources(self):
|
|
||||||
return {'Pixmap': 'Path-3DSurface',
|
|
||||||
'MenuText': QtCore.QT_TRANSLATE_NOOP("Path_Strategy", "Strategy"),
|
|
||||||
'Accel': "P, D",
|
|
||||||
'ToolTip': QtCore.QT_TRANSLATE_NOOP("Path_Strategy", "Creates a Path Strategy object")}
|
|
||||||
|
|
||||||
def IsActive(self):
|
|
||||||
if FreeCAD.ActiveDocument is not None:
|
|
||||||
for o in FreeCAD.ActiveDocument.Objects:
|
|
||||||
if o.Name[:3] == "Job":
|
|
||||||
return True
|
|
||||||
return False
|
|
||||||
|
|
||||||
def Activated(self):
|
|
||||||
|
|
||||||
ztop = 10
|
|
||||||
zbottom = 0
|
|
||||||
|
|
||||||
FreeCAD.ActiveDocument.openTransaction(translate("Path_Strategy", "Create Strategy"))
|
|
||||||
FreeCADGui.addModule("PathScripts.PathStrategy")
|
|
||||||
FreeCADGui.doCommand('obj = FreeCAD.ActiveDocument.addObject("Path::FeaturePython","Strategy")')
|
|
||||||
FreeCADGui.doCommand('PathScripts.PathStrategy.ObjectStrategy(obj)')
|
|
||||||
FreeCADGui.doCommand('obj.Active = True')
|
|
||||||
FreeCADGui.doCommand('PathScripts.PathStrategy.ViewProviderStrategy(obj.ViewObject)')
|
|
||||||
FreeCADGui.doCommand('from PathScripts import PathUtils')
|
|
||||||
FreeCADGui.doCommand('obj.ClearanceHeight = ' + str(ztop + 2))
|
|
||||||
FreeCADGui.doCommand('obj.StartDepth = ' + str(ztop))
|
|
||||||
FreeCADGui.doCommand('obj.SafeHeight = ' + str(ztop + 2))
|
|
||||||
FreeCADGui.doCommand('obj.StepDown = ' + str((ztop - zbottom) / 8))
|
|
||||||
FreeCADGui.doCommand('obj.FinalDepth=' + str(zbottom))
|
|
||||||
FreeCADGui.doCommand('PathScripts.PathUtils.addToJob(obj)')
|
|
||||||
FreeCAD.ActiveDocument.commitTransaction()
|
|
||||||
|
|
||||||
FreeCAD.ActiveDocument.recompute()
|
|
||||||
FreeCADGui.doCommand('obj.ViewObject.startEditing()')
|
|
||||||
|
|
||||||
|
|
||||||
class TaskPanel:
|
|
||||||
|
|
||||||
def __init__(self):
|
|
||||||
self.form = FreeCADGui.PySideUic.loadUi(FreeCAD.getHomePath() + "Mod/Path/StrategyEdit.ui")
|
|
||||||
#self.form = FreeCADGui.PySideUic.loadUi(":/panels/SurfaceEdit.ui")
|
|
||||||
|
|
||||||
def accept(self):
|
|
||||||
self.getFields()
|
|
||||||
|
|
||||||
FreeCADGui.ActiveDocument.resetEdit()
|
|
||||||
FreeCADGui.Control.closeDialog()
|
|
||||||
FreeCAD.ActiveDocument.recompute()
|
|
||||||
FreeCADGui.Selection.removeObserver(self.s)
|
|
||||||
|
|
||||||
def reject(self):
|
|
||||||
FreeCADGui.Control.closeDialog()
|
|
||||||
FreeCAD.ActiveDocument.recompute()
|
|
||||||
FreeCADGui.Selection.removeObserver(self.s)
|
|
||||||
|
|
||||||
def getFields(self):
|
|
||||||
if self.obj:
|
|
||||||
if hasattr(self.obj, "StartDepth"):
|
|
||||||
self.obj.StartDepth = self.form.startDepth.text()
|
|
||||||
if hasattr(self.obj, "FinalDepth"):
|
|
||||||
self.obj.FinalDepth = self.form.finalDepth.text()
|
|
||||||
if hasattr(self.obj, "FinishDepth"):
|
|
||||||
self.obj.FinishDepth = self.form.finishDepth.text()
|
|
||||||
if hasattr(self.obj, "StepDown"):
|
|
||||||
self.obj.StepDown = self.form.stepDown.value()
|
|
||||||
if hasattr(self.obj, "SafeHeight"):
|
|
||||||
self.obj.SafeHeight = self.form.safeHeight.text()
|
|
||||||
if hasattr(self.obj, "ClearanceHeight"):
|
|
||||||
self.obj.ClearanceHeight = self.form.clearanceHeight.text()
|
|
||||||
|
|
||||||
self.obj.Proxy.execute(self.obj)
|
|
||||||
|
|
||||||
def setFields(self):
|
|
||||||
self.form.startDepth.setText(str(self.obj.StartDepth.Value))
|
|
||||||
self.form.finalDepth.setText(str(self.obj.FinalDepth.Value))
|
|
||||||
self.form.finishDepth.setText(str(self.obj.FinishDepth.Value))
|
|
||||||
self.form.stepDown.setValue(self.obj.StepDown)
|
|
||||||
|
|
||||||
self.form.safeHeight.setText(str(self.obj.SafeHeight.Value))
|
|
||||||
self.form.clearanceHeight.setText(str(self.obj.ClearanceHeight.Value))
|
|
||||||
|
|
||||||
for i in self.obj.Base:
|
|
||||||
self.form.baseList.addItem(i[0].Name)
|
|
||||||
|
|
||||||
def open(self):
|
|
||||||
self.s = SelObserver()
|
|
||||||
# install the function mode resident
|
|
||||||
FreeCADGui.Selection.addObserver(self.s)
|
|
||||||
|
|
||||||
def addBase(self):
|
|
||||||
# check that the selection contains exactly what we want
|
|
||||||
selection = FreeCADGui.Selection.getSelectionEx()
|
|
||||||
if len(selection) != 1:
|
|
||||||
FreeCAD.Console.PrintError(translate(
|
|
||||||
"PathSurface", "Please select a single solid object from the project tree\n"))
|
|
||||||
return
|
|
||||||
|
|
||||||
if not len(selection[0].SubObjects) == 0:
|
|
||||||
FreeCAD.Console.PrintError(translate(
|
|
||||||
"PathSurface", "Please select a single solid object from the project tree\n"))
|
|
||||||
return
|
|
||||||
|
|
||||||
sel = selection[0].Object
|
|
||||||
# get type of object
|
|
||||||
# if sel.TypeId.startswith('Mesh'):
|
|
||||||
# # it is a mesh already
|
|
||||||
# print 'was already mesh'
|
|
||||||
|
|
||||||
# elif sel.TypeId.startswith('Part') and \
|
|
||||||
# (sel.Shape.BoundBox.XLength > 0) and \
|
|
||||||
# (sel.Shape.BoundBox.YLength > 0) and \
|
|
||||||
# (sel.Shape.BoundBox.ZLength > 0):
|
|
||||||
# print 'this is a solid Part object'
|
|
||||||
|
|
||||||
# else:
|
|
||||||
# FreeCAD.Console.PrintError(
|
|
||||||
# translate("PathSurface", "Cannot work with this object\n"))
|
|
||||||
# return
|
|
||||||
|
|
||||||
self.obj.Proxy.addbase(self.obj, sel)
|
|
||||||
|
|
||||||
self.setFields() # defaults may have changed. Reload.
|
|
||||||
self.form.baseList.clear()
|
|
||||||
for i in self.obj.Base:
|
|
||||||
self.form.baseList.addItem(i[0].Name)
|
|
||||||
|
|
||||||
def deleteBase(self):
|
|
||||||
dlist = self.form.baseList.selectedItems()
|
|
||||||
for d in dlist:
|
|
||||||
newlist = []
|
|
||||||
for i in self.obj.Base:
|
|
||||||
if not i[0].Name == d.text():
|
|
||||||
newlist.append(i)
|
|
||||||
self.obj.Base = newlist
|
|
||||||
self.form.baseList.takeItem(self.form.baseList.row(d))
|
|
||||||
self.obj.Proxy.execute(self.obj)
|
|
||||||
FreeCAD.ActiveDocument.recompute()
|
|
||||||
|
|
||||||
def itemActivated(self):
|
|
||||||
FreeCADGui.Selection.clearSelection()
|
|
||||||
slist = self.form.baseList.selectedItems()
|
|
||||||
for i in slist:
|
|
||||||
o = FreeCAD.ActiveDocument.getObject(i.text())
|
|
||||||
FreeCADGui.Selection.addSelection(o)
|
|
||||||
FreeCADGui.updateGui()
|
|
||||||
|
|
||||||
def reorderBase(self):
|
|
||||||
newlist = []
|
|
||||||
for i in range(self.form.baseList.count()):
|
|
||||||
s = self.form.baseList.item(i).text()
|
|
||||||
obj = FreeCAD.ActiveDocument.getObject(s)
|
|
||||||
newlist.append(obj)
|
|
||||||
self.obj.Base = newlist
|
|
||||||
self.obj.Proxy.execute(self.obj)
|
|
||||||
FreeCAD.ActiveDocument.recompute()
|
|
||||||
|
|
||||||
def getStandardButtons(self):
|
|
||||||
return int(QtGui.QDialogButtonBox.Ok)
|
|
||||||
|
|
||||||
def setupUi(self):
|
|
||||||
|
|
||||||
# Connect Signals and Slots
|
|
||||||
|
|
||||||
#Base Geometry
|
|
||||||
self.form.addBase.clicked.connect(self.addBase)
|
|
||||||
self.form.deleteBase.clicked.connect(self.deleteBase)
|
|
||||||
self.form.reorderBase.clicked.connect(self.reorderBase)
|
|
||||||
self.form.baseList.itemSelectionChanged.connect(self.itemActivated)
|
|
||||||
|
|
||||||
# Depths
|
|
||||||
self.form.startDepth.editingFinished.connect(self.getFields)
|
|
||||||
self.form.finalDepth.editingFinished.connect(self.getFields)
|
|
||||||
self.form.finishDepth.editingFinished.connect(self.getFields)
|
|
||||||
self.form.stepDown.editingFinished.connect(self.getFields)
|
|
||||||
|
|
||||||
# Heights
|
|
||||||
self.form.safeHeight.editingFinished.connect(self.getFields)
|
|
||||||
self.form.clearanceHeight.editingFinished.connect(self.getFields)
|
|
||||||
|
|
||||||
sel = FreeCADGui.Selection.getSelectionEx()
|
|
||||||
self.setFields()
|
|
||||||
|
|
||||||
if len(sel) != 0:
|
|
||||||
self.addBase()
|
|
||||||
|
|
||||||
|
|
||||||
class SelObserver:
|
|
||||||
|
|
||||||
def __init__(self):
|
|
||||||
import PathScripts.PathSelection as PST
|
|
||||||
PST.surfaceselect()
|
|
||||||
|
|
||||||
def __del__(self):
|
|
||||||
import PathScripts.PathSelection as PST
|
|
||||||
PST.clear()
|
|
||||||
|
|
||||||
def addSelection(self, doc, obj, sub, pnt): # Selection object
|
|
||||||
FreeCADGui.doCommand(
|
|
||||||
'Gui.Selection.addSelection(FreeCAD.ActiveDocument.' + obj + ')')
|
|
||||||
FreeCADGui.updateGui()
|
|
||||||
|
|
||||||
|
|
||||||
if FreeCAD.GuiUp:
|
|
||||||
# register the FreeCAD command
|
|
||||||
FreeCADGui.addCommand('Path_Strategy', CommandPathStrategy())
|
|
||||||
|
|
||||||
FreeCAD.Console.PrintLog("Loading PathStrategy... done\n")
|
|
|
@ -139,7 +139,7 @@ class ToolLibraryManager():
|
||||||
'''
|
'''
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.ToolLibrary = []
|
# self.ToolLibrary = []
|
||||||
self.prefs = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Path")
|
self.prefs = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Path")
|
||||||
return
|
return
|
||||||
|
|
||||||
|
@ -311,20 +311,20 @@ class ToolLibraryManager():
|
||||||
self.saveMainLibrary(tt)
|
self.saveMainLibrary(tt)
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def createToolController(self, job, tool):
|
# def createToolController(self, job, tool):
|
||||||
pass
|
# pass
|
||||||
|
|
||||||
def exportListHeeks(self, tooltable):
|
# def exportListHeeks(self, tooltable):
|
||||||
'''exports one or more Lists as a HeeksCNC tooltable'''
|
# '''exports one or more Lists as a HeeksCNC tooltable'''
|
||||||
pass
|
# pass
|
||||||
|
|
||||||
def exportListLinuxCNC(self, tooltable):
|
# def exportListLinuxCNC(self, tooltable):
|
||||||
'''exports one or more Lists as a LinuxCNC tooltable'''
|
# '''exports one or more Lists as a LinuxCNC tooltable'''
|
||||||
pass
|
# pass
|
||||||
|
|
||||||
def exportListXML(self, tooltable):
|
# def exportListXML(self, tooltable):
|
||||||
'''exports one or more Lists as an XML file'''
|
# '''exports one or more Lists as an XML file'''
|
||||||
pass
|
# pass
|
||||||
|
|
||||||
class EditorPanel():
|
class EditorPanel():
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
|
|
|
@ -26,15 +26,13 @@ import FreeCAD
|
||||||
import FreeCADGui
|
import FreeCADGui
|
||||||
import Part
|
import Part
|
||||||
import math
|
import math
|
||||||
import Draft
|
# import Path
|
||||||
import Path
|
|
||||||
import TechDraw
|
|
||||||
from DraftGeomUtils import geomType
|
from DraftGeomUtils import geomType
|
||||||
from DraftGeomUtils import findWires
|
# from DraftGeomUtils import findWires
|
||||||
import DraftVecUtils
|
# import DraftVecUtils
|
||||||
import PathScripts
|
import PathScripts
|
||||||
from PathScripts import PathJob
|
from PathScripts import PathJob
|
||||||
import itertools
|
# import itertools
|
||||||
|
|
||||||
def cleanedges(splines, precision):
|
def cleanedges(splines, precision):
|
||||||
'''cleanedges([splines],precision). Convert BSpline curves, Beziers, to arcs that can be used for cnc paths.
|
'''cleanedges([splines],precision). Convert BSpline curves, Beziers, to arcs that can be used for cnc paths.
|
||||||
|
@ -88,89 +86,89 @@ def curvetowire(obj, steps):
|
||||||
def fmt(val): return format(val, '.4f')
|
def fmt(val): return format(val, '.4f')
|
||||||
|
|
||||||
|
|
||||||
def getProjected(shape,direction):
|
# def getProjected(shape,direction):
|
||||||
"returns projected edges from a shape and a direction"
|
# "returns projected edges from a shape and a direction"
|
||||||
import Part,Drawing
|
# import Part,Drawing
|
||||||
edges = []
|
# edges = []
|
||||||
groups = Drawing.projectEx(shape,direction)
|
# groups = Drawing.projectEx(shape,direction)
|
||||||
for g in groups[0:5]:
|
# for g in groups[0:5]:
|
||||||
if g:
|
# if g:
|
||||||
edges.append(g)
|
# edges.append(g)
|
||||||
# if hasattr(obj,"Tessellation") and obj.Tessellation:
|
# # if hasattr(obj,"Tessellation") and obj.Tessellation:
|
||||||
# return DraftGeomUtils.cleanProjection(Part.makeCompound(edges),obj.Tessellation,obj.SegmentLength)
|
# # return DraftGeomUtils.cleanProjection(Part.makeCompound(edges),obj.Tessellation,obj.SegmentLength)
|
||||||
# else:
|
# # else:
|
||||||
return Part.makeCompound(edges)
|
# return Part.makeCompound(edges)
|
||||||
|
|
||||||
|
|
||||||
def silhouette(obj):
|
# def silhouette(obj):
|
||||||
from FreeCAD import Vector
|
# from FreeCAD import Vector
|
||||||
s = getProjected(obj.Shape, Vector(0,0,1))
|
# s = getProjected(obj.Shape, Vector(0,0,1))
|
||||||
print s
|
# print s
|
||||||
w = TechDraw.findOuterWire(s.Edges)
|
# w = TechDraw.findOuterWire(s.Edges)
|
||||||
return w
|
# return w
|
||||||
|
|
||||||
def isSameEdge(e1, e2):
|
# def isSameEdge(e1, e2):
|
||||||
"""isSameEdge(e1,e2): return True if the 2 edges are both lines or arcs/circles and have the same
|
# """isSameEdge(e1,e2): return True if the 2 edges are both lines or arcs/circles and have the same
|
||||||
points - inspired by Yorik's function isSameLine"""
|
# points - inspired by Yorik's function isSameLine"""
|
||||||
if not (isinstance(e1.Curve, Part.LineSegment) or isinstance(e1.Curve, Part.Circle)):
|
# if not (isinstance(e1.Curve, Part.Line) or isinstance(e1.Curve, Part.Circle)):
|
||||||
return False
|
# return False
|
||||||
if not (isinstance(e2.Curve, Part.LineSegment) or isinstance(e2.Curve, Part.Circle)):
|
# if not (isinstance(e2.Curve, Part.Line) or isinstance(e2.Curve, Part.Circle)):
|
||||||
return False
|
# return False
|
||||||
if type(e1.Curve) != type(e2.Curve):
|
# if type(e1.Curve) != type(e2.Curve):
|
||||||
return False
|
# return False
|
||||||
if isinstance(e1.Curve, Part.LineSegment):
|
# if isinstance(e1.Curve, Part.Line):
|
||||||
if (DraftVecUtils.equals(e1.Vertexes[0].Point, e2.Vertexes[0].Point)) and \
|
# if (DraftVecUtils.equals(e1.Vertexes[0].Point, e2.Vertexes[0].Point)) and \
|
||||||
(DraftVecUtils.equals(e1.Vertexes[-1].Point, e2.Vertexes[-1].Point)):
|
# (DraftVecUtils.equals(e1.Vertexes[-1].Point, e2.Vertexes[-1].Point)):
|
||||||
return True
|
# return True
|
||||||
elif (DraftVecUtils.equals(e1.Vertexes[-1].Point, e2.Vertexes[0].Point)) and \
|
# elif (DraftVecUtils.equals(e1.Vertexes[-1].Point, e2.Vertexes[0].Point)) and \
|
||||||
(DraftVecUtils.equals(e1.Vertexes[0].Point, e2.Vertexes[-1].Point)):
|
# (DraftVecUtils.equals(e1.Vertexes[0].Point, e2.Vertexes[-1].Point)):
|
||||||
return True
|
# return True
|
||||||
if isinstance(e1.Curve, Part.Circle):
|
# if isinstance(e1.Curve, Part.Circle):
|
||||||
center = False
|
# center = False
|
||||||
radius = False
|
# radius = False
|
||||||
endpts = False
|
# endpts = False
|
||||||
if e1.Curve.Center == e2.Curve.Center:
|
# if e1.Curve.Center == e2.Curve.Center:
|
||||||
center = True
|
# center = True
|
||||||
if e1.Curve.Radius == e2.Curve.Radius:
|
# if e1.Curve.Radius == e2.Curve.Radius:
|
||||||
radius = True
|
# radius = True
|
||||||
if (DraftVecUtils.equals(e1.Vertexes[0].Point, e2.Vertexes[0].Point)) and \
|
# if (DraftVecUtils.equals(e1.Vertexes[0].Point, e2.Vertexes[0].Point)) and \
|
||||||
(DraftVecUtils.equals(e1.Vertexes[-1].Point, e2.Vertexes[-1].Point)):
|
# (DraftVecUtils.equals(e1.Vertexes[-1].Point, e2.Vertexes[-1].Point)):
|
||||||
endpts = True
|
# endpts = True
|
||||||
elif (DraftVecUtils.equals(e1.Vertexes[-1].Point, e2.Vertexes[0].Point)) and \
|
# elif (DraftVecUtils.equals(e1.Vertexes[-1].Point, e2.Vertexes[0].Point)) and \
|
||||||
(DraftVecUtils.equals(e1.Vertexes[0].Point, e2.Vertexes[-1].Point)):
|
# (DraftVecUtils.equals(e1.Vertexes[0].Point, e2.Vertexes[-1].Point)):
|
||||||
endpts = True
|
# endpts = True
|
||||||
if (center and radius and endpts):
|
# if (center and radius and endpts):
|
||||||
return True
|
# return True
|
||||||
return False
|
# return False
|
||||||
|
|
||||||
|
|
||||||
def segments(poly):
|
def segments(poly):
|
||||||
''' A sequence of (x,y) numeric coordinates pairs '''
|
''' A sequence of (x,y) numeric coordinates pairs '''
|
||||||
return zip(poly, poly[1:] + [poly[0]])
|
return zip(poly, poly[1:] + [poly[0]])
|
||||||
|
|
||||||
def is_clockwise(obj):
|
# def is_clockwise(obj):
|
||||||
'''tests if a wire or Path is clockwise'''
|
# '''tests if a wire or Path is clockwise'''
|
||||||
sum = 0
|
# sum = 0
|
||||||
if isinstance(obj, Part.Wire):
|
# if isinstance(obj, Part.Wire):
|
||||||
for first, second in itertools.izip(obj.Edges, obj.Edges[1:]):
|
# for first, second in itertools.izip(obj.Edges, obj.Edges[1:]):
|
||||||
sum = (second.Vertexes[0].X - first.Vertexes[0].X) * (second.Vertexes[0].Y + first.Vertexes[0].Y)
|
# sum = (second.Vertexes[0].X - first.Vertexes[0].X) * (second.Vertexes[0].Y + first.Vertexes[0].Y)
|
||||||
sum += (obj.Edges[0].Vertexes[0].X - obj.Edges[-1].Vertexes[0].X) * (obj.Edges[0].Vertexes[0].Y + obj.Edges[-1].Vertexes[0].Y)
|
# sum += (obj.Edges[0].Vertexes[0].X - obj.Edges[-1].Vertexes[0].X) * (obj.Edges[0].Vertexes[0].Y + obj.Edges[-1].Vertexes[0].Y)
|
||||||
elif isinstance(obj, Path.Path):
|
# elif isinstance(obj, Path.Path):
|
||||||
movecommands = ['G1', 'G01', 'G2', 'G02', 'G3', 'G03']
|
# movecommands = ['G1', 'G01', 'G2', 'G02', 'G3', 'G03']
|
||||||
|
|
||||||
lastLocation = {'Y': 0, 'X': 0, 'Z': 0.0}
|
# lastLocation = {'Y': 0, 'X': 0, 'Z': 0.0}
|
||||||
currLocation = {'Y': 0, 'X': 0, 'Z': 0.0}
|
# currLocation = {'Y': 0, 'X': 0, 'Z': 0.0}
|
||||||
sum = 0
|
# sum = 0
|
||||||
|
|
||||||
for curCommand in obj.Commands:
|
# for curCommand in obj.Commands:
|
||||||
|
|
||||||
if curCommand.Name in movecommands:
|
# if curCommand.Name in movecommands:
|
||||||
lastLocation.update(currLocation)
|
# lastLocation.update(currLocation)
|
||||||
currLocation.update(curCommand.Parameters)
|
# currLocation.update(curCommand.Parameters)
|
||||||
sum += (currLocation["X"] - lastLocation["X"]) * (currLocation["Y"] + lastLocation["Y"])
|
# sum += (currLocation["X"] - lastLocation["X"]) * (currLocation["Y"] + lastLocation["Y"])
|
||||||
sum += (0 - lastLocation["X"]) * (0 + lastLocation["Y"])
|
# sum += (0 - lastLocation["X"]) * (0 + lastLocation["Y"])
|
||||||
|
|
||||||
return sum >= 0
|
# return sum >= 0
|
||||||
|
|
||||||
def loopdetect(obj, edge1, edge2):
|
def loopdetect(obj, edge1, edge2):
|
||||||
'''
|
'''
|
||||||
|
@ -192,15 +190,15 @@ def loopdetect(obj, edge1, edge2):
|
||||||
return loopwire
|
return loopwire
|
||||||
|
|
||||||
|
|
||||||
def check_clockwise(poly):
|
# def check_clockwise(poly):
|
||||||
'''
|
# '''
|
||||||
check_clockwise(poly) a function for returning a boolean if the selected wire is clockwise or counter clockwise
|
# check_clockwise(poly) a function for returning a boolean if the selected wire is clockwise or counter clockwise
|
||||||
based on point order. poly = [(x1,y1),(x2,y2),(x3,y3)]
|
# based on point order. poly = [(x1,y1),(x2,y2),(x3,y3)]
|
||||||
'''
|
# '''
|
||||||
clockwise = False
|
# clockwise = False
|
||||||
if (sum(x0 * y1 - x1 * y0 for ((x0, y0), (x1, y1)) in segments(poly))) < 0:
|
# if (sum(x0 * y1 - x1 * y0 for ((x0, y0), (x1, y1)) in segments(poly))) < 0:
|
||||||
clockwise = not clockwise
|
# clockwise = not clockwise
|
||||||
return clockwise
|
# return clockwise
|
||||||
|
|
||||||
|
|
||||||
def filterArcs(arcEdge):
|
def filterArcs(arcEdge):
|
||||||
|
@ -254,235 +252,235 @@ def reverseEdge(e):
|
||||||
|
|
||||||
return newedge
|
return newedge
|
||||||
|
|
||||||
def edge_to_path(lastpt, edge, Z, hf=2.0):
|
# def edge_to_path(lastpt, edge, Z, hf=2.0):
|
||||||
if isinstance(edge.Curve, Part.Circle):
|
# if isinstance(edge.Curve, Part.Circle):
|
||||||
# FreeCAD.Console.PrintMessage("arc\n")
|
# # FreeCAD.Console.PrintMessage("arc\n")
|
||||||
arcstartpt = edge.valueAt(edge.FirstParameter)
|
# arcstartpt = edge.valueAt(edge.FirstParameter)
|
||||||
midpt = edge.valueAt(
|
# midpt = edge.valueAt(
|
||||||
(edge.FirstParameter + edge.LastParameter) * 0.5)
|
# (edge.FirstParameter + edge.LastParameter) * 0.5)
|
||||||
arcendpt = edge.valueAt(edge.LastParameter)
|
# arcendpt = edge.valueAt(edge.LastParameter)
|
||||||
# arcchkpt = edge.valueAt(edge.LastParameter * .99)
|
# # arcchkpt = edge.valueAt(edge.LastParameter * .99)
|
||||||
|
|
||||||
if DraftVecUtils.equals(lastpt, arcstartpt):
|
# if DraftVecUtils.equals(lastpt, arcstartpt):
|
||||||
startpt = arcstartpt
|
# startpt = arcstartpt
|
||||||
endpt = arcendpt
|
# endpt = arcendpt
|
||||||
else:
|
# else:
|
||||||
startpt = arcendpt
|
# startpt = arcendpt
|
||||||
endpt = arcstartpt
|
# endpt = arcstartpt
|
||||||
center = edge.Curve.Center
|
# center = edge.Curve.Center
|
||||||
relcenter = center.sub(lastpt)
|
# relcenter = center.sub(lastpt)
|
||||||
# FreeCAD.Console.PrintMessage("arc startpt= " + str(startpt)+ "\n")
|
# # FreeCAD.Console.PrintMessage("arc startpt= " + str(startpt)+ "\n")
|
||||||
# FreeCAD.Console.PrintMessage("arc midpt= " + str(midpt)+ "\n")
|
# # FreeCAD.Console.PrintMessage("arc midpt= " + str(midpt)+ "\n")
|
||||||
# FreeCAD.Console.PrintMessage("arc endpt= " + str(endpt)+ "\n")
|
# # FreeCAD.Console.PrintMessage("arc endpt= " + str(endpt)+ "\n")
|
||||||
arc_cw = check_clockwise(
|
# arc_cw = check_clockwise(
|
||||||
[(startpt.x, startpt.y), (midpt.x, midpt.y), (endpt.x, endpt.y)])
|
# [(startpt.x, startpt.y), (midpt.x, midpt.y), (endpt.x, endpt.y)])
|
||||||
# FreeCAD.Console.PrintMessage("arc_cw="+ str(arc_cw)+"\n")
|
# # FreeCAD.Console.PrintMessage("arc_cw="+ str(arc_cw)+"\n")
|
||||||
if arc_cw:
|
# if arc_cw:
|
||||||
output = "G2"
|
# output = "G2"
|
||||||
else:
|
# else:
|
||||||
output = "G3"
|
# output = "G3"
|
||||||
output += " X" + str(fmt(endpt.x)) + " Y" + \
|
# output += " X" + str(fmt(endpt.x)) + " Y" + \
|
||||||
str(fmt(endpt.y)) + " Z" + str(fmt(Z)) + " F" + str(hf)
|
# str(fmt(endpt.y)) + " Z" + str(fmt(Z)) + " F" + str(hf)
|
||||||
output += " I" + str(fmt(relcenter.x)) + " J" + \
|
# output += " I" + str(fmt(relcenter.x)) + " J" + \
|
||||||
str(fmt(relcenter.y)) + " K" + str(fmt(relcenter.z))
|
# str(fmt(relcenter.y)) + " K" + str(fmt(relcenter.z))
|
||||||
output += "\n"
|
# output += "\n"
|
||||||
lastpt = endpt
|
# lastpt = endpt
|
||||||
# FreeCAD.Console.PrintMessage("last pt arc= " + str(lastpt)+ "\n")
|
# # FreeCAD.Console.PrintMessage("last pt arc= " + str(lastpt)+ "\n")
|
||||||
else:
|
# else:
|
||||||
point = edge.Vertexes[-1].Point
|
# point = edge.Vertexes[-1].Point
|
||||||
if DraftVecUtils.equals(point, lastpt): # edges can come flipped
|
# if DraftVecUtils.equals(point, lastpt): # edges can come flipped
|
||||||
point = edge.Vertexes[0].Point
|
# point = edge.Vertexes[0].Point
|
||||||
output = "G1 X" + str(fmt(point.x)) + " Y" + str(fmt(point.y)) + \
|
# output = "G1 X" + str(fmt(point.x)) + " Y" + str(fmt(point.y)) + \
|
||||||
" Z" + str(fmt(Z)) + " F" + str(hf) + "\n"
|
# " Z" + str(fmt(Z)) + " F" + str(hf) + "\n"
|
||||||
lastpt = point
|
# lastpt = point
|
||||||
# FreeCAD.Console.PrintMessage("line\n")
|
# # FreeCAD.Console.PrintMessage("line\n")
|
||||||
# FreeCAD.Console.PrintMessage("last pt line= " + str(lastpt)+ "\n")
|
# # FreeCAD.Console.PrintMessage("last pt line= " + str(lastpt)+ "\n")
|
||||||
return lastpt, output
|
# return lastpt, output
|
||||||
|
|
||||||
|
|
||||||
def convert(toolpath, Z=0.0, PlungeAngle=90.0, Zprevious=None, StopLength=None, vf=1.0, hf=2.0) :
|
# def convert(toolpath, Z=0.0, PlungeAngle=90.0, Zprevious=None, StopLength=None, vf=1.0, hf=2.0) :
|
||||||
'''convert(toolpath,Z=0.0,vf=1.0,hf=2.0,PlungeAngle=90.0,Zprevious=None,StopLength=None) Converts lines and arcs to G1,G2,G3 moves. Returns a string.'''
|
# '''convert(toolpath,Z=0.0,vf=1.0,hf=2.0,PlungeAngle=90.0,Zprevious=None,StopLength=None) Converts lines and arcs to G1,G2,G3 moves. Returns a string.'''
|
||||||
|
|
||||||
if PlungeAngle != 90.0:
|
# if PlungeAngle != 90.0:
|
||||||
if Zprevious is None:
|
# if Zprevious is None:
|
||||||
raise Exception("Cannot use PlungeAngle != 90.0 degrees without parameter Zprevious")
|
# raise Exception("Cannot use PlungeAngle != 90.0 degrees without parameter Zprevious")
|
||||||
tanA = math.tan(math.pi * PlungeAngle / 180.0)
|
# tanA = math.tan(math.pi * PlungeAngle / 180.0)
|
||||||
minA = (Zprevious - Z) / sum(edge.Length for edge in toolpath)
|
# minA = (Zprevious - Z) / sum(edge.Length for edge in toolpath)
|
||||||
if tanA < minA:
|
# if tanA < minA:
|
||||||
tanA = minA
|
# tanA = minA
|
||||||
#FreeCAD.Console.PrintMessage('Increasing ramp angle to {0} degrees, to be able to make a full round\n'.format(math.atan(tanA) * 180.0 / math.pi))
|
# #FreeCAD.Console.PrintMessage('Increasing ramp angle to {0} degrees, to be able to make a full round\n'.format(math.atan(tanA) * 180.0 / math.pi))
|
||||||
else:
|
# else:
|
||||||
Zprevious = Z
|
# Zprevious = Z
|
||||||
|
|
||||||
lastpt = None
|
# lastpt = None
|
||||||
output = ""
|
# output = ""
|
||||||
path_length = 0.0
|
# path_length = 0.0
|
||||||
Z_cur = Zprevious
|
# Z_cur = Zprevious
|
||||||
|
|
||||||
# create the path from the offset shape
|
# # create the path from the offset shape
|
||||||
for edge in toolpath:
|
# for edge in toolpath:
|
||||||
if not lastpt:
|
# if not lastpt:
|
||||||
# set the first point
|
# # set the first point
|
||||||
lastpt = edge.Vertexes[0].Point
|
# lastpt = edge.Vertexes[0].Point
|
||||||
# FreeCAD.Console.PrintMessage("last pt= " + str(lastpt)+ "\n")
|
# # FreeCAD.Console.PrintMessage("last pt= " + str(lastpt)+ "\n")
|
||||||
output += "G1 X" + str(fmt(lastpt.x)) + " Y" + str(fmt(lastpt.y)) + \
|
# output += "G1 X" + str(fmt(lastpt.x)) + " Y" + str(fmt(lastpt.y)) + \
|
||||||
" Z" + str(fmt(Z_cur)) + " F" + str(vf) + "\n"
|
# " Z" + str(fmt(Z_cur)) + " F" + str(vf) + "\n"
|
||||||
|
|
||||||
if StopLength:
|
# if StopLength:
|
||||||
if path_length + edge.Length > StopLength:
|
# if path_length + edge.Length > StopLength:
|
||||||
# have to split current edge in two
|
# # have to split current edge in two
|
||||||
t0 = edge.FirstParameter
|
# t0 = edge.FirstParameter
|
||||||
t1 = edge.LastParameter
|
# t1 = edge.LastParameter
|
||||||
dL = StopLength - path_length
|
# dL = StopLength - path_length
|
||||||
t = t0 + (t1 - t0) * dL / edge.Length
|
# t = t0 + (t1 - t0) * dL / edge.Length
|
||||||
assert(t0 < t < t1)
|
# assert(t0 < t < t1)
|
||||||
edge = edge.split(t).Edges[0]
|
# edge = edge.split(t).Edges[0]
|
||||||
path_length = StopLength
|
# path_length = StopLength
|
||||||
else:
|
# else:
|
||||||
path_length += edge.Length
|
# path_length += edge.Length
|
||||||
else:
|
# else:
|
||||||
path_length += edge.Length
|
# path_length += edge.Length
|
||||||
|
|
||||||
if Z_cur > Z:
|
# if Z_cur > Z:
|
||||||
Z_next = Zprevious - path_length * tanA
|
# Z_next = Zprevious - path_length * tanA
|
||||||
if Z_next < Z:
|
# if Z_next < Z:
|
||||||
# have to split current edge in two
|
# # have to split current edge in two
|
||||||
t0 = edge.FirstParameter
|
# t0 = edge.FirstParameter
|
||||||
t1 = edge.LastParameter
|
# t1 = edge.LastParameter
|
||||||
dZ = Z_cur - Z
|
# dZ = Z_cur - Z
|
||||||
t = t0 + (t1 - t0) * (dZ / tanA) / edge.Length
|
# t = t0 + (t1 - t0) * (dZ / tanA) / edge.Length
|
||||||
assert(t0 < t < t1)
|
# assert(t0 < t < t1)
|
||||||
subwire = edge.split(t)
|
# subwire = edge.split(t)
|
||||||
assert(len(subwire.Edges) == 2)
|
# assert(len(subwire.Edges) == 2)
|
||||||
Z_cur = Z
|
# Z_cur = Z
|
||||||
lastpt, codes = edge_to_path(lastpt, subwire.Edges[0], Z_cur, hf)
|
# lastpt, codes = edge_to_path(lastpt, subwire.Edges[0], Z_cur, hf)
|
||||||
output += codes
|
# output += codes
|
||||||
edge = subwire.Edges[1]
|
# edge = subwire.Edges[1]
|
||||||
else:
|
# else:
|
||||||
Z_cur = Z_next
|
# Z_cur = Z_next
|
||||||
|
|
||||||
lastpt, codes = edge_to_path(lastpt, edge, Z_cur, hf)
|
# lastpt, codes = edge_to_path(lastpt, edge, Z_cur, hf)
|
||||||
output += codes
|
# output += codes
|
||||||
|
|
||||||
if StopLength:
|
# if StopLength:
|
||||||
if path_length >= StopLength:
|
# if path_length >= StopLength:
|
||||||
break
|
# break
|
||||||
|
|
||||||
return output
|
# return output
|
||||||
|
|
||||||
def SortPath(wire, Side, radius, clockwise, firstedge=None, SegLen=0.5):
|
# def SortPath(wire, Side, radius, clockwise, firstedge=None, SegLen=0.5):
|
||||||
'''SortPath(wire,Side,radius,clockwise,firstedge=None,SegLen =0.5) Sorts the wire and reverses it, if needed. Splits arcs over 180 degrees in two. Returns the reordered offset of the wire. '''
|
# '''SortPath(wire,Side,radius,clockwise,firstedge=None,SegLen =0.5) Sorts the wire and reverses it, if needed. Splits arcs over 180 degrees in two. Returns the reordered offset of the wire. '''
|
||||||
if firstedge:
|
# if firstedge:
|
||||||
edgelist = wire.Edges[:]
|
# edgelist = wire.Edges[:]
|
||||||
if wire.isClosed():
|
# if wire.isClosed():
|
||||||
elindex = None
|
# elindex = None
|
||||||
n = 0
|
# n = 0
|
||||||
for e in edgelist:
|
# for e in edgelist:
|
||||||
if isSameEdge(e, firstedge):
|
# if isSameEdge(e, firstedge):
|
||||||
# FreeCAD.Console.PrintMessage('found first edge\n')
|
# # FreeCAD.Console.PrintMessage('found first edge\n')
|
||||||
elindex = n
|
# elindex = n
|
||||||
n = n + 1
|
# n = n + 1
|
||||||
l1 = edgelist[:elindex]
|
# l1 = edgelist[:elindex]
|
||||||
l2 = edgelist[elindex:]
|
# l2 = edgelist[elindex:]
|
||||||
newedgelist = l2 + l1
|
# newedgelist = l2 + l1
|
||||||
|
|
||||||
if clockwise:
|
# if clockwise:
|
||||||
newedgelist.reverse()
|
# newedgelist.reverse()
|
||||||
last = newedgelist.pop(-1)
|
# last = newedgelist.pop(-1)
|
||||||
newedgelist.insert(0, last)
|
# newedgelist.insert(0, last)
|
||||||
|
|
||||||
preoffset = []
|
# preoffset = []
|
||||||
for e in newedgelist:
|
# for e in newedgelist:
|
||||||
if clockwise:
|
# if clockwise:
|
||||||
r = reverseEdge(e)
|
# r = reverseEdge(e)
|
||||||
preoffset.append(r)
|
# preoffset.append(r)
|
||||||
else:
|
# else:
|
||||||
preoffset.append(e)
|
# preoffset.append(e)
|
||||||
|
|
||||||
sortedpreoff = Part.__sortEdges__(preoffset)
|
# sortedpreoff = Part.__sortEdges__(preoffset)
|
||||||
wire = Part.Wire(sortedpreoff)
|
# wire = Part.Wire(sortedpreoff)
|
||||||
#wire = findWires(sortedpreoff)[0]
|
# #wire = findWires(sortedpreoff)[0]
|
||||||
else:
|
# else:
|
||||||
sortedpreoff = Part.__sortEdges__(edgelist)
|
# sortedpreoff = Part.__sortEdges__(edgelist)
|
||||||
wire = Part.Wire(sortedpreoff)
|
# wire = Part.Wire(sortedpreoff)
|
||||||
#wire = findWires(sortedpreoff)[0]
|
# #wire = findWires(sortedpreoff)[0]
|
||||||
|
|
||||||
edgelist = []
|
# edgelist = []
|
||||||
for e in wire.Edges:
|
# for e in wire.Edges:
|
||||||
if geomType(e) == "Circle":
|
# if geomType(e) == "Circle":
|
||||||
arclist = filterArcs(e)
|
# arclist = filterArcs(e)
|
||||||
for a in arclist:
|
# for a in arclist:
|
||||||
edgelist.append(a)
|
# edgelist.append(a)
|
||||||
elif geomType(e) == "LineSegment":
|
# elif geomType(e) == "LineSegment":
|
||||||
edgelist.append(e)
|
# edgelist.append(e)
|
||||||
elif geomType(e) == "BSplineCurve" or \
|
# elif geomType(e) == "BSplineCurve" or \
|
||||||
geomType(e) == "BezierCurve" or \
|
# geomType(e) == "BezierCurve" or \
|
||||||
geomType(e) == "Ellipse":
|
# geomType(e) == "Ellipse":
|
||||||
edgelist.append(Part.Wire(curvetowire(e, (SegLen))))
|
# edgelist.append(Part.Wire(curvetowire(e, (SegLen))))
|
||||||
#newwire = Part.Wire(edgelist)
|
# #newwire = Part.Wire(edgelist)
|
||||||
sortededges = Part.__sortEdges__(edgelist)
|
# sortededges = Part.__sortEdges__(edgelist)
|
||||||
newwire = findWires(sortededges)[0]
|
# newwire = findWires(sortededges)[0]
|
||||||
|
|
||||||
if is_clockwise(newwire) is not clockwise:
|
# if is_clockwise(newwire) is not clockwise:
|
||||||
newwire.reverse()
|
# newwire.reverse()
|
||||||
|
|
||||||
if Side == 'Left':
|
# if Side == 'Left':
|
||||||
# we use the OCC offset feature
|
# # we use the OCC offset feature
|
||||||
offset = newwire.makeOffset(radius) # tool is outside line
|
# offset = newwire.makeOffset(radius) # tool is outside line
|
||||||
elif Side == 'Right':
|
# elif Side == 'Right':
|
||||||
offset = newwire.makeOffset(-radius) # tool is inside line
|
# offset = newwire.makeOffset(-radius) # tool is inside line
|
||||||
else:
|
# else:
|
||||||
if wire.isClosed():
|
# if wire.isClosed():
|
||||||
offset = newwire.makeOffset(0.0)
|
# offset = newwire.makeOffset(0.0)
|
||||||
else:
|
# else:
|
||||||
offset = newwire
|
# offset = newwire
|
||||||
offset.reverse()
|
# offset.reverse()
|
||||||
|
|
||||||
return offset
|
# return offset
|
||||||
|
|
||||||
|
|
||||||
def MakePath(wire, Side, radius, clockwise, ZClearance, StepDown, ZStart,
|
# def MakePath(wire, Side, radius, clockwise, ZClearance, StepDown, ZStart,
|
||||||
ZFinalDepth, firstedge=None, PathClosed=True, SegLen=0.5,
|
# ZFinalDepth, firstedge=None, PathClosed=True, SegLen=0.5,
|
||||||
VertFeed=1.0, HorizFeed=2.0, VertJog=1.0, HorizJog = 2.0, PlungeAngle=90.0):
|
# VertFeed=1.0, HorizFeed=2.0, VertJog=1.0, HorizJog = 2.0, PlungeAngle=90.0):
|
||||||
''' makes the path - just a simple profile for now '''
|
# ''' makes the path - just a simple profile for now '''
|
||||||
offset = SortPath(wire, Side, radius, clockwise, firstedge, SegLen=SegLen)
|
# offset = SortPath(wire, Side, radius, clockwise, firstedge, SegLen=SegLen)
|
||||||
if len(offset.Edges) == 0:
|
# if len(offset.Edges) == 0:
|
||||||
return ""
|
# return ""
|
||||||
|
|
||||||
toolpath = offset.Edges[:]
|
# toolpath = offset.Edges[:]
|
||||||
paths = ""
|
# paths = ""
|
||||||
paths += "G0 Z" + str(ZClearance) + "F " + fmt(VertJog) + "\n"
|
# paths += "G0 Z" + str(ZClearance) + "F " + fmt(VertJog) + "\n"
|
||||||
first = toolpath[0].Vertexes[0].Point
|
# first = toolpath[0].Vertexes[0].Point
|
||||||
paths += "G0 X" + str(fmt(first.x)) + "Y" + str(fmt(first.y)) + "F " + fmt(HorizJog) + "\n"
|
# paths += "G0 X" + str(fmt(first.x)) + "Y" + str(fmt(first.y)) + "F " + fmt(HorizJog) + "\n"
|
||||||
Zprevious = ZStart
|
# Zprevious = ZStart
|
||||||
ZCurrent = ZStart - StepDown
|
# ZCurrent = ZStart - StepDown
|
||||||
|
|
||||||
while ZCurrent > ZFinalDepth:
|
# while ZCurrent > ZFinalDepth:
|
||||||
paths += convert(toolpath, Z=ZCurrent, Zprevious=Zprevious, PlungeAngle=PlungeAngle,
|
# paths += convert(toolpath, Z=ZCurrent, Zprevious=Zprevious, PlungeAngle=PlungeAngle,
|
||||||
vf=VertFeed, hf=HorizFeed)
|
# vf=VertFeed, hf=HorizFeed)
|
||||||
if not PathClosed:
|
# if not PathClosed:
|
||||||
paths += "G0 Z" + str(ZClearance) + "F " + fmt(VertJog)
|
# paths += "G0 Z" + str(ZClearance) + "F " + fmt(VertJog)
|
||||||
paths += "G0 X" + str(fmt(first.x)) + "Y" + \
|
# paths += "G0 X" + str(fmt(first.x)) + "Y" + \
|
||||||
str(fmt(first.y)) + "F " + fmt(HorizJog) + "\n"
|
# str(fmt(first.y)) + "F " + fmt(HorizJog) + "\n"
|
||||||
Zprevious = ZCurrent
|
# Zprevious = ZCurrent
|
||||||
ZCurrent = ZCurrent - abs(StepDown)
|
# ZCurrent = ZCurrent - abs(StepDown)
|
||||||
|
|
||||||
# do the final Z value
|
# # do the final Z value
|
||||||
paths += convert(toolpath, Z=ZFinalDepth, Zprevious=Zprevious, PlungeAngle=PlungeAngle,
|
# paths += convert(toolpath, Z=ZFinalDepth, Zprevious=Zprevious, PlungeAngle=PlungeAngle,
|
||||||
vf=VertFeed, hf=HorizFeed)
|
# vf=VertFeed, hf=HorizFeed)
|
||||||
|
|
||||||
# when plunging with != 90 degree we have to do one last pass to clear the remaining ramp
|
# # when plunging with != 90 degree we have to do one last pass to clear the remaining ramp
|
||||||
if PlungeAngle != 90.0:
|
# if PlungeAngle != 90.0:
|
||||||
tanA = math.tan(math.pi * PlungeAngle / 180.0)
|
# tanA = math.tan(math.pi * PlungeAngle / 180.0)
|
||||||
if tanA <= 0.0:
|
# if tanA <= 0.0:
|
||||||
StopLength=None
|
# StopLength=None
|
||||||
else:
|
# else:
|
||||||
StopLength=abs(StepDown/tanA)
|
# StopLength=abs(StepDown/tanA)
|
||||||
paths += convert(toolpath, Z=ZFinalDepth, Zprevious=Zprevious, StopLength=StopLength,
|
# paths += convert(toolpath, Z=ZFinalDepth, Zprevious=Zprevious, StopLength=StopLength,
|
||||||
vf=VertFeed, hf=HorizFeed)
|
# vf=VertFeed, hf=HorizFeed)
|
||||||
|
|
||||||
paths += "G0 Z" + str(ZClearance) + "F " + fmt(VertJog) + "\n"
|
# paths += "G0 Z" + str(ZClearance) + "F " + fmt(VertJog) + "\n"
|
||||||
return paths
|
# return paths
|
||||||
|
|
||||||
# the next two functions are for automatically populating tool
|
# the next two functions are for automatically populating tool
|
||||||
# numbers/height offset numbers based on previously active toolnumbers
|
# numbers/height offset numbers based on previously active toolnumbers
|
||||||
|
@ -548,19 +546,19 @@ def getLastToolLoad(obj):
|
||||||
continue
|
continue
|
||||||
return tc
|
return tc
|
||||||
|
|
||||||
def getToolControllers(obj):
|
# def getToolControllers(obj):
|
||||||
controllers = []
|
# controllers = []
|
||||||
try:
|
# try:
|
||||||
parent = obj.InList[0]
|
# parent = obj.InList[0]
|
||||||
except:
|
# except:
|
||||||
parent = None
|
# parent = None
|
||||||
|
|
||||||
if parent is not None and hasattr(parent, 'Group'):
|
# if parent is not None and hasattr(parent, 'Group'):
|
||||||
sibs = parent.Group
|
# sibs = parent.Group
|
||||||
for g in sibs:
|
# for g in sibs:
|
||||||
if isinstance(g.Proxy, PathScripts.PathLoadTool.LoadTool):
|
# if isinstance(g.Proxy, PathScripts.PathLoadTool.LoadTool):
|
||||||
controllers.append(g.Name)
|
# controllers.append(g.Name)
|
||||||
return controllers
|
# return controllers
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -614,7 +612,6 @@ def addToJob(obj, jobname = None):
|
||||||
else:
|
else:
|
||||||
#form = FreeCADGui.PySideUic.loadUi(FreeCAD.getHomePath() + "Mod/Path/DlgJobChooser.ui")
|
#form = FreeCADGui.PySideUic.loadUi(FreeCAD.getHomePath() + "Mod/Path/DlgJobChooser.ui")
|
||||||
form = FreeCADGui.PySideUic.loadUi(":/panels/DlgJobChooser.ui")
|
form = FreeCADGui.PySideUic.loadUi(":/panels/DlgJobChooser.ui")
|
||||||
|
|
||||||
mylist = [i.Name for i in jobs]
|
mylist = [i.Name for i in jobs]
|
||||||
form.cboProject.addItems(mylist)
|
form.cboProject.addItems(mylist)
|
||||||
r = form.exec_()
|
r = form.exec_()
|
||||||
|
@ -629,15 +626,15 @@ def addToJob(obj, jobname = None):
|
||||||
job.Group = g
|
job.Group = g
|
||||||
return job
|
return job
|
||||||
|
|
||||||
def getLastZ(obj):
|
# def getLastZ(obj):
|
||||||
''' find the last z value in the job '''
|
# ''' find the last z value in the job '''
|
||||||
lastZ = ""
|
# lastZ = ""
|
||||||
for g in obj.Group:
|
# for g in obj.Group:
|
||||||
for c in g.Path.Commands:
|
# for c in g.Path.Commands:
|
||||||
for n in c.Parameters:
|
# for n in c.Parameters:
|
||||||
if n == 'Z':
|
# if n == 'Z':
|
||||||
lastZ = c.Parameters['Z']
|
# lastZ = c.Parameters['Z']
|
||||||
return lastZ
|
# return lastZ
|
||||||
|
|
||||||
def rapid(x=None, y=None, z=None):
|
def rapid(x=None, y=None, z=None):
|
||||||
""" Returns gcode string to perform a rapid move."""
|
""" Returns gcode string to perform a rapid move."""
|
||||||
|
|
|
@ -33,19 +33,19 @@ FreeCADGui = None
|
||||||
if FreeCAD.GuiUp:
|
if FreeCAD.GuiUp:
|
||||||
import FreeCADGui
|
import FreeCADGui
|
||||||
|
|
||||||
class OldHighlighter(QtGui.QSyntaxHighlighter):
|
# class OldHighlighter(QtGui.QSyntaxHighlighter):
|
||||||
def highlightBlock(self, text):
|
# def highlightBlock(self, text):
|
||||||
myClassFormat = QtGui.QTextCharFormat()
|
# myClassFormat = QtGui.QTextCharFormat()
|
||||||
myClassFormat.setFontWeight(QtGui.QFont.Bold)
|
# myClassFormat.setFontWeight(QtGui.QFont.Bold)
|
||||||
myClassFormat.setForeground(QtCore.Qt.green)
|
# myClassFormat.setForeground(QtCore.Qt.green)
|
||||||
# the regex pattern to be colored
|
# # the regex pattern to be colored
|
||||||
pattern = "(G.*?|M.*?)\\s"
|
# pattern = "(G.*?|M.*?)\\s"
|
||||||
expression = QtCore.QRegExp(pattern)
|
# expression = QtCore.QRegExp(pattern)
|
||||||
index = text.index(expression)
|
# index = text.index(expression)
|
||||||
while index >= 0:
|
# while index >= 0:
|
||||||
length = expression.matchedLength()
|
# length = expression.matchedLength()
|
||||||
setFormat(index, length, myClassFormat)
|
# setFormat(index, length, myClassFormat)
|
||||||
index = text.index(expression, index + length)
|
# index = text.index(expression, index + length)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -152,7 +152,7 @@ def editor(gcode):
|
||||||
'''pops up a handy little editor to look at the code output '''
|
'''pops up a handy little editor to look at the code output '''
|
||||||
dia = GCodeEditorDialog()
|
dia = GCodeEditorDialog()
|
||||||
dia.editor.setText(gcode)
|
dia.editor.setText(gcode)
|
||||||
result = dia.exec_()
|
# result = dia.exec_()
|
||||||
|
|
||||||
def fcoms(string,commentsym):
|
def fcoms(string,commentsym):
|
||||||
''' filter and rebuild comments with user preferred comment symbol'''
|
''' filter and rebuild comments with user preferred comment symbol'''
|
||||||
|
|
|
@ -1,190 +0,0 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<ui version="4.0">
|
|
||||||
<class>Dialog</class>
|
|
||||||
<widget class="QDialog" name="Dialog">
|
|
||||||
<property name="geometry">
|
|
||||||
<rect>
|
|
||||||
<x>0</x>
|
|
||||||
<y>0</y>
|
|
||||||
<width>423</width>
|
|
||||||
<height>435</height>
|
|
||||||
</rect>
|
|
||||||
</property>
|
|
||||||
<property name="windowTitle">
|
|
||||||
<string>Dialog</string>
|
|
||||||
</property>
|
|
||||||
<layout class="QVBoxLayout" name="verticalLayout">
|
|
||||||
<item>
|
|
||||||
<widget class="QGroupBox" name="groupBox_2">
|
|
||||||
<property name="title">
|
|
||||||
<string>Tool Properties</string>
|
|
||||||
</property>
|
|
||||||
<layout class="QFormLayout" name="formLayout">
|
|
||||||
<property name="fieldGrowthPolicy">
|
|
||||||
<enum>QFormLayout::AllNonFixedFieldsGrow</enum>
|
|
||||||
</property>
|
|
||||||
<item row="0" column="0">
|
|
||||||
<widget class="QLabel" name="label">
|
|
||||||
<property name="text">
|
|
||||||
<string>Name</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="0" column="1">
|
|
||||||
<widget class="QLineEdit" name="NameField"/>
|
|
||||||
</item>
|
|
||||||
<item row="2" column="0">
|
|
||||||
<widget class="QLabel" name="label_2">
|
|
||||||
<property name="text">
|
|
||||||
<string>Type</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="2" column="1">
|
|
||||||
<widget class="QComboBox" name="TypeField"/>
|
|
||||||
</item>
|
|
||||||
<item row="4" column="0">
|
|
||||||
<widget class="QLabel" name="label_3">
|
|
||||||
<property name="text">
|
|
||||||
<string>Material</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="4" column="1">
|
|
||||||
<widget class="QComboBox" name="MaterialField"/>
|
|
||||||
</item>
|
|
||||||
<item row="6" column="0">
|
|
||||||
<widget class="QLabel" name="label_4">
|
|
||||||
<property name="text">
|
|
||||||
<string>Diameter</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="6" column="1">
|
|
||||||
<widget class="QDoubleSpinBox" name="DiameterField">
|
|
||||||
<property name="suffix">
|
|
||||||
<string>mm</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="8" column="0">
|
|
||||||
<widget class="QLabel" name="label_5">
|
|
||||||
<property name="text">
|
|
||||||
<string>Length Offset</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="8" column="1">
|
|
||||||
<widget class="QDoubleSpinBox" name="LengthOffsetField">
|
|
||||||
<property name="suffix">
|
|
||||||
<string>mm</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="12" column="0">
|
|
||||||
<widget class="QLabel" name="label_6">
|
|
||||||
<property name="text">
|
|
||||||
<string>Flat Radius</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="12" column="1">
|
|
||||||
<widget class="QDoubleSpinBox" name="FlatRadiusField">
|
|
||||||
<property name="suffix">
|
|
||||||
<string>mm</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="14" column="0">
|
|
||||||
<widget class="QLabel" name="label_7">
|
|
||||||
<property name="text">
|
|
||||||
<string>Corner Radius</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="14" column="1">
|
|
||||||
<widget class="QDoubleSpinBox" name="CornerRadiusField">
|
|
||||||
<property name="suffix">
|
|
||||||
<string>mm</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="16" column="0">
|
|
||||||
<widget class="QLabel" name="label_9">
|
|
||||||
<property name="text">
|
|
||||||
<string>Cutting Edge Angle</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="16" column="1">
|
|
||||||
<widget class="QDoubleSpinBox" name="CuttingEdgeAngleField_2">
|
|
||||||
<property name="suffix">
|
|
||||||
<string>°</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="18" column="0">
|
|
||||||
<widget class="QLabel" name="label_8">
|
|
||||||
<property name="text">
|
|
||||||
<string>Cutting Edge Height</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="18" column="1">
|
|
||||||
<widget class="QDoubleSpinBox" name="CuttingEdgeHeightField">
|
|
||||||
<property name="suffix">
|
|
||||||
<string>mm</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
</layout>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<widget class="QDialogButtonBox" name="buttonBox">
|
|
||||||
<property name="orientation">
|
|
||||||
<enum>Qt::Horizontal</enum>
|
|
||||||
</property>
|
|
||||||
<property name="standardButtons">
|
|
||||||
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
</layout>
|
|
||||||
</widget>
|
|
||||||
<resources/>
|
|
||||||
<connections>
|
|
||||||
<connection>
|
|
||||||
<sender>buttonBox</sender>
|
|
||||||
<signal>accepted()</signal>
|
|
||||||
<receiver>Dialog</receiver>
|
|
||||||
<slot>accept()</slot>
|
|
||||||
<hints>
|
|
||||||
<hint type="sourcelabel">
|
|
||||||
<x>248</x>
|
|
||||||
<y>254</y>
|
|
||||||
</hint>
|
|
||||||
<hint type="destinationlabel">
|
|
||||||
<x>157</x>
|
|
||||||
<y>274</y>
|
|
||||||
</hint>
|
|
||||||
</hints>
|
|
||||||
</connection>
|
|
||||||
<connection>
|
|
||||||
<sender>buttonBox</sender>
|
|
||||||
<signal>rejected()</signal>
|
|
||||||
<receiver>Dialog</receiver>
|
|
||||||
<slot>reject()</slot>
|
|
||||||
<hints>
|
|
||||||
<hint type="sourcelabel">
|
|
||||||
<x>316</x>
|
|
||||||
<y>260</y>
|
|
||||||
</hint>
|
|
||||||
<hint type="destinationlabel">
|
|
||||||
<x>286</x>
|
|
||||||
<y>274</y>
|
|
||||||
</hint>
|
|
||||||
</hints>
|
|
||||||
</connection>
|
|
||||||
</connections>
|
|
||||||
</ui>
|
|
|
@ -1,72 +0,0 @@
|
||||||
################################################################################
|
|
||||||
# drag knife.py
|
|
||||||
#
|
|
||||||
# NC code creator for attaching Z coordinates to a surface
|
|
||||||
#
|
|
||||||
# Dan Heeks 26th April 2012
|
|
||||||
|
|
||||||
import recreator
|
|
||||||
dragging = False
|
|
||||||
from kurve_funcs import cut_curve as cut_curve
|
|
||||||
import nc
|
|
||||||
import area
|
|
||||||
|
|
||||||
################################################################################
|
|
||||||
class Creator(recreator.Redirector):
|
|
||||||
|
|
||||||
def __init__(self, original, drag_distance):
|
|
||||||
recreator.Redirector.__init__(self, original)
|
|
||||||
|
|
||||||
self.drag_distance = drag_distance
|
|
||||||
self.path = None
|
|
||||||
|
|
||||||
def cut_path(self):
|
|
||||||
if self.path == None: return
|
|
||||||
|
|
||||||
print self.drag_distance
|
|
||||||
self.path.OffsetForward(self.drag_distance, False)
|
|
||||||
|
|
||||||
nc.creator = nc.creator.original
|
|
||||||
|
|
||||||
if self.path.getNumVertices() > 0:
|
|
||||||
v = self.path.FirstVertex()
|
|
||||||
nc.creator.feed(v.p.x, v.p.y)
|
|
||||||
|
|
||||||
cut_curve(self.path)
|
|
||||||
nc.creator = self
|
|
||||||
|
|
||||||
self.path = area.Curve()
|
|
||||||
|
|
||||||
def feed(self, x=None, y=None, z=None, a=None, b=None, c=None):
|
|
||||||
px = self.x
|
|
||||||
py = self.y
|
|
||||||
pz = self.z
|
|
||||||
recreator.Redirector.feed(self, x, y, z, a, b, c)
|
|
||||||
if self.x == None or self.y == None or self.z == None:
|
|
||||||
return
|
|
||||||
if px == self.x and py == self.y:
|
|
||||||
return
|
|
||||||
|
|
||||||
# add a line to the path
|
|
||||||
if self.path == None: self.path = area.Curve()
|
|
||||||
self.path.append(area.Point(self.x, self.y))
|
|
||||||
|
|
||||||
def arc(self, x=None, y=None, z=None, i=None, j=None, k=None, r=None, ccw = True):
|
|
||||||
recreator.Redirector.arc(self, x, y, z, i, j, k, r, ccw)
|
|
||||||
|
|
||||||
# add an arc to the path
|
|
||||||
if self.path == None: self.path = area.Curve()
|
|
||||||
self.path.append(area.Vertex(1 if ccw else -1, area.Point(self.x, self.y), area.Point(i, j)))
|
|
||||||
|
|
||||||
def drag_begin(drag_distance):
|
|
||||||
global dragging
|
|
||||||
if dragging == True:
|
|
||||||
drag_end()
|
|
||||||
nc.creator = Creator(nc.creator, drag_distance)
|
|
||||||
dragging = True
|
|
||||||
|
|
||||||
def drag_end():
|
|
||||||
global dragging
|
|
||||||
nc.creator.cut_path()
|
|
||||||
nc.creator = nc.creator.original
|
|
||||||
attached = False
|
|
|
@ -1,306 +0,0 @@
|
||||||
import nc
|
|
||||||
import makerbot_codes as maker
|
|
||||||
import datetime
|
|
||||||
import iso_modal
|
|
||||||
import math
|
|
||||||
|
|
||||||
|
|
||||||
now = datetime.datetime.now()
|
|
||||||
|
|
||||||
################################################################################
|
|
||||||
class CreatorMakerbotHBP(iso_modal.CreatorIsoModal):
|
|
||||||
def __init__(self):
|
|
||||||
iso_modal.CreatorIsoModal.__init__(self)
|
|
||||||
|
|
||||||
self.absolute_flag = True
|
|
||||||
self.prev_g91 = ''
|
|
||||||
|
|
||||||
|
|
||||||
################################################################################
|
|
||||||
# program begin and end
|
|
||||||
|
|
||||||
def program_begin(self, id, name=''):
|
|
||||||
self.write((maker.codes.COMMENT(now)))
|
|
||||||
self.write((maker.codes.EXTRUDER_TEMP('220')) + (maker.codes.COMMENT('Extruder Temp')) )
|
|
||||||
self.write((maker.codes.BUILD_BED_TEMP('110'))+ (maker.codes.COMMENT('Build Bed Temp')) )
|
|
||||||
self.write((maker.codes.FAN_OFF()) + (maker.codes.COMMENT('Fan Off')) )
|
|
||||||
self.write((maker.codes.METRIC()) + (maker.codes.COMMENT('Metric units')) )
|
|
||||||
self.write((maker.codes.ABSOLUTE()) + (maker.codes.COMMENT('Absolute units')) )
|
|
||||||
self.write('G92 X0 Y0 Z0 (You are now at 0,0,0)\n')
|
|
||||||
self.write('G0 Z15 (Move up for warmup)\n')
|
|
||||||
self.write((maker.codes.EXTRUDER_SPEED_PWM('255')) + (maker.codes.COMMENT('Extruder Speed')) )
|
|
||||||
self.write('M6 T0 (Wait for tool to heat up)\n')
|
|
||||||
self.write('G04 P5000 (Wait 5 seconds)\n')
|
|
||||||
self.write((maker.codes.EXTRUDER_ON_FWD()) + (maker.codes.COMMENT('Extruder On')) )
|
|
||||||
self.write('G04 P5000 (Wait 5 seconds)\n')
|
|
||||||
self.write((maker.codes.EXTRUDER_OFF()) + (maker.codes.COMMENT('Extruder Off')) )
|
|
||||||
self.write('M01 (The heated build platform is heating up. Wait until after the lights have turned off for the first time, clear the test extrusion, and click yes.)\n')
|
|
||||||
self.write('G0 Z0 (Go back to zero.)\n')
|
|
||||||
|
|
||||||
def program_end(self):
|
|
||||||
self.write((maker.codes.COMMENT('End of the file. Begin cool-down')))
|
|
||||||
self.write((maker.codes.EXTRUDER_TEMP('0')) + (maker.codes.COMMENT('Extruder Temp')) )
|
|
||||||
self.write((maker.codes.BUILD_BED_TEMP('0')) + (maker.codes.COMMENT('Build Bed Temp')) )
|
|
||||||
self.write((maker.codes.FAN_ON()) + (maker.codes.COMMENT('Fan On')) )
|
|
||||||
self.write('G92 Z0 (zero our z axis - hack b/c skeinforge mangles gcodes in end.txt)\n')
|
|
||||||
self.write('G1 Z10 (go up 10 b/c it was zeroed earlier.)\n')
|
|
||||||
self.write('G1 X0 Y0 Z10 (go to 0,0,z)\n')
|
|
||||||
self.write((maker.codes.STEPPERS_OFF()) + (maker.codes.COMMENT('Steppers Off')) )
|
|
||||||
|
|
||||||
def program_stop(self):
|
|
||||||
self.write((maker.codes.EXTRUDER_TEMP('0')))
|
|
||||||
self.write((maker.codes.BUILD_BED_TEMP('0')))
|
|
||||||
self.write((maker.codes.STEPPERS_OFF()))
|
|
||||||
|
|
||||||
################################################################################
|
|
||||||
# general
|
|
||||||
def write_blocknum(self):
|
|
||||||
pass
|
|
||||||
|
|
||||||
def set_plane(self, plane):
|
|
||||||
pass
|
|
||||||
|
|
||||||
def workplane(self, id):
|
|
||||||
pass
|
|
||||||
|
|
||||||
def spindle(self, s, clockwise):
|
|
||||||
pass
|
|
||||||
################################################################################
|
|
||||||
# Extruder Control
|
|
||||||
|
|
||||||
def extruder_on(self):
|
|
||||||
self.write((maker.codes.EXTRUDER_ON()) + ('\n'))
|
|
||||||
|
|
||||||
def extruder_off(self):
|
|
||||||
self.write((maker.codes.EXTRUDER_OFF()) + ('\n'))
|
|
||||||
|
|
||||||
def set_extruder_flowrate(self, flowrate):
|
|
||||||
self.write((maker.codes.EXTRUDER_SPEED_PWM(flowrate)) + ('\n'))
|
|
||||||
|
|
||||||
def extruder_temp(self, temp):
|
|
||||||
self.write((maker.codes.EXTRUDER_TEMP(temp)) + ('\n'))
|
|
||||||
|
|
||||||
################################################################################
|
|
||||||
# Build Environment Control
|
|
||||||
def build_bed_temp(self, temp):
|
|
||||||
self.write((maker.codes.BUILD_BED_TEMP(temp)) + ('\n'))
|
|
||||||
|
|
||||||
def chamber_temp(self, temp):
|
|
||||||
self.write((maker.codes.CHAMBER_TEMP(temp)) + ('\n'))
|
|
||||||
|
|
||||||
################################################################################
|
|
||||||
# Fan Control
|
|
||||||
def fan_on(self):
|
|
||||||
self.write((maker.codes.FAN_ON()) + ('\n'))
|
|
||||||
|
|
||||||
def fan_off(self):
|
|
||||||
self.write((maker.codes.FAN_OFF()) + ('\n'))
|
|
||||||
|
|
||||||
################################################################################
|
|
||||||
# Custom routines
|
|
||||||
|
|
||||||
def wipe(self):
|
|
||||||
self.write(('(This would be a good place for a custom wipe routine)\n'))
|
|
||||||
|
|
||||||
################################################################################
|
|
||||||
# APT style INSERT- insert anything into program
|
|
||||||
|
|
||||||
def insert(self, text):
|
|
||||||
self.write((text + '\n'))
|
|
||||||
|
|
||||||
################################################################################
|
|
||||||
# tool info
|
|
||||||
def tool_change(self, id):
|
|
||||||
pass
|
|
||||||
# self.write_blocknum()
|
|
||||||
# self.write((maker.codes.TOOL() % id) + '\n')
|
|
||||||
# self.t = id
|
|
||||||
|
|
||||||
def tool_defn(self, id, name='', params=None):
|
|
||||||
pass
|
|
||||||
############################################################################
|
|
||||||
## Moves
|
|
||||||
|
|
||||||
def rapid(self, x=None, y=None, z=None, a=None, b=None, c=None ):
|
|
||||||
self.write_blocknum()
|
|
||||||
if self.g0123_modal:
|
|
||||||
if self.prev_g0123 != maker.codes.RAPID():
|
|
||||||
self.write(maker.codes.RAPID())
|
|
||||||
self.prev_g0123 = maker.codes.RAPID()
|
|
||||||
else:
|
|
||||||
self.write(maker.codes.RAPID())
|
|
||||||
self.write_preps()
|
|
||||||
if (x != None):
|
|
||||||
dx = x - self.x
|
|
||||||
if (self.absolute_flag ):
|
|
||||||
self.write(maker.codes.X() + (self.fmt % x))
|
|
||||||
else:
|
|
||||||
self.write(maker.codes.X() + (self.fmt % dx))
|
|
||||||
self.x = x
|
|
||||||
if (y != None):
|
|
||||||
dy = y - self.y
|
|
||||||
if (self.absolute_flag ):
|
|
||||||
self.write(maker.codes.Y() + (self.fmt % y))
|
|
||||||
else:
|
|
||||||
self.write(maker.codes.Y() + (self.fmt % dy))
|
|
||||||
|
|
||||||
self.y = y
|
|
||||||
if (z != None):
|
|
||||||
dz = z - self.z
|
|
||||||
if (self.absolute_flag ):
|
|
||||||
self.write(maker.codes.Z() + (self.fmt % z))
|
|
||||||
else:
|
|
||||||
self.write(maker.codes.Z() + (self.fmt % dz))
|
|
||||||
|
|
||||||
self.z = z
|
|
||||||
|
|
||||||
if (a != None):
|
|
||||||
da = a - self.a
|
|
||||||
if (self.absolute_flag ):
|
|
||||||
self.write(maker.codes.A() + (self.fmt % a))
|
|
||||||
else:
|
|
||||||
self.write(maker.codes.A() + (self.fmt % da))
|
|
||||||
self.a = a
|
|
||||||
|
|
||||||
if (b != None):
|
|
||||||
db = b - self.b
|
|
||||||
if (self.absolute_flag ):
|
|
||||||
self.write(maker.codes.B() + (self.fmt % b))
|
|
||||||
else:
|
|
||||||
self.write(maker.codes.B() + (self.fmt % db))
|
|
||||||
self.b = b
|
|
||||||
|
|
||||||
if (c != None):
|
|
||||||
dc = c - self.c
|
|
||||||
if (self.absolute_flag ):
|
|
||||||
self.write(maker.codes.C() + (self.fmt % c))
|
|
||||||
else:
|
|
||||||
self.write(maker.codes.C() + (self.fmt % dc))
|
|
||||||
self.c = c
|
|
||||||
self.write_spindle()
|
|
||||||
self.write_misc()
|
|
||||||
self.write('\n')
|
|
||||||
|
|
||||||
def feed(self, x=None, y=None, z=None, a = None, b = None, c = None):
|
|
||||||
if self.same_xyz(x, y, z): return
|
|
||||||
self.write_blocknum()
|
|
||||||
if self.g0123_modal:
|
|
||||||
if self.prev_g0123 != maker.codes.FEED():
|
|
||||||
self.write(maker.codes.FEED())
|
|
||||||
self.prev_g0123 = maker.codes.FEED()
|
|
||||||
else:
|
|
||||||
self.write(maker.codes.FEED())
|
|
||||||
self.write_preps()
|
|
||||||
dx = dy = dz = 0
|
|
||||||
if (x != None):
|
|
||||||
dx = x - self.x
|
|
||||||
if (self.absolute_flag ):
|
|
||||||
self.write(maker.codes.X() + (self.fmt % x))
|
|
||||||
else:
|
|
||||||
self.write(maker.codes.X() + (self.fmt % dx))
|
|
||||||
self.x = x
|
|
||||||
if (y != None):
|
|
||||||
dy = y - self.y
|
|
||||||
if (self.absolute_flag ):
|
|
||||||
self.write(maker.codes.Y() + (self.fmt % y))
|
|
||||||
else:
|
|
||||||
self.write(maker.codes.Y() + (self.fmt % dy))
|
|
||||||
|
|
||||||
self.y = y
|
|
||||||
if (z != None):
|
|
||||||
dz = z - self.z
|
|
||||||
if (self.absolute_flag ):
|
|
||||||
self.write(maker.codes.Z() + (self.fmt % z))
|
|
||||||
else:
|
|
||||||
self.write(maker.codes.Z() + (self.fmt % dz))
|
|
||||||
|
|
||||||
self.z = z
|
|
||||||
if (self.fhv) : self.calc_feedrate_hv(math.sqrt(dx*dx+dy*dy), math.fabs(dz))
|
|
||||||
self.write_feedrate()
|
|
||||||
self.write_spindle()
|
|
||||||
self.write_misc()
|
|
||||||
self.write('\n')
|
|
||||||
|
|
||||||
def same_xyz(self, x=None, y=None, z=None):
|
|
||||||
if (x != None):
|
|
||||||
if (self.fmt % x) != (self.fmt % self.x):
|
|
||||||
return False
|
|
||||||
if (y != None):
|
|
||||||
if (self.fmt % y) != (self.fmt % self.y):
|
|
||||||
return False
|
|
||||||
if (z != None):
|
|
||||||
if (self.fmt % z) != (self.fmt % self.z):
|
|
||||||
return False
|
|
||||||
|
|
||||||
return True
|
|
||||||
|
|
||||||
def arc(self, cw, x=None, y=None, z=None, i=None, j=None, k=None, r=None):
|
|
||||||
if self.same_xyz(x, y, z): return
|
|
||||||
self.write_blocknum()
|
|
||||||
arc_g_code = ''
|
|
||||||
if cw: arc_g_code = maker.codes.ARC_CW()
|
|
||||||
else: arc_g_code = maker.codes.ARC_CCW()
|
|
||||||
if self.g0123_modal:
|
|
||||||
if self.prev_g0123 != arc_g_code:
|
|
||||||
self.write(arc_g_code)
|
|
||||||
self.prev_g0123 = arc_g_code
|
|
||||||
else:
|
|
||||||
self.write(arc_g_code)
|
|
||||||
self.write_preps()
|
|
||||||
if (x != None):
|
|
||||||
dx = x - self.x
|
|
||||||
if (self.absolute_flag ):
|
|
||||||
self.write(maker.codes.X() + (self.fmt % x))
|
|
||||||
else:
|
|
||||||
self.write(maker.codes.X() + (self.fmt % dx))
|
|
||||||
self.x = x
|
|
||||||
if (y != None):
|
|
||||||
dy = y - self.y
|
|
||||||
if (self.absolute_flag ):
|
|
||||||
self.write(maker.codes.Y() + (self.fmt % y))
|
|
||||||
else:
|
|
||||||
self.write(maker.codes.Y() + (self.fmt % dy))
|
|
||||||
self.y = y
|
|
||||||
if (z != None):
|
|
||||||
dz = z - self.z
|
|
||||||
if (self.absolute_flag ):
|
|
||||||
self.write(maker.codes.Z() + (self.fmt % z))
|
|
||||||
else:
|
|
||||||
self.write(maker.codes.Z() + (self.fmt % dz))
|
|
||||||
self.z = z
|
|
||||||
if (i != None) : self.write(maker.codes.CENTRE_X() + (self.fmt % i))
|
|
||||||
if (j != None) : self.write(maker.codes.CENTRE_Y() + (self.fmt % j))
|
|
||||||
if (k != None) : self.write(maker.codes.CENTRE_Z() + (self.fmt % k))
|
|
||||||
if (r != None) : self.write(maker.codes.RADIUS() + (self.fmt % r))
|
|
||||||
# use horizontal feed rate
|
|
||||||
if (self.fhv) : self.calc_feedrate_hv(1, 0)
|
|
||||||
self.write_feedrate()
|
|
||||||
self.write_spindle()
|
|
||||||
self.write_misc()
|
|
||||||
self.write('\n')
|
|
||||||
|
|
||||||
def arc_cw(self, x=None, y=None, z=None, i=None, j=None, k=None, r=None):
|
|
||||||
self.arc(True, x, y, z, i, j, k, r)
|
|
||||||
|
|
||||||
def arc_ccw(self, x=None, y=None, z=None, i=None, j=None, k=None, r=None):
|
|
||||||
self.arc(False, x, y, z, i, j, k, r)
|
|
||||||
|
|
||||||
def dwell(self, t):
|
|
||||||
self.write_blocknum()
|
|
||||||
self.write_preps()
|
|
||||||
self.write(maker.codes.DWELL() + (maker.codes.TIME() % t))
|
|
||||||
self.write_misc()
|
|
||||||
self.write('\n')
|
|
||||||
|
|
||||||
def rapid_home(self, x=None, y=None, z=None, a=None, b=None, c=None):
|
|
||||||
pass
|
|
||||||
|
|
||||||
def rapid_unhome(self):
|
|
||||||
pass
|
|
||||||
|
|
||||||
def set_machine_coordinates(self):
|
|
||||||
self.write(maker.codes.MACHINE_COORDINATES())
|
|
||||||
self.prev_g0123 = ''
|
|
||||||
|
|
||||||
nc.creator = CreatorMakerbotHBP()
|
|
||||||
|
|
|
@ -1,128 +0,0 @@
|
||||||
################################################################################
|
|
||||||
# makerbot_codes.py
|
|
||||||
#
|
|
||||||
# a lot like iso_codes.py but with reprap/makerbot specific M codes.
|
|
||||||
#
|
|
||||||
# Brad Collette, 12th Sept 2010
|
|
||||||
#
|
|
||||||
# Many of these codes have nothing to do with reprap/additive machining but are left here in anticipation of future hybrid machines.
|
|
||||||
|
|
||||||
class Codes():
|
|
||||||
def SPACE(self): return(' ')
|
|
||||||
def FORMAT_FEEDRATE(self): return('%.2f')
|
|
||||||
def FORMAT_IN(self): return('%.5f')
|
|
||||||
def FORMAT_MM(self): return('%.3f')
|
|
||||||
def FORMAT_ANG(self): return('%.1f')
|
|
||||||
def FORMAT_TIME(self): return('%.2f')
|
|
||||||
def FORMAT_DWELL(self): return('P%f')
|
|
||||||
|
|
||||||
def BLOCK(self): return('N%i' + self.SPACE())
|
|
||||||
def COMMENT(self,comment): return( (' (%s)\n' % comment ) )
|
|
||||||
def VARIABLE(self): return( '#%i')
|
|
||||||
def VARIABLE_SET(self): return( '=%.3f')
|
|
||||||
|
|
||||||
def PROGRAM(self): return( 'O%i')
|
|
||||||
def PROGRAM_END(self): return( 'M02')
|
|
||||||
|
|
||||||
def SUBPROG_CALL(self): return( 'M98' + self.SPACE() + 'P%i')
|
|
||||||
def SUBPROG_END(self): return( 'M99')
|
|
||||||
|
|
||||||
def STOP_OPTIONAL(self): return('M01')
|
|
||||||
def STOP(self): return('M00')
|
|
||||||
|
|
||||||
def IMPERIAL(self): return(self.SPACE() + 'G20')
|
|
||||||
def METRIC(self): return(self.SPACE() + 'G21' + self.SPACE())
|
|
||||||
def ABSOLUTE(self): return(self.SPACE() + 'G90' + self.SPACE())
|
|
||||||
def INCREMENTAL(self): return(self.SPACE() + 'G91')
|
|
||||||
def SET_TEMPORARY_COORDINATE_SYSTEM(self): return('G92' + self.SPACE())
|
|
||||||
def REMOVE_TEMPORARY_COORDINATE_SYSTEM(self): return('G92.1' + self.SPACE())
|
|
||||||
def POLAR_ON(self): return(self.SPACE() + 'G16')
|
|
||||||
def POLAR_OFF(self): return(self.SPACE() + 'G15')
|
|
||||||
def PLANE_XY(self): return(self.SPACE() + 'G17')
|
|
||||||
def PLANE_XZ(self): return(self.SPACE() + 'G18')
|
|
||||||
def PLANE_YZ(self): return(self.SPACE() + 'G19')
|
|
||||||
|
|
||||||
def TOOL(self): return(self.SPACE() +'T%i')
|
|
||||||
def TOOL_DEFINITION(self): return('G10' + self.SPACE() + 'L1' + self.SPACE())
|
|
||||||
|
|
||||||
def WORKPLANE(self): return('G%i')
|
|
||||||
def WORKPLANE_BASE(self): return(53)
|
|
||||||
|
|
||||||
def FEEDRATE(self): return((self.SPACE() + ' F'))
|
|
||||||
def SPINDLE(self, format, speed): return(self.SPACE() + 'S' + (format % speed))
|
|
||||||
def SPINDLE_CW(self): return(self.SPACE() + 'M03')
|
|
||||||
def SPINDLE_CCW(self): return(self.SPACE() + 'M04')
|
|
||||||
def COOLANT_OFF(self): return(self.SPACE() + 'M09')
|
|
||||||
def COOLANT_MIST(self): return(self.SPACE() + 'M07')
|
|
||||||
def COOLANT_FLOOD(self): return(self.SPACE() + 'M08')
|
|
||||||
def GEAR_OFF(self): return(self.SPACE() + '?')
|
|
||||||
def GEAR(self): return('M%i')
|
|
||||||
def GEAR_BASE(self): return(37)
|
|
||||||
|
|
||||||
def RAPID(self): return('G0')
|
|
||||||
def FEED(self): return('G1')
|
|
||||||
def ARC_CW(self): return('G2')
|
|
||||||
def ARC_CCW(self): return('G3')
|
|
||||||
def DWELL(self): return('G04')
|
|
||||||
def DRILL(self): return(self.SPACE() + 'G81')
|
|
||||||
def DRILL_WITH_DWELL(self, format, dwell): return(self.SPACE() + 'G82' + (format % dwell))
|
|
||||||
def PECK_DRILL(self): return(self.SPACE() + 'G83')
|
|
||||||
def PECK_DEPTH(self, format, depth): return(self.SPACE() + 'Q' + (format % depth))
|
|
||||||
def RETRACT(self, format, height): return(self.SPACE() + 'R' + (format % height))
|
|
||||||
def END_CANNED_CYCLE(self): return(self.SPACE() + 'G80')
|
|
||||||
|
|
||||||
def X(self): return(self.SPACE() + 'X')
|
|
||||||
def Y(self): return(self.SPACE() + 'Y')
|
|
||||||
def Z(self): return(self.SPACE() + 'Z')
|
|
||||||
def A(self): return(self.SPACE() + 'A')
|
|
||||||
def B(self): return(self.SPACE() + 'B')
|
|
||||||
def C(self): return(self.SPACE() + 'C')
|
|
||||||
def CENTRE_X(self): return(self.SPACE() + 'I')
|
|
||||||
def CENTRE_Y(self): return(self.SPACE() + 'J')
|
|
||||||
def CENTRE_Z(self): return(self.SPACE() + 'K')
|
|
||||||
def RADIUS(self): return(self.SPACE() + 'R')
|
|
||||||
def TIME(self): return(self.SPACE() + 'P')
|
|
||||||
|
|
||||||
def PROBE_TOWARDS_WITH_SIGNAL(self): return('G38.2' + self.SPACE())
|
|
||||||
def PROBE_TOWARDS_WITHOUT_SIGNAL(self): return('G38.3' + self.SPACE())
|
|
||||||
def PROBE_AWAY_WITH_SIGNAL(self): return('G38.4' + self.SPACE())
|
|
||||||
def PROBE_AWAY_WITHOUT_SIGNAL(self): return('G38.5' + self.SPACE())
|
|
||||||
|
|
||||||
def MACHINE_COORDINATES(self): return('G53' + self.SPACE())
|
|
||||||
|
|
||||||
def EXTRUDER_ON (self): return('M101') #deprecated
|
|
||||||
def EXTRUDER_OFF (self): return('M103')
|
|
||||||
def EXTRUDER_TEMP (self, degree_celsius): return('M104 S' + '%s' % degree_celsius)
|
|
||||||
def EXTRUDER_TEMP_WAIT (self, degree_celsius): return('M109 S' + '%s' % degree_celsius)
|
|
||||||
def READ_EXTRUDER_TEMP (self): return('M105')
|
|
||||||
def EXTRUDER_SPEED_PWM (self, speed_in_PWM): return('M108 S' + '%s' % speed_in_PWM) #deprecated
|
|
||||||
def EXTRUDER_SPEED_RPM (self, speed_in_RPM): return('M108 P' + '%s' % speed_in_RPM) #deprecated
|
|
||||||
|
|
||||||
def STEPPERS_OFF(self): return(self.SPACE() + 'M118')
|
|
||||||
|
|
||||||
def ALL_WAIT (self): return(self.SPACE() + 'M116') # Wait for all temperature and slow-changing variables to reach set values
|
|
||||||
|
|
||||||
def FAN_ON (self): return(self.SPACE() + 'M106')
|
|
||||||
def FAN_OFF (self): return(self.SPACE() + 'M107')
|
|
||||||
|
|
||||||
def VALVE_OPEN (self, delay): return(self.SPACE() + ('M126 P' + '%' % delay) )
|
|
||||||
def VALVE_CLOSE (self, delay): return(self.SPACE() + ('M127 P' + '%' % delay) )
|
|
||||||
|
|
||||||
def BUILD_BED_TEMP (self, degree_celsius): return('M140 S' + '%s' % degree_celsius)
|
|
||||||
def BED_HOLDING_PRESSURE (self, pressure): return('M142 S' + '%s' % pressure)
|
|
||||||
|
|
||||||
def CHAMBER_TEMP (self, degree_celsius): return('M141 S' + '%s' % degree_celsius)
|
|
||||||
|
|
||||||
#The following codes are listed on the reprap wiki page at http://reprap.org/wiki/Mendel_User_Manual:_RepRapGCodes but require more study.
|
|
||||||
#
|
|
||||||
#G28 G Y Xnnn Ynnn Znnn Move to origin (on specified axes only, if X/Y/Z parameters are present)
|
|
||||||
#M105 M N none Request current extruder and base temperatures (in Celsius)
|
|
||||||
#M110 M N none Set current line number to Nxxx value preceeding command
|
|
||||||
#M111 M N Snnn Set debug level bitfield to value of parameter (default 6)
|
|
||||||
#M112 M N none Emergency stop (stop immediately, discarding any buffered commands)
|
|
||||||
#M113 M N Snnn Set Extruder PWM (to value defined by pot, or to parameter value if present)
|
|
||||||
#M114 M N none Get Current Position (return current X, Y, Z and E values)
|
|
||||||
#M117 M N none Get Zero Position (return X, Y, Z and E values of endstop hits)
|
|
||||||
|
|
||||||
|
|
||||||
codes = Codes()
|
|
|
@ -1,53 +0,0 @@
|
||||||
################################################################################
|
|
||||||
# printbot3d.py
|
|
||||||
#
|
|
||||||
# Dan Heeks 18th October 2010
|
|
||||||
|
|
||||||
import nc
|
|
||||||
import iso_modal
|
|
||||||
import math
|
|
||||||
|
|
||||||
################################################################################
|
|
||||||
class CreatorPrintbot(iso_modal.CreatorIsoModal):
|
|
||||||
|
|
||||||
def __init__(self):
|
|
||||||
iso_modal.CreatorIsoModal.__init__(self)
|
|
||||||
|
|
||||||
def tool_defn(self, id, name='', params=None):
|
|
||||||
pass
|
|
||||||
|
|
||||||
def write_blocknum(self):
|
|
||||||
pass
|
|
||||||
|
|
||||||
def set_plane(self, plane):
|
|
||||||
pass
|
|
||||||
|
|
||||||
def workplane(self, id):
|
|
||||||
pass
|
|
||||||
|
|
||||||
# Extruder Control
|
|
||||||
|
|
||||||
def extruder_on(self):
|
|
||||||
self.write('M101\n')
|
|
||||||
|
|
||||||
def extruder_off(self):
|
|
||||||
self.write('M103\n')
|
|
||||||
|
|
||||||
def set_extruder_flowrate(self, flowrate):
|
|
||||||
# re-use the spindle speed function
|
|
||||||
self.spindle(flowrate, True)
|
|
||||||
|
|
||||||
def extruder_temp(self, temp):
|
|
||||||
self.write((maker.codes.EXTRUDER_TEMP(temp)) + ('\n'))
|
|
||||||
|
|
||||||
# General
|
|
||||||
def rapid(x=None, y=None, z=None, a=None, b=None, c=None):
|
|
||||||
# do a G1 even for rapid moves
|
|
||||||
iso_modal.CreatorIsoModal.feed(self, x, y, z)
|
|
||||||
|
|
||||||
def feed(self, x=None, y=None, z=None, a = None, b = None, c = None):
|
|
||||||
iso_modal.CreatorIsoModal.feed(self, x, y, z)
|
|
||||||
|
|
||||||
################################################################################
|
|
||||||
|
|
||||||
nc.creator = CreatorPrintbot()
|
|
|
@ -1,17 +0,0 @@
|
||||||
import iso_read as iso
|
|
||||||
import sys
|
|
||||||
|
|
||||||
# based on the iso reader
|
|
||||||
|
|
||||||
class Parser(iso.Parser):
|
|
||||||
def __init__(self, writer):
|
|
||||||
iso.Parser.__init__(self, writer)
|
|
||||||
|
|
||||||
def ParseWord(self, word):
|
|
||||||
iso.Parser.ParseWord(self, word)
|
|
||||||
if (word == 'M103'):
|
|
||||||
self.path_col = "rapid"
|
|
||||||
self.col = "rapid"
|
|
||||||
elif (word == 'M101'):
|
|
||||||
self.path_col = "feed"
|
|
||||||
self.col = "feed"
|
|
|
@ -1,242 +0,0 @@
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
|
|
||||||
# ***************************************************************************
|
|
||||||
# * *
|
|
||||||
# * Copyright (c) 2014 sliptonic <shopinthewoods@gmail.com> *
|
|
||||||
# * *
|
|
||||||
# * This program is free software; you can redistribute it and/or modify *
|
|
||||||
# * it under the terms of the GNU Lesser General Public License (LGPL) *
|
|
||||||
# * as published by the Free Software Foundation; either version 2 of *
|
|
||||||
# * the License, or (at your option) any later version. *
|
|
||||||
# * for detail see the LICENCE text file. *
|
|
||||||
# * *
|
|
||||||
# * This program 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 program; if not, write to the Free Software *
|
|
||||||
# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
|
|
||||||
# * USA *
|
|
||||||
# * *
|
|
||||||
# ***************************************************************************
|
|
||||||
|
|
||||||
import FreeCAD
|
|
||||||
import xml.sax
|
|
||||||
import FreeCADGui
|
|
||||||
import Path
|
|
||||||
import Draft
|
|
||||||
import Part
|
|
||||||
import os
|
|
||||||
|
|
||||||
from PySide import QtCore, QtGui
|
|
||||||
|
|
||||||
try:
|
|
||||||
_encoding = QtGui.QApplication.UnicodeUTF8
|
|
||||||
|
|
||||||
def _translate(context, text, disambig):
|
|
||||||
return QtGui.QApplication.translate(context, text, disambig, _encoding)
|
|
||||||
except AttributeError:
|
|
||||||
def _translate(context, text, disambig):
|
|
||||||
return QtGui.QApplication.translate(context, text, disambig)
|
|
||||||
|
|
||||||
|
|
||||||
# Tooltable XML readers
|
|
||||||
|
|
||||||
class FreeCADTooltableHandler(xml.sax.ContentHandler):
|
|
||||||
# http://www.tutorialspoint.com/python/python_xml_processing.htm
|
|
||||||
|
|
||||||
def __init__(self):
|
|
||||||
self.tooltable = None
|
|
||||||
self.tool = None
|
|
||||||
self.number = None
|
|
||||||
|
|
||||||
# Call when an element is found
|
|
||||||
def startElement(self, tag, attributes):
|
|
||||||
if tag == "Tooltable":
|
|
||||||
self.tooltable = Path.Tooltable()
|
|
||||||
elif tag == "Toolslot":
|
|
||||||
self.number = int(attributes["number"])
|
|
||||||
elif tag == "Tool":
|
|
||||||
self.tool = Path.Tool()
|
|
||||||
self.tool.Name = str(attributes["name"])
|
|
||||||
self.tool.ToolType = str(attributes["type"])
|
|
||||||
self.tool.Material = str(attributes["mat"])
|
|
||||||
# for some reason without the following line I get an error
|
|
||||||
print attributes["diameter"]
|
|
||||||
self.tool.Diameter = float(attributes["diameter"])
|
|
||||||
self.tool.LengthOffset = float(attributes["length"])
|
|
||||||
self.tool.FlatRadius = float(attributes["flat"])
|
|
||||||
self.tool.CornerRadius = float(attributes["corner"])
|
|
||||||
self.tool.CuttingEdgeAngle = float(attributes["angle"])
|
|
||||||
self.tool.CuttingEdgeHeight = float(attributes["height"])
|
|
||||||
|
|
||||||
# Call when an elements ends
|
|
||||||
def endElement(self, tag):
|
|
||||||
if tag == "Toolslot":
|
|
||||||
if self.tooltable and self.tool and self.number:
|
|
||||||
self.tooltable.setTool(self.number, self.tool)
|
|
||||||
self.number = None
|
|
||||||
self.tool = None
|
|
||||||
|
|
||||||
|
|
||||||
class HeeksTooltableHandler(xml.sax.ContentHandler):
|
|
||||||
|
|
||||||
def __init__(self):
|
|
||||||
self.tooltable = Path.Tooltable()
|
|
||||||
self.tool = None
|
|
||||||
self.number = None
|
|
||||||
|
|
||||||
# Call when an element is found
|
|
||||||
def startElement(self, tag, attributes):
|
|
||||||
if tag == "Tool":
|
|
||||||
self.tool = Path.Tool()
|
|
||||||
self.number = int(attributes["tool_number"])
|
|
||||||
self.tool.Name = str(attributes["title"])
|
|
||||||
elif tag == "params":
|
|
||||||
t = str(attributes["type"])
|
|
||||||
if t == "drill":
|
|
||||||
self.tool.ToolType = "Drill"
|
|
||||||
elif t == "center_drill_bit":
|
|
||||||
self.tool.ToolType = "CenterDrill"
|
|
||||||
elif t == "end_mill":
|
|
||||||
self.tool.ToolType = "EndMill"
|
|
||||||
elif t == "slot_cutter":
|
|
||||||
self.tool.ToolType = "SlotCutter"
|
|
||||||
elif t == "ball_end_mill":
|
|
||||||
self.tool.ToolType = "BallEndMill"
|
|
||||||
elif t == "chamfer":
|
|
||||||
self.tool.ToolType = "Chamfer"
|
|
||||||
elif t == "engraving_bit":
|
|
||||||
self.tool.ToolType = "Engraver"
|
|
||||||
m = str(attributes["material"])
|
|
||||||
if m == "0":
|
|
||||||
self.tool.Material = "HighSpeedSteel"
|
|
||||||
elif m == "1":
|
|
||||||
self.tool.Material = "Carbide"
|
|
||||||
# for some reason without the following line I get an error
|
|
||||||
print attributes["diameter"]
|
|
||||||
self.tool.Diameter = float(attributes["diameter"])
|
|
||||||
self.tool.LengthOffset = float(attributes["tool_length_offset"])
|
|
||||||
self.tool.FlatRadius = float(attributes["flat_radius"])
|
|
||||||
self.tool.CornerRadius = float(attributes["corner_radius"])
|
|
||||||
self.tool.CuttingEdgeAngle = float(
|
|
||||||
attributes["cutting_edge_angle"])
|
|
||||||
self.tool.CuttingEdgeHeight = float(
|
|
||||||
attributes["cutting_edge_height"])
|
|
||||||
|
|
||||||
# Call when an elements ends
|
|
||||||
def endElement(self, tag):
|
|
||||||
if tag == "Tool":
|
|
||||||
if self.tooltable and self.tool and self.number:
|
|
||||||
self.tooltable.setTool(self.number, self.tool)
|
|
||||||
self.number = None
|
|
||||||
self.tool = None
|
|
||||||
|
|
||||||
|
|
||||||
class ToolLibraryManager():
|
|
||||||
'''
|
|
||||||
The Tool Library is a list of individual tool tables. Each
|
|
||||||
Tool Table can contain n tools. The tool library will be persisted to user
|
|
||||||
preferences and all or part of the library can be exported to other formats
|
|
||||||
'''
|
|
||||||
|
|
||||||
def __init__(self):
|
|
||||||
self.ToolLibrary = []
|
|
||||||
self.prefs = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Path/ToolLibrary")
|
|
||||||
return
|
|
||||||
|
|
||||||
def saveLibrary(self):
|
|
||||||
'''Persists the entire library to FreeCAD user preferences'''
|
|
||||||
tmpstring = ""
|
|
||||||
for table in self.ToolLibrary:
|
|
||||||
if table["listtype"] == 'User':
|
|
||||||
tmpstring += table["list"].Content
|
|
||||||
self.prefs.SetString("ToolLibrary", tmpstring)
|
|
||||||
|
|
||||||
# FreeCAD.ConfigSet("PathToolTable:" + table[0], table[2].Content)
|
|
||||||
|
|
||||||
def loadLibrary(self):
|
|
||||||
'''Loads the current library from FreeCAD user preferences'''
|
|
||||||
# Get persisted libraries from user prefs
|
|
||||||
tmpstring = self.prefs.GetString("ToolLibrary", "")
|
|
||||||
ToolLibrary = []
|
|
||||||
if tmpstring != "":
|
|
||||||
Handler = FreeCADTooltableHandler()
|
|
||||||
try:
|
|
||||||
xml.sax.parseString(tmpstring, Handler)
|
|
||||||
tt = Handler.tooltable
|
|
||||||
toollist = {'name': "main", 'listtype': "User", 'list': tt}
|
|
||||||
ToolLibrary.append(toollist)
|
|
||||||
except:
|
|
||||||
FreeCAD.Console.PrintError(
|
|
||||||
"Unable to import tools from user preferences")
|
|
||||||
|
|
||||||
# Get ToolTables from any open CNC jobs
|
|
||||||
for o in FreeCAD.ActiveDocument.Objects:
|
|
||||||
if "Proxy" in o.PropertiesList:
|
|
||||||
if hasattr(o, "Tooltable"):
|
|
||||||
toollist = {'name': o.Name,
|
|
||||||
'listtype': "Job", 'list': o.Tooltable}
|
|
||||||
ToolLibrary.append(toollist)
|
|
||||||
self.ToolLibrary = ToolLibrary
|
|
||||||
return self.ToolLibrary
|
|
||||||
|
|
||||||
# methods for lists
|
|
||||||
def addList(self, tablename, listtype="User", TL=None):
|
|
||||||
'''Add a new tooltable to the user library'''
|
|
||||||
if TL is None:
|
|
||||||
TL = Path.Tooltable()
|
|
||||||
toollist = {'name': tablename, 'listtype': listtype, 'list': TL}
|
|
||||||
self.ToolLibrary.append(toollist)
|
|
||||||
return TL
|
|
||||||
|
|
||||||
def deleteList(self, tablename):
|
|
||||||
'''Delete all lists from the user library with the given listname'''
|
|
||||||
for l in self.ToolLibrary:
|
|
||||||
if l['name'] == tablename:
|
|
||||||
# maybe check if tools exist in list
|
|
||||||
self.ToolLibrary.remove(l)
|
|
||||||
return
|
|
||||||
|
|
||||||
def findList(self, tablename):
|
|
||||||
'''Finds and returns list by name'''
|
|
||||||
returnlist = []
|
|
||||||
for l in self.ToolLibrary:
|
|
||||||
if l['name'] == tablename:
|
|
||||||
returnlist.append(l)
|
|
||||||
return returnlist
|
|
||||||
|
|
||||||
# methods for importing and exporting
|
|
||||||
def read(self):
|
|
||||||
"imports a tooltable from a file"
|
|
||||||
filename = QtGui.QFileDialog.getOpenFileName(None, _translate("ToolLibraryManager", "Import tooltable", None), None, _translate(
|
|
||||||
"ToolLibraryManager", "Tooltable XML (*.xml);;HeeksCAD tooltable (*.tooltable)", None))
|
|
||||||
if filename:
|
|
||||||
parser = xml.sax.make_parser()
|
|
||||||
parser.setFeature(xml.sax.handler.feature_namespaces, 0)
|
|
||||||
if os.path.splitext(filename[0])[1].lower() == ".tooltable":
|
|
||||||
Handler = HeeksTooltableHandler()
|
|
||||||
else:
|
|
||||||
Handler = FreeCADTooltableHandler()
|
|
||||||
parser.setContentHandler(Handler)
|
|
||||||
parser.parse(str(filename[0]))
|
|
||||||
if Handler.tooltable:
|
|
||||||
self.addList(filename[0], Handler.tooltable)
|
|
||||||
# self.reset()
|
|
||||||
|
|
||||||
def createToolController(self, job, tool):
|
|
||||||
pass
|
|
||||||
|
|
||||||
def exportListHeeks(self, tooltable):
|
|
||||||
'''exports one or more Lists as a HeeksCNC tooltable'''
|
|
||||||
pass
|
|
||||||
|
|
||||||
def exportListLinuxCNC(self, tooltable):
|
|
||||||
'''exports one or more Lists as a LinuxCNC tooltable'''
|
|
||||||
pass
|
|
||||||
|
|
||||||
def exportListXML(self, tooltable):
|
|
||||||
'''exports one or more Lists as an XML file'''
|
|
||||||
pass
|
|
Loading…
Reference in New Issue
Block a user