【NetTopologySuite类库】C#生成带约束(线、面)的Delaunay三角网

介绍

API地址:https://nettopologysuite.github.io/NetTopologySuite/api/NetTopologySuite.Triangulate.ConformingDelaunayTriangulationBuilder.html#NetTopologySuite_Triangulate_ConformingDelaunayTriangulationBuilder_Constraints

约束为线

效果图

红色线为约束线。
在这里插入图片描述

示例代码

var r = new WKTReader();
var wkt = "polygon((0 0,0 6,3 6,3 5,5 5,5 3,2 3,2 2,5 2,5 1,6 1,6 0,2 0,2 -1,7 -1,7 -2,-1 -2,-1 -1,0 -1,0 0))";
var geo = r.Read(wkt);

var lineWkt = "linestring(4 4,3 0,5 -2)";
var line = r.Read(lineWkt);

var tri = new ConformingDelaunayTriangulationBuilder();
tri.Constraints = line;//添加约束线
tri.SetSites(geo);
var tris = tri.GetEdges(GeometryFactory.Default);

约束为面

效果图

在这里插入图片描述

示例代码

var r = new WKTReader();
var wkt = "polygon((0 0,0 6,3 6,3 5,5 5,5 3,2 3,2 2,5 2,5 1,6 1,6 0,2 0,2 -1,7 -1,7 -2,-1 -2,-1 -1,0 -1,0 0))";
var geo = r.Read(wkt);

var wkt2 = "polygon((4 4,3 0,5 -2,4 4))";
var geo2 = r.Read(wkt2);

var tri = new ConformingDelaunayTriangulationBuilder();
tri.Constraints = geo2;//添加约束面
tri.SetSites(geo);
var tris = tri.GetEdges(GeometryFactory.Default);

可以自行将位于约束面内的三角边删掉。

不带约束

为了对比明显,再放一张不带约束的三角网:
在这里插入图片描述

  • 9
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
实现特征线约束Delaunay三角剖分算法可以使用以下步骤: 1. 对于给定的点集和特征线集合,首先将它们转换为有向边集合,即每个点对应一个包含它的三角形,并将特征线转换为对应的边。 2. 对于每个三角形,计算它的外心和外接圆半径,判断该三角形是否为Delaunay三角形。如果不是,则对该三角形进行Delaunay翻转,即交换其共享边的两个三角形,使得它们变成Delaunay三角形。 3. 进行特征线约束处理。对于每个特征线,将其与包含它的三角形的外接圆进行相交判断。如果特征线与某个三角形的外接圆相交,则将该三角形进行Delaunay翻转,直到不存在任何一个三角形与特征线相交。 4. 最后,将剩余的三角形构成的Delaunay三角网格输出。 以下是Python代码示例: ```python import math def is_delaunay(tri): """ 判断三角形是否为Delaunay三角形 """ a, b, c = tri ax, ay = a bx, by = b cx, cy = c # 计算外心和外接圆半径 d = 2 * (ax*(by-cy) + bx*(cy-ay) + cx*(ay-by)) if d == 0: return True ux = ((ax**2 + ay**2) * (by-cy) + (bx**2 + by**2) * (cy-ay) + (cx**2 + cy**2) * (ay-by)) / d uy = ((ax**2 + ay**2) * (cx-bx) + (bx**2 + by**2) * (ax-cx) + (cx**2 + cy**2) * (bx-ax)) / d r = math.sqrt((ax-ux)**2 + (ay-uy)**2) # 判断外接圆是否包含其他点 for p in points: if p in tri: continue px, py = p if (px-ux)**2 + (py-uy)**2 < r**2: return False return True def flip(tri1, tri2): """ 进行Delaunay翻转 """ a, b, c = tri1 d, e, f = tri2 ab, ac, ba, bc, ca, cb = ((a, b), (a, c), (b, a), (b, c), (c, a), (c, b)) de, df, ed, ef, fd, fe = ((d, e), (d, f), (e, d), (e, f), (f, d), (f, e)) # 找到共享边 common_edge = None for edge1 in (ab, ac, ba, bc, ca, cb): if common_edge: break for edge2 in (de, df, ed, ef, fd, fe): if edge1 == edge2: common_edge = edge1 break if not common_edge: return # 进行翻转 tri1.remove(common_edge[0]) tri1.remove(common_edge[1]) tri2.remove(common_edge[0]) tri2.remove(common_edge[1]) tri1.extend([d, e, f]) tri2.extend([a, b, c]) def delaunay(points, edges=[]): """ 进行特征线约束Delaunay三角剖分 """ # 构建初始三角形 xmin = min(x for x, y in points) xmax = max(x for x, y in points) ymin = min(y for x, y in points) ymax = max(y for x, y in points) dx = max(xmax-xmin, ymax-ymin) cx = (xmin + xmax) / 2 cy = (ymin + ymax) / 2 a = (cx-2*dx, cy-dx) b = (cx, cy+2*dx) c = (cx+2*dx, cy-dx) tris = [[a, b, c]] # 添加特征线 for e in edges: if e[0] not in points or e[1] not in points: continue tris_to_flip = [] for tri in tris: if set(e) & set(tri): continue ax, ay = tri[0] bx, by = tri[1] cx, cy = tri[2] d = (bx-ax) * (cy-ay) - (by-ay) * (cx-ax) if d > 0: tri.reverse() if is_delaunay(tri + [e]): continue tris_to_flip.append(tri) while tris_to_flip: tri1 = tris_to_flip.pop() for tri2 in tris: if tri1 == tri2 or set(e) & set(tri2): continue if set(tri1) & set(tri2): flip(tri1, tri2) if not is_delaunay(tri1): tris_to_flip.append(tri1) if not is_delaunay(tri2): tris_to_flip.append(tri2) # 移除超出初始三角形的三角形 result = [] for tri in tris: if tri[0][0] < xmin or tri[0][0] > xmax or \ tri[0][1] < ymin or tri[0][1] > ymax or \ tri[1][0] < xmin or tri[1][0] > xmax or \ tri[1][1] < ymin or tri[1][1] > ymax or \ tri[2][0] < xmin or tri[2][0] > xmax or \ tri[2][1] < ymin or tri[2][1] > ymax: continue result.append(tri) return result ``` 其中,`points`表示点集,`edges`表示特征线集合。`is_delaunay`函数用于判断三角形是否为Delaunay三角形,`flip`函数用于进行Delaunay翻转,`delaunay`函数用于进行特征线约束Delaunay三角剖分。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值