我有两个点数组:double[] minus
和double[] plus
,例如:
double[] minus = new[]
{
24.043414306636713,
26.521399902043807,
23.049167719142361,
24.473177606966754,
18.238281854192408,
};
double[] plus = new[]
{
8.31219054269323,
9.5909890877229582,
11.066525870449567,
22.769068312057193,
24.733540360065991,
};
我需要根据这个数字绘制2个图表并确定它们相对于彼此的位置:是否有一个交叉点,哪个是另一个?
我该怎么做? TIA
(请随意重新提出问题或更改主题,我不确定使用的数学术语是否合适)
编辑:这是一个Excel图表:
很容易确定哪个在上面,哪个在哪里。
如何确定红色(加号)与蓝色(减号)的交叉点?使用LINQ?
答案 0 :(得分:4)
要确定哪个更高,只需将minus [i]与plus [i]进行比较 - 无论哪个值越大,i处的“更高”值。
要确定交叉点,只需跟踪哪一个更高。当改变时,就会有一个交叉点。
修改强>
如果您无法追踪历史记录,那么:
if ((minus[i-1] > plus[i-1]) != (minus[i] > plus[i])) then
// there was an intersection
else
// there was not an intersection
答案 1 :(得分:4)
此代码可以找到所有碰撞:
double[] minus = new double[]
{
3, 24, 26, 23, 25, 18, 5, 5, 1, 10,
};
double[] plus = new ![alt text][1]double[]
{
3, 8, 9, 11, 22, 25, 5, 5, 3, 7
};
var collisionsBetweenIndices =
Enumerable.Range(1, minus.Length - 1)
.Where(i => ((minus[i - 1] - plus[i - 1] < 0) && (minus[i] - plus[i] > 0)) ||
((minus[i - 1] - plus[i - 1] > 0) && (minus[i] - plus[i] < 0)) ||
((minus[i - 1] - plus[i - 1] == 0) && (minus[i] - plus[i] == 0)))
.ToArray();
var collisionsOnIndices =
Enumerable.Range(0, minus.Length)
.Where(i => minus[i] == plus[i])
.ToArray();
foreach (var idx in collisionsBetweenIndices)
Console.WriteLine("Collision between {0} and {1}", idx - 1, idx);
foreach (var idx in collisionsOnIndices)
Console.WriteLine("Collision on {0}", idx);
// RESULTS:
// Collision between 4 and 5
// Collision between 6 and 7
// Collision between 8 and 9
// Collision on 0
// Collision on 6
// Collision on 7
编辑:
我做了两种不同的方法来区分碰撞的类型(即索引之间或索引之间),但如果你的purpouse只是为了检测是否发生碰撞,请执行以下操作:
var collisionDetected =
Enumerable.Range(0, minus.Length).Any(i =>
{
if (minus[i] == plus[i])
return true;
if (i > 0 &&
(((minus[i - 1] - plus[i - 1] < 0) && (minus[i] - plus[i] > 0)) ||
((minus[i - 1] - plus[i - 1] > 0) && (minus[i] - plus[i] < 0)) ||
((minus[i - 1] - plus[i - 1] == 0) && (minus[i] - plus[i] == 0))))
{
return true;
}
return false;
});
一旦发现碰撞,此代码就会返回,因此上述方法通常会更快。
答案 2 :(得分:3)
一种方法是将每个系列分成线段,然后比较两个系列中的相应(通过索引)段。
由于具体提及LINQ,这是实现这一目标的一种方法。它不是很漂亮:
var minusPairs = minus.Zip(minus.Skip(1), (prev, next) => new { prev, next });
var plusPairs = plus.Zip(plus.Skip(1), (prev, next) => new { prev, next });
var positions = minusPairs.Zip
(plusPairs, (mPair, pPair) =>
mPair.prev > pPair.prev
&& mPair.next > pPair.next ? "MinusAbove" :
mPair.prev < pPair.prev
&& mPair.next < pPair.next ? "PlusAbove" :
"Intersection");
输出:
MinusAbove
MinusAbove
MinusAbove
Intersection
(请注意,最后一点没有获得PlusAbove
,因为它所属的唯一段代表Intersection
。如果需要,您可能需要更改此行为。)
说实话,如果你需要做任何事情,我会回避任何“可爱”的解决方案,即使稍微比这更复杂(例如找到交叉点)。这里需要良好的面向对象设计。
答案 3 :(得分:1)
为什么你不能这样做:
for i=1...n
if minus[i] > plus[i]
return "Crossed over at index i"
答案 4 :(得分:1)
public string DetermineCollisionInfo(double current, double next)
{
string currentInfo =
current == 0.0 ? "Plus and Minus have same value" :
current < 0.0 && next > 0.0 ? "Intersection occurs" :
current > 0.0 && next < 0.0 ? "Intersection occurs" :
"No Intersection";
string nextInfo =
next > 0.0 ? "Plus will be on top" :
next < 0.0 ? "Minus will be on top" :
"Plus and Minus will have same value";
return currentInfo + ". " + nextInfo;
}
然后,后来:
IEnumerable<double> differences = Enumerable
.Range(0, minus.Length)
.Select(i => plus[i] - minus[i]);
double current = differences.First();
IEnumerable<string> analysis = differences
.Skip(1)
.Select(next =>
{
string result = DetermineCollisionInfo(current, next);
current = next;
return result;
});
foreach(string info in analysis)
{
Console.WriteLine(analysis);
}
答案 5 :(得分:1)
如果minus
和plus
是列表:
var plus1 = plus.Skip(1);
var retVal = minus
.Skip(1)
.Select((p,i) => new { index = i, value = (minus[i] > plus[i]) != (p > plus1[i])})
.Where( p => !p.value);