#---------------------------------------------------------------------- # Linear blending - second version # # Copyright (C) November 15, 2017 -- Dr. William T. Verts #---------------------------------------------------------------------- import time #********************************************************************** # Helper Functions #********************************************************************** #---------------------------------------------------------------------- # Return closest integer to N #---------------------------------------------------------------------- def INT (N): return int(round(N)) #---------------------------------------------------------------------- # Plot a centered circle at with radius R. Coordinates may be # either ints or floats; if floats the closest integer is used. #---------------------------------------------------------------------- def addCircleFilled (Canvas, X, Y, R, NewColor=black): addOvalFilled(Canvas, INT(X-R), INT(Y-R), INT(2*R), INT(2*R), NewColor) return #---------------------------------------------------------------------- # Plot a centered circle at 2D point P with radius R # Point P is a list [X,Y], where X is at P[0] and Y is at P[1] #---------------------------------------------------------------------- def addCircleFilledPoint (Canvas, P, R, NewColor=black): addCircleFilled(Canvas, P[0], P[1], R, NewColor) return #---------------------------------------------------------------------- # Compute the Euclidean distance between 2D points P0 and P1. # P0 and P1 are both [X,Y] lists. #---------------------------------------------------------------------- def DistancePoints2D (P0,P1): DeltaX = P1[0] - P0[0] DeltaY = P1[1] - P0[1] return math.sqrt(DeltaX*DeltaX + DeltaY*DeltaY) #---------------------------------------------------------------------- # Compute the Euclidean distance between points P0 and P1. # P0 and P1 are both lists, but may be of any number of dimensions. #---------------------------------------------------------------------- def DistancePoints (P0,P1): Total = 0.0 for I in range(min(len(P0),len(P1))): Delta = P1[I] - P0[I] Total = Total + Delta * Delta return math.sqrt(Total) #********************************************************************** # Blending Functions #********************************************************************** #---------------------------------------------------------------------- # Blend linearly between numbers P0 and P1 (which may be either ints # or floats). A float is always returned. #---------------------------------------------------------------------- def Blend (P0,P1,T): return (P1 - P0) * float(T) + P0 #---------------------------------------------------------------------- # Blend linearly between numbers P0 and P1 (which may be either ints # or floats). The closest integer is always returned. #---------------------------------------------------------------------- def BlendInt (P0,P1,T): return INT(Blend(P0,P1,T)) #---------------------------------------------------------------------- # Blend linearly between points P0 and P1 (which may be of any number # of dimensions). #---------------------------------------------------------------------- def BlendPoints (P0,P1,T): return [Blend(P0[I],P1[I],T) for I in range(min(len(P0),len(P1)))] #---------------------------------------------------------------------- # Blend linearly between two JES colors. #---------------------------------------------------------------------- def BlendColor (C0,C1,T): R = BlendInt(C0.getRed(), C1.getRed(), T) G = BlendInt(C0.getGreen(), C1.getGreen(), T) B = BlendInt(C0.getBlue(), C1.getBlue(), T) return makeColor(R,G,B) #********************************************************************** # Test program. Draw a line between P0 and P1, where P0 has color C0 # and P1 has color C1. Number of steps is chosen adaptively, based on # the distance between P0 and P1 and the radius of the plotted circle. #********************************************************************** def Main(): Canvas = makeEmptyPicture(800,600) show(Canvas) P0 = [200,50] P1 = [700,500] C0 = red C1 = green R = 3 # Point radius Steps = INT(DistancePoints(P0,P1) / R) # Number of points to plot, minus 1 for I in range(Steps+1): # Step through all points: T = float(I) / Steps # Turn step number into parameter P = BlendPoints(P0,P1,T) # Interpolate the point position C = BlendColor(C0,C1,T) # Interpolate the color addCircleFilledPoint(Canvas, P, R, C) # Plot the point repaint(Canvas) time.sleep(0.005) return