private void GeneratePoissonDistThreaded(object obj) { generatePoissonDistParam_t param = (generatePoissonDistParam_t)obj; param.dist.Generate(param.numSamples); for (int i = 0; i < param.dist.Samples.Count; i++) { param.result.Add(param.dist.Samples[i]); } param.autoResetEvent.Set(); }
public void Generate(int numColors, int samplesPerTile, int numThreads ) { random = new Random(); this.numColors = numColors; tiles = new List<WangTile>(); const int numEdges = 4; int numTiles = (int)Math.Pow(numColors, numEdges); #region generate Poisson distributions List<PoissonSample>[] distributions = new List<PoissonSample>[numTiles]; generatePoissonDistParam_t[] threadParams = new generatePoissonDistParam_t[numThreads]; PoissonDistribution[] generators = new PoissonDistribution[numThreads]; AutoResetEvent[] waitHandles = new AutoResetEvent[numThreads]; for (int i = 0; i < numThreads; i++) { threadParams[i].dist = new PoissonDistribution(); threadParams[i].numSamples = samplesPerTile; waitHandles[i] = new AutoResetEvent(false); threadParams[i].autoResetEvent = waitHandles[i]; } int t = 0; Queue<int> availableThreads = new Queue<int>(); for (int i = 0; i < numThreads; i++) availableThreads.Enqueue(i); if (OnConsoleMessage != null) OnConsoleMessage("Generating " + numTiles + " source Poisson Distributions with " + samplesPerTile + " samples each..."); Image debugImage = null; if (OnDebugStep != null) debugImage = new Bitmap(800, 800); while (t < numTiles || availableThreads.Count < numThreads) { while (availableThreads.Count > 0 && t < numTiles) { int i = availableThreads.Dequeue(); if (OnProgressReport != null) OnProgressReport((float)(t + 1) / numTiles); distributions[t] = new List<PoissonSample>(samplesPerTile); threadParams[i].result = distributions[t]; ThreadPool.QueueUserWorkItem(new WaitCallback(GeneratePoissonDistThreaded), threadParams[i]); t++; } int index = WaitHandle.WaitAny(waitHandles); if (debugImage != null) { PoissonDistribution.ToImage( threadParams[index].dist.Samples, Color.Black, debugImage, 1); OnDebugStep(debugImage, "Poisson Distribution " + t); } availableThreads.Enqueue(index); } #endregion #region generate seam tiles List<SourceTile> seamTiles = new List<SourceTile>(); #if DEBUG Color[] colors = new Color[numColors]; for( int i = 0; i < numColors; i++ ) colors[i] = Color.FromArgb(random.Next(256), random.Next(256), random.Next(256)); #endif for (int i = 0; i < numColors; i++) { PoissonDistribution distribution = new PoissonDistribution(); distribution.Generate(samplesPerTile); #if DEBUG foreach (PoissonSample p in distribution.Samples) p.color = colors[i]; #endif seamTiles.Add(new SourceTile(distribution.Samples, i)); } #endregion #region generate all edge permutations /* * 0000 0001 0002 ... 000n * 0010 0011 0012 ... 001n * 0020 0021 0022 ... 002n * ... * 00n0 00n1 00n2 ... 00nn * * 0100 0101 0102 ... 010n * 0110 0111 0112 ... 011n * ... * 01n0 01n1 01n2 ... 01nn * * ... * * nnn0 nnn1 nnn2 ... nnnn */ int[,] edgeCol = new int[numTiles,numEdges]; for (int i = 0; i < numEdges; i++) edgeCol[0, i] = 0; for (int i = 1; i < numTiles; i++) { for (int j = 0; j < numEdges; j++) { edgeCol[i,j] = (edgeCol[i-1,j] + (i % (int)Math.Pow(numColors, j) == 0 ? 1 : 0)) % numColors; } } #endregion #region generate wang tiles WangTile[] tileArray = new WangTile[numTiles]; t = 0; availableThreads.Clear(); createWangTileParam_t[] createWangTileParams = new createWangTileParam_t[numThreads]; for (int i = 0; i < numThreads; i++) { availableThreads.Enqueue(i); createWangTileParams[i] = new createWangTileParam_t(); createWangTileParams[i].autoResetEvent = waitHandles[i]; createWangTileParams[i].autoResetEvent.Reset(); createWangTileParams[i].tileArray = tileArray; } if (OnConsoleMessage != null) OnConsoleMessage("Merging distributions to generate Wang Tiles..." ); while (t < numTiles || availableThreads.Count < numThreads) { while (availableThreads.Count > 0 && t < numTiles) { int i = availableThreads.Dequeue(); if (OnProgressReport != null) OnProgressReport((float)( t + 1 ) / numTiles); createWangTileParams[i].tileBaseDistribution = distributions[t]; createWangTileParams[i].neighbours = new List<SourceTile>(); createWangTileParams[i].tileIndex = t; if (numColors > 1) { for (int j = 0; j < numEdges; j++) createWangTileParams[i].neighbours.Add(seamTiles[edgeCol[t, j]]); } ThreadPool.QueueUserWorkItem(new WaitCallback(CreateWangTileThreaded), createWangTileParams[i]); t++; } int index = WaitHandle.WaitAny(waitHandles); availableThreads.Enqueue(index); } tiles = tileArray.ToList(); SortTiles(); MakeRecursive(); if (OnDebugStep != null) { ToColorTiles(debugImage, new Size(8, 8)); OnDebugStep(debugImage, "Sample coverage of the generated Wang Tiles" ); } #endregion }
public void Generate(int numColors, int samplesPerTile, int numThreads) { random = new Random(); this.numColors = numColors; tiles = new List <WangTile>(); const int numEdges = 4; int numTiles = (int)Math.Pow(numColors, numEdges); #region generate Poisson distributions List <PoissonSample>[] distributions = new List <PoissonSample> [numTiles]; generatePoissonDistParam_t[] threadParams = new generatePoissonDistParam_t[numThreads]; PoissonDistribution[] generators = new PoissonDistribution[numThreads]; AutoResetEvent[] waitHandles = new AutoResetEvent[numThreads]; for (int i = 0; i < numThreads; i++) { threadParams[i].dist = new PoissonDistribution(); threadParams[i].numSamples = samplesPerTile; waitHandles[i] = new AutoResetEvent(false); threadParams[i].autoResetEvent = waitHandles[i]; } int t = 0; Queue <int> availableThreads = new Queue <int>(); for (int i = 0; i < numThreads; i++) { availableThreads.Enqueue(i); } if (OnConsoleMessage != null) { OnConsoleMessage("Generating " + numTiles + " source Poisson Distributions with " + samplesPerTile + " samples each..."); } Image debugImage = null; if (OnDebugStep != null) { debugImage = new Bitmap(800, 800); } while (t < numTiles || availableThreads.Count < numThreads) { while (availableThreads.Count > 0 && t < numTiles) { int i = availableThreads.Dequeue(); if (OnProgressReport != null) { OnProgressReport((float)(t + 1) / numTiles); } distributions[t] = new List <PoissonSample>(samplesPerTile); threadParams[i].result = distributions[t]; ThreadPool.QueueUserWorkItem(new WaitCallback(GeneratePoissonDistThreaded), threadParams[i]); t++; } int index = WaitHandle.WaitAny(waitHandles); if (debugImage != null) { PoissonDistribution.ToImage(threadParams[index].dist.Samples, Color.Black, debugImage, 1); OnDebugStep(debugImage, "Poisson Distribution " + t); } availableThreads.Enqueue(index); } #endregion #region generate seam tiles List <SourceTile> seamTiles = new List <SourceTile>(); #if DEBUG Color[] colors = new Color[numColors]; for (int i = 0; i < numColors; i++) { colors[i] = Color.FromArgb(random.Next(256), random.Next(256), random.Next(256)); } #endif for (int i = 0; i < numColors; i++) { PoissonDistribution distribution = new PoissonDistribution(); distribution.Generate(samplesPerTile); #if DEBUG foreach (PoissonSample p in distribution.Samples) { p.color = colors[i]; } #endif seamTiles.Add(new SourceTile(distribution.Samples, i)); } #endregion #region generate all edge permutations /* * 0000 0001 0002 ... 000n * 0010 0011 0012 ... 001n * 0020 0021 0022 ... 002n * ... * 00n0 00n1 00n2 ... 00nn * * 0100 0101 0102 ... 010n * 0110 0111 0112 ... 011n * ... * 01n0 01n1 01n2 ... 01nn * * ... * * nnn0 nnn1 nnn2 ... nnnn */ int[,] edgeCol = new int[numTiles, numEdges]; for (int i = 0; i < numEdges; i++) { edgeCol[0, i] = 0; } for (int i = 1; i < numTiles; i++) { for (int j = 0; j < numEdges; j++) { edgeCol[i, j] = (edgeCol[i - 1, j] + (i % (int)Math.Pow(numColors, j) == 0 ? 1 : 0)) % numColors; } } #endregion #region generate wang tiles WangTile[] tileArray = new WangTile[numTiles]; t = 0; availableThreads.Clear(); createWangTileParam_t[] createWangTileParams = new createWangTileParam_t[numThreads]; for (int i = 0; i < numThreads; i++) { availableThreads.Enqueue(i); createWangTileParams[i] = new createWangTileParam_t(); createWangTileParams[i].autoResetEvent = waitHandles[i]; createWangTileParams[i].autoResetEvent.Reset(); createWangTileParams[i].tileArray = tileArray; } if (OnConsoleMessage != null) { OnConsoleMessage("Merging distributions to generate Wang Tiles..."); } while (t < numTiles || availableThreads.Count < numThreads) { while (availableThreads.Count > 0 && t < numTiles) { int i = availableThreads.Dequeue(); if (OnProgressReport != null) { OnProgressReport((float)(t + 1) / numTiles); } createWangTileParams[i].tileBaseDistribution = distributions[t]; createWangTileParams[i].neighbours = new List <SourceTile>(); createWangTileParams[i].tileIndex = t; if (numColors > 1) { for (int j = 0; j < numEdges; j++) { createWangTileParams[i].neighbours.Add(seamTiles[edgeCol[t, j]]); } } ThreadPool.QueueUserWorkItem(new WaitCallback(CreateWangTileThreaded), createWangTileParams[i]); t++; } int index = WaitHandle.WaitAny(waitHandles); availableThreads.Enqueue(index); } tiles = tileArray.ToList(); SortTiles(); MakeRecursive(); if (OnDebugStep != null) { ToColorTiles(debugImage, new Size(8, 8)); OnDebugStep(debugImage, "Sample coverage of the generated Wang Tiles"); } #endregion }