以代码形式,笛卡尔系中极玫瑰点坐标的计算可以表示为:
X := OriginX + A * Cos(K * Theta) * Cos(Theta);
Y := OriginY + A * Cos(K * Theta) * Sin(Theta);
参数 | 意义 |
---|---|
|
玫瑰中心点的 坐标 |
|
玫瑰中心点的 坐标 |
|
目标玫瑰半径 |
|
角频率 |
上面的代码可以完美运行。例如,将
K
设置为 5
,我会得到一朵有五个花瓣的花。对于 K
的其他正整数值,我也得到了正确的花,与维基百科上给出的第一行一致:
图片来源:Jason Davies,来自 Wikimedia Commons。
现在我希望我的代码能够从其他行生成玫瑰。我找到了文章极地玫瑰园,里面有一张有各种玫瑰的图片,其中
k
是整数或实数:
https://blog.k2h.se/post/2020-01-03-polar-rose-garden_files/figure-html/unnamed-chunk-2-1.png
例如,对于
k = 1 / 3
,玫瑰应该是这样的:
另外https://blog.k2h.se/post/2020-01-03-polar-rose-garden_files/figure-html/unnamed-chunk-2-1.png查找标题
1/3
。
但是如果我使用以下代码:
var
Theta: Single;
OriginX: Integer;
OriginY: Integer;
Size: Integer;
X: Integer;
Y: Integer;
K: Single;
begin
OriginX := 120;
OriginY := 120;
Size := 120;
K := 1 / 3;
Theta := 0.0;
while Theta < Pi * 2 do
begin
X := Round(OriginX + Size * Cos(K * Theta) * Cos(Theta));
Y := Round(OriginY + Size * Cos(K * Theta) * Sin(Theta));
Canvas.Pixels[X, Y] := clGray;
Theta += 0.001;
end;
end;
玫瑰看起来像这样:
有人可以告诉我为什么我的图表损坏了吗?
PS:我不是数学家,所以 C/Pascal 代码就完美了。
我们转向 https://en.wikipedia.org/wiki/Rose_(mathematics)#Roses_with_rational_number_values_for_k 并了解到:
当n和d均为奇数时,正弦曲线的正半周期和负半周期是重合的。这些玫瑰花的图形在任意连续的极角区间(dπ长)中完成。
当 n 为偶数且 d 为奇数时,反之亦然,玫瑰将完全绘制在连续的极角区间2dπ长
中
因此应该进行快速模检查:
<script type="module" src="https://cdnjs.cloudflare.com/ajax/libs/graphics-element/1.11.1/graphics-element.js" integrity="sha512-fz6xdkeMImCEkyHV+HPpg7C9cxoqc0w9RdSzm9ufj2wjFQFz71iJvyazoM9tXRGBzN40GuNY2e5fmimRiBFoJw==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/graphics-element/1.11.1/graphics-element.css" integrity="sha512-sD4sJLVEBRXXbNNaSs/vwyt6vgq+jIiAhpg1MtqNdmhOt3k6K7V4wH5p5IxNvRXAoP51rAHyig0f4egsM+WdCQ==" crossorigin="anonymous" referrerpolicy="no-referrer" />
<graphics-element id="graphics" width="200px" height="160px" title="let's draw some roses">
<graphics-source>
const r = 70;
let k = 1;
function setup() {
addSlider(`n`, {min:1, max:7, step:1, value:1 });
addSlider(`d`, {min:1, max:9, step:1, value:3 });
}
function draw() {
k = n / d;
clear();
noFill();
translate(width/2, height/2);
start();
const oddN = (n % 2) === 1;
const oddD = (d % 2) === 1;
const limit = d * ((oddN && oddD) ? PI : TAU);
for (let theta = 0, f, x, y; theta <= limit; theta += 0.001) {
f = r * cos(k * theta);
x = f * cos(theta);
y = f * sin(theta);
vertex(x, y);
}
end();
}
</graphics-source>
</graphics-element>