Advertisement
Guest User

Untitled

a guest
Feb 11th, 2011
514
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
F# 7.84 KB | None | 0 0
  1. #r "System.Windows.dll"
  2. #r "System.Windows.Controls.dll"
  3. #r "TryFSharp.dll"
  4.  
  5. open System
  6. open System.Windows
  7. open System.Windows.Controls
  8. open Microsoft.TryFSharp
  9.  
  10. let canvas = App.Console.Canvas
  11.  
  12. let dispatch f =
  13.     Deployment.Current.Dispatcher.BeginInvoke (fun() -> f())
  14.  
  15. open System.Windows.Media
  16. open System.Windows.Shapes
  17.  
  18. //-----------------------------------------------
  19.  
  20. type IPaintObject =
  21.     abstract Paint : Canvas -> unit
  22.    
  23. // Keep a list of objects to draw
  24. let paintObjects = new ResizeArray<IPaintObject>()
  25.  
  26. //-----------------------------------------------
  27.  
  28. [<Measure>] type m
  29. [<Measure>] type km
  30. [<Measure>] type AU
  31. [<Measure>] type sRealTime
  32. [<Measure>] type s
  33. [<Measure>] type kg
  34. [<Measure>] type pixels
  35.  
  36. let G = 6.67e-11<m ^ 3 / (kg s^2)>
  37. let m_per_AU = 149597870691.0<m/AU>
  38. let AU_per_m = 1.0/m_per_AU
  39. let Pixels_per_AU = 200.0<pixels/AU>
  40. let m_per_km = 1000.0<m/km>
  41. let AU_per_km = m_per_km * AU_per_m
  42. let sec_per_year = 60.0<s> * 60.0 * 24.0 * 365.0
  43.  
  44. type System.TimeSpan with
  45.     member x.TotalSecondsTyped = (box x.TotalSeconds :?> float<sRealTime>)
  46.  
  47. // One second of real time is 1/80th of a year of model time
  48. let realTimeToModelTime (x:float<sRealTime>) = float x * sec_per_year / 80.0
  49.  
  50. type Planet(ipx:float<AU>,ipy:float<AU>,
  51.             ivx:float<AU/s>,ivy:float<AU/s>,
  52.             //brush:Brush,mass:float<kg>,
  53.             color:Color,mass:float<kg>,
  54.             width,height) =
  55.  
  56.     // For this sample we store the simulation state directly in the object
  57.     let mutable px = ipx
  58.     let mutable py = ipy
  59.     let mutable vx = ivx
  60.     let mutable vy = ivy
  61.  
  62.     // We also store the visual state
  63.     let mutable shape = null
  64.    
  65.     member p.Mass = mass
  66.     member p.X with get() = px and set(v) = (px <- v)
  67.     member p.Y with get() = py and set(v) = (py <- v)
  68.     member p.VX with get() = vx and set(v) = (vx <- v)
  69.     member p.VY with get() = vy and set(v) = (vy <- v)
  70.    
  71.     interface IPaintObject with
  72.         member obj.Paint(canvas) =
  73.             if (shape = null) then
  74.                 shape <- new Ellipse(Width=width,Height=height,Fill=new SolidColorBrush(color))
  75.                 canvas.Children.Add shape
  76.  
  77.             let x = float (px * Pixels_per_AU)-width/2.0
  78.             let y = float (py * Pixels_per_AU)-height/2.0
  79.             Canvas.SetLeft(shape, x)
  80.             Canvas.SetTop(shape, y)
  81.                  
  82. //-----------------------------------------------
  83.  
  84. type Simulator() =
  85.     // Get the start time for the animation
  86.     let startTime = System.DateTime.Now
  87.     let lastTimeOption = ref None
  88.  
  89.     let ComputeGravitationalAcceleration (obj:Planet) (obj2:Planet) =
  90.         let dx = (obj2.X-obj.X)*m_per_AU
  91.         let dy = (obj2.Y-obj.Y)*m_per_AU
  92.         let d2 = (dx*dx) + (dy*dy)
  93.         let d = sqrt d2
  94.         let g = obj.Mass * obj2.Mass * G /d2
  95.         let ax = (dx / d) * g / obj.Mass
  96.         let ay = (dy / d) * g / obj.Mass
  97.         ax,ay
  98.  
  99.     /// Find all the gravitational objects in the system except the given object
  100.     let FindObjects(obj) =
  101.         [ for paintObject in paintObjects do
  102.                 match paintObject with
  103.                 | :? Planet as p2 when p2 <> obj ->
  104.                     yield p2
  105.                 | _ ->
  106.                     yield! [] ]
  107.  
  108.     member sim.Step(time:TimeSpan) =
  109.         match !lastTimeOption with
  110.         | None -> ()
  111.         | Some(lastTime) ->
  112.             for paintObject in paintObjects do
  113.                 match paintObject with
  114.                 | :? Planet as obj ->
  115.                     let timeStep = (time - lastTime).TotalSecondsTyped |>  realTimeToModelTime
  116.                     obj.X <- obj.X + timeStep * obj.VX
  117.                     obj.Y <- obj.Y + timeStep * obj.VY
  118.  
  119.                     // Find all the gravitational objects in the system
  120.                     let objects = FindObjects(obj)
  121.  
  122.                     // For each object, apply its gravitational field to this object
  123.                     for obj2 in objects do
  124.                         let (ax,ay) = ComputeGravitationalAcceleration obj obj2
  125.                         obj.VX <- obj.VX + timeStep * ax * AU_per_m
  126.                         obj.VY <- obj.VY + timeStep * ay * AU_per_m
  127.                 | _ ->  ()
  128.  
  129.         lastTimeOption := Some time
  130.  
  131.     member sim.Start() =
  132.         async { while true do
  133.                     let time = System.DateTime.Now - startTime
  134.                     // Sleep a little to give better GUI updates
  135.                     do! Async.Sleep(1)
  136.                     sim.Step(time) }
  137.         |> Async.Start
  138.  
  139. let s = Simulator().Start()
  140.                                                  
  141. //-----------------------------------------------
  142.  
  143. let massOfEarth   = 5.9742e24<kg>
  144. let massOfMoon    = 7.3477e22<kg>
  145. let massOfMercury = 3.3022e23<kg>
  146. let massOfVenus   = 4.8685e24<kg>
  147. let massOfSun     = 1.98892e30<kg>
  148.  
  149. let mercuryDistanceFromSun  = 57910000.0<km> * AU_per_km
  150. let venusDistanceFromSun    = 0.723332<AU>
  151. let distanceFromMoonToEarth =384403.0<km> * AU_per_km
  152.  
  153. let orbitalSpeedOfMoon   = 1.023<km/s> * AU_per_km
  154. let orbitalSpeedOfMecury = 47.87<km/s> * AU_per_km
  155. let orbitalSpeedOfVenus  = 35.02<km/s> * AU_per_km
  156. let orbitalSpeedOfEarth  = 29.8<km/s>  * AU_per_km
  157.  
  158. let sun   = new Planet(ipx=1.1<AU>,                        
  159.                         ipy=1.1<AU>,
  160.                         ivx=0.0<AU/s>,
  161.                         ivy=0.0<AU/s>,
  162.                         color=Colors.Yellow,
  163.                         mass=massOfSun,
  164.                         width=20.0,
  165.                         height=20.0)
  166.  
  167. let mercury = new Planet(ipx=sun.X+mercuryDistanceFromSun,
  168.                         ipy=sun.Y,
  169.                         ivx=0.0<AU/s>,
  170.                         ivy=orbitalSpeedOfMecury,
  171.                         color=Colors.Brown,
  172.                         mass=massOfMercury,
  173.                         width=10.0,
  174.                         height=10.0)
  175.  
  176. let venus = new Planet(ipx=sun.X+venusDistanceFromSun,
  177.                         ipy=sun.Y,
  178.                         ivx=0.0<AU/s>,
  179.                         ivy=orbitalSpeedOfVenus,
  180.                         color=Colors.LightGray,
  181.                         mass=massOfVenus,
  182.                         width=10.0,
  183.                         height=10.0)
  184.  
  185. let earth = new Planet(ipx=sun.X+1.0<AU>,
  186.                         ipy=sun.Y,
  187.                         ivx=0.0<AU/s>,
  188.                         ivy=orbitalSpeedOfEarth,
  189.                         color=Colors.Green,
  190.                         mass=massOfEarth,
  191.                         width=10.0,
  192.                         height=10.0)
  193.  
  194. let moon  = new Planet(ipx=earth.X+distanceFromMoonToEarth,
  195.                         ipy=earth.Y,
  196.                         ivx=earth.VX,
  197.                         ivy=earth.VY+orbitalSpeedOfMoon,
  198.                         color=Colors.White,
  199.                         mass=massOfMoon,
  200.                         width=2.0,
  201.                         height=2.0)
  202.  
  203. let renderScene() =
  204.  
  205.     // Inner canvas represents the space in which planets move
  206.     let space = new Canvas(Width=500.0,Height=500.0,Background=new SolidColorBrush(Colors.Blue))
  207.  
  208.     canvas.Children.Add space
  209.  
  210.     let center() =
  211.         Canvas.SetLeft(space, max 0.0 (canvas.ActualWidth - space.Width)/2.0)
  212.         Canvas.SetTop(space, max 0.0 (canvas.ActualHeight - space.Height)/2.0)    
  213.  
  214.     // Center the inner canvas and keep it centered
  215.     center()
  216.     canvas.SizeChanged.Add(fun (eArg) -> center())
  217.  
  218.     // Add planets to visualize          
  219.     paintObjects.Add(sun)
  220.     paintObjects.Add(mercury)
  221.     paintObjects.Add(venus)
  222.     paintObjects.Add(earth)
  223.     paintObjects.Add(moon)
  224.    
  225.     // Start rendering loop
  226.     CompositionTarget.Rendering.Add(fun e ->
  227.         // Draw the paint objects
  228.         for paintObject in paintObjects do
  229.             paintObject.Paint space
  230.     )
  231.  
  232.  
  233. dispatch renderScene
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement