问题描述
目前我有这个来自 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.它只是GDICanvas
很难说你的螺旋是否正确......你可以检查黄金比例矩形(就像我一样).如果你得到了正确的螺旋,那么只需将子弹 #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:
choose the right angular position of the line
AB
I choose
1.5*M_PI [rad]
forA
and3.5*M_PI [rad]
forB
(on unrotated spiral)rotate your spiral by angle of your
AB
linethat is easy just add the angle to the final polar
->
cartesian coordinates conversion and that will rotate entire spiral so computed angular positions ofA,B
on spiral will match the real pointsAB
directionrescale your spiral to match the
AB
sizeSo compute the radiuses for angular points
A
,B
positons on spiral and then compute thescale=|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 arcsAqua
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 GDICanvas
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.
这篇关于在网络中绘制斐波那契数列时出错的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!