From 0c1aacac97d0a35b85d87c858eb27a7ddcbbc455 Mon Sep 17 00:00:00 2001 From: kijai <40791699+kijai@users.noreply.github.com> Date: Fri, 3 May 2024 22:30:50 +0300 Subject: [PATCH] Add InterpolateCoords -node --- __init__.py | 1 + nodes/curve_nodes.py | 67 +++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 67 insertions(+), 1 deletion(-) diff --git a/__init__.py b/__init__.py index 3d31d1c..c39eeb4 100644 --- a/__init__.py +++ b/__init__.py @@ -101,6 +101,7 @@ NODE_CONFIG = { "FloatToMask": {"class": FloatToMask, "name": "Float To Mask"}, "FloatToSigmas": {"class": FloatToSigmas, "name": "Float To Sigmas"}, "PlotCoordinates": {"class": PlotCoordinates, "name": "Plot Coordinates"}, + "InterpolateCoords": {"class": InterpolateCoords, "name": "Interpolate Coords"}, #experimental "StabilityAPI_SD3": {"class": StabilityAPI_SD3, "name": "Stability API SD3"}, "SoundReactive": {"class": SoundReactive, "name": "Sound Reactive"}, diff --git a/nodes/curve_nodes.py b/nodes/curve_nodes.py index 2f52540..4eee557 100644 --- a/nodes/curve_nodes.py +++ b/nodes/curve_nodes.py @@ -739,4 +739,69 @@ for example: print(tracked) - return (tracked, ) \ No newline at end of file + return (tracked, ) + +class InterpolateCoords: + + RETURN_TYPES = ("STRING",) + RETURN_NAMES = ("coordinates",) + FUNCTION = "interpolate" + CATEGORY = "KJNodes/experimental" + DESCRIPTION = """ +Interpolates coordinates based on a curve. +""" + + @classmethod + def INPUT_TYPES(s): + return { + "required": { + "coordinates": ("STRING", {"forceInput": True}), + "interpolation_curve": ("FLOAT", {"forceInput": True}), + + }, + } + + def interpolate(self, coordinates, interpolation_curve): + # Parse the JSON string to get the list of coordinates + coordinates = json.loads(coordinates.replace("'", '"')) + + # Convert the list of dictionaries to a list of (x, y) tuples for easier processing + coordinates = [(coord['x'], coord['y']) for coord in coordinates] + + # Calculate the total length of the original path + path_length = sum(np.linalg.norm(np.array(coordinates[i]) - np.array(coordinates[i-1])) for i in range(1, len(coordinates))) + + # Normalize the interpolation curve + normalized_curve = [x / path_length for x in interpolation_curve] + + # Initialize variables for interpolation + interpolated_coords = [] + current_length = 0 + current_index = 1 + + # Iterate over the normalized curve + for target_length in normalized_curve: + target_length *= path_length # Convert back to the original scale + while current_length < target_length and current_index < len(coordinates): + segment_length = np.linalg.norm(np.array(coordinates[current_index]) - np.array(coordinates[current_index-1])) + current_length += segment_length + current_index += 1 + + # Interpolate between the last two points + if current_index == 1: + interpolated_coords.append(coordinates[0]) + else: + p1, p2 = np.array(coordinates[current_index-2]), np.array(coordinates[current_index-1]) + segment_length = np.linalg.norm(p2 - p1) + if segment_length > 0: + t = (target_length - (current_length - segment_length)) / segment_length + interpolated_point = p1 + t * (p2 - p1) + interpolated_coords.append(interpolated_point.tolist()) + else: + interpolated_coords.append(p1.tolist()) + + # Convert back to string format if necessary + interpolated_coords_str = "[" + ", ".join([f"{{'x': {round(coord[0])}, 'y': {round(coord[1])}}}" for coord in interpolated_coords]) + "]" + + return (interpolated_coords_str, ) +