天气与日历 切换到窄版

 找回密码
 立即注册
中国膜结构网
十大进口膜材评选 十大国产膜材评选 十大膜结构设计评选 十大膜结构公司评选
查看: 61|回复: 0

C++实现Delaunay三角网生长算法

[复制链接]

该用户从未签到

主题

0

回帖

2912

积分

管理员

积分
2912
发表于 2024-6-22 09:46:18 | 显示全部楼层 |阅读模式
#include <iostream>
using namespace std;
#include <string>
#include <fstream>
#include <sstream>
#include <vector>
#include <list>

struct Pixel    //脚点数据
{
        double x, y, z;
        int Num;
        bool flag;
};
struct List //数据链表
{
        Pixel *pixel;
        List *next;
};
struct Line //三角形边
{
        Pixel *pixel1;  //三角形边一端点
        Pixel *pixel2;  //三角形边另一端点
        Pixel *pixel3;  //三角形边所对顶点
        bool flag;
};
struct Linelist //三角形边表
{
        Line *line;
        Linelist *next;
        Linelist() { line = new Line; }
};
struct Triangle //三角形表
{
        Line *line1;
        Line *line2;
        Line *line3;
        Triangle *next;
};

bool JudgeDis(Pixel* pt1, Pixel* pt2, Pixel *node) {//比较链表中node与pt2到pt1的距离
        return (pt1->x - node->x)*(pt1->x - node->x) + (pt1->y - node->y)*(pt1->y - node->y) < (pt1->x - pt2->x)*(pt1->x - pt2->x) + (pt1->y - pt2->y)*(pt1->y - pt2->y);
}

bool JudgePoint(Pixel* pt1, Pixel* pt2, Pixel* pt3, Pixel* node) {//比较链表中node pt3与pt1 pt2所成角的大小
        double dist11 = sqrt((pt1->x - node->x)*(pt1->x - node->x) + (pt1->y - node->y)*(pt1->y - node->y));
        double dist12 = sqrt((pt2->x - node->x)*(pt2->x - node->x) + (pt2->y - node->y)*(pt2->y - node->y));
        double dist12_3 = sqrt((pt1->x - pt2->x)*(pt1->x - pt2->x) + (pt1->y - pt2->y)*(pt1->y - pt2->y));
        double dist21 = sqrt((pt1->x - pt3->x)*(pt1->x - pt3->x) + (pt1->y - pt3->y)*(pt1->y - pt3->y));
        double dist22 = sqrt((pt3->x - pt2->x)*(pt3->x - pt2->x) + (pt3->y - pt2->y)*(pt3->y - pt2->y));
        return ((pow(dist11, 2) + pow(dist12, 2) - pow(dist12_3, 2)) / (2 * dist11*dist12) < (pow(dist21, 2) + pow(dist22, 2) - pow(dist12_3, 2)) / (2 * dist21*dist22)); //余弦判断角度
}

bool JudgeSameSide(double x1,double x2,double y1,double y2,double x3,double y3,Pixel* pixeltmp) {//判断该结点是否与该边所属三角形另一结点同侧
        //return ((pt2->y - pt1->y)*pixeltmp->x + (pt1->x - pt2->x)*pixeltmp->y + (pt2->x*pt1->y - pt1->x * pt2->y))*((pt2->y - pt1->y)*pt3->x + (pt1->x - pt2->x)*pt3->y + (pt2->x*pt1->y - pt1->x * pt2->y)) >= 0;
        return         ((y2 - y1)*pixeltmp->x + (x1 - x2)*pixeltmp -> y + (x2*y1 - x1 * y2))        *((y2 - y1)*x3 + (x1 - x2)*y3 + (x2*y1 - x1 * y2)) >= 0;
}

bool isInLineList(Pixel* pt1, Pixel* pt2,Line* linetemp) {//判断边pt1 pt2是否与linetemp相同
        return (pt1 == linetemp->pixel1 && pt2 == linetemp->pixel2) || (pt2 == linetemp->pixel1 && pt1 == linetemp->pixel2);
}

void BuildLine(Pixel* pt1,Pixel* pt2,Pixel* pt3, Linelist* &linenode) {//将当前边加入linenode边链表中
        linenode->line->pixel1 = pt1;
        linenode->line->pixel2 = pt2;
        linenode->line->pixel3 = pt3;
        linenode->line->flag = false;
        linenode->next = NULL;
}

void AddLine(Linelist* &linelast, Linelist* linenode) {//边链表中添加边
        linelast->next = linenode;
        linelast = linenode;
}

void getPoint3(List* &node, Pixel* &pt3, Pixel* pt1, Pixel* pt2) {//根据已知pt1 pt2 从node链表中寻找最佳pt3
        pt3 = NULL;
        while (node != NULL)
        {
                if (node->pixel == pt1 || node->pixel == pt2)
                {
                        node = node->next;
                        continue;
                }

                if (pt3 == NULL)
                {
                        pt3 = node->pixel;
                }
                else
                {
                        //比较当前结点pixel与pt3谁更合适--选取夹角最大的点
                        if (JudgePoint(pt1, pt2, pt3, node->pixel))
                                pt3 = node->pixel;
                }
                node = node->next;
        }
}

void setLineFlag(Linelist* &linetemp,Pixel* &pt1,Pixel* &pt2,Pixel* &pt3,Line* &ln,Linelist* &linelast,bool& flag)
{//遍历linetemp所有边,将pt1 pt3所在边ln的flag置为true,并更新三角网中的边链表linelast
        while (linetemp != NULL)
        {
                if (isInLineList(pt1, pt3, linetemp->line)) {
                        linetemp->line->flag = true;
                        flag = true;
                        ln = linetemp->line;//初始化三角形边ln2
                        break;
                }
                linetemp = linetemp->next;
        }
        if (!flag)//该边不在三角网的边链表中
        {

                Linelist* linenode = new Linelist();

                linenode->line->pixel1 = pt3;
                linenode->line->pixel2 = pt1;
                linenode->line->pixel3 = pt2;
                linenode->line->flag = false;
                linenode->next = NULL;

                //更新三角网的边链表
                linelast->next = linenode;
                linelast = linenode;

                ln = linenode->line;//初始化三角形边ln2

        }
}

void BuildFirstTri(const List* list,Triangle* &tglnode,Linelist* &linehead, Linelist* &linelast,Line* &ln1, Line* &ln2, Line* &ln3,Pixel* &pt1, Pixel* &pt2, Pixel* &pt3)
{
        pt1 = list->pixel;//数据链中的首点
        //找离pt1最近点pt2
        pt2 = list->next->pixel;//数据链表中的第二点

        List* node;
        node = list->next->next;
        while (node != NULL)
        {
                if (JudgeDis(pt1, pt2, node->pixel))
                        pt2 = node->pixel;
                node = node->next;
        }

        //找第三个点
        //重新初始化node为链表第一点的next
        node = list->next;
        getPoint3(node, pt3, pt1, pt2);

        //根据三点构建三角形
        Linelist* linenode;
        //构建边ln1
        linenode = new Linelist();
        BuildLine(pt1, pt2, pt3, linenode);
        ln1 = linenode->line;

        //设置边链表的头尾指针
        linehead = linelast = linenode;

        //构建边ln2
        linenode = new Linelist();
        BuildLine(pt2, pt3, pt1, linenode);
        ln2 = linenode->line;
        //设置边链表的尾指针
        AddLine(linelast, linenode);

        //构建边ln3
        linenode = new Linelist();
        BuildLine(pt3, pt1, pt2, linenode);
        ln3 = linenode->line;
        //设置边链表的尾指针
        AddLine(linelast, linenode);

        //first Triangle

        //构建三角形
        tglnode = new Triangle;
        tglnode->line1 = ln1;
        tglnode->line2 = ln2;
        tglnode->line3 = ln3;
        tglnode->next = NULL;
}

void BuildTIN(List* &list,Linelist* &linehead, Linelist* &linelast,Line* &ln1, Line* &ln2, Line* &ln3,Pixel* &pt1, Pixel* &pt2, Pixel* &pt3,bool &flag, Triangle* &tglnode, Triangle* &tgllast)
{
        Linelist *linetmp, *linetemp;
        List *pixeltmp;
        double x1, y1, x2, y2, x3, y3;
        linetmp = linehead;//三角网边链表的头指针
        while (linetmp != NULL)
        {
                if (linetmp->line->flag == true)//该边已经在三角网中
                {
                        linetmp = linetmp->next;
                        continue;
                }
                //获取当前边、当前边的结点pt1 pt2 及该边所属三角形中的第三个点(x3,y3)
                ln1 = linetmp->line;//初始化三角形边pt1 pt2 --ln1

                pt1 = linetmp->line->pixel1;
                pt2 = linetmp->line->pixel2;
                //当前三角形的三个结点坐标
                x1 = linetmp->line->pixel1->x;
                y1 = linetmp->line->pixel1->y;
                x2 = linetmp->line->pixel2->x;
                y2 = linetmp->line->pixel2->y;
                x3 = linetmp->line->pixel3->x;
                y3 = linetmp->line->pixel3->y;

                pixeltmp = list;//获取结点链表头指针
                //寻找下一结点pt3
                //getPoint3(pixeltmp, pt3, pt1, pt2);//有新增条件,不可复用
                pt3 = NULL;

                while (pixeltmp != NULL)
                {
                        if (pixeltmp->pixel == pt1 || pixeltmp->pixel == pt2)
                        {
                                pixeltmp = pixeltmp->next;
                                continue;
                        }
                        //判断该结点是否与该边所属三角形另一结点同侧--新增条件
                        if (JudgeSameSide(x1, x2, y1, y2, x3, y3, pixeltmp->pixel))
                        {
                                pixeltmp = pixeltmp->next;
                                continue;
                        }

                        //为pt3赋值
                        if (pt3 == NULL)pt3 = pixeltmp->pixel;
                        else//遍历所有结点,寻找最佳pt3
                        {
                                if (JudgePoint(pt1, pt2, pt3, pixeltmp->pixel))
                                        pt3 = pixeltmp->pixel;
                        }
                        pixeltmp = pixeltmp->next;
                }

                //初始化三角形边ln2
                if (pt3 != NULL)
                {
                        linetemp = linehead;
                        flag = false;
                        //遍历所有边,将pt1 pt3所在边ln2 flag置为true
                        setLineFlag(linetemp, pt1, pt2, pt3, ln2, linelast, flag);


                        //初始化三角形边ln3
                        linetemp = linehead;
                        flag = false;
                        //遍历所有边,将pt2 pt3所在边ln3 flag置为true
                        setLineFlag(linetemp, pt2, pt1, pt3, ln3,linelast, flag);

                        //构建三角形
                        tglnode = new Triangle;
                        tglnode->line1 = ln1;
                        tglnode->line2 = ln2;
                        tglnode->line3 = ln3;
                        tglnode->next = NULL;
                        //更新三角形链表
                        tgllast->next = tglnode;
                        tgllast = tglnode;
                }
                //当前边的flag置为true(遍历构建三角网完成)
                linetmp->line->flag = true;
                linetmp = linetmp->next;
        }
}

//以下是程序中关于建网的部分:
//功能:   用给定的数据链表数据,组建Delaunay不规则三角网
//输入参数:数据链表list;
//输出参数:不规则三角网首三角形地址

Triangle* CreateDelaunayTIN(List *list)
{
        //组建第一个三角形
       
        //List *node;
        Pixel *pt1, *pt2, *pt3;//三角形三个顶点
        bool flag;
        Line *ln1, *ln2, *ln3;//三角形的三条边
        Linelist *linehead, *linelast;// *linenode ;//三角网的边链表
        Triangle *tglhead, *tglnode, *tgllast;//三角网的三角形链表

        BuildFirstTri(list,tglnode,linehead,linelast,ln1,ln2,ln3,pt1,pt2,pt3);

        //第一个三角形构建完毕!更新三角形链表
        tglhead = tgllast = tglnode;

        BuildTIN(list,linehead,linelast,ln1,ln2,ln3,pt1,pt2,pt3,flag,tglnode,tgllast);
       
        Triangle *TIN;
        //创建三角网
        TIN = tglhead;

        return TIN;
}

void printList(List* list) {
        cout << "List:\n";
        while (list != NULL) {
                cout << list->pixel->Num << ": " << list->pixel->x << "," << list->pixel->y << endl;
                list = list->next;
        }
}

int main()
{
    //此处已删除读入点集数据文件
    //pts信息:vector<MyPoint>
    //MyPoint数据结构如下
    //ptNum:点的序号 x:点的投影坐标X y:点的投影坐标Y z:点的高程Z
        List *ListHead, *ListNode, *ListLast;
        ListHead = ListNode =ListLast=NULL;
        for (int i = 0; i < pts.size(); i++) {
                Pixel* p = new Pixel();
                p->x = pts.at(i).x;
                p->y = pts.at(i).y;
                p->z = pts.at(i).z;
                p->Num = pts.at(i).ptNum;
                List* Node = new List();
                Node->pixel = p;
                Node->next = NULL;
                if (i == 0) {
                        ListHead = Node;
                        ListNode = ListHead;
                }
                else {
                        ListNode->next = Node;
                        ListNode = ListNode->next;
                        ListLast = ListNode;
                }
               
        }

        printList(ListHead);
        Triangle* tri = new Triangle();

        tri=CreateDelaunayTIN(ListHead);
        int i = 0;
        while (tri != NULL) {
                cout << i << ": " << " e1:  p1: " << tri->line1->pixel1->Num << " p2: " << tri->line1->pixel2->Num << " e2:  p1: " << tri->line2->pixel1->Num << " p2: " << tri->line2->pixel2->Num
                        << " e3:  p1: " << tri->line3->pixel1->Num << " p2: " << tri->line3->pixel2->Num <<"\t"<< endl;
                tri = tri->next;
                i++;
        }

        return 0;
}

 

 

 

 

C++实现Delaunay三角网生长算法
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|Archiver|中国膜结构网|中国膜结构协会|进口膜材|国产膜材|ETFE|PVDF|PTFE|设计|施工|安装|车棚|看台|污水池|中国膜结构网_中国空间膜结构协会

GMT+8, 2024-11-1 10:32 , Processed in 0.135761 second(s), 26 queries .

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表