Exemple #1
0
    def __init__(self, *argv):
        if len(argv) == 1:
            if isinstance(argv[0], self.__class__):  # Clone
                self.p0, self.p1, self.p2, self.p3 = argv[0].p0, argv[
                    0].p1, argv[0].p2, argv[0].p3

            if isMultiInstance(argv[0], (tuple, list)):
                self.p0, self.p1, self.p2, self.p3 = [
                    Point(item) for item in argv[0]
                ]

        if len(argv) == 4:
            if isMultiInstance(argv, (tuple, list)):
                self.p0, self.p1, self.p2, self.p3 = [
                    Point(item) for item in argv
                ]

            if isMultiInstance(argv, Point):
                self.p0, self.p1, self.p2, self.p3 = argv

        if len(argv) == 8:
            if isMultiInstance(argv, (float, int)):
                self.p0, self.p1, self.p2, self.p3 = [
                    Point(argv[i], argv[i + 1]) for i in range(len(argv) - 1)
                ]

        self.transform = Transform()
Exemple #2
0
    def filterClosePoly(point_list, in_reverse=False, grow_value=0):
        min_x, max_x, min_y, max_y = GlyphSampler.getBounds(point_list)
        x = min_x - grow_value if not in_reverse else max_x + grow_value

        point_list.insert(0, Point(x, min_y))
        point_list.append(Point(x, max_y))

        return point_list
Exemple #3
0
	def intersect_line(self, other_line):
		'''Find intersection point (X, Y) for two lines.
		Returns (None, None) 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 (None, None)

		d = Point(self.p0 | self.p1, other_line.p0 | other_line.p1)
		x = (d | diff_x) / div
		y = (d | diff_y) / div
		return (x, y)
Exemple #4
0
	def slant_shift(self, shift_x, shift_y, angle):
		'''Slanted move - move a node (in inclined space) according to Y coordinate slanted at given angle.
		
		Arguments:
			shift_x, shift_y (float)
			angle (float): Angle in degrees
		'''
		# - Init
		new_point = Point((self.x + shift_x, self.y))
		new_point.angle = angle
		
		# - Calculate & set
		new_x = new_point.solve_width(new_point.y + shift_y)
		self.smart_reloc(new_x, self.y + shift_y)
Exemple #5
0
	def __init__(self, *args, **kwargs):
		super(Node, self).__init__(*args, **kwargs)
		self.parent = kwargs.pop('parent', None)

		# - Basics
		if len(args) == 1:
			if isinstance(args[0], self.__class__): # Clone
				self.x, self.y = args[0].x, args[0].y

			if isinstance(args[0], (tuple, list)):
				self.x, self.y = args[0]

		elif len(args) == 2:
			if isMultiInstance(args, (float, int)):
				self.x, self.y = float(args[0]), float(args[1])
		
		else:
			self.x, self.y = 0., 0.

		self.angle = kwargs.pop('angle', 0)
		self.transform = kwargs.pop('transform', Transform())
		self.complex_math = kwargs.pop('complex', True)
		self.weight = Point(kwargs.pop('weight', (0.,0.)))

		# - Metadata
		if not kwargs.pop('proxy', False): # Initialize in proxy mode
			self.type = kwargs.pop('type', node_types['on'])
			self.name = kwargs.pop('name', '')
			self.identifier = kwargs.pop('identifier', False)
			self.smooth = kwargs.pop('smooth', False)
			self.selected = kwargs.pop('selected', False)
			self.g2 = kwargs.pop('g2', False)
Exemple #6
0
	def lerp_shift(self, delta_x, delta_y):
		'''Interpolated shift aka Interpolated Nudge.
		
		Arguments:
			shift_x, shift_y (float)
		'''
		if self.is_on:
			# - Init 
			shift = Point(delta_x, delta_y)
			curr_segmet_nodes,  curr_segment = self.segment_nodes, self.segment
			prev_segment_nodes, prev_segment = self.prev_on.segment_nodes, self.prev_on.segment

			# - Process segments
			if isinstance(curr_segment, CubicBezier):
				new_curr = curr_segment.lerp_first(shift)
				
				for node, point in zip(curr_segmet_nodes, new_curr.tuple):
					node.smart_reloc(*point)
				
			# - Process segments
			if isinstance(prev_segment, CubicBezier):
				new_prev = prev_segment.lerp_last(shift)
				
				for node, point in zip(prev_segment_nodes, new_prev.tuple):
					node.smart_reloc(*point)

			if isinstance(curr_segment, Line) and isinstance(prev_segment, Line):
				self.smartShift(*shift.tuple)
Exemple #7
0
    def __init__(self, *argv):
        if len(argv) == 1:
            if isinstance(argv[0], self.__class__):  # Clone
                self.p0, self.p1 = argv[0].p0, argv[0].p1

            if isMultiInstance(argv[0], (tuple, list)):
                self.p0, self.p1 = [Point(item) for item in argv[0]]

        if len(argv) > 1:
            '''
			if isMultiInstance(argv[0], (tuple, list)):
				self.p0, self.p1 = Point(argv[0]), Point(argv[1])
			'''

            if isMultiInstance(argv, Point):
                self.p0, self.p1 = argv

            if isMultiInstance(argv, (tuple, list)):
                self.p0, self.p1 = Point(argv[0]), Point(argv[1])

            if isMultiInstance(argv, (float, int)):
                self.p0, self.p1 = Point(argv[0],
                                         argv[1]), Point(argv[2], argv[3])

        self.transform = Transform()
Exemple #8
0
        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)
Exemple #9
0
    def solve_extremes(self):
        '''Finds curve extremes and returns [(extreme_01_x, extreme_01_y, extreme_01_t)...(extreme_n_x, extreme_n_y, extreme_n_t)]'''

        tvalues, points = [], []
        x0, y0 = self.p0.x, self.p0.y
        x1, y1 = self.p1.x, self.p1.y
        x2, y2 = self.p2.x, self.p2.y
        x3, y3 = self.p3.x, self.p3.y

        for i in range(0, 2):
            if i == 0:
                b = float(6 * x0 - 12 * x1 + 6 * x2)
                a = float(-3 * x0 + 9 * x1 - 9 * x2 + 3 * x3)
                c = float(3 * x1 - 3 * x0)

            else:
                b = float(6 * y0 - 12 * y1 + 6 * y2)
                a = float(-3 * y0 + 9 * y1 - 9 * y2 + 3 * y3)
                c = float(3 * y1 - 3 * y0)

            if abs(a) < 1e-12:  # Numerical robustness
                if abs(b) < 1e-12:  # Numerical robustness
                    continue

                t = -c / b

                if 0 < t and t < 1:
                    tvalues.append(t)

                continue

            b2ac = float(b * b - 4 * c * a)

            if b2ac < 0:
                continue
            else:
                sqrtb2ac = math.sqrt(b2ac)

            t1 = (-b + sqrtb2ac) / (2 * a)
            if 0 < t1 and t1 < 1:
                tvalues.append(t1)

            t2 = (-b - sqrtb2ac) / (2 * a)
            if 0 < t2 and t2 < 1:
                tvalues.append(t2)

        for j in range(0, len(tvalues)):
            t = tvalues[j]
            mt = 1 - t
            x = (mt * mt * mt * x0) + (3 * mt * mt * t * x1) + (
                3 * mt * t * t * x2) + (t * t * t * x3)
            y = (mt * mt * mt * y0) + (3 * mt * mt * t * y1) + (
                3 * mt * t * t * y2) + (t * t * t * y3)

            points.append((Point(x, y), t))

        return points
Exemple #10
0
        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
Exemple #11
0
	def lerp_to(self, entity, time):
		'''Perform linear interpolation
		Args:
			entity -> Node or Point : Object to make delta to
			time(tx, ty) -> tuple((float, float) : Interpolation times (anisotropic X, Y) 

		Returns:
			None
		'''
		tx, ty = time
		self.point = Point(lerp(self.x, entity.x, tx), lerp(self.y, entity.y, ty))
Exemple #12
0
 def func(scale=(1., 1.),
          time=(0., 0.),
          transalte=(0., 0.),
          angle=0.,
          compensate=(0., 0.)):
     for idx in range(len(self.nodes)):
         self.nodes[idx].point = Point(
             adaptive_scale(
                 (node_array[idx][0], node_array[idx][1]), scale,
                 transalte, time, compensate, angle,
                 (node_array[idx][2][0], node_array[idx][3][0],
                  node_array[idx][2][1], node_array[idx][3][1])))
Exemple #13
0
    def solve_handle_distance_from_base(self, ratio=(.5, .5)):
        '''Finds new handle positions for given ratio from base points.'''
        from typerig.core.func.geometry import line_intersect

        handle_intersection = Point(line_intersect(*self.tuple))
        hl0i = Line(self.p0, handle_intersection)
        hl1i = Line(self.p3, handle_intersection)

        new_p1 = hl0i.solve_point(ratio[0])
        new_p2 = hl1i.solve_point(ratio[1])

        return self.__class__(self.p0.tuple, new_p1.tuple, new_p2.tuple,
                              self.p3.tuple)
Exemple #14
0
	def delta_to(self, other, scale=(1.,1.), time=(0.,0.), transalte=(0.,0.), angle=0., compensate=(0.,0.)):
		'''Perform adaptive scaling by keeping the stem/stroke weights
		Args:
			other -> Node: Object to make delta to
			scale(sx, sy) -> tuple((float, float) : Scale factors (X, Y)
			time(tx, ty) -> tuple((float, float) : Interpolation times (anisotropic X, Y) 
			translate(dx, dy) -> tuple((float, float) : Translate values (X, Y) 
			angle -> (radians) : Angle of sharing (for italic designs)  
			compensate(cx, cy) -> tuple((float, float) : Compensation factor 0.0 (no compensation) to 1.0 (full compensation) (X,Y)

		Returns:
			None
		'''
		self.point = Point(adaptive_scale(((self.x, self.y), (other.x, other.y)), scale, transalte, time, compensate, angle, (self.weight.x, self.weight.y, other.weight.x, other.weight.y)))
Exemple #15
0
    def filterBandPass(point_list,
                       cutout_depth=(10000, 10000),
                       in_reverse=False):
        min_x, max_x, min_y, max_y = GlyphSampler.getBounds(point_list)
        cutout_depth_x, cutout_depth_y = cutout_depth
        return_list = []

        cutout_value_x = [min_x, max_x
                          ][in_reverse] + cutout_depth_x * [1, -1][in_reverse]
        cutout_value_y = [min_y, max_y
                          ][in_reverse] + cutout_depth_y * [1, -1][in_reverse]

        for p in point_list:
            px, py = p.tuple
            if [px > cutout_value_x, px < cutout_value_x][in_reverse]:
                px = cutout_value_x
            if [py > cutout_value_y, py < cutout_value_y][in_reverse]:
                py = cutout_value_y

            return_list.append(Point(px, py))

        return return_list
Exemple #16
0
    def get_handle_length(self):
        '''Returns handle length and radii from base points.'''
        from typerig.core.func.geometry import line_intersect

        hl0 = Line(self.p0, self.p1)
        hl1 = Line(self.p2, self.p3)

        handle_intersection = Point(line_intersect(*self.tuple))

        hl0i = Line(self.p0, handle_intersection)
        hl1i = Line(self.p3, handle_intersection)

        radius_0 = hl0i.length if not math.isnan(hl0i.length) else 0.
        radius_1 = hl1i.length if not math.isnan(hl1i.length) else 0.

        handle_0 = hl0.length if not math.isnan(hl0.length) else 0.
        handle_1 = hl0.length if not math.isnan(hl1.length) else 0.

        #ratio_0 = ratfrac(hl0.length, radius_0, 1.)
        #ratio_1 = ratfrac(hl1.length, radius_1, 1.)

        return (radius_0, handle_0), (radius_1, handle_1)
Exemple #17
0
    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)
Exemple #18
0
 def max_point(self):
     return Point(self.xmax, self.ymax)
Exemple #19
0
 def min_point(self):
     return Point(self.x, self.y)
Exemple #20
0
	def reloc(self, new_x, new_y):
		'''Relocate the node to new coordinates'''
		self.point = Point(new_x, new_y)
Exemple #21
0
            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)
Exemple #22
0
	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)
Exemple #23
0
class Line(object):
	def __init__(self, *argv):
		if len(argv):
			if isinstance(argv[0], self.__class__): # Clone
				self.p0, self.p1 = argv[0].p0, argv[0].p1

			if isMultiInstance(argv, Point):
				self.p0, self.p1 = argv

			if isMultiInstance(argv, (tuple, list)):
				self.p0, self.p1 = Point(argv[0]), Point(argv[1])

			if isMultiInstance(argv, (float, int)):
				self.p0, self.p1 = Point(argv[0], argv[1]), Point(argv[2], argv[3])

		self.transform = Transform()

	def __add__(self, other):
		return self.__class__(self.p0 + other, self.p1 + other)

	def __sub__(self, other):
		return self.__class__(self.p0 - other, self.p1 - other)

	def __mul__(self, other):
		return self.__class__(self.p0 * other, self.p1 * other)

	__rmul__ = __mul__

	def __div__(self, other):
		return self.__class__(self.p0 / other, self.p1 / other)	

	def __and__(self, other):
		return self.intersect_line(other)

	def __repr__(self):
		return '<Line: {}, {}>'.format(self.p0.tuple, self.p1.tuple)

	# -- Properties
	@property
	def tuple(self):
		return (self.p0.tuple, self.p1.tuple)

	@property
	def points(self):
		return [self.p0, self.p1]

	@property
	def diff_x(self):		
		return self.p1.x - self.p0.x

	@property
	def diff_y(self):		
		return self.p1.y - self.p0.y

	@property
	def x(self):
		return min(self.p0.x, self.p1.x)

	@property
	def y(self):
		return min(self.p0.y, self.p1.y)

	@property
	def x_max(self):
		return max(self.p0.x, self.p1.x)

	@property
	def y_max(self):
		return max(self.p0.y, self.p1.y)

	@property
	def width(self):
		return abs(self.x_max - self.x)

	@property
	def height(self):
		return abs(self.y_max - self.y)
	
	@property
	def length(self):
		return math.hypot(self.p0.x - self.p1.x, self.p0.y - self.p1.y)

	@property
	def slope(self):
		try:
			return self.diff_y / float(self.diff_x)
		except ZeroDivisionError:
			return float('nan')

	@property
	def angle(self):
		return math.degrees(math.atan2(self.diff_y, self.diff_x))

	@property
	def y_intercept(self):
		'''Get the Y intercept of a line segment'''
		return self.p0.y - self.slope * self.p0.x if not math.isnan(self.slope) and self.slope != 0 else self.p0.y

	# -- Solvers
	def solve_y(self, x):
		'''Solve line equation for Y coordinate.'''
		return self.slope * x + self.y_intercept if not math.isnan(self.slope) and self.slope != 0 else self.p0.y
					
	def solve_x(self, y):
		'''Solve line equation for X coordinate.'''
		return (float(y) - self.y_intercept) / float(self.slope) if not math.isnan(self.slope) and self.slope != 0 else self.p0.x
		
	def solve_point(self, time):
		'''Find point on the line at given time'''
		return self.p0 * (1. - time) + self.p1 * time

	def solve_slice(self, time):
		'''Slice line at given time'''
		return self.__class__(self.p0.tuple, self.solve_point(time).tuple), self.__class__(self.solve_point(time).tuple, self.p1.tuple)

	def lerp(self, time):
		return self.solve_point(time)

	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 intersect_line(self, other_line):
		'''Find intersection point (X, Y) for two lines.
		Returns (None, None) 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 (None, None)

		d = Point(self.p0 | self.p1, other_line.p0 | other_line.p1)
		x = (d | diff_x) / div
		y = (d | diff_y) / div
		return (x, y)

	def shift(self, dx, dy):
		'''Shift coordinates by dx, dy'''
		self.p0.x += dx
		self.p1.x += dx
		self.p0.y += dy
		self.p1.y += dy

	# -- Modifiers
	def doSwap(self):
		return self.__class__(self.p1, self.p0)

	def doTransform(self, transform=None):
		if transform is None: transform = self.transform
		self.p0.doTransform(transform)
		self.p1.doTransform(transform)
Exemple #24
0
	def shift(self, delta_x, delta_y):
		'''Shift the node by given amout'''
		self.point += Point(delta_x, delta_y)
Exemple #25
0
    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
Exemple #26
0
		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))
Exemple #27
0
	def point(self):
		return Point(self.x, self.y, angle=self.angle, transform=self.transform, complex=self.complex_math)
Exemple #28
0
	@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)
	
Exemple #29
0
 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)
Exemple #30
0
		def func(tx, ty):
			self.point = Point(lerp(x0, x1, tx), lerp(y0, y1, ty))