from compas.geometry import Point, Frame, Vector, cross_vectors
import compas_slicer.utilities.utils as utils
import compas
__all__ = ['PrintPoint']
[docs]class PrintPoint(object):
"""
A PrintPoint consists of a compas.geometry.Point,
and additional attributes related to the printing process.
Attributes
----------
pt: :class:`compas.geometry.Point`
A compas Point consisting out of x, y, z coordinates.
layer_height: float
The distance between the point on this layer and the previous layer.
For planar slicing this is the vertical distance, for curved slicing this is absolute distance.
mesh_normal: :class:`compas.geometry.Vector`
Normal of the mesh at this PrintPoint.
For planar_slicing it is the projection of the normal on the XY plane.
# TODO: should we change that?
up_vector: :class:`compas.geometry.Vector`
Vector in up direction. For planar slicing this corresponds to the z axis, for curved slicing it varies.
frame: :class:`compas.geometry.Frame`
Frame with x-axis pointing up, y-axis pointing towards the mesh normal.
extruder_toggle: bool
True if extruder should be on (when printing), False if it should be off (when travelling).
velocity: float
Velocity to use for printing (print speed), in mm/s.
wait_time: float
Time in seconds to wait at this PrintPoint.
"""
[docs] def __init__(self, pt, layer_height, mesh_normal):
assert isinstance(pt, compas.geometry.Point)
assert isinstance(mesh_normal, compas.geometry.Vector)
assert layer_height
# --- basic printpoint
self.pt = pt
self.layer_height = layer_height
self.mesh_normal = mesh_normal # compas.geometry.Vector
self.up_vector = Vector(0, 0, 1) # default value that can be updated
self.frame = self.get_frame() # compas.geometry.Frame
# --- attributes transferred from the mesh (vertex / face attributes)
self.attributes = {} # dict. To fill this in,
# --- print_organization related attributes
self.extruder_toggle = None # bool
self.velocity = None # float (mm/s)
self.wait_time = None # float (sec)
self.blend_radius = None # float (mm)
# --- relation to support
self.closest_support_pt = None # <compas.geometry.Point>
self.distance_to_support = None # float
self.is_feasible = True # bool
def __repr__(self):
x, y, z = self.pt[0], self.pt[1], self.pt[2]
return "<PrintPoint object at (%.2f, %.2f, %.2f)>" % (x, y, z)
[docs] def get_frame(self):
""" Returns a Frame with x-axis pointing up, y-axis pointing towards the mesh normal. """
c = cross_vectors(self.up_vector, self.mesh_normal)
return Frame(self.pt, c, self.mesh_normal)
#################################
# --- To data , from data
[docs] def to_data(self):
"""Returns a dictionary of structured data representing the data structure.
TODO: The attributes of the printpoints are not saved in the dictionary because they can be non-Json
serializable. Find a solution for this.
Returns
-------
dict
The PrintPoints' data.
"""
point = {
'point': [self.pt[0], self.pt[1], self.pt[2]],
'layer_height': self.layer_height,
'mesh_normal': self.mesh_normal.to_data(),
'up_vector': self.up_vector.to_data(),
'frame': self.frame.to_data(),
'extruder_toggle': self.extruder_toggle,
'velocity': self.velocity,
'wait_time': self.wait_time,
'blend_radius': self.blend_radius,
'closest_support_pt': self.closest_support_pt.to_data() if self.closest_support_pt else None,
'distance_to_support': self.distance_to_support,
'is_feasible': self.is_feasible,
'attributes': utils.get_jsonable_attributes(self.attributes)
}
return point
[docs] @classmethod
def from_data(cls, data):
"""Construct a PrintPoint from its data representation.
Parameters
----------
data: dict
The data dictionary.
Returns
-------
layer
The constructed PrintPoint.
"""
pp = cls(pt=Point.from_data(data['point']),
layer_height=data['layer_height'],
mesh_normal=Vector.from_data(data['mesh_normal']))
pp.up_vector = Vector.from_data(data['up_vector'])
pp.frame = Frame.from_data(data['frame'])
pp.extruder_toggle = data['extruder_toggle']
pp.velocity = data['velocity']
pp.wait_time = data['wait_time']
pp.blend_radius = data['blend_radius']
pp.closest_support_pt = Point.from_data(data['closest_support_pt'])
pp.distance_to_support = data['distance_to_support']
pp.is_feasible = data['is_feasible']
pp.attributes = data['attributes']
return pp
if __name__ == "__main__":
pass