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.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):
|
||||
"""A file reader that reads gzipped g-code.
|
||||
|
||||
If you're zipping g-code, you might as well use gzip!
|
||||
"""
|
||||
|
||||
def __init__(self) -> None:
|
||||
super().__init__()
|
||||
MimeTypeDatabase.addMimeType(
|
||||
|
|
|
@ -13,26 +13,31 @@ from UM.Scene.SceneNode import SceneNode #For typing.
|
|||
from UM.i18n import i18nCatalog
|
||||
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):
|
||||
"""A file writer that writes gzipped g-code.
|
||||
|
||||
If you're zipping g-code, you might as well use gzip!
|
||||
"""
|
||||
|
||||
|
||||
def __init__(self) -> None:
|
||||
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:
|
||||
"""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:
|
||||
Logger.log("e", "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
|
||||
|
||||
## 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):
|
||||
## 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!
|
||||
version = 3
|
||||
"""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.
|
||||
"""
|
||||
|
||||
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 = {
|
||||
re.escape("\\\\"): "\\", #The escape character.
|
||||
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.
|
||||
}
|
||||
"""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):
|
||||
"""Initialises the g-code reader as a profile reader."""
|
||||
|
||||
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):
|
||||
"""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":
|
||||
return None
|
||||
|
||||
|
@ -94,22 +102,28 @@ class GCodeProfileReader(ProfileReader):
|
|||
profiles.append(readQualityProfileFromString(profile_string))
|
||||
return profiles
|
||||
|
||||
## Unescape a string which has been escaped for use in a gcode comment.
|
||||
#
|
||||
# \param string The string to unescape.
|
||||
# \return \type{str} The unscaped string.
|
||||
def unescapeGcodeComment(string):
|
||||
|
||||
def unescapeGcodeComment(string: str) -> str:
|
||||
"""Unescape a string which has been escaped for use in a gcode comment.
|
||||
|
||||
:param string: The string to unescape.
|
||||
:return: The unescaped string.
|
||||
"""
|
||||
|
||||
# Un-escape the serialized profile.
|
||||
pattern = re.compile("|".join(GCodeProfileReader.escape_characters.keys()))
|
||||
|
||||
# Perform the replacement with a regular expression.
|
||||
return pattern.sub(lambda m: GCodeProfileReader.escape_characters[re.escape(m.group(0))], string)
|
||||
|
||||
## Read in a profile from a serialized string.
|
||||
#
|
||||
# \param profile_string The profile data in serialized form.
|
||||
# \return \type{Profile} the resulting Profile object or None if it could not be read.
|
||||
def readQualityProfileFromString(profile_string):
|
||||
|
||||
def readQualityProfileFromString(profile_string) -> InstanceContainer:
|
||||
"""Read in a profile from a serialized 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
|
||||
profile = InstanceContainer("")
|
||||
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])])
|
||||
|
||||
|
||||
## This parser is intended to interpret the common firmware codes among all the
|
||||
# different flavors
|
||||
class FlavorParser:
|
||||
"""This parser is intended to interpret the common firmware codes among all the different flavors"""
|
||||
|
||||
def __init__(self) -> None:
|
||||
CuraApplication.getInstance().hideMessageSignal.connect(self._onHideMessage)
|
||||
|
@ -212,8 +211,9 @@ class FlavorParser:
|
|||
# G0 and G1 should be handled exactly the same.
|
||||
_gCode1 = _gCode0
|
||||
|
||||
## Home the head.
|
||||
def _gCode28(self, position: Position, params: PositionOptional, path: List[List[Union[float, int]]]) -> Position:
|
||||
"""Home the head."""
|
||||
|
||||
return self._position(
|
||||
params.x if params.x is not None else position.x,
|
||||
params.y if params.y is not None else position.y,
|
||||
|
@ -221,21 +221,26 @@ class FlavorParser:
|
|||
position.f,
|
||||
position.e)
|
||||
|
||||
## Set the absolute positioning
|
||||
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_extrusion = True
|
||||
return position
|
||||
|
||||
## Set the relative positioning
|
||||
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_extrusion = False
|
||||
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:
|
||||
"""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:
|
||||
# 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
|
||||
|
@ -291,8 +296,9 @@ class FlavorParser:
|
|||
_type_keyword = ";TYPE:"
|
||||
_layer_keyword = ";LAYER:"
|
||||
|
||||
## For showing correct x, y offsets for each extruder
|
||||
def _extruderOffsets(self) -> Dict[int, List[float]]:
|
||||
"""For showing correct x, y offsets for each extruder"""
|
||||
|
||||
result = {}
|
||||
for extruder in ExtruderManager.getInstance().getActiveExtruderStacks():
|
||||
result[int(extruder.getMetaData().get("position", "0"))] = [
|
||||
|
|
|
@ -3,8 +3,10 @@
|
|||
|
||||
from . import FlavorParser
|
||||
|
||||
## This parser is intended to interpret the RepRap Firmware g-code flavor.
|
||||
|
||||
class RepRapFlavorParser(FlavorParser.FlavorParser):
|
||||
"""This parser is intended to interpret the RepRap Firmware g-code flavor."""
|
||||
|
||||
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
|
@ -17,16 +19,20 @@ class RepRapFlavorParser(FlavorParser.FlavorParser):
|
|||
# Set relative extrusion mode
|
||||
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):
|
||||
"""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
|
||||
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):
|
||||
"""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
|
||||
return position
|
Loading…
Add table
Add a link
Reference in a new issue