mirror of
https://github.com/Ultimaker/Cura.git
synced 2025-07-06 22:47:29 -06:00
Convert doxygen to rst for GcodeReader, GcodeGzReader/Writer,
GCodeProfileReader
This commit is contained in:
parent
6ca9b4678e
commit
40327c4259
5 changed files with 98 additions and 64 deletions
|
@ -7,10 +7,13 @@ from UM.Mesh.MeshReader import MeshReader #The class we're extending/implementin
|
||||||
from UM.MimeTypeDatabase import MimeTypeDatabase, MimeType #To add the .gcode.gz files to the MIME type database.
|
from UM.MimeTypeDatabase import MimeTypeDatabase, MimeType #To add the .gcode.gz files to the MIME type database.
|
||||||
from UM.PluginRegistry import PluginRegistry
|
from UM.PluginRegistry import PluginRegistry
|
||||||
|
|
||||||
## A file reader that reads gzipped g-code.
|
|
||||||
#
|
|
||||||
# If you're zipping g-code, you might as well use gzip!
|
|
||||||
class GCodeGzReader(MeshReader):
|
class GCodeGzReader(MeshReader):
|
||||||
|
"""A file reader that reads gzipped g-code.
|
||||||
|
|
||||||
|
If you're zipping g-code, you might as well use gzip!
|
||||||
|
"""
|
||||||
|
|
||||||
def __init__(self) -> None:
|
def __init__(self) -> None:
|
||||||
super().__init__()
|
super().__init__()
|
||||||
MimeTypeDatabase.addMimeType(
|
MimeTypeDatabase.addMimeType(
|
||||||
|
|
|
@ -13,26 +13,31 @@ from UM.Scene.SceneNode import SceneNode #For typing.
|
||||||
from UM.i18n import i18nCatalog
|
from UM.i18n import i18nCatalog
|
||||||
catalog = i18nCatalog("cura")
|
catalog = i18nCatalog("cura")
|
||||||
|
|
||||||
## A file writer that writes gzipped g-code.
|
|
||||||
#
|
|
||||||
# If you're zipping g-code, you might as well use gzip!
|
|
||||||
class GCodeGzWriter(MeshWriter):
|
class GCodeGzWriter(MeshWriter):
|
||||||
|
"""A file writer that writes gzipped g-code.
|
||||||
|
|
||||||
|
If you're zipping g-code, you might as well use gzip!
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
def __init__(self) -> None:
|
def __init__(self) -> None:
|
||||||
super().__init__(add_to_recent_files = False)
|
super().__init__(add_to_recent_files = False)
|
||||||
|
|
||||||
## Writes the gzipped g-code to a stream.
|
|
||||||
#
|
|
||||||
# Note that even though the function accepts a collection of nodes, the
|
|
||||||
# entire scene is always written to the file since it is not possible to
|
|
||||||
# separate the g-code for just specific nodes.
|
|
||||||
#
|
|
||||||
# \param stream The stream to write the gzipped g-code to.
|
|
||||||
# \param nodes This is ignored.
|
|
||||||
# \param mode Additional information on what type of stream to use. This
|
|
||||||
# must always be binary mode.
|
|
||||||
# \return Whether the write was successful.
|
|
||||||
def write(self, stream: BufferedIOBase, nodes: List[SceneNode], mode = MeshWriter.OutputMode.BinaryMode) -> bool:
|
def write(self, stream: BufferedIOBase, nodes: List[SceneNode], mode = MeshWriter.OutputMode.BinaryMode) -> bool:
|
||||||
|
"""Writes the gzipped g-code to a stream.
|
||||||
|
|
||||||
|
Note that even though the function accepts a collection of nodes, the
|
||||||
|
entire scene is always written to the file since it is not possible to
|
||||||
|
separate the g-code for just specific nodes.
|
||||||
|
|
||||||
|
:param stream: The stream to write the gzipped g-code to.
|
||||||
|
:param nodes: This is ignored.
|
||||||
|
:param mode: Additional information on what type of stream to use. This
|
||||||
|
must always be binary mode.
|
||||||
|
:return: Whether the write was successful.
|
||||||
|
"""
|
||||||
|
|
||||||
if mode != MeshWriter.OutputMode.BinaryMode:
|
if mode != MeshWriter.OutputMode.BinaryMode:
|
||||||
Logger.log("e", "GCodeGzWriter does not support text mode.")
|
Logger.log("e", "GCodeGzWriter does not support text mode.")
|
||||||
self.setInformation(catalog.i18nc("@error:not supported", "GCodeGzWriter does not support text mode."))
|
self.setInformation(catalog.i18nc("@error:not supported", "GCodeGzWriter does not support text mode."))
|
||||||
|
|
|
@ -12,40 +12,48 @@ catalog = i18nCatalog("cura")
|
||||||
|
|
||||||
from cura.ReaderWriters.ProfileReader import ProfileReader, NoProfileException
|
from cura.ReaderWriters.ProfileReader import ProfileReader, NoProfileException
|
||||||
|
|
||||||
## A class that reads profile data from g-code files.
|
|
||||||
#
|
|
||||||
# It reads the profile data from g-code files and stores it in a new profile.
|
|
||||||
# This class currently does not process the rest of the g-code in any way.
|
|
||||||
class GCodeProfileReader(ProfileReader):
|
class GCodeProfileReader(ProfileReader):
|
||||||
## The file format version of the serialized g-code.
|
"""A class that reads profile data from g-code files.
|
||||||
#
|
|
||||||
# It can only read settings with the same version as the version it was
|
It reads the profile data from g-code files and stores it in a new profile.
|
||||||
# written with. If the file format is changed in a way that breaks reverse
|
This class currently does not process the rest of the g-code in any way.
|
||||||
# compatibility, increment this version number!
|
"""
|
||||||
version = 3
|
|
||||||
|
version = 3
|
||||||
|
"""The file format version of the serialized g-code.
|
||||||
|
|
||||||
|
It can only read settings with the same version as the version it was
|
||||||
|
written with. If the file format is changed in a way that breaks reverse
|
||||||
|
compatibility, increment this version number!
|
||||||
|
"""
|
||||||
|
|
||||||
## Dictionary that defines how characters are escaped when embedded in
|
|
||||||
# g-code.
|
|
||||||
#
|
|
||||||
# Note that the keys of this dictionary are regex strings. The values are
|
|
||||||
# not.
|
|
||||||
escape_characters = {
|
escape_characters = {
|
||||||
re.escape("\\\\"): "\\", #The escape character.
|
re.escape("\\\\"): "\\", #The escape character.
|
||||||
re.escape("\\n"): "\n", #Newlines. They break off the comment.
|
re.escape("\\n"): "\n", #Newlines. They break off the comment.
|
||||||
re.escape("\\r"): "\r" #Carriage return. Windows users may need this for visualisation in their editors.
|
re.escape("\\r"): "\r" #Carriage return. Windows users may need this for visualisation in their editors.
|
||||||
}
|
}
|
||||||
|
"""Dictionary that defines how characters are escaped when embedded in
|
||||||
|
|
||||||
|
g-code.
|
||||||
|
|
||||||
|
Note that the keys of this dictionary are regex strings. The values are
|
||||||
|
not.
|
||||||
|
"""
|
||||||
|
|
||||||
## Initialises the g-code reader as a profile reader.
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
|
"""Initialises the g-code reader as a profile reader."""
|
||||||
|
|
||||||
super().__init__()
|
super().__init__()
|
||||||
|
|
||||||
## Reads a g-code file, loading the profile from it.
|
|
||||||
#
|
|
||||||
# \param file_name The name of the file to read the profile from.
|
|
||||||
# \return The profile that was in the specified file, if any. If the
|
|
||||||
# specified file was no g-code or contained no parsable profile, \code
|
|
||||||
# None \endcode is returned.
|
|
||||||
def read(self, file_name):
|
def read(self, file_name):
|
||||||
|
"""Reads a g-code file, loading the profile from it.
|
||||||
|
|
||||||
|
:param file_name: The name of the file to read the profile from.
|
||||||
|
:return: The profile that was in the specified file, if any. If the
|
||||||
|
specified file was no g-code or contained no parsable profile,
|
||||||
|
None is returned.
|
||||||
|
"""
|
||||||
|
|
||||||
if file_name.split(".")[-1] != "gcode":
|
if file_name.split(".")[-1] != "gcode":
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
@ -94,22 +102,28 @@ class GCodeProfileReader(ProfileReader):
|
||||||
profiles.append(readQualityProfileFromString(profile_string))
|
profiles.append(readQualityProfileFromString(profile_string))
|
||||||
return profiles
|
return profiles
|
||||||
|
|
||||||
## Unescape a string which has been escaped for use in a gcode comment.
|
|
||||||
#
|
def unescapeGcodeComment(string: str) -> str:
|
||||||
# \param string The string to unescape.
|
"""Unescape a string which has been escaped for use in a gcode comment.
|
||||||
# \return \type{str} The unscaped string.
|
|
||||||
def unescapeGcodeComment(string):
|
:param string: The string to unescape.
|
||||||
|
:return: The unescaped string.
|
||||||
|
"""
|
||||||
|
|
||||||
# Un-escape the serialized profile.
|
# Un-escape the serialized profile.
|
||||||
pattern = re.compile("|".join(GCodeProfileReader.escape_characters.keys()))
|
pattern = re.compile("|".join(GCodeProfileReader.escape_characters.keys()))
|
||||||
|
|
||||||
# Perform the replacement with a regular expression.
|
# Perform the replacement with a regular expression.
|
||||||
return pattern.sub(lambda m: GCodeProfileReader.escape_characters[re.escape(m.group(0))], string)
|
return pattern.sub(lambda m: GCodeProfileReader.escape_characters[re.escape(m.group(0))], string)
|
||||||
|
|
||||||
## Read in a profile from a serialized string.
|
|
||||||
#
|
def readQualityProfileFromString(profile_string) -> InstanceContainer:
|
||||||
# \param profile_string The profile data in serialized form.
|
"""Read in a profile from a serialized string.
|
||||||
# \return \type{Profile} the resulting Profile object or None if it could not be read.
|
|
||||||
def readQualityProfileFromString(profile_string):
|
:param profile_string: The profile data in serialized form.
|
||||||
|
:return: The resulting Profile object or None if it could not be read.
|
||||||
|
"""
|
||||||
|
|
||||||
# Create an empty profile - the id and name will be changed by the ContainerRegistry
|
# Create an empty profile - the id and name will be changed by the ContainerRegistry
|
||||||
profile = InstanceContainer("")
|
profile = InstanceContainer("")
|
||||||
try:
|
try:
|
||||||
|
|
|
@ -28,9 +28,8 @@ PositionOptional = NamedTuple("Position", [("x", Optional[float]), ("y", Optiona
|
||||||
Position = NamedTuple("Position", [("x", float), ("y", float), ("z", float), ("f", float), ("e", List[float])])
|
Position = NamedTuple("Position", [("x", float), ("y", float), ("z", float), ("f", float), ("e", List[float])])
|
||||||
|
|
||||||
|
|
||||||
## This parser is intended to interpret the common firmware codes among all the
|
|
||||||
# different flavors
|
|
||||||
class FlavorParser:
|
class FlavorParser:
|
||||||
|
"""This parser is intended to interpret the common firmware codes among all the different flavors"""
|
||||||
|
|
||||||
def __init__(self) -> None:
|
def __init__(self) -> None:
|
||||||
CuraApplication.getInstance().hideMessageSignal.connect(self._onHideMessage)
|
CuraApplication.getInstance().hideMessageSignal.connect(self._onHideMessage)
|
||||||
|
@ -212,8 +211,9 @@ class FlavorParser:
|
||||||
# G0 and G1 should be handled exactly the same.
|
# G0 and G1 should be handled exactly the same.
|
||||||
_gCode1 = _gCode0
|
_gCode1 = _gCode0
|
||||||
|
|
||||||
## Home the head.
|
|
||||||
def _gCode28(self, position: Position, params: PositionOptional, path: List[List[Union[float, int]]]) -> Position:
|
def _gCode28(self, position: Position, params: PositionOptional, path: List[List[Union[float, int]]]) -> Position:
|
||||||
|
"""Home the head."""
|
||||||
|
|
||||||
return self._position(
|
return self._position(
|
||||||
params.x if params.x is not None else position.x,
|
params.x if params.x is not None else position.x,
|
||||||
params.y if params.y is not None else position.y,
|
params.y if params.y is not None else position.y,
|
||||||
|
@ -221,21 +221,26 @@ class FlavorParser:
|
||||||
position.f,
|
position.f,
|
||||||
position.e)
|
position.e)
|
||||||
|
|
||||||
## Set the absolute positioning
|
|
||||||
def _gCode90(self, position: Position, params: PositionOptional, path: List[List[Union[float, int]]]) -> Position:
|
def _gCode90(self, position: Position, params: PositionOptional, path: List[List[Union[float, int]]]) -> Position:
|
||||||
|
"""Set the absolute positioning"""
|
||||||
|
|
||||||
self._is_absolute_positioning = True
|
self._is_absolute_positioning = True
|
||||||
self._is_absolute_extrusion = True
|
self._is_absolute_extrusion = True
|
||||||
return position
|
return position
|
||||||
|
|
||||||
## Set the relative positioning
|
|
||||||
def _gCode91(self, position: Position, params: PositionOptional, path: List[List[Union[float, int]]]) -> Position:
|
def _gCode91(self, position: Position, params: PositionOptional, path: List[List[Union[float, int]]]) -> Position:
|
||||||
|
"""Set the relative positioning"""
|
||||||
|
|
||||||
self._is_absolute_positioning = False
|
self._is_absolute_positioning = False
|
||||||
self._is_absolute_extrusion = False
|
self._is_absolute_extrusion = False
|
||||||
return position
|
return position
|
||||||
|
|
||||||
## Reset the current position to the values specified.
|
|
||||||
# For example: G92 X10 will set the X to 10 without any physical motion.
|
|
||||||
def _gCode92(self, position: Position, params: PositionOptional, path: List[List[Union[float, int]]]) -> Position:
|
def _gCode92(self, position: Position, params: PositionOptional, path: List[List[Union[float, int]]]) -> Position:
|
||||||
|
"""Reset the current position to the values specified.
|
||||||
|
|
||||||
|
For example: G92 X10 will set the X to 10 without any physical motion.
|
||||||
|
"""
|
||||||
|
|
||||||
if params.e is not None:
|
if params.e is not None:
|
||||||
# Sometimes a G92 E0 is introduced in the middle of the GCode so we need to keep those offsets for calculate the line_width
|
# Sometimes a G92 E0 is introduced in the middle of the GCode so we need to keep those offsets for calculate the line_width
|
||||||
self._extrusion_length_offset[self._extruder_number] = position.e[self._extruder_number] - params.e
|
self._extrusion_length_offset[self._extruder_number] = position.e[self._extruder_number] - params.e
|
||||||
|
@ -291,8 +296,9 @@ class FlavorParser:
|
||||||
_type_keyword = ";TYPE:"
|
_type_keyword = ";TYPE:"
|
||||||
_layer_keyword = ";LAYER:"
|
_layer_keyword = ";LAYER:"
|
||||||
|
|
||||||
## For showing correct x, y offsets for each extruder
|
|
||||||
def _extruderOffsets(self) -> Dict[int, List[float]]:
|
def _extruderOffsets(self) -> Dict[int, List[float]]:
|
||||||
|
"""For showing correct x, y offsets for each extruder"""
|
||||||
|
|
||||||
result = {}
|
result = {}
|
||||||
for extruder in ExtruderManager.getInstance().getActiveExtruderStacks():
|
for extruder in ExtruderManager.getInstance().getActiveExtruderStacks():
|
||||||
result[int(extruder.getMetaData().get("position", "0"))] = [
|
result[int(extruder.getMetaData().get("position", "0"))] = [
|
||||||
|
|
|
@ -3,8 +3,10 @@
|
||||||
|
|
||||||
from . import FlavorParser
|
from . import FlavorParser
|
||||||
|
|
||||||
## This parser is intended to interpret the RepRap Firmware g-code flavor.
|
|
||||||
class RepRapFlavorParser(FlavorParser.FlavorParser):
|
class RepRapFlavorParser(FlavorParser.FlavorParser):
|
||||||
|
"""This parser is intended to interpret the RepRap Firmware g-code flavor."""
|
||||||
|
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
super().__init__()
|
super().__init__()
|
||||||
|
@ -17,16 +19,20 @@ class RepRapFlavorParser(FlavorParser.FlavorParser):
|
||||||
# Set relative extrusion mode
|
# Set relative extrusion mode
|
||||||
self._is_absolute_extrusion = False
|
self._is_absolute_extrusion = False
|
||||||
|
|
||||||
## Set the absolute positioning
|
|
||||||
# RepRapFlavor code G90 sets position of X, Y, Z to absolute
|
|
||||||
# For absolute E, M82 is used
|
|
||||||
def _gCode90(self, position, params, path):
|
def _gCode90(self, position, params, path):
|
||||||
|
"""Set the absolute positioning
|
||||||
|
|
||||||
|
RepRapFlavor code G90 sets position of X, Y, Z to absolute
|
||||||
|
For absolute E, M82 is used
|
||||||
|
"""
|
||||||
self._is_absolute_positioning = True
|
self._is_absolute_positioning = True
|
||||||
return position
|
return position
|
||||||
|
|
||||||
## Set the relative positioning
|
|
||||||
# RepRapFlavor code G91 sets position of X, Y, Z to relative
|
|
||||||
# For relative E, M83 is used
|
|
||||||
def _gCode91(self, position, params, path):
|
def _gCode91(self, position, params, path):
|
||||||
|
"""Set the relative positioning
|
||||||
|
|
||||||
|
RepRapFlavor code G91 sets position of X, Y, Z to relative
|
||||||
|
For relative E, M83 is used
|
||||||
|
"""
|
||||||
self._is_absolute_positioning = False
|
self._is_absolute_positioning = False
|
||||||
return position
|
return position
|
Loading…
Add table
Add a link
Reference in a new issue