我一直在尝试使用计算机绘制一些hypotrochoids,但我遇到了一些问题。对于那些不熟悉的人,hypotrochoid的参数方程是:
x(theta) = (R - r)cos(theta) + d*cos((R-r)/r*theta)
和
y(theta) = (R - r)sin(theta) - d*sin((R-r)/r*theta)
维基百科对hypotrochoid的定义可以进一步解释:
hypotrochoid是一个轮盘,由一个圆圈附近的一个点跟踪 半径r围绕半径为R的固定圆内侧滚动, 其中该点距离内部中心的距离为d 圈。
因此,值为r = d = 1
和R = 3
的hypotrochoid应该如下所示:
但这肯定不是我最终使用我的计算方法。我的hypotrochoid(具有相同的值)看起来像这样:
由于x和y值是由角度为theta
的x和y的函数确定的,我假设我可以简单地将theta
的值从0到2pi循环并计算x和y以某些间隔分别绘制值,然后以极坐标形式绘制坐标(其中r**2 = x**2 + y**2
),但我想我认为错了。也许我的公式是错误的,但我只是在math stackexchange与几个人检查过,我们无法弄清楚错误。如果我的方法错了,应该用什么方法来计算下丘脑?
以下是代码:
class _BaseCurve(event.EventAware):
# This is a basic curve class from which all other curves inherit from (as
# you will see below with the Hypotrochoid class). Basically what happens is
# each new curve class must implement a function (relation) to calculate the
# radius of the equation at each angle interval, then plots the equation in
# other code elsewhere.
def __init__(self, radius, init_angle, end_angle, speed, acceleration, *args, **kwargs):
# Initialize geometric data...
self.radius = radius
# Initialize curve start and end angles...
self.init_angle = init_angle
self.end_angle = end_angle
# Initialize time-based curve attributes...
self.speed = speed
self.accel = acceleration
self.current_pos = 0
# Initialize defaults...
self.max_speed = inf
self.min_speed = neginf
self.args = args
self.kwargs = kwargs
def set_max_speed(self, speed):
"""Set the maximum speed the path can achieve."""
if speed < self.min_speed:
errmsg = "Max speed cannot be less than min speed."
raise ValueError(errmsg)
self.max_speed = speed
def set_min_speed(self, speed):
"""Set the minimum speed the path can achieve."""
if speed > self.max_speed:
errmsg = "Min speed cannot be greater than max speed."
raise ValueError(errmsg)
self.max_speed = speed
def set_acceleration(self, acceleration):
"""Set a new acceleration for the path."""
self.accel = acceleration
def move(self):
"""Progress the path forward one step.
The amount progressed each time (curve).move is called
depends on the path's speed parameter and the distance
(i.e. angle_difference) it has to travel. The calculation
is as follows:
angle = angle_difference * current_position + init_angle
Where current_position is the position incremented by the
set speed in (curve).move().
"""
self.current_pos += self.speed
if self.accel != 1:
new_speed = self.speed * self.accel
self.speed = max(min(new_speed, self.max_speed), self.min_speed)
def angle(self):
"""Return the angle of the curve at the current position."""
return self.angle_difference * self.current_pos + self.init_angle
def relation(self):
"""Return the relationship of the current angle to the radius.
This is a blank function left to be filled in by subclasses of
_BasicCurve. The return value for this function must be a function
(or lambda expression), of which that function's return value should
be the radius of the curve at the current position. The parameters of
the return equation should be as follows:
(Assuming `r` is the function representing the relation):
radius = r(current_angle, *args, **kwargs)
Where *args and **kwargs are the additional *args and **kwargs specified
upon initializing the curve.
"""
return NotImplemented
def position(self):
"""Calculate the position on the curve at the current angle.
The return value of this function is the coordinate in polar
form. To view the coordinate in cartesian form, use the
`to_cartesian` function. # Ignore the `to_cartesian` function in this code snippet, it simply converts polar to cartesian coordinates.
NOTE: This function requires self.relation to be implemented.
"""
r = self.relation()
theta = self.current_angle
args = self.args
kwargs = self.kwargs
radius = self.radius*r(theta, *args, **kwargs)
return radius, theta
@property
def angle_difference(self):
"""The difference between the start and end angles specified."""
return (self.end_angle - self.init_angle)
@property
def current_angle(self):
"""The current angle (specified by self.current_pos)."""
return self.angle_difference * self.current_pos + self.init_angle
Curve = _BaseCurve
class Hypotrochoid(Curve):
def relation(self):
def _relation(theta, r, R, d):
x = (R - r)*math.cos(theta) + d*math.cos((R - r)/r * theta)
y = (R - r)*math.sin(theta) - d*math.sin((R - r)/r * theta)
return (x**2 + y**2)**(1/2)
return _relation
答案 0 :(得分:1)
将x,y和theta转换为极性形式输出是错误的。 Theta是参数方程的参数,它不是曲线点的极角(实际上是小圆心的极角)
所以x和y随时可以使用笛卡尔&#39;坐标。只需将这一点绘制成一步。这是Delphi测试,它准确地绘制了你想要的东西(Canvas.Pixels [x,y]用(x,y)坐标绘制一个点)
R := 120;
rr := 40;
d:= 40;
for i := 0 to 999 do begin
a := i * 2 * Pi / 1000;
y := 200 + Round((R - rr) * sin(a) - d*sin((R-rr)/rr*a));
x := 200 + Round((R - rr) * cos(a) + d*cos((R-rr)/rr*a));
Canvas.Pixels[x, y] := clRed;
end;