C#-加速使用嵌套for循环的列表比较
我目前正在开发一个测试程序,以确保主板上的孔不会彼此太近或重叠 为了做到这一点,我将保留名为holeInfo的对象中所有孔的X、Y坐标和半径,以及列表holeInfo列表中的对象 我目前正在使用嵌套for循环遍历所有孔,并使用基本数学公式检查孔之间的距离 以下是我使用的函数:C#-加速使用嵌套for循环的列表比较,c#,algorithm,list,object,for-loop,C#,Algorithm,List,Object,For Loop,我目前正在开发一个测试程序,以确保主板上的孔不会彼此太近或重叠 为了做到这一点,我将保留名为holeInfo的对象中所有孔的X、Y坐标和半径,以及列表holeInfo列表中的对象 我目前正在使用嵌套for循环遍历所有孔,并使用基本数学公式检查孔之间的距离 以下是我使用的函数: public void checkHoleConditions() { for (int i = 0; i < holeInfoList.Count - 1; i++) { error
public void checkHoleConditions()
{
for (int i = 0; i < holeInfoList.Count - 1; i++)
{
errorType = new List<string>();
for (int j = i + 1; j < holeInfoList.Count; j++)
{
holeMinSpaceFailed = false;
if (failsHoleConditions(holeInfoList[i], holeInfoList[j]))
{
if (holeMinSpaceFailed)
{
errorType.Add("X: " + holeInfoList[j].holeXCoordinate + " Y: " + holeInfoList[j].holeYCoordinate + "R: " + holeInfoList[j].holeDiameter + " too close.");
}
else
{
errorType.Add("X: " + holeInfoList[j].holeXCoordinate + " Y: " + holeInfoList[j].holeYCoordinate + "R: " + holeInfoList[j].holeDiameter + " overlap.");
}
invalidHole = new InvalidHole(holeInfoList[i], errorType);
invalidHoleList.Add(invalidHole);
Console.WriteLine("Hole Error Detected");
}
else
{
Console.WriteLine("Hole Check Successful");
}
}
}
}
public bool failsHoleConditions(HoleInfo holeOne, HoleInfo holeTwo)
{
float holeOneXCoordinate = holeOne.holeXCoordinate;
float holeOneYCoordinate = holeOne.holeYCoordinate;
float holeOneRadius = holeOne.holeDiameter / 2;
float holeTwoXCoordinate = holeTwo.holeXCoordinate;
float holeTwoYCoordinate = holeTwo.holeYCoordinate;
float holeTwoRadius = holeTwo.holeDiameter / 2;
float holeXDifferenceSquared = (float)Math.Pow((holeOneXCoordinate - holeTwoXCoordinate), 2);
float holeYDifferenceSquared = (float)Math.Pow((holeOneYCoordinate - holeTwoYCoordinate), 2);
float distanceBetweenCenters = (float)Math.Sqrt(holeXDifferenceSquared + holeYDifferenceSquared);
float distanceBetweenHoles = distanceBetweenCenters - (holeOneRadius + holeTwoRadius);
if (distanceBetweenHoles <= 0)
{
return true;
}
else if (distanceBetweenHoles <= minimumSpace)
{
holeMinSpaceFailed = true;
return true;
}
return false;
}
public void checkHoleConditions()
{
for(int i=0;i 如果(孔之间的距离如果需要对所有孔进行测试,一种优化方法是将它们放在一个nxn矩阵中,而不是一个列表中。然后,并行执行验证。矩阵越大,核越多越好。并行也可以在列表中执行,但我不能100%确定.Net是否会决定等待每个孔由于算法是连续的,所以一直读到最后
如果您的方法使用欧几里德距离,您可以尝试根据此距离对列表进行排序。sqr(x)+sqr(y)关于0,可以先进行排序。我认为.Net可以轻松处理此排序。稍后,只需运行您的算法,直到第一个允许的电路。然后,您知道必须接受其余的,因此您将只对列表的第一个元素执行此解决方案的灵感来自物理引擎,以及其中的优化注意碰撞检测
我并不完全知道它是如何工作的,为了更好的解决方案,你应该尝试研究ODE或Bullet动力学
基本上,解决方案是将对象(孔)分离成孤岛,并仅将每个对象的位置与同一个孤岛中的对象进行比较。如果无法找到正确分离孤岛的方法,您可以这样做:
假设一个正方形区域上有125个对象,5乘5。您可以将其划分为25个主要正方形岛,然后是8个相交岛(长岛,沿着主要岛的边缘。这些岛的最小边应该是您要计算的最小距离).Islands可能重叠。您必须分析整个列表一次才能进行此拆分。这意味着到目前为止,我们总共循环了125项-O(n)
接下来,对于每个孤岛(总共33个,O(n^(2/3))
,通过使用这些相同的嵌套循环,找到比必须更接近的对象。每个孤岛的总复杂度是O((n/n^(2/3))^2)
=O(n^(2/3))
。乘以孤岛的数量,我们得到该算法的总复杂度=O(n^(4/3))
,它小于最初显示的O(n^2)
希望这是有意义的。如果你想的话,我可以写一个Python演示。只是需要很多代码
编辑:
或者,您可以使用2D物理引擎,将对象绘制为直径等于孔之间最小距离的圆,然后让它检测碰撞。或者从那里获取相关代码(如果许可证允许),因为整个物理引擎对于任务来说有点过度。
编辑2:
254列出对象
我以为您正在分析254个不同的电路板。我强调的这个解决方案只有在巨大的计算负载下才有意义。如果failsHoleConditions为真,holeMinSpaceFailed将永远不会为真
别这样胡说逻辑
x*x
比Math.Pow
无需使用Sqrt-只需使用平方最小空间
类似于此。运行100万300毫秒。您的代码在几分钟内出错
static byte HoleTooClose(HoleInfo x, HoleInfo y, float minDistance)
{
float holeSize = (x.Diameter + y.Diameter) / 2;
float deltaX = y.X - x.X;
float deltaY = y.Y - x.Y;
float distanceSquared = deltaX * deltaX + deltaY * deltaY - holeSize * holeSize;
if (distanceSquared <= 0)
{
return 0;
}
float minDistanceSquared = minDistance * minDistance;
if (distanceSquared <= minDistanceSquared)
{
return 1;
}
return 2;
}
internal struct HoleInfo
{
public float Diameter { get; internal set; }
public float X { get; internal set; }
public float Y { get; internal set; }
public HoleInfo (float x, float y, float diameter)
{
X = x;
Y = y;
Diameter = diameter;
}
}
static bool DistanceTooClose(System.Windows.Point x, System.Windows.Point y, Double minDistance)
{
double deltaX = Math.Abs(y.X - x.X);
double deltaY = Math.Abs(y.Y - x.Y);
double distanceSquared = deltaX * deltaX + deltaY * deltaY;
//double distance = Math.Sqrt(distanceSquared);
Double minDistanceSquared = minDistance * minDistance;
return (distanceSquared <= minDistanceSquared);
}
静态字节HoleTooClose(HoleInfo x,HoleInfo y,float minDistance)
{
浮动孔尺寸=(x.直径+y.直径)/2;
浮动deltaX=y.X-X.X;
浮动三角洲=y.y-x.y;
浮动距离平方=deltaX*deltaX+deltaY*deltaY-holeSize*holeSize;
如果(距离平方)看起来更合适