Fixed merge issues & updated proto files

This commit is contained in:
Jaime van Kessel 2016-02-02 11:25:10 +01:00
commit 7c744044fd
5 changed files with 181 additions and 78 deletions

View file

@ -131,7 +131,7 @@ class Layer():
continue continue
if not make_mesh and not (polygon.type == Polygon.MoveCombingType or polygon.type == Polygon.MoveRetractionType): if not make_mesh and not (polygon.type == Polygon.MoveCombingType or polygon.type == Polygon.MoveRetractionType):
continue continue
poly_color = polygon.getColor() poly_color = polygon.getColor()
points = numpy.copy(polygon.data) points = numpy.copy(polygon.data)
@ -140,26 +140,7 @@ class Layer():
if polygon.type == Polygon.MoveCombingType or polygon.type == Polygon.MoveRetractionType: if polygon.type == Polygon.MoveCombingType or polygon.type == Polygon.MoveRetractionType:
points[:,1] += 0.01 points[:,1] += 0.01
# Calculate normals for the entire polygon using numpy. normals = polygon.getNormals()
normals = numpy.copy(points)
normals[:,1] = 0.0 # We are only interested in 2D normals
# Calculate the edges between points.
# The call to numpy.roll shifts the entire array by one so that
# we end up subtracting each next point from the current, wrapping
# around. This gives us the edges from the next point to the current
# point.
normals[:] = normals[:] - numpy.roll(normals, -1, axis = 0)
# Calculate the length of each edge using standard Pythagoras
lengths = numpy.sqrt(normals[:,0] ** 2 + normals[:,2] ** 2)
# The normal of a 2D vector is equal to its x and y coordinates swapped
# and then x inverted. This code does that.
normals[:,[0, 2]] = normals[:,[2, 0]]
normals[:,0] *= -1
# Normalize the normals.
normals[:,0] /= lengths
normals[:,2] /= lengths
# Scale all by the line width of the polygon so we can easily offset. # Scale all by the line width of the polygon so we can easily offset.
normals *= (polygon.lineWidth / 2) normals *= (polygon.lineWidth / 2)
@ -199,16 +180,33 @@ class Polygon():
self._data = data self._data = data
self._line_width = line_width / 1000 self._line_width = line_width / 1000
if type == self.Inset0Type:
self._color = Color(1.0, 0.0, 0.0, 1.0)
elif self._type == self.InsetXType:
self._color = Color(0.0, 1.0, 0.0, 1.0)
elif self._type == self.SkinType:
self._color = Color(1.0, 1.0, 0.0, 1.0)
elif self._type == self.SupportType:
self._color = Color(0.0, 1.0, 1.0, 1.0)
elif self._type == self.SkirtType:
self._color = Color(0.0, 1.0, 1.0, 1.0)
elif self._type == self.InfillType:
self._color = Color(1.0, 0.74, 0.0, 1.0)
elif self._type == self.SupportInfillType:
self._color = Color(0.0, 1.0, 1.0, 1.0)
elif self._type == self.MoveCombingType:
self._color = Color(0.0, 0.0, 1.0, 1.0)
elif self._type == self.MoveRetractionType:
self._color = Color(0.5, 0.5, 1.0, 1.0)
else:
self._color = Color(1.0, 1.0, 1.0, 1.0)
def build(self, offset, vertices, colors, indices): def build(self, offset, vertices, colors, indices):
self._begin = offset self._begin = offset
self._end = self._begin + len(self._data) - 1 self._end = self._begin + len(self._data) - 1
color = self.getColor()
color.setValues(color.r * 0.5, color.g * 0.5, color.b * 0.5, color.a)
color = numpy.array([color.r, color.g, color.b, color.a], numpy.float32)
vertices[self._begin:self._end + 1, :] = self._data[:, :] vertices[self._begin:self._end + 1, :] = self._data[:, :]
colors[self._begin:self._end + 1, :] = color colors[self._begin:self._end + 1, :] = numpy.array([self._color.r * 0.5, self._color.g * 0.5, self._color.b * 0.5, self._color.a], numpy.float32)
for i in range(self._begin, self._end): for i in range(self._begin, self._end):
indices[i, 0] = i indices[i, 0] = i
@ -218,26 +216,7 @@ class Polygon():
indices[self._end, 1] = self._begin indices[self._end, 1] = self._begin
def getColor(self): def getColor(self):
if self._type == self.Inset0Type: return self._color
return Color(1.0, 0.0, 0.0, 1.0)
elif self._type == self.InsetXType:
return Color(0.0, 1.0, 0.0, 1.0)
elif self._type == self.SkinType:
return Color(1.0, 1.0, 0.0, 1.0)
elif self._type == self.SupportType:
return Color(0.0, 1.0, 1.0, 1.0)
elif self._type == self.SkirtType:
return Color(0.0, 1.0, 1.0, 1.0)
elif self._type == self.InfillType:
return Color(1.0, 0.74, 0.0, 1.0)
elif self._type == self.SupportInfillType:
return Color(0.0, 1.0, 1.0, 1.0)
elif self._type == self.MoveCombingType:
return Color(0.0, 0.0, 1.0, 1.0)
elif self._type == self.MoveRetractionType:
return Color(0.5, 0.5, 1.0, 1.0)
else:
return Color(1.0, 1.0, 1.0, 1.0)
def vertexCount(self): def vertexCount(self):
return len(self._data) return len(self._data)
@ -257,3 +236,27 @@ class Polygon():
@property @property
def lineWidth(self): def lineWidth(self):
return self._line_width return self._line_width
# Calculate normals for the entire polygon using numpy.
def getNormals(self):
normals = numpy.copy(self._data)
normals[:,1] = 0.0 # We are only interested in 2D normals
# Calculate the edges between points.
# The call to numpy.roll shifts the entire array by one so that
# we end up subtracting each next point from the current, wrapping
# around. This gives us the edges from the next point to the current
# point.
normals[:] = normals[:] - numpy.roll(normals, -1, axis = 0)
# Calculate the length of each edge using standard Pythagoras
lengths = numpy.sqrt(normals[:,0] ** 2 + normals[:,2] ** 2)
# The normal of a 2D vector is equal to its x and y coordinates swapped
# and then x inverted. This code does that.
normals[:,[0, 2]] = normals[:,[2, 0]]
normals[:,0] *= -1
# Normalize the normals.
normals[:,0] /= lengths
normals[:,2] /= lengths
return normals

View file

@ -0,0 +1,104 @@
syntax = "proto3";
package cura.proto;
message ObjectList
{
repeated Object objects = 1;
repeated Setting settings = 2;
}
// typeid 1
message Slice
{
repeated ObjectList object_lists = 1;
}
message Object
{
int64 id = 1;
bytes vertices = 2; //An array of 3 floats.
bytes normals = 3; //An array of 3 floats.
bytes indices = 4; //An array of ints.
repeated Setting settings = 5; // Setting override per object, overruling the global settings.
}
// typeid 3
message Progress
{
float amount = 1;
}
// typeid 2
message SlicedObjectList
{
repeated SlicedObject objects = 1;
}
message SlicedObject
{
int64 id = 1;
repeated Layer layers = 2;
}
message Layer {
int32 id = 1;
float height = 2;
float thickness = 3;
repeated Polygon polygons = 4;
}
message Polygon {
enum Type {
NoneType = 0;
Inset0Type = 1;
InsetXType = 2;
SkinType = 3;
SupportType = 4;
SkirtType = 5;
InfillType = 6;
SupportInfillType = 7;
MoveCombingType = 8;
MoveRetractionType = 9;
}
Type type = 1;
bytes points = 2;
float line_width = 3;
}
// typeid 4
message GCodeLayer {
int64 id = 1;
bytes data = 2;
}
// typeid 5
message ObjectPrintTime {
int64 id = 1;
float time = 2;
float material_amount = 3;
}
// typeid 6
message SettingList {
repeated Setting settings = 1;
}
message Setting {
string name = 1;
bytes value = 2;
}
// typeid 7
message GCodePrefix {
bytes data = 2;
}
// typeid 8
message SlicingFinished {
}

View file

@ -13,6 +13,7 @@ from UM.Qt.Bindings.BackendProxy import BackendState #To determine the state of
from UM.Resources import Resources from UM.Resources import Resources
from UM.Settings.SettingOverrideDecorator import SettingOverrideDecorator from UM.Settings.SettingOverrideDecorator import SettingOverrideDecorator
from UM.Message import Message from UM.Message import Message
from UM.PluginRegistry import PluginRegistry
from cura.OneAtATimeIterator import OneAtATimeIterator from cura.OneAtATimeIterator import OneAtATimeIterator
from . import Cura_pb2 from . import Cura_pb2
@ -62,12 +63,12 @@ class CuraEngineBackend(Backend):
self._change_timer.setSingleShot(True) self._change_timer.setSingleShot(True)
self._change_timer.timeout.connect(self.slice) self._change_timer.timeout.connect(self.slice)
self._message_handlers[Cura_pb2.SlicedObjectList] = self._onSlicedObjectListMessage self._message_handlers["cura.proto.SlicedObjectList"] = self._onSlicedObjectListMessage
self._message_handlers[Cura_pb2.Progress] = self._onProgressMessage self._message_handlers["cura.proto.Progress"] = self._onProgressMessage
self._message_handlers[Cura_pb2.GCodeLayer] = self._onGCodeLayerMessage self._message_handlers["cura.proto.GCodeLayer"] = self._onGCodeLayerMessage
self._message_handlers[Cura_pb2.GCodePrefix] = self._onGCodePrefixMessage self._message_handlers["cura.proto.GCodePrefix"] = self._onGCodePrefixMessage
self._message_handlers[Cura_pb2.ObjectPrintTime] = self._onObjectPrintTimeMessage self._message_handlers["cura.proto.ObjectPrintTime"] = self._onObjectPrintTimeMessage
self._message_handlers[Cura_pb2.SlicingFinished] = self._onSlicingFinishedMessage self._message_handlers["cura.proto.SlicingFinished"] = self._onSlicingFinishedMessage
self._slicing = False self._slicing = False
self._restart = False self._restart = False
@ -230,16 +231,7 @@ class CuraEngineBackend(Backend):
self.printDurationMessage.emit(message.time, message.material_amount) self.printDurationMessage.emit(message.time, message.material_amount)
def _createSocket(self): def _createSocket(self):
super()._createSocket() super()._createSocket(os.path.abspath(os.path.join(PluginRegistry.getInstance().getPluginPath(self.getPluginId()), "Cura.proto")))
self._socket.registerMessageType(1, Cura_pb2.Slice)
self._socket.registerMessageType(2, Cura_pb2.SlicedObjectList)
self._socket.registerMessageType(3, Cura_pb2.Progress)
self._socket.registerMessageType(4, Cura_pb2.GCodeLayer)
self._socket.registerMessageType(5, Cura_pb2.ObjectPrintTime)
self._socket.registerMessageType(6, Cura_pb2.SettingList)
self._socket.registerMessageType(7, Cura_pb2.GCodePrefix)
self._socket.registerMessageType(8, Cura_pb2.SlicingFinished)
## Manually triggers a reslice ## Manually triggers a reslice
def forceSlice(self): def forceSlice(self):
@ -278,7 +270,6 @@ class CuraEngineBackend(Backend):
else: else:
self._layer_view_active = False self._layer_view_active = False
def _onInstanceChanged(self): def _onInstanceChanged(self):
self._terminate() self._terminate()
self.slicingCancelled.emit() self.slicingCancelled.emit()

View file

@ -56,21 +56,27 @@ class ProcessSlicedObjectListJob(Job):
layer_data = LayerData.LayerData() layer_data = LayerData.LayerData()
layer_count = 0 layer_count = 0
for object in self._message.objects: for i in range(self._message.repeatedMessageCount("objects")):
layer_count += len(object.layers) layer_count += self._message.getRepeatedMessage("objects", i).repeatedMessageCount("layers")
current_layer = 0 current_layer = 0
for object in self._message.objects: for i in range(self._message.repeatedMessageCount("objects")):
object = self._message.getRepeatedMessage("objects", i)
try: try:
node = object_id_map[object.id] node = object_id_map[object.id]
except KeyError: except KeyError:
continue continue
for layer in object.layers: for l in range(object.repeatedMessageCount("layers")):
layer = object.getRepeatedMessage("layers", l)
layer_data.addLayer(layer.id) layer_data.addLayer(layer.id)
layer_data.setLayerHeight(layer.id, layer.height) layer_data.setLayerHeight(layer.id, layer.height)
layer_data.setLayerThickness(layer.id, layer.thickness) layer_data.setLayerThickness(layer.id, layer.thickness)
for polygon in layer.polygons:
for p in range(layer.repeatedMessageCount("polygons")):
polygon = layer.getRepeatedMessage("polygons", p)
points = numpy.fromstring(polygon.points, dtype="i8") # Convert bytearray to numpy array points = numpy.fromstring(polygon.points, dtype="i8") # Convert bytearray to numpy array
points = points.reshape((-1,2)) # We get a linear list of pairs that make up the points, so make numpy interpret them correctly. points = points.reshape((-1,2)) # We get a linear list of pairs that make up the points, so make numpy interpret them correctly.
points = numpy.asarray(points, dtype=numpy.float32) points = numpy.asarray(points, dtype=numpy.float32)
@ -83,8 +89,6 @@ class ProcessSlicedObjectListJob(Job):
layer_data.addPolygon(layer.id, polygon.type, points, polygon.line_width) layer_data.addPolygon(layer.id, polygon.type, points, polygon.line_width)
Job.yieldThread()
current_layer += 1 current_layer += 1
progress = (current_layer / layer_count) * 100 progress = (current_layer / layer_count) * 100
# TODO: Rebuild the layer data mesh once the layer has been processed. # TODO: Rebuild the layer data mesh once the layer has been processed.

View file

@ -81,20 +81,21 @@ class StartSliceJob(Job):
self._sendSettings(self._profile) self._sendSettings(self._profile)
slice_message = Cura_pb2.Slice() slice_message = self._socket.createMessage("cura.proto.Slice");
for group in object_groups: for group in object_groups:
group_message = slice_message.object_lists.add() group_message = slice_message.addRepeatedMessage("object_lists");
for object in group: for object in group:
mesh_data = object.getMeshData().getTransformed(object.getWorldTransformation()) mesh_data = object.getMeshData().getTransformed(object.getWorldTransformation())
obj = group_message.objects.add() obj = group_message.addRepeatedMessage("objects");
obj.id = id(object) obj.id = id(object)
verts = numpy.array(mesh_data.getVertices()) verts = numpy.array(mesh_data.getVertices())
verts[:,[1,2]] = verts[:,[2,1]] verts[:,[1,2]] = verts[:,[2,1]]
verts[:,1] *= -1 verts[:,1] *= -1
obj.vertices = verts.tostring()
obj.vertices = verts
self._handlePerObjectSettings(object, obj) self._handlePerObjectSettings(object, obj)
@ -115,13 +116,13 @@ class StartSliceJob(Job):
return str(value).encode("utf-8") return str(value).encode("utf-8")
def _sendSettings(self, profile): def _sendSettings(self, profile):
msg = Cura_pb2.SettingList() msg = self._socket.createMessage("cura.proto.SettingList");
settings = profile.getAllSettingValues(include_machine = True) settings = profile.getAllSettingValues(include_machine = True)
start_gcode = settings["machine_start_gcode"] start_gcode = settings["machine_start_gcode"]
settings["material_bed_temp_prepend"] = "{material_bed_temperature}" not in start_gcode settings["material_bed_temp_prepend"] = "{material_bed_temperature}" not in start_gcode
settings["material_print_temp_prepend"] = "{material_print_temperature}" not in start_gcode settings["material_print_temp_prepend"] = "{material_print_temperature}" not in start_gcode
for key, value in settings.items(): for key, value in settings.items():
s = msg.settings.add() s = msg.addRepeatedMessage("settings")
s.name = key s.name = key
if key == "machine_start_gcode" or key == "machine_end_gcode": if key == "machine_start_gcode" or key == "machine_end_gcode":
s.value = self._expandGcodeTokens(key, value, settings) s.value = self._expandGcodeTokens(key, value, settings)
@ -134,7 +135,7 @@ class StartSliceJob(Job):
profile = node.callDecoration("getProfile") profile = node.callDecoration("getProfile")
if profile: if profile:
for key, value in profile.getAllSettingValues().items(): for key, value in profile.getAllSettingValues().items():
setting = message.settings.add() setting = message.addRepeatedMessage("settings")
setting.name = key setting.name = key
setting.value = str(value).encode() setting.value = str(value).encode()
@ -145,7 +146,7 @@ class StartSliceJob(Job):
return return
for key, value in object_settings.items(): for key, value in object_settings.items():
setting = message.settings.add() setting = message.addRepeatedMessage("settings")
setting.name = key setting.name = key
setting.value = str(value).encode() setting.value = str(value).encode()