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); }