📄 output.cpp
字号:
//Output.cpp, Copyright (c) 2000, 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
//
#include <math.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <fcntl.h> //file open flags
#include <sys/stat.h> //I/O flags
#ifdef _WINDOWS
#include <io.h> //for read/write
#else
#define O_BINARY 0x0
#include <unistd.h>
#endif
#include "rlplot.h"
tag_Units Units[] = {{0, "mm", 1.0f}, {1, "cm", 10.0f}, {2, "inch", 25.4f},
};
extern Default defs;
extern GraphObj *CurrGO, *TrackGO; //Selected Graphic Objects
extern Label *CurrLabel;
extern Graph *CurrGraph;
extern dragHandle *CurrHandle;
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Output base class
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
anyOutput::anyOutput()
{
units = defs.cUnits;
dBgCol = dFillCol = defs.Color(COL_BG);
xAxis.owner = yAxis.owner = zAxis.owner = (void *)this;
xAxis.flags = yAxis.flags = zAxis.flags = 0L;
xAxis.min = yAxis.min = zAxis.min = 0.0;
xAxis.max = yAxis.max = zAxis.max = 1.0;
xAxis.nBreaks = yAxis.nBreaks = zAxis.nBreaks = 0;
xAxis.breaks = yAxis.breaks = zAxis.breaks = 0L;
ddx = ddy = ddz = 1.0;
RLP.finc = 1.0f;
RLP.fp = 0.0f;
dPattern = 0xffffffffL; //impossible (invisible)line pattern to start with
dBgCol = defs.Color(COL_BG);
MrkMode = MRK_NONE; MrkRect = 0L;
VPorg.fx = VPorg.fy = 0.0; VPscale = 1.0;
MenuHeight = 0; cCursor = MC_ARROW;
rotM[0][0] = rotM[1][1] = rotM[2][2] = 1.0;
rotM[0][1] = rotM[0][2] = rotM[1][0] = rotM[1][2] = rotM[2][0] = rotM[2][1] = 0.0;
hasHistMenu = false; HistMenuSize = 0;
light_source.fx = light_source.fy = 0.0;
}
void
anyOutput::SetRect(fRECT rec, int u, AxisDEF *x_ax, AxisDEF *y_ax)
{
double spx, spy;
if (u >= 0 && u < NUM_UNITS) defs.cUnits = units = u;
else units = defs.cUnits;
spx = rec.Xmax - rec.Xmin; spy = rec.Ymin -rec.Ymax;
MrkMode = MRK_NONE;
Box1.Xmin = co2fix(rec.Xmin); Box1.Ymin = co2fiy(rec.Ymax);
Box1.Xmax = co2fix(rec.Xmax); Box1.Ymax = co2fiy(rec.Ymin);
if(!x_ax || !y_ax) return;
if(x_ax->flags & AXIS_DEFRECT) {
Box1.Xmin = co2fix(x_ax->loc[0].fx);
Box1.Xmax = co2fix(x_ax->loc[1].fx);
spx = x_ax->loc[1].fx - x_ax->loc[0].fx;
}
if(y_ax->flags & AXIS_DEFRECT) {
Box1.Ymin = co2fiy(y_ax->loc[0].fy);
Box1.Ymax = co2fiy(y_ax->loc[1].fy);
spy = y_ax->loc[1].fy - y_ax->loc[0].fy;
}
memcpy(&xAxis, x_ax, sizeof(AxisDEF));
memcpy(&yAxis, y_ax, sizeof(AxisDEF));
ddy = GetAxisFac(&yAxis, un2fiy(spy), 1);
ddx = GetAxisFac(&xAxis, un2fix(spx), 0);
xAxis.owner = yAxis.owner = this;
}
void
anyOutput::SetSpace(fPOINT3D *cub1, fPOINT3D *cub2, int u, double *rot,
fPOINT3D *cent, AxisDEF *x_ax, AxisDEF *y_ax, AxisDEF *z_ax)
{
double rotQ[6]; //rotation definition:
// unit vector x
// y
// z
// sin(phi)
// cos(phi)
// 1.0 -cos(phi)
double dp;
if (u >= 0 && u < NUM_UNITS) defs.cUnits = units = u;
else units = defs.cUnits;
MrkMode = MRK_NONE;
HideTextCursor();
memcpy(&xAxis, x_ax, sizeof(AxisDEF));
memcpy(&yAxis, y_ax, sizeof(AxisDEF));
memcpy(&zAxis, z_ax, sizeof(AxisDEF));
xAxis.owner = yAxis.owner = zAxis.owner = this;
//assume resolution equal in all directions: use un2fix() for
// all coordinates
Box1.Xmin = co2fix(cub1->fx); Box1.Ymin = co2fiy(cub2->fy);
Box1.Xmax = co2fix(cub2->fx); Box1.Ymax = co2fiy(cub1->fy);
Box1z.fx = un2fiz(cub1->fz); Box1z.fy = un2fiz(cub2->fz);
if(x_ax->flags & AXIS_DEFRECT) {
Box1.Xmin = co2fix(x_ax->loc[0].fx); Box1.Xmax = co2fix(x_ax->loc[1].fx);
}
if(y_ax->flags & AXIS_DEFRECT) {
Box1.Ymax = co2fiy(y_ax->loc[0].fy); Box1.Ymin = co2fiy(y_ax->loc[1].fy);
}
if(z_ax->flags & AXIS_DEFRECT) {
Box1z.fx = un2fiz(z_ax->loc[0].fz); Box1z.fy = un2fiz(z_ax->loc[1].fz);
}
ddx = GetAxisFac(&xAxis, Box1.Xmax-Box1.Xmin, 0);
ddy = GetAxisFac(&yAxis, Box1.Ymax-Box1.Ymin, 1);
ddz = GetAxisFac(&zAxis, Box1z.fy - Box1z.fx, 2);
rotC.fx = un2fix(cent->fx)+ VPorg.fx;
rotC.fy = un2fiy(cent->fy)+ VPorg.fy;
rotC.fz = un2fiz(cent->fz);
memcpy(rotQ, rot, sizeof(rotQ));
//normalize vector part of rotQ
dp = sqrt(rotQ[0]*rotQ[0] + rotQ[1]*rotQ[1] + rotQ[2]*rotQ[2]);
rotQ[0] /= dp; rotQ[1] /= dp; rotQ[2] /= dp;
dp = sqrt(rotQ[0]*rotQ[0] + rotQ[1]*rotQ[1] + rotQ[2]*rotQ[2]);
//set up rotation matrix from quaternion
//see: Graphic Gems, A.S. Glassner ed.; Academic Press Inc.
//M.E. Pique: Rotation Tools
// ISBN 0-12-286165-5, p. 466
rotM[0][0] = rotQ[5]*rotQ[0]*rotQ[0] + rotQ[4];
rotM[0][1] = rotQ[5]*rotQ[0]*rotQ[1] + rotQ[3]*rotQ[2];
rotM[0][2] = rotQ[5]*rotQ[0]*rotQ[2] - rotQ[3]*rotQ[1];
rotM[1][0] = rotQ[5]*rotQ[0]*rotQ[1] - rotQ[3]*rotQ[2];
rotM[1][1] = rotQ[5]*rotQ[1]*rotQ[1] + rotQ[4];
rotM[1][2] = rotQ[5]*rotQ[1]*rotQ[2] + rotQ[3]*rotQ[0];
rotM[2][0] = rotQ[5]*rotQ[0]*rotQ[2] + rotQ[3]*rotQ[1];
rotM[2][1] = rotQ[5]*rotQ[1]*rotQ[2] - rotQ[3]*rotQ[0];
rotM[2][2] = rotQ[5]*rotQ[2]*rotQ[2] + rotQ[4];
}
void
anyOutput::LightSource(double x, double y)
{
int i, j, m;
double angx, angy;
double a[3][3], b[3][3];
if(light_source.fx == 0.0 || light_source.fy == 0.0 ||
x != light_source.fx || y != light_source.fy) {
light_source.fx = x; light_source.fy = y;
angx = x * 0.017453292; angy = y * 0.017453292;
for (i = 0; i < 3; i++) for(j = 0; j < 3; j++) {
a[i][j] = b[i][j] = 0.0;
}
//first axis
a[0][0] = 1.0; a[1][1] = cos(angx); a[1][2] = -sin(angx);
a[2][1] = -a[1][2]; a[2][2] = a[1][1];
//second axis
b[0][0] = cos(angy); b[0][1] = -sin(angy); b[1][0] = -b[0][1];
b[1][1] = b[0][0]; b[2][2] = 1.0;
//combine the two rotations
for (i = 0; i < 3; i++) for(j = 0; j < 3; j++){
light_vec[i][j] = 0.0;
for(m = 0; m < 3; m++) light_vec[i][j] += (a[i][m] * b[m][j]);
}
}
}
DWORD
anyOutput::VecColor(double *plane_vec, DWORD color1, DWORD color2)
{
double v[3], vec[3], vlength;
int i, j;
//rotate vector towards the light source
if(!plane_vec) return color1;
v[0] = plane_vec[0]; v[1] = plane_vec[2]; v[2] = plane_vec[1];
for (i = 0; i < 3; i++) for(j = 0, vec[i] = 0.0; j < 3; j++)
vec[i] += (light_vec[i][j] * v[j]);
//normalize vec: both vector should have unit length but make sure
vlength = sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
if(vlength < 0.9) return color1;
vec[0] /= vlength; vec[1] /= vlength; vec[2] /= vlength;
//calc color
return IpolCol(color1, color2, fabs(vec[1]));
}
bool
anyOutput::GetSize(RECT *rc)
{
memcpy(rc, &DeskRect, sizeof(RECT));
return true;
}
double
anyOutput::fx2fix(double x)
{
double temp;
x = TransformValue(&xAxis, x, true);
temp = (x - xAxis.min)*ddx;
if(0 == (xAxis.flags & AXIS_INVERT)) return temp + Box1.Xmin;
return Box1.Xmax-temp;
}
double
anyOutput::fy2fiy(double y)
{
double temp;
y = TransformValue(&yAxis, y, true);
temp = (y - yAxis.min)*ddy;
if(AXIS_INVERT == (yAxis.flags & AXIS_INVERT)) return temp + Box1.Ymin;
return Box1.Ymax-temp;
}
double
anyOutput::fz2fiz(double z)
{
double temp;
z = TransformValue(&zAxis, z, true);
temp = (z - zAxis.min)*ddz;
if(0 == (zAxis.flags & AXIS_INVERT)) return temp + Box1z.fx;
return Box1z.fy-temp;
}
bool
anyOutput::fp2fip(lfPOINT *fdp, lfPOINT *fip)
{
double x, y, si, csi, temp;
if((xAxis.flags & AXIS_ANGULAR) && (yAxis.flags & AXIS_RADIAL)) {
x = 6.283185307 * TransformValue(&xAxis, fdp->fx + xAxis.Start, true)/(xAxis.max-xAxis.min);
si = sin(x); csi = cos(x);
y = TransformValue(&yAxis, fdp->fy, true);
temp = (y - yAxis.min)*ddy;
if(yAxis.flags & AXIS_INVERT) temp = Box1.Ymax - Box1.Ymin - temp;
fip->fx = ((Box1.Xmin + Box1.Xmax)/2.0) + csi * temp;
if(xAxis.flags & AXIS_INVERT) fip->fy = Box1.Ymax + si * temp;
else fip->fy = Box1.Ymax - si * temp;
fip->fy += disp_y;
return true;
}
else {
fip->fx = fx2fix(fdp->fx); fip->fy = fy2fiy(fdp->fy);
return true;
}
return false;
}
bool
anyOutput::fvec2ivec(fPOINT3D *v, fPOINT3D *iv)
{
double x, y, z;
if(!v || !iv) return false;
x = fx2fix(v->fx)-rotC.fx;
y = fy2fiy(v->fy)-rotC.fy;
z = fz2fiz(v->fz)-rotC.fz;
iv->fx = x * rotM[0][0] + y * rotM[0][1] + z * rotM[0][2] + rotC.fx;
iv->fy = x * rotM[1][0] + y * rotM[1][1] + z * rotM[1][2] + rotC.fy;
iv->fz = x * rotM[2][0] + y * rotM[2][1] + z * rotM[2][2] + rotC.fz;
iv->fx += disp_x; iv->fy += disp_y;
return true;
}
bool
anyOutput::cvec2ivec(fPOINT3D *v, fPOINT3D *iv)
{
double x, y, z;
if(!v || !iv) return false;
x = co2fix(v->fx)-rotC.fx;
y = co2fiy(v->fy)-rotC.fy;
z = un2fiz(v->fz)-rotC.fz;
iv->fx = x * rotM[0][0] + y * rotM[0][1] + z * rotM[0][2] + rotC.fx;
iv->fy = x * rotM[1][0] + y * rotM[1][1] + z * rotM[1][2] + rotC.fy;
iv->fz = x * rotM[2][0] + y * rotM[2][1] + z * rotM[2][2] + rotC.fz;
iv->fx += disp_x; iv->fy += disp_y;
return true;
}
bool
anyOutput::uvec2ivec(fPOINT3D *v, fPOINT3D *iv)
{
double x, y, z;
if(!v || !iv) return false;
x = un2fix(v->fx);
y = un2fiy(v->fy);
z = un2fiz(v->fz);
iv->fx = x * rotM[0][0] + y * rotM[0][1] + z * rotM[0][2];
iv->fy = x * rotM[1][0] + y * rotM[1][1] + z * rotM[1][2];
iv->fz = x * rotM[2][0] + y * rotM[2][1] + z * rotM[2][2];
return true;
}
double
anyOutput::un2fix(double x)
{
return (x * VPscale * hres*Units[units].convert/25.4);
}
double
anyOutput::un2fiy(double y)
{
return (y * VPscale * vres*Units[units].convert/25.4);
}
double
anyOutput::un2fiz(double z)
{
return (z * VPscale * hres*Units[units].convert/25.4);
}
double
anyOutput::fix2un(double fix)
{
return (fix/Units[units].convert*25.4/hres)/VPscale;
}
double
anyOutput::fiy2un(double fiy)
{
return (fiy/Units[units].convert*25.4/vres)/VPscale;
}
bool
anyOutput::GetLine(LineDEF *lDef)
{
if(lDef) {
lDef->width = LineWidth;
lDef->color = dLineCol;
lDef->pattern = dPattern;
return true;
}
return false;
}
bool
anyOutput::SetTextSpec(TextDEF *set)
{
memcpy(&TxtSet, set, sizeof(TextDEF));
TxtSet.text = 0L;
return true;
}
bool
anyOutput::ShowMark(void *src, int Mode)
{
GraphObj *go;
if(MrkMode != MRK_NONE) HideMark();
MrkMode = Mode; MrkRect = src;
switch (Mode) {
case MRK_INVERT:
return UpdateRect((RECT*)src, true);
case MRK_GODRAW: case MRK_SSB_DRAW:
go = (GraphObj *) src;
go->DoMark(this, true);
CurrGO = go;
if(CurrLabel && CurrLabel != CurrGO) {
HideTextCursor();
CurrLabel = 0L;
}
return true;
}
return false;
}
bool
anyOutput::HideMark()
{
CurrGO = 0L;
switch(MrkMode) {
case MRK_NONE:
return true;
case MRK_INVERT:
MrkMode = MRK_NONE;
return UpdateRect((RECT*)MrkRect, false);
case MRK_GODRAW:
MrkMode = MRK_NONE; //inhibit reentrance
if(CurrGraph) {
if(CurrGraph->Command(CMD_HIDE_MARK, MrkRect, this)){
return true;
}
else CurrGraph->Command(CMD_REDRAW, 0L, this);
}
return true;
case MRK_SSB_DRAW:
MrkMode = MRK_NONE;
if (MrkRect) ((GraphObj*)MrkRect)->DoMark(this, false);
return true;
}
return false;
}
int
anyOutput::CalcCursorPos(char *txt, POINT p, POINT *fit)
{
int i, d, w, h, CurrPos;
d = TxtSet.iSize >>2;
if(!txt || !fit) return 0;
if (!(i = strlen(txt)))return 0;
//right justified text
if(TXA_HRIGHT == (TxtSet.Align & TXA_HRIGHT)){
if((p.x - fit->x) < d) return i;
for (CurrPos = i-1; CurrPos >= 0; CurrPos--) {
if(!oGetTextExtent(txt+CurrPos, i-CurrPos, &w, &h)) return 0;
if((w = p.x - w - d) <= fit->x) return CurrPos;
}
return 0;
}
//left justified text
else {
if((fit->x - p.x) < d) return 0;
for (CurrPos = i; CurrPos >= 0; CurrPos--) {
if(!oGetTextExtent(txt, CurrPos, &w, &h)) return 0;
if((w = p.x + w - d) <= fit->x) return CurrPos;
}
}
return 0;
}
bool
anyOutput::TextCursor(char *txt, POINT p, POINT *fit, int *pos, int dx)
{
int i, w, h, CurrPos;
RECT disp;
if(fit) CurrPos = CalcCursorPos(txt, p, fit);
//recalculate caret position
if(txt && pos && !fit){
if(TxtSet.Align & TXA_HRIGHT) { //right justfied text
if((i = strlen(txt)-(*pos))){
if(!oGetTextExtent(txt+(*pos), i, &w, &h)) return false;
w = p.x - w;
}
else w = p.x-1;
}
else { //left justified text
if(!(*pos)) w = 0;
else if(!oGetTextExtent(txt, *pos, &w, &h))return false;
w += p.x;
}
}
else if(!fit)return false;
//right justified text: search caret and cursor position
else if(txt && (TxtSet.Align & TXA_HRIGHT)){
i = strlen(txt);
if(i == CurrPos) w = 1;
else if(!oGetTextExtent(txt+CurrPos, i-CurrPos, &w, &h)) return false;
w = p.x - w;
}
//left justified text: search caret and cursor position
else if(txt && fit) {
if (!CurrPos) w = 0;
else if(!oGetTextExtent(txt, CurrPos, & w, &h)) return false;
w += p.x;
}
if(fit && pos) *pos = CurrPos;
disp.left = disp.right = w+dx;
disp.top = p.y;
#ifdef _WINDOWS
disp.bottom = disp.top + TxtSet.iSize;
#else
disp.bottom = disp.top + iround(TxtSet.iSize*1.25);
#endif
ShowTextCursor(this, &disp, 0x0L);
return true;
}
//we need our own implementation of Bresenham's line drawing algorithm to draw
// a line with variable pattern sizes.
//Ref: P.S. Heckbert (1990) "Digital Line Drawing", in: Graphic Gems
// (A.S. Glassner, ed.); Academic Press, Inc.,
// ISBN 0-12-286165-5
bool
anyOutput::PatLine(POINT p1, POINT p2)
{
int d, ax, ay, sx, sy, dx, dy;
double fInc2;
bool bPen;
POINT tr[2];
dx = p2.x - p1.x;
fInc2 = RLP.finc * 0.414213562; //increment by sqrt(2) if 45
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -