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

问题描述

目前我有这个来自 Blindman67 的

第一季度.如何改变我的螺旋线,使 AB 线适合第一和第二个螺丝,而 A 是螺旋线的起点?

您也可以参考我之前的

  • Yellow 螺旋是四分之一圆弧的近似值
  • Aqua 是金色螺旋

正如你所看到的,它们并不匹配(这是 ratio*0.75 使它们更相似,但它应该只是 ratio)要么我有一个某个地方的错误,或者螺旋的原点发生了变化(但看起来不像)或者我有错误的比率常数 ratio = 0.3063489 或者黄金矩形引入了更高的浮动圆误差然后我教了或者我是错过了一些愚蠢的东西.

这里是 C++ 源代码,因此您可以提取您需要的内容:

//----------------------------------------------------------------------------#include <Math.h>//---------------------------------------------------------------------------布尔_重绘=假;//只是在螺旋变化后发出重新绘制窗口的信号双轴,Ay,Bx,By;//鼠标编辑点双 gr=0.75;//黄金螺旋比例应该是 1 !!!void GoldenSpiral_draw(TCanvas *can)//GDI 绘制{双 a0,a,b,l,x,y,r=5,ratio;//画AB线can->Pen->Color=clWhite;can->MoveTo(Ax,Ay);可以-> LineTo(Bx,By);//绘制 A,B 点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);//绘制黄金比例矩形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;//偏置以匹配真正的黄金螺旋可以->矩形(x,y,x+a,y+b);y-=a;for (int i=0;i矩形(x,y,x+a,y+a);b=a;a*=比率;x-=a;可以->矩形(x,y,x+a,y+a);y+=a;b=a;a*=比率;可以->矩形(x,y,x+a,y+a);x+=a;y-=b;b=a;a*=比率;可以->矩形(x,y,x+a,y+a);x-=b;b=a;a*=比率;y-=a;}//绘制黄金螺旋的圆弧近似比率=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;iArc(x-a,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;//计算黄金螺旋参数比率=0.3063489*gr;x=Bx-Ax;y=By-Ay;l=sqrt(x*x+y*y);//l=|AB|如果 (lPen->Color=clAqua;can->MoveTo(Ax,Ay);对于 (a=0.0;a<100.0*M_PI;a+=0.001){r=a*b*exp(比率*a);如果 (r>512.0) 中断;x=Ax+r*cos(a0+a);y=Ay-r*sin(a0+a);可以-> 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.

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

08-22 22:48