kb84tkhrのブログ

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

CGL_3_C: Polygon-Point Containment (続き5)

ちょっと寝かせてみたけど画期的なアイデアは浮かばず

あとは整理するくらい
locationを使うのであればy座標を使わなくても上下どちらにいるかわかるな
とか
whileループを二重にしなくてもcontinue使えばいいな
とか

class PointLocation(IntEnum):

    def is_online(self):
        return self in [PointLocation.ON_SEGMENT,
                        PointLocation.ONLINE_BACK,
                        PointLocation.ONLINE_FRONT]

class Polygon:

    def contains(self, p: Point) -> Containment:
        ps = Segment(p, Point(100000.0, p.y))
        count = 0

        prev_l = self.vertices[0].location(ps)
        if prev_l.is_online():
            prev_l = self.vertices[-1].location(ps)

        for s in self.sides():
            if p.location(s) == PointLocation.ON_SEGMENT:
                return Containment.ONLINE
            cur_l = s.p2.location(ps)
            if cur_l.is_online() or prev_l == cur_l:
                continue
            if ps.intersects(s):
                count += 1
            prev_l = cur_l

        return Containment.OUTSIDE if count % 2 == 0 \
            else Containment.INSIDE

最初の辺がx軸に平行だったときと
頂点がちょうど半直線の上にあるときの特別扱いはどうもなくせなかった

という範囲内ではまあまあ見やすくはなった気はしている
自分的にはこれでファイナルアンサーということにしよう