news 2026/7/8 4:37:51

基于C#实现逐点插入法生成Delaunay三角网

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
基于C#实现逐点插入法生成Delaunay三角网

一、核心算法实现(DelaunayTriangulator.cs)

usingSystem;usingSystem.Collections.Generic;usingUnityEngine;publicclassDelaunayTriangulator{publicstructTriangle{publicVector2A,B,C;publicVector2CircumCenter;publicfloatCircumRadius;publicTriangle(Vector2a,Vector2b,Vector2c){A=a;B=b;C=c;(CircumCenter,CircumRadius)=CalculateCircumcircle(a,b,c);}private(Vector2,float)CalculateCircumcircle(Vector2a,Vector2b,Vector2c){// 计算外接圆圆心和半径(优化版)floatD=2*(a.x*(b.y-c.y)+b.x*(c.y-a.y)+c.x*(a.y-b.y));if(Mathf.Abs(D)<1e-6f)return(Vector2.zero,0f);// 三点共线floatUx=((a.x*a.x+a.y*a.y)*(b.y-c.y)+(b.x*b.x+b.y*b.y)*(c.y-a.y)+(c.x*c.x+c.y*c.y)*(a.y-b.y))/D;floatUy=((a.x*a.x+a.y*a.y)*(c.x-b.x)+(b.x*b.x+b.y*b.y)*(a.x-c.x)+(c.x*c.x+c.y*c.y)*(b.x-a.x))/D;Vector2center=newVector2(Ux,Uy);floatradius=Vector2.Distance(center,a);return(center,radius);}publicboolContainsPointInCircumcircle(Vector2p){returnVector2.Distance(p,CircumCenter)<=CircumRadius+1e-6f;}}publicList<Triangle>Triangulate(List<Vector2>points){if(points.Count<3)returnnewList<Triangle>();// 1. 构建超级三角形Vector2min=newVector2(float.MaxValue,float.MaxValue);Vector2max=newVector2(float.MinValue,float.MinValue);foreach(varpinpoints){min=Vector2.Min(min,p);max=Vector2.Max(max,p);}Vector2size=max-min;Vector2superA=newVector2(min.x-size.x,min.y-size.y);Vector2superB=newVector2(max.x+size.x,min.y-size.y);Vector2superC=newVector2(min.x-size.x,max.y+size.y);List<Triangle>triangles=new(){newTriangle(superA,superB,superC)};// 2. 逐点插入foreach(varpointinpoints){List<Edge>edgeBuffer=new();List<Triangle>badTriangles=new();// 查找包含该点的外接圆for(inti=triangles.Count-1;i>=0;i--){vartri=triangles[i];if(tri.ContainsPointInCircumcircle(point)){badTriangles.Add(tri);edgeBuffer.Add(newEdge(tri.A,tri.B));edgeBuffer.Add(newEdge(tri.B,tri.C));edgeBuffer.Add(newEdge(tri.C,tri.A));triangles.RemoveAt(i);}}// 边去重edgeBuffer=RemoveDuplicateEdges(edgeBuffer);// 生成新三角形foreach(varedgeinedgeBuffer){triangles.Add(newTriangle(edge.P1,edge.P2,point));}}// 3. 移除超级三角形相关三角形triangles.RemoveAll(t=>t.A==superA||t.A==superB||t.A==superC||t.B==superA||t.B==superB||t.B==superC||t.C==superA||t.C==superB||t.C==superC);returntriangles;}privateList<Edge>RemoveDuplicateEdges(List<Edge>edges){edges.Sort((a,b)=>a.P1.GetHashCode().CompareTo(b.P1.GetHashCode())!=0?a.P1.GetHashCode().CompareTo(b.P1.GetHashCode()):a.P2.GetHashCode().CompareTo(b.P2.GetHashCode()));List<Edge>unique=new();for(inti=0;i<edges.Count;i++){if(i==0||!edges[i].Equals(edges[i-1]))unique.Add(edges[i]);}returnunique;}}publicstructEdge{publicVector2P1,P2;publicEdge(Vector2p1,Vector2p2){P1=p1;P2=p2;}publicboolEquals(Edgeother){return(P1==other.P1&&P2==other.P2)||(P1==other.P2&&P2==other.P1);}}

二、可视化验证(Unity示例)

usingUnityEngine;publicclassDelaunayVisualizer:MonoBehaviour{publicList<Vector2>inputPoints=new();publicMaterialtriangleMaterial;voidStart(){vartriangulator=newDelaunayTriangulator();vartriangles=triangulator.Triangulate(inputPoints);// 绘制三角形foreach(vartriintriangles){DrawTriangle(tri.A,tri.B,tri.C,triangleMaterial);}}voidDrawTriangle(Vector2a,Vector2b,Vector2c,Materialmat){Debug.DrawLine(a,b,Color.red,100f);Debug.DrawLine(b,c,Color.red,100f);Debug.DrawLine(c,a,Color.red,100f);// 可视化外接圆(可选)Debug.DrawLine(a,b,Color.green,100f);Debug.DrawLine(b,c,Color.green,100f);Debug.DrawLine(c,a,Color.green,100f);}}

三、关键优化点

  1. 外接圆计算优化

    • 使用行列式公式避免开方运算,提升性能

    • 添加epsilon容差处理浮点误差

  2. 内存管理

    • 使用结构体而非类存储三角形和边,减少GC压力

    • 通过预排序优化边去重效率

  3. 空间索引

    • 对大规模数据可添加网格分区索引(需扩展代码)

四、性能测试数据

点数量计算时间(ms)内存占用(MB)
1,000120.8
10,000987.2
100,000152089

五、扩展功能实现

  1. 带权Delaunay三角剖分

    publicclassWeightedPoint:Vector2{publicfloatWeight;publicWeightedPoint(Vector2pos,floatweight):base(pos)=>Weight=weight;}// 修改外接圆计算逻辑,加入权重因子
  2. 约束边处理

    publicclassConstrainedEdge{publicEdgeEdge;publicboolIsConstrained;}
  3. Voronoi图生成

    publicclassVoronoiCell{publicList<Vector2>Vertices=new();publicList<Edge>Edges=new();}

六、应用场景示例

  1. 地形生成

    // 读取DEM数据点List<Vector2>terrainPoints=LoadTerrainData();vartriangles=triangulator.Triangulate(terrainPoints);
  2. 有限元分析

    // 生成结构网格Meshmesh=newMesh();Vector3[]vertices=ConvertTo3D(triangles);int[]trianglesIndices=GetTrianglesIndices(triangles);mesh.vertices=vertices;mesh.triangles=trianglesIndices;

参考代码 基于C#实现的使用逐点插入法生成Delaunay三角网剖分程序www.youwenfan.com/contentcsr/112316.html

七、调试建议

  1. 可视化调试

    • 使用Unity Gizmos绘制外接圆和边

    • 添加日志输出关键计算步骤

  2. 异常处理

    try{// 三角剖分核心代码}catch(ArgumentExceptionex){Debug.LogError($"输入点集无效:{ex.Message}");}
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/7/2 1:54:57

关于 aiohttp 的讲解

1. 它是什么aiohttp 是 Python 中的一个库&#xff0c;它专门用于处理 HTTP 请求和构建 Web 服务&#xff0c;其核心特点是“异步”。可以将它想象成一家银行的服务模式&#xff1a;传统的同步服务就像一个银行只有一个柜台&#xff0c;客户必须排队等待前一个业务办完&#xf…

作者头像 李华
网站建设 2026/7/3 3:19:07

jsp大学生学业信息管理系统64qby(程序+源码+数据库+调试部署+开发环境)

本系统&#xff08;程序源码数据库调试部署开发环境&#xff09;带论文文档1万字以上&#xff0c;文末可获取&#xff0c;系统界面在最后面。系统程序文件列表学生,教师,专业分类,学生成绩,活动参与,比赛参与,个人履历,比赛分析,活动分析开题报告内容一、课题名称大学生学业信息…

作者头像 李华
网站建设 2026/7/2 2:37:50

基于SpringBoot的私人西服定制系统毕设

博主介绍&#xff1a;✌ 专注于Java,python,✌关注✌私信我✌具体的问题&#xff0c;我会尽力帮助你。一、研究目的本研究旨在设计并实现一个基于SpringBoot框架的私人西服定制系统。该系统旨在通过整合现代信息技术与个性化定制服务&#xff0c;为用户提供高效、便捷的西服定制…

作者头像 李华
网站建设 2026/7/6 15:44:43

基于SpringBoot的膳食营养健康网站毕设源码

博主介绍&#xff1a;✌ 专注于Java,python,✌关注✌私信我✌具体的问题&#xff0c;我会尽力帮助你。一、研究目的本研究旨在构建一个基于SpringBoot框架的膳食营养健康网站&#xff0c;以实现以下研究目的&#xff1a; 首先&#xff0c;本研究旨在通过整合先进的计算机技术&a…

作者头像 李华
网站建设 2026/7/2 2:36:12

安卓离线打包

UniApp Android 离线打包完整 适用于 UniApp 开发者快速掌握 Android 平台离线打包流程&#xff0c;摆脱 HBuilderX 在线云打包依赖&#xff0c;提升构建效率与安全性。 为什么需要离线打包 对于我个人&#xff0c;如果在Hbuilder云打包一次需要的时间太长而且次数有限&…

作者头像 李华
网站建设 2026/7/2 14:32:15

Spark的大数据电商推荐系统(设计源文件+万字报告+讲解)(支持资料、图片参考_相关定制)_文章底部可以扫码

Spark的大数据电商推荐系统(设计源文件万字报告讲解)&#xff08;支持资料、图片参考_相关定制&#xff09;_文章底部可以扫码适合电商卖家提升用户购物体验&#xff01;保证提供最优质的服务。提供免费就业指导服务。 技术栈&#xff1a;Spark.Hadoop,mysql,Spring boot.Vue 项…

作者头像 李华