生成三角网算法java,一种低效但逻辑简单清晰的Delaunay三角网生成算法
由离散样本点生成Delaunay三角网有多种算法,每个算法的执行效率都不一样,这里介绍一种最简单,最低效,但是算法逻辑最清晰的一种。
Delaunay三角网必须满足的一个条件是任何一个三角形的外接圆都不能包含其他任何一个样本点,因此,本算法通过枚举所有可能的三角形,再经过其外接圆不包含任何其他样本点的判断,如果满足,则记录该三角形,直到所有三角形枚举完毕。
效果图:
本算法用C++实现,核心代码如下:
const double EP = 0.00000001;
// 点结构
typedef struct PT{
double x;
double y;
}PT;
//线结构
typedef struct SEGMENT
{
PT* ptStart;
PT* ptEnd;
}SEGMENT;
//三角形类
class TRIANGLE
{
public:
TRIANGLE(PT* pt1, PT* pt2, PT* pt3)
{
//确保三个点x坐标升序排序
PT* temp;
if(pt1->x > pt2->x){temp = pt1; pt1 = pt2; pt2 = temp;}
if(pt3->x < pt1->x && pt3->x )
{
temp = pt3; pt3 = pt1; pt1 = temp;
if(pt3->x < pt2->x){temp=pt3;pt3=pt2;pt2=temp;}
}
if(pt3->x < pt2->x){temp=pt3;pt3=pt2;pt2=temp;}
_ptFirst = pt1;
_ptSecond = pt2;
_ptThird = pt3;
InitData();
}
PT* GetFirstPt(){return _ptFirst;}
PT* GetSecondPt(){return _ptSecond;}
PT* GetThirdPt(){return _ptThird;}
SEGMENT GetSegment1(){SEGMENT seg = {_ptFirst,_ptSecond};return seg;}
SEGMENT GetSegment2(){SEGMENT seg = {_ptFirst,_ptThird};return seg;}
SEGMENT GetSegment3(){SEGMENT seg = {_ptSecond,_ptThird};return seg;}
BOOL IsTriangleSame(TRIANGLE& tri)
{
if(tri.GetFirstPt() == _ptFirst &&
tri.GetSecondPt() == _ptSecond &&
tri.GetThirdPt() == _ptThird)
return TRUE;
return FALSE;
}
BOOL IsPtInCircle(PT* pt)
{
double offsetx = pt->x - _ptCenter.x;
double offsety = pt->y - _ptCenter.y;
if(sqrt(offsetx*offsetx + offsety*offsety) <= _Radius)
return TRUE;
return FALSE;
}
protected:
// 获取三角形外接圆中心点及半径
void InitData()
{
double x0 = _ptFirst->x;
double y0 = _ptFirst->y;
double x1 = _ptSecond->x;
double y1 = _ptSecond->y;
double x2 = _ptThird->x;
double y2 = _ptThird->y;
double y10 = y1 - y0;
double y21 = y2 - y1;
bool b21zero = y21 > -REAL_EPSILON && y21 < REAL_EPSILON;
if (y10 > -REAL_EPSILON && y10 < REAL_EPSILON)
{
if (b21zero)
{
if (x1 > x0)
{
if (x2 > x1) x1 = x2;
}
else
{
if (x2 < x0) x0 = x2;
}
_ptCenter.x = (x0 + x1) * .5F;
_ptCenter.y = y0;
}
else
{
double m1 = - (x2 - x1) / y21;
double mx1 = (x1 + x2) * .5F;
double my1 = (y1 + y2) * .5F;
_ptCenter.x = (x0 + x1) * .5F;
_ptCenter.y = m1 * (_ptCenter.x - mx1) + my1;
}
}
else if (b21zero)
{
double m0 = - (x1 - x0) / y10;
double mx0 = (x0 + x1) * .5F;
double my0 = (y0 + y1) * .5F;
_ptCenter.x = (x1 + x2) * .5F;
_ptCenter.y = m0 * (_ptCenter.x - mx0) + my0;
}
else
{
double m0 = - (x1 - x0) / y10;
double m1 = - (x2 - x1) / y21;
double mx0 = (x0 + x1) * .5F;
double my0 = (y0 + y1) * .5F;
double mx1 = (x1 + x2) * .5F;
double my1 = (y1 + y2) * .5F;
_ptCenter.x = (m0 * mx0 - m1 * mx1 + my1 - my0) / (m0 - m1);
_ptCenter.y = m0 * (_ptCenter.x - mx0) + my0;
}
double dx = x0 - _ptCenter.x;
double dy = y0 - _ptCenter.y;
_Radius2 = dx * dx + dy * dy; // the radius of the circumcircle, squared
_Radius = (double) sqrt(_Radius2); // the proper radius
_Radius2 *= 1.000001f;
}
private:
PT* _ptFirst;
PT* _ptSecond;
PT* _ptThird;
PT _ptCenter;
double _Radius2;
double _Radius;
};
class CMyDelaunay
{
public:
// 通过样本点集,生成三角形集,由vecTriangleWork输出
void BuildDelaunayEx(vector& vecPT, vector& vecTriangleWork);
BOOL IsPtsBuildTriangle(PT* pt1, PT* pt2, PT* pt3);
public:
CMyDelaunay();
virtual ~CMyDelaunay();
};
//判断三个点能否组成一个三角形
BOOL CMyDelaunay::IsPtsBuildTriangle(PT* pt1, PT* pt2, PT* pt3)
{
double offset_x1 = pt2->x - pt1->x;
double offset_x2 = pt3->x - pt2->x;
double offset_y1 = pt2->y - pt1->y;
double offset_y2 = pt3->y - pt2->y;
if((fabs(offset_x1) < EP) && (fabs(offset_x2) < EP)) //竖直
{
return FALSE;
}
if(fabs(offset_x1) > EP && fabs(offset_x2) > EP)
{
if(fabs(offset_y1/offset_x1 - offset_y2/offset_x2) < EP)
return FALSE;
}
return TRUE;
}
void CMyDelaunay::BuildDelaunayEx(vector& vecPT, vector& vecTriangleWork)
{
int nSize = vecPT.size();
if(nSize < 3)
return;
for(int i = 0; i < nSize - 2; ++i)
{
for(int j = i + 1; j < nSize - 1; ++j)
{
for(int k = j + 1; k < nSize; ++k)
{
PT* pt1 = &vecPT[i];
PT* pt2 = &vecPT[j];
PT* pt3 = &vecPT[k];
BOOL bFind = TRUE;
for(int m = 0; m < nSize; ++m)
{
PT* pt = &vecPT[m];
if(pt != pt1 && pt != pt2 && pt != pt3 && IsPtsBuildTriangle(pt1, pt2, pt3))
{
TRIANGLE tri(pt1, pt2, pt3);
if(tri.IsPtInCircle(pt))
{
bFind = FALSE;
break;
}
}
}
if(bFind)
{
vecTriangleWork.push_back(tri);
}
}
}
}
}
生成三角网算法java,一种低效但逻辑简单清晰的Delaunay三角网生成算法相关推荐
- 什么是陀螺仪的dr算法_一种基于DR/GPS/MM的组合定位系统数据融合算法
摘 要: 针对盲区中使用INS惯性导航系统进行定位存在误差积累的问题,提出一种基于DR航位推算.GPS全球定位系统和MM地图匹配的组合定位系统数据融合算法.该算法利用GPS和MM中得到的位置信息,一方 ...
- doa估计算法 matlab,一种未知信源数的DOA估计-music和capon算法仿真实验!
具体参考<一种未知信源数的高分辨DOA估计算法 >-[张涛麟 刘 颖 廖桂生 ],我是完全按照这篇文献做的,但是最后仿真出来的效果图根本就没有文献那么理想,请大神们指教 ...
- skew算法_一种基于FPGA的多通道高速输入信号自动de‑skew算法的制作方法
本发明涉及高速数据采集技术,更具体的涉及一种基于FPGA的多通道高速输入信号自动de-skew算法. 背景技术: 随着对精度和速率要求越来越高,目前数据采集系统向着多通道和超高速两个方向发展.多通道高 ...
- 隐藏浏览器滚动条但内容可以滚动的3种解决方式(简单清晰)
第一种:使用纯css样式属性隐藏滚动条 :火狐浏览器的css写法不兼容 <!DOCTYPE html> <html lang="en"> <head ...
- 低版本的Hadoop实现 Apriori 算法Java代码
Apriori 关联规则挖掘的一种算法,其逻辑简单,网上有很多关于算法逻辑的介绍,在此不再赘述.使用hadoop实现Apriori算法的核心在于,循环计算,在Map过程对候选项进行识别,Combine ...
- 结合二叉树和Graham扫描技术的高效Delaunay三角网构建算法
结合二叉树和Graham扫描技术的高效Delaunay三角网构建算法 摘 要:为了提高不规则三角网的构建速度,提出了一种高效构建Delaunay三角网算法.首先对平面上的离散点集按一定的阈值进行分块 ...
- java贝叶斯_贝叶斯算法Java实现
前言:朴素贝叶斯分类算法是一种基于贝叶斯定理的简单概率分类算法.贝叶斯分类的基础是概率推理,就是在各种条件的存在不确定,仅知其出现概率的情况下,如何完成推理和决策任务.概率推理是与确定性推理相对应的. ...
- Dijkstra 单源最短路径算法 Java实现
Dijkstra 单源最短路径算法 Java实现 算法导入 算法核心 复杂度分析 时间复杂度 空间复杂度 代码实现 参考资料 结尾 算法导入 在图论中,求最短路径有一个经典的算法 Dijkstra算法 ...
- 数据结构与算法Java(二)——字符串、矩阵压缩、递归、动态规划
不定期补充.修正.更新:欢迎大家讨论和指正 本文以数据结构(C语言版)第三版 李云清 杨庆红编著为主要参考资料,用Java来实现 数据结构与算法Java(一)--线性表 数据结构与算法Java(二)- ...
最新文章
- Keywords Search AC自动机QAQ
- C++ 落选,2021 年最想学习的五大编程语言
- Aim Controller:所有游戏都支持的PSVR
- 最大后验概率估计算法
- 2020美国计算机研究生学校排名,2020 US.news 美国研究生院排名出炉,美中国际独家解析!...
- 异常:Caused by: java.lang.ClassNotFoundException: com.mysql.jdbc.Driver
- 风控五大模型、三大风险指的是什么--几大模型PD、LGD、评分模型都有哪些细节点
- ubuntu 上 nvidia-smi 没显示所有的GPU
- [转载]Qlist的用法
- 第二季-专题5-核心初始化
- Python 手写数字识别实战分享
- ERP原理与应用期末复习
- JSchException: Algorithm negotiation fail
- 如何快速翻译医学类英文专业文献?
- 洛谷P2386放苹果
- WPS制作的电子签名有法律效力吗
- The following error occured:
- 手机端html跑马灯效果,jQuery实现适用于移动端的跑马灯抽奖特效示例
- 2023最新SSM计算机毕业设计选题大全(附源码+LW)之java自助旅游平台v294n
- 智慧能源三大应用场景
热门文章
- 想要高清壁纸,高图桌面壁纸网站值得收藏!
- 设计灵感|26个字母的花样插画解读方式
- 手机展示海报PSD模板、适用众多设计!
- Adobe Illustrator的教程:如何建立扁平化设计角色动画
- 全网唯一C++调用由com组件生成的dll教程
- TLB的作用及工作原理,如何查看TLB miss?
- ANSI C: union
- linux 双网卡 debian,Linux服务器双网卡双IP和单网卡双IP配置方法(Debian/Ubuntu)
- es用python增加字段_使用Python在ElasticSearch中添加@timestamp字段
- sudo修改文件夹名字_【转载】MAC系统修改帐号短名和个人文件夹名称