public void InternalRegenerateCloud() { _source = new WriteableBitmap((int)_layoutRoot.ActualWidth, (int)_layoutRoot.ActualHeight); int arraySize = (int)((_layoutRoot.ActualWidth / 4) + 2) * (int)((_layoutRoot.ActualHeight / 4) + 2); _mapping = new int[arraySize]; for (int i = 0; i < arraySize; i++) { _mapping[i] = -1; } if (Entries.Count() < 2) { _image.Source = _source; _image.InvalidateArrange(); return; } _random = new Random(10202); double minSize = Entries.OrderByDescending(e => e.SizeValue).Take(MaxWords).Min(e => e.SizeValue); if (!double.IsNaN(MinimumValue)) { minSize = Math.Min(MinimumValue, minSize); } double maxSize = Math.Max(Entries.Max(e => e.SizeValue), MinimumLargestValue); double range = Math.Max(0.00001, maxSize - minSize); double minColor = Entries.OrderByDescending(e => e.SizeValue).Take(MaxWords).Min(e => e.ColorValue); double maxColor = Entries.OrderByDescending(e => e.SizeValue).Take(MaxWords).Max(e => e.ColorValue); double maxAngle = Entries.OrderByDescending(e => e.SizeValue).Take(MaxWords).Max(e => e.Angle); if (!double.IsNaN(MinimumLargestAngleValue)) { maxAngle = Math.Max(MinimumLargestAngleValue, maxAngle); } double minAngle = Entries.OrderByDescending(e => e.SizeValue).Take(MaxWords).Min(e => e.Angle); if (!double.IsNaN(MaximumLowestAngleValue)) { minAngle = Math.Min(MaximumLowestAngleValue, minAngle); } double colorRange = Math.Max(0, maxColor - minColor); double angleRange = Math.Max(0, maxAngle - minAngle); //If there's a centre value then specify the range if (!double.IsNaN(AngleCenterValue)) { var lr = AngleCenterValue - minAngle; var ur = maxAngle - AngleCenterValue; angleRange = Math.Max(ur, lr); } var txt = new TextBlock { FontFamily = FontFamily, FontSize = 100, Text = "x" }; double areaPerLetter = ((txt.ActualWidth)) / (range); double targetWidth = _layoutRoot.ActualWidth * LargestSizeWidthProportion; WordCloudEntry od = Entries.OrderByDescending(e => (e.SizeValue - minSize) * e.Word.Length).First(); double maxFontSize = Math.Max(MinFontSize * 2.7, 100 / (((od.SizeValue - minSize) * od.Word.Length * areaPerLetter) / targetWidth)); double fontMultiplier = Math.Min((maxFontSize - MinFontSize) / range, 200); var points = new[] { new Point((int)(_layoutRoot.ActualWidth / 2), (int)(_layoutRoot.ActualHeight / 2)), new Point((int)(_layoutRoot.ActualWidth / 4), (int)(_layoutRoot.ActualHeight / 4)), new Point((int)(_layoutRoot.ActualWidth / 4), (int)(3 * _layoutRoot.ActualHeight / 2)), new Point((int)(3 * _layoutRoot.ActualWidth / 4), (int)(_layoutRoot.ActualHeight / 2)), new Point((int)(3 * _layoutRoot.ActualWidth / 4), (int)(3 * _layoutRoot.ActualHeight / 4)) }; int currentPoint = 0; foreach (WordCloudEntry e in Entries.OrderByDescending(e => e.SizeValue).Take(MaxWords)) { again: double position = 0.0; Point centre = points[currentPoint]; double angle = 0.0; if (double.IsNaN(AngleCenterValue)) { angle = angleRange >= 0.01 ? -90 + (((e.Angle - minAngle) / angleRange) * 90) : 0; } else { angle = angleRange >= 0.01 ? 90 * ((e.Angle - AngleCenterValue) / angleRange) : 0; } WriteableBitmap bm = CreateImage(e.Word, ((e.SizeValue - minSize) * fontMultiplier) + MinFontSize, SelectedItems.Contains(Entries.IndexOf(e)) ? -1 : (colorRange >= 0.01 ? (e.ColorValue - minColor) / colorRange : 1), e.Color, angle); Dictionary <Point, List <Point> > lst = CreateCollisionList(bm); bool collided = true; do { Point spiralPoint = GetSpiralPoint(position); int offsetX = (bm.PixelWidth / 2); int offsetY = (bm.PixelHeight / 2); var testPoint = new Point((int)(spiralPoint.X + centre.X - offsetX), (int)(spiralPoint.Y + centre.Y - offsetY)); if (position > (2 * Math.PI) * 580) { if (++currentPoint >= points.Length) { goto done; } goto again; } int cols = CountCollisions(testPoint, lst); if (cols == 0) { tryagain: double oldY = testPoint.Y; if (Math.Abs(testPoint.X + offsetX - centre.X) > 10) { if (testPoint.X + offsetX < centre.X) { do { testPoint.X += 2; } while (testPoint.X + offsetX < centre.X && CountCollisions(testPoint, lst) == 0); testPoint.X -= 2; } else { do { testPoint.X -= 2; } while (testPoint.X + offsetX > centre.X && CountCollisions(testPoint, lst) == 0); testPoint.X += 2; } } if (Math.Abs(testPoint.Y + offsetY - centre.Y) > 10) { if (testPoint.Y + offsetY < centre.Y) { do { testPoint.Y += 2; } while (testPoint.Y + offsetY < centre.Y && CountCollisions(testPoint, lst) == 0); testPoint.Y -= 2; } else { do { testPoint.Y -= 2; } while (testPoint.Y + offsetY > centre.Y && CountCollisions(testPoint, lst) == 0); testPoint.Y += 2; } if (testPoint.Y != oldY) { goto tryagain; } } collided = false; CopyBits(testPoint, bm, lst, Entries.IndexOf(e)); } else { if (cols <= 2) { position += (2 * Math.PI) / 100; } else { position += (2 * Math.PI) / 40; } } } while (collided); } done: _image.Source = _source; _image.InvalidateArrange(); }
private WordDrawing CreateWordGeometryDrawing(WordCloudEntry word) { var wordDrawing = new WordDrawing(word, CurrentTheme, DpiScale); return(wordDrawing); }
public LayoutItem(WordCloudEntry entry, PointD location, RectangleD measured) { Entry = entry; Location = location; Measured = measured; }
/* public class WordBitmap { public byte[] pixels; public int width; public int height; public int stride; private BitmapData bitmapData; private Bitmap bmps; public WordBitmap(Bitmap bmp) { //copy the pixels bitmapData = bmp.LockBits( new System.Drawing.Rectangle(0, 0, bmp.Width, bmp.Height), ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb); int numbytes = Math.Abs(bitmapData.Stride) * bitmapData.Height; pixels = new byte[numbytes]; // Copy the RGB values into the array. System.Runtime.InteropServices.Marshal.Copy(bitmapData.Scan0, pixels, 0, numbytes); stride = bitmapData.Stride; bmps = bmp; width = bmp.Width; height = bmp.Height; } public void Dispose() { bmps.UnlockBits(bitmapData); bitmapData = null; pixels = null; } } */ public static void Main(string[] args) { string fnin = null; string fnout = null; string fontt = null; string svgfn = null; string pdffn = null; string cf = null; bool cd = false; for(int i=0;i<args.Length;i++) if(args[i][0] == '-') switch(args[i][1]) { case 'i': fnin = args[i+1]; break; case 'o': fnout = args[i+1]; break; case 'f': fontt = args[i+1]; break; case 'c': cf = args[i+1]; break; case 'd': cd = true; break; case 's': svgfn = args[i+1]; break; case 'p': pdffn = args[i+1]; break; default: Console.Error.WriteLine("Unknown switch: {0}!",args[i]); break; } if(cd) { if(cf == null) { Console.Error.WriteLine("Error: No configfile specified!"); return; } StreamWriter sw = new StreamWriter(cf); WordCloud cloud1 = new WordCloud(); XmlSerializer s = new XmlSerializer(typeof(WordCloud)); s.Serialize(sw,cloud1); sw.Close(); return; } if(fnin == null || (fnout == null && pdffn == null && svgfn == null)) { Console.Error.WriteLine("Error: no input or output file name given!"); return; } WordCloud cloud; if(cf != null) { StreamReader s1 = new StreamReader(cf); XmlSerializer s = new XmlSerializer(typeof(WordCloud)); cloud = (WordCloud)s.Deserialize(s1); } else cloud = new WordCloud(); if(fontt != null) { cloud.fontname = fontt; } cloud.svgfn = svgfn; cloud.pdffn = pdffn; StreamReader sr = new StreamReader(fnin); Color c = new Color(0,0,0); int r,g,b; if(cloud.colorstring != null) if(cloud.colorstring.Length >= 7) if(cloud.colorstring[0] == '#') if(int.TryParse(cloud.colorstring.Substring(1,2),System.Globalization.NumberStyles.AllowHexSpecifier,null,out r) && int.TryParse(cloud.colorstring.Substring(3,2),System.Globalization.NumberStyles.AllowHexSpecifier,null,out g) && int.TryParse(cloud.colorstring.Substring(5,2),System.Globalization.NumberStyles.AllowHexSpecifier,null,out b)) c = new Color( ((double)r) / 255.0, ((double)g) / 255.0, ((double)b) / 255.0 ); cloud.Entries = new List<WordCloudEntry>(); while(!sr.EndOfStream) { string line = sr.ReadLine(); if(line == null) break; if(line.Length == 0) break; string[] e = line.Split(new char[]{':'}); if(e.Length < 2) break; WordCloudEntry e2 = new WordCloudEntry(); e2.Word = e[0]; e2.SizeValue = Convert.ToDouble(e[1]); e2.ColorValue = 0.0; e2.Color = c; e2.Angle = 0.0; cloud.Entries.Add(e2); } sr.Close(); cloud.InternalRegenerateCloud(); if(fnout != null) cloud.Save(fnout); }