Answer
It’s all a bit easier to discuss if we start with horizontal lines, like so:
As Ilmari Karonen said, this is just a displacement map. You start with a 3D topography h(x,y), and then each point (x,y) in the result should use the line starting at y0 = y − h(x,y).
With raster graphics, this can be rendered straight away, but to get clean vector lines we’d actually need to work the other way around: each line should be parameterised as
fy0(x) = y0 + h(x, fy0(x))
The problem is that this is only an implicit defining equation, because the RHS contains y = fy0(x). This could be solved with Newton-Raphson, but there’s a simpler way: just construct the lines going from left to right, and at each point go up or down as needed to fulfill the equation. Assuming continuity, this is always just a small update, so we can approximate h as constant there.
Implementation in Haskell:
type ℝ = Double
horizContourLine ::
((ℝ,ℝ) -> ℝ) -- ^ The topography/height function
-> (ℝ,ℝ) -- ^ x-interval on which to render the path
-> ℝ -- ^ Step size / resolution along the path
-> ℝ -- ^ Base-level y-coordinate of the line
-> [(ℝ,ℝ)] -- ^ Trail line
horizContourLine h (x₀,xe) δx y₀ = go (x₀,y₀)
where go (x,y) = (x,yTgt)
: if x<xe then go (x+δx, yTgt)
else []
where yTgt = y₀ + h (x,y)
Then, with a suitable image input like
we get contours like
Full code: https://gist.github.com/leftaroundabout/8b7075d25adecdf16806ea5d7a7ea2aa
Rotation to diagonal lines is left as an exercise.
Attribution
Source : Link , Question Author : aamee traders , Answer Author : leftaroundabout