def calculate_point_height(self, x, y, func): point = Point(x, y, self.outer.minz) if not self.outer.is_point_inside(point): return None for poly in self.inner: if poly.is_point_inside(point): return None point = Point(x, y, self.outer.minz) line_distances = [] for line in self.lines: cross_product = line.dir.cross(point.sub(line.p1)) if cross_product.z > 0: close_points = [] close_point = line.closest_point(point) if not line.is_point_inside(close_point): close_points.append(line.p1) close_points.append(line.p2) else: close_points.append(close_point) for p in close_points: direction = point.sub(p) dist = direction.norm line_distances.append(dist) elif cross_product.z == 0: # the point is on the line line_distances.append(0.0) # no other line can get closer than this break else: # the point is in the left of this line pass line_distances.sort() return self.z_level + func(line_distances[0])
def draw_direction_cone(p1, p2, position=0.5, precision=12, size=0.1): # convert p1 and p2 from list/tuple to Point if not hasattr(p1, "sub"): p1 = Point(*p1) if not hasattr(p2, "sub"): p2 = Point(*p2) distance = p2.sub(p1) length = distance.norm direction = distance.normalized() if direction is None: # zero-length line return cone_length = length * size cone_radius = cone_length / 3.0 # move the cone to the middle of the line GL.glTranslatef((p1.x + p2.x) * position, (p1.y + p2.y) * position, (p1.z + p2.z) * position) # rotate the cone according to the line direction # The cross product is a good rotation axis. cross = direction.cross(Point(0, 0, -1)) if cross.norm != 0: # The line direction is not in line with the z axis. try: angle = math.asin(sqrt(direction.x**2 + direction.y**2)) except ValueError: # invalid angle - just ignore this cone return # convert from radians to degree angle = angle / math.pi * 180 if direction.z < 0: angle = 180 - angle GL.glRotatef(angle, cross.x, cross.y, cross.z) elif direction.z == -1: # The line goes down the z axis - turn it around. GL.glRotatef(180, 1, 0, 0) else: # The line goes up the z axis - nothing to be done. pass # center the cone GL.glTranslatef(0, 0, -cone_length * position) # draw the cone GLUT.glutSolidCone(cone_radius, cone_length, precision, 1)
def draw_direction_cone(p1, p2, position=0.5, precision=12, size=0.1): # convert p1 and p2 from list/tuple to Point if not hasattr(p1, "sub"): p1 = Point(*p1) if not hasattr(p2, "sub"): p2 = Point(*p2) distance = p2.sub(p1) length = distance.norm direction = distance.normalized() if direction is None: # zero-length line return cone_length = length * size cone_radius = cone_length / 3.0 # move the cone to the middle of the line GL.glTranslatef((p1.x + p2.x) * position, (p1.y + p2.y) * position, (p1.z + p2.z) * position) # rotate the cone according to the line direction # The cross product is a good rotation axis. cross = direction.cross(Point(0, 0, -1)) if cross.norm != 0: # The line direction is not in line with the z axis. try: angle = math.asin(sqrt(direction.x ** 2 + direction.y ** 2)) except ValueError: # invalid angle - just ignore this cone return # convert from radians to degree angle = angle / math.pi * 180 if direction.z < 0: angle = 180 - angle GL.glRotatef(angle, cross.x, cross.y, cross.z) elif direction.z == -1: # The line goes down the z axis - turn it around. GL.glRotatef(180, 1, 0, 0) else: # The line goes up the z axis - nothing to be done. pass # center the cone GL.glTranslatef(0, 0, -cone_length * position) # draw the cone GLUT.glutSolidCone(cone_radius, cone_length, precision, 1)
def get_moves(self, safety_height, max_movement=None): class MoveContainer(object): def __init__(self, max_movement): self.max_movement = max_movement self.moved_distance = 0 self.moves = [] self.last_pos = None if max_movement is None: self.append = self.append_without_movement_limit else: self.append = self.append_with_movement_limit def append_with_movement_limit(self, new_position, rapid): if self.last_pos is None: # first move with unknown start position - ignore it self.moves.append((new_position, rapid)) self.last_pos = new_position return True else: distance = new_position.sub(self.last_pos).norm if self.moved_distance + distance > self.max_movement: partial = (self.max_movement - self.moved_distance) / \ distance partial_dest = self.last_pos.add( new_position.sub(self.last_pos).mul(partial)) self.moves.append((partial_dest, rapid)) self.last_pos = partial_dest # we are finished return False else: self.moves.append((new_position, rapid)) self.moved_distance += distance self.last_pos = new_position return True def append_without_movement_limit(self, new_position, rapid): self.moves.append((new_position, rapid)) return True p_last = None result = MoveContainer(max_movement) for path in self.paths: if not path: # ignore empty paths continue p_next = path.points[0] if p_last is None: p_last = Point(p_next.x, p_next.y, safety_height) if not result.append(p_last, True): return result.moves if ((abs(p_last.x - p_next.x) > epsilon) \ or (abs(p_last.y - p_next.y) > epsilon)): # Draw the connection between the last and the next path. # Respect the safety height. if (abs(p_last.z - p_next.z) > epsilon) \ or (p_last.sub(p_next).norm > \ self._max_safe_distance + epsilon): # The distance between these two points is too far. # This condition helps to prevent moves up/down for # adjacent lines. safety_last = Point(p_last.x, p_last.y, safety_height) safety_next = Point(p_next.x, p_next.y, safety_height) if not result.append(safety_last, True): return result.moves if not result.append(safety_next, True): return result.moves for p in path.points: if not result.append(p, False): return result.moves p_last = path.points[-1] if not p_last is None: p_last_safety = Point(p_last.x, p_last.y, safety_height) result.append(p_last_safety, True) return result.moves
def get_moves(self, safety_height, max_movement=None): class MoveContainer(object): def __init__(self, max_movement): self.max_movement = max_movement self.moved_distance = 0 self.moves = [] self.last_pos = None if max_movement is None: self.append = self.append_without_movement_limit else: self.append = self.append_with_movement_limit def append_with_movement_limit(self, new_position, rapid): if self.last_pos is None: # first move with unknown start position - ignore it self.moves.append((new_position, rapid)) self.last_pos = new_position return True else: distance = new_position.sub(self.last_pos).norm if self.moved_distance + distance > self.max_movement: partial = (self.max_movement - self.moved_distance) / \ distance partial_dest = self.last_pos.add(new_position.sub( self.last_pos).mul(partial)) self.moves.append((partial_dest, rapid)) self.last_pos = partial_dest # we are finished return False else: self.moves.append((new_position, rapid)) self.moved_distance += distance self.last_pos = new_position return True def append_without_movement_limit(self, new_position, rapid): self.moves.append((new_position, rapid)) return True p_last = None max_safe_distance = 2 * self.toolpath_settings.get_tool().radius \ + epsilon result = MoveContainer(max_movement) for path in self.get_paths(): if not path: # ignore empty paths continue p_next = path.points[0] if p_last is None: p_last = Point(p_next.x, p_next.y, safety_height) if not result.append(p_last, True): return result.moves if ((abs(p_last.x - p_next.x) > epsilon) \ or (abs(p_last.y - p_next.y) > epsilon)): # Draw the connection between the last and the next path. # Respect the safety height. if (abs(p_last.z - p_next.z) > epsilon) \ or (p_last.sub(p_next).norm > max_safe_distance): # The distance between these two points is too far. # This condition helps to prevent moves up/down for # adjacent lines. safety_last = Point(p_last.x, p_last.y, safety_height) safety_next = Point(p_next.x, p_next.y, safety_height) if not result.append(safety_last, True): return result.moves if not result.append(safety_next, True): return result.moves for p in path.points: if not result.append(p, False): return result.moves p_last = path.points[-1] if not p_last is None: p_last_safety = Point(p_last.x, p_last.y, safety_height) result.append(p_last_safety, True) return result.moves