Example #1
0
 public Wall(Node from, Node to)
 {
     From = from;
     To = to;
 }
Example #2
0
        bool PointInPolygon(Node point)
        {
            foreach (Wall wall in _walls)
            {
                if (IsOnLine(wall.From, wall.To, point))
                    return true;
            }

            bool c = false;

            foreach (Wall wall in _walls)
            {
                Node from = wall.From;
                Node to = wall.To;
                if (!IsOnLine(from, to, point) && (from.Y >= point.Y) != (to.Y >= point.Y) &&
                    (point.X <= (to.X - from.X) * (point.Y - from.Y) / (to.Y - from.Y) + from.X)
                  )
                    c = !c;
            }

            return c;
        }
Example #3
0
 private Wall[] SplitWall(Wall wall, Node node1, Node node2)
 {
     Wall[] splitWall = new Wall[2];
     if (Equals(wall.From, node1))
     {
         splitWall[0] = new Wall(node2, wall.To);
         splitWall[1] = null;
     }
     else if (Equals(wall.To, node1))
     {
         splitWall[0] = new Wall(wall.From, node2);
         splitWall[1] = null;
     }
     else if (Equals(wall.From, node2))
     {
         splitWall[0] = new Wall(node1, wall.To);
         splitWall[1] = null;
     }
     else if (Equals(wall.To, node2))
     {
         splitWall[0] = new Wall(wall.From, node1);
         splitWall[1] = null;
     }
     else
     {
         decimal distanceBetweenFromAndNode1 = (Math.Abs(wall.From.X - node1.X) + Math.Abs(wall.From.Y - node1.Y)) / 2;
         decimal distanceBetweenFromAndNode2 = (Math.Abs(wall.From.X - node2.X) + Math.Abs(wall.From.Y - node2.Y)) / 2;
         if (distanceBetweenFromAndNode1 < distanceBetweenFromAndNode2)
         {
             splitWall[0] = new Wall(wall.From, node1);
             splitWall[0] = new Wall(node2, wall.To);
         }
         else
         {
             splitWall[0] = new Wall(wall.From, node2);
             splitWall[0] = new Wall(node1, wall.To);
         }
     }
     return splitWall;
 }
Example #4
0
        public Node FindUnguardedPoint(ArrayList guards)
        {
            ArrayList wallsNotVisible = (ArrayList)_walls.Clone();
            foreach (Node guard in guards)
            {
                ArrayList visibleVertices = new ArrayList();
                ArrayList tempWallsNotVisible = (ArrayList)wallsNotVisible.Clone();
                foreach (Wall wall in tempWallsNotVisible)
                {
                    if (wall != null)
                    {
                        bool fromVisible = false, toVisible = false;
                        if (IsVisible(guard, wall.From))
                        {
                            visibleVertices.Add(wall.From);
                            wall.TemporaryViewablePoint = wall.From;
                            fromVisible = true;
                        }
                        if (IsVisible(guard, wall.To))
                        {
                            wall.TemporaryViewablePoint = wall.To;
                            toVisible = true;
                        }
                        if (fromVisible && toVisible)
                        {
                            wall.TemporaryViewablePoint = null;
                            //wall.VisibleSegments.Add(new Segment(wall.From, wall.To));
                            wallsNotVisible.Remove(wall);
                        }
                    }
                }

                foreach (Node vertex in visibleVertices)
                {
                    if (vertex.Type == VertexType.Special)
                    {
                        decimal dy = guard.Y - vertex.Y;
                        decimal dx = guard.X - vertex.X;
                        decimal e = (decimal)0.0000000001;

                        Node nearNode1, nearNode2, distantNode;
                        if (Equals(guard.X, vertex.X))
                        {
                            decimal diffY = 50 * dy;
                            if (guard.Y < vertex.Y)
                            {
                                nearNode1 = new Node(guard.X, guard.Y + 5 * e);
                                nearNode2 = new Node(vertex.X, vertex.Y + 2 * e);
                                distantNode = new Node(vertex.X, vertex.Y + diffY);
                            }
                            else
                            {
                                nearNode1 = new Node(guard.X, guard.Y - 5 * e);
                                nearNode2 = new Node(vertex.X, vertex.Y - e);
                                distantNode = new Node(vertex.X, vertex.Y - diffY);

                            }
                        }
                        else
                        {
                            decimal deltaX = e * dx;
                            decimal deltaY = e * dy;
                            decimal diffX = 50 * dx;
                            decimal diffY = 50 * dy;
                            if (guard.X < vertex.X)
                            {
                                nearNode1 = new Node(guard.X + deltaX, guard.Y + 5 * deltaY);
                                nearNode2 = new Node(vertex.X + deltaX, vertex.Y + deltaY);
                                distantNode = new Node(vertex.X + diffX, vertex.Y + diffY);
                            }
                            else
                            {
                                nearNode1 = new Node(guard.X - deltaX, guard.Y - 5 * deltaY);
                                nearNode2 = new Node(vertex.X - deltaX, vertex.Y - deltaY);
                                distantNode = new Node(vertex.X - diffX, vertex.Y - diffY);
                            }
                        }

                        if (PointInPolygon(nearNode2) && PointInPolygon(nearNode1))
                        {
                            Segment extendedLine = new Segment(new Node(guard.X, guard.Y), distantNode);
                            ArrayList intersectionList = new ArrayList();
                            ArrayList intersectionWallList = new ArrayList();

                            foreach (Wall wall in _walls)
                            {
                                if (wall != null)
                                {
                                    Node intersection = Intersection(extendedLine, wall.From, wall.To);
                                    if (intersection != null && !Equals(intersection, vertex))
                                    {
                                        intersectionList.Add(intersection);
                                        intersectionWallList.Add(wall);
                                    }
                                }
                            }
                            Node nearestIntersection = GetNearestIntersection(intersectionList);
                            if (nearestIntersection != null)
                            {
                                Wall wall = intersectionWallList[intersectionList.IndexOf(nearestIntersection)] as Wall;
                                if (wall != null)
                                {
                                    if (wall.TemporaryViewablePoint == null)
                                    {
                                        wall.TemporaryViewablePoint = nearestIntersection;
                                    }
                                    else
                                    {
                                        Wall[] splitWall = SplitWall(wall, wall.TemporaryViewablePoint, nearestIntersection);
                                        ArrayList tempWallsNotVisible2 = (ArrayList)wallsNotVisible.Clone();
                                        foreach (Wall wallNotVisible in tempWallsNotVisible2)
                                        {
                                            if (IsOnLine(wallNotVisible.From, wallNotVisible.To, nearestIntersection) &&
                                                !Equals(nearestIntersection, wall.From) && !Equals(nearestIntersection, wall.To))
                                            {
                                                wallsNotVisible.Remove(wall);
                                            }
                                        }
                                        wall.TemporaryViewablePoint = null;
                                        wallsNotVisible.Remove(wall);
                                        wallsNotVisible.Add(splitWall[0]);
                                        if (splitWall[1] != null) wallsNotVisible.Add(splitWall[1]);
                                    }
                                }
                            }
                        }
                    }
                }

                foreach (Wall wall in wallsNotVisible)
                {
                    if (wall != null)
                    {
                        wall.TemporaryViewablePoint = null;
                    }
                }
            }

            if (wallsNotVisible.Count == 0)
            {
                return new Node(100000, 100000);
            }
            foreach (Wall wall in wallsNotVisible)
            {
                if (wall != null)
                {
                    Wall unguardedWall = (Wall)wallsNotVisible[0];
                    decimal x = (unguardedWall.From.X + unguardedWall.To.X) / 2;
                    decimal y = (unguardedWall.From.Y + unguardedWall.To.Y) / 2;
                    return new Node(x, y);
                }
            }
            return new Node(100000, 100000);
        }
Example #5
0
        private bool IsVisible(Node guard, Node vertex)
        {
            if (Equals(guard.X, vertex.X) && Equals(guard.Y, vertex.Y)) return true;

            foreach (Wall wall in _walls)
            {
                if (Intersection(new Segment(wall.From, wall.To), guard, vertex) != null && !IsOnLine(wall.From, wall.To, guard)
                    && !IsOnLine(wall.From, wall.To, vertex) && !IsParallel(new Segment(wall.From, wall.To), new Segment(guard, vertex))
                    && !Equals(vertex, wall.From) && !Equals(vertex, wall.To))
                {
                    return false;
                }
            }
            for (decimal i = (decimal) 0.1; i < 1; i += (decimal) 0.1)
            {
                decimal dy = vertex.Y - guard.Y;
                decimal dx = vertex.X - guard.X;

                Node point;
                if (Equals(guard.X, vertex.X))
                {
                    decimal diffY = i * dy;
                    point = new Node(guard.X, guard.Y + diffY);
                }
                else
                {
                    decimal diffX = i * dx;
                    decimal diffY = i * dy;
                    point = new Node(guard.X + diffX, guard.Y + diffY);
                }

                if (!IsOnLine(vertex, guard, point) && !PointInPolygon(point))
                {
                    return false;
                }
            }
            return true;
        }
Example #6
0
 private VertexType GetVertexType(Node vertex)
 {
     decimal area = GetArea(new[] { GetPrevious(vertex), vertex, GetNext(vertex) });
     if (area < 0)
         return VertexType.Special;
     if (area > 0)
         return VertexType.Normal;
     return VertexType.NotAVertex;
 }
Example #7
0
        // TODO: Finish this function
        private Node Intersection(Segment segment1, Node from, Node to)
        {
            if (Equals(segment1.From, from) || Equals(segment1.From, to)
                || Equals(segment1.To, from) || Equals(segment1.To, to)
                || IsParallel(segment1, new Segment(from, to)))
            {
                return null;
            }

            decimal segment1X = segment1.From.X, segment1Y = segment1.From.Y;
            decimal segment1Dx = segment1.To.X - segment1.From.X, segment1Dy = segment1.To.Y - segment1.From.Y;
            decimal segment2X = to.X, segment2Y = to.Y;
            decimal segment2Dx = from.X - to.X, segment2Dy = from.Y - to.Y;

            if (Equals(segment1Dx, 0) && (from.X < segment1Y && to.X > segment1Y
                || from.X > segment1Y && to.X < segment1Y)) // Handle segment 1 is vertical
            {
                if (Equals(segment1Dx, segment2Dx))
                {
                    return null;
                }
                decimal gradient = segment2Dy / segment2Dx;
                Node node = new Node(segment1Y, segment1Y * gradient);
                if ((node.Y < segment1.From.Y && node.Y < segment1.To.Y)
                    || (node.Y > segment1.From.Y && node.Y > segment1.To.Y))
                {
                    return null;
                }
                return node;
            }
            if (Equals(segment2Dx, 0) && (from.X < segment2Y && to.X > segment2Y
                || from.X > segment2Y && to.X < segment2Y)) // Handle segment 2 is vertical
            {
                if (Equals(segment1Dx, segment2Dx))
                {
                    return null;
                }
                decimal gradient = segment1Dy / segment1Dx;
                Node node = new Node(segment2Y, segment2Y * gradient);
                if ((node.Y < from.Y && node.Y < to.Y)
                    || (node.Y > from.Y && node.Y > to.Y))
                {
                    return null;
                }
                return node;
            }

            if (!Equals(segment2Dx*segment1Dy, segment2Dy*segment1Dx))
            {
                try
                {
                    decimal t2 = (segment1Dx*(segment2Y - segment1Y) + segment1Dy*(segment1X - segment2X))/
                                 (segment2Dx*segment1Dy - segment2Dy*segment1Dx);
                    decimal t1 = (segment2X + segment2Dx*t2 - segment1X)/segment1Dx;
                    if (t2 <= 1 && t2 >= 0 && t1 >= 0 && t1 <= 1)
                    {
                        Node node = new Node(segment1X + segment1Dx*t1, segment1Y + segment1Dy*t1);
                        /*if (node == from || node == to) // TODO: If intersection is with a concave-inside vertex, ignore it (as above) - return null
                            {
                                if ((Math.Atan2((double)nextDy, (double)nextDx) >= 0 && Math.Atan2((double)previousDy, (double)previousDx) >= 0)
                                    || (Math.Atan2((double)nextDy, (double)nextDx) <= 0 && Math.Atan2((double)previousDy, (double)previousDx) <= 0))
                                { }
                                else { return null; }
                            }*/
                        return node;
                    }
                }
                catch (Exception e)
                {
                    Console.Write(e);
                }
            }
            return null;
        }
Example #8
0
 private Node GetPrevious(Node vertex)
 {
     var vertexIndex = _vertices.IndexOf(vertex);
     if (vertexIndex == 0)
         return (Node)_vertices[_vertices.Count - 1];
     return (Node)_vertices[vertexIndex - 1];
 }
Example #9
0
 private Node GetNext(Node vertex)
 {
     var vertexIndex = _vertices.IndexOf(vertex);
     if (vertexIndex == _vertices.Count - 1)
         return (Node)_vertices[0];
     return (Node)_vertices[vertexIndex + 1];
 }
Example #10
0
 private static decimal GetArea(Node[] vertices)
 {
     decimal area = 0;
     for (int i = 0; i < vertices.Length; i++)
     {
         int j = (i + 1) % vertices.Length;
         area += (vertices[i].X * vertices[j].Y);
         area -= (vertices[i].Y * vertices[j].X);
     }
     return area / 2;
 }
Example #11
0
 private static bool Equals(Node n1, Node n2)
 {
     if (Math.Abs(n1.X - n2.X) < epsilon && Math.Abs(n1.Y - n2.Y) < epsilon)
     {
         return true;
     }
     return false;
 }
Example #12
0
        public bool IsOnLine(Node endPoint1, Node endPoint2, Node checkPoint)
        {
            if ((Equals(checkPoint.X, endPoint1.X) && Equals(checkPoint.Y, endPoint1.Y)) ||
                (Equals(checkPoint.Y, endPoint2.X) && Equals(checkPoint.Y, endPoint2.Y)))
            {
                return true;
            }

            if (Equals(checkPoint.X - endPoint1.X, 0) && Equals(endPoint2.X - endPoint1.X, 0))
            {
                // vertical line
                // endPoint1.y < checkpoint.y < endPoint2.y => true
                // endPoint2.y < checkpoint.y < endPoint1.y => true
                // else false
                if ((endPoint1.Y <= checkPoint.Y && checkPoint.Y <= endPoint2.Y) ||
                    (endPoint2.Y <= checkPoint.Y && checkPoint.Y <= endPoint1.Y))
                {
                    return true;
                }
                return false;
            }
            try
            {
                if ((checkPoint.Y - endPoint1.Y) / (checkPoint.X - endPoint1.X)
                       == (endPoint2.Y - endPoint1.Y) / (endPoint2.X - endPoint1.X))
                {
                    // the gradient is the same
                    if ((endPoint1.Y <= checkPoint.Y && checkPoint.Y <= endPoint2.Y) ||
                    (endPoint2.Y <= checkPoint.Y && checkPoint.Y <= endPoint1.Y))
                    {
                        return true;
                    }
                    return false;
                }
            }
            catch (Exception e)
            {
                Console.Write(e);
            }
            return false;
        }