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 PathEngrave
|
||||
from PathScripts import PathSurface
|
||||
from PathScripts import PathRemote
|
||||
from PathScripts import PathSanity
|
||||
from PathScripts import DragknifeDressup
|
||||
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)
|
||||
|
||||
|
||||
class OldHighlighter(QtGui.QSyntaxHighlighter):
|
||||
# class OldHighlighter(QtGui.QSyntaxHighlighter):
|
||||
|
||||
def highlightBlock(self, text):
|
||||
# def highlightBlock(self, text):
|
||||
|
||||
myClassFormat = QtGui.QTextCharFormat()
|
||||
myClassFormat.setFontWeight(QtGui.QFont.Bold)
|
||||
myClassFormat.setForeground(QtCore.Qt.green)
|
||||
# the regex pattern to be colored
|
||||
pattern = "(G.*?|M.*?)\\s"
|
||||
expression = QtCore.QRegExp(pattern)
|
||||
index = text.index(expression)
|
||||
while index >= 0:
|
||||
length = expression.matchedLength()
|
||||
setFormat(index, length, myClassFormat)
|
||||
index = text.index(expression, index + length)
|
||||
# myClassFormat = QtGui.QTextCharFormat()
|
||||
# myClassFormat.setFontWeight(QtGui.QFont.Bold)
|
||||
# myClassFormat.setForeground(QtCore.Qt.green)
|
||||
# # the regex pattern to be colored
|
||||
# pattern = "(G.*?|M.*?)\\s"
|
||||
# expression = QtCore.QRegExp(pattern)
|
||||
# index = text.index(expression)
|
||||
# while index >= 0:
|
||||
# length = expression.matchedLength()
|
||||
# setFormat(index, length, myClassFormat)
|
||||
# index = text.index(expression, index + length)
|
||||
|
||||
|
||||
class GCodeHighlighter(QtGui.QSyntaxHighlighter):
|
||||
|
|
|
@ -28,8 +28,6 @@ from PySide import QtCore, QtGui
|
|||
from PathScripts.PathPostProcessor import PostProcessor
|
||||
from PathScripts.PathPreferences import PathPreferences
|
||||
import Draft
|
||||
import os
|
||||
import glob
|
||||
|
||||
|
||||
FreeCADGui = None
|
||||
|
|
|
@ -22,16 +22,9 @@
|
|||
# * *
|
||||
# ***************************************************************************
|
||||
'''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 DraftGeomUtils
|
||||
import DraftVecUtils
|
||||
from DraftGeomUtils import geomType
|
||||
import math
|
||||
import area
|
||||
import Path
|
||||
from PathScripts import PathUtils
|
||||
from nc.nc import *
|
||||
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)
|
||||
if layer_count * stepdown + 0.00001 < start_depth - final_depth:
|
||||
layer_count += 1
|
||||
current_start_depth = start_depth
|
||||
# current_start_depth = start_depth
|
||||
prev_depth = start_depth
|
||||
for i in range(1, layer_count + 1):
|
||||
if i == layer_count:
|
||||
|
@ -388,7 +381,7 @@ def profile2(curve, direction="on", radius=1.0, vertfeed=0.0,
|
|||
# do multiple depths
|
||||
depths = depthparams.get_depths()
|
||||
|
||||
current_start_depth = depthparams.start_depth
|
||||
# current_start_depth = depthparams.start_depth
|
||||
|
||||
# tags
|
||||
if len(tags) > 0:
|
||||
|
@ -532,7 +525,7 @@ class Tag:
|
|||
|
||||
height_above_depth = tag_top_depth - depth
|
||||
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
|
||||
|
||||
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):
|
||||
# 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
|
||||
cut_depth = start_depth - depth
|
||||
# cut_depth = start_depth - depth
|
||||
half_flat_top = radius + self.width / 2
|
||||
|
||||
z = depth
|
||||
|
|
|
@ -224,7 +224,7 @@ class ObjectFace:
|
|||
self.vertFeed = 100
|
||||
self.horizFeed = 100
|
||||
self.vertRapid = 100
|
||||
self.horiRrapid = 100
|
||||
self.horizRrapid = 100
|
||||
self.radius = 0.25
|
||||
obj.ToolNumber = 0
|
||||
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 FreeCADGui
|
||||
from FreeCAD import Vector
|
||||
#from FreeCAD import Vector
|
||||
|
||||
|
||||
def equals(p1, p2):
|
||||
'''returns True if vertexes have same coordinates within precision amount of digits '''
|
||||
precision = 12
|
||||
p = precision
|
||||
u = Vector(p1.X, p1.Y, p1.Z)
|
||||
v = Vector(p2.X, p2.Y, p2.Z)
|
||||
vector = (u.sub(v))
|
||||
isNull = (round(vector.x, p) == 0 and round(vector.y, p) == 0 and round(vector.z, p) == 0)
|
||||
return isNull
|
||||
# def equals(p1, p2):
|
||||
# '''returns True if vertexes have same coordinates within precision amount of digits '''
|
||||
# precision = 12
|
||||
# p = precision
|
||||
# u = Vector(p1.X, p1.Y, p1.Z)
|
||||
# v = Vector(p2.X, p2.Y, p2.Z)
|
||||
# vector = (u.sub(v))
|
||||
# isNull = (round(vector.x, p) == 0 and round(vector.y, p) == 0 and round(vector.z, p) == 0)
|
||||
# return isNull
|
||||
|
||||
|
||||
def segments(poly):
|
||||
''' A sequence of (x,y) numeric coordinates pairs '''
|
||||
return zip(poly, poly[1:] + [poly[0]])
|
||||
# def segments(poly):
|
||||
# ''' A sequence of (x,y) numeric coordinates pairs '''
|
||||
# return zip(poly, poly[1:] + [poly[0]])
|
||||
|
||||
|
||||
def check_clockwise(poly):
|
||||
'''
|
||||
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)]
|
||||
'''
|
||||
clockwise = False
|
||||
if (sum(x0*y1 - x1*y0 for ((x0, y0), (x1, y1)) in segments(poly))) < 0:
|
||||
clockwise = not clockwise
|
||||
return clockwise
|
||||
# def check_clockwise(poly):
|
||||
# '''
|
||||
# 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)]
|
||||
# '''
|
||||
# clockwise = False
|
||||
# if (sum(x0*y1 - x1*y0 for ((x0, y0), (x1, y1)) in segments(poly))) < 0:
|
||||
# clockwise = not clockwise
|
||||
# return clockwise
|
||||
|
||||
|
||||
class FGate:
|
||||
def allow(self, doc, obj, sub):
|
||||
return (sub[0:4] == 'Face')
|
||||
# class FGate:
|
||||
# def allow(self, doc, obj, sub):
|
||||
# return (sub[0:4] == 'Face')
|
||||
|
||||
|
||||
class VGate:
|
||||
def allow(self, doc, obj, sub):
|
||||
return (sub[0:6] == 'Vertex')
|
||||
# class VGate:
|
||||
# def allow(self, doc, obj, sub):
|
||||
# return (sub[0:6] == 'Vertex')
|
||||
|
||||
|
||||
class EGate:
|
||||
|
@ -182,14 +182,14 @@ def contourselect():
|
|||
FreeCADGui.Selection.addSelectionGate(CONTOURGate())
|
||||
FreeCAD.Console.PrintWarning("Contour Select Mode\n")
|
||||
|
||||
def fselect():
|
||||
FreeCADGui.Selection.addSelectionGate(FGate())
|
||||
FreeCAD.Console.PrintWarning("Face Select Mode\n")
|
||||
# def fselect():
|
||||
# FreeCADGui.Selection.addSelectionGate(FGate())
|
||||
# FreeCAD.Console.PrintWarning("Face Select Mode\n")
|
||||
|
||||
|
||||
def vselect():
|
||||
FreeCADGui.Selection.addSelectionGate(VGate())
|
||||
FreeCAD.Console.PrintWarning("Vertex Select Mode\n")
|
||||
# def vselect():
|
||||
# FreeCADGui.Selection.addSelectionGate(VGate())
|
||||
# FreeCAD.Console.PrintWarning("Vertex Select Mode\n")
|
||||
|
||||
|
||||
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):
|
||||
self.ToolLibrary = []
|
||||
# self.ToolLibrary = []
|
||||
self.prefs = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Path")
|
||||
return
|
||||
|
||||
|
@ -311,20 +311,20 @@ class ToolLibraryManager():
|
|||
self.saveMainLibrary(tt)
|
||||
return True
|
||||
|
||||
def createToolController(self, job, tool):
|
||||
pass
|
||||
# def createToolController(self, job, tool):
|
||||
# pass
|
||||
|
||||
def exportListHeeks(self, tooltable):
|
||||
'''exports one or more Lists as a HeeksCNC tooltable'''
|
||||
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 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
|
||||
# def exportListXML(self, tooltable):
|
||||
# '''exports one or more Lists as an XML file'''
|
||||
# pass
|
||||
|
||||
class EditorPanel():
|
||||
def __init__(self):
|
||||
|
|
|
@ -26,15 +26,13 @@ import FreeCAD
|
|||
import FreeCADGui
|
||||
import Part
|
||||
import math
|
||||
import Draft
|
||||
import Path
|
||||
import TechDraw
|
||||
# import Path
|
||||
from DraftGeomUtils import geomType
|
||||
from DraftGeomUtils import findWires
|
||||
import DraftVecUtils
|
||||
# from DraftGeomUtils import findWires
|
||||
# import DraftVecUtils
|
||||
import PathScripts
|
||||
from PathScripts import PathJob
|
||||
import itertools
|
||||
# import itertools
|
||||
|
||||
def cleanedges(splines, precision):
|
||||
'''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 getProjected(shape,direction):
|
||||
"returns projected edges from a shape and a direction"
|
||||
import Part,Drawing
|
||||
edges = []
|
||||
groups = Drawing.projectEx(shape,direction)
|
||||
for g in groups[0:5]:
|
||||
if g:
|
||||
edges.append(g)
|
||||
# if hasattr(obj,"Tessellation") and obj.Tessellation:
|
||||
# return DraftGeomUtils.cleanProjection(Part.makeCompound(edges),obj.Tessellation,obj.SegmentLength)
|
||||
# else:
|
||||
return Part.makeCompound(edges)
|
||||
# def getProjected(shape,direction):
|
||||
# "returns projected edges from a shape and a direction"
|
||||
# import Part,Drawing
|
||||
# edges = []
|
||||
# groups = Drawing.projectEx(shape,direction)
|
||||
# for g in groups[0:5]:
|
||||
# if g:
|
||||
# edges.append(g)
|
||||
# # if hasattr(obj,"Tessellation") and obj.Tessellation:
|
||||
# # return DraftGeomUtils.cleanProjection(Part.makeCompound(edges),obj.Tessellation,obj.SegmentLength)
|
||||
# # else:
|
||||
# return Part.makeCompound(edges)
|
||||
|
||||
|
||||
def silhouette(obj):
|
||||
from FreeCAD import Vector
|
||||
s = getProjected(obj.Shape, Vector(0,0,1))
|
||||
print s
|
||||
w = TechDraw.findOuterWire(s.Edges)
|
||||
return w
|
||||
# def silhouette(obj):
|
||||
# from FreeCAD import Vector
|
||||
# s = getProjected(obj.Shape, Vector(0,0,1))
|
||||
# print s
|
||||
# w = TechDraw.findOuterWire(s.Edges)
|
||||
# return w
|
||||
|
||||
def isSameEdge(e1, e2):
|
||||
"""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"""
|
||||
if not (isinstance(e1.Curve, Part.LineSegment) or isinstance(e1.Curve, Part.Circle)):
|
||||
return False
|
||||
if not (isinstance(e2.Curve, Part.LineSegment) or isinstance(e2.Curve, Part.Circle)):
|
||||
return False
|
||||
if type(e1.Curve) != type(e2.Curve):
|
||||
return False
|
||||
if isinstance(e1.Curve, Part.LineSegment):
|
||||
if (DraftVecUtils.equals(e1.Vertexes[0].Point, e2.Vertexes[0].Point)) and \
|
||||
(DraftVecUtils.equals(e1.Vertexes[-1].Point, e2.Vertexes[-1].Point)):
|
||||
return True
|
||||
elif (DraftVecUtils.equals(e1.Vertexes[-1].Point, e2.Vertexes[0].Point)) and \
|
||||
(DraftVecUtils.equals(e1.Vertexes[0].Point, e2.Vertexes[-1].Point)):
|
||||
return True
|
||||
if isinstance(e1.Curve, Part.Circle):
|
||||
center = False
|
||||
radius = False
|
||||
endpts = False
|
||||
if e1.Curve.Center == e2.Curve.Center:
|
||||
center = True
|
||||
if e1.Curve.Radius == e2.Curve.Radius:
|
||||
radius = True
|
||||
if (DraftVecUtils.equals(e1.Vertexes[0].Point, e2.Vertexes[0].Point)) and \
|
||||
(DraftVecUtils.equals(e1.Vertexes[-1].Point, e2.Vertexes[-1].Point)):
|
||||
endpts = True
|
||||
elif (DraftVecUtils.equals(e1.Vertexes[-1].Point, e2.Vertexes[0].Point)) and \
|
||||
(DraftVecUtils.equals(e1.Vertexes[0].Point, e2.Vertexes[-1].Point)):
|
||||
endpts = True
|
||||
if (center and radius and endpts):
|
||||
return True
|
||||
return False
|
||||
# def isSameEdge(e1, e2):
|
||||
# """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"""
|
||||
# if not (isinstance(e1.Curve, Part.Line) or isinstance(e1.Curve, Part.Circle)):
|
||||
# return False
|
||||
# if not (isinstance(e2.Curve, Part.Line) or isinstance(e2.Curve, Part.Circle)):
|
||||
# return False
|
||||
# if type(e1.Curve) != type(e2.Curve):
|
||||
# return False
|
||||
# if isinstance(e1.Curve, Part.Line):
|
||||
# if (DraftVecUtils.equals(e1.Vertexes[0].Point, e2.Vertexes[0].Point)) and \
|
||||
# (DraftVecUtils.equals(e1.Vertexes[-1].Point, e2.Vertexes[-1].Point)):
|
||||
# return True
|
||||
# elif (DraftVecUtils.equals(e1.Vertexes[-1].Point, e2.Vertexes[0].Point)) and \
|
||||
# (DraftVecUtils.equals(e1.Vertexes[0].Point, e2.Vertexes[-1].Point)):
|
||||
# return True
|
||||
# if isinstance(e1.Curve, Part.Circle):
|
||||
# center = False
|
||||
# radius = False
|
||||
# endpts = False
|
||||
# if e1.Curve.Center == e2.Curve.Center:
|
||||
# center = True
|
||||
# if e1.Curve.Radius == e2.Curve.Radius:
|
||||
# radius = True
|
||||
# if (DraftVecUtils.equals(e1.Vertexes[0].Point, e2.Vertexes[0].Point)) and \
|
||||
# (DraftVecUtils.equals(e1.Vertexes[-1].Point, e2.Vertexes[-1].Point)):
|
||||
# endpts = True
|
||||
# elif (DraftVecUtils.equals(e1.Vertexes[-1].Point, e2.Vertexes[0].Point)) and \
|
||||
# (DraftVecUtils.equals(e1.Vertexes[0].Point, e2.Vertexes[-1].Point)):
|
||||
# endpts = True
|
||||
# if (center and radius and endpts):
|
||||
# return True
|
||||
# return False
|
||||
|
||||
|
||||
def segments(poly):
|
||||
''' A sequence of (x,y) numeric coordinates pairs '''
|
||||
return zip(poly, poly[1:] + [poly[0]])
|
||||
|
||||
def is_clockwise(obj):
|
||||
'''tests if a wire or Path is clockwise'''
|
||||
sum = 0
|
||||
if isinstance(obj, Part.Wire):
|
||||
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 += (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):
|
||||
movecommands = ['G1', 'G01', 'G2', 'G02', 'G3', 'G03']
|
||||
# def is_clockwise(obj):
|
||||
# '''tests if a wire or Path is clockwise'''
|
||||
# sum = 0
|
||||
# if isinstance(obj, Part.Wire):
|
||||
# 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 += (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):
|
||||
# movecommands = ['G1', 'G01', 'G2', 'G02', 'G3', 'G03']
|
||||
|
||||
lastLocation = {'Y': 0, 'X': 0, 'Z': 0.0}
|
||||
currLocation = {'Y': 0, 'X': 0, 'Z': 0.0}
|
||||
sum = 0
|
||||
# lastLocation = {'Y': 0, 'X': 0, 'Z': 0.0}
|
||||
# currLocation = {'Y': 0, 'X': 0, 'Z': 0.0}
|
||||
# sum = 0
|
||||
|
||||
for curCommand in obj.Commands:
|
||||
# for curCommand in obj.Commands:
|
||||
|
||||
if curCommand.Name in movecommands:
|
||||
lastLocation.update(currLocation)
|
||||
currLocation.update(curCommand.Parameters)
|
||||
sum += (currLocation["X"] - lastLocation["X"]) * (currLocation["Y"] + lastLocation["Y"])
|
||||
sum += (0 - lastLocation["X"]) * (0 + lastLocation["Y"])
|
||||
# if curCommand.Name in movecommands:
|
||||
# lastLocation.update(currLocation)
|
||||
# currLocation.update(curCommand.Parameters)
|
||||
# sum += (currLocation["X"] - lastLocation["X"]) * (currLocation["Y"] + lastLocation["Y"])
|
||||
# sum += (0 - lastLocation["X"]) * (0 + lastLocation["Y"])
|
||||
|
||||
return sum >= 0
|
||||
# return sum >= 0
|
||||
|
||||
def loopdetect(obj, edge1, edge2):
|
||||
'''
|
||||
|
@ -192,15 +190,15 @@ def loopdetect(obj, edge1, edge2):
|
|||
return loopwire
|
||||
|
||||
|
||||
def check_clockwise(poly):
|
||||
'''
|
||||
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)]
|
||||
'''
|
||||
clockwise = False
|
||||
if (sum(x0 * y1 - x1 * y0 for ((x0, y0), (x1, y1)) in segments(poly))) < 0:
|
||||
clockwise = not clockwise
|
||||
return clockwise
|
||||
# def check_clockwise(poly):
|
||||
# '''
|
||||
# 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)]
|
||||
# '''
|
||||
# clockwise = False
|
||||
# if (sum(x0 * y1 - x1 * y0 for ((x0, y0), (x1, y1)) in segments(poly))) < 0:
|
||||
# clockwise = not clockwise
|
||||
# return clockwise
|
||||
|
||||
|
||||
def filterArcs(arcEdge):
|
||||
|
@ -254,235 +252,235 @@ def reverseEdge(e):
|
|||
|
||||
return newedge
|
||||
|
||||
def edge_to_path(lastpt, edge, Z, hf=2.0):
|
||||
if isinstance(edge.Curve, Part.Circle):
|
||||
# FreeCAD.Console.PrintMessage("arc\n")
|
||||
arcstartpt = edge.valueAt(edge.FirstParameter)
|
||||
midpt = edge.valueAt(
|
||||
(edge.FirstParameter + edge.LastParameter) * 0.5)
|
||||
arcendpt = edge.valueAt(edge.LastParameter)
|
||||
# arcchkpt = edge.valueAt(edge.LastParameter * .99)
|
||||
# def edge_to_path(lastpt, edge, Z, hf=2.0):
|
||||
# if isinstance(edge.Curve, Part.Circle):
|
||||
# # FreeCAD.Console.PrintMessage("arc\n")
|
||||
# arcstartpt = edge.valueAt(edge.FirstParameter)
|
||||
# midpt = edge.valueAt(
|
||||
# (edge.FirstParameter + edge.LastParameter) * 0.5)
|
||||
# arcendpt = edge.valueAt(edge.LastParameter)
|
||||
# # arcchkpt = edge.valueAt(edge.LastParameter * .99)
|
||||
|
||||
if DraftVecUtils.equals(lastpt, arcstartpt):
|
||||
startpt = arcstartpt
|
||||
endpt = arcendpt
|
||||
else:
|
||||
startpt = arcendpt
|
||||
endpt = arcstartpt
|
||||
center = edge.Curve.Center
|
||||
relcenter = center.sub(lastpt)
|
||||
# FreeCAD.Console.PrintMessage("arc startpt= " + str(startpt)+ "\n")
|
||||
# FreeCAD.Console.PrintMessage("arc midpt= " + str(midpt)+ "\n")
|
||||
# FreeCAD.Console.PrintMessage("arc endpt= " + str(endpt)+ "\n")
|
||||
arc_cw = check_clockwise(
|
||||
[(startpt.x, startpt.y), (midpt.x, midpt.y), (endpt.x, endpt.y)])
|
||||
# FreeCAD.Console.PrintMessage("arc_cw="+ str(arc_cw)+"\n")
|
||||
if arc_cw:
|
||||
output = "G2"
|
||||
else:
|
||||
output = "G3"
|
||||
output += " X" + str(fmt(endpt.x)) + " Y" + \
|
||||
str(fmt(endpt.y)) + " Z" + str(fmt(Z)) + " F" + str(hf)
|
||||
output += " I" + str(fmt(relcenter.x)) + " J" + \
|
||||
str(fmt(relcenter.y)) + " K" + str(fmt(relcenter.z))
|
||||
output += "\n"
|
||||
lastpt = endpt
|
||||
# FreeCAD.Console.PrintMessage("last pt arc= " + str(lastpt)+ "\n")
|
||||
else:
|
||||
point = edge.Vertexes[-1].Point
|
||||
if DraftVecUtils.equals(point, lastpt): # edges can come flipped
|
||||
point = edge.Vertexes[0].Point
|
||||
output = "G1 X" + str(fmt(point.x)) + " Y" + str(fmt(point.y)) + \
|
||||
" Z" + str(fmt(Z)) + " F" + str(hf) + "\n"
|
||||
lastpt = point
|
||||
# FreeCAD.Console.PrintMessage("line\n")
|
||||
# FreeCAD.Console.PrintMessage("last pt line= " + str(lastpt)+ "\n")
|
||||
return lastpt, output
|
||||
# if DraftVecUtils.equals(lastpt, arcstartpt):
|
||||
# startpt = arcstartpt
|
||||
# endpt = arcendpt
|
||||
# else:
|
||||
# startpt = arcendpt
|
||||
# endpt = arcstartpt
|
||||
# center = edge.Curve.Center
|
||||
# relcenter = center.sub(lastpt)
|
||||
# # FreeCAD.Console.PrintMessage("arc startpt= " + str(startpt)+ "\n")
|
||||
# # FreeCAD.Console.PrintMessage("arc midpt= " + str(midpt)+ "\n")
|
||||
# # FreeCAD.Console.PrintMessage("arc endpt= " + str(endpt)+ "\n")
|
||||
# arc_cw = check_clockwise(
|
||||
# [(startpt.x, startpt.y), (midpt.x, midpt.y), (endpt.x, endpt.y)])
|
||||
# # FreeCAD.Console.PrintMessage("arc_cw="+ str(arc_cw)+"\n")
|
||||
# if arc_cw:
|
||||
# output = "G2"
|
||||
# else:
|
||||
# output = "G3"
|
||||
# output += " X" + str(fmt(endpt.x)) + " Y" + \
|
||||
# str(fmt(endpt.y)) + " Z" + str(fmt(Z)) + " F" + str(hf)
|
||||
# output += " I" + str(fmt(relcenter.x)) + " J" + \
|
||||
# str(fmt(relcenter.y)) + " K" + str(fmt(relcenter.z))
|
||||
# output += "\n"
|
||||
# lastpt = endpt
|
||||
# # FreeCAD.Console.PrintMessage("last pt arc= " + str(lastpt)+ "\n")
|
||||
# else:
|
||||
# point = edge.Vertexes[-1].Point
|
||||
# if DraftVecUtils.equals(point, lastpt): # edges can come flipped
|
||||
# point = edge.Vertexes[0].Point
|
||||
# output = "G1 X" + str(fmt(point.x)) + " Y" + str(fmt(point.y)) + \
|
||||
# " Z" + str(fmt(Z)) + " F" + str(hf) + "\n"
|
||||
# lastpt = point
|
||||
# # FreeCAD.Console.PrintMessage("line\n")
|
||||
# # FreeCAD.Console.PrintMessage("last pt line= " + str(lastpt)+ "\n")
|
||||
# return lastpt, output
|
||||
|
||||
|
||||
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.'''
|
||||
# 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.'''
|
||||
|
||||
if PlungeAngle != 90.0:
|
||||
if Zprevious is None:
|
||||
raise Exception("Cannot use PlungeAngle != 90.0 degrees without parameter Zprevious")
|
||||
tanA = math.tan(math.pi * PlungeAngle / 180.0)
|
||||
minA = (Zprevious - Z) / sum(edge.Length for edge in toolpath)
|
||||
if 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))
|
||||
else:
|
||||
Zprevious = Z
|
||||
# if PlungeAngle != 90.0:
|
||||
# if Zprevious is None:
|
||||
# raise Exception("Cannot use PlungeAngle != 90.0 degrees without parameter Zprevious")
|
||||
# tanA = math.tan(math.pi * PlungeAngle / 180.0)
|
||||
# minA = (Zprevious - Z) / sum(edge.Length for edge in toolpath)
|
||||
# if 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))
|
||||
# else:
|
||||
# Zprevious = Z
|
||||
|
||||
lastpt = None
|
||||
output = ""
|
||||
path_length = 0.0
|
||||
Z_cur = Zprevious
|
||||
# lastpt = None
|
||||
# output = ""
|
||||
# path_length = 0.0
|
||||
# Z_cur = Zprevious
|
||||
|
||||
# create the path from the offset shape
|
||||
for edge in toolpath:
|
||||
if not lastpt:
|
||||
# set the first point
|
||||
lastpt = edge.Vertexes[0].Point
|
||||
# FreeCAD.Console.PrintMessage("last pt= " + str(lastpt)+ "\n")
|
||||
output += "G1 X" + str(fmt(lastpt.x)) + " Y" + str(fmt(lastpt.y)) + \
|
||||
" Z" + str(fmt(Z_cur)) + " F" + str(vf) + "\n"
|
||||
# # create the path from the offset shape
|
||||
# for edge in toolpath:
|
||||
# if not lastpt:
|
||||
# # set the first point
|
||||
# lastpt = edge.Vertexes[0].Point
|
||||
# # FreeCAD.Console.PrintMessage("last pt= " + str(lastpt)+ "\n")
|
||||
# output += "G1 X" + str(fmt(lastpt.x)) + " Y" + str(fmt(lastpt.y)) + \
|
||||
# " Z" + str(fmt(Z_cur)) + " F" + str(vf) + "\n"
|
||||
|
||||
if StopLength:
|
||||
if path_length + edge.Length > StopLength:
|
||||
# have to split current edge in two
|
||||
t0 = edge.FirstParameter
|
||||
t1 = edge.LastParameter
|
||||
dL = StopLength - path_length
|
||||
t = t0 + (t1 - t0) * dL / edge.Length
|
||||
assert(t0 < t < t1)
|
||||
edge = edge.split(t).Edges[0]
|
||||
path_length = StopLength
|
||||
else:
|
||||
path_length += edge.Length
|
||||
else:
|
||||
path_length += edge.Length
|
||||
# if StopLength:
|
||||
# if path_length + edge.Length > StopLength:
|
||||
# # have to split current edge in two
|
||||
# t0 = edge.FirstParameter
|
||||
# t1 = edge.LastParameter
|
||||
# dL = StopLength - path_length
|
||||
# t = t0 + (t1 - t0) * dL / edge.Length
|
||||
# assert(t0 < t < t1)
|
||||
# edge = edge.split(t).Edges[0]
|
||||
# path_length = StopLength
|
||||
# else:
|
||||
# path_length += edge.Length
|
||||
# else:
|
||||
# path_length += edge.Length
|
||||
|
||||
if Z_cur > Z:
|
||||
Z_next = Zprevious - path_length * tanA
|
||||
if Z_next < Z:
|
||||
# have to split current edge in two
|
||||
t0 = edge.FirstParameter
|
||||
t1 = edge.LastParameter
|
||||
dZ = Z_cur - Z
|
||||
t = t0 + (t1 - t0) * (dZ / tanA) / edge.Length
|
||||
assert(t0 < t < t1)
|
||||
subwire = edge.split(t)
|
||||
assert(len(subwire.Edges) == 2)
|
||||
Z_cur = Z
|
||||
lastpt, codes = edge_to_path(lastpt, subwire.Edges[0], Z_cur, hf)
|
||||
output += codes
|
||||
edge = subwire.Edges[1]
|
||||
else:
|
||||
Z_cur = Z_next
|
||||
# if Z_cur > Z:
|
||||
# Z_next = Zprevious - path_length * tanA
|
||||
# if Z_next < Z:
|
||||
# # have to split current edge in two
|
||||
# t0 = edge.FirstParameter
|
||||
# t1 = edge.LastParameter
|
||||
# dZ = Z_cur - Z
|
||||
# t = t0 + (t1 - t0) * (dZ / tanA) / edge.Length
|
||||
# assert(t0 < t < t1)
|
||||
# subwire = edge.split(t)
|
||||
# assert(len(subwire.Edges) == 2)
|
||||
# Z_cur = Z
|
||||
# lastpt, codes = edge_to_path(lastpt, subwire.Edges[0], Z_cur, hf)
|
||||
# output += codes
|
||||
# edge = subwire.Edges[1]
|
||||
# else:
|
||||
# Z_cur = Z_next
|
||||
|
||||
lastpt, codes = edge_to_path(lastpt, edge, Z_cur, hf)
|
||||
output += codes
|
||||
# lastpt, codes = edge_to_path(lastpt, edge, Z_cur, hf)
|
||||
# output += codes
|
||||
|
||||
if StopLength:
|
||||
if path_length >= StopLength:
|
||||
break
|
||||
# if StopLength:
|
||||
# if path_length >= StopLength:
|
||||
# break
|
||||
|
||||
return output
|
||||
# return output
|
||||
|
||||
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. '''
|
||||
if firstedge:
|
||||
edgelist = wire.Edges[:]
|
||||
if wire.isClosed():
|
||||
elindex = None
|
||||
n = 0
|
||||
for e in edgelist:
|
||||
if isSameEdge(e, firstedge):
|
||||
# FreeCAD.Console.PrintMessage('found first edge\n')
|
||||
elindex = n
|
||||
n = n + 1
|
||||
l1 = edgelist[:elindex]
|
||||
l2 = edgelist[elindex:]
|
||||
newedgelist = l2 + l1
|
||||
# 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. '''
|
||||
# if firstedge:
|
||||
# edgelist = wire.Edges[:]
|
||||
# if wire.isClosed():
|
||||
# elindex = None
|
||||
# n = 0
|
||||
# for e in edgelist:
|
||||
# if isSameEdge(e, firstedge):
|
||||
# # FreeCAD.Console.PrintMessage('found first edge\n')
|
||||
# elindex = n
|
||||
# n = n + 1
|
||||
# l1 = edgelist[:elindex]
|
||||
# l2 = edgelist[elindex:]
|
||||
# newedgelist = l2 + l1
|
||||
|
||||
if clockwise:
|
||||
newedgelist.reverse()
|
||||
last = newedgelist.pop(-1)
|
||||
newedgelist.insert(0, last)
|
||||
# if clockwise:
|
||||
# newedgelist.reverse()
|
||||
# last = newedgelist.pop(-1)
|
||||
# newedgelist.insert(0, last)
|
||||
|
||||
preoffset = []
|
||||
for e in newedgelist:
|
||||
if clockwise:
|
||||
r = reverseEdge(e)
|
||||
preoffset.append(r)
|
||||
else:
|
||||
preoffset.append(e)
|
||||
# preoffset = []
|
||||
# for e in newedgelist:
|
||||
# if clockwise:
|
||||
# r = reverseEdge(e)
|
||||
# preoffset.append(r)
|
||||
# else:
|
||||
# preoffset.append(e)
|
||||
|
||||
sortedpreoff = Part.__sortEdges__(preoffset)
|
||||
wire = Part.Wire(sortedpreoff)
|
||||
#wire = findWires(sortedpreoff)[0]
|
||||
else:
|
||||
sortedpreoff = Part.__sortEdges__(edgelist)
|
||||
wire = Part.Wire(sortedpreoff)
|
||||
#wire = findWires(sortedpreoff)[0]
|
||||
# sortedpreoff = Part.__sortEdges__(preoffset)
|
||||
# wire = Part.Wire(sortedpreoff)
|
||||
# #wire = findWires(sortedpreoff)[0]
|
||||
# else:
|
||||
# sortedpreoff = Part.__sortEdges__(edgelist)
|
||||
# wire = Part.Wire(sortedpreoff)
|
||||
# #wire = findWires(sortedpreoff)[0]
|
||||
|
||||
edgelist = []
|
||||
for e in wire.Edges:
|
||||
if geomType(e) == "Circle":
|
||||
arclist = filterArcs(e)
|
||||
for a in arclist:
|
||||
edgelist.append(a)
|
||||
elif geomType(e) == "LineSegment":
|
||||
edgelist.append(e)
|
||||
elif geomType(e) == "BSplineCurve" or \
|
||||
geomType(e) == "BezierCurve" or \
|
||||
geomType(e) == "Ellipse":
|
||||
edgelist.append(Part.Wire(curvetowire(e, (SegLen))))
|
||||
#newwire = Part.Wire(edgelist)
|
||||
sortededges = Part.__sortEdges__(edgelist)
|
||||
newwire = findWires(sortededges)[0]
|
||||
# edgelist = []
|
||||
# for e in wire.Edges:
|
||||
# if geomType(e) == "Circle":
|
||||
# arclist = filterArcs(e)
|
||||
# for a in arclist:
|
||||
# edgelist.append(a)
|
||||
# elif geomType(e) == "LineSegment":
|
||||
# edgelist.append(e)
|
||||
# elif geomType(e) == "BSplineCurve" or \
|
||||
# geomType(e) == "BezierCurve" or \
|
||||
# geomType(e) == "Ellipse":
|
||||
# edgelist.append(Part.Wire(curvetowire(e, (SegLen))))
|
||||
# #newwire = Part.Wire(edgelist)
|
||||
# sortededges = Part.__sortEdges__(edgelist)
|
||||
# newwire = findWires(sortededges)[0]
|
||||
|
||||
if is_clockwise(newwire) is not clockwise:
|
||||
newwire.reverse()
|
||||
# if is_clockwise(newwire) is not clockwise:
|
||||
# newwire.reverse()
|
||||
|
||||
if Side == 'Left':
|
||||
# we use the OCC offset feature
|
||||
offset = newwire.makeOffset(radius) # tool is outside line
|
||||
elif Side == 'Right':
|
||||
offset = newwire.makeOffset(-radius) # tool is inside line
|
||||
else:
|
||||
if wire.isClosed():
|
||||
offset = newwire.makeOffset(0.0)
|
||||
else:
|
||||
offset = newwire
|
||||
offset.reverse()
|
||||
# if Side == 'Left':
|
||||
# # we use the OCC offset feature
|
||||
# offset = newwire.makeOffset(radius) # tool is outside line
|
||||
# elif Side == 'Right':
|
||||
# offset = newwire.makeOffset(-radius) # tool is inside line
|
||||
# else:
|
||||
# if wire.isClosed():
|
||||
# offset = newwire.makeOffset(0.0)
|
||||
# else:
|
||||
# offset = newwire
|
||||
# offset.reverse()
|
||||
|
||||
return offset
|
||||
# return offset
|
||||
|
||||
|
||||
def MakePath(wire, Side, radius, clockwise, ZClearance, StepDown, ZStart,
|
||||
ZFinalDepth, firstedge=None, PathClosed=True, SegLen=0.5,
|
||||
VertFeed=1.0, HorizFeed=2.0, VertJog=1.0, HorizJog = 2.0, PlungeAngle=90.0):
|
||||
''' makes the path - just a simple profile for now '''
|
||||
offset = SortPath(wire, Side, radius, clockwise, firstedge, SegLen=SegLen)
|
||||
if len(offset.Edges) == 0:
|
||||
return ""
|
||||
# def MakePath(wire, Side, radius, clockwise, ZClearance, StepDown, ZStart,
|
||||
# ZFinalDepth, firstedge=None, PathClosed=True, SegLen=0.5,
|
||||
# VertFeed=1.0, HorizFeed=2.0, VertJog=1.0, HorizJog = 2.0, PlungeAngle=90.0):
|
||||
# ''' makes the path - just a simple profile for now '''
|
||||
# offset = SortPath(wire, Side, radius, clockwise, firstedge, SegLen=SegLen)
|
||||
# if len(offset.Edges) == 0:
|
||||
# return ""
|
||||
|
||||
toolpath = offset.Edges[:]
|
||||
paths = ""
|
||||
paths += "G0 Z" + str(ZClearance) + "F " + fmt(VertJog) + "\n"
|
||||
first = toolpath[0].Vertexes[0].Point
|
||||
paths += "G0 X" + str(fmt(first.x)) + "Y" + str(fmt(first.y)) + "F " + fmt(HorizJog) + "\n"
|
||||
Zprevious = ZStart
|
||||
ZCurrent = ZStart - StepDown
|
||||
# toolpath = offset.Edges[:]
|
||||
# paths = ""
|
||||
# paths += "G0 Z" + str(ZClearance) + "F " + fmt(VertJog) + "\n"
|
||||
# first = toolpath[0].Vertexes[0].Point
|
||||
# paths += "G0 X" + str(fmt(first.x)) + "Y" + str(fmt(first.y)) + "F " + fmt(HorizJog) + "\n"
|
||||
# Zprevious = ZStart
|
||||
# ZCurrent = ZStart - StepDown
|
||||
|
||||
while ZCurrent > ZFinalDepth:
|
||||
paths += convert(toolpath, Z=ZCurrent, Zprevious=Zprevious, PlungeAngle=PlungeAngle,
|
||||
vf=VertFeed, hf=HorizFeed)
|
||||
if not PathClosed:
|
||||
paths += "G0 Z" + str(ZClearance) + "F " + fmt(VertJog)
|
||||
paths += "G0 X" + str(fmt(first.x)) + "Y" + \
|
||||
str(fmt(first.y)) + "F " + fmt(HorizJog) + "\n"
|
||||
Zprevious = ZCurrent
|
||||
ZCurrent = ZCurrent - abs(StepDown)
|
||||
# while ZCurrent > ZFinalDepth:
|
||||
# paths += convert(toolpath, Z=ZCurrent, Zprevious=Zprevious, PlungeAngle=PlungeAngle,
|
||||
# vf=VertFeed, hf=HorizFeed)
|
||||
# if not PathClosed:
|
||||
# paths += "G0 Z" + str(ZClearance) + "F " + fmt(VertJog)
|
||||
# paths += "G0 X" + str(fmt(first.x)) + "Y" + \
|
||||
# str(fmt(first.y)) + "F " + fmt(HorizJog) + "\n"
|
||||
# Zprevious = ZCurrent
|
||||
# ZCurrent = ZCurrent - abs(StepDown)
|
||||
|
||||
# do the final Z value
|
||||
paths += convert(toolpath, Z=ZFinalDepth, Zprevious=Zprevious, PlungeAngle=PlungeAngle,
|
||||
vf=VertFeed, hf=HorizFeed)
|
||||
# # do the final Z value
|
||||
# paths += convert(toolpath, Z=ZFinalDepth, Zprevious=Zprevious, PlungeAngle=PlungeAngle,
|
||||
# vf=VertFeed, hf=HorizFeed)
|
||||
|
||||
# when plunging with != 90 degree we have to do one last pass to clear the remaining ramp
|
||||
if PlungeAngle != 90.0:
|
||||
tanA = math.tan(math.pi * PlungeAngle / 180.0)
|
||||
if tanA <= 0.0:
|
||||
StopLength=None
|
||||
else:
|
||||
StopLength=abs(StepDown/tanA)
|
||||
paths += convert(toolpath, Z=ZFinalDepth, Zprevious=Zprevious, StopLength=StopLength,
|
||||
vf=VertFeed, hf=HorizFeed)
|
||||
# # when plunging with != 90 degree we have to do one last pass to clear the remaining ramp
|
||||
# if PlungeAngle != 90.0:
|
||||
# tanA = math.tan(math.pi * PlungeAngle / 180.0)
|
||||
# if tanA <= 0.0:
|
||||
# StopLength=None
|
||||
# else:
|
||||
# StopLength=abs(StepDown/tanA)
|
||||
# paths += convert(toolpath, Z=ZFinalDepth, Zprevious=Zprevious, StopLength=StopLength,
|
||||
# vf=VertFeed, hf=HorizFeed)
|
||||
|
||||
paths += "G0 Z" + str(ZClearance) + "F " + fmt(VertJog) + "\n"
|
||||
return paths
|
||||
# paths += "G0 Z" + str(ZClearance) + "F " + fmt(VertJog) + "\n"
|
||||
# return paths
|
||||
|
||||
# the next two functions are for automatically populating tool
|
||||
# numbers/height offset numbers based on previously active toolnumbers
|
||||
|
@ -548,19 +546,19 @@ def getLastToolLoad(obj):
|
|||
continue
|
||||
return tc
|
||||
|
||||
def getToolControllers(obj):
|
||||
controllers = []
|
||||
try:
|
||||
parent = obj.InList[0]
|
||||
except:
|
||||
parent = None
|
||||
# def getToolControllers(obj):
|
||||
# controllers = []
|
||||
# try:
|
||||
# parent = obj.InList[0]
|
||||
# except:
|
||||
# parent = None
|
||||
|
||||
if parent is not None and hasattr(parent, 'Group'):
|
||||
sibs = parent.Group
|
||||
for g in sibs:
|
||||
if isinstance(g.Proxy, PathScripts.PathLoadTool.LoadTool):
|
||||
controllers.append(g.Name)
|
||||
return controllers
|
||||
# if parent is not None and hasattr(parent, 'Group'):
|
||||
# sibs = parent.Group
|
||||
# for g in sibs:
|
||||
# if isinstance(g.Proxy, PathScripts.PathLoadTool.LoadTool):
|
||||
# controllers.append(g.Name)
|
||||
# return controllers
|
||||
|
||||
|
||||
|
||||
|
@ -614,7 +612,6 @@ def addToJob(obj, jobname = None):
|
|||
else:
|
||||
#form = FreeCADGui.PySideUic.loadUi(FreeCAD.getHomePath() + "Mod/Path/DlgJobChooser.ui")
|
||||
form = FreeCADGui.PySideUic.loadUi(":/panels/DlgJobChooser.ui")
|
||||
|
||||
mylist = [i.Name for i in jobs]
|
||||
form.cboProject.addItems(mylist)
|
||||
r = form.exec_()
|
||||
|
@ -629,15 +626,15 @@ def addToJob(obj, jobname = None):
|
|||
job.Group = g
|
||||
return job
|
||||
|
||||
def getLastZ(obj):
|
||||
''' find the last z value in the job '''
|
||||
lastZ = ""
|
||||
for g in obj.Group:
|
||||
for c in g.Path.Commands:
|
||||
for n in c.Parameters:
|
||||
if n == 'Z':
|
||||
lastZ = c.Parameters['Z']
|
||||
return lastZ
|
||||
# def getLastZ(obj):
|
||||
# ''' find the last z value in the job '''
|
||||
# lastZ = ""
|
||||
# for g in obj.Group:
|
||||
# for c in g.Path.Commands:
|
||||
# for n in c.Parameters:
|
||||
# if n == 'Z':
|
||||
# lastZ = c.Parameters['Z']
|
||||
# return lastZ
|
||||
|
||||
def rapid(x=None, y=None, z=None):
|
||||
""" Returns gcode string to perform a rapid move."""
|
||||
|
|
|
@ -33,19 +33,19 @@ FreeCADGui = None
|
|||
if FreeCAD.GuiUp:
|
||||
import FreeCADGui
|
||||
|
||||
class OldHighlighter(QtGui.QSyntaxHighlighter):
|
||||
def highlightBlock(self, text):
|
||||
myClassFormat = QtGui.QTextCharFormat()
|
||||
myClassFormat.setFontWeight(QtGui.QFont.Bold)
|
||||
myClassFormat.setForeground(QtCore.Qt.green)
|
||||
# the regex pattern to be colored
|
||||
pattern = "(G.*?|M.*?)\\s"
|
||||
expression = QtCore.QRegExp(pattern)
|
||||
index = text.index(expression)
|
||||
while index >= 0:
|
||||
length = expression.matchedLength()
|
||||
setFormat(index, length, myClassFormat)
|
||||
index = text.index(expression, index + length)
|
||||
# class OldHighlighter(QtGui.QSyntaxHighlighter):
|
||||
# def highlightBlock(self, text):
|
||||
# myClassFormat = QtGui.QTextCharFormat()
|
||||
# myClassFormat.setFontWeight(QtGui.QFont.Bold)
|
||||
# myClassFormat.setForeground(QtCore.Qt.green)
|
||||
# # the regex pattern to be colored
|
||||
# pattern = "(G.*?|M.*?)\\s"
|
||||
# expression = QtCore.QRegExp(pattern)
|
||||
# index = text.index(expression)
|
||||
# while index >= 0:
|
||||
# length = expression.matchedLength()
|
||||
# setFormat(index, length, myClassFormat)
|
||||
# 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 '''
|
||||
dia = GCodeEditorDialog()
|
||||
dia.editor.setText(gcode)
|
||||
result = dia.exec_()
|
||||
# result = dia.exec_()
|
||||
|
||||
def fcoms(string,commentsym):
|
||||
''' 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