📄 plotobs.cpp
字号:
if(Whiskers) {
for(i = 0; i < nPoints; i++) if(Whiskers[i]) DeleteGO(Whiskers[i]);
free (Whiskers);
}
if(Boxes) {
for(i = 0; i < nPoints; i++) if(Boxes[i]) DeleteGO(Boxes[i]);
free (Boxes);
}
if(Symbols) {
for(i = 0; i < nPoints; i++) if(Symbols[i]) DeleteGO(Symbols[i]);
free (Symbols);
}
if(Labels) {
for(i = 0; i < nPoints; i++) if(Labels[i]) DeleteGO(Labels[i]);
free (Labels);
}
if(TheLine) DeleteGO(TheLine);
if(curr_data) delete curr_data; curr_data = 0L;
if(xRange) free(xRange); xRange = 0L;
if(yRange) free(yRange); yRange = 0L;
if(case_prefix) free(case_prefix); case_prefix = 0L;
if(name) free(name); name=0L;
Undo.InvalidGO(this);
}
double
BoxPlot::GetSize(int select)
{
int i;
double ft1, ft2, d;
switch(select){
case SIZE_BOXMINX:
if(BoxDist.fx >= 0.0001) return BoxDist.fx;
if((!Boxes) || (nPoints < 2)) return BoxDist.fx = 1.0;
ft1 = -HUGE_VAL; ft2 = HUGE_VAL; BoxDist.fx= HUGE_VAL;
for(i = 0; i < nPoints; i++) {
if(Boxes[i]) {
ft2 = Boxes[i]->GetSize(SIZE_XPOS);
d = fabs(ft2-ft1);
if(d != 0.0 && d < BoxDist.fx) BoxDist.fx = d;
}
ft1 = ft2;
}
return BoxDist.fx = BoxDist.fx > 0.0001 && BoxDist.fx != HUGE_VAL ? BoxDist.fx : 1.0;
case SIZE_BOXMINY:
if(BoxDist.fy >= 0.0001) return BoxDist.fy;
if((!Boxes) || (nPoints < 2)) return BoxDist.fy = 1.0;
ft1 = -HUGE_VAL; ft2 = HUGE_VAL; BoxDist.fy= HUGE_VAL;
for(i = 0; i < nPoints; i++) {
if(Boxes[i]) {
ft2 = Boxes[i]->GetSize(SIZE_YPOS);
d = fabs(ft2-ft1);
if(d != 0.0 && d < BoxDist.fy) BoxDist.fy = d;
}
ft1 = ft2;
}
return BoxDist.fy = BoxDist.fy > 0.0001 && BoxDist.fy != HUGE_VAL ? BoxDist.fy : 1.0;
default:
return Plot::GetSize(select);
}
}
bool
BoxPlot::SetSize(int select, double value)
{
int i;
switch(select & 0xfff){
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:
if(Whiskers) for(i = 0; i < nPoints; i++)
if(Whiskers[i]) Whiskers[i]->SetSize(select, value);
return true;
case SIZE_BOX: case SIZE_BOX_LINE:
if(Boxes) for(i = 0; i < nPoints; i++)
if(Boxes[i]) Boxes[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;
}
return false;
}
bool
BoxPlot::SetColor(int select, DWORD col)
{
int i;
switch(select) {
case COL_SYM_LINE: case COL_SYM_FILL:
if(Symbols) for(i = 0; i < nPoints; i++)
if(Symbols[i]) Symbols[i]->SetColor(select, col);
return true;
case COL_WHISKER:
if(Whiskers) for(i = 0; i < nPoints; i++)
if(Whiskers[i]) Whiskers[i]->SetColor(select, col);
return true;
case COL_BOX_LINE:
if(Boxes) for(i = 0; i < nPoints; i++)
if(Boxes[i]) Boxes[i]->SetColor(select, col);
return true;
default:
return false;
}
}
void
BoxPlot::DoPlot(anyOutput *o)
{
if(!parent || !o) return;
parent->Command(CMD_REG_AXISPLOT, (void*)this, o);
if(use_xaxis || use_yaxis) ApplyAxes(o);
ForEach(FE_PLOT, 0L, o);
dirty = false;
if(use_xaxis || use_yaxis)parent->Command(CMD_AXIS, 0L, o);
}
bool
BoxPlot::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(Boxes) for (i = 0; i < nPoints; i++) if(Boxes[i]) Boxes[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_SET_DATAOBJ:
Id = GO_BOXPLOT; data = (DataObj *)tmpl; dirty = true;
if(type && xRange && yRange && data) { //Stat. - Plot ?
CreateData();
return ForEach(CMD_SET_DATAOBJ, curr_data, o);
}
return ForEach(cmd, tmpl, o);
case CMD_AUTOSCALE:
if(hidden) return false;
if(dirty) {
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;
ForEach(cmd, tmpl, o);
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;
case CMD_UPDATE:
if(Boxes) SavVarObs((GraphObj **)Boxes, nPoints, UNDO_CONTINUE);
if(Whiskers) SavVarObs((GraphObj **)Whiskers, nPoints, UNDO_CONTINUE);
if(Symbols) SavVarObs((GraphObj **)Symbols, nPoints, UNDO_CONTINUE);
if(Labels) SavVarObs((GraphObj **)Labels, nPoints, UNDO_CONTINUE);
if(type && xRange && yRange) { //Stat. - Plot ?
CreateData();
ForEach(CMD_SET_DATAOBJ, curr_data, o);
}
ForEach(cmd, tmpl, o);
return dirty = true;
case CMD_USEAXIS:
UseAxis(*((int*)tmpl));
return true;
case CMD_MRK_DIRTY:
dirty = true;
case CMD_SETSCROLL: case CMD_REDRAW:
if(parent) return parent->Command(cmd, tmpl, o);
return false;
case CMD_SETTEXTDEF:
if(Labels) for(i = 0; i < nPoints; i++)
if(Labels[i]) Labels[i]->Command(cmd, tmpl, o);
return true;
case CMD_DELOBJ:
if(ForEach(FE_DELOBJ, tmpl, o)) {
parent->Command(CMD_REDRAW, 0L, o);
return true;
}
return false;
case CMD_SYMTEXT: 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_SAVE_SYMBOLS:
return SavVarObs((GraphObj **)Symbols, nPoints, 0L);
case CMD_SAVE_BARS:
return SavVarObs((GraphObj **)Boxes, nPoints, 0L);
case CMD_SAVE_BARS_CONT:
return SavVarObs((GraphObj **)Boxes, nPoints, UNDO_CONTINUE);
case CMD_SAVE_ERRS:
return SavVarObs((GraphObj **)Whiskers, nPoints, 0L);
case CMD_SAVE_LABELS:
return SavVarObs((GraphObj **)Labels, nPoints, 0L);
case CMD_BOX_TYPE:
BoxDist.fy = BoxDist.fx = 0.0;
case CMD_BOX_FILL:
if(Boxes) for (i = 0; i < nPoints; i++)
if(Boxes[i]) Boxes[i]->Command(cmd, tmpl, o);
return true;
case CMD_WHISKER_STYLE:
if(Whiskers) for (i = 0; i < nPoints; i++)
if(Whiskers[i]) Whiskers[i]->Command(cmd, tmpl, o);
return true;
}
return false;
}
bool
BoxPlot::ForEach(int cmd, void *tmpl, anyOutput *o)
{
GraphObj ***pobs[] = {(GraphObj***)&Boxes, (GraphObj***)&Whiskers,
(GraphObj***)&Symbols, (GraphObj***)&Labels};
GraphObj **p;
int i, j;
bool bRet;
switch(cmd) {
case FE_DELOBJ:
if(!o || !parent || !tmpl) return false;
for(i = 0; i < 4; i++) {
if(DeleteGOL(pobs[i], nPoints, (GraphObj*) tmpl, o)) return true;
}
if(TheLine && tmpl == (void *) TheLine) {
Undo.DeleteGO((GraphObj**)(&TheLine), 0L, o);
return true;
}
break;
case FE_PLOT:
if(TheLine) TheLine->DoPlot(o);
for(i = 0; i < 4; i++){
if(p= *pobs[i]) for(j = 0; j < nPoints; j++) {
if(p[j]) p[j]->DoPlot(o);
}
}
return true;
case CMD_MOUSE_EVENT: //invers to plot order
for(i = 3; i >= 0; i--){
if(p= *pobs[i]) for(j = nPoints-1; j >= 0; j--) {
if(p[j]) {
bRet = p[j]->Command(cmd, tmpl, o);
if(bRet && cmd == CMD_MOUSE_EVENT) return true;
}
}
}
if(TheLine) return TheLine->Command(cmd, tmpl, o);
return false;
default: //pass command to all objects
for(i = 0; i < 4; i++){
if(p= *pobs[i]) for(j = 0; j < nPoints; j++) {
if(p[j]) {
bRet = p[j]->Command(cmd, tmpl, o);
}
}
}
if(TheLine) return TheLine->Command(cmd, tmpl, o);
return false;
}
return false;
}
void
BoxPlot::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 & 0x0004) == 0x0004 || (type & 0x0030) == 0x0030 || (type & 0x0300) == 0x0300) {
//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 = 0;
}
else q1 = q2 = q3 = 0L;
if(type && (curr_data = new DataObj()) && curr_data->Init(j, 8)) {
for(i = 0; i < j; i++) curr_data->SetValue(i,0,ax[i]); // set x-values
for(i = 0; i < j; i++) { // set means
if(ny[i] > 1) switch(type & 0x000f) {
case 0x0001: default:
curr_data->SetValue(i, 1, y=d_amean(ny[i], ay[i]));
break;
case 0x0002:
curr_data->SetValue(i, 1, y=d_gmean(ny[i], ay[i]));
break;
case 0x0003:
curr_data->SetValue(i, 1, y=d_hmean(ny[i], ay[i]));
break;
case 0x0004:
curr_data->SetValue(i, 1, y=q2[i]);
break;
}
else curr_data->SetValue(i, 1, y= *ay[i]);
curr_data->SetValue(i, 6, y); //label's y
}
if((type & 0x00f0) == 0x0010 || (type & 0x00f0) == 0x0020 || (type & 0x00f0) == 0x0050
|| (type & 0x0f0f) == 0x0201 || (type & 0x0f0f) == 0x0501) for(i = 0; i < j; i++) {
// set SD, SE, Conf. Intervall
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 = sqrt(ss/(double)(ny[i]-1));
}
else {
y = *ay[i]; ss = 0.0;
}
//Box info is in cols 2 & 3
if((type & 0x00f0) == 0x0010) {
curr_data->SetValue(i, 2, y - ss); curr_data->SetValue(i, 3, y + ss);
}
else if((type & 0x00f0) == 0x0020) {
curr_data->SetValue(i, 2, y - ss/sqrt(ny[i]));
curr_data->SetValue(i, 3, y + ss/sqrt(ny[i]));
}
else if((type & 0x00f0) == 0x0050) {
d = ny[i] > 1 ? distinv(t_dist, ny[i]-1, 1, 1.0-(ci_box/100.0), 2.0) : 0;
curr_data->SetValue(i, 2, y - d*ss/sqrt(ny[i]));
curr_data->SetValue(i, 3, y + d*ss/sqrt(ny[i]));
}
//Whisker info is in cols 4 & 5
if((type & 0x0f0f) == 0x0101) {
curr_data->SetValue(i, 4, y - ss); curr_data->SetValue(i, 5, y + ss);
}
else if((type & 0x0f0f) == 0x0201) {
curr_data->SetValue(i, 4, y - ss/sqrt(ny[i]));
curr_data->SetValue(i, 5, y + ss/sqrt(ny[i]));
}
else if((type & 0x0f0f) == 0x0501) {
d = ny[i] > 1 ? distinv(t_dist, ny[i]-1, 1, 1.0-(ci_err/100.0), 2.0) : 0;
curr_data->SetValue(i, 4, y - d*ss/sqrt(ny[i]));
curr_data->SetValue(i, 5, y + d*ss/sqrt(ny[i]));
}
}
if((type & 0x00f0) == 0x0040 || (type & 0x0f00) == 0x0400) for(i = 0; i < j; i++) {
// set min and max
lo = hi = *ay[i];
if(ny[i] > 1) {
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];
}
}
if((type & 0x00f0) == 0x0040) {
curr_data->SetValue(i, 2, lo); curr_data->SetValue(i, 3, hi);
}
if((type & 0x0f00)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -