public static PathFindingTask TaskFromImage(Cairo.ImageSurface image)
 {
     var task = new PathFindingTask();
     var start = Utils.CairoPixelPositionModule.First(image, new Cairo.Color(0, 0, 1, 1));
     var goal = Utils.CairoPixelPositionModule.First(image, new Cairo.Color(1, 0, 0, 1));
     task.StartX = start.X;
     task.StartY = start.Y;
     task.TargetX = goal.X;
     task.TargetY = goal.Y;
     return task;
 }
 public void Step2_SetPathFinding(PathFindingTask pathFinding)
 {
     m_pathFinding = pathFinding;
 }
        public static List<int> SearchMap(PixelMap map, PathFindingTask pathFinding, bool[] mask, IndexHeap heap, PathNodes nodes)
        {
            var width = map.Width;
            var height = map.Height;
            var goalPosX = pathFinding.TargetX;
            var goalPosY = pathFinding.TargetY;

            heap.Compare = (int a, int b) =>
                (nodes.Data[a].Travelled + nodes.Data[a].DistanceToGoal).CompareTo(
                    nodes.Data[b].Travelled + nodes.Data[b].DistanceToGoal);

            IsVisitedDelegate IsVisited = (int x, int y) =>
                x < 0 || y < 0 || x >= width || y >= height || mask[x + y * width];

            // Contains the id of previous node.
            int node = -1;

            AddDelegate Add = delegate(int x, int y) {
                int id = x + y * width;
                nodes.Data[id].PreviousId = node;

                int dx = goalPosX - x;
                int dy = goalPosY - y;

                // Use square of length because it is faster.
                int dist = dx * dx + dy * dy;
                nodes.Data[id].DistanceToGoal = dist;

                if (node == -1) {
                    nodes.Data[id].Travelled = 0;
                } else {
                    dx = x - node % width;
                    dy = y - node / width;

                    // Use square of length because it is faster.
                    dist = dx * dx + dy * dy;

                    nodes.Data[id].Travelled = nodes.Data[node].Travelled + dist;
                }

                return id;
            };

            var start = Add(pathFinding.StartX, pathFinding.StartY);
            heap.Push(start);

            // Set values from the walls to the mask.
            mask.Initialize();
            var walls = map.Walls;
            int walls_length = walls.Count >> 1;
            int i, j, e, s;
            for (i = walls_length - 1; i >= 0; i--) {
                s = walls[i << 1];
                e = walls[(i << 1) + 1];
                for (j = e - 1; j >= s; j--) {
                    mask[j] = true;
                }
            }

            mask[start] = true;

            int n;
            int nodex;
            int nodey;
            while (heap.Cursor > 1) {
                node = heap.Pop();
                nodey = node / width;
                nodex = node - nodey * width;
                if (nodex == goalPosX &&
                    nodey == goalPosY) {
                    var list = new List<int>();
                    while (nodes.Data[node].PreviousId != -1) {
                        list.Add(node);
                        node = nodes.Data[node].PreviousId;
                    }
                    return list;
                }

                if (!IsVisited(nodex + 1, nodey)) {
                    n = Add(nodex + 1, nodey);
                    heap.Push(n);
                    mask[n] = true;
                }
                if (!IsVisited(nodex, nodey + 1)) {
                    n = Add(nodex, nodey + 1);
                    heap.Push(n);
                    mask[n] = true;
                }
                if (!IsVisited(nodex - 1, nodey)) {
                    n = Add(nodex - 1, nodey);
                    heap.Push(n);
                    mask[n] = true;
                }
                if (!IsVisited(nodex, nodey - 1)) {
                    n = Add(nodex, nodey - 1);
                    heap.Push(n);
                    mask[n] = true;
                }
            }

            return null;
        }