Создать отрезок из двух точек в Clojure - PullRequest
3 голосов
/ 28 марта 2011

Какой лучший способ сделать это?Вот то, что у меня есть до сих пор

(defn line-segment [start end]
  (let [x-direction (abs (- (first end) (first start)))
        y-direction (abs (- (last end) (last start)))]
    (cond
      (= 0 x-direction) (something ...)
      (= 0 y-direction) (something ...))))

Вот моя конечная цель

user=> (line-segment [5 6] [5 8])
([5 6] [5 7] [5 8])

И да, диагоналей нет, только движение x или y.

Спасибо.

Ответы [ 2 ]

2 голосов
/ 28 марта 2011

Я думаю, что это довольно элегантное решение:

(defn line-segment [start end]
  (let [x1 (first start) x2 (first end)
        y1 (last start)  y2 (last end)
        dx (if (> x1 x2) -1 1)
        dy (if (> y1 y2) -1 1)]
    (for [x (range x1 (+ dx x2) dx)
          y (range y1 (+ dy y2) dy)]
      [x y])))

REPL сессия:

user> (line-segment [5 6] [5 8])
([5 6] [5 7] [5 8])
user> (line-segment [5 8] [5 6])
([5 8] [5 7] [5 6])
user> (line-segment [-2 7] [1 7])
([-2 7] [-1 7] [0 7] [1 7])
user> (line-segment [1 7] [-2 7])
([1 7] [0 7] [-1 7] [-2 7])

Эта функция возвращает LazySeq, даже если ваш пример выходных данных был отформатирован как вектор,Я подумал, что это не важно.

0 голосов
/ 28 марта 2011

Вот простое решение, которое также допускает диагонали:

(use 'clojure.contrib.math)

(defn line-segment [start end]
  (let [x1 (first start) x2 (first end)
        y1 (last start)  y2 (last end)
        xdiff (- x2 x1)
        ydiff (- y2 y1)
        maxdiff (max (abs xdiff) (abs ydiff))
        dx (/ xdiff maxdiff)
        dy (/ ydiff maxdiff)]
    (for [i (range (inc maxdiff))]
      [(round (+ x1 (* i dx))) (round (+ y1 (* i dy)))])))

Как и в случае решения dbryne, это возвращает ленивую последовательность точек, а не вектор: я думаю, что это наиболее полезная форма, предполагающая, что вы впоследствии захотите что-то сделать с каждой из точек на отрезке линии по очереди.

...