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

📄 utils.cpp

📁 Linux/windows 环境下跨平台开发程序
💻 CPP
📖 第 1 页 / 共 5 页
字号:
		default:
			if((unsigned char)str[i] <= 127) TmpTxt[j++]=str[i];
			else {
				if(mbtowc(&wc, str+i, 1) >0) j += sprintf(TmpTxt+j, 
					"&#%d;", ((unsigned short)wc));
				}
			}
		}
	TmpTxt[j] = 0;
	return(TmpTxt);
}

// split string str into array of strings using sep as separator
// return number of lines created in nl
char **split(char *str, char sep, int *nl)
{
	int i, j, k, l, ns;
	char **ptr, *txt;

	if(!str || !sep) return 0L;
	if(!(txt = strdup(str))) return 0L;
	k = (int)strlen(txt);
	for(i = ns = 0; i < k; i++) if(txt[i] == sep) ns++;
	if(!(ptr = (char**)calloc(ns+2, sizeof(char*)))){
		free(txt);	return 0L;
		}
	for(i = j = l = 0; i < k; i++) {
		if(txt[i] == sep) {
			txt[i] = 0;		ptr[l++] = strdup(txt+j);		j = i+1;
			}
		}
	ptr[l++] = strdup(txt+j);	if(nl) *nl = l;		free(txt);
	return ptr;
}

char *fit_num_rect(anyOutput *o, int max_width, char *num_str)
{
	int i, j, k, w, h, slen;
	char mant[20], expo[20], fmt[10];
	double num;

	o->oGetTextExtent(num_str, slen = strlen(num_str), &w, &h);
	if(w < (max_width-5)) return num_str;
	//first try to remove leading zero from exponent
	for(i = 0; i < slen; i++) if(num_str[i] == 'e') break;
	if(num_str[i] == 'e') while (num_str[i+2] == '0') {
		for(j = i+2; num_str[j]; j++) num_str[j] = num_str[j+1];
		o->oGetTextExtent(num_str, slen = strlen(num_str), &w, &h);
		if(w < (max_width-5)) return num_str;
		}
	//no success: reduce the number of digit by rounding
	for(i = k = 0; i <= slen; i++){
		if(num_str[i] == '.') k = i;
		if((mant[i] = num_str[i]) == 'e' || mant[i] == 0) break;
		}
	if(num_str[i] =='e') mant[i] = 0;						k = i - k-1;
	for(j = 0; num_str[i]; j++, i++) expo[j] = num_str[i];		expo[j] = 0;
	sscanf(mant, "%lf", &num);	
	if(k >0) do {
		sprintf(fmt, "%s.%dlf%s", "%", k, expo);
		sprintf(num_str, fmt, num);							k--;
		o->oGetTextExtent(num_str, slen = strlen(num_str), &w, &h);
		if(w < (max_width-5)) return num_str;
		}while (k >= 0);
	//cannot fit: return hash marks instead
	for(i = w = 0; w < (max_width-5); i++) {
		sprintf(num_str+i, "#");
		o->oGetTextExtent(num_str, slen = strlen(num_str), &w, &h);
		}
	num_str[i-1] = 0;		return num_str;
}

//----------------------------------------------------------------------------
// bounding rectangle utilities
//----------------------------------------------------------------------------
void SetMinMaxRect(RECT *rc, int x1, int y1, int x2, int y2)
{
	if(x1 > x2) {
		rc->left = x2;		rc->right = x1;
		}
	else {
		rc->left = x1;		rc->right = x2;
		}
	if(y1 > y2) {
		rc->top = y2;		rc->bottom = y1;
		}
	else {
		rc->top = y1;		rc->bottom = y2;
		}
}

void UpdateMinMaxRect(RECT *rc, int x, int y)
{
	if(x < rc->left) rc->left = x;
	if(x > rc->right) rc->right = x;
	if(y < rc->top) rc->top = y;
	if(y > rc->bottom) rc->bottom = y;
}

void IncrementMinMaxRect(RECT *rc, int i)
{
	rc->left -= i;			rc->right += i;
	rc->top -= i;			rc->bottom += i;
}

bool IsInRect(RECT *rc, int x, int y)
{
	if(x < rc->left || x > rc->right || 
		y < rc->top || y > rc->bottom) return false;
	return true;
}

//----------------------------------------------------------------------------
// test if point (e.g. mouse position) is close to or iside a shape
//----------------------------------------------------------------------------
bool IsCloseToLine(POINT *p1, POINT *p2, int x, int y)
{
	bool bFound = false;
	int tmp, dx, dy;

	//do not process single point
	if(p1->x == p2->x && p1->y == p2->y) return false;
	//point must be bracketed by p1:p2
	if((x-2) > p1->x && (x-2) > p2->x) return false;
	if((x+2) < p1->x && (x+2) < p2->x) return false;
	if((y-2) > p1->y && (y-2) > p2->y) return false;
	if((y+2) < p1->y && (y+2) < p2->y) return false;
	if(abs(dx = (p2->x - p1->x)) < abs(dy = (p2->y - p1->y))) {	//y dominant
		tmp = (p1->x + ((y - p1->y) * dx)/dy);
		if(x > (tmp-3) && x < (tmp+3)) bFound = true;
		}
	else {							// x dominant
		tmp = (p1->y + ((x - p1->x) * dy)/dx);
		if(y > (tmp-3) && y < (tmp+3)) bFound = true;
		}
	return bFound;
}

bool IsCloseToPL(POINT p, POINT *pts, int cp)
{
	int i;

	for( i = 1; i < cp; i++) if(IsCloseToLine(pts+i-1, pts+i, p.x, p.y)) return true;
	return false;
}

//test if poitn p is within the polygon pts of size cp
//note: the last point of the polypon should be equal to the first point,
//   i.e. the polygon must be closed
int idx_point_on_line;
bool IsInPolygon(POINT *p, POINT *pts, int cp)
{
	int tmp1 = 0, tmp2 = 0, tmp3, i;

	for(i = 1; i < cp; i++) {
		if((pts[i-1].x <= p->x && pts[i].x > p->x) || (pts[i-1].x > p->x && pts[i].x <= p->x)) {
			tmp3 = ((p->x - pts[i-1].x)*(pts[i].y -pts[i-1].y))/(pts[i].x - pts[i-1].x);
			tmp3 += pts[i-1].y;
			if(p->y > tmp3) tmp1++;
			else if(p->y < tmp3) tmp2++;
			else return false;			//ignore points on the line
			}
		}
	return((tmp1 & 0x1) && (tmp2 & 0x1));
}

bool IsInPolygon3D(double x, double y, POINT3D *pts, int cp, int *us, int *ls)
{
	int tmp1 = 0, tmp2 = 0, i, idx1, idx2;
	double tmp3;

	for(i = 1, idx1 = idx2 = -1; i < cp; i++) {
		if((pts[i-1].x <= x && pts[i].x > x) || (pts[i-1].x > x && pts[i].x <= x)) {
			tmp3 = ((x - pts[i-1].x)*(pts[i].y -pts[i-1].y))/(pts[i].x - pts[i-1].x);
			tmp3 += pts[i-1].y;
			if(y > tmp3){
				tmp1++;				idx1 = i;
				}
			else if(y < tmp3) {
				tmp2++;				idx2 = i;
				}
			else {			//points is on the line
				idx1 = idx2 = idx_point_on_line = i;
				if(us) *us = idx1;		if(ls) *ls = idx2;
				return true;
				}
			}
		}
	//return an index to the bracketing sgments of the polygon
	if(us) *us = idx1;			if(ls) *ls = idx2;
	return((tmp1 & 0x1) && (tmp2 & 0x1));
}

//return true if two rectangles overlap
bool OverlapRect(RECT *rc1, RECT *rc2)
{
	if((rc1->left < rc2->right && rc1->right > rc2->left) ||
		(rc2->left < rc1->right && rc2->right > rc1->left)) {
		if((rc1->top < rc2->bottom && rc1->bottom > rc2->top) ||
			(rc2->top < rc1->bottom && rc2->bottom > rc1->top))
			return true;
		}
	return false;
}

//----------------------------------------------------------------------------
// collect points to a polygon
// keep number of points low by extrapolation
//----------------------------------------------------------------------------
void AddToPolygon(long *cp, POINT *pts, POINT *np)
{
	int ix, iy;
	long i = *cp;

	if(i && pts[i-1].x == np->x && pts[i-1].y == np->y) return;
	if(i < 2) {					//accept first points of polygon
		pts[i].x = np->x;	pts[i].y = np->y;	*cp = i+1;
		return;
		}
	if(pts[i-1].x == pts[i-2].x && pts[i-1].x == np->x) {
		if(np->y == pts[i-1].y) return;
		if((np->y > pts[i-1].y && pts[i-1].y > pts[i-2].y) ||
			(np->y < pts[i-1].y && pts[i-1].y < pts[i-2].y)) {
			pts[i-1].x = np->x;
			pts[i-1].y = np->y;
			return;
			}
		}
	if(pts[i-1].y == pts[i-2].y && pts[i-1].y == np->y) {
		if(np->x == pts[i-1].x) return;
		if((np->x > pts[i-1].x && pts[i-1].x > pts[i-2].x) ||
			(np->x < pts[i-1].x && pts[i-1].x < pts[i-2].x)) {
			pts[i-1].x = np->x;
			pts[i-1].y = np->y;
			return;
			}
		}
	//try linear extrapolation
	if((pts[i-1].x > pts[i-2].x && np->x > pts[i-1].x) ||
		(pts[i-1].x < pts[i-2].x && np->x < pts[i-1].x)) {
		ix = (pts[i-1].y != pts[i-2].y) ? (pts[i-2].x + ((np->y - pts[i-2].y) * 
			(pts[i-1].x - pts[i-2].x))/(pts[i-1].y - pts[i-2].y)) : 0;
		iy = (pts[i-1].x != pts[i-2].x) ? (pts[i-2].y + ((np->x - pts[i-2].x) * 
			(pts[i-1].y - pts[i-2].y))/(pts[i-1].x - pts[i-2].x)) : 0;
		if((ix && ix == np->x) || (iy && iy == np->y)) {
			pts[i-1].x = np->x;
			pts[i-1].y = np->y;
			return;
			}
		}
	//not explained by extrapolation, accept new point
	pts[i].x = np->x;
	pts[i].y = np->y;
	*cp = i+1;
	return;
}

//----------------------------------------------------------------------------
// create a circular polygon
//use circular Bresenham's algorithm to draw arcs
//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 
//----------------------------------------------------------------------------
POINT *MakeArc(int ix, int iy, int r, int qad, long *npts)
{
	int i, x, y, di, de, lim;
	static POINT *pts, *rpts;
	POINT np;

	if(r < 1) return 0L;
	if(!(pts = (POINT*) malloc((r+1)*8*sizeof(POINT))))return 0L;
	for(i = *npts = 0; i < 4; i++) {
		x = lim = 0;	y = r;	di = 2*(1-r);
		if(qad & (1<<i))while (y >= lim){
			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(i) {
			case 0:	np.x = ix-y;	np.y = iy+x;	break;
			case 1: np.x = ix+x;	np.y = iy+y;	break;
			case 2: np.x = ix+y;	np.y = iy-x;	break;
			case 3:	np.x = ix-x;	np.y = iy-y;	break;
				}
			AddToPolygon(npts, pts, &np);
			}
		}
	if(*npts < 3) return 0L;
	if(rpts = (POINT*)realloc(pts, sizeof(POINT)*(*npts))) return rpts;
	return pts;
}

//----------------------------------------------------------------------------
// display a marked polygon by displaying it with complement colors
//----------------------------------------------------------------------------
void InvertPolygon(POINT *pts, int nPts, LineDEF *Line, FillDEF *Fill, RECT *rc, 
	anyOutput *o, bool mark)
{
	LineDEF *FillLine;

	if(!Line || !Fill || !rc || !o) return;
	FillLine = Fill->hatch;
	if(mark) {
		if(FillLine)FillLine->color ^= 0x00ffffffL;
		Fill->color ^= 0x00ffffffL;
		Line->color ^= 0x00ffffffL;
		o->SetLine(Line);
		o->SetFill(Fill);
		o->oPolygon(pts, nPts);
		Fill->color ^= 0x00ffffffL;
		if(FillLine)FillLine->color ^= 0x00ffffffL;
		Line->color ^= 0x00ffffffL;
		InvertLine(pts, nPts, Line, 0L, o, mark);
		}
	else {
		InvertLine(pts, nPts, Line, 0L, o, mark);
		o->SetLine(Line);
		o->SetFill(Fill);
		o->oPolygon(pts, nPts);
		}
	if(rc) o->UpdateRect(rc, false);
}

//----------------------------------------------------------------------------
// display a marked line using complement colors
//----------------------------------------------------------------------------
void InvertLine(POINT *pts, int nPts, LineDEF *Line, RECT *rc, 
	anyOutput *o, bool mark)
{
	LineDEF OldLine;
	double minw = defs.GetSize(SIZE_DATA_LINE);

	memcpy(&OldLine, Line, sizeof(LineDEF));
	if(OldLine.width <= 0.001) memcpy(&OldLine, defs.GetLine(), sizeof(LineDEF));
	OldLine.color = mark ? Line->color : 0x00ffffffL;
	OldLine.width = OldLine.width < minw ? minw * 3.0 : OldLine.width *3.0;
	o->SetLine(&OldLine);
	o->oPolyline(pts, nPts);
	OldLine.width = Line->width;
	OldLine.color = mark ? Line->color ^ 0x00ffffffL : Line->color;
	o->SetLine(&OldLine);
	o->oPolyline(pts, nPts);
	if(rc) o->UpdateRect(rc, false);
}

//----------------------------------------------------------------------------
// color utilitis
//----------------------------------------------------------------------------
// calculate distance between two colors
unsigned int ColDiff(DWORD col1, DWORD col2)
{
	int ret = 0, d;

	d = (col1 & 0xff) - (col2 & 0xff);
	ret = isqr(d*d);
	d = ((col1>>8) & 0xff) - ((col2>>8) & 0xff);
	ret += isqr(d*d);
	d = ((col1>>16) & 0xff) - ((col2>>16) & 0xff);
	ret += isqr(d*d);
	return ret;	
}

//----------------------------------------------------------------------------
// interpolate between two colors
DWORD IpolCol(DWORD color1, DWORD color2, double fact)
{
	DWORD col1, col2, col3, c1;
	int i;

	col1 = color1;	col2 = color2;	col3 = 0x0L;
	for(i = 0; i < 3; i++) {
		c1 = iround(fabs(((col1 & 0xff0000)>>16) * fact));
		c1 += iround(fabs(((col2 & 0xff0000)>>16) *(1.0-fact)));
		col3 |= c1 < 0xff ? c1 : 0xff;
		col1 <<= 8;	col2 <<= 8; 
		if(i < 2) col3 <<= 8;
		}
	return col3;
}

//----------------------------------------------------------------------------
// Random number generator with low sequential correlations.
// ran2 returns a number betwee 0.0f and 1.0f;
// Ref: W.H. Press, B.P. Flannery, S.A. Teukolsky, W.T. Veterling
// Numerical Recipe in C, The Art of Scientific Computing
// Cambridge University Press 1988, ISBN 0-521-35465-X
//----------------------------------------------------------------------------
#define M 714025
#define IA 1366
#define IC 150889
double ran2(long *idum)

⌨️ 快捷键说明

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