Javascript 按顺序计算圆坐标
我需要一个接一个地获得给定圆的所有点坐标,这样我就可以通过从一个点跳到下一个点来使一个对象在圆中运动。我尝试了中点圆算法,但我发现的版本是用来绘制的,坐标不是连续的。它们是在8个象限同时产生的,并且在其上方的相反方向上产生。如果至少它们在同一个方向上,我可以为每个象限创建一个单独的数组,并在最后将它们相互附加。这是我现在使用的JavaScript代码:Javascript 按顺序计算圆坐标,javascript,algorithm,geometry,Javascript,Algorithm,Geometry,我需要一个接一个地获得给定圆的所有点坐标,这样我就可以通过从一个点跳到下一个点来使一个对象在圆中运动。我尝试了中点圆算法,但我发现的版本是用来绘制的,坐标不是连续的。它们是在8个象限同时产生的,并且在其上方的相反方向上产生。如果至少它们在同一个方向上,我可以为每个象限创建一个单独的数组,并在最后将它们相互附加。这是我现在使用的JavaScript代码: function calcCircle(centerCoordinates, radius) { var coordinatesAr
function calcCircle(centerCoordinates, radius) {
var coordinatesArray = new Array();
// Translate coordinates
var x0 = centerCoordinates.left;
var y0 = centerCoordinates.top;
// Define variables
var f = 1 - radius;
var ddFx = 1;
var ddFy = -radius << 1;
var x = 0;
var y = radius;
coordinatesArray.push(new Coordinates(x0, y0 + radius));
coordinatesArray.push(new Coordinates(x0, y0 - radius));
coordinatesArray.push(new Coordinates(x0 + radius, y0));
coordinatesArray.push(new Coordinates(x0 - radius, y0));
// Main loop
while (x < y) {
if (f >= 0) {
y--;
ddFy += 2;
f += ddFy;
}
x++;
ddFx += 2;
f += ddFx;
coordinatesArray.push(new Coordinates(x0 + x, y0 + y));
coordinatesArray.push(new Coordinates(x0 - x, y0 + y));
coordinatesArray.push(new Coordinates(x0 + x, y0 - y));
coordinatesArray.push(new Coordinates(x0 - x, y0 - y));
coordinatesArray.push(new Coordinates(x0 + y, y0 + x));
coordinatesArray.push(new Coordinates(x0 - y, y0 + x));
coordinatesArray.push(new Coordinates(x0 + y, y0 - x));
coordinatesArray.push(new Coordinates(x0 - y, y0 - x));
}
// Return the result
return coordinatesArray;
}
函数计算圆(中心坐标、半径){
var coordinateArray=新数组();
//平移坐标
var x0=中心坐标。左;
var y0=centerCoordinates.top;
//定义变量
var f=1-半径;
var-ddFx=1;
变量ddFy=-radius=0){
y--;
ddFy+=2;
f+=ddFy;
}
x++;
ddFx+=2;
f+=ddFx;
坐标阵列推进(新坐标(x0+x,y0+y));
坐标阵列推(新坐标(x0-x,y0+y));
坐标阵列推进(新坐标(x0+x,y0-y));
坐标阵列推(新坐标(x0-x,y0-y));
坐标阵列推进(新坐标(x0+y,y0+x));
坐标阵列推(新坐标(x0-y,y0+x));
坐标阵列推(新坐标(x0+y,y0-x));
坐标阵列推(新坐标(x0-y,y0-x));
}
//返回结果
返回协调阵列;
}
我更喜欢一些没有三角学的快速算法,但任何帮助都是非常感谢的
编辑
这是最终的解决办法。谢谢大家
function calcCircle(centerCoordinates, radius) {
var coordinatesArray = new Array();
var octantArrays =
{oct1: new Array(), oct2: new Array(), oct3: new Array(), oct4: new Array(),
oct5: new Array(), oct6: new Array(), oct7: new Array(), oct8: new Array()};
// Translate coordinates
var xp = centerCoordinates.left;
var yp = centerCoordinates.top;
// Define add coordinates to array
var setCrd =
function (targetArray, xC, yC) {
targetArray.push(new Coordinates(yC, xC));
};
// Define variables
var xoff = 0;
var yoff = radius;
var balance = -radius;
// Main loop
while (xoff <= yoff) {
// Quadrant 7 - Reverse
setCrd(octantArrays.oct7, xp + xoff, yp + yoff);
// Quadrant 6 - Straight
setCrd(octantArrays.oct6, xp - xoff, yp + yoff);
// Quadrant 3 - Reverse
setCrd(octantArrays.oct3, xp - xoff, yp - yoff);
// Quadrant 2 - Straight
setCrd(octantArrays.oct2, xp + xoff, yp - yoff);
// Avoid duplicates
if (xoff != yoff) {
// Quadrant 8 - Straight
setCrd(octantArrays.oct8, xp + yoff, yp + xoff);
// Quadrant 5 - Reverse
setCrd(octantArrays.oct5, xp - yoff, yp + xoff);
// Quadrant 4 - Straight
setCrd(octantArrays.oct4, xp - yoff, yp - xoff);
// Quadrant 1 - Reverse
setCrd(octantArrays.oct1, xp + yoff, yp - xoff);
}
// Some weird stuff
balance += xoff++ + xoff;
if (balance >= 0) {
balance -= --yoff + yoff;
}
}
// Reverse counter clockwise octant arrays
octantArrays.oct7.reverse();
octantArrays.oct3.reverse();
octantArrays.oct5.reverse();
octantArrays.oct1.reverse();
// Remove counter clockwise octant arrays last element (avoid duplicates)
octantArrays.oct7.pop();
octantArrays.oct3.pop();
octantArrays.oct5.pop();
octantArrays.oct1.pop();
// Append all arrays together
coordinatesArray =
octantArrays.oct4.concat(octantArrays.oct3).concat(octantArrays.oct2).concat(octantArrays.oct1).
concat(octantArrays.oct8).concat(octantArrays.oct7).concat(octantArrays.oct6).concat(octantArrays.oct5);
// Return the result
return coordinatesArray;
}
函数计算圆(中心坐标、半径){
var coordinateArray=新数组();
var Octantarray=
{oct1:new Array(),oct2:new Array(),oct3:new Array(),oct4:new Array(),
oct5:new Array(),oct6:new Array(),oct7:new Array(),oct8:new Array()};
//平移坐标
var xp=centerCoordinates.left;
var yp=centerCoordinates.top;
//定义并向数组添加坐标
var setCrd=
功能(targetArray、xC、yC){
推(新坐标(yC,xC));
};
//定义变量
var xoff=0;
var yoff=半径;
var余额=-半径;
//主回路
而(xoff=0){
余额-=--yoff+yoff;
}
}
//逆时针八角阵
oct7.reverse();
oct3.reverse();
oct5.reverse();
oct1.reverse();
//逆时针移除最后一个元素的八分之一数组(避免重复)
oct7.pop();
oct3.pop();
oct5.pop();
oct1.pop();
//将所有数组追加在一起
协调阵列=
Octantarays.oct4.concat(Octantarays.oct3).concat(Octantarays.oct2).concat(Octantarays.oct1)。
concat(Octantarays.oct8)、concat(Octantarays.oct7)、concat(Octantarays.oct6)、concat(Octantarays.oct5);
//返回结果
返回协调阵列;
}
据我所知,没有三角学你是做不到的,但它对我来说运行得相当快。对不起,我不熟悉Java,所以我用VB编写代码:
Dim PointList As New List(Of PointF)
For angle = 0 To Math.PI * 2 Step 0.01
'the smaller the step, the more points you get
PointList.Add(New PointF(Math.Cos(angle) * r + x0, Math.Sin(angle) * r + y0))
Next
x0和y0是圆的中心坐标,r是半径
希望我能回答你的问题。这里是一个基于Dave答案的javascript实现。有点过度设计,我想避免把罪恶和罪恶称为多余的东西。讽刺的是,利用戴夫的第一个答案,没有半径:)
函数计算圆(x,y,半径){
var basicPoints=getBasicCircle();
var i=基本点长度;
var points=[];//不要更改基本点:这会破坏缓存。
而(我--){
点[i]={
x:x+(半径*基本点[i].x),
y:y+(半径*基本点[i].y)
};
}
返回点;
}
函数getBasicCircle(){
if(!arguments.callee.points){
var points=arguments.callee.points=[];
var end=Math.PI*2;
对于(变量角度=0;角度<结束;角度+=0.1){
点推({x:Math.sin(角度),
y:Math.cos(角度)
});
}
}
返回参数.callee.points
}
Use可以尝试以下方法:使用您给出的算法,但将坐标推到八个不同的坐标轴上。之后,您必须反转其中的一半(具有(x0+x,y0-y)、(x0-x,y0+y)、(x0+y,y0+x)、(x0-y,y0-x)的数组),然后按正确的顺序追加所有数组。注意将前四个点添加到正确的数组中。我想知道,如果没有至少一个圆的半径,这是如何工作的。如果要在浏览器中沿圆形路径移动对象,那么最后一个问题应该是sin/cos的速度。我将预算对象将用于的坐标正是这个原因,这个物体实际上是很多物体。因此,正反方向的速度可能是一个问题。特别是上网本上的IE。sin/cos的另一个缺点是它产生的点数有限。随着圆半径的增加,如果计算的点数保持不变(因为它们在圆周上的间距增加),则渲染项目的视在速度将增加。谢谢Hemlock!能更详细地解释一下你做了什么吗?使用一些预先计算的圆,然后扩展为不同的半径?如果这些点不足以形成一个大的圆,那么这就不行了?是的,它预先计算了一个半径为1的圆。如果你想返回分辨率更高或更低的圆,你必须改变缓存函数。我也想到了这一点。我击败了你,但我仍然相信你;)另一个解决方案是计算整个圆,而不是只计算一个八分之一,但我不知道如何调整算法。
function calculateCircle(x,y,radius) {
var basicPoints = getBasicCircle();
var i = basicPoints.length;
var points = []; // don't change basicPoints: that would spoil the cache.
while (i--) {
points[i] = {
x: x + (radius * basicPoints[i].x),
y: y + (radius * basicPoints[i].y)
};
}
return points;
}
function getBasicCircle() {
if (!arguments.callee.points) {
var points = arguments.callee.points = [];
var end = Math.PI * 2;
for (var angle=0; angle < end; angle += 0.1) {
points.push({x: Math.sin(angle),
y: Math.cos(angle)
});
}
}
return arguments.callee.points
}