kb84tkhrのブログ

何を書こうか考え中です あ、あと組織とは関係ないってやつです 個人的なやつ

CGL_3_C: Polygon-Point Containment (続き3)

終点が半直線上にあって、その次の線分がx軸に平行な場合か

Point(2, 3)はそういう例になっていたはずだけど、
半直線の上から来て上に出ていくからたまたま問題が発生しなかった

まっとうに考えてここはテストケースを追加するところなんだろうな
ひとつの図形で全部テストしようとしたのもよくなかったかもしれない
そうじゃなくてもだんだん複雑になってきてテスト挙げきれてないけど

というよりもそれ以前か
場合分けがちゃんとできてない

だんだんややこしくなっているのはたぶんそもそもの方針が
よくなかったのではないか
でもいったんいけるところまでこのままいってみよう
その後で考え直す

まずは失敗するテストケースを追加する

        p = Polygon([Point(1, 1),
                     Point(7, 1),
                     Point(5, 3),
                     Point(3, 3),
                     Point(1, 5)])
        self.assertEqual(p.contains(Point(2, 3)), CN.INSIDE)

ちゃんとエラーになることを確認

ここを書き換えて、y座標が変わる頂点まで進むようにする
普通に多角形ならひとつ先まで進めばいいはずだけど

            p3 = self.vertices[self.next(self.next(k))]

p3がp2と同じy座標なら次に行く

    def contains(self, p: Point) -> Containment:
        ps = Segment(p, Point(100000.0, p.y))
        count = 0
        for k in range(self.n):
            p1 = self.vertices[k]
            k = self.next(k)
            p2 = self.vertices[k]
            s = Segment(p1, p2)
            if p.location(s) == PointLocation.ON_SEGMENT:
                return Containment.ONLINE
            if p.x < p1.x and float_equal(p.y, p1.y):
                continue
            if p.x < p2.x and float_equal(p.y, p2.y):
                k = self.next(k)
                while True:
                    p3 = self.vertices[k]
                    if not float_equal(p2.y, p3.y):
                        break
                    k = self.next(k)
                if p1.y < p2.y < p3.y or p1.y > p2.y > p3.y:
                    count += 1
            elif ps.intersects(s):
                count += 1
        return Containment.OUTSIDE if count % 2 == 0 \
            else Containment.INSIDE

ジャッジ
よし通った