Created
August 5, 2017 15:11
-
-
Save folkertdev/ff53e9b1182d2fc29e937e69dfe5c50d to your computer and use it in GitHub Desktop.
A proposal to allow easier composition of SubPaths
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
module SubPath exposing (..) | |
import Path exposing (DrawTo(..), MoveTo(..), lineTo, closePath, moveTo) | |
import Deque exposing (Deque) | |
import Vector2 as Vec2 exposing (Vec2) | |
import List.Extra as List | |
type SubPath | |
= SubPath { moveto : MoveTo, drawtos : Deque DrawTo } | |
| Empty | |
subpath : MoveTo -> List DrawTo -> SubPath | |
subpath moveto drawtos = | |
SubPath { moveto = moveto, drawtos = Deque.fromList drawtos } | |
area : List ( ( Float, Float ), ( Float, Float ) ) -> SubPath | |
area points = | |
let | |
( low, high ) = | |
points | |
|> List.unzip | |
in | |
step 1.0 low | |
|> connect (step 1.0 high) | |
|> close | |
{-| Join two subpaths, connecting them with a straight line | |
-} | |
connect : SubPath -> SubPath -> SubPath | |
connect x y = | |
case ( x, y ) of | |
( Empty, Empty ) -> | |
Empty | |
( Empty, subpath ) -> | |
subpath | |
( subpath, Empty ) -> | |
subpath | |
( SubPath a, SubPath b ) -> | |
let | |
(MoveTo secondStart) = | |
b.moveto | |
in | |
SubPath | |
{ moveto = a.moveto | |
, drawtos = | |
Deque.append a.drawtos (Deque.pushFront (lineTo [ secondStart ]) b.drawtos) | |
} | |
close : SubPath -> SubPath | |
close subpath = | |
case subpath of | |
Empty -> | |
Empty | |
SubPath { moveto, drawtos } -> | |
case Deque.popBack drawtos of | |
( Just ClosePath, preceding ) -> | |
-- subpath is already closed, return original | |
subpath | |
_ -> | |
SubPath { moveto = moveto, drawtos = Deque.pushBack closePath drawtos } | |
{-| Draw straight lines between the data points. | |
<img style="max-width: 100%;" src="https://rawgit.com/folkertdev/one-true-path-experiment/master/docs/linear.svg" /> | |
-} | |
linear : List (Vec2 Float) -> SubPath | |
linear points = | |
case points of | |
[] -> | |
Empty | |
x :: xs -> | |
subpath (moveTo x) [ lineTo xs ] | |
{-| Step goes some distance to the right, then to the y-coordinate of the next data point, and then draws to the next point. | |
The first argument determines where the step is. | |
* `step 1 points` is `stepAfter` | |
* `step 0 points` is `stepBefore` | |
* `step 0.5 points` steps exactly in the middle | |
<img style="max-width: 100%;" src="https://rawgit.com/folkertdev/one-true-path-experiment/master/docs/step.svg" /> | |
-} | |
step : Float -> List (Vec2 Float) -> SubPath | |
step factor points = | |
let | |
helper ( x0, y0 ) ( x, y ) = | |
if factor <= 0 then | |
[ ( x0, y ), ( x, y ) ] | |
else | |
let | |
x1 = | |
x0 * (1 - factor) + x * factor | |
in | |
[ ( x1, y0 ), ( x1, y ) ] | |
in | |
case points of | |
[] -> | |
Empty | |
p :: ps -> | |
p | |
:: (List.concat (List.map2 helper points ps) ++ [ List.last ps |> Maybe.withDefault p ]) | |
|> linear |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment