简体   繁体   English

如何绘制不同颜色的蓝色贝塞尔曲线的每一段?

[英]How to draw each section of the blue Bezier curves with different color?

This is below I'm drawing Bezier curves , but It consists of many subset of Quadratic curves are joined together to form a one Bezier curve from P0 to P6.这是我正在绘制Bezier curves的下方,但它由许多Quadratic curves子集组成,它们连接在一起形成一条从 P0 到 P6 的贝塞尔曲线。 Where a curve has been drawn from P0 to M0 and another one from M0 to M1 and so on as shown below.其中从 P0 到 M0 绘制了一条曲线,从 M0 到 M1 绘制了另一条曲线,依此类推,如下所示。 I need to display each curve with different color, Could I get any help please?我需要用不同的颜色显示每条曲线,请问有什么帮助吗?

贝塞尔曲线

I'm expecting something as shown below, not exactly, but same idea我期待如下所示的东西,不完全是,但同样的想法

在此处输入图像描述

This is the Python code of Bezier:这是贝塞尔曲线的 Python 代码:

import numpy as np
import scipy.special
import matplotlib.pyplot as plt

def calc_bezier_path(control_points, n_points=100):
    """
    Compute bezier path (trajectory) given control points.
    :param control_points: (numpy array)
    :param n_points: (int) number of points in the trajectory
    :return: (numpy array)
    """
    traj = []
    for t in np.linspace(0, 1, n_points):
        traj.append(bezier(t, control_points))

    return np.array(traj)


def bernstein_poly(n, i, t):
    """
    Bernstein polynom.
    :param n: (int) polynom degree
    :param i: (int)
    :param t: (float)
    :return: (float)
    """
    return scipy.special.comb(n, i) * t ** i * (1 - t) ** (n - i)


def bezier(t, control_points):
    """
    Return one point on the bezier curve.
    :param t: (float) number in [0, 1]
    :param control_points: (numpy array)
    :return: (numpy array) Coordinates of the point
    """
    n = len(control_points) - 1
    return np.sum([bernstein_poly(n, i, t) * control_points[i] for i in range(n + 1)], axis=0)

def line_bezier(visx, visy, control, mod="nothing"):
    vis = np.column_stack((visx,visy))
    path_x, path_y = np.array([]),np.array([])
    setting = {"nothing":[len(vis)-2, 1, 1], "start":[len(vis)-1, 0, 0], "end":[len(vis)-1, 1, 0], "both":[len(vis), 0, -1]}
    epoch = setting[mod][0]
    start = setting[mod][1]
    end = setting[mod][2]
    if len(vis) > 2:
        current_control = vis[0]
        for x in range(epoch):
            if x != (epoch-1):
                for y in control:
                    if y == control[0]:
                        mid_control = [(vis[x+start,0]+(vis[x+(start+1),0]-vis[x+start,0])*y), (vis[x+start,1]+(vis[x+(start+1),1]-vis[x+start,1])*y)]
                        plt.annotate(f"M{x}", mid_control)
                        bezier_line = calc_bezier_path(np.array([current_control,vis[x+start], mid_control]))
                        path_x = np.append(path_x, bezier_line.T[0])
                        path_y = np.append(path_y, bezier_line.T[1])
                        current_control = mid_control
                    else:
                        mid_control = [(vis[x+start,0]+(vis[x+(start+1),0]-vis[x+start,0])*y), (vis[x+start,1]+(vis[x+(start+1),1]-vis[x+start,1])*y)]
                        plt.annotate(f"M{x}", mid_control)
                        bezier_line = calc_bezier_path(np.array([current_control, mid_control]))
                        path_x = np.append(path_x, bezier_line.T[0])
                        path_y = np.append(path_y, bezier_line.T[1])
                        current_control = mid_control
                        
            else:
                if mod == "end" or mod == "both":
                    bezier_line = calc_bezier_path(np.array([current_control, vis[x+(end+1)]]))
                else:
                    bezier_line = calc_bezier_path(np.array([current_control, vis[x+end], vis[x+(end+1)]]))
                path_x = np.append(path_x, bezier_line.T[0])
                path_y = np.append(path_y, bezier_line.T[1])
    else:
        path_x, path_y = visx, visy
    return path_x, path_y

visx, visy = [1,2,10,15,20,25,21], [0,5,1,4,2,3,3]
control = [0.25,0.57]
path_x, path_y = line_bezier(visx, visy, control,mod="end")
plt.plot(path_x, path_y)
plt.plot(visx, visy, "--o")
for xy in range(len(visx)):
    plt.annotate(f"P{xy}", [visx[xy], visy[xy]])
plt.show()

Currently, you're joining the bezier curve together (using path = np.append(path, bezier) . If you additionally create a list (eg line_collection ) to hold each part of the bezier, you can plot them separately afterwards:目前,您正在将贝塞尔曲线连接在一起(使用path = np.append(path, bezier) 。如果您另外创建一个列表(例如line_collection )来保存贝塞尔曲线的每个部分,您可以在之后分别 plot 它们:

import numpy as np
import scipy.special
import matplotlib.pyplot as plt

def calc_bezier_path(control_points, n_points=100):
    """
    Compute bezier path (trajectory) given control points.
    :param control_points: (numpy array)
    :param n_points: (int) number of points in the trajectory
    :return: (numpy array)
    """
    traj = []
    for t in np.linspace(0, 1, n_points):
        traj.append(bezier(t, control_points))

    return np.array(traj)


def bernstein_poly(n, i, t):
    """
    Bernstein polynom.
    :param n: (int) polynom degree
    :param i: (int)
    :param t: (float)
    :return: (float)
    """
    return scipy.special.comb(n, i) * t ** i * (1 - t) ** (n - i)


def bezier(t, control_points):
    """
    Return one point on the bezier curve.
    :param t: (float) number in [0, 1]
    :param control_points: (numpy array)
    :return: (numpy array) Coordinates of the point
    """
    n = len(control_points) - 1
    return np.sum([bernstein_poly(n, i, t) * control_points[i] for i in range(n + 1)], axis=0)

def line_bezier(visx, visy, control, mod="nothing"):
    vis = np.column_stack((visx,visy))
    path_x, path_y = np.array([]),np.array([])
    setting = {"nothing":[len(vis)-2, 1, 1], "start":[len(vis)-1, 0, 0], "end":[len(vis)-1, 1, 0], "both":[len(vis), 0, -1]}
    epoch = setting[mod][0]
    start = setting[mod][1]
    end = setting[mod][2]
    
    ## create a new list to hold the line segments
    line_collection=[]
    if len(vis) > 2:
        current_control = vis[0]
        for x in range(epoch):
            if x != (epoch-1):
                for y in control:
                    if y == control[0]:
                        mid_control = [(vis[x+start,0]+(vis[x+(start+1),0]-vis[x+start,0])*y), (vis[x+start,1]+(vis[x+(start+1),1]-vis[x+start,1])*y)]
                        plt.annotate(f"M{x}", mid_control)
                        bezier_line = calc_bezier_path(np.array([current_control,vis[x+start], mid_control]))
                        path_x = np.append(path_x, bezier_line.T[0])
                        path_y = np.append(path_y, bezier_line.T[1])
                        
                        ## append the segment to the list
                        line_collection.append(bezier_line)
                        current_control = mid_control
                    else:
                        mid_control = [(vis[x+start,0]+(vis[x+(start+1),0]-vis[x+start,0])*y), (vis[x+start,1]+(vis[x+(start+1),1]-vis[x+start,1])*y)]
                        plt.annotate(f"M{x}", mid_control)
                        bezier_line = calc_bezier_path(np.array([current_control, mid_control]))
                        path_x = np.append(path_x, bezier_line.T[0])
                        path_y = np.append(path_y, bezier_line.T[1])
                        
                        ## append the segment to the list
                        line_collection.append(bezier_line)
                        current_control = mid_control
                        
            else:
                if mod == "end" or mod == "both":
                    bezier_line = calc_bezier_path(np.array([current_control, vis[x+(end+1)]]))
                else:
                    bezier_line = calc_bezier_path(np.array([current_control, vis[x+end], vis[x+(end+1)]]))
                path_x = np.append(path_x, bezier_line.T[0])
                path_y = np.append(path_y, bezier_line.T[1])
                ## append the segment to the list:
                line_collection.append(bezier_line)
                
    else:
        path_x, path_y = visx, visy
    return path_x, path_y, line_collection ## return the line_collection here


visx, visy = [1,2,10,15,20,25,21], [0,5,1,4,2,3,3]
control = [0.25,0.57]
path_x, path_y, line_collection = line_bezier(visx, visy, control,mod="end") ## init the line_collection

## iterate over list elements
for line_seg in line_collection:
    plt.plot(line_seg.T[0],line_seg.T[1],linestyle="solid",linewidth=5,alpha=.5,zorder=10)

# plt.plot(path_x, path_y) ## dont need to plot this now
plt.plot(visx, visy, "--o")
for xy in range(len(visx)):
    plt.annotate(f"P{xy}", [visx[xy], visy[xy]])
plt.show()

yields:产量:

分段贝塞尔曲线

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如何在用paper.js创建的opencv(python)中使用贝塞尔曲线绘制路径 - how to draw paths with bezier curves in opencv (python) created with paper.js 在 PyMuPDF 中使用贝塞尔曲线绘制圆角矩形 - Using bezier curves to draw a rectangle with rounded corners in PyMuPDF 即使存在不同深浅的蓝色,如何将水的蓝色转换为另一种颜色? - How can I convert the blue color of water into another even if there are different shades of blue present? 如何用 Python 绘制贝塞尔线? - How can I draw a Bezier line with Python? 如何为图像中的每个对象着色不同的颜色 - How to color objects in an image with different color each 如何在 python 中绘制四分之一圆曲线 - How to draw quarter circle curves in python 如何通过SciPy绘制3D曲线? - How to draw 3D curves by SciPy? 如何在 MEL 中从顶点到顶点绘制曲线 - how to draw curves from vertex to vertex in MEL connectionstyle arc3(FancyArrowPatch)和路径CURVE3-两个二次贝塞尔曲线,结果不同吗? - connectionstyle arc3 (FancyArrowPatch) and path CURVE3 - two quadratic Bezier curves, different outcomes? 尽管具有相同的锚点/句柄(manim),为什么这会生成两条不同的贝塞尔曲线? - Why does this generate two different Bezier curves despite having the same anchors/handles (manim)?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM