Safe Haskell | Safe-Inferred |
---|---|
Language | Haskell2010 |
Documentation
Find the iso lines of a function (= where the function has the same height,
like e.g. height lines on a map) within a certain Grid
(which unifies size and
resolution).
This function can be partially applied to cache the function values when drawing iso lines, which is especially useful if repeatedly sampling the function is expensive:
-- BAD! Recalculates the values of f across the grid for each invocationisosBad
= [isoLines
grid f isoHeight | isoHeight <- [1..10]] -- Good: Calculates the value table only onceisosGood
= let iso =isoLines
grid f in [iso isoHeight | isoHeight [1..10]]
This is also the reason why the contour threshold is not implitly zero but an explicit parameter: if we used the family of functions \(f_h(x) = f(x)-h\) to calculate the iso lines at height \(h\), we would have to recreate the value table for each invocation.
Concrete example
Let’s draw some circles! The equation of a circle of radius \(r\) at point \(p\) is
\[ \left\{ x \; \big| \; \| x-p\| = r, \, x\in\mathbb R^2 \right\} \]
We can translate this directly into code like so (squaring the equation to save us a costly call to sqrt
),
circle p = \x ->normSquare
(x-.
p)
and finding the contour lines at height \(r^2\) gives us our circles!
grid ::Grid
grid =Grid
(Vec2
(-10) (-10),Vec2
10 10) (100, 100) circleTrajectory ::Double
-> [Vec2
] circleTrajectory = let iso =isoLines
grid (circlezero
) in \r -> head (iso (r^
2)) -- NB head is safe here because each of our functions has exactly one iso line at a certain height manyCircles :: [[Vec2
]] manyCircles =map
circleTrajectory [1..9]
Specification of a discrete grid, used for sampling contour lines.
Subdivide the unit square with 50 squares (51 steps!) in x direction, and 30 (31 steps!) in y direction:
Grid
(Vec2
0 0,Vec2
1 1) (50, 30)