def intersect_line(self, other_line, projection=False): '''Find intersection point (X, Y) for two lines. Returns Void() point if lines do not intersect.''' diff_x = Point(self.p0.x - self.p1.x, other_line.p0.x - other_line.p1.x) diff_y = Point(self.p0.y - self.p1.y, other_line.p0.y - other_line.p1.y) div = diff_x | diff_y if div == 0: return Void() # (None, None) d = Point(self.p0 | self.p1, other_line.p0 | other_line.p1) x = (d | diff_x) / div y = (d | diff_y) / div if projection: return Point(x, y) else: if self.hasPoint(Point(x, y)) and other_line.hasPoint(Point(x, y)): return Point(x, y) return Void() # (None, None)
def shift(self, delta_x, delta_y): '''Shift the layer by given amout''' for node in self.nodes: node.point += Point(delta_x, delta_y)
w0 = max(a0, key=lambda i: i[0])[0] - min(a0, key=lambda i: i[0])[0] w1 = max(a0, key=lambda i: i[1])[1] - min(a0, key=lambda i: i[1])[1] h0 = max(a1, key=lambda i: i[0])[0] - min(a0, key=lambda i: i[0])[0] h1 = max(a1, key=lambda i: i[1])[1] - min(a0, key=lambda i: i[1])[1] sx, sy = utils.adjuster(((w0, w1), (h0, h1)), scale_or_dimension, (ntx, nty), (dx, dy), (a0[0][2], a0[0][3], a1[0][2], a1[0][3])) result = map( lambda arr: self.__delta_scale(arr[0], arr[1], ntx, nty, sx, sy, cx, cy, dx, dy, i), process_array) return result if __name__ == '__main__': arr = PointArray([Point(10, 10), Point(740, 570), Point(70, 50)]) points = [[(10, 10), (20, 20), (60, 60)], [(30, 30), (40, 40), (70, 70)], [(50, 50), (60, 60), (80, 80)]] stems = [[(10, 20)], [(30, 50)], [(80, 90)]] arr_lerp = DeltaArray(points) a = DeltaScale(points, stems) b = DeltaScale(a) #print(a.scale_by_time((1,1), (1,3), (1.0, 1.0), (0,0), 0)) #print(a.scale_by_stem((40,25), (1,3), (1.0, 1.0), (0,0), 0)) print(a.x)
def solve_tunni(self): '''Make proportional handles keeping curvature and on-curve point positions Based on modified Andres Torresi implementation of Eduardo Tunni's method for control points ''' practicalInfinity = Point(100000, 100000) # - Helper functions def getCrossing(p0, p1, p2, p3): # - Init diffA = p1 - p0 # p1.x - p0.x, p1.y - p0.y prodA = p1 & Point(p0.y, -p0.x) # p1.x * p0.y - p0.x * p1.y diffB = p3 - p2 prodB = p3 & Point(p2.y, -p2.x) # - Get intersection det = diffA & Point( diffB.y, -diffB.x) # diffA.x * diffB.y - diffB.x * diffA.y x = diffB.x * prodA - diffA.x * prodB y = diffB.y * prodA - diffA.y * prodB try: return Point(x / det, y / det) except ZeroDivisionError: return practicalInfinity def setProportion(pointA, pointB, prop): # - Set proportions according to Edaurdo Tunni sign = lambda x: (1, -1)[x < 0] # Helper function xDiff = max(pointA.x, pointB.x) - min(pointA.x, pointB.x) yDiff = max(pointA.y, pointB.y) - min(pointA.y, pointB.y) xEnd = pointA.x + xDiff * prop * sign(pointB.x - pointA.x) yEnd = pointA.y + yDiff * prop * sign(pointB.y - pointA.y) return Point(xEnd, yEnd) # - Run ------------------ # -- Init crossing = getCrossing(self.p3, self.p2, self.p0, self.p1) if crossing != practicalInfinity: node2extrema = math.hypot(self.p3.x - crossing.x, self.p3.y - crossing.y) node2bcp = math.hypot(self.p3.x - self.p2.x, self.p3.y - self.p2.y) proportion = (node2bcp / node2extrema) # -- Calculate bcp2b = setProportion(self.p0, crossing, proportion) propA = math.hypot( self.p0.x - self.p1.x, self.p0.y - self.p1.y) / math.hypot( self.p0.x - crossing.x, self.p0.y - crossing.y) propB = math.hypot( self.p0.x - bcp2b.x, self.p0.y - bcp2b.y) / math.hypot( self.p0.x - crossing.x, self.p0.y - crossing.y) propMean = (propA + propB) / 2 bcp2c = setProportion(self.p0, crossing, propMean) bcp1b = setProportion(self.p3, crossing, propMean) return self.__class__(self.p0.tuple, (bcp2c.x, bcp2c.y), (bcp1b.x, bcp1b.y), self.p3.tuple) else: return None
def max_point(self): return Point(self.xmax, self.ymax)
def min_point(self): return Point(self.x, self.y)
def point(self): return Point(self.x, self.y, angle=self.angle, transform=self.transform, complex=self.complex_math)
def func(scale=(1.,1.), time=(0.,0.), transalte=(0.,0.), angle=0., compensate=(0.,0.)): self.point = Point(adaptive_scale(((x0, y0), (x1, y1)), scale, transalte, time, compensate, angle, weights))
def func(tx, ty): self.point = Point(lerp(x0, x1, tx), lerp(y0, y1, ty))
def shift(self, delta_x, delta_y): '''Shift the node by given amout''' self.point += Point(delta_x, delta_y)
def reloc(self, new_x, new_y): '''Relocate the node to new coordinates''' self.point = Point(new_x, new_y)
@staticmethod def to_XML(self): raise NotImplementedError @staticmethod def from_XML(string): raise NotImplementedError if __name__ == '__main__': # - Test initialization, normal and from VFJ n0 = Node.from_VFJ('10 20 s g2') n1 = Node.from_VFJ('20 30 s') n2 = Node(35, 55.65) n3 = Node(44, 67, type='smooth') n4 = Node(n3) print(n3, n4) # - Test math and VFJ export n3.point = Point(34,88) n3.point += 30 print(n3.to_VFJ()) # - Test Containers and VFJ export c = Container([n0, n1, n2, n3, n4], default_factory=Node) c.append((99,99)) print(n0) n0.lerp_to(n1, (.5,.5)) print(n0)
def lerp_xy(self, time_x, time_y) : return Point(self.p0.x * (1. - time_x) + self.p1.x * time_x, self.p0.y * (1 - time_y) + self.p1.y * time_y)
def __init__(self, data, useVoid=False): if not isMultiInstance(data, Point): data = [Point(item) for item in data] super(PointArray, self).__init__(data) self.__useVoid = useVoid
def func(tx, ty): for idx in range(len(self.nodes)): self.nodes[idx].point = Point( lerp(node_array[idx][0].x, node_array[idx][1].x, tx), lerp(node_array[idx][0].y, node_array[idx][1].y, ty))
@property def angle(self): return self._angle @angle.setter def angle(self, value): self._angle = value @property def slope(self): return self._slope @slope.setter def slope(self, value): self._slope = value # - Getters def getSlope(self): try: return self.diff_y / float(self.diff_x) except ZeroDivisionError: return float('nan') def getAngle(self): return math.degrees(math.atan2(self.diff_y, self.diff_x)) if __name__ == '__main__': a = Line(Point(0, 0), Point(4, 0)) b = a.solve_length(10, -1) print(a.length, b.length, a, b)