In code form, the calculation of the coordinates of the polar rose point in the Cartesian system can be represented as follows:
X := OriginX + A * Cos(K * Theta) * Cos(Theta);
Y := OriginY + A * Cos(K * Theta) * Sin(Theta);
Parameter | Meaning |
---|---|
OriginX |
the X coordinate of the rose's center point |
OriginY |
the Y coordinate of the rose's center point |
A |
target rose radius |
K |
angular frequency |
The above code works prefectly. For example, setting K
as 5
, I get a flower with five petals. For other positive integer values of K
I also get correct flowers, consistent with the first row of those given on Wikipedia:
Image credit: Jason Davies via Wikimedia Commons.
Now I would like my code to be able to generate roses from other rows. I found the article Polar rose garden and there is a image with various roses, where k
is integer or real:
https://blog.k2h.se/post/2020-01-03-polar-rose-garden_files/figure-html/unnamed-chunk-2-1.png
For example, for k = 1 / 3
, the rose should look like this:
Also https://blog.k2h.se/post/2020-01-03-polar-rose-garden_files/figure-html/unnamed-chunk-2-1.png look for caption 1/3
.
but if I use the following code:
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;
the rose looks like this:
Could anyone advise why my graph is broken?
PS: I'm not a mathematician, so C/Pascal code would be perfect.
We can't just blindly run from 0 to 2PI, because that doesn't guarantee a full period of the graph. After all, we're not working with cos(theta)
and sin(theta)
, we're working with an additional factor cos(n/d * theta)
, so we'll need to at the very least multiply by d in order to get back to full periods, but n is a bit sneaky here.
If we turn to the Wikipedia page for rose curves, specifically the section for when k is rational, we learn that:
In the case when both n and d are odd, the positive and negative half-cycles of the sinusoid are coincident. The graph of these roses are completed in any continuous interval of polar angles that is dπ long.
When n is even and d is odd, or visa versa, the rose will be completely graphed in a continuous polar angle interval 2dπ long
So a modulo-based check should do:
<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);
// what's our "loop limit"?
const oddN = (n % 2) === 1;
const oddD = (d % 2) === 1;
const limit = d * ((oddN && oddD) ? PI : TAU);
// let's draw!
start();
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>
The last time I've used Pascal was probably 40 years ago, so you'll have to "port" that solution yourself, but that should be pretty easy =)