Skip to content

Instantly share code, notes, and snippets.

@mefuru
Created November 29, 2017 11:40
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mefuru/455cda84c3d705cb694d3fa60f519361 to your computer and use it in GitHub Desktop.
Save mefuru/455cda84c3d705cb694d3fa60f519361 to your computer and use it in GitHub Desktop.
squircle
;; Wed Nov 29 10:09:47 2017
;; Draw a square using trig
;; Instructions
;; cider-jack-in
;; cider-refresh
;; User interactions
(ns my-sketch.core
(:require [quil.core :as q]
[quil.middleware :as m]))
(def num-points 720)
(defn h
([] (h 1.0))
([value] (* (q/height) value)))
(defn w
([] (w 1.0))
([value] (* (q/width) value)))
(defn setup []
(q/no-loop)
(q/stroke-weight 0.5))
(defn key-pressed [state event]
(let [key-p (:key event)
new-state (case key-p
:s (do
(q/save (str (java.util.Date.)))
state)
(do
state
))]
new-state))
(defn update-state [state]
state)
(defmacro doseq-indexed [index-sym [item-sym coll] & body]
`(doseq [[~index-sym ~item-sym] (map list (range) ~coll)]
~@body))
(defn sign [x]
(cond
(< x 0) -1
(> x 0) 1
:else 0))
(defn squircle-x [theta width]
(* width
(sign (q/cos theta))
(q/sqrt (Math/abs (q/cos theta)))))
(defn squircle-y [theta width]
(* width
(sign (q/sin theta))
(q/sqrt (Math/abs (q/sin theta)))))
(defn draw-squircle [radius]
(let [thetas (range 0 (* 2 Math/PI) (/ Math/PI num-points))
xs (map (fn[theta] (squircle-x theta radius))
thetas)
ys (map (fn[theta] (squircle-y theta radius))
thetas)]
(doseq-indexed i [x xs]
(let [y (nth ys i)]
(q/point x y)))))
(defn circle-x [theta width]
(* width (q/cos theta)))
(defn circle-y [theta width]
(* width (q/sin theta)))
(defn draw-circle [radius]
(let [thetas (range 0 (* 2 Math/PI) (/ Math/PI num-points))
xs (map (fn[theta] (circle-x theta radius))
thetas)
ys (map (fn[theta] (circle-y theta radius))
thetas)]
(doseq-indexed i [x xs]
(let [y (nth ys i)]
(q/point x y)))))
(defn square-x [theta width]
(cond
(< theta (* Math/PI 0.25)) width
(< theta (* Math/PI 0.75)) (* width (/ 1 (q/tan theta)))
(< theta (* Math/PI 1.25)) (- width)
(< theta (* Math/PI 1.75)) (* -1 width (/ 1 (q/tan theta)))
:else width))
(defn square-y [theta width]
(cond
(< theta (* Math/PI 0.25)) (* width (q/tan theta))
(< theta (* Math/PI 0.75)) width
(< theta (* Math/PI 1.25)) (* -1 width (q/tan theta))
(< theta (* Math/PI 1.75)) (- width)
:else (* (q/tan theta) width)))
(defn draw-square[width]
(let [thetas (range 0 (* 2 Math/PI) (/ Math/PI num-points))
xs (map (fn[theta] (square-x theta width))
thetas)
ys (map (fn[theta] (square-y theta width))
thetas)]
(doseq-indexed i [x xs]
(let [y (nth ys i)]
(q/point x y)))))
(defn half-circle-half-squircle [width lerp-amount]
(let [thetas (range 0 (* 2 Math/PI) (/ Math/PI num-points))
xs-circle (map (fn[theta] (circle-x theta width))
thetas)
ys-circle (map (fn[theta] (circle-y theta width))
thetas)
xs-squircle (map (fn[theta] (squircle-x theta width))
thetas)
ys-squircle (map (fn[theta] (squircle-y theta width))
thetas)
xs (map-indexed (fn [i x]
(q/lerp x (nth xs-squircle i) lerp-amount))
xs-circle)
ys (map-indexed (fn [i y]
(q/lerp y (nth ys-squircle i) lerp-amount))
ys-circle)]
(doseq-indexed i [x xs]
(let [y (nth ys i)]
(q/point x y)))))
(defn half-square-half-squircle [width lerp-amount]
(let [thetas (range 0 (* 2 Math/PI) (/ Math/PI num-points))
xs-square (map (fn[theta] (square-x theta width))
thetas)
ys-square (map (fn[theta] (square-y theta width))
thetas)
xs-squircle (map (fn[theta] (squircle-x theta width))
thetas)
ys-squircle (map (fn[theta] (squircle-y theta width))
thetas)
xs (map-indexed (fn [i x]
(q/lerp x (nth xs-squircle i) lerp-amount))
xs-square)
ys (map-indexed (fn [i y]
(q/lerp y (nth ys-squircle i) lerp-amount))
ys-square)]
(doseq-indexed i [x xs]
(let [y (nth ys i)]
(q/point x y)))))
(defn half-square-half-circle [width lerp-amount]
(let [thetas (range 0 (* 2 Math/PI) (/ Math/PI num-points))
xs-square (map (fn[theta] (square-x theta width))
thetas)
ys-square (map (fn[theta] (square-y theta width))
thetas)
xs-circle (map (fn[theta] (circle-x theta width))
thetas)
ys-circle (map (fn[theta] (circle-y theta width))
thetas)
xs (map-indexed (fn [i x]
(q/lerp x (nth xs-circle i) lerp-amount))
xs-square)
ys (map-indexed (fn [i y]
(q/lerp y (nth ys-circle i) lerp-amount))
ys-square)]
(doseq-indexed i [x xs]
(let [y (nth ys i)]
(q/point x y)))
))
(defn mix-shapes [shape-1 shape-2 width lerp-amt]
(let [thetas (range 0 (* 2 Math/PI) (/ Math/PI num-points))
x-fn-1 (case shape-1
"squircle" squircle-x
"square" square-x
"circle" circle-x)
y-fn-1 (case shape-1
"squircle" squircle-y
"square" square-y
"circle" circle-y)
x-fn-2 (case shape-2
"squircle" squircle-x
"square" square-x
"circle" circle-x)
y-fn-2 (case shape-2
"squircle" squircle-y
"square" square-y
"circle" circle-y)
xs-1 (map (fn[theta] (x-fn-1 theta width))
thetas)
ys-1 (map (fn[theta] (y-fn-1 theta width))
thetas)
xs-2 (map (fn[theta] (x-fn-2 theta width))
thetas)
ys-2 (map (fn[theta] (y-fn-2 theta width))
thetas)
xs (map-indexed (fn [i x]
(q/lerp x (nth xs-2 i) lerp-amt))
xs-1)
ys (map-indexed (fn [i y]
(q/lerp y (nth ys-2 i) lerp-amt))
ys-1)]
(doseq-indexed i [x xs]
(let [y (nth ys i)]
(q/point x y)))
))
(defn draw [state]
(q/translate (w 0.5) (h 0.5))
;; (draw-circle 100)
;; (draw-square 100)
;; (half-square-half-circle 100 0.5)
;; (half-circle-half-squircle 100 0.5)
;; (half-square-half-squircle 100 0.5)
;; (mix-shapes "square" "circle" 100 0.5)
(doseq [lerp-amt (vec (range -10 1 0.1))]
(mix-shapes "squircle" "circle" 100 lerp-amt)
)
;; (draw-squircle 100)
(q/save (str (java.util.Date.))))
(q/defsketch my-sketch
:title "Square with theta"
:size [500 500]
:setup setup
:update update-state
:key-pressed key-pressed
:draw draw
:features [:keep-on-top]
:middleware [m/fun-mode])
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment