2046 lines
58 KiB
C#
2046 lines
58 KiB
C#
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
|
|
{
|
|
#region Log4Net
|
|
// C2018-035 Added error Handling to provide more useful information when a plot fails
|
|
private static readonly log4net.ILog _MyLog = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
|
|
#endregion
|
|
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
|
|
{
|
|
public override string ToString() // Make it easier to Debug
|
|
{
|
|
return string.Format("{0},{1}", APoint.xyValue[X],APoint.xyValue[Y]);
|
|
}
|
|
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];
|
|
}
|
|
// C2018-035 Added error Handling to provide more useful information when a plot fails
|
|
private string _XYPlotIssue;
|
|
public string XYPlotIssue
|
|
{
|
|
get { return _XYPlotIssue; }
|
|
set { _XYPlotIssue = value; }
|
|
}
|
|
private point GetPair(int flag)
|
|
{
|
|
point retval = new point();
|
|
retval.xyValue = new int[Dimensions];
|
|
double x, y;
|
|
char[] sepchar = { ',' };
|
|
string nextPiece = NextPiece(); // Plot Definition
|
|
string[] xystr = nextPiece.Split(sepchar);
|
|
// C2018-035 Added error Handling to provide more useful information when a plot fails
|
|
if (xystr.Length != 2)
|
|
XYPlotIssue = String.Format("Invalid Pair {0}", nextPiece);
|
|
if (xystr.Length == 1)
|
|
throw new Exception(XYPlotIssue);
|
|
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 != '"' && retval != '\x1C') // open double quote
|
|
MessageBox.Show("Double Quote not found", "Syntax problem in XY Plot");
|
|
retval = NextChar();
|
|
while (retval != 0 && retval != '\n')
|
|
{
|
|
switch (retval)
|
|
{
|
|
case '"':
|
|
case '\x1D': // close double quote
|
|
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 = Buff.Replace(">\n ", ">\r\n "); // C2022-003 if RO has symbols
|
|
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(">\n<", ">\r\n<"); // C2022-003 if RO has symbols
|
|
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
|
|
Buff = Regex.Replace(Buff, @"\\u([0-9]{1,4})\?", m => int.TryParse(m?.Groups[1]?.Value, out int result) ? Convert.ToChar(result).ToString() : "");
|
|
Buff = Regex.Replace(Buff, @"([0-9])\r\n([0-9])", "$1 $2");
|
|
}
|
|
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)
|
|
{
|
|
CheckDataPoints(linestart);
|
|
int pltptListIdx = -1;
|
|
while (++pltptListIdx < linestart.PlotDataPoints.Count - 1)
|
|
{
|
|
DoSubArcs(linestart.PlotDataPoints, pltptListIdx, pg, vgOutput);
|
|
}
|
|
}
|
|
|
|
private void CheckDataPoints(PlotLine linestart)
|
|
{
|
|
for(int i = 0;i<linestart.PlotDataPoints.Count-1;i++)
|
|
{
|
|
DataPoint dp0 = linestart.PlotDataPoints[i];
|
|
DataPoint dp1 = linestart.PlotDataPoints[i+1];
|
|
double x0 = dp0.APoint.xyValue[X];
|
|
double x1 = dp1.APoint.xyValue[X];
|
|
if (x0 > x1)
|
|
{
|
|
XYPlotIssue = "X Values should be Increasing";
|
|
throw new Exception("Curve has Invalid Values");
|
|
}
|
|
}
|
|
}
|
|
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
|
|
if (r2 != 0) 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];
|
|
// B2017-008 Support a reverse Axis which goes from a larger value to a smaller value.
|
|
if (newmaximum < newminimum) delta[flag] = -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 ("`���".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)
|
|
{
|
|
// MSWord enters left and right double-quotes when you press the double-quote key
|
|
//B2017 - Replace left and right double-quotes with normal double-quotes
|
|
PlotCommands = PlotCommands.Replace('\u201C', '"').Replace('\u201D', '"');
|
|
LoadBuffFromString(PlotCommands);
|
|
Setup();
|
|
//#if DEBUG
|
|
//VG.VG_Arc.iColor = 0;
|
|
//#endif
|
|
}
|
|
private int _OffsetX = 0;
|
|
public int OffsetX
|
|
{
|
|
get { return _OffsetX; }
|
|
set { _OffsetX = value; }
|
|
}
|
|
private int _OffsetY = 0;
|
|
public int OffsetY
|
|
{
|
|
get { return _OffsetY; }
|
|
set { _OffsetY = value; }
|
|
}
|
|
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 'O':
|
|
OffsetX = getint();
|
|
OffsetY = getint();
|
|
break;
|
|
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);
|
|
string step = "Process";
|
|
try // C2018-035 Added error Handling to Process to provide more useful information when a plot fails
|
|
{
|
|
step = "GenerateGrid";GenerateGrid(pg, vgOutput);
|
|
step = "DoAxisTitles";DoAxisTitles(pg, vgOutput);
|
|
step = "DrawLines";DrawLines(pg, vgOutput);
|
|
step = "DoBoxes";DoBoxes(pg, vgOutput);
|
|
step = "FreeBoxList";FreeBoxList();
|
|
step = "FreeLineList";FreeLineList();
|
|
step = "CloseGraph";CloseGraph();
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
_MyLog.WarnFormat("X/Y Plot Error - {0} - {1} - {2}", step, XYPlotIssue ?? "Unknown Issue");
|
|
throw new Exception(String.Format("X/Y Plot Error - {0} - {1}",step,XYPlotIssue ?? "Unknown Issue"));
|
|
}
|
|
}
|
|
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]);
|
|
}
|
|
}
|
|
} |