Exemplo n.º 1
0
        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());
            }
        }
Exemplo n.º 3
0
        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());
            }
        }