mirror of
https://github.com/Ultimaker/Cura.git
synced 2025-07-11 16:57:51 -06:00
Allow to set print sequence manually
This commit is contained in:
parent
6aaee84b95
commit
2b05a370ca
53 changed files with 1021 additions and 88 deletions
88
cura/HitChecker.py
Normal file
88
cura/HitChecker.py
Normal file
|
@ -0,0 +1,88 @@
|
|||
from typing import List, Dict
|
||||
from cura.Scene.CuraSceneNode import CuraSceneNode
|
||||
|
||||
|
||||
class HitChecker:
|
||||
"""Checks if nodes can be printed without causing any collisions and interference"""
|
||||
|
||||
def __init__(self, nodes: List[CuraSceneNode]) -> None:
|
||||
self._hit_map = self._buildHitMap(nodes)
|
||||
|
||||
def anyTwoNodesBlockEachOther(self, nodes: List[CuraSceneNode]) -> bool:
|
||||
"""Returns True if any 2 nodes block each other"""
|
||||
for a in nodes:
|
||||
for b in nodes:
|
||||
if self._hit_map[a][b] and self._hit_map[b][a]:
|
||||
return True
|
||||
return False
|
||||
|
||||
def canPrintBefore(self, node: CuraSceneNode, other_nodes: List[CuraSceneNode]) -> bool:
|
||||
"""Returns True if node doesn't block other_nodes and can be printed before them"""
|
||||
no_hits = all(not self._hit_map[node][other_node] for other_node in other_nodes)
|
||||
return no_hits
|
||||
|
||||
def canPrintAfter(self, node: CuraSceneNode, other_nodes: List[CuraSceneNode]) -> bool:
|
||||
"""Returns True if node doesn't hit other nodes and can be printed after them"""
|
||||
no_hits = all(not self._hit_map[other_node][node] for other_node in other_nodes)
|
||||
return no_hits
|
||||
|
||||
def calculateScore(self, a: CuraSceneNode, b: CuraSceneNode) -> int:
|
||||
"""Calculate score simply sums the number of other objects it 'blocks'
|
||||
|
||||
:param a: node
|
||||
:param b: node
|
||||
:return: sum of the number of other objects
|
||||
"""
|
||||
|
||||
score_a = sum(self._hit_map[a].values())
|
||||
score_b = sum(self._hit_map[b].values())
|
||||
return score_a - score_b
|
||||
|
||||
def canPrintNodesInProvidedOrder(self, ordered_nodes: List[CuraSceneNode]) -> bool:
|
||||
"""Returns True If nodes don't have any hits in provided order"""
|
||||
for node_index, node in enumerate(ordered_nodes):
|
||||
nodes_before = ordered_nodes[:node_index - 1] if node_index - 1 >= 0 else []
|
||||
nodes_after = ordered_nodes[node_index + 1:] if node_index + 1 < len(ordered_nodes) else []
|
||||
if not self.canPrintBefore(node, nodes_after) or not self.canPrintAfter(node, nodes_before):
|
||||
return False
|
||||
return True
|
||||
|
||||
@staticmethod
|
||||
def _buildHitMap(nodes: List[CuraSceneNode]) -> Dict[CuraSceneNode, CuraSceneNode]:
|
||||
"""Pre-computes all hits between all objects
|
||||
|
||||
:nodes: nodes that need to be checked for collisions
|
||||
:return: dictionary where hit_map[node1][node2] is False if there node1 can be printed before node2
|
||||
"""
|
||||
hit_map = {j: {i: HitChecker._checkHit(j, i) for i in nodes} for j in nodes}
|
||||
return hit_map
|
||||
|
||||
@staticmethod
|
||||
def _checkHit(a: CuraSceneNode, b: CuraSceneNode) -> bool:
|
||||
"""Checks if a can be printed before b
|
||||
|
||||
:param a: node
|
||||
:param b: node
|
||||
:return: False if a can be printed before b
|
||||
"""
|
||||
|
||||
if a == b:
|
||||
return False
|
||||
|
||||
a_hit_hull = a.callDecoration("getConvexHullBoundary")
|
||||
b_hit_hull = b.callDecoration("getConvexHullHeadFull")
|
||||
overlap = a_hit_hull.intersectsPolygon(b_hit_hull)
|
||||
|
||||
if overlap:
|
||||
return True
|
||||
|
||||
# Adhesion areas must never overlap, regardless of printing order
|
||||
# This would cause over-extrusion
|
||||
a_hit_hull = a.callDecoration("getAdhesionArea")
|
||||
b_hit_hull = b.callDecoration("getAdhesionArea")
|
||||
overlap = a_hit_hull.intersectsPolygon(b_hit_hull)
|
||||
|
||||
if overlap:
|
||||
return True
|
||||
else:
|
||||
return False
|
Loading…
Add table
Add a link
Reference in a new issue