private static void DrawRenderOptions(RenderOptions renderOptions, DistanceInfo distanceInfo, Cell cell, int imageCenter, SKSurface surface, ShortestPathInfo shortestPathInfo, CircularMaze maze) { var position = maze.GetPositionOfCell(cell); var centerOfCell = GetCenterOfCell(position, imageCenter); var whitePaint = new SKPaint { Color = SKColors.White, StrokeWidth = 1, TextAlign = SKTextAlign.Center }; var startPaint = new SKPaint { Color = SKColors.Green, StrokeWidth = 1, TextAlign = SKTextAlign.Center }; var finishPaint = new SKPaint { Color = SKColors.Red, StrokeWidth = 1, TextAlign = SKTextAlign.Center }; var pathPaint = new SKPaint { Color = SKColors.Yellow, StrokeWidth = 1, TextAlign = SKTextAlign.Center }; if (renderOptions.ShowGradientOfDistanceFromStart) { var path = new SKPath(); if (position.RingNumber > 0) { var innerRadius = GetRadiusAtRing(position.RingNumber - 1); var outerRadius = GetRadiusAtRing(position.RingNumber); var innerBounds = new SKRect(imageCenter - innerRadius, imageCenter - innerRadius, imageCenter + innerRadius, imageCenter + innerRadius); var outerBounds = new SKRect(imageCenter - outerRadius, imageCenter - outerRadius, imageCenter + outerRadius, imageCenter + outerRadius); var degreeDifference = position.EndingDegree - position.StartingDegree; var firstLineCoords = GetCoords(outerRadius, position.EndingDegree); var secondLineCoords = GetCoords(innerRadius, position.StartingDegree); path.AddArc(innerBounds, NormalizeAngle(position.StartingDegree), NormalizeAngle(degreeDifference)); path.LineTo(imageCenter + firstLineCoords.x, imageCenter + firstLineCoords.y); path.ArcTo(outerBounds, position.EndingDegree, -degreeDifference, false); path.LineTo(imageCenter + secondLineCoords.x, imageCenter + secondLineCoords.y); } else { // Center cell should be fully shaded path.AddCircle(imageCenter, imageCenter, CenterCellRadius); } var finishingCellDistance = distanceInfo.DistanceFromStartMap[distanceInfo.FarthestCell]; var currentCellDistance = distanceInfo.DistanceFromStartMap[cell]; var intensity = (byte)(255 * (currentCellDistance / (decimal)finishingCellDistance)); var color = new SKColor(0, 0, intensity); var paint = new SKPaint { Color = color }; surface.Canvas.DrawPath(path, paint); } if (renderOptions.HighlightShortestPath && shortestPathInfo.IsCellInPath(cell)) { var paint = cell == maze.StartingCell ? startPaint : cell == maze.FinishingCell ? finishPaint : pathPaint; var distance = distanceInfo.DistanceFromStartMap[cell]; surface.Canvas.DrawText(distance.ToString(), centerOfCell.x, centerOfCell.y, paint); } else if (renderOptions.ShowAllDistances && distanceInfo.DistanceFromStartMap.ContainsKey(cell)) { var distance = distanceInfo.DistanceFromStartMap[cell]; surface.Canvas.DrawText(distance.ToString(), centerOfCell.x, centerOfCell.y, whitePaint); } else if (cell == maze.StartingCell) { surface.Canvas.DrawText("S", centerOfCell.x, centerOfCell.y, startPaint); } else if (cell == maze.FinishingCell) { surface.Canvas.DrawText("E", centerOfCell.x, centerOfCell.y, finishPaint); } }
public static SKImage RenderWithSkia(this RectangularMaze maze, RenderOptions renderOptions, DistanceInfo distanceInfo, ShortestPathInfo shortestPathInfo) { if (maze == null) { throw new ArgumentNullException(nameof(maze)); } renderOptions = renderOptions ?? new RenderOptions(); var imageWidth = (CellSize * maze.ColumnCount) + (Margin * 2); var imageHeight = (CellSize * maze.RowCount) + (Margin * 2); var imageInfo = new SKImageInfo(imageWidth, imageHeight, SKColorType.Rgba8888, SKAlphaType.Premul); using (var surface = SKSurface.Create(imageInfo)) { surface.Canvas.Clear(SKColors.Black); var whitePaint = new SKPaint { Color = SKColors.White, StrokeWidth = CellLineWidth }; var startPaint = new SKPaint { Color = SKColors.Green, StrokeWidth = CellLineWidth }; var finishPaint = new SKPaint { Color = SKColors.Red, StrokeWidth = CellLineWidth }; var pathPaint = new SKPaint { Color = SKColors.Yellow, StrokeWidth = CellLineWidth }; foreach (var cell in maze.AllCells) { var(row, column) = maze.GetPositionOfCell(cell); var leftX = (column * CellSize) + Margin; var rightX = leftX + CellSize; var topY = (row * CellSize) + Margin; var bottomY = topY + CellSize; var isNorthFacingExit = (maze.FinishingCell == cell || maze.StartingCell == cell) && row == 0 && column > 1; var isSouthFacingExit = (maze.FinishingCell == cell || maze.StartingCell == cell) && row == maze.RowCount - 1 && column > 1; var isEastFacingExit = (maze.FinishingCell == cell || maze.StartingCell == cell) && column == maze.ColumnCount - 1; var isWestFacingExit = (maze.FinishingCell == cell || maze.StartingCell == cell) && column == 0; var passableDirections = GetPassableDirections(maze, cell); if (!passableDirections.North && !isNorthFacingExit) { surface.Canvas.DrawLine(leftX, topY, rightX, topY, whitePaint); } if (!passableDirections.South && !isSouthFacingExit) { surface.Canvas.DrawLine(leftX, bottomY, rightX, bottomY, whitePaint); } if (!passableDirections.East && !isEastFacingExit) { surface.Canvas.DrawLine(rightX, topY, rightX, bottomY, whitePaint); } if (!passableDirections.West && !isWestFacingExit) { surface.Canvas.DrawLine(leftX, topY, leftX, bottomY, whitePaint); } if (renderOptions.ShowGradientOfDistanceFromStart) { const int shadingMargin = 2; var finishingCellDistance = distanceInfo.DistanceFromStartMap[distanceInfo.FarthestCell]; var currentCellDistance = distanceInfo.DistanceFromStartMap[cell]; var intensity = (byte)(255 * (currentCellDistance / (decimal)finishingCellDistance)); var color = new SKColor(0, 0, intensity); var paint = new SKPaint { Color = color }; var shadeWidth = rightX - leftX - (shadingMargin * 2); var shadeHeight = bottomY - topY - (shadingMargin * 2); surface.Canvas.DrawRect(leftX + shadingMargin, topY + shadingMargin, shadeWidth, shadeHeight, paint); } if (renderOptions.HighlightShortestPath && shortestPathInfo.IsCellInPath(cell)) { var paint = cell == maze.StartingCell ? startPaint : cell == maze.FinishingCell ? finishPaint : pathPaint; var distance = distanceInfo.DistanceFromStartMap[cell]; surface.Canvas.DrawText(distance.ToString(), leftX + LabelMarginX, topY + LabelMarginY, paint); } else if (renderOptions.ShowAllDistances && distanceInfo.DistanceFromStartMap.ContainsKey(cell)) { var distance = distanceInfo.DistanceFromStartMap[cell]; surface.Canvas.DrawText(distance.ToString(), leftX + LabelMarginX, topY + LabelMarginY, whitePaint); } else if (cell == maze.StartingCell) { surface.Canvas.DrawText("S", leftX + LabelMarginX, topY + LabelMarginY, startPaint); } else if (cell == maze.FinishingCell) { surface.Canvas.DrawText("E", leftX + LabelMarginX, topY + LabelMarginY, finishPaint); } } return(surface.Snapshot()); } }
public static SKImage RenderWithSkia(this TriangleMaze maze, RenderOptions renderOptions, DistanceInfo distanceInfo, ShortestPathInfo shortestPathInfo) { if (maze == null) { throw new ArgumentNullException(nameof(maze)); } renderOptions = renderOptions ?? new RenderOptions(); // All corner adjustments. Image starts 0,0 top left and goes downward, therefore top has to be adjusted // by negative from center while bottom adjusted by positive from center. var topMid = (x : 0, y : -HalfHeight); var bottomRight = (x : HalfWidth, y : HalfHeight); var bottomLeft = (x : -HalfWidth, y : HalfHeight); var bottomMid = (x : 0, y : HalfHeight); var topLeft = (x : -HalfWidth, y : -HalfHeight); var topRight = (x : HalfWidth, y : -HalfHeight); var imageWidth = (Margin * 2) + (maze.ColumnCount * HalfWidth) + HalfWidth; var imageHeight = (Margin * 2) + (maze.RowCount * CellHeight); var imageInfo = new SKImageInfo(imageWidth, imageHeight, SKColorType.Rgba8888, SKAlphaType.Premul); using (var surface = SKSurface.Create(imageInfo)) { surface.Canvas.Clear(SKColors.Black); var whitePaint = new SKPaint { Color = SKColors.White, StrokeWidth = CellLineWidth, TextAlign = SKTextAlign.Center }; var startPaint = new SKPaint { Color = SKColors.Green, StrokeWidth = 1, TextAlign = SKTextAlign.Center }; var finishPaint = new SKPaint { Color = SKColors.Red, StrokeWidth = 1, TextAlign = SKTextAlign.Center }; var pathPaint = new SKPaint { Color = SKColors.Yellow, StrokeWidth = 1, TextAlign = SKTextAlign.Center }; foreach (var cell in maze.AllCells) { var(row, column) = maze.GetPositionOfCell(cell); var centerX = Margin + (column * HalfWidth) + HalfWidth; var centerY = Margin + (row * CellHeight) + HalfHeight; var center = (x : centerX, y : centerY); if (renderOptions.ShowGradientOfDistanceFromStart) { var finishingCellDistance = distanceInfo.DistanceFromStartMap[distanceInfo.FarthestCell]; var currentCellDistance = distanceInfo.DistanceFromStartMap[cell]; var intensity = (byte)(255 * (currentCellDistance / (decimal)finishingCellDistance)); var color = new SKColor(0, 0, intensity); var paint = new SKPaint { Color = color, Style = SKPaintStyle.Fill }; var path = new SKPath(); if (TriangleMaze.IsCellPointingUp(row, column)) { path.MoveTo(topMid.x + centerX, topMid.y + centerY); path.LineTo(bottomRight.x + centerX, bottomRight.y + centerY); path.LineTo(bottomLeft.x + centerX, bottomLeft.y + centerY); path.LineTo(topMid.x + centerX, topMid.y + centerY); } else { path.MoveTo(bottomMid.x + centerX, bottomMid.y + centerY); path.LineTo(topLeft.x + centerX, topLeft.y + centerY); path.LineTo(topRight.x + centerX, topRight.y + centerY); path.LineTo(bottomMid.x + centerX, bottomMid.y + centerY); } surface.Canvas.DrawPath(path, paint); } var passableWalls = new[] { false, false, false }; // left, right, vertical foreach (var cellWall in cell.CellWalls.Where(x => x.IsPassable)) { var otherCellPosition = maze.GetPositionOfCell(cellWall.GetOtherCell(cell)); if (otherCellPosition.row == row && otherCellPosition.column < column) { passableWalls[0] = true; } else if (otherCellPosition.row == row && otherCellPosition.column > column) { passableWalls[1] = true; } else { passableWalls[2] = true; } } if (TriangleMaze.IsCellPointingUp(row, column)) { if (!passableWalls[0]) { surface.Canvas.DrawLine(GetCenteredPoint(bottomLeft, center), GetCenteredPoint(topMid, center), whitePaint); } if (!passableWalls[1]) { surface.Canvas.DrawLine(GetCenteredPoint(topMid, center), GetCenteredPoint(bottomRight, center), whitePaint); } if (!passableWalls[2]) { surface.Canvas.DrawLine(GetCenteredPoint(bottomRight, center), GetCenteredPoint(bottomLeft, center), whitePaint); } } else { if (!passableWalls[0]) { surface.Canvas.DrawLine(GetCenteredPoint(bottomMid, center), GetCenteredPoint(topLeft, center), whitePaint); } if (!passableWalls[1]) { surface.Canvas.DrawLine(GetCenteredPoint(topRight, center), GetCenteredPoint(bottomMid, center), whitePaint); } if (!passableWalls[2]) { surface.Canvas.DrawLine(GetCenteredPoint(topLeft, center), GetCenteredPoint(topRight, center), whitePaint); } } var textYAdjust = TriangleMaze.IsCellPointingUp(row, column) ? HalfHeight / 3 : -HalfHeight / 3; if (renderOptions.HighlightShortestPath && shortestPathInfo.IsCellInPath(cell)) { var paint = cell == maze.StartingCell ? startPaint : cell == maze.FinishingCell ? finishPaint : pathPaint; var distance = distanceInfo.DistanceFromStartMap[cell]; surface.Canvas.DrawText(distance.ToString(), center.x, center.y + textYAdjust, paint); } else if (renderOptions.ShowAllDistances && distanceInfo.DistanceFromStartMap.ContainsKey(cell)) { var distance = distanceInfo.DistanceFromStartMap[cell]; surface.Canvas.DrawText(distance.ToString(), center.x, center.y + textYAdjust, whitePaint); } else if (cell == maze.StartingCell) { surface.Canvas.DrawText("S", center.x, center.y + textYAdjust, startPaint); } else if (cell == maze.FinishingCell) { surface.Canvas.DrawText("E", center.x, center.y + textYAdjust, finishPaint); } } return(surface.Snapshot()); } }