void DrawSimpleRectWithHoleExample(Painter painter) { Poly2Tri.TriangulationPoint[] box = new Poly2Tri.TriangulationPoint[] { new Poly2Tri.TriangulationPoint(5, 5), new Poly2Tri.TriangulationPoint(45, 5), new Poly2Tri.TriangulationPoint(45, 45), new Poly2Tri.TriangulationPoint(5, 45) }; Poly2Tri.TriangulationPoint[] hole = new Poly2Tri.TriangulationPoint[] { new Poly2Tri.TriangulationPoint(10, 10), new Poly2Tri.TriangulationPoint(40, 10), new Poly2Tri.TriangulationPoint(40, 40), new Poly2Tri.TriangulationPoint(10, 40) }; Poly2Tri.Polygon polygon = new Poly2Tri.Polygon(box); polygon.AddHole(new Poly2Tri.Polygon(hole)); Poly2Tri.P2T.Triangulate(polygon); painter.StrokeColor = Color.Black; DrawPoly2TriPolygon(painter, new List <Poly2Tri.Polygon>() { polygon }); }
static void CreateIndexedMesh(IList <Poly2Tri.DelaunayTriangle> listTriangles, List <Vector3> listVerticesOut, List <int> listIndicesOut, Matrix4x4 mtxTransform, bool bTransform) { listVerticesOut.Clear(); listIndicesOut.Clear(); Vector3 v3Vertex = Vector3.zero; foreach (Poly2Tri.DelaunayTriangle triangle in listTriangles) { for (int i = 0; i < 3; i++) { bool bFound = false; int nIndex = 0; Poly2Tri.TriangulationPoint point = triangle.PointCWFrom(triangle.Points[i]); v3Vertex.x = point.Xf; v3Vertex.z = point.Yf; foreach (Vector3 v3VertexIndexed in listVerticesOut) { if ((v3Vertex - v3VertexIndexed).magnitude < Parameters.EPSILONDISTANCEVERTEX) { bFound = true; break; } nIndex++; } if (bFound == false) { listIndicesOut.Add(listVerticesOut.Count); listVerticesOut.Add(v3Vertex); } else { listIndicesOut.Add(nIndex); } } } if (bTransform) { for (int i = 0; i < listVerticesOut.Count; i++) { listVerticesOut[i] = mtxTransform.MultiplyPoint3x4(listVerticesOut[i]); } } }
public static void dbugDrawPoly2TriPolygon(this Painter painter, List <Poly2Tri.Polygon> polygons) { foreach (Poly2Tri.Polygon polygon in polygons) { foreach (Poly2Tri.DelaunayTriangle tri in polygon.Triangles) { Poly2Tri.TriangulationPoint p0 = tri.P0; Poly2Tri.TriangulationPoint p1 = tri.P1; Poly2Tri.TriangulationPoint p2 = tri.P2; painter.DrawLine(p0.X, p0.Y, p1.X, p1.Y); painter.DrawLine(p1.X, p1.Y, p2.X, p2.Y); painter.DrawLine(p2.X, p2.Y, p0.X, p0.Y); } } }
/// <summary> /// create polygon from GlyphContour /// </summary> /// <param name="cnt"></param> /// <returns></returns> static Poly2Tri.Polygon CreatePolygon(List <Vertex> flattenPoints) { List <Poly2Tri.TriangulationPoint> points = new List <Poly2Tri.TriangulationPoint>(); //limitation: poly tri not accept duplicated points! *** double prevX = 0; double prevY = 0; #if DEBUG //dbug check if all point is unique dbugCheckAllGlyphsAreUnique(flattenPoints); #endif int j = flattenPoints.Count; //pass for (int i = 0; i < j; ++i) { Vertex p = flattenPoints[i]; double x = p.OX; //start from original X*** double y = p.OY; //start from original Y*** if (x == prevX && y == prevY) { if (i > 0) { throw new NotSupportedException(); } } else { var triPoint = new Poly2Tri.TriangulationPoint(prevX = x, prevY = y) { userData = p }; #if DEBUG p.dbugTriangulationPoint = triPoint; #endif points.Add(triPoint); } } return(new Poly2Tri.Polygon(points.ToArray())); }
void DrawSimpleRectExample(Painter painter) { Poly2Tri.TriangulationPoint[] points = new Poly2Tri.TriangulationPoint[] { new Poly2Tri.TriangulationPoint(10, 10), new Poly2Tri.TriangulationPoint(40, 10), new Poly2Tri.TriangulationPoint(40, 40), new Poly2Tri.TriangulationPoint(10, 40) }; Poly2Tri.Polygon polygon = new Poly2Tri.Polygon(points); Poly2Tri.P2T.Triangulate(polygon); painter.StrokeColor = Color.Black; DrawPoly2TriPolygon(painter, new List <Poly2Tri.Polygon>() { polygon }); }
void DrawVxsArrowHoleExample(Painter painter) { //1. background box Poly2Tri.TriangulationPoint[] box = new Poly2Tri.TriangulationPoint[] { new Poly2Tri.TriangulationPoint(5, 5), new Poly2Tri.TriangulationPoint(200, 5), new Poly2Tri.TriangulationPoint(200, 200), new Poly2Tri.TriangulationPoint(5, 200) }; Poly2Tri.Polygon bgBoxPolygon = new Poly2Tri.Polygon(box); //2. arrow-shape hole VertexStore vxs = BuildArrow(true); using (Poly2TriTool.Borrow(out var p23tool)) { p23tool.YAxisPointDown = true; //since our vxs is create from Y axis point down world List <Poly2Tri.Polygon> polygons = new List <Poly2Tri.Polygon>(); p23tool.PreparePolygons(vxs, polygons); foreach (Poly2Tri.Polygon polygon in polygons) { //arrow-shape hole bgBoxPolygon.AddHole(polygon); } Poly2Tri.P2T.Triangulate(bgBoxPolygon); painter.StrokeColor = Color.Black; DrawPoly2TriPolygon(painter, new List <Poly2Tri.Polygon>() { bgBoxPolygon }); } }
/// <summary> /// create polygon from GlyphContour /// </summary> /// <param name="cnt"></param> /// <returns></returns> static Poly2Tri.Polygon CreatePolygon(List <System.Drawing.PointF> flattenPoints) { List <Poly2Tri.TriangulationPoint> points = new List <Poly2Tri.TriangulationPoint>(); //limitation: poly tri not accept duplicated points! *** double prevX = 0; double prevY = 0; int j = flattenPoints.Count; //pass for (int i = 0; i < j; ++i) { System.Drawing.PointF p = flattenPoints[i]; double x = p.X; //start from original X*** double y = p.Y; //start from original Y*** if (x == prevX && y == prevY) { if (i > 0) { //skip duplicated point continue; } } else { var triPoint = new Poly2Tri.TriangulationPoint(prevX = x, prevY = y) { userData = p }; points.Add(triPoint); } } return(new Poly2Tri.Polygon(points.ToArray())); }
void DrawOutput() { if (_g == null) { return; } //----------- //for GDI+ only bool flipYAxis = chkFlipY.Checked; int viewHeight = this.panel1.Height; //----------- //show tess _g.Clear(Color.White); int[] contourEndIndices; float[] polygon1 = GetPolygonData(out contourEndIndices); if (polygon1 == null) { return; } // if (flipYAxis) { var transformMat = new System.Drawing.Drawing2D.Matrix(); transformMat.Scale(1, -1); transformMat.Translate(0, -viewHeight); polygon1 = TransformPoints(polygon1, transformMat); //when we flipY, meaning of clockwise-counter clockwise is changed. // //see https://stackoverflow.com/questions/1165647/how-to-determine-if-a-list-of-polygon-points-are-in-clockwise-order //...(comment) //...A minor caveat: this answer assumes a normal Cartesian coordinate system. //The reason that's worth mentioning is that some common contexts, like HTML5 canvas, use an inverted Y-axis. //Then the rule has to be flipped: if the area is negative, the curve is clockwise. – LarsH Oct 11 '13 at 20:49 } using (Pen pen1 = new Pen(Color.LightGray, 6)) { int nn = polygon1.Length; int a = 0; PointF p0; PointF p1; int contourCount = contourEndIndices.Length; int startAt = 3; for (int cnt_index = 0; cnt_index < contourCount; ++cnt_index) { int endAt = contourEndIndices[cnt_index]; for (int m = startAt; m <= endAt;) { p0 = new PointF(polygon1[m - 3], polygon1[m - 2]); p1 = new PointF(polygon1[m - 1], polygon1[m]); _g.DrawLine(pen1, p0, p1); _g.DrawString(a.ToString(), this.Font, Brushes.Black, p0); m += 2; a++; } //close contour p0 = new PointF(polygon1[endAt - 1], polygon1[endAt]); p1 = new PointF(polygon1[startAt - 3], polygon1[startAt - 2]); _g.DrawLine(pen1, p0, p1); _g.DrawString(a.ToString(), this.Font, Brushes.Black, p0); // startAt = (endAt + 1) + 3; } } //---------------------------------------------------------------------------- //tess if (rdoTessSGI.Checked) { //SGI Tess Lib if (!_tessTool.TessPolygon(polygon1, _contourEnds)) { return; } //1. List <ushort> indexList = _tessTool.TessIndexList; //2. List <TessVertex2d> tempVertexList = _tessTool.TempVertexList; //3. int vertexCount = indexList.Count; //----------------------------- int orgVertexCount = polygon1.Length / 2; float[] vtx = new float[vertexCount * 2];//*** int n = 0; for (int p = 0; p < vertexCount; ++p) { ushort index = indexList[p]; if (index >= orgVertexCount) { //extra coord (newly created) TessVertex2d extraVertex = tempVertexList[index - orgVertexCount]; vtx[n] = (float)extraVertex.x; vtx[n + 1] = (float)extraVertex.y; } else { //original corrd vtx[n] = (float)polygon1[index * 2]; vtx[n + 1] = (float)polygon1[(index * 2) + 1]; } n += 2; } //----------------------------- //draw tess result int j = vtx.Length; for (int i = 0; i < j;) { var p0 = new PointF(vtx[i], vtx[i + 1]); var p1 = new PointF(vtx[i + 2], vtx[i + 3]); var p2 = new PointF(vtx[i + 4], vtx[i + 5]); _g.DrawLine(Pens.Red, p0, p1); _g.DrawLine(Pens.Red, p1, p2); _g.DrawLine(Pens.Red, p2, p0); i += 6; } } else { List <Poly2Tri.Polygon> outputPolygons = new List <Poly2Tri.Polygon>(); Poly2TriExampleHelper.Triangulate(polygon1, contourEndIndices, flipYAxis, outputPolygons); foreach (Poly2Tri.Polygon polygon in outputPolygons) { foreach (Poly2Tri.DelaunayTriangle tri in polygon.Triangles) { Poly2Tri.TriangulationPoint p0 = tri.P0; Poly2Tri.TriangulationPoint p1 = tri.P1; Poly2Tri.TriangulationPoint p2 = tri.P2; _g.DrawLine(Pens.Red, (float)p0.X, (float)p0.Y, (float)p1.X, (float)p1.Y); _g.DrawLine(Pens.Red, (float)p1.X, (float)p1.Y, (float)p2.X, (float)p2.Y); _g.DrawLine(Pens.Red, (float)p2.X, (float)p2.Y, (float)p0.X, (float)p0.Y); } } } }
/// <summary> /// create polygon from flatten curve outline point /// </summary> /// <param name="cnt"></param> /// <returns></returns> static Poly2Tri.Polygon CreatePolygon2(GlyphContour cnt) { List <Poly2Tri.TriangulationPoint> points = new List <Poly2Tri.TriangulationPoint>(); List <GlyphPart> allParts = cnt.parts; //--------------------------------------- //merge all generated points //also remove duplicated point too! List <GlyphPoint2D> mergedPoints = new List <GlyphPoint2D>(); cnt.mergedPoints = mergedPoints; //--------------------------------------- { int tt = 0; int j = allParts.Count; for (int i = 0; i < j; ++i) { GlyphPart p = allParts[i]; List <GlyphPoint2D> fpoints = p.GetFlattenPoints(); if (tt == 0) { int n = fpoints.Count; for (int m = 0; m < n; ++m) { //GlyphPoint2D fp = fpoints[m]; mergedPoints.Add(fpoints[m]); //allPoints.Add((float)fp.x); //allPoints.Add((float)fp.y); } tt++; } else { //except first point int n = fpoints.Count; for (int m = 1; m < n; ++m) { //GlyphPoint2D fp = fpoints[m]; mergedPoints.Add(fpoints[m]); //allPoints.Add((float)fp.x); //allPoints.Add((float)fp.y); } } } } //--------------------------------------- { //check last (x,y) and first (x,y) int lim = mergedPoints.Count - 1; { if (mergedPoints[lim].IsEqualValues(mergedPoints[0])) { //remove last (x,y) mergedPoints.RemoveAt(lim); lim -= 1; } } //limitation: poly tri not accept duplicated points! double prevX = 0; double prevY = 0; Dictionary <TmpPoint, bool> tmpPoints = new Dictionary <TmpPoint, bool>(); lim = mergedPoints.Count; for (int i = 0; i < lim; ++i) { GlyphPoint2D p = mergedPoints[i]; double x = p.x; double y = p.y; if (x == prevX && y == prevY) { if (i > 0) { throw new NotSupportedException(); } } else { TmpPoint tmp_point = new TmpPoint(x, y); if (!tmpPoints.ContainsKey(tmp_point)) { //ensure no duplicated point tmpPoints.Add(tmp_point, true); var userTriangulationPoint = new Poly2Tri.TriangulationPoint(x, y) { userData = p }; p.triangulationPoint = userTriangulationPoint; points.Add(userTriangulationPoint); } else { throw new NotSupportedException(); } prevX = x; prevY = y; } } Poly2Tri.Polygon polygon = new Poly2Tri.Polygon(points.ToArray()); return(polygon); } }
void DrawOutput() { if (_g == null) { return; } //----------- //for GDI+ only bool drawInvert = chkInvert.Checked; int viewHeight = this.panel1.Height; //----------- //show tess _g.Clear(Color.White); int[] contourEndIndices; float[] polygon1 = GetPolygonData(out contourEndIndices); if (polygon1 == null) { return; } // if (drawInvert) { var transformMat = new System.Drawing.Drawing2D.Matrix(); transformMat.Scale(1, -1); transformMat.Translate(0, -viewHeight); // polygon1 = TransformPoints(polygon1, transformMat); } using (Pen pen1 = new Pen(Color.LightGray, 6)) { int nn = polygon1.Length; int a = 0; PointF p0; PointF p1; int contourCount = contourEndIndices.Length; int startAt = 3; for (int cnt_index = 0; cnt_index < contourCount; ++cnt_index) { int endAt = contourEndIndices[cnt_index]; for (int m = startAt; m <= endAt;) { p0 = new PointF(polygon1[m - 3], polygon1[m - 2]); p1 = new PointF(polygon1[m - 1], polygon1[m]); _g.DrawLine(pen1, p0, p1); _g.DrawString(a.ToString(), this.Font, Brushes.Black, p0); m += 2; a++; } //close contour p0 = new PointF(polygon1[endAt - 1], polygon1[endAt]); p1 = new PointF(polygon1[startAt - 3], polygon1[startAt - 2]); _g.DrawLine(pen1, p0, p1); _g.DrawString(a.ToString(), this.Font, Brushes.Black, p0); // startAt = (endAt + 1) + 3; } } //---------------------------------------------------------------------------- //tess if (rdoTessSGI.Checked) { //SGI Tess Lib if (!_tessTool.TessPolygon(polygon1, _contourEnds)) { return; } //1. List <ushort> indexList = _tessTool.TessIndexList; //2. List <TessVertex2d> tempVertexList = _tessTool.TempVertexList; //3. int vertexCount = indexList.Count; //----------------------------- int orgVertexCount = polygon1.Length / 2; float[] vtx = new float[vertexCount * 2];//*** int n = 0; for (int p = 0; p < vertexCount; ++p) { ushort index = indexList[p]; if (index >= orgVertexCount) { //extra coord (newly created) TessVertex2d extraVertex = tempVertexList[index - orgVertexCount]; vtx[n] = (float)extraVertex.x; vtx[n + 1] = (float)extraVertex.y; } else { //original corrd vtx[n] = (float)polygon1[index * 2]; vtx[n + 1] = (float)polygon1[(index * 2) + 1]; } n += 2; } //----------------------------- //draw tess result int j = vtx.Length; for (int i = 0; i < j;) { var p0 = new PointF(vtx[i], vtx[i + 1]); var p1 = new PointF(vtx[i + 2], vtx[i + 3]); var p2 = new PointF(vtx[i + 4], vtx[i + 5]); _g.DrawLine(Pens.Red, p0, p1); _g.DrawLine(Pens.Red, p1, p2); _g.DrawLine(Pens.Red, p2, p0); i += 6; } } else { Poly2Tri.Polygon mainPolygon = Poly2TriExampleHelper.Triangulate(polygon1, contourEndIndices); foreach (Poly2Tri.DelaunayTriangle tri in mainPolygon.Triangles) { Poly2Tri.TriangulationPoint p0 = tri.P0; Poly2Tri.TriangulationPoint p1 = tri.P1; Poly2Tri.TriangulationPoint p2 = tri.P2; _g.DrawLine(Pens.Red, (float)p0.X, (float)p0.Y, (float)p1.X, (float)p1.Y); _g.DrawLine(Pens.Red, (float)p1.X, (float)p1.Y, (float)p2.X, (float)p2.Y); _g.DrawLine(Pens.Red, (float)p2.X, (float)p2.Y, (float)p0.X, (float)p0.Y); } } }
private void PreparePolygons(IEnumerable <Poly2Tri.DelaunayTriangle> triangles) { this.PolygonEdges.Clear(); this.Polygons.Clear(); // For building edges we need a mapping of the original triangles to polygons Dictionary <Poly2Tri.DelaunayTriangle, Poly2Tri.Point2DList> triangleToPolygon = new Dictionary <Poly2Tri.DelaunayTriangle, Poly2Tri.Point2DList>(); Dictionary <Poly2Tri.Point2DList, Poly2Tri.DelaunayTriangle> polygonToTriangle = new Dictionary <Poly2Tri.Point2DList, Poly2Tri.DelaunayTriangle>(); // Initially, our polygons are simply the triangles in polygon form foreach (var triangle in triangles) { var polygonPoints = triangle.Points.Select(p => new Poly2Tri.Point2D(p.X, p.Y)).ToList(); Poly2Tri.Point2DList polygon = new Poly2Tri.Point2DList(polygonPoints); triangleToPolygon[triangle] = polygon; polygonToTriangle[polygon] = triangle; this.Polygons.Add(polygon); } // Build up the edge list foreach (var polygon in this.Polygons) { // Does this polygon have any neighbors? If so, that's how we make our edges. var triangle = polygonToTriangle[polygon]; // We can have up to 3 neighbors on each triangle for (int n = 0; n < 3; ++n) { var neighborTriangle = triangle.Neighbors[n]; if (neighborTriangle == null) { continue; } if (!triangleToPolygon.ContainsKey(neighborTriangle)) { continue; } var neighborPolygon = triangleToPolygon[neighborTriangle]; // If the neighbor polygon still has a triangle associated with it then we haven't added its edges yet // Otherwise, we have added her edges and we don't want to do so again if (!polygonToTriangle.ContainsKey(neighborPolygon)) { continue; } // Gather the points needed for the edge Poly2Tri.TriangulationPoint triPoint1 = triangle.Points[(n + 1) % 3]; Poly2Tri.TriangulationPoint triPoint2 = triangle.Points[(n + 2) % 3]; // Create an polygon edge SharedPolygonEdge edge = new SharedPolygonEdge(); edge.PolygonA = polygon; edge.PolygonB = neighborPolygon; edge.EdgePoint1 = new Poly2Tri.PolygonPoint(triPoint1.X, triPoint1.Y); edge.EdgePoint2 = new Poly2Tri.PolygonPoint(triPoint2.X, triPoint2.Y); this.PolygonEdges.Add(edge); } // Remove the polygon from the triangle mapping. We are done with it. polygonToTriangle.Remove(polygon); } }