📄 axes.cpp
字号:
//Axes.cpp, Copyright 2000, 2001, 2002, 2003, 2004 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 module contains most of the axis-object and related stuff
// like ticks and grid lines.
#include "rlplot.h"
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>
extern char TmpTxt[];
extern Default defs;
extern GraphObj *CurrGO, *TrackGO; //Selected Graphic Objects
extern Axis **CurrAxes;
extern UndoObj Undo;
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// define an object for each grid line
GridLine::GridLine(GraphObj *par, DataObj *d, int which, DWORD df):
GraphObj(par, d)
{
FileIO(INIT_VARS);
type = which;
flags = df;
if(flags & AXIS_RADIAL) type |= DL_CIRCULAR; //default to circular grid
Id = GO_GRIDLINE;
if(parent) parent->Command(CMD_GET_GRIDLINE, &LineDef, 0L);
bModified = false;
}
GridLine::GridLine(int src):GraphObj(0L, 0L)
{
FileIO(INIT_VARS);
if(src == FILE_READ) {
FileIO(FILE_READ);
}
bModified = false;
}
GridLine::~GridLine()
{
int i;
if(bModified) Undo.InvalidGO(this);
if(cpts) free(cpts); cpts = 0L;
if(gl1) free(gl1); gl1 = 0L;
if(gl2) free(gl2); gl2 = 0L;
if(gl3) free(gl3); gl3 = 0L;
if(ls) {
for(i = 0; i < 3; i++) if(ls[i]) delete(ls[i]);
free(ls); ls = 0L;
}
if(mo) DelBitmapClass(mo); mo = 0L;
}
void
GridLine::DoPlot(anyOutput *o)
{
int tmp, ix, iy, ir;
AxisDEF *axdef;
if(!parent || !o) return;
o->SetLine(&LineDef);
if(mo) DelBitmapClass(mo); mo = 0L;
if(!type) type = DL_LEFT | DL_BOTTOM;
if(type & DL_CIRCULAR) {
axdef = (AxisDEF*)((Axis*)(parent->parent))->GetAxis();
ix = o->co2ix(axdef->Center.fx + parent->GetSize(SIZE_GRECT_LEFT));
iy = o->co2iy(axdef->Center.fy + parent->GetSize(SIZE_GRECT_TOP));
ir = abs((int)(parent->GetSize(SIZE_YBASE))-iy);
ncpts = 0;
cpts = MakeArc(ix, iy, ir, 0x0f, &ncpts);
SetMinMaxRect(&rDims, ix-ir, iy-ir, ix+ir, iy+ir);
IncrementMinMaxRect(&rDims, 3);
o->oPolyline(cpts, (int)ncpts);
return;
}
if(parent && parent->Id == GO_TICK) {
pts[0].x = pts[1].x = pts[2].x = pts[3].x = (long)parent->GetSize(SIZE_XBASE);
pts[0].y = pts[1].y = pts[2].y = pts[3].y = (long)parent->GetSize(SIZE_YBASE);
if(type & DL_LEFT) {
tmp = o->fx2ix(parent->GetSize(SIZE_BOUNDS_LEFT));
if(tmp < pts[0].x) pts[0].x = tmp;
if(tmp > pts[1].x) pts[1].x = tmp;
}
if(type & DL_RIGHT) {
tmp = o->fx2ix(parent->GetSize(SIZE_BOUNDS_RIGHT));
if(tmp < pts[0].x) pts[0].x = tmp;
if(tmp > pts[1].x) pts[1].x = tmp;
}
if(type & DL_YAXIS) {
tmp = iround(parent->GetSize(SIZE_YAXISX));
if(tmp < pts[0].x) pts[0].x = tmp;
if(tmp > pts[1].x) pts[1].x = tmp;
}
if(type & DL_TOP) {
tmp = o->fy2iy(parent->GetSize(SIZE_BOUNDS_TOP));
if(tmp < pts[2].y) pts[2].y = tmp;
if(tmp > pts[3].y) pts[3].y = tmp;
}
if(type & DL_BOTTOM) {
tmp = o->fy2iy(parent->GetSize(SIZE_BOUNDS_BOTTOM));
if(tmp < pts[2].y) pts[2].y = tmp;
if(tmp > pts[3].y) pts[3].y = tmp;
}
if(type & DL_XAXIS) {
tmp = iround(parent->GetSize(SIZE_XAXISY));
if(tmp < pts[2].y) pts[2].y = tmp;
if(tmp > pts[3].y) pts[3].y = tmp;
}
SetMinMaxRect(&rDims, pts[0].x, pts[2].y, pts[1].x, pts[3].y);
IncrementMinMaxRect(&rDims, 3);
if(pts[0].x != pts[1].x || pts[0].y != pts[1].y) o->oPolyline(pts, 2);
if(pts[2].x != pts[3].x || pts[2].y != pts[3].y) o->oPolyline(pts+2, 2);
}
}
void
GridLine::DoMark(anyOutput *o, bool mark)
{
if(cpts && mark){
InvertLine(cpts, ncpts, &LineDef, &rDims, o, mark);
}
else if(cpts) {
InvertLine(cpts, ncpts, &LineDef, &rDims, o, mark);
}
}
bool
GridLine::Command(int cmd, void *tmpl, anyOutput *o)
{
MouseEvent *mev;
POINT p1;
switch(cmd){
case CMD_SET_DATAOBJ:
Id = GO_GRIDLINE;
return true;
case CMD_SETSCROLL:
case CMD_SET_GO3D:
case CMD_REDRAW:
if(parent) return parent->Command(cmd, tmpl, o);
return false;
case CMD_SET_GRIDLINE:
if(tmpl) memcpy(&LineDef, tmpl, sizeof(LineDEF));
return true;
case CMD_SET_GRIDTYPE:
if(tmpl)type = *((int*)tmpl);
return true;
case CMD_MOUSE_EVENT:
mev = (MouseEvent *) tmpl;
switch (mev->Action) {
case MOUSE_LBUP:
if(IsInRect(&rDims, p1.x = mev->x, p1.y = mev->y)) {
if(cpts && (type & DL_CIRCULAR) && IsCloseToPL(p1, cpts, ncpts)) {
o->ShowMark(this, MRK_GODRAW);
return true;
}
else if(!(type & DL_CIRCULAR)){
o->ShowMark(&rDims, MRK_INVERT);
CurrGO = this;
return true;
}
}
break;
}
return false;
}
return false;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Gridline for axes and plots in 3D space
GridLine3D::GridLine3D(GraphObj *par, DataObj *d, int which, DWORD df):
GridLine(par, d, which, df)
{
Id = GO_GRIDLINE3D;
}
GridLine3D::GridLine3D(int src):GridLine(src)
{
}
GridLine3D::~GridLine3D()
{
int i;
if(cpts) free(cpts); cpts = 0L;
if(gl1) free(gl1); gl1 = 0L;
if(gl2) free(gl2); gl2 = 0L;
if(gl3) free(gl3); gl3 = 0L;
if(ls) {
for(i = 0; i < 6; i++) if(ls[i]) delete(ls[i]);
free(ls); ls = 0L;
}
if(mo) DelBitmapClass(mo); mo = 0L;
}
void
GridLine3D::DoMark(anyOutput *o, bool mark)
{
int i;
POINT3D *gl;
if(mark){
if(ls){
memcpy(&mrc, &rDims, sizeof(RECT));
IncrementMinMaxRect(&mrc, 6 + o->un2ix(LineDef.width));
mo = GetRectBitmap(&mrc, o);
for(i = 0; i < 6; i++) if(ls[i]) {
switch(i) {
case 0: case 1:
gl = gl1; break;
case 2: case 3:
gl = gl2; break;
case 4: case 5:
gl = gl3; break;
}
if(gl) {
if(gl[0].x && gl[0].y && gl[1].x && gl[1].y) {
pts[0].x = gl[0].x; pts[1].x = gl[1].x;
pts[0].y = gl[0].y; pts[1].y = gl[1].y;
InvertLine(pts, 2, &LineDef, &mrc, o, mark);
}
if(gl[2].x && gl[2].y && gl[3].x && gl[3].y) {
pts[0].x = gl[2].x; pts[1].x = gl[3].x;
pts[0].y = gl[2].y; pts[1].y = gl[3].y;
InvertLine(pts, 2, &LineDef, &mrc, o, mark);
}
}
}
}
}
else if(mo) RestoreRectBitmap(&mo, &mrc, o);
}
void
GridLine3D:: DoPlot(anyOutput *o)
{
fPOINT3D p1, p2, pn;
int i;
if(!parent || !o) return;
if(mo) DelBitmapClass(mo); mo = 0L;
if(!gl1) gl1 = (POINT3D*)calloc(4, sizeof(POINT3D));
if(!gl2) gl2 = (POINT3D*)calloc(4, sizeof(POINT3D));
if(!gl3) gl3 = (POINT3D*)calloc(4, sizeof(POINT3D));
if(!ls) ls = (line_segment**)calloc(6, sizeof(line_segment*));
o->ActualSize(&rDims);
Swap(rDims.left, rDims.right); Swap(rDims.top, rDims.bottom);
if(gl1 && gl2 && gl3 && ls) {
for(i = 0; i < 6; i++) if(ls[i]) {
delete(ls[i]); ls[i] = 0L;
}
if(type & 0x01) {
pn.fx = parent->GetSize(SIZE_BOUNDS_XMIN); pn.fy = parent->GetSize(SIZE_BOUNDS_YMIN);
pn.fz = parent->GetSize(SIZE_MINE); o->fvec2ivec(&pn, &p1);
pn.fx = parent->GetSize(SIZE_BOUNDS_XMAX); o->fvec2ivec(&pn, &p2);
gl1[0].x = iround(p1.fx); gl1[0].y = iround(p1.fy);
gl1[1].x = iround(p2.fx); gl1[1].y = iround(p2.fy);
gl1[0].z = iround(p1.fz); gl1[1].z = iround(p2.fz);
if(ls[0] = new line_segment(this, data, &LineDef, &gl1[0], &gl1[1]))
ls[0]->DoPlot(o);
UpdateMinMaxRect(&rDims, gl1[0].x, gl1[0].y);
UpdateMinMaxRect(&rDims, gl1[1].x, gl1[1].y);
}
if(type & 0x02) {
pn.fx = parent->GetSize(SIZE_BOUNDS_XMIN); pn.fy = parent->GetSize(SIZE_BOUNDS_YMIN);
pn.fz = parent->GetSize(SIZE_MINE); o->fvec2ivec(&pn, &p1);
pn.fy = parent->GetSize(SIZE_BOUNDS_YMAX); o->fvec2ivec(&pn, &p2);
gl1[2].x = iround(p1.fx); gl1[2].y = iround(p1.fy);
gl1[3].x = iround(p2.fx); gl1[3].y = iround(p2.fy);
gl1[2].z = iround(p1.fz); gl1[3].z = iround(p2.fz);
if(ls[1] = new line_segment(this, data, &LineDef, &gl1[2], &gl1[3]))
ls[1]->DoPlot(o);
UpdateMinMaxRect(&rDims, gl1[2].x, gl1[2].y);
UpdateMinMaxRect(&rDims, gl1[3].x, gl1[3].y);
}
if(type & 0x04) {
pn.fx = parent->GetSize(SIZE_BOUNDS_XMIN); pn.fy = parent->GetSize(SIZE_MINE);
pn.fz = parent->GetSize(SIZE_BOUNDS_ZMIN); o->fvec2ivec(&pn, &p1);
pn.fx = parent->GetSize(SIZE_BOUNDS_XMAX); o->fvec2ivec(&pn, &p2);
gl2[0].x = iround(p1.fx); gl2[0].y = iround(p1.fy);
gl2[1].x = iround(p2.fx); gl2[1].y = iround(p2.fy);
gl2[0].z = iround(p1.fz); gl2[1].z = iround(p2.fz);
if(ls[2] = new line_segment(this, data, &LineDef, &gl2[0], &gl2[1]))
ls[2]->DoPlot(o);
UpdateMinMaxRect(&rDims, gl2[0].x, gl2[0].y);
UpdateMinMaxRect(&rDims, gl2[1].x, gl2[1].y);
}
if(type & 0x08) {
pn.fx = parent->GetSize(SIZE_BOUNDS_XMIN); pn.fy = parent->GetSize(SIZE_MINE);
pn.fz = parent->GetSize(SIZE_BOUNDS_ZMIN); o->fvec2ivec(&pn, &p1);
pn.fz = parent->GetSize(SIZE_BOUNDS_ZMAX); o->fvec2ivec(&pn, &p2);
gl2[2].x = iround(p1.fx); gl2[2].y = iround(p1.fy);
gl2[3].x = iround(p2.fx); gl2[3].y = iround(p2.fy);
gl2[2].z = iround(p1.fz); gl2[3].z = iround(p2.fz);
if(ls[3] = new line_segment(this, data, &LineDef, &gl2[2], &gl2[3]))
ls[3]->DoPlot(o);
UpdateMinMaxRect(&rDims, gl2[2].x, gl2[2].y);
UpdateMinMaxRect(&rDims, gl2[3].x, gl2[3].y);
}
if(type & 0x10) {
pn.fx = parent->GetSize(SIZE_MINE); pn.fy = parent->GetSize(SIZE_BOUNDS_YMIN);
pn.fz = parent->GetSize(SIZE_BOUNDS_ZMIN); o->fvec2ivec(&pn, &p1);
pn.fy = parent->GetSize(SIZE_BOUNDS_YMAX); o->fvec2ivec(&pn, &p2);
gl3[0].x = iround(p1.fx); gl3[0].y = iround(p1.fy);
gl3[1].x = iround(p2.fx); gl3[1].y = iround(p2.fy);
gl3[0].z = iround(p1.fz); gl3[1].z = iround(p2.fz);
if(ls[4] = new line_segment(this, data, &LineDef, &gl3[0], &gl3[1]))
ls[4]->DoPlot(o);
UpdateMinMaxRect(&rDims, gl3[0].x, gl3[0].y);
UpdateMinMaxRect(&rDims, gl3[1].x, gl3[1].y);
}
if(type & 0x20) {
pn.fx = parent->GetSize(SIZE_MINE); pn.fy = parent->GetSize(SIZE_BOUNDS_YMIN);
pn.fz = parent->GetSize(SIZE_BOUNDS_ZMIN); o->fvec2ivec(&pn, &p1);
pn.fz = parent->GetSize(SIZE_BOUNDS_ZMAX); o->fvec2ivec(&pn, &p2);
gl3[2].x = iround(p1.fx); gl3[2].y = iround(p1.fy);
gl3[3].x = iround(p2.fx); gl3[3].y = iround(p2.fy);
gl3[2].z = iround(p1.fz); gl3[3].z = iround(p2.fz);
if(ls[5] = new line_segment(this, data, &LineDef, &gl3[2], &gl3[3]))
ls[5]->DoPlot(o);
UpdateMinMaxRect(&rDims, gl3[2].x, gl3[2].y);
UpdateMinMaxRect(&rDims, gl3[3].x, gl3[3].y);
}
}
IncrementMinMaxRect(&rDims, 4);
}
bool
GridLine3D::Command(int cmd, void *tmpl, anyOutput *o)
{
int i;
switch(cmd) {
case CMD_SET_DATAOBJ:
Id = GO_GRIDLINE3D;
return true;
case CMD_MOUSE_EVENT:
if(tmpl && ls) switch (((MouseEvent *)tmpl)->Action) {
case MOUSE_LBUP:
for(i = 0; i < 6; i++) if(ls[i] &&
ls[i]->ObjThere(((MouseEvent *)tmpl)->x, ((MouseEvent *)tmpl)->y)) {
o->ShowMark(this, MRK_GODRAW);
return true;
}
}
break;
default:
return GridLine::Command(cmd, tmpl, o);
}
return false;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Radial Gridline for polar plots: spokes for the plot
GridRadial::GridRadial(GraphObj *par, DataObj *d, int which, DWORD df):
GridLine(par, d, which, df)
{
Id = GO_GRIDRADIAL;
}
GridRadial::GridRadial(int src):GridLine(src)
{
}
GridRadial::~GridRadial()
{
if(mo) DelBitmapClass(mo); mo = 0L;
}
void
GridRadial::DoPlot(anyOutput *o)
{
AxisDEF *axdef;
if(!parent || !o) return;
if(mo) DelBitmapClass(mo); mo = 0L;
o->SetLine(&LineDef);
if(parent->Id == GO_TICK && parent->parent && parent->parent->Id == GO_AXIS) {
axdef = (AxisDEF*)((Axis*)(parent->parent))->GetAxis();
pts[0].x = iround(parent->GetSize(SIZE_XBASE));
pts[0].y = iround(parent->GetSize(SIZE_YBASE));
pts[1].x = o->co2ix(axdef->Center.fx + parent->GetSize(SIZE_GRECT_LEFT));
pts[1].y = o->co2iy(axdef->Center.fy + parent->GetSize(SIZE_GRECT_TOP));
SetMinMaxRect(&rDims, pts[0].x, pts[0].y, pts[1].x, pts[1].y);
IncrementMinMaxRect(&rDims, 3);
o->oPolyline(pts, 2);
}
}
void
GridRadial::DoMark(anyOutput *o, bool mark)
{
if(mark) {
memcpy(&mrc, &rDims, sizeof(RECT));
IncrementMinMaxRect(&mrc, 6 + o->un2ix(LineDef.width));
mo = GetRectBitmap(&mrc, o);
InvertLine(pts, 2, &LineDef, &rDims, o, mark);
}
else if(mo) RestoreRectBitmap(&mo, &mrc, o);
}
bool
GridRadial::Command(int cmd, void *tmpl, anyOutput *o)
{
POINT p1;
switch(cmd) {
case CMD_SET_DATAOBJ:
Id = GO_GRIDRADIAL;
return true;
case CMD_MOUSE_EVENT:
if(tmpl) switch (((MouseEvent *)tmpl)->Action) {
case MOUSE_LBUP:
if(IsInRect(&rDims, p1.x=((MouseEvent *)tmpl)->x, p1.y=((MouseEvent *)tmpl)->y)){
if(IsCloseToPL(p1, pts, 2)) {
o->ShowMark(this, MRK_GODRAW);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -