【问题标题】:Trouble with drawing Bezier curve in Python在 Python 中绘制贝塞尔曲线的问题
【发布时间】:2014-07-11 11:38:26
【问题描述】:

大家好,我需要一些帮助。我用 Python (Tkinter) 编写了一个绘制 3 度贝塞尔曲线的代码,它可以工作......有点。我的问题是:我如何直接从键盘 x 和 y 输入控制点的坐标,而不是第一个 x 然后 y(就像在我的代码中一样)。第二个问题是关于参数(u 或 t)值。通常它是标准化的(值 0 到 1),但 for 循环不适用于步骤的十进制值(我知道它很明显:))。如果我把 u=1->1000 然后除以 1000 它是数值不稳定的。第三个也是最不重要的是如何绘制曲线,你会发现我使用了真正的小线愚蠢但不知道其他方式这是我的代码,对不起它是Word格式的,遇到了一些麻烦:

import tkinter

from tkinter import*

master=Tk()

w=Canvas(master,width=800,height=800)


w.pack()

def kriva():

        P0=[]
        P1=[]
        P2=[]
        P3=[]
        P0.append (float(input(" x for P0")))  #HERE IS THE PLACE FOR INPUT COORDINATES OF CONTROL POINTS
        P0.append (float(input(" y for P0")))
        P1.append(float(input(" x for P1")))
        P1.append(float(input(" yfor P1")))    
        P2.append(float(input(" x for za P2")))
        P2.append(float(input(" y for za P2")))

        P3.append(float(input(" x for P3")))
        P3.append(float(input(" y for P3")))


        for u  in range (0,1000,1):
            u=(u/1000) # PARAMETAR FOR CURVE
               x=(P0[0]*(1-u)**3+P1[0]*3*u*(1-u)**2+P2[0]*3*u**2*(1-u)+P3[0])*u**3#BERNSTAIN    POLYNOMS FOR X AND Y         
               y=(P0[1]*(1-u)**3+P1[1]*3*u*(1-u)**2+P2[1]*3*u**2*(1-u)+P3[1]*u**3)
            x1=x+1 #THIS IS END OF THE LINE
            y1=y+1
            print (x)
            print (y)
            w.create_line(x,y,x1,y1) #IM DOOING THIS THIS WAY BECAUSE I DONT KNOW ANY OTHER    WAY TO DRAW CURVE :)

kriva()
mainloop()

修复了所有问题..这是最终代码...特别感谢帮助

导入 tkinter

从 tkinter 导入*

master=Tk()

w=Canvas(master,width=800,height=800)

w.pack()

def kriva():

P0=[]

P1=[]

P2=[]

P3=[]

#p0:

unosp0=input("unesi koordinate za P0")

koordinatep0=unosp0.split(',')

print (koordinatep0)

P0.append(float((koordinatep0[0])))

P0.append(float((koordinatep0[1])))

print (P0)

#p1:

unosp1=input("unesi koordinate za P1")

koordinatep1=unosp1.split(',')

print (koordinatep1)

P1.append(float((koordinatep1[0])))

P1.append(float((koordinatep1[1])))

print (P1)

#p2:

unosp2=input("unesi koordinate za P2")

koordinatep2=unosp2.split(',')

print (koordinatep2)

P2.append(float((koordinatep2[0])))

P2.append(float((koordinatep2[1])))

print (P2)

#p3:

unosp3=input("unesi koordinate za P3")

koordinatep3=unosp3.split(',')

print (koordinatep3)

P3.append(float((koordinatep3[0])))

P3.append(float((koordinatep3[1])))

print (P3)

x1=P0[0]

y1=P0[1]

for u  in range (0,1001,1):

    u=(u/1000)

    x=(P0[0]*(1-u)**3+P1[0]*3*u*(1-u)**2+P2[0]*3*u**2*(1-u)+P3[0]*u**3)

    y=(P0[1]*(1-u)**3+P1[1]*3*u*(1-u)**2+P2[1]*3*u**2*(1-u)+P3[1]*u**3)

打印 (x)

打印(y)

打印 (x1)

打印(y1)

x1=str(x+000001)

y1=str(x+0,00001)

    linija=w.create_line(x,y,x1,y1)

    x1=x

    y1=y

kriva()

主循环()

【问题讨论】:

  • 通过绘制许多小线来绘制曲线并不愚蠢。这几乎是最好的方法。
  • Sundar,我不确定哪些错误...我已经尝试运行脚本并且它可以工作...没有报告错误。谢谢
  • Kevin 你知道我可以用其他方法吗?至少用点,如果不是平滑曲线?
  • “我试过运行脚本,它可以工作”。您的意思是,您已经复制粘贴了您在此处编写的确切代码,然后运行它,它可以工作吗?或者您的意思是,您最初从作品中转录此代码的代码?因为后者不排除你提问时打错的可能性。
  • “至少有点,如果不是平滑曲线的话?” 我不知道你的意思。线由点组成。

标签: python bezier


【解决方案1】:

要从同一个输入中获取 X 和 Y 坐标,您只需决定一个简单的语法并对其进行解析。比如你可以说 X 和 Y 会按这个顺序输入,用逗号隔开,然后做这样的事情

inp = input('Enter X,Y coordinates:')
parts = inp.split(',')
if len(parts) != 2:
    raise ValueErrror("You entered the wrong number of coordinates!")
x = float(parts[0].strip())
y = float(parts[1].strip())

或者更简洁(但没有错误处理):

x, y = (float(p.strip()) for p in input('Enter X,Y coordinates:').split(','))

对于浮点数的迭代,除以 1000 的想法很好。你是什​​么意思它的数值不稳定?我会这样做:

num_of_points = 1000
for i in xrange(num_of_points+1):
    u = float(i) / float(num_of_points)

请注意,我将范围设置为 num_of_points+1,因此 num_of_points 实际上会被包含在内:这意味着循环实际上会从 0 变为 1.0(含)。

在点之间画一条线可能是正确的答案。是的,这是一个近似值,但它仅受图像分辨率和您要绘制的点数的限制。如果您想要更准确的描述,只需遍历更大的num_of_points

要进行比直线更准确的操作,您需要计算出这两个点之间曲线的近似值。但这正是您的脚本正在做的事情,它近似于贝塞尔曲线。因此,您可以递归地逼近找到的每对点之间的曲线,但这与在逼近中添加更多点是一样的。

也就是说,你画线的具体方式让我感到困惑。据我所知,您正在计算曲线上的一个点(x,y)(更具体地说,(x(u), y(u)) 用于参数u),然后从该点画一条线到(x+1, y+1) 的点。换句话说,你总是从曲线上的点画出一点 45 度的“勾号”。不太清楚为什么,除非你只想做一个小标记并且不确定如何只填充一个像素。

不管是什么原因,正确的做法是确定曲线上的两个“相邻”点,然后用一条线将它们连接起来。比如:

last_point = calculate_point_on_curve(u=0)
for i in xrange(1, num_of_points+1):
    x, y = calculate_point_on_curve( float(i) / float(num_of_points) )
    last_x, last_y = last_point
    w.create_line(last_x, last_y, x, y)
    last_point = (x, y)

这里计算线上点的实际参数方程隐藏在calculate_point_on_curve函数中,只是为了简化代码sn-p。

要解决您明显的抽取问题,请尝试以下操作:

u = 0.0
for t in xrange(10001):
    calculate_point_on_curve(u)
    u = u + 0.0001

【讨论】:

  • sh 1ftst0rm...非常感谢... inp.split 是我一直在寻找但找不到的东西,现在我明白了。当涉及到数值不稳定时,当你运行代码时您可以看到,由于 u 的值更大,尤其是在 p2 和 p3 之间,线之间的间隙更大。这是合乎逻辑的,因为 u/1000 的近似值越来越不等于 u 为 0->1 时的那个值...任何想法如何解决这个问题?
  • 我还是不太明白你的意思。是的,浮点数只能近似大多数值,但我不明白你对它们越来越差的意思。例如,0、0.25、0.5、0.75 和 1.0 都可以用浮点数精确表示,许多其他值也可以。所以 500.0/1000.0 应该是准确的,125.0/1000.0 等也应该是准确的。
  • 说实话在回答之前我并没有仔细看你的代码,但我只是注意到你画线的方式:你为什么总是画从曲线上的点到(+1,+1) 的线?您应该将它从曲线上的一个点绘制到曲线上的下一个点。
  • 我已经编辑了答案,以便更好地描述如何按照我上一条评论中的建议绘制线条。
  • 好的,再次感谢......我现在试着弄清楚......我试着像你告诉我的那样解决坐标问题,但是 python 一直告诉我他不知道什么是“strip " 是,我也不是 :) 你能帮我解决这个问题吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-02-26
  • 2013-08-21
  • 2014-09-29
  • 1970-01-01
  • 1970-01-01
  • 2017-05-18
相关资源
最近更新 更多