python高级练习题:贝塞尔曲线【难度:4级】:

贝塞尔曲线

当使用矢量图形中描述了一种形状,其轮廓通常被描述为线性,二次,和三次贝塞尔曲线的序列.您可以在维基百科阅读贝塞尔曲线.

你不需要知道很多关于贝塞尔曲线来解决这个习题.只知道线性方程,二次和三次曲线(分别)给出:

1.P(T)=(1 - T)* P0 + T * P1 2.P(T)=(1 - T)** 2 * P0 + 2 *(1 - T)*T* P1 + T ** 2 * P2 3.P(T)=(1 - T)** 3 * P0 + 3 *(1 - T)** 2 *T* P1 + 3 *(1 - T)*T** 2 * P2 + 吨** 3 * P3

P0,P1,P2,P3被称为曲线的控制点,和t是一个变量,该变量,从0取值为1时,会引起P(吨)跟踪的曲线.

这应该足以实现point_at(T)你要实现的类方法.

为了实现sub_segment(吨)方法,参见,特别是对构建上面引用的维基百科文章的Bézier曲线段.

该部分显示的贝塞尔曲线如何成长的动画.该动画被显示越来越长的子部分,因此,示出的子部分是如何构造的.如果你在四曲线动画仔细观察,你可以看到如何控制点从开始都在P0分别为P0,P1和P2结束了移动.现在仔细一看,在三次曲线的动画.看到不断增长的小节开始在P0的控制点,并在P0,P1,P2和P3结束.无需读什么,只是看看.在引用款到底有到德卡斯特里奥算法,您可能发现有用的链接,但我不会去那里.只要仔细看动画.

在这习题,你被要求实现一个类为每个线性,二次和三次贝塞尔曲线.这些类必须扩展以下抽象基类,并实现抽象方法:

的Python
从ABC进口ABCMeta,abstractmethod


类链段(元类= ABCMeta):

    @属性
    @abstractmethod
    高清control_points(个体经营):
        通过

    @abstractmethod
    DEF point_at(个体,T):
        通过

    @abstractmethod
    DEF sub_segment(个体,T):
        通过

control_points是返回定义曲线的点的坐标的属性.由于线性曲线具有两个控制点(该段的开始和结束),control_points将持有4个浮点,这是x轴和随后的x和的y坐标中的第一点的y坐标第二点.对于二次和三次曲线分别有6个8控制点.

该方法point_at(吨)应返回方程对于曲线中插入t时获得的点.此方法将在间隔``t的值进行测试[0,1]只(尽管这是可能的外推曲线).

该方法sub_segment(T_0)应该返回开始于第一点和在由point_at(T_0)返回的点处结束和如下,该方法是在调用否则该对象的曲线的曲线.例如,如果quad是二次曲线,然后quad.sub_segment(T_0)是开始于quad的第一点和在quad.point_at(T_0)结束二次曲线和如下的曲线.更确切地说,

quad.point_at(T_0 * T)== quad.sub_segment(T_0).point_at(t)的

在间隔``t的所有值[0,1].

编程目标:

from abc import ABCMeta, abstractmethod
class Segment(metaclass=ABCMeta):
    @property
    @abstractmethod
    def control_points(self):
        pass
    @abstractmethod
    def point_at(self, t):
        pass
    @abstractmethod
        pass
class Line(Segment):
    def __init__(self, *coords):
        self._control_points = coords

测试样例:

Test.describe('Full test suite')
Test.it('Initialization')
line = Line(1, 2, 3, 4)
Test.expect(isinstance(line, Segment))
Test.expect(isinstance(line, Line))
quad = Quad(1, 2, 3, 4, 5, 6)
cubic = Cubic(1, 2, 3, 4, 5, 6, 7, 8)
Test.expect(isinstance(cubic, Segment))
Test.expect(isinstance(cubic, Cubic))
Test.it('Control points')
18