GCODEReader.py 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235
  1. # Copyright (c) 2015 Ultimaker B.V.
  2. # Copyright (c) 2013 David Braam
  3. # Uranium is released under the terms of the AGPLv3 or higher.
  4. from UM.Mesh.MeshReader import MeshReader
  5. import os
  6. from UM.Scene.SceneNode import SceneNode
  7. from UM.Scene.Iterator.DepthFirstIterator import DepthFirstIterator
  8. from UM.Math.Vector import Vector
  9. from UM.Math.AxisAlignedBox import AxisAlignedBox
  10. from UM.Application import Application
  11. from cura import LayerDataBuilder
  12. from cura import LayerDataDecorator
  13. from cura import LayerPolygon
  14. import numpy
  15. class GCODEReader(MeshReader):
  16. def __init__(self):
  17. super(GCODEReader, self).__init__()
  18. self._supported_extensions = [".gcode", ".g"]
  19. def getInt(self, line, code):
  20. n = line.find(code) + 1
  21. if n < 1:
  22. return None
  23. m = line.find(' ', n)
  24. try:
  25. if m < 0:
  26. return int(line[n:])
  27. return int(line[n:m])
  28. except:
  29. return None
  30. def getFloat(self, line, code):
  31. n = line.find(code) + 1
  32. if n < 1:
  33. return None
  34. m = line.find(' ', n)
  35. try:
  36. if m < 0:
  37. return float(line[n:])
  38. return float(line[n:m])
  39. except:
  40. return None
  41. def parent_changed(self, node):
  42. if node.getParent() is None:
  43. scene = Application.getInstance().getController().getScene()
  44. def findAny():
  45. for node1 in DepthFirstIterator(scene.getRoot()):
  46. if hasattr(node1, "gcode") and getattr(node1, "gcode") is True:
  47. return True
  48. return False
  49. backend = Application.getInstance().getBackend()
  50. if not findAny():
  51. backend._pauseSlicing = False
  52. Application.getInstance().setHideSettings(False)
  53. Application.getInstance().getPrintInformation().setPreSliced(False)
  54. else:
  55. backend._pauseSlicing = True
  56. backend.backendStateChange.emit(3)
  57. Application.getInstance().getPrintInformation().setPreSliced(True)
  58. Application.getInstance().setHideSettings(True)
  59. def read(self, file_name):
  60. scene_node = None
  61. extension = os.path.splitext(file_name)[1]
  62. if extension.lower() in self._supported_extensions:
  63. Application.getInstance().deleteAll()
  64. scene_node = SceneNode()
  65. def getBoundingBox():
  66. return AxisAlignedBox(minimum=Vector(0, 0, 0), maximum=Vector(10, 10, 10))
  67. scene_node.getBoundingBox = getBoundingBox
  68. scene_node.gcode = True
  69. backend = Application.getInstance().getBackend()
  70. backend._pauseSlicing = True
  71. backend.close()
  72. backend.backendStateChange.emit(1)
  73. glist = getattr(Application.getInstance().getController().getScene(), "gcode_list")
  74. glist.clear()
  75. file = open(file_name, "r")
  76. layer_data = LayerDataBuilder.LayerDataBuilder()
  77. current_extruder = 1
  78. current_path = []
  79. current_x = 0
  80. current_y = 0
  81. current_z = 0
  82. current_e = 0
  83. layers = []
  84. for line in file:
  85. glist.append(line)
  86. if len(line) == 0:
  87. continue
  88. if line[0] == ";":
  89. continue
  90. G = self.getInt(line, "G")
  91. if G is not None:
  92. if G == 0 or G == 1:
  93. z = self.getFloat(line, "Z")
  94. if z is not None and z not in layers and z >= 0:
  95. layers.append(z)
  96. layers.sort()
  97. file.seek(0)
  98. for layer in layers:
  99. layer_id = layers.index(layer)
  100. layer_data.addLayer(layer_id)
  101. layer_data.setLayerHeight(layer_id, layer)
  102. layer_data.setLayerThickness(layer_id, 0.25)
  103. def CreatePolygon():
  104. try:
  105. this_layer = layer_data.getLayer(layers.index(current_path[0][1]))
  106. except ValueError:
  107. current_path.clear()
  108. return
  109. count = len(current_path)
  110. line_types = numpy.empty((count-1, 1), numpy.int32)
  111. line_types[:, 0] = 1
  112. line_widths = numpy.empty((count-1, 1), numpy.int32)
  113. line_widths[:, 0] = 0.5
  114. points = numpy.empty((count, 3), numpy.float32)
  115. i = 0
  116. for point in current_path:
  117. points[i, 0] = point[0]
  118. points[i, 1] = point[1]
  119. points[i, 2] = point[2]
  120. if i > 0:
  121. line_types[i-1] = point[3]
  122. i += 1
  123. this_poly = LayerPolygon.LayerPolygon(layer_data, current_extruder, line_types, points, line_widths)
  124. this_poly.buildCache()
  125. this_layer.polygons.append(this_poly)
  126. current_path.clear()
  127. for line in file:
  128. if len(line) == 0:
  129. continue
  130. if line[0] == ";":
  131. continue
  132. G = self.getInt(line, "G")
  133. if G is not None:
  134. if G == 0 or G == 1:
  135. x = self.getFloat(line, "X")
  136. y = self.getFloat(line, "Y")
  137. z = self.getFloat(line, "Z")
  138. e = self.getFloat(line, "E")
  139. z_changed = False
  140. if x is not None:
  141. current_x = x
  142. if y is not None:
  143. current_y = y
  144. if z is not None:
  145. if not current_z == z:
  146. z_changed = True
  147. current_z = z
  148. if e is not None:
  149. if e > current_e:
  150. current_path.append([current_x, current_z, -current_y, 1])
  151. else:
  152. current_path.append([current_x, current_z, -current_y, 0])
  153. current_e = e
  154. else:
  155. current_path.append([current_x, current_z, -current_y, 0])
  156. if z_changed:
  157. if len(current_path) > 1:
  158. CreatePolygon()
  159. else:
  160. current_path.clear()
  161. elif G == 28:
  162. x = self.getFloat(line, "X")
  163. y = self.getFloat(line, "Y")
  164. if x is not None:
  165. current_x = x
  166. if y is not None:
  167. current_y = y
  168. current_z = 0
  169. elif G == 92:
  170. x = self.getFloat(line, "X")
  171. y = self.getFloat(line, "Y")
  172. z = self.getFloat(line, "Z")
  173. if x is not None:
  174. current_x += x
  175. if y is not None:
  176. current_y += y
  177. if z is not None:
  178. current_z += z
  179. if len(current_path) > 1:
  180. CreatePolygon()
  181. layer_mesh = layer_data.build()
  182. decorator = LayerDataDecorator.LayerDataDecorator()
  183. decorator.setLayerData(layer_mesh)
  184. scene_node.addDecorator(decorator)
  185. Application.getInstance().getPrintInformation()._pre_sliced = True
  186. scene_node.parentChanged.connect(self.parent_changed)
  187. scene_node_parent = Application.getInstance().getBuildVolume()
  188. scene_node.setParent(scene_node_parent)
  189. settings = Application.getInstance().getGlobalContainerStack()
  190. machine_width = settings.getProperty("machine_width", "value")
  191. machine_depth = settings.getProperty("machine_depth", "value")
  192. scene_node.setPosition(Vector(-machine_width / 2, 0, machine_depth / 2))
  193. view = Application.getInstance().getController().getActiveView()
  194. if view.getPluginId() == "LayerView":
  195. view.resetLayerData()
  196. view.setLayer(999999)
  197. view.calculateMaxLayers()
  198. return scene_node