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

📄 output.cpp

📁 Linux/windows 环境下跨平台开发程序
💻 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 + -