import Data.Ratio main :: IO () main = mapM_ printIntersection ls where ls = [ ((Point 0 8 , Point 4 0) , (Point 2 4 , Point 8 12)) , ((Point 0 0 , Point 4 6) , (Point 0 0 , Point 7 15)) , ((Point 0 0 , Point 1 2) , (Point 1 1 , Point 2 3)) , ((Point (-9) (-9), Point 9 9) , (Point 5 0 , Point 5 7)) , ((Point 3 4 , Point 6 7) , (Point 3 8 , Point 9 (-1))) , ((Point (-1) 0 , Point 4 18), (Point (-2) (-5), Point 1 3)) , ((Point 1 2 , Point 4 18), (Point 1 2 , Point 4 18)) ] printIntersection :: (Segment, Segment) -> IO () printIntersection (l, m) = putStrLn s where s = if not (onSegment l && onSegment m) || any isNaN [x, y] then "交点なし" else show (x, y) Point x y = intersection (uncurry line l) (uncurry line m) onSegment :: Segment -> Bool onSegment ((Point x1 y1), (Point x2 y2)) = checkX && checkY where checkX = f x1 x x2 checkY = f y1 y y2 f a b c = g (if a <= c then (<=) else (>=)) [a, b, c] g op = and . (flip (zipWith op) =<< tail) type Segment = (Point, Point) data Point = Point Double Double data Line = Line Rational Rational Rational line :: Point -> Point -> Line line (Point x1 y1) (Point x2 y2) | dx /= 0 = Line (toRational slope) (-1) (toRational $ slope * x1 - y1) | otherwise = Line 1 0 (toRational x1) where slope = dy / dx dx = x2 - x1 dy = y2 - y1 intersection :: Line -> Line -> Point intersection l@(Line a b p) m@(Line c d q) | not $ parallel l m = Point (fromRational x) (fromRational y) | otherwise = Point nan nan where x = invd * p + invb * q y | a == 0 = c * x + q | c == 0 = a * x + p | otherwise = invc * p + inva * q [inva, invb, invc, invd] = map (/ det l m) [a, -b, -c, d] nan :: Double nan = 0 / 0 parallel :: Line -> Line -> Bool parallel l m = det l m == (0 % 1) det :: Line -> Line -> Rational det (Line a b _) (Line c d _) = a * d - b * c