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

📄 plotobs.cpp

📁 Linux/windows 环境下跨平台开发程序
💻 CPP
📖 第 1 页 / 共 5 页
字号:
//PlotObs.cpp, Copyright (c) 2001, 2002, 2003, 2004, 2005 R.Lackner
//
//    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
//
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// This modules contains code for the differnt Plot objects. Plots are
// graphic objects containing more objects, which represent the data.
// Several Plots may be contained in a Graph: Plots are the different layers
// of a Graph.
// Most part of this module has been moved here from rlplot.cpp of
// earlier versions. 
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#include "rlplot.h"
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>

extern char TmpTxt[];
extern Default defs;
extern int cPlots;
extern GraphObj *CurrGO, *TrackGO;			//Selected Graphic Objects
extern Axis **CurrAxes;						//axes of current graph
extern UndoObj Undo;

int AxisTempl3D = 0;

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Plot::Plot(GraphObj *par, DataObj *d):GraphObj(par, d)
{
	Id = GO_PLOT;
	Bounds.Xmin = Bounds.Ymin = HUGE_VAL;	Bounds.Xmax = Bounds.Ymax = -HUGE_VAL;
	sprintf(TmpTxt, "Plot %d", ++cPlots);
	name = strdup(TmpTxt);
	use_xaxis = use_yaxis = 0;
	hidden = 0;
}

double
Plot::GetSize(int select)
{
	switch(select){
	case SIZE_MINE:				return 0.0;
	//The Bounds values must be returned by every plot:
	//   they are necessary for scaling !
	case SIZE_BOUNDS_XMIN:		
		return parent ? parent->GetSize(SIZE_BOUNDS_XMIN) : Bounds.Xmin;
	case SIZE_BOUNDS_XMAX:		
		return parent ? parent->GetSize(SIZE_BOUNDS_XMAX) : Bounds.Xmax;
	case SIZE_BOUNDS_YMIN:		
		return parent ? parent->GetSize(SIZE_BOUNDS_YMIN) : Bounds.Ymin;	
	case SIZE_BOUNDS_YMAX:		
		return parent ? parent->GetSize(SIZE_BOUNDS_YMAX) : Bounds.Ymax;
	case SIZE_BARMINX:
	case SIZE_BARMINY:
		return 1.0f;
	default:
		if(parent) return parent->GetSize(select);
		else return defs.GetSize(select);
		}
}

DWORD
Plot::GetColor(int select)
{
	if(parent) return parent->GetColor(select);
	else return defs.Color(select);
}

void
Plot::CheckBounds(double x, double y)
{
	if(x < Bounds.Xmin) Bounds.Xmin = x;	if(x > Bounds.Xmax) Bounds.Xmax = x;
	if(y < Bounds.Ymin) Bounds.Ymin = y;	if(y > Bounds.Ymax) Bounds.Ymax = y;
}

bool
Plot::UseAxis(int idx)
{
	double dx, dy;

	if(CurrAxes && CurrAxes[idx]) {
		dx = fabs(CurrAxes[idx]->GetSize(SIZE_XPOS+1) -
			CurrAxes[idx]->GetSize(SIZE_XPOS));
		dy = fabs(CurrAxes[idx]->GetSize(SIZE_YPOS+1) -
			CurrAxes[idx]->GetSize(SIZE_YPOS));
		if(dx > dy && idx != use_xaxis) {
			Undo.ValInt(parent, &use_xaxis, 0L);
			use_xaxis = idx;			return true;
			}
		else if(idx != use_yaxis) {
			Undo.ValInt(parent, &use_yaxis, 0L);
			use_yaxis = idx;			return true;
			}
		}
	return false;
}

void
Plot::ApplyAxes(anyOutput *o)
{
	AxisDEF x_axis, y_axis;
	double dsp;
	fRECT CurrRect;
	
	if(!o || !CurrAxes || !parent) return;
	memcpy(&x_axis, &o->xAxis, sizeof(AxisDEF));
	memcpy(&y_axis, &o->yAxis, sizeof(AxisDEF));
	CurrRect.Xmin = (dsp = parent->GetSize(SIZE_GRECT_LEFT)) +
		parent->GetSize(SIZE_DRECT_LEFT);
	CurrRect.Xmax = dsp + parent->GetSize(SIZE_DRECT_RIGHT);
	if(use_xaxis && CurrAxes[use_xaxis]) {
		memcpy(&x_axis, CurrAxes[use_xaxis]->axis, sizeof(AxisDEF));
		if(x_axis.flags & AXIS_DEFRECT) {
			x_axis.loc[0].fx += dsp;	x_axis.loc[1].fx += dsp;
			}
		}
	else use_xaxis = 0;
	CurrRect.Ymin = (dsp = parent->GetSize(SIZE_GRECT_TOP)) +
		parent->GetSize(SIZE_DRECT_BOTTOM);
	CurrRect.Ymax = dsp + parent->GetSize(SIZE_DRECT_TOP);
	if(use_yaxis && CurrAxes[use_yaxis]) {
		memcpy(&y_axis, CurrAxes[use_yaxis]->axis, sizeof(AxisDEF));
		if(y_axis.flags & AXIS_DEFRECT) {
			y_axis.loc[0].fy += dsp;	y_axis.loc[1].fy += dsp;
			}
		}
	else use_yaxis = 0;
	o->SetRect(CurrRect, o->units, &x_axis, &y_axis);
}

void
Plot::CheckBounds3D(double x, double y, double z)
{
	if(x < xBounds.fx) xBounds.fx = x;	if(x > xBounds.fy) xBounds.fy = x;
	if(y < yBounds.fx) yBounds.fx = y;	if(y > yBounds.fy) yBounds.fy = y;
	if(z < zBounds.fx) zBounds.fx = z;	if(z > zBounds.fy) zBounds.fy = z;
	CheckBounds(x, y);
}

bool
Plot::SavVarObs(GraphObj **gol, long ngo, DWORD flags)
{
	int i;
	void *ptr;

	if(!gol || !ngo) return false;
	SavVarInit(150 * ngo);
	for(i = 0; i < ngo; i++) 
		if(gol[i]) gol[i]->FileIO(SAVE_VARS);
	ptr = SavVarFetch();
	Undo.SavVarBlock(this, &ptr, flags);
	return true;
}

DataObj *
Plot::CreaCumData(char *xr, char *yr, int mode, double base)
{
	char **yranges;
	int i, j, nc, nr, ir, ic;
	double value, old_val;
	DataObj *CumData = 0L;
	AccRange *ax = 0L, *ay = 0L;

	if(!xr || !yr || !mode || !data) return 0L;
	if(!(CumData = new DataObj()))return 0L;
	if(!(ax = new AccRange(xr))) {
		delete CumData;		return 0L;
		}
	nr = ax->CountItems();
	if(!(yranges = split(yr, '&', &nc))){
		delete CumData;		delete ax;		return 0L;
		}
	if(CumData->Init(mode == 1 || mode == 2 ? nr : nr * 2, nc+2)){
		// set x values as first column
		for(i = 0, ax->GetFirst(&ic, &ir); ax->GetNext(&ic, &ir); i++) {
			if(data->GetValue(ir, ic, &value)) CumData->SetValue(i, 0, value);
			CumData->SetValue(i, 1, base);
			}
		if(mode == 3 || mode == 4) for(i = 1; i <= nr; i++) {	//complete polygon data
			if(CumData->GetValue(nr-i, 0, &value)) CumData->SetValue(i-1+nr, 0, value);
			}
		//process all y-ranges
		for (j = 2; j <= (nc+1); j++) if(ay = new AccRange(yranges[j-2])){
			for(i = 0; i < nr; i++) {
				if(CumData->GetValue(i, j-1, &value)) CumData->SetValue(i, j, value);
				}
			for(i = 0, ay->GetFirst(&ic, &ir); ay->GetNext(&ic, &ir) && i < nr; i++) {
				if(data->GetValue(ir, ic, &value) && CumData->GetValue(i, j, &old_val)){
					switch (mode) {
					case 1:	case 3:	value += old_val;			break;
					case 2:	case 4: value = old_val -value;		break;
						}
					CumData->SetValue(i, j, value);
					}
				}
			if(mode == 3 || mode == 4) for(i = 1; i <= nr; i++) {
				//complete polygon data
				if(CumData->GetValue(nr-i, j-1, &value)) CumData->SetValue(i-1+nr, j, value);
				}
			delete ay;		ay = 0L;
			}
		}



	for(i = 0; i < nc; i++) if(yranges[i]) free(yranges[i]);
	if(ax) delete ax;	if(ay) delete ay;
	free(yranges);
	return CumData;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// PlotScatt handles most XY-Plots: its a Plot-Class
PlotScatt::PlotScatt(GraphObj *par, DataObj *d, DWORD presel):Plot(par, d)
{
	FileIO(INIT_VARS);
	DefSel = presel;
	Id = GO_PLOTSCATT;
	if (!d) {
		if(parent && parent->Command(CMD_DELOBJ, this, NULL)) return;
		ErrorBox("Attempt to create plot\nwithout any data.");
		return;
		}
}

PlotScatt::PlotScatt(GraphObj *par, DataObj *d, int cBars, Bar **bars):Plot(par, d)
{
	int i;

	FileIO(INIT_VARS);
	if(cBars && bars) {
		if((Bars = (Bar**)calloc(cBars, sizeof(Bar*)))) {
			nPoints = cBars;
			for(i = 0; i < cBars; i++) {
				if((Bars[i] = bars[i])) Bars[i]->parent = this;
				bars[i] = 0L;
				}
			}
		}
	Id = GO_PLOTSCATT;
}

PlotScatt::PlotScatt(GraphObj *par, DataObj *d, int nPts, Symbol **sym, DataLine *lin):
	Plot(par, d)
{
	int i;

	FileIO(INIT_VARS);
	nPoints = nPts;
	if(Symbols = sym) for(i = 0; i < nPts; i++) if(Symbols[i]) Symbols[i]->parent = this;
	if(TheLine = lin) TheLine->parent = this;
	Id = GO_PLOTSCATT;
}

PlotScatt::PlotScatt(int src):Plot(0L, 0L)
{
	FileIO(INIT_VARS);
	if(src == FILE_READ) {
		FileIO(FILE_READ);
		}
}

PlotScatt::~PlotScatt()
{
	ForEach(FE_FLUSH, 0L, 0L);
	if(name) free(name);		name=0L;
	Undo.InvalidGO(this);
}

double
PlotScatt::GetSize(int select)
{
	int i;
	double ft1, ft2, d;

	switch(select){
	case SIZE_BARMINX:
		if(BarDist.fx >= 0.0001) return BarDist.fx;
		if((!Bars) || (nPoints < 2)) return BarDist.fx = 1.0;
		ft1 = -HUGE_VAL;	ft2 = HUGE_VAL;		BarDist.fx= HUGE_VAL;
		for(i = 0; i < nPoints; i++) {
			if(Bars[i]) {
				ft2 = Bars[i]->GetSize(SIZE_XPOS);
				d = fabs(ft2-ft1);
				if(d != 0.0 && d < BarDist.fx) BarDist.fx = d;
				}
			ft1 = ft2;
			}
		return BarDist.fx = BarDist.fx > 0.0001 && BarDist.fx != HUGE_VAL  ? BarDist.fx : 1.0;
	case SIZE_BARMINY:
		if(BarDist.fy >= 0.0001) return BarDist.fy;
		if((!Bars) || (nPoints < 2)) return BarDist.fy = 1.0;
		ft1 = -HUGE_VAL;	ft2 = HUGE_VAL;		BarDist.fy= HUGE_VAL;
		for(i = 0; i < nPoints; i++) {
			if(Bars[i]) {
				ft2 = Bars[i]->GetSize(SIZE_YPOS);
				d = fabs(ft2-ft1);
				if(d != 0.0 && d < BarDist.fy) BarDist.fy = d;
				}
			ft1 = ft2;
			}
		return BarDist.fy = BarDist.fy > 0.0001 && BarDist.fy != HUGE_VAL  ? BarDist.fy : 1.0;
	default:
		return Plot::GetSize(select);
		}
}

bool
PlotScatt::SetSize(int select, double value)
{
	int i;

	switch(select & 0xfff){
	case SIZE_BARMINX:
		BarDist.fx = value;
		return true;
	case SIZE_BARMINY:
		BarDist.fy = value;
		return true;
	case SIZE_SYMBOL:		case SIZE_SYM_LINE:
		if(Symbols)	for(i = 0; i < nPoints; i++) 
			if(Symbols[i]) Symbols[i]->SetSize(select, value);
		return true;
	case SIZE_WHISKER:		case SIZE_WHISKER_LINE:
	case SIZE_ERRBAR:		case SIZE_ERRBAR_LINE:
		if(Errors)	for(i = 0; i < nPoints; i++) 
			if(Errors[i]) Errors[i]->SetSize(select, value);
		return true;
	case SIZE_BAR_LINE:		case SIZE_BAR:		case SIZE_XBASE:		case SIZE_YBASE:
		if(Bars) for(i = 0; i < nPoints; i++) 
			if(Bars[i]) Bars[i]->SetSize(select, value);
		return true;
	case SIZE_LB_XDIST:		case SIZE_LB_YDIST:
		if(Labels) for(i = 0; i < nPoints; i++)
			if(Labels[i]) Labels[i]->SetSize(select, value);
		return true;
	case SIZE_ARROW_LINE:	case SIZE_ARROW_CAPWIDTH:	case SIZE_ARROW_CAPLENGTH:
		if(Arrows) for(i = 0; i < nPoints; i++)
			if(Arrows[i]) Arrows[i]->SetSize(select, value);
		return true;
	}
	return false;
}

bool
PlotScatt::SetColor(int select, DWORD col)
{
	int i;
	GraphObj **go = 0L;

	switch(select) {
	case COL_SYM_LINE:
	case COL_SYM_FILL:		go = (GraphObj**)Symbols;		break;
	case COL_WHISKER:
	case COL_ERROR_LINE:	go = (GraphObj**)Errors;		break;
	case COL_BAR_LINE:
	case COL_BAR_FILL:		go = (GraphObj**)Bars;			break;
	case COL_ARROW:			go = (GraphObj**)Arrows;		break;
	default:				return false;
		}
	if(go) for(i = 0; i < nPoints; i++)
		if(go[i]) go[i]->SetColor(select, col);
	return true;
}

void
PlotScatt::DoPlot(anyOutput *o)
{
	if(!parent) return;
	parent->Command(CMD_REG_AXISPLOT, (void*)this, o);
	if(use_xaxis || use_yaxis) {
		ApplyAxes(o);
		ForEach(FE_PLOT, 0L, o);
		parent->Command(CMD_AXIS, 0L, o);
		}
	else {
		ForEach(FE_PLOT, 0L, o);
		}
	dirty = false;
}

bool
PlotScatt::Command(int cmd, void *tmpl, anyOutput *o)
{
	int i;

	switch (cmd) {
	case CMD_MOUSE_EVENT:
		if(hidden) return false;
		if(!CurrGO && ((MouseEvent*)tmpl)->Action == MOUSE_LBUP)
			return ForEach(cmd, tmpl, o);
		return false;
	case CMD_LEGEND:
		if(((GraphObj*)tmpl)->Id != GO_LEGEND) return false;
		if(Bars) for (i = 0; i < nPoints; i++)
			if(Bars[i]) Bars[i]->Command(cmd, tmpl, o);
		if(Symbols) {
			if(TheLine && TheLine->Id == GO_DATALINE) {
				for (i = 0; i < nPoints && i < 100; i++)
					if(Symbols[i]) ((Legend*)tmpl)->HasSym(&TheLine->LineDef, Symbols[i]);
				}
			else {
				for (i = 0; i < nPoints && i < 100; i++)
					if(Symbols[i]) ((Legend*)tmpl)->HasSym(0L, Symbols[i]);
				}
			if(TheLine && TheLine->Id == GO_DATAPOLYGON) TheLine->Command(cmd, tmpl, o);
			}
		else if(TheLine) TheLine->Command(cmd, tmpl, o);
		break;
	case CMD_MRK_DIRTY:
		dirty = true;
	case CMD_SETSCROLL:		case CMD_REDRAW:
		if(parent) return parent->Command(cmd, tmpl, o);
		return false;
	case CMD_USEAXIS:
		return UseAxis(*((int*)tmpl));
	case CMD_FLUSH:
		return ForEach(FE_FLUSH, 0L, 0L);
	case CMD_AUTOSCALE:
		if(hidden) return false;
		if(dirty){

⌨️ 快捷键说明

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