在Web中绘制Fibonacci时出错

在Web中绘制Fibonacci时出错

本文介绍了在Web中绘制Fibonacci时出错的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

目前我有来自Blindman67的



Q1。 如何更改地雷螺旋线,以便 A 是开始时线条 AB 将适合第一个和第二个螺钉之间的距离的螺旋?



您也可以参考我以前的


  • 黄色螺旋线按四分之一圆弧近似
  • Aqua 就是金色螺旋线



正如你所看到的,它们并不相符(这是 ratio * 0.75 使它们更类似,但应该只是比率)或者我有一个错误,或者原点螺旋的位移(但看起来不像)或我有错误的比率常数 ratio = 0.3063489 或者黄金长方形引入了更高的浮动圆形错误,然后我教或我错过了一些愚蠢的东西。



这里是C ++源代码,您可以提取所需内容:

  // ---------------------------------------------- ----------------------------- 
#include
// -------------------------------------------- -------------------------------
bool _redraw = false; //只是在螺旋变化后发信号给重绘窗口
双Ax,Ay,Bx,By; // mouse eddited points
double gr = 0.75; //金色螺旋比例尺应为1!

void GoldenSpiral_draw(TCanvas * can)// GDI draw
{
double a0,a,b,l,x,y,r = 5,ratio;

//绘制AB线
can-> Pen-> Color = clWhite;
can-> MoveTo(Ax,Ay);
can-> LineTo(Bx,By);
//绘制A,B分数
can-> Pen-> Color = clBlue;
can-> Brush-> Color = clAqua;
can->椭圆(Ax-r,Ay-r,Ax + r,Ay + r);
can->椭圆(Bx-r,By-r,Bx + r,By + r);
//绘制黄金比例矩形
can-> Pen-> Color = clDkGray;
can-> Brush-> Style = bsClear;
比率= 1.6180339887;
a = 5.0; B = A /比; X = AX; Y = Ay的;
y- = 0.5 * b; X- = 0.5 * B; //偏向匹配真正的金色螺旋
can-> Rectangle(x,y,x + a,y + b); Y- = A;
for(int i = 0; i {
can-> Rectangle(x,y,x + a,y + a); B = A; A * =比; X- = A;
can-> Rectangle(x,y,x + a,y + a); Y + = A; B = A; A * =比;
can-> Rectangle(x,y,x + a,y + a); X + = A; Y- = B; B = A; A * =比;
can-> Rectangle(x,y,x + a,y + a); X- = B; B = A; A * =比; Y- = A;
}
//绘制圆弧近似金色螺旋线
ratio = 1.6180339887;
a = 5.0; B = A /比; X = AX; Y = Ay的; R = 10000; Y- = A;
y- = 0.5 * b; X- = 0.5 * B; //偏向匹配真正的金色螺旋
can-> Pen-> Color = clYellow;
for(int i = 0; i {
can-> Arc(xa,y,x + a,y + a + a,+ r,0 ,0,-r); B = A; A * =比; X- = A;
can-> Arc(x,y,x + a + a,y + a + a,0,-r,-r,0); Y + = A; B = A; A * =比;
can-> Arc(x,y-a,x + a + a,y + a,-r,0,0,+ r); X + = A; Y- = B; B = A; A * =比;
can-> Arc(x-a,y-a,x + a,y + a,0,+ r,+ r,0); X- = B; B = A; A * =比; Y- = A;
}
can-> Brush-> Style = bsSolid;

//计算金色螺旋参数
ratio = 0.3063489 * gr;
x = Bx-Ax;
y = By-Ay;
l = sqrt(x * x + y * y); // l = | AB |
if(l a0 = atan2(-y,x); // a = atan2(AB)
a0 + = 0.5 * M_PI; //偏移,所以AB的方向匹配正常的
a = 1.5 * M_PI; R = A * EXP(比* A); B = R等
a + = 2.0 * M_PI; R = A * EXP(比* A); B = R-B;
b = l / r; // b =螺旋缩放以匹配AB螺丝距离
//绘制金色螺旋线
can-> Pen-> Color = clAqua;
can-> MoveTo(Ax,Ay); (a = 0.0; a< 100.0 * M_PI; a + = 0.001)
{
r = a * b * exp(ratio * a);如果(r> 512.0)中断;
x = Ax + r * cos(a0 + a);
y = Ay-r * sin(a0 + a);
can-> LineTo(x,y);
}
}
// ---------------------------------- -----------------------------------------




  • 您可以忽略黄金比例矩形和圆弧...

  • 根据 can-> 将图纸更改为gfx API。它只是 GDI Canvas



如果你的螺旋线是正确的......你可以检查黄金比例矩形(就像我做的那样)。如果你有正确的螺旋,那么只要将子弹#1,#2,#3 应用到它,你应该没问题。


Currently I have this fiddle from Blindman67 which draws Golden spiral figure 1(see image below).

function renderSpiral(pointA, pointB, turns){
var dx, dy, rad, i, ang, cx, cy, dist, a, c, angleStep, numberTurns, nTFPB, scale, styles;
// clear the canvas
ctx.clearRect(0, 0, ctx.canvas.width,ctx.canvas.height)

// spiral stuff
a = 1;         // the larger this number the larger the spiral
c = 1.358456;   // constant See https://en.wikipedia.org/wiki/Golden_spiral
angleStep = Math.PI/20;  // set the angular resultion for drawing
numberTurns = 6;  // total half turns drawn
nTFPB = 2;   //  numberOfTurnsForPointB is the number of turns to point
                 // B should be integer and describes the number off
                 // turns made befor reaching point B

// get the ang from pointA to B
ang = Math.atan2(pointB.y-pointA.y,pointB.x-pointA.x);
// get the distance from A to B
dist = Math.sqrt(Math.pow(pointB.y-pointA.y,2)+Math.pow(pointB.x-pointA.x,2));
if(dist === 0){
    return;  // this makes no sense so exit as nothing to draw
}
// get the spiral radius at point B
rad = Math.pow(c,ang + nTFPB * 2 * Math.PI); // spiral radius at point2

// now just need to get the correct scale so the spiral fist to the
// constraints requiered.
scale = dist / rad;


// ajust the number of turns so that the spiral fills the canvas
while(Math.pow(c,Math.PI*numberTurns)*scale < ctx.canvas.width){
    numberTurns += 2;
}

// set the scale, and origin to centre
ctx.setTransform(scale, 0, 0, scale, pointA.x, pointA.y)

// make it look nice create some line styles


// first just draw the line A-B
ctx.strokeStyle = "black";
ctx.lineWidth = 2 * ( 1 / scale); // because it is scaled invert the scale
                                  // can calculate the width requiered
// ready to draw
ctx.beginPath();
ctx.moveTo(0, 0)        // start at center
ctx.lineTo((pointB.x-pointA.x)*(1/scale),(pointB.y-pointA.y)*(1/scale) );  // add line
ctx.stroke();  // draw it all

// Now draw the sporal. draw it for each style
styles.forEach( function(style) {
    ctx.strokeStyle = style.colour;
    ctx.lineWidth = style.width * ( 1 / scale); // because it is scaled invert the scale
                                                // can calculate the width requiered
    // ready to draw
    ctx.beginPath();
    for( i = 0; i <= Math.PI *numberTurns; i+= angleStep){
        dx = Math.cos(i);  // get the vector for angle i
        dy = Math.sin(i);
        var rad = Math.pow(c, i);  // calculate the radius
        if(i === 0) {
            ctx.moveTo(0, 0)        // start at center
        }else{
            ctx.lineTo(dx * rad, dy * rad );  // add line
        }
    }
    ctx.stroke();  // draw it all
});
ctx.setTransform(1,0,0,1,0,0); // reset tranfrom to default;
}

What I want to obtain is figure 2 (see image below).

Q1. How can I change mine spiral so line AB will fit between first and second screw while A is the start of spiral?

You can also refer to my earlier question for better understanding of my problem.

解决方案

To achieve the properties you need you need to adjust your spiral like following:

  1. choose the right angular position of the line AB

    I choose 1.5*M_PI [rad] for A and 3.5*M_PI [rad] for B (on unrotated spiral)

  2. rotate your spiral by angle of your AB line

    that is easy just add the angle to the final polar -> cartesian coordinates conversion and that will rotate entire spiral so computed angular positions of A,B on spiral will match the real points AB direction

  3. rescale your spiral to match the AB size

    So compute the radiuses for angular points A,B positons on spiral and then compute the scale=|AB|-(r(b)-r(a)). Now just multiply this to compute radius of each rendered point ...

I played a bit with the golden ratio and spiral a bit and here is the result

  • Yellow spiral is approximation by quarter circle arcs
  • Aqua is the Golden spiral

As you can see they do not match so much (this is with ratio*0.75 to make them more similar but it should be just ratio) Either I have a bug somewhere, or the origin of spiral is shifted (but does not look like it) or I have wrong ratio constant ratio = 0.3063489 or the Golden rectangles are introducing higher floating round errors then I taught or I am missing something stupid.

Here the C++ source code so you can extract what you need:

//---------------------------------------------------------------------------
#include <Math.h>
//---------------------------------------------------------------------------
bool _redraw=false;                     // just signal to repaint window after spiral change
double Ax,Ay,Bx,By;                     // mouse eddited points
double gr=0.75;                         // golden spiral ratio scale should be 1 !!!

void GoldenSpiral_draw(TCanvas *can)    // GDI draw
    {
    double a0,a,b,l,x,y,r=5,ratio;

    // draw AB line
    can->Pen->Color=clWhite;
    can->MoveTo(Ax,Ay);
    can->LineTo(Bx,By);
    // draw A,B points
    can->Pen->Color=clBlue;
    can->Brush->Color=clAqua;
    can->Ellipse(Ax-r,Ay-r,Ax+r,Ay+r);
    can->Ellipse(Bx-r,By-r,Bx+r,By+r);
    // draw golden ratio rectangles
    can->Pen->Color=clDkGray;
    can->Brush->Style=bsClear;
    ratio=1.6180339887;
    a=5.0; b=a/ratio; x=Ax; y=Ay;
    y-=0.5*b; x-=0.5*b; // bias to match real golden spiral
    can->Rectangle(x,y,x+a,y+b); y-=a;
    for (int i=0;i<5;i++)
        {
        can->Rectangle(x,y,x+a,y+a);             b=a; a*=ratio; x-=a;
        can->Rectangle(x,y,x+a,y+a); y+=a;       b=a; a*=ratio;
        can->Rectangle(x,y,x+a,y+a); x+=a; y-=b; b=a; a*=ratio;
        can->Rectangle(x,y,x+a,y+a); x-=b;       b=a; a*=ratio; y-=a;
        }
    // draw circle arc approximation of golden spiral
    ratio=1.6180339887;
    a=5.0; b=a/ratio; x=Ax; y=Ay; r=10000; y-=a;
    y-=0.5*b; x-=0.5*b; // bias to match real golden spiral
    can->Pen->Color=clYellow;
    for (int i=0;i<5;i++)
        {
        can->Arc(x-a,y,x+a,y+a+a,+r, 0, 0,-r);             b=a; a*=ratio; x-=a;
        can->Arc(x,y,x+a+a,y+a+a, 0,-r,-r, 0); y+=a;       b=a; a*=ratio;
        can->Arc(x,y-a,x+a+a,y+a,-r, 0, 0,+r); x+=a; y-=b; b=a; a*=ratio;
        can->Arc(x-a,y-a,x+a,y+a, 0,+r,+r, 0); x-=b;       b=a; a*=ratio; y-=a;
        }
    can->Brush->Style=bsSolid;

    // compute golden spiral parameters
    ratio=0.3063489*gr;
    x=Bx-Ax;
    y=By-Ay;
    l=sqrt(x*x+y*y);    // l=|AB|
    if (l<1.0) return;  // prevent domain errors
    a0=atan2(-y,x);     // a=atan2(AB)
    a0+=0.5*M_PI;       // offset so direction of AB matches the normal
    a=1.5*M_PI; r=a*exp(ratio*a); b=r;
    a+=2.0*M_PI; r=a*exp(ratio*a); b=r-b;
    b=l/r;              // b=zoom of spiral to match AB screw distance
    // draw golden spiral
    can->Pen->Color=clAqua;
    can->MoveTo(Ax,Ay);
    for (a=0.0;a<100.0*M_PI;a+=0.001)
        {
        r=a*b*exp(ratio*a); if (r>512.0) break;
        x=Ax+r*cos(a0+a);
        y=Ay-r*sin(a0+a);
        can->LineTo(x,y);
        }
    }
//---------------------------------------------------------------------------

  • You can ignore the golden ratio rectangles and circular arcs ...
  • change the drawings based on can-> to your gfx API. It is just GDI Canvas

Hard to say if your spiral is correct ... you can check with the golden ratio rectangles (as I did). If you got correct spiral then just apply the bullets #1,#2,#3 to it and you should be fine.

这篇关于在Web中绘制Fibonacci时出错的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

07-31 14:18