import Data.Ratio
main
= mapM_ printIntersection ls
where
ls =
[
(((0, 8), (4, 0)), ((2, 4), (8, 12)))
, (((0, 0), (4, 6)), ((0, 0), (7, 15)))
, (((0, 0), (1, 2)), ((1, 1), (2, 3)))
, (((-9, -9), (9, 9)), ((5, 0), (5, 7)))
, (((3, 4), (6, 7)), ((3, 8), (9, -1)))
, (((-1, 0), (4, 18)), ((-2, -5), (1, 3)))
]
printIntersection
:: ((Point
, Point
), (Point
, Point
)) -> IO () where
s =
if not (onSegment l
&& onSegment m
) || any isNaN [x
, y
] then "交点なし"
else
onSegment ((x1, y1), (x2, y2)) = checkX && checkY
where
checkX = cmp (if x1 <= x2 then (<=) else (>=)) [x1, x, x2]
checkY = cmp (if y1 <= y2 then (<=) else (>=)) [y1, y, y2]
line :: Point -> Point -> Line
line (x1, y1) (x2, y2)
where
slope = dy / dx
dx = x2 - x1
dy = y2 - y1
intersection :: Line -> Line -> Point
intersection l@(a, b, p) m@(c, d, q)
where
x = invd * p + invb * q
y
| 0 == a = c * x + q
| 0 == c = a * x + p
[inva
, invb
, invc
, invd
] = map (/ det l m
) [a
, -b
, -c
, d
] nan = 0 / 0
parallel
:: Line
-> Line
-> Boolparallel l m = det l m == (0 % 1)
det
:: Line
-> Line
-> Ratio
Integerdet (a, b, _) (c, d, _) = a * d - b * c
aW1wb3J0IERhdGEuUmF0aW8KCm1haW4gOjogSU8gKCkKbWFpbiA9IG1hcE1fIHByaW50SW50ZXJzZWN0aW9uIGxzCiAgd2hlcmUKICAgIGxzID0KICAgICAgWwogICAgICAgICgoKDAsIDgpLCAoNCwgMCkpLCAoKDIsIDQpLCAoOCwgMTIpKSkKICAgICAgLCAoKCgwLCAwKSwgKDQsIDYpKSwgKCgwLCAwKSwgKDcsIDE1KSkpCiAgICAgICwgKCgoMCwgMCksICgxLCAyKSksICgoMSwgMSksICgyLCAzKSkpCiAgICAgICwgKCgoLTksIC05KSwgKDksIDkpKSwgKCg1LCAwKSwgKDUsIDcpKSkKICAgICAgLCAoKCgzLCA0KSwgKDYsIDcpKSwgKCgzLCA4KSwgKDksIC0xKSkpCiAgICAgICwgKCgoLTEsIDApLCAoNCwgMTgpKSwgKCgtMiwgLTUpLCAoMSwgMykpKQogICAgICBdCgpwcmludEludGVyc2VjdGlvbiA6OiAoKFBvaW50LCBQb2ludCksIChQb2ludCwgUG9pbnQpKSAtPiBJTyAoKQpwcmludEludGVyc2VjdGlvbiAobCwgbSkgPSBwdXRTdHJMbiBzCiAgd2hlcmUKICAgIHMgPQogICAgIGlmIG5vdCAob25TZWdtZW50IGwgJiYgb25TZWdtZW50IG0pIHx8IGFueSBpc05hTiBbeCwgeV0gdGhlbgogICAgICAgIuS6pOeCueOBquOBlyIKICAgICBlbHNlCiAgICAgICBzaG93ICh4LCB5KQogICAgKHgsIHkpID0gaW50ZXJzZWN0aW9uICh1bmN1cnJ5IGxpbmUgbCkgKHVuY3VycnkgbGluZSBtKQoKICAgIG9uU2VnbWVudCAoKHgxLCB5MSksICh4MiwgeTIpKSA9IGNoZWNrWCAmJiBjaGVja1kKICAgICAgd2hlcmUKICAgICAgICBjaGVja1ggPSBjbXAgKGlmIHgxIDw9IHgyIHRoZW4gKDw9KSBlbHNlICg+PSkpIFt4MSwgeCwgeDJdCiAgICAgICAgY2hlY2tZID0gY21wIChpZiB5MSA8PSB5MiB0aGVuICg8PSkgZWxzZSAoPj0pKSBbeTEsIHksIHkyXQogICAgICAgIGNtcCBmID0gYW5kIC4gKGZsaXAgKHppcFdpdGggZikgPTw8IHRhaWwpCgoKdHlwZSBQb2ludCA9IChEb3VibGUsIERvdWJsZSkKdHlwZSBMaW5lICA9IChSYXRpbyBJbnRlZ2VyLCBSYXRpbyBJbnRlZ2VyLCBSYXRpbyBJbnRlZ2VyKQoKbGluZSA6OiBQb2ludCAtPiBQb2ludCAtPiBMaW5lCmxpbmUgKHgxLCB5MSkgKHgyLCB5MikKICB8IGR4IC89IDAgICA9ICh0b1JhdGlvbmFsIHNsb3BlLCAtMSwgdG9SYXRpb25hbCAkIHNsb3BlICogeDEgLSB5MSkKICB8IGR4ID09IDAgICA9ICgxLCAwLCB0b1JhdGlvbmFsIHgxKQogIHwgb3RoZXJ3aXNlID0gKDAsIDAsIDApCiAgd2hlcmUKICAgIHNsb3BlID0gZHkgLyBkeAogICAgZHggPSB4MiAtIHgxCiAgICBkeSA9IHkyIC0geTEKCmludGVyc2VjdGlvbiA6OiBMaW5lIC0+IExpbmUgLT4gUG9pbnQKaW50ZXJzZWN0aW9uIGxAKGEsIGIsIHApIG1AKGMsIGQsIHEpCiAgfCBub3QgJCBwYXJhbGxlbCBsIG0gPSAoZnJvbVJhdGlvbmFsIHgsIGZyb21SYXRpb25hbCB5KQogIHwgb3RoZXJ3aXNlICAgICAgICAgID0gKG5hbiwgbmFuKQogIHdoZXJlCiAgICB4ID0gaW52ZCAqIHAgKyBpbnZiICogcQogICAgeQogICAgICB8IDAgPT0gYSAgICA9IGMgKiB4ICsgcQogICAgICB8IDAgPT0gYyAgICA9IGEgKiB4ICsgcAogICAgICB8IG90aGVyd2lzZSA9IGludmMgKiBwICsgaW52YSAqIHEKICAgIFtpbnZhLCBpbnZiLCBpbnZjLCBpbnZkXSA9IG1hcCAoLyBkZXQgbCBtKSBbYSwgLWIsIC1jLCBkXQogICAgbmFuIDo6IERvdWJsZQogICAgbmFuID0gMCAvIDAKCnBhcmFsbGVsIDo6IExpbmUgLT4gTGluZSAtPiBCb29sCnBhcmFsbGVsIGwgbSA9IGRldCBsIG0gPT0gKDAgJSAxKQoKZGV0IDo6IExpbmUgLT4gTGluZSAtPiBSYXRpbyBJbnRlZ2VyCmRldCAoYSwgYiwgXykgKGMsIGQsIF8pID0gYSAqIGQgLSBiICogYwo=