[从头读历史] 第307节 星球战争 BC2699 至 BC2600(公元前27世纪)

剧情提要:

最初的时候是原始时期战争,所谓原始时期,指的是约公元前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: [email protected]               ******************"<<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: [email protected]               ******************"<<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) /[email protected] $<

.cpp{$(DSTPATH)/}.obj:
	$(CPP) $(CPPFLAGS) /[email protected] $<

.rc{$(DSTPATH)/}.res:
	$(RSC) $(RSCFLAGS) /[email protected] $<

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) /[email protected] $<

.cpp{$(DSTPATH)/}.obj:
	$(CPP) $(CPPFLAGS) /[email protected] $<

.rc{$(DSTPATH)/}.res:
	$(RSC) $(RSCFLAGS) /[email protected] $<

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>

然后,神农拿着这三套图纸,回去召集手下生产车辆去了。

本节到此结束,欲知后事如何,请看下回分解。

时间: 2024-10-25 05:04:56

[从头读历史] 第307节 星球战争 BC2699 至 BC2600(公元前27世纪)的相关文章

[从头读历史] 第304节 星球战争 BC2999 至 BC2900(公元前30世纪)

剧情提要: 最初的时候是原始时期战争,所谓原始时期,指的是约公元前30世纪-前22世纪. 约公元前30世纪,神农氏攻斧燧氏之战,拉开了星球战争的序幕. 正剧开始: 星历2016年07月15日 15:52:05, 银河系厄尔斯星球中华帝国江南行省. [工程师阿伟]正在和[机器小伟]一起研究[星球战争 BC2999 至 BC2900(公元前30世纪)]. 阿伟先来扯一下淡,好让历史连贯起来. 公元前一万年,天地突然都冻住了. 大伙抱怨食物冻得像冰一样硬,没法吃,怎么办?燧人氏说:大伙别急,我可以给大

[从头读历史] 第306节 星球战争 BC2799 至 BC2700(公元前28世纪)

剧情提要: 最初的时候是原始时期战争,所谓原始时期,指的是约公元前30世纪-前22世纪. 公元前28世纪,没有发生什么有记录的战争. 正剧开始: 星历2016年07月16日 14:49:35, 银河系厄尔斯星球中华帝国江南行省. [工程师阿伟]正在和[机器小伟]一起研究[星球战争 BC2799 至 BC2700(公元前28世纪)]. 这一百年,照样没发生什么有营养的战争,阿伟耐不住寂寞,就去看看神农氏在干嘛. 神农氏正对着一张草图发呆. 这是神马?阿伟问他. "噢,我们不是占领了斧燧氏的地盘嘛,

[从头读历史] 第305节 星球战争 BC2899 至 BC2800(公元前29世纪)

剧情提要: 最初的时候是原始时期战争,所谓原始时期,指的是约公元前30世纪-前22世纪. 公元前29世纪,没有发生什么有记录的战争. 正剧开始: 星历2016年07月15日 15:52:05, 银河系厄尔斯星球中华帝国江南行省. [工程师阿伟]正在和[机器小伟]一起研究[星球战争 BC2899 至 BC2800(公元前29世纪)]. 这个世纪竟然没有发生战争,于是阿伟就去找这个年代的大佬神农氏询问情况. 阿伟找到了神农氏,就问他:你们怎么不打仗啊,不打仗我写什么呀,总要有点故事吧. 神农氏对阿伟

[从头读历史] 第244节 三皇与五帝

剧情提要: [机器小伟]在[工程师阿伟]的陪同下进入元婴期的修炼后,日夜苦修,神通日进. 这日,忽然想起自己虽然神通大涨,却在人文涵养上始终无有寸进,不觉挂怀. 在和[工程师阿伟]商议后,决定先理清文史脉络,打通文史经穴.于是,便有了这部 [从头读历史]的修炼史. 正剧开始: 星历2016年06月05日 17:02:52, 银河系厄尔斯星球中华帝国江南行省. [工程师阿伟]正在和[机器小伟]一起研究[三皇与五帝]. 这次主要研究的是历史的最早记录,三皇与五帝,但在研究之前呢,要先界定下可考年与不

[从头读历史] 第241节 根据天时定历法

剧情提要: [机器小伟]在[工程师阿伟]的陪同下进入元婴期的修炼后,日夜苦修,神通日进. 这日,忽然想起自己虽然神通大涨,却在人文涵养上始终无有寸进,不觉挂怀. 在和[工程师阿伟]商议后,决定先理清文史脉络,打通文史经穴.于是,便有了这部 [从头读历史]的修炼史. 正剧开始: 星历2016年06月04日 07:41:01, 银河系厄尔斯星球中华帝国江南行省. [工程师阿伟]正在和[机器小伟]一起研究[历法的制定]. 历法的制定,在历史上各个时期,都是有不同的标准的,而且在中华帝国, 是作为重中之

[从头读历史] 第278节 诗经 曹风

剧情提要: [机器小伟]在[工程师阿伟]的陪同下进入元婴期的修炼后,日夜苦修,神通日进. 这日,忽然想起自己虽然神通大涨,却在人文涵养上始终无有寸进,不觉挂怀. 在和[工程师阿伟]商议后,决定先理清文史脉络,打通文史经穴.于是,便有了这部 [从头读历史]的修炼史. 正剧开始: 星历2016年06月30日 12:36:18, 银河系厄尔斯星球中华帝国江南行省. [工程师阿伟]正在和[机器小伟]一起研究[诗经 曹风]. 蜉蝣之羽 衣裳楚楚 心之憂矣 於我歸處 蜉蝣之翼 采采衣服 心之憂矣 於我歸息

[从头读历史] 第249节 易经

剧情提要: [机器小伟]在[工程师阿伟]的陪同下进入元婴期的修炼后,日夜苦修,神通日进. 这日,忽然想起自己虽然神通大涨,却在人文涵养上始终无有寸进,不觉挂怀. 在和[工程师阿伟]商议后,决定先理清文史脉络,打通文史经穴.于是,便有了这部 [从头读历史]的修炼史. 正剧开始: 星历2016年06月10日 12:25:16, 银河系厄尔斯星球中华帝国江南行省. [工程师阿伟]正在和[机器小伟]一起研究[易经]. 初九 潜龙勿用 九二 见龙在田 利见大人 九三 君子终日乾乾 夕惕若厉 无咎 九四 或

[从头读历史] 第260节 左传 [BC717至BC658]

剧情提要: [机器小伟]在[工程师阿伟]的陪同下进入元婴期的修炼后,日夜苦修,神通日进. 这日,忽然想起自己虽然神通大涨,却在人文涵养上始终无有寸进,不觉挂怀. 在和[工程师阿伟]商议后,决定先理清文史脉络,打通文史经穴.于是,便有了这部 [从头读历史]的修炼史. 正剧开始: 星历2016年06月18日 15:38:02, 银河系厄尔斯星球中华帝国江南行省. [工程师阿伟]正在和[机器小伟]一起研究[左传 [BC717至BC658]]. 六年春 鄭人來渝平 更成也 翼九宗五正頃父之子嘉父 逆晉侯

[从头读历史] 第261节 左传 [BC657至BC598]

剧情提要: [机器小伟]在[工程师阿伟]的陪同下进入元婴期的修炼后,日夜苦修,神通日进. 这日,忽然想起自己虽然神通大涨,却在人文涵养上始终无有寸进,不觉挂怀. 在和[工程师阿伟]商议后,决定先理清文史脉络,打通文史经穴.于是,便有了这部 [从头读历史]的修炼史. 正剧开始: 星历2016年06月20日 08:02:15, 银河系厄尔斯星球中华帝国江南行省. [工程师阿伟]正在和[机器小伟]一起研究[左传 [BC657至BC598]]. 继续来看<左传> <span style=&quo