def add_cutout(self, kind, corner_1, corner_2, bb_inner='sw', name=None, rotate=0, flipxy=False): import copy c1 = copy.copy(corner_1) c2 = copy.copy(corner_2) # Change signs so positive relative movements go into the side if 'n' in bb_inner: c1.y = -corner_1.y c2.y = -corner_2.y if 'e' in bb_inner: c1.x = -corner_1.x c2.x = -corner_2.x if flipxy: c1 = Point(c1.y, c1.x) c2 = Point(c2.y, c2.x) bb = self.inner_bounding_box[bb_inner] c1 = c1.relative_to(bb) c2 = c2.relative_to(bb) c1.rotate(rotate, bb) c2.rotate(rotate, bb) self.cutouts.append((kind, name, c1, c2))
def _scale(self, point, rel, reverse, ratio): width = float(self.shape.bounds.width) height = float(self.shape.bounds.height) if ratio: old_r = self.grabbed_stamp.scale[1] / self.grabbed_stamp.scale[0] if old_r != ratio: self.grabbed_stamp.scale = (self.grabbed_stamp.scale[0], ratio * self.grabbed_stamp.scale[0]) print 'ratio:', self.grabbed_stamp.scale[1] / self.grabbed_stamp.scale[0] if reverse: anchor = Point(width/2 * self.grabbed_stamp.scale[0], height/2 * self.grabbed_stamp.scale[1]) else: anchor = Point(-width/2 * self.grabbed_stamp.scale[0], -height/2 * self.grabbed_stamp.scale[1]) anchor = Point.rotate(anchor, self.grabbed_stamp.angle) anchor.x += self.grabbed_stamp.pos.x anchor.y += self.grabbed_stamp.pos.y rel = Point(point.x - anchor.x, point.y - anchor.y) rel = Point.rotate(rel, -self.grabbed_stamp.angle) if ratio != None: a = self.grabbed_stamp.scale[0] > 0 b = rel.x < rel.y c = reverse # No, this is not pretty. But I didn't like the alternative much # either. This reassigns either the x or y value such that # rel.y / rel.x = ratio, while also indirectly keeding the anchor # 'within' rel. This creates the expeceted behavior while resizing # and keeping the ratio, even when mirrored and flipped. if ((a and b and c) or (a and not b and not c) or (not a and b and not c) or (not a and not b and c)): rel.y = ratio * rel.x elif ((a and b and not c) or (a and not b and c) or (not a and b and c) or (not a and not b and not c)): rel.x = 1 / ratio * rel.y dx = rel.x dy = rel.y if reverse: dx = -dx dy = -dy old_scale_x = self.grabbed_stamp.scale[0] old_scale_y = self.grabbed_stamp.scale[1] old_dx = width - old_scale_x * width old_dy = height - old_scale_y * height new_dx = old_dx + dx new_dy = old_dy + dy new_scale_x = (width - new_dx) / width new_scale_y = (height - new_dy) / height if abs(new_scale_x) > 0.1 and abs(new_scale_y) > 0.1: self.grabbed_stamp.scale = (new_scale_x, new_scale_y) if reverse: dx = -dx dy = -dy p = Point.rotate(Point(dx, dy), self.grabbed_stamp.angle) self.grabbed_stamp.pos.x += p.x / 2.0 self.grabbed_stamp.pos.y += p.y / 2.0
def pointWithin(self, point, size): point = point.copy() point.x -= self.pos.x point.y -= self.pos.y point = Point.rotate(point, -self.angle) # Must shift coordinates back point.x += self.pos.x point.y += self.pos.y half_width = size[0] * self.scale[0] / 2.0 half_height = size[1] * self.scale[1] / 2.0 # For mirrored position the control points are mirrored as well. hw = half_width hh = half_height half_width = abs(half_width) half_height = abs(half_height) left = self.pos.x - half_width right = self.pos.x + half_width top = self.pos.y - half_height bottom = self.pos.y + half_height if left <= point.x <= right and top <= point.y <= bottom: if left <= point.x <= left + self.control_size: if top <= point.y <= top + self.control_size: if hw >= 0: if hh >= 0: return self.SCALE_TL else: return self.ROTATE_BL else: if hh >= 0: return self.ROTATE_TR else: return self.SCALE_BR elif bottom - self.control_size <= point.y <= bottom: if hw >= 0: if hh >= 0: return self.ROTATE_BL else: return self.SCALE_TL else: if hh >= 0: return self.SCALE_BR else: return self.ROTATE_TR elif right - self.control_size <= point.x <= right: if top <= point.y <= top + self.control_size: if hw >= 0: if hh >= 0: return self.ROTATE_TR else: return self.SCALE_BR else: if hh >= 0: return self.SCALE_TL else: return self.ROTATE_BL elif bottom - self.control_size <= point.y <= bottom: if hw >= 0: if hh >= 0: return self.SCALE_BR else: return self.ROTATE_TR else: if hh >= 0: return self.ROTATE_BL else: return self.SCALE_TL # There is probably a better way to do that, but I'm not going to worry about it :) return self.TRANSLATE else: return None
def rotate_position(self, position, angle): rotated_point = Point.rotate(position, -angle) return tuple(rotated_point)