简单多边形的三角剖分
Contents
[
Hide
]
使用 Aspose.3D for .NET API,开发人员可以对简单多边形进行三角测量。任何多边形都可以划分为三角形。三角形的所有操作和计算可以分段应用于多边形。
三角化多边形
开发人员可以从多边形区域中选取顶点,然后通过调用 PolygonModifier
类的 Triangulate
方法来形成三角形,每个三角形的形式为V{1},V{i-1},V{i},索引i从3到n。演示应用程序 (名称: Triangulate) 下 Triangulate/PolygonCanvas.cs
文件中的 Vertex
和 PolygonCanvas
类演示了使用 Aspose.3D API 对多边形进行三角剖分的方法。
我们准备了一个演示项目。请参阅 这个网址。
三角测量的编程示例
此代码示例从多边形区域中拾取顶点,然后应用算法创建三角形。您可以从 这里 下载此示例的完整工作项目。
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// For complete examples and data files, please go to https://github.com/aspose-3d/Aspose.3D-for-.NET | |
public class Vertex | |
{ | |
[Browsable(false)] | |
public int Index { get; set; } | |
public double X { get; set; } | |
public double Y { get; set; } | |
public Vertex(int index, double x, double y) | |
{ | |
Index = index; | |
X = x; | |
Y = y; | |
} | |
public override string ToString() | |
{ | |
return string.Format("#{0}: {1} {2}", Index, X, Y); | |
} | |
} | |
class PolygonCanvas : Control | |
{ | |
public List<Vertex> points = new List<Vertex>(); | |
public event EventHandler TriangleUpdated; | |
private Point mousePos; | |
private Pen virtualLine = new Pen(Color.DarkSeaGreen); | |
private Vector4[][] triangles; | |
private int[][] triangleIndices; | |
private Pen polygonPen = Pens.Black; | |
private Brush[] brushes = new Brush[] {Brushes.Blue, Brushes.BlueViolet, Brushes.DarkCyan, Brushes.ForestGreen, Brushes.LimeGreen}; | |
private Brush textBrush = Brushes.Black; | |
public PolygonCanvas() | |
{ | |
SetStyle(ControlStyles.ResizeRedraw, true); | |
SetStyle(ControlStyles.UserPaint, true); | |
SetStyle(ControlStyles.Selectable, true); | |
SetStyle(ControlStyles.OptimizedDoubleBuffer, true); | |
SetStyle(ControlStyles.AllPaintingInWmPaint , true); | |
Cursor = Cursors.Cross; | |
virtualLine.DashStyle = DashStyle.Dash; | |
virtualLine.DashPattern = new float[] {10, 10}; | |
} | |
protected override void OnPaint(PaintEventArgs e) | |
{ | |
base.OnPaint(e); | |
Graphics g = e.Graphics; | |
g.Clear(Color.AliceBlue); | |
if (points.Count == 0) | |
return; | |
Size size = this.Size; | |
if (points.Count == 1) | |
{ | |
// Draw virtual line | |
PointF pt = ToPoint(points[0], size); | |
g.DrawLine(virtualLine, mousePos, pt); | |
} | |
else if (points.Count == 2) | |
{ | |
// Draw virtual triangle | |
PointF pt1 = ToPoint(points[0], size); | |
PointF pt2 = ToPoint(points[1], size); | |
g.DrawLine(polygonPen, pt2, pt1); | |
g.DrawLine(virtualLine, mousePos, pt1); | |
g.DrawLine(virtualLine, mousePos, pt2); | |
} | |
else | |
{ | |
// Draw polygon and virtual line | |
// Draw triangles | |
if (triangles != null) | |
{ | |
for (int i = 0; i < triangles.Length; i++) | |
{ | |
PointF[] tri = ToPoints(triangles[i]); | |
// Shrink the triangle so we can see each triangle | |
float inv = 1.0f/3.0f; | |
float cx= (tri[0].X + tri[1].X + tri[2].X) * inv; | |
float cy= (tri[0].Y + tri[1].Y + tri[2].Y) * inv; | |
Shrink(tri, 0, cx, cy); | |
Shrink(tri, 1, cx, cy); | |
Shrink(tri, 2, cx, cy); | |
Brush brush = brushes[i%brushes.Length]; | |
g.FillPolygon(brush, tri); | |
// Draw triangle index | |
string text = string.Format("{0}/{1}/{2}", triangleIndices[i][0], triangleIndices[i][1], triangleIndices[i][2]); | |
g.DrawString(text, Font, textBrush, cx, cy); | |
} | |
} | |
// Draw index of each vertex | |
PointF[] polygon = ToPoints(this.points); | |
g.DrawPolygon(polygonPen, polygon); | |
for (int i = 0; i < polygon.Length; i++) | |
{ | |
string text = string.Format("{0}", i); | |
g.DrawString(text, Font, textBrush, polygon[i]); | |
} | |
g.DrawLine(virtualLine, mousePos, polygon[0]); | |
g.DrawLine(virtualLine, mousePos, polygon[polygon.Length - 1]); | |
} | |
} | |
private void Shrink(PointF[] tri, int i, float cx, float cy) | |
{ | |
float dx = tri[i].X - cx; | |
float dy = tri[i].Y - cy; | |
float inv = 5.0f/(float) Math.Sqrt(dx*dx + dy*dy); | |
dx *= inv; | |
dy *= inv; | |
tri[i] = new PointF(tri[i].X - dx, tri[i].Y - dy); | |
} | |
private PointF[] ToPoints(IList<Vector4> vec) | |
{ | |
Size size = Size; | |
PointF[] ret = new PointF[vec.Count]; | |
for(int i = 0; i < ret.Length; i++) | |
ret[i] = new PointF((float)vec[i].x * size.Width, (float)vec[i].y * Height); | |
return ret; | |
} | |
private PointF[] ToPoints(IList<Vertex> vec) | |
{ | |
Size size = Size; | |
PointF[] ret = new PointF[vec.Count]; | |
for(int i = 0; i < ret.Length; i++) | |
ret[i] = ToPoint(vec[i], size); | |
return ret; | |
} | |
private PointF ToPoint(Vertex vec, Size size) | |
{ | |
return new PointF((float)vec.X * size.Width, (float)vec.Y * Height); | |
} | |
protected override void OnMouseMove(MouseEventArgs e) | |
{ | |
base.OnMouseMove(e); | |
mousePos = e.Location; | |
Invalidate(); | |
} | |
protected override void OnMouseUp(MouseEventArgs e) | |
{ | |
base.OnMouseUp(e); | |
if (e.Button == MouseButtons.Left) | |
{ | |
Vertex pt = new Vertex(points.Count, e.X*1.0/Width, e.Y*1.0/Height); | |
points.Add(pt); | |
UpdateTriangles(); | |
} | |
else | |
{ | |
// Erase last point | |
if (points.Count > 0) | |
{ | |
points.RemoveAt(points.Count - 1); | |
UpdateTriangles(); | |
} | |
} | |
} | |
public void UpdateTriangles() | |
{ | |
DoTriangulate(); | |
Invalidate(); | |
if(TriangleUpdated != null) | |
TriangleUpdated(this, new EventArgs()); | |
} | |
/// <summary> | |
/// Triangulate the polygon into a lot of triangles | |
/// </summary> | |
private void DoTriangulate() | |
{ | |
triangles = null; | |
if (points.Count <= 3) | |
return; | |
// Convert to Vector4[] | |
Vector4[] controlPoints = new Vector4[points.Count]; | |
for (int i = 0; i < points.Count; i++) | |
{ | |
controlPoints[i] = new Vector4(points[i].X, points[i].Y, 0); | |
} | |
// Triangulate the polygon | |
triangleIndices = PolygonModifier.Triangulate(controlPoints); | |
// Save triangle vertex for later drawing. | |
triangles = new Vector4[triangleIndices.Length][]; | |
for (int i = 0; i < triangleIndices.Length; i++) | |
{ | |
int[] triangleFace = triangleIndices[i]; | |
Vector4[] triangle = triangles[i] = new Vector4[3]; | |
triangle[0] = controlPoints[triangleFace[0]]; | |
triangle[1] = controlPoints[triangleFace[1]]; | |
triangle[2] = controlPoints[triangleFace[2]]; | |
} | |
} | |
} |