⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 utils.cpp

📁 Linux/windows 环境下跨平台开发程序
💻 CPP
📖 第 1 页 / 共 5 页
字号:
	if(loc && old_v != new_v) {
		Undo.ValInt(par, loc, flags);
		*loc = new_v;						return (flags | UNDO_CONTINUE);
		}
	return flags;
}

DWORD CheckNewDword(DWORD *loc, DWORD old_v, DWORD new_v, GraphObj *par, DWORD flags)
{
	if(loc && old_v != new_v) {
		Undo.ValDword(par, loc, flags);
		*loc = new_v;						return (flags | UNDO_CONTINUE);
		}
	return flags;
}

DWORD CheckNewLFPoint(lfPOINT *loc, lfPOINT *old_v, lfPOINT *new_v, GraphObj *par, DWORD flags)
{
	if(loc && old_v && new_v && (old_v->fx != new_v->fx || old_v->fy != new_v->fy)) {
		Undo.SaveLFP(par, loc, flags);
		loc->fx = new_v->fx;	loc->fy = new_v->fy;	return (flags | UNDO_CONTINUE);
		}
	return flags;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//execute clipping of 3D objects
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
typedef struct {			//structure required by 3D Bresenhan's algorithm
	int d, a, s, *r, l;
	}moveDEF;

long sph_r2;
int sph_x, sph_y, sph_z, nclp_pg, seg_x_seg;
POINT3D *clp_pg, *sphlim1, *sphlim2;
double *vclp_pg = 0L;

int test_sphere(int x, int y, int z)
{
	int d;
	long ld;
	
	ld = (d = x-sph_x) * d;			ld += (d = y-sph_y) * d;
	ld += (d = z-sph_z) * d;
	return (ld > sph_r2) ? 1 : 0;
}

//use a 3D Bresenham alorithm to find z coordinates where x == lx or y == ly
bool line3D_z(POINT3D *p1, POINT3D *p2, int lx, int ly, int *cx, int *cy, int *cz)
{
	moveDEF mx, my, mz, *m1, *m2, *m3;
	int x, y, z, d1, d2;

	mx.d = p2->x - p1->x;		mx.a = mx.d >= 0 ? mx.d : -mx.d;
	mx.s = mx.d >= 0 ? 1 : -1;	mx.r = &x;		mx.l = p2->x;	x = p1->x;
	my.d = p2->y - p1->y;		my.a = my.d >= 0 ? my.d : -my.d;
	my.s = my.d >= 0 ? 1 : -1;	my.r = &y;		my.l = p2->y;	y = p1->y;
	mz.d = p2->z - p1->z;		mz.a = mz.d >= 0 ? mz.d : -mz.d;
	mz.s = mz.d >= 0 ? 1 : -1;	mz.r = &z;		mz.l = p2->z;	z = p1->z;
	if(mx.a > my.a) {
		if(mz.a > mx.a) {
			m1 = &mz;		m2 = &mx;	m3 = &my;
			}
		else if(mz.a > my.a) {
			m1 = &mx;		m2 = &mz;	m3 = &my;
			}
		else {
			m1 = &mx;		m2 = &my;	m3 = &mz;
			}
		}
	else {
		if(mz.a > my.a) {
			m1 = &mz;		m2 = &my;	m3 = &mx;
			}
		else if(mz.a > mx.a) {
			m1 = &my;		m2 = &mz;	m3 = &mx;
			}
		else {
			m1 = &my;		m2 = &mx;	m3 = &mz;
			}
		}
	d1 = m2->a - (m1->a >>1);		d2 = m3->a - (m1->a >>1);
	for(; ;) {
		//process point at (m1.r, m2.r, m3.r);
		if(x == lx || y == ly) {
			*cx = x;	*cy = y;	*cz = z;
			return true;
			}
		if(*(m1->r) == m1->l) return false;
		if(d1 >= 0) {
			*(m2->r) += m2->s;	d1 -= m1->a;
			}
		if(d2 >= 0) {
			*(m3->r) += m3->s;	d2 -= m1->a;
			}
		*(m1->r) += m1->s;	d1 += m2->a;		d2 += m3->a;
		}
}

//test if point is 1) outside, 2) above, 3) on the line, or 0) hidden by a plane 
int test_plane(int x, int y, int z)
{
	int us, ls, us1, ls1, x1, y1, z1, x2, y2, z2;
	static int last = 0;
	POINT3D p1, p2;

	if(IsInPolygon3D(x, y, clp_pg, nclp_pg, &us, &ls)) {
		if(us == ls){
			seg_x_seg = us;
			return last = 3;		//point is on line: visible
			}
		if(vclp_pg) {
			if(iround((x * vclp_pg[0] + y * vclp_pg[1] - vclp_pg[3])/vclp_pg[2]) < z)
				return last = 2;
			else return last = 0;
			}
		if(us < 1) us1 = nclp_pg -1;	else us1 = us -1;
		if(ls < 1) ls1 = nclp_pg -1;	else ls1 = ls -1;
		if(z < clp_pg[us1].z && z < clp_pg[us].z && z < clp_pg[ls1].z &&
			z < clp_pg[ls].z) return last = 0;		//far below plane
		if(z > clp_pg[us1].z && z > clp_pg[us].z && z > clp_pg[ls1].z &&
			z > clp_pg[ls].z) return last = 2;		//far above plane
		if(line3D_z(&clp_pg[us1], &clp_pg[us], x, -1, &x1, &y1, &z1) &&
			line3D_z(&clp_pg[ls1], &clp_pg[ls], x, -1, &x2, &y2, &z2)){
			if(z1 < z && z2 < z) return last = 2;
			if(z1 >= z && z2 >= z) return last = 0;
			p1.x = x1;	p1.y = y1; p1.z = z1;	p2.x = x2;	p2.y = y2; p2.z = z2;
			if(line3D_z(&p1, &p2, -1, y, &x1, &y1, &z1)) {
				if(z > z1) return last = 2;
				else return last = 0;
				}
			}
		return last;
		}
	return last = 1;
}

int test_planeandline(int x, int y, int z)
{
	int ret;

	ret = test_plane(x, y, z);
	if(ret == 3 && clp_pg && nclp_pg && idx_point_on_line < nclp_pg) {
		if(vclp_pg) {
			if(iround((x * vclp_pg[0] + y * vclp_pg[1] - vclp_pg[3])/vclp_pg[2]) < z)
				return 2;
			else return 0;
			}
		else {
			// no equation for plane available
			}
		}
	return ret;
}


void proc_polygon(int vis, POINT3D *pnt, POINT3D * last);	//prototype

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//use a 3D Bresenham algorithm to clip lines
void clip_line_3D(GraphObj *go, POINT3D *p1, POINT3D *p2, int(*proc)(int, int, int))
{
	moveDEF mx, my, mz, *m1, *m2, *m3;
	int x, y, z, d1, d2, vis;
	bool bVisible, bDrawLater = false;
	POINT3D p, lp;

	if(p1->x == p2->x && p1->y == p2->y && p1->z == p2->z) return;
	mx.d = p2->x - p1->x;		mx.a = mx.d >= 0 ? mx.d : -mx.d;
	mx.s = mx.d >= 0 ? 1 : -1;	mx.r = &x;		mx.l = p2->x;	x = p1->x;
	my.d = p2->y - p1->y;		my.a = my.d >= 0 ? my.d : -my.d;
	my.s = my.d >= 0 ? 1 : -1;	my.r = &y;		my.l = p2->y;	y = p1->y;
	mz.d = p2->z - p1->z;		mz.a = mz.d >= 0 ? mz.d : -mz.d;
	mz.s = mz.d >= 0 ? 1 : -1;	mz.r = &z;		mz.l = p2->z;	z = p1->z;
	if(mx.a > my.a) {
		if(mz.a > mx.a) {
			m1 = &mz;		m2 = &mx;	m3 = &my;
			}
		else if(mz.a > my.a) {
			m1 = &mx;		m2 = &mz;	m3 = &my;
			}
		else {
			m1 = &mx;		m2 = &my;	m3 = &mz;
			}
		}
	else {
		if(mz.a > my.a) {
			m1 = &mz;		m2 = &my;	m3 = &mx;
			}
		else if(mz.a > mx.a) {
			m1 = &my;		m2 = &mz;	m3 = &mx;
			}
		else {
			m1 = &my;		m2 = &mx;	m3 = &mz;
			}
		}
	bVisible = (0 != (vis = (*proc)(x, y, z)));
	if((bDrawLater = (vis == 2)) && go) go->Command(CMD_DRAW_LATER, 0L, 0L);
	lp.x = p1->x;	lp.y = p1->y;	lp.z = p1->z;
	if(!go && vis) proc_polygon(vis, p1, p1);
	d1 = m2->a - (m1->a >>1);		d2 = m3->a - (m1->a >>1);
	for(; ;) {
		//process point at (m1.r, m2.r, m3.r);
		vis = (*proc)(x, y, z);
		if(!bDrawLater && vis == 2){
			if(go) go->Command(CMD_DRAW_LATER, 0L, 0L);
			bDrawLater = true;
			}
		if(bVisible) {
			if(!vis) {
				p.x = x;	p.y = y;	p.z = z;
				if(go) go->Command(CMD_ADDTOLINE, &lp, 0L);
				else proc_polygon(vis, &p, &lp);
				bVisible = false;
				}
			}
		else if(vis){
			p.x = x;	p.y = y;	p.z = z;
			if(go) go->Command(CMD_STARTLINE, &p, 0L);
			else proc_polygon(vis, &p, &lp);
			bVisible = true;
			}
		if(*(m1->r) == m1->l){
			if(vis){
				p.x = x;	p.y = y;	p.z = z;
				if(go) go->Command(CMD_ADDTOLINE, &p, 0L);
				else proc_polygon(vis, &p, &lp);
				}
			return;
			}
		lp.x = x;	lp.y = y;	lp.z = z;
		if(d1 >= 0) {
			*(m2->r) += m2->s;	d1 -= m1->a;
			}
		if(d2 >= 0) {
			*(m3->r) += m3->s;	d2 -= m1->a;
			}
		*(m1->r) += m1->s;	d1 += m2->a;		d2 += m3->a;
		}
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//use circular Bresenham's algorithm to clip a spherical scanline
//Ref: C. Montani, R. Scopigno (1990) "Speres-To-Voxel Conversion", in:
//   Graphic Gems (A.S. Glassner ed.) Academic Press, Inc.; 
//   ISBN 0-12-288165-5 
void clip_spher_line(GraphObj *go, POINT3D *cent, int r, bool bVert, int(*proc)(int, int, int))
{
	int x, y, q, di, de, lim;
	int vis = 0, o_vis;
	POINT3D cpos;

	if(r < 1) return;
	cpos.x = cent->x;	cpos.y = cent->y;	cpos.z = cent->z;
	if(bVert) cpos.y -= r;
	else cpos.x -= r;
	for(q = 0; q < 2; q++) {
		x = lim = 0;	y = r;	di = 2*(1-r);
		while (y >= lim){
			o_vis = vis;
			if(bVert && (cpos.x < sphlim1->x || cpos.x > sphlim2->x)) vis = 0;
			else if (cpos.y < sphlim1->y || cpos.y > sphlim2->y) vis = 0;
			else if (cpos.x > 0 && cpos.y >0) vis = (*proc)(cpos.x, cpos.y, cpos.z);
			if(vis != o_vis) {
				if(vis) go->Command(CMD_STARTLINE, &cpos, 0L);
				else go->Command(CMD_ADDTOLINE, &cpos, 0L);
				}
			if(di < 0) {
				de = 2*di + 2*y -1;
				if(de > 0) {
					x++;	y--;	di += (2*x -2*y +2);
					}
				else {
					x++;	di += (2*x +1);
					}
				}
			else {
				de = 2*di -2*x -1;
				if(de > 0) {
					y--;	di += (-2*y +1);
					}
				else {
					x++;	y--;	di += (2*x -2*y +2);
					}
				}
			switch(q) {
			case 0:
				if(bVert) cpos.y = cent->y - y;
				else cpos.x = cent->x - y;
				cpos.z = cent->z + x;
				break;
			case 1:
				if(vis && y < lim) go->Command(CMD_ADDTOLINE, &cpos, 0L);
				if(bVert) cpos.y = cent->y + x;
				else cpos.x = cent->x + x;
				cpos.z = cent->z + y;
				break;
				}
			}
		}
	return;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//come here to process polygon clipping events
int ppg_vis, ppg_level, ppg_reason, ppg_firstvis, ppg_nact, ppg_nmask;
bool ppg_nowvis;
POINT *ppg_mask;
POINT3D ppg_first, *ppg_act;
GraphObj *ppg_par;
double *ppg_vec = 0L;

// test if point is on line of 3D polygon
//Ref: P.S. Heckbert (1990) "Digital Line Drawing", in: Graphic Gems
//   (A.S. Glassner, ed.); Academic Press, Inc.,
//   ISBN 0-12-286165-5
// void AddToPolygon(long *cp, POINT *pts, POINT *np);
bool IsOnLine(POINT *p1, POINT *p2, int x, int y)
{
	int d, ax, ay, sx, sy, dx, dy;
	POINT tr;

	dx = p2->x - p1->x;
	if ( p2->x < p1->x) { 	ax = (-dx)<<1;		sx = -1;		}
	else {					ax = dx <<1;		sx = 1;		}
	dy = p2->y - p1->y;
	if (p2->y < p1->y) {	ay = (-dy)<<1;		sy = -1;		}
	else {					ay = dy<<1;			sy = 1;		}
	tr.x = p1->x;			tr.y = p1->y;
	if (ax > ay) {									// x dominant
		d = ay - (ax >>1);
		for ( ; ; ) {
			if(tr.y == y && tr.x == x) return true;	//match
			if(tr.x == p2->x) return false;
			if (d >= 0) {tr.y += sy;		d -= ax;}
			tr.x += sx;		d += ay;
			}
		}
	else {											// y dominant
		d = ax - (ay >>1);
		for ( ; ; ) {
			if(tr.x == x && tr.y == y) return true;	//match
			if (tr.y == p2->y) return false;
			if (d >= 0) {tr.x += sx;		d -= ay;}
			tr.y += sy;		d += ax;
			}
		}
}

//use Bresenham's algorithm to complete a partially hidden polygon
//   by the shadow of the above surface
//Ref: P.S. Heckbert (1990) "Digital Line Drawing", in: Graphic Gems
//   (A.S. Glassner, ed.); Academic Press, Inc.,
//   ISBN 0-12-286165-5
// void AddToPolygon(long *cp, POINT *pts, POINT *np);
bool ShadowPolygon(POINT *p1, POINT *p2, POINT *tp, int ntp, POINT *pts, long *cp, POINT *lim)
{
	int d, ax, ay, sx, sy, dx, dy;
	bool bPen, vis;
	POINT tr, mp;
	long d1, ndist, dist = 99999;

	dx = p2->x - p1->x;
	if ( p2->x < p1->x) { 	ax = (-dx)<<1;		sx = -1;		}
	else {					ax = dx <<1;		sx = 1;		}
	dy = p2->y - p1->y;
	if (p2->y < p1->y) {	ay = (-dy)<<1;		sy = -1;		}
	else {					ay = dy<<1;			sy = 1;		}
	tr.x = p1->x;			tr.y = p1->y;
	bPen = IsInPolygon(&tr, tp, ntp) || IsCloseToPL(tr, tp, ntp);
	AddToPolygon(cp, pts, p1);				//first Point is always visible
	if (ax > ay) {							// x dominant
		d = ay - (ax >>1);
		for ( ; ; ) {
			if(abs(tr.y - lim->y) < 3 && abs(tr.x - lim->x) < 3) {
				ndist = (d1=(tr.y - lim->y))*d1;
				ndist += ((d1=(tr.x - lim->x))*d1);
				if(ndist <= dist) {
					mp.x = tr.x;	mp.y = tr.y;	dist = ndist;
					}
				else {
					//mp is the closest point
					AddToPolygon(cp, pts, &mp);
					return false;
					}
				}
			vis = IsInPolygon(&tr, tp, ntp) || IsCloseToPL(tr, tp, ntp);
			if(bPen && !vis) {
				AddToPolygon(cp, pts, &tr);
				return false;				//now leaving the polygon
				}
			if(tr.x == p2->x) return true;	//still inside
			if (d >= 0) {tr.y += sy;		d -= ax;}
			bPen = vis;		tr.x += sx;		d += ay;
			}
		}
	else {									// y dominant
		d = ax - (ay >>1);
		for ( ; ; ) {
			if(abs(tr.x - lim->x) < 3 && abs(tr.y - lim->y) < 3) {
				ndist = (d1=(tr.y - lim->y))*d1;
				ndist += ((d1=(tr.x - lim->x))*d1);
				if(ndist <= dist) {
					mp.x = tr.x;	mp.y = tr.y;	dist = ndist;
					}
				else {

⌨️ 快捷键说明

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