Click here to Skip to main content
15,885,216 members
Articles / Programming Languages / C# 4.0

A Complex - Yet Quite Intelligible - Pathfinding in C#

Rate me:
Please Sign up or sign in to vote.
4.96/5 (41 votes)
30 Aug 2013CPOL21 min read 59.5K   2.5K   88  
A semi-analytic 2D path-finding for large dynamic scenarios.
using System;
using System.Collections.Generic;
using System.Drawing;

namespace YinYang.CodeProject.Projects.SimplePathfinding.Helpers
{
    public class DirectionHelper
    {
        public static Point GetShift(DirectionType direction, Size size)
        {
            Point result = new Point(0, 0);

            switch (direction)
            {
                case DirectionType.North: result = new Point(size.Width >> 1, 0); break;
                case DirectionType.NorthEast: result = new Point(size.Width, 0); break;
                case DirectionType.East: result = new Point(size.Width, size.Height >> 1); break;
                case DirectionType.SouthEast: result = new Point(size.Width, size.Height); break;
                case DirectionType.South: result = new Point(size.Width >> 1, size.Height); break;
                case DirectionType.SouthWest: result = new Point(0, size.Height); break;
                case DirectionType.West: result = new Point(0, size.Height >> 1); break;
                case DirectionType.NorthWest: result = new Point(0, 0); break;
            }

            return result;
        }

        public static Point GetNextStep(Point startPoint, DirectionType direction)
        {
            Point nextPoint = GetNextStep(direction);
            return new Point(startPoint.X + nextPoint.X, startPoint.Y + nextPoint.Y);
        }

        public static Point GetNextStep(DirectionType direction)
        {
            Int32 x = 0, y = 0;

            if (direction.HasFlag(DirectionType.West)) x = -1;
            if (direction.HasFlag(DirectionType.East)) x = +1;
            if (direction.HasFlag(DirectionType.North)) y = -1;
            if (direction.HasFlag(DirectionType.South)) y = +1;

            return new Point(x, y);
        }

        public static DirectionType Rotate(DirectionType direction, Boolean leftSide, Boolean allowDiagonals)
        {
            return leftSide ? RotateLeft(direction, allowDiagonals) : RotateRight(direction, allowDiagonals);
        }

        public static DirectionType RotateLeft(DirectionType direction, Boolean allowDiagonals = true)
        {
            DirectionType result = DirectionType.None;

            if (allowDiagonals)
            {
                switch (direction)
                {
                    case DirectionType.North: result = DirectionType.NorthWest; break;
                    case DirectionType.NorthEast: result = DirectionType.North; break;
                    case DirectionType.East: result = DirectionType.NorthEast; break;
                    case DirectionType.SouthEast: result = DirectionType.East; break;
                    case DirectionType.South: result = DirectionType.SouthEast; break;
                    case DirectionType.SouthWest: result = DirectionType.South; break;
                    case DirectionType.West: result = DirectionType.SouthWest; break;
                    case DirectionType.NorthWest: result = DirectionType.West; break;
                }
            }
            else
            {
                switch (direction)
                {
                    case DirectionType.North: result = DirectionType.West; break;
                    case DirectionType.NorthEast: result = DirectionType.North; break;
                    case DirectionType.East: result = DirectionType.North; break;
                    case DirectionType.SouthEast: result = DirectionType.East; break;
                    case DirectionType.South: result = DirectionType.East; break;
                    case DirectionType.SouthWest: result = DirectionType.South; break;
                    case DirectionType.West: result = DirectionType.South; break;
                    case DirectionType.NorthWest: result = DirectionType.West; break;
                }
            }

            return result;
        }

        public static DirectionType RotateRight(DirectionType direction, Boolean allowDiagonals = true)
        {
            DirectionType result = DirectionType.None;

            if (allowDiagonals)
            {
                switch (direction)
                {
                    case DirectionType.North: result = DirectionType.NorthEast; break;
                    case DirectionType.NorthEast: result = DirectionType.East; break;
                    case DirectionType.East: result = DirectionType.SouthEast; break;
                    case DirectionType.SouthEast: result = DirectionType.South; break;
                    case DirectionType.South: result = DirectionType.SouthWest; break;
                    case DirectionType.SouthWest: result = DirectionType.West; break;
                    case DirectionType.West: result = DirectionType.NorthWest; break;
                    case DirectionType.NorthWest: result = DirectionType.North; break;
                }
            }
            else
            {
                switch (direction)
                {
                    case DirectionType.North: result = DirectionType.East; break;
                    case DirectionType.NorthEast: result = DirectionType.East; break;
                    case DirectionType.East: result = DirectionType.South; break;
                    case DirectionType.SouthEast: result = DirectionType.South; break;
                    case DirectionType.South: result = DirectionType.West; break;
                    case DirectionType.SouthWest: result = DirectionType.West; break;
                    case DirectionType.West: result = DirectionType.North; break;
                    case DirectionType.NorthWest: result = DirectionType.North; break;
                }
            }

            return result;
        }

        public static DirectionType InfereDirection(Point previousPoint, Point nextPoint)
        {
            DirectionType result = DirectionType.None;
            
            Int32 deltaX = nextPoint.X - previousPoint.X;
            Int32 deltaY = nextPoint.Y - previousPoint.Y;

            if (deltaX == -1) result |= DirectionType.West;
            if (deltaX == +1) result |= DirectionType.East;
            if (deltaY == -1) result |= DirectionType.North;
            if (deltaY == +1) result |= DirectionType.South;

            return result;
        }

        public static DirectionType Reverse(DirectionType direction)
        {
            DirectionType result = DirectionType.None;

            switch (direction)
            {
                case DirectionType.North: result = DirectionType.South; break;
                case DirectionType.NorthEast: result = DirectionType.SouthWest; break;
                case DirectionType.East: result = DirectionType.West; break;
                case DirectionType.SouthEast: result = DirectionType.NorthWest; break;
                case DirectionType.South: result = DirectionType.North; break;
                case DirectionType.SouthWest: result = DirectionType.NorthEast; break;
                case DirectionType.West: result = DirectionType.East; break;
                case DirectionType.NorthWest: result = DirectionType.SouthEast; break;
            }

            return result;
        }

        public static IEnumerable<DirectionType> GetValues()
        {
            yield return DirectionType.North;
            yield return DirectionType.NorthEast;
            yield return DirectionType.East;
            yield return DirectionType.SouthEast;
            yield return DirectionType.South;
            yield return DirectionType.SouthWest;
            yield return DirectionType.West;
            yield return DirectionType.NorthWest;
        }
    }
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer
Czech Republic Czech Republic
Contacts: EMAIL - smartk8@gmail.com

Comments and Discussions