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

📄 utils.cpp

📁 Linux/windows 环境下跨平台开发程序
💻 CPP
📖 第 1 页 / 共 5 页
字号:
//Utils.cpp, Copyright (c) 2000, 2001, 2002, 2003, 2004, 2005 R.Lackner
//Collection of utility functions and classes for RLPlot
//
//    This file is part of RLPlot.
//
//    RLPlot is free software; you can redistribute it and/or modify
//    it under the terms of the GNU General Public License as published by
//    the Free Software Foundation; either version 2 of the License, or
//    (at your option) any later version.
//
//    RLPlot is distributed in the hope that it will be useful,
//    but WITHOUT ANY WARRANTY; without even the implied warranty of
//    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//    GNU General Public License for more details.
//
//    You should have received a copy of the GNU General Public License
//    along with RLPlot; if not, write to the Free Software
//    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
//
#include <math.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "rlplot.h"

extern GraphObj *CurrGO;			//Selected Graphic Objects
extern Label *CurrLabel;
extern Default defs;
extern UndoObj Undo;

char TmpTxt[TMP_TXT_SIZE];

//----------------------------------------------------------------------------
// Get the rectanpular part of bitmap. Used for screen updates
//----------------------------------------------------------------------------
anyOutput *GetRectBitmap(RECT *rc, anyOutput *src)
{
	RECT cr;
	anyOutput *bm;

	if(!rc || !src) return 0L;
	src->ActualSize(&cr);
	if(rc->left < cr.left) rc->left = cr.left;
	if(rc->right > cr.right) rc->right = cr.right;
	if(rc->top < cr.top) rc->top = cr.top;
	if(rc->bottom > cr.bottom) rc->bottom = cr.bottom;
	if(rc->left == rc->right) return 0L;
	if(rc->top == rc->bottom) return 0L;
	if(!(bm = NewBitmapClass(rc->right - rc->left, rc->bottom - rc->top, 
		src->hres, src->vres)))return 0L;
	bm->CopyBitmap(0, 0, src, rc->left, rc->top, rc->right - rc->left, 
		rc->bottom - rc->top, false);
	return bm;
}

void RestoreRectBitmap(anyOutput **pmo, RECT *mrc, anyOutput *o)
{
	if(pmo && *pmo && o && mrc) {
		o->CopyBitmap(mrc->left, mrc->top, *pmo, 0, 0, mrc->right - mrc->left, 
			mrc->bottom - mrc->top, false);
		DelBitmapClass(*pmo);		*pmo = 0L;
		o->UpdateRect(mrc, false);
		}
}

//----------------------------------------------------------------------------
// Axis utility functions
//----------------------------------------------------------------------------
void NiceAxis(AxisDEF *axis, int nTick)
{
	double diff, logStep, Step, Magn, LoVal, HiVal;
	int i;

	axis->Start = axis->min;
	axis->Step = (axis->max - axis->min)/((double)nTick);
	diff = axis->max - axis->min;
	if(axis->breaks) for(i = 0; i < axis->nBreaks; i++) {
		diff -= fabs(axis->breaks[i].fy - axis->breaks[i].fx);
		}
	if(diff <= 0.0) return;
	logStep = log10(diff/(double)nTick);
	Magn = floor(logStep);
	logStep -= Magn;
	Step = 1.0;
	if(logStep > 0.301) Step = 2.0; 
	if(logStep > 0.699) Step = 5.0;
	Step *= pow(10.0, Magn);
	HiVal = LoVal = Step * floor(axis->min/Step);
	axis->max *=1.05f;
	while(HiVal < axis->max) HiVal += Step;
	axis->min = LoVal;
	axis->max = HiVal;
	axis->Start = axis->min;
	axis->Step = Step;
}

void NiceStep(AxisDEF *axis, int nTick)
{
	double diff, logStep, Step, Magn;
	int i;

	diff = axis->max - axis->min;
	if(axis->breaks) for(i = 0; i < axis->nBreaks; i++) {
		diff -= fabs(axis->breaks[i].fy - axis->breaks[i].fx);
		}
	if(diff < 0.0) return;
	logStep = log10(diff/(double)nTick);
	Magn = floor(logStep);
	logStep -= Magn;
	Step = 1.0;
	if(logStep > 0.301) Step = 2.0; 
	if(logStep > 0.699) Step = 5.0;
	Step *= pow(10.0, Magn);
	axis->Step = Step;
}

double base4log(AxisDEF *axis, int direc)
{
	double lv, Step = 1.0, Magn;
	int cmd;

	switch (direc) {
	case 0:		cmd = SIZE_BOUNDS_XMIN;		break;
	case 1:		cmd = SIZE_BOUNDS_YMIN;		break;
	case 2:		cmd = SIZE_BOUNDS_ZMIN;		break;
	default:	return 1.0;
		}
	if(axis->min > defs.min4log) lv = axis->min;
	else lv = ((GraphObj*)axis->owner)->GetSize(cmd);
	if(lv <= defs.min4log) return defs.min4log;
	lv = log10(lv);
	lv -= (Magn = floor(lv));
	if(lv > 0.301) Step = 2.0; 
	if(lv > 0.699) Step = 5.0;
	Step *= pow(10.0, Magn);
	return Step > defs.min4log ? Step : 1.0;
}

double TransformValue(AxisDEF *axis, double val, bool transform)
{
	int i;
	double f1, f2, RetVal = val;

	if(!axis) return val;
	if(axis->breaks) {
		for (i = 0; i < axis->nBreaks; i++) {
			f1 = axis->breaks[i].fx;	f2 = axis->breaks[i].fy;
			if(val > f2) RetVal -= (f2-f1);
			else if(val > f1 && val <= f2) RetVal -= (val-f1);
			}
		}
	else (axis->nBreaks = 0);
	if(transform) {
		switch(axis->flags & 0x7000L) {
		case AXIS_LINEAR:	break;
		case AXIS_LOG:
			if(axis->flags & AXIS_RADIAL) RetVal = fabs(RetVal);
			RetVal = RetVal > defs.min4log ? log10(RetVal): log10(defs.min4log);
			break;
		case AXIS_RECI:		RetVal = RetVal > defs.min4log || RetVal < - defs.min4log ?
				1.0/RetVal : 0.0;		break;
		case AXIS_SQR:		RetVal = RetVal >= 0.0 ? sqrt(RetVal) : 0.0;					break;
			}
		}
	return RetVal;
}

void SortAxisBreaks(AxisDEF *axis)
{
	int i, j;
	double ftmp;
	bool sorted;

	if(!axis || !axis->nBreaks || !axis->breaks) return;
	//low values first
	for(i = 0; i < axis->nBreaks; i++) {
		if(axis->breaks[i].fy < axis->breaks[i].fx) {
			ftmp = axis->breaks[i].fx;
			axis->breaks[i].fx = axis->breaks[i].fy;
			axis->breaks[i].fy = ftmp;
			}
		}
	//a simple bubble sort should do
	if(axis->nBreaks >1) do {
		sorted = true;
		for(i = 1; i < axis->nBreaks; i++) {
			if(axis->breaks[i-1].fx > axis->breaks[i].fx) {
				ftmp = axis->breaks[i-1].fx;
				axis->breaks[i-1].fx = axis->breaks[i].fx;
				axis->breaks[i].fx = ftmp;
				ftmp = axis->breaks[i-1].fy;
				axis->breaks[i-1].fy = axis->breaks[i].fy;
				axis->breaks[i].fy = ftmp;
				sorted = false;
				}
			}
		}while(!sorted);
	//combine overlapping ranges
	if((j = axis->nBreaks) >1) for(i = j = 1; i < axis->nBreaks; i++) {
		if(axis->breaks[i].fx > axis->breaks[j-1].fy) {
			axis->breaks[j].fx = axis->breaks[i].fx;
			axis->breaks[j].fy = axis->breaks[i].fy;
			j++;
			}
		else {
			j--;
			axis->breaks[j++].fy = axis->breaks[i].fy;
			}
		}
	axis->nBreaks = j;
}

double GetAxisFac(AxisDEF *axis, double delta, int direc)
{
	double da, v1, v2;

	switch(axis->flags & 0x7000L) {
	case AXIS_LOG:		
		axis->max = axis->max > defs.min4log ? log10(axis->max): log10(defs.min4log);
		axis->min = axis->min > defs.min4log ? log10(axis->min): 
			log10(base4log(axis, direc));
		if(axis->max <= axis->min) axis->max = axis->min +1.0;
		break;
	case AXIS_RECI:
		v1 = fabs(axis->min) >defs.min4log ? axis->min :
			base4log(axis, direc);
		if(fabs(v1) > defs.min4log) v1 = 1.0/v1;
		else v1 = 1.0e+34;
		if(fabs(axis->max) >defs.min4log) v2 = 1.0/axis->max;
		else v2 = 0.0;
		if(fabs(v2) < fabs(v1/10.0)) v2 = 0.0;
		axis->min = v2;		axis->max = v1;
		break;
	case AXIS_SQR:
		axis->max = axis->max > defs.min4log ? sqrt(axis->max) : 0.0;
		axis->min = axis->min > defs.min4log ? sqrt(axis->min) : 0.0;
		break;
		}
	v2 = TransformValue(axis, axis->max, false);	//process breaks
	v1 = TransformValue(axis, axis->min, false);
	da = v2 != v1 ? v2 - v1 : 1.0;
	return delta / da;
}

//----------------------------------------------------------------------------
// Text utility functions: internationalization and formats
//----------------------------------------------------------------------------
// restyle formula
void ReshapeFormula(char **text)
{
	int i, j, l;

	if(!text || !*text || !**text) return;
	l = strlen(*text);
	for(i = j = 0; i < l; i++) {
		if((*text)[i] == ';') {
			if((*text)[i+1] == ';' || (*text)[i+1] == '\n') i++;
			}
		TmpTxt[j++] = (*text)[i];
		}
	TmpTxt[j] = 0;
	if((int)strlen(TmpTxt) < l && TmpTxt[0]) {
		free(*text);	*text = strdup(TmpTxt);	
		}
}

void CleanTags(char *txt, int *i1, int *i2, int *i3)
{
	char *no_tags[] = {"<b></b>", "</b><b>", "<b><b>", "</b></b>",
		"<i></i>", "</i><i>", "<i><i>", "</i></i>", "<u></u>",
		"</u><u>", "<u><u>", "</u></u>", "<sub></sub>",
		"</sub><sub>", "<sup></sup>", "</sup><sup>", 
		0L};
	int i, j, k, l, w;
	bool na;

	for(i = j = 0; txt[i]; i++) {
		if(txt[i] != '<') txt[j++] = txt[i];
		else {
			for(k = 0, na = true; no_tags[k]; k++) {
				for(l=1; no_tags[k][l] && txt[i+l]; l++) 
					if(no_tags[k][l] != txt[i+l]) break;
				if(!no_tags[k][l]){
					na = false;
					i += ((w=strlen(no_tags[k]))-1);
					if(i1 && *i1 > i) *i1 -= w;
					if(i2 && *i2 > i) *i2 -= w;
					if(i3 && *i3 > i) *i3 -= w;
					break;
					}
				}
			if(na) txt[j++] = txt[i];
			}
		}
	txt[j++] = 0;
}

//replace one character in string
void ChangeChar(char *text, char c1, char c2)	//replace one char in string
{
	int i;

	for(i = 0; text[i]; i++) if (text[i] == c1) text[i] = c2;
}

char *Int2Nat(char *text)	//format ASCII number to locale format
{
	int i;

	for(i = 0; text[i]; i++) if (text[i] == '.') text[i] = defs.DecPoint[0];
	return text;
}

char *Nat2Int(char *text)	//format locale number to intranational notation
{
	int i;

	for(i = 0; text[i]; i++) if (text[i] == defs.DecPoint[0]) text[i] = '.';
	return text;
}

void WriteNatFloatToBuff(char *buff, double val)
{
	WriteFloatToBuff(buff, val);
	Int2Nat(buff);
}

bool Txt2Flt(char *txt, double *val)
{
	char *tmp = 0L;

	if(txt && txt[0] && val) {
		if(!txt[1] && (txt[0] == defs.DecPoint[0] || txt[0] < '0' ||
			txt[0] > '9'))return false;
		if(txt && txt[0] && (tmp = strdup(txt))){
			Nat2Int(tmp);
			//the return value of sscanf only roughly identifies a number
			if(!sscanf(tmp,"%lf", val)){
				free(tmp);
				return false;
				}
			free(tmp);
			return true;
			}
		}
	return false;
}

void RmTrail(char *txt)
{
	int i;

	i = strlen(txt);
	while(i >0 && (txt[i-1] == '0' || txt[i-1] < 32)) txt[--i] = 0;
	if(i > 1 && txt[i-1] == '.') txt[i-1] = 0;
}

double NiceValue(double fv)
{
	double sign = fv > 0.0f ? 1.0 : -1.0;
	double fa = fabs(fv);
	double magn = floor(log10(fa));
	int i = iround(fa/pow(10.0, magn-1.0));

	return sign*pow(10.0, magn-1.0) *(double)i;
}

char *Int2ColLabel(int nr1, bool uc)
{
	static char RetTxt[10];
	int i, j, nr = nr1;
	char base = uc ? 'A' : 'a';

	sprintf(RetTxt+8, "%c\0", base + (nr %26));
	nr /= 26;
	for (i = 7; nr && i>=0; i--) {
		j = nr %27;
		RetTxt[i] = base + (j ? j-1 : j);
		if (nr == 26) nr = 0;
		else nr = nr/26;
		}
	return RetTxt+i+1;
}

//convert strings to XML specifications
//this offers a limited support for special characters
char *str2xml(char *str)
{
	int i, j;
	wchar_t wc;

	if(!str) return 0L;
	for(i = j = 0; str[i] && j < 4090; i++) {
		switch(str[i]) {
		case '"':
			j += sprintf(TmpTxt+j, "&quot;");
			break;
		case '&':
			j += sprintf(TmpTxt+j, "&amp;");
			break;
		case '<':
			j += sprintf(TmpTxt+j, "&lt;");
			break;
		case '>':
			j += sprintf(TmpTxt+j, "&gt;");
			break;

⌨️ 快捷键说明

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