public void GetTriangleList() { using var subdiv = new Subdiv2D(new Rect(0, 0, 500, 500)); var points = new[] { new Point2f(300, 100), new Point2f(200, 300), new Point2f(400, 300) }; subdiv.Insert(points[0]); subdiv.Insert(points[1]); subdiv.Insert(points[2]); var triangles = subdiv.GetTriangleList(); Assert.Single(triangles); var triangleVertices = new[] { triangles[0].Item0, triangles[0].Item1, triangles[0].Item2, triangles[0].Item3, triangles[0].Item4, triangles[0].Item5, }; foreach (var point in points) { Assert.Contains(point.X, triangleVertices); Assert.Contains(point.Y, triangleVertices); } }
/// <summary> /// Perform Delaunay triangulation on a given set of landmark points. /// </summary> /// <param name="points">The landmark points to use for triangulation.</param> /// <returns>A list of Triangle structures that each refer to a single triangle of landmark points.</returns> public static IEnumerable <Triangle> GetDelaunayTriangles(IEnumerable <Point> points) { var result = new List <Triangle>(); // calculate the bounding box around the points var rect = Cv2.BoundingRect(points); rect.Inflate(10, 10); // the Subdiv2D class handles Delaunay triangulation // first we add all points, and then start triangulation Vec6f[] triangles; using (var subdiv = new Subdiv2D(rect)) { foreach (var p in points) { var cv_p = new OpenCvSharp.Point2f(p.X, p.Y); subdiv.Insert(cv_p); } triangles = subdiv.GetTriangleList(); } // return result as an enumeration of triangle structs return(from t in triangles let p1 = new Point(t[0], t[1]) let p2 = new Point(t[2], t[3]) let p3 = new Point(t[4], t[5]) where rect.Contains(p1) && rect.Contains(p2) && rect.Contains(p3) select new Triangle(p1, p2, p3)); }
public void Run() { const int Size = 600; // Creates random point list var rand = new Random(); var points = Enumerable.Range(0, 100).Select(_ => new Point2f(rand.Next(0, Size), rand.Next(0, Size))).ToArray(); Mat img = Mat.Zeros(Size, Size, MatType.CV_8UC3); foreach (var p in points) { img.Circle(p, 4, Scalar.Red, -1); } // Initializes Subdiv2D var subdiv = new Subdiv2D(); subdiv.InitDelaunay(new Rect(0, 0, Size, Size)); subdiv.Insert(points); // Draws voronoi diagram Point2f[][] facetList; Point2f[] facetCenters; subdiv.GetVoronoiFacetList(null, out facetList, out facetCenters); var vonoroi = img.Clone(); foreach (var list in facetList) { var before = list.Last(); foreach (var p in list) { vonoroi.Line(before, p, new Scalar(64, 255, 128), 1); before = p; } } // Draws delaunay diagram Vec4f[] edgeList = subdiv.GetEdgeList(); var delaunay = img.Clone(); foreach (var edge in edgeList) { var p1 = new Point(edge.Item0, edge.Item1); var p2 = new Point(edge.Item2, edge.Item3); delaunay.Line(p1, p2, new Scalar(64, 255, 128), 1); } Cv2.ImShow("voronoi", vonoroi); Cv2.ImShow("delaunay", delaunay); Cv2.WaitKey(); Cv2.DestroyAllWindows(); }
public void GetVoronoiFacetList() { using var subdiv = new Subdiv2D(new Rect(0, 0, 500, 500)); var points = new[] { new Point2f(300, 100), new Point2f(200, 300), new Point2f(400, 300) }; subdiv.Insert(points); subdiv.GetVoronoiFacetList(null, out var facetList, out var facetCenters); Assert.Equal(3, facetList.Length); Assert.Equal(3, facetCenters.Length); Assert.Equal(4, facetList[0].Length); }
public void Run() { const int Size = 600; // Creates random point list var rand = new Random(); var points = Enumerable.Range(0, 100).Select(_ => new Point2f(rand.Next(0, Size), rand.Next(0, Size))).ToArray(); Mat img = Mat.Zeros(Size, Size, MatType.CV_8UC3); foreach (var p in points) { img.Circle(p, 4, CvColor.Red, -1); } // Initializes Subdiv2D var subdiv = new Subdiv2D(); subdiv.InitDelaunay(new Rect(0, 0, Size, Size)); subdiv.Insert(points); // Draws voronoi diagram Point2f[][] facetList; Point2f[] facetCenters; subdiv.GetVoronoiFacetList(null, out facetList, out facetCenters); var vonoroi = img.Clone(); foreach (var list in facetList) { var before = list.Last(); foreach (var p in list) { vonoroi.Line(before, p, new CvColor(64, 255, 128), 1); before = p; } } // Draws delaunay diagram Vec4f[] edgeList = subdiv.GetEdgeList(); var delaunay = img.Clone(); foreach (var edge in edgeList) { var p1 = new Point(edge.Item0, edge.Item1); var p2 = new Point(edge.Item2, edge.Item3); delaunay.Line(p1, p2, new CvColor(64, 255, 128), 1); } Cv2.ImShow("voronoi", vonoroi); Cv2.ImShow("delaunay", delaunay); Cv2.WaitKey(); Cv2.DestroyAllWindows(); }
private static IEnumerable <int[]> GetDelaunayTriangulationIndexes(Rect rect, List <Point2f> points) { rect = Cv2.BoundingRect(points).Union(rect); using (var subdivision = new Subdiv2D(rect)) { subdivision.Insert(points); var triangulation = subdivision.GetTriangleList(); foreach (var cell in triangulation) { var p1 = new Point2f(cell.Item0, cell.Item1); var p2 = new Point2f(cell.Item2, cell.Item3); var p3 = new Point2f(cell.Item4, cell.Item5); if (rect.Contains(p1) && rect.Contains(p2) && rect.Contains(p3)) { var indexA = points.IndexOf(p1); var indexB = points.IndexOf(p2); var indexC = points.IndexOf(p3); var indexes = new[] { indexA, indexB, indexC }; yield return(indexes); } } } }
private void CreateDelaunay(ref Mat img, ref Subdiv2D subdiv, ref VectorOfPointF points, bool drawAnimated, ref VectorOfVectorOfInt triangleIndexes) { PointF[] pointsArr = points.ToArray(); foreach (PointF p in pointsArr) { subdiv.Insert(p); if (drawAnimated) { Mat imgCopy = img.Clone(); DrawDelaunay(ref imgCopy, ref subdiv, new MCvScalar(255, 255, 255)); CvInvoke.Imshow("Delaunay Triangulation", imgCopy); } } // Unfortunately we don't get the triangles by there original point indexes. // We only get them with their vertex coordinates. // So we have to map them again to get the triangles with their point indexes. Size size = img.Size; Rectangle rect = new Rectangle(0, 0, size.Width, size.Height); VectorOfInt ind = new VectorOfInt(); int[] indArr = new int[3]; Triangle2DF[] triangleList = subdiv.GetDelaunayTriangles(); for (int i = 0; i < triangleList.Length; i++) { Triangle2DF t = triangleList[i]; PointF ptzero = new PointF { X = t.V0.X, Y = t.V0.Y }; PointF[] PZero = new PointF[] { ptzero }; PointF ptone = new PointF { X = t.V1.X, Y = t.V1.Y }; PointF[] POne = new PointF[] { ptone }; PointF pttwo = new PointF { X = t.V2.X, Y = t.V2.Y }; PointF[] PTwo = new PointF[] { pttwo }; VectorOfPointF pt = new VectorOfPointF(); pt.Push(PZero); pt.Push(POne); pt.Push(PTwo); if (rect.Contains(new Point((int)pt[0].X, (int)pt[0].Y)) && rect.Contains(new Point((int)pt[1].X, (int)pt[1].Y)) && rect.Contains(new Point((int)pt[2].X, (int)pt[2].Y))) { for (int j = 0; j < 3; j++) { for (int k = 0; k < points.Size; k++) { if (Math.Abs(pt[j].X - points[k].X) < 1.0 && Math.Abs(pt[j].Y - points[k].Y) < 1) { indArr[j] = k; } } } } ind = new VectorOfInt(indArr); triangleIndexes.Push(ind); } }