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

📄 utils.cpp

📁 Linux/windows 环境下跨平台开发程序
💻 CPP
📖 第 1 页 / 共 5 页
字号:
{
	static long iy, ir[98];
	static int iff = 0;
	int j;

	if(*idum < 0 || iff == 0) {
		iff = 1;
		if((*idum = (IC-(*idum)) % M) < 0) *idum = -(*idum);
		for(j = 1; j <= 97; j++) {
			*idum = (IA*(*idum)+IC) % M;
			ir[j] = (*idum);
			}
		*idum=(IA*(*idum)+IC) % M;
		iy=(*idum);
		}
	j = 1+97 * iy/M;
	if(j > 97 || j< 1) return 0.0f;		//impossible
	iy = ir[j];
	*idum = (IA*(*idum)+IC) % M;
	ir[j] = (*idum);
	return (float) iy/M;
}
#undef IC
#undef IA
#undef M

//----------------------------------------------------------------------------
// integer square root
// calculate the largest number <= sqr(n)
// Christopher J. Musial in Graphics Gems II, page 37ff, page 610
// Academic Press, 1991
// modified
//----------------------------------------------------------------------------

unsigned long int isqr(unsigned long int n)
{
	unsigned long int nextTrial, decrement;

	if (nextTrial = n>>1) {
		for ( ; ; ){
			if(decrement = (nextTrial - n/nextTrial)>>1) nextTrial -= decrement;
			else if(nextTrial * nextTrial > n) return nextTrial-1;
			else return nextTrial;
			}
		}
	return n;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// multiply two rotation matrices
//  see: Graphic Gems, A.S. Glassner ed.; Academic Press Inc.
//  ISBN 0-12-286165-5, p.640
//
bool MatMul(double a[3][3], double b[3][3], double c[3][3])
{
	int i, j, k;
	bool success = true;

	for(i = 0; i < 3; i++) {
		for (j = 0; j < 3; j++) {
			c[i][j] = 0.0;
			for(k = 0; k < 3; k++) c[i][j] += a[i][k] * b[k][j];
			if(c[i][j] < -.99999 || c[i][j] > .99999) success = false;
			}
		}
	return success;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//Return a format string depending on the range
//
char *GetNumFormat(double Magn)
{
	if(Magn < -3.0) return("%0.2le");
	if(Magn == -3.0) return("%0.4lf");
	if(Magn == -2.0) return("%0.3lf");
	if(Magn == -1.0) return("%0.2lf");
	if(Magn == 0.0) return("%0.1lf");
	if(Magn >= 5.0) return("%0.2le");
	return("%0.0lf");
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//Delete a graphic object using the Id member of the class to select the 
//   the proper destructor
void DeleteGO(GraphObj *go)
{
	if(!go) return;
	if(!go->Id) {
		//this will also set the Id member of the class
		go->Command(CMD_SET_DATAOBJ, 0L, 0L);
		}
	if(go == CurrGO) CurrGO = 0L;
	switch(go->Id) {
	case GO_AXIS:			delete((Axis*)go);			break;
	case GO_TICK:			delete((Tick*)go);			break;
	case GO_GRIDLINE:		delete((GridLine*)go);		break;
	case GO_GRIDLINE3D:		delete((GridLine3D*)go);	break;
	case GO_SYMBOL:			delete((Symbol*)go);		break;
	case GO_BUBBLE:			delete((Bubble*)go);		break;
	case GO_BAR:			delete((Bar*)go);			break;
	case GO_ERRBAR:			delete((ErrorBar*)go);		break;
	case GO_ARROW:			delete((Arrow*)go);			break;
	case GO_BOX:			delete((Box*)go);			break;
	case GO_WHISKER:		delete((Whisker*)go);		break;
	case GO_DROPLINE:		delete((DropLine*)go);		break;
	case GO_DATALINE:
		//we call ~DataLine for ~DataPolygon because variables are
		//   initialized in DataLine ??!!??!!
		//   otherwise we would crash with ~DataPolygon.
	case GO_DATAPOLYGON:	delete((DataLine*)go);		break;
	case GO_SPHERE:			delete((Sphere*)go);		break;
	case GO_PLANE:			delete((plane*)go);			break;
	case GO_BRICK:			delete((Brick*)go);			break;
	case GO_LINE3D:			delete((Line3D*)go);		break;
	case GO_LABEL:			delete((Label*)go);			break;
	case GO_MLABEL:			delete((mLabel*)go);		break;
	case GO_SEGMENT:		delete((segment*)go);		break;
	case GO_POLYGON:
	case GO_POLYLINE:		delete((polyline*)go);		break;
	case GO_REGLINE:		delete((RegLine*)go);		break;
	case GO_SDELLIPSE:		delete((SDellipse*)go);		break;
	case GO_ELLIPSE:		
	case GO_ROUNDREC:
	case GO_RECTANGLE:		delete((rectangle*)go);		break;
	case GO_DRAGHANDLE:		delete((dragHandle*)go);	break;
	case GO_DRAGRECT:		delete((dragRect*)go);		break;
	case GO_DRAG3D:			delete((Drag3D*)go);		break;
	case GO_FRAMERECT:		delete((FrmRect*)go);		break;
	case GO_PLOT:			delete((Plot*)go);			break;
	case GO_BARCHART:
	case GO_PLOTSCATT:		delete((PlotScatt*)go);		break;
	case GO_REGRESSION:		delete((Regression*)go);	break;
	case GO_BUBBLEPLOT:		delete((BubblePlot*)go);	break;
	case GO_BOXPLOT:		delete((BoxPlot*)go);		break;
	case GO_DENSDISP:		delete((DensDisp*)go);		break;
	case GO_STACKBAR:
	case GO_WATERFALL:
	case GO_STACKPG:		delete((StackBar*)go);		break;
	case GO_POLARPLOT:		delete((PolarPlot*)go);		break;
	case GO_RINGCHART:
	case GO_PIECHART:		delete((PieChart*)go);		break;
	case GO_GROUP:
	case GO_STARCHART:		delete((GoGroup*)go);		break;
	case GO_SCATT3D:		delete((Scatt3D*)go);		break;
	case GO_PLOT3D:			delete((Plot3D*)go);		break;
	case GO_PAGE:
	case GO_GRAPH:			delete((Graph*)go);			break;
	case GO_SVGOPTIONS:		delete((svgOptions*)go);	break;
	case GO_DROPL3D:		delete((DropLine3D*)go);	break;
	case GO_ARROW3D:		delete((Arrow3D*)go);		break;
	case GO_LIMITS:			delete((Limits*)go);		break;
	case GO_GRIDRADIAL:		delete((GridRadial*)go);	break;
	case GO_DEFRW:			delete((DefsRW*)go);		break;
	case GO_PLANE3D:		delete((Plane3D*)go);		break;
	case GO_RIBBON:			delete((Ribbon*)go);		break;
	case GO_FUNCTION:		delete((Function*)go);		break;
	case GO_FITFUNC:		delete((FitFunc*)go);		break;
	case GO_LEGITEM:		delete((LegItem*)go);		break;
	case GO_LEGEND:			delete((Legend*)go);		break;
	case GO_OBJTREE:		delete((ObjTree*)go);		break;
	case GO_FREQDIST:		delete((FreqDist*)go);		break;
	case GO_GRID3D:			delete((Grid3D*)go);		break;
	case GO_FUNC3D:			delete((Func3D*)go);		break;
	case GO_XYSTAT:			delete((xyStat*)go);		break;
	default:
		sprintf(TmpTxt, "Cannot delete Object\nwith Id %ld", go->Id);
		ErrorBox(TmpTxt);
		//we do not delete the object, probably we recover
		}
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//Delete a graphic object from a list 
bool DeleteGOL(GraphObj ***gol, long n, GraphObj *go, anyOutput *o)
{
	long i;
	int c;
	GraphObj **g, *p;

	if(!gol || !(*gol) || !go || !n) return false;
	for (i = 0, c = 0, g = *gol; i < n; i++, g++) {
		if(*g) {
			c++;
			if(*g == go) {
				p = (*g)->parent;
				if(o) o->HideMark();
				Undo.DeleteGO(g, 0L, o);
				if(c == 1) {
					for (g++, i++ ;i < n; i++, g++) {
						if(*g) return true;
						}
					if(p) Undo.DropMemory(p, (void**) gol, UNDO_CONTINUE);
					}
				return true;
				}
			}
		}
	return false;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//backup file before writing a new one
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
bool BackupFile(char *FileName)
{
	int i;
	FILE *TheFile;
	char TmpFileName[512], Name[512], ext[6];

	//no backup necessary if file does not exist
	if(!(FileExist(FileName))) return true;
	strcpy(Name, FileName);
	i = strlen(Name)-1;
	if(Name[--i] == '.') Name[i] = 0;
	else if(Name[--i] == '.') Name[i] = 0;
	else if(Name[--i] == '.') Name[i] = 0;
	else return false;
	i = 1;
	do {
		sprintf(ext, ".%03d", i);
		sprintf(TmpFileName, "%s%s", Name, ext);
		if((TheFile = fopen(TmpFileName, "r"))) fclose(TheFile);
		i++;
	} while (i < 999 && TheFile);
	if(i >= 999) {								//too many backups exist already
		ErrorBox("Too many backup\files exist already.");
		return false;
		}
	if(-1 == rename(FileName, TmpFileName)) {
		ErrorBox("Error accessing file.");
		return false;
		}
	return true;
}

bool IsRlpFile(char *FileName)
{
	FILE *TheFile;
	char Line[10];
	bool bRet = false;

	if(0L ==(TheFile = fopen(FileName, "r"))) return false;
	fread(Line, 1, 8, TheFile);
	Line[5] = 0;
	if(0 == strcmp(Line, ";RLP "))bRet = true;
	fclose(TheFile);
	return bRet;
}

bool IsXmlFile(char *FileName)
{
	FILE *TheFile;
	char Line[10];
	bool bRet = false;

	if(0L ==(TheFile = fopen(FileName, "r"))) return false;
	fread(Line, 1, 8, TheFile);
	Line[6] = 0;
	if(0 == strcmp(Line, "<?xml "))bRet = true;
	fclose(TheFile);
	return bRet;
}

bool FileExist(char *FileName)
{
	FILE *TheFile;

	if(0L ==(TheFile = fopen(FileName, "r"))) return false;
	fclose(TheFile);
	return true;
}


//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//check Object for certain properties
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
bool IsPlot3D(GraphObj *g)
{
	if(g && (g->Id == GO_PLOT3D || g->Id == GO_FUNC3D)) return true;
	return false;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//duplicate a block of memory
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
void *memdup(void *ptr, int cb_old, int cb_new)
{
	void *p;

	if(cb_new > cb_old) {
		if((p = calloc(cb_new, 1)) && ptr) memcpy(p, ptr, cb_old);
		}
	else {
		if((p = malloc(cb_old)) && ptr) memcpy(p, ptr, cb_old);
		}
	return p;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//calculate angle from sin(angle)
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
double trig2deg(double si, double csi)
{
	double ang;

	ang = acos(csi);
	if(si < 0.0) ang *= -1.0;
	return floor(ang * 57.29577951 +0.5);
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//replace graphic object with new: typically used for undo
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
bool ReplaceGO(GraphObj **oldobj, GraphObj **newobj)
{
	newobj[1]->parent = newobj[0]->parent;
	newobj[1]->Command(CMD_SET_DATAOBJ, newobj[0]->data, 0L);
	*oldobj = newobj[1];
	newobj[0]->parent = 0L;		//disable messaging
	Undo.InvalidGO(newobj[0]);
	DeleteGO(newobj[0]);
	return true;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//calculate a 'unique' hash value for a string
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
unsigned int HashValue(unsigned char *str)
{
	unsigned int i = 0, ret=0;

	if(!str) return 0;
	do {
		if(str[i] > 32) ret = ((str[i]-32) + (ret <<2));
		i++;
		}while(str[i]);
	if(i < 4) memcpy(&ret, str, i);
	return ret;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//compare data structures: return true if changed or save undo info
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
bool cmpLineDEF(LineDEF *l1, LineDEF *l2)
{
	if(!l1 || !l2 || l1 == l2) return false;	//oh, oh !
	if(l1->width != l2->width) return true;
	if(l1->patlength != l2->patlength) return true;
	if(l1->color != l2->color) return true;
	if(l1->pattern != l2->pattern) return true;
	return false;
}

bool cmpFillDEF(FillDEF *f1, FillDEF *f2)
{
	if(!f1 || !f2 || f1 == f2) return false;	//oh, oh!
	if(f1->type != f2->type || f1->color != f2->color ||
		f1->scale != f2->scale || f1->color2 != f2->color2) return true;
	//the hatch line is subject to a separate call to cmpLineDEF
	return false;
}

bool cmpAxisDEF(AxisDEF *a1, AxisDEF *a2)
{
	int i;

	if(!a1 || !a2 || a1 == a2) return false;	//oh, oh!
	if(a1->flags != a2->flags || a1->min != a2->min || a1->max != a2->max ||
		a1->loc[0].fx != a2->loc[0].fx || a1->loc[0].fy != a2->loc[0].fy ||
		a1->loc[0].fz != a2->loc[0].fz || a1->loc[1].fx != a2->loc[1].fx ||
		a1->loc[1].fy != a2->loc[1].fy || a1->loc[1].fz != a2->loc[1].fz ||
		a1->Start != a2->Start || a1->Step != a2->Step || a1->Radius != a2->Radius ||
		a1->Center.fx != a2->Center.fx || a1->Center.fy != a2->Center.fy ||
		a1->nBreaks != a2->nBreaks) return true;
	for(i = 0; i < a1->nBreaks; i++) {
		if(a1->breaks[i].fx != a2->breaks[i].fx ||
			a1->breaks[i].fy != a2->breaks[i].fy) return true;
		}
	return false;
}

bool cmpTextDEF(TextDEF *t1, TextDEF *t2)
{
	if(!t1 || !t2) return false;
	if(t1->ColTxt != t2->ColTxt || t1->ColBg != t2->ColBg || t1->fSize != t2->fSize ||
		t1->RotBL != t2->RotBL || t1->RotCHAR != t2->RotCHAR || t1->iSize != t2->iSize ||
		t1->Align != t2->Align || t1->Mode != t2->Mode || t1->Style != t2->Style ||
		t1->Font != t2->Font) return true;
	if((!(t1->text) && (t2->text)) || (!(t2->text) && (t1->text))) return true;
	if(t1->text && t2->text && strcmp(t1->text, t2->text)) return true;
	return false;
}

// Dialog Undo utilitites
DWORD CheckNewFloat(double *loc, double old_v, double new_v, GraphObj *par, DWORD flags)
{
	if(loc && old_v != new_v) {
		Undo.ValFloat(par, loc, flags);
		*loc = new_v;						return (flags | UNDO_CONTINUE);
		}
	return flags;
}

DWORD CheckNewInt(int *loc, int old_v, int new_v, GraphObj *par, DWORD flags)
{

⌨️ 快捷键说明

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