Skip to content

Instantly share code, notes, and snippets.

@bohdanszymanik
Created May 29, 2012 10:36
Show Gist options
  • Save bohdanszymanik/2824858 to your computer and use it in GitHub Desktop.
Save bohdanszymanik/2824858 to your computer and use it in GitHub Desktop.
MichLet file generator from Kayak Foundry export
open System
open System.IO
let cSs = File.ReadAllLines(@"C:\Extras\kfoundry1.6.4\520x50a.txt")
(*
Raw form data exported from kfoundry with baseline at the waterline looks like this:
Form Position, X (mm), Y (mm)
...
Form at 52 cm, 60, 39.3333
Form at 52 cm, 54.6667, 25
Form at 52 cm, 49, 11.6667
Form at 52 cm, 43, 0
Form at 52 cm, 36.6667, -10
Form at 52 cm, 33.3333, -14.6667
Form at 52 cm, 29.6667, -18.6667
Form at 52 cm, 28, -20.6667
...
Michlet only takes shape data for the below the waterline - so we only want the negative portion.
Michlet uses constant vertical intervals... so we need to treat y like x and interpolate a value for x
*)
let rawForms =
cSs
|> Seq.skip 1
|> Seq.filter (fun l -> not(l.StartsWith("Cockpit") ) )
|> Seq.filter (fun l -> not(l.StartsWith("Bow") ) )
|> Seq.filter (fun l -> not(l.StartsWith("Stern") ) )
|> Seq.filter ( String.IsNullOrEmpty >> not )
let parseRawForm (s:string) =
let values = s.Replace("0,", "0.").Replace(",", "").Split(' ' )
// and change to metres
(float values.[2])/100., (float values.[4])/1000., (float values.[5])/1000.
let forms =
rawForms
|> Seq.map parseRawForm
// z is Form Postion, the x and y are reversed from the file header
|> Seq.filter ( fun (_,_,y) -> y <= 0.)
|> Seq.groupBy ( fun (z, _, _) -> z)
|> Seq.map (fun (z,zxy) -> (z, zxy |> Seq.map (fun (z,x,y) -> (-1. * y, x) ) |> Seq.sortBy (fun (y, _) -> y ) ) ) // changed to a function of height
let inline interpolateY xys x =
let rec getX1Y1X2Y2' xys x =
//printfn "list: %A" xys
match xys with
| (_, _)::[] -> 0.
| [] -> 0. // if not found then michlet expects a 0 - also, that typed 0 is negating the benefit of the inline...
| (x1, y1)::t ->
let (x2, y2) = t.Head
if (x1 <= x) && (x < x2) then
//printfn "%A adjacent points: %A" x (x1, y1, x2, y2)
y1 + ( (y2 - y1) / (x2 - x1) * ( x - x1) )
else
getX1Y1X2Y2' t x
getX1Y1X2Y2' xys x
let _,maxX = forms |> Seq.map (fun (z, xys) -> z, xys |> Seq.maxBy (fun (x,_) -> x) |> fun (x,_) -> x ) |> Seq.maxBy (fun (z, x) -> x)
let divs = 10.
let xVals = [0. .. maxX/divs .. maxX ]
// for each station
// iterate through xs getting the intepolated ys - straight lines good enough after all chines can be discontinuous
// write out ys - one line per station
forms
|> Seq.iter ( fun (z, xys) ->
let interpolatedValues =
xVals
|> Seq.map (fun xv -> sprintf "%.4f" (interpolateY (Seq.toList xys) xv ) )
|> Seq.toList
|> List.rev
//printfn "%A - %A - %s" z (Seq.toList xys) ( String.Join(",", interpolatedValues) )
printfn "%s" ( String.Join(",", interpolatedValues) )
)
@bohdanszymanik
Copy link
Author

OK, gives the right interpolated offsets now...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment