public void RotateInPlace(RawDrawing drawing, double angleDegrees) { float minX = float.PositiveInfinity, minY = float.PositiveInfinity, maxX = float.NegativeInfinity, maxY = float.NegativeInfinity; foreach (var line in drawing.Lines) { foreach (var rawPoint in line) { minX = Math.Min(minX, rawPoint.X); minY = Math.Min(minY, rawPoint.Y); maxX = Math.Max(maxX, rawPoint.X); maxY = Math.Max(maxY, rawPoint.Y); } } float ox = (minX + maxX) / 2; float oy = (minY + maxY) / 2; float sin = (float)Math.Sin(angleDegrees / 180 * Math.PI); float cos = (float)Math.Cos(angleDegrees / 180 * Math.PI); foreach (var line in drawing.Lines) { for (int i = 0; i < line.Length; ++i) { float dx = line[i].X - ox; float dy = line[i].Y - oy; line[i].X = cos * dx - sin * dy + ox; line[i].Y = sin * dx + cos * dy + oy; } } }
public Bitmap Rasterize(RawDrawing drawing, int imageSize, float penSizePerc, bool extraMargin, bool drawPoints) { Bitmap img = new Bitmap(imageSize, imageSize, PixelFormat.Format24bppRgb); Rasterize(img, new Rectangle(0, 0, img.Width, img.Height), drawing, penSizePerc, extraMargin, drawPoints); return(img); }
public RawDrawing Rotate(RawDrawing drawing, double angleDegrees) { var newDrawing = new RawDrawing(drawing); RotateInPlace(drawing, angleDegrees); return(newDrawing); }
public RawDrawing Normalize(RawDrawing drawing) { var newDrawing = new RawDrawing(drawing); NormalizeInPlace(newDrawing); return(newDrawing); }
public void Rasterize(Bitmap img, Rectangle dest, RawDrawing drawing, float penSizePerc, bool extraMargin, bool drawPoints) { using (var g = Graphics.FromImage(img)) { g.Clear(Color.White); g.SetClip(new Rectangle(0, 0, img.Width, img.Height)); rasterize(g, drawing, penSizePerc, extraMargin, drawPoints); } }
/// <summary> /// Centers and expands the drawing to [0, 1] rectanlge. /// </summary> /// <param name="drawing"></param> public void NormalizeInPlace(RawDrawing drawing) { float minX = float.PositiveInfinity, minY = float.PositiveInfinity, maxX = float.NegativeInfinity, maxY = float.NegativeInfinity; foreach (var line in drawing.Lines) { foreach (var rawPoint in line) { minX = Math.Min(minX, rawPoint.X); minY = Math.Min(minY, rawPoint.Y); maxX = Math.Max(maxX, rawPoint.X); maxY = Math.Max(maxY, rawPoint.Y); } } if (float.IsInfinity(minX) || float.IsInfinity(minY) || float.IsInfinity(maxX) || float.IsInfinity(maxY)) { // No points. Nothing to normalize. return; } float wid = maxX - minX; float hei = maxY - minY; float scale = Math.Max(wid, hei); if (scale < 1e-6) { // Single point or way too small. Ignore. return; } float xOffset = (1 - wid / scale) / 2; float yOffset = (1 - hei / scale) / 2; Contract.Assert(xOffset == 0 || yOffset == 0); foreach (var line in drawing.Lines) { for (int i = 0; i < line.Length; ++i) { line[i].X = xOffset + (line[i].X - minX) / scale; line[i].Y = yOffset + (line[i].Y - minY) / scale; } } }
public static RawDrawing Deserialize(byte[] data) { int dataIndex = 0; var resultDrawing = new RawDrawing(); int linesCount = SerializationHelper.DeserializeInt(data, ref dataIndex); resultDrawing.Lines = new RawPoint[linesCount][]; for (int l = 0; l < linesCount; ++l) { int lineLength = SerializationHelper.DeserializeInt(data, ref dataIndex); resultDrawing.Lines[l] = new RawPoint[lineLength]; SerializationHelper.DeserializeArray(resultDrawing.Lines[l], data, ref dataIndex); } return(resultDrawing); }
public RawDrawing(RawDrawing rd) { Lines = rd.Lines.Select(l => l.ToArray()).ToArray(); }
public void Rasterize(Bitmap img, RawDrawing drawing) { Rasterize(img, new Rectangle(0, 0, img.Width, img.Height), drawing, PenSizePerc, ExtraMargin, DrawPoints); }
public Bitmap Rasterize(RawDrawing drawing) { return(Rasterize(drawing, ImageSize, PenSizePerc, ExtraMargin, DrawPoints)); }
private void rasterize(Graphics g, RawDrawing drawing, float penSizePerc, bool extraMargin, bool drawPoints) { float penSize = ((g.ClipBounds.Width + g.ClipBounds.Height) / 2) * penSizePerc; // Pen has to be local otherwise it cannot be user in multiple threads. var pen = new Pen(Color.Black, penSize) { StartCap = LineCap.Round, EndCap = LineCap.Round, LineJoin = LineJoin.Round, }; // Given points are from 0 to 1 inclusive, max is thus (size - 1). SizeF drawingMult = new SizeF(g.ClipBounds.Width - 1, g.ClipBounds.Height - 1); PointF offset = g.ClipBounds.Location; if (extraMargin) { // Make sure to fill all available space (pixel precise). // All strokes should be exactly to the edge of image. drawingMult.Width += 2; drawingMult.Height += 2; float off = (float)Math.Ceiling(penSize / 2); drawingMult.Width -= 2 * off; drawingMult.Height -= 2 * off; off -= 1; offset.X += off; offset.Y += off; } var pointsColors = new Pen[] { Pens.Red, Pens.Lime, Pens.Yellow }; g.SmoothingMode = SmoothingMode.HighQuality; foreach (var line in drawing.Lines) { if (line.Length == 0) { continue; } var pts = new PointF[line.Length]; for (int i = 0; i < line.Length; i++) { pts[i].X = offset.X + line[i].X * drawingMult.Width; pts[i].Y = offset.Y + line[i].Y * drawingMult.Height; } g.DrawLines(pen, pts); } if (drawPoints) { int lineIndex = 0; foreach (var line in drawing.Lines) { if (line.Length == 0) { continue; } var ptPen = pointsColors[lineIndex % pointsColors.Length]; for (int i = 0; i < line.Length; i++) { float x = (float)Math.Round(offset.X + line[i].X * drawingMult.Width); float y = (float)Math.Round(offset.Y + line[i].Y * drawingMult.Height); g.DrawLine(ptPen, x, y, x + 0.2f, y); g.DrawLine(ptPen, x, y, x - 0.2f, y); } lineIndex += 1; } } }
/// <summary> /// Removes lines with less than two points. /// </summary> public void CleanData(RawDrawing drawing) { drawing.Lines = drawing.Lines .Where(l => l.Length >= 2) .ToArray(); }