📄 utils.cpp
字号:
//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, """);
break;
case '&':
j += sprintf(TmpTxt+j, "&");
break;
case '<':
j += sprintf(TmpTxt+j, "<");
break;
case '>':
j += sprintf(TmpTxt+j, ">");
break;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -