diff options
author | ThaHobbyist | 2025-01-16 12:08:22 +0530 |
---|---|---|
committer | ThaHobbyist | 2025-01-16 12:08:22 +0530 |
commit | 7cd9ef9d02b65c285578ef67e596d763ea3288e5 (patch) | |
tree | ba2843c0a408dc163f7f7ce6973f9dfb4467b747 | |
parent | 99722f2e24ea78f31a9b1e5209adf0024db0e09e (diff) | |
download | venturial-7cd9ef9d02b65c285578ef67e596d763ea3288e5.tar.gz venturial-7cd9ef9d02b65c285578ef67e596d763ea3288e5.tar.bz2 venturial-7cd9ef9d02b65c285578ef67e596d763ea3288e5.zip |
Implemented Algorithms for viewing different kinds of edges
-rw-r--r-- | models/edge_gen_algorithms.py | 239 | ||||
-rw-r--r-- | models/edges_panel_operators.py | 38 |
2 files changed, 191 insertions, 86 deletions
diff --git a/models/edge_gen_algorithms.py b/models/edge_gen_algorithms.py index 2cb894f..66fc830 100644 --- a/models/edge_gen_algorithms.py +++ b/models/edge_gen_algorithms.py @@ -59,85 +59,174 @@ def generate_catmull_rom_curve(resolution, points): return curve_points +def generate_arc_curve_og(resolution, points): + + if len(points) != 3: + raise ValueError("Exactly 3 points are required for Arc interpolation.") + + print(f"points ----------> {points}") + A = np.array(points[0]) # end point + B = np.array(points[1]) # handler point + C = np.array(points[2]) # end point + + def mod(v): + return np.sqrt(v[0]**2 + v[1]**2 + v[2]**2) + + u1 = (B-A) + + u = u1/mod(u1) + + w1 = np.cross(C-A, u1) + + w = w1/mod(w1) + + v = np.cross(w,u) + + b = (np.dot(B-A, u), 0) + + c = (np.dot(C-A, u), np.dot(C-A, v)) + + h = ( (c[0] - b[0]/2)**2 + c[1]**2 - (b[0]/2)**2 ) / ( 2 * c[1] ) + + Cn = A + ((b[0]/2) * u ) + (h * v) # center of the circle + + r = mod(Cn - A) # Radius of the circle + + axis = np.cross((B-A)/mod(B-A), (C-A)/mod(C-A)) + a = u + b = np.cross(axis, a) + + def arc_point(t, c, a, b, r): + return ( + c[0] + r*np.cos(t)*a[0] + r*np.sin(t)*b[0], + c[1] + r*np.cos(t)*a[1] + r*np.sin(t)*b[1], + c[2] + r*np.cos(t)*a[2] + r*np.sin(t)*b[2] + ) + + def get_arc_param(p, c, a, b, r): + k = (p[0] - c[0]) / r + R = np.sqrt(a[0]**2 + b[0]**2) + phi = np.arctan2(b[0], a[0]) + t = np.arcsin(k / R) - phi + + return t + + t1 = get_arc_param(A, Cn, a, b, r) + t2 = get_arc_param(C, Cn, a, b, r) + + e2 = 0 + e1 = 0 + if t2>t1: + e2 = t2 + e1 = t1 + else: + e2 = t1 + e1 = t2 + + d = (e2 - e1) / resolution + + curve_points = [] + i = e1 + while i <= e2: + curve_points.append(arc_point(i, Cn, a, b, r)) + i += d + + print("Completed ARC Generation") + print(f"curve_points ----------> {curve_points}") + + return curve_points + def generate_arc_curve(resolution, points): + if len(points) != 3: + raise ValueError("Exactly 3 points are required for Arc interpolation.") + + # Extract points + A = np.array(points[0]) # Start point + B = np.array(points[1]) # Control point + C = np.array(points[2]) # End point + + def normalize(v): + return v / np.linalg.norm(v) + + # Basis vectors + u = normalize(B - A) + w = normalize(np.cross(C - A, B - A)) + v = np.cross(w, u) + + # Calculate intermediate parameters + b_u = np.dot(B - A, u) + c_u = np.dot(C - A, u) + c_v = np.dot(C - A, v) + + # Compute circle center and radius + h = ((c_u - b_u / 2) ** 2 + c_v ** 2 - (b_u / 2) ** 2) / (2 * c_v) + Cn = A + (b_u / 2) * u + h * v + r = np.linalg.norm(Cn - A) + + # Calculate angle parameters for the arc + def get_arc_param(p): + dp = p - Cn + return np.arctan2(np.dot(dp, v), np.dot(dp, u)) + + t1 = get_arc_param(A) + t2 = get_arc_param(C) + + # Ensure angles are ordered correctly + if t2 < t1: + t1, t2 = t2, t1 + + # Generate arc points + t_values = np.linspace(t1, t2, resolution) + curve_points = [ + (Cn + r * np.cos(t) * u + r * np.sin(t) * v).tolist() + for t in t_values + ] + + return curve_points + +def generate_bspline_curve(resolution, verts): """ - Generate points representing an arc of a circle passing through three points in 3D space. + Generate a B-spline curve from given control points. Parameters: - p1: tuple of floats (x1, y1, z1) - First fixed point. - p2: tuple of floats (x2, y2, z2) - Control point. - p3: tuple of floats (x3, y3, z3) - Second fixed point. - resolution: int - Number of points in the output arc. + resolution (int): Number of points to generate on the B-spline curve. + verts (list of list/tuple): Control points (at least 3 points). + verts[0] and verts[-1] are endpoints, and verts[1:-1] are control points. Returns: - List of tuples representing points on the arc. + list: List of points forming the B-spline curve. """ - # Convert points to numpy arrays - p1 = np.array(points[0]) - p2 = np.array(points[1]) - p3 = np.array(points[2]) - - # Find the plane normal - v1 = p2 - p1 - v2 = p3 - p1 - normal = np.cross(v1, v2) - normal = normal / np.linalg.norm(normal) - - # Calculate the circle center and radius - def find_circle_center(p1, p2, p3): - mid1 = (p1 + p2) / 2 - mid2 = (p2 + p3) / 2 - - normal1 = np.cross(p2 - p1, normal) - normal2 = np.cross(p3 - p2, normal) - - # Set up linear equations to solve for center - A = np.array([normal1, -normal2]) - b = np.array([np.dot(normal1, mid1), np.dot(normal2, mid2)]) - - try: - center = np.linalg.lstsq(A.T, b, rcond=None)[0] - except np.linalg.LinAlgError: - raise ValueError("The points do not define a unique circle.") - return center - - center = find_circle_center(p1, p2, p3) - radius = np.linalg.norm(p1 - center) - - # Generate points on the arc - def angle_between(v1, v2): - """Calculate the angle between two vectors.""" - v1_u = v1 / np.linalg.norm(v1) - v2_u = v2 / np.linalg.norm(v2) - return np.arccos(np.clip(np.dot(v1_u, v2_u), -1.0, 1.0)) - - v_start = p1 - center - v_end = p3 - center - - theta_start = 0 - theta_end = angle_between(v_start, v_end) - - # Determine direction of rotation - if np.dot(np.cross(v_start, v_end), normal) < 0: - theta_end = -theta_end - - theta = np.linspace(theta_start, theta_end, resolution) - - arc_points = [] - for t in theta: - point = (center + np.cos(t) * v_start + np.sin(t) * np.cross(normal, v_start)) - arc_points.append(tuple(point)) - - return arc_points - - -# Example usage -# interpolation_points = [ -# (0.0, 0.0, 0.0), -# (1.0, 2.0, 0.0), -# (4.0, 2.0, 0.0), -# (7.0, 0.0, 0.0) -# ] -# resolution = 10 -# curve = generate_catmull_rom_curve(resolution, interpolation_points) -# print(curve) + if len(verts) < 3: + raise ValueError("At least 3 control points are required to generate a B-spline.") + + # Define the B-spline basis matrix + basis_matrix = np.array([ + [-1, 3, -3, 1], + [ 3, -6, 3, 0], + [-3, 0, 3, 0], + [ 1, 4, 1, 0] + ]) / 6.0 + + # Ensure verts is a numpy array + verts = np.array(verts) + + # Add extra points at the start and end to handle endpoints properly + extended_verts = np.vstack([verts[0], verts, verts[-1]]) + + # Initialize result list + bspline_points = [verts[0]] + + # Iterate through the segments formed by control points + for i in range(len(extended_verts) - 3): + # Extract 4 control points for the current segment + P = extended_verts[i:i+4] + + # Generate points for the current segment + for j in range(resolution): + t = j / (resolution - 1) # Parameter t in [0, 1] + T = np.array([t**3, t**2, t, 1]) + point = T @ basis_matrix @ P + bspline_points.append(point) + + bspline_points.append(verts[-1]) + return bspline_points diff --git a/models/edges_panel_operators.py b/models/edges_panel_operators.py index 84063a0..02632bd 100644 --- a/models/edges_panel_operators.py +++ b/models/edges_panel_operators.py @@ -279,17 +279,19 @@ def draw_p(self, context): # print(f"------> {cs.ecustom[i].edge_type}") curve_p = [] - ''' # This Piece of code is to be implemented when there is point generating alorithms for each edge type + # This Piece of code is to be implemented when there is point generating alorithms for each edge type if cs.ecustom[i].edge_type == 'SPL': - print("Using Splien Gen") + print("Using Spline Gen") curve_p = generate_catmull_rom_curve(100, verts[i]) elif cs.ecustom[i].edge_type == 'ARC': print("Using ARC Gen") - curve_p = generate_catmull_rom_curve(100, verts[i]) - else: - print("Edge type yet to implement") - ''' - curve_p = generate_catmull_rom_curve(100, verts[i]) # To be replaced with previous code block once all spline generating algorithms are implemented + curve_p = generate_arc_curve(100, verts[i]) + elif cs.ecustom[i].edge_type == 'PLY': + curve_p = verts[i] + elif cs.ecustom[i].edge_type == 'BSPL': + curve_p = generate_bspline_curve(100, verts[i]) + + # curve_p = generate_catmull_rom_curve(100, verts[i]) # To be replaced with previous code block once all spline generating algorithms are implemented # print(f"------> {catmull_p}") @@ -298,18 +300,32 @@ def draw_p(self, context): # verts[i] = [i for i in catmull_p(lin)] verts[i] = curve_p - a[i] = bpy.types.SpaceView3D.draw_handler_add(draw1, ((verts[i], i)), 'WINDOW', 'POST_VIEW') + a[i] = bpy.types.SpaceView3D.draw_handler_add(draw_edge_viewport, ((verts[i], i)), 'WINDOW', 'POST_VIEW') -def draw1(verts, index): +def draw_edge_viewport(verts, index): try: curr_spline = bpy.context.scene.ecustom[index] except Exception as e: return shader = gpu.shader.from_builtin('3D_UNIFORM_COLOR') - bgl.glLineWidth(curr_spline.size) + # bgl.glLineWidth(curr_spline.size) + col = (curr_spline.color[0], curr_spline.color[1], curr_spline.color[2], curr_spline.color[3]) + batch = batch_for_shader(shader, 'LINE_STRIP', {'pos': verts}) + + gpu.state.depth_test_set("LESS_EQUAL") + + gpu.state.blend_set("ALPHA") + gpu.state.face_culling_set("BACK") + shader.bind() + shader.uniform_float('color', col) - batch.draw(shader)
\ No newline at end of file + + batch.draw(shader) + + gpu.state.blend_set("NONE") + gpu.state.face_culling_set("NONE") + gpu.state.depth_test_set("NONE")
\ No newline at end of file |