Advertisement
Guest User

Untitled

a guest
May 7th, 2018
77
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
F# 10.66 KB | None | 0 0
  1. module sampling
  2. open Tracer
  3. open Interfaces
  4. open System
  5.  
  6. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  7. //                                               logic for creating sampleSets                                                                          //
  8. //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  9.  
  10. let private ran = new System.Random()
  11.  
  12. //takes a lower and an upper-bound of a box. Returns a random value within that box
  13. let private randomInBound value increment =
  14.             let lowerValue = value-increment
  15.             let mutable rnvalue = (ran.NextDouble()*((value-lowerValue))+lowerValue)
  16.             if rnvalue > value then rnvalue <- rnvalue-increment
  17.             if rnvalue < lowerValue then rnvalue <- rnvalue
  18.             rnvalue
  19.  
  20. //combines 2 arrays of values into a tupple array
  21. let private combineXY (listx:array<float>) (listy:array<float>) =
  22.     let mutable tmp = Array.create listx.Length (0.0,0.0)
  23.     for i in [0 .. listx.Length-1]
  24.         do
  25.         tmp.[i] <- (listx.[i],listy.[i])
  26.     tmp
  27.  
  28. // Knuth shuffle on array
  29. let private shuffle inputArray =
  30.     for x in [0 .. (Array.length inputArray)-1]
  31.         do
  32.         let randomValue = ran.Next(0, Array.length inputArray)
  33.         let tmp = inputArray.[x]
  34.         inputArray.[x] <- inputArray.[randomValue]
  35.         inputArray.[randomValue] <- tmp
  36.  
  37. // creates x amount of samplemethod
  38. let private createSetsOfSampleMethod sampleMethod setsAmount n =
  39.     let mutable sampleSets = Array.create setsAmount [||]
  40.     for i in [0 .. (setsAmount-1)]
  41.         do
  42.         sampleSets.[i] <- (sampleMethod n)
  43.     shuffle sampleSets
  44.     sampleSets
  45.  
  46. // Given a natural number n produces n^2 regular placed sample points.
  47. let private mkRegular n =
  48.     if n = 1 then [|0.5,0.5|] else
  49.     let sampleSize = (float n)
  50.     let padding = (1.0-((sampleSize-1.0)/sampleSize))*0.5
  51.     let increment = 1.0/(sampleSize) // Given N produces N^2  -> Solution to get increment is 1/(n+1)
  52.     let mutable cordArray = Array.create (n*n) (0.0,0.0)
  53.     let mutable i = 0
  54.     for x in [padding..increment..1.0]
  55.         do
  56.         for y in [padding..increment..1.0]
  57.             do
  58.             cordArray.[i] <- (x,y)
  59.             i <- i + 1
  60.     shuffle cordArray
  61.     cordArray
  62.  
  63. // given a natural number n produces n randomized sample points. This is a bad sampling method!
  64. let private mkRandom n =
  65.     let sampleSize = (float n)
  66.     let mutable cordArray = Array.create n (0.0,0.0)
  67.     let mutable ii = 0
  68.     for i in [1.0 .. sampleSize]
  69.         do
  70.         let x = ran.NextDouble()
  71.         let y = ran.NextDouble()
  72.         cordArray.[ii] <- (x,y)
  73.         ii <- ii + 1
  74.     shuffle cordArray
  75.     cordArray
  76.  
  77. // given n produces n^2 squares in the unit pixel and randomly places one within each.
  78. let private mkJitter n =
  79.     let sampleSize = (float n)
  80.     let increment = 1.0/(sampleSize)
  81.     let mutable cordArray = Array.create (n*n) (0.0,0.0)
  82.     let mutable i = 0
  83.     for x:float in [increment..increment..1.0]
  84.         do
  85.         for y in [increment..increment..1.0]
  86.             do
  87.             cordArray.[i] <- ((randomInBound x increment),(randomInBound y increment))
  88.             i <- i + 1
  89.     shuffle cordArray
  90.     cordArray
  91.  
  92. // produces N points that upholds the nrooks-properties
  93. let private mkNRook n =
  94.     if n = 2 then [|0.5,0.5|] else
  95.     let sampleSize = (float n)
  96.     let increment = 1.0/(sampleSize) // Solution to get increment is 1/(n+1)
  97.     let mutable xcordArray = Array.create n 0.0
  98.     let mutable ycordArray = Array.create n 0.0
  99.     let mutable i = 0
  100.  
  101.     for y:float in [increment .. increment .. (1.0-increment)]
  102.         do
  103.         xcordArray.[i] <- y
  104.         ycordArray.[i] <- y
  105.         i <- i + 1
  106.     shuffle xcordArray
  107.     shuffle ycordArray
  108.     let cordArray = combineXY xcordArray ycordArray
  109.     shuffle cordArray
  110.     cordArray
  111.  
  112. // given n produces n^2 squares in the unit pixel and places a sample within each that still upholds the N-Rooks properties.
  113. let private mkMultiJitter n =
  114.     let sampleSize = (float n)
  115.     let increment = 1.0/(sampleSize)
  116.     let inc = 1.0/(sampleSize**2.0)
  117.  
  118.     let mutable cordArray = Array.create (n*n) (0.0,0.0)
  119.     let mutable count = 0.0
  120.     let mutable y = 0.0
  121.     let mutable i = 0
  122.  
  123.     while y < (1.0-inc)
  124.         do
  125.         for x:float in [(inc+count) .. increment .. 1.0]
  126.             do
  127.             y <- y + inc
  128.  
  129.             //randomize cords within a 1/n^2 box
  130.             cordArray.[i] <- ((randomInBound y inc),(randomInBound x inc))
  131.             i <- i+1
  132.         count <- count + inc
  133.  
  134.     // randomize x and y values (n-rooks)
  135.     for i in [0 .. (n-1)]
  136.         do
  137.         for j in [0 .. (n-1)]
  138.             do
  139.             let rn = ran.Next(0, n)
  140.             let (tmpx,tmpy) = cordArray.[i+(j*n)]
  141.             let (rnx,rny) = cordArray.[i + (rn*n)]
  142.             cordArray.[i+(n*j)] <- (rnx,tmpy)
  143.             cordArray.[(rn*n)+i] <- (tmpx,rny)
  144.  
  145.             let rn = ran.Next(0, n)
  146.             let (tmpx,tmpy) = cordArray.[j+(i*n)]
  147.             let (rnx,rny) = cordArray.[rn + (i*n)]
  148.             cordArray.[j+(n*i)] <- (rnx,tmpy)
  149.             cordArray.[(i*n)+rn] <- (tmpx,rny)
  150.     shuffle cordArray
  151.     cordArray
  152.  
  153. let pibyfour = (System.Math.PI / 4.0)
  154.  
  155. let findQuarter (x,y) =
  156.     match (x,y) with
  157.     | (x,y) when (x>=y) && x>=(-y) -> (x,(pibyfour*(y/x))) //quarter 1
  158.     | (x,y) when (x<=y) && x>=(-y) -> (y,(pibyfour*(2.0-(x/y)))) //quarter 2
  159.     | (x,y) when (x<=y) && x<=(-y) -> (-x,(pibyfour*(4.0+(y/x))))// quarter 3
  160.     | (x,y) when (x>=y) && x<=(-y) -> (-y,(pibyfour*(6.0-(x/y)))) // quarter 4
  161.     | (_,_) -> failwith "Should never go here - didn't find a quarter in disc mapping"
  162.    
  163. //Transforms a point to a point on a disc
  164. let private transformToDiscMap (x,y) =  
  165.  
  166.     // map to unitsquare size 2.0
  167.     let x = (x*2.0)-1.0
  168.     let y = (y*2.0)-1.0
  169.  
  170.     //transform and map to disc
  171.     let transformed = findQuarter (x,y)
  172.  
  173.     let a =
  174.         match transformed with
  175.         | (r,pehta) -> (System.Math.Cos(pehta)*r)  //normalize for debugging: (System.Math.Cos(pehta)*r+1.0)/2
  176.     let b =
  177.         match transformed with
  178.         |(r,pehta) -> (System.Math.Sin(pehta)*r) //normalize for debugging: (System.Math.Cos(pehta)*r+1.0)/2
  179.  
  180.     (a,b)
  181.  
  182. //Transforms a point to a point on a hemisphere
  183. let private transformToHemiMap (x,y) =  
  184.  
  185.     // close to 0 means closer to Z axis?
  186.     let e = 100.0
  187.  
  188.     let a = 2.0*System.Math.PI*x
  189.     let b = System.Math.Acos((1.0-y)**(1.0/e+1.0))
  190.     (Math.Sin(b)*Math.Cos(a),Math.Sin(b)*Math.Sin(a),Math.Cos(b))
  191.  
  192.  
  193. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  194. //                                                  logic for handling threads                                                                               //
  195. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  196.  
  197. open System.Collections.Concurrent    
  198. exception NoMoreJuice of string // no more samples
  199.  
  200. let indexMap : ConcurrentDictionary<int,int> = new ConcurrentDictionary<int,int>()
  201. let setAmountMap : ConcurrentDictionary<int,int> = new ConcurrentDictionary<int,int>()
  202. let samplerMap : ConcurrentDictionary<ISampler,(float*float)[][]>  = new ConcurrentDictionary<ISampler,(float*float)[][]>()
  203.  
  204.          
  205. let rec getNext id sampler samplingMethod n sets =
  206.     if indexMap.IsEmpty || (not (indexMap.ContainsKey(id)))
  207.     then
  208.         if (not (samplerMap.ContainsKey sampler))
  209.         then
  210.             samplerMap.TryAdd (sampler,(createSetsOfSampleMethod samplingMethod sets n)) |> ignore
  211.  
  212.         indexMap.TryAdd (id, Array.length (samplerMap.Item sampler)-1) |> ignore
  213.         setAmountMap.TryAdd (id,sets)  |> ignore
  214.         getNext id sampler samplingMethod n sets
  215.     else
  216.         let nextIndex = indexMap.Item id
  217.         let sampleSetLength = (Array.length (samplerMap.Item sampler))-1
  218.         let setIndex = setAmountMap.Item id
  219.         indexMap.TryAdd (id,nextIndex-1) |> ignore
  220.         if nextIndex <= sampleSetLength // check if there are more samples left (0 if no)
  221.         then
  222.             if(setIndex) = 0 // check if there are more sets available
  223.                 then
  224.                     indexMap.TryRemove (id) |> ignore
  225.                     setAmountMap.TryRemove (id) |> ignore
  226.                     raise (NoMoreJuice("All samples were delivered. Should continue"))
  227.                 else
  228.                     let nextSet = (setIndex)-1 //move to next set
  229.                     indexMap.TryAdd (id,sampleSetLength) |> ignore
  230.                     setAmountMap.TryAdd(id,nextSet) |> ignore
  231.                     samplerMap.Item(sampler).[nextSet].[sampleSetLength]
  232.         else
  233.             samplerMap.Item(sampler).[setIndex].[nextIndex]
  234.  
  235.  
  236. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  237. //                                                  types and inheritance                                                                                     //
  238. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  239.  
  240. type private baseSampler(n,sets, samplingMethod) =
  241.     interface ISampler with
  242.         member  this.n = n
  243.         member this.sets = sets
  244.         member this.samplingMethod i = samplingMethod i
  245.         member this.getNext id = getNext id this samplingMethod n sets
  246.         member this.transformToHemi x = transformToHemiMap x
  247.         member this.transformToDisc x = transformToDiscMap x
  248.  
  249. type private RegularSampler(n) =
  250.     inherit baseSampler(n, 0, mkRegular)
  251.  
  252. type private RandomSampler(n, sets) =
  253.     inherit baseSampler(n, sets, mkRandom)
  254.  
  255. type private JitteredSampler(n, sets) =
  256.     inherit baseSampler(n, sets, mkJitter)
  257.  
  258. type private NRookSampler(n, sets) =
  259.     inherit baseSampler(n, sets, mkNRook)
  260.  
  261. type private MultiJittered(n, sets) =
  262.     inherit baseSampler(n, sets, mkMultiJitter)  
  263.  
  264.  
  265. let mkRegularSampler n = new RegularSampler(n) :> ISampler
  266. let mkRandomSampler n sets = new RandomSampler(n, sets) :> ISampler
  267. let mkJitteredSampler n sets = new JitteredSampler(n, sets) :> ISampler
  268. let mkNRookSampler n sets = new NRookSampler(n, sets) :> ISampler
  269. let mkMultiJitteredSampler n sets = new MultiJittered(n, sets) :> ISampler
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement