private List <float> SearchCrossingEdges(DetectedVertices polygon, int y)
        {
            if (polygon == null)
            {
                throw new ArgumentNullException("polygon", "'polygon' can't be null.");
            }

            if (polygon.Count < 3)
            {
                throw new ArgumentException("'polygon.MainPolygon.Count' can't be less then 3.");
            }

            List <float> result = SearchCrossingEdges((Vertices)polygon, y);

            if (polygon.Holes != null)
            {
                for (int i = 0; i < polygon.Holes.Count; i++)
                {
                    result.AddRange(SearchCrossingEdges(polygon.Holes[i], y));
                }
            }

            result.Sort();
            return(result);
        }
        private bool DistanceToHullAcceptable(DetectedVertices polygon, FVector2 point, bool higherDetail)
        {
            if (polygon == null)
            {
                throw new ArgumentNullException("polygon", "'polygon' can't be null.");
            }

            if (polygon.Count < 3)
            {
                throw new ArgumentException("'polygon.MainPolygon.Count' can't be less then 3.");
            }

            // Check the distance to main polygon.
            if (DistanceToHullAcceptable((Vertices)polygon, point, higherDetail))
            {
                if (polygon.Holes != null)
                {
                    for (int i = 0; i < polygon.Holes.Count; i++)
                    {
                        // If there is one distance not acceptable then return false.
                        if (!DistanceToHullAcceptable(polygon.Holes[i], point, higherDetail))
                        {
                            return(false);
                        }
                    }
                }

                // All distances are larger then _hullTolerance.
                return(true);
            }

            // Default to false.
            return(false);
        }
        private bool InPolygon(DetectedVertices polygon, FVector2 point)
        {
            bool inPolygon = !DistanceToHullAcceptable(polygon, point, true);

            if (!inPolygon)
            {
                List <float> xCoords = SearchCrossingEdges(polygon, (int)point.Y);

                if (xCoords.Count > 0 && xCoords.Count % 2 == 0)
                {
                    for (int i = 0; i < xCoords.Count; i += 2)
                    {
                        if (xCoords[i] <= point.X && xCoords[i + 1] >= point.X)
                        {
                            return(true);
                        }
                    }
                }

                return(false);
            }

            return(true);
        }
        public List <DetectedVertices> DetectVertices()
        {
            #region Check TextureConverter setup.

            if (_data == null)
            {
                throw new Exception(
                          "'_data' can't be null. You have to use SetTextureData(uint[] data, int width) before calling this method.");
            }

            if (_data.Length < 4)
            {
                throw new Exception(
                          "'_data' length can't be less then 4. Your texture must be at least 2 x 2 pixels in size. " +
                          "You have to use SetTextureData(uint[] data, int width) before calling this method.");
            }

            if (_width < 2)
            {
                throw new Exception(
                          "'_width' can't be less then 2. Your texture must be at least 2 x 2 pixels in size. " +
                          "You have to use SetTextureData(uint[] data, int width) before calling this method.");
            }

            if (_data.Length % _width != 0)
            {
                throw new Exception(
                          "'_width' has an invalid value. You have to use SetTextureData(uint[] data, int width) before calling this method.");
            }

            #endregion


            List <DetectedVertices> detectedPolygons = new List <DetectedVertices>();

            DetectedVertices polygon;
            Vertices         holePolygon;

            FVector2?holeEntrance    = null;
            FVector2?polygonEntrance = null;

            List <FVector2> blackList = new List <FVector2>();

            bool searchOn;
            do
            {
                if (detectedPolygons.Count == 0)
                {
                    // First pass / single polygon
                    polygon = new DetectedVertices(CreateSimplePolygon(FVector2.Zero, FVector2.Zero));

                    if (polygon.Count > 2)
                    {
                        polygonEntrance = GetTopMostVertex(polygon);
                    }
                }
                else if (polygonEntrance.HasValue)
                {
                    // Multi pass / multiple polygons
                    polygon = new DetectedVertices(CreateSimplePolygon(
                                                       polygonEntrance.Value, new FVector2(polygonEntrance.Value.X - 1f, polygonEntrance.Value.Y)));
                }
                else
                {
                    break;
                }

                searchOn = false;


                if (polygon.Count > 2)
                {
                    if (_holeDetection)
                    {
                        do
                        {
                            holeEntrance = SearchHoleEntrance(polygon, holeEntrance);

                            if (holeEntrance.HasValue)
                            {
                                if (!blackList.Contains(holeEntrance.Value))
                                {
                                    blackList.Add(holeEntrance.Value);
                                    holePolygon = CreateSimplePolygon(holeEntrance.Value,
                                                                      new FVector2(holeEntrance.Value.X + 1, holeEntrance.Value.Y));

                                    if (holePolygon != null && holePolygon.Count > 2)
                                    {
                                        switch (_polygonDetectionType)
                                        {
                                        case VerticesDetectionType.Integrated:

                                            // Add first hole polygon vertex to close the hole polygon.
                                            holePolygon.Add(holePolygon[0]);

                                            int vertex1Index, vertex2Index;
                                            if (SplitPolygonEdge(polygon, holeEntrance.Value, out vertex1Index, out vertex2Index))
                                            {
                                                polygon.InsertRange(vertex2Index, holePolygon);
                                            }

                                            break;

                                        case VerticesDetectionType.Separated:
                                            if (polygon.Holes == null)
                                            {
                                                polygon.Holes = new List <Vertices>();
                                            }

                                            polygon.Holes.Add(holePolygon);
                                            break;
                                        }
                                    }
                                }
                                else
                                {
                                    break;
                                }
                            }
                            else
                            {
                                break;
                            }
                        }while (true);
                    }

                    detectedPolygons.Add(polygon);
                }

                if (_multipartDetection || polygon.Count <= 2)
                {
                    if (SearchNextHullEntrance(detectedPolygons, polygonEntrance.Value, out polygonEntrance))
                    {
                        searchOn = true;
                    }
                }
            }while (searchOn);

            if (detectedPolygons == null || (detectedPolygons != null && detectedPolygons.Count == 0))
            {
                throw new Exception("Couldn't detect any vertices.");
            }


            // Post processing.
            if (PolygonDetectionType == VerticesDetectionType.Separated) // Only when VerticesDetectionType.Separated? -> Recheck.
            {
                ApplyTriangulationCompatibleWinding(ref detectedPolygons);
            }

            if (_pixelOffsetOptimization)
            {
                ApplyPixelOffsetOptimization(ref detectedPolygons);
            }

            if (_transform != FMatrix.Identity)
            {
                ApplyTransform(ref detectedPolygons);
            }


            return(detectedPolygons);
        }