SourceCode/PROMS/XYPlots/XYPlots.cs
Rich 5271561b84 Erase the existing background (including any lines) before drawing a box. This allows boxes to be placed over curves and lines.
Change the order of lines being drawn to support boxes being able to be placed on top of curves and lines.
2013-10-24 21:47:01 +00:00

1974 lines
55 KiB
C#
Raw Blame History

using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Windows.Forms;
using System.Text;
using System.Drawing;
using System.Text.RegularExpressions;
using VG;
namespace XYPlots
{
/// <summary>
/// Summary description for XYPlot.
/// </summary>
public class XYPlot
{
static string _MyFontFamily = "Letter Gothic Tall";
public static string MyFontFamily
{
get { return _MyFontFamily; }
set { _MyFontFamily = value; }
}
private static Color _BlackColor = Color.Red;
public static Color BlackColor
{
get { return VG.VG.BlackColor; }
set { VG.VG.BlackColor = value; }
}
public float Width
{
get { return 72 * (LeftMargin + RightMargin) + printerunits[0] * .05F; }
}
public float Height
{
get { return 72 * (TopMargin + BottomMargin) + printerunits[1] * .05F; }
}
public float PlotWidth
{
get { return (float) userunits[X]; }
}
public float PlotHeight
{
get { return (float) userunits[Y]; }
}
private double ConvertToTwips = 4.8;
static int MAX_XY_STACK = 8; /* this is max of CIE cursor/font stack */
static int DPI = 1440; //300;
static int CWIDEDOTS = 120; //25;
static int CHIGHDOTS = 240; //50;
static int STRAIGHT = 0;
static int CURVE = 1;
static int X = 0;
static int Y = 1;
static int Dimensions = 2;
static int USER = 0;
static int PLOT = 1;
static double PI = 3.141592653;
static double Zero = 0.0;
static double ANGLELIMIT = 1.0;
// !!!! NEED REAL SUPERSCRIPT ON/OFF TOKENS
static string[] SuperScript = { "##", "##" };
static string[] SubScript = { "~~", "~~" };
FileStream XYPlotFile;
private int[] SavedX;
private int[] SavedY;
private int stack;
/// <summary>
/// Set All Margins at once
/// </summary>
/// <param name="leftMargin">Left Margin in Inches.</param>
/// <param name="topMargin">Top Margin in Inches.</param>
/// <param name="rightMargin">Right Margin in Inches.</param>
/// <param name="bottomMargin">Bottom Margin in Inches.</param>
public void SetMargins(float leftMargin, float topMargin, float rightMargin, float bottomMargin)
{
_LeftMargin = leftMargin * 1440;
_TopMargin = yTopMarginAdjust + topMargin * 1440;
_RightMargin = rightMargin * 1440;
_BottomMargin = bottomMargin * 1440;
}
private float _LeftMargin = 1440;
/// <summary>
/// Left Margin in Inches.
/// </summary>
public float LeftMargin
{
get { return _LeftMargin / 1440; }
set { _LeftMargin = value * 1440; }
}
private float _RightMargin = 720;
/// <summary>
/// Right Margin in Inches.
/// </summary>
public float RightMargin
{
get { return _RightMargin / 1440; }
set { _RightMargin = value * 1440; }
}
private float _TopMargin = 1440;
/// <summary>
/// Top Margin in Inches.
/// </summary>
public float TopMargin
{
get { return _TopMargin / 1440; }
set { _TopMargin = value * 1440; }
}
private float _BottomMargin = 1440;
/// <summary>
/// Bottom Margin in Inches.
/// </summary>
public float BottomMargin
{
get { return _BottomMargin / 1440; }
set { _BottomMargin = value * 1440; }
}
public int LinesUsed;
private string valuestring;
private string powerstring;
private int GridOnFlag, Visible, ShadowFlag;
private char[] type = new char[Dimensions];
private double FontPitch = 10.0;
private double[] minimum = new double[Dimensions];
private double[] maximum = new double[Dimensions];
private double[] userunits = new double[Dimensions];
private int[] printerunits = new int[Dimensions];
private int[] Position = new int[Dimensions];
private double[,] Scale = new double[2, Dimensions];
private double[,] Offset = new double[2, Dimensions];
private double[] delta = new double[Dimensions];
private int[] cycles = new int[Dimensions];
private int[] onecycle = new int[Dimensions];
private int[] minor = new int[Dimensions];
private int[] spcminor = new int[Dimensions];
private string[] AxisTitles = new string[Dimensions];
private int[] AxisLabel = new int[Dimensions];// 1 for YES(default), 0 for NO
private int CurPenWidth, DrawDirection, LineFlag, LineDiv;
private int EndFlag = 0;
public string Buff;
private int BuffPtr = 0;
private bool[,] doLOG10 = { { false, false }, { false, false } };
public struct point
{
public int[] xyValue; //new int[Dimensions];
}
public struct XyBox
{
public int Shadow;
public string BoxText;
public point BoxMinimum;
public point BoxMaximum;
};
public class XyBoxes : List<XyBox>
{
}
private XyBoxes AllBoxes = new XyBoxes();
private XyBoxes ActiveBoxes = new XyBoxes();
public class DataPoint
{
private point m_APoint;
public point APoint
{
get { return m_APoint; }
set { m_APoint = value; }
}
private double m_slope; // slope of tangent to circle at this point
public double slope
{
get { return m_slope; }
set { m_slope = value; }
}
};
public class DataPoints : List<DataPoint>
{
}
public struct PlotLine
{
public int PlotType;
public int PlotDivisions;
public DataPoints PlotDataPoints;
};
private List<PlotLine> AllPlots = new List<PlotLine>();
private int YLandScape = 0; /* y axis title is horizontal */
private point YTitleOrigin; /* y axis title origin if vertical */
private double FixAngle(double a1)
{
double retval;
int sign;
if (a1 < 0)
{
a1 = -a1;
sign = -1;
}
else
sign = 1;
retval = sign * Math.Floor(0.5 + a1);
return retval;
}
private double dsquare(int val)
{
double result;
result = (double)(val * val);
return result;
}
private double FMin(double f1, double f2)
{
return ((f1 >= f2) ? f2 : f1);
}
private double FMax(double f1, double f2)
{
return ((f1 >= f2) ? f1 : f2);
}
private double atan_deg(double x)
{
return (Math.Atan(x) * 180.0 / PI);
}
private double cos_deg(double x)
{
return (Math.Cos(x * PI / 180.0));
}
private double tan_deg(double x)
{
return (Math.Tan(x * PI / 180.0));
}
private double sin_deg(double x)
{
return (Math.Sin(x * PI / 180.0));
}
/// <summary>
/// the following function is pointed to by a function pointer
/// and is provided for compatibility with log10() function usage
/// </summary>
/// <param name="x"></param>
/// <returns></returns>
private double linear(double x)
{
return x;
}
private bool isWhiteSpace(char cptr)
{
bool rtnval = false;
if (!cptr.Equals(null))
{
int idx = "\t\n\r\f ".IndexOf(cptr);
rtnval = (idx > -1);
}
return rtnval;
}
private string NextPiece()
{
string rtnval;
int ptr;
while (BuffPtr >= 0 && Buff[BuffPtr] != 0 && isWhiteSpace(Buff[BuffPtr])) BuffPtr++;
ptr = BuffPtr;
while (BuffPtr >= 0 && Buff[BuffPtr] != 0 && !isWhiteSpace(Buff[BuffPtr])) BuffPtr++;
if (EndOfCommand()) EndFlag = 1;
rtnval = Buff.Substring(ptr, BuffPtr - ptr);
BuffPtr++;
return rtnval;
}
private bool EndOfCommand()
{
int tmpPtr = BuffPtr;
while (!Buff[tmpPtr].Equals('\0') && Buff[tmpPtr].Equals(' ')) tmpPtr++;
if (!Buff[tmpPtr].Equals('\0') && !isWhiteSpace(Buff[tmpPtr]))
return false;
else if (Buff[tmpPtr] == '\r' || Buff[tmpPtr] == '\n' || Buff[tmpPtr] == '\0')
return true;
else
return false;
}
private bool LoadBuff(string FileName)
{
if (!File.Exists(FileName))
{
// File does not exist, show error message
MessageBox.Show(String.Format("X/Y Plot File {0} Does Not Exist", FileName), "Error Opening X/Y Plot File");
return false;
}
// Open the X/Y Plot file
try
{
XYPlotFile = File.OpenRead(FileName);
}
catch (Exception e)
{
// cannot open the x/y plot file
MessageBox.Show(e.Message, String.Format("Error Opening {0} for Reading", FileName));
return false;
}
int blen = (int)XYPlotFile.Length;
int bread = 0;
// initialize a byte array to read into
byte[] bbuf = new byte[blen + 1];
for (int i = 0; i < blen; i++) bbuf[i] = 0;
// Read the contents of the x/y plot file into the byte array
try
{
bread = XYPlotFile.Read(bbuf, 0, blen);
}
catch (Exception e)
{
MessageBox.Show(e.Message, String.Format("Error Reading {0}", FileName));
return false;
}
try
{
XYPlotFile.Close();
}
catch (Exception e)
{
MessageBox.Show(e.Message, String.Format("Error Closing {0}", FileName));
return false;
}
StringBuilder sb = new StringBuilder();
for (int i = 0; i < bbuf.Length; i++)
{
if (bbuf[i] == '\r' && bbuf[i - 1] == ' ')
sb.Remove(i - 1, 1);
sb.Append(Convert.ToChar(bbuf[i]));
}
Buff = sb.ToString();
BuffPtr = 0;
return true;
}
private void LoadBuffFromString(string str)
{
Buff = str;
}
private int getint()
{
int retval;
string np = NextPiece();
np = Regex.Replace(np, "[^0-9]", "");
retval = Convert.ToInt32(np, 10);
return retval;
}
// A 'special' isWhiteSpaceDelta, NextPieceDelta, and getdoubleDelta was added because Wolf Creek
// has a ',' between the x/y delta of one of their plots (C-1).
// this was causing the x delta to be set to 50,250.
private bool isWhiteSpaceDelta(char cptr)
{
bool rtnval = false;
if (!cptr.Equals(null))
{
int idx = "\t\n\r\f ,".IndexOf(cptr);
rtnval = (idx > -1);
}
return rtnval;
}
private string NextPieceDelta()
{
string rtnval;
int ptr;
while (BuffPtr >= 0 && Buff[BuffPtr] != 0 && isWhiteSpaceDelta(Buff[BuffPtr])) BuffPtr++;
ptr = BuffPtr;
while (BuffPtr >= 0 && Buff[BuffPtr] != 0 && !isWhiteSpaceDelta(Buff[BuffPtr])) BuffPtr++;
if (EndOfCommand()) EndFlag = 1;
rtnval = Buff.Substring(ptr, BuffPtr - ptr);
BuffPtr++;
return rtnval;
}
private double getdoubleDelta()
{
double retval;
retval = Convert.ToDouble(NextPieceDelta());
return retval;
}
private double getdouble()
{
double retval;
retval = Convert.ToDouble(NextPiece());
return retval;
}
private char NextChar()
{
return Buff[BuffPtr++];
}
private char getchr()
{
string nxtstring = NextPiece();
if (nxtstring.Equals(""))
return '\0';
else
return nxtstring[0];
}
private point GetPair(int flag)
{
point retval = new point();
retval.xyValue = new int[Dimensions];
double x, y;
char[] sepchar = { ',' };
string[] xystr = NextPiece().Split(sepchar);
x = double.Parse(xystr[0]);
char[] trimEndDot = { '.' }; // Wolf Creek OFN SB-008, figure 3 had a string like 50.0. so trim the ending '.'
string ystr = xystr[1];
if (ystr.EndsWith(".0")) // bug fix B2012-169, the Trim converted a ".75" value to a "75.0" value
ystr = ystr.Trim(trimEndDot);
// count the number of '.', if there are two and the last char is a '.', trim it (this was causing
// a crash in CAL-OTO-OTO-BG-00001. This was done this way so as to be very specific to the
// problem found in Callaway, i.e. didn't want to break something else.
int cnt = 0;
int indx = ystr.IndexOf(".");
while (indx >= 0)
{
cnt++;
indx = indx+1==ystr.Length?-1:ystr.IndexOf(".", indx + 1);
}
if (cnt > 1) ystr = ystr.TrimEnd(trimEndDot);
y = double.Parse(ystr);
if (doLOG10[flag, X])
retval.xyValue[X] = (int)(Offset[flag, X] + Scale[flag, X] * Math.Log10(x) + .5);
else
retval.xyValue[X] = (int)(Offset[flag, X] + Scale[flag, X] * x + .5);
if (doLOG10[flag, Y])
retval.xyValue[Y] = (int)(printerunits[Y] - (Offset[flag, Y] + Scale[flag, Y] * Math.Log10(y) + .5));
else
retval.xyValue[Y] = (int)(printerunits[Y] - (Offset[flag, Y] + Scale[flag, Y] * y + .5));
return (retval);
}
private string GetString()
{
char retval;
StringBuilder Lbuff = new StringBuilder();
retval = NextChar();
if (retval != '"')
MessageBox.Show("Double Quote not found", "String value syntax problem");
retval = NextChar();
while (retval != 0 && retval != '\n')
{
switch (retval)
{
case '"':
retval = NextChar();
if (retval == ' ')
{
Lbuff.Append('\n');
retval = NextChar();
retval = NextChar();
}
break;
case '\r':
retval = NextChar();
break;
case '\\':
retval = NextChar(); /*always take next*/
Lbuff.Append(retval);
retval = NextChar();
break;
default:
Lbuff.Append(retval);
retval = NextChar();
break;
}
}
return Lbuff.ToString();
}
private void FixBuffIfNeeded()
{
int ptr = 0;
Buff = Buff.Trim(" \r\n".ToCharArray());
while (Buff.Contains("> ")) Buff = Buff.Replace("> ", ">");
if (Buff.StartsWith("<<G "))
{
Buff = Buff.Substring(4);
}
// remove an extra spaces between ><
//Buff = Regex.Replace(Buff, @"[ ]+<", "<");
Buff = Buff.Replace(">\r ", ">\r\n ");
Buff = Regex.Replace(Buff, @"[ ]+<", "<");
// some data only had carriage return, replace these with cr/nl so that following code
// will work
Buff = Buff.Replace(">\r<", ">\r\n<");
Buff = Buff.Replace("><", ">\r\n<");
// some data had cr/cr/nl, change to cr/nl
Buff = Buff.Replace("\r\r\n", "\r\n");
while ((ptr = Buff.IndexOf(">\r\n<", ptr)) > 0)
{
// blank out ">"
Buff = Buff.Remove(ptr, 1);
Buff = Buff.Insert(ptr, " ");
// remove "<"
Buff = Buff.Remove(ptr + 3, 1);
// if command on next line is blank,
// combine with the previous line
if (Buff[ptr + 3] == ' ')
Buff = Buff.Remove(ptr, 3);
}
ptr = Buff.Length - 5; // back up past >>\r\n
if (Buff.IndexOf(">>\r\n", ptr) > 0)
{
Buff = Buff.Remove(ptr, 2);
Buff = Buff.Insert(ptr, " ");
}
else if (Buff.EndsWith(">>")) // doesn't end with return chars...
Buff = Buff.Substring(0, Buff.Length - 2) + " \r\n\0x00"; // needs to end with null
else if (Buff.EndsWith(">")) // doesn't end with return chars...
Buff = Buff.Substring(0, Buff.Length - 1) + " \r\n\0x00"; // needs to end with null
}
private void CloseGraph()
{
/* Send back number of lines used assuming 6 lines per inch */
if (LinesUsed == 0)
LinesUsed = (int)(1.5 * CHIGHDOTS); /* adjust for x axis tics */
LinesUsed += printerunits[Y];
LinesUsed = LinesUsed / CHIGHDOTS;
}
private void GetScaleInfo()
{
GridOnFlag = getint();
userunits[X] = getdouble();
userunits[Y] = getdouble();
printerunits[X] = (int)(DPI * userunits[X]);
printerunits[Y] = (int)(DPI * userunits[Y]);
minimum[X] = getdouble();
maximum[X] = getdouble();
minimum[Y] = getdouble();
maximum[Y] = getdouble();
type[X] = getchr();
type[Y] = getchr();
if (EndFlag == 0) delta[X] = getdoubleDelta();
if (EndFlag == 0) delta[Y] = getdoubleDelta();
if (EndFlag == 0) spcminor[X] = getint();
if (EndFlag == 0) spcminor[Y] = getint();
Offset[USER, X] = 0;
Offset[USER, Y] = 0;
Scale[USER, X] = DPI;
Scale[USER, Y] = DPI;
/*
in the following if blocks, the array variable f is a function
pointer which is set to either the function linear or log10.
*/
/* X-axis function generation and scaling */
if (type[X] != 'L')
{
// Linear
doLOG10[PLOT, X] = false;
LinearScale(X);
Scale[PLOT, X] = printerunits[X] / (maximum[X] - minimum[X]);
Offset[PLOT, X] = -Scale[PLOT, X] * minimum[X];
}
else
{
// Log10
doLOG10[PLOT, X] = true;
LogScale(X);
Scale[PLOT, X] = printerunits[X] /
(Math.Log10(maximum[X]) - Math.Log10(minimum[X]));
Offset[PLOT, X] = -Scale[PLOT, X] * Math.Log10(minimum[X]);
}
/* Y-axis function generation and scaling */
if (type[Y] != 'L')
{
// Linear
doLOG10[PLOT, Y] = false;
LinearScale(Y);
Scale[PLOT, Y] = printerunits[Y] / (maximum[Y] - minimum[Y]);
Offset[PLOT, Y] = -Scale[PLOT, Y] * minimum[Y];
}
else
{
// Log10
doLOG10[PLOT, Y] = true;
LogScale(Y);
Scale[PLOT, Y] = printerunits[Y] /
(Math.Log10(maximum[Y]) - Math.Log10(minimum[Y]));
Offset[PLOT, Y] = -Scale[PLOT, Y] * Math.Log10(minimum[Y]);
}
}
private void GetAxisTitle(int flag)
{
AxisTitles[flag] = GetString();
}
private string stripSuperSub(string instr)
{
StringBuilder sb = new StringBuilder(instr);
sb.Replace(SuperScript[0], "");
sb.Replace(SuperScript[1], "");
sb.Replace(SubScript[0], "");
sb.Replace(SubScript[1], "");
return sb.ToString();
}
private point DetermineBoxMax(XyBox boxptr)
{
point newval = new point();
newval.xyValue = new int[Dimensions];
string tmp;
int pos = 0, prevPos = 0;
int nl = 0, xmax = 0, ilen = 0;
tmp = stripSuperSub(boxptr.BoxText);
tmp = tmp.Replace("\r\n", "\n");
while ((pos = tmp.IndexOf('\n', pos)) > -1)
{
ilen = pos - prevPos;
xmax = Math.Max(xmax, ilen);
// OLD: prevPos = pos;
prevPos = pos + 1;
pos++;
nl++;
}
// OLD: ilen = tmp.Substring(prevPos + 1).Length;
ilen = tmp.Length - prevPos; // tmp.Substring(prevPos).Length;
xmax = Math.Max(xmax, ilen) + 2;
newval.xyValue[X] = boxptr.BoxMinimum.xyValue[X] + (xmax * CWIDEDOTS);
// OLD: newval.xyValue[Y] = boxptr.BoxMinimum.xyValue[Y] - (nl * CHIGHDOTS) - (int)(30 * ConvertToTwips);
newval.xyValue[Y] = boxptr.BoxMinimum.xyValue[Y] - (nl * CHIGHDOTS) - (int)(19 * ConvertToTwips);
return newval;
}
private float yTopMarginAdjust = 0;
private void GetBoxParameters()
{
XyBox NewBox = new XyBox();
point Origin;
Origin = GetPair(USER);
string str = GetString();
NewBox.BoxText = str;
NewBox.BoxMinimum = Origin;
NewBox.Shadow = ShadowFlag;
ShadowFlag = 0;
NewBox.BoxMaximum = DetermineBoxMax(NewBox);
point minPoint = new point();
minPoint.xyValue = new int[Dimensions];
point maxPoint = new point();
maxPoint.xyValue = new int[Dimensions];
minPoint.xyValue[X] = Origin.xyValue[X];
minPoint.xyValue[Y] = NewBox.BoxMaximum.xyValue[Y];
maxPoint.xyValue[X] = NewBox.BoxMaximum.xyValue[X];
maxPoint.xyValue[Y] = Origin.xyValue[Y];
NewBox.BoxMinimum = minPoint;
if (minPoint.xyValue[Y] < 0) // If the box is above the range of the Plot then the top margin must be adjusted
// so that the text is visible
yTopMarginAdjust = -(minPoint.xyValue[Y]+720); // TopMargin defaults to .5 Inches (720 Twips)
NewBox.BoxMaximum = maxPoint;
AllBoxes.Add(NewBox);
}
private void GetLineParameters()
{
DataPoints dataPoints = new DataPoints();
int pointcount;
pointcount = EndFlag = 0;
while (EndFlag == 0)
{
DataPoint pl = new DataPoint();
pl.APoint = new point();
pl.APoint = GetPair(PLOT);
pointcount++;
dataPoints.Add(pl);
}
if (LineFlag == CURVE && pointcount > 2)
CalculateSlopes(dataPoints);
else
LineFlag = STRAIGHT;
//#if DEBUG
//ShowPoints(dataPoints);
//#endif
AddAPlot(dataPoints);
}
private double FindSlope(point first, point last)
{
double dx, dy, result;
dx = last.xyValue[X] - first.xyValue[X];
dy = (last.xyValue[Y] - first.xyValue[Y]);
if (dx == 0.0)
{
if (dy > 0)
result = Convert.ToDouble("1.E99");
else
result = Convert.ToDouble("-1.E99");
}
else
result = dy / dx;
return result;
}
private double FindEndSlope(point first, point last, double s1)
{
double result;
result = 2.0 * FindSlope(first, last) - s1;
if (result * s1 < 0.0)
result = 0.0;
return result;
}
private void CalculateSlopes(DataPoints dataPoints)
{
DataPoint thispt, prevpt, firstpt;
long yval, y1, y3;
int PlAryIdx = 0;
int PlAryNumItems = dataPoints.Count;
prevpt = dataPoints[PlAryIdx];
PlAryIdx++;
thispt = dataPoints[PlAryIdx];
while (PlAryIdx + 1 < dataPoints.Count)
{
thispt.slope = Zero;
yval = thispt.APoint.xyValue[Y];
y1 = prevpt.APoint.xyValue[Y];
y3 = dataPoints[PlAryIdx + 1].APoint.xyValue[Y];
if ((yval - y1) * (y3 - yval) > 0)
thispt.slope = FindSlope(prevpt.APoint, dataPoints[PlAryIdx + 1].APoint);
prevpt = thispt;
PlAryIdx++;
thispt = dataPoints[PlAryIdx];
}
firstpt = dataPoints[0];
firstpt.slope = FindEndSlope(firstpt.APoint, dataPoints[1].APoint, dataPoints[1].slope);
thispt.slope = FindEndSlope(thispt.APoint, prevpt.APoint, prevpt.slope);
}
private void AddAPlot(DataPoints ptr)
{
PlotLine NewLine = new PlotLine();
NewLine.PlotType = LineFlag;
NewLine.PlotDivisions = LineDiv;
NewLine.PlotDataPoints = ptr;
AllPlots.Insert(0, NewLine);
}
private void GenerateGrid(VG.Page pg, IVGOutput vgOutput)
{
ActiveBoxes.Clear();
Position[X] = 0;
Position[Y] = 0; // printerunits[Y];
SavePosition();
SetPenDiameter(5);
BoxRelative(printerunits[X], printerunits[Y], CurPenWidth, pg, vgOutput);
if (GridOnFlag == 0) Visible = 0;
//if (vgOutput is VGOut_Graphics)
//{
DoGrid(X, pg, vgOutput, 1);
DoGrid(Y, pg, vgOutput, 1);
DoGrid(X, pg, vgOutput, 2);
DoGrid(Y, pg, vgOutput, 2);
DoGrid(X, pg, vgOutput, 3);
DoGrid(Y, pg, vgOutput, 3);
//}
//else if (vgOutput is VGOut_C1PDF)
//{
// DrawDirection = Y;
// DoGrid(X, pg, vgOutput);
// DrawDirection = X;
// DoGrid(Y, pg, vgOutput);
//}
Visible = 1;
RecallPosition();
// Draw outline last to overlap any grid lines.
//SetPenDiameter(5);
//BoxRelative(printerunits[X], printerunits[Y], CurPenWidth, pg, vgOutput);
}
private void DoGrid(int flag, VG.Page pg, IVGOutput vgOutput)
{
if (type[flag] != 'L')
DoLinearGrid(flag, pg, vgOutput);
else
DoLogGrid(flag, pg, vgOutput);
}
private void DoLinearGrid(int flag, VG.Page pg, IVGOutput vgOutput)
{
int i, n, ns, subminor;
int ptval;
n = (int)(0.5 + (maximum[flag] - minimum[flag]) / delta[flag]);
ns = n * minor[flag];
if ((minor[flag] % 2) != 0)
subminor = minor[flag];
else
subminor = minor[flag] / 2;
for (i = 0; i <= ns; i++)
{
SetPenDiameter((((i % minor[flag]) != 0) ? (((i % subminor) != 0) ? 1 : 2) : 3));
ptval = ((int)printerunits[flag]) * i / ns;
if (flag == Y)
ptval = printerunits[Y] - ptval;
MoveAbsolute(((flag == X) ? ptval : 0), ((flag == Y) ? ptval : 0));
if (i % minor[flag] == 0)
WriteValue(flag, minimum[flag] + i * delta[flag] / minor[flag], false, pg, vgOutput);
DrawGridLine((flag == 0) ? 1 : 0, ptval, pg, vgOutput);
}
}
private void DoGrid(int flag, VG.Page pg, IVGOutput vgOutput, int gridPen)
{
DrawDirection = 1 - flag;
if (type[flag] != 'L')
DoLinearGrid(flag, pg, vgOutput, gridPen);
else
if (gridPen == 3) DoLogGrid(flag, pg, vgOutput);
}
private void DoLinearGrid(int flag, VG.Page pg, IVGOutput vgOutput, int gridPen)
{
int i, n, ns, subminor;
int ptval;
n = (int)(0.5 + (maximum[flag] - minimum[flag]) / delta[flag]);
ns = n * minor[flag];
if ((minor[flag] % 2) != 0)
subminor = minor[flag];
else
subminor = minor[flag] / 2;
for (i = 0; i <= ns; i++)
{
int pd = (((i % minor[flag]) != 0) ? (((i % subminor) != 0) ? 1 : 2) : 3);
if (pd == gridPen)
{
SetPenDiameter(pd);
ptval = ((int)printerunits[flag]) * i / ns;
if (flag == Y)
ptval = printerunits[Y] - ptval;
MoveAbsolute(((flag == X) ? ptval : 0), ((flag == Y) ? ptval : 0));
if (i % minor[flag] == 0)
WriteValue(flag, minimum[flag] + i * delta[flag] / minor[flag], false, pg, vgOutput);
DrawGridLine((flag == 0) ? 1 : 0, ptval, pg, vgOutput);
}
}
}
private void DoLogGrid(int flag, VG.Page pg, IVGOutput vgOutput)
{
double showval;
int gs, ge, gd;
int i, ptval;
showval = minimum[flag];
for (i = 0; i < cycles[flag]; i++)
{
gs = gd = 100;
ge = 1000;
ptval = ((int)printerunits[flag]) * i / cycles[flag];
if (flag == Y)
ptval = printerunits[Y] - ptval; //jj
MoveAbsolute(((flag == X) ? ptval : 0), ((flag == Y) ? ptval : 0));
SetPenDiameter(3);
WriteValue(flag, showval, false, pg, vgOutput);
GenGrid(flag, gs, ge, gd, onecycle[flag], 2, i * onecycle[flag], pg, vgOutput);
showval *= 10.0;
}
ptval = ((int)printerunits[flag]) * i / cycles[flag];
if (flag == Y)
ptval = printerunits[Y] - ptval; //jj
MoveAbsolute(((flag == X) ? ptval : 0), ((flag == Y) ? ptval : 0));
SetPenDiameter(3);
WriteValue(flag, showval, false, pg, vgOutput);
}
private void WriteValue(int flag, double val, bool SubLogValue, VG.Page pg, IVGOutput vgOutput)
{
int size;
size = GenNumberString(val);
SavePosition();
if (flag == X)
{
MoveRelative(0, -printerunits[Y]);
if (!SubLogValue)
DrawGridRelative(0, (int)(-30 * ConvertToTwips), pg, vgOutput);
// OLD: MoveRelative((int)((-130 * size / (int)FontPitch) * ConvertToTwips), (int)(-60 * ConvertToTwips));
MoveRelative((int)((2 - 130 * size / (int)FontPitch) * ConvertToTwips), (int)(-62 * ConvertToTwips));
if ((AxisLabel[0]) != 0)
{
if (SubLogValue)
{
StringBuilder sb = new StringBuilder();
sb.Append(SuperScript[0]);
sb.Append(valuestring);
sb.Append(SuperScript[1]);
valuestring = sb.ToString();
MoveRelative(30, 30);
}
GraphText(valuestring, pg, vgOutput);
}
}
else
{
if (!SubLogValue)
DrawGridRelative((int)(-30 * ConvertToTwips), 0, pg, vgOutput);
// OLD: MoveRelative((int)(-(15 + 300 * size / (int)FontPitch) * ConvertToTwips), (int)(-15 * ConvertToTwips));
MoveRelative((int)(-(14 + 250 * size / (int)FontPitch) * ConvertToTwips), (int)(-16 * ConvertToTwips));
if ((AxisLabel[1]) != 0)
{
if (SubLogValue)
{
StringBuilder sb = new StringBuilder();
sb.Append(SuperScript[0]);
sb.Append(valuestring);
sb.Append(SuperScript[1]);
valuestring = sb.ToString();
MoveRelative(90, -90); //jj
}
GraphText(valuestring, pg, vgOutput);
}
}
RecallPosition();
}
private int GenNumberString(double x)
{
int power, size, sign;
double mantissa;
if (x == 0.0) return (savenumber(x));
if (x < 0.0)
{
x = -x;
sign = 1;
}
else
sign = 0;
mantissa = Math.Log10(x);
power = 0;
while (mantissa < 0.999)
{
power--;
mantissa++;
}
while (mantissa >= 0.999)
{
power++;
mantissa--;
}
if (mantissa < 0)
mantissa = 0;
if (power > -5 && power < 5)
size = savenumber(x);
else
{
size = savenumber(Math.Pow(10.0, mantissa));
size += addpower(power);
if (valuestring.StartsWith("1x"))
{
size -= 2;
valuestring = valuestring.Remove(0, 2);
}
}
if (sign != 0)
{
valuestring = "-" + valuestring;
size++;
}
return (size);
}
private int savenumber(double x)
{
valuestring = x.ToString("G");
return valuestring.Length;
}
private int addpower(int i)
{
int tlen;
powerstring = string.Format("x10{0}{1}{2}", SuperScript[0], i.ToString(), SuperScript[1]);
valuestring = valuestring + powerstring;
tlen = SuperScript[0].Length + SuperScript[1].Length;
return (powerstring.Length - tlen);
}
private void DoAxisTitles(VG.Page pg, IVGOutput vgOutput)
{
int len, frommargin;
string str;
SavePosition();
if ((AxisTitles[X] != null) && (len = AxisTitles[X].Length) > 0)
{
frommargin = (int)((0.5 * (printerunits[X])) - (0.47 * (len * CWIDEDOTS)));
// OLD: frommargin = (int)((0.5 * (printerunits[X])) - (0.5 * (len * CWIDEDOTS)));
MoveAbsolute(frommargin, (3 * CHIGHDOTS) + printerunits[Y]);
PrintText(AxisTitles[X], pg, vgOutput);
LinesUsed += (3 * CHIGHDOTS);
AxisTitles[X] = null;
}
if ((AxisTitles[Y] != null) && (len = AxisTitles[Y].Length) > 0)
{
if (YLandScape > 0)
{
int strIdx = 0;
MoveTo(YTitleOrigin);
str = AxisTitles[Y];
while (strIdx < str.Length)
{
PrintText(str[strIdx].ToString(), pg, vgOutput);
MoveRelative(0, -CHIGHDOTS);
strIdx++;
}
}
else
{
MoveAbsolute(-3 * CWIDEDOTS, -CHIGHDOTS);
PrintText(AxisTitles[Y], pg, vgOutput);
}
AxisTitles[Y] = null;
}
RecallPosition();
}
private void DoBoxes(VG.Page pg, IVGOutput vgOutput)
{
int dx, dy;
XyBox current;
string str;
SavePosition();
int BoxIdx = 0;
SetPenDiameter(5);
while (BoxIdx < AllBoxes.Count)
{
current = AllBoxes[BoxIdx];
MoveTo(current.BoxMinimum);
dx = current.BoxMaximum.xyValue[X] - current.BoxMinimum.xyValue[X];
dy = current.BoxMaximum.xyValue[Y] - current.BoxMinimum.xyValue[Y];
if (current.Shadow != 2) BoxRelative(dx, dy, CurPenWidth, pg, vgOutput);
if (current.Shadow == 1)
{
int savePenWidth = CurPenWidth;
SavePosition();
SetPenDiameter(10);
MoveRelative((int)(10 * ConvertToTwips), -(dy + (int)(5 * ConvertToTwips)));
DrawRelative(dx, 0, pg, vgOutput);
MoveRelative(-(int)(3 * ConvertToTwips), -(int)(5 * ConvertToTwips));
DrawRelative(0, dy, pg, vgOutput);
CurPenWidth = savePenWidth;
RecallPosition();
}
MoveRelative((CWIDEDOTS * (3 / 2)), -(CHIGHDOTS * (5 / 4)));
str = current.BoxText;
int stridx = 0;
while (stridx < str.Length)
{
string tstr = str;
int idx;
if ((idx = str.IndexOf("\n", stridx)) >= 0)
{
tstr = str.Substring(stridx, idx - stridx);
stridx = idx + 1;
}
else
stridx = str.Length + 1;
PrintText(tstr, pg, vgOutput);
MoveRelative(0, -CHIGHDOTS);
}
BoxIdx++;
}
RecallPosition();
}
private void DrawLines(VG.Page pg, IVGOutput vgOutput)
{
int PlotsIdx = 0;
DataPoint curpoint;
PlotLine current;
SavePosition();
SetPenDiameter(8);
/* begin plotting the graph lines, which may be straight or curved */
while (PlotsIdx < AllPlots.Count)
{
current = AllPlots[PlotsIdx];
int pntListIdx = 0;
LineDiv = current.PlotDivisions;
if (current.PlotType == STRAIGHT)
{ /* straight plot */
curpoint = current.PlotDataPoints[pntListIdx];
MoveTo(curpoint.APoint);
while (++pntListIdx < current.PlotDataPoints.Count)
{
curpoint = current.PlotDataPoints[pntListIdx];
DrawLineTo(curpoint.APoint, pg, vgOutput);
}
}
else
{
DrawCurve(current, pg, vgOutput); /* curved plot */
}
PlotsIdx++;
} /* repeat for each plot (while) */
RecallPosition();
}
private point FindCenterOfArc(point StartPoint, double Slope1, point EndPoint, double Slope2)
{
point center = new point();
double s1, s2;
int x1, y1, x2, y2;
center.xyValue = new int[Dimensions];
s1 = tan_deg(FixAngle(atan_deg(Slope1)));
s2 = tan_deg(FixAngle(atan_deg(Slope2)));
x1 = StartPoint.xyValue[X];
y1 = StartPoint.xyValue[Y];
x2 = EndPoint.xyValue[X];
y2 = EndPoint.xyValue[Y];
center.xyValue[X] = (int)(((s2 * s1) * (y2 - y1) + (s1 * x2) - (s2 * x1)) / (s1 - s2));
if (s1 == 0.0)
center.xyValue[Y] = (int)(y2 - ((center.xyValue[X] - x2) / s2));
else
center.xyValue[Y] = (int)(y1 - ((center.xyValue[X] - x1) / s1));
return (center);
}
private point FindModifiedCenter(double rprime, point PtOnArc, double ang)
{
point newcenter = new point();
newcenter.xyValue = new int[Dimensions];
newcenter.xyValue[X] = (int)(PtOnArc.xyValue[X] - rprime * cos_deg(ang));
newcenter.xyValue[Y] = (int)(PtOnArc.xyValue[Y] - rprime * sin_deg(ang));
return (newcenter);
}
private int AddMidPoint(DataPoints ptLstAry, int pt1Idx, int pt2Idx)
{
DataPoint midpt;
DataPoint pt1, pt2;
point pt;
double so;
int x1, y1, x2, y2;
pt1 = ptLstAry[pt1Idx];
pt2 = ptLstAry[pt2Idx];
x1 = pt1.APoint.xyValue[X];
y1 = pt1.APoint.xyValue[Y];
x2 = pt2.APoint.xyValue[X];
y2 = pt2.APoint.xyValue[Y];
midpt = new DataPoint();
pt = new point();
pt.xyValue = new int[Dimensions];
so = FindSlope(pt1.APoint, pt2.APoint);
midpt.slope = (4.0 * so - pt1.slope - pt2.slope) / 2.0;
pt.xyValue[X] = x1 + (x2 - x1) / 2;
pt.xyValue[Y] = y1 + (y2 - y1) / 2;
midpt.APoint = pt;
ptLstAry.Insert(pt1Idx + 1, midpt);
return (pt1Idx + 1);
}
private double FindTheta(point Endpoint, point Centerpoint)
{
double dy, dx, result;
dx = Endpoint.xyValue[X] - Centerpoint.xyValue[X];
dy = Endpoint.xyValue[Y] - Centerpoint.xyValue[Y];
result = 90.0 - atan_deg((dy / dx));
if (dx < 0) result += 180.0;
return (result);
}
private double FindRadius(point Endpoint, point Centerpoint)
{
double dy, dx, r;
dx = Centerpoint.xyValue[X] - Endpoint.xyValue[X];
dy = Centerpoint.xyValue[Y] - Endpoint.xyValue[Y];
r = Math.Sqrt(((dx * dx) + (dy * dy)));
return (r);
}
private void DrawCurve(PlotLine linestart, VG.Page pg, IVGOutput vgOutput)
{
int pltptListIdx = -1;
while (++pltptListIdx < linestart.PlotDataPoints.Count - 1)
{
DoSubArcs(linestart.PlotDataPoints, pltptListIdx, pg, vgOutput);
}
}
private double GetAngle(double s1)
{
double t1;
t1 = atan_deg(s1);
return (t1);
}
private double GetAngleBetweenPoints(point pt1, point pt2)
{
double retval;
retval = GetAngle(FindSlope(pt1, pt2));
if (pt2.xyValue[X] < pt1.xyValue[X])
{
if (retval < 0)
retval += 180;
else
retval -= 180;
}
return (retval);
}
private double SpecialGetAngleBetweenPoints(point pt1, point pt2, double s1)
{
double retval;
if (s1 == 0.0)
{
if (pt1.xyValue[Y] < pt2.xyValue[Y])
s1 = Convert.ToDouble("1.E99");
else
s1 = Convert.ToDouble("-1.E99");
}
else
s1 = -1 / s1;
retval = GetAngle(s1);
if (pt2.xyValue[X] < pt1.xyValue[X])
{
if (retval < 0)
retval += 180;
else
retval -= 180;
}
return (retval);
}
private double GetArcAngle(double s1, double s2)
{
double result, t1, t2;
t1 = GetAngle(s1);
t2 = GetAngle(s2);
result = t1 - t2;
return (result);
}
private void DoSubArcs(DataPoints dataPoints, int aryIdx, VG.Page pg, IVGOutput vgOutput)
{
bool debug = false; //jsj
int x, y, x1, x2, y1, y2;
DataPoint pt1 = dataPoints[aryIdx];
DataPoint pt2 = dataPoints[aryIdx + 1];
DebugOutput("pt1={0},{1},{2}", pt1.APoint.xyValue[0], pt1.APoint.xyValue[1], pt1.slope);
DebugOutput("pt2={0},{1},{2}", pt2.APoint.xyValue[0], pt2.APoint.xyValue[1], pt2.slope);
double theta, delta1, delta2, r1, r2, t1, t2, theta1, theta2, thetaa, t3, t4;
double c1, c2, s1, s2;
double t3a, t4a;
point cp1, cp2;
t3 = FixAngle(t3a=GetAngle(pt1.slope));
t4 = FixAngle(t4a=GetAngle(pt2.slope));
thetaa = GetAngleBetweenPoints(pt1.APoint, pt2.APoint);
if ((t3 - thetaa) * (t4 - thetaa) >= 0.0)
{
double tprime;
tprime = FixAngle(thetaa);
if (Math.Abs(tprime - t3) < ANGLELIMIT)
{
MoveTo(pt1.APoint);
DrawTo(pt2.APoint, pg, vgOutput);
return;
}
else
{
pt2 = dataPoints[AddMidPoint(dataPoints, aryIdx, aryIdx + 1)];
t4 = FixAngle(GetAngle(pt2.slope));
thetaa = GetAngleBetweenPoints(pt1.APoint, pt2.APoint);
}
}
if (thetaa < t3)
t1 = t3 + 90;
else
t1 = t3 - 90;
if (thetaa > t4)
t2 = t4 + 90;
else
t2 = t4 - 90;
theta = t2 - t1;
theta1 = FixAngle(thetaa - t3);
theta2 = theta - theta1;
if (Math.Abs(theta1) < Math.Abs(theta2))
{
if (Math.Abs(theta1) < ANGLELIMIT)
{
theta1 = 0;
theta2 = theta;
}
}
else if (Math.Abs(theta2) < Math.Abs(theta1))
{
if (Math.Abs(theta2) < ANGLELIMIT)
{
theta2 = 0;
theta1 = theta;
}
}
x1 = pt1.APoint.xyValue[X];
y1 = pt1.APoint.xyValue[Y];
x2 = pt2.APoint.xyValue[X];
y2 = pt2.APoint.xyValue[Y];
s1 = sin_deg(t1 + 180);
s2 = sin_deg(t2 + 180);
c1 = cos_deg(t1 + 180);
c2 = cos_deg(t2 + 180);
if (s1 == 0.0)
{
r2 = (x1 - x2) / s2;
r1 = (y2 + r2 * c2 - y1) / c1;
}
else if (s2 == 0.0)
{
r1 = (x2 - x1) / s1;
r2 = (y1 + r1 * c1 - y2) / c2;
}
else if (c1 == 0.0)
{
r2 = (y1 - y2) / c2;
r1 = (x2 + r2 * s2 - x1) / s1;
}
else if (c2 == 0.0)
{
r1 = (y2 - y1) / c1;
r2 = (x1 + r1 * s1 - x2) / s2;
}
else
{
r2 = (((x2 - x1) / c1) - ((y2 - y1) / s1)) / (s2 / s1 - c2 / c1);
r1 = (y2 - y1 + r2 * s2) / s1;
}
MoveTo(pt1.APoint);
if (debug) //jsj
{
DrawTo(pt2.APoint, pg, vgOutput);
return;
}
if (Math.Abs(theta1) > ANGLELIMIT && Math.Abs(theta2) > ANGLELIMIT)
{
delta1 = (r2 - r1) / (
(1.0 - cos_deg(theta1)) +
(1.0 - cos_deg(theta2)) * sin_deg(theta1) / sin_deg(theta2));
r1 = Math.Floor(0.5 + r1 + delta1);
cp1 = FindModifiedCenter(r1, pt1.APoint, t1);
x = (int)(cp1.xyValue[X] + r1 * cos_deg(t1 + theta1));
y = (int)(cp1.xyValue[Y] + r1 * sin_deg(t1 + theta1));
delta2 = delta1 * sin_deg(theta1) / sin_deg(theta2);
r2 = Math.Floor(0.5 + r2 - delta2);
cp2 = FindModifiedCenter(r2, pt2.APoint, t2);
//#if DEBUG
//DebugOutput("DrawArc1"); VG_Arc.iColor = 1;
//#endif
DrawArc(r1, t1, t1 + theta1, cp1, x, y, pg, vgOutput);
DebugShowLocation("DrawArc1");
MoveTo(pt2.APoint);
DebugShowLocation("MoveTo1");
if (r2 > 15000)
{
DebugOutput("DrawAbs1 {0},{1}", x, y);
DrawAbsolute(x, y, pg, vgOutput);
DebugShowLocation("DrawAbs1");
}
else
{
//#if DEBUG
//DebugOutput("DrawArc2"); VG_Arc.iColor = 2;
//#endif
DrawArc(r2, t2, t2 - theta2, cp2, x, y, pg, vgOutput);
DebugShowLocation("DrawArc2");
}
}
else if (Math.Abs(theta1) > ANGLELIMIT)
{
delta1 = (r2 - r1) / (1.0 - cos_deg(theta1));
r1 = Math.Floor(0.5 + r1 + delta1);
if (r1 < 0) r1 = -r1;
cp1 = FindModifiedCenter(r1, pt1.APoint, t1);
x = (int)(cp1.xyValue[X] + r1 * cos_deg(t1 + theta1));
y = (int)(cp1.xyValue[Y] + r1 * sin_deg(t1 + theta1));
if (r1 > 15000)
{
DebugOutput("DrawAbs2");
DrawAbsolute(x, y, pg, vgOutput);
DebugShowLocation("DrawAbs2");
}
else
{
//Console.WriteLine("{0},{1},{2},{3},{4},{5},{6},{7},{8},{9}", t3, t3a, t4, t4a, thetaa, t1, t2, r1, r2, aryIdx);
//#if DEBUG
//DebugOutput("DrawArc3"); VG_Arc.iColor = 3;
//VG_Arc.iColor = 4;
//#endif
DrawArc(r1, t1, t1 + theta1, cp1, x, y, pg, vgOutput);
//Console.WriteLine("'DrawArc3','{0}',{1},{2}", Key, r1, theta1);
DebugShowLocation("DrawArc3");
}
MoveAbsolute(x, y);
DebugShowLocation("MoveAbs2");
DebugOutput("DrawTo1");
DrawTo(pt2.APoint, pg, vgOutput);
DebugShowLocation("DrawTo1");
//DebugOutput("DrawArc4"); VG_Arc.iColor = 4;
//DrawArc(r1, t1, t1 + theta1, cp1, x, y, pg, vgOutput);
//DebugShowLocation("DrawArc4");
}
else if (Math.Abs(theta2) > ANGLELIMIT)
{
delta2 = (r2 - r1) / (1.0 - cos_deg(theta2));
r2 = Math.Floor(0.5 + r2 - delta2);
if (r2 < 0) r2 = -r2;
cp2 = FindModifiedCenter(r2, pt2.APoint, t2);
x = (int)(cp2.xyValue[X] + r2 * cos_deg(t2 - theta2));
y = (int)(cp2.xyValue[Y] + r2 * sin_deg(t2 - theta2));
DebugOutput("DrawAbs3");
DrawAbsolute(x, y, pg, vgOutput);
DebugShowLocation("DrawAbs3");
MoveTo(pt2.APoint);
DebugShowLocation("MoveTo1");
if (r2 > 15000)
{
DebugOutput("DrawAbs4");
DrawAbsolute(x, y, pg, vgOutput);
DebugShowLocation("DrawAbs4");
}
else
{
//#if DEBUG
//DebugOutput("DrawArc5"); VG_Arc.iColor = 5;
//VG_Arc.iColor = 6;
//#endif
DrawArc(r2, t2, t2 - theta2, cp2, x, y, pg, vgOutput);
DebugShowLocation("DrawArc5");
}
//DebugOutput(""); VG_Arc.iColor = 6;
//DrawArc(r2, t2, t2 - theta2, cp2, x, y, pg, vgOutput);
//DebugShowLocation("DrawArc6");
}
else
{
DebugOutput("DrawTo2");
DrawTo(pt2.APoint, pg, vgOutput);
DebugShowLocation("DrawTo2");
pt2.slope = FindSlope(pt1.APoint, pt2.APoint);
}
return;
}
private void SetPenDiameter(int pd)
{
if ((pd * ConvertToTwips) != CurPenWidth)
{
CurPenWidth = (int)(pd * ConvertToTwips);
}
}
private void PrintStackError(string relation, int limit)
{
MessageBox.Show(String.Format("Position Stack Pointer {0} {1}", relation, limit.ToString()), "Print Stack Error");
}
private void SavePosition()
{
if (stack >= MAX_XY_STACK) PrintStackError(">=", MAX_XY_STACK);
SavedX[stack] = Position[X];
SavedY[stack++] = Position[Y];
}
private void RecallPosition()
{
if (stack <= 0) PrintStackError(" <", 0);
Position[X] = SavedX[--stack];
Position[Y] = SavedY[stack];
}
private void MoveTo(point pnt)
{
MoveAbsolute(pnt.xyValue[X], pnt.xyValue[Y]);
}
private void DrawTo(point pnt, VG.Page pg, IVGOutput vgOutput)
{
DrawAbsolute(pnt.xyValue[X], pnt.xyValue[Y], pg, vgOutput);
}
private void MoveAbsolute(int ptx, int pty)
{
int x, y;
x = ptx - Position[X];
y = Position[Y] - pty;
MoveRelative(x, y);
}
private void DrawAbsolute(int ptx, int pty, VG.Page pg, IVGOutput vgOutput)
{
int x, y;
x = ptx - Position[X];
y = Position[Y] - pty;
DrawRelative(x, y, pg, vgOutput);
}
private void DrawGridAbsolute(int ptx, int pty, VG.Page pg, IVGOutput vgOutput)
{
int x, y;
x = ptx - Position[X];
y = Position[Y] - pty;
DrawGridRelative(x, y, pg, vgOutput);
}
private void relval(string ptr, int i)
{
ptr = string.Format("+{0}", i.ToString());
}
private void MoveRelative(int x, int y)
{
Position[X] += x;
Position[Y] -= y;
}
private void DrawRelative(int x, int y, VG.Page pg, IVGOutput vgOutput)
{
if (Visible == 0)
MoveRelative(x, y);
else
{
int toX, toY;
toX = Position[X] + x;
toY = Position[Y] - y;
VG_Line RelLine = new VG_Line(Position[X], Position[Y], toX, toY, CurPenWidth, pg);
Position[X] += x;
Position[Y] -= y;
RelLine.Draw(vgOutput);
}
}
private void DrawGridRelative(int x, int y, VG.Page pg, IVGOutput vgOutput)
{
if (Visible == 0)
MoveRelative(x, y);
else
{
DrawRelative(x, y, pg, vgOutput);
}
}
private void DrawArc(double radius, double Sangle, double Eangle, point cp, int x, int y, VG.Page pg, IVGOutput vgOutput)
{
DebugOutput("r={0} sAngle={1} eAngle={2} cp={3},{4} x={5} y={6}", radius, Sangle, Eangle, cp.xyValue[0], cp.xyValue[1], x, y);
int dx, dy;
long radchk;
radchk = (long)radius;
if (radchk > 72000L)
{
DrawAbsolute(x, y, pg, vgOutput);
return;
}
dx = x - cp.xyValue[X]; //jj
dy = Math.Abs(cp.xyValue[Y] - Position[Y]); //jj
float x1 = cp.xyValue[X] - (float)radius;
float y1 = cp.xyValue[Y] - (float)radius;
float w1 = (float)radius * 2;
VG_Arc arc = new VG_Arc(x1, y1, w1, w1, (float)Sangle, (float)(Eangle - Sangle), CurPenWidth, pg);
DebugOutput("arc {0},{1},{2},{3},{4},{5}", x1, y1, w1, w1, (float)Sangle, (float)(Eangle - Sangle));
arc.Draw(vgOutput);
}
private void DrawGridLine(int flag, int val, VG.Page pg, IVGOutput vgOutput)
{
XyBox curbox;
int v1, v2;
int BoxesIdx = 0;
FindBoxesinArea(val, (flag == 0) ? 1 : 0);
v1 = Position[flag];
if (ActiveBoxes.Count > 0)
{
curbox = ActiveBoxes[BoxesIdx];
while (BoxesIdx < ActiveBoxes.Count)
{
int my_x, my_y;
v2 = curbox.BoxMinimum.xyValue[flag];
my_x = (flag == X) ? ((v2 < printerunits[flag]) ? v2 : printerunits[flag])
: val;
my_y = (flag == Y) ?
((v2 < printerunits[flag]) ? v2 : printerunits[flag])
: val;
DrawGridAbsolute(my_x, my_y, pg, vgOutput);
v1 = curbox.BoxMaximum.xyValue[flag];
while ((BoxesIdx < ActiveBoxes.Count) && (curbox.BoxMinimum.xyValue[flag] < v1))
{
v1 = (curbox.BoxMaximum.xyValue[flag]);
BoxesIdx++;
if (BoxesIdx < ActiveBoxes.Count)
curbox = ActiveBoxes[BoxesIdx];
}
MoveAbsolute((flag == X ? v1 : val), (flag == Y ? v1 : val));
}
}
v2 = printerunits[flag];
if (v1 < v2) DrawGridAbsolute((flag == X ? v2 : val), (flag == Y ? v2 : val), pg, vgOutput);
ActiveBoxes.Clear();
}
private void LogScale(int flag)
{
double newminimum, newmaximum, maxlimit = maximum[flag] * .9;
newminimum = 1.0;
while (newminimum < minimum[flag]) newminimum *= 10.0;
while (newminimum > minimum[flag]) newminimum /= 10.0;
newmaximum = 10.0 * newminimum;
cycles[flag] = 1;
while (newmaximum < maxlimit)
{
newmaximum *= 10.0;
cycles[flag]++;
}
onecycle[flag] = printerunits[flag] / cycles[flag];
minimum[flag] = newminimum;
maximum[flag] = newmaximum;
}
private void LinearScale(int flag)
{
double mantissa, nx;
double newminimum, newmaximum;
int power = 0;
if (spcminor[flag] == 0)
minor[flag] = 10;
else
minor[flag] = spcminor[flag];
if (delta[flag] == 0)
{
delta[flag] = maximum[flag] - minimum[flag];
mantissa = Math.Log10(delta[flag]);
while (mantissa < 1.2)
{
mantissa++;
power--;
}
while (mantissa > 1.2)
{
mantissa--;
power++;
}
if (mantissa < 0) mantissa = 0;
nx = Math.Pow(10.0, mantissa);
if (nx > 5.0)
{
delta[flag] = 1.0;
}
else if (nx > 3.001)
{ // allow for roundoff
delta[flag] = 0.5;
}
else if (nx > 2.001)
{ // allow for roundoff
delta[flag] = 0.25;
}
else
{
delta[flag] = 0.2;
if (spcminor[flag] == 0) minor[flag] = 8;
}
while (power > 0)
{
power--;
delta[flag] *= 10.0;
}
while (power < 0)
{
power++;
delta[flag] /= 10.0;
}
}
if (GridOnFlag == 0 || GridOnFlag == 1)
minor[flag] = 1;
else if (GridOnFlag == 2)
minor[flag] /= 2;
newminimum = ((int)(0.01 + minimum[flag] / delta[flag])) * delta[flag];
if (newminimum > minimum[flag] + (delta[flag] * 0.001))
newminimum -= delta[flag];
newmaximum = ((int)(maximum[flag] / delta[flag])) * delta[flag];
if (newmaximum < maximum[flag] - (delta[flag] * 0.001))
newmaximum += delta[flag];
minimum[flag] = newminimum;
maximum[flag] = newmaximum;
}
private void err_exit(string msg, string msg2)
{
MessageBox.Show(msg + "\n" + msg2 + "\n\n This p=Process Will Terminate", "\n## ERROR ## - ");
Environment.Exit(255);
}
private void FindBoxesinArea(int ptval, int flag)
{
XyBox cptr;
int BoxesIdx = 0;
while (BoxesIdx < AllBoxes.Count)
{
cptr = AllBoxes[BoxesIdx];
if (cptr.BoxMinimum.xyValue[flag] <= ptval &&
cptr.BoxMaximum.xyValue[flag] >= ptval)
if(cptr.BoxMinimum.xyValue[1-flag] > 0 &&
cptr.BoxMaximum.xyValue[1 - flag] < printerunits[1-flag])// Don't include box if it is outside of the range of the grid.
AddBoxToActiveList(cptr);
BoxesIdx++;
}
}
private void AddBoxToActiveList(XyBox box)
{
int i = 0;
while (i < ActiveBoxes.Count)
{
if (box.BoxMinimum.xyValue[DrawDirection] < ActiveBoxes[i].BoxMinimum.xyValue[DrawDirection])
break; // Located the location to insert the box
i++;
}
ActiveBoxes.Insert(i, box);
}
private void GenGrid(int flag, int ss, int ee, int dd, int w, int lw, int goffset, VG.Page pg, IVGOutput vgOutput)
{
int val, wn, valn;
double p2;
int n, dn, MinorGrid = 0;
if ((GridOnFlag * lw) <= 1) return;
if (ee / ss == 10) MinorGrid = 2;
n = ss;
p2 = n;
w = (int)(w / Math.Log10(ee / p2)); //jj
val = (int)(Math.Log10(p2 / ss) * w + goffset);
MoveAbsolute((flag == X ? val : 0), (flag == Y ? val : 0));
DrawGridLine((flag == 0) ? 1 : 0, val, pg, vgOutput);
if ((GridOnFlag * lw) == 2) return;
SetPenDiameter(lw);
while (n < ee)
{
n += dd;
p2 = n;
valn = (int)(Math.Log10(p2 / ss) * w + goffset);
wn = valn - val;
if (wn > DPI / 20 && lw > 1)
{
if (wn > DPI * 2 / 5) dn = dd / 10;
else if (wn > DPI / 5) dn = dd / 5;
else dn = dd / 2;
GenGrid(flag, n - dd, n, dn, wn, lw - 1, val, pg, vgOutput);
wn = 0;
}
val = valn;
if (flag == Y)
val = printerunits[Y] - val; //jj
MoveAbsolute((flag == X ? val : 0), (flag == Y ? val : 0));
if ((MinorGrid != 0) && (MinorGrid < 10))
{
WriteValue(flag, MinorGrid++, true, pg, vgOutput); //these numbers are in dots
}
DrawGridLine((flag == 0) ? 1 : 0, val, pg, vgOutput);
}
}
private void PrintText(string txt, VG.Page pg, IVGOutput vgOutput)
{
StringBuilder tstr = new StringBuilder(txt);
int ptr;
SavePosition(); /* 'cause TEXT...,E screws up position! */
ptr = 0;
while (ptr < tstr.Length)
{
if ("`<60><><EFBFBD>".IndexOf(tstr[ptr]) >= 0)
{
string SpecialChar = "";
switch ((byte)tstr[ptr])
{
case 0x60: /* backquote */
case 0xF8: SpecialChar = "\u00B0"; /* degree symbol */
break;
case 0xF2: SpecialChar = "\u2265"; /* greaterthanequal */
break;
case 0xF3: SpecialChar = "\u2264"; /* lessthanequal */
break;
}
tstr.Remove(ptr, 1);
tstr.Insert(ptr, SpecialChar);
ptr++;
}
else
{
ptr++;
}
}
GraphText(tstr.ToString(), pg, vgOutput);
RecallPosition();
}
private void FreeBoxList()
{
AllBoxes.Clear();
}
private void FreeLineList()
{
AllPlots.Clear();
}
private void Init_Graphic_Vars()
{
int i;
SavedX = new int[MAX_XY_STACK];
SavedY = new int[MAX_XY_STACK];
LinesUsed = 0; /* Number lines used by graph, in dots */
Visible = 1;
ShadowFlag = 0;
CurPenWidth = 0;
DrawDirection = -1;
AxisTitles[X] = null;
AxisTitles[Y] = null;
AxisLabel[0] = 1;
AxisLabel[1] = 1;
EndFlag = 0;
for (i = 0; i < Dimensions; i++)
{
Scale[0, i] = 0;
Scale[1, i] = 0;
Offset[0, i] = 0;
Offset[1, i] = 0;
delta[i] = 0;
cycles[i] = 0;
onecycle[i] = 0;
minor[i] = 0;
}
}
private void DrawLineTo(point pnt, VG.Page pg, IVGOutput vgOutput)
{
int x1, y1, x2, y2;
int nd, x, y, i;
long ddx, ddy, dx, dy;
x1 = Position[X];
y1 = Position[Y];
x2 = pnt.xyValue[X];
y2 = pnt.xyValue[Y];
if (LineDiv != 0)
{
nd = LineDiv * 4;
dx = x2 - x1;
dy = y2 - y1;
for (i = 1; i <= nd; i++)
{
ddx = dx * i;
ddy = dy * i;
x = (int)(x1 + ddx / nd);
y = (int)(y1 + ddy / nd);
if ((i & 2) != 0)
MoveAbsolute(x, y);
else
DrawAbsolute(x, y, pg, vgOutput);
}
}
else
DrawTo(pnt, pg, vgOutput);
}
private void BoxRelative(int dx, int dy, int LineWidth, VG.Page pg, IVGOutput vgOutput)
{
VG_Rect vgrec = new VG_Rect((int)Position[X], (int)Position[Y], dx, dy, LineWidth, pg);
vgrec.Draw(vgOutput);
}
private void GraphText(string txt, VG.Page pg, IVGOutput vgOutput)
{
// Look for a Superscript or Subsript.
// - break up the string (if needed) and change the font pitch
// for the text that is to be super/subscripted
VG_Text drawText;
string tstr = "";
int Xpos, Ypos;
int sidx = 0; // beginning of string
int idx = 0; // current position in string
Xpos = Position[X];
Ypos = Position[Y];
while (idx < txt.Length)
{
int tidx;
if ((tidx = txt.IndexOf(SuperScript[0], idx)) > -1)
{
// print text up to the superscript
tstr = txt.Substring(sidx, tidx - sidx);
drawText = new VG_Text(Xpos, Ypos, (int)FontPitch, tstr, MyFontFamily, "", "", "", pg);
drawText.Draw(vgOutput);
Xpos += (CWIDEDOTS * tstr.Length);
tidx += SuperScript[0].Length;
idx = tidx;
sidx = idx;
tidx = txt.IndexOf(SuperScript[1], idx);
if (tidx > 0)
{
// switch font pitch, move up some, and print the superscript text
tstr = txt.Substring(sidx, tidx - sidx);
Ypos -= (CHIGHDOTS / 2); // move up half a char heigth
drawText = new VG_Text(Xpos, Ypos, (int)(FontPitch / 2), tstr, MyFontFamily, "", "", "", pg);
drawText.Draw(vgOutput);
Ypos += (CHIGHDOTS / 2); // move back down
Xpos += ((CWIDEDOTS / 2) * tstr.Length); // positon half the width of the string
tidx += SuperScript[1].Length;
idx = tidx;
sidx = idx;
continue; // go back to beginning of while loop
}
}
else if ((tidx = txt.IndexOf(SubScript[0], idx)) > -1)
{
// print text up to the superscript
tstr = txt.Substring(sidx, tidx - sidx);
drawText = new VG_Text(Xpos, Ypos, (int)FontPitch, tstr, MyFontFamily, "", "", "", pg);
drawText.Draw(vgOutput);
Xpos += (CWIDEDOTS * tstr.Length);
tidx += SubScript[0].Length;
idx = tidx;
sidx = idx;
tidx = txt.IndexOf(SubScript[1], idx);
if (tidx > 0)
{
// switch font pitch, move up some, and print the superscript text
tstr = txt.Substring(sidx, tidx - sidx);
drawText = new VG_Text(Xpos, Ypos, (int)(FontPitch / 2), tstr, MyFontFamily, "", "", "", pg);
drawText.Draw(vgOutput);
Xpos += ((CWIDEDOTS / 2) * tstr.Length); // positon half the width of the string
tidx += SubScript[1].Length;
idx = tidx;
sidx = idx;
continue; // go back to beginning of while loop
}
}
else
{
idx++;
}
} // end while
if (sidx < txt.Length)
{
tstr = txt.Substring(sidx);
drawText = new VG_Text(Xpos, Ypos, (int)FontPitch, tstr, MyFontFamily, "", "", "", pg);
drawText.Draw(vgOutput);
}
}
/// <summary>
/// Generates a vgOutput files containing an X/Y PLot generated from the passed in
/// commands.
/// </summary>
/// <param name="PlotCommands">Plot Commands</param>
public XYPlot(string PlotCommands)
{
LoadBuffFromString(PlotCommands);
Setup();
//#if DEBUG
//VG.VG_Arc.iColor = 0;
//#endif
}
public void Setup()
{
char Command, PrevCommand = ' ';
Init_Graphic_Vars();
FixBuffIfNeeded();
GetScaleInfo();
while ((Command = char.ToUpper(getchr())) != '\0')
{
LineDiv = 0;
LineFlag = CURVE;
ShadowFlag = 0;
switch (Command)
{
case 'T':
ShadowFlag += 2; // 2 for no box
GetBoxParameters();
break;
case 'W':
ShadowFlag++; // 1 for shadow box
GetBoxParameters();
break;
case 'B':
GetBoxParameters(); // 0 for box
break;
case 'D':
LineDiv = getint();
LineFlag = STRAIGHT;
GetLineParameters();
break;
case 'L':
LineFlag = STRAIGHT;
GetLineParameters();
break;
case 'C':
GetLineParameters();
break;
case 'X':
GetAxisTitle(X);
break;
case 'Y':
GetAxisTitle(Y);
break;
case 'Z':
YLandScape = 1;
YTitleOrigin = GetPair(USER);
GetAxisTitle(Y);
break;
case 'A':
AxisLabel[0] = getint();
AxisLabel[1] = getint();
break;
default:
if (PrevCommand.Equals(null))
MessageBox.Show("Check the first line of the X/Y Plot definition.", "Unrecognized Graph Command");
else
MessageBox.Show(string.Format("Problem with the X/Y Plot Command after {0}", PrevCommand.ToString()), "Unrecognized Graph Command");
break;
}
PrevCommand = Command;
}
}
public void Process(IVGOutput vgOutput)
{
VG.Page pg = new Page(true, _LeftMargin, _TopMargin, _RightMargin, _BottomMargin);
GenerateGrid(pg, vgOutput);
DoAxisTitles(pg, vgOutput);
DrawLines(pg, vgOutput);
DoBoxes(pg, vgOutput);
FreeBoxList();
FreeLineList();
CloseGraph();
}
private void ShowPoints(DataPoints dataPoints)
{
//#if DEBUG
//foreach (DataPoint pl in dataPoints)
//{
// DebugOutput("x={0},y={1},slope={2}", pl.APoint.xyValue[0], pl.APoint.xyValue[1], pl.slope);
//}
//#endif
}
public static string Key = "";
private void DebugOutput(string format, params object[] args)
{
//#if DEBUG
//if (args.Length == 0)
// Console.WriteLine("'{0}','{1}'",Key,format);
//Console.WriteLine(format, args);
//#endif
}
private void DebugShowLocation(string command)
{
//Console.WriteLine("'{0}',{1},{2}", command, Position[X], Position[Y]);
}
}
}