2

この C# メソッドを Scala Function に変換する最善の方法を考えていましたが、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;
}
4

2 に答える 2

1

アルゴリズムが正しいとすればboolean、特定の条件が満たされるたびにトグルすることで結果が得られることがわかります。したがって、それらの条件を数えることができます。

さらに、ポイントをペアごとに反復処理しています(j基本的には、コードを正しく理解していれば、ラップバックする必要がi - 1ある最初の反復を除いて)。jpoly.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 ...これは、折りたたまれた引数をエレガントにアンパックするために、再びパターン マッチング ( ) を使用します。

于 2012-07-25T00:10:22.203 に答える
1

どうですか:

sealed case class Loc(lat: Double, long: Double)

def isPointInPolygon(poly: List[Loc], x: Loc): Boolean = {
  (poly.last :: poly).sliding(2).foldLeft(false) { case (c, List(i, j)) =>
    val cond = {
      (
        (i.lat <= x.lat && x.lat < j.lat) ||
        (j.lat <= x.lat && x.lat < i.lat)
      ) &&
      (x.long < (j.long - i.long) * (x.lat - i.lat) / (j.lat - i.lat) + i.long)
    }

    if (cond) !c else c
  }
}
于 2014-10-10T01:16:50.133 に答える