【问题标题】:Find an index for a given Point coordinate from an array of Points从点数组中查找给定点坐标的索引
【发布时间】:2018-06-03 06:33:37
【问题描述】:

给定一个 Point 数组和任意 x,y 坐标,找到最接近给定坐标的 _points 的 index

PointD[] _points
//create a list of x,y coordinates:
for (int i = 0; i < _numberOfArcSegments + 1; i++)
{

    double x1 = _orbitEllipseSemiMaj * Math.Sin(angle) - _focalDistance; //we add the focal distance so the focal point is "center"
    double y1 = _orbitEllipseSemiMinor * Math.Cos(angle);

    //rotates the points to allow for the LongditudeOfPeriapsis. 
    double x2 = (x1 * Math.Cos(_orbitAngleRadians)) - (y1 * Math.Sin(_orbitAngleRadians));
    double y2 = (x1 * Math.Sin(_orbitAngleRadians)) + (y1 * Math.Cos(_orbitAngleRadians));
    angle += _segmentArcSweepRadians;
    _points[i] = new PointD() { x = x2, y = y2 };
}

我正在画一个代表轨道的椭圆。我首先在上面创建点数组,然后当我绘制它时,我(尝试)找到最接近轨道体所在位置的点。

为此,我一直在尝试计算从椭圆中心到身体的角度:

public void Update()
{    
    //adjust so moons get the right positions (body position - focal point position) 
    Vector4 pos = _bodyPositionDB.AbsolutePosition - _positionDB.AbsolutePosition;   
    //adjust for focal point
    pos.X += _focalDistance; 

    //rotate to the LonditudeOfPeriapsis. 
    double x2 = (pos.X * Math.Cos(-_orbitAngleRadians)) - (pos.Y * Math.Sin(-_orbitAngleRadians));
    double y2 = (pos.X * Math.Sin(-_orbitAngleRadians)) + (pos.Y * Math.Cos(-_orbitAngleRadians));

    _ellipseStartArcAngleRadians = (float)(Math.Atan2(y2, x2));  //Atan2 returns a value between -180 and 180; 
}

然后:

double unAdjustedIndex = (_ellipseStartArcAngleRadians / _segmentArcSweepRadians);
while (unAdjustedIndex < 0)
{
    unAdjustedIndex += (2 * Math.PI);
}
int index = (int)unAdjustedIndex;

椭圆画得很好,(点阵列是正确的,一旦针对视屏和相机偏移和缩放进行了调整,一切都很好) 但不是从正确的点开始(我正在减少颜色中的 alpha,因此生成的椭圆会随着距离身体越远而消失) 我花了几天时间试图找出我在这里做错了什么,并尝试了十几种不同的方法来找出我的数学错在哪里,但我没有看到。

【问题讨论】:

  • 您假设椭圆上最接近给定点的点与从椭圆中心到给定点的角度相同是不正确的。为了使这个假设正确,您需要首先平移椭圆和点,使椭圆的中心为 0,0。然后你需要缩放椭圆(和它的点),使椭圆变成一个圆。然后你可以使用你的角度假设。
  • 你没有错,这正是 Update() 函数正在做的事情,虽然不是椭圆,但我们正在寻找角度。它没有调整偏心率,因为在这种情况下应该不需要。轨道物体所在的点将穿过椭圆的每个点。

标签: c# math trigonometry ellipse


【解决方案1】:

我假设 _points 应该是一个 PointD 数组; 这是获得离您的数组最近的点的最短方法(calcdistance 应该是一个计算欧几里德距离的简单函数):

PointD p = _points.OrderBy(p => CalcDistance(p, gievnPoint)).First();

【讨论】:

  • 糟糕,我的错,应该是 PointD[] _points;仅剪切代码的重要位时出错。在大约 80 到 255 大小的点数组上进行排序与​​ Math.Sin、Cos、Atan 之间的成本差异是什么?
  • 关于索引,您可以将其转换为常规for循环并保存最小索引。关于性能问题,你应该衡量它。在我看来,排序成本低于数学函数
  • 虽然我更希望找出我的代码出了什么问题,但这是一种更简单的方法。该问题没有产生更多回复,因此我将给出已接受的答案。
猜你喜欢
  • 1970-01-01
  • 2012-06-04
  • 2022-01-11
  • 2021-05-31
  • 1970-01-01
  • 2021-09-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多