我想知道将此 C# 方法转换为 Scala 函数的最佳方法,看起来使用 scala 的语法可能会更简洁。
bool IsPointInPolygon(List<Loc> poly, Loc point)
{
int i, j;
bool c = false;
for (i = 0, j = poly.Count - 1; i < poly.Count; j = i++)
{
if ((((poly[i].Lt <= point.Lt) && (point.Lt < poly[j].Lt)) ||
((poly[j].Lt <= point.Lt) && (point.Lt < poly[i].Lt))) &&
(point.Lg < (poly[j].Lg - poly[i].Lg) * (point.Lt - poly[i].Lt) /
(poly[j].Lt - poly[i].Lt) + poly[i].Lg))
c = !c;
}
return c;
}
最佳答案
假设您的算法是正确的,您可以观察到生成的 bool 值是通过每次满足特定条件时进行切换来获得的。因此您可以计算这些条件。
此外,您将逐对迭代点(如果我正确理解代码,j
基本上是 i - 1
,除了初始迭代,其中 j
必须换回 poly.Count - 1
)。
要获取对,如果 poly
是 scala.List
:
val pairs = (poly.last :: poly).sliding(2, 1)
在与 sliding
形成对之前,将最后一个元素添加到列表中,例如
val x = List("a", "b", "c")
(x.last :: x).sliding(2,1).toList // gives List(List(c, a), List(a, b), List(b, c))
(严格来说,last
在 scala.List
上并不是一个非常有效的方法,但它确实有效)
那么你就会有
pairs.count { case Seq(pi, pj) => checkCondition } % 2 == 1
其中,case Seq(pi, pj)
再次为您提取相邻点,% 2 == 1
询问您是否计算了奇数次。
滑动的替代方法是使用 foldLeft
方法。这可能更具性能,因为没有创建嵌套集合,但更像是一个聪明的解决方案。诀窍是传递前一点和当前结果(原始代码中的c
):
poly.foldLeft(poly.last -> false) { case ((pj, c), pi) => pi -> (c ^ checkCondition)}
这再次使用模式匹配(case ...
)来优雅地解包折叠参数。
关于scala - 用scala编写的多边形中的点,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11640630/