点到直线的距离
【题目】给定两个点P1,P2,可以唯一地确定一条直线。另给定一点 P0,求P0到直线的距离。
已知的是3个点。求的结果是一个浮点数。
当 P1= P2 的时候,直线不存在,故无解。其它情况都是有解的。
解法一:
考虑三角形 P0P1P2 的面积为 S, P1 P2 距离为 d,就可求来 高 h,即为解。
三角形面积可用:海伦定理,或三阶生列式。
type Point = (Double, Double)
type Line = (Point, Point)
ptToLine :: Point -> Line -> Maybe Double
ptToLine (x0,y0) ((x1,y1), (x2,y2))
| dis == 0 = Nothing
| otherwise = Just (area * 2 / dis)
where
dis = sqrt $ (x2-x1)^2 + (y2-y1)^2
area = abs(x0*y1 + x1*y2 + x2*y0 - x2*y1 - x1*y0 - x0*y2) * 0.5
main :: IO ()
main = do
print $ ptToLine (0,0) ((0,5),(15/4,0))
print $ ptToLine (4,4) ((5,0),(5,8))
解法二:
如上图。做向量 v1 = p1->p0, v2 = p1->p2
如果能把这两个向量同时旋转,使得 v2 与 x 轴重合。此时的 v1 的虚部即为所求。
旋转就是复数的乘法,为了保持模不变,乘的应该是个单位复数。它的方向是v2的共轭复数。
import Data.Complex
type Point = (Double, Double)
type Line = (Point, Point)
ptToLine :: Point -> Line -> Maybe Double
ptToLine (x0,y0) ((x1,y1), (x2,y2))
| v2 == 0 = Nothing
| otherwise = Just . abs . imagPart $ v1'
where
v1 = (x0-x1) :+ (y0-y1)
v2 = (x2-x1) :+ (y2-y1)
v2u = conjugate $ v2 / (magnitude v2 :+ 0)
v1' = v1 * v2u
main :: IO ()
main = do
print $ ptToLine (0,0) ((0,5),(15/4,0))
print $ ptToLine (4,4) ((5,0),(5,8))