public Bitmap DrawMazeOrdered(T structure, DrawingParameters parameters, IEnumerable <Cell> order) { if (!parameters.strokeEnabled && !parameters.fillEnabled) { return(null); } var size = CalculateBitmapSize(structure, parameters); Bitmap bitmap = new Bitmap(size.width, size.height); using (Graphics graphics = Graphics.FromImage(bitmap)) { graphics.CompositingQuality = CompositingQuality.HighQuality; graphics.SmoothingMode = SmoothingMode.HighQuality; graphics.PixelOffsetMode = PixelOffsetMode.HighQuality; if (parameters.fillEnabled) { FillMaze(graphics, structure, parameters, order); } if (parameters.strokeEnabled) { StrokeMaze(graphics, structure, parameters); } } return(bitmap); }
protected override (int width, int height) CalculateBitmapSize(CircularStructure structure, DrawingParameters parameters) { int diameter = (int)((structure.parameters.rings * 2 + 1) * parameters.cellSize + 2 * parameters.strokeWidth); return(diameter, diameter); }
protected override (int width, int height) CalculateBitmapSize(RectangularStructure structure, DrawingParameters parameters) { int width = (int)(structure.parameters.width * parameters.cellSize + parameters.strokeWidth * 2); int height = (int)(structure.parameters.height * parameters.cellSize + parameters.strokeWidth * 2); return(width, height); }
protected override (int width, int height) CalculateBitmapSize(ShapedStructure structure, DrawingParameters parameters) { int width = (int)(structure.parameters.shape.Width * parameters.cellSize); int height = (int)(structure.parameters.shape.Height * parameters.cellSize); return(width, height); }
protected override void StrokeMaze(Graphics graphics, RectangularStructure structure, DrawingParameters parameters) { graphics.TranslateTransform(parameters.strokeWidth, parameters.strokeWidth); float width = structure.parameters.width; float height = structure.parameters.height; float drawWidth = parameters.cellSize; float drawHeight = parameters.cellSize; Pen pen = new Pen(parameters.strokeColor, parameters.strokeWidth); pen.StartCap = LineCap.Round; pen.EndCap = LineCap.Round; for (int x = 0; x < width; x++) { for (int y = 0; y < height; y++) { PointF p1 = new PointF(x * drawWidth, y * drawHeight); PointF p2 = new PointF((x + 1) * drawWidth, y * drawHeight); PointF p3 = new PointF((x + 1) * drawWidth, (y + 1) * drawHeight); PointF p4 = new PointF(x * drawWidth, (y + 1) * drawHeight); Cell curCell = structure.GetCellAtPosition(new RectangularPosition(x, y)); if (!structure.ContainsCellAtPosition(new RectangularPosition(x - 1, y))) { graphics.DrawLine(pen, p1, p4); } if (!structure.ContainsCellAtPosition(new RectangularPosition(x, y - 1))) { graphics.DrawLine(pen, p1, p2); } if (!structure.ContainsCellAtPosition(new RectangularPosition(x + 1, y)) || !structure.IsAdjacent(curCell, structure.GetCellAtPosition(new RectangularPosition(x + 1, y)))) { graphics.DrawLine(pen, p2, p3); } if (!structure.ContainsCellAtPosition(new RectangularPosition(x, y + 1)) || !structure.IsAdjacent(curCell, structure.GetCellAtPosition(new RectangularPosition(x, y + 1)))) { graphics.DrawLine(pen, p3, p4); } } } graphics.ResetTransform(); }
protected override void FillMaze(Graphics graphics, RectangularStructure structure, DrawingParameters parameters, IEnumerable <Cell> order) { graphics.TranslateTransform(parameters.strokeWidth, parameters.strokeWidth); float drawWidth = parameters.cellSize; float drawHeight = parameters.cellSize; int i = 0; int count = order.Count(); Brush brush = new SolidBrush(parameters.fillColor); foreach (Cell cell in order) { if (parameters.fillType == FillType.GenerationGradient) { brush = new SolidBrush(Helpers.Lerp(Color.Black, parameters.fillColor, (float)i / count)); } RectangularPosition pos = cell.Position as RectangularPosition; int x = pos.x; int y = pos.y; PointF p1 = new PointF(x * drawWidth, y * drawHeight); PointF p2 = new PointF((x + 1) * drawWidth, y * drawHeight); PointF p3 = new PointF((x + 1) * drawWidth, (y + 1) * drawHeight); PointF p4 = new PointF(x * drawWidth, (y + 1) * drawHeight); GraphicsPath bounds = new GraphicsPath(); bounds.AddLine(p1, p2); bounds.AddLine(p2, p3); bounds.AddLine(p3, p4); bounds.AddLine(p4, p1); graphics.FillPath(brush, bounds); i++; } graphics.ResetTransform(); }
protected override void StrokeMaze(Graphics graphics, CircularStructure structure, DrawingParameters parameters) { float translate = parameters.strokeWidth + structure.parameters.rings * parameters.cellSize + parameters.cellSize * 0.5f; graphics.TranslateTransform(translate, translate); float ringHeight = parameters.cellSize; float halfHeight = ringHeight * 0.5f; int prevRingCount = 1; Pen pen = new Pen(parameters.strokeColor, parameters.strokeWidth); pen.StartCap = LineCap.Round; pen.EndCap = LineCap.Round; for (int x = 1; x <= structure.parameters.rings; x++) { int cellsNumber = CircularFunctions.CellsInRing(x, structure.parameters.ratio, prevRingCount); for (int y = 0; y < cellsNumber; y++) { Brush brush = new SolidBrush(parameters.fillColor); var polarSideA = CircularFunctions.CircularPositionToPolar(x, y, ringHeight, cellsNumber); var polarSideB = CircularFunctions.CircularPositionToPolar(x, y + 1, ringHeight, cellsNumber); float innerSize = (x * ringHeight - halfHeight); float outerSize = (x * ringHeight + halfHeight); var t1 = CircularFunctions.PolarToCartesian(innerSize, polarSideA.angle); var t2 = CircularFunctions.PolarToCartesian(outerSize, polarSideA.angle); var t3 = CircularFunctions.PolarToCartesian(outerSize, polarSideB.angle); var t4 = CircularFunctions.PolarToCartesian(innerSize, polarSideB.angle); RectangleF inner = new RectangleF(-innerSize, -innerSize, innerSize * 2, innerSize * 2); RectangleF outer = new RectangleF(-outerSize, -outerSize, outerSize * 2, outerSize * 2); float sweep = CircularFunctions.RadToDeg(polarSideB.angle) - CircularFunctions.RadToDeg(polarSideA.angle); Cell curCell = structure.GetCellAtPosition(new CircularPosition(x, y)); foreach (Cell neighbourCell in curCell.NeighbourCells) { CircularPosition neighborPosition = neighbourCell.Position as CircularPosition; if (neighborPosition.ring == (x - 1) && !structure.IsAdjacent(curCell, neighbourCell)) { graphics.DrawArc(pen, inner, CircularFunctions.RadToDeg(polarSideB.angle), -sweep); } if ((neighborPosition.step == (y + 1) || y == (cellsNumber - 1) && neighborPosition.step == 0) && !structure.IsAdjacent(curCell, neighbourCell)) { graphics.DrawLine(pen, t3.x, t3.y, t4.x, t4.y); } } if (x == structure.parameters.rings) { graphics.DrawArc(pen, outer, CircularFunctions.RadToDeg(polarSideA.angle), sweep); } } prevRingCount = cellsNumber; } graphics.ResetTransform(); }
protected override void FillMaze(Graphics graphics, CircularStructure structure, DrawingParameters parameters, IEnumerable <Cell> order) { float translate = parameters.strokeWidth + structure.parameters.rings * parameters.cellSize + parameters.cellSize * 0.5f; graphics.TranslateTransform(translate, translate); float ringHeight = parameters.cellSize; float halfHeight = ringHeight * 0.5f; int prevRingCount = 1; int i = 0; int count = order.Count(); Brush brush = new SolidBrush(parameters.fillColor); foreach (Cell cell in order) { if (parameters.fillType == FillType.GenerationGradient) { brush = new SolidBrush(Helpers.Lerp(Color.Black, parameters.fillColor, (float)i / count)); } CircularPosition pos = cell.Position as CircularPosition; int x = pos.ring; int y = pos.step; if (x == 0) { graphics.FillEllipse(brush, -halfHeight, -halfHeight, ringHeight, ringHeight); continue; } int cellsInRing = CircularFunctions.CellsInRing(x, structure.parameters.ratio); var polarSideA = CircularFunctions.CircularPositionToPolar(x, y, ringHeight, cellsInRing); var polarSideB = CircularFunctions.CircularPositionToPolar(x, y + 1, ringHeight, cellsInRing); float innerSize = (x * ringHeight - halfHeight); float outerSize = (x * ringHeight + halfHeight); var t1 = CircularFunctions.PolarToCartesian(innerSize, polarSideA.angle); var t2 = CircularFunctions.PolarToCartesian(outerSize, polarSideA.angle); var t3 = CircularFunctions.PolarToCartesian(outerSize, polarSideB.angle); var t4 = CircularFunctions.PolarToCartesian(innerSize, polarSideB.angle); RectangleF inner = new RectangleF(-innerSize, -innerSize, innerSize * 2, innerSize * 2); RectangleF outer = new RectangleF(-outerSize, -outerSize, outerSize * 2, outerSize * 2); float sweep = CircularFunctions.RadToDeg(polarSideB.angle) - CircularFunctions.RadToDeg(polarSideA.angle); GraphicsPath bounds = new GraphicsPath(); bounds.AddLine(t1.Item1, t1.Item2, t2.Item1, t2.Item2); bounds.AddArc(outer, CircularFunctions.RadToDeg(polarSideA.angle), sweep); bounds.AddLine(t3.Item1, t3.Item2, t4.Item1, t4.Item2); bounds.AddArc(inner, CircularFunctions.RadToDeg(polarSideB.angle), -sweep); bounds.CloseFigure(); graphics.FillPath(brush, bounds); i++; } graphics.ResetTransform(); }
public Bitmap DrawMaze(T structure, DrawingParameters parameters) { return(DrawMazeOrdered(structure, parameters, structure)); }
protected abstract (int width, int height) CalculateBitmapSize(T structure, DrawingParameters parameters);
protected abstract void StrokeMaze(Graphics graphics, T structure, DrawingParameters parameters);
protected abstract void FillMaze(Graphics graphics, T structure, DrawingParameters parameters, IEnumerable <Cell> order);