cdt.h

来自「这是个生成约束delaunay triangulations源程序。对学习约束d」· C头文件 代码 · 共 668 行

H
668
字号
// file name: cdt.h//	including all the data structure used in //	constrained delaunay triangultaion(CDT).//// author: Zhihua Wang (zhihua@cs.nyu.edu)// date: Dec 12, 2002/*************************************************************///#define	OUTPUT//#define	DEBUG//#define	DETECT_COLLINEAR_DEGENERACY#define	COMMENT_ON#define	NOT_SUPPORT_SAME_X#undef	NOT_SUPPORT_SAME_X// *************************************************************//	predefinitions// *************************************************************#include	<math.h>#include	"geom2d.h"#include	"myMacro.h"// *************************************************************//	io utility// *************************************************************#include <stdio.h>#include <stdlib.h>#include <assert.h>#define	BLANK	' '#define	TAB	'\t'#define	noff_keyword "NOFF"#define	LINE_LENGTH	80#define	NO_ERR	1#define	ERR_IMPORT_FILE	-1#define	ERR_CANNOT_OPEN_FILE -2#define	ERR_NOT_VALID_FORMAT -3#define	ERR_WRONG_VERTEX_NUMBER -4#define	ERR_WRONG_FACE_NUMBER -4void	reportString(char* str){	fprintf(stderr,"%s\n",str);}void	reportErrorString(char*	str){	fprintf(stderr,"Error: %s\n",str);	exit(-1);}void	reportError(char*	str,int line,char* file){	fprintf(stderr,"Error: [%s:%d] %s\n",file,line,str);	exit(-1);}void	reportWarningString(char* str){	fprintf(stderr,"Warning: %s\n",str);}void	reportWarning(char* str,int line,char* file){	fprintf(stderr,"Warning: [%s:%d] %s\n",file,line,str);}// read one line of file fp points to from current pointvoid	readToLineEnd(FILE * fp){	int	c;	c=fgetc(fp);	while	(c!='\n')		c=fgetc(fp);}int	readFirstNonspaceChar(FILE* fp){	int	c;	c=fgetc(fp);	while	(c==BLANK || c==TAB)		c=fgetc(fp);	return c;}// omit the comment in fp// in case the first character of line is '#'void	omitComment(FILE* fp,char Leading_Comment_Char='#'){/*	int c;	//omit comment	c=readFirstNonspaceChar(fp);#ifdef	DEBUG	printf("First Charater:%c\n",c);#endif//	DEBUG		// omit comment line	while	(c==Leading_Comment_Char)	{		readToLineEnd(fp);		c=readFirstNonspaceChar(fp);#ifdef	DEBUG	printf("First Charater:%c\n",c);#endif//	DEBUG	}	fseek(fp,-1L,SEEK_CUR);	//put back one character*/	}// *************************************************************//	primitives// 	data structure// *************************************************************#define	NON_CONSTRANED	-1	// type value of non constrained edge (see below)#define	CONSTRAINED		1#define	VIRTUAL			0#define SEPOFFSET	1	// some value >0 to make offset#define MAX_Y	HUGE_VAL#define MIN_Y	-HUGE_VALclass	Mesh;class	Vertex;class	Halfedge;class	Edge;class	EdgeList;class	Slab;class	Quad;struct	Window;typedef	Mesh*	MeshPointer;typedef	Vertex*	VPointer;typedef	Halfedge*	HePointer;typedef	Edge*	EPointer;typedef	EdgeList*	EListPointer;typedef	Slab*	SPointer;typedef	Quad*	QPointer;typedef	Window* WPointer;// planar graphclass	Mesh{	HePointer	getHullHalfedge(VPointer v,int sep_index,bool lowside);	HePointer	getHullHalfedgeNextTo(HePointer _he,VPointer v,int l,int sep_index,int r,bool lowside);	void	findInitialCandidatePair(WPointer w,		VPointer &p0,VPointer &q0,		HePointer &p_he,HePointer &q_he,		bool	lowside);	EPointer	advancePairToBridge(WPointer w,VPointer p0,VPointer q0,HePointer p_he,HePointer q_he,bool lowside);public:	int v_num;	//the number of vertices read from input	VPointer* v_array;	// the array pointing to the vertices	double*	sep_array;	// x-value of vertical separate lines	int e_num;	// numver of edges	int ce_num;	// number of constrained edges read from input	EListPointer	e_head,e_tail;	//bounding box (mins.x, maxs.x) * (mins.y maxs,y)	Point	maxs;		Point	mins;	//bounding utility	VPointer vlb,vlt;	//left most, btm and top vertex added manually	VPointer vrb,vrt;	EPointer sky_e;	EPointer eth_e;	//slab head	SPointer	s_head;//	SPointer	s_tail;	Mesh();	EPointer addEdge(VPointer v1,VPointer v2,int type=NON_CONSTRANED);	void	deleteEdge(EPointer e);	int initSlabs();	int	mergeSlabs();	void mergeSlabPair(SPointer	ls);	void sortVertices();	int import2OFFFile(char* sf);	int	export2OFFFile(char* sf,char* f=NULL);	EPointer findBridge(WPointer w,bool lowside);	EPointer findNextBaseEdge(WPointer w,EPointer e);	void buildCDTOfWindow(WPointer w);	int	buildCDT();	void	display();	MeshPointer copy();};//vertex	class Vertex{private:////members	int	valence;	int	index;	// index in x coordinate order////functionspublic:////members	////topology	HePointer	out_he;	//out halfedge pointer	////geometry	Point	pos;////functions	//constructor	Vertex(double _x,double _y,int i);//	Vertex(const Point &p=O,int i=0);	~Vertex();	//field access	int	getIndex()const	{return	index;};	//not user interface, only used by exportXXFile()	void setIndex(int _i){index=_i;};			//not user interface, only used by exportXXFile()	//initOutHalfedgeList();	void addToOutHalfedgeList(HePointer he);	// not an interface for user	void deleteFromOutHalfedgeList(HePointer he);	//not an interface for use	HePointer findOutHalfedgeInRing(VPointer v2);	HePointer findInHalfedgeInRing(VPointer v2);	HePointer	addHalfedge(VPointer v2,EPointer e);// not an interface to user, only called by addEdge()	int	getValence()const{return	valence;};};// of Vertex// Halfedgeclass Halfedge{public:////members	//topology	VPointer	v;	// vertex pointer to front v(fv)	//back v(bv) is pre_he->v	EPointer	e;	// edge pointer	HePointer inv_he;	// opposite halfedge pointer	HePointer next_he;	//next halfedge	HePointer pre_he;	//pre halfedge		//geometry	//normalized direction	vector	//	double	v[Dimension];	Vector	d;//direction from back v to front v////functions	Halfedge(VPointer _v=NULL,EPointer _e=NULL):v(_v),e(_e){inv_he=next_he=pre_he=NULL;d.x=0;d.y=0;};	~Halfedge();	//field access	//topology query	VPointer	getBackVertex()	const{return	inv_he->v;};	VPointer	getFrontVertex()	const{return	v;};};// of Halfedge// Edgeclass Edge{public://members	//topology	//he[0] is always from left to right	//he[1] is always from right to left	HePointer	he[2];	//halfedge pointer pair, he[0]->v->pos.x > he[1]'s	//scene level	EListPointer	iter;		//type, can be constrained or nonconstrained	int	type;//functions	Edge(VPointer v1,VPointer v2,int type=NON_CONSTRANED);	~Edge();	//field access	//topology query	//if an Edge exists, there must be 2 Halfedge 	VPointer	getOneVertex()const	{return	he[0]->v;};		VPointer	getTheOtherVertex()const{return he[1]->v;};};// of Edgeclass	EdgeList{public:	EPointer	e;	EListPointer next;		EdgeList(EPointer _e):e(_e){e->iter=this;next=NULL;};};//slabclass Slab{public:	int	l,r;	// indices of left and right separate line	QPointer	q_head,q_tail;	// head of list of quads	SPointer	next;	// next slab //methords	//constructor with li as left index and ri as right index	Slab(int li,int ri);	void pushBackQuad(QPointer q);};// quadclass Quad{public:	// highest and lowest vertices in the quad	VPointer	top_v,btm_v;	// top and bottom long edges of this quad (refer to long edge above)	HePointer	top_he;// top half-edge from right to left	HePointer	btm_he;// bottom half-edge from left to right	// indices of left and right vertical line	int		l,r;	// y value corresponding to the intersection of top_v and top_he	double		top_y;	// y value corresponding to the intersection of btm_v and btm_he	double		btm_y;	// y value of four cornor	double		left_top_y;			double		left_btm_y;			double		right_top_y;		double		right_btm_y;		QPointer		next;	// next quad in the list for this slab//methords	// constructor with highv as hv, lowv as lv, t as top and b as btm	Quad(VPointer highv,VPointer lowv,HePointer t,HePointer b,int _l,int _r);	Quad();	void updateLongEdge(EPointer e);	void computeCornorY(double lx,double rx);};struct	Window{//	int	m;		//middle separate line index	QPointer	lq,rq;	// left and right quad	//-1 :left above right	//0	: identical	// 1: left below right	int	upsign,downsign;	//sign indicating the intersection situation for lq,rq's top,btm halfedges};//given two quad which share a separate line, return their intersection window//return null if no intersection and set lgr to true if lq is above rqWPointer	getWindow(QPointer lq,QPointer rq,bool &lgr){#define	LEFT_ABOVE_RIGHT	true#define	RIGHT_ABOVE_LEFT	!LEFT_ABOVE_RIGHT	WPointer	w;#ifdef	DEBUG	assert(lq->r==rq->l);#endif	//use this to avoid comparision double numbers	if	(	lq->btm_he	==	rq->top_he->inv_he		||	lq->right_btm_y>rq->left_top_y)	{		lgr=LEFT_ABOVE_RIGHT;		return NULL;	}//	w->m=lq->r;	//use this to avoid comparision double numbers	if	(	lq->top_he->inv_he	==	rq->btm_he		||	lq->right_top_y<rq->left_btm_y)	{		lgr=RIGHT_ABOVE_LEFT;		return NULL;	}	w=new Window();	//use this to avoid comparision double numbers	if	(lq->top_he==rq->top_he)	{		w->upsign=0;	}	else	if	(lq->right_top_y>rq->left_top_y)	{		w->upsign=-1;	}	else//lq->right_top_y<rq->left_top_y	{		w->upsign=1;	}	if	(lq->btm_he==rq->btm_he)	{		w->downsign=0;	}	else	if	(lq->right_btm_y>rq->left_btm_y)	{		w->downsign=-1;	}	else//lq->right_btm_y<rq->left_btm_y	{		w->downsign=1;	}	w->lq=lq;	w->rq=rq;	return w;}//primitives in computational geometry/******************************************************************Given ratio of (xq-x1)/(xq-x2), assume xq!=x2Return:never be 1=0	:xq eq x1<0  : xq in middle of x1,x20< <1: x1 is in middle of xq,x2>1	:x2 is in middle of xq,x1******************************************************************//*//#EXACTdouble	getLambda(double xq,double x1,doube x2){	assert(xq-x2);	return((xq-x1)/(xq-x2));}*//******************************************************************is xq in between x1,x2, assume xq not eq x1 or x2******************************************************************/bool	inBetween(double xq,double x1,double x2){	assert(xq-x1);	assert(xq-x2);	return((xq-x1)*(xq-x2)<0);}/******************************************************************Given two vertices on a line,get the y-value of vertex on line whose x-vaule is given too.Using line equation (y-y1)/(x-x1)=(y2-y1)/(x2-x1)      y*(x2-x1)=(x-x1)*(y2-y1)+y1*(x2-x1)=(x-x1)*y2+y1*(x2-x)******************************************************************///#EXACTdouble	yOfLineGivenX(double x1,double y1,double x2,double y2,double x)	{	assert(x2-x1);	return ((x-x1)*y2+y1*(x2-x))/(x2-x1);	}/****************************************************************** Point on the side of radial line: (x,y)'s position according to  radial line (ox,oy) to (x1,y1) return value:    -1 left    0 on line    1 right******************************************************************///#EXACT	this function requires exact computationint	pointToLine(double x,double y,double ox,double oy,double x1,double y1){	// translation, o(x1,y1) as the new Oriental point	x=x-ox;	y=y-oy;	x1=x1-ox;	y1=y1-oy;	//rotation, op1 as the positive x direction	// x'=cos(a)*x+sin(a)*y *sqrt(x1^2+y1^2)	// y'=-sin(a)*x+cos(a)*y *sqrt(x1^2+y1^2)	//-->	//	x'=x1*x+y1*y	//	y'=-y1*x+x1*y	double D=y1*x-x1*y;   	if (D != 0)          return (D > 0) ? 1 : -1;        else          return 0;}/*  The side of (px,py) to the circumcircle of three points  (ax,ay), (bx,by) and (cx,cy)  return value:  -1 outside   0 on the circle   1 inside*///#EXACT	this function requires exact computationint pointToCircle(double px,double py,		double ax,double ay,		double bx,double by,		double cx,double cy){   bx = bx- ax;   by = by- ay;   double bw = bx*bx + by*by;   cx = cx- ax;   cy = cy- ay;   double cw = cx*cx + cy*cy;         double d1 = cy*bw - by*cw;   double d2 = bx*cw - cx*bw;   double d3 = by*cx - bx*cy;   px = px - ax;   py = py - ay;   double pw = px*px + py*py;   double D = px*d1 + py*d2 + pw*d3;   if (D != 0)      return (D > 0) ? 1 : -1;   else      return 0;} /*   primitive test on whether q(xq,yq) falls in the angle from  op1((xo,yo)->(x1,y1)) to op2((xo,yo)->(x2,y2))  return value:   -2 collinear to op2		here COLLINEAR stands for ONLY half of the line  -1 collinear to op1  0	outside  1	yes, inside*///#EXACT	this function requires exact computationint	pointInAngle(double xo,double yo,			double	xq,double yq,			double	x1,double y1,			double	x2,double y2){	double xx,yy;	// translation, o(xo,yo) as the new Oriental point	xq=xq-xo;	yq=yq-yo;	x1=x1-xo;	y1=y1-yo;	x2=x2-xo;	y2=y2-yo;	// whether (xq,yq) is collinear with (x1,y1) and on the same side of (0,0)	if	(	pointToLine(xq,yq,0,0,x1,y1)==0		&&	!	inBetween(0,xq,x1)	)		return	-1;	if	(	pointToLine(xq,yq,0,0,x2,y2)==0		&&	!	inBetween(0,xq,x2)	)		return	-2;	//rotation, op1 as the positive x direction	// x'=cos(a)*x+sin(a)*y 	// x'*sqrt(x1^2+y1^2)=x1*x+y1*y	// y'=-sin(a)*x+cos(a)*y 	// y'*sqrt(x1^2+y1^2)=-y1*x+x1*y	xx=xq;	yy=yq;	xq=x1*xx+y1*yy;	yq=-y1*xx+x1*yy;	xx=x2;	yy=y2;	x2=x1*xx+y1*yy;	y2=-y1*xx+x1*yy;	double sign=xq*y2-x2*yq;	// here we assume no collinear	if(x2>=0)	{		if(y2>0)		{			// (x2,y2) is in 1st quadrant			return(sign>0 && xq>0 && yq>0);		}		else		{			//4th quadrant			return !(sign<0 && xq>0 && yq<0);		}	}	else	{		if(y2>=0)		{			//2nd 			return( yq>0 &&(xq>=0 || xq<0 && sign>0));		}		else		{			//3rd 			return( yq>=0 || yq<0 && xq<0 && sign>0);		}	}}// *************************************************************//	sort algorithm used to sort vertices by x value// *************************************************************//***************** quick sort functions begin **********************// for partitionvoid	swap(VPointer* array,int i,int j){	VPointer tmpv;	tmpv=array[i];	array[i]=array[j];	array[j]=tmpv;	//modify index	/* commented 08/02, so that array[i]->index remains the sort information	array[i]->index=i;	array[j]->index=j;	*/}// for quick sortint	partition(VPointer* array,int p,int r){	double x;	int	i;		x=array[r]->pos.x;	i=p-1;	for (int j=p;j<r;j++)	{		if(array[j]->pos.x==x)		{			// vertices sharing same x values			reportWarning("Not supporting vertiecs sharing same x value now!",__LINE__,__FILE__);#ifdef	NOT_SUPPORT_SAME_X			exit(-1);#endif		}		else		if(array[j]->pos.x<x)		{			i++;			//	exchange array[i] and array[j]			swap(array,i,j);		}	}	swap(array,i+1,r);	return i+1;}// quick sort// input :from is the index where sort begins// count is the index of where sort ends// usually quicksort(array,0,n-1)void quicksort(VPointer* array,int from,int to){	int middle;	if(from<to)	{		middle=partition(array,from,to);#ifdef DEBUG		if		(middle>=0)		{#endif			quicksort(array,from,middle-1);			quicksort(array,middle+1,to);#ifdef DEBUG		}#endif	}	}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?