Created
May 29, 2012 10:36
-
-
Save bohdanszymanik/2824858 to your computer and use it in GitHub Desktop.
MichLet file generator from Kayak Foundry export
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
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) ) | |
) |
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
Still in development...