如何在考虑每个点的位置和方向的情况下连接点 [英] How to connect points taking into consideration position and orientation of each of them

查看:40
本文介绍了如何在考虑每个点的位置和方向的情况下连接点的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在附加的图像中,我们可以看到点运动的真实值(绿色)和估计值(红色).带有条形(=图案)的圆圈旁边的每个数字对应一个时间.现在已经开发了所有算法,我想通过将所有图案连接在一起,同时考虑位置和方向(由条的方向定义)来提高可视化的质量.我试图找到一种方法来做到这一点,但找不到任何方法.有人有想法吗?

有关信息:我有坐标(x,y)和角度,可以根据需要将其更改为导数.

这里有一些关于我想将模式连接在一起的方式的说明.

  • 我想按照每个模式旁边的数字顺序连接所有模式
  • 我希望我的曲线穿过每个图案的中心
  • 我希望每种图案的曲线陡度都与绘制的条相同.

总结:我正在寻找一种方法来绘制连接点的曲线并在每个点拟合所需的陡度.

解决方案

总结一下问题:您想通过多个点插入一条平滑曲线.对于2D空间中的每个点,您都有坐标以及定义该点曲线切线的角度.

一种解决方案可能是使用三阶

所以我们可以定义一条贝塞尔曲线,它有两个中间点,沿着每个点的角度给定的切线.本身并没有暗示两个中间点应该位于该切线的哪个位置,因此我们可以选择距两个端点的任意距离.在下面的代码中,这就是所谓的 r .为这个参数选择一个合适的值 r 是获得平滑曲线的关键.

将 numpy 导入为 np来自scipy.special import binom导入matplotlib.pyplot作为plt伯恩斯坦= lambda n,k,t:binom(n,k)* t ** k *(1.-t)**(n-k)def bezier(点,num = 200):N = len(点)t = np.linspace(0, 1, num=num)曲线= np.zeros((num,2))对于范围(N)中的i:曲线+ = np.outer(bernstein(N-1,i,t),points [i])回报曲线Segment()类:def __init__(self, p1, p2,angle1,angle2, **kw):self.p1 = p1;self.p2 = p2self.angle1 = angle1;self.angle2 =角度2self.numpoints = kw.get("numpoints",100)方法= kw.get(方法",常量")如果method =="const":self.r = kw.get("r",1.)别的:r = kw.get("r", 0.3)d = np.sqrt(np.sum((self.p2-self.p1)** 2))self.r = r * dself.p = np.zeros((4,2))self.p[0,:] = self.p1[:]self.p[3,:] = self.p2[:]self.calc_intermediate_points(self.r)def calc_intermediate_points(self,r):self.p [1 ,:] = self.p1 + np.array([self.r * np.cos(self.angle1),self.r * np.sin(self.angle1)])self.p [2 ,:] = self.p2 + np.array([self.r * np.cos(self.angle2 + np.pi),self.r * np.sin(self.angle2 + np.pi)])self.curve = bezier(self.p,self.numpoints)def get_curve(points,** kw):段 = []对于范围内的我(len(points-1)):seg = Segment(points [i,:2],points [i + 1,:2],points [i,2],points [i + 1,2],** kw)段.附加(段)curve = np.concatenate([s曲线段中的s]返回段,曲线def plot_point(ax, xy, 角度, r=0.3):ax.plot([xy [0]],[xy [1]],marker ="o",ms = 9,alpha = 0.5,color ="indigo")p = xy + np.array([r*np.cos(angle),r*np.sin(angle)])ax.plot([xy[0],p[0]], [xy[1],p[1]], color="limegreen")如果 __name__ == "__main__":# x y 角度点 = np.array([[ 6.0, 0.5, 1.5],[5.4, 1.2, 2.2],[ 5.0, 1.7, 2.6],[ 2.8, 2.4, 2.1],[ 1.3, 3.2, 1.6],[1.9,3.9,-0.2],[ 4.0, 3.0, 0.2],[ 5.1, 3.7, 1.4]])无花果,ax = plt.subplots()点对点:plot_point(ax, point[:2],point[2], r=0.1)s1, c1 = get_curve(points, method="const", r=0.7)ax.plot(c1 [:,0],c1 [:,1],color =绯红色",zorder = 0,label =常量0.7个单位")s2,c2 = get_curve(points,method ="prop",r = 0.3)ax.plot(c2 [:,0],c2 [:,1],color ="gold",zorder = 0,label ="prop 30%of distance")plt.legend()plt.show()

在上图中比较了两种情况.一个是 r 是常数 0.7 单位,另一个是 r 是两点之间距离的相对30%.

In the attached image we can see the groundtruth (green) and the estimation (red) of the motion of a point. Each number next to the circle with the bar (=pattern) correspond to a time. Now that all the algorithm has been developed I would like to improve the quality of the visualization by connecting all the pattern together taking into consideration the position but also the orientation (defined by the direction of the bar). I tried to find a way to do that but couldn't find any. Anyone has an idea?

For information: I have the coordinates (x,y) and the angle which could be changed into the derivative if necessary.

EDIT: Here are some clarification regarding the way I would like to connect the patterns together.

  • I would like to connect all the patterns in the order of the number next to each pattern
  • I would like my curve to go through the center of each pattern
  • I would like the steepness of my curve at each pattern being the same as the drawn bar has.

To sum up: I am looking for a way to plot a curve connecting points and fitting a desired steepness at each point.

解决方案

To summarize the problem: You want to interpolate a smooth curve through a number of points. For each point in 2D space, you have the coordinates as well as an angle which defines the tangent of the curve in this point.

A solution may be to use Bézier curves of third order. Such a curve will be defined by 4 points; the two end points, which are two successive points in the plot, and two intermediate points, which define the direction of the curve. Bézier curves are often used in graphics software and also internally by matplotlib to draw paths.

So we can define a Bezier curve which has its two intermediate points along the tangent given by the angle to each of the points. There is per se no hint on where on that tangent the two intermediate points should lie, so we might chose some arbitrary distance from the two end points. This is what is called r in the code below. Chosing a good value for this parameter r is key to obtaining a smooth curve.

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

bernstein = lambda n, k, t: binom(n,k)* t**k * (1.-t)**(n-k)

def bezier(points, num=200):
    N = len(points)
    t = np.linspace(0, 1, num=num)
    curve = np.zeros((num, 2))
    for i in range(N):
        curve += np.outer(bernstein(N - 1, i, t), points[i])
    return curve

class Segment():
    def __init__(self, p1, p2, angle1, angle2, **kw):
        self.p1 = p1; self.p2 = p2
        self.angle1 = angle1; self.angle2 = angle2
        self.numpoints = kw.get("numpoints", 100)
        method = kw.get("method", "const")
        if method=="const":
            self.r = kw.get("r", 1.)
        else:
            r = kw.get("r", 0.3)
            d = np.sqrt(np.sum((self.p2-self.p1)**2))
            self.r = r*d
        self.p = np.zeros((4,2))
        self.p[0,:] = self.p1[:]
        self.p[3,:] = self.p2[:]
        self.calc_intermediate_points(self.r)

    def calc_intermediate_points(self,r):
        self.p[1,:] = self.p1 + np.array([self.r*np.cos(self.angle1),
                                    self.r*np.sin(self.angle1)])
        self.p[2,:] = self.p2 + np.array([self.r*np.cos(self.angle2+np.pi),
                                    self.r*np.sin(self.angle2+np.pi)])
        self.curve = bezier(self.p,self.numpoints)


def get_curve(points, **kw):
    segments = []
    for i in range(len(points)-1):
        seg = Segment(points[i,:2], points[i+1,:2], points[i,2],points[i+1,2],**kw)
        segments.append(seg)
    curve = np.concatenate([s.curve for s in segments])
    return segments, curve


def plot_point(ax, xy, angle, r=0.3):
    ax.plot([xy[0]],[xy[1]], marker="o", ms=9, alpha=0.5, color="indigo")
    p = xy + np.array([r*np.cos(angle),r*np.sin(angle)])
    ax.plot([xy[0],p[0]], [xy[1],p[1]], color="limegreen")


if __name__ == "__main__":        
    #                   x    y    angle        
    points =np.array([[ 6.0, 0.5, 1.5],
                      [ 5.4, 1.2, 2.2],
                      [ 5.0, 1.7, 2.6],
                      [ 2.8, 2.4, 2.1],
                      [ 1.3, 3.2, 1.6],
                      [ 1.9, 3.9,-0.2],
                      [ 4.0, 3.0, 0.2],
                      [ 5.1, 3.7, 1.4]])

    fig, ax = plt.subplots()

    for point in points:
        plot_point(ax, point[:2],point[2], r=0.1)

    s1, c1 = get_curve(points, method="const", r=0.7)
    ax.plot(c1[:,0], c1[:,1], color="crimson", zorder=0, label="const 0.7 units")

    s2, c2 = get_curve(points, method="prop", r=0.3)
    ax.plot(c2[:,0], c2[:,1], color="gold", zorder=0, label="prop 30% of distance")
    plt.legend()
    plt.show()

In the plot above two cases are compared. One where r is constant 0.7 units, the other where r is relative 30% of the distance between the two points.

这篇关于如何在考虑每个点的位置和方向的情况下连接点的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆