Ejemplo n.º 1
0
        public Line(Vertex v1, Vertex v2)
            : this()
        {
            V1 = v1;
            V2 = v2;

            if (Point)
            {
                return;
            }

            if (!Orthogonal)
            {
                throw new ArgumentException("Must be an orthogonal line.");
            }

            int x1 = V1.X, x2 = V2.X, y1 = V1.Y, y2 = V2.Y;
            if (Vertical && y1 > y2)
            {
                V1 = new Vertex(x1, y2);
                V2 = new Vertex(x2, y1);
                return;
            }

            if (!Horizontal || x1 <= x2)
            {
                return;
            }
            V1 = new Vertex(x2, y1);
            V2 = new Vertex(x1, y2);
        }
Ejemplo n.º 2
0
        /// <summary>
        /// This maps all the polygon "diagonals" between concave vertices.
        /// </summary>
        private static HashSet<Line> FindDiagonals(List<Vertex> allConcaves, List<Line> lines)
        {
            HashSet<Line> diagonals = new HashSet<Line>();
            foreach (Vertex concave in allConcaves)
            {
                Vertex reference = concave;
                List<Vertex> axisNeighbors =
                    allConcaves.Where(cv => cv.X == reference.X || cv.Y == reference.Y).ToList();
                axisNeighbors.Remove(reference);

                var leftNeighbors = axisNeighbors.Where(an => an.X < reference.X).OrderBy(an => an.X);
                Vertex leftVertex = new Vertex(Int32.MinValue, Int32.MinValue);
                if (leftNeighbors.Any())
                {
                    leftVertex = leftNeighbors.Last();
                }

                Vertex rightVertex = new Vertex(Int32.MinValue, Int32.MinValue);
                var rightNeighbors = axisNeighbors.Where(an => an.X > reference.X).OrderBy(an => an.X);
                if (rightNeighbors.Any())
                {
                    rightVertex = rightNeighbors.First();
                }

                var topNeighbors = axisNeighbors.Where(an => an.Y > reference.Y).OrderBy(an => an.Y);
                Vertex topVertex = new Vertex(Int32.MinValue, Int32.MinValue);
                if (topNeighbors.Any())
                {
                    topVertex = topNeighbors.First();
                }

                var bottomNeighbors = axisNeighbors.Where(an => an.Y < reference.Y).OrderBy(an => an.Y);
                Vertex bottomVertex = new Vertex(Int32.MinValue, Int32.MinValue);
                if (bottomNeighbors.Any())
                {
                    bottomVertex = bottomNeighbors.Last();
                }

                Line testLine;
                if (TestLineIntersection(reference, leftVertex, out testLine, lines))
                {
                    diagonals.Add(testLine);
                }
                if (TestLineIntersection(reference, rightVertex, out testLine, lines))
                {
                    diagonals.Add(testLine);
                }
                if (TestLineIntersection(reference, topVertex, out testLine, lines))
                {
                    diagonals.Add(testLine);
                }
                if (TestLineIntersection(reference, bottomVertex, out testLine, lines))
                {
                    diagonals.Add(testLine);
                }
            }
            return diagonals;
        }
Ejemplo n.º 3
0
        public bool Intersects(Line l2)
        {
            int determinant = A * l2.B - l2.A * B;

            if (determinant == 0)
            {
                return false;
            }

            int x1 = ( l2.B * C - B * l2.C ) / determinant;
            int y1 = ( A * l2.C - l2.A * C ) / determinant;

            Vertex test = new Vertex(x1, y1);
            return Contains(test) && l2.Contains(test);
        }
Ejemplo n.º 4
0
        /// <summary>
        /// Checks to see if this line contains a <see cref="Vertex"/>
        /// within it.  Since we're dealing with integer coordinate
        /// orthogonal lines, this is pretty easy.
        /// </summary>
        public bool Contains(Vertex v)
        {
            int x1 = V1.X, x2 = V2.X, y1 = V1.Y, y2 = V2.Y;
            int swap;
            if (x1 > x2)
            {
                swap = x1;
                x1 = x2;
                x2 = swap;
            }

            if (y1 <= y2)
            {
                return v.X >= x1 && v.X <= x2 && v.Y >= y1 && v.Y <= y2;
            }

            swap = y1;
            y1 = y2;
            y2 = swap;

            return v.X >= x1 && v.X <= x2 && v.Y >= y1 && v.Y <= y2;
        }
Ejemplo n.º 5
0
 public bool Equals(Vertex other)
 {
     return X == other.X && Y == other.Y;
 }
Ejemplo n.º 6
0
        /// <summary>
        /// This processes polygons to determine where to slice them in order to find rectangles.
        /// </summary>
        private static void ProcessAreas(Dictionary<int, List<Cell>> areas)
        {
            Queue<List<Cell>> areasQueue = new Queue<List<Cell>>();

            foreach (var pair in areas)
            {
                areasQueue.Enqueue(pair.Value);
            }

            while (areasQueue.Count > 0)
            {
                if (_showStatus)
                {
                    Console.WriteLine("{0} area{1} to process.", areasQueue.Count, areasQueue.Count == 1 ? "" : "s");
                }
                var newArea = areasQueue.Dequeue();
                newArea = ResetArea(newArea);
                var lines = GetEdgeLines(newArea);
                HashSet<Vertex> concaves = new HashSet<Vertex>();
                foreach (Vertex concaveVertex in newArea.SelectMany(cell => cell.ConcaveVertices))
                {
                    concaves.Add(concaveVertex);
                }
                List<Vertex> allConcaves = concaves.OrderBy(v => v.Y).ThenBy(v => v.X).ToList();

                //	We're done with this rectangle, store it.
                if (allConcaves.Count == 0)
                {
                    StoreArea(newArea);
                    continue;
                }

                //	Slice on a diagonal and enqueue the results
                var diagonals = FindDiagonals(allConcaves, lines);
                if (diagonals.Count > 0)
                {
                    int max = diagonals.Max(d => d.Length);
                    Line l = diagonals.First(d => d.Length == max);
                    List<Cell> newCells = newArea.ToList();
                    Slice(newCells, l);
                    var possibles = MapCellsToAreas(newCells);
                    foreach (var possible in possibles)
                    {
                        if (_showStatus)
                        {
                            Console.WriteLine("Enqueueing....");
                        }
                        areasQueue.Enqueue(possible.Value);
                    }
                    continue;
                }

                //	Take a concave, find a valid closest wall, and slice to it.
                if (allConcaves.Count > 0)
                {
                    Vertex bad1 = new Vertex(int.MaxValue, int.MaxValue);
                    Vertex bad2 = new Vertex(int.MaxValue - 1, int.MaxValue);
                    Vertex bad3 = new Vertex(int.MaxValue, int.MaxValue - 1);

                    Vertex v = allConcaves.First();
                    var vLines = lines.Where(l => l.Vertical && !(l.V1==v||l.V2==v)).OrderBy(l => Math.Abs(l.V1.X - v.X)).ToList();
                    var hLines = lines.Where(l => l.Horizontal && !(l.V1==v||l.V2==v)).OrderBy(l => Math.Abs(l.V1.Y - v.Y)).ToList();

                    Line hLineTest = new Line();
                    foreach (var hLine in hLines)
                    {
                        Vertex v2 = new Vertex(v.X, hLine.V1.Y);
                        if (TestLineIntersection(v, v2, out hLineTest, lines))
                        {
                            hLineTest = new Line(v, v2);
                            break;
                        }
                        hLineTest = new Line(bad1, bad2);
                    }

                    Line vLineTest = new Line();
                    foreach (Vertex v2 in vLines.Select(vLine => new Vertex(vLine.V1.X, v.Y)))
                    {
                        if (TestLineIntersection(v, v2, out vLineTest, lines))
                        {
                            vLineTest = new Line(v, v2);
                            break;
                        }
                        vLineTest = new Line(bad1, bad3);
                    }

                    int vLineDist1 = Math.Abs(v.X - vLineTest.V1.X);
                    int vLineDist2 = Math.Abs(v.X - vLineTest.V2.X);
                    int vLineDist = vLineDist1 < vLineDist2 ? vLineDist2 : vLineDist1;

                    int hLineDist1 = Math.Abs(v.Y - hLineTest.V1.Y);
                    int hLineDist2 = Math.Abs(v.Y - hLineTest.V2.Y);
                    int hLineDist = hLineDist1 < hLineDist2 ? hLineDist2 : hLineDist1;

                    Line slicer = vLineDist < hLineDist ? vLineTest : hLineTest;

                    List<Cell> newCells = newArea.ToList();
                    Slice(newCells, slicer);
                    var possibles = MapCellsToAreas(newCells);
                    foreach (var possible in possibles)
                    {
                        if (_showStatus)
                        {
                            Console.WriteLine("Enqueueing....");
                        }
                        areasQueue.Enqueue(possible.Value);
                    }
                }
            }
        }
Ejemplo n.º 7
0
        /// <summary>
        /// Checks to see if a theoretical line between two vertices will intersect with a list of lines.
        /// </summary>
        /// <param name="reference">Starting vertex</param>
        /// <param name="testVertex">Ending vertex</param>
        /// <param name="test">Line to modify in return</param>
        /// <param name="lines">List of lines to test</param>
        /// <returns>True if intersections.</returns>
        private static bool TestLineIntersection(Vertex reference, Vertex testVertex, out Line test, List<Line> lines)
        {
            test = default ( Line );
            if (testVertex.X == Int32.MinValue && testVertex.Y == Int32.MinValue)
            {
                return false;
            }

            Line testing = new Line(reference, testVertex);
            if (testing.Point)
            {
                return false;
            }

            //	Find lines that may contain the test line
            List<Line> testOverLines = testing.Horizontal
                ? lines.Where(li => li.Horizontal && li.V1.Y == testing.V1.Y).ToList()
                : lines.Where(li => li.Vertical && li.V1.X == testing.V1.X).ToList();

            if (testOverLines.Any(tol => tol.Contains(testing)))
            {
                return false;
            }

            //	Test to see if the line contains any edge lines
            if (testOverLines.Any(testing.Contains))
            {
                return false;
            }

            //	Find lines that may intersect
            List<Line> testCrossLines = testing.Horizontal
                ? lines.Where(li => li.Vertical && li.V1.X > testing.V1.X && li.V1.X < testing.V2.X).ToList()
                : lines.Where(li => li.Horizontal && li.V1.Y > testing.V1.Y && li.V1.Y < testing.V2.Y).ToList();

            //	No lines between.  We pass.
            if (testCrossLines.Count == 0)
            {
                test = testing;
                return true;
            }

            //	Nothing intersects.  We pass.
            if (testCrossLines.Any(tcl => tcl.Intersects(testing)))
            {
                return false;
            }

            test = testing;
            return true;
        }