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

📄 plotobs.cpp

📁 Linux/windows 环境下跨平台开发程序
💻 CPP
📖 第 1 页 / 共 5 页
字号:
			Bounds.Xmin = Bounds.Ymin = HUGE_VAL;
			Bounds.Xmax = Bounds.Ymax = -HUGE_VAL;
			}
		else{
			if(parent && parent->Id >= GO_PLOT && parent->Id < GO_GRAPH && 
				Bounds.Xmax > Bounds.Xmin && Bounds.Ymax > Bounds.Ymin) {
				((Plot*)parent)->CheckBounds(Bounds.Xmin, Bounds.Ymin);
				((Plot*)parent)->CheckBounds(Bounds.Xmax, Bounds.Ymax);
				return true;
				}
			}
		dirty = false;
	case CMD_UPDATE:
		if(cmd == CMD_UPDATE){
			if (Symbols) SavVarObs((GraphObj **)Symbols, nPoints, UNDO_CONTINUE);
			if (Bars) SavVarObs((GraphObj **)Bars, nPoints, UNDO_CONTINUE);
			if (Errors) SavVarObs((GraphObj **)Errors, nPoints, UNDO_CONTINUE);
			if (Arrows) SavVarObs((GraphObj **)Arrows, nPoints, UNDO_CONTINUE);
			if (DropLines) SavVarObs((GraphObj **)DropLines, nPoints, UNDO_CONTINUE);
			if (Labels) SavVarObs((GraphObj **)Labels, nPoints, UNDO_CONTINUE);
			dirty = true;
			}
	case CMD_SET_DATAOBJ:
		if(cmd == CMD_SET_DATAOBJ) {
			Id = GO_PLOTSCATT;
			if(data && data == (DataObj *) tmpl) return true;
			data = (DataObj *)tmpl;	
			}
		ForEach(cmd, tmpl, o);
		if(cmd == CMD_AUTOSCALE && parent && parent->Id >= GO_PLOT && parent->Id < GO_GRAPH
			&& Bounds.Xmax > Bounds.Xmin && Bounds.Ymax > Bounds.Ymin) {
			((Plot*)parent)->CheckBounds(Bounds.Xmin, Bounds.Ymin);
			((Plot*)parent)->CheckBounds(Bounds.Xmax, Bounds.Ymax);
			}
		return true;
	case CMD_HIDE_MARK:
		return ForEach(cmd, tmpl, o);
	case CMD_MUTATE:		case CMD_REPL_GO:
		dirty = true;
		return ForEach(cmd == CMD_REPL_GO ? FE_REPLGO : FE_MUTATE, tmpl, o);
	case CMD_SYMTEXT:		case CMD_SYMTEXT_UNDO:	case CMD_SYM_RANGETEXT:
	case CMD_SYMTEXTDEF:	case CMD_SYM_TYPE:
		if(Symbols) for(i = 0; i < nPoints; i++)
			if(Symbols[i]) Symbols[i]->Command(cmd, tmpl, o);
		return true;
	case CMD_SETTEXTDEF:
		if(Labels) for(i = 0; i < nPoints; i++)
			if(Labels[i]) Labels[i]->Command(cmd, tmpl, o);
		return true;
	case CMD_DL_LINE:		case CMD_DL_TYPE:
		if(DropLines) for(i = 0; i < nPoints; i++)
			if(DropLines[i]) DropLines[i]->Command(cmd, tmpl, o);
		return true;
	case CMD_ERR_TYPE:		case CMD_WHISKER_STYLE:
		if(Errors) for(i = 0; i < nPoints; i++) {
			if(Errors[i]) Errors[i]->Command(cmd, tmpl, o);
			}
	case CMD_BAR_TYPE:		case CMD_BAR_FILL:
		if(Bars) for(i = 0; i < nPoints; i++) {
			if(Bars[i]) Bars[i]->Command(cmd, tmpl, o);
			}
		return true;
	case CMD_ARROW_TYPE:	case CMD_ARROW_ORG:
		if(Arrows) for(i = 0; i < nPoints; i++) {
			if(Arrows[i]) Arrows[i]->Command(cmd, tmpl, o);
			}
		return true;
	case CMD_DELOBJ:
		dirty = true;
		if(parent && tmpl && o) return ForEach(FE_DELOBJ, tmpl, o);
		break;
	case CMD_SAVE_SYMBOLS:
		return SavVarObs((GraphObj **)Symbols, nPoints, 0L);
	case CMD_SAVE_BARS:
		return SavVarObs((GraphObj **)Bars, nPoints, 0L);
	case CMD_SAVE_ERRS:
		return SavVarObs((GraphObj **)Errors, nPoints, 0L);
	case CMD_SAVE_ARROWS:
		return SavVarObs((GraphObj **)Arrows, nPoints, 0L);
	case CMD_SAVE_DROPLINES:
		return SavVarObs((GraphObj **)DropLines, nPoints, 0L);
	case CMD_SAVE_LABELS:
		return SavVarObs((GraphObj **)Labels, nPoints, 0L);
		}
	return false;
}

bool
PlotScatt::ForEach(int cmd, void *tmp, anyOutput *o)
{
	int i, j;
	GraphObj **obs[] = {(GraphObj**)Symbols, (GraphObj**)Errors, (GraphObj**)Arrows,
		(GraphObj**)DropLines, (GraphObj**)Labels, (GraphObj**)Bars};
	GraphObj ***go = 0L;
	GraphObj **tmpPlots;
	bool bRedraw, bFound;

	switch(cmd) {
	case FE_MUTATE:
	case FE_REPLGO:
		if((tmpPlots = (GraphObj **)tmp) && tmpPlots[0] && tmpPlots[1]) {
			for(j = 0; j < 6; j++){
				if(obs[j]) for(i = 0; i < nPoints; i++){
					if(obs[j][i] && obs[j][i] == tmpPlots[0]) {
						if(cmd == FE_REPLGO) return ReplaceGO(&obs[j][i], tmpPlots);
						else {
							Undo.MutateGO(&obs[j][i], tmpPlots[1], 0L, o);
							return true;
							}
						}
					}
				}
			if(TheLine == tmpPlots[0]){
				if(cmd == FE_REPLGO) return ReplaceGO((GraphObj**)&TheLine, tmpPlots);
				else {
					Undo.MutateGO((GraphObj**)&TheLine, tmpPlots[1], 0L, o);
					return true;
					}
				}
			}
		return false;
	case FE_PARENT:
		for(j = 0; j < 6; j++){
			if(obs[j]) for(i = 0; i < nPoints; i++){
				if(obs[j][i]) obs[j][i]->parent = this;
				}
			}
		if(TheLine) TheLine->parent = this;
		return true;
	case CMD_UPDATE:
	case CMD_SET_DATAOBJ:
	case CMD_AUTOSCALE:
		for(j = 0; j < 6; j++){
			if(obs[j]) for(i = 0; i < nPoints; i++){
				if(obs[j][i]) obs[j][i]->Command(cmd, tmp, o);
				}
			}
		if(TheLine) TheLine->Command(cmd, tmp, o);
		return true;
	case FE_PLOT:
		if(TheLine) TheLine->DoPlot(o);
		for(j = 5; j >= 0; j--){
			if(obs[j]) for(i = 0; i < nPoints; i++){
				if(obs[j][i]) obs[j][i]->DoPlot(o);
				}
			}
		return true;
	case FE_FLUSH:
		for(j = 0; j < 6; j++){
			if(obs[j]) {
				for(i = 0; i < nPoints; i++) if(obs[j][i]) DeleteGO(obs[j][i]);
				free(obs[j]);	obs[j] = 0L;
				}
			}
		if(ErrRange) free(ErrRange);	if(yRange) free(yRange);
		if(xRange) free(xRange);		if(LbRange) free(LbRange);
		ErrRange = yRange = xRange = LbRange = 0L;
		if(TheLine) DeleteGO(TheLine);
		Bars = 0L;		Symbols = 0L;		Errors = 0L; 
		Arrows = 0L;	DropLines = 0L;		Labels = 0L;	TheLine = 0L;
		return true;
	case FE_DELOBJ:
		if(!o) return false;
		for(j = 0, bRedraw = false, go = 0L; j < 6 && !bRedraw; j++) {
			if(obs[j]) for(i = 0; i < nPoints; i++){
				if(obs[j][i]){
					if(tmp == (void*)obs[j][i]) {
						o->MrkMode = MRK_NONE;
						o->MouseCursor(MC_WAIT, true);
						Undo.DeleteGO(&obs[j][i], 0L, o);
						switch(j) {
						case 0: go = (GraphObj***)&Symbols;		break;
						case 1: go = (GraphObj***)&Errors;		break;
						case 2: go = (GraphObj***)&Arrows;		break;
						case 3: go = (GraphObj***)&DropLines;	break;
						case 4: go = (GraphObj***)&Labels;		break;
						case 5: go = (GraphObj***)&Bars;		break;
							}
						bRedraw = true;
						break;
						}
					}
				}
			}
		if(!bRedraw && TheLine && tmp == (void *) TheLine) {
			o->MrkMode = MRK_NONE;
			Undo.DeleteGO((GraphObj**)(&TheLine), 0L, o);
			bRedraw = true;
			}
		if(bRedraw && go) for(i = j = 0; i < nPoints; i++) if(go[0][i]) j++;
		if(!j) Undo.DropMemory(this, (void**)go, UNDO_CONTINUE);
		if(bRedraw && dirty) Command(CMD_AUTOSCALE, 0L, o); 
		if(!Bars && !Symbols && !Errors && !Arrows && !TheLine && !DropLines
			&& !Labels) parent->Command(CMD_DELOBJ_CONT, this, o);
		else if(bRedraw) parent->Command(CMD_REDRAW, NULL, o);
		return bRedraw;
	case CMD_HIDE_MARK:
		if(!o || !tmp) return false;
		if(bFound =(tmp == (void*)TheLine)) TheLine->DoMark(o, false);
		else for(j = 5; j >= 0 && !bFound; j--){
			if(obs[j]) for(i = 0; i < nPoints && !bFound; i++){
				if(bFound = (tmp == (void*)obs[j][i])) obs[j][i]->DoMark(o, false);
				else if(obs[j][i] && obs[j][i]->Id == GO_MLABEL &&
					obs[j][i]->Command(cmd, tmp, o)) return true;
				}
			}
		return bFound;
	default:							//pass command to all objects
		for(j = 0; j < 6; j++){
			if(obs[j]) for(i = 0; i < nPoints; i++){
				if(obs[j][i]) if(obs[j][i]->Command(cmd, tmp, o)) return true;
				}
			}
		if(TheLine) return (TheLine->Command(cmd, tmp, o));
		return false;
		}
	return false;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// xyStat is based on scatterplot
xyStat::xyStat(GraphObj *par, DataObj *d):PlotScatt(par, d, 0L)
{
	FileIO(INIT_VARS);
	Id = GO_XYSTAT;
}

xyStat::xyStat(int src):PlotScatt(0)
{
	FileIO(INIT_VARS);
	if(src == FILE_READ) {
		FileIO(FILE_READ);
		}
}

xyStat::~xyStat()
{
	ForEach(FE_FLUSH, 0L, 0L);
	if(curr_data) delete curr_data;			curr_data = 0L;
	if(case_prefix) free(case_prefix);		case_prefix = 0L;
	if(yRange) free(yRange);				yRange = 0L;
	if(xRange) free(xRange);				xRange = 0L;
	if(name) free(name);					name=0L;
	Undo.InvalidGO(this);
}

bool
xyStat::Command(int cmd, void *tmpl, anyOutput *o)
{
	switch (cmd) {
	case CMD_UPDATE:
		if (Symbols) SavVarObs((GraphObj **)Symbols, nPoints, UNDO_CONTINUE);
		if (Bars) SavVarObs((GraphObj **)Bars, nPoints, UNDO_CONTINUE);
		if (Errors) SavVarObs((GraphObj **)Errors, nPoints, UNDO_CONTINUE);
		if (Labels) SavVarObs((GraphObj **)Labels, nPoints, UNDO_CONTINUE);
		CreateData();
		ForEach(CMD_SET_DATAOBJ, curr_data, o);
		ForEach(CMD_UPDATE, tmpl, o);
		return dirty = true;
	case CMD_SET_DATAOBJ:
		if(cmd == CMD_SET_DATAOBJ) {
			Id = GO_XYSTAT;
			if(data && data == (DataObj *) tmpl) return true;
			if(curr_data) delete curr_data;		curr_data = 0L;
			data = (DataObj *)tmpl;
			if(data && !curr_data) CreateData();
			tmpl = curr_data;
			}
		ForEach(cmd, tmpl, o);
		return true;
	default:
		return PlotScatt::Command(cmd, tmpl, o);
		}
	return false;
}

void
xyStat::CreateData()
{
	int i, j, k, l, m, n, *ny;
	double x, y, ss, d, lo, hi, **ay, *ax, *tay, *q1, *q2, *q3;
	lfPOINT *xy;
	AccRange *rX, *rY;

	if(curr_data) delete curr_data;			curr_data = 0L;
	if(!data || !xRange || !yRange || !xRange[0] || !yRange[0]) return;
	if(!(rX = new AccRange(xRange)) || !(rY = new AccRange(yRange))) return;
	m = rX->CountItems();	n = 0;
	if(m < 2 || !(xy = (lfPOINT*) malloc(m * sizeof(lfPOINT)))) {
		delete rX;	delete rY;
		return;
		}
	ny = (int*) calloc(m, sizeof(int));
	ay = (double**) calloc(m, sizeof(double*));
	ax = (double*) calloc(m, sizeof(double));
	tay = (double*)malloc(m * sizeof(double));
	if(!ny || !ay || !ax || !tay) {
		if(ny) free(ny);	if(ay) free(ay);
		if(ax) free(ax);	if(tay) free(tay);
		delete rX;	delete rY;
		return;
		}
	rX->GetFirst(&i, &j);	rY->GetFirst(&k, &l);
	rX->GetNext(&i, &j);	rY->GetNext(&k, &l);	n=0;
	do {
		if(data->GetValue(j, i, &x) && data->GetValue(l, k, &y)){
			xy[n].fx = x;		xy[n].fy = y;
			n++;
			}
		}while(rX->GetNext(&i, &j) && rY->GetNext(&k, &l));
	delete rX;			delete rY;
	if(!n) {
		if(ny) free(ny);	if(ay) free(ay);
		if(ax) free(ax);	if(tay) free(tay);
		return;
		}
	SortFpArray(n, xy);
	for(i = j = 0; i < (n-1); i++, j++) {
		ax[j] = xy[i].fx;		tay[0] = xy[i].fy;
		ny[j] = 1;
		for(k = 1; xy[i+1].fx == xy[i].fx; k++) {
			tay[k] = xy[i+1].fy;
			i++;		ny[j]++;
			}
		ay[j] = (double*)memdup(tay, k * sizeof(double), 0);
		}
	if(xy[i].fx > xy[i-1].fx) {
		ax[j] = xy[i].fx;		tay[0] = xy[i].fy;
		ny[j] = 1;
		ay[j++] = (double*)memdup(tay, sizeof(double), 0);
		}
	if(type & 0x0480) {		//medians and/or percentiles required
		q1 = (double *)malloc(j * sizeof(double));
		q2 = (double *)malloc(j * sizeof(double));
		q3 = (double *)malloc(j * sizeof(double));
		if(q1 && q2 && q3) {
			for(i = 0; i < j; i++) {
				if(ny[i] > 1) d_quartile(ny[i], ay[i], q1+i, q2+i, q3+i);
				else q1[i] = q2[i] = q3[i] = *ay[i];
				}
			}
		else type &= (~0x0480);
		}
	else q1 = q2 = q3 = 0L;
	if((curr_data = new DataObj()) && curr_data->Init(j, 6)) {
		for(i = 0; i < j; i++) curr_data->SetValue(i,0,ax[i]);	// set x-values
		for(i = 0; i < j; i++) {								// set y-values
			if(ny[i] > 1) switch(type & 0x00f0) {
				case 0x0010:	default:
					curr_data->SetValue(i, 1, y=d_amean(ny[i], ay[i]));
					break;
				case 0x0020:
					curr_data->SetValue(i, 1, y=d_gmean(ny[i], ay[i]));
					break;
				case 0x0040:
					curr_data->SetValue(i, 1, y=d_hmean(ny[i], ay[i]));
					break;
				case 0x0080:
					curr_data->SetValue(i, 1, y=q2[i]);
					break;
				}
			else curr_data->SetValue(i, 1, y= *ay[i]);
			curr_data->SetValue(i, 4, y);
			}
		for(i = 0; i < j; i++) {								// set errors
			switch(type & 0x1f00) {
			case 0x0100:	case 0x0200:	case 0x1000:	//SD, SEM, conf. int.
				if(ny[i] > 1) {
					y = d_amean(ny[i], ay[i]);
					for(k = 0, ss = 0.0; k < (ny[i]); k++) {
						ss += ((d=ay[i][k]-y)*d);
						ny[i] = ny[i];
						}
					ss = ss/(double)(ny[i]-1);
					switch(type & 0x1f00) {
					case 0x0100:
						curr_data->SetValue(i, 2, sqrt(ss));
						break;
					case 0x0200:
						curr_data->SetValue(i, 2, sqrt(ss)/sqrt(ny[i]));
						break;
					case 0x1000:
						d = distinv(t_dist, ny[i]-1, 1, 1.0-(ci/100.0), 2.0);
						curr_data->SetValue(i, 2, d * sqrt(ss)/sqrt(ny[i]));
						break;
						}
					}
				else curr_data->SetValue(i, 2, 0.0);
				if(curr_data->GetValue(i, 1, &y) && curr_data->GetValue(i, 2, &hi))
					curr_data->SetValue(i, 4, hi+y);
				break;
			case 0x0400:								//percentiles
				curr_data->SetValue(i, 2, q1[i]);	curr_data->SetValue(i, 3, q3[i]);
				curr_data->SetValue(i, 4, q3[i]);
				break;
			case 0x0800:								//min-max
				lo = hi = *ay[i];
				for(k = 1; k < ny[i]; k++) {
					if(ay[i][k] < lo) lo = ay[i][k];
					if(ay[i][k] > hi) hi = ay[i][k];
					}
				curr_data->SetValue(i, 2, lo);		curr_data->SetValue(i, 3, hi);
				curr_data->SetValue(i, 4, hi);
				break;
				}
			}
		if(type & 0x6000) for(i = 0; i < j; i++) {				// number of cases
			sprintf(TmpTxt, "%s%d", case_prefix ? case_prefix : "", ny[i]);
			curr_data->SetText(i, 5, TmpTxt);
			}
		}
	else {
		if(curr_data) delete curr_data;
		curr_data = 0L;
		}
	if(q1) free(q1);	if(q2) free(q2);	if(q3) free(q3);
	for(i = 0; i < m; i++) if(ay[i]) free(ay[i]);
	free(tay);	free(ay);	free(ax);	free(ny);	free(xy);
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// BarChart is based on scatterplot
BarChart::BarChart(GraphObj *par, DataObj *d):PlotScatt(par, d, 0L)
{
	Id = GO_BARCHART;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Frequenc distribution: bar chart with function
FreqDist::FreqDist(GraphObj *par, DataObj *d):Plot(par, d)
{
	FileIO(INIT_VARS);
	Id = GO_FREQDIST;
}

FreqDist::FreqDist(int src):Plot(0L, 0L)
{

⌨️ 快捷键说明

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