Merge branch '2.1' of https://github.com/Ultimaker/Cura into 2.1

This commit is contained in:
Tim Kuipers 2016-03-02 15:14:33 +01:00
commit 98652fea50
5 changed files with 51 additions and 24 deletions

View File

@ -9,8 +9,10 @@ class ConvexHullDecorator(SceneNodeDecorator):
# In case of printing all at once this is the same as the convex hull. For one at the time this is the area without the head. # In case of printing all at once this is the same as the convex hull. For one at the time this is the area without the head.
self._convex_hull_boundary = None self._convex_hull_boundary = None
# In case of printing all at once this is the same as the convex hull. For one at the time this is area with full head # In case of printing all at once this is the same as the convex hull. For one at the time this is area with intersection of mirrored head
self._convex_hull_head = None self._convex_hull_head = None
# In case of printing all at once this is the same as the convex hull. For one at the time this is area with intersection of full head
self._convex_hull_head_full = None
self._convex_hull_node = None self._convex_hull_node = None
self._convex_hull_job = None self._convex_hull_job = None
@ -28,6 +30,11 @@ class ConvexHullDecorator(SceneNodeDecorator):
def getConvexHull(self): def getConvexHull(self):
return self._convex_hull return self._convex_hull
def getConvexHullHeadFull(self):
if not self._convex_hull_head_full:
return self.getConvexHull()
return self._convex_hull_head_full
def getConvexHullHead(self): def getConvexHullHead(self):
if not self._convex_hull_head: if not self._convex_hull_head:
return self.getConvexHull() return self.getConvexHull()
@ -41,6 +48,9 @@ class ConvexHullDecorator(SceneNodeDecorator):
def setConvexHullBoundary(self, hull): def setConvexHullBoundary(self, hull):
self._convex_hull_boundary = hull self._convex_hull_boundary = hull
def setConvexHullHeadFull(self, hull):
self._convex_hull_head_full = hull
def setConvexHullHead(self, hull): def setConvexHullHead(self, hull):
self._convex_hull_head = hull self._convex_hull_head = hull

View File

@ -55,12 +55,16 @@ class ConvexHullJob(Job):
# Printing one at a time and it's not an object in a group # Printing one at a time and it's not an object in a group
self._node.callDecoration("setConvexHullBoundary", copy.deepcopy(hull)) self._node.callDecoration("setConvexHullBoundary", copy.deepcopy(hull))
head_and_fans = Polygon(numpy.array(profile.getSettingValue("machine_head_with_fans_polygon"), numpy.float32)) head_and_fans = Polygon(numpy.array(profile.getSettingValue("machine_head_with_fans_polygon"), numpy.float32))
# Full head hull is used to actually check the order.
full_head_hull = hull.getMinkowskiHull(head_and_fans)
self._node.callDecoration("setConvexHullHeadFull", full_head_hull)
mirrored = copy.deepcopy(head_and_fans) mirrored = copy.deepcopy(head_and_fans)
mirrored.mirror([0, 0], [0, 1]) #Mirror horizontally. mirrored.mirror([0, 0], [0, 1]) #Mirror horizontally.
mirrored.mirror([0, 0], [1, 0]) #Mirror vertically. mirrored.mirror([0, 0], [1, 0]) #Mirror vertically.
head_and_fans = head_and_fans.intersectionConvexHulls(mirrored) head_and_fans = head_and_fans.intersectionConvexHulls(mirrored)
head_hull = hull.getMinkowskiHull(head_and_fans) # Min head hull is used for the push free
self._node.callDecoration("setConvexHullHead", head_hull) min_head_hull = hull.getMinkowskiHull(head_and_fans)
self._node.callDecoration("setConvexHullHead", min_head_hull)
hull = hull.getMinkowskiHull(Polygon(numpy.array(profile.getSettingValue("machine_head_polygon"),numpy.float32))) hull = hull.getMinkowskiHull(Polygon(numpy.array(profile.getSettingValue("machine_head_polygon"),numpy.float32)))
else: else:
self._node.callDecoration("setConvexHullHead", None) self._node.callDecoration("setConvexHullHead", None)

View File

@ -30,10 +30,11 @@ class OneAtATimeIterator(Iterator.Iterator):
self._node_stack = node_list[:] self._node_stack = node_list[:]
return return
# Copy the list
self._original_node_list = node_list[:] self._original_node_list = node_list[:]
## Initialise the hit map (pre-compute all hits between all objects) ## Initialise the hit map (pre-compute all hits between all objects)
self._hit_map = [[self._checkHit(j,i) for i in node_list] for j in node_list] self._hit_map = [[self._checkHit(i,j) for i in node_list] for j in node_list]
# Check if we have to files that block eachother. If this is the case, there is no solution! # Check if we have to files that block eachother. If this is the case, there is no solution!
for a in range(0,len(node_list)): for a in range(0,len(node_list)):
@ -69,14 +70,16 @@ class OneAtATimeIterator(Iterator.Iterator):
def _checkHitMultiple(self, node, other_nodes): def _checkHitMultiple(self, node, other_nodes):
node_index = self._original_node_list.index(node) node_index = self._original_node_list.index(node)
for other_node in other_nodes: for other_node in other_nodes:
if self._hit_map[node_index][self._original_node_list.index(other_node)]: other_node_index = self._original_node_list.index(other_node)
if self._hit_map[node_index][other_node_index]:
return True return True
return False return False
def _checkBlockMultiple(self, node, other_nodes): def _checkBlockMultiple(self, node, other_nodes):
node_index = self._original_node_list.index(node) node_index = self._original_node_list.index(node)
for other_node in other_nodes: for other_node in other_nodes:
if self._hit_map[self._original_node_list.index(other_node)][node_index] and node_index != self._original_node_list.index(other_node): other_node_index = self._original_node_list.index(other_node)
if self._hit_map[other_node_index][node_index] and node_index != other_node_index:
return True return True
return False return False
@ -91,7 +94,7 @@ class OneAtATimeIterator(Iterator.Iterator):
if a == b: if a == b:
return False return False
overlap = a.callDecoration("getConvexHullBoundary").intersectsPolygon(b.callDecoration("getConvexHullHead")) overlap = a.callDecoration("getConvexHullBoundary").intersectsPolygon(b.callDecoration("getConvexHullHeadFull"))
if overlap: if overlap:
return True return True
else: else:

View File

@ -4,6 +4,7 @@
from UM.Application import Application #To get the machine manager to create the new profile in. from UM.Application import Application #To get the machine manager to create the new profile in.
from UM.Settings.Profile import Profile from UM.Settings.Profile import Profile
from UM.Settings.ProfileReader import ProfileReader from UM.Settings.ProfileReader import ProfileReader
from UM.Logger import Logger
import re #Regular expressions for parsing escape characters in the settings. import re #Regular expressions for parsing escape characters in the settings.
## A class that reads profile data from g-code files. ## A class that reads profile data from g-code files.
@ -40,6 +41,9 @@ class GCodeProfileReader(ProfileReader):
# specified file was no g-code or contained no parsable profile, \code # specified file was no g-code or contained no parsable profile, \code
# None \endcode is returned. # None \endcode is returned.
def read(self, file_name): def read(self, file_name):
if file_name.split(".")[-1] != "gcode":
return None
prefix = ";SETTING_" + str(GCodeProfileReader.version) + " " prefix = ";SETTING_" + str(GCodeProfileReader.version) + " "
prefix_length = len(prefix) prefix_length = len(prefix)
@ -62,6 +66,10 @@ class GCodeProfileReader(ProfileReader):
profile = Profile(machine_manager = Application.getInstance().getMachineManager(), read_only = False) profile = Profile(machine_manager = Application.getInstance().getMachineManager(), read_only = False)
try: try:
profile.unserialise(serialised) profile.unserialise(serialised)
except Exception as e: #Not a valid g-code file. profile.setType(None) #Force type to none so it's correctly added.
profile.setReadOnly(False)
profile.setDirty(True)
except Exception as e: #Not a valid g-comachine_instance_profilede file.
Logger.log("e", "Unable to serialise the profile: %s", str(e))
return None return None
return profile return profile

View File

@ -63,6 +63,8 @@ class LegacyProfileReader(ProfileReader):
# file could not be read or didn't contain a valid profile, \code None # file could not be read or didn't contain a valid profile, \code None
# \endcode is returned. # \endcode is returned.
def read(self, file_name): def read(self, file_name):
if file_name.split(".")[-1] != "ini":
return None
Logger.log("i", "Importing legacy profile from file " + file_name + ".") Logger.log("i", "Importing legacy profile from file " + file_name + ".")
profile = Profile(machine_manager = Application.getInstance().getMachineManager(), read_only = False) #Create an empty profile. profile = Profile(machine_manager = Application.getInstance().getMachineManager(), read_only = False) #Create an empty profile.
@ -122,5 +124,5 @@ class LegacyProfileReader(ProfileReader):
if len(profile.getChangedSettings()) == 0: if len(profile.getChangedSettings()) == 0:
Logger.log("i", "A legacy profile was imported but everything evaluates to the defaults, creating an empty profile.") Logger.log("i", "A legacy profile was imported but everything evaluates to the defaults, creating an empty profile.")
profile.setDirty(True)
return profile return profile