Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

This revision is NPlot-Gtk 0.9.9.2 and is the Gtk wrapper of NPlot 0.…

…9.9.2.

svn path=/trunk/nplot-gtk/; revision=65798
  • Loading branch information...
commit c209bfbce5fcce8cc45ab3689706c02cc4c332d0 0 parents
Carlos Ble authored
Showing with 29,556 additions and 0 deletions.
  1. +4 −0 ChangeLog
  2. +9 −0 Makefile
  3. BIN  NPlot.dll
  4. +18 −0 README
  5. BIN  lib/.Gtk.PlotSurface2D.cs.swp
  6. +767 −0 lib/AdapterUtils.cs
  7. +455 −0 lib/ArrowItem.cs
  8. +68 −0 lib/AssemblyInfo.cs
  9. +519 −0 lib/AxesConstraint.cs
  10. +1,654 −0 lib/Axis.cs
  11. +298 −0 lib/BarPlot.cs
  12. +138 −0 lib/BasePlot.cs
  13. +96 −0 lib/BasePlot3D.cs
  14. +69 −0 lib/BaseSequenceLinePlot.cs
  15. +118 −0 lib/BaseSequencePlot.cs
  16. +541 −0 lib/Bitmap.PlotSurface2D.cs
  17. +72 −0 lib/BubblePlot.cs
  18. +891 −0 lib/CandlePlot.cs
  19. +702 −0 lib/DateTimeAxis.cs
  20. +179 −0 lib/ErrorHandler.cs
  21. +203 −0 lib/FilledRegion.cs
  22. +46 −0 lib/FontScaler.cs
  23. +248 −0 lib/Grid.cs
  24. +303 −0 lib/Gtk.PlotSurface2D.cs
  25. +521 −0 lib/HistogramPlot.cs
  26. +287 −0 lib/HorizontalLine.cs
  27. +72 −0 lib/IDrawable.cs
  28. +27 −0 lib/IDrawable3D.cs
  29. +73 −0 lib/IGradient.cs
  30. +49 −0 lib/IMeshPlot.cs
  31. +104 −0 lib/IPlot.cs
  32. +33 −0 lib/IPlot3D.cs
  33. +255 −0 lib/IPlotSurface2D.cs
  34. +19 −0 lib/IPlotSurface2Dnew.cs
  35. +17 −0 lib/IPlotSurface3D.cs
  36. +85 −0 lib/ISequencePlot.cs
  37. +98 −0 lib/ISurface.cs
  38. +78 −0 lib/ITransform2D.cs
  39. +369 −0 lib/ImagePlot.cs
  40. +356 −0 lib/LabelAxis.cs
  41. +324 −0 lib/LabelPointPlot.cs
  42. +352 −0 lib/Legend.cs
  43. +459 −0 lib/LegendBase.cs
  44. +355 −0 lib/LinePlot.cs
  45. +650 −0 lib/LinearAxis.cs
  46. +159 −0 lib/LinearGradient.cs
  47. +678 −0 lib/LogAxis.cs
  48. +1,278 −0 lib/MainForm.cs
  49. +99 −0 lib/Makefile
  50. +487 −0 lib/Marker.cs
  51. +136 −0 lib/MarkerItem.cs
  52. BIN  lib/NPlot.Gtk.dll
  53. +6 −0 lib/NPlot.Gtk.dll.config
  54. BIN  lib/NPlot.Gtk.dll.mdb
  55. +393 −0 lib/NPlot.csproj
  56. +48 −0 lib/NPlot.csproj.user
  57. BIN  lib/NPlot.dll
  58. BIN  lib/NPlot.dll.mdb
  59. +297 −0 lib/NPlot.ndoc
  60. +30 −0 lib/NPlot.sln
  61. +90 −0 lib/NPlotException.cs
  62. +151 −0 lib/PageAlignedPhysicalAxis.cs
  63. +276 −0 lib/PhysicalAxis.cs
  64. +230 −0 lib/PiAxis.cs
  65. +120 −0 lib/PiePlot.cs
  66. +1,334 −0 lib/PlotSurface2D.cs
  67. +439 −0 lib/PlotSurface2Dnew.cs
  68. +64 −0 lib/PlotSurface3D.cs
  69. +26 −0 lib/PlotSurfaceDefinitions/CrossedAxes.xml
  70. +21 −0 lib/PlotSurfaceDefinitions/OppositeCloned.xml
  71. +14 −0 lib/PlotSurfaceDefinitions/Standard.xml
  72. +91 −0 lib/PointD.cs
  73. +45 −0 lib/PointD3D.cs
  74. +182 −0 lib/PointPlot.cs
  75. +65 −0 lib/PointPlot3D.cs
  76. +1,953 −0 lib/RectangleBrushes.cs
  77. +143 −0 lib/RectangleD.cs
  78. +330 −0 lib/SequenceAdapter.cs
  79. +28 −0 lib/SequenceAdapter3D.cs
  80. +111 −0 lib/StartStep.cs
  81. +149 −0 lib/StepGradient.cs
  82. +347 −0 lib/StepPlot.cs
  83. BIN  lib/StrongName.snk
  84. +178 −0 lib/TextItem.cs
  85. +713 −0 lib/TradingDateTimeAxis.cs
  86. +190 −0 lib/Transform2D.cs
  87. +379 −0 lib/Utils.cs
  88. +293 −0 lib/VerticalLine.cs
  89. +121 −0 lib/Web.Design.PlotSurface2D.cs
  90. +671 −0 lib/Web.PlotSurface2D.cs
  91. +113 −0 lib/Windows.PlotSurface.cs
  92. +42 −0 lib/Windows.PlotSurface.resx
  93. +2,942 −0 lib/Windows.PlotSurface2D.cs
  94. +106 −0 lib/Windows.PlotSurface2D.resx
  95. +155 −0 lib/Windows.PlotSurface2Dnew.cs
  96. +1,214 −0 lib/asx_jbh.xml
  97. +295 −0 lib/changelog.txt
  98. +94 −0 lib/house_rules.txt
  99. BIN  lib/icon.ico
  100. +44 −0 lib/license.txt
  101. BIN  lib/mf.exe.mdb
  102. +51 −0 lib/sysdraw.cs
  103. +154 −0 lib/test.cs
  104. BIN  lib/test.exe.mdb
4 ChangeLog
@@ -0,0 +1,4 @@
+2006-09-21 Carlos Ble <carlosble@shidix.com>
+
+ * updating the whole software to NPlot 0.9.9.2
+
9 Makefile
@@ -0,0 +1,9 @@
+all:
+ (cd lib; make all)
+
+install:
+ @if test x$$prefix = x; then \
+ echo -e "\nError, usage is:\n\n\t make install prefix=INSTALLPREFIX\n"; \
+ exit 1; \
+ fi;
+ (cd lib; make install prefix=$$prefix)
BIN  NPlot.dll
Binary file not shown
18 README
@@ -0,0 +1,18 @@
+The first version of NPlot-Gtk was made by Miguel de Icaza, and was
+a wrapper of NPlot 0.9.8.5.
+
+Now the wrapper of version 0.9.9.2 has just an NPlot upgrade and
+a few hacks over the work of Miguel (Carlos)
+
+------------------------
+
+This version of NPlot has been extended to support Gtk# on Linux.
+
+The version is based on NPlot 0.9.9.2
+
+To build, type `make'
+
+The Gtk# demo is in lib/mf.exe and lib/test.exe
+
+Notice that you must include in your distirbution not only the .dll
+files, but also the .config files.
BIN  lib/.Gtk.PlotSurface2D.cs.swp
Binary file not shown
767 lib/AdapterUtils.cs
@@ -0,0 +1,767 @@
+/*
+NPlot - A charting library for .NET
+
+AdapterUtils.cs
+Copyright (C) 2003-2005
+Matt Howlett
+
+Redistribution and use of NPlot or parts there-of in source and
+binary forms, with or without modification, are permitted provided
+that the following conditions are met:
+
+1. Re-distributions in source form must retain at the head of each
+ source file the above copyright notice, this list of conditions
+ and the following disclaimer.
+
+2. Any product ("the product") that makes use NPlot or parts
+ there-of must either:
+
+ (a) allow any user of the product to obtain a complete machine-
+ readable copy of the corresponding source code for the
+ product and the version of NPlot used for a charge no more
+ than your cost of physically performing source distribution,
+ on a medium customarily used for software interchange, or:
+
+ (b) reproduce the following text in the documentation, about
+ box or other materials intended to be read by human users
+ of the product that is provided to every human user of the
+ product:
+
+ "This product includes software developed as
+ part of the NPlot library project available
+ from: http://www.nplot.com/"
+
+ The words "This product" may optionally be replace with
+ the actual name of the product.
+
+------------------------------------------------------------------------
+
+THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*/
+
+
+using System;
+using System.Collections;
+using System.Data;
+
+namespace NPlot
+{
+
+ /// <summary>
+ /// Encapsulates functionality relating to exposing data in various
+ /// different data structures in a consistent way.
+ /// </summary>
+ /// <remarks>It would be more efficient to have iterator style access
+ /// to the data, rather than index based, and Count.</remarks>
+ public class AdapterUtils
+ {
+
+ #region AxisSuggesters
+
+ /// <summary>
+ /// Interface for classes that can suggest an axis for data they contain.
+ /// </summary>
+ public interface IAxisSuggester
+ {
+ /// <summary>
+ /// Calculates a suggested axis for the data contained by the implementing class.
+ /// </summary>
+ /// <returns>the suggested axis</returns>
+ Axis Get();
+ }
+
+
+ /// <summary>
+ /// Implements functionality for suggesting an axis suitable for charting
+ /// data in multiple columns of a DataRowCollection.
+ /// </summary>
+ /// <remarks>This is currently not used.</remarks>
+ public class AxisSuggester_MultiColumns : IAxisSuggester
+ {
+
+ DataRowCollection rows_;
+ string abscissaName_;
+
+
+ /// <summary>
+ /// Constructor
+ /// </summary>
+ /// <param name="rows">The DataRowCollection containing the data.</param>
+ /// <param name="abscissaName">the column with this name is not considered</param>
+ public AxisSuggester_MultiColumns(DataRowCollection rows, string abscissaName)
+ {
+ rows_ = rows;
+ abscissaName_ = abscissaName;
+ }
+
+
+ /// <summary>
+ /// Calculates a suggested axis for the DataRowCollection data.
+ /// </summary>
+ /// <returns>the suggested axis</returns>
+ public Axis Get()
+ {
+ double t_min = double.MaxValue;
+ double t_max = double.MinValue;
+
+ System.Collections.IEnumerator en = rows_[0].Table.Columns.GetEnumerator();
+
+ while (en.MoveNext())
+ {
+ string colName = ((DataColumn)en.Current).Caption;
+
+ if (colName == abscissaName_)
+ {
+ continue;
+ }
+
+ double min;
+ double max;
+ if (Utils.RowArrayMinMax(rows_, out min, out max, colName))
+ {
+ if (min < t_min)
+ {
+ t_min = min;
+ }
+ if (max > t_max)
+ {
+ t_max = max;
+ }
+ }
+ }
+
+ return new LinearAxis(t_min, t_max);
+ }
+
+ }
+
+
+ /// <summary>
+ /// This class gets an axis suitable for plotting the data contained in an IList.
+ /// </summary>
+ public class AxisSuggester_IList : IAxisSuggester
+ {
+ private IList data_;
+
+ /// <summary>
+ /// Constructor.
+ /// </summary>
+ /// <param name="data">the data we want to find a suitable axis for.</param>
+ public AxisSuggester_IList(IList data)
+ {
+ data_ = data;
+ }
+
+ /// <summary>
+ /// Calculates a suggested axis for the IList data.
+ /// </summary>
+ /// <returns>the suggested axis</returns>
+ public Axis Get()
+ {
+ double min;
+ double max;
+
+ if (Utils.ArrayMinMax(data_, out min, out max))
+ {
+ if (data_[0] is DateTime)
+ {
+ return new DateTimeAxis(min, max);
+ }
+
+ else
+ {
+ return new LinearAxis(min, max);
+ }
+
+ // perhaps return LogAxis here if range large enough
+ // + other constraints?
+ }
+
+ return new LinearAxis(0.0, 1.0);
+ }
+ }
+
+
+ /// <summary>
+ /// This class is responsible for supplying a default axis via the IAxisSuggester interface.
+ /// </summary>
+ public class AxisSuggester_Null : IAxisSuggester
+ {
+ /// <summary>
+ /// Returns a default axis.
+ /// </summary>
+ /// <returns>the suggested axis</returns>
+ public Axis Get()
+ {
+ return new LinearAxis(0.0, 1.0);
+ }
+ }
+
+
+ /// <summary>
+ /// This class gets an axis corresponding to a StartStep object. The data on
+ /// the orthogonal axis is of course also needed to calculate this.
+ /// </summary>
+ public class AxisSuggester_StartStep : IAxisSuggester
+ {
+ StartStep abscissaData_;
+ IList ordinateData_;
+
+ /// <summary>
+ /// Constructor
+ /// </summary>
+ /// <param name="axisOfInterest">StartStep object corresponding to axis of interest</param>
+ /// <param name="otherAxisData">data of other axis (needed to get count value)</param>
+ public AxisSuggester_StartStep(StartStep axisOfInterest, IList otherAxisData)
+ {
+ ordinateData_ = otherAxisData;
+ abscissaData_ = axisOfInterest;
+ }
+
+ /// <summary>
+ /// Calculates a suggested axis given the data specified in the constructor.
+ /// </summary>
+ /// <returns>the suggested axis</returns>
+ public Axis Get()
+ {
+ return new LinearAxis(
+ abscissaData_.Start,
+ abscissaData_.Start + (double)(ordinateData_.Count - 1) * abscissaData_.Step);
+ }
+ }
+
+
+ /// <summary>
+ /// Provides default axis if only data corresponding to orthogonal axis is provided.
+ /// </summary>
+ public class AxisSuggester_Auto : IAxisSuggester
+ {
+
+ IList ordinateData_;
+
+ /// <summary>
+ /// Constructor
+ /// </summary>
+ /// <param name="ordinateData">Data corresponding to orthogonal axis.</param>
+ public AxisSuggester_Auto(IList ordinateData)
+ {
+ ordinateData_ = ordinateData;
+ }
+
+ /// <summary>
+ /// Calculates a suggested axis given the data specified in the constructor.
+ /// </summary>
+ /// <returns>the suggested axis</returns>
+ public Axis Get()
+ {
+ return new LinearAxis(0, ordinateData_.Count - 1);
+ }
+ }
+
+
+ /// <summary>
+ /// Provides default axis if only data corresponding to orthogonal axis is provided.
+ /// </summary>
+ public class AxisSuggester_RowAuto : IAxisSuggester
+ {
+ DataRowCollection ordinateData_;
+
+ /// <summary>
+ /// Construbtor
+ /// </summary>
+ /// <param name="ordinateData">Data corresponding to orthogonal axis.</param>
+ public AxisSuggester_RowAuto(DataRowCollection ordinateData)
+ {
+ ordinateData_ = ordinateData;
+ }
+
+ /// <summary>
+ /// Calculates a suggested axis given the data specified in the constructor.
+ /// </summary>
+ /// <returns>the suggested axis</returns>
+ public Axis Get()
+ {
+ return new LinearAxis(0, ordinateData_.Count - 1);
+ }
+ }
+
+ /// <summary>
+ /// Provides axis for data in a given column of a DataRowCollection.
+ /// </summary>
+ public class AxisSuggester_Rows : IAxisSuggester
+ {
+ DataRowCollection rows_;
+ string columnName_;
+
+ /// <summary>
+ /// Constructor
+ /// </summary>
+ /// <param name="rows">DataRowCollection containing the data to suggest axis for.</param>
+ /// <param name="columnName">the column to get data.</param>
+ public AxisSuggester_Rows(DataRowCollection rows, string columnName)
+ {
+ rows_ = rows;
+ columnName_ = columnName;
+ }
+
+ /// <summary>
+ /// Calculates a suggested axis given the data specified in the constructor.
+ /// </summary>
+ /// <returns>the suggested axis</returns>
+ public Axis Get()
+ {
+ double min;
+ double max;
+
+ if (Utils.RowArrayMinMax(rows_, out min, out max, columnName_))
+ {
+ if ((rows_[0])[columnName_] is DateTime)
+ {
+ return new DateTimeAxis(min, max);
+ }
+
+ else
+ {
+ return new LinearAxis(min, max);
+ }
+ }
+
+ return new LinearAxis(0.0, 1.0);
+ }
+ }
+
+
+ /// <summary>
+ /// Provides axis suggestion for data in a particular column of a DataView.
+ /// </summary>
+ public class AxisSuggester_DataView : IAxisSuggester
+ {
+ DataView data_;
+ string columnName_;
+
+ /// <summary>
+ /// Constructor
+ /// </summary>
+ /// <param name="data">DataView that contains data to suggest axis for</param>
+ /// <param name="columnName">the column of interest in the DataView</param>
+ public AxisSuggester_DataView(DataView data, string columnName)
+ {
+ data_ = data;
+ columnName_ = columnName;
+ }
+
+ /// <summary>
+ /// Calculates a suggested axis given the data specified in the constructor.
+ /// </summary>
+ /// <returns>the suggested axis</returns>
+ public Axis Get()
+ {
+ double min;
+ double max;
+
+ if (Utils.DataViewArrayMinMax(data_, out min, out max, columnName_))
+ {
+ if ((data_[0])[columnName_] is DateTime)
+ {
+ return new DateTimeAxis(min, max);
+ }
+
+ else
+ {
+ return new LinearAxis(min, max);
+ }
+ }
+
+ return new LinearAxis(0.0, 1.0);
+ }
+ }
+
+ #endregion
+ #region Counters
+
+ /// <summary>
+ /// Interface that enables a dataholding class to report how many data items it holds.
+ /// </summary>
+ public interface ICounter
+ {
+ /// <summary>
+ /// Number of data items in container.
+ /// </summary>
+ /// <value>Number of data items in container.</value>
+ int Count { get; }
+ }
+
+ /// <summary>
+ /// Class that provides the number of items in an IList via the ICounter interface.
+ /// </summary>
+ public class Counter_IList : ICounter
+ {
+ private IList data_;
+
+ /// <summary>
+ /// Constructor
+ /// </summary>
+ /// <param name="data">the IList data to provide count of</param>
+ public Counter_IList(IList data)
+ {
+ data_ = data;
+ }
+
+ /// <summary>
+ /// Number of data items in container.
+ /// </summary>
+ /// <value>Number of data items in container.</value>
+ public int Count
+ {
+ get
+ {
+ return data_.Count;
+ }
+ }
+ }
+
+ /// <summary>
+ /// Class that returns 0 via the ICounter interface.
+ /// </summary>
+ public class Counter_Null : ICounter
+ {
+ /// <summary>
+ /// Number of data items in container.
+ /// </summary>
+ /// <value>Number of data items in container.</value>
+ public int Count
+ {
+ get
+ {
+ return 0;
+ }
+ }
+ }
+
+ /// <summary>
+ /// Class that provides the number of items in a DataRowCollection via the ICounter interface.
+ /// </summary>
+ public class Counter_Rows : ICounter
+ {
+ DataRowCollection rows_;
+
+ /// <summary>
+ /// Constructor
+ /// </summary>
+ /// <param name="rows">the DataRowCollection data to provide count of number of rows of.</param>
+ public Counter_Rows(DataRowCollection rows)
+ {
+ rows_ = rows;
+ }
+
+ /// <summary>
+ /// Number of data items in container.
+ /// </summary>
+ /// <value>Number of data items in container.</value>
+ public int Count
+ {
+ get
+ {
+ return rows_.Count;
+ }
+ }
+ }
+
+ /// <summary>
+ /// Class that provides the number of items in a DataView via the ICounter interface.
+ /// </summary>
+ public class Counter_DataView : ICounter
+ {
+ DataView dataView_;
+
+ /// <summary>
+ /// Constructor
+ /// </summary>
+ /// <param name="dataView">the DataBiew data to provide count of number of rows of.</param>
+ public Counter_DataView(DataView dataView)
+ {
+ dataView_ = dataView;
+ }
+
+ /// <summary>
+ /// Number of data items in container.
+ /// </summary>
+ /// <value>Number of data items in container.</value>
+ public int Count
+ {
+ get
+ {
+ return dataView_.Count;
+ }
+ }
+
+ }
+
+ #endregion
+ #region DataGetters
+
+ /// <summary>
+ /// Interface for data holding classes that allows users to get the ith value.
+ /// </summary>
+ /// <remarks>
+ /// TODO: should change this to GetNext() and Reset() for more generality.
+ /// </remarks>
+ public interface IDataGetter
+ {
+ /// <summary>
+ /// Gets the ith data value.
+ /// </summary>
+ /// <param name="i">sequence number of data to get.</param>
+ /// <returns>ith data value.</returns>
+ double Get(int i);
+ }
+
+ /// <summary>
+ /// Provides data in an IList via the IDataGetter interface.
+ /// </summary>
+ public class DataGetter_IList : IDataGetter
+ {
+ private IList data_;
+
+ /// <summary>
+ /// Constructor
+ /// </summary>
+ /// <param name="data">IList that contains the data</param>
+ public DataGetter_IList(IList data)
+ {
+ data_ = data;
+ }
+
+ /// <summary>
+ /// Gets the ith data value.
+ /// </summary>
+ /// <param name="i">sequence number of data to get.</param>
+ /// <returns>ith data value.</returns>
+ public double Get(int i)
+ {
+ return Utils.ToDouble(data_[i]);
+ }
+ }
+
+
+ /// <summary>
+ /// Provides data in an array of doubles via the IDataGetter interface.
+ /// </summary>
+ /// <remarks>
+ /// A speed-up version of DataDetter_IList; no boxing/unboxing overhead.
+ /// </remarks>
+ public class DataGetter_DoublesArray : IDataGetter
+ {
+ private double[] data_;
+
+ /// <summary>
+ /// Constructor
+ /// </summary>
+ /// <param name="data">array of doubles that contains the data</param>
+ public DataGetter_DoublesArray(double[] data)
+ {
+ data_ = data;
+ }
+
+ /// <summary>
+ /// Gets the ith data value.
+ /// </summary>
+ /// <param name="i">sequence number of data to get.</param>
+ /// <returns>ith data value.</returns>
+ public double Get(int i)
+ {
+ return data_[i];
+ }
+ }
+
+
+ /// <summary>
+ /// Provides no data.
+ /// </summary>
+ public class DataGetter_Null : IDataGetter
+ {
+ /// <summary>
+ /// Gets the ith data value.
+ /// </summary>
+ /// <param name="i">sequence number of data to get.</param>
+ /// <returns>ith data value.</returns>
+ public double Get(int i)
+ {
+ throw new NPlotException( "No Data!" );
+ }
+ }
+
+ /// <summary>
+ /// Provides data points from a StartStep object via the IDataGetter interface.
+ /// </summary>
+ public class DataGetter_StartStep : IDataGetter
+ {
+ StartStep data_;
+
+ /// <summary>
+ /// Constructor
+ /// </summary>
+ /// <param name="data">StartStep to derive data from.</param>
+ public DataGetter_StartStep(StartStep data)
+ {
+ data_ = data;
+ }
+
+ /// <summary>
+ /// Gets the ith data value.
+ /// </summary>
+ /// <param name="i">sequence number of data to get.</param>
+ /// <returns>ith data value.</returns>
+ public double Get(int i)
+ {
+ return data_.Start + (double)(i) * data_.Step;
+ }
+ }
+
+ /// <summary>
+ /// Provides the natural numbers (and 0) via the IDataGetter interface.
+ /// </summary>
+ public class DataGetter_Count : IDataGetter
+ {
+ /// <summary>
+ /// Gets the ith data value.
+ /// </summary>
+ /// <param name="i">sequence number of data to get.</param>
+ /// <returns>ith data value.</returns>
+ public double Get(int i)
+ {
+ return (double)i;
+ }
+ }
+
+
+ /// <summary>
+ /// Provides data in a DataRowCollection via the IDataGetter interface.
+ /// </summary>
+ public class DataGetter_Rows : IDataGetter
+ {
+ private DataRowCollection rows_;
+ private string columnName_;
+
+ /// <summary>
+ /// Constructor
+ /// </summary>
+ /// <param name="rows">DataRowCollection to get data from</param>
+ /// <param name="columnName">Get data in this column</param>
+ public DataGetter_Rows(DataRowCollection rows, string columnName)
+ {
+ rows_ = rows;
+ columnName_ = columnName;
+ }
+
+ /// <summary>
+ /// Gets the ith data value.
+ /// </summary>
+ /// <param name="i">sequence number of data to get.</param>
+ /// <returns>ith data value.</returns>
+ public double Get(int i)
+ {
+ return Utils.ToDouble((rows_[i])[columnName_]);
+ }
+ }
+
+ /// <summary>
+ /// Provides data in a DataView via the IDataGetter interface.
+ /// </summary>
+ public class DataGetter_DataView : IDataGetter
+ {
+ private DataView data_;
+ private string columnName_;
+
+ /// <summary>
+ /// Constructor
+ /// </summary>
+ /// <param name="data">DataView to get data from.</param>
+ /// <param name="columnName">Get data in this column</param>
+ public DataGetter_DataView(DataView data, string columnName)
+ {
+ data_ = data;
+ columnName_ = columnName;
+ }
+
+ /// <summary>
+ /// Gets the ith data value.
+ /// </summary>
+ /// <param name="i">sequence number of data to get.</param>
+ /// <returns>ith data value.</returns>
+ public double Get(int i)
+ {
+ return Utils.ToDouble((data_[i])[columnName_]);
+ }
+
+ }
+
+
+ /// <summary>
+ /// Gets data
+ /// </summary>
+ /// <remarks>Note: Does not implement IDataGetter... Currently this class is not used.</remarks>
+ public class DataGetter_MultiRows
+ {
+
+ DataRowCollection rows_;
+ string abscissaName_;
+ int abscissaColumnNumber_;
+
+ /// <summary>
+ /// Constructor
+ /// </summary>
+ /// <param name="rows">DataRowCollection to get data from.</param>
+ /// <param name="omitThisColumn">don't get data from this column</param>
+ public DataGetter_MultiRows(DataRowCollection rows, string omitThisColumn )
+ {
+ rows_ = rows;
+ abscissaName_ = omitThisColumn;
+
+ abscissaColumnNumber_ = rows_[0].Table.Columns.IndexOf( omitThisColumn );
+ if (abscissaColumnNumber_ < 0)
+ throw new NPlotException( "invalid column name" );
+ }
+
+ /// <summary>
+ /// Number of data points
+ /// </summary>
+ public int Count
+ {
+ get
+ {
+ return rows_[0].Table.Columns.Count-1;
+ }
+ }
+
+ /// <summary>
+ /// Gets data at a given index, in the given series (column number).
+ /// </summary>
+ /// <param name="index">index in the series to get data for</param>
+ /// <param name="seriesIndex">series number (column number) to get data for.</param>
+ /// <returns>the required data point.</returns>
+ public double PointAt( int index, int seriesIndex )
+ {
+ if (seriesIndex < abscissaColumnNumber_)
+ return Utils.ToDouble( rows_[index][seriesIndex] );
+ else
+ return Utils.ToDouble( rows_[index][seriesIndex+1] );
+ }
+
+ }
+
+
+ #endregion
+
+ }
+}
455 lib/ArrowItem.cs
@@ -0,0 +1,455 @@
+/*
+NPlot - A charting library for .NET
+
+ArrowItem.cs
+Copyright (C) 2003
+Matt Howlett
+
+Redistribution and use of NPlot or parts there-of in source and
+binary forms, with or without modification, are permitted provided
+that the following conditions are met:
+
+1. Re-distributions in source form must retain at the head of each
+ source file the above copyright notice, this list of conditions
+ and the following disclaimer.
+
+2. Any product ("the product") that makes use NPlot or parts
+ there-of must either:
+
+ (a) allow any user of the product to obtain a complete machine-
+ readable copy of the corresponding source code for the
+ product and the version of NPlot used for a charge no more
+ than your cost of physically performing source distribution,
+ on a medium customarily used for software interchange, or:
+
+ (b) reproduce the following text in the documentation, about
+ box or other materials intended to be read by human users
+ of the product that is provided to every human user of the
+ product:
+
+ "This product includes software developed as
+ part of the NPlot library project available
+ from: http://www.nplot.com/"
+
+ The words "This product" may optionally be replace with
+ the actual name of the product.
+
+------------------------------------------------------------------------
+
+THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*/
+
+using System;
+using System.Drawing;
+
+namespace NPlot
+{
+
+ /// <summary>
+ /// An Arrow IDrawable, with a text label that is automatically
+ /// nicely positioned at the non-pointy end of the arrow. Future
+ /// feature idea: have constructor that takes a dataset, and have
+ /// the arrow know how to automatically set it's angle to avoid
+ /// the data.
+ /// </summary>
+ public class ArrowItem : IDrawable
+ {
+
+ private void Init()
+ {
+ FontFamily fontFamily = new FontFamily("Arial");
+ font_ = new Font(fontFamily, 10, FontStyle.Regular, GraphicsUnit.Pixel);
+ }
+
+
+ /// <summary>
+ /// Default constructor :
+ /// text = ""
+ /// angle = 45 degrees anticlockwise from horizontal.
+ /// </summary>
+ /// <param name="position">The position the arrow points to.</param>
+ public ArrowItem( PointD position )
+ {
+ to_ = position;
+ Init();
+ }
+
+
+ /// <summary>
+ /// Constructor
+ /// </summary>
+ /// <param name="position">The position the arrow points to.</param>
+ /// <param name="angle">angle of arrow with respect to x axis.</param>
+ public ArrowItem( PointD position, double angle )
+ {
+ to_ = position;
+ angle_ = -angle;
+ Init();
+ }
+
+
+ /// <summary>
+ /// Constructor
+ /// </summary>
+ /// <param name="position">The position the arrow points to.</param>
+ /// <param name="angle">angle of arrow with respect to x axis.</param>
+ /// <param name="text">The text associated with the arrow.</param>
+ public ArrowItem( PointD position, double angle, string text )
+ {
+ to_ = position;
+ angle_ = -angle;
+ text_ = text;
+ Init();
+ }
+
+
+ /// <summary>
+ /// Text associated with the arrow.
+ /// </summary>
+ public string Text
+ {
+ get
+ {
+ return text_;
+ }
+ set
+ {
+ text_ = value;
+ }
+ }
+ private string text_ = "";
+
+
+ /// <summary>
+ /// Angle of arrow anti-clockwise to right horizontal in degrees.
+ /// </summary>
+ /// <remarks>The code relating to this property in the Draw method is
+ /// a bit weird. Internally, all rotations are clockwise [this is by
+ /// accient, I wasn't concentrating when I was doing it and was half
+ /// done before I realised]. The simplest way to make angle represent
+ /// anti-clockwise rotation (as it is normal to do) is to make the
+ /// get and set methods negate the provided value.</remarks>
+ public double Angle
+ {
+ get
+ {
+ return -angle_;
+ }
+ set
+ {
+ angle_ = -value;
+ }
+ }
+ private double angle_ = -45.0;
+
+
+ /// <summary>
+ /// Physical length of the arrow.
+ /// </summary>
+ public float PhysicalLength
+ {
+ get
+ {
+ return physicalLength_;
+ }
+ set
+ {
+ physicalLength_ = value;
+ }
+ }
+ private float physicalLength_ = 40.0f;
+
+
+ /// <summary>
+ /// The point the arrow points to.
+ /// </summary>
+ public PointD To
+ {
+ get
+ {
+ return to_;
+ }
+ set
+ {
+ to_ = value;
+ }
+ }
+ private PointD to_;
+
+
+ /// <summary>
+ /// Size of the arrow head sides in pixels.
+ /// </summary>
+ public float HeadSize
+ {
+ get
+ {
+ return headSize_;
+ }
+ set
+ {
+ headSize_ = value;
+ }
+ }
+ private float headSize_ = 10.0f;
+
+
+ /// <summary>
+ /// angle between sides of arrow head in degrees
+ /// </summary>
+ public float HeadAngle
+ {
+ get
+ {
+ return headAngle_;
+ }
+ set
+ {
+ headAngle_ = value;
+ }
+ }
+ private float headAngle_ = 40.0f;
+
+
+ /// <summary>
+ /// Draws the arrow on a plot surface.
+ /// </summary>
+ /// <param name="g">graphics surface on which to draw</param>
+ /// <param name="xAxis">The X-Axis to draw against.</param>
+ /// <param name="yAxis">The Y-Axis to draw against.</param>
+ public void Draw( System.Drawing.Graphics g, PhysicalAxis xAxis, PhysicalAxis yAxis )
+ {
+ if (this.To.X > xAxis.Axis.WorldMax || this.To.X < xAxis.Axis.WorldMin)
+ return;
+
+ if (this.To.Y > yAxis.Axis.WorldMax || this.To.Y < yAxis.Axis.WorldMin)
+ return;
+
+ double angle = this.angle_;
+
+ if (this.angle_ < 0.0)
+ {
+ int mul = -(int)(this.angle_ / 360.0) + 2;
+ angle = angle_ + 360.0 * (double)mul;
+ }
+
+ double normAngle = (double)angle % 360.0; // angle in range 0 -> 360.
+
+ Point toPoint = new Point(
+ (int)xAxis.WorldToPhysical( to_.X, true ).X,
+ (int)yAxis.WorldToPhysical( to_.Y, true ).Y );
+
+
+ float xDir = (float)Math.Cos( normAngle * 2.0 * Math.PI / 360.0 );
+ float yDir = (float)Math.Sin( normAngle * 2.0 * Math.PI / 360.0 );
+
+ toPoint.X += (int)(xDir*headOffset_);
+ toPoint.Y += (int)(yDir*headOffset_);
+
+ float xOff = physicalLength_ * xDir;
+ float yOff = physicalLength_ * yDir;
+
+ Point fromPoint = new Point(
+ (int)(toPoint.X + xOff),
+ (int)(toPoint.Y + yOff) );
+
+ g.DrawLine( pen_, toPoint, fromPoint );
+
+ Point[] head = new Point[3];
+
+ head[0] = toPoint;
+
+ xOff = headSize_ * (float)Math.Cos( (normAngle-headAngle_/2.0f) * 2.0 * Math.PI / 360.0 );
+ yOff = headSize_ * (float)Math.Sin( (normAngle-headAngle_/2.0f) * 2.0 * Math.PI / 360.0 );
+
+ head[1] = new Point(
+ (int)(toPoint.X + xOff),
+ (int)(toPoint.Y + yOff) );
+
+ float xOff2 = headSize_ * (float)Math.Cos( (normAngle+headAngle_/2.0f) * 2.0 * Math.PI / 360.0 );
+ float yOff2 = headSize_ * (float)Math.Sin( (normAngle+headAngle_/2.0f) * 2.0 * Math.PI / 360.0 );
+
+ head[2] = new Point(
+ (int)(toPoint.X + xOff2),
+ (int)(toPoint.Y + yOff2) );
+
+ g.FillPolygon( arrowBrush_, head );
+
+ SizeF textSize = g.MeasureString( text_, font_ );
+ SizeF halfSize = new SizeF( textSize.Width / 2.0f, textSize.Height / 2.0f );
+
+ float quadrantSlideLength = halfSize.Width + halfSize.Height;
+
+ float quadrantF = (float)normAngle / 90.0f; // integer part gives quadrant.
+ int quadrant = (int)quadrantF; // quadrant in.
+ float prop = quadrantF - (float)quadrant; // proportion of way through this qadrant.
+ float dist = prop * quadrantSlideLength; // distance along quarter of bounds rectangle.
+
+ // now find the offset from the middle of the text box that the
+ // rear end of the arrow should end at (reverse this to get position
+ // of text box with respect to rear end of arrow).
+ //
+ // There is almost certainly an elgant way of doing this involving
+ // trig functions to get all the signs right, but I'm about ready to
+ // drop off to sleep at the moment, so this blatent method will have
+ // to do.
+ PointF offsetFromMiddle = new PointF( 0.0f, 0.0f );
+ switch (quadrant)
+ {
+ case 0:
+ if (dist > halfSize.Height)
+ {
+ dist -= halfSize.Height;
+ offsetFromMiddle = new PointF( -halfSize.Width + dist, halfSize.Height );
+ }
+ else
+ {
+ offsetFromMiddle = new PointF( -halfSize.Width, - dist );
+ }
+ break;
+
+ case 1:
+ if (dist > halfSize.Width)
+ {
+ dist -= halfSize.Width;
+ offsetFromMiddle = new PointF( halfSize.Width, halfSize.Height - dist );
+ }
+ else
+ {
+ offsetFromMiddle = new PointF( dist, halfSize.Height );
+ }
+ break;
+
+ case 2:
+ if (dist > halfSize.Height)
+ {
+ dist -= halfSize.Height;
+ offsetFromMiddle = new PointF( halfSize.Width - dist, -halfSize.Height );
+ }
+ else
+ {
+ offsetFromMiddle = new PointF( halfSize.Width, -dist );
+ }
+
+ break;
+
+ case 3:
+ if (dist > halfSize.Width)
+ {
+ dist -= halfSize.Width;
+ offsetFromMiddle = new PointF( -halfSize.Width, -halfSize.Height + dist );
+ }
+ else
+ {
+ offsetFromMiddle = new PointF( -dist, -halfSize.Height );
+ }
+
+ break;
+
+ default:
+ throw new NPlotException( "Programmer error." );
+
+ }
+
+ g.DrawString(
+ text_, font_, textBrush_,
+ (int)(fromPoint.X - halfSize.Width - offsetFromMiddle.X),
+ (int)(fromPoint.Y - halfSize.Height + offsetFromMiddle.Y) );
+
+ }
+
+
+ /// <summary>
+ /// The brush used to draw the text associated with the arrow.
+ /// </summary>
+ public Brush TextBrush
+ {
+ get
+ {
+ return textBrush_;
+ }
+ set
+ {
+ textBrush_ = value;
+ }
+ }
+
+
+ /// <summary>
+ /// Set the text to be drawn with a solid brush of this color.
+ /// </summary>
+ public Color TextColor
+ {
+ set
+ {
+ textBrush_ = new SolidBrush( value );
+ }
+ }
+
+
+ /// <summary>
+ /// The color of the pen used to draw the arrow.
+ /// </summary>
+ public Color ArrowColor
+ {
+ get
+ {
+ return pen_.Color;
+ }
+ set
+ {
+ pen_.Color = value;
+ arrowBrush_ = new SolidBrush( value );
+ }
+ }
+
+
+ /// <summary>
+ /// The font used to draw the text associated with the arrow.
+ /// </summary>
+ public Font TextFont
+ {
+ get
+ {
+ return this.font_;
+ }
+ set
+ {
+ this.font_ = value;
+ }
+ }
+
+
+ /// <summary>
+ /// Offset the whole arrow back in the arrow direction this many pixels from the point it's pointing to.
+ /// </summary>
+ public int HeadOffset
+ {
+ get
+ {
+ return headOffset_;
+ }
+ set
+ {
+ headOffset_ = value;
+ }
+ }
+ private int headOffset_ = 2;
+
+
+ private Brush arrowBrush_ = new SolidBrush( Color.Black );
+ private Brush textBrush_ = new SolidBrush( Color.Black );
+ private Pen pen_ = new Pen( Color.Black );
+ private Font font_;
+ }
+}
68 lib/AssemblyInfo.cs
@@ -0,0 +1,68 @@
+/*
+NPlot - A charting library for .NET
+
+AssemblyInfo.cs
+Copyright (C) 2003
+Matt Howlett
+
+Redistribution and use of NPlot or parts there-of in source and
+binary forms, with or without modification, are permitted provided
+that the following conditions are met:
+
+1. Re-distributions in source form must retain at the head of each
+ source file the above copyright notice, this list of conditions
+ and the following disclaimer.
+
+2. Any product ("the product") that makes use NPlot or parts
+ there-of must either:
+
+ (a) allow any user of the product to obtain a complete machine-
+ readable copy of the corresponding source code for the
+ product and the version of NPlot used for a charge no more
+ than your cost of physically performing source distribution,
+ on a medium customarily used for software interchange, or:
+
+ (b) reproduce the following text in the documentation, about
+ box or other materials intended to be read by human users
+ of the product that is provided to every human user of the
+ product:
+
+ "This product includes software developed as
+ part of the NPlot library project available
+ from: http://www.nplot.com/"
+
+ The words "This product" may optionally be replace with
+ the actual name of the product.
+
+------------------------------------------------------------------------
+
+THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*/
+
+
+using System;
+using System.Reflection;
+using System.Runtime.CompilerServices;
+
+[assembly: AssemblyTitle("NPlot")]
+[assembly: AssemblyDescription("NPlot Charting Library")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("netcontrols")]
+[assembly: AssemblyProduct("")]
+[assembly: AssemblyCopyright("")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+[assembly: AssemblyVersion("0.9.9.2")]
+[assembly: CLSCompliant(true)]
+[assembly: AssemblyKeyFile("StrongName.snk")]
+
519 lib/AxesConstraint.cs
@@ -0,0 +1,519 @@
+/*
+NPlot - A charting library for .NET
+
+AxesConstraint.cs
+Copyright (C) 2003
+Matt Howlett
+
+Redistribution and use of NPlot or parts there-of in source and
+binary forms, with or without modification, are permitted provided
+that the following conditions are met:
+
+1. Re-distributions in source form must retain at the head of each
+ source file the above copyright notice, this list of conditions
+ and the following disclaimer.
+
+2. Any product ("the product") that makes use NPlot or parts
+ there-of must either:
+
+ (a) allow any user of the product to obtain a complete machine-
+ readable copy of the corresponding source code for the
+ product and the version of NPlot used for a charge no more
+ than your cost of physically performing source distribution,
+ on a medium customarily used for software interchange, or:
+
+ (b) reproduce the following text in the documentation, about
+ box or other materials intended to be read by human users
+ of the product that is provided to every human user of the
+ product:
+
+ "This product includes software developed as
+ part of the NPlot library project available
+ from: http://www.nplot.com/"
+
+ The words "This product" may optionally be replace with
+ the actual name of the product.
+
+------------------------------------------------------------------------
+
+THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*/
+
+using System;
+using System.Drawing;
+using System.Drawing.Drawing2D;
+
+namespace NPlot
+{
+
+ /// <summary>
+ /// Classes derived from this abstract base class define and can apply
+ /// some form of constraint to the positioning and length of one or more
+ /// of the four axes of a PlotSurface2D.
+ /// </summary>
+ public abstract class AxesConstraint
+ {
+
+ /// <summary>
+ /// Defines an AxisConstraint that forces the world length corresponding
+ /// to one pixel on the bottom x-axis to be a certain value.
+ ///
+ /// TODO: Allow the pixel world length to be set for the top axis.
+ /// </summary>
+ public class XPixelWorldLength : AxesConstraint
+ {
+ private double pWorldLength_ = 0.0f;
+ private object holdFixedY_ = null;
+
+ /// <summary>
+ /// Constructor, which defines the world pixel length only. Both
+ /// y-axes will be moved by equal amounts in order to force this
+ /// constraint.
+ /// </summary>
+ /// <param name="p">The world pixel length</param>
+ public XPixelWorldLength( double p )
+ {
+ this.pWorldLength_ = p;
+ }
+
+ /// <summary>
+ /// Constructor, which defines the world pixel length together with
+ /// the y-axis that should be held constant when forcing this
+ /// constraint [the other y-axis only will be moved].
+ /// </summary>
+ /// <param name="p">The world pixel length</param>
+ /// <param name="holdFixedY">The position of this y-axis will be
+ /// held constant. The other y-axis will be moved in order to
+ /// force the constraint.</param>
+ public XPixelWorldLength( double p, PlotSurface2D.YAxisPosition holdFixedY )
+ {
+ this.pWorldLength_ = p;
+ this.holdFixedY_ = holdFixedY;
+ }
+
+ /// <summary>
+ /// Applies the constraint to the axes.
+ /// </summary>
+ /// <param name="pXAxis1">The bottom x-axis.</param>
+ /// <param name="pYAxis1">The left y-axis.</param>
+ /// <param name="pXAxis2">The top x-axis.</param>
+ /// <param name="pYAxis2">The right y-axis.</param>
+ public override void ApplyConstraint(
+ PhysicalAxis pXAxis1, PhysicalAxis pYAxis1,
+ PhysicalAxis pXAxis2, PhysicalAxis pYAxis2 )
+ {
+ int desiredLength = (int)(pXAxis1.Axis.WorldLength / (double)this.pWorldLength_);
+ int currentLength = pXAxis1.PhysicalLength;
+ int delta = currentLength - desiredLength;
+
+ int changeLeft = delta / 2;
+ int changeRight = delta / 2;
+ if (this.holdFixedY_ != null)
+ {
+ if ( (PlotSurface2D.YAxisPosition)this.holdFixedY_ == PlotSurface2D.YAxisPosition.Left )
+ {
+ changeLeft = 0;
+ changeRight = delta;
+ }
+ else
+ {
+ changeLeft = delta;
+ changeRight = 0;
+ }
+ }
+
+ pXAxis1.PhysicalMin = new Point( pXAxis1.PhysicalMin.X+changeLeft, pXAxis1.PhysicalMin.Y );
+ pXAxis1.PhysicalMax = new Point( pXAxis1.PhysicalMax.X-changeRight, pXAxis1.PhysicalMax.Y );
+ pXAxis2.PhysicalMin = new Point( pXAxis2.PhysicalMin.X+changeLeft, pXAxis2.PhysicalMin.Y );
+ pXAxis2.PhysicalMax = new Point( pXAxis2.PhysicalMax.X-changeRight, pXAxis2.PhysicalMax.Y );
+
+ pYAxis1.PhysicalMin = new Point( pYAxis1.PhysicalMin.X+changeLeft, pYAxis1.PhysicalMin.Y );
+ pYAxis1.PhysicalMax = new Point( pYAxis1.PhysicalMax.X+changeLeft, pYAxis1.PhysicalMax.Y );
+ pYAxis2.PhysicalMin = new Point( pYAxis2.PhysicalMin.X-changeRight, pYAxis2.PhysicalMin.Y );
+ pYAxis2.PhysicalMax = new Point( pYAxis2.PhysicalMax.X-changeRight, pYAxis2.PhysicalMax.Y );
+
+ }
+ }
+
+
+ /// <summary>
+ /// Defines an AxisConstraint that forces the world length corresponding
+ /// to one pixel on the left y-axis to be a certain value.
+ ///
+ /// TODO: Allow the pixel world length to be set for the right axis.
+ /// </summary>
+ public class YPixelWorldLength : AxesConstraint
+ {
+ private double pWorldLength_ = 0.0;
+ private object holdFixedX_ = null;
+
+ /// <summary>
+ /// Constructor, which defines the world pixel length only. Both
+ /// x-axes will be moved by equal amounts in order to force this
+ /// constraint.
+ /// </summary>
+ /// <param name="p">The world pixel length</param>
+ public YPixelWorldLength( double p )
+ {
+ this.pWorldLength_ = p;
+ }
+
+ /// <summary>
+ /// Constructor, which defines the world pixel length together with
+ /// the x-axis that should be held constant when forcing this
+ /// constraint [the other x-axis only will be moved].
+ /// </summary>
+ /// <param name="p">The world pixel length</param>
+ /// <param name="holdFixedX">The position of this x-axis will be held constant. The other x-axis will be moved in order to force the constraint.</param>
+ public YPixelWorldLength( double p, PlotSurface2D.XAxisPosition holdFixedX )
+ {
+ this.pWorldLength_ = p;
+ this.holdFixedX_ = holdFixedX;
+ }
+
+
+ /// <summary>
+ /// Applies the constraint to the axes.
+ /// </summary>
+ /// <param name="pXAxis1">The bottom x-axis.</param>
+ /// <param name="pYAxis1">The left y-axis.</param>
+ /// <param name="pXAxis2">The top x-axis.</param>
+ /// <param name="pYAxis2">The right y-axis.</param>
+ public override void ApplyConstraint(
+ PhysicalAxis pXAxis1, PhysicalAxis pYAxis1,
+ PhysicalAxis pXAxis2, PhysicalAxis pYAxis2 )
+ {
+
+ int desiredLength = (int)(pYAxis1.Axis.WorldLength / this.pWorldLength_);
+ int currentLength = pYAxis1.PhysicalLength;
+ int delta = currentLength - desiredLength;
+
+ int changeBottom = -delta / 2;
+ int changeTop = -delta / 2;
+ if (this.holdFixedX_ != null)
+ {
+ if ( (PlotSurface2D.XAxisPosition)this.holdFixedX_ == PlotSurface2D.XAxisPosition.Bottom )
+ {
+ changeBottom = 0;
+ changeTop = -delta;
+ }
+ else
+ {
+ changeBottom = -delta;
+ changeTop = 0;
+ }
+ }
+
+ pYAxis1.PhysicalMin = new Point( pYAxis1.PhysicalMin.X, pYAxis1.PhysicalMin.Y+changeBottom );
+ pYAxis1.PhysicalMax = new Point( pYAxis1.PhysicalMax.X, pYAxis1.PhysicalMax.Y-changeTop );
+ pYAxis2.PhysicalMin = new Point( pYAxis2.PhysicalMin.X, pYAxis2.PhysicalMin.Y+changeBottom );
+ pYAxis2.PhysicalMax = new Point( pYAxis2.PhysicalMax.X, pYAxis2.PhysicalMax.Y-changeTop );
+
+ pXAxis1.PhysicalMin = new Point( pXAxis1.PhysicalMin.X, pXAxis1.PhysicalMin.Y+changeBottom );
+ pXAxis1.PhysicalMax = new Point( pXAxis1.PhysicalMax.X, pXAxis1.PhysicalMax.Y+changeBottom );
+ pXAxis2.PhysicalMin = new Point( pXAxis2.PhysicalMin.X, pXAxis2.PhysicalMin.Y-changeTop );
+ pXAxis2.PhysicalMax = new Point( pXAxis2.PhysicalMax.X, pXAxis2.PhysicalMax.Y-changeTop );
+
+ }
+ }
+
+
+ /// <summary>
+ /// Defines an AxisConstraint that forces the specified axis to be placed at a
+ /// specific physical position. The position of the axis opposite is held
+ /// constant.
+ /// </summary>
+ public class AxisPosition : AxesConstraint
+ {
+
+ private object xAxisPosition_;
+ private object yAxisPosition_;
+ private int position_;
+
+
+ /// <summary>
+ /// Constructor, which defines an horizontal axis and the physical
+ /// y position it should be drawn at.
+ /// </summary>
+ /// <param name="axis">The x-axis for which the y position is to be specified.</param>
+ /// <param name="yPosition">The [physical] y position of the axis.</param>
+ public AxisPosition( PlotSurface2D.XAxisPosition axis, int yPosition )
+ {
+ position_ = yPosition;
+ xAxisPosition_ = axis;
+ }
+
+
+ /// <summary>
+ /// Constructor, which defines a vertical axis and the physical
+ /// x position it should be drawn at.
+ /// </summary>
+ /// <param name="axis">The y-axis for which the x position is to be specified.</param>
+ /// <param name="xPosition">The [physical] x position of the axis.</param>
+ public AxisPosition( PlotSurface2D.YAxisPosition axis, int xPosition )
+ {
+ position_ = xPosition;
+ yAxisPosition_ = axis;
+ }
+
+ /// <summary>
+ /// Applies the constraint to the axes.
+ /// </summary>
+ /// <param name="pXAxis1">The bottom x-axis.</param>
+ /// <param name="pYAxis1">The left y-axis.</param>
+ /// <param name="pXAxis2">The top x-axis.</param>
+ /// <param name="pYAxis2">The right y-axis.</param>
+ public override void ApplyConstraint(
+ PhysicalAxis pXAxis1, PhysicalAxis pYAxis1,
+ PhysicalAxis pXAxis2, PhysicalAxis pYAxis2 )
+ {
+
+ if ( xAxisPosition_ != null )
+ {
+
+ if ((PlotSurface2D.XAxisPosition)xAxisPosition_ == PlotSurface2D.XAxisPosition.Bottom)
+ {
+ pXAxis1.PhysicalMin = new Point( pXAxis1.PhysicalMin.X, position_ );
+ pXAxis1.PhysicalMax = new Point( pXAxis1.PhysicalMax.X, position_ );
+
+ pYAxis1.PhysicalMin = new Point( pYAxis1.PhysicalMin.X, position_ );
+ pYAxis2.PhysicalMin = new Point( pYAxis2.PhysicalMin.X, position_ );
+ }
+ else
+ {
+ pXAxis2.PhysicalMin = new Point( pXAxis2.PhysicalMin.X, position_ );
+ pXAxis2.PhysicalMax = new Point( pXAxis2.PhysicalMax.X, position_ );
+
+ pYAxis1.PhysicalMax = new Point( pYAxis1.PhysicalMax.X, position_ );
+ pYAxis2.PhysicalMax = new Point( pYAxis2.PhysicalMax.X, position_ );
+ }
+
+ }
+ else if (yAxisPosition_ != null )
+ {
+
+ if ((PlotSurface2D.YAxisPosition)yAxisPosition_ == PlotSurface2D.YAxisPosition.Left)
+ {
+ pYAxis1.PhysicalMin = new Point( position_, pYAxis1.PhysicalMin.Y );
+ pYAxis1.PhysicalMax = new Point( position_, pYAxis1.PhysicalMax.Y );
+
+ pXAxis1.PhysicalMin = new Point( position_, pXAxis1.PhysicalMin.Y );
+ pXAxis2.PhysicalMin = new Point( position_, pXAxis2.PhysicalMin.Y );
+ }
+ else
+ {
+ pYAxis2.PhysicalMin = new Point( position_, pYAxis2.PhysicalMin.Y );
+ pYAxis2.PhysicalMax = new Point( position_, pYAxis2.PhysicalMax.Y );
+
+ pXAxis1.PhysicalMax = new Point( position_, pXAxis1.PhysicalMax.Y );
+ pXAxis2.PhysicalMax = new Point( position_, pXAxis2.PhysicalMax.Y );
+ }
+
+ }
+
+ }
+
+ }
+
+
+ /// <summary>
+ /// Defines an axes constraint that forces the world width and height pixel lengths
+ /// to be at the provided ratio. For example, an aspect ratio of 3:2 or
+ /// 1.5 indicates that there should be 1.5 times as many pixels per fixed
+ /// world length along the x direction than for the same world length along
+ /// the y direction. In other words, the world length of one pixel along
+ /// the x direction is 2/3rds that of the world length of one pixel height
+ /// in the y direction.
+ /// </summary>
+ /// <remarks>
+ /// This class will never increase the size of the plot bounding box. It
+ /// will always be made smaller.
+ /// </remarks>
+ public class AspectRatio : AxesConstraint
+ {
+ private double a_;
+ private object holdFixedX_ = null;
+ private object holdFixedY_ = null;
+
+ /// <summary>
+ /// Constructor.
+ /// </summary>
+ /// <param name="a">Aspect Ratio</param>
+ public AspectRatio( double a )
+ {
+ this.a_ = a;
+ }
+
+ /// <summary>
+ /// Constructor
+ /// </summary>
+ /// <param name="a">Aspect Ratio</param>
+ /// <param name="holdFixedX">
+ /// When adjusting the position of axes, the specified axis will never
+ /// be moved.
+ /// </param>
+ public AspectRatio( double a, PlotSurface2D.XAxisPosition holdFixedX )
+ {
+ this.a_ = a;
+ this.holdFixedX_ = holdFixedX;
+ }
+
+ /// <summary>
+ /// Constructor
+ /// </summary>
+ /// <param name="a">Aspect Ratio</param>
+ /// <param name="holdFixedY">
+ /// When adjusting the position of axes, the
+ /// specified axis will never be moved.
+ /// </param>
+ public AspectRatio( double a, PlotSurface2D.YAxisPosition holdFixedY )
+ {
+ this.a_ = a;
+ this.holdFixedY_ = holdFixedY;
+ }
+
+ /// <summary>
+ /// Constructor
+ /// </summary>
+ /// <param name="a">Aspect Ratio</param>
+ /// <param name="holdFixedX">When adjusting the position of axes, the specified axis will never be moved.</param>
+ /// <param name="holdFixedY">When adjusting the position of axes, the specified axis will never be moved.</param>
+ public AspectRatio(
+ double a,
+ PlotSurface2D.XAxisPosition holdFixedX,
+ PlotSurface2D.YAxisPosition holdFixedY )
+ {
+ this.a_ = a;
+ this.holdFixedX_ = holdFixedX;
+ this.holdFixedY_ = holdFixedY;
+ }
+
+ /// <summary>
+ /// Applies the constraint to the axes.
+ /// </summary>
+ /// <param name="pXAxis1">The bottom x-axis.</param>
+ /// <param name="pYAxis1">The left y-axis.</param>
+ /// <param name="pXAxis2">The top x-axis.</param>
+ /// <param name="pYAxis2">The right y-axis.</param>
+ public override void ApplyConstraint(
+ PhysicalAxis pXAxis1, PhysicalAxis pYAxis1,
+ PhysicalAxis pXAxis2, PhysicalAxis pYAxis2 )
+ {
+ double xWorldRange = Math.Abs( pXAxis1.Axis.WorldMax - pXAxis1.Axis.WorldMin );
+ double xPhysicalRange = Math.Abs( pXAxis1.PhysicalMax.X - pXAxis1.PhysicalMin.X );
+ double xDirPixelSize = xWorldRange / xPhysicalRange;
+
+ double yWorldRange = Math.Abs( pYAxis1.Axis.WorldMax - pYAxis1.Axis.WorldMin );
+ double yPhysicalRange = Math.Abs( pYAxis1.PhysicalMax.Y - pYAxis1.PhysicalMin.Y );
+ double yDirPixelSize = yWorldRange / yPhysicalRange;
+
+ double currentAspectRatio = yDirPixelSize / xDirPixelSize;
+
+ // we want to change the current aspect ratio to be the desired.
+ // to do this, we may only add the world pixel lengths.
+
+ if ( this.a_ > currentAspectRatio )
+ {
+ // want to increase aspect ratio. Therefore, want to add some amount
+ // to yDirPixelSize (numerator).
+
+ double toAdd = ( this.a_ - currentAspectRatio ) * xDirPixelSize;
+ int newHeight =
+ (int)( Math.Abs(pYAxis1.Axis.WorldMax - pYAxis1.Axis.WorldMin) / (yDirPixelSize + toAdd) );
+ int changeInHeight = (int)yPhysicalRange - newHeight;
+
+ int changeBottom = changeInHeight/2;
+ int changeTop = changeInHeight/2;
+ if (this.holdFixedX_ != null)
+ {
+ if ( (PlotSurface2D.XAxisPosition)this.holdFixedX_ == PlotSurface2D.XAxisPosition.Bottom )
+ {
+ changeBottom = 0;
+ changeTop = changeInHeight;
+ }
+ else
+ {
+ changeBottom = changeInHeight;
+ changeTop = 0;
+ }
+ }
+
+ pYAxis1.PhysicalMin = new Point( pYAxis1.PhysicalMin.X, pYAxis1.PhysicalMin.Y-changeBottom );
+ pYAxis1.PhysicalMax = new Point( pYAxis1.PhysicalMax.X, pYAxis1.PhysicalMax.Y+changeTop );
+ pYAxis2.PhysicalMin = new Point( pYAxis2.PhysicalMin.X, pYAxis2.PhysicalMin.Y-changeBottom );
+ pYAxis2.PhysicalMax = new Point( pYAxis2.PhysicalMax.X, pYAxis2.PhysicalMax.Y+changeTop );
+
+ pXAxis1.PhysicalMin = new Point( pXAxis1.PhysicalMin.X, pXAxis1.PhysicalMin.Y-changeBottom );
+ pXAxis1.PhysicalMax = new Point( pXAxis1.PhysicalMax.X, pXAxis1.PhysicalMax.Y-changeBottom );
+ pXAxis2.PhysicalMin = new Point( pXAxis2.PhysicalMin.X, pXAxis2.PhysicalMin.Y+changeTop );
+ pXAxis2.PhysicalMax = new Point( pXAxis2.PhysicalMax.X, pXAxis2.PhysicalMax.Y+changeTop );
+
+ }
+
+ else
+ {
+
+ // want to decrease aspect ratio. Therefore, want to add some amount
+ // to xDirPixelSize (denominator).
+
+ double toAdd = yDirPixelSize / this.a_ - xDirPixelSize;
+ int newWidth =
+ (int)( Math.Abs(pXAxis1.Axis.WorldMax - pXAxis1.Axis.WorldMin) / (xDirPixelSize + toAdd) );
+ int changeInWidth = (int)xPhysicalRange - newWidth;
+
+ int changeLeft = changeInWidth / 2;
+ int changeRight = changeInWidth / 2;
+ if (this.holdFixedY_ != null)
+ {
+ if ( (PlotSurface2D.YAxisPosition)this.holdFixedY_ == PlotSurface2D.YAxisPosition.Left )
+ {
+ changeLeft = 0;
+ changeRight = changeInWidth;
+ }
+ else
+ {
+ changeLeft = changeInWidth;
+ changeRight = 0;
+ }
+ }
+
+ pXAxis1.PhysicalMin = new Point( pXAxis1.PhysicalMin.X+changeLeft, pXAxis1.PhysicalMin.Y );
+ pXAxis1.PhysicalMax = new Point( pXAxis1.PhysicalMax.X-changeRight, pXAxis1.PhysicalMax.Y );
+ pXAxis2.PhysicalMin = new Point( pXAxis2.PhysicalMin.X+changeLeft, pXAxis2.PhysicalMin.Y );
+ pXAxis2.PhysicalMax = new Point( pXAxis2.PhysicalMax.X-changeRight, pXAxis2.PhysicalMax.Y );
+
+ pYAxis1.PhysicalMin = new Point( pYAxis1.PhysicalMin.X+changeLeft, pYAxis1.PhysicalMin.Y );
+ pYAxis1.PhysicalMax = new Point( pYAxis1.PhysicalMax.X+changeLeft, pYAxis1.PhysicalMax.Y );
+ pYAxis2.PhysicalMin = new Point( pYAxis2.PhysicalMin.X-changeRight, pYAxis2.PhysicalMin.Y );
+ pYAxis2.PhysicalMax = new Point( pYAxis2.PhysicalMax.X-changeRight, pYAxis2.PhysicalMax.Y );
+
+ }
+
+ }
+
+ }
+
+
+ /// <summary>
+ /// Applies the constraint to the axes. Must be overriden.
+ /// </summary>
+ /// <param name="pXAxis1">The bottom x-axis.</param>
+ /// <param name="pYAxis1">The left y-axis.</param>
+ /// <param name="pXAxis2">The top x-axis.</param>
+ /// <param name="pYAxis2">The right y-axis.</param>
+ public abstract void ApplyConstraint(
+ PhysicalAxis pXAxis1, PhysicalAxis pYAxis1,
+ PhysicalAxis pXAxis2, PhysicalAxis pYAxis2 );
+ }
+
+}
1,654 lib/Axis.cs
@@ -0,0 +1,1654 @@
+/*
+NPlot - A charting library for .NET
+
+Axis.cs
+Copyright (C) 2003
+Matt Howlett
+
+Redistribution and use of NPlot or parts there-of in source and
+binary forms, with or without modification, are permitted provided
+that the following conditions are met:
+
+1. Re-distributions in source form must retain at the head of each
+ source file the above copyright notice, this list of conditions
+ and the following disclaimer.
+
+2. Any product ("the product") that makes use NPlot or parts
+ there-of must either:
+
+ (a) allow any user of the product to obtain a complete machine-
+ readable copy of the corresponding source code for the
+ product and the version of NPlot used for a charge no more
+ than your cost of physically performing source distribution,
+ on a medium customarily used for software interchange, or:
+
+ (b) reproduce the following text in the documentation, about
+ box or other materials intended to be read by human users
+ of the product that is provided to every human user of the
+ product:
+
+ "This product includes software developed as
+ part of the NPlot library project available
+ from: http://www.nplot.com/"
+
+ The words "This product" may optionally be replace with
+ the actual name of the product.
+
+------------------------------------------------------------------------
+
+THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*/
+
+using System.Drawing.Drawing2D;
+using System.Drawing;
+using System;
+using System.Collections;
+
+namespace NPlot
+{
+
+ /// <summary>
+ /// Encapsulates functionality common to all axis classes. All specific
+ /// axis classes derive from Axis. Axis can be used as a concrete class
+ /// itself - it is an Axis without any embilishments [tick marks or tick
+ /// mark labels].<br></br><br></br>
+ /// This class encapsulates no physical information about where the axes
+ /// are drawn.
+ /// </summary>
+ public class Axis : System.ICloneable
+ {
+
+ /// <summary>
+ /// If true, tick marks will cross the axis, with their centre on the axis line.
+ /// If false, tick marks will be drawn as a line with origin starting on the axis line.
+ /// </summary>
+ public bool TicksCrossAxis
+ {
+ get
+ {
+ return ticksCrossAxis_;
+ }
+ set
+ {
+ ticksCrossAxis_ = value;
+ }
+ }
+ bool ticksCrossAxis_ = false;
+
+
+ /// <summary>
+ /// The maximum world extent of the axis. Note that it is sensical if
+ /// WorldMax is less than WorldMin - the axis would just be descending
+ /// not ascending. Currently Axes won't display properly if you do
+ /// this - use the Axis.Reversed property instead to achieve the same
+ /// result.
+ ///
+ /// Setting this raises the WorldMinChanged event and the WorldExtentsChanged event.
+ /// </summary>
+ public virtual double WorldMax
+ {
+ get
+ {
+ return worldMax_;
+ }
+ set
+ {
+ this.worldMax_ = value;
+ /*
+ if (this.WorldExtentsChanged != null)
+ this.WorldExtentsChanged(this, new WorldValueChangedArgs(worldMax_, WorldValueChangedArgs.MinMaxType.Max));
+ if (this.WorldMaxChanged != null)
+ this.WorldMaxChanged(this, new WorldValueChangedArgs(worldMax_, WorldValueChangedArgs.MinMaxType.Max));
+ */
+ }
+ }
+ private double worldMax_;
+
+
+ /// <summary>
+ /// The minumum world extent of the axis. Note that it is sensical if
+ /// WorldMax is less than WorldMin - the axis would just be descending
+ /// not ascending. Currently Axes won't display properly if you do
+ /// this - use the Axis.Reversed property instead to achieve the same
+ /// result.
+ ///
+ /// Setting this raises the WorldMinChanged event and the WorldExtentsChanged event.
+ /// </summary>
+ public virtual double WorldMin
+ {
+ get
+ {
+ return this.worldMin_;
+ }
+ set
+ {
+ this.worldMin_ = value;
+ /*
+ if (this.WorldExtentsChanged != null)
+ this.WorldExtentsChanged( this, new WorldValueChangedArgs( worldMin_, WorldValueChangedArgs.MinMaxType.Min) );
+ if (this.WorldMinChanged != null)
+ this.WorldMinChanged( this, new WorldValueChangedArgs(worldMin_, WorldValueChangedArgs.MinMaxType.Min) );
+ */
+ }
+ }
+ private double worldMin_;
+
+
+ /// <summary>
+ /// Length (in pixels) of a large tick. <b>Not</b> the distance
+ /// between large ticks. The length of the tick itself.
+ /// </summary>
+ public int LargeTickSize
+ {
+ get
+ {
+ return largeTickSize_;
+ }
+ set
+ {
+ largeTickSize_ = value;
+ }
+ }
+ private int largeTickSize_;
+
+
+ /// <summary>
+ /// Length (in pixels) of the small ticks.
+ /// </summary>
+ public int SmallTickSize
+ {
+ get
+ {
+ return smallTickSize_;
+ }
+ set
+ {
+ smallTickSize_ = value;
+ }
+ }
+ private int smallTickSize_;
+
+
+ /// <summary>
+ /// The Axis Label
+ /// </summary>
+ public string Label
+ {
+ get
+ {
+ return label_;
+ }
+ set
+ {
+ label_ = value;
+ }
+ }
+ private string label_;
+
+
+ /// <summary>
+ /// If true, text associated with tick marks will be drawn on the other side of the
+ /// axis line [next to the axis]. If false, tick mark text will be drawn at the end
+ /// of the tick mark [on the same of the axis line as the tick].
+ /// </summary>
+ public bool TickTextNextToAxis
+ {
+ get
+ {
+ return tickTextNextToAxis_;
+ }
+ set
+ {
+ tickTextNextToAxis_ = value;
+ }
+ }
+ bool tickTextNextToAxis_;
+
+
+ /// <summary>
+ /// If set to true, the axis is hidden. That is, the axis line, ticks, tick
+ /// labels and axis label will not be drawn.
+ /// </summary>
+ public bool Hidden
+ {
+ get
+ {
+ return hidden_;
+ }
+ set
+ {
+ hidden_ = value;
+ }
+ }
+ private bool hidden_;
+
+
+ /// <summary>
+ /// If set true, the axis will behave as though the WorldMin and WorldMax values
+ /// have been swapped.
+ /// </summary>
+ public bool Reversed
+ {
+ get
+ {
+ return reversed_;
+ }
+ set
+ {
+ reversed_ = value;
+ }
+ }
+ private bool reversed_;
+
+
+ /// <summary>
+ /// If true, no text will be drawn next to any axis tick marks.
+ /// </summary>
+ public bool HideTickText
+ {
+ get
+ {
+ return hideTickText_;
+ }
+ set
+ {
+ hideTickText_ = value;
+ }
+ }
+ private bool hideTickText_;
+
+
+ /// <summary>
+ /// This font is used for the drawing of text next to the axis tick marks.
+ /// </summary>
+ public Font TickTextFont
+ {
+ get
+ {
+ return this.tickTextFont_;
+ }
+ set
+ {
+ this.tickTextFont_ = value;
+ UpdateScale();
+ }
+ }
+ private Font tickTextFont_;
+ private Font tickTextFontScaled_;
+
+
+ /// <summary>
+ /// This font is used to draw the axis label.
+ /// </summary>
+ public Font LabelFont
+ {
+ get
+ {
+ return labelFont_;
+ }
+ set
+ {
+ labelFont_ = value;
+ UpdateScale();
+ }
+ }
+ private Font labelFont_;
+ private Font labelFontScaled_;
+
+
+ /// <summary>
+ /// Specifies the format used for drawing tick labels. See
+ /// StringBuilder.AppendFormat for a description of this
+ /// string.
+ /// </summary>
+ public string NumberFormat
+ {
+ get
+ {
+ return numberFormat_;
+ }
+ set
+ {
+ numberFormat_ = value;
+ }
+ }
+ private string numberFormat_;
+
+
+ /// <summary>
+ /// If LargeTickStep isn't specified, then this will be calculated
+ /// automatically. The calculated value will not be less than this
+ /// amount.
+ /// </summary>
+ public int MinPhysicalLargeTickStep
+ {
+ get
+ {
+ return minPhysicalLargeTickStep_;
+ }
+ set
+ {
+ minPhysicalLargeTickStep_ = value;
+ }
+ }
+ private int minPhysicalLargeTickStep_ = 30;
+
+
+ /// <summary>
+ /// The color of the pen used to draw the ticks and the axis line.
+ /// </summary>
+ public System.Drawing.Color AxisColor
+ {
+ get
+ {
+ return linePen_.Color;
+ }
+ set
+ {
+ linePen_ = new Pen( (Color)value );
+ }
+ }
+
+
+ /// <summary>
+ /// The pen used to draw the ticks and the axis line.
+ /// </summary>
+ public System.Drawing.Pen AxisPen
+ {
+ get
+ {
+ return linePen_;
+ }
+ set
+ {
+ linePen_ = value;
+ }
+ }
+ private System.Drawing.Pen linePen_;
+
+
+ /// <summary>
+ /// If true, automated tick placement will be independent of the physical
+ /// extent of the axis. Tick placement will look good for charts of typical
+ /// size (say physical dimensions of 640x480). If you want to produce the
+ /// same chart on two graphics surfaces of different sizes [eg Windows.Forms
+ /// control and printer], then you will want to set this property to true.
+ /// If false [default], the number of ticks and their placement will be
+ /// optimally calculated to look the best for the given axis extent. This
+ /// is very useful if you are creating a cart with particularly small or
+ /// large physical dimensions.
+ /// </summary>
+ public bool TicksIndependentOfPhysicalExtent
+ {
+ get
+ {
+ return ticksIndependentOfPhysicalExtent_;
+ }
+ set
+ {
+ ticksIndependentOfPhysicalExtent_ = value;
+ }
+ }
+ private bool ticksIndependentOfPhysicalExtent_ = false;
+
+
+ /// <summary>
+ /// If true label is flipped about the text center line parallel to the text.
+ /// </summary>
+ public bool FlipTicksLabel
+ {
+ get
+ {
+ return flipTicksLabel_;
+ }
+ set
+ {
+ flipTicksLabel_ = value;
+ }
+ }
+ private bool flipTicksLabel_ = false;
+
+
+ /// <summary>
+ /// Angle to draw ticks at (measured anti-clockwise from axis direction).
+ /// </summary>
+ public float TicksAngle
+ {
+ get
+ {
+ return ticksAngle_;
+ }
+ set
+ {
+ ticksAngle_ = value;
+ }
+ }
+ private float ticksAngle_ = (float)Math.PI / 2.0f;
+
+
+ /// <summary>
+ /// Angle to draw large tick labels at (clockwise from horizontal). Note:
+ /// this is currently only implemented well for the lower x-axis.
+ /// </summary>
+ public float TicksLabelAngle
+ {
+ get
+ {
+ return ticksLabelAngle_;
+ }
+ set
+ {
+ ticksLabelAngle_ = value;
+ }
+ }
+ private float ticksLabelAngle_ = 0.0f;
+
+
+ /// <summary>
+ /// The color of the brush used to draw the axis label.
+ /// </summary>
+ public Color LabelColor
+ {
+ set
+ {
+ labelBrush_ = new SolidBrush( value );
+ }
+ }
+
+
+ /// <summary>
+ /// The brush used to draw the axis label.
+ /// </summary>
+ public Brush LabelBrush
+ {
+ get
+ {
+ return labelBrush_;
+ }
+ set
+ {
+ labelBrush_ = value;
+ }
+ }
+ private Brush labelBrush_;
+
+
+ /// <summary>
+ /// The color of the brush used to draw the axis tick labels.
+ /// </summary>
+ public Color TickTextColor
+ {
+ set
+ {
+ tickTextBrush_ = new SolidBrush( value );
+ }
+ }
+
+
+ /// <summary>
+ /// The brush used to draw the tick text.
+ /// </summary>
+ public Brush TickTextBrush
+ {
+ get
+ {
+ return tickTextBrush_;
+ }
+ set
+ {
+ tickTextBrush_ = value;
+ }
+ }
+ private Brush tickTextBrush_;
+
+
+ /// <summary>
+ /// If true, label and tick text will be scaled to match size
+ /// of PlotSurface2D. If false, they won't be.
+ /// </summary>
+ /// <remarks>Could also be argued this belongs in PlotSurface2D</remarks>
+ public bool AutoScaleText
+ {
+ get
+ {
+ return autoScaleText_;
+ }
+ set
+ {
+ autoScaleText_ = value;
+ }
+ }
+ private bool autoScaleText_;
+
+
+ /// <summary>
+ /// If true, tick lengths will be scaled to match size
+ /// of PlotSurface2D. If false, they won't be.
+ /// </summary>
+ /// <remarks>Could also be argued this belongs in PlotSurface2D</remarks>
+ public bool AutoScaleTicks
+ {
+ get
+ {
+ return autoScaleTicks_;
+ }
+ set
+ {
+ autoScaleTicks_ = value;
+ }
+ }