Search code examples
clojureclojure-contrib

Create line segment from two points in Clojure


What's the best way to go about doing this? Here's what I've got so far

(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 ...))))

Here's my end goal

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

And yes, there are no diagonals, only x or y movement.

Thanks.


Solution

  • I think this is a pretty elegant solution:

    (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 session:

    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])
    

    This function returns a LazySeq even though your sample output was formatted as a vector. I figured this wasn't important.