剧情提要:
最初的时候是原始时期战争,所谓原始时期,指的是约公元前30世纪—前22世纪。
公元前27世纪,没有发生什么有记录的战争。
正剧开始:
星历2016年07月18日 11:40:04, 银河系厄尔斯星球中华帝国江南行省。
这图纸其实设计得还很详细,只是没有说明书,确实有点难为神农他老人家。
[机器小伟]一阵忙活,生成了一张说明书:
阿伟照样先理出了制造工艺流程:
好了,程序不应该那么大,阿伟告诉神农,大的东西是不可靠的。
最初的时候是原始时期战争,所谓原始时期,指的是约公元前30世纪—前22世纪。
公元前27世纪,没有发生什么有记录的战争。
正剧开始:
星历2016年07月18日 11:40:04, 银河系厄尔斯星球中华帝国江南行省。
[工程师阿伟]正在和[机器小伟]一起研究[星球战争 BC2699 至 BC2600(公元前27世纪)]。
神农氏来找阿伟闲聊,谈到他准备去攻打河北,那里有一个部落不服他。那个部落叫什么名字,
他没有说。可能名字神马的不是很重要吧。
然后神农氏叹了口气说,路途遥远,要想去那里必须要有车,我费了很多心思,花了高价,
才从黑市上买到两张车辆的制造图纸。对方还不附说明书,意思是让阿伟帮他参详一下。
阿伟点头同意,于是神农掏出了第一张图纸:
<span style="font-size:18px;">///D:/360极速浏览器下载/Bowyer_Watson/Bowyer_Watson/BowyerWatson.cpp
#include "Point.h"
#include "Line.h"
#include "Triangle.h"
#include "BowyerWatson.h"
CBowyerWatson* CBowyerWatson::m_pBowyerWatson = NULL;
CBowyerWatson::CBowyerWatson()
{
ClearBowyerWatson();
}
CBowyerWatson::~CBowyerWatson()
{
ClearBowyerWatson();
}
CBowyerWatson* CBowyerWatson::GetInstance()
{
if( !m_pBowyerWatson )
m_pBowyerWatson = new CBowyerWatson;
return m_pBowyerWatson;
}
void CBowyerWatson::ClearBowyerWatson()
{
m_bUpdateDrawFlag = false;
std::list<CPoint*>::iterator iter_point = m_lstBowyerWatsonPointList.begin();
while (iter_point != m_lstBowyerWatsonPointList.end())
{
std::list<CPoint*>::iterator iter_pointNext = iter_point;
iter_pointNext++;
SAFE_DELETE(*iter_point);
m_lstBowyerWatsonPointList.erase(iter_point);
iter_point = iter_pointNext;
}//Point
std::list<CLine*>::iterator iter_line = m_lstBowyerWatsonLineList.begin();
while (iter_line != m_lstBowyerWatsonLineList.end())
{
std::list<CLine*>::iterator iter_lineNext = iter_line;
iter_lineNext++;
SAFE_DELETE(*iter_line);
m_lstBowyerWatsonLineList.erase(iter_line);
iter_line = iter_lineNext;
}//line
std::list<CTriangle*>::iterator iter_triangle = m_lstBowyerWatsonTriangleList.begin();
while (iter_triangle != m_lstBowyerWatsonTriangleList.end())
{
std::list<CTriangle*>::iterator iter_triangleNext = iter_triangle;
iter_triangleNext++;
SAFE_DELETE(*iter_triangle);
m_lstBowyerWatsonTriangleList.erase(iter_triangle);
iter_triangle = iter_triangleNext;
}//Triangle
iter_point = m_lstAddPointList.begin();
while (iter_point != m_lstAddPointList.end())
{
std::list<CPoint*>::iterator iter_pointNext = iter_point;
iter_pointNext++;
SAFE_DELETE(*iter_point);
m_lstAddPointList.erase(iter_point);
iter_point = iter_pointNext;
}//Point
}
void CBowyerWatson::CreateHelperPoint(CPoint pt1, CPoint pt2, CPoint pt3, CPoint pt4)
{
mHelperPoints[0] = pt1;
mHelperPoints[1] = pt2;
mHelperPoints[2] = pt3;
mHelperPoints[3] = pt4;
//加入辅助点4个
AddBowyerWatsonPoint(pt1);
AddBowyerWatsonPoint(pt2);
AddBowyerWatsonPoint(pt3);
AddBowyerWatsonPoint(pt4);
//加入辅助窗体的5条边
CLine line1 = CLine(pt1,pt2);
CLine line2 = CLine(pt2,pt3);
CLine line3 = CLine(pt3,pt4);
CLine line4 = CLine(pt4,pt1);
CLine line5 = CLine(pt2,pt4);
AddBowyerWatsonLine(line1);
AddBowyerWatsonLine(line2);
AddBowyerWatsonLine(line3);
AddBowyerWatsonLine(line4);
AddBowyerWatsonLine(line5);
//加入辅助三角形2个
CTriangle tg1 = CTriangle(pt1,pt2,pt4);
CTriangle tg2 = CTriangle(pt2,pt3,pt4);
AddBowyerWatsonTriangle(tg1);
AddBowyerWatsonTriangle(tg2);
}
void CBowyerWatson::AddNewPoint(CPoint pt)
{
bool existflag = false;
std::list<CPoint*>::iterator iter_point = m_lstAddPointList.begin();
for ( ;iter_point != m_lstAddPointList.end();iter_point++)
{
if (pt == (**iter_point))
{
existflag = true;
}
}
if (!existflag)
{
CPoint* newPoint = new CPoint(pt.x,pt.y);
m_lstAddPointList.push_back(newPoint);
}
}
void CBowyerWatson::UpdateNewPoint()
{
std::list<CPoint*>::iterator iter_point = m_lstAddPointList.begin();
while (iter_point != m_lstAddPointList.end())
{
ProcessNewPoint(**iter_point);
std::list<CPoint*>::iterator iter_pointNext = iter_point;
iter_pointNext++;
SAFE_DELETE(*iter_point);
m_lstAddPointList.erase(iter_point);
iter_point = iter_pointNext;
}//Point
//剔除辅助边
std::list<CLine*>::iterator iter = m_lstBowyerWatsonLineList.begin();
while(iter != m_lstBowyerWatsonLineList.end())
{
CLine line = (**iter);
if (line.CheckPointExist(mHelperPoints[0]) || line.CheckPointExist(mHelperPoints[1]) || \
line.CheckPointExist(mHelperPoints[2]) || line.CheckPointExist(mHelperPoints[3]))
{
std::list<CLine*>::iterator iter_next = iter;
iter_next++;
SAFE_DELETE(*iter);
m_lstBowyerWatsonLineList.erase(iter);
iter = iter_next;
}
else{
iter++;
}
}
//剔除辅助三角形
std::list<CTriangle*>::iterator iter_triangle = m_lstBowyerWatsonTriangleList.begin();
while(iter_triangle != m_lstBowyerWatsonTriangleList.end())
{
CTriangle triangle = (**iter_triangle);
if (triangle.CheckPointExist(mHelperPoints[0]) || triangle.CheckPointExist(mHelperPoints[1]) || \
triangle.CheckPointExist(mHelperPoints[2]) || triangle.CheckPointExist(mHelperPoints[3]))
{
std::list<CTriangle*>::iterator iter_nextTriangle = iter_triangle;
iter_nextTriangle++;
SAFE_DELETE(*iter_triangle);
m_lstBowyerWatsonTriangleList.erase(iter_triangle);
iter_triangle = iter_nextTriangle;
}
else{
iter_triangle++;
}
}
}
void CBowyerWatson::AddBowyerWatsonPoint(CPoint pt)
{
bool existflag = false;
std::list<CPoint*>::iterator iter_point = m_lstBowyerWatsonPointList.begin();
for ( ;iter_point != m_lstBowyerWatsonPointList.end();iter_point++)
{
if (pt == (**iter_point))
{
existflag = true;
}
}
if (!existflag)
{
CPoint* newPoint = new CPoint(pt.x,pt.y);
m_lstBowyerWatsonPointList.push_back(newPoint);
}
}
void CBowyerWatson::AddBowyerWatsonLine(CLine line)
{
bool existflag = false;
std::list<CLine*>::iterator iter_line = m_lstBowyerWatsonLineList.begin();
for ( ;iter_line != m_lstBowyerWatsonLineList.end();iter_line++)
{
if (line == (**iter_line))
{
existflag = true;
}
}
if (!existflag)
{
CLine* newLine = new CLine(line.p1,line.p2);
m_lstBowyerWatsonLineList.push_back(newLine);
}
}
void CBowyerWatson::DelBowyerWatsonLine(CLine line)
{
std::list<CLine*>::iterator iter_line = m_lstBowyerWatsonLineList.begin();
while (iter_line != m_lstBowyerWatsonLineList.end())
{
if (line == (**iter_line))
{
SAFE_DELETE(*iter_line);
m_lstBowyerWatsonLineList.erase(iter_line);
break;
}
else
iter_line++;
}//line
std::list<CTriangle*>::iterator iter_Triangle = m_lstBowyerWatsonTriangleList.begin();
while (iter_Triangle != m_lstBowyerWatsonTriangleList.end())
{
if ((*iter_Triangle)->l1 == line || (*iter_Triangle)->l2 == line || (*iter_Triangle)->l3 == line )
{
SAFE_DELETE(*iter_Triangle);
m_lstBowyerWatsonTriangleList.erase(iter_Triangle);
break;
}
else
iter_Triangle++;
}//Triangle
}
void CBowyerWatson::AddBowyerWatsonTriangle(CTriangle triangle)
{
bool existflag = false;
std::list<CTriangle*>::iterator iter_Triangle = m_lstBowyerWatsonTriangleList.begin();
for ( ;iter_Triangle != m_lstBowyerWatsonTriangleList.end();iter_Triangle++)
{
if (triangle == (**iter_Triangle))
{
existflag = true;
}
}
if (!existflag)
{
CTriangle* newTriangle = new CTriangle(triangle.p1,triangle.p2,triangle.p3);
m_lstBowyerWatsonTriangleList.push_back(newTriangle);
}
}
void CBowyerWatson::DelBowyerWatsonTriangle(CTriangle triangle)
{
std::list<CTriangle*>::iterator iter_Triangle = m_lstBowyerWatsonTriangleList.begin();
while (iter_Triangle != m_lstBowyerWatsonTriangleList.end())
{
if (triangle == (**iter_Triangle))
{
SAFE_DELETE(*iter_Triangle);
m_lstBowyerWatsonTriangleList.erase(iter_Triangle);
return;
}
else
iter_Triangle++;
}//line
}
void CBowyerWatson::ProcessNewPoint(CPoint pt)
{
std::list<CLine*> lineList ;
std::list<CTriangle*> triangleList;
std::vector<CTriangle*> commonTriangleVector;
std::list<CLine*>::iterator iter_line = m_lstBowyerWatsonLineList.begin();
for(;iter_line != m_lstBowyerWatsonLineList.end();iter_line++)
{
CLine* newline = new CLine();
memcpy(newline, *iter_line, sizeof(CLine));
lineList.push_back(newline);
}
std::list<CTriangle*>::iterator iter_triangle = m_lstBowyerWatsonTriangleList.begin();
for(;iter_triangle != m_lstBowyerWatsonTriangleList.end();iter_triangle++)
{
CTriangle* newtriangle = new CTriangle();
memcpy(newtriangle, *iter_triangle, sizeof(CTriangle));
triangleList.push_back(newtriangle);
}
iter_triangle = triangleList.begin();
while (iter_triangle != triangleList.end())
{
//是否存在三角形外接圆内
if ((*iter_triangle)->CheckInCircle(pt))
{
commonTriangleVector.push_back(*iter_triangle);
}
iter_triangle++;
}// triangle
if (commonTriangleVector.size() == 1)
{
std::vector<CTriangle*>::iterator iter_v = commonTriangleVector.begin();
//删除三角形
DelBowyerWatsonTriangle(**iter_v);
/
//连接三角形三点
CLine line1 = CLine(pt,(*iter_v)->p1);
CLine line2 = CLine(pt,(*iter_v)->p2);
CLine line3 = CLine(pt,(*iter_v)->p3);
AddBowyerWatsonLine(line1);
AddBowyerWatsonLine(line2);
AddBowyerWatsonLine(line3);
//加入新三角形
if (CheckTriangleLinesExist(pt, (*iter_v)->p1, (*iter_v)->p2))
{
CTriangle tg1 = CTriangle(pt,(*iter_v)->p1,(*iter_v)->p2);
AddBowyerWatsonTriangle(tg1);
}
if (CheckTriangleLinesExist(pt, (*iter_v)->p2, (*iter_v)->p3))
{
CTriangle tg2 = CTriangle(pt,(*iter_v)->p2,(*iter_v)->p3);
AddBowyerWatsonTriangle(tg2);
}
if (CheckTriangleLinesExist(pt, (*iter_v)->p3, (*iter_v)->p1))
{
CTriangle tg3 = CTriangle(pt,(*iter_v)->p3,(*iter_v)->p1);
AddBowyerWatsonTriangle(tg3);
}
}
if (commonTriangleVector.size() > 1)
{
for (int i = 0;i < (commonTriangleVector.size()-1);i++)
{
for (int j = i+1;j <commonTriangleVector.size();j++)
{
CTriangle* trg1 = *(commonTriangleVector.begin() + i);
CTriangle* trg2 = *(commonTriangleVector.begin() +j);
CLine* commonLine = trg1->FindCommonLine(*trg2);
if (commonLine != NULL)
{
//删除影响三角形
DelBowyerWatsonTriangle(*trg1);
DelBowyerWatsonTriangle(*trg2);
//删除公共边
DelBowyerWatsonLine(*commonLine);
/
//连接三角形三点
CLine line1_1 = CLine(pt,trg1->p1);
CLine line1_2 = CLine(pt,trg1->p2);
CLine line1_3 = CLine(pt,trg1->p3);
CLine line2_1 = CLine(pt,trg2->p1);
CLine line2_2 = CLine(pt,trg2->p2);
CLine line2_3 = CLine(pt,trg2->p3);
AddBowyerWatsonLine(line1_1);
AddBowyerWatsonLine(line1_2);
AddBowyerWatsonLine(line1_3);
AddBowyerWatsonLine(line2_1);
AddBowyerWatsonLine(line2_2);
AddBowyerWatsonLine(line2_3);
//加入新三角形
if (CheckTriangleLinesExist(pt, trg1->p1, trg1->p2))
{
CTriangle tg1 = CTriangle(pt, trg1->p1, trg1->p2);
AddBowyerWatsonTriangle(tg1);
}
if (CheckTriangleLinesExist(pt, trg1->p2, trg1->p3))
{
CTriangle tg2 = CTriangle(pt,trg1->p2,trg1->p3);
AddBowyerWatsonTriangle(tg2);
}
if (CheckTriangleLinesExist(pt, trg1->p3, trg1->p1))
{
CTriangle tg3 = CTriangle(pt, trg1->p3, trg1->p1);
AddBowyerWatsonTriangle(tg3);
}
if (CheckTriangleLinesExist(pt, trg2->p1, trg2->p2))
{
CTriangle tg1 = CTriangle(pt, trg2->p1, trg2->p2);
AddBowyerWatsonTriangle(tg1);
}
if (CheckTriangleLinesExist(pt, trg2->p2, trg2->p3))
{
CTriangle tg2 = CTriangle(pt,trg2->p2,trg2->p3);
AddBowyerWatsonTriangle(tg2);
}
if (CheckTriangleLinesExist(pt, trg2->p3, trg2->p1))
{
CTriangle tg3 = CTriangle(pt, trg2->p3, trg2->p1);
AddBowyerWatsonTriangle(tg3);
}
}
}
}
}
AddBowyerWatsonPoint(pt);
iter_line = lineList.begin();
while (iter_line != lineList.end())
{
std::list<CLine*>::iterator iter_lineNext = iter_line;
iter_lineNext++;
SAFE_DELETE(*iter_line);
lineList.erase(iter_line);
iter_line = iter_lineNext;
}//line
iter_triangle = triangleList.begin();
while (iter_triangle != triangleList.end())
{
std::list<CTriangle*>::iterator iter_triangleNext = iter_triangle;
iter_triangleNext++;
SAFE_DELETE(*iter_triangle);
triangleList.erase(iter_triangle);
iter_triangle = iter_triangleNext;
}//Triangle
}
bool CBowyerWatson::CheckTriangleLinesExist(CPoint pt1, CPoint pt2, CPoint pt3)
{
bool exist_line1 = false;
bool exist_line2 = false;
bool exist_line3 = false;
CLine line1 = CLine(pt1, pt2);
CLine line2 = CLine(pt2, pt3);
CLine line3 = CLine(pt3, pt1);
std::list<CLine*>::iterator iter_line = m_lstBowyerWatsonLineList.begin();
for ( ;iter_line != m_lstBowyerWatsonLineList.end();iter_line++)
{
if (line1 == (**iter_line))
{
exist_line1 = true;
continue;
}
if (line2 == (**iter_line))
{
exist_line2 = true;
continue;
}
if (line3 == (**iter_line))
{
exist_line3 = true;
}
}
if (exist_line1 && exist_line2 && exist_line3)
{
return true;
}
return false;
}
void CBowyerWatson::DrawMesh()
{
std::list<CLine*>::iterator iter = m_lstBowyerWatsonLineList.begin();
for ( ;iter != m_lstBowyerWatsonLineList.end();iter++)
{
//(*iter)->p1.x, (*iter)->p1.y
//(*iter)->p2.x, (*iter)->p2.y
}
}
void CBowyerWatson::Update()
{
if (m_bUpdateDrawFlag)
{
DrawMesh();
}
}
///D:/360极速浏览器下载/Bowyer_Watson/Bowyer_Watson/BowyerWatson.h
#ifndef __CBOWYER_WATSON_H__
#define __CBOWYER_WATSON_H__
#include <list>
#include <vector>
class CPoint;
class CLine;
class CTriangle;
class CBowyerWatson{
public:
CBowyerWatson();
~CBowyerWatson();
static CBowyerWatson* GetInstance();
void ClearBowyerWatson();
void CreateHelperPoint(CPoint pt1, CPoint pt2, CPoint pt3, CPoint pt4);
void AddNewPoint(CPoint pt);
void UpdateNewPoint();
void AddBowyerWatsonPoint(CPoint pt);
void AddBowyerWatsonLine(CLine line);
void DelBowyerWatsonLine(CLine line);
void AddBowyerWatsonTriangle(CTriangle triangle);
void DelBowyerWatsonTriangle(CTriangle triangle);
void ProcessNewPoint(CPoint pt);
bool CheckTriangleLinesExist(CPoint pt1, CPoint pt2, CPoint pt3);
void DrawMesh();
void SetUpdateDrawFlag(bool flag){m_bUpdateDrawFlag = flag;};
void Update();
const std::list<CLine*>& GetBowyerWatsonLines(){return m_lstBowyerWatsonLineList;};
const std::list<CTriangle*>& GetBowyerWatsonTriangles(){return m_lstBowyerWatsonTriangleList;};
private:
std::list<CPoint*> m_lstBowyerWatsonPointList;
std::list<CLine*> m_lstBowyerWatsonLineList;
std::list<CTriangle*> m_lstBowyerWatsonTriangleList;
std::list<CPoint*> m_lstAddPointList;
CPoint mHelperPoints[4];
static CBowyerWatson* m_pBowyerWatson;
bool m_bUpdateDrawFlag;
};
#endif
///D:/360极速浏览器下载/Bowyer_Watson/Bowyer_Watson/Line.cpp
#include "Line.h"
#include "Point.h"
float CLine::Point2LineDistance(CPoint pt)
{
float a = p2.y - p1.y;
float b = p1.x - p2.x;
float c = p2.x*p1.y - p1.x*p2.y;
float dis = fabs(a*pt.x + b*pt.y + c)/sqrt(a*a + b*b);
return dis;
}
bool CLine::operator ==(const CLine& l)
{
if (l.p1.x == p1.x && l.p1.y == p1.y &&l.p2.x == p2.x && l.p2.y == p2.y)
{
return true;
}
if (l.p2.x == p1.x && l.p2.y == p1.y &&l.p1.x == p2.x && l.p1.y == p2.y)
{
return true;
}
return false;
}
CLine& CLine::operator =(const CLine& l)
{
p1 = l.p1;
p2 = l.p2;
return *this;
}
///D:/360极速浏览器下载/Bowyer_Watson/Bowyer_Watson/Line.h
#ifndef __CLINEH__
#define __CLINEH__
#include "Point.h"
class CLine{
public:
CPoint p1;
CPoint p2;
CLine()
{
};
CLine(CPoint pt1, CPoint pt2)
{
p1.x = pt1.x;
p1.y = pt1.y;
p2.x = pt2.x;
p2.y = pt2.y;
};
bool CheckPointExist(CPoint pt)
{
if (pt == p1 || pt == p2)
{
return true;
}
return false;
};
float Point2LineDistance(CPoint pt);
bool operator ==(const CLine& l);
CLine& operator =(const CLine& l);
};
#endif
///D:/360极速浏览器下载/Bowyer_Watson/Bowyer_Watson/Main.cpp 原版
#include<iostream>
#include <map>
#include "Line.h"
#include "Point.h"
#include "Triangle.h"
#include "BowyerWatson.h"
using namespace std;
void main()
{
cout<<"********************* Bowyer_Watson_algorithm ****************** "<<endl;
cout<<"********************* 本程序目标为实现Bowyer_Watson算法 ******************"<<endl;
cout<<"********************* 如有遇到BUG请联系作者 ******************"<<endl;
cout<<"********************* email: zzzzyu@sina.com ******************"<<endl;
cout<<"********************* Blog: blog.csdn.net/zzzzyu ******************"<<endl;
cout<<endl<<endl;
CBowyerWatson::GetInstance()->ClearBowyerWatson();
CBowyerWatson::GetInstance()->CreateHelperPoint(CPoint(0,0),CPoint(0,100),CPoint(100,100),CPoint(100,0));
CBowyerWatson::GetInstance()->AddNewPoint(CPoint(25,25));
CBowyerWatson::GetInstance()->AddNewPoint(CPoint(35,50));
CBowyerWatson::GetInstance()->AddNewPoint(CPoint(40,48));
CBowyerWatson::GetInstance()->AddNewPoint(CPoint(50,25));
CBowyerWatson::GetInstance()->AddNewPoint(CPoint(50,40));
CBowyerWatson::GetInstance()->UpdateNewPoint();
const std::list<CLine*> lineList = CBowyerWatson::GetInstance()->GetBowyerWatsonLines();
std::list<CLine*>::const_iterator ite_line = lineList.begin();
for ( ;ite_line != lineList.end();ite_line++)
{
cout<<"line : ("<<(*ite_line)->p1.x<<" "<<(*ite_line)->p1.y<<") " \
<<"("<<(*ite_line)->p2.x<<" "<<(*ite_line)->p2.y<<")"<<endl;
}
cout<<endl<<endl;
const std::list<CTriangle*> triangleList = CBowyerWatson::GetInstance()->GetBowyerWatsonTriangles();
std::list<CTriangle*>::const_iterator iter_triangle = triangleList.begin();
for ( ;iter_triangle != triangleList.end();iter_triangle++)
{
cout<<"Triangle : ("<<(*iter_triangle)->p1.x<<" "<<(*iter_triangle)->p1.y<<") " \
<<(*iter_triangle)->p2.x<<" "<<(*iter_triangle)->p2.y<<") " \
<<"("<<(*iter_triangle)->p3.x<<" "<<(*iter_triangle)->p3.y<<")"<<endl;
}
cout<<"Lines count : "<<lineList.size()<<endl;
cout<<"Triangles count : "<<triangleList.size()<<endl;
int ci;
cin>>ci;
return;
}
///D:/360极速浏览器下载/Bowyer_Watson/Bowyer_Watson/Main.cpp 改良后
#include <cstdlib>
#include <iostream>
#include <cstring>
#include <string>
#include <fstream>
#include <map>
#include "Line.h"
#include "Point.h"
#include "Triangle.h"
#include "BowyerWatson.h"
using namespace std;
void GetPoint(double &xx,double &yy,double &zz,string line)//从字符串line中解析出点的x,y,z坐标
{
int flag=0;
string tmp="";
char *cstr;
/*这段似乎不能分析^num1, num2, num3$这种格式的输入
for (int i=(int)line.find(',')+1;i<(int)line.size();i++)
{
if (line[i]==',')
{
cstr=new char[tmp.size()+1];
strcpy(cstr,tmp.c_str());
if (flag==0) {xx=atof(cstr);tmp.resize(0);flag++;}
else if (flag==1) {yy=atof(cstr);tmp.resize(0);flag++;}
continue;
}
tmp=tmp+line[i];
} */
int xPos = 0, yPos = 0, zPos = 0; //记录逗号分隔符位置
xPos = line.find(',');
tmp = line.substr(0, xPos);
cstr=new char[tmp.size()+1];
strcpy(cstr,tmp.c_str());
xx=atof(cstr);
tmp.resize(0);
cstr = NULL;
yPos = line.find(',', xPos+1);
tmp = line.substr(xPos+1, (yPos-xPos-1));
cstr=new char[tmp.size()+1];
strcpy(cstr,tmp.c_str());
yy=atof(cstr);
tmp.resize(0);
cstr = NULL;
if (fabs(xx)<1.0e-6) xx=0.0;
if (fabs(yy)<1.0e-6) yy=0.0;
if (fabs(zz)<1.0e-6) zz=0.0;
}
void main()
{
cout<<"********************* Bowyer_Watson_algorithm ****************** "<<endl;
cout<<"********************* 本程序目标为实现Bowyer_Watson算法 ******************"<<endl;
cout<<"********************* 如有遇到BUG请联系作者 ******************"<<endl;
cout<<"********************* email: zzzzyu@sina.com ******************"<<endl;
cout<<"********************* Blog: blog.csdn.net/zzzzyu ******************"<<endl;
cout<<endl<<endl;
CBowyerWatson::GetInstance()->ClearBowyerWatson();
CBowyerWatson::GetInstance()->CreateHelperPoint(CPoint(0,0),CPoint(1000,0),CPoint(1000,1000),CPoint(0, 1000));
//从文件中读取点
ifstream infile("input.txt");//打开"input.txt"文件
if (!infile)//判断文件是否正常打开
{
cout<<"Unable to input nodes!";
exit(1);
}
string line;
double xx,yy,zz;
int nodeSize;
cout<<"读取边界点:"<<endl;
for (int i=0;i<4;i++)//读入4外边框点
{
getline(infile,line);
GetPoint(xx,yy,zz,line);
cout<<"["<<xx<<", "<<yy<<"], "<<endl;
}
getline(infile,line);//读入节点数,用于后面循环
char *cstr;
cstr=new char[line.size()+1];
strcpy(cstr,line.c_str());
nodeSize=atoi(cstr);
cout<<"读取顶点数量:"<<nodeSize<<endl;
cout<<"读取顶点:"<<endl;
for (int i=0;i<nodeSize;i++)//读入每个节点的坐标
{
getline(infile,line);
GetPoint(xx,yy,zz,line);
cout<<"["<<xx<<", "<<yy<<"],";
CBowyerWatson::GetInstance()->AddNewPoint(CPoint(xx,yy));
}
infile.close();
/*
CBowyerWatson::GetInstance()->AddNewPoint(CPoint(25,25));
CBowyerWatson::GetInstance()->AddNewPoint(CPoint(35,50));
CBowyerWatson::GetInstance()->AddNewPoint(CPoint(40,48));
CBowyerWatson::GetInstance()->AddNewPoint(CPoint(50,25));
CBowyerWatson::GetInstance()->AddNewPoint(CPoint(50,40));
*/
CBowyerWatson::GetInstance()->UpdateNewPoint();
const std::list<CLine*> lineList = CBowyerWatson::GetInstance()->GetBowyerWatsonLines();
std::list<CLine*>::const_iterator ite_line = lineList.begin();
cout<<endl<<"line :"<<endl;
for ( ;ite_line != lineList.end();ite_line++)
{
cout<<"[["<<(*ite_line)->p1.x<<", "<<(*ite_line)->p1.y<<"], " \
<<"["<<(*ite_line)->p2.x<<", "<<(*ite_line)->p2.y<<"]], "<<endl;
}
cout<<endl<<endl;
const std::list<CTriangle*> triangleList = CBowyerWatson::GetInstance()->GetBowyerWatsonTriangles();
std::list<CTriangle*>::const_iterator iter_triangle = triangleList.begin();
cout<<"Triangle :"<<endl;
for ( ;iter_triangle != triangleList.end();iter_triangle++)
{
cout<<"[["<<(*iter_triangle)->p1.x<<", "<<(*iter_triangle)->p1.y<<"], " \
<<"["<<(*iter_triangle)->p2.x<<", "<<(*iter_triangle)->p2.y<<"], " \
<<"["<<(*iter_triangle)->p3.x<<", "<<(*iter_triangle)->p3.y<<"]],"<<endl;
}
cout<<"Lines count : "<<lineList.size()<<endl;
cout<<"Triangles count : "<<triangleList.size()<<endl;
int ci;
cout<<"输入任意数结束程序!"<<endl;
cin>>ci;
return;
}
///D:/360极速浏览器下载/Bowyer_Watson/Bowyer_Watson/Point.cpp
#include "Point.h"
bool CPoint::operator ==(const CPoint& p)
{
if (p.x == x && p.y == y)
{
return true;
}
return false;
}
CPoint& CPoint::operator =(const CPoint& p)
{
x = p.x;
y = p.y;
return *this;
}
///D:/360极速浏览器下载/Bowyer_Watson/Bowyer_Watson/Point.h
#ifndef __CPOINTH__
#define __CPOINTH__
#define NULL 0
#define SAFE_DELETE(x) if( (x)!=NULL ) { delete (x); (x)=NULL; }
#include <math.h>
class CPoint{
public:
float x;
float y;
CPoint()
{
x = 0;
y = 0;
};
static float distance(CPoint pt1 , CPoint pt2)
{
return sqrt((pt1.x-pt2.x)*(pt1.x-pt2.x) + (pt1.y-pt2.y)*(pt1.y-pt2.y));
};
CPoint(float fx, float fy)
{
x = fx;
y = fy;
};
bool operator ==(const CPoint& p);
CPoint& operator =(const CPoint& p);
};
#endif
///D:/360极速浏览器下载/Bowyer_Watson/Bowyer_Watson/Triangle.cpp
#include "Triangle.h"
#include <math.h>
CTriangle::CTriangle(CPoint pt1, CPoint pt2, CPoint pt3)
{
p1 = pt1;
p2 = pt2;
p3 = pt3;
l1 = CLine(p1,p2);
l2 = CLine(p2,p3);
l3 = CLine(p3,p1);
float dis1 = CPoint::distance(p1,p2);
float dis2 = CPoint::distance(p2,p3);
float dis3 = CPoint::distance(p3,p1);
radiu = dis1*dis2*dis3/TriangleArea()/4;
float c1, c2;
float xA, yA, xB, yB, xC, yC;
xA = p1.x; yA = p1.y;
xB = p2.x; yB = p2.y;
xC = p3.x; yC = p3.y;
c1 = (xA * xA + yA * yA - xB * xB - yB * yB) / 2;
c2 = (xA * xA + yA * yA - xC * xC - yC * yC) / 2;
center.x = (c1 * (yA - yC) - c2 * (yA - yB)) /
((xA - xB) * (yA - yC) - (xA - xC) * (yA - yB));
center.y = (c1 * (xA - xC) - c2 * (xA - xB)) /
((yA - yB) * (xA - xC) - (yA - yC) * (xA - xB));
}
float CTriangle::TriangleArea()
{
return fabs(p1.x * p2.y + p2.x * p3.y
+ p3.x * p1.y - p2.x * p1.y
- p3.x * p2.y - p1.x * p3.y) / 2;
}
bool CTriangle::CheckInCircle(CPoint pt)
{
if (CPoint::distance(center,pt) <= radiu)
{
return true;
}
return false;
}
CLine CTriangle::FindNearestLine(CPoint pt)
{
float dis1 = l1.Point2LineDistance(pt);
float dis2 = l2.Point2LineDistance(pt);
float dis3 = l3.Point2LineDistance(pt);
if (dis1 <= dis2 && dis1 <= dis3)
{
return l1;
}
if (dis2 <= dis1 && dis2 <= dis3)
{
return l2;
}
return l3;
}
CLine* CTriangle::FindCommonLine(CTriangle tg)
{
if (this->l1 == tg.l1 || this->l1 == tg.l2 || this->l1 == tg.l3)
{
return &l1;
}
if (this->l2 == tg.l1 || this->l2 == tg.l2 || this->l2 == tg.l3)
{
return &l2;
}
if (this->l3 == tg.l1 || this->l3 == tg.l2 || this->l3 == tg.l3)
{
return &l3;
}
return NULL;
}
CPoint CTriangle::GetOtherPoint(CPoint pt1, CPoint pt2)
{
if (!(p1 == pt1) && !(p1 == pt2))
{
return p1;
}
if (!(p2 == pt1) && !(p2 == pt2))
{
return p2;
}
return p3;
}
bool CTriangle::CheckPointExist(CPoint pt)
{
if (pt == p1 || pt == p2 || pt == p3)
{
return true;
}
return false;
}
bool CTriangle::operator ==(const CTriangle& t)
{
if ((p1 == t.p1) && (p2 == t.p2) && (p3 == t.p3))
{
return true;
}
if ((p1 == t.p1) && (p3 == t.p2) && (p2 == t.p3))
{
return true;
}
if ((p2 == t.p1) && (p1 == t.p2) && (p3 == t.p3))
{
return true;
}
if ((p2 == t.p1) && (p3 == t.p2) && (p1 == t.p3))
{
return true;
}
if ((p3 == t.p1) && (p2 == t.p2) && (p1 == t.p3))
{
return true;
}
if ((p3 == t.p1) && (p1 == t.p2) && (p2 == t.p3))
{
return true;
}
return false;
}
///D:/360极速浏览器下载/Bowyer_Watson/Bowyer_Watson/Triangle.h
#ifndef __CTRIANGLEH__
#define __CTRIANGLEH__
#include "Point.h"
#include "Line.h"
class CTriangle{
public :
CPoint p1;
CPoint p2;
CPoint p3;
CLine l1;
CLine l2;
CLine l3;
CPoint center;
float radiu;
CTriangle(){};
CTriangle(CPoint pt1, CPoint pt2, CPoint pt3);
bool CheckInCircle(CPoint pt);
float TriangleArea();
CLine FindNearestLine(CPoint pt);
CLine* FindCommonLine(CTriangle tg);
CPoint GetOtherPoint(CPoint pt1, CPoint pt2);
bool CheckPointExist(CPoint pt);
bool operator ==(const CTriangle& t);
};
#endif
</span>
这图纸其实设计得还很详细,只是没有说明书,确实有点难为神农他老人家。
阿伟念动咒语,生成了制造工艺流程:
<span style="font-size:18px;">#nmake /f winc.mak
#源文件目录和编译输出目录
SRCPATH =
DSTPATH = .\dst
#编译器
CPP = cl
RSC = rc
LINK = link
#编译选项
CPPFLAGS = /nologo /EHsc /W3 /O2 /D "WIN32" /D _X86_ /D "NDEBUG" /D "_MBCS" /c
RSCFLAGS =
LINKFALGS = /nologo
#预定义链接库
LINKLIB = \
user32.lib kernel32.lib gdi32.lib
#平台
PLATFORM = /machine:I386 /subsystem:console
#目标文件名
#前缀加地址 $(DSTPATH)/
EXETARGET = $(DSTPATH)/Main.exe
DLLTARGET =
OBJTARGET = $(DSTPATH)/Point.obj $(DSTPATH)/Line.obj $(DSTPATH)/Triangle.obj \
$(DSTPATH)/BowyerWatson.obj $(DSTPATH)/Main.obj
RESTARGET =
#编译规则
all: create.dir \
$(EXETARGET) $(DLLTARGET) $(OBJTARGET) $(RESTARGET)
!if "$(EXETARGET)" != ""
$(EXETARGET): $(OBJTARGET) $(RESTARGET)
$(LINK) $(LINKFLAGS) $(PLATFORM) $(LINKLIB) $(OBJTARGET) $(RESTARGET) /OUT:$(EXETARGET)
!endif
.c{$(DSTPATH)/}.obj:
$(CPP) $(CPPFLAGS) /Fo$@ $<
.cpp{$(DSTPATH)/}.obj:
$(CPP) $(CPPFLAGS) /Fo$@ $<
.rc{$(DSTPATH)/}.res:
$(RSC) $(RSCFLAGS) /Fo$@ $<
create.dir:
-if not exist $(DSTPATH)\*.* mkdir $(DSTPATH)
clean:
-if exist $(DSTPATH)\*.obj erase $(DSTPATH)\*.obj
-if exist $(DSTPATH)\*.res erase $(DSTPATH)\*.res</span>
[机器小伟]一阵忙活,生成了一张说明书:
神农看了半天,表示他不识数,只看得懂图。
图来:
阿伟和神农都没有说话,神农默默地掏出了第二张图纸:
<span style="font-size:18px;">///D:/360极速浏览器下载/delaunay/delaunay.cpp
#include "delaunay.h"
Delaunay::Delaunay(Point p1,Point p2,Point p3,Point p4)
{
//四个边框点为左上->右上->右下->左下的环形顺序
m_Pts.resize(4);
m_Pts[0]=p1;
m_Pts[1]=p2;
m_Pts[2]=p3;
m_Pts[3]=p4;//添加四个外边框点
m_Edges.resize(4);
Edge l1={0,1,-1};
Edge l2={1,2,-1};
Edge l3={0,3,-1};
Edge l4={2,3,-1};
m_Edges[0]=l1;
m_Edges[1]=l2;
m_Edges[2]=l3;
m_Edges[3]=l4;//添加四个外边框的边
MakeTriangle(0,1,2);
MakeTriangle(0,2,3);//添加初始的两个三角形
}
Delaunay::~Delaunay()//清空Delaunay类的数据成员
{
m_Pts.resize(0);
m_Edges.resize(0);
m_Tris.resize(0);
}
void Delaunay::MakeTriangle(int n1,int n2,int n3)
{
double x_centre,y_centre,radius;
Cal_Centre(x_centre,y_centre,radius,n1,n2,n3);//获得顶点为n1,n2,n3的三角形的外接圆圆心坐标和半径
Triangle newTriangle={{n1,n2,n3},{{n1,n2,1},{n2,n3,1},{n1,n3,1}},x_centre,y_centre,radius};//生成指定的三角形
m_Tris.push_back(newTriangle);//向m_Tris中添加新构造的三角形
int EdgeSzie=(int)m_Edges.size();//获得目前的边数
int flag;
for (int i=0;i<3;i++)
{
flag=1;
for(int j=0;j<EdgeSzie;j++)//通过循环判断新构造的三角形的各边是否已经存在于m_Edges中,如果存在则只增加该边的计数,否则添加新边
{
if (newTriangle.s[i].left==m_Edges[j].left&&newTriangle.s[i].right==m_Edges[j].right&&m_Edges[j].count!=-1) {flag=0;m_Edges[j].count+=1;break;}
else if(newTriangle.s[i].left==m_Edges[j].left&&newTriangle.s[i].right==m_Edges[j].right&&m_Edges[j].count==-1) {flag=0;break;}
}
if (flag==1) m_Edges.push_back(newTriangle.s[i]);
}
}
void Delaunay::Cal_Centre(double &x_centre,double &y_centre,double &radius,int n1,int n2,int n3)
{
double x1,x2,x3,y1,y2,y3;
x1=m_Pts[n1].x;
y1=m_Pts[n1].y;
x2=m_Pts[n2].x;
y2=m_Pts[n2].y;
x3=m_Pts[n3].x;
y3=m_Pts[n3].y;
x_centre=((y2-y1)*(y3*y3-y1*y1+x3*x3-x1*x1)-(y3-y1)*(y2*y2-y1*y1+x2*x2-x1*x1))/(2*(x3-x1)*(y2-y1)-2*((x2-x1)*(y3-y1)));//计算外接圆圆心的x坐标
y_centre=((x2-x1)*(x3*x3-x1*x1+y3*y3-y1*y1)-(x3-x1)*(x2*x2-x1*x1+y2*y2-y1*y1))/(2*(y3-y1)*(x2-x1)-2*((y2-y1)*(x3-x1)));//计算外接圆圆心的y坐标
radius= sqrt((x1 - x_centre)*(x1 - x_centre) + (y1 - y_centre)*(y1 - y_centre));//计算外接圆的半径
}
bool Delaunay::AddPoint(double xx,double yy,double zz)
{
EdgeArray BoundEdges;//BoundEdges用于存储在删除三角形后留下的边框,用于构造新的三角形
Point newPoint={xx,yy,zz};
m_Pts.push_back(newPoint);//向m_Pts中添加新点
intArray badTriangle;//badTriangle用于存储不符合空圆规则的三角形的索引号
int TriSize=(int)m_Tris.size();//获得目前的三角形数
for (int i=0;i<TriSize;i++)//通过循环找到所有不符合空圆规则的三角形,并将其索引号存在badTriangle中
{
if (inCircle(xx,yy,m_Tris[i])==true) badTriangle.push_back(i);
}
for (int i=0;i<(int)badTriangle.size();i++)//通过循环删除所有不符合空圆规则的三角形,同时保留边框
{
DelTriangle(badTriangle[i],BoundEdges);
for (int j=i+1;j<(int)badTriangle.size();j++) badTriangle[j]-=1;
}
int PtSize=(int)m_Pts.size();//获得目前的点数
for (int i=0;i<(int)BoundEdges.size();i++)//生成新的三角形
{
if (PtSize-1<BoundEdges[i].left) MakeTriangle(PtSize-1,BoundEdges[i].left,BoundEdges[i].right);
else if (PtSize-1>BoundEdges[i].left && PtSize-1<BoundEdges[i].right) MakeTriangle(BoundEdges[i].left,PtSize-1,BoundEdges[i].right);
else MakeTriangle(BoundEdges[i].left,BoundEdges[i].right,PtSize-1);
}
return true;
}
bool Delaunay::inCircle(double xx,double yy,Triangle currentTris)//判断点是否在三角形的外接圆内
{
double dis=sqrt((currentTris.xc-xx)*(currentTris.xc-xx)+(currentTris.yc-yy)*(currentTris.yc-yy));
if (dis>currentTris.r) return false;
else return true;
}
void Delaunay::DelTriangle(int n,EdgeArray &BoundEdges)
{
for (int i=0;i<3;i++)
{
for (int j=0;j<(int)m_Edges.size();j++)
{
if (m_Edges[j].left==m_Tris[n].s[i].left&&m_Edges[j].right==m_Tris[n].s[i].right)
{
if (m_Edges[j].count==2)//若要删除三角形的一边的计数为2,则将其计数减1,并将其压入BoundEdges容器中
{
m_Edges[j].count=1;
BoundEdges.push_back(m_Edges[j]);
}
else if (m_Edges[j].count==-1) BoundEdges.push_back(m_Edges[j]);//如果是外边框,则直接压入BoundEdges容器中
else if (m_Edges[j].count==1)//如果删除三角形的一边的计数为1,则删除该边,同时查看BoundEdges中是否有此边,若有,则删除
{
for (int k=0;k<(int)BoundEdges.size();k++)
{
if (BoundEdges[k].left==m_Edges[j].left&&BoundEdges[k].right==m_Edges[j].right)
{
BoundEdges.erase(BoundEdges.begin()+k);
break;
}
}
m_Edges.erase(m_Edges.begin()+j);
j--;
}
break;
}
}
}
m_Tris.erase(m_Tris.begin()+n);//删除该三角形
}
void Delaunay::output()//向“output.log"文件中写入ANSYS命令流
{
ofstream outfile("output.log");
if (!outfile)
{
cout<<"Unable to output nodes!";
exit(1);
}
outfile<<"/PREP7"<<endl;
for (int i=0;i<(int)m_Pts.size();i++)
{
outfile<<"K,"<<i+1<<","<<m_Pts[i].x<<","<<m_Pts[i].y<<","<<m_Pts[i].z<<endl;
}
for (int i=0;i<(int)m_Edges.size();i++)
{
outfile<<"L,"<<m_Edges[i].left+1<<","<<m_Edges[i].right+1<<endl;
}
outfile.close();
}
/*原版
void GetPoint(double &xx,double &yy,double &zz,string line)//从字符串line中解析出点的x,y,z坐标
{
int flag=0;
string tmp="";
char *cstr;
for (int i=(int)line.find(',')+1;i<(int)line.size();i++)
{
if (line[i]==',')
{
cstr=new char[tmp.size()+1];
strcpy(cstr,tmp.c_str());
if (flag==0) {xx=atof(cstr);tmp.resize(0);flag++;}
else if (flag==1) {yy=atof(cstr);tmp.resize(0);flag++;}
continue;
}
tmp=tmp+line[i];
}
if (fabs(xx)<1.0e-6) xx=0.0;
if (fabs(yy)<1.0e-6) yy=0.0;
if (fabs(zz)<1.0e-6) zz=0.0;
}
*/
//改良后
void GetPoint(double &xx,double &yy,double &zz,string line)//从字符串line中解析出点的x,y,z坐标
{
int flag=0;
string tmp="";
char *cstr;
/*这段似乎不能分析^num1, num2, num3$这种格式的输入
for (int i=(int)line.find(',')+1;i<(int)line.size();i++)
{
if (line[i]==',')
{
cstr=new char[tmp.size()+1];
strcpy(cstr,tmp.c_str());
if (flag==0) {xx=atof(cstr);tmp.resize(0);flag++;}
else if (flag==1) {yy=atof(cstr);tmp.resize(0);flag++;}
continue;
}
tmp=tmp+line[i];
} */
int xPos = 0, yPos = 0, zPos = 0; //记录逗号分隔符位置
xPos = line.find(',');
tmp = line.substr(0, xPos);
cstr=new char[tmp.size()+1];
strcpy(cstr,tmp.c_str());
xx=atof(cstr);
tmp.resize(0);
cstr = NULL;
yPos = line.find(',', xPos+1);
tmp = line.substr(xPos+1, (yPos-xPos-1));
cstr=new char[tmp.size()+1];
strcpy(cstr,tmp.c_str());
yy=atof(cstr);
tmp.resize(0);
cstr = NULL;
//不理会z值,需要时再扩展
zz = 0.0;
if (fabs(xx)<1.0e-6) xx=0.0;
if (fabs(yy)<1.0e-6) yy=0.0;
if (fabs(zz)<1.0e-6) zz=0.0;
}
void Delaunay::Delete_Frame()//删除外边框
{
EdgeArray BoundEdges;
for (int i=0;i<4;i++) m_Pts.erase(m_Pts.begin());
for (int i=0;i<(int)m_Tris.size();i++)
{
if (m_Tris[i].v[0]==0||m_Tris[i].v[0]==1||m_Tris[i].v[0]==2||m_Tris[i].v[0]==3)
{
DelTriangle(i,BoundEdges);
BoundEdges.resize(0);
i--;
}
else
{
for (int j=0;j<3;j++)
{
m_Tris[i].v[j]-=4;
m_Tris[i].s[j].left-=4;
m_Tris[i].s[j].right-=4;
}
}
}
for (int i=0;i<4;i++) m_Edges.erase(m_Edges.begin());
for (int i=0;i<(int)m_Edges.size();i++)
{
m_Edges[i].left-=4;
m_Edges[i].right-=4;
}
}
void Delaunay::Boundary_Recover(int fromPoint,int toPoint)//恢复由指定点组成的边界
{
EdgeArray BoundEdges;
for (int i=0;i<(int)m_Tris.size();i++)
{
if (m_Tris[i].v[0]>=(fromPoint-1)&&m_Tris[i].v[2]<=(toPoint-1))
{
DelTriangle(i,BoundEdges);
BoundEdges.resize(0);
i--;
}
}
}
///D:/360极速浏览器下载/delaunay/delaunay.h
#ifndef DELAUNAY_H_INCLUDED
#define DELAUNAY_H_INCLUDED
#include <cstdlib>
#include <iostream>
#include <cstring>
#include <string>
#include <fstream>
#include <math.h>
#include <vector>
using namespace std;
typedef struct
{
double x;
double y;
double z;
}Point;//定义点类
typedef vector<Point> PointArray;//定义点类的vector容器
typedef struct
{
int left;
int right;
int count;//边的计数,如果计数为0,则删除此边
}Edge;//定义边类
typedef vector<Edge> EdgeArray;//定义边类的vector容器
typedef struct
{
int v[3];//三角形的三个顶点
Edge s[3];//三角形的三条边
double xc;//三角形外接圆圆心的x坐标
double yc;//三角形外接圆圆心的y坐标
double r;//三角形外接圆的半径
}Triangle;//定义三角形类
typedef vector<Triangle> TriangleArray;//定义三角形类的vector容器
typedef vector<int> intArray;//定义int类的vector容器
class Delaunay//定义Delaunay类
{
public:
Delaunay(Point p1,Point p2,Point p3,Point p4);//Delaunay类的构造函数,创建外边框
~Delaunay();//Delaunay类的析构函数
bool AddPoint(double xx,double yy,double zz);//向已有剖分图形中加点的函数
void Delete_Frame();//删除外边框
void Boundary_Recover(int fromPoint,int toPoint);//边界恢复
void output();//输出ANSYS命令流文件
private:
void Cal_Centre(double &x_centre,double &y_centre,double &radius,int n1,int n2,int n3);//计算三角形的外接圆圆心坐标和半径
void MakeTriangle(int n1,int n2,int n3);//生成指定顶点的三角形
bool inCircle(double xx,double yy,Triangle currentTris);//判断点是否在圆内
void DelTriangle(int n,EdgeArray &BoundEdges);//删除指定的三角形
PointArray m_Pts;//m_Pts用于存储所有点
EdgeArray m_Edges;//m_Edges用于存储所有边
TriangleArray m_Tris;//m_Tris用于存储所有三角形
};
void GetPoint(double &xx,double &yy,double &zz,string line);//解析从input文件中读取的每一行数据
#endif // DELAUNAY_H_INCLUDED
///D:/360极速浏览器下载/delaunay/main.cpp
#include "delaunay.h"
int main()
{
ifstream infile("input.txt");//打开"input.txt"文件
if (!infile)//判断文件是否正常打开
{
cout<<"Unable to input nodes!";
exit(1);
}
string line;
PointArray p;
double xx,yy,zz;
int nodeSize;
for (int i=0;i<4;i++)//读入4外边框点
{
getline(infile,line);
GetPoint(xx,yy,zz,line);
Point tmp={xx,yy,zz};
p.push_back(tmp);
}
Delaunay MyMesh(p[0],p[1],p[2],p[3]);//实例化Delaunay类
getline(infile,line);//读入节点数,用于后面循环
char *cstr;
cstr=new char[line.size()+1];
strcpy(cstr,line.c_str());
nodeSize=atoi(cstr);
for (int i=0;i<nodeSize;i++)//读入每个节点的坐标
{
getline(infile,line);
GetPoint(xx,yy,zz,line);
MyMesh.AddPoint(xx,yy,zz);
}
infile.close();
MyMesh.Delete_Frame();//删除外边框
/*
MyMesh.Boundary_Recover(203,466);
MyMesh.Boundary_Recover(467,487);
MyMesh.Boundary_Recover(488,511);
MyMesh.Boundary_Recover(512,537);//以上都是恢复指定边界
*/
MyMesh.output();//将相应ANSYS命令流输出
return 0;
}
</span>
阿伟照样先理出了制造工艺流程:
<span style="font-size:18px;">///D:/360极速浏览器下载/delaunay/winc.mak
#nmake /f winc.mak
#源文件目录和编译输出目录
SRCPATH =
DSTPATH = .\dst
#编译器
CPP = cl
RSC = rc
LINK = link
#编译选项
CPPFLAGS = /nologo /EHsc /W3 /O2 /D "WIN32" /D _X86_ /D "NDEBUG" /D "_MBCS" /c
RSCFLAGS =
LINKFALGS = /nologo
#预定义链接库
LINKLIB = \
user32.lib kernel32.lib gdi32.lib
#平台
PLATFORM = /machine:I386 /subsystem:console
#目标文件名
#前缀加地址 $(DSTPATH)/
EXETARGET = $(DSTPATH)/main.exe
DLLTARGET =
OBJTARGET = $(DSTPATH)/delaunay.obj $(DSTPATH)/main.obj
RESTARGET =
#编译规则
all: create.dir \
$(EXETARGET) $(DLLTARGET) $(OBJTARGET) $(RESTARGET)
!if "$(EXETARGET)" != ""
$(EXETARGET): $(OBJTARGET) $(RESTARGET)
$(LINK) $(LINKFLAGS) $(PLATFORM) $(LINKLIB) $(OBJTARGET) $(RESTARGET) /OUT:$(EXETARGET)
!endif
.c{$(DSTPATH)/}.obj:
$(CPP) $(CPPFLAGS) /Fo$@ $<
.cpp{$(DSTPATH)/}.obj:
$(CPP) $(CPPFLAGS) /Fo$@ $<
.rc{$(DSTPATH)/}.res:
$(RSC) $(RSCFLAGS) /Fo$@ $<
create.dir:
-if not exist $(DSTPATH)\*.* mkdir $(DSTPATH)
clean:
-if exist $(DSTPATH)\*.obj erase $(DSTPATH)\*.obj
-if exist $(DSTPATH)\*.res erase $(DSTPATH)\*.res</span>
这套生产线还只有一半。
神农告诉阿伟那另外半套生产线需要装一个相当大的程序,那个名字他听都没听说过。
嗯,天下数据一家亲,阿伟让神农不要着急。
<span style="font-size:18px;">#读取ANSYS命令流文件数据
def tmp2():
fin = open('input.txt', 'r');
fout = open('output.txt', 'w');
verts = [];
edges = [];
for line in fin.readlines():
if (line[0] == 'K'):
line = line[:-1]; #去除行尾'\n'
a = line.split(',');
#暂时取第二项,即顶点序号,以及x, y坐标值
verts.append([float(a[2]), float(a[3])]);
elif (line[0] == 'L'):
line = line[:-1];
a = line.split(',');
point_1 = verts[int(a[1])-1];
point_2 = verts[int(a[2])-1];
edges.append([point_1, point_2]);
print('共有顶点{0}个,边{1}条'.format(len(verts), len(edges)));
fout.write('$Verts = [');
s = '';
for i in range(len(verts)):
s += str(verts[i])+',';
fout.write(s+']\n');
fout.write('$Edges = [');
s = '';
for i in range(len(edges)):
s += str(edges[i])+',';
fout.write(s+']\n');
fin.close();
fout.close();</span>
好了,程序不应该那么大,阿伟告诉神农,大的东西是不可靠的。
一阵吱吱乱响,[机器小伟]继续出图:
费这么半天工夫,貌似结果一样啊。
阿伟不得不对神农说,你看,要早知的结果也就这样,那你还不如用我的那套设计图纸呢,虽然还有很多奇怪的地方,但总是要简单些啊。
<span style="font-size:18px;">import geo;
###
# @usage Bowyer-Watson算法进行Delaunay三角剖分
# @author mw
# @date 2016年07月15日 星期五 10:31:36
# @param
# @return
#
###
class Delaunay():
#设置顶点
#vertices是[[x_0, y_0], [x_1, y_1], ...]顶点对格式
def setVertice(self, vertices):
return vertices;
def sortVerticebyX(self, vertices):
v_x = sorted(vertices, key = lambda a : a[0]);
return v_x;
def sortVerticebyY(self, vertices):
v_y = sorted(vertices, key = lambda a : a[1]);
return v_y;
#去除重复点
def removeDup(self, vertices):
v_new = [];
len_1 = len(vertices);
len_2 = 0;
for i in range(len_1):
len_2 = len(v_new);
if (len_2 < 1):
v_new.append(vertices[i]);
else:
for j in range(len_2):
if v_new[j] == vertices[i]:
break;
if (j >= len_2-1):
v_new.append(vertices[i]);
return v_new;
#计算边界
def calcBound(self, vertices):
len_ = len(vertices)
v_x = self.sortVerticebyX(vertices);
xMin = v_x[0][0];
xMax = v_x[len_-1][0];
v_y = self.sortVerticebyY(vertices);
yMin = v_y[0][1];
yMax = v_y[len_-1][1];
return [xMin, xMax, yMin, yMax];
#超级三角形
def superTri(self, vertices):
bound = self.calcBound(vertices);
xMin = bound[0]-10;
xMax = bound[1]+10;
yMin = bound[2]-10;
yMax = bound[3]+10;
xCenter = (xMin+xMax)/2;
yCenter = (yMin+yMax)/2;
xR = (xMax-xMin)/2;
yR = (yMax-yMin)/2;
xMin_ = xCenter-2*xR;
xMax_ = xCenter+2*xR;
yMin_ = yMin;
yMax_ = yMin + 4*yR;
return [[xMin_, yMin_], [xMax_, yMin_], [xCenter, yMax_]];
#计算剖分三角形
def calcDelaunayTri(self, vertices, mode = 1):
#移除重复点
vertices = self.removeDup(vertices);
#按X坐标由小到大排序
vertices = self.sortVerticebyX(vertices);
#顶点数量
vertNum = len(vertices);
#临时三角形存放处
tempTriArray = [];
#三角形存放处
triArray = [];
#边存放处
edgeArray = [];
supertri = self.superTri(vertices);
tempTriArray.append(supertri);
triArray.append(supertri);
for i in range(vertNum):
P0 = vertices[i];
tmpTriNum = len(tempTriArray);
print('顶点{0} --> {1}个临时三角形'.format(i, tmpTriNum));
edgeArray = [];
tmpTri = [];
for j in range(tmpTriNum):
P1, P2, P3 = tempTriArray[j][0], tempTriArray[j][1], tempTriArray[j][2];
#调用geo的circle方法
circleProp = geo.circle(P1, P2, P3);
#取得圆心和半径
P_center, R = circleProp[0], circleProp[1];
#print(P_center, 'R = ', R);
d = geo.distance2D(P0, P_center);
if (P0[0] > P_center[0]+R):
#对比点是在圆外右侧的三角形,已经得到晋级确认
#由于某些时候会多出一些冗余三角形,先加入一个判断试试能不能解决该问题
triArray.append([P1, P2, P3]);
elif (d > R):
#不确定的三角形,不理它
tmpTri.append([P1, P2, P3]);
else:
#对比点在圆内,这个三角形被淘汰
edgeArray.append([P1, P2]);
edgeArray.append([P2, P3]);
edgeArray.append([P3, P1]);
edgeArray = self.removeDupEdge(edgeArray);
edges = len(edgeArray);
print('顶点{0} --> {1}条边'.format(i, edges));
for k in range(edges):
P1, P2 = edgeArray[k][0], edgeArray[k][1];
if (geo.pointInLine(P1, P2, P0) == False):
tmpTri.append([P0, P1, P2]);
#临时数组已经重新安排
tempTriArray = [];
tempTriArray = self.removeDupTri(tmpTri);
triArray += tempTriArray;
triArray = self.removeDupTri(triArray);
if (mode == 0):
return triArray;
else:
newTriArray = [];
triNum = len(triArray);
for i in range(triNum):
tri_ = triArray[i];
relate = False;
for j in range(3):
if relate == True:
break;
for k in range(3):
if tri_[j] == supertri[k]:
relate = True;
break;
if relate == False:
newTriArray.append(tri_);
return newTriArray;
#移除相同的三角形
def removeDupTri(self, triArray):
newTriArray = [];
for i in range(len(triArray)):
len_ = len(newTriArray);
if (len_ <= 0):
newTriArray.append(triArray[i]);
else:
for j in range(len_):
if self.judgeSameTri(newTriArray[j], triArray[i]) == True:
break;
if (j >= len_ -1):
newTriArray.append(triArray[i]);
return newTriArray;
#判断两个三角形相同
#三角形格式[P1, P2, P3], P是顶点
def judgeSameTri(self, tri_1, tri_2):
P_11, P_12, P_13, P_21, P_22, P_23 = tri_1[0], tri_1[1], tri_1[2], tri_2[0], tri_2[1], tri_2[2];
tri_1 = sorted(tri_1, key = lambda a:(a[0], a[1]));
tri_2 = sorted(tri_2, key = lambda a:(a[0], a[1]));
if (tri_1 == tri_2):
return True;
else:
return False;
#判断两个三角形有共同边
def judge2TriHaveSameEdge(self, tri_1, tri_2):
pass;
#移除相同的边,本算法的去重指的是要成对的却除相同的边
#而不是只允许出现一次那种
def removeDupEdge(self, edgeArray):
newEdgeArray = [];
'''
for i in range(len(edgeArray)):
len_ = len(newEdgeArray);
if (len_ <= 0):
newEdgeArray.append(edgeArray[i]);
else:
for j in range(len_):
if self.judgeSameEdge(newEdgeArray[j], edgeArray[i]) == True:
newEdgeArray = newEdgeArray[:j]+newEdgeArray[j+1:];
break;
if (j >= len_ -1):
newEdgeArray.append(edgeArray[i]);
return newEdgeArray;
'''
len1 = len(edgeArray);
'''
for i in range(len_):
edgeArray[i] = sorted(edgeArray[i], key = lambda a:(a[0], a[1]));
'''
for i in range(len(edgeArray)):
len_ = len(newEdgeArray);
if (len_ <= 0):
newEdgeArray.append([edgeArray[i], 1]);
else:
for j in range(len_):
if self.judgeSameEdge(newEdgeArray[j][0], edgeArray[i]) == True:
newEdgeArray[j][1] += 1;
break;
if (j >= len_ -1):
newEdgeArray.append([edgeArray[i], 1]);
result = [];
for i in range(len(newEdgeArray)):
if (newEdgeArray[i][1] <= 1):
result.append(newEdgeArray[i][0]);
return result;
#判断两条边相同
#边格式[P1, P2], P是顶点
def judgeSameEdge(self, edge_1, edge_2):
P_11, P_12, P_21, P_22 = edge_1[0], edge_1[1], edge_2[0], edge_2[1];
if (P_11 == P_21 and P_12 == P_22) or (P_11 == P_22 and P_12 == P_21):
return True;
else:
return False;
def tmp1():
delaunay = Delaunay();
picDataArray = [[15, 7, 161, 311], [18, 7, 160, 369], [11, 8, 171, 239], [8, 10, 221, 170], [21, 10, 209, 435], [23, 13, 283, 463], [6, 14, 300, 142], [13, 14, 300, 278], [15, 14, 301, 319], [17, 15, 325, 354], [11, 16, 338, 245], [17, 17, 352, 363], [23, 17, 361, 479], [7, 18, 381, 159], [12, 18, 376, 265], [14, 18, 385, 293], [19, 18, 380, 377], [17, 19, 404, 347], [15, 20, 408, 309], [8, 21, 444, 175], [22, 21, 441, 450], [9, 24, 489, 203], [19, 24, 495, 397], [12, 26, 540, 257], [16, 26, 539, 329], ];
verts = [];
mapWidth, mapHeight = 700/2, 600/2;
for i in range(len(picDataArray)):
x = picDataArray[i][2];
y = picDataArray[i][3];
if (abs(x-mapWidth)<=350 and abs(y-mapHeight)<=270):
verts.append([x, y, 0]);
print('顶点集:', verts);
'''
if (len(verts) >= 3):
a = delaunay.calcDelaunayTri(verts);
print('写入文件开始。>>>');
fout = open('output.txt', 'w');
print('共有顶点{0}个,共有三角形{1}个'.format(len(verts), len(a)));
s = '$Verts = ';
s += str(verts);
fout.write(s + '\n\n\n\n');
s = '$Triangles = ';
s += str(a);
fout.write(s+'\n');
fout.close();
print('写入文件完毕。');
'''
print('写入文件开始。>>>');
fout = open('output.txt', 'w');
bound = [[0, 0, 0], [1000, 0, 0], [1000, 1000, 0], [0, 1000, 0]];
len_ = len(bound);
print(len_);
for i in range(len_):
s = str(bound[i]);
fout.write(s+'\n');
fout.write(str(len(verts))+'\n');
for i in range(len(verts)):
s = str(verts[i]);
fout.write(s+'\n');
fout.close();
print('写入文件完毕。');</span>
然后,神农拿着这三套图纸,回去召集手下生产车辆去了。
本节到此结束,欲知后事如何,请看下回分解。