我实现了Haversine公式来计算两个坐标(纬度、经度)之间的距离。
我在想,对于Clojure程序员来说,这看上去是否很自然。还有什么可以改进的?
(ns br.com.reactive-poc.calc)
(def raio 6372.795477598)
(defn calculate-distance
"Calcula distância entre duas coordenadas geográficas"
([source to]
{:pre [every? (every-pred map? #(contains? % :lgt) #(contains? % :ltd)) [source to]]}
(let [delta-latitude (Math/toRadians (- (:source/ltd source) (:to/ltd to)))
delta-longitude (Math/toRadians (- (:source/lgt source) (:to/lgt to)))
]
(* (* raio (* 2 (Math/atan2 (Math/sqrt (+ (Math/pow (Math/sin (/ delta-latitude 2)) 2)
(* (Math/cos (Math/toRadians (:source/ltd source))) (Math/cos (Math/toRadians (:to/ltd to))) (Math/sin (/ delta-longitude 2)) (Math/sin (/ delta-longitude 2)))))
(Math/sqrt (- 1 (+ (Math/pow (Math/sin (/ delta-latitude 2)) 2)
(* (Math/cos (Math/toRadians (:source/ltd source))) (Math/cos (Math/toRadians (:to/ltd to)) ) (Math/sin (/ delta-longitude 2)) (Math/sin (/ delta-longitude 2))))))))) 1000)
)
)
)发布于 2017-05-13 13:16:22
预条件
让我们减少这个函数,这样它就可以分解它的参数:
(defn calculate-distance
"Calcula distância entre duas coordenadas geográficas"
[source to]
{:pre [every? (every-pred map? #(contains? % :lgt) #(contains? % :ltd)) [source to]]}
(let [delta-latitude (Math/toRadians (- (:source/ltd source) (:to/ltd to)))
delta-longitude (Math/toRadians (- (:source/lgt source) (:to/lgt to)))]
[delta-latitude delta-longitude]))(我已经不使用包含单个数据的无害但多余的括号了)。
前提是
{:pre [every? (every-pred map? #(contains? % :lgt) #(contains? % :ltd)) [source to]]}这反过来评估,
every?(every-pred map? #(contains? % :lgt) #(contains? % :ltd))[source to]..。所有这些在逻辑上都是正确的--两个函数和一个向量。
您需要将整个表达式包装在( ... )中,以使其评估:
{:pre [(every? (every-pred map? #(contains? % :lgt) #(contains? % :ltd)) [source to])]}在我们这样做之前,让我们看一下函数所需的数据形状。例如,
(calculate-distance {:source/ltd 0, :source/lgt 0}
{:to/ltd 0, :to/lgt 0})
=> [0.0 0.0]let中的表达式使用限定关键字::source/ltd .。
这很糟糕。我们希望用相同的形状指定两个点--因为它们实际上是对称的:从这里到那里的距离和从这里到这里的距离是一样的。
让我们来看看(校正的)前提条件所需的形状:
(defn calculate-distance
"Calcula distância entre duas coordenadas geográficas"
[source to]
{:pre [(every? (every-pred map? #(contains? % :lgt) #(contains? % :ltd)) [source to])]}
(let [delta-latitude (Math/toRadians (- (:ltd source) (:ltd to)))
delta-longitude (Math/toRadians (- (:lgt source) (:lgt to)))]
[delta-latitude delta-longitude]))现在
(calculate-distance {:source/ltd 0, :source/lgt 0}
{:to/ltd 0, :to/lgt 0})
AssertionError ...但
(calculate-distance {:ltd 0, :lgt 0}
{:ltd 0, :lgt 0})
=> [0.0 0.0]到现在为止还好。
让我们举几个简单的例子:
(calculate-distance {:ltd 0, :lgt 0}
{:ltd 0, :lgt 0})
=> 0.0好的。
(calculate-distance {:ltd 0, :lgt 0}
{:ltd 0, :lgt 90})
=> 1.0010363727626067E7从北极到赤道沿格林威治子午线的距离约为一千万米或一万公里--没错。
至于计算,我对其他的答案没有什么可补充的。尽管我希望在JVM环境中像您这样做并直接调用Math函数。
https://codereview.stackexchange.com/questions/156722
复制相似问题