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
This commit is contained in:
Коммит
c209bfbce5
|
@ -0,0 +1,4 @@
|
|||
2006-09-21 Carlos Ble <carlosble@shidix.com>
|
||||
|
||||
* updating the whole software to NPlot 0.9.9.2
|
||||
|
|
@ -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)
|
Двоичный файл не отображается.
|
@ -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.
|
Двоичный файл не отображается.
|
@ -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
|
||||
|
||||
}
|
||||
}
|
|
@ -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_;
|
||||
}
|
||||
}
|
|
@ -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")]
|
||||
|
|
@ -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 );
|
||||
}
|
||||
|
||||
}
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -0,0 +1,298 @@
|
|||
/*
|
||||
NPlot - A charting library for .NET
|
||||
|
||||
BarPlot.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>
|
||||
/// Draws
|
||||
/// </summary>
|
||||
public class BarPlot : BasePlot, IPlot, IDrawable
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// Default Constructor
|
||||
/// </summary>
|
||||
public BarPlot()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the data, or column name for the ordinate [y] axis.
|
||||
/// </summary>
|
||||
public object OrdinateDataTop
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.ordinateDataTop_;
|
||||
}
|
||||
set
|
||||
{
|
||||
this.ordinateDataTop_ = value;
|
||||
}
|
||||
}
|
||||
private object ordinateDataTop_ = null;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the data, or column name for the ordinate [y] axis.
|
||||
/// </summary>
|
||||
public object OrdinateDataBottom
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.ordinateDataBottom_;
|
||||
}
|
||||
set
|
||||
{
|
||||
this.ordinateDataBottom_ = value;
|
||||
}
|
||||
}
|
||||
private object ordinateDataBottom_ = null;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the data, or column name for the abscissa [x] axis.
|
||||
/// </summary>
|
||||
public object AbscissaData
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.abscissaData_;
|
||||
}
|
||||
set
|
||||
{
|
||||
this.abscissaData_ = value;
|
||||
}
|
||||
}
|
||||
private object abscissaData_ = null;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Draws the line plot on a GDI+ surface against the provided x and y axes.
|
||||
/// </summary>
|
||||
/// <param name="g">The GDI+ 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( Graphics g, PhysicalAxis xAxis, PhysicalAxis yAxis )
|
||||
{
|
||||
SequenceAdapter dataTop =
|
||||
new SequenceAdapter( this.DataSource, this.DataMember, this.OrdinateDataTop, this.AbscissaData );
|
||||
|
||||
SequenceAdapter dataBottom =
|
||||
new SequenceAdapter( this.DataSource, this.DataMember, this.OrdinateDataBottom, this.AbscissaData );
|
||||
|
||||
ITransform2D t = Transform2D.GetTransformer( xAxis, yAxis );
|
||||
|
||||
for (int i=0; i<dataTop.Count; ++i)
|
||||
{
|
||||
PointF physicalBottom = t.Transform( dataBottom[i] );
|
||||
PointF physicalTop = t.Transform( dataTop[i] );
|
||||
|
||||
if (physicalBottom != physicalTop)
|
||||
{
|
||||
Rectangle r = new Rectangle( (int)(physicalBottom.X - BarWidth/2), (int)physicalTop.Y,
|
||||
(int)BarWidth, (int)(physicalBottom.Y - physicalTop.Y) );
|
||||
|
||||
g.FillRectangle( this.rectangleBrush_.Get(r), r );
|
||||
g.DrawRectangle( borderPen_, r );
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns an x-axis that is suitable for drawing this plot.
|
||||
/// </summary>
|
||||
/// <returns>A suitable x-axis.</returns>
|
||||
public Axis SuggestXAxis()
|
||||
{
|
||||
SequenceAdapter dataBottom_ =
|
||||
new SequenceAdapter( this.DataSource, this.DataMember, this.OrdinateDataBottom, this.AbscissaData );
|
||||
|
||||
SequenceAdapter dataTop_ =
|
||||
new SequenceAdapter( this.DataSource, this.DataMember, this.OrdinateDataTop, this.AbscissaData );
|
||||
|
||||
Axis axis = dataTop_.SuggestXAxis();
|
||||
axis.LUB(dataBottom_.SuggestXAxis());
|
||||
return axis;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Returns a y-axis that is suitable for drawing this plot.
|
||||
/// </summary>
|
||||
/// <returns>A suitable y-axis.</returns>
|
||||
public Axis SuggestYAxis()
|
||||
{
|
||||
SequenceAdapter dataBottom_ =
|
||||
new SequenceAdapter( this.DataSource, this.DataMember, this.OrdinateDataBottom, this.AbscissaData );
|
||||
|
||||
SequenceAdapter dataTop_ =
|
||||
new SequenceAdapter( this.DataSource, this.DataMember, this.OrdinateDataTop, this.AbscissaData );
|
||||
|
||||
Axis axis = dataTop_.SuggestYAxis();
|
||||
axis.LUB(dataBottom_.SuggestYAxis());
|
||||
return axis;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Draws a representation of this plot in the legend.
|
||||
/// </summary>
|
||||
/// <param name="g">The graphics surface on which to draw.</param>
|
||||
/// <param name="startEnd">A rectangle specifying the bounds of the area in the legend set aside for drawing.</param>
|
||||
public virtual void DrawInLegend(Graphics g, Rectangle startEnd)
|
||||
{
|
||||
int smallerHeight = (int)(startEnd.Height * 0.5f);
|
||||
int heightToRemove = (int)(startEnd.Height * 0.5f);
|
||||
Rectangle newRectangle = new Rectangle( startEnd.Left, startEnd.Top + smallerHeight / 2, startEnd.Width, smallerHeight );
|
||||
g.FillRectangle( rectangleBrush_.Get( newRectangle ), newRectangle );
|
||||
g.DrawRectangle( borderPen_, newRectangle );
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The pen used to draw the plot
|
||||
/// </summary>
|
||||
public System.Drawing.Pen BorderPen
|
||||
{
|
||||
get
|
||||
{
|
||||
return borderPen_;
|
||||
}
|
||||
set
|
||||
{
|
||||
borderPen_ = value;
|
||||
}
|
||||
}
|
||||
private System.Drawing.Pen borderPen_ = new Pen(Color.Black);
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// The color of the pen used to draw lines in this plot.
|
||||
/// </summary>
|
||||
public System.Drawing.Color BorderColor
|
||||
{
|
||||
set
|
||||
{
|
||||
if (borderPen_ != null)
|
||||
{
|
||||
borderPen_.Color = value;
|
||||
}
|
||||
else
|
||||
{
|
||||
borderPen_ = new Pen(value);
|
||||
}
|
||||
}
|
||||
get
|
||||
{
|
||||
return borderPen_.Color;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Set/Get the fill brush
|
||||
/// </summary>
|
||||
public IRectangleBrush FillBrush
|
||||
{
|
||||
get
|
||||
{
|
||||
return rectangleBrush_;
|
||||
}
|
||||
set
|
||||
{
|
||||
rectangleBrush_ = value;
|
||||
}
|
||||
|
||||
}
|
||||
private IRectangleBrush rectangleBrush_ = new RectangleBrushes.Solid( Color.LightGray );
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Set/Get the width of the bar in physical pixels.
|
||||
/// </summary>
|
||||
public float BarWidth
|
||||
{
|
||||
get
|
||||
{
|
||||
return barWidth_;
|
||||
}
|
||||
set
|
||||
{
|
||||
barWidth_ = value;
|
||||
}
|
||||
}
|
||||
private float barWidth_ = 8;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Write data associated with the plot as text.
|
||||
/// </summary>
|
||||
/// <param name="sb">the string builder to write to.</param>
|
||||
/// <param name="region">Only write out data in this region if onlyInRegion is true.</param>
|
||||
/// <param name="onlyInRegion">If true, only data in region is written, else all data is written.</param>
|
||||
/// <remarks>TODO: not implemented.</remarks>
|
||||
public void WriteData( System.Text.StringBuilder sb, RectangleD region, bool onlyInRegion )
|
||||
{
|
||||
sb.Append( "Write data not implemented yet for BarPlot\r\n" );
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,138 @@
|
|||
/*
|
||||
NPlot - A charting library for .NET
|
||||
|
||||
BasePlot.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>
|
||||
/// Supplies implementation of basic legend handling properties, and
|
||||
/// basic data specifying properties which are used by all plots.
|
||||
/// </summary>
|
||||
/// <remarks>If C# had multiple inheritance, the heirachy would be different.</remarks>
|
||||
public abstract class BasePlot
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// A label to associate with the plot - used in the legend.
|
||||
/// </summary>
|
||||
public string Label
|
||||
{
|
||||
get
|
||||
{
|
||||
return label_;
|
||||
}
|
||||
set
|
||||
{
|
||||
this.label_ = value;
|
||||
}
|
||||
}
|
||||
|
||||
private string label_ = "";
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Whether or not to include an entry for this plot in the legend if it exists.
|
||||
/// </summary>
|
||||
public bool ShowInLegend
|
||||
{
|
||||
get
|
||||
{
|
||||
return showInLegend_;
|
||||
}
|
||||
set
|
||||
{
|
||||
this.showInLegend_ = value;
|
||||
}
|
||||
}
|
||||
private bool showInLegend_ = true;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the source containing a list of values used to populate the plot object.
|
||||
/// </summary>
|
||||
public object DataSource
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.dataSource_;
|
||||
}
|
||||
set
|
||||
{
|
||||
this.dataSource_ = value;
|
||||
}
|
||||
}
|
||||
private object dataSource_ = null;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the specific data member in a multimember data source to get data from.
|
||||
/// </summary>
|
||||
public string DataMember
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.dataMember_;
|
||||
}
|
||||
set
|
||||
{
|
||||
this.dataMember_ = value;
|
||||
}
|
||||
}
|
||||
private string dataMember_ = null;
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,96 @@
|
|||
// ******** experimental ********
|
||||
/*
|
||||
using System;
|
||||
|
||||
namespace NPlot
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// Functionality shared amoungst all 3D plots. TODO: Not implemented.
|
||||
/// </summary>
|
||||
public class BasePlot3D
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// Constructor.
|
||||
/// </summary>
|
||||
public BasePlot3D()
|
||||
{
|
||||
}
|
||||
|
||||
// DATA SPECIFIERS
|
||||
|
||||
// in first instance I think just have a DataSource, with
|
||||
// the only way of specifying points as an ArrayList of
|
||||
// point3s
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the source containing a list of values used to populate the plot object.
|
||||
/// </summary>
|
||||
public object DataSource
|
||||
{
|
||||
get
|
||||
{
|
||||
return dataSource_;
|
||||
}
|
||||
set
|
||||
{
|
||||
dataSource_ = value;
|
||||
}
|
||||
}
|
||||
object dataSource_ = null;
|
||||
|
||||
|
||||
need a SequenceAdapter3D to interpret all this crap -
|
||||
probably build on SequenceAdapter.
|
||||
|
||||
public string DataMember
|
||||
{
|
||||
get
|
||||
{
|
||||
return dataMember_;
|
||||
}
|
||||
set
|
||||
{
|
||||
dataMember_ = value;
|
||||
}
|
||||
}
|
||||
string dataMember_ = null;
|
||||
|
||||
|
||||
// these are needed for access to table columns.
|
||||
|
||||
public object XData
|
||||
{
|
||||
get
|
||||
{
|
||||
}
|
||||
set
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
public object YData
|
||||
{
|
||||
get
|
||||
{
|
||||
}
|
||||
set
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
public object ZData
|
||||
{
|
||||
get
|
||||
{
|
||||
}
|
||||
set
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
*/
|
|
@ -0,0 +1,69 @@
|
|||
using System;
|
||||
using System.Drawing;
|
||||
|
||||
namespace NPlot
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// supplies implementation of basic functionality for plots based on drawing
|
||||
/// lines [line, step and histogram].
|
||||
/// </summary>
|
||||
/// <remarks>If C# had multiple inheritance, the heirachy would be different. The way it is isn't very nice.</remarks>
|
||||
public class BaseSequenceLinePlot : BaseSequencePlot, ISequencePlot
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// Draws a representation of this plot in the legend.
|
||||
/// </summary>
|
||||
/// <param name="g">The graphics surface on which to draw.</param>
|
||||
/// <param name="startEnd">A rectangle specifying the bounds of the area in the legend set aside for drawing.</param>
|
||||
public virtual void DrawInLegend( Graphics g, Rectangle startEnd )
|
||||
{
|
||||
g.DrawLine( pen_, startEnd.Left, (startEnd.Top + startEnd.Bottom)/2,
|
||||
startEnd.Right, (startEnd.Top + startEnd.Bottom)/2 );
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// The pen used to draw the plot
|
||||
/// </summary>
|
||||
public System.Drawing.Pen Pen
|
||||
{
|
||||
get
|
||||
{
|
||||
return pen_;
|
||||
}
|
||||
set
|
||||
{
|
||||
pen_ = value;
|
||||
}
|
||||
}
|
||||
private System.Drawing.Pen pen_ = new Pen( Color.Black );
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// The color of the pen used to draw lines in this plot.
|
||||
/// </summary>
|
||||
public System.Drawing.Color Color
|
||||
{
|
||||
set
|
||||
{
|
||||
if (pen_ != null)
|
||||
{
|
||||
pen_.Color = value;
|
||||
}
|
||||
else
|
||||
{
|
||||
pen_ = new Pen( value );
|
||||
}
|
||||
}
|
||||
get
|
||||
{
|
||||
return pen_.Color;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,118 @@
|
|||
/*
|
||||
NPlot - A charting library for .NET
|
||||
|
||||
BaseSequencePlot.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;
|
||||
|
||||
namespace NPlot
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// Adds additional basic functionality to BasePlot that is common to all
|
||||
/// plots that implement the ISequencePlot interface.
|
||||
/// </summary>
|
||||
/// <remarks>If C# had multiple inheritance, the heirachy would be different. The way it is isn't very nice.</remarks>
|
||||
public class BaseSequencePlot : BasePlot, ISequencePlot
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the data, or column name for the ordinate [y] axis.
|
||||
/// </summary>
|
||||
public object OrdinateData
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.ordinateData_;
|
||||
}
|
||||
set
|
||||
{
|
||||
this.ordinateData_ = value;
|
||||
}
|
||||
}
|
||||
private object ordinateData_ = null;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the data, or column name for the abscissa [x] axis.
|
||||
/// </summary>
|
||||
public object AbscissaData
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.abscissaData_;
|
||||
}
|
||||
set
|
||||
{
|
||||
this.abscissaData_ = value;
|
||||
}
|
||||
}
|
||||
private object abscissaData_ = null;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Writes text data of the plot object to the supplied string builder. It is
|
||||
/// possible to specify that only data in the specified range be written.
|
||||
/// </summary>
|
||||
/// <param name="sb">the StringBuilder object to write to.</param>
|
||||
/// <param name="region">a region used if onlyInRegion is true.</param>
|
||||
/// <param name="onlyInRegion">If true, only data enclosed in the provided region will be written.</param>
|
||||
public void WriteData( System.Text.StringBuilder sb, RectangleD region, bool onlyInRegion )
|
||||
{
|
||||
SequenceAdapter data_ =
|
||||
new SequenceAdapter( this.DataSource, this.DataMember, this.OrdinateData, this.AbscissaData );
|
||||
|
||||
sb.Append( "Label: " );
|
||||
sb.Append( this.Label );
|
||||
sb.Append( "\r\n" );
|
||||
data_.WriteData( sb, region, onlyInRegion );
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,541 @@
|
|||
/*
|
||||
NPlot - A charting library for .NET
|
||||
|
||||
Bitmap.PlotSurface2D.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;
|
||||
using System.Collections;
|
||||
|
||||
namespace NPlot
|
||||
{
|
||||
|
||||
namespace Bitmap
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// Wrapper around NPlot.PlotSurface2D that provides extra functionality
|
||||
/// specific to drawing to Bitmaps.
|
||||
/// </summary>
|
||||
public class PlotSurface2D: IPlotSurface2D
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// Constructor.
|
||||
/// </summary>
|
||||
/// <param name="width">width of the bitmap.</param>
|
||||
/// <param name="height">height of the bitmap.</param>
|
||||
public PlotSurface2D( int width, int height )
|
||||
{
|
||||
b_ = new System.Drawing.Bitmap( width, height );
|
||||
ps_ = new NPlot.PlotSurface2D();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructor.
|
||||
/// </summary>
|
||||
/// <param name="b">The Bitmap where the plot is to be rendered.</param>
|
||||
public PlotSurface2D( System.Drawing.Bitmap b )
|
||||
{
|
||||
b_ = b;
|
||||
ps_ = new NPlot.PlotSurface2D();
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Renders the plot.
|
||||
/// </summary>
|
||||
/// <param name="g">The graphics surface.</param>
|
||||
/// <param name="bounds">The rectangle storing the bounds for rendering.</param>
|
||||
public void Draw( Graphics g, Rectangle bounds )
|
||||
{
|
||||
ps_.Draw( g, bounds );
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Clears the plot.
|
||||
/// </summary>
|
||||
public void Clear()
|
||||
{
|
||||
ps_.Clear();
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Adds a drawable object to the plot surface. If the object is an IPlot,
|
||||
/// the PlotSurface2D axes will also be updated.
|
||||
/// </summary>
|
||||
/// <param name="p">The IDrawable object to add to the plot surface.</param>
|
||||
public void Add( IDrawable p )
|
||||
{
|
||||
ps_.Add( p );
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Adds a drawable object to the plot surface against the specified axes. If
|
||||
/// the object is an IPlot, the PlotSurface2D axes will also be updated.
|
||||
/// </summary>
|
||||
/// <param name="p">the IDrawable object to add to the plot surface</param>
|
||||
/// <param name="xp">the x-axis to add the plot against.</param>
|
||||
/// <param name="yp">the y-axis to add the plot against.</param>
|
||||
public void Add( IDrawable p, NPlot.PlotSurface2D.XAxisPosition xp, NPlot.PlotSurface2D.YAxisPosition yp )
|
||||
{
|
||||
ps_.Add( p, xp, yp );
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds a drawable object to the plot surface. If the object is an IPlot,
|
||||
/// the PlotSurface2D axes will also be updated.
|
||||
/// </summary>
|
||||
/// <param name="p">The IDrawable object to add to the plot surface.</param>
|
||||
/// <param name="zOrder">The z-ordering when drawing (objects with lower numbers are drawn first)</param>
|
||||
public void Add( IDrawable p, int zOrder )
|
||||
{
|
||||
ps_.Add( p, zOrder );
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Adds a drawable object to the plot surface against the specified axes. If
|
||||
/// the object is an IPlot, the PlotSurface2D axes will also be updated.
|
||||
/// </summary>
|
||||
/// <param name="p">the IDrawable object to add to the plot surface</param>
|
||||
/// <param name="xp">the x-axis to add the plot against.</param>
|
||||
/// <param name="yp">the y-axis to add the plot against.</param>
|
||||
/// <param name="zOrder">The z-ordering when drawing (objects with lower numbers are drawn first)</param>
|
||||
public void Add( IDrawable p, NPlot.PlotSurface2D.XAxisPosition xp,
|
||||
NPlot.PlotSurface2D.YAxisPosition yp, int zOrder )
|
||||
{
|
||||
ps_.Add( p, xp, yp , zOrder);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The plot surface title.
|
||||
/// </summary>
|
||||
public string Title
|
||||
{
|
||||
get
|
||||
{
|
||||
return ps_.Title;
|
||||
}
|
||||
set
|
||||
{
|
||||
ps_.Title = value;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// The plot title font.
|
||||
/// </summary>
|
||||
public Font TitleFont
|
||||
{
|
||||
get
|
||||
{
|
||||
return ps_.TitleFont;
|
||||
}
|
||||
set
|
||||
{
|
||||
ps_.TitleFont = value;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// The distance in pixels to leave between of the edge of the bounding rectangle
|
||||
/// supplied to the Draw method, and the markings that make up the plot.
|
||||
/// </summary>
|
||||
public int Padding
|
||||
{
|
||||
get
|
||||
{
|
||||
return ps_.Padding;
|
||||
}
|
||||
set
|
||||
{
|
||||
ps_.Padding = value;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// The bottom abscissa axis.
|
||||
/// </summary>
|
||||
public Axis XAxis1
|
||||
{
|
||||
get
|
||||
{
|
||||
return ps_.XAxis1;
|
||||
}
|
||||
set
|
||||
{
|
||||
ps_.XAxis1 = value;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// The left ordinate axis.
|
||||
/// </summary>
|
||||
public Axis YAxis1
|
||||
{
|
||||
get
|
||||
{
|
||||
return ps_.YAxis1;
|
||||
}
|
||||
set
|
||||
{
|
||||
ps_.YAxis1 = value;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// The top abscissa axis.
|
||||
/// </summary>
|
||||
public Axis XAxis2
|
||||
{
|
||||
get
|
||||
{
|
||||
return ps_.XAxis2;
|
||||
}
|
||||
set
|
||||
{
|
||||
ps_.XAxis2 = value;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// The right ordinate axis.
|
||||
/// </summary>
|
||||
public Axis YAxis2
|
||||
{
|
||||
get
|
||||
{
|
||||
return ps_.YAxis2;
|
||||
}
|
||||
set
|
||||
{
|
||||
ps_.YAxis2 = value;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Gets or Sets the legend to use with this plot surface.
|
||||
/// </summary>
|
||||
public NPlot.Legend Legend
|
||||
{
|
||||
get
|
||||
{
|
||||
return ps_.Legend;
|
||||
}
|
||||
set
|
||||
{
|
||||
ps_.Legend = value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or Sets the legend z-order.
|
||||
/// </summary>
|
||||
public int LegendZOrder
|
||||
{
|
||||
get
|
||||
{
|
||||
return ps_.LegendZOrder;
|
||||
}
|
||||
set
|
||||
{
|
||||
ps_.LegendZOrder = value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// A color used to paint the plot background. Mutually exclusive with PlotBackImage and PlotBackBrush
|
||||
/// </summary>
|
||||
public System.Drawing.Color PlotBackColor
|
||||
{
|
||||
set
|
||||
{
|
||||
ps_.PlotBackColor = value;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// An imaged used to paint the plot background. Mutually exclusive with PlotBackColor and PlotBackBrush
|
||||
/// </summary>
|
||||
public System.Drawing.Bitmap PlotBackImage
|
||||
{
|
||||
set
|
||||
{
|
||||
ps_.PlotBackImage = value;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// A Rectangle brush used to paint the plot background. Mutually exclusive with PlotBackColor and PlotBackBrush
|
||||
/// </summary>
|
||||
public IRectangleBrush PlotBackBrush
|
||||
{
|
||||
set
|
||||
{
|
||||
ps_.PlotBackBrush = value;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Smoothing mode to use when drawing plots.
|
||||
/// </summary>
|
||||
public System.Drawing.Drawing2D.SmoothingMode SmoothingMode
|
||||
{
|
||||
get
|
||||
{
|
||||
return ps_.SmoothingMode;
|
||||
}
|
||||
set
|
||||
{
|
||||
ps_.SmoothingMode = value;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// The bitmap width
|
||||
/// </summary>
|
||||
public int Width
|
||||
{
|
||||
get
|
||||
{
|
||||
return b_.Width;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// The bitmap height
|
||||
/// </summary>
|
||||
public int Height
|
||||
{
|
||||
get
|
||||
{
|
||||
return b_.Height;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Renders the bitmap to a MemoryStream. Useful for returning the bitmap from
|
||||
/// an ASP.NET page.
|
||||
/// </summary>
|
||||
/// <returns>The MemoryStream object.</returns>
|
||||
public System.IO.MemoryStream ToStream( System.Drawing.Imaging.ImageFormat imageFormat )
|
||||
{
|
||||
System.IO.MemoryStream stream = new System.IO.MemoryStream();
|
||||
ps_.Draw(Graphics.FromImage(this.Bitmap),new System.Drawing.Rectangle(0,0,b_.Width,b_.Height));
|
||||
this.Bitmap.Save(stream, imageFormat);
|
||||
return stream;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// The bitmap to use as the drawing surface.
|
||||
/// </summary>
|
||||
public System.Drawing.Bitmap Bitmap
|
||||
{
|
||||
get
|
||||
{
|
||||
return b_;
|
||||
}
|
||||
set
|
||||
{
|
||||
b_ = value;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// The bitmap background color outside the bounds of the plot surface.
|
||||
/// </summary>
|
||||
public Color BackColor
|
||||
{
|
||||
set
|
||||
{
|
||||
backColor_ = value;
|
||||
}
|
||||
}
|
||||
object backColor_ = null;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Refreshes (draws) the plot.
|
||||
/// </summary>
|
||||
public void Refresh()
|
||||
{
|
||||
if (this.backColor_!=null)
|
||||
{
|
||||
Graphics g = Graphics.FromImage( b_ );
|
||||
g.FillRectangle( (new Pen( (Color)this.backColor_)).Brush,0,0,b_.Width,b_.Height );
|
||||
}
|
||||
ps_.Draw( Graphics.FromImage(b_), new System.Drawing.Rectangle(0,0,b_.Width,b_.Height) );
|
||||
}
|
||||
|
||||
|
||||
private NPlot.PlotSurface2D ps_;
|
||||
private System.Drawing.Bitmap b_;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Add an axis constraint to the plot surface. Axis constraints can
|
||||
/// specify relative world-pixel scalings, absolute axis positions etc.
|
||||
/// </summary>
|
||||
/// <param name="c">The axis constraint to add.</param>
|
||||
public void AddAxesConstraint( AxesConstraint c )
|
||||
{
|
||||
ps_.AddAxesConstraint( c );
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Whether or not the title will be scaled according to size of the plot
|
||||
/// surface.
|
||||
/// </summary>
|
||||
public bool AutoScaleTitle
|
||||
{
|
||||
get
|
||||
{
|
||||
return ps_.AutoScaleTitle;
|
||||
}
|
||||
set
|
||||
{
|
||||
ps_.AutoScaleTitle = value;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// When plots are added to the plot surface, the axes they are attached to
|
||||
/// are immediately modified to reflect data of the plot. If
|
||||
/// AutoScaleAutoGeneratedAxes is true when a plot is added, the axes will
|
||||
/// be turned in to auto scaling ones if they are not already [tick marks,
|
||||
/// tick text and label size scaled to size of plot surface]. If false,
|
||||
/// axes will not be autoscaling.
|
||||
/// </summary>
|
||||
public bool AutoScaleAutoGeneratedAxes
|
||||
{
|
||||
get
|
||||
{
|
||||
return ps_.AutoScaleAutoGeneratedAxes;
|
||||
}
|
||||
set
|
||||
{
|
||||
ps_.AutoScaleAutoGeneratedAxes = value;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Sets the title to be drawn using a solid brush of this color.
|
||||
/// </summary>
|
||||
public Color TitleColor
|
||||
{
|
||||
set
|
||||
{
|
||||
ps_.TitleColor = value;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// The brush used for drawing the title.
|
||||
/// </summary>
|
||||
public Brush TitleBrush
|
||||
{
|
||||
get
|
||||
{
|
||||
return ps_.TitleBrush;
|
||||
}
|
||||
set
|
||||
{
|
||||
ps_.TitleBrush = value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Remove a drawable object from the plot surface.
|
||||
/// </summary>
|
||||
/// <param name="p">the drawable to remove</param>
|
||||
/// <param name="updateAxes">whether or not to update the axes after removing the idrawable.</param>
|
||||
public void Remove(IDrawable p, bool updateAxes)
|
||||
{
|
||||
ps_.Remove(p, updateAxes);
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Gets an array list containing all drawables currently added to the PlotSurface2D.
|
||||
/// </summary>
|
||||
public ArrayList Drawables
|
||||
{
|
||||
get
|
||||
{
|
||||
return ps_.Drawables;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,72 @@
|
|||
using System;
|
||||
|
||||
/*
|
||||
namespace NPlot
|
||||
{
|
||||
/// <summary>
|
||||
/// Summary description for BubblePlot.
|
||||
/// </summary>
|
||||
public class BubblePlot : BasePlot, IPlot
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// Constructor
|
||||
/// </summary>
|
||||
public BubblePlot()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
public void DrawInLegend(System.Drawing.Graphics g, System.Drawing.Rectangle startEnd)
|
||||
{
|
||||
// TODO: Add BubblePlot.DrawInLegend implementation
|
||||
}
|
||||
|
||||
public string Label
|
||||
{
|
||||
get
|
||||
{
|
||||
// TODO: Add BubblePlot.Label getter implementation
|
||||
return null;
|
||||
}
|
||||
set
|
||||
{
|
||||
// TODO: Add BubblePlot.Label setter implementation
|
||||
}
|
||||
}
|
||||
|
||||
public bool ShowInLegend
|
||||
{
|
||||
get
|
||||
{
|
||||
// TODO: Add BubblePlot.ShowInLegend getter implementation
|
||||
return false;
|
||||
}
|
||||
set
|
||||
{
|
||||
// TODO: Add BubblePlot.ShowInLegend setter implementation
|
||||
}
|
||||
}
|
||||
|
||||
public Axis SuggestXAxis()
|
||||
{
|
||||
// TODO: Add BubblePlot.SuggestXAxis implementation
|
||||
return null;
|
||||
}
|
||||
|
||||
public Axis SuggestYAxis()
|
||||
{
|
||||
// TODO: Add BubblePlot.SuggestYAxis implementation
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
public void Draw(System.Drawing.Graphics g, PhysicalAxis xAxis, PhysicalAxis yAxis)
|
||||
{
|
||||
// TODO: Add BubblePlot.Draw implementation
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
*/
|
|
@ -0,0 +1,891 @@
|
|||
/*
|
||||
NPlot - A charting library for .NET
|
||||
|
||||
CandlePlot.cs
|
||||
Copyright (C) 2003
|
||||
Matt Howlett
|
||||
Pawel Konieczny
|
||||
|
||||
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.Data;
|
||||
|
||||
namespace NPlot
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// Encapsulates open, low, high and close values useful for specifying financial data
|
||||
/// over a time period, together with a [single] x-value indicating the time [period] the
|
||||
/// data corresponds to.
|
||||
/// </summary>
|
||||
public class PointOLHC
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// Constructor
|
||||
/// </summary>
|
||||
/// <param name="x">value representing the time period that the financial values refer to</param>
|
||||
/// <param name="open">The value at open of time period.</param>
|
||||
/// <param name="low">The low value over the time period</param>
|
||||
/// <param name="high">The high value over the time period.</param>
|
||||
/// <param name="close">The value at close of time period.</param>
|
||||
public PointOLHC( double x, double open, double low, double high, double close )
|
||||
{
|
||||
this.x_ = x;
|
||||
this.open_ = open;
|
||||
this.close_ = close;
|
||||
this.low_ = low;
|
||||
this.high_ = high;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// value representing the time period that the financial values apply to.
|
||||
/// </summary>
|
||||
public double X
|
||||
{
|
||||
get
|
||||
{
|
||||
return x_;
|
||||
}
|
||||
set
|
||||
{
|
||||
this.x_ = value;
|
||||
}
|
||||
}
|
||||
private double x_;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// The value at open of time period.
|
||||
/// </summary>
|
||||
public double Open
|
||||
{
|
||||
get
|
||||
{
|
||||
return open_;
|
||||
}
|
||||
set
|
||||
{
|
||||
open_ = value;
|
||||
}
|
||||
}
|
||||
private double open_;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// The value at close of time period.
|
||||
/// </summary>
|
||||
public double Close
|
||||
{
|
||||
get
|
||||
{
|
||||
return close_;
|
||||
}
|
||||
set
|
||||
{
|
||||
close_ = value;
|
||||
}
|
||||
}
|
||||
private double close_;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Low value of the time period.
|
||||
/// </summary>
|
||||
public double Low
|
||||
{
|
||||
get
|
||||
{
|
||||
return low_;
|
||||
}
|
||||
set
|
||||
{
|
||||
low_ = value;
|
||||
}
|
||||
}
|
||||
private double low_;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// High value of the time period.
|
||||
/// </summary>
|
||||
public double High
|
||||
{
|
||||
get
|
||||
{
|
||||
return high_;
|
||||
}
|
||||
set
|
||||
{
|
||||
high_ = value;
|
||||
}
|
||||
}
|
||||
private double high_;
|
||||
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Encapsulates functionality for drawing finacial candle charts.
|
||||
/// </summary>
|
||||
public class CandlePlot : BasePlot, IPlot
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public abstract class CandleStyle
|
||||
{
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="d"></param>
|
||||
/// <returns></returns>
|
||||
public abstract CandleStyle Create(CandleDataAdapter d);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public class Stick : CandleStyle
|
||||
{
|
||||
private Stick() { }
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="d"></param>
|
||||
/// <returns></returns>
|
||||
public override CandleStyle Create(CandleDataAdapter d)
|
||||
{
|
||||
return new Stick();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// This class is responsible for interpreting the various ways you can
|
||||
/// specify data to CandlePlot objects
|
||||
/// </summary>
|
||||
public class CandleDataAdapter
|
||||
{
|
||||
private object openData_;
|
||||
private object lowData_;
|
||||
private object highData_;
|
||||
private object closeData_;
|
||||
private object abscissaData_;
|
||||
|
||||
private object dataSource_;
|
||||
private string dataMember_;
|
||||
DataRowCollection rows_ = null;
|
||||
|
||||
// speed optimizations if data is double.
|
||||
private double[] openDataArray_;
|
||||
private double[] lowDataArray_;
|
||||
private double[] highDataArray_;
|
||||
private double[] closeDataArray_;
|
||||
private double[] abscissaDataArray_;
|
||||
private bool useDoublesArrays_;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Constructor
|
||||
/// </summary>
|
||||
/// <param name="dataSource"></param>
|
||||
/// <param name="dataMember"></param>
|
||||
/// <param name="abscissaData"></param>
|
||||
/// <param name="openData"></param>
|
||||
/// <param name="lowData"></param>
|
||||
/// <param name="highData"></param>
|
||||
/// <param name="closeData"></param>
|
||||
public CandleDataAdapter(
|
||||
object dataSource, string dataMember, object abscissaData,
|
||||
object openData, object lowData, object highData, object closeData )
|
||||
{
|
||||
this.openData_ = openData;
|
||||
this.lowData_ = lowData;
|
||||
this.highData_ = highData;
|
||||
this.closeData_ = closeData;
|
||||
this.abscissaData_ = abscissaData;
|
||||
|
||||
this.dataSource_ = dataSource;
|
||||
this.dataMember_ = dataMember;
|
||||
|
||||
if (dataSource_ != null)
|
||||
{
|
||||
if ( dataSource_ is DataSet )
|
||||
{
|
||||
if (dataMember_ != null)
|
||||
{
|
||||
rows_ = ((DataTable)((DataSet)dataSource_).Tables[dataMember_]).Rows;
|
||||
}
|
||||
else
|
||||
{
|
||||
rows_ = ((DataTable)((DataSet)dataSource_).Tables[0]).Rows;
|
||||
}
|
||||
}
|
||||
|
||||
else if (dataSource_ is DataTable )
|
||||
{
|
||||
rows_ = ((DataTable)dataSource_).Rows;
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
throw new NPlotException ( "not implemented yet" );
|
||||
}
|
||||
}
|
||||
|
||||
openDataArray_ = openData_ as System.Double[];
|
||||
lowDataArray_ = lowData_ as System.Double[];
|
||||
highDataArray_ = highData_ as System.Double[];
|
||||
closeDataArray_ = closeData_ as System.Double[];
|
||||
abscissaDataArray_ = abscissaData_ as System.Double[];
|
||||
useDoublesArrays_ = (
|
||||
openDataArray_ != null &&
|
||||
lowDataArray_ != null &&
|
||||
highDataArray_ != null &&
|
||||
lowDataArray_ != null &&
|
||||
abscissaDataArray_ != null
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Gets the ith point in the candle adapter
|
||||
/// </summary>
|
||||
/// <param name="i">index of datapoint to get</param>
|
||||
/// <returns>the datapoint.</returns>
|
||||
public PointOLHC this[int i]
|
||||
{
|
||||
get
|
||||
{
|
||||
|
||||
// try a fast track first
|
||||
if (useDoublesArrays_)
|
||||
{
|
||||
return new PointOLHC(
|
||||
abscissaDataArray_[i],
|
||||
openDataArray_[i],
|
||||
lowDataArray_[i],
|
||||
highDataArray_[i],
|
||||
closeDataArray_[i]);
|
||||
}
|
||||
|
||||
// is the data coming from a data source?
|
||||
else if (rows_ != null)
|
||||
{
|
||||
double x = Utils.ToDouble(((DataRow)(rows_[i]))[(string)abscissaData_]);
|
||||
double open = Utils.ToDouble(((DataRow)(rows_[i]))[(string)openData_]);
|
||||
double low = Utils.ToDouble(((DataRow)(rows_[i]))[(string)lowData_]);
|
||||
double high = Utils.ToDouble(((DataRow)(rows_[i]))[(string)highData_]);
|
||||
double close = Utils.ToDouble(((DataRow)(rows_[i]))[(string)closeData_]);
|
||||
|
||||
return new PointOLHC(x, open, low, high, close);
|
||||
}
|
||||
|
||||
// the data is coming from individual arrays.
|
||||
else if (abscissaData_ is Array && openData_ is Array && lowData_ is Array && highData_ is Array && closeData_ is Array)
|
||||
{
|
||||
double x = Utils.ToDouble(((Array)abscissaData_).GetValue(i));
|
||||
double open = Utils.ToDouble(((Array)openData_).GetValue(i));
|
||||
double low = Utils.ToDouble(((Array)lowData_).GetValue(i));
|
||||
double high = Utils.ToDouble(((Array)highData_).GetValue(i));
|
||||
double close = Utils.ToDouble(((Array)closeData_).GetValue(i));
|
||||
|
||||
return new PointOLHC(x, open, low, high, close);
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
throw new NPlotException("not implemented yet");
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// The number of datapoints available via the candle adapter.
|
||||
/// </summary>
|
||||
/// <value>the number of datapoints available.</value>
|
||||
public int Count
|
||||
{
|
||||
get
|
||||
{
|
||||
// this is inefficient [could set up delegates in constructor].
|
||||
|
||||
if (useDoublesArrays_)
|
||||
{
|
||||
return openDataArray_.Length;
|
||||
}
|
||||
|
||||
if (openData_ == null)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (rows_ != null)
|
||||
{
|
||||
return rows_.Count;
|
||||
}
|
||||
|
||||
if (openData_ is Array)
|
||||
{
|
||||
int size = ((Array)openData_).Length;
|
||||
if (size != ((Array)closeData_).Length)
|
||||
throw new NPlotException("open and close arrays are not of same length");
|
||||
if (size != ((Array)lowData_).Length)
|
||||
throw new NPlotException("open and close arrays are not of same length");
|
||||
if (size != ((Array)highData_).Length)
|
||||
throw new NPlotException("open and close arrays are not of same length");
|
||||
return size;
|
||||
}
|
||||
|
||||
throw new NPlotException( "data not in correct format" );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Returns an x-axis that is suitable for drawing the data.
|
||||
/// </summary>
|
||||
/// <returns>A suitable x-axis.</returns>
|
||||
public Axis SuggestXAxis()
|
||||
{
|
||||
double min;
|
||||
double max;
|
||||
double minStep = 0.0;
|
||||
|
||||
if (this.rows_ == null)
|
||||
{
|
||||
Utils.ArrayMinMax((System.Collections.IList)this.abscissaData_, out min, out max);
|
||||
|
||||
if (((System.Collections.IList)abscissaData_).Count > 1)
|
||||
{
|
||||
double first = Utils.ToDouble(((Array)abscissaData_).GetValue(0));
|
||||
double second = Utils.ToDouble(((Array)abscissaData_).GetValue(1));
|
||||
minStep = Math.Abs(second - first);
|
||||
}
|
||||
if (((System.Collections.IList)abscissaData_).Count > 2)
|
||||
{
|
||||
double first = Utils.ToDouble(((Array)abscissaData_).GetValue(1));
|
||||
double second = Utils.ToDouble(((Array)abscissaData_).GetValue(2));
|
||||
if (Math.Abs(second - first) < minStep)
|
||||
minStep = Math.Abs(second - first);
|
||||
}
|
||||
if (((System.Collections.IList)abscissaData_)[0] is DateTime)
|
||||
{
|
||||
return new DateTimeAxis(min - minStep / 2.0, max + minStep / 2.0);
|
||||
}
|
||||
else
|
||||
{
|
||||
return new LinearAxis(min - minStep / 2.0, max + minStep / 2.0);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
Utils.RowArrayMinMax(this.rows_, out min, out max, (string)this.abscissaData_);
|
||||
|
||||
if (rows_.Count > 1)
|
||||
{
|
||||
double first = Utils.ToDouble(rows_[0][(string)abscissaData_]);
|
||||
double second = Utils.ToDouble(rows_[1][(string)abscissaData_]);
|
||||
minStep = Math.Abs(second - first);
|
||||
}
|
||||
if (rows_.Count > 2)
|
||||
{
|
||||
double first = Utils.ToDouble(rows_[1][(string)abscissaData_]);
|
||||
double second = Utils.ToDouble(rows_[2][(string)abscissaData_]);
|
||||
if (Math.Abs(second - first) < minStep)
|
||||
minStep = Math.Abs(second - first);
|
||||
}
|
||||
|
||||
if ((rows_[0])[(string)abscissaData_] is DateTime)
|
||||
{
|
||||
return new DateTimeAxis(min - minStep / 2.0, max + minStep / 2.0);
|
||||
}
|
||||
else
|
||||
{
|
||||
return new LinearAxis(min - minStep / 2.0, max + minStep / 2.0);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Returns a y-axis that is suitable for drawing the data.
|
||||
/// </summary>
|
||||
/// <returns>A suitable y-axis.</returns>
|
||||
public Axis SuggestYAxis()
|
||||
{
|
||||
|
||||
double min_l;
|
||||
double max_l;
|
||||
double min_h;
|
||||
double max_h;
|
||||
|
||||
if (this.rows_ == null)
|
||||
{
|
||||
Utils.ArrayMinMax((System.Collections.IList)lowData_, out min_l, out max_l);
|
||||
Utils.ArrayMinMax((System.Collections.IList)highData_, out min_h, out max_h);
|
||||
}
|
||||
else
|
||||
{
|
||||
Utils.RowArrayMinMax(this.rows_, out min_l, out max_l, (string)this.lowData_);
|
||||
Utils.RowArrayMinMax(this.rows_, out min_h, out max_h, (string)this.highData_);
|
||||
}
|
||||
|
||||
Axis a = new LinearAxis( min_l, max_h );
|
||||
a.IncreaseRange( 0.08 );
|
||||
return a;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Default constructor.
|
||||
/// </summary>
|
||||
public CandlePlot()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Calculates the physical (not world) separation between abscissa values.
|
||||
/// </summary>
|
||||
/// <param name="cd">Candle adapter containing data</param>
|
||||
/// <param name="xAxis">Physical x axis the data is plotted against.</param>
|
||||
/// <returns>physical separation between abscissa values.</returns>
|
||||
private static float CalculatePhysicalSeparation( CandleDataAdapter cd, PhysicalAxis xAxis )
|
||||
{
|
||||
if (cd.Count > 1)
|
||||
{
|
||||
int xPos1 = (int)(xAxis.WorldToPhysical( ((PointOLHC)cd[0]).X, false )).X;
|
||||
int xPos2 = (int)(xAxis.WorldToPhysical( ((PointOLHC)cd[1]).X, false )).X;
|
||||
int minDist = xPos2 - xPos1;
|
||||
|
||||
if (cd.Count > 2)
|
||||
{ // to be pretty sure we get the smallest gap.
|
||||
int xPos3 = (int)(xAxis.WorldToPhysical(((PointOLHC)cd[2]).X, false)).X;
|
||||
if (xPos3 - xPos2 < minDist) minDist = xPos3 - xPos2;
|
||||
|
||||
if (cd.Count > 3)
|
||||
{
|
||||
int xPos4 = (int)(xAxis.WorldToPhysical(((PointOLHC)cd[3]).X, false)).X;
|
||||
if (xPos4 - xPos3 < minDist) minDist = xPos4 - xPos3;
|
||||
}
|
||||
}
|
||||
|
||||
return minDist;
|
||||
}
|
||||
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Draws the candle plot on a GDI+ surface agains the provided x and y axes.
|
||||
/// </summary>
|
||||
/// <param name="g">The GDI+ 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( Graphics g, PhysicalAxis xAxis, PhysicalAxis yAxis )
|
||||
{
|
||||
CandleDataAdapter cd = new CandleDataAdapter( this.DataSource, this.DataMember,
|
||||
this.AbscissaData, this.OpenData, this.LowData, this.HighData, this.CloseData );
|
||||
|
||||
Brush bearishBrush = new SolidBrush( BearishColor );
|
||||
Brush bullishBrush = new SolidBrush( BullishColor );
|
||||
|
||||
uint offset = 0;
|
||||
if (this.centered_)
|
||||
{
|
||||
offset = (uint)(CalculatePhysicalSeparation(cd,xAxis) / 2.0f);
|
||||
}
|
||||
|
||||
uint addAmount = (uint)StickWidth/2;
|
||||
uint stickWidth = (uint)StickWidth;
|
||||
|
||||
if (StickWidth == AutoScaleStickWidth)
|
||||
{
|
||||
// default
|
||||
addAmount = 2;
|
||||
stickWidth = 4;
|
||||
|
||||
float minDist = CalculatePhysicalSeparation( cd, xAxis );
|
||||
|
||||
addAmount = (uint)(minDist / 3);
|
||||
stickWidth = addAmount * 2;
|
||||
}
|
||||
|
||||
Pen p = new Pen(this.color_);
|
||||
|
||||
/*
|
||||
// brant hyatt proposed.
|
||||
if (this.Style == Styles.Stick)
|
||||
{
|
||||
p.Width = stickWidth;
|
||||
addAmount = stickWidth + 2;
|
||||
}
|
||||
*/
|
||||
|
||||
for (int i=0; i<cd.Count; ++i)
|
||||
{
|
||||
|
||||
PointOLHC point = (PointOLHC)cd[i];
|
||||
if ( (!double.IsNaN (point.Open)) && (!double.IsNaN(point.High)) && (!double.IsNaN (point.Low)) && (!double.IsNaN(point.Close)) )
|
||||
{
|
||||
|
||||
int xPos = (int)(xAxis.WorldToPhysical( point.X, false )).X;
|
||||
|
||||
if (xPos + offset + addAmount < xAxis.PhysicalMin.X || xAxis.PhysicalMax.X < xPos + offset - addAmount)
|
||||
continue;
|
||||
|
||||
int yPos1 = (int)(yAxis.WorldToPhysical( point.Low, false )).Y;
|
||||
int yPos2 = (int)(yAxis.WorldToPhysical( point.High, false )).Y;
|
||||
int yPos3 = (int)(yAxis.WorldToPhysical( point.Open, false )).Y;
|
||||
int yPos4 = (int)(yAxis.WorldToPhysical( point.Close, false )).Y;
|
||||
|
||||
if (this.Style == Styles.Stick)
|
||||
{
|
||||
|
||||
/*
|
||||
// brant hyatt proposed.
|
||||
if (i > 0)
|
||||
{
|
||||
if ( ((PointOLHC)cd[i]).Close > ((PointOLHC)cd[i-1]).Close)
|
||||
{
|
||||
p.Color = BullishColor;
|
||||
}
|
||||
else
|
||||
{
|
||||
p.Color = BearishColor;
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
g.DrawLine( p, xPos+offset, yPos1, xPos+offset, yPos2 );
|
||||
g.DrawLine( p, xPos-addAmount+offset, yPos3, xPos+offset, yPos3 );
|
||||
g.DrawLine( p, xPos+offset, yPos4, xPos+addAmount+offset, yPos4 );
|
||||
}
|
||||
|
||||
else if (this.Style == Styles.Filled)
|
||||
{
|
||||
g.DrawLine( p, xPos+offset, yPos1, xPos+offset, yPos2 );
|
||||
if (yPos3 > yPos4)
|
||||
{
|
||||
g.FillRectangle( bullishBrush, xPos-addAmount+offset, yPos4, stickWidth, yPos3 - yPos4 );
|
||||
g.DrawRectangle( p, xPos-addAmount+offset, yPos4, stickWidth, yPos3 - yPos4 );
|
||||
}
|
||||
else if (yPos3 < yPos4)
|
||||
{
|
||||
g.FillRectangle( bearishBrush, xPos-addAmount+offset, yPos3, stickWidth, yPos4 - yPos3 );
|
||||
g.DrawRectangle( p, xPos-addAmount+offset, yPos3, stickWidth, yPos4 - yPos3 );
|
||||
}
|
||||
else
|
||||
{
|
||||
g.DrawLine( p, xPos-addAmount+offset, yPos3, xPos-addAmount+stickWidth+offset, yPos3 );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Returns an x-axis that is suitable for drawing this plot.
|
||||
/// </summary>
|
||||
/// <returns>A suitable x-axis.</returns>
|
||||
public Axis SuggestXAxis()
|
||||
{
|
||||
CandleDataAdapter candleData = new CandleDataAdapter( this.DataSource, this.DataMember,
|
||||
this.AbscissaData, this.OpenData, this.LowData, this.HighData, this.CloseData );
|
||||
|
||||
return candleData.SuggestXAxis();
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Returns a y-axis that is suitable for drawing this plot.
|
||||
/// </summary>
|
||||
/// <returns>A suitable y-axis.</returns>
|
||||
public Axis SuggestYAxis()
|
||||
{
|
||||
CandleDataAdapter candleData = new CandleDataAdapter( this.DataSource, this.DataMember,
|
||||
this.AbscissaData, this.OpenData, this.LowData, this.HighData, this.CloseData );
|
||||
|
||||
return candleData.SuggestYAxis();
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the data, or column name for the open values.
|
||||
/// </summary>
|
||||
public object OpenData
|
||||
{
|
||||
get
|
||||
{
|
||||
return openData_;
|
||||
}
|
||||
set
|
||||
{
|
||||
openData_ = value;
|
||||
}
|
||||
}
|
||||
private object openData_ = null;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the data, or column name for the interval low values.
|
||||
/// </summary>
|
||||
public object LowData
|
||||
{
|
||||
get
|
||||
{
|
||||
return lowData_;
|
||||
}
|
||||
set
|
||||
{
|
||||
lowData_ = value;
|
||||
}
|
||||
}
|
||||
private object lowData_ = null;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the data, or column name for the interval high values.
|
||||
/// </summary>
|
||||
public object HighData
|
||||
{
|
||||
get
|
||||
{
|
||||
return highData_;
|
||||
}
|
||||
set
|
||||
{
|
||||
highData_ = value;
|
||||
}
|
||||
}
|
||||
private object highData_ = null;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the data, or column name for the close values.
|
||||
/// </summary>
|
||||
public object CloseData
|
||||
{
|
||||
get
|
||||
{
|
||||
return closeData_;
|
||||
}
|
||||
set
|
||||
{
|
||||
closeData_ = value;
|
||||
}
|
||||
}
|
||||
private object closeData_ = null;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the data, or column name for the abscissa [x] axis.
|
||||
/// </summary>
|
||||
public object AbscissaData
|
||||
{
|
||||
get
|
||||
{
|
||||
return abscissaData_;
|
||||
}
|
||||
set
|
||||
{
|
||||
abscissaData_ = value;
|
||||
}
|
||||
}
|
||||
private object abscissaData_ = null;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Draws a representation of this plot in the legend.
|
||||
/// </summary>
|
||||
/// <param name="g">The graphics surface on which to draw.</param>
|
||||
/// <param name="startEnd">A rectangle specifying the bounds of the area in the legend set aside for drawing.</param>
|
||||
public virtual void DrawInLegend( Graphics g, Rectangle startEnd )
|
||||
{
|
||||
Pen p = new Pen(this.color_);
|
||||
|
||||
g.DrawLine( p, startEnd.Left, (startEnd.Top + startEnd.Bottom)/2,
|
||||
startEnd.Right, (startEnd.Top + startEnd.Bottom)/2 );
|
||||
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Color of this plot [excluding interior of filled boxes if Style is fill]. To
|
||||
/// change the Bullish and Bearish colours in Filled mode, use the BullishColor
|
||||
/// and BearishColor properties.
|
||||
/// </summary>
|
||||
public System.Drawing.Color Color
|
||||
{
|
||||
get
|
||||
{
|
||||
return color_;
|
||||
}
|
||||
set
|
||||
{
|
||||
color_ = value;
|
||||
}
|
||||
}
|
||||
Color color_ = Color.Black;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Possible CandleStick styles.
|
||||
/// </summary>
|
||||
public enum Styles
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// Draw vertical line between low and high, tick on left for open and tick on right for close.
|
||||
/// </summary>
|
||||
Stick,
|
||||
|
||||
/// <summary>
|
||||
/// Draw vertical line between low and high and place on top of this a box with bottom
|
||||
/// and top determined by open and high values. The box is filled using the colors specified
|
||||
/// in BullishColor and BearishColor properties.
|
||||
/// </summary>
|
||||
Filled
|
||||
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Specifies the CandleStick style to use.
|
||||
/// </summary>
|
||||
public Styles Style = Styles.Filled;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// If CandlePlot.Style is Filled, then bullish open-close moves are displayed in this color.
|
||||
/// </summary>
|
||||
public Color BullishColor = Color.White;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// If CandlePlot.Style is Filled, then bearish moves are displayed in this color.
|
||||
/// </summary>
|
||||
public Color BearishColor = Color.Black;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Width of each stick in pixels. It is best if this is an odd number.
|
||||
/// </summary>
|
||||
public int StickWidth
|
||||
{
|
||||
get
|
||||
{
|
||||
return stickWidth_;
|
||||
}
|
||||
set
|
||||
{
|
||||
if (value < 1)
|
||||
{
|
||||
throw new NPlotException( "Stick width must be greater than 0." );
|
||||
}
|
||||
stickWidth_ = value;
|
||||
}
|
||||
}
|
||||
private int stickWidth_ = AutoScaleStickWidth;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// If stick width is set equal to this value, the width will be
|
||||
/// automatically scaled dependant on the space between sticks.
|
||||
/// </summary>
|
||||
public const int AutoScaleStickWidth = 0;
|
||||
|
||||
/// <summary>
|
||||
/// If true (default), bars will be centered on the abscissa times.
|
||||
/// If false, bars will be drawn between the corresponding abscissa time
|
||||
/// and the next abscissa time.
|
||||
/// </summary>
|
||||
/// <value></value>
|
||||
public bool Centered
|
||||
{
|
||||
get
|
||||
{
|
||||
return centered_;
|
||||
}
|
||||
set
|
||||
{
|
||||
centered_ = value;
|
||||
}
|
||||
}
|
||||
private bool centered_ = true;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Write data associated with the plot as text.
|
||||
/// </summary>
|
||||
/// <param name="sb">the string builder to write to.</param>
|
||||
/// <param name="region">Only write out data in this region if onlyInRegion is true.</param>
|
||||
/// <param name="onlyInRegion">If true, only data in region is written, else all data is written.</param>
|
||||
/// <remarks>TODO: not implemented.</remarks>
|
||||
public void WriteData( System.Text.StringBuilder sb, RectangleD region, bool onlyInRegion )
|
||||
{
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,702 @@
|
|||
/*
|
||||
NPlot - A charting library for .NET
|
||||
|
||||
DateTimeAxis.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.Collections;
|
||||
using System.Globalization;
|
||||
|
||||
// TODO: More control over how labels are displayed.
|
||||
// TODO: SkipWeekends property.
|
||||
// TODO: Make a relative (as opposed to absolute) TimeAxis.
|
||||
|
||||
namespace NPlot
|
||||
{
|
||||
/// <summary>
|
||||
/// The DateTimeAxis class
|
||||
/// </summary>
|
||||
public class DateTimeAxis : Axis
|
||||
{
|
||||
|
||||
#region Clone implementation
|
||||
/// <summary>
|
||||
/// Deep copy of DateTimeAxis.
|
||||
/// </summary>
|
||||
/// <returns>A copy of the DateTimeAxis Class.</returns>
|
||||
public override object Clone()
|
||||
{
|
||||
DateTimeAxis a = new DateTimeAxis();
|
||||
// ensure that this isn't being called on a derived type. If it is, then oh no!
|
||||
if (this.GetType() != a.GetType())
|
||||
{
|
||||
throw new NPlotException( "Clone not defined in derived type. Help!" );
|
||||
}
|
||||
DoClone( this, a );
|
||||
return a;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Helper method for Clone.
|
||||
/// </summary>
|
||||
/// <param name="a">The original object to clone.</param>
|
||||
/// <param name="b">The cloned object.</param>
|
||||
protected static void DoClone( DateTimeAxis b, DateTimeAxis a )
|
||||
{
|
||||
Axis.DoClone( b, a );
|
||||
}
|
||||
#endregion
|
||||
|
||||
private void Init()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Constructor
|
||||
/// </summary>
|
||||
/// <param name="a">Axis to construct from</param>
|
||||
public DateTimeAxis( Axis a )
|
||||
: base( a )
|
||||
{
|
||||
this.Init();
|
||||
this.NumberFormat = null;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Default Constructor
|
||||
/// </summary>
|
||||
public DateTimeAxis()
|
||||
: base()
|
||||
{
|
||||
this.Init();
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Constructor
|
||||
/// </summary>
|
||||
/// <param name="worldMin">World min of axis</param>
|
||||
/// <param name="worldMax">World max of axis</param>
|
||||
public DateTimeAxis( double worldMin, double worldMax )
|
||||
: base( worldMin, worldMax )
|
||||
{
|
||||
this.Init();
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Constructor
|
||||
/// </summary>
|
||||
/// <param name="worldMin">World min of axis</param>
|
||||
/// <param name="worldMax">World max of axis</param>
|
||||
public DateTimeAxis( long worldMin, long worldMax )
|
||||
: base( (double)worldMin, (double)worldMax )
|
||||
{
|
||||
this.Init();
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Constructor
|
||||
/// </summary>
|
||||
/// <param name="worldMin">World min of axis</param>
|
||||
/// <param name="worldMax">World max of axis</param>
|
||||
public DateTimeAxis( DateTime worldMin, DateTime worldMax )
|
||||
: base( (double)worldMin.Ticks, (double)worldMax.Ticks )
|
||||
{
|
||||
this.Init();
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Draw the ticks.
|
||||
/// </summary>
|
||||
/// <param name="g">The drawing surface on which to draw.</param>
|
||||
/// <param name="physicalMin">The minimum physical extent of the axis.</param>
|
||||
/// <param name="physicalMax">The maximum physical extent of the axis.</param>
|
||||
/// <param name="boundingBox">out: smallest box that completely encompasses all of the ticks and tick labels.</param>
|
||||
/// <param name="labelOffset">out: a suitable offset from the axis to draw the axis label.</param>
|
||||
protected override void DrawTicks(
|
||||
Graphics g,
|
||||
Point physicalMin,
|
||||
Point physicalMax,
|
||||
out object labelOffset,
|
||||
out object boundingBox )
|
||||
{
|
||||
|
||||
// TODO: Look at offset and bounding box logic again here. why temp and other vars?
|
||||
|
||||
Point tLabelOffset;
|
||||
Rectangle tBoundingBox;
|
||||
|
||||
labelOffset = this.getDefaultLabelOffset( physicalMin, physicalMax );
|
||||
boundingBox = null;
|
||||
|
||||
ArrayList largeTicks;
|
||||
ArrayList smallTicks;
|
||||
this.WorldTickPositions( physicalMin, physicalMax, out largeTicks, out smallTicks );
|
||||
|
||||
// draw small ticks.
|
||||
for (int i=0; i<smallTicks.Count; ++i)
|
||||
{
|
||||
this.DrawTick( g, (double)smallTicks[i],
|
||||
this.SmallTickSize, "", new Point(0, 0),
|
||||
physicalMin, physicalMax,
|
||||
out tLabelOffset, out tBoundingBox );
|
||||
// assume label offset and bounding box unchanged by small tick bounds.
|
||||
}
|
||||
|
||||
// draw large ticks.
|
||||
for (int i=0; i<largeTicks.Count; ++i)
|
||||
{
|
||||
|
||||
DateTime tickDate = new DateTime( (long)((double)largeTicks[i]) );
|
||||
string label = LargeTickLabel(tickDate);
|
||||
|
||||
this.DrawTick( g, (double)largeTicks[i],
|
||||
this.LargeTickSize, label, new Point( 0, 0 ),
|
||||
physicalMin, physicalMax, out tLabelOffset, out tBoundingBox );
|
||||
|
||||
Axis.UpdateOffsetAndBounds( ref labelOffset, ref boundingBox, tLabelOffset, tBoundingBox );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the label corresponding to the provided date time
|
||||
/// </summary>
|
||||
/// <param name="tickDate">the date time to get the label for</param>
|
||||
/// <returns>label for the provided DateTime</returns>
|
||||
protected virtual string LargeTickLabel(DateTime tickDate)
|
||||
{
|
||||
string label = "";
|
||||
|
||||
if(this.NumberFormat == null || this.NumberFormat == String.Empty)
|
||||
{
|
||||
if ( this.LargeTickLabelType_ == LargeTickLabelType.year )
|
||||
{
|
||||
label = tickDate.Year.ToString();
|
||||
}
|
||||
|
||||
else if ( this.LargeTickLabelType_ == LargeTickLabelType.month )
|
||||
{
|
||||
label = tickDate.ToString("MMM");
|
||||
label += " ";
|
||||
label += tickDate.Year.ToString().Substring(2,2);
|
||||
}
|
||||
|
||||
else if ( this.LargeTickLabelType_ == LargeTickLabelType.day )
|
||||
{
|
||||
label = (tickDate.Day).ToString();
|
||||
label += " ";
|
||||
label += tickDate.ToString("MMM");
|
||||
}
|
||||
|
||||
else if ( this.LargeTickLabelType_ == LargeTickLabelType.hourMinute )
|
||||
{
|
||||
string minutes = tickDate.Minute.ToString();
|
||||
if (minutes.Length == 1)
|
||||
{
|
||||
minutes = "0" + minutes;
|
||||
}
|
||||
label = tickDate.Hour.ToString() + ":" + minutes;
|
||||
}
|
||||
else if ( this.LargeTickLabelType_ == LargeTickLabelType.hourMinuteSeconds )
|
||||
{
|
||||
string minutes = tickDate.Minute.ToString();
|
||||
string seconds = tickDate.Second.ToString();
|
||||
if (seconds.Length == 1)
|
||||
{
|
||||
seconds = "0" + seconds;
|
||||
}
|
||||
|
||||
if (minutes.Length == 1)
|
||||
{
|
||||
minutes = "0" + minutes;
|
||||
}
|
||||
label = tickDate.Hour.ToString() + ":" + minutes + "." + seconds;
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
label = tickDate.ToString(NumberFormat);
|
||||
}
|
||||
|
||||
return label;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Enumerates the different types of tick label possible.
|
||||
/// </summary>
|
||||
protected enum LargeTickLabelType
|
||||
{
|
||||
/// <summary>
|
||||
/// default - no tick labels.
|
||||
/// </summary>
|
||||
none = 0,
|
||||
|
||||
/// <summary>
|
||||
/// tick labels should be years
|
||||
/// </summary>
|
||||
year = 1,
|
||||
|
||||
/// <summary>
|
||||
/// Tick labels should be month names
|
||||
/// </summary>
|
||||
month = 2,
|
||||
|
||||
/// <summary>
|
||||
/// Tick labels should be day names
|
||||
/// </summary>
|
||||
day = 3,
|
||||
|
||||
/// <summary>
|
||||
/// Tick labels should be hour / minutes.
|
||||
/// </summary>
|
||||
hourMinute = 4,
|
||||
|
||||
/// <summary>
|
||||
/// tick labels should be hour / minute / second.
|
||||
/// </summary>
|
||||
hourMinuteSeconds = 5
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// this gets set after a get LargeTickPositions.
|
||||
/// </summary>
|
||||
protected LargeTickLabelType LargeTickLabelType_;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Determines the positions, in world coordinates, of the large ticks. No
|
||||
/// small tick marks are currently calculated by this method.
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="physicalMin">The physical position corresponding to the world minimum of the axis.</param>
|
||||
/// <param name="physicalMax">The physical position corresponding to the world maximum of the axis.</param>
|
||||
/// <param name="largeTickPositions">ArrayList containing the positions of the large ticks.</param>
|
||||
/// <param name="smallTickPositions">null</param>
|
||||
internal override void WorldTickPositions_FirstPass(
|
||||
Point physicalMin,
|
||||
Point physicalMax,
|
||||
out ArrayList largeTickPositions,
|
||||
out ArrayList smallTickPositions
|
||||
)
|
||||
{
|
||||
smallTickPositions = null;
|
||||
|
||||
largeTickPositions = new ArrayList();
|
||||
|
||||
const int daysInMonth = 30;
|
||||
|
||||
TimeSpan timeLength = new TimeSpan( (long)(WorldMax-WorldMin));
|
||||
DateTime worldMinDate = new DateTime( (long)this.WorldMin );
|
||||
DateTime worldMaxDate = new DateTime( (long)this.WorldMax );
|
||||
|
||||
if(largeTickStep_ == TimeSpan.Zero)
|
||||
{
|
||||
|
||||
// if less than 10 minutes, then large ticks on second spacings.
|
||||
|
||||
if ( timeLength < new TimeSpan(0,0,2,0,0) )
|
||||
{
|
||||
this.LargeTickLabelType_ = LargeTickLabelType.hourMinuteSeconds;
|
||||
|
||||
double secondsSkip;
|
||||
|
||||
if (timeLength < new TimeSpan( 0,0,0,10,0 ) )
|
||||
secondsSkip = 1.0;
|
||||
else if ( timeLength < new TimeSpan(0,0,0,20,0) )
|
||||
secondsSkip = 2.0;
|
||||
else if ( timeLength < new TimeSpan(0,0,0,50,0) )
|
||||
secondsSkip = 5.0;
|
||||
else if ( timeLength < new TimeSpan(0,0,2,30,0) )
|
||||
secondsSkip = 15.0;
|
||||
else
|
||||
secondsSkip = 30.0;
|
||||
|
||||
int second = worldMinDate.Second;
|
||||
second -= second % (int)secondsSkip;
|
||||
|
||||
DateTime currentTickDate = new DateTime(
|
||||
worldMinDate.Year,
|
||||
worldMinDate.Month,
|
||||
worldMinDate.Day,
|
||||
worldMinDate.Hour,
|
||||
worldMinDate.Minute,
|
||||
second,0 );
|
||||
|
||||
while ( currentTickDate < worldMaxDate )
|
||||
{
|
||||
double world = (double)currentTickDate.Ticks;
|
||||
|
||||
if ( world >= this.WorldMin && world <= this.WorldMax )
|
||||
{
|
||||
largeTickPositions.Add( world );
|
||||
}
|
||||
|
||||
currentTickDate = currentTickDate.AddSeconds( secondsSkip );
|
||||
}
|
||||
}
|
||||
|
||||
// Less than 2 hours, then large ticks on minute spacings.
|
||||
|
||||
else if ( timeLength < new TimeSpan(0,2,0,0,0) )
|
||||
{
|
||||
this.LargeTickLabelType_ = LargeTickLabelType.hourMinute;
|
||||
|
||||
double minuteSkip;
|
||||
|
||||
if ( timeLength < new TimeSpan(0,0,10,0,0) )
|
||||
minuteSkip = 1.0;
|
||||
else if ( timeLength < new TimeSpan(0,0,20,0,0) )
|
||||
minuteSkip = 2.0;
|
||||
else if ( timeLength < new TimeSpan(0,0,50,0,0) )
|
||||
minuteSkip = 5.0;
|
||||
else if ( timeLength < new TimeSpan(0,2,30,0,0) )
|
||||
minuteSkip = 15.0;
|
||||
else //( timeLength < new TimeSpan( 0,5,0,0,0) )
|
||||
minuteSkip = 30.0;
|
||||
|
||||
int minute = worldMinDate.Minute;
|
||||
minute -= minute % (int)minuteSkip;
|
||||
|
||||
DateTime currentTickDate = new DateTime(
|
||||
worldMinDate.Year,
|
||||
worldMinDate.Month,
|
||||
worldMinDate.Day,
|
||||
worldMinDate.Hour,
|
||||
minute,0,0 );
|
||||
|
||||
while ( currentTickDate < worldMaxDate )
|
||||
{
|
||||
double world = (double)currentTickDate.Ticks;
|
||||
|
||||
if ( world >= this.WorldMin && world <= this.WorldMax )
|
||||
{
|
||||
largeTickPositions.Add( world );
|
||||
}
|
||||
|
||||
currentTickDate = currentTickDate.AddMinutes( minuteSkip );
|
||||
}
|
||||
}
|
||||
|
||||
// Less than 2 days, then large ticks on hour spacings.
|
||||
|
||||
else if ( timeLength < new TimeSpan(2,0,0,0,0) )
|
||||
{
|
||||
this.LargeTickLabelType_ = LargeTickLabelType.hourMinute;
|
||||
|
||||
double hourSkip;
|
||||
if ( timeLength < new TimeSpan(0,10,0,0,0) )
|
||||
hourSkip = 1.0;
|
||||
else if ( timeLength < new TimeSpan(0,20,0,0,0) )
|
||||
hourSkip = 2.0;
|
||||
else
|
||||
hourSkip = 6.0;
|
||||
|
||||
|
||||
int hour = worldMinDate.Hour;
|
||||
hour -= hour % (int)hourSkip;
|
||||
|
||||
DateTime currentTickDate = new DateTime(
|
||||
worldMinDate.Year,
|
||||
worldMinDate.Month,
|
||||
worldMinDate.Day,
|
||||
hour,0,0,0 );
|
||||
|
||||
while ( currentTickDate < worldMaxDate )
|
||||
{
|
||||
double world = (double)currentTickDate.Ticks;
|
||||
|
||||
if ( world >= this.WorldMin && world <= this.WorldMax )
|
||||
{
|
||||
largeTickPositions.Add( world );
|
||||
}
|
||||
|
||||
currentTickDate = currentTickDate.AddHours( hourSkip );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
// less than 5 months, then large ticks on day spacings.
|
||||
|
||||
else if ( timeLength < new TimeSpan(daysInMonth*4,0,0,0,0))
|
||||
{
|
||||
this.LargeTickLabelType_ = LargeTickLabelType.day;
|
||||
|
||||
double daySkip;
|
||||
if ( timeLength < new TimeSpan(10,0,0,0,0) )
|
||||
daySkip = 1.0;
|
||||
else if (timeLength < new TimeSpan(20,0,0,0,0) )
|
||||
daySkip = 2.0;
|
||||
else if (timeLength < new TimeSpan(7*10,0,0,0,0) )
|
||||
daySkip = 7.0;
|
||||
else
|
||||
daySkip = 14.0;
|
||||
|
||||
DateTime currentTickDate = new DateTime(
|
||||
worldMinDate.Year,
|
||||
worldMinDate.Month,
|
||||
worldMinDate.Day );
|
||||
|
||||
if (daySkip == 2.0)
|
||||
{
|
||||
|
||||
TimeSpan timeSinceBeginning = currentTickDate - DateTime.MinValue;
|
||||
|
||||
if (timeSinceBeginning.Days % 2 == 1)
|
||||
currentTickDate = currentTickDate.AddDays(-1.0);
|
||||
}
|
||||
|
||||
if (daySkip == 7 || daySkip == 14.0)
|
||||
{
|
||||
DayOfWeek dow = currentTickDate.DayOfWeek;
|
||||
switch (dow)
|
||||
{
|
||||
case DayOfWeek.Monday:
|
||||
break;
|
||||
case DayOfWeek.Tuesday:
|
||||
currentTickDate = currentTickDate.AddDays(-1.0);
|
||||
break;
|
||||
case DayOfWeek.Wednesday:
|
||||
currentTickDate = currentTickDate.AddDays(-2.0);
|
||||
break;
|
||||
case DayOfWeek.Thursday:
|
||||
currentTickDate = currentTickDate.AddDays(-3.0);
|
||||
break;
|
||||
case DayOfWeek.Friday:
|
||||
currentTickDate = currentTickDate.AddDays(-4.0);
|
||||
break;
|
||||
case DayOfWeek.Saturday:
|
||||
currentTickDate = currentTickDate.AddDays(-5.0);
|
||||
break;
|
||||
case DayOfWeek.Sunday:
|
||||
currentTickDate = currentTickDate.AddDays(-6.0);
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (daySkip == 14.0f)
|
||||
{
|
||||
TimeSpan timeSinceBeginning = currentTickDate - DateTime.MinValue;
|
||||
|
||||
if ((timeSinceBeginning.Days / 7) % 2 == 1)
|
||||
{
|
||||
currentTickDate = currentTickDate.AddDays(-7.0);
|
||||
}
|
||||
}
|
||||
|
||||
while ( currentTickDate < worldMaxDate )
|
||||
{
|
||||
double world = (double)currentTickDate.Ticks;
|
||||
|
||||
if ( world >= this.WorldMin && world <= this.WorldMax )
|
||||
{
|
||||
largeTickPositions.Add( world );
|
||||
}
|
||||
|
||||
currentTickDate = currentTickDate.AddDays(daySkip);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// else ticks on month or year spacings.
|
||||
|
||||
else if ( timeLength >= new TimeSpan(daysInMonth*4,0,0,0,0) )
|
||||
{
|
||||
|
||||
int monthSpacing = 0;
|
||||
|
||||
if ( timeLength.Days < daysInMonth*(12*3+6) )
|
||||
{
|
||||
LargeTickLabelType_ = LargeTickLabelType.month;
|
||||
|
||||
if ( timeLength.Days < daysInMonth*10 )
|
||||
monthSpacing = 1;
|
||||
else if ( timeLength.Days < daysInMonth*(12*2) )
|
||||
monthSpacing = 3;
|
||||
else // if ( timeLength.Days < daysInMonth*(12*3+6) )
|
||||
monthSpacing = 6;
|
||||
}
|
||||
else
|
||||
{
|
||||
LargeTickLabelType_ = LargeTickLabelType.year;
|
||||
|
||||
if (timeLength.Days < daysInMonth * (12 * 6))
|
||||
monthSpacing = 12;
|
||||
else if (timeLength.Days < daysInMonth * (12 * 12))
|
||||
monthSpacing = 24;
|
||||
else if (timeLength.Days < daysInMonth * (12 * 30))
|
||||
monthSpacing = 60;
|
||||
else
|
||||
monthSpacing = 120;
|
||||
//LargeTickLabelType_ = LargeTickLabelType.none;
|
||||
}
|
||||
|
||||
// truncate start
|
||||
DateTime currentTickDate = new DateTime(
|
||||
worldMinDate.Year,
|
||||
worldMinDate.Month,
|
||||
1 );
|
||||
|
||||
if (monthSpacing > 1)
|
||||
{
|
||||
currentTickDate = currentTickDate.AddMonths(
|
||||
-(currentTickDate.Month-1)%monthSpacing );
|
||||
}
|
||||
|
||||
// Align on 2 or 5 year boundaries if necessary.
|
||||
if (monthSpacing >= 24)
|
||||
{
|
||||
currentTickDate = currentTickDate.AddYears(
|
||||
-(currentTickDate.Year)%(monthSpacing/12) );
|
||||
}
|
||||
|
||||
//this.firstLargeTick_ = (double)currentTickDate.Ticks;
|
||||
|
||||
if ( LargeTickLabelType_ != LargeTickLabelType.none )
|
||||
{
|
||||
while ( currentTickDate < worldMaxDate )
|
||||
{
|
||||
double world = (double)currentTickDate.Ticks;
|
||||
|
||||
if ( world >= this.WorldMin && world <= this.WorldMax )
|
||||
{
|
||||
largeTickPositions.Add( world );
|
||||
}
|
||||
|
||||
currentTickDate = currentTickDate.AddMonths( monthSpacing );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (DateTime date = worldMinDate; date < worldMaxDate; date += largeTickStep_)
|
||||
{
|
||||
largeTickPositions.Add((double)date.Ticks);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Compute the small tick positions for largetick size of one or more years.
|
||||
/// - inside the domain or the large tick positons, is take the mid-point of pairs of large ticks
|
||||
/// - outside the large tick range, check if a half tick is inside the world min/max
|
||||
/// This method works only if there are atleast 2 large ticks,
|
||||
/// since we don't know if its minutes, hours, month, or yearly divisor.
|
||||
/// </summary>
|
||||
/// <param name="physicalMin">The physical position corresponding to the world minimum of the axis.</param>
|
||||
/// <param name="physicalMax">The physical position corresponding to the world maximum of the axis.</param>
|
||||
/// <param name="largeTickPositions">Read in the large tick positions</param>
|
||||
/// <param name="smallTickPositions">Fill in the corresponding small tick positions</param>
|
||||
/// <remarks>Added by Rosco Hill</remarks>
|
||||
internal override void WorldTickPositions_SecondPass(
|
||||
Point physicalMin,
|
||||
Point physicalMax,
|
||||
ArrayList largeTickPositions,
|
||||
ref ArrayList smallTickPositions
|
||||
)
|
||||
{
|
||||
if (largeTickPositions.Count < 2 || !(LargeTickLabelType_.Equals(LargeTickLabelType.year)))
|
||||
{
|
||||
smallTickPositions = new ArrayList(); ;
|
||||
}
|
||||
else
|
||||
{
|
||||
smallTickPositions = new ArrayList();
|
||||
double diff = 0.5 * (((double)largeTickPositions[1]) - ((double)largeTickPositions[0]));
|
||||
if (((double)largeTickPositions[0] - diff) > this.WorldMin)
|
||||
{
|
||||
smallTickPositions.Add((double)largeTickPositions[0] - diff);
|
||||
}
|
||||
for (int i = 0; i < largeTickPositions.Count - 1; i++)
|
||||
{
|
||||
smallTickPositions.Add(((double)largeTickPositions[i]) + diff);
|
||||
}
|
||||
if (((double)largeTickPositions[largeTickPositions.Count - 1] + diff) < this.WorldMax)
|
||||
{
|
||||
smallTickPositions.Add((double)largeTickPositions[largeTickPositions.Count - 1] + diff);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// The distance between large ticks. If this is set to Zero [default],
|
||||
/// this distance will be calculated automatically.
|
||||
/// </summary>
|
||||
public TimeSpan LargeTickStep
|
||||
{
|
||||
set
|
||||
{
|
||||
largeTickStep_ = value;
|
||||
}
|
||||
get
|
||||
{
|
||||
return largeTickStep_;
|
||||
}
|
||||
}
|
||||
private TimeSpan largeTickStep_ = TimeSpan.Zero;
|
||||
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,179 @@
|
|||
/*
|
||||
NPlot - A charting library for .NET
|
||||
|
||||
ErrorHandler.cs
|
||||
Copyright (C) 2004
|
||||
Matt Howlett
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the following text in
|
||||
the documentation and / or other materials provided with the
|
||||
distribution:
|
||||
|
||||
"This product includes software developed as part of
|
||||
the NPlot charting library project available from:
|
||||
http://www.nplot.com/"
|
||||
|
||||
------------------------------------------------------------------------
|
||||
|
||||
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.
|
||||
|
||||
$Id: ErrorHandler.cs,v 1.2 2004/11/04 12:18:24 mhowlett Exp $
|
||||
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
|
||||
|
||||
namespace NPlot
|
||||
{
|
||||
/// <summary>
|
||||
/// Error class that
|
||||
/// (a) adds source of problem.
|
||||
/// (b) by default throws exception.
|
||||
/// (c) default behaviour can be overridden.
|
||||
/// </summary>
|
||||
public class ErrorHandler
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// The singular ErrorHandler instance
|
||||
/// </summary>
|
||||
public static readonly ErrorHandler Instance = new ErrorHandler();
|
||||
|
||||
/// <summary>
|
||||
/// Defines the allowed message levels.
|
||||
/// </summary>
|
||||
public enum Level
|
||||
{
|
||||
/// <summary>
|
||||
/// Debugging Message. Note it's best not to use the general
|
||||
/// handle method to emit these - use the conditional Debug
|
||||
/// function.
|
||||
/// </summary>
|
||||
Debug = 0,
|
||||
/// <summary>
|
||||
/// Something went wrong, but code execution can continue.
|
||||
/// </summary>
|
||||
Continuing = 1,
|
||||
/// <summary>
|
||||
/// Something wend wrong, and code execution can not continue.
|
||||
/// </summary>
|
||||
Critical = 2
|
||||
}
|
||||
|
||||
private delegate void HandlerDelegate( string message );
|
||||
|
||||
private HandlerDelegate[] handlers_;
|
||||
|
||||
private void HandleError( string message )
|
||||
{
|
||||
throw new System.Exception( message );
|
||||
}
|
||||
|
||||
private void NullHandler( string message )
|
||||
{
|
||||
// do nothing.
|
||||
}
|
||||
|
||||
private ErrorHandler()
|
||||
{
|
||||
// set up default
|
||||
handlers_ = new HandlerDelegate[3];
|
||||
handlers_[0] = new HandlerDelegate(HandleError);
|
||||
handlers_[1] = new HandlerDelegate(HandleError);
|
||||
handlers_[2] = new HandlerDelegate(HandleError);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Handles a debug message.
|
||||
/// </summary>
|
||||
/// <param name="message">message to handle</param>
|
||||
[Conditional("DEBUG")]
|
||||
public void DebugError( string message )
|
||||
{
|
||||
handlers_[(int)Level.Debug]( GetPrepend() + message );
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Handles a continuing error.
|
||||
/// </summary>
|
||||
/// <param name="message">message to handle</param>
|
||||
public void ContinuingError( string message )
|
||||
{
|
||||
handlers_[(int)Level.Continuing]( GetPrepend() + message );
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Handles a critical error.
|
||||
/// </summary>
|
||||
/// <param name="message">message to handle</param>
|
||||
public void CriticalError( string message )
|
||||
{
|
||||
handlers_[(int)Level.Critical]( GetPrepend() + message );
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Handles a message of the given level.
|
||||
/// </summary>
|
||||
/// <param name="level">The message level.</param>
|
||||
/// <param name="message">The message to handle.</param>
|
||||
public void Handle( Level level, string message )
|
||||
{
|
||||
handlers_[(int)level]( GetPrepend() + message );
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Get text to prepend to log message to describe its origin. This is the first
|
||||
/// place in stack outside Cts.Library.MessageLog.
|
||||
/// </summary>
|
||||
/// <returns>string to prepend to messages detailing its origin.</returns>
|
||||
private string GetPrepend()
|
||||
{
|
||||
System.Diagnostics.StackTrace st = new StackTrace();
|
||||
System.Diagnostics.StackFrame sf = null;
|
||||
string prepend = "";
|
||||
int i = 0;
|
||||
while (i < st.FrameCount)
|
||||
{
|
||||
sf = st.GetFrame(i);
|
||||
if ( sf.GetMethod().ReflectedType != this.GetType() )
|
||||
{
|
||||
break;
|
||||
}
|
||||
i += 1;
|
||||
}
|
||||
|
||||
sf = st.GetFrame(i);
|
||||
prepend =
|
||||
"[" +
|
||||
sf.GetMethod().ReflectedType +
|
||||
"." +
|
||||
sf.GetMethod().Name +
|
||||
"] ";
|
||||
return prepend;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,203 @@
|
|||
/*
|
||||
NPlot - A charting library for .NET
|
||||
|
||||
FilledRegion.cs
|
||||
Copyright (C) 2004
|
||||
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>
|
||||
/// A quick and dirty Filled region plottable object
|
||||
/// </summary>
|
||||
public class FilledRegion : IDrawable
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// Constructor
|
||||
/// </summary>
|
||||
/// <param name="lp1">LinePlot that provides bounds to filled region [upper or lower]</param>
|
||||
/// <param name="lp2">LinePlot that provides bounds to filled region [upper or lower]</param>
|
||||
/// <remarks>TODO: make this work with other plot types.</remarks>
|
||||
public FilledRegion( LinePlot lp1, LinePlot lp2 )
|
||||
{
|
||||
lp1_ = lp1;
|
||||
lp2_ = lp2;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Constructor
|
||||
/// </summary>
|
||||
/// <param name="l1">Vertical line to provide bounds for filled region</param>
|
||||
/// <param name="l2">The other Vertical line to provide bounds for filled region</param>
|
||||
public FilledRegion(VerticalLine l1, VerticalLine l2)
|
||||
{
|
||||
vl1_ = l1;
|
||||
vl2_ = l2;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Constructor
|
||||
/// </summary>
|
||||
/// <param name="l1">Vertical line to provide bounds for filled region</param>
|
||||
/// <param name="l2">The other Vertical line to provide bounds for filled region</param>
|
||||
public FilledRegion(HorizontalLine l1, HorizontalLine l2)
|
||||
{
|
||||
hl1_ = l1;
|
||||
hl2_ = l2;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Draw the filled region
|
||||
/// </summary>
|
||||
/// <param name="g">The GDI+ 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 )
|
||||
{
|
||||
ITransform2D t = Transform2D.GetTransformer(xAxis, yAxis);
|
||||
|
||||
Brush b = brush_;
|
||||
if (b == null)
|
||||
{
|
||||
b = areaBrush_.Get(new Rectangle(xAxis.PhysicalMin.X, yAxis.PhysicalMax.Y, xAxis.PhysicalLength, yAxis.PhysicalLength));
|
||||
}
|
||||
|
||||
if (hl1_ != null && hl2_ != null)
|
||||
{
|
||||
PointF[] points = new PointF[4];
|
||||
points[0] = t.Transform(xAxis.Axis.WorldMin, hl1_.OrdinateValue);
|
||||
points[1] = t.Transform(xAxis.Axis.WorldMax, hl1_.OrdinateValue);
|
||||
points[2] = t.Transform(xAxis.Axis.WorldMax, hl2_.OrdinateValue);
|
||||
points[3] = t.Transform(xAxis.Axis.WorldMin, hl2_.OrdinateValue);
|
||||
|
||||
g.FillPolygon(b, points);
|
||||
}
|
||||
else if (vl1_ != null && vl2_ != null)
|
||||
{
|
||||
PointF[] points = new PointF[4];
|
||||
points[0] = t.Transform(vl1_.AbscissaValue, yAxis.Axis.WorldMin);
|
||||
points[1] = t.Transform(vl1_.AbscissaValue, yAxis.Axis.WorldMax);
|
||||
points[2] = t.Transform(vl2_.AbscissaValue, yAxis.Axis.WorldMax);
|
||||
points[3] = t.Transform(vl2_.AbscissaValue, yAxis.Axis.WorldMin);
|
||||
|
||||
g.FillPolygon(b, points);
|
||||
}
|
||||
else if (lp1_ != null && lp2_ != null)
|
||||
{
|
||||
|
||||
SequenceAdapter a1 = new SequenceAdapter(lp1_.DataSource, lp1_.DataMember, lp1_.OrdinateData, lp1_.AbscissaData);
|
||||
SequenceAdapter a2 = new SequenceAdapter(lp2_.DataSource, lp2_.DataMember, lp2_.OrdinateData, lp2_.AbscissaData);
|
||||
|
||||
|
||||
int count = a1.Count + a2.Count;
|
||||
PointF[] points = new PointF[count];
|
||||
for (int i = 0; i < a1.Count; ++i)
|
||||
{
|
||||
points[i] = t.Transform(a1[i]);
|
||||
}
|
||||
for (int i = 0; i < a2.Count; ++i)
|
||||
{
|
||||
points[i + a1.Count] = t.Transform(a2[a2.Count - i - 1]);
|
||||
}
|
||||
|
||||
g.FillPolygon(b, points);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new NPlotException("One of bounds was set to null");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Use this brush (and not a RectangleBrush) for drawing.
|
||||
/// </summary>
|
||||
public Brush Brush
|
||||
{
|
||||
set
|
||||
{
|
||||
brush_ = value;
|
||||
areaBrush_ = null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Use this RectangleBrush (and not a normal Brush) for drawing.
|
||||
/// </summary>
|
||||
public IRectangleBrush RectangleBrush
|
||||
{
|
||||
set
|
||||
{
|
||||
brush_ = null;
|
||||
areaBrush_ = value;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private VerticalLine vl1_;
|
||||
private VerticalLine vl2_;
|
||||
|
||||
private HorizontalLine hl1_;
|
||||
private HorizontalLine hl2_;
|
||||
|
||||
private LinePlot lp1_;
|
||||
private LinePlot lp2_;
|
||||
|
||||
private Brush brush_ = new SolidBrush( Color.GhostWhite );
|
||||
private IRectangleBrush areaBrush_ = null;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,46 @@
|
|||
/*
|
||||
NPlot - A charting library for .NET
|
||||
|
||||
FontScaler.cs
|
||||
Copyright (C) 2003
|
||||
Matt Howlett
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the following text in
|
||||
the documentation and / or other materials provided with the
|
||||
distribution:
|
||||
|
||||
"This product includes software developed as part of
|
||||
the NPlot charting library project available from:
|
||||
http://www.nplot.com/"
|
||||
|
||||
------------------------------------------------------------------------
|
||||
|
||||
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.
|
||||
|
||||
$Id: FontScaler.cs,v 1.10 2004/11/04 12:18:24 mhowlett Exp $
|
||||
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Drawing;
|
||||
|
||||
namespace NPlot
|
||||
{
|
||||
|
||||
}
|
|
@ -0,0 +1,248 @@
|
|||
/*
|
||||
NPlot - A charting library for .NET
|
||||
|
||||
Grid.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;
|
||||
using System.Collections;
|
||||
|
||||
namespace NPlot
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// Encapsulates a Grid IDrawable object. Instances of this to a PlotSurface2D
|
||||
/// instance to produce a grid.
|
||||
/// </summary>
|
||||
public class Grid : IDrawable
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public enum GridType
|
||||
{
|
||||
/// <summary>
|
||||
/// No grid.
|
||||
/// </summary>
|
||||
None = 0,
|
||||
/// <summary>
|
||||
/// Coarse grid. Lines at large tick positions only.
|
||||
/// </summary>
|
||||
Coarse = 1,
|
||||
/// <summary>
|
||||
/// Fine grid. Lines at both large and small tick positions.
|
||||
/// </summary>
|
||||
Fine = 2
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Default constructor
|
||||
/// </summary>
|
||||
public Grid()
|
||||
{
|
||||
minorGridPen_ = new Pen( Color.LightGray );
|
||||
float[] pattern = {1.0f, 2.0f};
|
||||
minorGridPen_.DashPattern = pattern;
|
||||
|
||||
majorGridPen_ = new Pen( Color.LightGray );
|
||||
|
||||
horizontalGridType_ = GridType.Coarse;
|
||||
|
||||
verticalGridType_ = GridType.Coarse;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Specifies the horizontal grid type (none, coarse or fine).
|
||||
/// </summary>
|
||||
public GridType HorizontalGridType
|
||||
{
|
||||
get
|
||||
{
|
||||
return horizontalGridType_;
|
||||
}
|
||||
set
|
||||
{
|
||||
horizontalGridType_ = value;
|
||||
}
|
||||
}
|
||||
GridType horizontalGridType_;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Specifies the vertical grid type (none, coarse, or fine).
|
||||
/// </summary>
|
||||
public GridType VerticalGridType
|
||||
{
|
||||
get
|
||||
{
|
||||
return verticalGridType_;
|
||||
}
|
||||
set
|
||||
{
|
||||
verticalGridType_ = value;
|
||||
}
|
||||
}
|
||||
GridType verticalGridType_;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// The pen used to draw major (coarse) grid lines.
|
||||
/// </summary>
|
||||
public System.Drawing.Pen MajorGridPen
|
||||
{
|
||||
get
|
||||
{
|
||||
return majorGridPen_;
|
||||
}
|
||||
set
|
||||
{
|
||||
majorGridPen_ = value;
|
||||
}
|
||||
}
|
||||
private Pen majorGridPen_;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// The pen used to draw minor (fine) grid lines.
|
||||
/// </summary>
|
||||
public System.Drawing.Pen MinorGridPen
|
||||
{
|
||||
get
|
||||
{
|
||||
return minorGridPen_;
|
||||
}
|
||||
set
|
||||
{
|
||||
minorGridPen_ = value;
|
||||
}
|
||||
}
|
||||
private Pen minorGridPen_;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Does all the work in drawing grid lines.
|
||||
/// </summary>
|
||||
/// <param name="g">The graphics surface on which to render.</param>
|
||||
/// <param name="axis">TODO</param>
|
||||
/// <param name="orthogonalAxis">TODO</param>
|
||||
/// <param name="a">the list of world values to draw grid lines at.</param>
|
||||
/// <param name="horizontal">true if want horizontal lines, false otherwise.</param>
|
||||
/// <param name="p">the pen to use to draw the grid lines.</param>
|
||||
private void DrawGridLines(
|
||||
Graphics g, PhysicalAxis axis, PhysicalAxis orthogonalAxis,
|
||||
System.Collections.ArrayList a, bool horizontal, Pen p )
|
||||
{
|
||||
for (int i=0; i<a.Count; ++i)
|
||||
{
|
||||
PointF p1 = axis.WorldToPhysical((double)a[i], true);
|
||||
PointF p2 = p1;
|
||||
PointF p3 = orthogonalAxis.PhysicalMax;
|
||||
PointF p4 = orthogonalAxis.PhysicalMin;
|
||||
if (horizontal)
|
||||
{
|
||||
p1.Y = p4.Y;
|
||||
p2.Y = p3.Y;
|
||||
}
|
||||
else
|
||||
{
|
||||
p1.X = p4.X;
|
||||
p2.X = p3.X;
|
||||
}
|
||||
// note: casting all drawing was necessary for sane display. why?
|
||||
g.DrawLine( p, (int)p1.X, (int)p1.Y, (int)p2.X, (int)p2.Y );
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Draws the grid
|
||||
/// </summary>
|
||||
/// <param name="g">The graphics surface on which to draw</param>
|
||||
/// <param name="xAxis">The physical x axis to draw horizontal lines parallel to.</param>
|
||||
/// <param name="yAxis">The physical y axis to draw vertical lines parallel to.</param>
|
||||
public void Draw( Graphics g, PhysicalAxis xAxis, PhysicalAxis yAxis )
|
||||
{
|
||||
|
||||
ArrayList xLargePositions = null;
|
||||
ArrayList yLargePositions = null;
|
||||
ArrayList xSmallPositions = null;
|
||||
ArrayList ySmallPositions = null;
|
||||
|
||||
if (this.horizontalGridType_ != GridType.None)
|
||||
{
|
||||
xAxis.Axis.WorldTickPositions_FirstPass( xAxis.PhysicalMin, xAxis.PhysicalMax, out xLargePositions, out xSmallPositions );
|
||||
DrawGridLines( g, xAxis, yAxis, xLargePositions, true, this.MajorGridPen );
|
||||
}
|
||||
|
||||
if (this.verticalGridType_ != GridType.None)
|
||||
{
|
||||
yAxis.Axis.WorldTickPositions_FirstPass( yAxis.PhysicalMin, yAxis.PhysicalMax, out yLargePositions, out ySmallPositions );
|
||||
DrawGridLines( g, yAxis, xAxis, yLargePositions, false, this.MajorGridPen );
|
||||
}
|
||||
|
||||
|
||||
if (this.horizontalGridType_ == GridType.Fine)
|
||||
{
|
||||
xAxis.Axis.WorldTickPositions_SecondPass( xAxis.PhysicalMin, xAxis.PhysicalMax, xLargePositions, ref xSmallPositions );
|
||||
DrawGridLines( g, xAxis, yAxis, xSmallPositions, true, this.MinorGridPen );
|
||||
}
|
||||
|
||||
if (this.verticalGridType_ == GridType.Fine)
|
||||
{
|
||||
yAxis.Axis.WorldTickPositions_SecondPass( yAxis.PhysicalMin, yAxis.PhysicalMax, yLargePositions, ref ySmallPositions );
|
||||
DrawGridLines( g, yAxis, xAxis, ySmallPositions, false, this.MinorGridPen );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,303 @@
|
|||
using System;
|
||||
using System.Collections;
|
||||
using System.ComponentModel;
|
||||
using System.Data;
|
||||
|
||||
using Gtk;
|
||||
using System.Drawing;
|
||||
|
||||
namespace NPlot { namespace Gtk {
|
||||
|
||||
public class PlotSurface2D : DrawingArea, IPlotSurface2D {
|
||||
NPlot.PlotSurface2D ps;
|
||||
/*Axis xAxis1Cache;
|
||||
Axis yAxis1Cache;
|
||||
Axis xAxis2Cache;
|
||||
Axis yAxis2Cache;*/
|
||||
|
||||
// The cache.
|
||||
System.Drawing.Bitmap bitmap_cache;
|
||||
Gdk.Rectangle current_allocation; // The current allocation.
|
||||
bool allocated = false;
|
||||
|
||||
public PlotSurface2D (IntPtr x) : base (x)
|
||||
{
|
||||
Console.WriteLine (Environment.StackTrace);
|
||||
}
|
||||
|
||||
public PlotSurface2D ()
|
||||
{
|
||||
ps = new NPlot.PlotSurface2D ();
|
||||
CanFocus = false;
|
||||
SetSizeRequest (200, 200);
|
||||
}
|
||||
|
||||
public void Refresh ()
|
||||
{
|
||||
UpdateCache ();
|
||||
QueueDrawArea (0, 0, Allocation.Width, Allocation.Height);
|
||||
}
|
||||
|
||||
protected override bool OnExposeEvent (Gdk.EventExpose args)
|
||||
{
|
||||
Gdk.Rectangle area = args.Area;
|
||||
|
||||
Console.WriteLine (area);
|
||||
using (Graphics g = Gdk.Graphics.FromDrawable (args.Window)){
|
||||
Rectangle bounds = new Rectangle (area.X, area.Y, area.Width, area.Height);
|
||||
|
||||
g.DrawImage (bitmap_cache, bounds, bounds, GraphicsUnit.Pixel);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
protected override void OnSizeAllocated (Gdk.Rectangle allocation)
|
||||
{
|
||||
allocated = true;
|
||||
current_allocation = allocation;
|
||||
UpdateCache ();
|
||||
base.OnSizeAllocated (allocation);
|
||||
}
|
||||
|
||||
void UpdateCache ()
|
||||
{
|
||||
if (!allocated)
|
||||
return;
|
||||
|
||||
if (bitmap_cache != null)
|
||||
bitmap_cache.Dispose ();
|
||||
|
||||
bitmap_cache = new System.Drawing.Bitmap (current_allocation.Width, current_allocation.Height);
|
||||
using (Graphics g = Graphics.FromImage (bitmap_cache)){
|
||||
Rectangle bounds = new Rectangle (
|
||||
0, 0, current_allocation.Width, current_allocation.Height);
|
||||
ps.Draw (g, bounds);
|
||||
}
|
||||
}
|
||||
|
||||
#region IPlotSurface2D interface implementation
|
||||
|
||||
public void Add (IDrawable p, int zOrder)
|
||||
{
|
||||
ps.Add (p, zOrder);
|
||||
}
|
||||
|
||||
public void Add (IDrawable p)
|
||||
{
|
||||
ps.Add (p);
|
||||
}
|
||||
|
||||
|
||||
public void Add (IDrawable p, NPlot.PlotSurface2D.XAxisPosition xp, NPlot.PlotSurface2D.YAxisPosition yp)
|
||||
{
|
||||
ps.Add (p, xp, yp);
|
||||
}
|
||||
|
||||
public void Add (NPlot.IDrawable p, NPlot.PlotSurface2D.XAxisPosition xp, NPlot.PlotSurface2D.YAxisPosition yp, int zOrder)
|
||||
{
|
||||
ps.Add (p, xp, yp, zOrder);
|
||||
}
|
||||
|
||||
public void Clear()
|
||||
{
|
||||
ps.Clear ();
|
||||
}
|
||||
|
||||
public NPlot.Legend Legend {
|
||||
get {
|
||||
return ps.Legend;
|
||||
}
|
||||
|
||||
set {
|
||||
ps.Legend = value;
|
||||
}
|
||||
}
|
||||
|
||||
public int Padding {
|
||||
get {
|
||||
return ps.Padding;
|
||||
}
|
||||
|
||||
set {
|
||||
ps.Padding = value;
|
||||
}
|
||||
}
|
||||
|
||||
public int LegendZOrder {
|
||||
get {
|
||||
return ps.LegendZOrder;
|
||||
}
|
||||
|
||||
set {
|
||||
ps.LegendZOrder = value;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
public System.Drawing.Color PlotBackColor {
|
||||
set {
|
||||
ps.PlotBackColor = value;
|
||||
}
|
||||
}
|
||||
|
||||
public System.Drawing.Bitmap PlotBackImage
|
||||
{
|
||||
set {
|
||||
ps.PlotBackImage = value;
|
||||
}
|
||||
}
|
||||
|
||||
public IRectangleBrush PlotBackBrush
|
||||
{
|
||||
set {
|
||||
ps.PlotBackBrush = value;
|
||||
}
|
||||
}
|
||||
|
||||
public Color TitleColor
|
||||
{
|
||||
set
|
||||
{
|
||||
ps.TitleColor = value;
|
||||
}
|
||||
}
|
||||
|
||||
public Brush TitleBrush
|
||||
{
|
||||
get
|
||||
{
|
||||
return ps.TitleBrush;
|
||||
}
|
||||
set
|
||||
{
|
||||
ps.TitleBrush = value;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Gets an array list containing all drawables currently added to the PlotSurface2D.
|
||||
/// </summary>
|
||||
public ArrayList Drawables
|
||||
{
|
||||
get
|
||||
{
|
||||
return ps.Drawables;
|
||||
}
|
||||
}
|
||||
|
||||
public void Remove (IDrawable p, bool updateAxes)
|
||||
{
|
||||
ps.Remove(p, updateAxes);
|
||||
}
|
||||
|
||||
public string Title {
|
||||
get {
|
||||
return ps.Title;
|
||||
}
|
||||
|
||||
set {
|
||||
ps.Title = value;
|
||||
}
|
||||
}
|
||||
|
||||
public System.Drawing.Font TitleFont {
|
||||
get {
|
||||
return ps.TitleFont;
|
||||
}
|
||||
|
||||
set {
|
||||
ps.TitleFont = value;
|
||||
}
|
||||
}
|
||||
|
||||
public System.Drawing.Drawing2D.SmoothingMode SmoothingMode {
|
||||
get {
|
||||
return ps.SmoothingMode;
|
||||
}
|
||||
set {
|
||||
ps.SmoothingMode = value;
|
||||
}
|
||||
}
|
||||
|
||||
public void AddAxesConstraint (AxesConstraint c)
|
||||
{
|
||||
ps.AddAxesConstraint (c);
|
||||
}
|
||||
|
||||
public Axis XAxis1 {
|
||||
get {
|
||||
return ps.XAxis1;
|
||||
}
|
||||
set
|
||||
{
|
||||
ps.XAxis1 = value;
|
||||
}
|
||||
}
|
||||
|
||||
public Axis YAxis1 {
|
||||
get {
|
||||
return ps.YAxis1;
|
||||
}
|
||||
|
||||
set {
|
||||
ps.YAxis1 = value;
|
||||
}
|
||||
}
|
||||
|
||||
public Axis XAxis2 {
|
||||
get {
|
||||
return ps.XAxis2;
|
||||
}
|
||||
|
||||
set {
|
||||
ps.XAxis2 = value;
|
||||
}
|
||||
}
|
||||
|
||||
public Axis YAxis2 {
|
||||
get {
|
||||
return ps.YAxis2;
|
||||
}
|
||||
set {
|
||||
ps.YAxis2 = value;
|
||||
}
|
||||
}
|
||||
|
||||
public bool AutoScaleTitle {
|
||||
get {
|
||||
return ps.AutoScaleTitle;
|
||||
}
|
||||
|
||||
set {
|
||||
ps.AutoScaleTitle = value;
|
||||
}
|
||||
}
|
||||
|
||||
public bool AutoScaleAutoGeneratedAxes {
|
||||
get {
|
||||
return ps.AutoScaleAutoGeneratedAxes;
|
||||
}
|
||||
|
||||
set {
|
||||
ps.AutoScaleAutoGeneratedAxes = value;
|
||||
}
|
||||
}
|
||||
|
||||
public System.Drawing.Bitmap Bitmap {
|
||||
get { return bitmap_cache;}
|
||||
}
|
||||
|
||||
public int Width {
|
||||
get { return current_allocation.Width; }
|
||||
}
|
||||
|
||||
public int Height {
|
||||
get { return current_allocation.Height;}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
} }
|
||||
}
|
|
@ -0,0 +1,521 @@
|
|||
/*
|
||||
NPlot - A charting library for .NET
|
||||
|
||||
HistogramPlot.cs
|
||||
Copyright (C) 2003
|
||||
Matt Howlett, Paolo Pierini
|
||||
|
||||
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;
|
||||
using System.Collections;
|
||||
|
||||
namespace NPlot
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// Provides ability to draw histogram plots.
|
||||
/// </summary>
|
||||
public class HistogramPlot : BaseSequencePlot, IPlot, ISequencePlot
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// Set/Get the brush to use if the histogram is filled.
|
||||
/// </summary>
|
||||
public IRectangleBrush RectangleBrush
|
||||
{
|
||||
get
|
||||
{
|
||||
return rectangleBrush_;
|
||||
}
|
||||
set
|
||||
{
|
||||
rectangleBrush_ = value;
|
||||
}
|
||||
|
||||
}
|
||||
private IRectangleBrush rectangleBrush_ = new RectangleBrushes.Solid( Color.Black );
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Constructor
|
||||
/// </summary>
|
||||
public HistogramPlot()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Renders the histogram.
|
||||
/// </summary>
|
||||
/// <param name="g">The 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( Graphics g, PhysicalAxis xAxis, PhysicalAxis yAxis )
|
||||
{
|
||||
SequenceAdapter data =
|
||||
new SequenceAdapter( this.DataSource, this.DataMember, this.OrdinateData, this.AbscissaData );
|
||||
|
||||
float yoff;
|
||||
|
||||
for ( int i=0; i<data.Count; ++i )
|
||||
{
|
||||
|
||||
// (1) determine the top left hand point of the bar (assuming not centered)
|
||||
PointD p1 = data[i];
|
||||
if ( double.IsNaN(p1.X) || double.IsNaN(p1.Y) )
|
||||
continue;
|
||||
|
||||
// (2) determine the top right hand point of the bar (assuming not centered)
|
||||
PointD p2;
|
||||
if (i+1 != data.Count)
|
||||
{
|
||||
p2 = data[i+1];
|
||||
if ( double.IsNaN(p2.X) || double.IsNaN(p2.Y) )
|
||||
continue;
|
||||
p2.Y = p1.Y;
|
||||
}
|
||||
else if (i != 0)
|
||||
{
|
||||
p2 = data[i-1];
|
||||
if ( double.IsNaN(p2.X) || double.IsNaN(p2.Y) )
|
||||
continue;
|
||||
double offset = p1.X - p2.X;
|
||||
p2.X = p1.X + offset;
|
||||
p2.Y = p1.Y;
|
||||
}
|
||||
else
|
||||
{
|
||||
double offset = 1.0f;
|
||||
p2.X = p1.X + offset;
|
||||
p2.Y = p1.Y;
|
||||
}
|
||||
|
||||
// (3) now account for plots this may be stacked on top of.
|
||||
HistogramPlot currentPlot = this;
|
||||
yoff = 0.0f;
|
||||
double yval = 0.0f;
|
||||
while (currentPlot.isStacked_)
|
||||
{
|
||||
SequenceAdapter stackedToData = new SequenceAdapter(
|
||||
currentPlot.stackedTo_.DataSource,
|
||||
currentPlot.stackedTo_.DataMember,
|
||||
currentPlot.stackedTo_.OrdinateData,
|
||||
currentPlot.stackedTo_.AbscissaData );
|
||||
|
||||
yval += stackedToData[i].Y;
|
||||
yoff = yAxis.WorldToPhysical( yval, false ).Y;
|
||||
p1.Y += stackedToData[i].Y;
|
||||
p2.Y += stackedToData[i].Y;
|
||||
currentPlot = currentPlot.stackedTo_;
|
||||
}
|
||||
|
||||
// (4) now account for centering
|
||||
if ( center_ )
|
||||
{
|
||||
double offset = ( p2.X - p1.X ) / 2.0f;
|
||||
p1.X -= offset;
|
||||
p2.X -= offset;
|
||||
}
|
||||
|
||||
// (5) now account for BaseOffset (shift of bar sideways).
|
||||
p1.X += baseOffset_;
|
||||
p2.X += baseOffset_;
|
||||
|
||||
// (6) now get physical coordinates of top two points.
|
||||
PointF xPos1 = xAxis.WorldToPhysical( p1.X, false );
|
||||
PointF yPos1 = yAxis.WorldToPhysical( p1.Y, false );
|
||||
PointF xPos2 = xAxis.WorldToPhysical( p2.X, false );
|
||||
PointF yPos2 = yAxis.WorldToPhysical( p2.Y, false );
|
||||
|
||||
if (isStacked_)
|
||||
{
|
||||
currentPlot = this;
|
||||
while (currentPlot.isStacked_)
|
||||
{
|
||||
currentPlot = currentPlot.stackedTo_;
|
||||
}
|
||||
this.baseWidth_ = currentPlot.baseWidth_;
|
||||
}
|
||||
|
||||
float width = xPos2.X - xPos1.X;
|
||||
float height;
|
||||
if (isStacked_)
|
||||
{
|
||||
height = -yPos1.Y+yoff;
|
||||
}
|
||||
else
|
||||
{
|
||||
height = -yPos1.Y+yAxis.PhysicalMin.Y;
|
||||
}
|
||||
|
||||
float xoff = (1.0f - baseWidth_)/2.0f*width;
|
||||
Rectangle r = new Rectangle( (int)(xPos1.X+xoff), (int)yPos1.Y, (int)(width-2*xoff), (int)height );
|
||||
|
||||
if (this.Filled)
|
||||
{
|
||||
if (r.Height != 0 && r.Width != 0)
|
||||
{
|
||||
// room for optimization maybe.
|
||||
g.FillRectangle( rectangleBrush_.Get(r), r );
|
||||
}
|
||||
}
|
||||
|
||||
g.DrawRectangle( Pen, r.X, r.Y, r.Width, r.Height );
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Whether or not the histogram columns will be filled.
|
||||
/// </summary>
|
||||
public bool Filled
|
||||
{
|
||||
get
|
||||
{
|
||||
return filled_;
|
||||
}
|
||||
set
|
||||
{
|
||||
filled_ = value;
|
||||
}
|
||||
}
|
||||
private bool filled_ = false;
|
||||
|
||||
|
||||
private float baseWidth_ = 1.0f;
|
||||
/// <summary>
|
||||
/// The width of the histogram bar as a proportion of the data spacing
|
||||
/// (in range 0.0 - 1.0).
|
||||
/// </summary>
|
||||
public float BaseWidth
|
||||
{
|
||||
get
|
||||
{
|
||||
return baseWidth_;
|
||||
}
|
||||
set
|
||||
{
|
||||
if (value > 0.0 && value <= 1.0)
|
||||
{
|
||||
baseWidth_ = value;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new NPlotException( "Base width must be between 0.0 and 1.0" );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Returns an x-axis that is suitable for drawing this plot.
|
||||
/// </summary>
|
||||
/// <returns>A suitable x-axis.</returns>
|
||||
public Axis SuggestXAxis()
|
||||
{
|
||||
SequenceAdapter data =
|
||||
new SequenceAdapter( this.DataSource, this.DataMember, this.OrdinateData, this.AbscissaData );
|
||||
|
||||
Axis a = data.SuggestXAxis();
|
||||
|
||||
PointD p1;
|
||||
PointD p2;
|
||||
PointD p3;
|
||||
PointD p4;
|
||||
if (data.Count < 2)
|
||||
{
|
||||
p1 = data[0];
|
||||
p1.X -= 1.0;
|
||||
p2 = data[0];
|
||||
p3 = p1;
|
||||
p4 = p2;
|
||||
}
|
||||
else
|
||||
{
|
||||
p1 = data[0];
|
||||
p2 = data[1];
|
||||
p3 = data[data.Count-2];
|
||||
p4 = data[data.Count-1];
|
||||
}
|
||||
|
||||
double offset1;
|
||||
double offset2;
|
||||
|
||||
if (!center_)
|
||||
{
|
||||
offset1 = 0.0f;
|
||||
offset2 = p4.X - p3.X;
|
||||
}
|
||||
else
|
||||
{
|
||||
offset1 = (p2.X - p1.X)/2.0f;
|
||||
offset2 = (p4.X - p3.X)/2.0f;
|
||||
}
|
||||
|
||||
a.WorldMin -= offset1;
|
||||
a.WorldMax += offset2;
|
||||
|
||||
return a;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Returns a y-axis that is suitable for drawing this plot.
|
||||
/// </summary>
|
||||
/// <returns>A suitable y-axis.</returns>
|
||||
public Axis SuggestYAxis()
|
||||
{
|
||||
|
||||
if ( this.isStacked_ )
|
||||
{
|
||||
double tmpMax = 0.0f;
|
||||
ArrayList adapterList = new ArrayList();
|
||||
|
||||
HistogramPlot currentPlot = this;
|
||||
do
|
||||
{
|
||||
adapterList.Add( new SequenceAdapter(
|
||||
currentPlot.DataSource,
|
||||
currentPlot.DataMember,
|
||||
currentPlot.OrdinateData,
|
||||
currentPlot.AbscissaData )
|
||||
);
|
||||
} while ((currentPlot = currentPlot.stackedTo_) != null);
|
||||
|
||||
SequenceAdapter[] adapters =
|
||||
(SequenceAdapter[])adapterList.ToArray(typeof(SequenceAdapter));
|
||||
|
||||
for (int i=0; i<adapters[0].Count; ++i)
|
||||
{
|
||||
double tmpHeight = 0.0f;
|
||||
for (int j=0; j<adapters.Length; ++j)
|
||||
{
|
||||
tmpHeight += adapters[j][i].Y;
|
||||
}
|
||||
tmpMax = Math.Max(tmpMax, tmpHeight);
|
||||
}
|
||||
|
||||
Axis a = new LinearAxis(0.0f,tmpMax);
|
||||
// TODO make 0.08 a parameter.
|
||||
a.IncreaseRange( 0.08 );
|
||||
return a;
|
||||
}
|
||||
else
|
||||
{
|
||||
SequenceAdapter data =
|
||||
new SequenceAdapter( this.DataSource, this.DataMember, this.OrdinateData, this.AbscissaData );
|
||||
|
||||
return data.SuggestYAxis();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
private double centerLine_ = 0.0;
|
||||
/// <summary>
|
||||
/// Histogram bars extend from the data value to this value. Default value is 0.
|
||||
/// </summary>
|
||||
public double CenterLine
|
||||
{
|
||||
get
|
||||
{
|
||||
return centerLine_;
|
||||
}
|
||||
set
|
||||
{
|
||||
centerLine_ = value;
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
private bool center_ = true;
|
||||
/// <summary>
|
||||
/// If true, each histogram column will be centered on the associated abscissa value.
|
||||
/// If false, each histogram colum will be drawn between the associated abscissa value, and the next abscissa value.
|
||||
/// Default value is true.
|
||||
/// </summary>
|
||||
public bool Center
|
||||
{
|
||||
set
|
||||
{
|
||||
center_ = value;
|
||||
}
|
||||
get
|
||||
{
|
||||
return center_;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// If this histogram plot has another stacked on top, this will be true. Else false.
|
||||
/// </summary>
|
||||
public bool IsStacked
|
||||
{
|
||||
get
|
||||
{
|
||||
return isStacked_;
|
||||
}
|
||||
}
|
||||
private bool isStacked_;
|
||||
|
||||
|
||||
private HistogramPlot stackedTo_;
|
||||
/// <summary>
|
||||
/// Stack the histogram to another HistogramPlot.
|
||||
/// </summary>
|
||||
public void StackedTo(HistogramPlot hp)
|
||||
{
|
||||
SequenceAdapter data =
|
||||
new SequenceAdapter( this.DataSource, this.DataMember, this.OrdinateData, this.AbscissaData );
|
||||
|
||||
SequenceAdapter hpData =
|
||||
new SequenceAdapter( hp.DataSource, hp.DataMember, hp.OrdinateData, hp.AbscissaData );
|
||||
|
||||
if ( hp != null )
|
||||
{
|
||||
isStacked_ = true;
|
||||
if ( hpData.Count != data.Count )
|
||||
{
|
||||
throw new NPlotException("Can stack HistogramPlot data only with the same number of datapoints.");
|
||||
}
|
||||
for ( int i=0; i < data.Count; ++i )
|
||||
{
|
||||
if ( data[i].X != hpData[i].X )
|
||||
{
|
||||
throw new NPlotException("Can stack HistogramPlot data only with the same X coordinates.");
|
||||
}
|
||||
if ( hpData[i].Y < 0.0f)
|
||||
{
|
||||
throw new NPlotException("Can stack HistogramPlot data only with positive Y coordinates.");
|
||||
}
|
||||
}
|
||||
}
|
||||
stackedTo_ = hp;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Draws a representation of this plot in the legend.
|
||||
/// </summary>
|
||||
/// <param name="g">The graphics surface on which to draw.</param>
|
||||
/// <param name="startEnd">A rectangle specifying the bounds of the area in the legend set aside for drawing.</param>
|
||||
public void DrawInLegend( Graphics g, Rectangle startEnd )
|
||||
{
|
||||
|
||||
if (Filled)
|
||||
{
|
||||
g.FillRectangle( rectangleBrush_.Get(startEnd), startEnd );
|
||||
}
|
||||
|
||||
g.DrawRectangle( Pen, startEnd.X, startEnd.Y, startEnd.Width, startEnd.Height );
|
||||
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// The pen used to draw the plot
|
||||
/// </summary>
|
||||
public System.Drawing.Pen Pen
|
||||
{
|
||||
get
|
||||
{
|
||||
return pen_;
|
||||
}
|
||||
set
|
||||
{
|
||||
pen_ = value;
|
||||
}
|
||||
}
|
||||
private System.Drawing.Pen pen_ = new Pen(Color.Black);
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// The color of the pen used to draw lines in this plot.
|
||||
/// </summary>
|
||||
public System.Drawing.Color Color
|
||||
{
|
||||
set
|
||||
{
|
||||
if (pen_ != null)
|
||||
{
|
||||
pen_.Color = value;
|
||||
}
|
||||
else
|
||||
{
|
||||
pen_ = new Pen(value);
|
||||
}
|
||||
}
|
||||
get
|
||||
{
|
||||
return pen_.Color;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Horizontal position of histogram columns is offset by this much (in world coordinates).
|
||||
/// </summary>
|
||||
public double BaseOffset
|
||||
{
|
||||
set
|
||||
{
|
||||
baseOffset_ = value;
|
||||
}
|
||||
get
|
||||
{
|
||||
return baseOffset_;
|
||||
}
|
||||
}
|
||||
private double baseOffset_;
|
||||
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,287 @@
|
|||
/*
|
||||
NPlot - A charting library for .NET
|
||||
|
||||
HorizontalLine.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>
|
||||
/// Encapsulates functionality for drawing a horizontal line on a plot surface.
|
||||
/// </summary>
|
||||
public class HorizontalLine : IPlot
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// Constructor
|
||||
/// </summary>
|
||||
/// <param name="ordinateValue">ordinate (Y) value of line.</param>
|
||||
public HorizontalLine( double ordinateValue )
|
||||
{
|
||||
this.value_ = ordinateValue;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Constructor
|
||||
/// </summary>
|
||||
/// <param name="ordinateValue">ordinate (Y) value of line.</param>
|
||||
/// <param name="color">draw the line using this color.</param>
|
||||
public HorizontalLine( double ordinateValue, Color color )
|
||||
{
|
||||
this.value_ = ordinateValue;
|
||||
this.pen_ = new Pen( color );
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructor
|
||||
/// </summary>
|
||||
/// <param name="ordinateValue">ordinate (Y) value of line.</param>
|
||||
/// <param name="pen">Pen to use to draw the line.</param>
|
||||
public HorizontalLine( double ordinateValue, Pen pen )
|
||||
{
|
||||
this.value_ = ordinateValue;
|
||||
this.pen_ = pen;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Draws a representation of the horizontal line in the legend.
|
||||
/// </summary>
|
||||
/// <param name="g">The graphics surface on which to draw</param>
|
||||
/// <param name="startEnd">A rectangle specifying the bounds of the area in the legend set aside for drawing.</param>
|
||||
public void DrawInLegend(System.Drawing.Graphics g, System.Drawing.Rectangle startEnd)
|
||||
{
|
||||
g.DrawLine( pen_, startEnd.Left, (startEnd.Top + startEnd.Bottom)/2,
|
||||
startEnd.Right, (startEnd.Top + startEnd.Bottom)/2 );
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// A label to associate with the plot - used in the legend.
|
||||
/// </summary>
|
||||
public string Label
|
||||
{
|
||||
get
|
||||
{
|
||||
return label_;
|
||||
}
|
||||
set
|
||||
{
|
||||
this.label_ = value;
|
||||
}
|
||||
}
|
||||
|
||||
private string label_ = "";
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Whether or not to include an entry for this plot in the legend if it exists.
|
||||
/// </summary>
|
||||
public bool ShowInLegend
|
||||
{
|
||||
get
|
||||
{
|
||||
return showInLegend_;
|
||||
}
|
||||
set
|
||||
{
|
||||
this.showInLegend_ = value;
|
||||
}
|
||||
}
|
||||
private bool showInLegend_ = false;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Returns null indicating that x extremities of the line are variable.
|
||||
/// </summary>
|
||||
/// <returns>null</returns>
|
||||
public Axis SuggestXAxis()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Returns a y-axis that is suitable for drawing this plot.
|
||||
/// </summary>
|
||||
/// <returns>A suitable y-axis.</returns>
|
||||
public Axis SuggestYAxis()
|
||||
{
|
||||
return new LinearAxis( this.value_, this.value_ );
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes text data describing the horizontal line object to the supplied string builder. It is
|
||||
/// possible to specify that the data will be written only if the line is in the specified
|
||||
/// region.
|
||||
/// </summary>
|
||||
/// <param name="sb">the StringBuilder object to write to.</param>
|
||||
/// <param name="region">a region used if onlyInRegion is true.</param>
|
||||
/// <param name="onlyInRegion">If true, data will be written only if the line is in the specified region.</param>
|
||||
public void WriteData(System.Text.StringBuilder sb, RectangleD region, bool onlyInRegion)
|
||||
{
|
||||
|
||||
// return if line is not in plot region and
|
||||
if (value_ > region.Y+region.Height || value_ < region.Y)
|
||||
{
|
||||
if (onlyInRegion)
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
sb.Append( "Label: " );
|
||||
sb.Append( this.Label );
|
||||
sb.Append( "\r\n" );
|
||||
sb.Append( value_.ToString() );
|
||||
sb.Append( "\r\n" );
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Draws the horizontal line plot on a GDI+ surface against the provided x and y axes.
|
||||
/// </summary>
|
||||
/// <param name="g">The GDI+ 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)
|
||||
{
|
||||
int xMin = xAxis.PhysicalMin.X;
|
||||
int xMax = xAxis.PhysicalMax.X;
|
||||
|
||||
xMin += pixelIndent_;
|
||||
xMax -= pixelIndent_;
|
||||
|
||||
float length = Math.Abs(xMax - xMin);
|
||||
float lengthDiff = length - length*scale_;
|
||||
float indentAmount = lengthDiff/2;
|
||||
|
||||
xMin += (int)indentAmount;
|
||||
xMax -= (int)indentAmount;
|
||||
|
||||
int yPos = (int)yAxis.WorldToPhysical( value_, false ).Y;
|
||||
|
||||
g.DrawLine( pen_, new System.Drawing.Point( xMin, yPos ), new System.Drawing.Point( xMax, yPos ) );
|
||||
|
||||
// todo: clip and proper logic for flipped axis min max.
|
||||
}
|
||||
|
||||
private double value_;
|
||||
/// <summary>
|
||||
/// ordinate (Y) value to draw horizontal line at.
|
||||
/// </summary>
|
||||
public double OrdinateValue
|
||||
{
|
||||
get
|
||||
{
|
||||
return value_;
|
||||
}
|
||||
set
|
||||
{
|
||||
value_ = value;
|
||||
}
|
||||
}
|
||||
|
||||
private Pen pen_ = new Pen( Color.Black );
|
||||
/// <summary>
|
||||
/// Pen to use to draw the horizontal line.
|
||||
/// </summary>
|
||||
public Pen Pen
|
||||
{
|
||||
get
|
||||
{
|
||||
return pen_;
|
||||
}
|
||||
set
|
||||
{
|
||||
pen_ = value;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Each end of the line is indented by this many pixels.
|
||||
/// </summary>
|
||||
public int PixelIndent
|
||||
{
|
||||
get
|
||||
{
|
||||
return pixelIndent_;
|
||||
}
|
||||
set
|
||||
{
|
||||
pixelIndent_ = value;
|
||||
}
|
||||
}
|
||||
private int pixelIndent_ = 0;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// The line length is multiplied by this amount. Default
|
||||
/// corresponds to a value of 1.0.
|
||||
/// </summary>
|
||||
public float LengthScale
|
||||
{
|
||||
get
|
||||
{
|
||||
return scale_;
|
||||
}
|
||||
set
|
||||
{
|
||||
scale_ = value;
|
||||
}
|
||||
}
|
||||
private float scale_ = 1.0f;
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,72 @@
|
|||
/*
|
||||
NPlot - A charting library for .NET
|
||||
|
||||
IDrawable.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>
|
||||
/// Defines a Draw method for drawing objects against an x and y
|
||||
/// Physical Axis.
|
||||
/// </summary>
|
||||
public interface IDrawable
|
||||
{
|
||||
/// <summary>
|
||||
/// Draws this object against an x and y PhysicalAxis.
|
||||
/// </summary>
|
||||
/// <param name="g">The graphics surface on which to draw.</param>
|
||||
/// <param name="xAxis">The physical x-axis to draw against.</param>
|
||||
/// <param name="yAxis">The physical y-axis to draw against.</param>
|
||||
void Draw( Graphics g, PhysicalAxis xAxis, PhysicalAxis yAxis );
|
||||
}
|
||||
}
|
|
@ -0,0 +1,27 @@
|
|||
// ******** experimental ********
|
||||
/*
|
||||
using System;
|
||||
using System.Drawing;
|
||||
|
||||
namespace NPlot
|
||||
{
|
||||
/// <summary>
|
||||
/// Defines a Draw method for drawing objects against x, y and z
|
||||
/// Physical Axes.
|
||||
/// </summary>
|
||||
public interface IDrawable3D
|
||||
{
|
||||
/// <summary>
|
||||
/// Draws this object against x, y and z PhysicalAxes.
|
||||
/// </summary>
|
||||
/// <param name="g">The graphics surface on which to draw.</param>
|
||||
/// <param name="xAxis">The physical x-axis to draw against.</param>
|
||||
/// <param name="yAxis">The physical y-axis to draw against.</param>
|
||||
/// <param name="zAxis">The physical z-axis to draw against.</param>
|
||||
/// <remarks>Other or different parameters will probably be needed here - basically
|
||||
/// the supplied parameters need to allow the Draw method to do the world -> physical
|
||||
/// transform.</remarks>
|
||||
void Draw( Graphics g, PhysicalAxis xAxis, PhysicalAxis yAxis, PhysicalAxis zAxis );
|
||||
}
|
||||
}
|
||||
*/
|
|
@ -0,0 +1,73 @@
|
|||
/*
|
||||
NPlot - A charting library for .NET
|
||||
|
||||
IGradient.cs
|
||||
Copyright (C) 2003-2004
|
||||
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>
|
||||
/// Defines a gradient.
|
||||
/// </summary>
|
||||
public interface IGradient
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// Gets a color corresponding to a number between 0.0 and 1.0 inclusive.
|
||||
/// </summary>
|
||||
/// <param name="prop">the number to get corresponding color for (between 0.0 and 1.0)</param>
|
||||
/// <returns>The color corresponding to the supplied number.</returns>
|
||||
Color GetColor( double prop );
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,49 @@
|
|||
/*
|
||||
NPlot - A charting library for .NET
|
||||
|
||||
IMeshPlot.cs
|
||||
Copyright (C) 2003
|
||||
Matt Howlett
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the following text in
|
||||
the documentation and / or other materials provided with the
|
||||
distribution:
|
||||
|
||||
"This product includes software developed as part of
|
||||
the NPlot charting library project available from:
|
||||
http://www.nplot.com/"
|
||||
|
||||
------------------------------------------------------------------------
|
||||
|
||||
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.
|
||||
|
||||
$Id: IMeshPlot.cs,v 1.9 2004/10/23 07:08:35 mhowlett Exp $
|
||||
|
||||
*/
|
||||
|
||||
namespace NPlot
|
||||
{
|
||||
/// <summary>
|
||||
/// TODO
|
||||
/// </summary>
|
||||
public interface IMeshPlot : IPlot
|
||||
{
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,104 @@
|
|||
/*
|
||||
NPlot - A charting library for .NET
|
||||
|
||||
IPlot.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;
|
||||
|
||||
namespace NPlot
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// Defines the interface for objects that (a) can draw a representation of
|
||||
/// themselves in the legend and (b) can recommend a good axis to draw themselves
|
||||
/// against.
|
||||
/// </summary>
|
||||
public interface IPlot : IDrawable
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// Method used to draw a representation of the plot in a legend.
|
||||
/// </summary>
|
||||
void DrawInLegend( Graphics g, Rectangle startEnd );
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// The label associated with the plot [used in legend]
|
||||
/// </summary>
|
||||
string Label { get; set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Whether or not to include an entry for this plot in the legend if it exists.
|
||||
/// </summary>
|
||||
bool ShowInLegend { get; set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// The method used to set the default abscissa axis.
|
||||
/// </summary>
|
||||
Axis SuggestXAxis();
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// The method used to set the default ordinate axis.
|
||||
/// </summary>
|
||||
Axis SuggestYAxis();
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Write data associated with the plot as text.
|
||||
/// </summary>
|
||||
/// <param name="sb">the string builder to write to.</param>
|
||||
/// <param name="region">Only write out data in this region if onlyInRegion is true.</param>
|
||||
/// <param name="onlyInRegion">If true, only data in region is written, else all data is written.</param>
|
||||
void WriteData( System.Text.StringBuilder sb, RectangleD region, bool onlyInRegion );
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,33 @@
|
|||
/*
|
||||
using System;
|
||||
|
||||
namespace NPlot
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// 3D plottable objects implement this interface.
|
||||
/// </summary>
|
||||
public interface IPlot3D
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// The method used to set the default x axis.
|
||||
/// </summary>
|
||||
Axis SuggestXAxis();
|
||||
|
||||
/// <summary>
|
||||
/// The method used to set the default y axis.
|
||||
/// </summary>
|
||||
Axis SuggestYAxis();
|
||||
|
||||
/// <summary>
|
||||
/// The method used to set the default z axis.
|
||||
/// </summary>
|
||||
Axis SuggestZAxis();
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
*/
|
|
@ -0,0 +1,255 @@
|
|||
/*
|
||||
NPlot - A charting library for .NET
|
||||
|
||||
IPlotSurface2D.cs
|
||||
Copyright (C) 2003
|
||||
Paolo Pierini, 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;
|
||||
|
||||
namespace NPlot
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// Defines the PlotSurface2D interface - All specific PlotSurface2D classes
|
||||
/// that use PlotSurface2D for their underlying operations should implement
|
||||
/// this class.
|
||||
/// </summary>
|
||||
public interface IPlotSurface2D
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// Adds a drawable object to the plot surface. If the object is an IPlot,
|
||||
/// the PlotSurface2D axes will also be updated.
|
||||
/// </summary>
|
||||
/// <param name="p">The IDrawable object to add to the plot surface.</param>
|
||||
/// <param name="zOrder">The z-ordering when drawing (objects with lower numbers are drawn first)</param>
|
||||
void Add( IDrawable p, int zOrder );
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Adds a drawable object to the plot surface against the specified axes. If
|
||||
/// the object is an IPlot, the PlotSurface2D axes will also be updated.
|
||||
/// </summary>
|
||||
/// <param name="p">the IDrawable object to add to the plot surface</param>
|
||||
/// <param name="xp">the x-axis to add the plot against.</param>
|
||||
/// <param name="yp">the y-axis to add the plot against.</param>
|
||||
/// <param name="zOrder">The z-ordering when drawing (objects with lower numbers are drawn first)</param>
|
||||
void Add( IDrawable p, NPlot.PlotSurface2D.XAxisPosition xp, NPlot.PlotSurface2D.YAxisPosition yp, int zOrder );
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Adds a drawable object to the plot surface. If the object is an IPlot,
|
||||
/// the PlotSurface2D axes will also be updated.
|
||||
/// </summary>
|
||||
/// <param name="p">The IDrawable object to add to the plot surface.</param>
|
||||
void Add(IDrawable p);
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Adds a drawable object to the plot surface against the specified axes. If
|
||||
/// the object is an IPlot, the PlotSurface2D axes will also be updated.
|
||||
/// </summary>
|
||||
/// <param name="p">the IDrawable object to add to the plot surface</param>
|
||||
/// <param name="xax">the x-axis to add the plot against.</param>
|
||||
/// <param name="yax">the y-axis to add the plot against.</param>
|
||||
void Add(IDrawable p, NPlot.PlotSurface2D.XAxisPosition xax, NPlot.PlotSurface2D.YAxisPosition yax);
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Clears the PlotSurface2D.
|
||||
/// </summary>
|
||||
void Clear();
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Gets or Sets the legend to use with this plot surface.
|
||||
/// </summary>
|
||||
NPlot.Legend Legend { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Setting this value determines the order (relative to IDrawables added to the plot surface)
|
||||
/// that the legend is drawn.
|
||||
/// </summary>
|
||||
int LegendZOrder { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The distance in pixels to leave between of the edge of the bounding rectangle
|
||||
/// supplied to the Draw method, and the markings that make up the plot.
|
||||
/// </summary>
|
||||
int Padding { get; set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// A color used to paint the plot background. Mutually exclusive with PlotBackImage and PlotBackBrush
|
||||
/// </summary>
|
||||
System.Drawing.Color PlotBackColor { set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// An imaged used to paint the plot background. Mutually exclusive with PlotBackColor and PlotBackBrush
|
||||
/// </summary>
|
||||
System.Drawing.Bitmap PlotBackImage { set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// A Rectangle brush used to paint the plot background. Mutually exclusive with PlotBackColor and PlotBackBrush
|
||||
/// </summary>
|
||||
IRectangleBrush PlotBackBrush { set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// The plot surface title.
|
||||
/// </summary>
|
||||
string Title { get; set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Whether or not the title will be scaled according to size of the plot
|
||||
/// surface.
|
||||
/// </summary>
|
||||
bool AutoScaleTitle { get; set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// When plots are added to the plot surface, the axes they are attached to
|
||||
/// are immediately modified to reflect data of the plot. If
|
||||
/// AutoScaleAutoGeneratedAxes is true when a plot is added, the axes will
|
||||
/// be turned in to auto scaling ones if they are not already [tick marks,
|
||||
/// tick text and label size scaled to size of plot surface]. If false,
|
||||
/// axes will not be autoscaling.
|
||||
/// </summary>
|
||||
bool AutoScaleAutoGeneratedAxes { get; set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Sets the title to be drawn using a solid brush of this color.
|
||||
/// </summary>
|
||||
System.Drawing.Color TitleColor { set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// The brush used for drawing the title.
|
||||
/// </summary>
|
||||
System.Drawing.Brush TitleBrush { get; set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// The plot title font.
|
||||
/// </summary>
|
||||
System.Drawing.Font TitleFont { get; set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Smoothing mode to use when drawing plots.
|
||||
/// </summary>
|
||||
System.Drawing.Drawing2D.SmoothingMode SmoothingMode { get; set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Add an axis constraint to the plot surface. Axis constraints can
|
||||
/// specify relative world-pixel scalings, absolute axis positions etc.
|
||||
/// </summary>
|
||||
/// <param name="c">The axis constraint to add.</param>
|
||||
void AddAxesConstraint( AxesConstraint c );
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// The bottom abscissa axis.
|
||||
/// </summary>
|
||||
Axis XAxis1 { get; set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// The top abscissa axis.
|
||||
/// </summary>
|
||||
Axis XAxis2 { get; set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// The left ordinate axis.
|
||||
/// </summary>
|
||||
Axis YAxis1 { get; set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// The right ordinate axis.
|
||||
/// </summary>
|
||||
Axis YAxis2 { get; set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Remove a drawable object from the plot surface.
|
||||
/// </summary>
|
||||
/// <param name="p">the object to remove</param>
|
||||
/// <param name="updateAxes">whether or not to update the axes after removal.</param>
|
||||
void Remove( IDrawable p, bool updateAxes );
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Gets an array list containing all drawables currently added to the PlotSurface2D.
|
||||
/// </summary>
|
||||
ArrayList Drawables { get; }
|
||||
|
||||
/*
|
||||
/// <summary>
|
||||
/// Calculates axes approprate to IPlots on PlotSurface. Note that
|
||||
/// this is done automatically as a new plot is added. You may wish
|
||||
/// to call this again if you update data in the plot.
|
||||
/// </summary>
|
||||
void AutoCalculateAxes();
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// C
|
||||
/// </summary>
|
||||
/// <param name="p"></param>
|
||||
void UpdateAxes( IPlot p );
|
||||
*/
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
// ******** experimental ********
|
||||
/*
|
||||
namespace NPlot
|
||||
{
|
||||
/// <summary>
|
||||
/// Defines the PlotSurface2Dnew interface - All specific PlotSurface2Dnew classes
|
||||
/// that use PlotSurface2Dnew for their underlying operations should implement
|
||||
/// this class. TODO: this is experimental.
|
||||
/// </summary>
|
||||
public interface IPlotSurface2Dnew
|
||||
{
|
||||
/// <summary>
|
||||
/// The distance in pixels to leave between of the edge of the bounding rectangle
|
||||
/// supplied to the Draw method, and the markings that make up the plot.
|
||||
/// </summary>
|
||||
int Padding { get; set; }
|
||||
}
|
||||
}
|
||||
*/
|
|
@ -0,0 +1,17 @@
|
|||
// ******** experimental ********
|
||||
/*
|
||||
using System;
|
||||
|
||||
namespace NPlot
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// TODO.
|
||||
/// </summary>
|
||||
public interface IPlotSurface3D
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
*/
|
|
@ -0,0 +1,85 @@
|
|||
/*
|
||||
NPlot - A charting library for .NET
|
||||
|
||||
IPlot.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;
|
||||
|
||||
namespace NPlot
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// Defines an mix-in style interface for plots that use SequenceAdapter to interpret supplied data.
|
||||
/// </summary>
|
||||
public interface ISequencePlot
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the source containing a list of values used to populate the plot object.
|
||||
/// </summary>
|
||||
object DataSource { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the specific data member in a multimember data source to get data from.
|
||||
/// </summary>
|
||||
string DataMember { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the data, or column name for the abscissa [x] axis.
|
||||
/// </summary>
|
||||
object AbscissaData { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the data, or column name for the ordinate [y] axis.
|
||||
/// </summary>
|
||||
object OrdinateData { get; set; }
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,98 @@
|
|||
/*
|
||||
NPlot - A charting library for .NET
|
||||
|
||||
ISurface.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.Windows.Forms;
|
||||
|
||||
namespace NPlot
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// All PlotSurface's implement this interface.
|
||||
/// </summary>
|
||||
/// <remarks>Some of the parameter lists will change to be made more uniform.</remarks>
|
||||
public interface ISurface
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// Provides functionality for drawing the control.
|
||||
/// </summary>
|
||||
/// <param name="pe">paint event args</param>
|
||||
/// <param name="width">width of the control.</param>
|
||||
/// <param name="height">height of the control.</param>
|
||||
void DoPaint( PaintEventArgs pe, int width, int height );
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Provides functionality for handling mouse up events.
|
||||
/// </summary>
|
||||
/// <param name="e">mouse event args</param>
|
||||
/// <param name="ctr">the control</param>
|
||||
void DoMouseUp( MouseEventArgs e, System.Windows.Forms.Control ctr );
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Provides functionality for handling mouse move events.
|
||||
/// </summary>
|
||||
/// <param name="e">mouse event args</param>
|
||||
/// <param name="ctr">the control</param>
|
||||
void DoMouseMove( MouseEventArgs e, System.Windows.Forms.Control ctr );
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Provides functionality for handling mouse down events.
|
||||
/// </summary>
|
||||
/// <param name="e">mouse event args</param>
|
||||
void DoMouseDown( MouseEventArgs e );
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,78 @@
|
|||
/*
|
||||
NPlot - A charting library for .NET
|
||||
|
||||
ITransform2D.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>
|
||||
/// This interface is useful in the Plot classes for transforming
|
||||
/// world to physical coordinates. Create on using the GetTransformer
|
||||
/// static method in Transform2D.
|
||||
/// </summary>
|
||||
public interface ITransform2D
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// Transforms the given world point to physical coordinates
|
||||
/// </summary>
|
||||
PointF Transform( double x, double y );
|
||||
|
||||
/// <summary>
|
||||
/// Transforms the given world point to physical coordinates
|
||||
/// </summary>
|
||||
PointF Transform( PointD worldPoint );
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,369 @@
|
|||
/*
|
||||
NPlot - A charting library for .NET
|
||||
|
||||
ImagePlot.cs
|
||||
Copyright (C) 2003-2004
|
||||
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>
|
||||
/// Encapsulates functionality for plotting data as a 2D image chart.
|
||||
/// </summary>
|
||||
public class ImagePlot : IPlot
|
||||
{
|
||||
private double[,] data_;
|
||||
private double xStart_ = 0.0;
|
||||
private double xStep_ = 1.0;
|
||||
private double yStart_ = 0.0;
|
||||
private double yStep_ = 1.0;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// At or below which value a minimum gradient color should be used.
|
||||
/// </summary>
|
||||
public double DataMin
|
||||
{
|
||||
get
|
||||
{
|
||||
return dataMin_;
|
||||
}
|
||||
set
|
||||
{
|
||||
dataMin_ = value;
|
||||
}
|
||||
}
|
||||
private double dataMin_;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// At or above which value a maximum gradient color should be used.
|
||||
/// </summary>
|
||||
public double DataMax
|
||||
{
|
||||
get
|
||||
{
|
||||
return dataMax_;
|
||||
}
|
||||
set
|
||||
{
|
||||
dataMax_ = value;
|
||||
}
|
||||
}
|
||||
private double dataMax_;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Calculates the minimum and maximum values of the data array.
|
||||
/// </summary>
|
||||
private void calculateMinMax()
|
||||
{
|
||||
dataMin_ = data_[0,0];
|
||||
dataMax_ = data_[0,0];
|
||||
for (int i=0; i<data_.GetLength(0); ++i)
|
||||
{
|
||||
for (int j=0; j<data_.GetLength(1); ++j)
|
||||
{
|
||||
if (data_[i,j]<dataMin_)
|
||||
{
|
||||
dataMin_ = data_[i,j];
|
||||
}
|
||||
if (data_[i,j]>dataMax_)
|
||||
{
|
||||
dataMax_ = data_[i,j];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Constructor
|
||||
/// </summary>
|
||||
/// <param name="data">the 2D array to plot</param>
|
||||
/// <param name="xStart">the world value corresponding to the 1st position in the x-direction</param>
|
||||
/// <param name="xStep">the world step size between pixels in the x-direction.</param>
|
||||
/// <param name="yStart">the world value corresponding to the 1st position in the y-direction</param>
|
||||
/// <param name="yStep">the world step size between pixels in the y-direction.</param>
|
||||
/// <remarks>no adapters for this yet - when we get some more 2d
|
||||
/// plotting functionality, then perhaps create some.</remarks>
|
||||
public ImagePlot( double[,] data, double xStart, double xStep, double yStart, double yStep )
|
||||
{
|
||||
|
||||
#if CHECK_ERRORS
|
||||
if (data == null || data.GetLength(0) == 0 || data.GetLength(1) == 0)
|
||||
{
|
||||
throw new NPlotException( "ERROR: ImagePlot.ImagePlot: Data null, or zero length" );
|
||||
}
|
||||
#endif
|
||||
|
||||
this.data_ = data;
|
||||
this.xStart_ = xStart;
|
||||
this.xStep_ = xStep;
|
||||
this.yStart_ = yStart;
|
||||
this.yStep_ = yStep;
|
||||
this.calculateMinMax();
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Constructor
|
||||
/// </summary>
|
||||
/// <param name="data">The 2D array to plot.</param>
|
||||
public ImagePlot( double[,] data )
|
||||
{
|
||||
this.data_ = data;
|
||||
this.calculateMinMax();
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Draw on to the supplied graphics surface against the supplied axes.
|
||||
/// </summary>
|
||||
/// <param name="g">The 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>
|
||||
/// <remarks>TODO: block positions may be off by a pixel or so. maybe. Re-think calculations</remarks>
|
||||
public void Draw( Graphics g, PhysicalAxis xAxis, PhysicalAxis yAxis )
|
||||
{
|
||||
if ( data_==null || data_.GetLength(0) == 0 || data_.GetLength(1) == 0 )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
double worldWidth = xAxis.Axis.WorldMax - xAxis.Axis.WorldMin;
|
||||
double numBlocksHorizontal = worldWidth / this.xStep_;
|
||||
double worldHeight = yAxis.Axis.WorldMax - yAxis.Axis.WorldMin;
|
||||
double numBlocksVertical = worldHeight / this.yStep_;
|
||||
|
||||
double physicalWidth = xAxis.PhysicalMax.X - xAxis.PhysicalMin.X;
|
||||
double blockWidth = physicalWidth / numBlocksHorizontal;
|
||||
bool wPositive = true;
|
||||
if (blockWidth < 0.0)
|
||||
{
|
||||
wPositive = false;
|
||||
}
|
||||
blockWidth = Math.Abs(blockWidth)+1;
|
||||
|
||||
double physicalHeight = yAxis.PhysicalMax.Y - yAxis.PhysicalMin.Y;
|
||||
double blockHeight = physicalHeight / numBlocksVertical;
|
||||
bool hPositive = true;
|
||||
if (blockHeight < 0.0)
|
||||
{
|
||||
hPositive = false;
|
||||
}
|
||||
blockHeight = Math.Abs(blockHeight)+1;
|
||||
|
||||
for (int i=0; i<data_.GetLength(0); ++i)
|
||||
{
|
||||
for (int j=0; j<data_.GetLength(1); ++j)
|
||||
{
|
||||
double wX = (double)j*this.xStep_ + xStart_;
|
||||
double wY = (double)i*this.yStep_ + yStart_;
|
||||
if ( !hPositive )
|
||||
{
|
||||
wY += yStep_;
|
||||
}
|
||||
if (!wPositive )
|
||||
{
|
||||
wX += xStep_;
|
||||
}
|
||||
|
||||
if (this.center_)
|
||||
{
|
||||
wX -= this.xStep_/2.0;
|
||||
wY -= this.yStep_/2.0;
|
||||
}
|
||||
Pen p = new Pen( this.Gradient.GetColor( (data_[i,j]-this.dataMin_)/(this.dataMax_-this.dataMin_) ) );
|
||||
int x = (int)xAxis.WorldToPhysical(wX,false).X;
|
||||
int y = (int)yAxis.WorldToPhysical(wY,false).Y;
|
||||
g.FillRectangle( p.Brush,
|
||||
x,
|
||||
y,
|
||||
(int)blockWidth,
|
||||
(int)blockHeight);
|
||||
//g.DrawRectangle(Pens.White,x,y,(int)blockWidth,(int)blockHeight);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// The gradient that specifies the mapping between value and color.
|
||||
/// </summary>
|
||||
/// <remarks>memory allocation in get may be inefficient.</remarks>
|
||||
public IGradient Gradient
|
||||
{
|
||||
get
|
||||
{
|
||||
if (gradient_ == null)
|
||||
{
|
||||
// TODO: suboptimal.
|
||||
gradient_ = new LinearGradient( Color.FromArgb(255,255,255), Color.FromArgb(0,0,0) );
|
||||
}
|
||||
return this.gradient_;
|
||||
}
|
||||
set
|
||||
{
|
||||
this.gradient_ = value;
|
||||
}
|
||||
}
|
||||
private IGradient gradient_;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Draws a representation of this plot in the legend.
|
||||
/// </summary>
|
||||
/// <param name="g">The graphics surface on which to draw.</param>
|
||||
/// <param name="startEnd">A rectangle specifying the bounds of the area in the legend set aside for drawing.</param>
|
||||
public void DrawInLegend( Graphics g, Rectangle startEnd )
|
||||
{
|
||||
// not implemented yet.
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// A label to associate with the plot - used in the legend.
|
||||
/// </summary>
|
||||
public string Label
|
||||
{
|
||||
get
|
||||
{
|
||||
return label_;
|
||||
}
|
||||
set
|
||||
{
|
||||
this.label_ = value;
|
||||
}
|
||||
}
|
||||
private string label_ = "";
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Returns an x-axis that is suitable for drawing this plot.
|
||||
/// </summary>
|
||||
/// <returns>A suitable x-axis.</returns>
|
||||
public Axis SuggestXAxis()
|
||||
{
|
||||
if (this.center_)
|
||||
{
|
||||
return new LinearAxis( this.xStart_ - this.xStep_/2.0, this.xStart_ + this.xStep_ * data_.GetLength(1) - this.xStep_/2.0 );
|
||||
}
|
||||
|
||||
return new LinearAxis( this.xStart_, this.xStart_ + this.xStep_ * data_.GetLength(1) );
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Returns a y-axis that is suitable for drawing this plot.
|
||||
/// </summary>
|
||||
/// <returns>A suitable y-axis.</returns>
|
||||
public Axis SuggestYAxis()
|
||||
{
|
||||
if (this.center_)
|
||||
{
|
||||
return new LinearAxis( this.yStart_ - this.yStep_/2.0, this.yStart_ + this.yStep_ * data_.GetLength(0) - this.yStep_/2.0 );
|
||||
}
|
||||
|
||||
return new LinearAxis( this.yStart_, this.yStart_ + this.yStep_ * data_.GetLength(0) );
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// If true, pixels are centered on their respective coordinates. If false, they are drawn
|
||||
/// between their coordinates and the coordinates of the the next point in each direction.
|
||||
/// </summary>
|
||||
public bool Center
|
||||
{
|
||||
set
|
||||
{
|
||||
center_ = value;
|
||||
}
|
||||
get
|
||||
{
|
||||
return center_;
|
||||
}
|
||||
}
|
||||
private bool center_ = true;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Whether or not to include an entry for this plot in the legend if it exists.
|
||||
/// </summary>
|
||||
public bool ShowInLegend
|
||||
{
|
||||
get
|
||||
{
|
||||
return showInLegend_;
|
||||
}
|
||||
set
|
||||
{
|
||||
this.showInLegend_ = value;
|
||||
}
|
||||
}
|
||||
private bool showInLegend_ = true;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Write data associated with the plot as text.
|
||||
/// </summary>
|
||||
/// <param name="sb">the string builder to write to.</param>
|
||||
/// <param name="region">Only write out data in this region if onlyInRegion is true.</param>
|
||||
/// <param name="onlyInRegion">If true, only data in region is written, else all data is written.</param>
|
||||
/// <remarks>TODO: not implemented.</remarks>
|
||||
public void WriteData( System.Text.StringBuilder sb, RectangleD region, bool onlyInRegion )
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,356 @@
|
|||
/*
|
||||
NPlot - A charting library for .NET
|
||||
|
||||
LabelAxis.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.Collections;
|
||||
using System.Drawing;
|
||||
|
||||
namespace NPlot
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// Allows the creation of axes with any number of user defined labels at
|
||||
/// user defined world values along the axis.
|
||||
/// </summary>
|
||||
public class LabelAxis : Axis
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// Deep copy of LabelAxis.
|
||||
/// </summary>
|
||||
/// <returns>A copy of the LinearAxis Class.</returns>
|
||||
public override object Clone()
|
||||
{
|
||||
LabelAxis a = new LabelAxis();
|
||||
// ensure that this isn't being called on a derived type. If it is, then oh no!
|
||||
if (this.GetType() != a.GetType())
|
||||
{
|
||||
throw new NPlotException( "Error. Clone method is not defined in derived type." );
|
||||
}
|
||||
DoClone( this, a );
|
||||
return a;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Helper method for Clone.
|
||||
/// </summary>
|
||||
/// <param name="a">The original object to clone.</param>
|
||||
/// <param name="b">The cloned object.</param>
|
||||
protected static void DoClone( LabelAxis b, LabelAxis a )
|
||||
{
|
||||
Axis.DoClone( b, a );
|
||||
|
||||
a.labels_ = (ArrayList)b.labels_.Clone();
|
||||
a.numbers_ = (ArrayList)b.numbers_.Clone();
|
||||
|
||||
a.ticksBetweenText_ = b.ticksBetweenText_;
|
||||
a.sortDataIfNecessary_ = b.sortDataIfNecessary_;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Initialise LabelAxis to default state.
|
||||
/// </summary>
|
||||
private void Init()
|
||||
{
|
||||
labels_ = new ArrayList();
|
||||
numbers_ = new ArrayList();
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Copy constructor
|
||||
/// </summary>
|
||||
/// <param name="a">The Axis to clone.</param>
|
||||
/// <remarks>TODO: [review notes] I don't think this will work as desired.</remarks>
|
||||
public LabelAxis( Axis a )
|
||||
: base( a )
|
||||
{
|
||||
Init();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Default constructor
|
||||
/// </summary>
|
||||
public LabelAxis()
|
||||
: base()
|
||||
{
|
||||
Init();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructor
|
||||
/// </summary>
|
||||
/// <param name="worldMin">Minimum world value</param>
|
||||
/// <param name="worldMax">Maximum world value</param>
|
||||
public LabelAxis( double worldMin, double worldMax )
|
||||
: base( worldMin, worldMax )
|
||||
{
|
||||
Init();
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Adds a label to the axis
|
||||
/// </summary>
|
||||
/// <param name="name">The label</param>
|
||||
/// <param name="val">The world value at which to place the label</param>
|
||||
public void AddLabel( string name, double val )
|
||||
{
|
||||
labels_.Add( name );
|
||||
numbers_.Add( val );
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Given Graphics surface, and physical extents of axis, draw ticks and
|
||||
/// associated labels.
|
||||
/// </summary>
|
||||
/// <param name="g">The GDI+ Graphics surface on which to draw.</param>
|
||||
/// <param name="physicalMin">The physical location of the world min point</param>
|
||||
/// <param name="physicalMax">The physical location of the world max point</param>
|
||||
/// <param name="boundingBox">out: smallest box that completely encompasses all of the ticks and tick labels.</param>
|
||||
/// <param name="labelOffset">out: a suitable offset from the axis to draw the axis label.</param>
|
||||
protected override void DrawTicks(
|
||||
Graphics g,
|
||||
Point physicalMin,
|
||||
Point physicalMax,
|
||||
out object labelOffset,
|
||||
out object boundingBox )
|
||||
{
|
||||
|
||||
Point tLabelOffset;
|
||||
Rectangle tBoundingBox;
|
||||
|
||||
labelOffset = this.getDefaultLabelOffset( physicalMin, physicalMax );
|
||||
boundingBox = null;
|
||||
|
||||
// draw the tick labels (but not the ticks).
|
||||
PointF lastPos = WorldToPhysical( (double)numbers_[0], physicalMin, physicalMax, true );
|
||||
for (int i=0; i<labels_.Count; ++i)
|
||||
{
|
||||
|
||||
if ((double)numbers_[i] > WorldMin && (double)numbers_[i] < WorldMax)
|
||||
{
|
||||
|
||||
// check to make sure labels are far enough appart.
|
||||
PointF thisPos = WorldToPhysical( (double)numbers_[i], physicalMin, physicalMax, true );
|
||||
float dist = Utils.Distance( thisPos, lastPos );
|
||||
|
||||
if ( i==0 || (dist > this.PhysicalSpacingMin) )
|
||||
{
|
||||
lastPos = thisPos;
|
||||
|
||||
this.DrawTick( g, (double)numbers_[i], 0,
|
||||
(string)labels_[i],
|
||||
new Point(0,0),
|
||||
physicalMin, physicalMax,
|
||||
out tLabelOffset, out tBoundingBox );
|
||||
|
||||
Axis.UpdateOffsetAndBounds(
|
||||
ref labelOffset, ref boundingBox,
|
||||
tLabelOffset, tBoundingBox );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// now draw the ticks (which might not be aligned with the tick text).
|
||||
ArrayList largeTickPositions;
|
||||
ArrayList smallTickPositions;
|
||||
WorldTickPositions_FirstPass( physicalMin, physicalMax, out largeTickPositions, out smallTickPositions );
|
||||
lastPos = WorldToPhysical( (double)largeTickPositions[0], physicalMin, physicalMax, true );
|
||||
for (int i=0; i<largeTickPositions.Count; ++i)
|
||||
{
|
||||
double tickPos = (double)largeTickPositions[i];
|
||||
|
||||
// check to see that labels are far enough appart.
|
||||
PointF thisPos = WorldToPhysical( tickPos, physicalMin, physicalMax, true );
|
||||
float dist = Utils.Distance( thisPos, lastPos );
|
||||
if ( (i==0) || (dist> this.PhysicalSpacingMin) )
|
||||
{
|
||||
lastPos = thisPos;
|
||||
|
||||
this.DrawTick( g, tickPos, LargeTickSize,
|
||||
"",
|
||||
new Point(0,0),
|
||||
physicalMin, physicalMax,
|
||||
out tLabelOffset, out tBoundingBox );
|
||||
|
||||
Axis.UpdateOffsetAndBounds(
|
||||
ref labelOffset, ref boundingBox,
|
||||
tLabelOffset, tBoundingBox );
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Determines the positions, in world coordinates, of the large ticks.
|
||||
///
|
||||
/// Label axes do not have small ticks.
|
||||
/// </summary>
|
||||
/// <param name="physicalMin">The physical position corresponding to the world minimum of the axis.</param>
|
||||
/// <param name="physicalMax">The physical position corresponding to the world maximum of the axis.</param>
|
||||
/// <param name="largeTickPositions">ArrayList containing the positions of the large ticks.</param>
|
||||
/// <param name="smallTickPositions">null</param>
|
||||
internal override void WorldTickPositions_FirstPass(
|
||||
Point physicalMin,
|
||||
Point physicalMax,
|
||||
out ArrayList largeTickPositions,
|
||||
out ArrayList smallTickPositions
|
||||
)
|
||||
{
|
||||
smallTickPositions = null;
|
||||
largeTickPositions = new ArrayList();
|
||||
|
||||
// if ticks correspond to position of text
|
||||
if (!ticksBetweenText_)
|
||||
{
|
||||
for (int i=0; i<labels_.Count; ++i)
|
||||
{
|
||||
if ((double)numbers_[i] > WorldMin && (double)numbers_[i] < WorldMax)
|
||||
{
|
||||
largeTickPositions.Add( numbers_[i] );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// if ticks correspond to gaps between text
|
||||
else
|
||||
{
|
||||
ArrayList numbers_copy;
|
||||
if (sortDataIfNecessary_)
|
||||
{
|
||||
numbers_copy = (ArrayList)numbers_.Clone(); // shallow copy.
|
||||
numbers_copy.Sort();
|
||||
}
|
||||
else
|
||||
{
|
||||
numbers_copy = numbers_;
|
||||
}
|
||||
|
||||
for (int i=1; i<labels_.Count; ++i)
|
||||
{
|
||||
double worldPosition = ((double)numbers_copy[i] + (double)numbers_copy[i-1])/2.0;
|
||||
if (worldPosition > WorldMin && worldPosition < WorldMax)
|
||||
{
|
||||
largeTickPositions.Add( worldPosition );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// If true, large ticks are drawn between the labels, rather
|
||||
/// than at the position of the labels.
|
||||
/// </summary>
|
||||
public bool TicksBetweenText
|
||||
{
|
||||
get
|
||||
{
|
||||
return ticksBetweenText_;
|
||||
}
|
||||
set
|
||||
{
|
||||
ticksBetweenText_ = value;
|
||||
}
|
||||
}
|
||||
private bool ticksBetweenText_ = false;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// If your data may be be specified out of order (that is
|
||||
/// abscissa values with a higher index may be less than
|
||||
/// abscissa values of a lower index), then data sorting
|
||||
/// may be necessary to implement some of the functionality
|
||||
/// of this object. If you know your data is already
|
||||
/// ordered with abscissa values lowest -> highest, then
|
||||
/// you may set this to false. It's default is true.
|
||||
/// </summary>
|
||||
public bool SortDataIfNecessary
|
||||
{
|
||||
get
|
||||
{
|
||||
return sortDataIfNecessary_;
|
||||
}
|
||||
set
|
||||
{
|
||||
sortDataIfNecessary_ = value;
|
||||
}
|
||||
}
|
||||
private bool sortDataIfNecessary_ = true;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// If consecutive labels are less than this number of pixels appart,
|
||||
/// some of the labels will not be drawn.
|
||||
/// </summary>
|
||||
public int PhysicalSpacingMin
|
||||
{
|
||||
get
|
||||
{
|
||||
return physicalSpacingMin_;
|
||||
}
|
||||
set
|
||||
{
|
||||
physicalSpacingMin_ = value;
|
||||
}
|
||||
}
|
||||
private int physicalSpacingMin_ = 0;
|
||||
|
||||
|
||||
private ArrayList labels_;
|
||||
private ArrayList numbers_;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,324 @@
|
|||
/*
|
||||
NPlot - A charting library for .NET
|
||||
|
||||
LabelPointPlot.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.Data;
|
||||
|
||||
namespace NPlot
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// Encapsulates functionality
|
||||
/// </summary>
|
||||
public class LabelPointPlot : PointPlot, ISequencePlot
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// This class us used in conjunction with SequenceAdapter to interpret data
|
||||
/// specified to the TextPlot class.
|
||||
/// </summary>
|
||||
private class TextDataAdapter
|
||||
{
|
||||
|
||||
private object data_;
|
||||
private object dataSource_;
|
||||
private string dataMember_;
|
||||
|
||||
public TextDataAdapter( object dataSource, string dataMember, object data )
|
||||
{
|
||||
this.data_ = data;
|
||||
this.dataSource_ = dataSource;
|
||||
this.dataMember_ = dataMember;
|
||||
}
|
||||
|
||||
public string this[int i]
|
||||
{
|
||||
get
|
||||
{
|
||||
|
||||
// this is inefficient [could set up delegates in constructor].
|
||||
|
||||
if (data_ is string[])
|
||||
{
|
||||
return ((string[])data_)[i];
|
||||
}
|
||||
|
||||
if (data_ is string)
|
||||
{
|
||||
if (dataSource_ == null)
|
||||
{
|
||||
throw new NPlotException( "Error: DataSource null" );
|
||||
}
|
||||
|
||||
System.Data.DataRowCollection rows;
|
||||
|
||||
if ( dataSource_ is System.Data.DataSet )
|
||||
{
|
||||
if (dataMember_ != null)
|
||||
{
|
||||
// TODO error check
|
||||
rows = ((DataTable)((DataSet)dataSource_).Tables[dataMember_]).Rows;
|
||||
}
|
||||
else
|
||||
{
|
||||
// TODO error check
|
||||
rows = ((DataTable)((DataSet)dataSource_).Tables[0]).Rows;
|
||||
}
|
||||
}
|
||||
|
||||
else if (dataSource_ is System.Data.DataTable )
|
||||
{
|
||||
rows = ((DataTable)dataSource_).Rows;
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
throw new NPlotException ( "not implemented yet" );
|
||||
}
|
||||
|
||||
return (string)((System.Data.DataRow)(rows[i]))[(string)data_];
|
||||
}
|
||||
|
||||
if (data_ is System.Collections.ArrayList)
|
||||
{
|
||||
object dataPoint = ((System.Collections.ArrayList)data_)[i];
|
||||
if (dataPoint is string)
|
||||
return (string)dataPoint;
|
||||
throw new NPlotException( "TextDataAdapter: data not in recognised format" );
|
||||
}
|
||||
|
||||
if (data_ == null)
|
||||
{
|
||||
return "text";
|
||||
}
|
||||
|
||||
throw new NPlotException( "Text data not of recognised type" );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public int Count
|
||||
{
|
||||
get
|
||||
{
|
||||
// this is inefficient [could set up delegates in constructor].
|
||||
|
||||
if (data_ == null)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
if (data_ is string[])
|
||||
{
|
||||
return ((string[])data_).Length;
|
||||
}
|
||||
if (data_ is System.Collections.ArrayList)
|
||||
{
|
||||
return ((System.Collections.ArrayList)data_).Count;
|
||||
}
|
||||
throw new NPlotException( "Text data not in correct format" );
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Enumeration of all label positions relative to a point.
|
||||
/// </summary>
|
||||
public enum LabelPositions
|
||||
{
|
||||
/// <summary>
|
||||
/// Above the point
|
||||
/// </summary>
|
||||
Above,
|
||||
/// <summary>
|
||||
/// Below the point
|
||||
/// </summary>
|
||||
Below,
|
||||
/// <summary>
|
||||
/// To the left of the point
|
||||
/// </summary>
|
||||
Left,
|
||||
/// <summary>
|
||||
/// To the right of the point
|
||||
/// </summary>
|
||||
Right
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Default Constructor
|
||||
/// </summary>
|
||||
public LabelPointPlot()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Constructor
|
||||
/// </summary>
|
||||
/// <param name="marker">The marker type to use for this plot.</param>
|
||||
public LabelPointPlot( Marker marker )
|
||||
: base( marker )
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// The position of the text label in relation to the point.
|
||||
/// </summary>
|
||||
public LabelPositions LabelTextPosition
|
||||
{
|
||||
get
|
||||
{
|
||||
return labelTextPosition_;
|
||||
}
|
||||
set
|
||||
{
|
||||
labelTextPosition_ = value;
|
||||
}
|
||||
}
|
||||
private LabelPositions labelTextPosition_ = LabelPositions.Above;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// The text datasource to attach to each point.
|
||||
/// </summary>
|
||||
public object TextData
|
||||
{
|
||||
get
|
||||
{
|
||||
return textData_;
|
||||
}
|
||||
set
|
||||
{
|
||||
textData_ = value;
|
||||
}
|
||||
}
|
||||
object textData_;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// The Font used to write text.
|
||||
/// </summary>
|
||||
public Font Font
|
||||
{
|
||||
get
|
||||
{
|
||||
return font_;
|
||||
}
|
||||
set
|
||||
{
|
||||
font_ = value;
|
||||
}
|
||||
}
|
||||
private Font font_ = new Font( "Arial", 8.0f );
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Draws the plot on a GDI+ surface against the provided x and y axes.
|
||||
/// </summary>
|
||||
/// <param name="g">The GDI+ 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 override void Draw( Graphics g, PhysicalAxis xAxis, PhysicalAxis yAxis )
|
||||
{
|
||||
SequenceAdapter data =
|
||||
new SequenceAdapter( this.DataSource, this.DataMember, this.OrdinateData, this.AbscissaData );
|
||||
|
||||
TextDataAdapter textData =
|
||||
new TextDataAdapter( this.DataSource, this.DataMember, this.TextData );
|
||||
|
||||
// first plot the marker
|
||||
// we can do this cast, since the constructor accepts only this type!
|
||||
for (int i=0; i<data.Count; ++i)
|
||||
{
|
||||
try
|
||||
{
|
||||
PointD pt = data[i];
|
||||
if ( !Double.IsNaN(pt.X) && !Double.IsNaN(pt.Y) )
|
||||
{
|
||||
PointF xPos = xAxis.WorldToPhysical( pt.X, false);
|
||||
PointF yPos = yAxis.WorldToPhysical( pt.Y, false);
|
||||
Marker.Draw( g, (int)xPos.X, (int)yPos.Y );
|
||||
if ( textData[i] != "" )
|
||||
{
|
||||
SizeF size = g.MeasureString( textData[i], this.Font );
|
||||
switch (labelTextPosition_)
|
||||
{
|
||||
case LabelPositions.Above:
|
||||
g.DrawString( textData[i], font_, Brushes.Black, new PointF(xPos.X-size.Width/2,yPos.Y-size.Height-Marker.Size*2/3));
|
||||
break;
|
||||
case LabelPositions.Below:
|
||||
g.DrawString( textData[i], font_, Brushes.Black, new PointF(xPos.X-size.Width/2,yPos.Y+Marker.Size*2/3));
|
||||
break;
|
||||
case LabelPositions.Left:
|
||||
g.DrawString( textData[i], font_, Brushes.Black, new PointF(xPos.X-size.Width-Marker.Size*2/3,yPos.Y-size.Height/2));
|
||||
break;
|
||||
case LabelPositions.Right:
|
||||
g.DrawString( textData[i], font_, Brushes.Black, new PointF(xPos.X+Marker.Size*2/3,yPos.Y-size.Height/2));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
throw new NPlotException("Error in TextPlot.Draw");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,352 @@
|
|||
/*
|
||||
NPlot - A charting library for .NET
|
||||
|
||||
Legend.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;
|
||||
using System.Collections;
|
||||
|
||||
namespace NPlot
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// Legend functionality specific to Legends associated with a PlotSurface2D.
|
||||
/// </summary>
|
||||
public class Legend : LegendBase
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// Enumeration of possible Legend placements.
|
||||
/// </summary>
|
||||
public enum Placement
|
||||
{
|
||||
/// <summary>
|
||||
/// Inside the plot area.
|
||||
/// </summary>
|
||||
Inside = 0,
|
||||
/// <summary>
|
||||
/// Outside the plot area.
|
||||
/// </summary>
|
||||
Outside = 1
|
||||
}
|
||||
|
||||
private int xOffset_;
|
||||
private int yOffset_;
|
||||
private PlotSurface2D.XAxisPosition xAttach_;
|
||||
private PlotSurface2D.YAxisPosition yAttach_;
|
||||
private Placement horizontalEdgePlacement_;
|
||||
private Placement verticalEdgePlacement_;
|
||||
private bool neverShiftAxes_;
|
||||
|
||||
/// <summary>
|
||||
/// Whether or not the positions of the Axes may be shifted to make
|
||||
/// room for the Legend.
|
||||
/// </summary>
|
||||
public bool NeverShiftAxes
|
||||
{
|
||||
get
|
||||
{
|
||||
return neverShiftAxes_;
|
||||
}
|
||||
set
|
||||
{
|
||||
neverShiftAxes_ = value;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Offset from the chosen Y-Axis. TODO: better description.
|
||||
/// </summary>
|
||||
public int XOffset
|
||||
{
|
||||
get
|
||||
{
|
||||
return xOffset_;
|
||||
}
|
||||
set
|
||||
{
|
||||
xOffset_ = value;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Offset from the X-Axis. TODO: better description.
|
||||
/// </summary>
|
||||
public int YOffset
|
||||
{
|
||||
get
|
||||
{
|
||||
return yOffset_;
|
||||
}
|
||||
set
|
||||
{
|
||||
yOffset_ = value;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Whether or not to attach the legend on the inside of the top
|
||||
/// or bottom axis (which, is specified using the AttachTo method) or the
|
||||
/// outside.
|
||||
/// </summary>
|
||||
public Legend.Placement VerticalEdgePlacement
|
||||
{
|
||||
get
|
||||
{
|
||||
return verticalEdgePlacement_;
|
||||
}
|
||||
set
|
||||
{
|
||||
verticalEdgePlacement_ = value;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Whether or not to attach the legend on the inside of the
|
||||
/// left or right axis (which, is specified using the AttachTo method)
|
||||
/// or the outside.
|
||||
/// </summary>
|
||||
public Legend.Placement HorizontalEdgePlacement
|
||||
{
|
||||
get
|
||||
{
|
||||
return horizontalEdgePlacement_;
|
||||
}
|
||||
set
|
||||
{
|
||||
horizontalEdgePlacement_ = value;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Specify the Axes to attach the legend to.
|
||||
/// </summary>
|
||||
/// <param name="xa">Specify which horizontal axis the legend should be attached to.</param>
|
||||
/// <param name="ya">Specify which vertical axis the legend should be attached to.</param>
|
||||
public void AttachTo( PlotSurface2D.XAxisPosition xa, PlotSurface2D.YAxisPosition ya )
|
||||
{
|
||||
xAttach_ = xa;
|
||||
yAttach_ = ya;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Default constructor.
|
||||
/// </summary>
|
||||
public Legend()
|
||||
{
|
||||
xAttach_ = PlotSurface2D.XAxisPosition.Top;
|
||||
yAttach_ = PlotSurface2D.YAxisPosition.Right;
|
||||
xOffset_ = 10;
|
||||
yOffset_ = 1;
|
||||
verticalEdgePlacement_ = Placement.Outside;
|
||||
horizontalEdgePlacement_ = Placement.Inside;
|
||||
neverShiftAxes_ = false;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Updates the PlotSurface2D axes to compensate for the legend.
|
||||
/// </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>
|
||||
/// <param name="plots">list of plots.</param>
|
||||
/// <param name="scale">scale parameter (for text and other)</param>
|
||||
/// <param name="padding">padding around plot within bounds.</param>
|
||||
/// <param name="bounds">graphics surface bounds</param>
|
||||
/// <param name="position">legend position</param>
|
||||
public void UpdateAxesPositions(
|
||||
PhysicalAxis pXAxis1,
|
||||
PhysicalAxis pYAxis1,
|
||||
PhysicalAxis pXAxis2,
|
||||
PhysicalAxis pYAxis2,
|
||||
ArrayList plots,
|
||||
float scale, int padding, Rectangle bounds,
|
||||
out Point position )
|
||||
{
|
||||
|
||||
int leftIndent = 0;
|
||||
int rightIndent = 0;
|
||||
int bottomIndent = 0;
|
||||
int topIndent = 0;
|
||||
|
||||
position = new Point(0,0);
|
||||
|
||||
// now determine if legend should change any of these (legend should be fully
|
||||
// visible at all times), and draw legend.
|
||||
|
||||
Rectangle legendWidthHeight = this.GetBoundingBox( new Point(0,0), plots, scale );
|
||||
|
||||
if (legendWidthHeight.Width > bounds.Width)
|
||||
{
|
||||
legendWidthHeight.Width = bounds.Width;
|
||||
}
|
||||
|
||||
// (1) calculate legend position.
|
||||
|
||||
// y
|
||||
|
||||
position.Y = this.yOffset_;
|
||||
|
||||
if ( this.xAttach_ == PlotSurface2D.XAxisPosition.Bottom )
|
||||
{
|
||||
position.Y += pYAxis1.PhysicalMin.Y;
|
||||
if ( this.horizontalEdgePlacement_ == Legend.Placement.Inside )
|
||||
{
|
||||
position.Y -= legendWidthHeight.Height;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
position.Y += pYAxis1.PhysicalMax.Y;
|
||||
if ( this.horizontalEdgePlacement_ == Legend.Placement.Outside )
|
||||
{
|
||||
position.Y -= legendWidthHeight.Height;
|
||||
}
|
||||
}
|
||||
|
||||
// x
|
||||
|
||||
position.X = this.xOffset_;
|
||||
|
||||
if ( this.yAttach_ == PlotSurface2D.YAxisPosition.Left )
|
||||
{
|
||||
if ( this.verticalEdgePlacement_ == Legend.Placement.Outside )
|
||||
{
|
||||
position.X -= legendWidthHeight.Width;
|
||||
}
|
||||
position.X += pXAxis1.PhysicalMin.X;
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( this.verticalEdgePlacement_ == Legend.Placement.Inside )
|
||||
{
|
||||
position.X -= legendWidthHeight.Width;
|
||||
}
|
||||
position.X += pXAxis1.PhysicalMax.X;
|
||||
}
|
||||
|
||||
|
||||
// determine update amounts for axes
|
||||
|
||||
if ( !this.neverShiftAxes_ )
|
||||
{
|
||||
|
||||
if ( position.X < padding )
|
||||
{
|
||||
int changeAmount = -position.X + padding;
|
||||
// only allow axes to move away from bounds.
|
||||
if ( changeAmount > 0 )
|
||||
{
|
||||
leftIndent = changeAmount;
|
||||
}
|
||||
position.X += changeAmount;
|
||||
}
|
||||
|
||||
if ( position.X + legendWidthHeight.Width > bounds.Right - padding )
|
||||
{
|
||||
int changeAmount = (position.X - bounds.Right + legendWidthHeight.Width + padding );
|
||||
// only allow axes to move away from bounds.
|
||||
if ( changeAmount > 0.0f )
|
||||
{
|
||||
rightIndent = changeAmount;
|
||||
}
|
||||
position.X -= changeAmount;
|
||||
}
|
||||
|
||||
if ( position.Y < padding )
|
||||
{
|
||||
int changeAmount = -position.Y + padding;
|
||||
// only allow axes to move away from bounds.
|
||||
if ( changeAmount > 0.0f )
|
||||
{
|
||||
topIndent = changeAmount;
|
||||
}
|
||||
position.Y += changeAmount;
|
||||
}
|
||||
|
||||
if ( position.Y + legendWidthHeight.Height > bounds.Bottom - padding )
|
||||
{
|
||||
int changeAmount = (position.Y - bounds.Bottom + legendWidthHeight.Height + padding );
|
||||
// only allow axes to move away from bounds.
|
||||
if ( changeAmount > 0.0f )
|
||||
{
|
||||
bottomIndent = changeAmount;
|
||||
}
|
||||
position.Y -= changeAmount;
|
||||
}
|
||||
|
||||
// update axes.
|
||||
|
||||
pXAxis1.PhysicalMin = new Point( pXAxis1.PhysicalMin.X + leftIndent, pXAxis1.PhysicalMin.Y - bottomIndent );
|
||||
pXAxis1.PhysicalMax = new Point( pXAxis1.PhysicalMax.X - rightIndent, pXAxis1.PhysicalMax.Y - bottomIndent );
|
||||
pYAxis1.PhysicalMin = new Point( pYAxis1.PhysicalMin.X + leftIndent, pYAxis1.PhysicalMin.Y - bottomIndent );
|
||||
pYAxis1.PhysicalMax = new Point( pYAxis1.PhysicalMax.X + leftIndent, pYAxis1.PhysicalMax.Y + topIndent );
|
||||
|
||||
pXAxis2.PhysicalMin = new Point( pXAxis2.PhysicalMin.X + leftIndent, pXAxis2.PhysicalMin.Y + topIndent );
|
||||
pXAxis2.PhysicalMax = new Point( pXAxis2.PhysicalMax.X - rightIndent, pXAxis2.PhysicalMax.Y + topIndent );
|
||||
pYAxis2.PhysicalMin = new Point( pYAxis2.PhysicalMin.X - rightIndent, pYAxis2.PhysicalMin.Y - bottomIndent );
|
||||
pYAxis2.PhysicalMax = new Point( pYAxis2.PhysicalMax.X - rightIndent, pYAxis2.PhysicalMax.Y + topIndent );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,459 @@
|
|||
/*
|
||||
NPlot - A charting library for .NET
|
||||
|
||||
LegendBase.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.Collections;
|
||||
using System.Drawing;
|
||||
|
||||
namespace NPlot
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// Provides functionality for drawing legends.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The class is quite closely tied to PlotSurface2D.
|
||||
/// </remarks>
|
||||
public class LegendBase
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// Constructor.
|
||||
/// </summary>
|
||||
public LegendBase()
|
||||
{
|
||||
this.Font = new Font( new FontFamily("Arial"), 10, FontStyle.Regular, GraphicsUnit.Pixel );
|
||||
this.BackgroundColor = Color.White;
|
||||
this.BorderColor = Color.Black;
|
||||
this.TextColor = Color.Black;
|
||||
this.borderStyle_ = BorderType.Shadow;
|
||||
this.autoScaleText_ = false;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Get the bounding box of the rectangle.
|
||||
/// </summary>
|
||||
/// <param name="position">the position of the top left of the legend.</param>
|
||||
/// <param name="plots">Array of plot objects to appear in the legend.</param>
|
||||
/// <param name="scale">if the legend is set to scale, the amount to scale by.</param>>
|
||||
/// <returns></returns>
|
||||
/// <remarks>do implementation that doesn't call draw. Change xPos, yPos to PointF</remarks>
|
||||
public Rectangle GetBoundingBox( Point position, ArrayList plots, float scale )
|
||||
{
|
||||
System.Drawing.Bitmap b = new System.Drawing.Bitmap(1,1);
|
||||
Graphics g = Graphics.FromImage(b);
|
||||
return this.Draw( g, position, plots, scale );
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Draw The legend
|
||||
/// </summary>
|
||||
/// <param name="g">The graphics surface on which to draw</param>
|
||||
/// <param name="position">The position of the top left of the axis.</param>
|
||||
/// <param name="plots">Array of plot objects to appear in the legend.</param>
|
||||
/// <param name="scale">if the legend is set to scale, the amount to scale by.</param>
|
||||
/// <returns>bounding box</returns>
|
||||
public Rectangle Draw( Graphics g, Point position, ArrayList plots, float scale )
|
||||
{
|
||||
|
||||
// first of all determine the Font to use in the legend.
|
||||
Font textFont;
|
||||
if (this.AutoScaleText)
|
||||
{
|
||||
textFont = Utils.ScaleFont( this.font_, scale );
|
||||
}
|
||||
else
|
||||
{
|
||||
textFont = this.font_;
|
||||
}
|
||||
|
||||
// determine max width and max height of label strings and
|
||||
// count the labels.
|
||||
int labelCount = 0;
|
||||
int maxHt = 0;
|
||||
int maxWd = 0;
|
||||
int unnamedCount = 0;
|
||||
for (int i=0; i<plots.Count; ++i)
|
||||
{
|
||||
if (!(plots[i] is IPlot))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
IPlot p = (IPlot)plots[i];
|
||||
|
||||
if (!p.ShowInLegend)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
string label = p.Label;
|
||||
if (label == "")
|
||||
{
|
||||
unnamedCount += 1;
|
||||
label = "Series " + unnamedCount.ToString();
|
||||
}
|
||||
SizeF labelSize = g.MeasureString( label, textFont );
|
||||
if ( labelSize.Height > maxHt )
|
||||
{
|
||||
maxHt = (int)labelSize.Height;
|
||||
}
|
||||
if ( labelSize.Width > maxWd )
|
||||
{
|
||||
maxWd = (int)labelSize.Width;
|
||||
}
|
||||
|
||||
++labelCount;
|
||||
}
|
||||
|
||||
bool extendingHorizontally = numberItemsHorizontally_ == -1;
|
||||
bool extendingVertically = numberItemsVertically_ == -1;
|
||||
|
||||
|
||||
// determine width in legend items count units.
|
||||
int widthInItemCount = 0;
|
||||
if (extendingVertically)
|
||||
{
|
||||
if (labelCount >= numberItemsHorizontally_)
|
||||
{
|
||||
widthInItemCount = numberItemsHorizontally_;
|
||||
}
|
||||
else
|
||||
{
|
||||
widthInItemCount = labelCount;
|
||||
}
|
||||
}
|
||||
else if (extendingHorizontally)
|
||||
{
|
||||
widthInItemCount = labelCount / numberItemsVertically_;
|
||||
if (labelCount % numberItemsVertically_ != 0)
|
||||
widthInItemCount += 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new NPlotException( "logic error in legend base" );
|
||||
}
|
||||
|
||||
|
||||
// determine height of legend in items count units.
|
||||
int heightInItemCount = 0;
|
||||
if (extendingHorizontally)
|
||||
{
|
||||
if (labelCount >= numberItemsVertically_)
|
||||
{
|
||||
heightInItemCount = numberItemsVertically_;
|
||||
}
|
||||
else
|
||||
{
|
||||
heightInItemCount = labelCount;
|
||||
}
|
||||
}
|
||||
else // extendingVertically
|
||||
{
|
||||
heightInItemCount = labelCount / numberItemsHorizontally_;
|
||||
if (labelCount % numberItemsHorizontally_ != 0)
|
||||
heightInItemCount += 1;
|
||||
}
|
||||
|
||||
int lineLength = 20;
|
||||
int hSpacing = (int)(5.0f * scale);
|
||||
int vSpacing = (int)(3.0f * scale);
|
||||
int boxWidth = (int) ((float)widthInItemCount * (lineLength + maxWd + hSpacing * 2.0f ) + hSpacing);
|
||||
int boxHeight = (int)((float)heightInItemCount * (maxHt + vSpacing) + vSpacing);
|
||||
|
||||
int totalWidth = boxWidth;
|
||||
int totalHeight = boxHeight;
|
||||
|
||||
// draw box around the legend.
|
||||
|
||||
if ( this.BorderStyle == BorderType.Line )
|
||||
{
|
||||
g.FillRectangle( new SolidBrush( this.bgColor_ ), position.X, position.Y, boxWidth, boxHeight );
|
||||
g.DrawRectangle( new Pen( this.borderColor_ ), position.X, position.Y, boxWidth, boxHeight );
|
||||
}
|
||||
else if ( this.BorderStyle == BorderType.Shadow )
|
||||
{
|
||||
int offset = (int)(4.0f * scale);
|
||||
g.FillRectangle( new SolidBrush( Color.FromArgb(128, Color.Gray) ), position.X+offset, position.Y+offset, boxWidth, boxHeight );
|
||||
g.FillRectangle( new SolidBrush( this.bgColor_ ), position.X, position.Y, boxWidth, boxHeight );
|
||||
g.DrawRectangle( new Pen( this.borderColor_ ), position.X, position.Y, boxWidth, boxHeight );
|
||||
|
||||
totalWidth += offset;
|
||||
totalHeight += offset;
|
||||
}
|
||||
|
||||
/*
|
||||
else if ( this.BorderStyle == BorderType.Curved )
|
||||
{
|
||||
// TODO. make this nice.
|
||||
}
|
||||
*/
|
||||
|
||||
else
|
||||
{
|
||||
// do nothing.
|
||||
}
|
||||
|
||||
// now draw entries in box..
|
||||
labelCount = 0;
|
||||
unnamedCount = 0;
|
||||
|
||||
int plotCount = -1;
|
||||
for (int i=0; i<plots.Count; ++i)
|
||||
{
|
||||
if (!(plots[i] is IPlot))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
IPlot p = (IPlot)plots[i];
|
||||
|
||||
if (!p.ShowInLegend)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
plotCount += 1;
|
||||
|
||||
int xpos, ypos;
|
||||
if (extendingVertically)
|
||||
{
|
||||
xpos = plotCount % numberItemsHorizontally_;
|
||||
ypos = plotCount / numberItemsHorizontally_;
|
||||
}
|
||||
else
|
||||
{
|
||||
xpos = plotCount / numberItemsVertically_;
|
||||
ypos = plotCount % numberItemsVertically_;
|
||||
}
|
||||
|
||||
int lineXPos = (int)(position.X + hSpacing + xpos * (lineLength + maxWd + hSpacing * 2.0f));
|
||||
int lineYPos = (int)(position.Y + vSpacing + ypos * (vSpacing + maxHt));
|
||||
p.DrawInLegend( g, new Rectangle( lineXPos, lineYPos, lineLength, maxHt ) );
|
||||
|
||||
int textXPos = lineXPos + hSpacing + lineLength;
|
||||
int textYPos = lineYPos;
|
||||
string label = p.Label;
|
||||
if (label == "")
|
||||
{
|
||||
unnamedCount += 1;
|
||||
label = "Series " + unnamedCount.ToString();
|
||||
}
|
||||
|
||||
g.DrawString( label, textFont,
|
||||
new SolidBrush( this.textColor_ ), textXPos, textYPos );
|
||||
|
||||
++labelCount;
|
||||
}
|
||||
return new Rectangle( position.X, position.Y, totalWidth, totalHeight );
|
||||
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// The font used to draw text in the legend.
|
||||
/// </summary>
|
||||
public Font Font
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.font_;
|
||||
}
|
||||
set
|
||||
{
|
||||
this.font_ = value;
|
||||
}
|
||||
}
|
||||
private Font font_;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// The color used to draw text in the legend.
|
||||
/// </summary>
|
||||
public Color TextColor
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.textColor_;
|
||||
}
|
||||
set
|
||||
{
|
||||
this.textColor_ = value;
|
||||
}
|
||||
}
|
||||
Color textColor_;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// The background color of the legend.
|
||||
/// </summary>
|
||||
public Color BackgroundColor
|
||||
{
|
||||
get
|
||||
{
|
||||
return bgColor_;
|
||||
}
|
||||
set
|
||||
{
|
||||
bgColor_ = value;
|
||||
}
|
||||
}
|
||||
Color bgColor_;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// The color of the legend border.
|
||||
/// </summary>
|
||||
public Color BorderColor
|
||||
{
|
||||
get
|
||||
{
|
||||
return borderColor_;
|
||||
}
|
||||
set
|
||||
{
|
||||
borderColor_ = value;
|
||||
}
|
||||
}
|
||||
Color borderColor_;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// The types of legend borders (enum).
|
||||
/// </summary>
|
||||
public enum BorderType
|
||||
{
|
||||
/// <summary>
|
||||
/// No border.
|
||||
/// </summary>
|
||||
None = 0,
|
||||
/// <summary>
|
||||
/// Line border.
|
||||
/// </summary>
|
||||
Line = 1,
|
||||
/// <summary>
|
||||
/// Shaded border.
|
||||
/// </summary>
|
||||
Shadow = 2
|
||||
//Curved = 3
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// The border style to use for the legend.
|
||||
/// </summary>
|
||||
public Legend.BorderType BorderStyle
|
||||
{
|
||||
get
|
||||
{
|
||||
return borderStyle_;
|
||||
}
|
||||
set
|
||||
{
|
||||
borderStyle_ = value;
|
||||
}
|
||||
}
|
||||
private NPlot.Legend.BorderType borderStyle_;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Whether or not to auto scale text in the legend according the physical
|
||||
/// dimensions of the plot surface.
|
||||
/// </summary>
|
||||
public bool AutoScaleText
|
||||
{
|
||||
get
|
||||
{
|
||||
return autoScaleText_;
|
||||
}
|
||||
set
|
||||
{
|
||||
autoScaleText_ = value;
|
||||
}
|
||||
}
|
||||
bool autoScaleText_;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Setting this does two things. First of all, it sets the maximum number of
|
||||
/// items in the legend vertically. Second of all, it makes the legend grow
|
||||
/// horizontally (as it must given this constraint).
|
||||
/// </summary>
|
||||
public int NumberItemsVertically
|
||||
{
|
||||
set
|
||||
{
|
||||
this.numberItemsVertically_ = value;
|
||||
this.numberItemsHorizontally_ = -1;
|
||||
}
|
||||
}
|
||||
int numberItemsVertically_ = -1;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Setting this does two things. First of all, it sets the maximum number of
|
||||
/// items in the legend horizontally. Second of all, it makes the legend grow
|
||||
/// vertically (as it must given this constraint).
|
||||
/// </summary>
|
||||
public int NumberItemsHorizontally
|
||||
{
|
||||
set
|
||||
{
|
||||
this.numberItemsHorizontally_ = value;
|
||||
this.numberItemsVertically_ = -1;
|
||||
}
|
||||
}
|
||||
int numberItemsHorizontally_ = 1;
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,355 @@
|
|||
/*
|
||||
NPlot - A charting library for .NET
|
||||
|
||||
LinePlot.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.Diagnostics;
|
||||
|
||||
namespace NPlot
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// Encapsulates functionality for plotting data as a line chart.
|
||||
/// </summary>
|
||||
public class LinePlot : BaseSequencePlot, IPlot, ISequencePlot
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// Default constructor
|
||||
/// </summary>
|
||||
public LinePlot()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Constructor
|
||||
/// </summary>
|
||||
/// <param name="dataSource">The data source to associate with this plot</param>
|
||||
public LinePlot( object dataSource )
|
||||
{
|
||||
this.DataSource = dataSource;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Constructor
|
||||
/// </summary>
|
||||
/// <param name="ordinateData">the ordinate data to associate with this plot.</param>
|
||||
/// <param name="abscissaData">the abscissa data to associate with this plot.</param>
|
||||
public LinePlot( object ordinateData, object abscissaData )
|
||||
{
|
||||
this.OrdinateData = ordinateData;
|
||||
this.AbscissaData = abscissaData;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Draws the line plot on a GDI+ surface against the provided x and y axes.
|
||||
/// </summary>
|
||||
/// <param name="g">The GDI+ 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>
|
||||
/// <param name="drawShadow">If true draw the shadow for the line. If false, draw line.</param>
|
||||
public void DrawLineOrShadow( Graphics g, PhysicalAxis xAxis, PhysicalAxis yAxis, bool drawShadow )
|
||||
{
|
||||
Pen shadowPen = null;
|
||||
if (drawShadow)
|
||||
{
|
||||
shadowPen = (Pen)this.Pen.Clone();
|
||||
shadowPen.Color = this.ShadowColor;
|
||||
}
|
||||
|
||||
SequenceAdapter data =
|
||||
new SequenceAdapter( this.DataSource, this.DataMember, this.OrdinateData, this.AbscissaData );
|
||||
|
||||
ITransform2D t = Transform2D.GetTransformer( xAxis, yAxis );
|
||||
|
||||
int numberPoints = data.Count;
|
||||
|
||||
if (data.Count == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// clipping is now handled assigning a clip region in the
|
||||
// graphic object before this call
|
||||
if (numberPoints == 1)
|
||||
{
|
||||
PointF physical = t.Transform( data[0] );
|
||||
|
||||
if (drawShadow)
|
||||
{
|
||||
g.DrawLine( shadowPen,
|
||||
physical.X - 0.5f + this.ShadowOffset.X,
|
||||
physical.Y + this.ShadowOffset.Y,
|
||||
physical.X + 0.5f + this.ShadowOffset.X,
|
||||
physical.Y + this.ShadowOffset.Y );
|
||||
}
|
||||
else
|
||||
{
|
||||
g.DrawLine( Pen, physical.X-0.5f, physical.Y, physical.X+0.5f, physical.Y);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
// prepare for clipping
|
||||
double leftCutoff = xAxis.PhysicalToWorld(xAxis.PhysicalMin, false);
|
||||
double rightCutoff = xAxis.PhysicalToWorld(xAxis.PhysicalMax, false);
|
||||
if (leftCutoff > rightCutoff)
|
||||
{
|
||||
Utils.Swap(ref leftCutoff, ref rightCutoff);
|
||||
}
|
||||
if (drawShadow)
|
||||
{
|
||||
// correct cut-offs
|
||||
double shadowCorrection =
|
||||
xAxis.PhysicalToWorld(ShadowOffset, false) - xAxis.PhysicalToWorld(new Point(0,0), false);
|
||||
leftCutoff -= shadowCorrection;
|
||||
rightCutoff -= shadowCorrection;
|
||||
}
|
||||
|
||||
for (int i = 1; i < numberPoints; ++i)
|
||||
{
|
||||
// check to see if any values null. If so, then continue.
|
||||
double dx1 = data[i-1].X;
|
||||
double dx2 = data[i].X;
|
||||
double dy1 = data[i-1].Y;
|
||||
double dy2 = data[i].Y;
|
||||
if ( Double.IsNaN(dx1) || Double.IsNaN(dy1) ||
|
||||
Double.IsNaN(dx2) || Double.IsNaN(dy2) )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// do horizontal clipping here, to speed up
|
||||
if ((dx1 < leftCutoff || rightCutoff < dx1) &&
|
||||
(dx2 < leftCutoff || rightCutoff < dx2))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// else draw line.
|
||||
PointF p1 = t.Transform( data[i-1] );
|
||||
PointF p2 = t.Transform( data[i] );
|
||||
|
||||
// when very far zoomed in, points can fall ontop of each other,
|
||||
// and g.DrawLine throws an overflow exception
|
||||
if (p1.Equals(p2))
|
||||
continue;
|
||||
|
||||
if (drawShadow)
|
||||
{
|
||||
g.DrawLine( shadowPen,
|
||||
p1.X + ShadowOffset.X,
|
||||
p1.Y + ShadowOffset.Y,
|
||||
p2.X + ShadowOffset.X,
|
||||
p2.Y + ShadowOffset.Y );
|
||||
}
|
||||
else
|
||||
{
|
||||
g.DrawLine( Pen, p1.X, p1.Y, p2.X, p2.Y );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Draws the line plot on a GDI+ surface against the provided x and y axes.
|
||||
/// </summary>
|
||||
/// <param name="g">The GDI+ 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( Graphics g, PhysicalAxis xAxis, PhysicalAxis yAxis )
|
||||
{
|
||||
if (this.shadow_)
|
||||
{
|
||||
this.DrawLineOrShadow( g, xAxis, yAxis, true );
|
||||
}
|
||||
|
||||
this.DrawLineOrShadow( g, xAxis, yAxis, false );
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Returns an x-axis that is suitable for drawing this plot.
|
||||
/// </summary>
|
||||
/// <returns>A suitable x-axis.</returns>
|
||||
public Axis SuggestXAxis()
|
||||
{
|
||||
SequenceAdapter data_ =
|
||||
new SequenceAdapter( this.DataSource, this.DataMember, this.OrdinateData, this.AbscissaData );
|
||||
|
||||
return data_.SuggestXAxis();
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Returns a y-axis that is suitable for drawing this plot.
|
||||
/// </summary>
|
||||
/// <returns>A suitable y-axis.</returns>
|
||||
public Axis SuggestYAxis()
|
||||
{
|
||||
SequenceAdapter data_ =
|
||||
new SequenceAdapter( this.DataSource, this.DataMember, this.OrdinateData, this.AbscissaData );
|
||||
|
||||
return data_.SuggestYAxis();
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// If true, draw a shadow under the line.
|
||||
/// </summary>
|
||||
public bool Shadow
|
||||
{
|
||||
get
|
||||
{
|
||||
return shadow_;
|
||||
}
|
||||
set
|
||||
{
|
||||
shadow_ = value;
|
||||
}
|
||||
}
|
||||
private bool shadow_ = false;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Color of line shadow if drawn. Use Shadow method to turn shadow on and off.
|
||||
/// </summary>
|
||||
public Color ShadowColor
|
||||
{
|
||||
get
|
||||
{
|
||||
return shadowColor_;
|
||||
}
|
||||
set
|
||||
{
|
||||
shadowColor_ = value;
|
||||
}
|
||||
}
|
||||
private Color shadowColor_ = Color.FromArgb(100,100,100);
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Offset of shadow line from primary line.
|
||||
/// </summary>
|
||||
public Point ShadowOffset
|
||||
{
|
||||
get
|
||||
{
|
||||
return shadowOffset_;
|
||||
}
|
||||
set
|
||||
{
|
||||
shadowOffset_ = value;
|
||||
}
|
||||
}
|
||||
private Point shadowOffset_ = new Point( 1, 1 );
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Draws a representation of this plot in the legend.
|
||||
/// </summary>
|
||||
/// <param name="g">The graphics surface on which to draw.</param>
|
||||
/// <param name="startEnd">A rectangle specifying the bounds of the area in the legend set aside for drawing.</param>
|
||||
public virtual void DrawInLegend(Graphics g, Rectangle startEnd)
|
||||
{
|
||||
g.DrawLine(pen_, startEnd.Left, (startEnd.Top + startEnd.Bottom) / 2,
|
||||
startEnd.Right, (startEnd.Top + startEnd.Bottom) / 2);
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// The pen used to draw the plot
|
||||
/// </summary>
|
||||
public System.Drawing.Pen Pen
|
||||
{
|
||||
get
|
||||
{
|
||||
return pen_;
|
||||
}
|
||||
set
|
||||
{
|
||||
pen_ = value;
|
||||
}
|
||||
}
|
||||
private System.Drawing.Pen pen_ = new Pen(Color.Black);
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// The color of the pen used to draw lines in this plot.
|
||||
/// </summary>
|
||||
public System.Drawing.Color Color
|
||||
{
|
||||
set
|
||||
{
|
||||
if (pen_ != null)
|
||||
{
|
||||
pen_.Color = value;
|
||||
}
|
||||
else
|
||||
{
|
||||
pen_ = new Pen(value);
|
||||
}
|
||||
}
|
||||
get
|
||||
{
|
||||
return pen_.Color;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,650 @@
|
|||
/*
|
||||
NPlot - A charting library for .NET
|
||||
|
||||
LinearAxis.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;
|
||||
using System.Collections;
|
||||
using System;
|
||||
using System.Text;
|
||||
using System.Diagnostics;
|
||||
|
||||
namespace NPlot
|
||||
{
|
||||
/// <summary>
|
||||
/// Provides functionality for drawing axes with a linear numeric scale.
|
||||
/// </summary>
|
||||
public class LinearAxis : Axis, System.ICloneable
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// Deep copy of LinearAxis.
|
||||
/// </summary>
|
||||
/// <returns>A copy of the LinearAxis Class</returns>
|
||||
public override object Clone()
|
||||
{
|
||||
LinearAxis a = new LinearAxis();
|
||||
// ensure that this isn't being called on a derived type. If it is, then oh no!
|
||||
if (this.GetType() != a.GetType())
|
||||
{
|
||||
throw new NPlotException( "Clone not defined in derived type. Help!" );
|
||||
}
|
||||
this.DoClone( this, a );
|
||||
return a;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Helper method for Clone.
|
||||
/// </summary>
|
||||
protected void DoClone( LinearAxis b, LinearAxis a )
|
||||
{
|
||||
Axis.DoClone( b, a );
|
||||
|
||||
a.numberSmallTicks_ = b.numberSmallTicks_;
|
||||
a.largeTickValue_ = b.largeTickValue_;
|
||||
a.largeTickStep_ = b.largeTickStep_;
|
||||
|
||||
a.offset_ = b.offset_;
|
||||
a.scale_ = b.scale_;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Copy constructor
|
||||
/// </summary>
|
||||
/// <param name="a">The Axis to clone</param>
|
||||
public LinearAxis( Axis a )
|
||||
: base( a )
|
||||
{
|
||||
Init();
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Default constructor.
|
||||
/// </summary>
|
||||
public LinearAxis()
|
||||
: base()
|
||||
{
|
||||
Init();
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Construct a linear axis with the provided world min and max values.
|
||||
/// </summary>
|
||||
/// <param name="worldMin">the world minimum value of the axis.</param>
|
||||
/// <param name="worldMax">the world maximum value of the axis.</param>
|
||||
public LinearAxis( double worldMin, double worldMax )
|
||||
: base( worldMin, worldMax )
|
||||
{
|
||||
Init();
|
||||
}
|
||||
|
||||
|
||||
private void Init()
|
||||
{
|
||||
this.NumberFormat = "{0:g5}";
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Draws the large and small ticks [and tick labels] for this axis.
|
||||
/// </summary>
|
||||
/// <param name="g">The graphics surface on which to draw.</param>
|
||||
/// <param name="physicalMin">The physical position corresponding to the world minimum of the axis.</param>
|
||||
/// <param name="physicalMax">The physical position corresponding to the world maximum of the axis.</param>
|
||||
/// <param name="boundingBox">out: smallest box that completely surrounds all ticks and associated labels for this axis.</param>
|
||||
/// <param name="labelOffset">out: offset from the axis to draw the axis label.</param>
|
||||
protected override void DrawTicks(
|
||||
Graphics g,
|
||||
Point physicalMin,
|
||||
Point physicalMax,
|
||||
out object labelOffset,
|
||||
out object boundingBox )
|
||||
{
|
||||
|
||||
Point tLabelOffset;
|
||||
Rectangle tBoundingBox;
|
||||
|
||||
labelOffset = this.getDefaultLabelOffset( physicalMin, physicalMax );
|
||||
boundingBox = null;
|
||||
|
||||
ArrayList largeTickPositions;
|
||||
ArrayList smallTickPositions;
|
||||
this.WorldTickPositions( physicalMin, physicalMax, out largeTickPositions, out smallTickPositions );
|
||||
|
||||
labelOffset = new Point( 0, 0 );
|
||||
boundingBox = null;
|
||||
|
||||
if (largeTickPositions.Count > 0)
|
||||
{
|
||||
for (int i = 0; i < largeTickPositions.Count; ++i)
|
||||
{
|
||||
double labelNumber = (double)largeTickPositions[i];
|
||||
|
||||
// TODO: Find out why zero is sometimes significantly not zero [seen as high as 10^-16].
|
||||
if (Math.Abs(labelNumber) < 0.000000000000001)
|
||||
{
|
||||
labelNumber = 0.0;
|
||||
}
|
||||
|
||||
StringBuilder label = new StringBuilder();
|
||||
label.AppendFormat(this.NumberFormat, labelNumber);
|
||||
|
||||
this.DrawTick( g, ((double)largeTickPositions[i]/this.scale_-this.offset_),
|
||||
this.LargeTickSize, label.ToString(),
|
||||
new Point(0,0), physicalMin, physicalMax,
|
||||
out tLabelOffset, out tBoundingBox );
|
||||
|
||||
Axis.UpdateOffsetAndBounds( ref labelOffset, ref boundingBox,
|
||||
tLabelOffset, tBoundingBox );
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i<smallTickPositions.Count; ++i)
|
||||
{
|
||||
this.DrawTick( g, ((double)smallTickPositions[i]/this.scale_-this.offset_),
|
||||
this.SmallTickSize, "",
|
||||
new Point(0, 0), physicalMin, physicalMax,
|
||||
out tLabelOffset, out tBoundingBox );
|
||||
|
||||
// assume bounding box and label offset unchanged by small tick bounds.
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Determines the positions, in world coordinates, of the small ticks
|
||||
/// if they have not already been generated.
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="physicalMin">The physical position corresponding to the world minimum of the axis.</param>
|
||||
/// <param name="physicalMax">The physical position corresponding to the world maximum of the axis.</param>
|
||||
/// <param name="largeTickPositions">The positions of the large ticks.</param>
|
||||
/// <param name="smallTickPositions">If null, small tick positions are returned via this parameter. Otherwise this function does nothing.</param>
|
||||
internal override void WorldTickPositions_SecondPass(
|
||||
Point physicalMin,
|
||||
Point physicalMax,
|
||||
ArrayList largeTickPositions,
|
||||
ref ArrayList smallTickPositions )
|
||||
{
|
||||
|
||||
// return if already generated.
|
||||
if (smallTickPositions != null)
|
||||
return;
|
||||
|
||||
int physicalAxisLength = Utils.Distance( physicalMin, physicalMax );
|
||||
|
||||
double adjustedMax = this.AdjustedWorldValue( WorldMax );
|
||||
double adjustedMin = this.AdjustedWorldValue( WorldMin );
|
||||
|
||||
smallTickPositions = new ArrayList();
|
||||
|
||||
// TODO: Can optimize this now.
|
||||
bool shouldCullMiddle;
|
||||
double bigTickSpacing = this.DetermineLargeTickStep( physicalAxisLength, out shouldCullMiddle );
|
||||
|
||||
int nSmall = this.DetermineNumberSmallTicks( bigTickSpacing );
|
||||
double smallTickSpacing = bigTickSpacing / (double)nSmall;
|
||||
|
||||
// if there is at least one big tick
|
||||
if (largeTickPositions.Count > 0)
|
||||
{
|
||||
double pos1 = (double)largeTickPositions[0] - smallTickSpacing;
|
||||
while (pos1 > adjustedMin)
|
||||
{
|
||||
smallTickPositions.Add( pos1 );
|
||||
pos1 -= smallTickSpacing;
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < largeTickPositions.Count; ++i )
|
||||
{
|
||||
for (int j = 1; j < nSmall; ++j )
|
||||
{
|
||||
double pos = (double)largeTickPositions[i] + ((double)j) * smallTickSpacing;
|
||||
if (pos <= adjustedMax)
|
||||
{
|
||||
smallTickPositions.Add( pos );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adjusts a real world value to one that has been modified to
|
||||
/// reflect the Axis Scale and Offset properties.
|
||||
/// </summary>
|
||||
/// <param name="world">world value to adjust</param>
|
||||
/// <returns>adjusted world value</returns>
|
||||
public double AdjustedWorldValue( double world )
|
||||
{
|
||||
return world * this.scale_ + this.offset_;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Determines the positions, in world coordinates, of the large ticks.
|
||||
/// When the physical extent of the axis is small, some of the positions
|
||||
/// that were generated in this pass may be converted to small tick
|
||||
/// positions and returned as well.
|
||||
///
|
||||
/// If the LargeTickStep isn't set then this is calculated automatically and
|
||||
/// depends on the physical extent of the axis.
|
||||
/// </summary>
|
||||
/// <param name="physicalMin">The physical position corresponding to the world minimum of the axis.</param>
|
||||
/// <param name="physicalMax">The physical position corresponding to the world maximum of the axis.</param>
|
||||
/// <param name="largeTickPositions">ArrayList containing the positions of the large ticks.</param>
|
||||
/// <param name="smallTickPositions">ArrayList containing the positions of the small ticks if calculated, null otherwise.</param>
|
||||
internal override void WorldTickPositions_FirstPass(
|
||||
Point physicalMin,
|
||||
Point physicalMax,
|
||||
out ArrayList largeTickPositions,
|
||||
out ArrayList smallTickPositions
|
||||
)
|
||||
{
|
||||
|
||||
// (1) error check
|
||||
|
||||
if ( double.IsNaN(WorldMin) || double.IsNaN(WorldMax) )
|
||||
{
|
||||
throw new NPlotException( "world extent of axis not set." );
|
||||
}
|
||||
|
||||
double adjustedMax = this.AdjustedWorldValue( WorldMax );
|
||||
double adjustedMin = this.AdjustedWorldValue( WorldMin );
|
||||
|
||||
// (2) determine distance between large ticks.
|
||||
bool shouldCullMiddle;
|
||||
double tickDist = this.DetermineLargeTickStep(
|
||||
Utils.Distance(physicalMin, physicalMax),
|
||||
out shouldCullMiddle );
|
||||
|
||||
// (3) determine starting position.
|
||||
|
||||
double first = 0.0f;
|
||||
|
||||
if (!double.IsNaN(largeTickValue_))
|
||||
{
|
||||
// this works for both case when largTickValue_ lt or gt adjustedMin.
|
||||
first = largeTickValue_ + (Math.Ceiling((adjustedMin-largeTickValue_)/tickDist))*tickDist;
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
if( adjustedMin > 0.0 )
|
||||
{
|
||||
double nToFirst = Math.Floor(adjustedMin / tickDist) + 1.0f;
|
||||
first = nToFirst * tickDist;
|
||||
}
|
||||
else
|
||||
{
|
||||
double nToFirst = Math.Floor(-adjustedMin/tickDist) - 1.0f;
|
||||
first = -nToFirst * tickDist;
|
||||
}
|
||||
|
||||
// could miss one, if first is just below zero.
|
||||
if ((first - tickDist) >= adjustedMin)
|
||||
{
|
||||
first -= tickDist;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// (4) now make list of large tick positions.
|
||||
|
||||
largeTickPositions = new ArrayList();
|
||||
|
||||
if (tickDist < 0.0) // some sanity checking. TODO: remove this.
|
||||
throw new NPlotException( "Tick dist is negative" );
|
||||
|
||||
double position = first;
|
||||
int safetyCount = 0;
|
||||
while (
|
||||
(position <= adjustedMax) &&
|
||||
(++safetyCount < 5000) )
|
||||
{
|
||||
largeTickPositions.Add( position );
|
||||
position += tickDist;
|
||||
}
|
||||
|
||||
// (5) if the physical extent is too small, and the middle
|
||||
// ticks should be turned into small ticks, then do this now.
|
||||
smallTickPositions = null;
|
||||
if (shouldCullMiddle)
|
||||
{
|
||||
smallTickPositions = new ArrayList();
|
||||
|
||||
if (largeTickPositions.Count > 2)
|
||||
{
|
||||
for (int i=1; i<largeTickPositions.Count-1; ++i)
|
||||
{
|
||||
smallTickPositions.Add( largeTickPositions[i] );
|
||||
}
|
||||
}
|
||||
|
||||
ArrayList culledPositions = new ArrayList();
|
||||
culledPositions.Add( largeTickPositions[0] );
|
||||
culledPositions.Add( largeTickPositions[largeTickPositions.Count-1] );
|
||||
largeTickPositions = culledPositions;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Calculates the world spacing between large ticks, based on the physical
|
||||
/// axis length (parameter), world axis length, Mantissa values and
|
||||
/// MinPhysicalLargeTickStep. A value such that at least two
|
||||
/// </summary>
|
||||
/// <param name="physicalLength">physical length of the axis</param>
|
||||
/// <param name="shouldCullMiddle">Returns true if we were forced to make spacing of
|
||||
/// large ticks too small in order to ensure that there are at least two of
|
||||
/// them. The draw ticks method should not draw more than two large ticks if this
|
||||
/// returns true.</param>
|
||||
/// <returns>Large tick spacing</returns>
|
||||
/// <remarks>TODO: This can be optimised a bit.</remarks>
|
||||
private double DetermineLargeTickStep( float physicalLength, out bool shouldCullMiddle )
|
||||
{
|
||||
shouldCullMiddle = false;
|
||||
|
||||
if ( double.IsNaN(WorldMin) || double.IsNaN(WorldMax) )
|
||||
{
|
||||
throw new NPlotException( "world extent of axis not set." );
|
||||
}
|
||||
|
||||
// if the large tick has been explicitly set, then return this.
|
||||
if ( !double.IsNaN(largeTickStep_) )
|
||||
{
|
||||
if ( largeTickStep_ <= 0.0f )
|
||||
{
|
||||
throw new NPlotException(
|
||||
"can't have negative or zero tick step - reverse WorldMin WorldMax instead."
|
||||
);
|
||||
}
|
||||
return largeTickStep_;
|
||||
}
|
||||
|
||||
// otherwise we need to calculate the large tick step ourselves.
|
||||
|
||||
// adjust world max and min for offset and scale properties of axis.
|
||||
double adjustedMax = this.AdjustedWorldValue( WorldMax );
|
||||
double adjustedMin = this.AdjustedWorldValue( WorldMin );
|
||||
double range = adjustedMax - adjustedMin;
|
||||
|
||||
// if axis has zero world length, then return arbitrary number.
|
||||
if ( Utils.DoubleEqual( adjustedMax, adjustedMin ) )
|
||||
{
|
||||
return 1.0f;
|
||||
}
|
||||
|
||||
double approxTickStep;
|
||||
if (TicksIndependentOfPhysicalExtent)
|
||||
{
|
||||
approxTickStep = range / 6.0f;
|
||||
}
|
||||
else
|
||||
{
|
||||
approxTickStep = (MinPhysicalLargeTickStep / physicalLength) * range;
|
||||
}
|
||||
|
||||
double exponent = Math.Floor( Math.Log10( approxTickStep ) );
|
||||
double mantissa = Math.Pow( 10.0, Math.Log10( approxTickStep ) - exponent );
|
||||
|
||||
// determine next whole mantissa below the approx one.
|
||||
int mantissaIndex = Mantissas.Length-1;
|
||||
for (int i=1; i<Mantissas.Length; ++i)
|
||||
{
|
||||
if (mantissa < Mantissas[i])
|
||||
{
|
||||
mantissaIndex = i-1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// then choose next largest spacing.
|
||||
mantissaIndex += 1;
|
||||
if (mantissaIndex == Mantissas.Length)
|
||||
{
|
||||
mantissaIndex = 0;
|
||||
exponent += 1.0;
|
||||
}
|
||||
|
||||
if (!TicksIndependentOfPhysicalExtent)
|
||||
{
|
||||
// now make sure that the returned value is such that at least two
|
||||
// large tick marks will be displayed.
|
||||
double tickStep = Math.Pow( 10.0, exponent ) * Mantissas[mantissaIndex];
|
||||
float physicalStep = (float)((tickStep / range) * physicalLength);
|
||||
|
||||
while (physicalStep > physicalLength/2)
|
||||
{
|
||||
shouldCullMiddle = true;
|
||||
|
||||
mantissaIndex -= 1;
|
||||
if (mantissaIndex == -1)
|
||||
{
|
||||
mantissaIndex = Mantissas.Length-1;
|
||||
exponent -= 1.0;
|
||||
}
|
||||
|
||||
tickStep = Math.Pow( 10.0, exponent ) * Mantissas[mantissaIndex];
|
||||
physicalStep = (float)((tickStep / range) * physicalLength);
|
||||
}
|
||||
}
|
||||
|
||||
// and we're done.
|
||||
return Math.Pow( 10.0, exponent ) * Mantissas[mantissaIndex];
|
||||
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Given the large tick step, determine the number of small ticks that should
|
||||
/// be placed in between.
|
||||
/// </summary>
|
||||
/// <param name="bigTickDist">the large tick step.</param>
|
||||
/// <returns>the number of small ticks to place between large ticks.</returns>
|
||||
private int DetermineNumberSmallTicks( double bigTickDist )
|
||||
{
|
||||
|
||||
if (this.numberSmallTicks_ != null)
|
||||
{
|
||||
return (int)this.numberSmallTicks_+1;
|
||||
}
|
||||
|
||||
if (this.SmallTickCounts.Length != this.Mantissas.Length)
|
||||
{
|
||||
throw new NPlotException( "Mantissa.Length != SmallTickCounts.Length" );
|
||||
}
|
||||
|
||||
if (bigTickDist > 0.0f)
|
||||
{
|
||||
|
||||
double exponent = Math.Floor( Math.Log10( bigTickDist ) );
|
||||
double mantissa = Math.Pow( 10.0, Math.Log10( bigTickDist ) - exponent );
|
||||
|
||||
for (int i=0; i<Mantissas.Length; ++i)
|
||||
{
|
||||
if ( Math.Abs(mantissa-Mantissas[i]) < 0.001 )
|
||||
{
|
||||
return SmallTickCounts[i]+1;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// The distance between large ticks. If this is set to NaN [default],
|
||||
/// this distance will be calculated automatically.
|
||||
/// </summary>
|
||||
public double LargeTickStep
|
||||
{
|
||||
set
|
||||
{
|
||||
largeTickStep_ = value;
|
||||
}
|
||||
get
|
||||
{
|
||||
return largeTickStep_;
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// If set !NaN, gives the distance between large ticks.
|
||||
/// </summary>
|
||||
private double largeTickStep_ = double.NaN;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// If set, a large tick will be placed at this position, and other large ticks will
|
||||
/// be placed relative to this position.
|
||||
/// </summary>
|
||||
public double LargeTickValue
|
||||
{
|
||||
set
|
||||
{
|
||||
largeTickValue_ = value;
|
||||
}
|
||||
get
|
||||
{
|
||||
return largeTickValue_;
|
||||
}
|
||||
}
|
||||
private double largeTickValue_ = double.NaN;
|
||||
|
||||
/// <summary>
|
||||
/// The number of small ticks between large ticks.
|
||||
/// </summary>
|
||||
public int NumberOfSmallTicks
|
||||
{
|
||||
set
|
||||
{
|
||||
numberSmallTicks_ = value;
|
||||
}
|
||||
get
|
||||
{
|
||||
// TODO: something better here.
|
||||
return (int)numberSmallTicks_;
|
||||
}
|
||||
}
|
||||
private object numberSmallTicks_ = null;
|
||||
|
||||
/// <summary>
|
||||
/// Scale to apply to world values when labelling axis:
|
||||
/// (labelWorld = world * scale + offset). This does not
|
||||
/// affect the "real" world range of the axis.
|
||||
/// </summary>
|
||||
public double Scale
|
||||
{
|
||||
get
|
||||
{
|
||||
return scale_;
|
||||
}
|
||||
set
|
||||
{
|
||||
scale_ = value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Offset to apply to world values when labelling the axis:
|
||||
/// (labelWorld = axisWorld * scale + offset). This does not
|
||||
/// affect the "real" world range of the axis.
|
||||
/// </summary>
|
||||
public double Offset
|
||||
{
|
||||
get
|
||||
{
|
||||
return offset_;
|
||||
}
|
||||
set
|
||||
{
|
||||
offset_ = value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// If LargeTickStep isn't specified, then a suitable value is
|
||||
/// calculated automatically. To determine the tick spacing, the
|
||||
/// world axis length is divided by ApproximateNumberLargeTicks
|
||||
/// and the next lowest distance m*10^e for some m in the Mantissas
|
||||
/// set and some integer e is used as the large tick spacing.
|
||||
/// </summary>
|
||||
public float ApproxNumberLargeTicks = 3.0f;
|
||||
|
||||
/// <summary>
|
||||
/// If LargeTickStep isn't specified, then a suitable value is
|
||||
/// calculated automatically. The value will be of the form
|
||||
/// m*10^e for some m in this set.
|
||||
/// </summary>
|
||||
public double[] Mantissas = {1.0, 2.0, 5.0};
|
||||
|
||||
/// <summary>
|
||||
/// If NumberOfSmallTicks isn't specified then ....
|
||||
/// If specified LargeTickStep manually, then no small ticks unless
|
||||
/// NumberOfSmallTicks specified.
|
||||
/// </summary>
|
||||
public int[] SmallTickCounts = {4, 1, 4};
|
||||
|
||||
|
||||
private double offset_ = 0.0;
|
||||
|
||||
private double scale_ = 1.0;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,159 @@
|
|||
/*
|
||||
NPlot - A charting library for .NET
|
||||
|
||||
Gradient.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>
|
||||
/// Class for creating a linear gradient.
|
||||
/// </summary>
|
||||
public class LinearGradient : IGradient
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// Constructor.
|
||||
/// </summary>
|
||||
/// <param name="minColor">The color corresponding to 0.0</param>
|
||||
/// <param name="maxColor">The color corresponding to 1.0</param>
|
||||
public LinearGradient( Color minColor, Color maxColor )
|
||||
{
|
||||
this.minColor_ = minColor;
|
||||
this.maxColor_ = maxColor;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// The color corresponding to 0.0
|
||||
/// </summary>
|
||||
public Color MaxColor
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.maxColor_;
|
||||
}
|
||||
set
|
||||
{
|
||||
this.maxColor_ = value;
|
||||
}
|
||||
}
|
||||
private Color maxColor_;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// The color corresponding to 1.0
|
||||
/// </summary>
|
||||
public Color MinColor
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.minColor_;
|
||||
}
|
||||
set
|
||||
{
|
||||
this.minColor_ = value;
|
||||
}
|
||||
}
|
||||
private Color minColor_;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// The color corresponding to NaN
|
||||
/// </summary>
|
||||
public Color VoidColor
|
||||
{
|
||||
get
|
||||
{
|
||||
return voidColor_;
|
||||
}
|
||||
set
|
||||
{
|
||||
voidColor_ = value;
|
||||
}
|
||||
}
|
||||
private Color voidColor_ = Color.Black;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Gets a color corresponding to a number between 0.0 and 1.0 inclusive. The color will
|
||||
/// be a linear interpolation of the min and max colors.
|
||||
/// </summary>
|
||||
/// <param name="prop">the number to get corresponding color for (between 0.0 and 1.0)</param>
|
||||
/// <returns>The color corresponding to the supplied number.</returns>
|
||||
public Color GetColor( double prop )
|
||||
{
|
||||
if (Double.IsNaN(prop))
|
||||
{
|
||||
return voidColor_;
|
||||
}
|
||||
|
||||
if ( prop <= 0.0 )
|
||||
{
|
||||
return this.MinColor;
|
||||
}
|
||||
|
||||
if ( prop >= 1.0 )
|
||||
{
|
||||
return this.MaxColor;
|
||||
}
|
||||
|
||||
byte r = (byte)((int)(this.MinColor.R) + (int)(((double)this.MaxColor.R - (double)this.MinColor.R)*prop));
|
||||
byte g = (byte)((int)(this.MinColor.G) + (int)(((double)this.MaxColor.G - (double)this.MinColor.G)*prop));
|
||||
byte b = (byte)((int)(this.MinColor.B) + (int)(((double)this.MaxColor.B - (double)this.MinColor.B)*prop));
|
||||
|
||||
return Color.FromArgb(r,g,b);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,678 @@
|
|||
/*
|
||||
NPlot - A charting library for .NET
|
||||
|
||||
LogAxis.cs
|
||||
Copyright (C) 2003
|
||||
Paolo Pierini, 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.Collections;
|
||||
using System.Text;
|
||||
|
||||
namespace NPlot
|
||||
{
|
||||
/// <summary>
|
||||
/// The class implementing logarithmic axes.
|
||||
/// </summary>
|
||||
public class LogAxis : Axis
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// Deep Copy of the LogAxis.
|
||||
/// </summary>
|
||||
/// <returns>A Copy of the LogAxis Class.</returns>
|
||||
public override object Clone()
|
||||
{
|
||||
LogAxis a = new LogAxis();
|
||||
if (this.GetType() != a.GetType())
|
||||
{
|
||||
throw new NPlotException("Clone not defined in derived type. Help!");
|
||||
}
|
||||
this.DoClone( this, a );
|
||||
return a;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Helper method for Clone (actual implementation)
|
||||
/// </summary>
|
||||
/// <param name="a">The original object to clone.</param>
|
||||
/// <param name="b">The cloned object.</param>
|
||||
protected void DoClone(LogAxis b, LogAxis a)
|
||||
{
|
||||
Axis.DoClone(b,a);
|
||||
// add specific elemtents of the class for the deep copy of the object
|
||||
a.numberSmallTicks_ = b.numberSmallTicks_;
|
||||
a.largeTickValue_ = b.largeTickValue_;
|
||||
a.largeTickStep_ = b.largeTickStep_;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Default constructor.
|
||||
/// </summary>
|
||||
public LogAxis()
|
||||
: base()
|
||||
{
|
||||
Init();
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Copy Constructor
|
||||
/// </summary>
|
||||
/// <param name="a">The Axis to clone.</param>
|
||||
public LogAxis(Axis a)
|
||||
: base(a)
|
||||
{
|
||||
Init();
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Constructor
|
||||
/// </summary>
|
||||
/// <param name="worldMin">Minimum World value for the axis.</param>
|
||||
/// <param name="worldMax">Maximum World value for the axis.</param>
|
||||
public LogAxis(double worldMin, double worldMax)
|
||||
: base( worldMin, worldMax )
|
||||
{
|
||||
Init();
|
||||
}
|
||||
|
||||
|
||||
private void Init()
|
||||
{
|
||||
this.NumberFormat = "{0:g5}";
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Draw the ticks.
|
||||
/// </summary>
|
||||
/// <param name="g">The drawing surface on which to draw.</param>
|
||||
/// <param name="physicalMin">The minimum physical extent of the axis.</param>
|
||||
/// <param name="physicalMax">The maximum physical extent of the axis.</param>
|
||||
/// <param name="boundingBox">out: smallest box that completely encompasses all of the ticks and tick labels.</param>
|
||||
/// <param name="labelOffset">out: a suitable offset from the axis to draw the axis label.</param>
|
||||
/// <returns> An ArrayList containing the offset from the axis required for an axis label
|
||||
/// to miss this tick, followed by a bounding rectangle for the tick and tickLabel drawn.</returns>
|
||||
protected override void DrawTicks(
|
||||
Graphics g,
|
||||
Point physicalMin,
|
||||
Point physicalMax,
|
||||
out object labelOffset,
|
||||
out object boundingBox )
|
||||
{
|
||||
|
||||
Point tLabelOffset;
|
||||
Rectangle tBoundingBox;
|
||||
|
||||
labelOffset = this.getDefaultLabelOffset( physicalMin, physicalMax );
|
||||
boundingBox = null;
|
||||
|
||||
ArrayList largeTickPositions;
|
||||
ArrayList smallTickPositions;
|
||||
this.WorldTickPositions( physicalMin, physicalMax, out largeTickPositions, out smallTickPositions );
|
||||
|
||||
Point offset = new Point( 0, 0 );
|
||||
object bb = null;
|
||||
// Missed this protection
|
||||
if (largeTickPositions.Count > 0)
|
||||
{
|
||||
for (int i=0; i<largeTickPositions.Count; ++i)
|
||||
{
|
||||
StringBuilder label = new StringBuilder();
|
||||
// do google search for "format specifier writeline" for help on this.
|
||||
label.AppendFormat(this.NumberFormat, (double)largeTickPositions[i]);
|
||||
this.DrawTick( g, (double)largeTickPositions[i], this.LargeTickSize, label.ToString(),
|
||||
new Point(0,0), physicalMin, physicalMax, out tLabelOffset, out tBoundingBox );
|
||||
|
||||
Axis.UpdateOffsetAndBounds( ref labelOffset, ref boundingBox, tLabelOffset, tBoundingBox );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// just get the axis bounding box)
|
||||
PointF dir = Utils.UnitVector(physicalMin,physicalMax);
|
||||
Rectangle rr = new Rectangle( physicalMin.X,
|
||||
(int)((physicalMax.X-physicalMin.X)*dir.X),
|
||||
physicalMin.Y,
|
||||
(int)((physicalMax.Y-physicalMin.Y)*dir.Y) );
|
||||
bb = rr;
|
||||
}
|
||||
|
||||
|
||||
// missed protection for zero ticks
|
||||
if (smallTickPositions.Count > 0)
|
||||
{
|
||||
for (int i=0; i<smallTickPositions.Count; ++i)
|
||||
{
|
||||
this.DrawTick( g, (double)smallTickPositions[i], this.SmallTickSize,
|
||||
"", new Point(0,0), physicalMin, physicalMax, out tLabelOffset, out tBoundingBox );
|
||||
// ignore r for now - assume bb unchanged by small tick bounds.
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Determines the positions, in world coordinates, of the small ticks
|
||||
/// if they have not already been generated.
|
||||
/// </summary>
|
||||
/// <param name="physicalMin">The physical position corresponding to the world minimum of the axis.</param>
|
||||
/// <param name="physicalMax">The physical position corresponding to the world maximum of the axis.</param>
|
||||
/// <param name="largeTickPositions">The positions of the large ticks, unchanged</param>
|
||||
/// <param name="smallTickPositions">If null, small tick positions are returned via this parameter. Otherwise this function does nothing.</param>
|
||||
internal override void WorldTickPositions_SecondPass(
|
||||
Point physicalMin,
|
||||
Point physicalMax,
|
||||
ArrayList largeTickPositions,
|
||||
ref ArrayList smallTickPositions )
|
||||
{
|
||||
|
||||
if (smallTickPositions != null)
|
||||
{
|
||||
throw new NPlotException( "not expecting smallTickPositions to be set already." );
|
||||
}
|
||||
|
||||
smallTickPositions = new ArrayList();
|
||||
|
||||
// retrieve the spacing of the big ticks. Remember this is decades!
|
||||
double bigTickSpacing = this.DetermineTickSpacing();
|
||||
int nSmall = this.DetermineNumberSmallTicks( bigTickSpacing );
|
||||
|
||||
// now we have to set the ticks
|
||||
// let us start with the easy case where the major tick distance
|
||||
// is larger than a decade
|
||||
if ( bigTickSpacing > 1.0f )
|
||||
{
|
||||
if (largeTickPositions.Count > 0)
|
||||
{
|
||||
// deal with the smallticks preceding the
|
||||
// first big tick
|
||||
double pos1 = (double)largeTickPositions[0];
|
||||
while (pos1 > this.WorldMin)
|
||||
{
|
||||
pos1 = pos1 / 10.0f;
|
||||
smallTickPositions.Add( pos1 );
|
||||
}
|
||||
// now go on for all other Major ticks
|
||||
for (int i=0; i<largeTickPositions.Count; ++i )
|
||||
{
|
||||
double pos = (double)largeTickPositions[i];
|
||||
for (int j=1; j<=nSmall; ++j )
|
||||
{
|
||||
pos=pos*10.0F;
|
||||
// check to see if we are still in the range
|
||||
if (pos < WorldMax)
|
||||
{
|
||||
smallTickPositions.Add( pos );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// guess what...
|
||||
double [] m = { 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f, 8.0f, 9.0f };
|
||||
// Then we deal with the other ticks
|
||||
if (largeTickPositions.Count > 0)
|
||||
{
|
||||
// first deal with the smallticks preceding the first big tick
|
||||
// positioning before the first tick
|
||||
double pos1=(double)largeTickPositions[0]/10.0f;
|
||||
for (int i=0; i<m.Length; i++)
|
||||
{
|
||||
double pos=pos1*m[i];
|
||||
if (pos>this.WorldMin)
|
||||
{
|
||||
smallTickPositions.Add(pos);
|
||||
}
|
||||
}
|
||||
// now go on for all other Major ticks
|
||||
for (int i=0; i<largeTickPositions.Count; ++i )
|
||||
{
|
||||
pos1=(double)largeTickPositions[i];
|
||||
for (int j=0; j<m.Length; ++j )
|
||||
{
|
||||
double pos=pos1*m[j];
|
||||
// check to see if we are still in the range
|
||||
if (pos < WorldMax)
|
||||
{
|
||||
smallTickPositions.Add( pos );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// probably a minor tick would anyway fall in the range
|
||||
// find the decade preceding the minimum
|
||||
double dec=Math.Floor(Math.Log10(WorldMin));
|
||||
double pos1=Math.Pow(10.0,dec);
|
||||
for (int i=0; i<m.Length; i++)
|
||||
{
|
||||
double pos=pos1*m[i];
|
||||
if (pos>this.WorldMin && pos< this.WorldMax )
|
||||
{
|
||||
smallTickPositions.Add(pos);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static double m_d5Log = -Math.Log10(0.5); // .30103
|
||||
private static double m_d5RegionPos = Math.Abs(m_d5Log + ((1 - m_d5Log) / 2)); // ' .6505
|
||||
private static double m_d5RegionNeg = Math.Abs(m_d5Log / 2); // '.1505
|
||||
|
||||
private void CalcGrids( double dLenAxis, int nNumDivisions, ref double dDivisionInterval)
|
||||
{
|
||||
double dMyInterval = dLenAxis / nNumDivisions;
|
||||
double dPower = Math.Log10(dMyInterval);
|
||||
dDivisionInterval = 10 ^ (int)dPower;
|
||||
double dFixPower = dPower - (int)dPower;
|
||||
double d5Region = Math.Abs(dPower - dFixPower);
|
||||
double dMyMult;
|
||||
if (dPower < 0)
|
||||
{
|
||||
d5Region = -(dPower - dFixPower);
|
||||
dMyMult = 0.5;
|
||||
}
|
||||
else
|
||||
{
|
||||
d5Region = 1 - (dPower - dFixPower);
|
||||
dMyMult = 5;
|
||||
}
|
||||
if ((d5Region >= m_d5RegionNeg) && (d5Region <= m_d5RegionPos))
|
||||
{
|
||||
dDivisionInterval = dDivisionInterval * dMyMult;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Determines the positions, in world coordinates, of the log spaced large ticks.
|
||||
/// </summary>
|
||||
/// <param name="physicalMin">The physical position corresponding to the world minimum of the axis.</param>
|
||||
/// <param name="physicalMax">The physical position corresponding to the world maximum of the axis.</param>
|
||||
/// <param name="largeTickPositions">ArrayList containing the positions of the large ticks.</param>
|
||||
/// <param name="smallTickPositions">null</param>
|
||||
internal override void WorldTickPositions_FirstPass(
|
||||
Point physicalMin,
|
||||
Point physicalMax,
|
||||
out ArrayList largeTickPositions,
|
||||
out ArrayList smallTickPositions
|
||||
)
|
||||
{
|
||||
|
||||
smallTickPositions = null;
|
||||
largeTickPositions = new ArrayList();
|
||||
|
||||
if ( double.IsNaN(WorldMin) || double.IsNaN(WorldMax) )
|
||||
{
|
||||
throw new NPlotException( "world extent of axis not set." );
|
||||
}
|
||||
|
||||
double roundTickDist = this.DetermineTickSpacing( );
|
||||
|
||||
// now determine first tick position.
|
||||
double first = 0.0f;
|
||||
|
||||
// if the user hasn't specified a large tick position.
|
||||
if (double.IsNaN(largeTickValue_))
|
||||
{
|
||||
if( WorldMin > 0.0 )
|
||||
{
|
||||
|
||||
double nToFirst = Math.Floor(Math.Log10(WorldMin) / roundTickDist)+1.0f;
|
||||
first = nToFirst * roundTickDist;
|
||||
}
|
||||
|
||||
// could miss one, if first is just below zero.
|
||||
if (first-roundTickDist >= Math.Log10(WorldMin))
|
||||
{
|
||||
first -= roundTickDist;
|
||||
}
|
||||
}
|
||||
|
||||
// the user has specified one place they would like a large tick placed.
|
||||
else
|
||||
{
|
||||
first = Math.Log10( this.LargeTickValue );
|
||||
|
||||
// TODO: check here not too much different.
|
||||
// could result in long loop.
|
||||
while (first < Math.Log10(WorldMin))
|
||||
{
|
||||
first += roundTickDist;
|
||||
}
|
||||
|
||||
while (first > Math.Log10(WorldMin)+roundTickDist)
|
||||
{
|
||||
first -= roundTickDist;
|
||||
}
|
||||
}
|
||||
|
||||
double mark = first;
|
||||
while (mark <= Math.Log10(WorldMax))
|
||||
{
|
||||
// up to here only logs are dealt with, but I want to return
|
||||
// a real value in the arraylist
|
||||
double val;
|
||||
val = Math.Pow( 10.0, mark );
|
||||
largeTickPositions.Add( val );
|
||||
mark += roundTickDist;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Determines the tick spacing.
|
||||
/// </summary>
|
||||
/// <returns>The tick spacing (in decades!)</returns>
|
||||
private double DetermineTickSpacing( )
|
||||
{
|
||||
if ( double.IsNaN(WorldMin) || double.IsNaN(WorldMax) )
|
||||
{
|
||||
throw new NPlotException( "world extent of axis is not set." );
|
||||
}
|
||||
|
||||
// if largeTickStep has been set, it is used
|
||||
if ( !double.IsNaN( this.largeTickStep_) )
|
||||
{
|
||||
if ( this.largeTickStep_ <= 0.0f )
|
||||
{
|
||||
throw new NPlotException( "can't have negative tick step - reverse WorldMin WorldMax instead." );
|
||||
}
|
||||
|
||||
return this.largeTickStep_;
|
||||
}
|
||||
|
||||
double MagRange = (double)(Math.Floor(Math.Log10(WorldMax)) - Math.Floor(Math.Log10(WorldMin))+1.0);
|
||||
|
||||
if ( MagRange > 0.0 )
|
||||
{
|
||||
// for now, a simple logic
|
||||
// start with a major tick every order of magnitude, and
|
||||
// increment if in order not to have more than 10 ticks in
|
||||
// the plot.
|
||||
double roundTickDist=1.0F;
|
||||
int nticks=(int)(MagRange/roundTickDist);
|
||||
while (nticks > 10)
|
||||
{
|
||||
roundTickDist++;
|
||||
nticks=(int)(MagRange/roundTickDist);
|
||||
}
|
||||
return roundTickDist;
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0.0f;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Determines the number of small ticks between two large ticks.
|
||||
/// </summary>
|
||||
/// <param name="bigTickDist">The distance between two large ticks.</param>
|
||||
/// <returns>The number of small ticks.</returns>
|
||||
private int DetermineNumberSmallTicks( double bigTickDist )
|
||||
{
|
||||
// if the big ticks is more than one decade, the
|
||||
// small ticks are every decade, I don't let the user set it.
|
||||
if (this.numberSmallTicks_ != null && bigTickDist == 1.0f)
|
||||
{
|
||||
return (int)this.numberSmallTicks_+1;
|
||||
}
|
||||
|
||||
// if we are plotting every decade, we have to
|
||||
// put the log ticks. As a start, I put every
|
||||
// small tick (.2,.3,.4,.5,.6,.7,.8,.9)
|
||||
if (bigTickDist == 1.0f)
|
||||
{
|
||||
return 8;
|
||||
}
|
||||
// easy, put a tick every missed decade
|
||||
else if (bigTickDist > 1.0f)
|
||||
{
|
||||
return (int)bigTickDist - 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new NPlotException("Wrong Major tick distance setting");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// The step between large ticks, expressed in decades for the Log scale.
|
||||
/// </summary>
|
||||
public double LargeTickStep
|
||||
{
|
||||
set
|
||||
{
|
||||
largeTickStep_ = value;
|
||||
}
|
||||
get
|
||||
{
|
||||
return largeTickStep_;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Position of one of the large ticks [other positions will be calculated relative to this one].
|
||||
/// </summary>
|
||||
public double LargeTickValue
|
||||
{
|
||||
set
|
||||
{
|
||||
largeTickValue_ = value;
|
||||
}
|
||||
get
|
||||
{
|
||||
return largeTickValue_;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// The number of small ticks between large ticks.
|
||||
/// </summary>
|
||||
public int NumberSmallTicks
|
||||
{
|
||||
set
|
||||
{
|
||||
numberSmallTicks_ = value;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Private members
|
||||
private object numberSmallTicks_;
|
||||
private double largeTickValue_ = double.NaN;
|
||||
private double largeTickStep_ = double.NaN;
|
||||
|
||||
/// <summary>
|
||||
/// World to physical coordinate transform.
|
||||
/// </summary>
|
||||
/// <param name="coord">The coordinate value to transform.</param>
|
||||
/// <param name="physicalMin">The physical position corresponding to the world minimum of the axis.</param>
|
||||
/// <param name="physicalMax">The physical position corresponding to the world maximum of the axis.</param>
|
||||
/// <param name="clip">if false, then physical value may extend outside worldMin / worldMax. If true, the physical value returned will be clipped to physicalMin or physicalMax if it lies outside this range.</param>
|
||||
/// <returns>The transformed coordinates.</returns>
|
||||
/// <remarks>TODO: make Reversed property work for this.</remarks>
|
||||
public override PointF WorldToPhysical(
|
||||
double coord,
|
||||
PointF physicalMin,
|
||||
PointF physicalMax,
|
||||
bool clip )
|
||||
{
|
||||
// if want clipped value, return extrema if outside range.
|
||||
if (clip)
|
||||
{
|
||||
if (coord > WorldMax)
|
||||
{
|
||||
return physicalMax;
|
||||
}
|
||||
if (coord < WorldMin)
|
||||
{
|
||||
return physicalMin;
|
||||
}
|
||||
}
|
||||
|
||||
if (coord < 0.0f)
|
||||
{
|
||||
throw new NPlotException( "Cannot have negative values for data using Log Axis" );
|
||||
}
|
||||
|
||||
// inside range or don't want to clip.
|
||||
double lrange = (double)(Math.Log10(WorldMax) - Math.Log10(WorldMin));
|
||||
double prop = (double)((Math.Log10(coord) - Math.Log10(WorldMin)) / lrange);
|
||||
PointF offset = new PointF( (float)(prop * (physicalMax.X - physicalMin.X)),
|
||||
(float)(prop * (physicalMax.Y - physicalMin.Y)) );
|
||||
|
||||
return new PointF( physicalMin.X + offset.X, physicalMin.Y + offset.Y );
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Return the world coordinate of the projection of the point p onto
|
||||
/// the axis.
|
||||
/// </summary>
|
||||
/// <param name="p">The point to project onto the axis</param>
|
||||
/// <param name="physicalMin">The physical position corresponding to the world minimum of the axis.</param>
|
||||
/// <param name="physicalMax">The physical position corresponding to the world maximum of the axis.</param>
|
||||
/// <param name="clip">If true, the world value will be clipped to WorldMin or WorldMax as appropriate if it lies outside this range.</param>
|
||||
/// <returns>The world value corresponding to the projection of the point p onto the axis.</returns>
|
||||
public override double PhysicalToWorld( PointF p, PointF physicalMin, PointF physicalMax, bool clip )
|
||||
{
|
||||
// use the base method to do the projection on the axis.
|
||||
double t = base.PhysicalToWorld( p, physicalMin, physicalMax, clip );
|
||||
|
||||
// now reconstruct phys dist prop along this assuming linear scale as base method did.
|
||||
double v = (t - this.WorldMin) / (this.WorldMax - this.WorldMin);
|
||||
|
||||
double ret = WorldMin*Math.Pow( WorldMax / WorldMin, v );
|
||||
|
||||
// if want clipped value, return extrema if outside range.
|
||||
if (clip)
|
||||
{
|
||||
ret = Math.Max( ret, WorldMin );
|
||||
ret = Math.Min( ret, WorldMax );
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// The minimum world extent of the axis. Must be greater than zero.
|
||||
/// </summary>
|
||||
public override double WorldMin
|
||||
{
|
||||
get
|
||||
{
|
||||
return (double)base.WorldMin;
|
||||
}
|
||||
set
|
||||
{
|
||||
if (value > 0.0f)
|
||||
{
|
||||
base.WorldMin = value;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new NPlotException("Cannot have negative values in Log Axis");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// The maximum world extent of the axis. Must be greater than zero.
|
||||
/// </summary>
|
||||
public override double WorldMax
|
||||
{
|
||||
get
|
||||
{
|
||||
return (double)base.WorldMax;
|
||||
}
|
||||
set
|
||||
{
|
||||
if (value > 0.0F)
|
||||
{
|
||||
base.WorldMax = value;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new NPlotException("Cannot have negative values in Log Axis");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get whether or not this axis is linear. It is not.
|
||||
/// </summary>
|
||||
public override bool IsLinear
|
||||
{
|
||||
get
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -0,0 +1,99 @@
|
|||
CSC=mcs -debug+
|
||||
VERSION=0.9.9.2
|
||||
NPLOT_SOURCES = \
|
||||
AdapterUtils.cs \
|
||||
NPlotException.cs \
|
||||
ArrowItem.cs \
|
||||
AssemblyInfo.cs \
|
||||
AxesConstraint.cs \
|
||||
Axis.cs \
|
||||
BasePlot.cs \
|
||||
BaseSequenceLinePlot.cs \
|
||||
BaseSequencePlot.cs \
|
||||
Bitmap.PlotSurface2D.cs \
|
||||
CandlePlot.cs \
|
||||
DateTimeAxis.cs \
|
||||
ErrorHandler.cs \
|
||||
FilledRegion.cs \
|
||||
FontScaler.cs \
|
||||
Grid.cs \
|
||||
HistogramPlot.cs \
|
||||
HorizontalLine.cs \
|
||||
IDrawable.cs \
|
||||
IGradient.cs \
|
||||
ImagePlot.cs \
|
||||
IMeshPlot.cs \
|
||||
IPlot.cs \
|
||||
IPlotSurface2D.cs \
|
||||
ITransform2D.cs \
|
||||
ISequencePlot.cs \
|
||||
LabelAxis.cs \
|
||||
LabelPointPlot.cs \
|
||||
LegendBase.cs \
|
||||
Legend.cs \
|
||||
LinearAxis.cs \
|
||||
LinearGradient.cs \
|
||||
LinePlot.cs \
|
||||
LogAxis.cs \
|
||||
Marker.cs \
|
||||
MarkerItem.cs \
|
||||
PageAlignedPhysicalAxis.cs \
|
||||
PhysicalAxis.cs \
|
||||
PiAxis.cs \
|
||||
PiePlot.cs \
|
||||
PlotSurface2D.cs \
|
||||
PlotSurface3D.cs \
|
||||
PointD.cs \
|
||||
PointPlot.cs \
|
||||
RectangleBrushes.cs \
|
||||
RectangleD.cs \
|
||||
SequenceAdapter.cs \
|
||||
StartStep.cs \
|
||||
StepPlot.cs \
|
||||
Transform2D.cs \
|
||||
Utils.cs \
|
||||
VerticalLine.cs \
|
||||
Web.Design.PlotSurface2D.cs \
|
||||
Web.PlotSurface2D.cs
|
||||
|
||||
NPLOT_GTK_SOURCES = \
|
||||
Gtk.PlotSurface2D.cs \
|
||||
sysdraw.cs
|
||||
|
||||
all: NPlot.dll NPlot.Gtk.dll tests
|
||||
|
||||
tests: mf.exe test.exe
|
||||
|
||||
NPLOT_DLLS= -r:System.Web \
|
||||
-r:System.Design \
|
||||
-r:System.Drawing \
|
||||
-r:System.Data
|
||||
|
||||
NPLOT_GTK_DLLS= -r:System.Web \
|
||||
-r:System.Design \
|
||||
-r:System.Drawing \
|
||||
-r:System.Data \
|
||||
-pkg:gtk-sharp-2.0 \
|
||||
-r:NPlot.dll
|
||||
|
||||
|
||||
NPlot.dll: $(NPLOT_SOURCES) Makefile
|
||||
$(CSC) $(NPLOT_SOURCES) -target:library -out:NPlot.dll $(NPLOT_DLLS)
|
||||
|
||||
NPlot.Gtk.dll: $(NPLOT_SOURCES) $(NPLOT_GTK_SOURCES) NPlot.dll Makefile
|
||||
$(CSC) $(NPLOT_GTK_SOURCES) -target:library -out:NPlot.Gtk.dll $(NPLOT_GTK_DLLS)
|
||||
|
||||
mf.exe: MainForm.cs NPlot.Gtk.dll
|
||||
$(CSC) MainForm.cs -out:mf.exe -r:NPlot.dll -r:NPlot.Gtk.dll -pkg:gtk-sharp-2.0 -r:System.Drawing -r:System.Data -resource:asx_jbh.xml,NPlotDemo.resources.asx_jbh.xml
|
||||
|
||||
test.exe: NPlot.dll test.cs
|
||||
$(CSC) test.cs -r:NPlot.dll -r:NPlot.Gtk.dll -pkg:gtk-sharp-2.0 -r:System.Drawing
|
||||
|
||||
install: NPlot.dll NPlot.Gtk.dll
|
||||
-mkdir -p $(prefix)/lib/nplot
|
||||
cp NPlot.dll NPlot.Gtk.dll $(prefix)/lib/mono/1.0/
|
||||
sed -e "s,@prefix@,$(prefix),g" -e "s/@VERSION@/$(VERSION)/" < nplot.pc.in > $(prefix)/lib/pkgconfig/nplot.pc
|
||||
sed -e "s,@prefix@,$(prefix),g" -e "s/@VERSION@/$(VERSION)/" < nplot-gtk.pc.in > $(prefix)/lib/pkgconfig/nplot-gtk.pc
|
||||
|
||||
clean:
|
||||
rm *exe *dll *mdb
|
|
@ -0,0 +1,487 @@
|
|||
/*
|
||||
NPlot - A charting library for .NET
|
||||
|
||||
Marker.cs
|
||||
Copyright (C) 2003
|
||||
Paolo Pierini, 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>
|
||||
/// Encapsulates functionality relating to markers used by the PointPlot class.
|
||||
/// </summary>
|
||||
public class Marker
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// Enumeration of all different types of marker.
|
||||
/// </summary>
|
||||
public enum MarkerType
|
||||
{
|
||||
/// <summary>
|
||||
/// A simple cross marker (x).
|
||||
/// </summary>
|
||||
Cross1,
|
||||
/// <summary>
|
||||
/// Another simple cross marker (+).
|
||||
/// </summary>
|
||||
Cross2,
|
||||
/// <summary>
|
||||
/// A circle marker.
|
||||
/// </summary>
|
||||
Circle,
|
||||
/// <summary>
|
||||
/// A square marker.
|
||||
/// </summary>
|
||||
Square,
|
||||
/// <summary>
|
||||
/// A triangle marker (upwards).
|
||||
/// </summary>
|
||||
Triangle,
|
||||
/// <summary>
|
||||
/// A triangle marker (upwards).
|
||||
/// </summary>
|
||||
TriangleUp,
|
||||
/// <summary>
|
||||
/// A triangle marker (upwards).
|
||||
/// </summary>
|
||||
TriangleDown,
|
||||
/// <summary>
|
||||
/// A diamond,
|
||||
/// </summary>
|
||||
Diamond,
|
||||
/// <summary>
|
||||
/// A filled circle
|
||||
/// </summary>
|
||||
FilledCircle,
|
||||
/// <summary>
|
||||
/// A filled square
|
||||
/// </summary>
|
||||
FilledSquare,
|
||||
/// <summary>
|
||||
/// A filled triangle
|
||||
/// </summary>
|
||||
FilledTriangle,
|
||||
/// <summary>
|
||||
/// A small flag (up)
|
||||
/// </summary>
|
||||
Flag,
|
||||
/// <summary>
|
||||
/// A small flag (up)
|
||||
/// </summary>
|
||||
FlagUp,
|
||||
/// <summary>
|
||||
/// A small flag (down)
|
||||
/// </summary>
|
||||
FlagDown,
|
||||
/// <summary>
|
||||
/// No marker
|
||||
/// </summary>
|
||||
None
|
||||
}
|
||||
|
||||
private MarkerType markerType_;
|
||||
private int size_;
|
||||
private int h_;
|
||||
private System.Drawing.Pen pen_ = new Pen( Color.Black );
|
||||
private System.Drawing.Brush brush_ = new SolidBrush( Color.Black );
|
||||
private bool filled_ = false;
|
||||
private bool dropLine_ = false;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// The type of marker.
|
||||
/// </summary>
|
||||
public MarkerType Type
|
||||
{
|
||||
get
|
||||
{
|
||||
return markerType_;
|
||||
}
|
||||
set
|
||||
{
|
||||
markerType_ = value;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Whether or not to draw a dropline.
|
||||
/// </summary>
|
||||
public bool DropLine
|
||||
{
|
||||
get
|
||||
{
|
||||
return dropLine_;
|
||||
}
|
||||
set
|
||||
{
|
||||
dropLine_ = value;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// The marker size.
|
||||
/// </summary>
|
||||
public int Size
|
||||
{
|
||||
get
|
||||
{
|
||||
return size_;
|
||||
}
|
||||
set
|
||||
{
|
||||
size_ = value;
|
||||
h_ = size_/2;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// The brush used to fill the marker.
|
||||
/// </summary>
|
||||
public Brush FillBrush
|
||||
{
|
||||
get
|
||||
{
|
||||
return brush_;
|
||||
}
|
||||
set
|
||||
{
|
||||
brush_ = value;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Fill with color.
|
||||
/// </summary>
|
||||
public bool Filled
|
||||
{
|
||||
get
|
||||
{
|
||||
return filled_;
|
||||
}
|
||||
set
|
||||
{
|
||||
filled_ = value;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Sets the pen color and fill brush to be solid with the specified color.
|
||||
/// </summary>
|
||||
public System.Drawing.Color Color
|
||||
{
|
||||
set
|
||||
{
|
||||
pen_.Color = value;
|
||||
brush_ = new SolidBrush( value );
|
||||
}
|
||||
get
|
||||
{
|
||||
return pen_.Color;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// The Pen used to draw the marker.
|
||||
/// </summary>
|
||||
public System.Drawing.Pen Pen
|
||||
{
|
||||
set
|
||||
{
|
||||
pen_ = value;
|
||||
}
|
||||
get
|
||||
{
|
||||
return pen_;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Default constructor.
|
||||
/// </summary>
|
||||
public Marker()
|
||||
{
|
||||
markerType_ = MarkerType.Square;
|
||||
Size = 4;
|
||||
filled_ = false;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Constructor
|
||||
/// </summary>
|
||||
/// <param name="markertype">The marker type.</param>
|
||||
public Marker( MarkerType markertype )
|
||||
{
|
||||
markerType_ = markertype;
|
||||
Size = 4;
|
||||
filled_ = false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructor
|
||||
/// </summary>
|
||||
/// <param name="markertype">The marker type.</param>
|
||||
/// <param name="size">The marker size.</param>
|
||||
public Marker( MarkerType markertype, int size )
|
||||
{
|
||||
markerType_ = markertype;
|
||||
Size = size;
|
||||
filled_ = false;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Constructor
|
||||
/// </summary>
|
||||
/// <param name="markertype">The marker type.</param>
|
||||
/// <param name="size">The marker size.</param>
|
||||
/// <param name="color">The marker color.</param>
|
||||
public Marker( MarkerType markertype, int size, Color color )
|
||||
{
|
||||
markerType_ = markertype;
|
||||
Size = size;
|
||||
Color = color;
|
||||
filled_ = false;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Constructor
|
||||
/// </summary>
|
||||
/// <param name="markertype">The marker type.</param>
|
||||
/// <param name="size">The marker size.</param>
|
||||
/// <param name="pen">The marker Pen.</param>
|
||||
public Marker( MarkerType markertype, int size, Pen pen )
|
||||
{
|
||||
markerType_ = markertype;
|
||||
Size = size;
|
||||
Pen = pen;
|
||||
filled_ = false;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Constructor
|
||||
/// </summary>
|
||||
/// <param name="markertype">The marker type.</param>
|
||||
/// <param name="size">The marker size.</param>
|
||||
/// <param name="pen">The marker Pen.</param>
|
||||
/// <param name="fill">The fill flag.</param>
|
||||
public Marker( MarkerType markertype, int size, Pen pen, bool fill )
|
||||
{
|
||||
markerType_ = markertype;
|
||||
Size = size;
|
||||
Pen = pen;
|
||||
filled_ = fill;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Draws the marker at the given position
|
||||
/// </summary>
|
||||
/// <param name="g">The graphics surface on which to draw.</param>
|
||||
/// <param name="x">The [physical] x position to draw the marker.</param>
|
||||
/// <param name="y">The [physical] y position to draw the marker.</param>
|
||||
public void Draw( Graphics g, int x, int y )
|
||||
{
|
||||
|
||||
switch (markerType_)
|
||||
{
|
||||
|
||||
case MarkerType.Cross1:
|
||||
g.DrawLine( pen_, x-h_, y+h_, x+h_, y-h_ );
|
||||
g.DrawLine( pen_, x+h_, y+h_, x-h_, y-h_ );
|
||||
break;
|
||||
|
||||
case MarkerType.Cross2:
|
||||
g.DrawLine( pen_, x, y-h_, x, y+h_ );
|
||||
g.DrawLine( pen_, x-h_, y, x+h_, y );
|
||||
break;
|
||||
|
||||
case MarkerType.Circle:
|
||||
g.DrawEllipse( pen_, x-h_, y-h_, size_, size_ );
|
||||
if ( this.filled_ )
|
||||
{
|
||||
g.FillEllipse( brush_, x-h_, y-h_, size_, size_ );
|
||||
}
|
||||
break;
|
||||
|
||||
case MarkerType.Square:
|
||||
g.DrawRectangle( pen_, x-h_, y-h_, size_, size_ );
|
||||
if ( this.filled_ )
|
||||
{
|
||||
g.FillRectangle( brush_, x-h_, y-h_, size_, size_ );
|
||||
}
|
||||
break;
|
||||
|
||||
case MarkerType.Triangle:
|
||||
case MarkerType.TriangleDown:
|
||||
{
|
||||
Point p1 = new Point( x-h_, y-h_ );
|
||||
Point p2 = new Point( x, y+h_ );
|
||||
Point p3 = new Point( x+h_, y-h_ );
|
||||
Point [] pts = new Point [3] { p1, p2, p3 };
|
||||
GraphicsPath gp = new GraphicsPath();
|
||||
gp.AddPolygon( pts );
|
||||
g.DrawPath( pen_, gp );
|
||||
if (this.filled_)
|
||||
{
|
||||
g.FillPath( brush_, gp );
|
||||
}
|
||||
break;
|
||||
}
|
||||
case MarkerType.TriangleUp:
|
||||
{
|
||||
Point p1 = new Point( x-h_, y+h_ );
|
||||
Point p2 = new Point( x, y-h_ );
|
||||
Point p3 = new Point( x+h_, y+h_ );
|
||||
Point [] pts = new Point [3] { p1, p2, p3 };
|
||||
GraphicsPath gp = new GraphicsPath();
|
||||
gp.AddPolygon( pts );
|
||||
g.DrawPath( pen_, gp );
|
||||
if (this.filled_)
|
||||
{
|
||||
g.FillPath( brush_, gp );
|
||||
}
|
||||
break;
|
||||
}
|
||||
case MarkerType.FilledCircle:
|
||||
g.DrawEllipse( pen_, x-h_, y-h_, size_, size_ );
|
||||
g.FillEllipse( brush_, x-h_, y-h_, size_, size_ );
|
||||
break;
|
||||
|
||||
case MarkerType.FilledSquare:
|
||||
g.DrawRectangle( pen_, x-h_, y-h_, size_, size_ );
|
||||
g.FillRectangle( brush_, x-h_, y-h_, size_, size_ );
|
||||
break;
|
||||
|
||||
case MarkerType.FilledTriangle:
|
||||
{
|
||||
Point p1 = new Point( x-h_, y-h_ );
|
||||
Point p2 = new Point( x, y+h_ );
|
||||
Point p3 = new Point( x+h_, y-h_ );
|
||||
Point [] pts = new Point [3] { p1, p2, p3 };
|
||||
GraphicsPath gp = new GraphicsPath();
|
||||
gp.AddPolygon( pts );
|
||||
g.DrawPath( pen_, gp );
|
||||
g.FillPath( brush_, gp );
|
||||
break;
|
||||
}
|
||||
case MarkerType.Diamond:
|
||||
{
|
||||
Point p1 = new Point( x-h_, y );
|
||||
Point p2 = new Point( x, y-h_ );
|
||||
Point p3 = new Point( x+h_, y );
|
||||
Point p4 = new Point( x, y+h_ );
|
||||
Point [] pts = new Point [4] { p1, p2, p3, p4 };
|
||||
GraphicsPath gp = new GraphicsPath();
|
||||
gp.AddPolygon( pts );
|
||||
g.DrawPath( pen_, gp );
|
||||
if (this.filled_)
|
||||
{
|
||||
g.FillPath( brush_, gp );
|
||||
}
|
||||
break;
|
||||
}
|
||||
case MarkerType.Flag:
|
||||
case MarkerType.FlagUp:
|
||||
{
|
||||
Point p1 = new Point( x, y );
|
||||
Point p2 = new Point( x, y-size_ );
|
||||
Point p3 = new Point( x+size_, y-size_+size_/3 );
|
||||
Point p4 = new Point( x, y-size_+2*size_/3 );
|
||||
g.DrawLine( pen_, p1, p2 );
|
||||
Point [] pts = new Point [3] { p2, p3, p4 };
|
||||
GraphicsPath gp = new GraphicsPath();
|
||||
gp.AddPolygon( pts );
|
||||
g.DrawPath( pen_, gp );
|
||||
if (this.filled_)
|
||||
{
|
||||
g.FillPath( brush_, gp );
|
||||
}
|
||||
break;
|
||||
}
|
||||
case MarkerType.FlagDown:
|
||||
{
|
||||
Point p1 = new Point( x, y );
|
||||
Point p2 = new Point( x, y+size_ );
|
||||
Point p3 = new Point( x+size_, y+size_-size_/3 );
|
||||
Point p4 = new Point( x, y+size_-2*size_/3 );
|
||||
g.DrawLine( pen_, p1, p2 );
|
||||
Point [] pts = new Point [3] { p2, p3, p4 };
|
||||
GraphicsPath gp = new GraphicsPath();
|
||||
gp.AddPolygon( pts );
|
||||
g.DrawPath( pen_, gp );
|
||||
if (this.filled_)
|
||||
{
|
||||
g.FillPath( brush_, gp );
|
||||
}
|
||||
break;
|
||||
}
|
||||
case MarkerType.None:
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,136 @@
|
|||
/*
|
||||
NPlot - A charting library for .NET
|
||||
|
||||
MarkerItem.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>
|
||||
/// Class for placement of a single marker.
|
||||
/// </summary>
|
||||
public class MarkerItem : IDrawable
|
||||
{
|
||||
|
||||
private Marker marker_;
|
||||
private double x_;
|
||||
private double y_;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Constructs a square marker at the (world) point point.
|
||||
/// </summary>
|
||||
/// <param name="point">the world position at which to place the marker</param>
|
||||
public MarkerItem( PointD point )
|
||||
{
|
||||
marker_ = new Marker( Marker.MarkerType.Square );
|
||||
x_ = point.X;
|
||||
y_ = point.Y;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Default constructor - a square black marker.
|
||||
/// </summary>
|
||||
/// <param name="x">The world x position of the marker</param>
|
||||
/// <param name="y">The world y position of the marker</param>
|
||||
public MarkerItem( double x, double y )
|
||||
{
|
||||
marker_ = new Marker( Marker.MarkerType.Square );
|
||||
x_ = x;
|
||||
y_ = y;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Constructor
|
||||
/// </summary>
|
||||
/// <param name="marker">The marker to place on the chart.</param>
|
||||
/// <param name="x">The world x position of the marker</param>
|
||||
/// <param name="y">The world y position of the marker</param>
|
||||
public MarkerItem( Marker marker, double x, double y )
|
||||
{
|
||||
marker_ = marker;
|
||||
x_ = x;
|
||||
y_ = y;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructor
|
||||
/// </summary>
|
||||
/// <param name="marker">The marker to place on the chart.</param>
|
||||
/// <param name="point">The world position of the marker</param>
|
||||
public MarkerItem( Marker marker, PointD point )
|
||||
{
|
||||
marker_ = marker;
|
||||
x_ = point.X;
|
||||
y_ = point.Y;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Draws the marker 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 )
|
||||
{
|
||||
PointF point = new PointF(
|
||||
xAxis.WorldToPhysical( x_, true ).X,
|
||||
yAxis.WorldToPhysical( y_, true ).Y );
|
||||
|
||||
marker_.Draw( g, (int)point.X, (int)point.Y );
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
Двоичный файл не отображается.
|
@ -0,0 +1,6 @@
|
|||
<configuration>
|
||||
<dllmap dll="libglib-2.0-0.dll" target="libglib-2.0.so.0"/>
|
||||
<dllmap dll="libgobject-2.0-0.dll" target="libgobject-2.0.so.0"/>
|
||||
<dllmap dll="libgdk-win32-2.0-0.dll" target="libgdk-x11-2.0.so.0"/>
|
||||
<dllmap dll="libgdk_pixbuf-2.0-0.dll" target="libgdk_pixbuf-2.0.so.0"/>
|
||||
</configuration>
|
Двоичный файл не отображается.
|
@ -0,0 +1,393 @@
|
|||
<VisualStudioProject>
|
||||
<CSHARP
|
||||
ProjectType = "Local"
|
||||
ProductVersion = "7.10.3077"
|
||||
SchemaVersion = "2.0"
|
||||
ProjectGuid = "{E6867FF5-74EC-4464-8958-D71CB46232F3}"
|
||||
>
|
||||
<Build>
|
||||
<Settings
|
||||
ApplicationIcon = ""
|
||||
AssemblyKeyContainerName = ""
|
||||
AssemblyName = "NPlot"
|
||||
AssemblyOriginatorKeyFile = ""
|
||||
DefaultClientScript = "JScript"
|
||||
DefaultHTMLPageLayout = "Grid"
|
||||
DefaultTargetSchema = "IE50"
|
||||
DelaySign = "false"
|
||||
OutputType = "Library"
|
||||
PreBuildEvent = ""
|
||||
PostBuildEvent = ""
|
||||
RootNamespace = "NPlot"
|
||||
RunPostBuildEvent = "OnBuildSuccess"
|
||||
StartupObject = ""
|
||||
>
|
||||
<Config
|
||||
Name = "Debug"
|
||||
AllowUnsafeBlocks = "false"
|
||||
BaseAddress = "285212672"
|
||||
CheckForOverflowUnderflow = "false"
|
||||
ConfigurationOverrideFile = ""
|
||||
DefineConstants = "DEBUG;TRACE;CHECK_ERRORS"
|
||||
DocumentationFile = "NPlot.xml"
|
||||
DebugSymbols = "true"
|
||||
FileAlignment = "4096"
|
||||
IncrementalBuild = "false"
|
||||
NoStdLib = "false"
|
||||
NoWarn = ""
|
||||
Optimize = "false"
|
||||
OutputPath = "bin\Debug\"
|
||||
RegisterForComInterop = "false"
|
||||
RemoveIntegerChecks = "false"
|
||||
TreatWarningsAsErrors = "false"
|
||||
WarningLevel = "4"
|
||||
/>
|
||||
<Config
|
||||
Name = "Release"
|
||||
AllowUnsafeBlocks = "false"
|
||||
BaseAddress = "285212672"
|
||||
CheckForOverflowUnderflow = "false"
|
||||
ConfigurationOverrideFile = ""
|
||||
DefineConstants = "TRACE"
|
||||
DocumentationFile = "NPlot.xml"
|
||||
DebugSymbols = "false"
|
||||
FileAlignment = "4096"
|
||||
IncrementalBuild = "false"
|
||||
NoStdLib = "false"
|
||||
NoWarn = ""
|
||||
Optimize = "true"
|
||||
OutputPath = "bin\Release\"
|
||||
RegisterForComInterop = "false"
|
||||
RemoveIntegerChecks = "false"
|
||||
TreatWarningsAsErrors = "false"
|
||||
WarningLevel = "4"
|
||||
/>
|
||||
</Settings>
|
||||
<References>
|
||||
<Reference
|
||||
Name = "System"
|
||||
AssemblyName = "System"
|
||||
HintPath = "C:\WINDOWS\Microsoft.NET\Framework\v1.0.3705\System.dll"
|
||||
/>
|
||||
<Reference
|
||||
Name = "System.Data"
|
||||
AssemblyName = "System.Data"
|
||||
HintPath = "C:\WINDOWS\Microsoft.NET\Framework\v1.0.3705\System.Data.dll"
|
||||
/>
|
||||
<Reference
|
||||
Name = "System.XML"
|
||||
AssemblyName = "System.Xml"
|
||||
HintPath = "C:\WINDOWS\Microsoft.NET\Framework\v1.0.3705\System.XML.dll"
|
||||
/>
|
||||
<Reference
|
||||
Name = "System.Drawing"
|
||||
AssemblyName = "System.Drawing"
|
||||
HintPath = "C:\WINDOWS\Microsoft.NET\Framework\v1.0.3705\System.Drawing.dll"
|
||||
/>
|
||||
<Reference
|
||||
Name = "System.Windows.Forms"
|
||||
AssemblyName = "System.Windows.Forms"
|
||||
HintPath = "C:\WINDOWS\Microsoft.NET\Framework\v1.0.3705\System.Windows.Forms.dll"
|
||||
/>
|
||||
<Reference
|
||||
Name = "System.Web"
|
||||
AssemblyName = "System.Web"
|
||||
HintPath = "..\..\..\..\..\..\WINDOWS\Microsoft.NET\Framework\v1.0.3705\System.Web.dll"
|
||||
/>
|
||||
<Reference
|
||||
Name = "System.Design"
|
||||
AssemblyName = "System.Design"
|
||||
HintPath = "..\..\..\..\..\..\..\WINDOWS\Microsoft.NET\Framework\v1.0.3705\System.Design.dll"
|
||||
/>
|
||||
</References>
|
||||
</Build>
|
||||
<Files>
|
||||
<Include>
|
||||
<File
|
||||
RelPath = "AdapterUtils.cs"
|
||||
SubType = "Code"
|
||||
BuildAction = "Compile"
|
||||
/>
|
||||
<File
|
||||
RelPath = "ArrowItem.cs"
|
||||
SubType = "Code"
|
||||
BuildAction = "Compile"
|
||||
/>
|
||||
<File
|
||||
RelPath = "AssemblyInfo.cs"
|
||||
SubType = "Code"
|
||||
BuildAction = "Compile"
|
||||
/>
|
||||
<File
|
||||
RelPath = "AxesConstraint.cs"
|
||||
SubType = "Code"
|
||||
BuildAction = "Compile"
|
||||
/>
|
||||
<File
|
||||
RelPath = "Axis.cs"
|
||||
SubType = "Code"
|
||||
BuildAction = "Compile"
|
||||
/>
|
||||
<File
|
||||
RelPath = "BarPlot.cs"
|
||||
SubType = "Code"
|
||||
BuildAction = "Compile"
|
||||
/>
|
||||
<File
|
||||
RelPath = "BasePlot.cs"
|
||||
SubType = "Code"
|
||||
BuildAction = "Compile"
|
||||
/>
|
||||
<File
|
||||
RelPath = "BaseSequencePlot.cs"
|
||||
SubType = "Code"
|
||||
BuildAction = "Compile"
|
||||
/>
|
||||
<File
|
||||
RelPath = "Bitmap.PlotSurface2D.cs"
|
||||
SubType = "Code"
|
||||
BuildAction = "Compile"
|
||||
/>
|
||||
<File
|
||||
RelPath = "CandlePlot.cs"
|
||||
SubType = "Code"
|
||||
BuildAction = "Compile"
|
||||
/>
|
||||
<File
|
||||
RelPath = "changelog.txt"
|
||||
BuildAction = "Content"
|
||||
/>
|
||||
<File
|
||||
RelPath = "DateTimeAxis.cs"
|
||||
SubType = "Code"
|
||||
BuildAction = "Compile"
|
||||
/>
|
||||
<File
|
||||
RelPath = "FilledRegion.cs"
|
||||
SubType = "Code"
|
||||
BuildAction = "Compile"
|
||||
/>
|
||||
<File
|
||||
RelPath = "Grid.cs"
|
||||
SubType = "Code"
|
||||
BuildAction = "Compile"
|
||||
/>
|
||||
<File
|
||||
RelPath = "HistogramPlot.cs"
|
||||
SubType = "Code"
|
||||
BuildAction = "Compile"
|
||||
/>
|
||||
<File
|
||||
RelPath = "HorizontalLine.cs"
|
||||
SubType = "Code"
|
||||
BuildAction = "Compile"
|
||||
/>
|
||||
<File
|
||||
RelPath = "icon.ico"
|
||||
BuildAction = "EmbeddedResource"
|
||||
/>
|
||||
<File
|
||||
RelPath = "IDrawable.cs"
|
||||
SubType = "Code"
|
||||
BuildAction = "Compile"
|
||||
/>
|
||||
<File
|
||||
RelPath = "IGradient.cs"
|
||||
SubType = "Code"
|
||||
BuildAction = "Compile"
|
||||
/>
|
||||
<File
|
||||
RelPath = "ImagePlot.cs"
|
||||
SubType = "Code"
|
||||
BuildAction = "Compile"
|
||||
/>
|
||||
<File
|
||||
RelPath = "IPlot.cs"
|
||||
SubType = "Code"
|
||||
BuildAction = "Compile"
|
||||
/>
|
||||
<File
|
||||
RelPath = "IPlotSurface2D.cs"
|
||||
SubType = "Code"
|
||||
BuildAction = "Compile"
|
||||
/>
|
||||
<File
|
||||
RelPath = "ISequencePlot.cs"
|
||||
SubType = "Code"
|
||||
BuildAction = "Compile"
|
||||
/>
|
||||
<File
|
||||
RelPath = "ISurface.cs"
|
||||
SubType = "Code"
|
||||
BuildAction = "Compile"
|
||||
/>
|
||||
<File
|
||||
RelPath = "ITransform2D.cs"
|
||||
SubType = "Code"
|
||||
BuildAction = "Compile"
|
||||
/>
|
||||
<File
|
||||
RelPath = "LabelAxis.cs"
|
||||
SubType = "Code"
|
||||
BuildAction = "Compile"
|
||||
/>
|
||||
<File
|
||||
RelPath = "LabelPointPlot.cs"
|
||||
SubType = "Code"
|
||||
BuildAction = "Compile"
|
||||
/>
|
||||
<File
|
||||
RelPath = "Legend.cs"
|
||||
SubType = "Code"
|
||||
BuildAction = "Compile"
|
||||
/>
|
||||
<File
|
||||
RelPath = "LegendBase.cs"
|
||||
SubType = "Code"
|
||||
BuildAction = "Compile"
|
||||
/>
|
||||
<File
|
||||
RelPath = "LinearAxis.cs"
|
||||
SubType = "Code"
|
||||
BuildAction = "Compile"
|
||||
/>
|
||||
<File
|
||||
RelPath = "LinearGradient.cs"
|
||||
SubType = "Code"
|
||||
BuildAction = "Compile"
|
||||
/>
|
||||
<File
|
||||
RelPath = "LinePlot.cs"
|
||||
SubType = "Code"
|
||||
BuildAction = "Compile"
|
||||
/>
|
||||
<File
|
||||
RelPath = "LogAxis.cs"
|
||||
SubType = "Code"
|
||||
BuildAction = "Compile"
|
||||
/>
|
||||
<File
|
||||
RelPath = "Marker.cs"
|
||||
SubType = "Code"
|
||||
BuildAction = "Compile"
|
||||
/>
|
||||
<File
|
||||
RelPath = "MarkerItem.cs"
|
||||
SubType = "Code"
|
||||
BuildAction = "Compile"
|
||||
/>
|
||||
<File
|
||||
RelPath = "NPlotException.cs"
|
||||
SubType = "Code"
|
||||
BuildAction = "Compile"
|
||||
/>
|
||||
<File
|
||||
RelPath = "PageAlignedPhysicalAxis.cs"
|
||||
SubType = "Code"
|
||||
BuildAction = "Compile"
|
||||
/>
|
||||
<File
|
||||
RelPath = "PhysicalAxis.cs"
|
||||
SubType = "Code"
|
||||
BuildAction = "Compile"
|
||||
/>
|
||||
<File
|
||||
RelPath = "PiAxis.cs"
|
||||
SubType = "Code"
|
||||
BuildAction = "Compile"
|
||||
/>
|
||||
<File
|
||||
RelPath = "PlotSurface2D.cs"
|
||||
SubType = "Code"
|
||||
BuildAction = "Compile"
|
||||
/>
|
||||
<File
|
||||
RelPath = "PointD.cs"
|
||||
SubType = "Code"
|
||||
BuildAction = "Compile"
|
||||
/>
|
||||
<File
|
||||
RelPath = "PointPlot.cs"
|
||||
SubType = "Code"
|
||||
BuildAction = "Compile"
|
||||
/>
|
||||
<File
|
||||
RelPath = "RectangleBrushes.cs"
|
||||
SubType = "Code"
|
||||
BuildAction = "Compile"
|
||||
/>
|
||||
<File
|
||||
RelPath = "RectangleD.cs"
|
||||
SubType = "Code"
|
||||
BuildAction = "Compile"
|
||||
/>
|
||||
<File
|
||||
RelPath = "SequenceAdapter.cs"
|
||||
SubType = "Code"
|
||||
BuildAction = "Compile"
|
||||
/>
|
||||
<File
|
||||
RelPath = "StartStep.cs"
|
||||
SubType = "Code"
|
||||
BuildAction = "Compile"
|
||||
/>
|
||||
<File
|
||||
RelPath = "StepGradient.cs"
|
||||
SubType = "Code"
|
||||
BuildAction = "Compile"
|
||||
/>
|
||||
<File
|
||||
RelPath = "StepPlot.cs"
|
||||
SubType = "Code"
|
||||
BuildAction = "Compile"
|
||||
/>
|
||||
<File
|
||||
RelPath = "TextItem.cs"
|
||||
SubType = "Code"
|
||||
BuildAction = "Compile"
|
||||
/>
|
||||
<File
|
||||
RelPath = "TradingDateTimeAxis.cs"
|
||||
SubType = "Code"
|
||||
BuildAction = "Compile"
|
||||
/>
|
||||
<File
|
||||
RelPath = "Transform2D.cs"
|
||||
SubType = "Code"
|
||||
BuildAction = "Compile"
|
||||
/>
|
||||
<File
|
||||
RelPath = "Utils.cs"
|
||||
SubType = "Code"
|
||||
BuildAction = "Compile"
|
||||
/>
|
||||
<File
|
||||
RelPath = "VerticalLine.cs"
|
||||
SubType = "Code"
|
||||
BuildAction = "Compile"
|
||||
/>
|
||||
<File
|
||||
RelPath = "Web.Design.PlotSurface2D.cs"
|
||||
SubType = "Code"
|
||||
BuildAction = "Compile"
|
||||
/>
|
||||
<File
|
||||
RelPath = "Web.PlotSurface2D.cs"
|
||||
SubType = "Code"
|
||||
BuildAction = "Compile"
|
||||
/>
|
||||
<File
|
||||
RelPath = "Windows.PlotSurface2D.cs"
|
||||
SubType = "Component"
|
||||
BuildAction = "Compile"
|
||||
/>
|
||||
<File
|
||||
RelPath = "Windows.PlotSurface2D.resx"
|
||||
DependentUpon = "Windows.PlotSurface2D.cs"
|
||||
BuildAction = "EmbeddedResource"
|
||||
/>
|
||||
</Include>
|
||||
</Files>
|
||||
</CSHARP>
|
||||
</VisualStudioProject>
|
||||
|
|
@ -0,0 +1,48 @@
|
|||
<VisualStudioProject>
|
||||
<CSHARP LastOpenVersion = "7.10.3077" >
|
||||
<Build>
|
||||
<Settings ReferencePath = "" >
|
||||
<Config
|
||||
Name = "Debug"
|
||||
EnableASPDebugging = "false"
|
||||
EnableASPXDebugging = "false"
|
||||
EnableUnmanagedDebugging = "false"
|
||||
EnableSQLServerDebugging = "false"
|
||||
RemoteDebugEnabled = "false"
|
||||
RemoteDebugMachine = ""
|
||||
StartAction = "Project"
|
||||
StartArguments = ""
|
||||
StartPage = ""
|
||||
StartProgram = ""
|
||||
StartURL = ""
|
||||
StartWorkingDirectory = ""
|
||||
StartWithIE = "false"
|
||||
/>
|
||||
<Config
|
||||
Name = "Release"
|
||||
EnableASPDebugging = "false"
|
||||
EnableASPXDebugging = "false"
|
||||
EnableUnmanagedDebugging = "false"
|
||||
EnableSQLServerDebugging = "false"
|
||||
RemoteDebugEnabled = "false"
|
||||
RemoteDebugMachine = ""
|
||||
StartAction = "Project"
|
||||
StartArguments = ""
|
||||
StartPage = ""
|
||||
StartProgram = ""
|
||||
StartURL = ""
|
||||
StartWorkingDirectory = ""
|
||||
StartWithIE = "false"
|
||||
/>
|
||||
</Settings>
|
||||
</Build>
|
||||
<OtherProjectSettings
|
||||
CopyProjectDestinationFolder = ""
|
||||
CopyProjectUncPath = ""
|
||||
CopyProjectOption = "0"
|
||||
ProjectView = "ProjectFiles"
|
||||
ProjectTrust = "0"
|
||||
/>
|
||||
</CSHARP>
|
||||
</VisualStudioProject>
|
||||
|
Двоичный файл не отображается.
Двоичный файл не отображается.
|
@ -0,0 +1,297 @@
|
|||
<project SchemaVersion="1.3">
|
||||
<assemblies>
|
||||
<assembly location="C:\cvshome\lib\bin\Debug\NPlot.dll" documentation="C:\cvshome\lib\NPlot.xml" />
|
||||
</assemblies>
|
||||
<namespaces>
|
||||
<namespace name="NPlot"></namespace>
|
||||
<namespace name="NPlot.Bitmap"></namespace>
|
||||
<namespace name="NPlot.web"></namespace>
|
||||
<namespace name="NPlot.web.Design"></namespace>
|
||||
<namespace name="NPlot.Windows"></namespace>
|
||||
</namespaces>
|
||||
<documenters>
|
||||
<documenter name="JavaDoc">
|
||||
<property name="OutputDirectory" value=".\doc\" />
|
||||
<property name="ShowMissingSummaries" value="False" />
|
||||
<property name="ShowMissingRemarks" value="False" />
|
||||
<property name="ShowMissingParams" value="False" />
|
||||
<property name="ShowMissingReturns" value="False" />
|
||||
<property name="ShowMissingValues" value="False" />
|
||||
<property name="DocumentExplicitInterfaceImplementations" value="False" />
|
||||
<property name="DocumentInternals" value="False" />
|
||||
<property name="DocumentProtected" value="True" />
|
||||
<property name="DocumentSealedProtected" value="False" />
|
||||
<property name="DocumentPrivates" value="False" />
|
||||
<property name="DocumentProtectedInternalAsProtected" value="False" />
|
||||
<property name="DocumentEmptyNamespaces" value="False" />
|
||||
<property name="SkipNamespacesWithoutSummaries" value="False" />
|
||||
<property name="EditorBrowsableFilter" value="Off" />
|
||||
<property name="IncludeAssemblyVersion" value="False" />
|
||||
<property name="CopyrightText" value="" />
|
||||
<property name="CopyrightHref" value="" />
|
||||
<property name="ReferencesPath" value="" />
|
||||
<property name="FeedbackEmailAddress" value="" />
|
||||
<property name="UseNamespaceDocSummaries" value="False" />
|
||||
<property name="AutoPropertyBackerSummaries" value="False" />
|
||||
<property name="AutoDocumentConstructors" value="True" />
|
||||
<property name="GetExternalSummaries" value="True" />
|
||||
<property name="Preliminary" value="False" />
|
||||
<property name="UseNDocXmlFile" value="" />
|
||||
<property name="CleanIntermediates" value="False" />
|
||||
<property name="DocumentAttributes" value="False" />
|
||||
<property name="ShowTypeIdInAttributes" value="False" />
|
||||
<property name="DocumentedAttributes" value="" />
|
||||
<property name="InheritPlatformSupport" value="True" />
|
||||
<property name="DefaultOSSupport" value="all" />
|
||||
<property name="SupportCompactFrameworkByDefault" value="False" />
|
||||
<property name="SupportMONOFrameworkByDefault" value="False" />
|
||||
<property name="AdditionalFrameworkList" value="" />
|
||||
<property name="AdditionalOSList" value="" />
|
||||
</documenter>
|
||||
<documenter name="LaTeX">
|
||||
<property name="OutputDirectory" value=".\doc\" />
|
||||
<property name="TextFileFullName" value="Documentation.tex" />
|
||||
<property name="TexFileBaseName" value="Documentation" />
|
||||
<property name="LatexCompiler" value="latex" />
|
||||
<property name="TexFileFullPath" value=".\doc\Documentation.tex" />
|
||||
<property name="ShowMissingSummaries" value="False" />
|
||||
<property name="ShowMissingRemarks" value="False" />
|
||||
<property name="ShowMissingParams" value="False" />
|
||||
<property name="ShowMissingReturns" value="False" />
|
||||
<property name="ShowMissingValues" value="False" />
|
||||
<property name="DocumentExplicitInterfaceImplementations" value="False" />
|
||||
<property name="DocumentInternals" value="False" />
|
||||
<property name="DocumentProtected" value="True" />
|
||||
<property name="DocumentSealedProtected" value="False" />
|
||||
<property name="DocumentPrivates" value="False" />
|
||||
<property name="DocumentProtectedInternalAsProtected" value="False" />
|
||||
<property name="DocumentEmptyNamespaces" value="False" />
|
||||
<property name="SkipNamespacesWithoutSummaries" value="False" />
|
||||
<property name="EditorBrowsableFilter" value="Off" />
|
||||
<property name="IncludeAssemblyVersion" value="False" />
|
||||
<property name="CopyrightText" value="" />
|
||||
<property name="CopyrightHref" value="" />
|
||||
<property name="ReferencesPath" value="" />
|
||||
<property name="FeedbackEmailAddress" value="" />
|
||||
<property name="UseNamespaceDocSummaries" value="False" />
|
||||
<property name="AutoPropertyBackerSummaries" value="False" />
|
||||
<property name="AutoDocumentConstructors" value="True" />
|
||||
<property name="GetExternalSummaries" value="True" />
|
||||
<property name="Preliminary" value="False" />
|
||||
<property name="UseNDocXmlFile" value="" />
|
||||
<property name="CleanIntermediates" value="False" />
|
||||
<property name="DocumentAttributes" value="False" />
|
||||
<property name="ShowTypeIdInAttributes" value="False" />
|
||||
<property name="DocumentedAttributes" value="" />
|
||||
<property name="InheritPlatformSupport" value="True" />
|
||||
<property name="DefaultOSSupport" value="all" />
|
||||
<property name="SupportCompactFrameworkByDefault" value="False" />
|
||||
<property name="SupportMONOFrameworkByDefault" value="False" />
|
||||
<property name="AdditionalFrameworkList" value="" />
|
||||
<property name="AdditionalOSList" value="" />
|
||||
</documenter>
|
||||
<documenter name="LinearHtml">
|
||||
<property name="IncludeTypeMemberDetails" value="False" />
|
||||
<property name="OutputDirectory" value=".\doc\" />
|
||||
<property name="MethodParametersInTable" value="False" />
|
||||
<property name="TypeIncludeRegexp" value="" />
|
||||
<property name="NamespaceExcludeRegexp" value="" />
|
||||
<property name="Title" value="An NDoc Documented Class Library" />
|
||||
<property name="IncludeHierarchy" value="False" />
|
||||
<property name="SortTOCByNamespace" value="True" />
|
||||
<property name="HeaderHtml" value="" />
|
||||
<property name="FooterHtml" value="" />
|
||||
<property name="FilesToInclude" value="" />
|
||||
<property name="ShowMissingSummaries" value="False" />
|
||||
<property name="ShowMissingRemarks" value="False" />
|
||||
<property name="ShowMissingParams" value="False" />
|
||||
<property name="ShowMissingReturns" value="False" />
|
||||
<property name="ShowMissingValues" value="False" />
|
||||
<property name="DocumentExplicitInterfaceImplementations" value="False" />
|
||||
<property name="DocumentInternals" value="False" />
|
||||
<property name="DocumentProtected" value="True" />
|
||||
<property name="DocumentSealedProtected" value="False" />
|
||||
<property name="DocumentPrivates" value="False" />
|
||||
<property name="DocumentProtectedInternalAsProtected" value="False" />
|
||||
<property name="DocumentEmptyNamespaces" value="False" />
|
||||
<property name="SkipNamespacesWithoutSummaries" value="False" />
|
||||
<property name="EditorBrowsableFilter" value="Off" />
|
||||
<property name="IncludeAssemblyVersion" value="False" />
|
||||
<property name="CopyrightText" value="" />
|
||||
<property name="CopyrightHref" value="" />
|
||||
<property name="ReferencesPath" value="" />
|
||||
<property name="FeedbackEmailAddress" value="" />
|
||||
<property name="UseNamespaceDocSummaries" value="False" />
|
||||
<property name="AutoPropertyBackerSummaries" value="False" />
|
||||
<property name="AutoDocumentConstructors" value="True" />
|
||||
<property name="GetExternalSummaries" value="True" />
|
||||
<property name="Preliminary" value="False" />
|
||||
<property name="UseNDocXmlFile" value="" />
|
||||
<property name="CleanIntermediates" value="False" />
|
||||
<property name="DocumentAttributes" value="False" />
|
||||
<property name="ShowTypeIdInAttributes" value="False" />
|
||||
<property name="DocumentedAttributes" value="" />
|
||||
<property name="InheritPlatformSupport" value="True" />
|
||||
<property name="DefaultOSSupport" value="all" />
|
||||
<property name="SupportCompactFrameworkByDefault" value="False" />
|
||||
<property name="SupportMONOFrameworkByDefault" value="False" />
|
||||
<property name="AdditionalFrameworkList" value="" />
|
||||
<property name="AdditionalOSList" value="" />
|
||||
</documenter>
|
||||
<documenter name="MSDN">
|
||||
<property name="OutputDirectory" value="C:\cvshome\lib\doc\" />
|
||||
<property name="HtmlHelpName" value="NPlot_Documentation" />
|
||||
<property name="IncludeFavorites" value="False" />
|
||||
<property name="Title" value="" />
|
||||
<property name="DefaultTOC" value="" />
|
||||
<property name="IncludeHierarchy" value="False" />
|
||||
<property name="ShowVisualBasic" value="True" />
|
||||
<property name="RootPageFileName" value="" />
|
||||
<property name="RootPageContainsNamespaces" value="False" />
|
||||
<property name="BinaryTOC" value="True" />
|
||||
<property name="OutputTarget" value="HtmlHelpAndWeb" />
|
||||
<property name="HeaderHtml" value="<i>Documentation for the <a href="http://netcontrols.org/nplot/" target="_top">NPlot</a> .NET charting library v0.9.7</i>
<h2>%TOPIC_TITLE%<h2>
" />
|
||||
<property name="FooterHtml" value="Copyright 2003, 2004 Matt Howlett and others.<br><br>
" />
|
||||
<property name="FilesToInclude" value="" />
|
||||
<property name="LinkToSdkDocVersion" value="SDK_v1_1" />
|
||||
<property name="ExtensibilityStylesheet" value="" />
|
||||
<property name="ShowMissingSummaries" value="False" />
|
||||
<property name="ShowMissingRemarks" value="False" />
|
||||
<property name="ShowMissingParams" value="False" />
|
||||
<property name="ShowMissingReturns" value="False" />
|
||||
<property name="ShowMissingValues" value="False" />
|
||||
<property name="DocumentExplicitInterfaceImplementations" value="False" />
|
||||
<property name="DocumentInternals" value="False" />
|
||||
<property name="DocumentProtected" value="True" />
|
||||
<property name="DocumentSealedProtected" value="False" />
|
||||
<property name="DocumentPrivates" value="False" />
|
||||
<property name="DocumentProtectedInternalAsProtected" value="False" />
|
||||
<property name="DocumentEmptyNamespaces" value="False" />
|
||||
<property name="SkipNamespacesWithoutSummaries" value="False" />
|
||||
<property name="EditorBrowsableFilter" value="Off" />
|
||||
<property name="IncludeAssemblyVersion" value="True" />
|
||||
<property name="CopyrightText" value="" />
|
||||
<property name="CopyrightHref" value="" />
|
||||
<property name="ReferencesPath" value="" />
|
||||
<property name="FeedbackEmailAddress" value="" />
|
||||
<property name="UseNamespaceDocSummaries" value="False" />
|
||||
<property name="AutoPropertyBackerSummaries" value="False" />
|
||||
<property name="AutoDocumentConstructors" value="False" />
|
||||
<property name="GetExternalSummaries" value="True" />
|
||||
<property name="Preliminary" value="True" />
|
||||
<property name="UseNDocXmlFile" value="" />
|
||||
<property name="CleanIntermediates" value="True" />
|
||||
<property name="DocumentAttributes" value="False" />
|
||||
<property name="ShowTypeIdInAttributes" value="False" />
|
||||
<property name="DocumentedAttributes" value="" />
|
||||
<property name="InheritPlatformSupport" value="True" />
|
||||
<property name="DefaultOSSupport" value="all" />
|
||||
<property name="SupportCompactFrameworkByDefault" value="False" />
|
||||
<property name="SupportMONOFrameworkByDefault" value="False" />
|
||||
<property name="AdditionalFrameworkList" value="" />
|
||||
<property name="AdditionalOSList" value="" />
|
||||
</documenter>
|
||||
<documenter name="VS.NET 2003">
|
||||
<property name="OutputDirectory" value=".\doc\" />
|
||||
<property name="HtmlHelpName" value="Documentation" />
|
||||
<property name="Title" value="An NDoc documented library" />
|
||||
<property name="IncludeHierarchy" value="False" />
|
||||
<property name="RegisterTitleWithNamespace" value="False" />
|
||||
<property name="CollectionNamespace" value="" />
|
||||
<property name="RegisterTitleAsCollection" value="False" />
|
||||
<property name="GenerateCollectionFiles" value="False" />
|
||||
<property name="PlugInNamespace" value="ms.vscc" />
|
||||
<property name="CollectionTOCStyle" value="Hierarchical" />
|
||||
<property name="LinkToSdkDocVersion" value="SDK_v1_1" />
|
||||
<property name="CharacterSet" value="UTF8" />
|
||||
<property name="LangID" value="1033" />
|
||||
<property name="BuildSeparateIndexFile" value="False" />
|
||||
<property name="DocSetList" value="NETFramework" />
|
||||
<property name="Version" value="1.0.0.0" />
|
||||
<property name="CreateFullTextIndex" value="True" />
|
||||
<property name="IncludeDefaultStopWordList" value="True" />
|
||||
<property name="UseHelpNamespaceMappingFile" value="" />
|
||||
<property name="OmitSyntaxSection" value="False" />
|
||||
<property name="IntroductionPage" value="" />
|
||||
<property name="AboutPageInfo" value="" />
|
||||
<property name="EmptyIndexTermPage" value="" />
|
||||
<property name="NavFailPage" value="" />
|
||||
<property name="AboutPageIconPage" value="" />
|
||||
<property name="AdditionalContentResourceDirectory" value="" />
|
||||
<property name="ExtensibilityStylesheet" value="" />
|
||||
<property name="ShowMissingSummaries" value="False" />
|
||||
<property name="ShowMissingRemarks" value="False" />
|
||||
<property name="ShowMissingParams" value="False" />
|
||||
<property name="ShowMissingReturns" value="False" />
|
||||
<property name="ShowMissingValues" value="False" />
|
||||
<property name="DocumentExplicitInterfaceImplementations" value="False" />
|
||||
<property name="DocumentInternals" value="False" />
|
||||
<property name="DocumentProtected" value="True" />
|
||||
<property name="DocumentSealedProtected" value="False" />
|
||||
<property name="DocumentPrivates" value="False" />
|
||||
<property name="DocumentProtectedInternalAsProtected" value="False" />
|
||||
<property name="DocumentEmptyNamespaces" value="False" />
|
||||
<property name="SkipNamespacesWithoutSummaries" value="False" />
|
||||
<property name="EditorBrowsableFilter" value="Off" />
|
||||
<property name="IncludeAssemblyVersion" value="False" />
|
||||
<property name="CopyrightText" value="" />
|
||||
<property name="CopyrightHref" value="" />
|
||||
<property name="ReferencesPath" value="" />
|
||||
<property name="FeedbackEmailAddress" value="" />
|
||||
<property name="UseNamespaceDocSummaries" value="False" />
|
||||
<property name="AutoPropertyBackerSummaries" value="False" />
|
||||
<property name="AutoDocumentConstructors" value="True" />
|
||||
<property name="GetExternalSummaries" value="True" />
|
||||
<property name="Preliminary" value="False" />
|
||||
<property name="UseNDocXmlFile" value="" />
|
||||
<property name="CleanIntermediates" value="False" />
|
||||
<property name="DocumentAttributes" value="False" />
|
||||
<property name="ShowTypeIdInAttributes" value="False" />
|
||||
<property name="DocumentedAttributes" value="" />
|
||||
<property name="InheritPlatformSupport" value="True" />
|
||||
<property name="DefaultOSSupport" value="all" />
|
||||
<property name="SupportCompactFrameworkByDefault" value="False" />
|
||||
<property name="SupportMONOFrameworkByDefault" value="False" />
|
||||
<property name="AdditionalFrameworkList" value="" />
|
||||
<property name="AdditionalOSList" value="" />
|
||||
</documenter>
|
||||
<documenter name="XML">
|
||||
<property name="OutputFile" value=".\doc\doc.xml" />
|
||||
<property name="ShowMissingSummaries" value="False" />
|
||||
<property name="ShowMissingRemarks" value="False" />
|
||||
<property name="ShowMissingParams" value="False" />
|
||||
<property name="ShowMissingReturns" value="False" />
|
||||
<property name="ShowMissingValues" value="False" />
|
||||
<property name="DocumentExplicitInterfaceImplementations" value="False" />
|
||||
<property name="DocumentInternals" value="False" />
|
||||
<property name="DocumentProtected" value="True" />
|
||||
<property name="DocumentSealedProtected" value="False" />
|
||||
<property name="DocumentPrivates" value="False" />
|
||||
<property name="DocumentProtectedInternalAsProtected" value="False" />
|
||||
<property name="DocumentEmptyNamespaces" value="False" />
|
||||
<property name="SkipNamespacesWithoutSummaries" value="False" />
|
||||
<property name="EditorBrowsableFilter" value="Off" />
|
||||
<property name="IncludeAssemblyVersion" value="False" />
|
||||
<property name="CopyrightText" value="" />
|
||||
<property name="CopyrightHref" value="" />
|
||||
<property name="ReferencesPath" value="" />
|
||||
<property name="FeedbackEmailAddress" value="" />
|
||||
<property name="UseNamespaceDocSummaries" value="False" />
|
||||
<property name="AutoPropertyBackerSummaries" value="False" />
|
||||
<property name="AutoDocumentConstructors" value="True" />
|
||||
<property name="GetExternalSummaries" value="True" />
|
||||
<property name="Preliminary" value="False" />
|
||||
<property name="UseNDocXmlFile" value="" />
|
||||
<property name="CleanIntermediates" value="False" />
|
||||
<property name="DocumentAttributes" value="False" />
|
||||
<property name="ShowTypeIdInAttributes" value="False" />
|
||||
<property name="DocumentedAttributes" value="" />
|
||||
<property name="InheritPlatformSupport" value="True" />
|
||||
<property name="DefaultOSSupport" value="all" />
|
||||
<property name="SupportCompactFrameworkByDefault" value="False" />
|
||||
<property name="SupportMONOFrameworkByDefault" value="False" />
|
||||
<property name="AdditionalFrameworkList" value="" />
|
||||
<property name="AdditionalOSList" value="" />
|
||||
</documenter>
|
||||
</documenters>
|
||||
</project>
|
|
@ -0,0 +1,30 @@
|
|||
Microsoft Visual Studio Solution File, Format Version 8.00
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NPlot", "NPlot.csproj", "{E6867FF5-74EC-4464-8958-D71CB46232F3}"
|
||||
ProjectSection(ProjectDependencies) = postProject
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NPlotDemo", "..\demos\cs\NPlotDemo.csproj", "{7427C7A7-6CB0-4CB3-A0DB-F11603C5C29A}"
|
||||
ProjectSection(ProjectDependencies) = postProject
|
||||
{E6867FF5-74EC-4464-8958-D71CB46232F3} = {E6867FF5-74EC-4464-8958-D71CB46232F3}
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfiguration) = preSolution
|
||||
Debug = Debug
|
||||
Release = Release
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfiguration) = postSolution
|
||||
{E6867FF5-74EC-4464-8958-D71CB46232F3}.Debug.ActiveCfg = Debug|.NET
|
||||
{E6867FF5-74EC-4464-8958-D71CB46232F3}.Debug.Build.0 = Debug|.NET
|
||||
{E6867FF5-74EC-4464-8958-D71CB46232F3}.Release.ActiveCfg = Release|.NET
|
||||
{E6867FF5-74EC-4464-8958-D71CB46232F3}.Release.Build.0 = Release|.NET
|
||||
{7427C7A7-6CB0-4CB3-A0DB-F11603C5C29A}.Debug.ActiveCfg = Debug|.NET
|
||||
{7427C7A7-6CB0-4CB3-A0DB-F11603C5C29A}.Debug.Build.0 = Debug|.NET
|
||||
{7427C7A7-6CB0-4CB3-A0DB-F11603C5C29A}.Release.ActiveCfg = Release|.NET
|
||||
{7427C7A7-6CB0-4CB3-A0DB-F11603C5C29A}.Release.Build.0 = Release|.NET
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityAddIns) = postSolution
|
||||
EndGlobalSection
|
||||
EndGlobal
|
|
@ -0,0 +1,90 @@
|
|||
/*
|
||||
NPlot - A charting library for .NET
|
||||
|
||||
NPlotException.cs
|
||||
Copyright (C) 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;
|
||||
|
||||
namespace NPlot
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// All exceptions thrown by NPlot are of this type.
|
||||
/// </summary>
|
||||
public class NPlotException : System.Exception
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// Constructor
|
||||
/// </summary>
|
||||
/// <param name="message">The error message that explains the reason for the exception.</param>
|
||||
/// <param name="innerException">The exception that is the cause of the current exception.</param>
|
||||
public NPlotException( string message, System.Exception innerException )
|
||||
: base( message, innerException )
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructor
|
||||
/// </summary>
|
||||
/// <param name="message">The error message that explains the reason for the exception.</param>
|
||||
public NPlotException( string message )
|
||||
: base( message )
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructor.
|
||||
/// </summary>
|
||||
public NPlotException()
|
||||
{
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,151 @@
|
|||
/*
|
||||
NPlot - A charting library for .NET
|
||||
|
||||
PageAlignedPhysicalAxis.cs
|
||||
Copyright (C) 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;
|
||||
|
||||
namespace NPlot
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// The bare minimum needed to do world->physical and physical->world transforms for
|
||||
/// vertical axes. Also includes tick placements. Built for speed.
|
||||
/// </summary>
|
||||
/// <remarks>currently unused</remarks>
|
||||
public class PageAlignedPhysicalAxis
|
||||
{
|
||||
|
||||
private int pMin_;
|
||||
private int pMax_;
|
||||
private int pLength_; // cached.
|
||||
|
||||
private double worldMin_;
|
||||
private double worldMax_;
|
||||
private double worldLength_; // cached.
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Construct from a fully-blown physical axis.
|
||||
/// </summary>
|
||||
/// <param name="physicalAxis">the physical axis to get initial values from.</param>
|
||||
public PageAlignedPhysicalAxis( PhysicalAxis physicalAxis )
|
||||
{
|
||||
worldMin_ = physicalAxis.Axis.WorldMin;
|
||||
worldMax_ = physicalAxis.Axis.WorldMax;
|
||||
worldLength_ = worldMax_ - worldMin_;
|
||||
|
||||
if ( physicalAxis.PhysicalMin.X == physicalAxis.PhysicalMax.X )
|
||||
{
|
||||
pMin_ = physicalAxis.PhysicalMin.Y;
|
||||
pMax_ = physicalAxis.PhysicalMax.Y;
|
||||
}
|
||||
else if ( physicalAxis.PhysicalMin.Y == physicalAxis.PhysicalMax.Y )
|
||||
{
|
||||
pMin_ = physicalAxis.PhysicalMin.X;
|
||||
pMax_ = physicalAxis.PhysicalMax.X;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new NPlotException( "Physical axis is not page aligned" );
|
||||
}
|
||||
|
||||
pLength_ = pMax_ - pMin_;
|
||||
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// return the physical coordinate corresponding to the supplied world coordinate.
|
||||
/// </summary>
|
||||
/// <param name="world">world coordinate to determine physical coordinate for.</param>
|
||||
/// <returns>the physical coordinate corresoindng to the supplied world coordinate.</returns>
|
||||
public float WorldToPhysical( double world )
|
||||
{
|
||||
return (float)(((world-worldMin_) / worldLength_) * (float)pLength_ + (float)pMin_);
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// return the physical coordinate corresponding to the supplied world coordinate,
|
||||
/// clipped if it is outside the bounds of the axis
|
||||
/// </summary>
|
||||
/// <param name="world">world coordinate to determine physical coordinate for.</param>
|
||||
/// <returns>the physical coordinate corresoindng to the supplied world coordinate.</returns>
|
||||
public float WorldToPhysicalClipped( double world )
|
||||
{
|
||||
if (world > worldMax_)
|
||||
{
|
||||
return pMax_;
|
||||
}
|
||||
|
||||
if (world < worldMin_)
|
||||
{
|
||||
return pMin_;
|
||||
}
|
||||
|
||||
// is this quicker than returning WorldToPhysical?
|
||||
return (float)(((world-worldMin_) / worldLength_) * (float)pLength_ + (float)pMin_);
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// return the world coordinate corresponding to the supplied physical coordinate.
|
||||
/// </summary>
|
||||
/// <param name="physical">physical coordinate to determine world coordinate for.</param>
|
||||
/// <returns>the world coordinate corresponding to the supplied </returns>
|
||||
public double PhysicalToWorld( float physical )
|
||||
{
|
||||
return ((float)(physical-pMin_) / (float)pLength_) * worldLength_ + worldMin_;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,276 @@
|
|||
/*
|
||||
NPlot - A charting library for .NET
|
||||
|
||||
PhysicalAxis.cs
|
||||
Copyright (C) 2003
|
||||
Matt Howlett, Paolo Pierini
|
||||
|
||||
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;
|
||||
using System.Collections;
|
||||
|
||||
namespace NPlot
|
||||
{
|
||||
/// <summary>
|
||||
/// This class adds physical positioning information [PhysicalMin, PhysicalMax]
|
||||
/// and related functionality on top of a specific Axis class.
|
||||
///
|
||||
/// It's an interesting
|
||||
/// question where to put this information. It belongs with every specific axis
|
||||
/// type, but on the other hand, users of the library as it is normally used
|
||||
/// should not see it because
|
||||
/// positioning of axes is handled internally by PlotSurface2D. Therefore it doesn't make sense
|
||||
/// to put it in the Axis class unless it is internal. But if this were done it would restrict
|
||||
/// use of this information outside the library always, which is not what is wanted.
|
||||
/// The main disadvantage with the method chosen is that there is a lot of passing
|
||||
/// of the positional information between physical axis and the underlying logical
|
||||
/// axis type.
|
||||
///
|
||||
/// C# doesn't have templates. If it did, I might derive PhysicalAxis from the
|
||||
/// templated Axis type (LinearAxis etc). Instead, have used a has-a relationship
|
||||
/// with an Axis superclass.
|
||||
/// </summary>
|
||||
public class PhysicalAxis
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// Prevent default construction.
|
||||
/// </summary>
|
||||
private PhysicalAxis()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Construct
|
||||
/// </summary>
|
||||
/// <param name="a">The axis this is a physical representation of.</param>
|
||||
/// <param name="physicalMin">the physical position of the world minimum axis value.</param>
|
||||
/// <param name="physicalMax">the physical position of the world maximum axis value.</param>
|
||||
public PhysicalAxis( Axis a, Point physicalMin, Point physicalMax )
|
||||
{
|
||||
this.Axis = a;
|
||||
this.PhysicalMin = physicalMin;
|
||||
this.PhysicalMax = physicalMax;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Returns the smallest rectangle that completely contains all parts of the axis [including ticks and label].
|
||||
/// </summary>
|
||||
/// <returns>the smallest rectangle that completely contains all parts of the axis [including ticks and label].</returns>
|
||||
public virtual Rectangle GetBoundingBox()
|
||||
{
|
||||
System.Drawing.Bitmap scratchArea_ = new System.Drawing.Bitmap( 1, 1 );
|
||||
Graphics g = Graphics.FromImage( scratchArea_ );
|
||||
Rectangle bounds;
|
||||
this.Draw( g, out bounds );
|
||||
return bounds;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Draws the axis on the given graphics surface.
|
||||
/// </summary>
|
||||
/// <param name="g">The graphics surface on which to draw.</param>
|
||||
/// <param name="boundingBox">out: the axis bounding box - the smallest rectangle that
|
||||
/// completely contains all parts of the axis [including ticks and label].</param>
|
||||
public virtual void Draw( System.Drawing.Graphics g, out Rectangle boundingBox )
|
||||
{
|
||||
this.Axis.Draw( g, PhysicalMin, PhysicalMax, out boundingBox );
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Given a world coordinate value, returns the physical position of the
|
||||
/// coordinate along the axis.
|
||||
/// </summary>
|
||||
/// <param name="coord">the world coordinate</param>
|
||||
/// <param name="clip">if true, the physical position returned will be clipped to the physical max / min position as appropriate if the world value is outside the limits of the axis.</param>
|
||||
/// <returns>the physical position of the coordinate along the axis.</returns>
|
||||
public PointF WorldToPhysical( double coord, bool clip )
|
||||
{
|
||||
return Axis.WorldToPhysical( coord, PhysicalMin, PhysicalMax, clip );
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Given a physical point on the graphics surface, returns the world
|
||||
/// value of it's projection onto the axis [i.e. closest point on the axis].
|
||||
/// The function is implemented for axes of arbitrary orientation.
|
||||
/// </summary>
|
||||
/// <param name="p">Physical point to find corresponding world value of.</param>
|
||||
/// <param name="clip">if true, returns a world position outside WorldMin / WorldMax
|
||||
/// range if this is closer to the axis line. If false, such values will
|
||||
/// be clipped to be either WorldMin or WorldMax as appropriate.</param>
|
||||
/// <returns>the world value of the point's projection onto the axis.</returns>
|
||||
public double PhysicalToWorld( Point p, bool clip )
|
||||
{
|
||||
return Axis.PhysicalToWorld( p, PhysicalMin, PhysicalMax, clip );
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// This sets new world limits for the axis from two physical points
|
||||
/// selected within the plot area.
|
||||
/// </summary>
|
||||
/// <param name="min">The upper left point of the selection.</param>
|
||||
/// <param name="max">The lower right point of the selection.</param>
|
||||
public void SetWorldLimitsFromPhysical( Point min, Point max )
|
||||
{
|
||||
double minc;
|
||||
double maxc;
|
||||
if (Axis != null)
|
||||
{
|
||||
minc = Axis.WorldMin;
|
||||
maxc = Axis.WorldMax;
|
||||
if ( !Axis.Reversed )
|
||||
{
|
||||
double tmp = this.PhysicalToWorld(min,true);
|
||||
Axis.WorldMax = this.PhysicalToWorld(max,true);
|
||||
Axis.WorldMin = tmp;
|
||||
}
|
||||
else
|
||||
{
|
||||
double tmp = this.PhysicalToWorld(min,true);
|
||||
Axis.WorldMin = this.PhysicalToWorld(max,true);
|
||||
Axis.WorldMax = tmp;
|
||||
}
|
||||
// need to trap somehow if the user selects an
|
||||
// arbitrarily small range. Otherwise the GDI+
|
||||
// drawing routines lead to an overflow in painting
|
||||
// the picture. This may be not the optimal solution,
|
||||
// but if the GDI+ draw leads to an overflow the
|
||||
// graphic surface becomes unusable anymore and I
|
||||
// had difficulty to trap the error.
|
||||
double half = (Axis.WorldMin + Axis.WorldMax)/2;
|
||||
double width = Axis.WorldMax - Axis.WorldMin;
|
||||
if (Math.Abs(half/width) > 1.0e12)
|
||||
{
|
||||
Axis.WorldMin = minc;
|
||||
Axis.WorldMax = maxc;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// The physical position corresponding to WorldMin.
|
||||
/// </summary>
|
||||
public Point PhysicalMin
|
||||
{
|
||||
get
|
||||
{
|
||||
return physicalMin_;
|
||||
}
|
||||
set
|
||||
{
|
||||
physicalMin_ = value;
|
||||
}
|
||||
}
|
||||
private Point physicalMin_;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// The physical position corresponding to WorldMax.
|
||||
/// </summary>
|
||||
public Point PhysicalMax
|
||||
{
|
||||
get
|
||||
{
|
||||
return physicalMax_;
|
||||
}
|
||||
set
|
||||
{
|
||||
physicalMax_ = value;
|
||||
}
|
||||
}
|
||||
private Point physicalMax_;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// The axis this object adds physical extents to.
|
||||
/// </summary>
|
||||
public Axis Axis
|
||||
{
|
||||
get
|
||||
{
|
||||
return axis_;
|
||||
}
|
||||
set
|
||||
{
|
||||
axis_ = value;
|
||||
}
|
||||
}
|
||||
private Axis axis_;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// The length in pixels of the axis.
|
||||
/// </summary>
|
||||
public int PhysicalLength
|
||||
{
|
||||
get
|
||||
{
|
||||
return Utils.Distance( PhysicalMin, PhysicalMax );
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The length in world coordinates of one pixel.
|
||||
/// </summary>
|
||||
public double PixelWorldLength
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.Axis.WorldLength / this.PhysicalLength;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,230 @@
|
|||
/*
|
||||
NPlot - A charting library for .NET
|
||||
|
||||
PiAxis.cs
|
||||
Copyright (C) 2004
|
||||
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.Collections;
|
||||
|
||||
namespace NPlot
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// Axis with labels in multiples of Pi. Maybe needs a better name.
|
||||
/// Lots of functionality still to be added - currently only puts labels
|
||||
/// at whole increments of pi, want arbitrary increments, automatically
|
||||
/// determined and dependance on physical length.
|
||||
/// Volunteers?
|
||||
/// </summary>
|
||||
public class PiAxis : Axis
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// Deep copy of PiAxis.
|
||||
/// </summary>
|
||||
/// <returns>A copy of the LinearAxis Class.</returns>
|
||||
public override object Clone()
|
||||
{
|
||||
PiAxis a = new PiAxis();
|
||||
// ensure that this isn't being called on a derived type. If it is, then oh no!
|
||||
if (this.GetType() != a.GetType())
|
||||
{
|
||||
throw new NPlotException( "Error. Clone method is not defined in derived type." );
|
||||
}
|
||||
DoClone( this, a );
|
||||
return a;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Helper method for Clone.
|
||||
/// </summary>
|
||||
/// <param name="a">The original object to clone.</param>
|
||||
/// <param name="b">The cloned object.</param>
|
||||
protected static void DoClone( PiAxis b, PiAxis a )
|
||||
{
|
||||
Axis.DoClone( b, a );
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Initialise PiAxis to default state.
|
||||
/// </summary>
|
||||
private void Init()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Copy constructor
|
||||
/// </summary>
|
||||
/// <param name="a">The Axis to clone.</param>
|
||||
/// <remarks>TODO: [review notes] I don't think this will work as desired.</remarks>
|
||||
public PiAxis( Axis a )
|
||||
: base( a )
|
||||
{
|
||||
Init();
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Default constructor
|
||||
/// </summary>
|
||||
public PiAxis()
|
||||
: base()
|
||||
{
|
||||
Init();
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Constructor
|
||||
/// </summary>
|
||||
/// <param name="worldMin">Minimum world value</param>
|
||||
/// <param name="worldMax">Maximum world value</param>
|
||||
public PiAxis( double worldMin, double worldMax )
|
||||
: base( worldMin, worldMax )
|
||||
{
|
||||
Init();
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Given Graphics surface, and physical extents of axis, draw ticks and
|
||||
/// associated labels.
|
||||
/// </summary>
|
||||
/// <param name="g">The GDI+ Graphics surface on which to draw.</param>
|
||||
/// <param name="physicalMin">The physical location of the world min point</param>
|
||||
/// <param name="physicalMax">The physical location of the world max point</param>
|
||||
/// <param name="boundingBox">out: smallest box that completely encompasses all of the ticks and tick labels.</param>
|
||||
/// <param name="labelOffset">out: a suitable offset from the axis to draw the axis label.</param>
|
||||
protected override void DrawTicks(
|
||||
Graphics g,
|
||||
Point physicalMin,
|
||||
Point physicalMax,
|
||||
out object labelOffset,
|
||||
out object boundingBox )
|
||||
{
|
||||
Point tLabelOffset;
|
||||
Rectangle tBoundingBox;
|
||||
|
||||
labelOffset = this.getDefaultLabelOffset( physicalMin, physicalMax );
|
||||
boundingBox = null;
|
||||
|
||||
int start = (int)Math.Ceiling( this.WorldMin / Math.PI );
|
||||
int end = (int)Math.Floor( this.WorldMax / Math.PI );
|
||||
|
||||
// sanity checking.
|
||||
if ( end - start < 0 || end - start > 30 )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
for (int i=start; i<=end; ++i)
|
||||
{
|
||||
string label = i.ToString() + "Pi";
|
||||
|
||||
if (i == 0)
|
||||
label = "0";
|
||||
else if (i == 1)
|
||||
label = "Pi";
|
||||
|
||||
this.DrawTick( g, i*Math.PI, this.LargeTickSize,
|
||||
label,
|
||||
new Point(0,0),
|
||||
physicalMin, physicalMax,
|
||||
out tLabelOffset, out tBoundingBox );
|
||||
|
||||
Axis.UpdateOffsetAndBounds(
|
||||
ref labelOffset, ref boundingBox,
|
||||
tLabelOffset, tBoundingBox );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Determines the positions, in world coordinates, of the large ticks.
|
||||
///
|
||||
/// Label axes do not have small ticks.
|
||||
/// </summary>
|
||||
/// <param name="physicalMin">The physical position corresponding to the world minimum of the axis.</param>
|
||||
/// <param name="physicalMax">The physical position corresponding to the world maximum of the axis.</param>
|
||||
/// <param name="largeTickPositions">ArrayList containing the positions of the large ticks.</param>
|
||||
/// <param name="smallTickPositions">null</param>
|
||||
internal override void WorldTickPositions_FirstPass(
|
||||
Point physicalMin,
|
||||
Point physicalMax,
|
||||
out ArrayList largeTickPositions,
|
||||
out ArrayList smallTickPositions
|
||||
)
|
||||
{
|
||||
smallTickPositions = null;
|
||||
largeTickPositions = new ArrayList();
|
||||
|
||||
int start = (int)Math.Ceiling( this.WorldMin / Math.PI );
|
||||
int end = (int)Math.Floor( this.WorldMax / Math.PI );
|
||||
|
||||
// sanity checking.
|
||||
if ( end - start < 0 || end - start > 30 )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
for (int i=start; i<end; ++i)
|
||||
{
|
||||
largeTickPositions.Add( i*Math.PI );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,120 @@
|
|||
/*
|
||||
NPlot - A charting library for .NET
|
||||
|
||||
PiePlot.cs
|
||||
Copyright (C) 2004
|
||||
Thierry Malo
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
$Id: PiePlot.cs,v 1.3 2004/10/23 07:08:35 mhowlett Exp $
|
||||
|
||||
*/
|
||||
|
||||
/*
|
||||
using System;
|
||||
using System.Drawing;
|
||||
|
||||
namespace scpl
|
||||
{
|
||||
/// <summary>
|
||||
/// Description résumée de PiePlot.
|
||||
/// </summary>
|
||||
public class PiePlot : BasePlot, IPlot
|
||||
{
|
||||
public PiePlot(ISequenceAdapter datas)
|
||||
{
|
||||
//
|
||||
// TODO : ajoutez ici la logique du constructeur
|
||||
//
|
||||
this.Data=datas;
|
||||
|
||||
_brushes=new Brush[_MaxBrush];
|
||||
|
||||
_brushes[0] = Brushes.DarkBlue;
|
||||
_brushes[1] = Brushes.Yellow;
|
||||
_brushes[2] = Brushes.Green;
|
||||
_brushes[3] = Brushes.Brown;
|
||||
_brushes[4] = Brushes.Blue;
|
||||
_brushes[5] = Brushes.Red;
|
||||
_brushes[6] = Brushes.LightGreen;
|
||||
_brushes[7] = Brushes.Salmon;
|
||||
}
|
||||
|
||||
private ISequenceAdapter data_;
|
||||
private double _Total;
|
||||
const int _MaxBrush=8;
|
||||
private Brush[] _brushes;
|
||||
|
||||
public ISequenceAdapter Data
|
||||
{
|
||||
get
|
||||
{
|
||||
return data_;
|
||||
}
|
||||
set
|
||||
{
|
||||
data_ = value;
|
||||
|
||||
// calculate the sum of all value (this is related to 360°)
|
||||
_Total = 0;
|
||||
for ( int i=0; i<data_.Count; ++i )
|
||||
{
|
||||
_Total += data_[i].Y;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#region SuggestXAxis
|
||||
public virtual Axis SuggestXAxis()
|
||||
{
|
||||
return data_.SuggestXAxis();
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region SuggestXAxis
|
||||
public virtual Axis SuggestYAxis()
|
||||
{
|
||||
return data_.SuggestYAxis();
|
||||
}
|
||||
#endregion
|
||||
|
||||
public virtual void Draw( Graphics g, PhysicalAxis xAxis, PhysicalAxis yAxis )
|
||||
{
|
||||
int LastAngle=0,ReelAngle;
|
||||
|
||||
float rx=(xAxis.PhysicalMax.X - xAxis.PhysicalMin.X);
|
||||
float ry=(yAxis.PhysicalMin.Y - yAxis.PhysicalMax.Y);
|
||||
|
||||
int h=(int) (ry * 0.8);
|
||||
int w= (int) (rx * 0.8);
|
||||
|
||||
// This is to keep the pie based on a circle (i.e. inside a square)
|
||||
int s=Math.Min(h,w);
|
||||
|
||||
// calculate boundary rectangle coordinate
|
||||
int cy=(int) (yAxis.PhysicalMax.Y + (h * 1.2 - s) / 2);
|
||||
int cx=(int) (xAxis.PhysicalMin.X + (w * 1.2 - s) / 2);
|
||||
|
||||
for (int i=0; i<this.Data.Count; ++i)
|
||||
{
|
||||
ReelAngle = (int) (data_[i].Y * 360 / _Total);
|
||||
g.FillPie(_brushes[i % _MaxBrush], cx, cy, s, s, LastAngle, ReelAngle);
|
||||
LastAngle += ReelAngle;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -0,0 +1,439 @@
|
|||
// ******** experimental ********
|
||||
/*
|
||||
using System;
|
||||
using System.Xml;
|
||||
using System.Data;
|
||||
using System.Collections;
|
||||
using System.IO;
|
||||
using System.Reflection;
|
||||
using System.Drawing;
|
||||
|
||||
namespace NPlot
|
||||
{
|
||||
|
||||
class PlotSurface2Dnew
|
||||
{
|
||||
|
||||
private ArrayList axisLines_;
|
||||
private ArrayList axisDefinitions_;
|
||||
private ArrayList drawables_;
|
||||
private ArrayList xAxisPositions_;
|
||||
private ArrayList yAxisPositions_;
|
||||
|
||||
private System.Collections.Hashtable axes_;
|
||||
|
||||
/// <summary>
|
||||
/// PlotSurface2D styles supplied with the library.
|
||||
/// </summary>
|
||||
public enum PlotSurfaceStyle
|
||||
{
|
||||
Standard,
|
||||
CrossedAxes,
|
||||
OppositeCloned
|
||||
}
|
||||
|
||||
private class AxisDefinition
|
||||
{
|
||||
public string Name = "";
|
||||
public AxisLine axisLine = null;
|
||||
public int Min = 0;
|
||||
public int Max = 100;
|
||||
}
|
||||
|
||||
private class AxisLine
|
||||
{
|
||||
public enum OrientationType
|
||||
{
|
||||
Horizontal,
|
||||
Vertical
|
||||
}
|
||||
|
||||
public string Name = "";
|
||||
public OrientationType Orientation = OrientationType.Horizontal;
|
||||
public float Position = 0;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Constructor
|
||||
/// </summary>
|
||||
public PlotSurface2Dnew()
|
||||
{
|
||||
Init();
|
||||
}
|
||||
|
||||
|
||||
private AxisDefinition parseAxis( XmlNode node )
|
||||
{
|
||||
// get Parameters
|
||||
AxisDefinition d = new AxisDefinition();
|
||||
|
||||
for (int i=0; i<node.Attributes.Count; ++i)
|
||||
{
|
||||
XmlAttribute a = node.Attributes[i];
|
||||
switch (a.Name.ToLower())
|
||||
{
|
||||
case "name":
|
||||
d.Name = a.Value;
|
||||
break;
|
||||
|
||||
case "axisline":
|
||||
bool found = false;
|
||||
for (int j=0; j<axisLines_.Count; ++j)
|
||||
{
|
||||
if (((AxisLine)axisLines_[j]).Name == a.Value)
|
||||
{
|
||||
d.axisLine = (AxisLine)axisLines_[j];
|
||||
found = true;
|
||||
}
|
||||
}
|
||||
if (!found)
|
||||
{
|
||||
ErrorHandler.Instance.CriticalError( "AxisLine not found" );
|
||||
}
|
||||
break;
|
||||
|
||||
case "physicalmin":
|
||||
try
|
||||
{
|
||||
d.Min = Convert.ToInt32( a.Value );
|
||||
}
|
||||
catch
|
||||
{
|
||||
ErrorHandler.Instance.CriticalError( "min value not numeric" );
|
||||
}
|
||||
if (d.Min< 0 || d.Min > 100)
|
||||
{
|
||||
ErrorHandler.Instance.CriticalError( "min value must be between 0 and 100" );
|
||||
}
|
||||
break;
|
||||
|
||||
case "physicalmax":
|
||||
try
|
||||
{
|
||||
d.Max = Convert.ToInt32( a.Value );
|
||||
}
|
||||
catch
|
||||
{
|
||||
ErrorHandler.Instance.CriticalError( "max value not numeric" );
|
||||
}
|
||||
if (d.Max < 0 || d.Max > 100)
|
||||
{
|
||||
ErrorHandler.Instance.CriticalError( "max value must be between 0 and 100" );
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
ErrorHandler.Instance.CriticalError( "unknown attribute: " + a.Name );
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
return d;
|
||||
}
|
||||
|
||||
|
||||
private AxisLine parseAxisLine( XmlNode node )
|
||||
{
|
||||
|
||||
AxisLine l = new AxisLine();
|
||||
|
||||
for (int i=0; i<node.Attributes.Count; ++i)
|
||||
{
|
||||
XmlAttribute a = node.Attributes[i];
|
||||
switch (a.Name.ToLower())
|
||||
{
|
||||
case "name":
|
||||
l.Name = a.Value;
|
||||
break;
|
||||
|
||||
case "orientation":
|
||||
if (a.Value.ToLower() == "horizontal")
|
||||
l.Orientation = AxisLine.OrientationType.Horizontal;
|
||||
else if (a.Value.ToLower() == "vertical")
|
||||
l.Orientation = AxisLine.OrientationType.Vertical;
|
||||
else
|
||||
{
|
||||
ErrorHandler.Instance.CriticalError( "Unexpected orientation :" + a.Value.ToString() );
|
||||
}
|
||||
break;
|
||||
|
||||
case "position":
|
||||
try
|
||||
{
|
||||
l.Position = Convert.ToInt32( a.Value );
|
||||
}
|
||||
catch
|
||||
{
|
||||
ErrorHandler.Instance.CriticalError( "position not numeric" );
|
||||
}
|
||||
if (l.Position < 0 || l.Position > 100)
|
||||
{
|
||||
ErrorHandler.Instance.CriticalError( "axis position must be between 0 and 100" );
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
ErrorHandler.Instance.CriticalError( "unknown axis line attribute: " + a.Name );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return l;
|
||||
}
|
||||
|
||||
|
||||
public void SetDefinition( )
|
||||
{
|
||||
|
||||
Assembly ass = Assembly.GetExecutingAssembly();
|
||||
System.IO.Stream xmlStream =
|
||||
ass.GetManifestResourceStream( "NPlot.PlotSurfaceDefinitions.OppositeCloned.xml" );
|
||||
|
||||
// load xml
|
||||
|
||||
XmlDocument xmlDoc = null;
|
||||
|
||||
try
|
||||
{
|
||||
xmlDoc = new XmlDocument();
|
||||
xmlDoc.Load( xmlStream );
|
||||
}
|
||||
catch
|
||||
{
|
||||
ErrorHandler.Instance.CriticalError( "PlotSurface2D definition file malformed" );
|
||||
}
|
||||
|
||||
XmlElement el = xmlDoc.DocumentElement;
|
||||
|
||||
// check we're a PlotSurface2D.
|
||||
if (el.Name.ToLower() != "plotsurface2d")
|
||||
{
|
||||
ErrorHandler.Instance.CriticalError( "Root element must be PlotSurface2D" );
|
||||
return;
|
||||
}
|
||||
|
||||
// enforce only one axis set for now.
|
||||
if (el.ChildNodes.Count != 1)
|
||||
{
|
||||
ErrorHandler.Instance.CriticalError( "need one and only one axis set." );
|
||||
return;
|
||||
}
|
||||
|
||||
// loop around all AxisSets.
|
||||
foreach (XmlNode n in el.ChildNodes)
|
||||
{
|
||||
if (n.Name.ToLower() != "axisset")
|
||||
{
|
||||
ErrorHandler.Instance.CriticalError( "Expected AxisSet node" );
|
||||
return;
|
||||
}
|
||||
|
||||
// loop around all nodes in this axis set.
|
||||
foreach (XmlNode n2 in n.ChildNodes)
|
||||
{
|
||||
switch (n2.Name.ToLower())
|
||||
{
|
||||
case "axisline":
|
||||
{
|
||||
axisLines_.Add( parseAxisLine(n2) );
|
||||
break;
|
||||
}
|
||||
case "axis":
|
||||
{
|
||||
axisDefinitions_.Add( parseAxis(n2) );
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
ErrorHandler.Instance.CriticalError( "Unexpected node type encountered: " + n2.Name );
|
||||
return;
|
||||
}
|
||||
}
|
||||
} // end loop around each node in axis set
|
||||
|
||||
// add all axes to class
|
||||
for (int i=0; i<axisDefinitions_.Count; ++i)
|
||||
{
|
||||
//axes_.Add( ((AxisDefinition)axisDefinitions_[i]).Name, null );
|
||||
}
|
||||
|
||||
} // end loop around axis sets.
|
||||
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// The distance in pixels to leave between of the edge of the bounding rectangle
|
||||
/// supplied to the Draw method, and the markings that make up the plot.
|
||||
/// </summary>
|
||||
public int Padding
|
||||
{
|
||||
get
|
||||
{
|
||||
return padding_;
|
||||
}
|
||||
set
|
||||
{
|
||||
padding_ = value;
|
||||
}
|
||||
}
|
||||
private int padding_;
|
||||
|
||||
|
||||
private void Init()
|
||||
{
|
||||
axes_ = null;
|
||||
|
||||
drawables_ = new ArrayList();
|
||||
xAxisPositions_ = new ArrayList();
|
||||
yAxisPositions_ = new ArrayList();
|
||||
axisLines_ = new ArrayList();
|
||||
axisDefinitions_ = new ArrayList();
|
||||
|
||||
padding_ = 10;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Draw the the PlotSurface2D and all contents [axes, drawables, and legend] on the
|
||||
/// supplied graphics surface.
|
||||
/// </summary>
|
||||
/// <param name="g">The graphics surface on which to draw.</param>
|
||||
/// <param name="bounds">A bounding box on this surface that denotes the area on the
|
||||
/// surface to confine drawing to.</param>
|
||||
public void Draw( Graphics g, Rectangle bounds )
|
||||
{
|
||||
Rectangle realBounds = new Rectangle(
|
||||
bounds.X + padding_ / 2,
|
||||
bounds.Y + padding_ / 2,
|
||||
bounds.Width - padding_,
|
||||
bounds.Height - padding_
|
||||
);
|
||||
|
||||
// create initial set of physical axes. These will
|
||||
// be moved later to ensure everything is drawn ok.
|
||||
ArrayList physicalAxes = new ArrayList();
|
||||
|
||||
for (int i=0; i<axisDefinitions_.Count; ++i)
|
||||
{
|
||||
AxisDefinition d = (AxisDefinition)axisDefinitions_[i];
|
||||
|
||||
Point physicalMin = new Point(0,0);
|
||||
Point physicalMax = new Point(0,0);
|
||||
|
||||
if (d.axisLine.Orientation == AxisLine.OrientationType.Horizontal)
|
||||
{
|
||||
int yPos = (int)(realBounds.Top + ((float)d.axisLine.Position/100.0 * realBounds.Height));
|
||||
|
||||
physicalMin.X = realBounds.Left;
|
||||
physicalMin.Y = yPos;
|
||||
physicalMax.X = realBounds.Right;
|
||||
physicalMax.Y = yPos;
|
||||
}
|
||||
else
|
||||
{
|
||||
int xPos = (int)(realBounds.Left + ((float)d.axisLine.Position/100.0 * realBounds.Width));
|
||||
|
||||
physicalMin.X = xPos;
|
||||
physicalMin.Y = realBounds.Bottom;
|
||||
physicalMax.X = xPos;
|
||||
physicalMax.Y = realBounds.Top;
|
||||
}
|
||||
|
||||
physicalAxes.Add( new PhysicalAxis( new LinearAxis(0.0,1.0), physicalMin, physicalMax ) );
|
||||
}
|
||||
|
||||
for (int i=0; i<physicalAxes.Count; ++i)
|
||||
{
|
||||
Rectangle axisBounds;
|
||||
((PhysicalAxis)physicalAxes[i]).Draw( g, out axisBounds );
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
private void UpdateAxes()
|
||||
{
|
||||
// make sure drawable lists exist.
|
||||
if (drawables_.Count==0 || xAxisPositions_.Count==0 || yAxisPositions_.Count==0)
|
||||
{
|
||||
ErrorHandler.Instance.ContinuingError( "UpdateAxes called from function other than Add." );
|
||||
}
|
||||
|
||||
int last = drawables_.Count - 1;
|
||||
|
||||
if ( last != xAxisPositions_.Count-1 || last != yAxisPositions_.Count-1 )
|
||||
{
|
||||
ErrorHandler.Instance.CriticalError( "plots and axis position arrays our of sync" );
|
||||
}
|
||||
|
||||
|
||||
// make sure axes exit.
|
||||
AxisDefinition xAxisDefinition = null;
|
||||
AxisDefinition yAxisDefinition = null;
|
||||
for (int i=0; i<this.axisDefinitions_.Count; ++i)
|
||||
{
|
||||
AxisDefinition def = (AxisDefinition)axisDefinitions_[i];
|
||||
if (def.Name == (string)xAxisPositions_[last])
|
||||
xAxisDefinition = def;
|
||||
|
||||
if (def.Name == (string)yAxisPositions_[last])
|
||||
yAxisDefinition = def;
|
||||
}
|
||||
|
||||
if (xAxisDefinition == null || yAxisDefinition == null)
|
||||
{
|
||||
ErrorHandler.Instance.CriticalError( "Axis does not exist." );
|
||||
}
|
||||
|
||||
IPlot p = (IPlot)drawables_[last];
|
||||
|
||||
// update x axis.
|
||||
if (axes_[xAxisDefinition.Name] == null)
|
||||
{
|
||||
this.axes_[xAxisDefinition.Name] = p.SuggestXAxis();
|
||||
}
|
||||
else
|
||||
{
|
||||
((Axis)this.axes_[xAxisDefinition.Name]).LUB( p.SuggestXAxis() );
|
||||
}
|
||||
|
||||
// update y axis.
|
||||
if (axes_[yAxisDefinition.Name] == null)
|
||||
{
|
||||
this.axes_[yAxisDefinition.Name] = p.SuggestYAxis();
|
||||
}
|
||||
else
|
||||
{
|
||||
((Axis)this.axes_[yAxisDefinition.Name]).LUB( p.SuggestYAxis() );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Adds a drawable object to the plot surface against the specified axes. If
|
||||
/// the object is an IPlot, the PlotSurface2D axes will also be updated.
|
||||
/// </summary>
|
||||
/// <param name="p">the IDrawable object to add to the plot surface</param>
|
||||
/// <param name="xAxis">the x-axis to add the plot against.</param>
|
||||
/// <param name="yAxis">the y-axis to add the plot against.</param>
|
||||
public void Add( IDrawable p, string xAxis, string yAxis )
|
||||
{
|
||||
drawables_.Add( p );
|
||||
xAxisPositions_.Add( xAxis );
|
||||
yAxisPositions_.Add( yAxis );
|
||||
|
||||
if ( p is IPlot )
|
||||
{
|
||||
this.UpdateAxes();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
*/
|
|
@ -0,0 +1,64 @@
|
|||
// ******** experimental ********
|
||||
|
||||
/*
|
||||
NPlot - A charting library for .NET
|
||||
|
||||
PlotSurface3D.cs
|
||||
Copyright (C) 2003
|
||||
Matt Howlett
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the following text in
|
||||
the documentation and / or other materials provided with the
|
||||
distribution:
|
||||
|
||||
"This product includes software developed as part of
|
||||
the NPlot charting library project available from:
|
||||
http://www.nplot.com/"
|
||||
|
||||
------------------------------------------------------------------------
|
||||
|
||||
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.
|
||||
|
||||
$Id: PlotSurface3D.cs,v 1.9 2004/11/17 10:39:19 mhowlett Exp $
|
||||
|
||||
*/
|
||||
/*
|
||||
|
||||
using System;
|
||||
|
||||
namespace NPlot
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// TODO
|
||||
/// </summary>
|
||||
public class PlotSurface3D : IPlotSurface3D
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// TODO
|
||||
/// </summary>
|
||||
public PlotSurface3D()
|
||||
{
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
*/
|
|
@ -0,0 +1,26 @@
|
|||
<!-- ******** experimental ******** -->
|
||||
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
|
||||
<PlotSurface2D name="CrossedAxes">
|
||||
|
||||
<AxisSet rotation="0">
|
||||
|
||||
<AxisLine name="MiddleHorizontalLine" type="X" placement="80" ExtendDirection=-90/>
|
||||
<AxisLine name="MiddleVerticalLine" type="Y" placement="50" ExtendDirection=-90/>
|
||||
|
||||
<Axis type="X" name="XAxis">
|
||||
<Placement line="MiddleHorizontalLine" PhysicalMin=0 PhysicalMax=100 />
|
||||
</Axis>
|
||||
|
||||
<Axis type="Y" name="YAxis">
|
||||
<Placement line="MiddleVerticalLine" PhysicalMin=0 PhysicalMax=100 />
|
||||
</Axis>
|
||||
|
||||
<Axis type="Y" name="YAxis2">
|
||||
<Placement line="MiddleVerticalLine" PhysicalMin=0 PhysicalMax=100 />
|
||||
</Axis>
|
||||
|
||||
</AxisSet>
|
||||
|
||||
</PlotSurface2D>
|
|
@ -0,0 +1,21 @@
|
|||
<!-- ******** experimental ******** -->
|
||||
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
|
||||
<PlotSurface2D>
|
||||
|
||||
<AxisSet rotation="0">
|
||||
|
||||
<AxisLine Name="MiddleHorizontalLine" orientation="Horizontal" position="20" />
|
||||
<AxisLine name="MiddleVerticalLine" orientation="Vertical" position="50" />
|
||||
|
||||
<Axis name="XAxis" axisLine="MiddleHorizontalLine" physicalMin="0" physicalMax="100">
|
||||
</Axis>
|
||||
|
||||
<Axis name="YAxis" axisLine="MiddleVerticalLine" physicalMin="0" physicalMax="100">
|
||||
</Axis>
|
||||
|
||||
|
||||
</AxisSet>
|
||||
|
||||
</PlotSurface2D>
|
|
@ -0,0 +1,14 @@
|
|||
<!-- ******** experimental ******** -->
|
||||
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
|
||||
<PlotSurface name="Standard">
|
||||
|
||||
<AxisSet rotation="0">
|
||||
|
||||
<AxisLine name="MiddleHorizontalLine" type="X" placement="80" ExtendDire/>
|
||||
<AxisLine name="MiddleVerticalLine" type="Y" placement="50"/>
|
||||
|
||||
</AxisSet>
|
||||
|
||||
</PlotSurface>
|
|
@ -0,0 +1,91 @@
|
|||
/*
|
||||
NPlot - A charting library for .NET
|
||||
|
||||
PointD.cs
|
||||
Copyright (C) 2003-2004
|
||||
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.
|
||||
|
||||
*/
|
||||
|
||||
namespace NPlot
|
||||
{
|
||||
/// <summary>
|
||||
/// Represtents a point in two-dimensional space. Used for representation
|
||||
/// of points world coordinates.
|
||||
/// </summary>
|
||||
public struct PointD
|
||||
{
|
||||
/// <summary>
|
||||
/// X-Coordinate of the point.
|
||||
/// </summary>
|
||||
public double X;
|
||||
|
||||
/// <summary>
|
||||
/// Y-Coordinate of the point.
|
||||
/// </summary>
|
||||
public double Y;
|
||||
|
||||
/// <summary>
|
||||
/// Constructor
|
||||
/// </summary>
|
||||
/// <param name="x">X-Coordinate of the point.</param>
|
||||
/// <param name="y">Y-Coordinate of the point.</param>
|
||||
public PointD( double x, double y )
|
||||
{
|
||||
X = x;
|
||||
Y = y;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// returns a string representation of the point.
|
||||
/// </summary>
|
||||
/// <returns>string representation of the point.</returns>
|
||||
public override string ToString()
|
||||
{
|
||||
return X.ToString() + "\t" + Y.ToString();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,45 @@
|
|||
// ******** experimental ********
|
||||
/*
|
||||
using System;
|
||||
|
||||
namespace NPlot
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// Represtents a point in three-dimensional space. Used for representation
|
||||
/// of points world coordinates.
|
||||
/// </summary>
|
||||
public struct PointD3D
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// X-Coordinate of the point.
|
||||
/// </summary>
|
||||
public double X;
|
||||
|
||||
/// <summary>
|
||||
/// Y-Coordinate of the point.
|
||||
/// </summary>
|
||||
public double Y;
|
||||
|
||||
/// <summary>
|
||||
/// Z-Coordinate of the point.
|
||||
/// </summary>
|
||||
public double Z;
|
||||
|
||||
/// <summary>
|
||||
/// Constructor
|
||||
/// </summary>
|
||||
/// <param name="x">X-Coordinate of the point.</param>
|
||||
/// <param name="y">Y-Coordinate of the point.</param>
|
||||
/// <param name="z">Z-Coordinate of the point.</param>
|
||||
public PointD3D( double x, double y, double z )
|
||||
{
|
||||
X = x;
|
||||
Y = y;
|
||||
Z = z;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
*/
|
|
@ -0,0 +1,182 @@
|
|||
/*
|
||||
NPlot - A charting library for .NET
|
||||
|
||||
PointPlot.cs
|
||||
Copyright (C) 2003
|
||||
Matt Howlett, Paolo Pierini
|
||||
|
||||
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>
|
||||
/// Encapsulates functionality for drawing data as a series of points.
|
||||
/// </summary>
|
||||
public class PointPlot : BaseSequencePlot, ISequencePlot, IPlot
|
||||
{
|
||||
private Marker marker_;
|
||||
|
||||
/// <summary>
|
||||
/// Default Constructor
|
||||
/// </summary>
|
||||
public PointPlot()
|
||||
{
|
||||
marker_ = new Marker();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructor for the marker plot.
|
||||
/// </summary>
|
||||
/// <param name="marker">The marker to use.</param>
|
||||
public PointPlot( Marker marker )
|
||||
{
|
||||
marker_ = marker;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Draws the point plot on a GDI+ surface against the provided x and y axes.
|
||||
/// </summary>
|
||||
/// <param name="g">The GDI+ 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 virtual void Draw( Graphics g, PhysicalAxis xAxis, PhysicalAxis yAxis )
|
||||
{
|
||||
SequenceAdapter data_ =
|
||||
new SequenceAdapter( this.DataSource, this.DataMember, this.OrdinateData, this.AbscissaData );
|
||||
|
||||
float leftCutoff_ = xAxis.PhysicalMin.X - marker_.Size;
|
||||
float rightCutoff_ = xAxis.PhysicalMax.X + marker_.Size;
|
||||
|
||||
for (int i=0; i<data_.Count; ++i)
|
||||
{
|
||||
if ( !Double.IsNaN(data_[i].X) && !Double.IsNaN(data_[i].Y) )
|
||||
{
|
||||
PointF xPos = xAxis.WorldToPhysical( data_[i].X, false);
|
||||
if (xPos.X < leftCutoff_ || rightCutoff_ < xPos.X)
|
||||
continue;
|
||||
|
||||
PointF yPos = yAxis.WorldToPhysical( data_[i].Y, false);
|
||||
marker_.Draw( g, (int)xPos.X, (int)yPos.Y );
|
||||
if (marker_.DropLine)
|
||||
{
|
||||
PointD yMin = new PointD( data_[i].X, Math.Max( 0.0f, yAxis.Axis.WorldMin ) );
|
||||
PointF yStart = yAxis.WorldToPhysical( yMin.Y, false );
|
||||
g.DrawLine( marker_.Pen, new Point((int)xPos.X,(int)yStart.Y), new Point((int)xPos.X,(int)yPos.Y) );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Returns an x-axis that is suitable for drawing this plot.
|
||||
/// </summary>
|
||||
/// <returns>A suitable x-axis.</returns>
|
||||
public Axis SuggestXAxis()
|
||||
{
|
||||
SequenceAdapter data_ =
|
||||
new SequenceAdapter( this.DataSource, this.DataMember, this.OrdinateData, this.AbscissaData );
|
||||
|
||||
return data_.SuggestXAxis();
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Returns a y-axis that is suitable for drawing this plot.
|
||||
/// </summary>
|
||||
/// <returns>A suitable y-axis.</returns>
|
||||
public Axis SuggestYAxis()
|
||||
{
|
||||
SequenceAdapter data_ =
|
||||
new SequenceAdapter( this.DataSource, this.DataMember, this.OrdinateData, this.AbscissaData );
|
||||
|
||||
return data_.SuggestYAxis();
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Draws a representation of this plot in the legend.
|
||||
/// </summary>
|
||||
/// <param name="g">The graphics surface on which to draw.</param>
|
||||
/// <param name="startEnd">A rectangle specifying the bounds of the area in the legend set aside for drawing.</param>
|
||||
public void DrawInLegend( Graphics g, Rectangle startEnd )
|
||||
{
|
||||
if (marker_.Size > 0)
|
||||
{
|
||||
marker_.Draw(g, (startEnd.Left + startEnd.Right) / 2, (startEnd.Top + startEnd.Bottom) / 2);
|
||||
}
|
||||
else if (marker_.Pen.Width > 0)
|
||||
{
|
||||
g.DrawLine(marker_.Pen,
|
||||
(startEnd.Left + startEnd.Right) / 2, (startEnd.Top + startEnd.Bottom - marker_.Pen.Width) / 2,
|
||||
(startEnd.Left + startEnd.Right) / 2, (startEnd.Top + startEnd.Bottom + marker_.Pen.Width) / 2);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// The Marker object used for the plot.
|
||||
/// </summary>
|
||||
public Marker Marker
|
||||
{
|
||||
set
|
||||
{
|
||||
marker_ = value;
|
||||
}
|
||||
get
|
||||
{
|
||||
return marker_;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,65 @@
|
|||
// ******** experimental ********
|
||||
|
||||
/*
|
||||
using System;
|
||||
using System.Drawing;
|
||||
|
||||
namespace NPlot
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// Think we should just implement point plot first, unless you need
|
||||
/// other stuff.
|
||||
/// </summary>
|
||||
public class PointPlot3D : BasePlot3D, IPlot3D
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// Constructor
|
||||
/// </summary>
|
||||
public PointPlot3D()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Draws the points on the supplied axes. TODO.
|
||||
/// </summary>
|
||||
/// <param name="g"></param>
|
||||
/// <param name="xAxis"></param>
|
||||
/// <param name="yAxis"></param>
|
||||
/// <param name="zAxis"></param>
|
||||
void Draw( Graphics g, PhysicalAxis xAxis, PhysicalAxis yAxis, PhysicalAxis zAxis )
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The method used to set the default x axis.
|
||||
/// </summary>
|
||||
public Axis SuggestXAxis()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The method used to set the default y axis.
|
||||
/// </summary>
|
||||
public Axis SuggestYAxis()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The method used to set the default z axis.
|
||||
/// </summary>
|
||||
public Axis SuggestZAxis()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
*/
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -0,0 +1,143 @@
|
|||
/*
|
||||
NPlot - A charting library for .NET
|
||||
|
||||
RectangleD.cs
|
||||
Copyright (C) 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.Drawing;
|
||||
|
||||
namespace NPlot
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// Stores a set of four double numbers that represent the location and size of
|
||||
/// a rectangle. TODO: implement more functionality similar to Drawing.RectangleF.
|
||||
/// </summary>
|
||||
public struct RectangleD
|
||||
{
|
||||
/// <summary>
|
||||
/// Constructor
|
||||
/// </summary>
|
||||
public RectangleD( double x, double y, double width, double height )
|
||||
{
|
||||
x_ = x;
|
||||
y_ = y;
|
||||
width_ = width;
|
||||
height_ = height;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The rectangle height.
|
||||
/// </summary>
|
||||
public double Height
|
||||
{
|
||||
get
|
||||
{
|
||||
return height_;
|
||||
}
|
||||
set
|
||||
{
|
||||
height_ = value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The rectangle width.
|
||||
/// </summary>
|
||||
public double Width
|
||||
{
|
||||
get
|
||||
{
|
||||
return width_;
|
||||
}
|
||||
set
|
||||
{
|
||||
width_ = value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The minimum x coordinate of the rectangle.
|
||||
/// </summary>
|
||||
public double X
|
||||
{
|
||||
get
|
||||
{
|
||||
return x_;
|
||||
}
|
||||
set
|
||||
{
|
||||
x_ = value;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// The minimum y coordinate of the rectangle.
|
||||
/// </summary>
|
||||
public double Y
|
||||
{
|
||||
get
|
||||
{
|
||||
return y_;
|
||||
}
|
||||
set
|
||||
{
|
||||
y_ = value;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private double x_;
|
||||
private double y_;
|
||||
private double width_;
|
||||
private double height_;
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,330 @@
|
|||
/*
|
||||
NPlot - A charting library for .NET
|
||||
|
||||
SequenceAdapter.cs
|
||||
Copyright (C) 2003-2004
|
||||
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>
|
||||
/// This class is responsible for interpreting the various ways you can
|
||||
/// specify data to plot objects using the DataSource, DataMember, ordinateData
|
||||
/// and AbscissaData properties. It is a bridge that provides access to this
|
||||
/// data via a single interface.
|
||||
/// </summary>
|
||||
public class SequenceAdapter
|
||||
{
|
||||
private AdapterUtils.IAxisSuggester XAxisSuggester_;
|
||||
private AdapterUtils.IAxisSuggester YAxisSuggester_;
|
||||
private AdapterUtils.ICounter counter_;
|
||||
private AdapterUtils.IDataGetter xDataGetter_;
|
||||
private AdapterUtils.IDataGetter yDataGetter_;
|
||||
|
||||
/// <summary>
|
||||
/// Constructor. The data source specifiers must be specified here.
|
||||
/// </summary>
|
||||
/// <param name="dataSource">The source containing a list of values to plot.</param>
|
||||
/// <param name="dataMember">The specific data member in a multimember data source to get data from.</param>
|
||||
/// <param name="ordinateData">The source containing a list of values to plot on the ordinate axis, or a the name of the column to use for this data.</param>
|
||||
/// <param name="abscissaData">The source containing a list of values to plot on the abscissa axis, or a the name of the column to use for this data.</param>
|
||||
public SequenceAdapter( object dataSource, string dataMember, object ordinateData, object abscissaData )
|
||||
{
|
||||
|
||||
if (dataSource == null && dataMember == null)
|
||||
{
|
||||
if (ordinateData is IList)
|
||||
{
|
||||
|
||||
this.YAxisSuggester_ = new AdapterUtils.AxisSuggester_IList((IList)ordinateData);
|
||||
if (ordinateData is Double[])
|
||||
this.yDataGetter_ = new AdapterUtils.DataGetter_DoublesArray((Double[])ordinateData);
|
||||
else
|
||||
this.yDataGetter_ = new AdapterUtils.DataGetter_IList((IList)ordinateData);
|
||||
|
||||
this.counter_ = new AdapterUtils.Counter_IList((IList)ordinateData);
|
||||
|
||||
if (abscissaData is IList)
|
||||
{
|
||||
this.XAxisSuggester_ = new AdapterUtils.AxisSuggester_IList((IList)abscissaData);
|
||||
if (abscissaData is Double[])
|
||||
this.xDataGetter_ = new AdapterUtils.DataGetter_DoublesArray((Double[])abscissaData);
|
||||
else
|
||||
this.xDataGetter_ = new AdapterUtils.DataGetter_IList((IList)abscissaData);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
else if (abscissaData is StartStep)
|
||||
{
|
||||
this.XAxisSuggester_ = new AdapterUtils.AxisSuggester_StartStep((StartStep)abscissaData, (IList)ordinateData);
|
||||
this.xDataGetter_ = new AdapterUtils.DataGetter_StartStep((StartStep)abscissaData);
|
||||
return;
|
||||
}
|
||||
|
||||
else if (abscissaData == null)
|
||||
{
|
||||
this.XAxisSuggester_ = new AdapterUtils.AxisSuggester_Auto((IList)ordinateData);
|
||||
this.xDataGetter_ = new AdapterUtils.DataGetter_Count();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
else if (ordinateData == null)
|
||||
{
|
||||
if (abscissaData == null)
|
||||
{
|
||||
this.XAxisSuggester_ = new AdapterUtils.AxisSuggester_Null();
|
||||
this.YAxisSuggester_ = new AdapterUtils.AxisSuggester_Null();
|
||||
this.counter_ = new AdapterUtils.Counter_Null();
|
||||
this.xDataGetter_ = new AdapterUtils.DataGetter_Null();
|
||||
this.yDataGetter_ = new AdapterUtils.DataGetter_Null();
|
||||
return;
|
||||
}
|
||||
else if (abscissaData is IList)
|
||||
{
|
||||
this.XAxisSuggester_ = new AdapterUtils.AxisSuggester_IList((IList)abscissaData);
|
||||
this.YAxisSuggester_ = new AdapterUtils.AxisSuggester_Auto((IList)abscissaData);
|
||||
this.counter_ = new AdapterUtils.Counter_IList((IList)abscissaData);
|
||||
if (abscissaData is Double[])
|
||||
this.xDataGetter_ = new AdapterUtils.DataGetter_DoublesArray((Double[])abscissaData);
|
||||
else
|
||||
this.xDataGetter_ = new AdapterUtils.DataGetter_IList((IList)abscissaData);
|
||||
|
||||
this.yDataGetter_ = new AdapterUtils.DataGetter_Count();
|
||||
return;
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
// unknown.
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
// unknown
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
else if (dataSource is IList && dataMember == null)
|
||||
{
|
||||
if (dataSource is DataView)
|
||||
{
|
||||
DataView data = (DataView)dataSource;
|
||||
|
||||
this.counter_ = new AdapterUtils.Counter_DataView(data);
|
||||
this.xDataGetter_ = new AdapterUtils.DataGetter_DataView(data, (string)abscissaData);
|
||||
this.yDataGetter_ = new AdapterUtils.DataGetter_DataView(data, (string)ordinateData);
|
||||
this.XAxisSuggester_ = new AdapterUtils.AxisSuggester_DataView(data, (string)abscissaData);
|
||||
this.YAxisSuggester_ = new AdapterUtils.AxisSuggester_DataView(data, (string)ordinateData);
|
||||
return;
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
this.YAxisSuggester_ = new AdapterUtils.AxisSuggester_IList((IList)dataSource);
|
||||
this.counter_ = new AdapterUtils.Counter_IList((IList)dataSource);
|
||||
this.yDataGetter_ = new AdapterUtils.DataGetter_IList((IList)dataSource);
|
||||
|
||||
if ((ordinateData == null) && (abscissaData == null))
|
||||
{
|
||||
this.XAxisSuggester_ = new AdapterUtils.AxisSuggester_Auto((IList)dataSource);
|
||||
this.xDataGetter_ = new AdapterUtils.DataGetter_Count();
|
||||
return;
|
||||
}
|
||||
|
||||
else if ((ordinateData == null) && (abscissaData is StartStep))
|
||||
{
|
||||
this.XAxisSuggester_ = new AdapterUtils.AxisSuggester_StartStep((StartStep)abscissaData, (IList)ordinateData);
|
||||
this.xDataGetter_ = new AdapterUtils.DataGetter_StartStep((StartStep)abscissaData);
|
||||
return;
|
||||
}
|
||||
|
||||
else if ((ordinateData == null) && (abscissaData is IList))
|
||||
{
|
||||
this.XAxisSuggester_ = new AdapterUtils.AxisSuggester_IList((IList)abscissaData);
|
||||
this.xDataGetter_ = new AdapterUtils.DataGetter_IList((IList)abscissaData);
|
||||
return;
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
// unknown.
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
else if ( ((dataSource is DataTable) && (dataMember == null)) || (dataSource is DataSet) )
|
||||
{
|
||||
DataRowCollection rows = null;
|
||||
|
||||
if (dataSource is DataSet)
|
||||
{
|
||||
if (dataMember != null)
|
||||
{
|
||||
rows = ((DataTable)((DataSet)dataSource).Tables[dataMember]).Rows;
|
||||
}
|
||||
else
|
||||
{
|
||||
rows = ((DataTable)((DataSet)dataSource).Tables[0]).Rows;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
rows = ((DataTable)dataSource).Rows;
|
||||
}
|
||||
|
||||
this.yDataGetter_ = new AdapterUtils.DataGetter_Rows(rows, (string)ordinateData);
|
||||
this.YAxisSuggester_ = new AdapterUtils.AxisSuggester_Rows(rows, (string)ordinateData);
|
||||
this.counter_ = new AdapterUtils.Counter_Rows(rows);
|
||||
|
||||
if ((abscissaData is string) && (ordinateData is string))
|
||||
{
|
||||
this.XAxisSuggester_ = new AdapterUtils.AxisSuggester_Rows(rows, (string)abscissaData);
|
||||
this.xDataGetter_ = new AdapterUtils.DataGetter_Rows(rows, (string)abscissaData);
|
||||
return;
|
||||
}
|
||||
else if ((abscissaData == null) && (ordinateData is string))
|
||||
{
|
||||
this.XAxisSuggester_ = new AdapterUtils.AxisSuggester_RowAuto(rows);
|
||||
this.xDataGetter_ = new AdapterUtils.DataGetter_Count();
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
// unknown.
|
||||
}
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
// unknown.
|
||||
}
|
||||
|
||||
throw new NPlotException( "Do not know how to interpret data provided to chart." );
|
||||
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Returns the number of points.
|
||||
/// </summary>
|
||||
public int Count
|
||||
{
|
||||
get
|
||||
{
|
||||
return counter_.Count;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Returns the ith point.
|
||||
/// </summary>
|
||||
public PointD this[int i]
|
||||
{
|
||||
get
|
||||
{
|
||||
return new PointD( this.xDataGetter_.Get(i), this.yDataGetter_.Get(i) );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Returns an x-axis that is suitable for drawing the data.
|
||||
/// </summary>
|
||||
/// <returns>A suitable x-axis.</returns>
|
||||
public Axis SuggestXAxis()
|
||||
{
|
||||
return this.XAxisSuggester_.Get();
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Returns a y-axis that is suitable for drawing the data.
|
||||
/// </summary>
|
||||
/// <returns>A suitable y-axis.</returns>
|
||||
public Axis SuggestYAxis()
|
||||
{
|
||||
Axis a = this.YAxisSuggester_.Get();
|
||||
// TODO make 0.08 a parameter.
|
||||
a.IncreaseRange( 0.08 );
|
||||
return a;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Writes data out as text.
|
||||
/// </summary>
|
||||
/// <param name="sb">StringBuilder to write to.</param>
|
||||
/// <param name="region">Only write out data in this region if onlyInRegion is true.</param>
|
||||
/// <param name="onlyInRegion">If true, only data in region is written, else all data is written.</param>
|
||||
public void WriteData( System.Text.StringBuilder sb, RectangleD region, bool onlyInRegion )
|
||||
{
|
||||
for (int i=0; i<this.Count; ++i)
|
||||
{
|
||||
if ( !(onlyInRegion &&
|
||||
(this[i].X >= region.X && this[i].X <= region.X+region.Width) &&
|
||||
(this[i].Y >= region.Y && this[i].Y <= region.Y+region.Height)) )
|
||||
continue;
|
||||
|
||||
sb.Append( this[i].ToString() );
|
||||
sb.Append( "\r\n" );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
// ******** experimental ********
|
||||
/*
|
||||
using System;
|
||||
|
||||
namespace NPlot
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// This class will be analogous to SequenceAdapter for 2D charting.
|
||||
/// Don't use it initially - offer only one method of getting in data
|
||||
/// for similicity.
|
||||
/// TODO. Not implemented.
|
||||
/// </summary>
|
||||
public class SequenceAdapter3D
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// Constructor. TODO.
|
||||
/// </summary>
|
||||
public SequenceAdapter3D()
|
||||
{
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
*/
|
|
@ -0,0 +1,111 @@
|
|||
/*
|
||||
NPlot - A charting library for .NET
|
||||
|
||||
StartStep.cs
|
||||
Copyright (C) 2004
|
||||
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;
|
||||
|
||||
namespace NPlot
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// Encapsulates a Start and Step value. This is useful for specifying a regularly spaced set of
|
||||
/// abscissa values.
|
||||
/// </summary>
|
||||
public class StartStep
|
||||
{
|
||||
|
||||
private double start_;
|
||||
private double step_;
|
||||
|
||||
/// <summary>
|
||||
/// Constructor
|
||||
/// </summary>
|
||||
/// <param name="start">the first value of the set of points specified by this object.</param>
|
||||
/// <param name="step">the step that specifies the separation between successive points.</param>
|
||||
public StartStep( double start, double step )
|
||||
{
|
||||
this.Start = start;
|
||||
this.Step = step;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// The first value of the set of points specified by this object.
|
||||
/// </summary>
|
||||
public double Start
|
||||
{
|
||||
get
|
||||
{
|
||||
return start_;
|
||||
}
|
||||
set
|
||||
{
|
||||
this.start_ = value;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// The step that specifies the separation between successive points.
|
||||
/// </summary>
|
||||
public double Step
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.step_;
|
||||
}
|
||||
set
|
||||
{
|
||||
this.step_ = value;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,149 @@
|
|||
/*
|
||||
NPlot - A charting library for .NET
|
||||
|
||||
StepGradient.cs
|
||||
Copyright (C) 2004
|
||||
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>
|
||||
/// Class for creating a rainbow legend.
|
||||
/// </summary>
|
||||
public class StepGradient : IGradient
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// Types of step gradient defined.
|
||||
/// </summary>
|
||||
public enum Type
|
||||
{
|
||||
/// <summary>
|
||||
/// Rainbow gradient type (colors of the rainbow)
|
||||
/// </summary>
|
||||
Rainbow,
|
||||
|
||||
/// <summary>
|
||||
/// RGB gradient type (red, green blud).
|
||||
/// </summary>
|
||||
RGB
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the type of step gradient.
|
||||
/// </summary>
|
||||
public Type StepType
|
||||
{
|
||||
get
|
||||
{
|
||||
return stepType_;
|
||||
}
|
||||
set
|
||||
{
|
||||
stepType_ = value;
|
||||
}
|
||||
}
|
||||
Type stepType_ = Type.RGB;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Default Constructor
|
||||
/// </summary>
|
||||
public StepGradient()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Constructor
|
||||
/// </summary>
|
||||
/// <param name="stepType">type of gradient</param>
|
||||
public StepGradient( Type stepType )
|
||||
{
|
||||
stepType_ = stepType;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a color corresponding to a number between 0.0 and 1.0 inclusive. The color will
|
||||
/// be a linear interpolation of the min and max colors.
|
||||
/// </summary>
|
||||
/// <param name="prop">the number to get corresponding color for (between 0.0 and 1.0)</param>
|
||||
/// <returns>The color corresponding to the supplied number.</returns>
|
||||
public Color GetColor( double prop )
|
||||
{
|
||||
switch (stepType_)
|
||||
{
|
||||
case Type.RGB:
|
||||
{
|
||||
if (prop < 1.0/3.0) return Color.Red;
|
||||
if (prop < 2.0/3.0) return Color.Green;
|
||||
return Color.Blue;
|
||||
}
|
||||
case Type.Rainbow:
|
||||
{
|
||||
if (prop < 0.125) return Color.Red;
|
||||
if (prop < 0.25) return Color.Orange;
|
||||
if (prop < 0.375) return Color.Yellow;
|
||||
if (prop < 0.5) return Color.Green;
|
||||
if (prop < 0.625) return Color.Cyan;
|
||||
if (prop < 0.75) return Color.Blue;
|
||||
if (prop < 0.825) return Color.Purple;
|
||||
return Color.Pink;
|
||||
}
|
||||
default:
|
||||
{
|
||||
return Color.Black;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,347 @@
|
|||
/*
|
||||
NPlot - A charting library for .NET
|
||||
|
||||
StepPlot.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>
|
||||
/// Encapsulates functionality for plotting data as a stepped line.
|
||||
/// </summary>
|
||||
public class StepPlot : BaseSequencePlot, IPlot, ISequencePlot
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// Constructor.
|
||||
/// </summary>
|
||||
public StepPlot()
|
||||
{
|
||||
this.Center = false;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Draws the step plot on a GDI+ surface against the provided x and y axes.
|
||||
/// </summary>
|
||||
/// <param name="g">The GDI+ 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 virtual void Draw( Graphics g, PhysicalAxis xAxis, PhysicalAxis yAxis )
|
||||
{
|
||||
|
||||
SequenceAdapter data =
|
||||
new SequenceAdapter( this.DataSource, this.DataMember, this.OrdinateData, this.AbscissaData );
|
||||
|
||||
double leftCutoff = xAxis.PhysicalToWorld(xAxis.PhysicalMin, false);
|
||||
double rightCutoff = xAxis.PhysicalToWorld(xAxis.PhysicalMax, false);
|
||||
|
||||
for (int i=0; i<data.Count; ++i)
|
||||
{
|
||||
PointD p1 = data[i];
|
||||
if (Double.IsNaN(p1.X) || Double.IsNaN(p1.Y))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
PointD p2;
|
||||
PointD p3;
|
||||
if (i+1 != data.Count)
|
||||
{
|
||||
p2 = data[i+1];
|
||||
if (Double.IsNaN(p2.X) || Double.IsNaN(p2.Y))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
p2.Y = p1.Y;
|
||||
p3 = data[i+1];
|
||||
}
|
||||
else
|
||||
{
|
||||
p2 = data[i-1];
|
||||
double offset = p1.X - p2.X;
|
||||
p2.X = p1.X + offset;
|
||||
p2.Y = p1.Y;
|
||||
p3 = p2;
|
||||
}
|
||||
|
||||
if ( this.center_ )
|
||||
{
|
||||
double offset = ( p2.X - p1.X ) / 2.0f;
|
||||
p1.X -= offset;
|
||||
p2.X -= offset;
|
||||
p3.X -= offset;
|
||||
}
|
||||
|
||||
PointF xPos1 = xAxis.WorldToPhysical( p1.X, false );
|
||||
PointF yPos1 = yAxis.WorldToPhysical( p1.Y, false );
|
||||
PointF xPos2 = xAxis.WorldToPhysical( p2.X, false );
|
||||
PointF yPos2 = yAxis.WorldToPhysical( p2.Y, false );
|
||||
PointF xPos3 = xAxis.WorldToPhysical( p3.X, false );
|
||||
PointF yPos3 = yAxis.WorldToPhysical( p3.Y, false );
|
||||
|
||||
// do horizontal clipping here, to speed up
|
||||
if ((p1.X < leftCutoff || p1.X > rightCutoff ) &&
|
||||
(p2.X < leftCutoff || p2.X > rightCutoff ) &&
|
||||
(p3.X < leftCutoff || p3.X > rightCutoff ) )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!this.hideHorizontalSegments_)
|
||||
{
|
||||
if (scale_ != 1.0f)
|
||||
{
|
||||
float middle = (xPos2.X + xPos1.X) / 2.0f;
|
||||
float width = xPos2.X - xPos1.X;
|
||||
width *= this.scale_;
|
||||
g.DrawLine( Pen, (int)(middle-width/2.0f), yPos1.Y, (int)(middle+width/2.0f), yPos2.Y );
|
||||
}
|
||||
else
|
||||
{
|
||||
g.DrawLine( Pen, xPos1.X, yPos1.Y, xPos2.X, yPos2.Y );
|
||||
}
|
||||
}
|
||||
|
||||
if (!this.hideVerticalSegments_)
|
||||
{
|
||||
g.DrawLine( Pen, xPos2.X, yPos2.Y, xPos3.X, yPos3.Y );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Returns an X-axis suitable for use by this plot. The axis will be one that is just long
|
||||
/// enough to show all data.
|
||||
/// </summary>
|
||||
/// <returns>X-axis suitable for use by this plot.</returns>
|
||||
public Axis SuggestXAxis()
|
||||
{
|
||||
SequenceAdapter data =
|
||||
new SequenceAdapter( this.DataSource, this.DataMember, this.OrdinateData, this.AbscissaData );
|
||||
|
||||
if (data.Count < 2)
|
||||
{
|
||||
return data.SuggestXAxis();
|
||||
}
|
||||
|
||||
// else
|
||||
|
||||
Axis a = data.SuggestXAxis();
|
||||
|
||||
PointD p1 = data[0];
|
||||
PointD p2 = data[1];
|
||||
PointD p3 = data[data.Count-2];
|
||||
PointD p4 = data[data.Count-1];
|
||||
|
||||
double offset1;
|
||||
double offset2;
|
||||
|
||||
if (!center_)
|
||||
{
|
||||
offset1 = 0.0f;
|
||||
offset2 = p4.X - p3.X;
|
||||
}
|
||||
else
|
||||
{
|
||||
offset1 = (p2.X - p1.X)/2.0f;
|
||||
offset2 = (p4.X - p3.X)/2.0f;
|
||||
}
|
||||
|
||||
a.WorldMin -= offset1;
|
||||
a.WorldMax += offset2;
|
||||
|
||||
return a;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Returns an Y-axis suitable for use by this plot. The axis will be one that is just long
|
||||
/// enough to show all data.
|
||||
/// </summary>
|
||||
/// <returns>Y-axis suitable for use by this plot.</returns>
|
||||
public Axis SuggestYAxis()
|
||||
{
|
||||
SequenceAdapter data =
|
||||
new SequenceAdapter( this.DataSource, this.DataMember, this.OrdinateData, this.AbscissaData );
|
||||
|
||||
return data.SuggestYAxis();
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets whether or not steps should be centered. If true, steps will be centered on the
|
||||
/// X abscissa values. If false, the step corresponding to a given x-value will be drawn between
|
||||
/// this x-value and the next x-value at the current y-height.
|
||||
/// </summary>
|
||||
public bool Center
|
||||
{
|
||||
set
|
||||
{
|
||||
center_ = value;
|
||||
}
|
||||
get
|
||||
{
|
||||
return center_;
|
||||
}
|
||||
}
|
||||
private bool center_;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Draws a representation of this plot in the legend.
|
||||
/// </summary>
|
||||
/// <param name="g">The graphics surface on which to draw.</param>
|
||||
/// <param name="startEnd">A rectangle specifying the bounds of the area in the legend set aside for drawing.</param>
|
||||
public virtual void DrawInLegend(Graphics g, Rectangle startEnd)
|
||||
{
|
||||
g.DrawLine(pen_, startEnd.Left, (startEnd.Top + startEnd.Bottom) / 2,
|
||||
startEnd.Right, (startEnd.Top + startEnd.Bottom) / 2);
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// The pen used to draw the plot
|
||||
/// </summary>
|
||||
public System.Drawing.Pen Pen
|
||||
{
|
||||
get
|
||||
{
|
||||
return pen_;
|
||||
}
|
||||
set
|
||||
{
|
||||
pen_ = value;
|
||||
}
|
||||
}
|
||||
private System.Drawing.Pen pen_ = new Pen(Color.Black);
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// The color of the pen used to draw lines in this plot.
|
||||
/// </summary>
|
||||
public System.Drawing.Color Color
|
||||
{
|
||||
set
|
||||
{
|
||||
if (pen_ != null)
|
||||
{
|
||||
pen_.Color = value;
|
||||
}
|
||||
else
|
||||
{
|
||||
pen_ = new Pen(value);
|
||||
}
|
||||
}
|
||||
get
|
||||
{
|
||||
return pen_.Color;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// If true, then vertical lines are hidden.
|
||||
/// </summary>
|
||||
public bool HideVerticalSegments
|
||||
{
|
||||
get
|
||||
{
|
||||
return hideVerticalSegments_;
|
||||
}
|
||||
set
|
||||
{
|
||||
hideVerticalSegments_ = value;
|
||||
}
|
||||
}
|
||||
bool hideVerticalSegments_ = false;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// If true, then vertical lines are hidden.
|
||||
/// </summary>
|
||||
public bool HideHorizontalSegments
|
||||
{
|
||||
get
|
||||
{
|
||||
return hideHorizontalSegments_;
|
||||
}
|
||||
set
|
||||
{
|
||||
hideHorizontalSegments_ = value;
|
||||
}
|
||||
}
|
||||
bool hideHorizontalSegments_ = false;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// The horizontal line length is multiplied by this amount. Default
|
||||
/// corresponds to a value of 1.0.
|
||||
/// </summary>
|
||||
public float WidthScale
|
||||
{
|
||||
get
|
||||
{
|
||||
return scale_;
|
||||
}
|
||||
set
|
||||
{
|
||||
scale_ = value;
|
||||
}
|
||||
}
|
||||
private float scale_ = 1.0f;
|
||||
|
||||
}
|
||||
}
|
Двоичный файл не отображается.
|
@ -0,0 +1,178 @@
|
|||
/*
|
||||
NPlot - A charting library for .NET
|
||||
|
||||
TextItem.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>
|
||||
/// This class implements drawing text against two physical axes.
|
||||
/// </summary>
|
||||
public class TextItem : IDrawable
|
||||
{
|
||||
private void Init()
|
||||
{
|
||||
FontFamily fontFamily = new FontFamily("Arial");
|
||||
font_ = new Font(fontFamily, 10, FontStyle.Regular, GraphicsUnit.Pixel);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructor
|
||||
/// </summary>
|
||||
/// <param name="position">The position the text starts.</param>
|
||||
/// <param name="text">The text.</param>
|
||||
public TextItem( PointD position, string text )
|
||||
{
|
||||
start_ = position;
|
||||
text_ = text;
|
||||
Init();
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Text associated.
|
||||
/// </summary>
|
||||
public string Text
|
||||
{
|
||||
get
|
||||
{
|
||||
return text_;
|
||||
}
|
||||
set
|
||||
{
|
||||
text_ = value;
|
||||
}
|
||||
}
|
||||
private string text_ = "";
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// The starting point for the text.
|
||||
/// </summary>
|
||||
public PointD Start
|
||||
{
|
||||
get
|
||||
{
|
||||
return start_;
|
||||
}
|
||||
set
|
||||
{
|
||||
start_ = value;
|
||||
}
|
||||
}
|
||||
private PointD start_;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Draws the text 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 )
|
||||
{
|
||||
Point startPoint = new Point(
|
||||
(int)xAxis.WorldToPhysical( start_.X, true ).X,
|
||||
(int)yAxis.WorldToPhysical( start_.Y, true ).Y );
|
||||
|
||||
g.DrawString(text_, font_, textBrush_,(int)startPoint.X,(int)startPoint.Y);
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// The brush used to draw the text.
|
||||
/// </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 font used to draw the text associated with the arrow.
|
||||
/// </summary>
|
||||
public Font TextFont
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.font_;
|
||||
}
|
||||
set
|
||||
{
|
||||
this.font_ = value;
|
||||
}
|
||||
}
|
||||
|
||||
private Brush textBrush_ = new SolidBrush( Color.Black );
|
||||
private Pen pen_ = new Pen( Color.Black );
|
||||
private Font font_;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,713 @@
|
|||
/*
|
||||
NPlot - A charting library for .NET
|
||||
|
||||
TradingDateTimeAxis.cs
|
||||
Copyright (C) 2006
|
||||
Pawel Konieczny
|
||||
|
||||
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.Collections;
|
||||
|
||||
|
||||
namespace NPlot
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// Provides a DateTime axis that removes non-trading days.
|
||||
/// </summary>
|
||||
public class TradingDateTimeAxis : DateTimeAxis
|
||||
{
|
||||
// we keep shadow "virtual" copies of WorldMin/Max for speed
|
||||
// which are already remapped, so it is essential that changes
|
||||
// to WorldMin/Max are captured here
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// The axis world min value.
|
||||
/// </summary>
|
||||
public override double WorldMin
|
||||
{
|
||||
get
|
||||
{
|
||||
return base.WorldMin;
|
||||
}
|
||||
set
|
||||
{
|
||||
base.WorldMin = value;
|
||||
virtualWorldMin_ = SparseWorldRemap(value);
|
||||
}
|
||||
}
|
||||
private double virtualWorldMin_ = double.NaN;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// The axis world max value.
|
||||
/// </summary>
|
||||
public override double WorldMax
|
||||
{
|
||||
get
|
||||
{
|
||||
return base.WorldMax;
|
||||
}
|
||||
set
|
||||
{
|
||||
base.WorldMax = value;
|
||||
virtualWorldMax_ = SparseWorldRemap(value);
|
||||
}
|
||||
}
|
||||
private double virtualWorldMax_ = double.NaN;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Optional time at which trading begins.
|
||||
/// All data points earlied than that (same day) will be collapsed.
|
||||
/// </summary>
|
||||
public virtual TimeSpan StartTradingTime
|
||||
{
|
||||
get
|
||||
{
|
||||
return new TimeSpan(startTradingTime_);
|
||||
}
|
||||
set
|
||||
{
|
||||
startTradingTime_ = value.Ticks;
|
||||
tradingTimeSpan_ = endTradingTime_ - startTradingTime_;
|
||||
}
|
||||
}
|
||||
private long startTradingTime_;
|
||||
|
||||
/// <summary>
|
||||
/// Optional time at which trading ends.
|
||||
/// All data points later than that (same day) will be collapsed.
|
||||
/// </summary>
|
||||
public virtual TimeSpan EndTradingTime
|
||||
{
|
||||
get
|
||||
{
|
||||
return new TimeSpan(endTradingTime_);
|
||||
}
|
||||
set
|
||||
{
|
||||
endTradingTime_ = value.Ticks;
|
||||
tradingTimeSpan_ = endTradingTime_ - startTradingTime_;
|
||||
}
|
||||
}
|
||||
private long endTradingTime_;
|
||||
|
||||
private long tradingTimeSpan_;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Get whether or not this axis is linear.
|
||||
/// </summary>
|
||||
public override bool IsLinear
|
||||
{
|
||||
get
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Constructor
|
||||
/// </summary>
|
||||
public TradingDateTimeAxis() : base()
|
||||
{
|
||||
Init();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Copy Constructor
|
||||
/// </summary>
|
||||
/// <param name="a">construct a TradingDateTimeAxis based on this provided axis.</param>
|
||||
public TradingDateTimeAxis(Axis a) : base(a)
|
||||
{
|
||||
Init();
|
||||
if (a is TradingDateTimeAxis)
|
||||
DoClone((TradingDateTimeAxis)a, this);
|
||||
else if (a is DateTimeAxis)
|
||||
DoClone((DateTimeAxis)a, this);
|
||||
else
|
||||
{
|
||||
DoClone(a, this);
|
||||
this.NumberFormat = null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Helper function for constructors.
|
||||
/// </summary>
|
||||
private void Init()
|
||||
{
|
||||
startTradingTime_ = 0;
|
||||
endTradingTime_ = TimeSpan.TicksPerDay;
|
||||
tradingTimeSpan_ = endTradingTime_ - startTradingTime_;
|
||||
virtualWorldMin_ = SparseWorldRemap(WorldMin);
|
||||
virtualWorldMax_ = SparseWorldRemap(WorldMax);
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Deep copy of DateTimeAxis.
|
||||
/// </summary>
|
||||
/// <returns>A copy of the DateTimeAxis Class.</returns>
|
||||
public override object Clone()
|
||||
{
|
||||
TradingDateTimeAxis a = new TradingDateTimeAxis();
|
||||
// ensure that this isn't being called on a derived type. If it is, then oh no!
|
||||
if (this.GetType() != a.GetType())
|
||||
{
|
||||
throw new NPlotException( "Clone not defined in derived type. Help!" );
|
||||
}
|
||||
DoClone( this, a );
|
||||
return a;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Helper method for Clone.
|
||||
/// </summary>
|
||||
/// <param name="a">The cloned target object.</param>
|
||||
/// <param name="b">The cloned source object.</param>
|
||||
protected static void DoClone(TradingDateTimeAxis b, TradingDateTimeAxis a)
|
||||
{
|
||||
DateTimeAxis.DoClone(b, a);
|
||||
a.startTradingTime_ = b.startTradingTime_;
|
||||
a.endTradingTime_ = b.endTradingTime_;
|
||||
a.tradingTimeSpan_ = b.tradingTimeSpan_;
|
||||
a.WorldMin = b.WorldMin;
|
||||
a.WorldMax = b.WorldMax;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// World to physical coordinate transform.
|
||||
/// </summary>
|
||||
/// <param name="coord">The coordinate value to transform.</param>
|
||||
/// <param name="physicalMin">The physical position corresponding to the world minimum of the axis.</param>
|
||||
/// <param name="physicalMax">The physical position corresponding to the world maximum of the axis.</param>
|
||||
/// <param name="clip">if false, then physical value may extend outside worldMin / worldMax. If true, the physical value returned will be clipped to physicalMin or physicalMax if it lies outside this range.</param>
|
||||
/// <returns>The transformed coordinates.</returns>
|
||||
/// <remarks>Not sure how much time is spent in this often called function. If it's lots, then
|
||||
/// worth optimizing (there is scope to do so).</remarks>
|
||||
public override PointF WorldToPhysical(
|
||||
double coord,
|
||||
PointF physicalMin,
|
||||
PointF physicalMax,
|
||||
bool clip)
|
||||
{
|
||||
|
||||
// (1) account for reversed axis. Could be tricky and move
|
||||
// this out, but would be a little messy.
|
||||
|
||||
PointF _physicalMin;
|
||||
PointF _physicalMax;
|
||||
|
||||
if (this.Reversed)
|
||||
{
|
||||
_physicalMin = physicalMax;
|
||||
_physicalMax = physicalMin;
|
||||
}
|
||||
else
|
||||
{
|
||||
_physicalMin = physicalMin;
|
||||
_physicalMax = physicalMax;
|
||||
}
|
||||
|
||||
|
||||
// (2) if want clipped value, return extrema if outside range.
|
||||
|
||||
if (clip)
|
||||
{
|
||||
if (WorldMin < WorldMax)
|
||||
{
|
||||
if (coord > WorldMax)
|
||||
{
|
||||
return _physicalMax;
|
||||
}
|
||||
if (coord < WorldMin)
|
||||
{
|
||||
return _physicalMin;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (coord < WorldMax)
|
||||
{
|
||||
return _physicalMax;
|
||||
}
|
||||
if (coord > WorldMin)
|
||||
{
|
||||
return _physicalMin;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// (3) we are inside range or don't want to clip.
|
||||
|
||||
coord = SparseWorldRemap(coord);
|
||||
double range = virtualWorldMax_ - virtualWorldMin_;
|
||||
double prop = (double)((coord - virtualWorldMin_) / range);
|
||||
//double range = WorldMax - WorldMin;
|
||||
//double prop = (double)((coord - WorldMin) / range);
|
||||
//if (range1 != range)
|
||||
// range1 = range;
|
||||
|
||||
// Force clipping at bounding box largeClip times that of real bounding box
|
||||
// anyway. This is effectively at infinity.
|
||||
const double largeClip = 100.0;
|
||||
if (prop > largeClip && clip)
|
||||
prop = largeClip;
|
||||
|
||||
if (prop < -largeClip && clip)
|
||||
prop = -largeClip;
|
||||
|
||||
if (range == 0)
|
||||
{
|
||||
if (coord >= virtualWorldMin_)
|
||||
prop = largeClip;
|
||||
|
||||
if (coord < virtualWorldMin_)
|
||||
prop = -largeClip;
|
||||
}
|
||||
|
||||
// calculate the physical coordinate.
|
||||
PointF offset = new PointF(
|
||||
(float)(prop * (_physicalMax.X - _physicalMin.X)),
|
||||
(float)(prop * (_physicalMax.Y - _physicalMin.Y)));
|
||||
|
||||
return new PointF(_physicalMin.X + offset.X, _physicalMin.Y + offset.Y);
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Transforms a physical coordinate to an axis world
|
||||
/// coordinate given the physical extremites of the axis.
|
||||
/// </summary>
|
||||
/// <param name="p">the point to convert</param>
|
||||
/// <param name="physicalMin">the physical minimum extremity of the axis</param>
|
||||
/// <param name="physicalMax">the physical maximum extremity of the axis</param>
|
||||
/// <param name="clip">whether or not to clip the world value to lie in the range of the axis if it is outside.</param>
|
||||
/// <returns></returns>
|
||||
public override double PhysicalToWorld(
|
||||
PointF p,
|
||||
PointF physicalMin,
|
||||
PointF physicalMax,
|
||||
bool clip)
|
||||
{
|
||||
// (1) account for reversed axis. Could be tricky and move
|
||||
// this out, but would be a little messy.
|
||||
|
||||
PointF _physicalMin;
|
||||
PointF _physicalMax;
|
||||
|
||||
if (this.Reversed)
|
||||
{
|
||||
_physicalMin = physicalMax;
|
||||
_physicalMax = physicalMin;
|
||||
}
|
||||
else
|
||||
{
|
||||
_physicalMin = physicalMin;
|
||||
_physicalMax = physicalMax;
|
||||
}
|
||||
|
||||
// normalised axis dir vector
|
||||
float axis_X = _physicalMax.X - _physicalMin.X;
|
||||
float axis_Y = _physicalMax.Y - _physicalMin.Y;
|
||||
float len = (float)Math.Sqrt(axis_X * axis_X + axis_Y * axis_Y);
|
||||
axis_X /= len;
|
||||
axis_Y /= len;
|
||||
|
||||
// point relative to axis physical minimum.
|
||||
PointF posRel = new PointF(p.X - _physicalMin.X, p.Y - _physicalMin.Y);
|
||||
|
||||
// dist of point projection on axis, normalised.
|
||||
float prop = (axis_X * posRel.X + axis_Y * posRel.Y) / len;
|
||||
|
||||
//double world = prop * (WorldMax - WorldMin) + WorldMin;
|
||||
double world = prop * (virtualWorldMax_ - virtualWorldMin_) + virtualWorldMin_;
|
||||
world = ReverseSparseWorldRemap(world);
|
||||
|
||||
// if want clipped value, return extrema if outside range.
|
||||
if (clip)
|
||||
{
|
||||
world = Math.Max(world, WorldMin);
|
||||
world = Math.Min(world, WorldMax);
|
||||
}
|
||||
|
||||
return world;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Remap a world coordinate into a "virtual" world, where non-trading dates and times are collapsed.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This code works under asumption that there are exactly 24*60*60 seconds in a day
|
||||
/// This is strictly speaking not correct but apparently .NET 2.0 does not count leap seconds.
|
||||
/// Luckilly, Ticks == 0 =~= 0001-01-01T00:00 =~= Monday
|
||||
/// First tried a version fully on floating point arithmetic,
|
||||
/// but failed hopelessly due to rounding errors.
|
||||
/// </remarks>
|
||||
/// <param name="coord">world coordinate to transform.</param>
|
||||
/// <returns>equivalent virtual world coordinate.</returns>
|
||||
protected double SparseWorldRemap(double coord)
|
||||
{
|
||||
long ticks = (long)coord;
|
||||
long whole_days = ticks / TimeSpan.TicksPerDay;
|
||||
long ticks_in_last_day = ticks % TimeSpan.TicksPerDay;
|
||||
long full_weeks = whole_days / 7;
|
||||
long days_in_last_week = whole_days % 7;
|
||||
if (days_in_last_week >= 5)
|
||||
{
|
||||
days_in_last_week = 5;
|
||||
ticks_in_last_day = 0;
|
||||
}
|
||||
if (ticks_in_last_day < startTradingTime_) ticks_in_last_day = startTradingTime_;
|
||||
else if (ticks_in_last_day > endTradingTime_) ticks_in_last_day = endTradingTime_;
|
||||
ticks_in_last_day -= startTradingTime_;
|
||||
|
||||
long whole_working_days = (full_weeks * 5 + days_in_last_week);
|
||||
long working_ticks = whole_working_days * tradingTimeSpan_;
|
||||
long new_ticks = working_ticks + ticks_in_last_day;
|
||||
return (double)new_ticks;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Remaps a "virtual" world coordinates back to true world coordinates.
|
||||
/// </summary>
|
||||
/// <param name="coord">virtual world coordinate to transform.</param>
|
||||
/// <returns>equivalent world coordinate.</returns>
|
||||
protected double ReverseSparseWorldRemap(double coord)
|
||||
{
|
||||
long ticks = (long)coord;
|
||||
//ticks += startTradingTime_;
|
||||
long ticks_in_last_day = ticks % tradingTimeSpan_;
|
||||
ticks /= tradingTimeSpan_;
|
||||
long full_weeks = ticks / 5;
|
||||
long week_part = ticks % 5;
|
||||
|
||||
long day_ticks = (full_weeks * 7 + week_part) * TimeSpan.TicksPerDay;
|
||||
return (double)(day_ticks + ticks_in_last_day + startTradingTime_);
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Adds a delta amount to the given world coordinate in such a way that
|
||||
/// all "sparse gaps" are skipped. In other words, the returned value is
|
||||
/// in delta distance from the given in the "virtual" world.
|
||||
/// </summary>
|
||||
/// <param name="coord">world coordinate to shift.</param>
|
||||
/// <param name="delta">shif amount in "virtual" units.</param>
|
||||
/// <returns></returns>
|
||||
public double SparseWorldAdd(double coord, double delta)
|
||||
{
|
||||
return ReverseSparseWorldRemap(SparseWorldRemap(coord) + delta);
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// World extent in virtual (sparse) units.
|
||||
/// </summary>
|
||||
public double SparseWorldLength
|
||||
{
|
||||
get
|
||||
{
|
||||
return SparseWorldRemap(WorldMax) - SparseWorldRemap(WorldMin);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Check whether the given coordinate falls within defined trading hours.
|
||||
/// </summary>
|
||||
/// <param name="coord">world coordinate in ticks to check.</param>
|
||||
/// <returns>true if in trading hours, false if in non-trading gap.</returns>
|
||||
public bool WithinTradingHours(double coord)
|
||||
{
|
||||
long ticks = (long)coord;
|
||||
long whole_days = ticks / TimeSpan.TicksPerDay;
|
||||
long ticks_in_last_day = ticks % TimeSpan.TicksPerDay;
|
||||
long days_in_last_week = whole_days % 7;
|
||||
if (days_in_last_week >= 5)
|
||||
return false;
|
||||
|
||||
if (ticks_in_last_day < startTradingTime_) return false;
|
||||
if (ticks_in_last_day >= endTradingTime_) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Check whether the given coordinate falls on trading days.
|
||||
/// </summary>
|
||||
/// <param name="coord">world coordinate in ticks to check.</param>
|
||||
/// <returns>true if on Mon - Fri.</returns>
|
||||
public bool OnTradingDays(double coord)
|
||||
{
|
||||
long ticks = (long)coord;
|
||||
long whole_days = ticks / TimeSpan.TicksPerDay;
|
||||
long days_in_last_week = whole_days % 7;
|
||||
return (days_in_last_week < 5);
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Determines the positions of all Large and Small ticks.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The method WorldTickPositions_FirstPass() from the base works just fine, except that it
|
||||
/// does not account for non-trading gaps in time, therefore, when less than two days are visible
|
||||
/// an own algorithm is used (to show intraday time). Otherwise the base class implementation is used
|
||||
/// but the output is corrected to remove ticks on non-trading days (Sat, Sun).
|
||||
/// </remarks>
|
||||
/// <param name="physicalMin">The physical position corresponding to the world minimum of the axis.</param>
|
||||
/// <param name="physicalMax">The physical position corresponding to the world maximum of the axis.</param>
|
||||
/// <param name="largeTickPositions">ArrayList containing the positions of the large ticks.</param>
|
||||
/// <param name="smallTickPositions">null</param>
|
||||
internal override void WorldTickPositions_FirstPass(
|
||||
Point physicalMin,
|
||||
Point physicalMax,
|
||||
out ArrayList largeTickPositions,
|
||||
out ArrayList smallTickPositions
|
||||
)
|
||||
{
|
||||
if (LargeTickStep != TimeSpan.Zero || SparseWorldLength > 2.0 * (double)tradingTimeSpan_) // utilise base class
|
||||
{
|
||||
ArrayList largeTickPositions_FirstPass;
|
||||
base.WorldTickPositions_FirstPass(physicalMin, physicalMax, out largeTickPositions_FirstPass, out smallTickPositions);
|
||||
|
||||
if (largeTickPositions_FirstPass.Count < 2)
|
||||
{
|
||||
// leave it alone, whatever that single tick may be (better something than nothing...)
|
||||
largeTickPositions = largeTickPositions_FirstPass;
|
||||
}
|
||||
else if ((double)largeTickPositions_FirstPass[1] - (double)largeTickPositions_FirstPass[0] > 27.0 * (double)TimeSpan.TicksPerDay)
|
||||
{
|
||||
// For distances between ticks in months or longer, just accept all ticks
|
||||
largeTickPositions = largeTickPositions_FirstPass;
|
||||
}
|
||||
else
|
||||
{
|
||||
// for daily ticks, ignore non-trading hours but obey (skip) non-trading days
|
||||
largeTickPositions = new ArrayList();
|
||||
foreach (object tick in largeTickPositions_FirstPass)
|
||||
{
|
||||
if (OnTradingDays((double)tick))
|
||||
largeTickPositions.Add(tick);
|
||||
}
|
||||
}
|
||||
}
|
||||
else // intraday ticks, own algorithm
|
||||
{
|
||||
smallTickPositions = null;
|
||||
largeTickPositions = new ArrayList();
|
||||
|
||||
TimeSpan timeLength = new TimeSpan((long)SparseWorldLength);
|
||||
DateTime worldMinDate = new DateTime( (long)this.WorldMin );
|
||||
DateTime worldMaxDate = new DateTime( (long)this.WorldMax );
|
||||
|
||||
DateTime currentTickDate;
|
||||
long skip; // in time ticks
|
||||
|
||||
// The following if-else flow establishes currentTickDate to the beginning of series
|
||||
// and skip to the optimal distance between ticks
|
||||
|
||||
// if less than 10 minutes, then large ticks on second spacings.
|
||||
|
||||
if ( timeLength < new TimeSpan(0,0,10,0,0) )
|
||||
{
|
||||
this.LargeTickLabelType_ = LargeTickLabelType.hourMinuteSeconds;
|
||||
|
||||
int secondsSkip;
|
||||
|
||||
if (timeLength < new TimeSpan( 0,0,0,10,0 ) )
|
||||
secondsSkip = 1;
|
||||
else if ( timeLength < new TimeSpan(0,0,0,20,0) )
|
||||
secondsSkip = 2;
|
||||
else if ( timeLength < new TimeSpan(0,0,0,50,0) )
|
||||
secondsSkip = 5;
|
||||
else if ( timeLength < new TimeSpan(0,0,2,30,0) )
|
||||
secondsSkip = 15;
|
||||
else
|
||||
secondsSkip = 30;
|
||||
|
||||
int second = worldMinDate.Second;
|
||||
second -= second % secondsSkip;
|
||||
|
||||
currentTickDate = new DateTime(
|
||||
worldMinDate.Year,
|
||||
worldMinDate.Month,
|
||||
worldMinDate.Day,
|
||||
worldMinDate.Hour,
|
||||
worldMinDate.Minute,
|
||||
second,0 );
|
||||
|
||||
skip = secondsSkip * TimeSpan.TicksPerSecond;
|
||||
}
|
||||
|
||||
// Less than 2 hours, then large ticks on minute spacings.
|
||||
|
||||
else if ( timeLength < new TimeSpan(0,2,0,0,0) )
|
||||
{
|
||||
this.LargeTickLabelType_ = LargeTickLabelType.hourMinute;
|
||||
|
||||
int minuteSkip;
|
||||
|
||||
if ( timeLength < new TimeSpan(0,0,10,0,0) )
|
||||
minuteSkip = 1;
|
||||
else if ( timeLength < new TimeSpan(0,0,20,0,0) )
|
||||
minuteSkip = 2;
|
||||
else if ( timeLength < new TimeSpan(0,0,50,0,0) )
|
||||
minuteSkip = 5;
|
||||
else if ( timeLength < new TimeSpan(0,2,30,0,0) )
|
||||
minuteSkip = 15;
|
||||
else //( timeLength < new TimeSpan( 0,5,0,0,0) )
|
||||
minuteSkip = 30;
|
||||
|
||||
int minute = worldMinDate.Minute;
|
||||
minute -= minute % minuteSkip;
|
||||
|
||||
currentTickDate = new DateTime(
|
||||
worldMinDate.Year,
|
||||
worldMinDate.Month,
|
||||
worldMinDate.Day,
|
||||
worldMinDate.Hour,
|
||||
minute,0,0 );
|
||||
|
||||
skip = minuteSkip * TimeSpan.TicksPerMinute;
|
||||
}
|
||||
|
||||
// Else large ticks on hour spacings.
|
||||
|
||||
else
|
||||
{
|
||||
this.LargeTickLabelType_ = LargeTickLabelType.hourMinute;
|
||||
|
||||
int hourSkip;
|
||||
if (timeLength < new TimeSpan(0, 10, 0, 0, 0))
|
||||
hourSkip = 1;
|
||||
else if (timeLength < new TimeSpan(0, 20, 0, 0, 0))
|
||||
hourSkip = 2;
|
||||
else
|
||||
hourSkip = 6;
|
||||
|
||||
|
||||
int hour = worldMinDate.Hour;
|
||||
hour -= hour % hourSkip;
|
||||
|
||||
currentTickDate = new DateTime(
|
||||
worldMinDate.Year,
|
||||
worldMinDate.Month,
|
||||
worldMinDate.Day,
|
||||
hour, 0, 0, 0);
|
||||
|
||||
skip = hourSkip * TimeSpan.TicksPerHour;
|
||||
}
|
||||
|
||||
|
||||
// place ticks
|
||||
|
||||
while (currentTickDate < worldMaxDate)
|
||||
{
|
||||
double world = (double)currentTickDate.Ticks;
|
||||
|
||||
if (!WithinTradingHours(world))
|
||||
{
|
||||
// add gap boundary instead
|
||||
world = ReverseSparseWorldRemap(SparseWorldRemap(world)); // moves forward
|
||||
long gap = (long)world;
|
||||
gap -= gap % skip;
|
||||
currentTickDate = new DateTime(gap);
|
||||
}
|
||||
|
||||
if (world >= this.WorldMin && world <= this.WorldMax)
|
||||
{
|
||||
largeTickPositions.Add(world);
|
||||
}
|
||||
|
||||
currentTickDate = currentTickDate.AddTicks(skip);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Get an appropriate label name, given the DateTime of a label
|
||||
/// </summary>
|
||||
/// <param name="tickDate">the DateTime to get the label name for</param>
|
||||
/// <returns>A label name appropriate to the supplied DateTime.</returns>
|
||||
protected override string LargeTickLabel(DateTime tickDate)
|
||||
{
|
||||
string label;
|
||||
|
||||
if ( this.NumberFormat == null
|
||||
&& (LargeTickLabelType_ == LargeTickLabelType.hourMinute ||
|
||||
LargeTickLabelType_ == LargeTickLabelType.hourMinuteSeconds)
|
||||
&& tickDate.TimeOfDay == StartTradingTime)
|
||||
{
|
||||
// in such case always show the day date
|
||||
label = (tickDate.Day).ToString();
|
||||
label += " ";
|
||||
label += tickDate.ToString("MMM");
|
||||
}
|
||||
else
|
||||
{
|
||||
label = base.LargeTickLabel(tickDate);
|
||||
}
|
||||
return label;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,190 @@
|
|||
/*
|
||||
NPlot - A charting library for .NET
|
||||
|
||||
Transform2D.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>
|
||||
/// Encapsulates functionality for transforming world to physical coordinates optimally.
|
||||
/// </summary>
|
||||
/// <remarks>The existence of the whole ITransform2D thing might need revising. Not convinced it's the best way.</remarks>
|
||||
public class Transform2D
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// Constructs the optimal ITransform2D object for the supplied x and y axes.
|
||||
/// </summary>
|
||||
/// <param name="xAxis">The xAxis to use for the world to physical transform.</param>
|
||||
/// <param name="yAxis">The yAxis to use for the world to physical transform.</param>
|
||||
/// <returns>An ITransform2D derived object for converting from world to physical coordinates.</returns>
|
||||
public static ITransform2D GetTransformer( PhysicalAxis xAxis, PhysicalAxis yAxis )
|
||||
{
|
||||
ITransform2D ret = null;
|
||||
|
||||
// if (xAxis.Axis.IsLinear && yAxis.Axis.IsLinear && !xAxis.Axis.Reversed && !yAxis.Axis.Reversed)
|
||||
// ret = new FastTransform2D( xAxis, yAxis );
|
||||
// else
|
||||
// ret = new DefaultTransform2D( xAxis, yAxis );
|
||||
|
||||
ret = new DefaultTransform2D( xAxis, yAxis );
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// This class does world -> physical transforms for the general case
|
||||
/// </summary>
|
||||
public class DefaultTransform2D : ITransform2D
|
||||
{
|
||||
private PhysicalAxis xAxis_;
|
||||
private PhysicalAxis yAxis_;
|
||||
|
||||
/// <summary>
|
||||
/// Constructor
|
||||
/// </summary>
|
||||
/// <param name="xAxis">The x-axis to use for transforms</param>
|
||||
/// <param name="yAxis">The y-axis to use for transforms</param>
|
||||
public DefaultTransform2D( PhysicalAxis xAxis, PhysicalAxis yAxis )
|
||||
{
|
||||
xAxis_ = xAxis;
|
||||
yAxis_ = yAxis;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Transforms the given world point to physical coordinates
|
||||
/// </summary>
|
||||
/// <param name="x">x coordinate of world point to transform.</param>
|
||||
/// <param name="y">y coordinate of world point to transform.</param>
|
||||
/// <returns>the corresponding physical point.</returns>
|
||||
public PointF Transform( double x, double y )
|
||||
{
|
||||
return new PointF(
|
||||
xAxis_.WorldToPhysical( x, false ).X,
|
||||
yAxis_.WorldToPhysical( y, false ).Y );
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Transforms the given world point to physical coordinates
|
||||
/// </summary>
|
||||
/// <param name="worldPoint">the world point to transform</param>
|
||||
/// <returns>the corresponding physical point</returns>
|
||||
public PointF Transform( PointD worldPoint )
|
||||
{
|
||||
return new PointF(
|
||||
xAxis_.WorldToPhysical( worldPoint.X, false ).X,
|
||||
yAxis_.WorldToPhysical( worldPoint.Y, false ).Y );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// This class does highly efficient world->physical and physical->world transforms
|
||||
/// for linear axes.
|
||||
/// </summary>
|
||||
public class FastTransform2D : ITransform2D
|
||||
{
|
||||
|
||||
private PageAlignedPhysicalAxis xAxis_;
|
||||
private PageAlignedPhysicalAxis yAxis_;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Constructor
|
||||
/// </summary>
|
||||
/// <param name="xAxis">The x-axis to use for transforms</param>
|
||||
/// <param name="yAxis">The y-axis to use for transforms</param>
|
||||
public FastTransform2D( PhysicalAxis xAxis, PhysicalAxis yAxis )
|
||||
{
|
||||
xAxis_ = new PageAlignedPhysicalAxis( xAxis );
|
||||
yAxis_ = new PageAlignedPhysicalAxis( yAxis );
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Transforms the given world point to physical coordinates
|
||||
/// </summary>
|
||||
/// <param name="x">x coordinate of world point to transform.</param>
|
||||
/// <param name="y">y coordinate of world point to transform.</param>
|
||||
/// <returns>the corresponding physical point.</returns>
|
||||
public PointF Transform( double x, double y )
|
||||
{
|
||||
return new PointF(
|
||||
xAxis_.WorldToPhysicalClipped( x ),
|
||||
yAxis_.WorldToPhysicalClipped( y ) );
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Transforms the given world point to physical coordinates
|
||||
/// </summary>
|
||||
/// <param name="worldPoint">the world point to transform</param>
|
||||
/// <returns>the corresponding physical point</returns>
|
||||
public PointF Transform( PointD worldPoint )
|
||||
{
|
||||
return new PointF(
|
||||
xAxis_.WorldToPhysical( worldPoint.X ),
|
||||
yAxis_.WorldToPhysical( worldPoint.Y ) );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,379 @@
|
|||
/*
|
||||
NPlot - A charting library for .NET
|
||||
|
||||
Utils.cs
|
||||
Copyright (C) 2003-2004
|
||||
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;
|
||||
using System.Data;
|
||||
using System.Collections;
|
||||
|
||||
namespace NPlot
|
||||
{
|
||||
/// <summary>
|
||||
/// General purpose utility functions used internally.
|
||||
/// </summary>
|
||||
internal class Utils
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// Numbers less than this are considered insignificant. This number is
|
||||
/// bigger than double.Epsilon.
|
||||
/// </summary>
|
||||
public const double Epsilon = double.Epsilon * 1000.0;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Returns true if the absolute difference between parameters is less than Epsilon
|
||||
/// </summary>
|
||||
/// <param name="a">first number to compare</param>
|
||||
/// <param name="b">second number to compare</param>
|
||||
/// <returns>true if equal, false otherwise</returns>
|
||||
public static bool DoubleEqual( double a, double b )
|
||||
{
|
||||
if ( System.Math.Abs(a-b) < Epsilon )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Swaps the value of two doubles.
|
||||
/// </summary>
|
||||
/// <param name="a">first value to swap.</param>
|
||||
/// <param name="b">second value to swap.</param>
|
||||
public static void Swap( ref double a, ref double b )
|
||||
{
|
||||
double c = a;
|
||||
a = b;
|
||||
b = c;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Calculate the distance between two points, a and b.
|
||||
/// </summary>
|
||||
/// <param name="a">First point</param>
|
||||
/// <param name="b">Second point</param>
|
||||
/// <returns>Distance between points a and b</returns>
|
||||
public static float Distance( PointF a, PointF b )
|
||||
{
|
||||
return (float)System.Math.Sqrt( (a.X - b.X)*(a.X - b.X) + (a.Y - b.Y)*(a.Y - b.Y) );
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Calculate the distance between two points, a and b.
|
||||
/// </summary>
|
||||
/// <param name="a">First point</param>
|
||||
/// <param name="b">Second point</param>
|
||||
/// <returns>Distance between points a and b</returns>
|
||||
public static int Distance( Point a, Point b )
|
||||
{
|
||||
return (int)System.Math.Sqrt( (a.X - b.X)*(a.X - b.X) + (a.Y - b.Y)*(a.Y - b.Y) );
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Converts an object of type DateTime or IConvertible to double representation.
|
||||
/// Mapping is 1:1. Note: the System.Convert.ToDouble method can not convert a boxed
|
||||
/// DateTime to double. This implementation can - but the "is" check probably makes
|
||||
/// it much slower.
|
||||
/// </summary>
|
||||
/// <remarks>Compare speed with System.Convert.ToDouble and revise code that calls this if significant speed difference.</remarks>
|
||||
/// <param name="o">The object to convert to double.</param>
|
||||
/// <returns>double value associated with the object.</returns>
|
||||
public static double ToDouble( object o )
|
||||
{
|
||||
if (o is DateTime)
|
||||
{
|
||||
return (double)(((DateTime)o).Ticks);
|
||||
}
|
||||
|
||||
else if (o is IConvertible)
|
||||
{
|
||||
return System.Convert.ToDouble(o);
|
||||
}
|
||||
|
||||
throw new NPlotException( "Invalid datatype" );
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Returns the minimum and maximum values in an IList. The members of the list
|
||||
/// can be of different types - any type for which the function Utils.ConvertToDouble
|
||||
/// knows how to convert into a double.
|
||||
/// </summary>
|
||||
/// <param name="a">The IList to search.</param>
|
||||
/// <param name="min">The minimum value.</param>
|
||||
/// <param name="max">The maximum value.</param>
|
||||
/// <returns>true if min max set, false otherwise (a == null or zero length).</returns>
|
||||
public static bool ArrayMinMax( IList a, out double min, out double max )
|
||||
{
|
||||
if ( a == null || a.Count == 0 )
|
||||
{
|
||||
min = 0.0;
|
||||
max = 0.0;
|
||||
return false;
|
||||
}
|
||||
|
||||
min = Utils.ToDouble(a[0]);
|
||||
max = Utils.ToDouble(a[0]);
|
||||
|
||||
foreach ( object o in a )
|
||||
{
|
||||
|
||||
double e = Utils.ToDouble(o);
|
||||
|
||||
if ( (min.Equals (double.NaN)) && (!e.Equals (double.NaN)) )
|
||||
{
|
||||
// if min/max are double.NaN and the current value not, then
|
||||
// set them to the current value.
|
||||
min = e;
|
||||
max = e;
|
||||
}
|
||||
if (!double.IsNaN(e))
|
||||
{
|
||||
if (e < min)
|
||||
{
|
||||
min = e;
|
||||
}
|
||||
if (e > max)
|
||||
{
|
||||
max = e;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (min.Equals (double.NaN))
|
||||
{
|
||||
// if min == double.NaN, then max is also double.NaN
|
||||
min = 0.0;
|
||||
max = 0.0;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Returns the minimum and maximum values in a DataRowCollection.
|
||||
/// </summary>
|
||||
/// <param name="rows">The row collection to search.</param>
|
||||
/// <param name="min">The minimum value.</param>
|
||||
/// <param name="max">The maximum value.</param>
|
||||
/// <param name="columnName">The name of the column in the row collection to search over.</param>
|
||||
/// <returns>true is min max set, false otherwise (a = null or zero length).</returns>
|
||||
public static bool RowArrayMinMax( DataRowCollection rows,
|
||||
out double min, out double max, string columnName )
|
||||
{
|
||||
// double[] is a reference type and can be null, if it is then I reckon the best
|
||||
// values for min and max are also null. double is a value type so can't be set
|
||||
// to null. So min an max return object, and we understand that if it is not null
|
||||
// it is a boxed double (same trick I use lots elsewhere in the lib). The
|
||||
// wonderful comment I didn't write at the top should explain everything.
|
||||
if ( rows == null || rows.Count == 0 )
|
||||
{
|
||||
min = 0.0;
|
||||
max = 0.0;
|
||||
return false;
|
||||
}
|
||||
|
||||
min = Utils.ToDouble( (rows[0])[columnName] );
|
||||
max = Utils.ToDouble( (rows[0])[columnName] );
|
||||
|
||||
foreach ( DataRow r in rows )
|
||||
{
|
||||
double e = Utils.ToDouble( r[columnName] );
|
||||
|
||||
if ( (min.Equals (double.NaN)) && (!e.Equals (double.NaN)) )
|
||||
{
|
||||
// if min/max are double.NaN and the current value not, then
|
||||
// set them to the current value.
|
||||
min = e;
|
||||
max = e;
|
||||
}
|
||||
|
||||
if (!double.IsNaN(e))
|
||||
{
|
||||
if (e < min)
|
||||
{
|
||||
min = e;
|
||||
}
|
||||
if (e > max)
|
||||
{
|
||||
max = e;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (min.Equals (double.NaN))
|
||||
{
|
||||
// if min == double.NaN, then max is also double.NaN
|
||||
min = 0.0;
|
||||
max = 0.0;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Returns the minimum and maximum values in a DataView.
|
||||
/// </summary>
|
||||
/// <param name="data">The DataView to search.</param>
|
||||
/// <param name="min">The minimum value.</param>
|
||||
/// <param name="max">The maximum value.</param>
|
||||
/// <param name="columnName">The name of the column in the row collection to search over.</param>
|
||||
/// <returns>true is min max set, false otherwise (a = null or zero length).</returns>
|
||||
public static bool DataViewArrayMinMax( DataView data,
|
||||
out double min, out double max, string columnName )
|
||||
{
|
||||
// double[] is a reference type and can be null, if it is then I reckon the best
|
||||
// values for min and max are also null. double is a value type so can't be set
|
||||
// to null. So min an max return object, and we understand that if it is not null
|
||||
// it is a boxed double (same trick I use lots elsewhere in the lib). The
|
||||
// wonderful comment I didn't write at the top should explain everything.
|
||||
if ( data == null || data.Count == 0 )
|
||||
{
|
||||
min = 0.0;
|
||||
max = 0.0;
|
||||
return false;
|
||||
}
|
||||
|
||||
min = Utils.ToDouble( (data[0])[columnName] );
|
||||
max = Utils.ToDouble( (data[0])[columnName] );
|
||||
|
||||
for (int i=0; i<data.Count; ++i)
|
||||
{
|
||||
|
||||
double e = Utils.ToDouble( data[i][columnName] );
|
||||
|
||||
if (e < min)
|
||||
{
|
||||
min = e;
|
||||
}
|
||||
|
||||
if (e > max)
|
||||
{
|
||||
max = e;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Returns unit vector along the line a->b.
|
||||
/// </summary>
|
||||
/// <param name="a">line start point.</param>
|
||||
/// <param name="b">line end point.</param>
|
||||
/// <returns>The unit vector along the specified line.</returns>
|
||||
public static PointF UnitVector( PointF a, PointF b )
|
||||
{
|
||||
PointF dir = new PointF( b.X - a.X, b.Y - a.Y );
|
||||
double dirNorm = System.Math.Sqrt( dir.X*dir.X + dir.Y*dir.Y );
|
||||
if ( dirNorm > 0.0f )
|
||||
{
|
||||
dir = new PointF(
|
||||
(float)((1.0f/dirNorm)*dir.X),
|
||||
(float)((1.0f/dirNorm)*dir.Y) ); // normalised axis direction vector
|
||||
}
|
||||
return dir;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get a Font exactly the same as the passed in one, except for scale factor.
|
||||
/// </summary>
|
||||
/// <param name="initial">The font to scale.</param>
|
||||
/// <param name="scale">Scale by this factor.</param>
|
||||
/// <returns>The scaled font.</returns>
|
||||
public static Font ScaleFont( Font initial, double scale )
|
||||
{
|
||||
FontStyle fs = initial.Style;
|
||||
GraphicsUnit gu = initial.Unit;
|
||||
double sz = initial.Size;
|
||||
sz = sz * scale ;
|
||||
string nm = initial.Name;
|
||||
return new Font( nm, (float)sz, fs, gu );
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Creates a bitmap from another that is tiled size times in each direction.
|
||||
/// </summary>
|
||||
/// <param name="image">bitmap to tile</param>
|
||||
/// <param name="size">number of times to tile in each direction.</param>
|
||||
/// <returns>the tiled bitmap.</returns>
|
||||
public static System.Drawing.Bitmap TiledImage( System.Drawing.Bitmap image, Size size )
|
||||
{
|
||||
System.Drawing.Bitmap final = new System.Drawing.Bitmap( size.Width, size.Height );
|
||||
|
||||
for (int i=0; i<(size.Width / image.Width)+1; ++i)
|
||||
{
|
||||
for (int j=0; j<(size.Height / image.Height)+1; ++j)
|
||||
{
|
||||
Graphics.FromImage( final ).DrawImage( image, i*image.Width, j*image.Height );
|
||||
}
|
||||
}
|
||||
|
||||
return final;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -0,0 +1,293 @@
|
|||
/*
|
||||
NPlot - A charting library for .NET
|
||||
|
||||
VerticalLine.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>
|
||||
/// Encapsulates functionality for drawing a vertical line on a plot surface.
|
||||
/// </summary>
|
||||
public class VerticalLine : IPlot
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// Constructor
|
||||
/// </summary>
|
||||
/// <param name="abscissaValue">abscissa (X) value of line.</param>
|
||||
public VerticalLine( double abscissaValue )
|
||||
{
|
||||
this.value_ = abscissaValue;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Constructor
|
||||
/// </summary>
|
||||
/// <param name="abscissaValue">abscissa (X) value of line.</param>
|
||||
/// <param name="color">draw the line using this color.</param>
|
||||
public VerticalLine( double abscissaValue, Color color )
|
||||
{
|
||||
this.value_ = abscissaValue;
|
||||
this.pen_ = new Pen( color );
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Constructor
|
||||
/// </summary>
|
||||
/// <param name="abscissaValue">abscissa (X) value of line.</param>
|
||||
/// <param name="pen">Pen to use to draw the line.</param>
|
||||
public VerticalLine( double abscissaValue, Pen pen )
|
||||
{
|
||||
this.value_ = abscissaValue;
|
||||
this.pen_ = pen;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Draws a representation of the line in the legend
|
||||
/// </summary>
|
||||
/// <param name="g">The graphics surface on which to draw.</param>
|
||||
/// <param name="startEnd">A rectangle specifying the bounds of the area in the legend set aside for drawing.</param>
|
||||
public void DrawInLegend(System.Drawing.Graphics g, System.Drawing.Rectangle startEnd)
|
||||
{
|
||||
g.DrawLine( pen_, startEnd.Left, (startEnd.Top + startEnd.Bottom)/2,
|
||||
startEnd.Right, (startEnd.Top + startEnd.Bottom)/2 );
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// A label to associate with the plot - used in the legend.
|
||||
/// </summary>
|
||||
public string Label
|
||||
{
|
||||
get
|
||||
{
|
||||
return label_;
|
||||
}
|
||||
set
|
||||
{
|
||||
this.label_ = value;
|
||||
}
|
||||
}
|
||||
|
||||
private string label_ = "";
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Whether or not to include an entry for this plot in the legend if it exists.
|
||||
/// </summary>
|
||||
public bool ShowInLegend
|
||||
{
|
||||
get
|
||||
{
|
||||
return showInLegend_;
|
||||
}
|
||||
set
|
||||
{
|
||||
this.showInLegend_ = value;
|
||||
}
|
||||
}
|
||||
private bool showInLegend_ = false;
|
||||
|
||||
/// <summary>
|
||||
/// Returns an x-axis that is suitable for drawing this plot.
|
||||
/// </summary>
|
||||
/// <returns>A suitable x-axis.</returns>
|
||||
public Axis SuggestXAxis()
|
||||
{
|
||||
return new LinearAxis( value_, value_ );
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Returns null indicating that y extremities of the line are variable.
|
||||
/// </summary>
|
||||
/// <returns>null</returns>
|
||||
public Axis SuggestYAxis()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Writes text data describing the vertical line object to the supplied string builder. It is
|
||||
/// possible to specify that the data will be written only if the line is in the specified
|
||||
/// region.
|
||||
/// </summary>
|
||||
/// <param name="sb">the StringBuilder object to write to.</param>
|
||||
/// <param name="region">a region used if onlyInRegion is true.</param>
|
||||
/// <param name="onlyInRegion">If true, data will be written only if the line is in the specified region.</param>
|
||||
public void WriteData(System.Text.StringBuilder sb, RectangleD region, bool onlyInRegion)
|
||||
{
|
||||
|
||||
// return if line is not in plot region and
|
||||
if (value_ > region.X+region.Width || value_ < region.X)
|
||||
{
|
||||
if (onlyInRegion)
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
sb.Append( "Label: " );
|
||||
sb.Append( this.Label );
|
||||
sb.Append( "\r\n" );
|
||||
sb.Append( value_.ToString() );
|
||||
sb.Append( "\r\n" );
|
||||
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Draws the vertical line plot on a GDI+ surface against the provided x and y axes.
|
||||
/// </summary>
|
||||
/// <param name="g">The GDI+ 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)
|
||||
{
|
||||
int yMin = yAxis.PhysicalMin.Y;
|
||||
int yMax = yAxis.PhysicalMax.Y;
|
||||
|
||||
yMin -= pixelIndent_;
|
||||
yMax += pixelIndent_;
|
||||
|
||||
float length = Math.Abs(yMax - yMin);
|
||||
float lengthDiff = length - length*scale_;
|
||||
float indentAmount = lengthDiff/2;
|
||||
|
||||
yMin -= (int)indentAmount;
|
||||
yMax += (int)indentAmount;
|
||||
|
||||
int xPos = (int)xAxis.WorldToPhysical( value_, false ).X;
|
||||
|
||||
g.DrawLine( pen_, new System.Drawing.Point( xPos, yMin ), new System.Drawing.Point( xPos, yMax ) );
|
||||
|
||||
// todo: clip and proper logic for flipped axis min max.
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// abscissa (X) value to draw horizontal line at.
|
||||
/// </summary>
|
||||
public double AbscissaValue
|
||||
{
|
||||
get
|
||||
{
|
||||
return value_;
|
||||
}
|
||||
set
|
||||
{
|
||||
value_ = value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Pen to use to draw the horizontal line.
|
||||
/// </summary>
|
||||
public Pen Pen
|
||||
{
|
||||
get
|
||||
{
|
||||
return pen_;
|
||||
}
|
||||
set
|
||||
{
|
||||
pen_ = value;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private double value_;
|
||||
private Pen pen_ = new Pen( Color.Black );
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Each end of the line is indented by this many pixels.
|
||||
/// </summary>
|
||||
public int PixelIndent
|
||||
{
|
||||
get
|
||||
{
|
||||
return pixelIndent_;
|
||||
}
|
||||
set
|
||||
{
|
||||
pixelIndent_ = value;
|
||||
}
|
||||
}
|
||||
private int pixelIndent_ = 0;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// The line length is multiplied by this amount. Default
|
||||
/// corresponds to a value of 1.0.
|
||||
/// </summary>
|
||||
public float LengthScale
|
||||
{
|
||||
get
|
||||
{
|
||||
return scale_;
|
||||
}
|
||||
set
|
||||
{
|
||||
scale_ = value;
|
||||
}
|
||||
}
|
||||
private float scale_ = 1.0f;
|
||||
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,121 @@
|
|||
/*
|
||||
NPlot - A charting library for .NET
|
||||
|
||||
Web.PlotSurface2d.cs
|
||||
Copyright (C) 2003
|
||||
Matt Howlett, Paolo Pierini
|
||||
|
||||
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.Imaging;
|
||||
using System.IO;
|
||||
using System.Web.UI;
|
||||
using System.Web.UI.WebControls;
|
||||
using System.ComponentModel;
|
||||
using NPlot;
|
||||
|
||||
namespace NPlot
|
||||
{
|
||||
|
||||
namespace Web
|
||||
{
|
||||
namespace Design
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// The Design Time rendered for the NPlot.web.PlotSurface2D control.
|
||||
/// </summary>
|
||||
public class PlotSurface2D : System.Web.UI.Design.ControlDesigner
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// The design time generated HTML for the control.
|
||||
/// </summary>
|
||||
/// <returns>A string containing the HTML rendering.</returns>
|
||||
public override string GetDesignTimeHtml()
|
||||
{
|
||||
|
||||
// Extremely simple design time rendering!
|
||||
// will work on something better sooner or later.
|
||||
// This acts as a placeholder.
|
||||
Web.PlotSurface2D plot = (Web.PlotSurface2D)Component;
|
||||
|
||||
int xs = Convert.ToInt32(plot.Width.Value);
|
||||
if ( xs < 1 ) return "";
|
||||
int ys = Convert.ToInt32(plot.Height.Value);
|
||||
if ( ys < 1 ) return "";
|
||||
|
||||
StringWriter sw = new StringWriter();
|
||||
HtmlTextWriter output= new HtmlTextWriter(sw);
|
||||
output.AddAttribute("border",plot.BorderWidth.ToString());
|
||||
output.AddAttribute("borderColor",plot.BorderColor.ToKnownColor().ToString());
|
||||
output.AddAttribute("cellSpacing","0");
|
||||
output.AddAttribute("cellPadding","0");
|
||||
output.AddAttribute("width",xs.ToString());
|
||||
output.RenderBeginTag("table ");
|
||||
output.RenderBeginTag("tr");
|
||||
output.AddAttribute("vAlign","center");
|
||||
output.AddAttribute("align","middle");
|
||||
output.AddAttribute("height",ys.ToString());
|
||||
output.RenderBeginTag("td");
|
||||
output.RenderBeginTag("P");
|
||||
output.Write("PlotSurface2D:" + plot.Title);
|
||||
output.RenderEndTag();
|
||||
output.RenderEndTag();
|
||||
output.RenderEndTag();
|
||||
output.RenderEndTag();
|
||||
output.Flush();
|
||||
return sw.ToString();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,671 @@
|
|||
/*
|
||||
NPlot - A charting library for .NET
|
||||
|
||||
Web.PlotSurface2d.cs
|
||||
Copyright (C) 2003
|
||||
Matt Howlett, Paolo Pierini
|
||||
|
||||
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.Imaging;
|
||||
using System.Web.UI;
|
||||
using System.Web.UI.WebControls;
|
||||
using System.ComponentModel;
|
||||
using System.IO;
|
||||
using System.Collections;
|
||||
using System.Text;
|
||||
|
||||
namespace NPlot
|
||||
{
|
||||
|
||||
namespace Web
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// A PlotSurface2D web control. Rather than use this control, I generally create bitmaps
|
||||
/// using Bitmap.PlotSurface2D, then use the ToBrowser() method in Bitmap.PlotSurface2D to
|
||||
/// return them as a page request response (and point the src in an image tag to this page).
|
||||
///
|
||||
/// This is not as nice from a users perspective but is more efficient.
|
||||
///
|
||||
/// Note: this control can chew up memory until the user session ends if the client cancels
|
||||
/// the page load before the image has loaded.
|
||||
/// </summary>
|
||||
[
|
||||
DefaultProperty("Title"),
|
||||
ToolboxData("<{0}:PlotSurface2D runat=server></{0}:PlotSurface2D>"),
|
||||
Designer(typeof(NPlot.Web.Design.PlotSurface2D))
|
||||
]
|
||||
public class PlotSurface2D : System.Web.UI.WebControls.WebControl, IPlotSurface2D
|
||||
{
|
||||
|
||||
private NPlot.PlotSurface2D ps_ = new NPlot.PlotSurface2D();
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Default constructor.
|
||||
/// </summary>
|
||||
public PlotSurface2D() :
|
||||
base()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// The URL to redirect for the plot.
|
||||
/// </summary>
|
||||
private string plotUrl;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// the prefix used for the session variables
|
||||
/// </summary>
|
||||
private string prefix()
|
||||
{
|
||||
string toReturn = "__PlotSurface2D_";
|
||||
toReturn += this.ClientID;
|
||||
toReturn += "_";
|
||||
toReturn += this.Page.ToString();
|
||||
toReturn += "_";
|
||||
return toReturn;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Clears the plot.
|
||||
/// </summary>
|
||||
public void Clear()
|
||||
{
|
||||
ps_.Clear();
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Adds a drawable object to the plot surface. If the object is an IPlot,
|
||||
/// the PlotSurface2D axes will also be updated.
|
||||
/// </summary>
|
||||
/// <param name="p">The IDrawable object to add to the plot surface.</param>
|
||||
public void Add( IDrawable p )
|
||||
{
|
||||
ps_.Add( p );
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Adds a drawable object to the plot surface against the specified axes. If
|
||||
/// the object is an IPlot, the PlotSurface2D axes will also be updated.
|
||||
/// </summary>
|
||||
/// <param name="p">the IDrawable object to add to the plot surface</param>
|
||||
/// <param name="xp">the x-axis to add the plot against.</param>
|
||||
/// <param name="yp">the y-axis to add the plot against.</param>
|
||||
public void Add( IDrawable p, NPlot.PlotSurface2D.XAxisPosition xp, NPlot.PlotSurface2D.YAxisPosition yp )
|
||||
{
|
||||
ps_.Add( p, xp, yp );
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Adds a drawable object to the plot surface. If the object is an IPlot,
|
||||
/// the PlotSurface2D axes will also be updated.
|
||||
/// </summary>
|
||||
/// <param name="p">The IDrawable object to add to the plot surface.</param>
|
||||
/// <param name="zOrder">The z-ordering when drawing (objects with lower numbers are drawn first)</param>
|
||||
public void Add( IDrawable p, int zOrder )
|
||||
{
|
||||
ps_.Add( p, zOrder );
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Adds a drawable object to the plot surface against the specified axes. If
|
||||
/// the object is an IPlot, the PlotSurface2D axes will also be updated.
|
||||
/// </summary>
|
||||
/// <param name="p">the IDrawable object to add to the plot surface</param>
|
||||
/// <param name="xp">the x-axis to add the plot against.</param>
|
||||
/// <param name="yp">the y-axis to add the plot against.</param>
|
||||
/// <param name="zOrder">The z-ordering when drawing (objects with lower numbers are drawn first)</param>
|
||||
public void Add( IDrawable p, NPlot.PlotSurface2D.XAxisPosition xp,
|
||||
NPlot.PlotSurface2D.YAxisPosition yp, int zOrder )
|
||||
{
|
||||
ps_.Add( p, xp, yp , zOrder);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The plot surface title.
|
||||
/// </summary>
|
||||
[
|
||||
Browsable(true),
|
||||
Bindable(true)
|
||||
]
|
||||
public string Title
|
||||
{
|
||||
get
|
||||
{
|
||||
return ps_.Title;
|
||||
}
|
||||
set
|
||||
{
|
||||
ps_.Title = value;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// The plot title font.
|
||||
/// </summary>
|
||||
[
|
||||
Browsable(true)
|
||||
]
|
||||
public System.Drawing.Font TitleFont
|
||||
{
|
||||
get
|
||||
{
|
||||
return ps_.TitleFont;
|
||||
}
|
||||
set
|
||||
{
|
||||
ps_.TitleFont = value;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// The distance in pixels to leave between of the edge of the bounding rectangle
|
||||
/// supplied to the Draw method, and the markings that make up the plot.
|
||||
/// </summary>
|
||||
[
|
||||
Browsable(true),
|
||||
Category("Data"),
|
||||
Bindable(true)
|
||||
]
|
||||
public int Padding
|
||||
{
|
||||
get
|
||||
{
|
||||
return ps_.Padding;
|
||||
}
|
||||
set
|
||||
{
|
||||
ps_.Padding = value;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// The first abscissa axis.
|
||||
/// </summary>
|
||||
[
|
||||
Browsable(false),
|
||||
Bindable(false)
|
||||
]
|
||||
public Axis XAxis1
|
||||
{
|
||||
get
|
||||
{
|
||||
return ps_.XAxis1;
|
||||
}
|
||||
set
|
||||
{
|
||||
ps_.XAxis1 = value;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// The first ordinate axis.
|
||||
/// </summary>
|
||||
[
|
||||
Browsable(false),
|
||||
Bindable(false)
|
||||
]
|
||||
public Axis YAxis1
|
||||
{
|
||||
get
|
||||
{
|
||||
return ps_.YAxis1;
|
||||
}
|
||||
set
|
||||
{
|
||||
ps_.YAxis1 = value;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// The second abscissa axis.
|
||||
/// </summary>
|
||||
[
|
||||
Browsable(false),
|
||||
Bindable(false)
|
||||
]
|
||||
public Axis XAxis2
|
||||
{
|
||||
get
|
||||
{
|
||||
return ps_.XAxis2;
|
||||
}
|
||||
set
|
||||
{
|
||||
ps_.XAxis2 = value;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// The second ordinate axis.
|
||||
/// </summary>
|
||||
[
|
||||
Browsable(false),
|
||||
Bindable(false)
|
||||
]
|
||||
public Axis YAxis2
|
||||
{
|
||||
get
|
||||
{
|
||||
return ps_.YAxis2;
|
||||
}
|
||||
set
|
||||
{
|
||||
ps_.YAxis2 = value;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// A color used to paint the plot background. Mutually exclusive with PlotBackImage and PlotBackBrush
|
||||
/// </summary>
|
||||
[
|
||||
Bindable(true),
|
||||
Browsable(true)
|
||||
]
|
||||
public System.Drawing.Color PlotBackColor
|
||||
{
|
||||
set
|
||||
{
|
||||
ps_.PlotBackColor = value;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// An imaged used to paint the plot background. Mutually exclusive with PlotBackColor and PlotBackBrush
|
||||
/// </summary>
|
||||
public System.Drawing.Bitmap PlotBackImage
|
||||
{
|
||||
set
|
||||
{
|
||||
ps_.PlotBackImage = value;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// A Rectangle brush used to paint the plot background. Mutually exclusive with PlotBackColor and PlotBackBrush
|
||||
/// </summary>
|
||||
public IRectangleBrush PlotBackBrush
|
||||
{
|
||||
set
|
||||
{
|
||||
ps_.PlotBackBrush = value;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Gets or Sets the legend to use with this plot surface.
|
||||
/// </summary>
|
||||
[
|
||||
Bindable(false),
|
||||
Browsable(false)
|
||||
]
|
||||
public NPlot.Legend Legend
|
||||
{
|
||||
get
|
||||
{
|
||||
return ps_.Legend;
|
||||
}
|
||||
set
|
||||
{
|
||||
ps_.Legend = value;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Gets or Sets the legend z-order.
|
||||
/// </summary>
|
||||
[
|
||||
Bindable(true),
|
||||
Browsable(true)
|
||||
]
|
||||
public int LegendZOrder
|
||||
{
|
||||
get
|
||||
{
|
||||
return ps_.LegendZOrder;
|
||||
}
|
||||
set
|
||||
{
|
||||
ps_.LegendZOrder = value;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Smoothing mode to use when drawing plots.
|
||||
/// </summary>
|
||||
[
|
||||
Bindable(true),
|
||||
Browsable(true)
|
||||
]
|
||||
public System.Drawing.Drawing2D.SmoothingMode SmoothingMode
|
||||
{
|
||||
get
|
||||
{
|
||||
return ps_.SmoothingMode;
|
||||
}
|
||||
set
|
||||
{
|
||||
ps_.SmoothingMode = value;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// The bitmap background color outside the bounds of the plot surface.
|
||||
/// </summary>
|
||||
[
|
||||
Bindable(true),
|
||||
Browsable(true)
|
||||
]
|
||||
public override Color BackColor
|
||||
{
|
||||
set
|
||||
{
|
||||
backColor_ = value;
|
||||
}
|
||||
}
|
||||
object backColor_ = null;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Ivan Ivanov wrote this function. From his email:
|
||||
/// If the request string contains encoded parameters values [e.g. # - %23].
|
||||
/// The call to request.Url.ToString() will decode values [e.g. instead of %23
|
||||
/// it will return #]. On the subsequent request to the page that contains the
|
||||
/// nplot control [when the actual drawing of the image takes place] the request
|
||||
/// url will be cut up to the unformated value [e.g. #] and since the PlotSurface2D_
|
||||
/// is added at the end of the query string, it will be missing.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
private String buildPlotURL()
|
||||
{
|
||||
StringBuilder urlParams = new StringBuilder();
|
||||
|
||||
foreach (string getParamName in Context.Request.QueryString.AllKeys)
|
||||
{
|
||||
urlParams.Append(getParamName + "=" +
|
||||
Context.Server.UrlEncode(Context.Request.QueryString[getParamName]) + "&");
|
||||
}
|
||||
|
||||
return Context.Request.Url.AbsolutePath +
|
||||
(urlParams.Length > 0 ?
|
||||
"?" + urlParams.Append("PlotSurface2D_" + this.ClientID + "=1").ToString() :
|
||||
"?PlotSurface2D_" + this.ClientID + "=1");
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Initialization event.
|
||||
/// </summary>
|
||||
/// <param name="e"></param>
|
||||
protected override void OnInit(EventArgs e)
|
||||
{
|
||||
System.Web.HttpRequest request = Context.Request;
|
||||
System.Web.HttpResponse response = Context.Response;
|
||||
if (request.Params["PlotSurface2D_" + this.ClientID] != null)
|
||||
{
|
||||
// retrieve the bitmap and display
|
||||
response.Clear();
|
||||
try
|
||||
{
|
||||
response.ContentType = "Image/Png";
|
||||
System.Drawing.Bitmap bmp = (System.Drawing.Bitmap) Context.Session[prefix()+"PNG"];
|
||||
|
||||
// don't ask why, but if I write directly to the response
|
||||
// I have a GDI+ error, if I first write to a MemoryStream and
|
||||
// then to the response.OutputStream I don't get an error.
|
||||
System.IO.MemoryStream s = new System.IO.MemoryStream();
|
||||
bmp.Save( s, System.Drawing.Imaging.ImageFormat.Png);
|
||||
s.WriteTo(response.OutputStream);
|
||||
Context.Session.Remove(prefix()+"PNG");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
response.ContentType = "Text/HTML";
|
||||
response.Write( ex.Message );
|
||||
}
|
||||
finally
|
||||
{
|
||||
response.Flush();
|
||||
response.End();
|
||||
}
|
||||
}
|
||||
|
||||
this.plotUrl = this.buildPlotURL();
|
||||
base.OnInit (e);
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Render this control as an HTML stream.
|
||||
/// </summary>
|
||||
/// <param name="output">The HTML writer to write out to.</param>
|
||||
protected override void Render(HtmlTextWriter output)
|
||||
{
|
||||
|
||||
// first of all render the bitmap;
|
||||
System.Drawing.Bitmap b = new System.Drawing.Bitmap( (int)this.Width.Value, (int)this.Height.Value );
|
||||
if (backColor_!=null)
|
||||
{
|
||||
Graphics g = Graphics.FromImage( b );
|
||||
g.FillRectangle( (new Pen( (Color)this.backColor_)).Brush,0,0,b.Width,b.Height );
|
||||
}
|
||||
ps_.Draw( Graphics.FromImage(b), new System.Drawing.Rectangle(0,0,b.Width,b.Height) );
|
||||
|
||||
// then store in context memory.
|
||||
Context.Session[prefix()+"PNG"] = b;
|
||||
|
||||
// now render html.
|
||||
if (this.BorderStyle == BorderStyle.None)
|
||||
{
|
||||
output.AddAttribute("border","0");
|
||||
}
|
||||
else
|
||||
{
|
||||
output.AddAttribute("border",this.BorderWidth.ToString());
|
||||
output.AddAttribute("borderColor",this.BorderColor.ToKnownColor().ToString());
|
||||
}
|
||||
output.AddAttribute("cellSpacing","0");
|
||||
output.AddAttribute("cellPadding","0");
|
||||
output.RenderBeginTag("table");
|
||||
output.RenderBeginTag("tr");
|
||||
output.AddAttribute("vAlign","center");
|
||||
output.AddAttribute("align","middle");
|
||||
output.RenderBeginTag("td");
|
||||
output.RenderBeginTag("P");
|
||||
output.AddAttribute("src",this.plotUrl);
|
||||
output.AddAttribute("alt",this.ToolTip);
|
||||
output.RenderBeginTag("img");
|
||||
output.RenderEndTag();
|
||||
output.RenderEndTag();
|
||||
output.RenderEndTag();
|
||||
output.RenderEndTag();
|
||||
output.RenderEndTag();
|
||||
output.Flush();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Add an axis constraint to the plot surface. Axis constraints can
|
||||
/// specify relative world-pixel scalings, absolute axis positions etc.
|
||||
/// </summary>
|
||||
/// <param name="c">The axis constraint to add.</param>
|
||||
public void AddAxesConstraint( AxesConstraint c )
|
||||
{
|
||||
ps_.AddAxesConstraint( c );
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Whether or not the title will be scaled according to size of the plot
|
||||
/// surface.
|
||||
/// </summary>
|
||||
[
|
||||
Browsable(true),
|
||||
Bindable(true)
|
||||
]
|
||||
public bool AutoScaleTitle
|
||||
{
|
||||
get
|
||||
{
|
||||
return ps_.AutoScaleTitle;
|
||||
}
|
||||
set
|
||||
{
|
||||
ps_.AutoScaleTitle = value;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// When plots are added to the plot surface, the axes they are attached to
|
||||
/// are immediately modified to reflect data of the plot. If
|
||||
/// AutoScaleAutoGeneratedAxes is true when a plot is added, the axes will
|
||||
/// be turned in to auto scaling ones if they are not already [tick marks,
|
||||
/// tick text and label size scaled to size of plot surface]. If false,
|
||||
/// axes will not be autoscaling.
|
||||
/// </summary>
|
||||
[
|
||||
Browsable(true),
|
||||
Bindable(true),
|
||||
]
|
||||
public bool AutoScaleAutoGeneratedAxes
|
||||
{
|
||||
get
|
||||
{
|
||||
return ps_.AutoScaleAutoGeneratedAxes;
|
||||
}
|
||||
set
|
||||
{
|
||||
ps_.AutoScaleAutoGeneratedAxes = value;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Sets the title to be drawn using a solid brush of this color.
|
||||
/// </summary>
|
||||
[
|
||||
Browsable(true),
|
||||
Bindable(true)
|
||||
]
|
||||
public Color TitleColor
|
||||
{
|
||||
set
|
||||
{
|
||||
ps_.TitleColor = value;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// The brush used for drawing the title.
|
||||
/// </summary>
|
||||
[
|
||||
Browsable(false)
|
||||
]
|
||||
public Brush TitleBrush
|
||||
{
|
||||
get
|
||||
{
|
||||
return ps_.TitleBrush;
|
||||
}
|
||||
set
|
||||
{
|
||||
ps_.TitleBrush = value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Remove a drawable object from the plot surface.
|
||||
/// </summary>
|
||||
/// <param name="p">the drawable to remove</param>
|
||||
/// <param name="updateAxes">whether or not to update the axes after removing the idrawable.</param>
|
||||
public void Remove( IDrawable p, bool updateAxes )
|
||||
{
|
||||
ps_.Remove( p, updateAxes );
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Gets an array list containing all drawables currently added to the PlotSurface2D.
|
||||
/// </summary>
|
||||
[
|
||||
Browsable(false)
|
||||
]
|
||||
public ArrayList Drawables
|
||||
{
|
||||
get
|
||||
{
|
||||
return ps_.Drawables;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,113 @@
|
|||
using System;
|
||||
using System.Collections;
|
||||
using System.ComponentModel;
|
||||
using System.Drawing;
|
||||
using System.Data;
|
||||
using System.Windows.Forms;
|
||||
|
||||
namespace NPlot.Windows
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// An all encompasing Windows.Forms PlotSurface. This class allows you
|
||||
/// to place a single control in your form layout and draw to any type of
|
||||
/// plot surface (PlotSurface2D, PlotSurface3D etc) on it. As there is only
|
||||
/// one type of plot surface currently, this
|
||||
/// class isn't necessary... but more a planned soon.
|
||||
/// Also, the implementation isn't finished.
|
||||
/// </summary>
|
||||
public class PlotSurface : System.Windows.Forms.UserControl
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// control resize handler.
|
||||
/// </summary>
|
||||
/// <param name="e">event args.</param>
|
||||
protected override void OnResize( EventArgs e )
|
||||
{
|
||||
this.Refresh();
|
||||
base.OnResize(e);
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// control paint handler.
|
||||
/// </summary>
|
||||
/// <param name="pe">paint event args.</param>
|
||||
protected override void OnPaint( PaintEventArgs pe )
|
||||
{
|
||||
surface_.DoPaint( pe, this.Width, this.Height );
|
||||
base.OnPaint(pe);
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Mouse down event handler.
|
||||
/// </summary>
|
||||
/// <param name="e">mouse event args</param>
|
||||
protected override void OnMouseDown(MouseEventArgs e)
|
||||
{
|
||||
surface_.DoMouseDown(e);
|
||||
base.OnMouseDown(e);
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Mouse Up event handler.
|
||||
/// </summary>
|
||||
/// <param name="e">mouse event args.</param>
|
||||
protected override void OnMouseUp(MouseEventArgs e)
|
||||
{
|
||||
surface_.DoMouseUp(e, this);
|
||||
base.OnMouseUp(e);
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Mouse Move event handler.
|
||||
/// </summary>
|
||||
/// <param name="e">mouse event args.</param>
|
||||
protected override void OnMouseMove(MouseEventArgs e)
|
||||
{
|
||||
surface_.DoMouseMove(e, this);
|
||||
base.OnMouseMove(e);
|
||||
}
|
||||
|
||||
/*
|
||||
enum Type
|
||||
{
|
||||
PlotSurface2D,
|
||||
PlotSurface2Dnew,
|
||||
PlotSurface3D,
|
||||
PieChart
|
||||
}
|
||||
*/
|
||||
|
||||
ISurface surface_ = null;
|
||||
/// <summary>
|
||||
/// Gets the underlying plot surface.
|
||||
/// </summary>
|
||||
public ISurface Surface
|
||||
{
|
||||
get
|
||||
{
|
||||
return surface_;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructor.
|
||||
/// </summary>
|
||||
public PlotSurface()
|
||||
{
|
||||
// double buffer, and update when resize.
|
||||
base.SetStyle(ControlStyles.AllPaintingInWmPaint, true);
|
||||
base.SetStyle(ControlStyles.DoubleBuffer, true);
|
||||
base.SetStyle(ControlStyles.UserPaint, true);
|
||||
base.ResizeRedraw = true;
|
||||
|
||||
surface_ = new NPlot.Windows.PlotSurface2D();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,42 @@
|
|||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<root>
|
||||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||
<xsd:element name="root" msdata:IsDataSet="true">
|
||||
<xsd:complexType>
|
||||
<xsd:choice maxOccurs="unbounded">
|
||||
<xsd:element name="data">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
<xsd:attribute name="type" type="xsd:string" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="resheader">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:choice>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:schema>
|
||||
<resheader name="ResMimeType">
|
||||
<value>text/microsoft-resx</value>
|
||||
</resheader>
|
||||
<resheader name="Version">
|
||||
<value>1.0.0.0</value>
|
||||
</resheader>
|
||||
<resheader name="Reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<resheader name="Writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
</root>
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -0,0 +1,106 @@
|
|||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<root>
|
||||
<!--
|
||||
Microsoft ResX Schema
|
||||
|
||||
Version 1.3
|
||||
|
||||
The primary goals of this format is to allow a simple XML format
|
||||
that is mostly human readable. The generation and parsing of the
|
||||
various data types are done through the TypeConverter classes
|
||||
associated with the data types.
|
||||
|
||||
Example:
|
||||
|
||||
... ado.net/XML headers & schema ...
|
||||
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||
<resheader name="version">1.3</resheader>
|
||||
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||
<data name="Name1">this is my long string</data>
|
||||
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||
[base64 mime encoded serialized .NET Framework object]
|
||||
</data>
|
||||
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
[base64 mime encoded string representing a byte array form of the .NET Framework object]
|
||||
</data>
|
||||
|
||||
There are any number of "resheader" rows that contain simple
|
||||
name/value pairs.
|
||||
|
||||
Each data row contains a name, and value. The row also contains a
|
||||
type or mimetype. Type corresponds to a .NET class that support
|
||||
text/value conversion through the TypeConverter architecture.
|
||||
Classes that don't support this are serialized and stored with the
|
||||
mimetype set.
|
||||
|
||||
The mimetype is used forserialized objects, and tells the
|
||||
ResXResourceReader how to depersist the object. This is currently not
|
||||
extensible. For a given mimetype the value must be set accordingly:
|
||||
|
||||
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||
that the ResXResourceWriter will generate, however the reader can
|
||||
read any of the formats listed below.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.binary.base64
|
||||
value : The object must be serialized with
|
||||
: System.Serialization.Formatters.Binary.BinaryFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.soap.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||
value : The object must be serialized into a byte array
|
||||
: using a System.ComponentModel.TypeConverter
|
||||
: and then encoded with base64 encoding.
|
||||
-->
|
||||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||
<xsd:element name="root" msdata:IsDataSet="true">
|
||||
<xsd:complexType>
|
||||
<xsd:choice maxOccurs="unbounded">
|
||||
<xsd:element name="data">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" msdata:Ordinal="1" />
|
||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="resheader">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:choice>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:schema>
|
||||
<resheader name="resmimetype">
|
||||
<value>text/microsoft-resx</value>
|
||||
</resheader>
|
||||
<resheader name="version">
|
||||
<value>1.3</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<data name="$this.TrayLargeIcon" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
||||
<value>False</value>
|
||||
</data>
|
||||
<data name="$this.Name">
|
||||
<value>PlotSurface2D</value>
|
||||
</data>
|
||||
</root>
|
|
@ -0,0 +1,155 @@
|
|||
// ******** experimental ********
|
||||
|
||||
/*
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.ComponentModel;
|
||||
using System.Drawing;
|
||||
using System.Data;
|
||||
using System.Windows.Forms;
|
||||
using System.IO;
|
||||
|
||||
namespace NPlot.Windows
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// Experimental
|
||||
/// </summary>
|
||||
public class PlotSurface2Dnew : System.Windows.Forms.UserControl, IPlotSurface2Dnew
|
||||
{
|
||||
/// <summary>
|
||||
/// Required designer variable.
|
||||
/// </summary>
|
||||
private System.ComponentModel.Container components = null;
|
||||
|
||||
/// <summary>
|
||||
/// Constructor
|
||||
/// </summary>
|
||||
public PlotSurface2Dnew()
|
||||
{
|
||||
// This call is required by the Windows.Forms Form Designer.
|
||||
InitializeComponent();
|
||||
|
||||
// double buffer, and update when resize.
|
||||
base.SetStyle(ControlStyles.AllPaintingInWmPaint, true);
|
||||
base.SetStyle(ControlStyles.DoubleBuffer, true);
|
||||
base.SetStyle(ControlStyles.UserPaint, true);
|
||||
base.ResizeRedraw = true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Clean up any resources being used.
|
||||
/// </summary>
|
||||
protected override void Dispose( bool disposing )
|
||||
{
|
||||
if( disposing )
|
||||
{
|
||||
if( components != null )
|
||||
components.Dispose();
|
||||
}
|
||||
base.Dispose( disposing );
|
||||
}
|
||||
|
||||
#region Component Designer generated code
|
||||
/// <summary>
|
||||
/// Required method for Designer support - do not modify
|
||||
/// the contents of this method with the code editor.
|
||||
/// </summary>
|
||||
private void InitializeComponent()
|
||||
{
|
||||
components = new System.ComponentModel.Container();
|
||||
}
|
||||
#endregion
|
||||
|
||||
private NPlot.PlotSurface2Dnew Inner = new NPlot.PlotSurface2Dnew();
|
||||
|
||||
/// <summary>
|
||||
/// Experimental
|
||||
/// </summary>
|
||||
public void SetDefinition( )
|
||||
{
|
||||
Inner.SetDefinition( );
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// the paint event callback.
|
||||
/// </summary>
|
||||
/// <param name="pe">paint event arguments - used to get graphics surface to draw on.</param>
|
||||
protected override void OnPaint( PaintEventArgs pe )
|
||||
{
|
||||
Graphics g = pe.Graphics;
|
||||
|
||||
Rectangle border = new Rectangle( 0, 0, this.Width, this.Height );
|
||||
|
||||
if ( g == null )
|
||||
{
|
||||
ErrorHandler.Instance.CriticalError( "graphics context null" );
|
||||
}
|
||||
|
||||
if ( border == Rectangle.Empty )
|
||||
{
|
||||
ErrorHandler.Instance.CriticalError( "Control has zero extent" );
|
||||
return;
|
||||
}
|
||||
|
||||
this.Draw( g, border );
|
||||
|
||||
base.OnPaint(pe);
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Draws the plot surface on the supplied graphics surface [not the control surface].
|
||||
/// </summary>
|
||||
/// <param name="g">The graphics surface on which to draw</param>
|
||||
/// <param name="bounds">A bounding box on this surface that denotes the area on the
|
||||
/// surface to confine drawing to.</param>
|
||||
public void Draw( Graphics g, Rectangle bounds )
|
||||
{
|
||||
try
|
||||
{
|
||||
Inner.Draw( g, bounds );
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
System.Diagnostics.Debugger.Log( 1, "", "Exception drawing plot:" + ex + "\r\n" );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Padding of this width will be left between what is drawn and the control border.
|
||||
/// </summary>
|
||||
[
|
||||
Category("PlotSurface2D"),
|
||||
Description("Padding of this width will be left between what is drawn and the control border."),
|
||||
Browsable(true)
|
||||
]
|
||||
public int Padding
|
||||
{
|
||||
get
|
||||
{
|
||||
return Inner.Padding;
|
||||
}
|
||||
set
|
||||
{
|
||||
Inner.Padding = value;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Adds a drawable object to the plot surface against the specified axes. If
|
||||
/// the object is an IPlot, the PlotSurface2D axes will also be updated.
|
||||
/// </summary>
|
||||
/// <param name="p">the IDrawable object to add to the plot surface</param>
|
||||
/// <param name="xAxis">the x-axis to add the plot against.</param>
|
||||
/// <param name="yAxis">the y-axis to add the plot against.</param>am>
|
||||
public void Add( IDrawable p, string xAxis, string yAxis )
|
||||
{
|
||||
this.Inner.Add( p, xAxis, yAxis );
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
*/
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -0,0 +1,295 @@
|
|||
0.9.9.2 28 Feb 2006
|
||||
|
||||
Fixed bug in DateTimeAxis.WorldTickPositions_FirstPass reported by Pawel Konieczny.
|
||||
Fixed a bug in WorldTickPositions_SecondPass - thanks to Pawel Konieczny.
|
||||
Fixed a problem in Axis.WorldToPhysical - Thanks to Pawel Konieczny again for this one.
|
||||
Adding TradingDateTimeAxis contributed by Pawel Konieczny.
|
||||
Made changes to DateTimeAxis to allow TradingDateTimeAxis to work.
|
||||
Added Line in legend for point plot in appropriate case (thanks to Pawel Konieczny).
|
||||
Pawel Konieczny: Fixing suggested axes in BarPlot, which did not take into account
|
||||
all Y points originally. Made bar width configurable
|
||||
Pawel Konieczny: A small fix for vertical and horizontal guidelines, to remove
|
||||
their remnants from the plot. The remnants can be left over when the
|
||||
mouse move is fast such that the interaction does not get enough move
|
||||
even to remove itself. This fix does not really solve all problems with
|
||||
guidelines; for instance, try the following: run a demo application with
|
||||
a plot with a guideline, cover part of the plot by a window of another
|
||||
program, then hover the mouse over the not obscured area of the plot.
|
||||
Pawel Konieczny: A fix in CandlePlot.CalculatePhysicalSeparation(). The
|
||||
original code bombs with a null pointer exception when there are exactly
|
||||
three points.
|
||||
Pawel Konieczny: fixed bugs in horizontal and vertical drag interactions when
|
||||
the axis is non-linear. It fixes also a small bug for a linear axes,
|
||||
which led to a slight and steady zoom-in process when dragging the plot
|
||||
somewhat longer.
|
||||
Pawel Konieczny: fixed bugs in axis drag interaction for non-linear axes.
|
||||
Pawel Konieczny: MouseWheelZoom (which actually does scroll) adapted to
|
||||
non-linear axes. Additionally, Interaction.MouseWheelZoom improved to do
|
||||
zoom and handle Y axis too.
|
||||
Pawel Konieczny: Performance enhancements to CandlePlot
|
||||
Pawel Konieczny: Performance enhancements to LinePlot
|
||||
Pawel Konieczny: Performance enhancements to Transform2D
|
||||
Pawel Konieczny: Performance enhancements to SequenceAdapter
|
||||
Pawel Konieczny: Performance enhancements to PointPlot
|
||||
Pawel Konieczny: DataGetter_DoublesArray added to AdapeterUtils
|
||||
Pawel Konieczny: Performance enhancements to Windows.PlotSurface2D and
|
||||
contained classes.
|
||||
Added comments to uncommented public methods.
|
||||
Pawel Konieczny: This one makes HorizontalRangeSelection forgiving accidental
|
||||
clicks. Originally, a single click on a plot area with
|
||||
HorizontalRangeSelection active would immediately zoom into an
|
||||
indefinitely small zoom window. The change makes the interaction to
|
||||
ignore very small selections, that may be made accidentally (I suppose
|
||||
nobody would try to make deliberately such small selections, simply
|
||||
because it is very hard to make them accurately with a mouse).
|
||||
Matt: Added a property to set minimum select width in pixels in
|
||||
HorizontalRangeSelection.
|
||||
Pawel Konieczny: This one allows changing list of interactions on MouseUp.
|
||||
Originally, on MouseUp, the list of the registered interactions is
|
||||
looped through to dispatch the event. However, since the list is being
|
||||
looped, it cannot be modified during that process (otherwise an
|
||||
exception occurs).
|
||||
Pawel Konieczny: I have added handling of "MouseLeave" to the list of events
|
||||
that interaction may react to. This fine tunes the problem of "cleaning
|
||||
up" the guidelines (not unconditionally anymore), and is used in some
|
||||
new interactions I will send you later.
|
||||
Pawel Konieczny: I have disable the check whether the candle width is not
|
||||
zero. The effect was that when the amount of data displayed increases
|
||||
(e.g. zoom out) and the candles got thinner and thinner, suddenly they
|
||||
become thick again, overlapping each other. It may be even so, that by
|
||||
scrolling left or right, due to different rounding errors, they become
|
||||
thin again, and then again thick. I don't think it is useful to
|
||||
prohibit candles of zero width (there always will be the vertical line
|
||||
visible), since in such cases the distance between them is so small that
|
||||
they form an almost contiguous fill region.
|
||||
Pawel Konieczny: A few changes to ImagePlot. The point here is that the
|
||||
ImagePlot by default uses the gradient to span from the minimum value to
|
||||
maximum value. This is sometimes useful, but sometimes not. For
|
||||
instance, when the image plot is used to show a sort of a topographic
|
||||
map, where each color should correspond to some absolute value. The
|
||||
changes here allow to explicitly set the values corresponding to the
|
||||
gradient boundaries. Values outside the boundaries are mapped to the
|
||||
boundary colors (that functionality was already present in the
|
||||
gradient code, except that some debug check was throwing an exception
|
||||
when it happened - I had to remove that too). For instance, values of
|
||||
0.0 and all negatives could be mapped to black. I have also added a
|
||||
possibility of a "void" color, which is used for NaN values. I use NaN
|
||||
values to indicate that no data is present for a given point.
|
||||
Pawel Konieczny: A small patch in drawing a shadow of the legend box. In the
|
||||
original NPlot, the shadow is not really a shadow - it is a light gray
|
||||
opaque rectangle box.
|
||||
Small fix from Rosco to allow zero height bars in BarPlot.
|
||||
Added data clipping speed up code to StepPlot (similar to code in Line, Point
|
||||
and CandlePlot).
|
||||
Added SmallestAllowedRange property to HorizontalRangeSelection interaction.
|
||||
|
||||
|
||||
0.9.9.1 20 Feb 2006 (not released).
|
||||
|
||||
Fixed bug with Linear Axis Offset and Scale properties which caused incorrect display.
|
||||
|
||||
|
||||
0.9.9 22 July 2005
|
||||
|
||||
Added LegendZOrder to PlotSurface2D.
|
||||
Added PhysicalSpacingMin to LabelAxis
|
||||
Added RemoveInteraction method to Windows.PlotSurface2D. Thanks to Måns Erlandson.
|
||||
Fixed bug in Windows.PlotSurface2D.DoMouseMove reported by Måns Erlandson.
|
||||
Added StepGradient with RGB and Rainbow types.
|
||||
Ivan Ivanov fixed a bug in the Web Control when url contains params.
|
||||
Image stored in session variable is now explicitly deleted (known issue, but thanks
|
||||
to Ivan Ivanov for pointing this out also).
|
||||
Fixed up designer attributes in web control.
|
||||
Other (substantial) tweaking of web control. Note that this will eventually use the
|
||||
DynamicImage control in ASP.NET 2.0, this control will be much more efficient.
|
||||
Revised attributes (Bindable, Browsable, Description, Category) on relevant public
|
||||
properties on Windows.PlotSurface2D.
|
||||
Rosco Hill pointed out a bug in RefreshZOrdering.
|
||||
Spent quite a lot of time designing MultiLinePlot and MultiSequenceAdapter classes
|
||||
and supporting functions in AdapterUtils. There are issues remaining. I have
|
||||
left this out of pre 1.0 releases.
|
||||
Now prints title in centre of plot if there is no data.
|
||||
Took StringFormat construction out of PlotSurface2D.Draw method and put in
|
||||
constructor (to avoid unnecessarily creating this many times).
|
||||
Removed PlotSurface3D and all related.
|
||||
Removed PlotSurface2Dnew and all related.
|
||||
Removed BubblePlot.cs
|
||||
Removed PLotSurface and all related.
|
||||
Removed StartStep and all related.
|
||||
Removed MathExtra from Utils (3D calculations)
|
||||
Finished commenting AdapterUtils
|
||||
Filled in missing comments from other classes as well.
|
||||
Deleted ErrorHandler class (wasn't a good move that one...).
|
||||
Added NPlotException class - all NPlot exceptions throw of this type.
|
||||
Added quick fix from Rosco Hill for fixing weird behaviour when Legend is wider
|
||||
than plotting surface.
|
||||
Changed ToBrowser method in Bitmap.PlotSurface2D to ToStream and to take image
|
||||
format parameter.
|
||||
|
||||
|
||||
0.9.8.9 [21 May 2005]
|
||||
|
||||
Gareth Hayter found the bug introduced in 0.9.8.8 whereby LinePlots are sometimes
|
||||
not drawn.
|
||||
Added LengthScale and PixelIndent properties to VerticalLine and HorizontalLine
|
||||
Added ability to have multiple lines of text in the title.
|
||||
Added HideVerticalLines property to StepPlot
|
||||
Added HideHorizontalLines property to StepPlot.
|
||||
Added ScaleWidth property to StepPlot.
|
||||
Added zOffset to Windows.PlotSurface2D Web.PlotSurface2D and Bitmap.PlotSurface2D
|
||||
classes.
|
||||
Legends can now have items placed in a grid (not just vertically).
|
||||
Added BarPlot for charting a series of two ordinate values as bars. This still
|
||||
has work to go - the horizontal spacing is just a hack at the moment.
|
||||
Added ability of legend to grow horizontally or vertically, and to specify the
|
||||
maximum in the other direction.
|
||||
Ticks can be placed between labels in the label axis.
|
||||
|
||||
|
||||
0.9.8.8 [15 May 2005]
|
||||
|
||||
Added functionality to Filled region such that VerticalLine or Horizontal lines
|
||||
can be specified in the bounds.
|
||||
Added functionality that allows data to be obtained from arrays in CandleAdapter
|
||||
class. Code implemented was a more general version of that contributed Gareth
|
||||
Hayter.
|
||||
Added new demo plot to demonstrate this.
|
||||
Fixed problem with PlotSurface2D.Remove reported by Jonne van Wijngaarden.
|
||||
Added patch from Jonne van Wijngaarden that makes axes drag expand from the point
|
||||
clicked rather than the center.
|
||||
Bug fix by Rosco Hill in line plot when zoomed right in.
|
||||
Rosco Hill added code to draw small ticks in DateTime axis when in year mode.
|
||||
Anton fixed a bug in Web.PlotSurface2D.
|
||||
Change by Mike Miller for drawing Large Tickes on DateTime axes for time-spans
|
||||
greater than 30 years.
|
||||
Fix by Mike Miller in WorldToPhysical. Great work traking this one down.
|
||||
Implemented z-ordering in PlotSurface2D Add methods after suggestion by Gareth
|
||||
Hayter.
|
||||
Revised default positioning of candle bars based on justification by Mike Miller.
|
||||
Added Centered property to CandlePlot to chose between old default and new
|
||||
default positioning of bars.
|
||||
Converted back to VS2003 solution file.
|
||||
René van Kleef fixed a bug in linear axis on large zooms.
|
||||
Fixed Reversed flag not working anymore bug reported by "Steven". Thanks to
|
||||
René van Kleef for finding the problem.
|
||||
Fixed error found by René van Kleef in MarkerItem - incorrectly derived from
|
||||
Marker
|
||||
Added Constructors to MarkerItem as suggested by René van Kleef.
|
||||
Added TextItem implementation submitted by René van Kleef.
|
||||
|
||||
|
||||
0.9.8.7 []
|
||||
|
||||
DateTimeAxis now scales down to second resolution.
|
||||
Added strong name key.
|
||||
Windows.Plotsurface2D.Draw no longer catches exceptions.
|
||||
Implemented interactions (lots of additions here).
|
||||
Large Chunk of 3D Plotsurface and related classes implemented.
|
||||
Changed axisCache variables in Windows.PlotSurface2D to zoomAxisCache.
|
||||
Changed "Zoom Back" to "Original Dimensions".
|
||||
Changed AllowSelection to EnableSelection.
|
||||
Added EnableDrag property and implementation.
|
||||
Arrow is not displayed if outside area of chart.
|
||||
Made threads created in demo STA. Made CopyToClipboard copy = true.
|
||||
Changed DateTimeAxis such that if scaled such that tick spacings every 2, 7, or 14 days, ticks
|
||||
are always placed in the same spot regardless of WorldMin / WorldMax.
|
||||
Changed Axis.Length property name to Axis.WorldLength.
|
||||
Added LabelOffsetAbsolute property to Axis class.
|
||||
|
||||
|
||||
0.9.8.5 [15 February 2005]
|
||||
|
||||
Przemyslaw Grodzki pointed out a Windows bug which caused "copy data to
|
||||
clipboard" to crash, and provided a solution.
|
||||
Added check for null in RightMenu property of Windows.PlotSurface2D.
|
||||
Made NumberFormat null on DateTimeAxis Axis copy constructor to avoid formatting
|
||||
problems when constrructing from non DateTime axes.
|
||||
Changed the space between values in "copy data to clipboard" to a tab. This
|
||||
makes it easier to insert values into Microsoft Excel and other programs.
|
||||
Removed redundent WorldMin and WorldMax properties from DateTimeAxis.
|
||||
|
||||
|
||||
0.9.8.4 [13 February 2005]
|
||||
Removed context menu from Windows.PlotSurface2D and provided public methods for all functions
|
||||
previously only available through the ContextMenu in Windows.PlotSurface2D.
|
||||
Created PlotContextMenu class and associated classes which allow the right context menu to be
|
||||
completely customized and extended.
|
||||
Created the PlotSurface class and rearranged PlotSurface2D such that this is possible. PlotSurface
|
||||
is not working completely yet, but the concept is proved. This is going to be an all encompasing
|
||||
class for all types of plot surfaces (PiePlotSurface, RadialPlotSurface PlotSurface3D etc). Thanks
|
||||
to Roberto Peña for useful discussions on this topic.
|
||||
Added Drawables property to PlotSurface2D
|
||||
Added CopyDataToClipboard functionality. This needs modifying now so that values reflect axis types.
|
||||
Minor changes to LogAxis (object->double).
|
||||
Added LabelOffset and LabelOffsetScaled to Axis class.
|
||||
Changed the default Axis Label offset so it looks better.
|
||||
Added HorizontalLine class to make drawing horizontal lines easy (it takes a bit of
|
||||
effort to set up a LinePlot to do this).
|
||||
Added VerticalLine class as well.
|
||||
Added PiAxis class. Currently this can only print labels at integral values of Pi.
|
||||
Added placeholder for TextItem. This IDrawable is needed.
|
||||
Added RectangleD. This is used for CopyDataToClipboard
|
||||
When no tick marks are shown, the Axis label position is now shown in a more reasonable position.
|
||||
Rearranged the demo.
|
||||
Bug when O/L/C/H value is NaN fixed in CandlePlot by Florian Hoertlehner.
|
||||
Roberto Peña fixed a bug in LegendBase in the case that there are no lines.
|
||||
|
||||
|
||||
0.9.8.3 [23 January 2005]
|
||||
|
||||
Florian Hoertlehner provided better NaN handling ability in Utils.RowArrayMinMax.
|
||||
NPlot now is, and is marked CLSCompliant. Thanks to Roberto Peña for point this out.
|
||||
Added lots of pre-defined Solid RectangleBrushes. Still need to add lots of predefined other style brushes.
|
||||
Fixed bug whereby sometimes on Windows.Forms resize, the world bounds were randomly changing. The problem
|
||||
turned out to be in OnMouseUp function [proved v. hard to track down!].
|
||||
Cleaned up the demo code a bit.
|
||||
Removed PropertyGrid from Windows.PlotSurface2D. I've left all the object selection code in there as it
|
||||
will be useful in the future, but I don't wan't ProperyGrid to be on the control itself.
|
||||
|
||||
|
||||
0.9.8.2 [12 January 2005]
|
||||
|
||||
Added patch by Rosco Hill for removing drawables from PlotSurfaces.
|
||||
Fixed bug introduced in 0.9.8.1 that prevented LogAxes from working correctly. This
|
||||
involved improvements to Transform2D and related classes.
|
||||
|
||||
|
||||
0.9.8.1 [3 December 2004]
|
||||
|
||||
Przemyslaw Grodzki fixed a small internationalization bug in the demo.
|
||||
PlotSurface gradient backgrounds.
|
||||
PlotSurface Bitmap backgrounds.
|
||||
Added some ready to go RectangleBrushes.
|
||||
Improved efficiency of Line drawing - using optimized transform class.
|
||||
Added shadow property for line class.
|
||||
Juraj Skripsky fixed a bug in the SuggestYAxis method in HistogramPlot for stacked histograms.
|
||||
Fixed "shakey lines" bug due to sub-optimal rounding. Thanks to René van Kleef for pointing this out.
|
||||
Made Physical Axis Caches public in Windows.PlotSurface2D. Thanks to Stephan Puchegger for pointing this out.
|
||||
|
||||
|
||||
0.9.8 [17 November 2004]
|
||||
|
||||
SequenceAdapter can now handle DataViews.
|
||||
Revised implementation and interaction of Color, Pen and Brush properties in appropriate classes.
|
||||
Added ArrowItem Drawable object.
|
||||
Added skeleton code for 3D plots. No implementation yet.
|
||||
Added Miguel's patch that reduces excessive memory allocations due to font scaling.
|
||||
Applied many other similar optimizations.
|
||||
In process of rethinking license.
|
||||
ScreenAlignedPhysicalAxis (not in use yet).
|
||||
Transform2D class skeleton (not in use yet).
|
||||
Cleaned up Marker.cs. Removed creation of Brush object in every call to Draw.
|
||||
Added MarkerItem IDrawable.
|
||||
Made RectangleBrush classes [moving out of HistogramPlot].
|
||||
Changed lots of floats to ints - convention:
|
||||
* double in world domain.
|
||||
* in physical domain: float only where need for accurate calculations, otherwise int.
|
||||
* float for angles (not doubles) - as with .net Graphics class.
|
||||
made candle widths depend on distance between successive points.
|
||||
Added patches by Alexander Kucheravy relating to angled tick labels and large tick spacing for DateTime Axes.
|
||||
|
||||
|
||||
0.9.7 [4 November 2004]
|
||||
|
||||
change log started.
|
||||
|
|
@ -0,0 +1,94 @@
|
|||
House Rules and random notes:
|
||||
|
||||
Note: I haven't followed these always. They reflect my current preferences, which
|
||||
vary a little from time to time. Anything reasonably close is good enough.
|
||||
|
||||
|
||||
o Classes begin with a capital letter and each world is capitalized. Eg:
|
||||
|
||||
HistogramPlot
|
||||
|
||||
|
||||
o Class member functions begin with capital letter and each word is capitalized. Eg:
|
||||
|
||||
public void DrawTicks()
|
||||
|
||||
|
||||
o Class member variables begin with a lower case letter, each word there-after capitalized.
|
||||
Trailing underscore. Eg:
|
||||
|
||||
float worldMax_
|
||||
|
||||
|
||||
o variables begin with a lower case letter, each world there-after capitalized.
|
||||
This includes variables in a argumant list. Eg:
|
||||
|
||||
float worldMax
|
||||
public void DrawTicks( float myArgument )
|
||||
|
||||
|
||||
o use ++i over i++. (habbit from c++, ++i never less efficient than i++, sometimes more).
|
||||
|
||||
|
||||
o always use braces. Do:
|
||||
|
||||
if ( a == 3 )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
not
|
||||
|
||||
if ( a == 3 )
|
||||
return;
|
||||
|
||||
|
||||
o add your name to the copyright list of a file if you do significant modifications
|
||||
to it, or create it.
|
||||
|
||||
|
||||
o Don't use hungarian notation. :-). It's not the done thing in C#, and the other
|
||||
rules here allow differentiation between identifier types.
|
||||
|
||||
|
||||
o braces like this:
|
||||
|
||||
if (a == 3)
|
||||
{
|
||||
Console.WriteLine( "Hello world\n" );
|
||||
}
|
||||
|
||||
not like this:
|
||||
|
||||
if (a == 3) {
|
||||
Console.WriteLine( "Hello world\n" );
|
||||
}
|
||||
|
||||
|
||||
o spaces like this:
|
||||
|
||||
if (a == 3)
|
||||
|
||||
not like this:
|
||||
|
||||
if( a == 3 )
|
||||
|
||||
or this:
|
||||
|
||||
if (a==3)
|
||||
|
||||
or this:
|
||||
|
||||
if(a==3)
|
||||
|
||||
o Comments:
|
||||
|
||||
(1) Avoid obvious comments, they annoy me.
|
||||
(2) Make sure you _really_ understand what is going on before commenting. No comment is much much better than an incorrect comment.
|
||||
(3) Use comments to leave notes to other coders (in particular me), so that I can quickly
|
||||
see what has changed. I'll feel free to delete them.
|
||||
|
||||
o CVS:
|
||||
|
||||
Don't check in code that doesn't compile and run.
|
||||
|
Двоичный файл не отображается.
После Ширина: | Высота: | Размер: 318 B |
|
@ -0,0 +1,44 @@
|
|||
NPlot - A charting library for .NET
|
||||
Copyright (C) 2003-2005 Matt Howlett and others.
|
||||
|
||||
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.
|
Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше
Загрузка…
Ссылка в новой задаче