123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272 |
- import numpy
- from typing import Optional, cast
- from UM.Qt.Bindings.Theme import Theme
- from UM.Qt.QtApplication import QtApplication
- from UM.Logger import Logger
- class LayerPolygon:
- NoneType = 0
- Inset0Type = 1
- InsetXType = 2
- SkinType = 3
- SupportType = 4
- SkirtType = 5
- InfillType = 6
- SupportInfillType = 7
- MoveCombingType = 8
- MoveRetractionType = 9
- SupportInterfaceType = 10
- PrimeTowerType = 11
- __number_of_types = 12
- __jump_map = numpy.logical_or(numpy.logical_or(numpy.arange(__number_of_types) == NoneType,
- numpy.arange(__number_of_types) == MoveCombingType),
- numpy.arange(__number_of_types) == MoveRetractionType)
- def __init__(self, extruder: int, line_types: numpy.ndarray, data: numpy.ndarray,
- line_widths: numpy.ndarray, line_thicknesses: numpy.ndarray, line_feedrates: numpy.ndarray) -> None:
- """LayerPolygon, used in ProcessSlicedLayersJob
- :param extruder: The position of the extruder
- :param line_types: array with line_types
- :param data: new_points
- :param line_widths: array with line widths
- :param line_thicknesses: array with type as index and thickness as value
- :param line_feedrates: array with line feedrates
- """
- self._extruder = extruder
- self._types = line_types
- unknown_types = numpy.where(self._types >= self.__number_of_types, self._types, None)
- if unknown_types.any():
-
- for idx in unknown_types:
- Logger.warning(f"Found an unknown line type at: {idx}")
- self._types[idx] = self.NoneType
- self._data = data
- self._line_widths = line_widths
- self._line_thicknesses = line_thicknesses
- self._line_feedrates = line_feedrates
- self._vertex_begin = 0
- self._vertex_end = 0
- self._index_begin = 0
- self._index_end = 0
- self._jump_mask = self.__jump_map[self._types]
- self._jump_count = numpy.sum(self._jump_mask)
- self._mesh_line_count = len(self._types) - self._jump_count
- self._vertex_count = self._mesh_line_count + numpy.sum(self._types[1:] == self._types[:-1])
-
-
- self._color_map = LayerPolygon.getColorMap()
- self._colors = self._color_map[self._types]
-
-
-
-
- self._is_infill_or_skin_type_map = numpy.array([0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0], dtype=bool)
- self._build_cache_line_mesh_mask = None
- self._build_cache_needed_points = None
- def buildCache(self) -> None:
-
- self._build_cache_line_mesh_mask = numpy.ones(self._jump_mask.shape, dtype = bool)
- self._index_begin = 0
- self._index_end = cast(int, numpy.sum(self._build_cache_line_mesh_mask))
- self._build_cache_needed_points = numpy.ones((len(self._types), 2), dtype = bool)
-
- self._build_cache_needed_points[1:, 0][:, numpy.newaxis] = self._types[1:] != self._types[:-1]
-
- numpy.logical_and(self._build_cache_needed_points, self._build_cache_line_mesh_mask, self._build_cache_needed_points)
- self._vertex_begin = 0
- self._vertex_end = cast(int, numpy.sum(self._build_cache_needed_points))
- def build(self, vertex_offset: int, index_offset: int, vertices: numpy.ndarray,
- colors: numpy.ndarray, line_dimensions: numpy.ndarray, feedrates: numpy.ndarray,
- extruders: numpy.ndarray, line_types: numpy.ndarray, indices: numpy.ndarray) -> None:
- """Set all the arrays provided by the function caller, representing the LayerPolygon
- The arrays are either by vertex or by indices.
- :param vertex_offset: determines where to start and end filling the arrays
- :param index_offset: determines where to start and end filling the arrays
- :param vertices: vertex numpy array to be filled
- :param colors: vertex numpy array to be filled
- :param line_dimensions: vertex numpy array to be filled
- :param feedrates: vertex numpy array to be filled
- :param extruders: vertex numpy array to be filled
- :param line_types: vertex numpy array to be filled
- :param indices: index numpy array to be filled
- """
- if self._build_cache_line_mesh_mask is None or self._build_cache_needed_points is None:
- self.buildCache()
- if self._build_cache_line_mesh_mask is None or self._build_cache_needed_points is None:
- Logger.log("w", "Failed to build cache for layer polygon")
- return
- line_mesh_mask = self._build_cache_line_mesh_mask
- needed_points_list = self._build_cache_needed_points
-
-
-
-
- index_list = (numpy.arange(len(self._types)).reshape((-1, 1)) + numpy.array([[0, 1]])).reshape((-1, 1))[needed_points_list.reshape((-1, 1))]
-
- self._vertex_begin += vertex_offset
- self._vertex_end += vertex_offset
-
- vertices[self._vertex_begin:self._vertex_end, :] = self._data[index_list, :]
-
- colors[self._vertex_begin:self._vertex_end, :] = numpy.tile(self._colors, (1, 2)).reshape((-1, 4))[needed_points_list.ravel()]
-
- line_dimensions[self._vertex_begin:self._vertex_end, 0] = numpy.tile(self._line_widths, (1, 2)).reshape((-1, 1))[needed_points_list.ravel()][:, 0]
- line_dimensions[self._vertex_begin:self._vertex_end, 1] = numpy.tile(self._line_thicknesses, (1, 2)).reshape((-1, 1))[needed_points_list.ravel()][:, 0]
-
- feedrates[self._vertex_begin:self._vertex_end] = numpy.tile(self._line_feedrates, (1, 2)).reshape((-1, 1))[needed_points_list.ravel()][:, 0]
- extruders[self._vertex_begin:self._vertex_end] = self._extruder
-
- line_types[self._vertex_begin:self._vertex_end] = numpy.tile(self._types, (1, 2)).reshape((-1, 1))[needed_points_list.ravel()][:, 0]
-
-
- self._index_begin += index_offset
- self._index_end += index_offset
- indices[self._index_begin:self._index_end, :] = numpy.arange(self._index_end-self._index_begin, dtype=numpy.int32).reshape((-1, 1))
-
- indices[self._index_begin:self._index_end, :] += numpy.cumsum(needed_points_list[line_mesh_mask.ravel(), 0], dtype = numpy.int32).reshape((-1, 1))
-
-
- indices[self._index_begin:self._index_end, :] += numpy.array([self._vertex_begin - 1, self._vertex_begin])
- self._build_cache_line_mesh_mask = None
- self._build_cache_needed_points = None
- def getColors(self):
- return self._colors
- def mapLineTypeToColor(self, line_types: numpy.ndarray) -> numpy.ndarray:
- return self._color_map[line_types]
- def isInfillOrSkinType(self, line_types: numpy.ndarray) -> numpy.ndarray:
- return self._is_infill_or_skin_type_map[line_types]
- def lineMeshVertexCount(self) -> int:
- return self._vertex_end - self._vertex_begin
- def lineMeshElementCount(self) -> int:
- return self._index_end - self._index_begin
- @property
- def extruder(self):
- return self._extruder
- @property
- def types(self):
- return self._types
- @property
- def data(self):
- return self._data
- @property
- def elementCount(self):
- return (self._index_end - self._index_begin) * 2
- @property
- def lineWidths(self):
- return self._line_widths
- @property
- def lineThicknesses(self):
- return self._line_thicknesses
- @property
- def lineFeedrates(self):
- return self._line_feedrates
- @property
- def jumpMask(self):
- return self._jump_mask
- @property
- def meshLineCount(self):
- return self._mesh_line_count
- @property
- def jumpCount(self):
- return self._jump_count
- def getNormals(self) -> numpy.ndarray:
- """Calculate normals for the entire polygon using numpy.
- :return: normals for the entire polygon
- """
- normals = numpy.copy(self._data)
- normals[:, 1] = 0.0
-
-
-
-
- normals = numpy.diff(normals, 1, 0)
-
- lengths = numpy.sqrt(normals[:, 0] ** 2 + normals[:, 2] ** 2)
-
-
- normals[:, [0, 2]] = normals[:, [2, 0]]
- normals[:, 0] *= -1
-
- normals[:, 0] /= lengths
- normals[:, 2] /= lengths
- return normals
- __color_map = None
- @classmethod
- def getColorMap(cls) -> numpy.ndarray:
- """Gets the instance of the VersionUpgradeManager, or creates one."""
- if cls.__color_map is None:
- theme = cast(Theme, QtApplication.getInstance().getTheme())
- cls.__color_map = numpy.array([
- theme.getColor("layerview_none").getRgbF(),
- theme.getColor("layerview_inset_0").getRgbF(),
- theme.getColor("layerview_inset_x").getRgbF(),
- theme.getColor("layerview_skin").getRgbF(),
- theme.getColor("layerview_support").getRgbF(),
- theme.getColor("layerview_skirt").getRgbF(),
- theme.getColor("layerview_infill").getRgbF(),
- theme.getColor("layerview_support_infill").getRgbF(),
- theme.getColor("layerview_move_combing").getRgbF(),
- theme.getColor("layerview_move_retraction").getRgbF(),
- theme.getColor("layerview_support_interface").getRgbF(),
- theme.getColor("layerview_prime_tower").getRgbF()
- ])
- return cls.__color_map
|