First I want a function that will

**tabulate**a function f.

f is to be a function of two floats x and y returning a float. The table is to operate over an x-axis range and a y-axis range, each described by a tuple of floats. So here is a sample function of the type I mean:

let testfun (x:float) (y:float) =

let r = sqrt ((x * x) + (y * y))

if r < 2.0

then

if r < 1.0

then 7.0

else 4.0

else

0.0

My

**tabulate**function is to return a two-dimensional array of floats. Here it is:

let tabulate funct (xrange : (float*float)) (yrange : (float*float)) : float[,]=

let x0 = fst xrange

let dx = (snd xrange - fst xrange) / 50.0

let y0 = fst yrange

let dy = (snd yrange - fst yrange) / 50.0

Array2D.init 51 51 (fun i j -> funct (x0+(float i * dx)) (y0+(float j * dy)))

The function

**Array2D.init**takes the size of the two dimensions of the array and a function that will populate each element in the array, given the indices I and j. I'm breaking my ranges into 50 parts so I want 51 elements in each direction.

Now to

**project**this table of values as in isometric type sheet: create a new array of the same size but here each element is a tuple of values p and q that represent screen coordinates. p works down from the top left and q works across. So p and q depend on the index i and j, and p also depends on the value of the array that I've passed through. I've scaled the value by 10.0 pixels quite arbitrarily. The grid is drawn by going right 5 pixels per cell and either up or down by 3.5 pixels for p and q axis, so:

let project (valueTable : float [,]) : (float * float)[,] =

Array2D.init 51 51

(fun (i:int) (j:int) ->

let p = (float i * 5.0) + (float j * 5.0) + 20.0

let q = (float i * 3.5) - (float j * 3.5) + 300.0 - (valueTable.[i,j] * 10.0)

(p,q))

Right, now I want to

**plot**out the projected table as an SVG element. After some research it looks like this is the thing to do:

let plot (a:(float * float)[,]) : unit =

use file = System.IO.File.CreateText("plotout.svg")

fprintfn file """<svg xmlns="http://www.w3.org/2000/svg" version="1.1">"""

for j in 0..49 do

for i in 0..49 do

fprintf file """<polygon fill="#FFFFFF" """

fprintf file """stroke="#000000" stroke-width="1" points="""

fprintfn file "\"%.2f,%.2f %.2f,%.2f %.2f,%.2f %.2f,%.2f\" "

(fst a.[i,j]) (snd a.[i,j])

(fst a.[i,j+1]) (snd a.[i,j+1])

(fst a.[i+1,j+1]) (snd a.[i+1,j+1])

(fst a.[i+1,j]) (snd a.[i+1,j])

fprintfn file """/>"""

fprintfn file """</svg>"""

The SVG document contains a

**polygon**element which has a fill colour and a stroke width and colour and a list of points - each point is represented by a two floats separated by a comma. For each element i, j I'm drawing a four sided shape with the points from i,j - i+1,j - i+1,j+1 - i,j+1.

So finally to tabulate and plot my test function in the range -3 to 3:

let main () =

(tabulate testfun (-3.0, 3.0) (-3.0, 3.0)) |> project |> plot

Then you can open the resulting file in the browser:

This looks a bit rough round the back of the raised area. Really I need to plot starting from the cells that are furthest away and then working forward, so get the hidden ones properly hidden. Still, nice first try.

## No comments:

## Post a Comment