2013年12月12日木曜日

開発環境

初めてのコンピュータサイエンス(Jennifer CampbellPaul GriesJason MontojoGreg Wilson(著)長尾 高弘(翻訳))の12章(各種ツール)、12.7(練習問題)、12-4、5.を解いてみる。

12.7(練習問題)、12-4、5.

テストケース
line1line2出力説明
10[[0, 0], [1, 1]]ValueError2つの引数が浮動小数点数の対になっているか
[[0.0], [1, 1]][[1, 0], [2, 1]]None線分が交わらない場合
[[0, 0], [1, 1][[0, 1], [1, 0]][0.5, 0.5]線分が1点で交わる場合
[[0, 0], [1, 1]][[1, 1], [2, 2]][1, 1]線分の端が接している場合
[[0, 0], [1, 1]][[0, 0], [1, 1]]GeometryError, [[0, 0], [1, 1]]一致する場合
[[0, 0], [2, 2]][[1, 1], [3, 3]][[0, 0], [2, 2]]線分が部分的に重なり合う場合

コード(BBEdit)

sample.py

#!/usr/bin/env python3.3
#-*- coding: utf-8 -*-

class GeometryError(Exception):
    def __str__(self):
        return "GeometryError"

def lineIntersect(line1, line2):
    if not (type(line1) == list and len(line1) == 2 and type(line2) == list
           and len(line2) == 2):
        raise ValueError("ValueError")
    new_line1 = newline(line1)
    new_line2 = newline(line2)
    if new_line1 == new_line2:
        raise GeometryError()
    if new_line1[0] == new_line2[1]:
        return new_line1[0]
    if new_line1[1] == new_line2[0]:
        return new_line1[1]
    slope1 = slope(new_line1)
    slope2 = slope(new_line2)
    if slope1 == None and slope2 == None:
        return None
    if slope2 == None:
        x = new_line2[0][0]
        if x < new_line1[0][0] or new_line1[1][0] < x:
            return None
        y = slope1 * x + yIntercept(new_line1)
        return [x, y]
    if slope1 == None:
        x = new_line1[0][0]
        if x < new_line2[0][0] or new_line2[1][0] < x:
            return None
        y = slope2 * x + yIntercept(new_line2)
        return [x, y]
    y_intercept1 = yIntercept(new_line1)
    y_intercept2 = yIntercept(new_line2)
    if slope1 == slope2:
        if y_intercept1 == y_intercept2 and \
                new_line1[0][0] < new_line2[0][0] < new_line1[1][0]:
            return line1
        else:
            return None
    x = -(y_intercept1 - y_intercept2) / (slope1 - slope2)
    if new_line1[0][0] <= x <= new_line1[1][0]:
        y = slope1 * x + y_intercept1
        y1 = min(new_line1[0][1], new_line1[1][1])
        y2 = max(new_line1[0][1], new_line1[1][1])
        if y1 <= y <= y2:
            return [x, y]
    else:
        return None
    
def slope(line):
    x1 = line[0][0]
    x2 = line[1][0]
    y1 = line[0][1]
    y2 = line[1][1]
    if y2 == y1:
        return None
    return (x2 - x1) / (y2 - y1)

def newline(line):
    new_line = []
    x1 = line[0][0]
    x2 = line[1][0]
    y1 = line[0][1]
    y2 = line[1][1]
    if x1 > x2 or (x1 == x2 and y1 > y2):
        new_line = [[x2, y2], [x1, y1]]
    else:
        new_line = line[:]
    return new_line

def yIntercept(line):
    p = line[0]
    x = p[0]
    y = p[1]
    return y - slope(line) * x

if __name__ == '__main__':
    for line1, line2 in [(10, [[0, 0], [1, 1]]),
                         ([[0, 0], [1, 1]], [[1, 0], [2, 1]]),
                         ([[0, 0], [1, 1]], [[0, 1], [1, 0]]),
                         ([[0, 0], [1, 1]], [[1, 1], [2, 2]]),
                         ([[0, 0], [1, 1]], [[0, 0], [1, 1]]),
                         ([[0, 0], [2, 2]], [[1, 1], [3, 3]])]:
        try:
            print(lineIntersect(line1, line2))
        except ValueError as err:
            print(err)
        except GeometryError as err:
            print(err)
        except Exception as err:
            print(err)

入出力結果(Terminal)

$ ./sample.py
ValueError
None
[0.5, 0.5]
[1, 1]
GeometryError
[[0, 0], [2, 2]]
$

0 コメント:

コメントを投稿