1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432 |
- // Licensed to the .NET Foundation under one or more agreements.
- // The .NET Foundation licenses this file to you under the MIT license.
- // See the LICENSE file in the project root for more information.
- //
- // Purpose: The chart element is base class for the big number
- // of classes. It stores common methods and data.
- //
- using System;
- using System.Diagnostics.CodeAnalysis;
- using System.Drawing.Drawing2D;
- namespace FastReport.DataVisualization.Charting
- {
- #region Enumerations
- /// <summary>
- /// An enumeration that specifies a label alignment.
- /// </summary>
- [
- Flags
- ]
- public enum LabelAlignmentStyles
- {
- /// <summary>
- /// Label is aligned to the top of the data point.
- /// </summary>
- Top = 1,
- /// <summary>
- /// Label is aligned to the bottom of the data point.
- /// </summary>
- Bottom = 2,
- /// <summary>
- /// Label is aligned to the right of the data point.
- /// </summary>
- Right = 4,
- /// <summary>
- /// Label is aligned to the left of the data point.
- /// </summary>
- Left = 8,
- /// <summary>
- /// Label is aligned to the top-left corner of the data point.
- /// </summary>
- TopLeft = 16,
- /// <summary>
- /// Label is aligned to the top-right corner of the data point.
- /// </summary>
- TopRight = 32,
- /// <summary>
- /// Label is aligned to the bottom-left of the data point.
- /// </summary>
- BottomLeft = 64,
- /// <summary>
- /// Label is aligned to the bottom-right of the data point.
- /// </summary>
- BottomRight = 128,
- /// <summary>
- /// Label is aligned to the center of the data point.
- /// </summary>
- Center = 256,
- }
- /// <summary>
- /// An enumeration of chart types.
- /// </summary>
- public enum SeriesChartType
- {
- /// <summary>
- /// Point chart type.
- /// </summary>
- Point,
- /// <summary>
- /// FastPoint chart type.
- /// </summary>
- FastPoint,
- /// <summary>
- /// Bubble chart type.
- /// </summary>
- Bubble,
- /// <summary>
- /// Line chart type.
- /// </summary>
- Line,
- /// <summary>
- /// Spline chart type.
- /// </summary>
- Spline,
- /// <summary>
- /// StepLine chart type.
- /// </summary>
- StepLine,
- /// <summary>
- /// FastLine chart type.
- /// </summary>
- FastLine,
- /// <summary>
- /// Bar chart type.
- /// </summary>
- Bar,
- /// <summary>
- /// Stacked bar chart type.
- /// </summary>
- StackedBar,
- /// <summary>
- /// Hundred percent stacked bar chart type.
- /// </summary>
- StackedBar100,
- /// <summary>
- /// Column chart type.
- /// </summary>
- Column,
- /// <summary>
- /// Stacked column chart type.
- /// </summary>
- StackedColumn,
- /// <summary>
- /// Hundred percent stacked column chart type.
- /// </summary>
- StackedColumn100,
- /// <summary>
- /// Area chart type.
- /// </summary>
- Area,
- /// <summary>
- /// Spline area chart type.
- /// </summary>
- SplineArea,
- /// <summary>
- /// Stacked area chart type.
- /// </summary>
- StackedArea,
- /// <summary>
- /// Hundred percent stacked area chart type.
- /// </summary>
- StackedArea100,
- /// <summary>
- /// Pie chart type.
- /// </summary>
- Pie,
- /// <summary>
- /// Doughnut chart type.
- /// </summary>
- Doughnut,
- /// <summary>
- /// Stock chart type.
- /// </summary>
- Stock,
- /// <summary>
- /// CandleStick chart type.
- /// </summary>
- Candlestick,
- /// <summary>
- /// Range chart type.
- /// </summary>
- Range,
- /// <summary>
- /// Spline range chart type.
- /// </summary>
- SplineRange,
- /// <summary>
- /// RangeBar chart type.
- /// </summary>
- RangeBar,
- /// <summary>
- /// Range column chart type.
- /// </summary>
- RangeColumn,
- /// <summary>
- /// Radar chart type.
- /// </summary>
- Radar,
- /// <summary>
- /// Polar chart type.
- /// </summary>
- Polar,
- /// <summary>
- /// Error bar chart type.
- /// </summary>
- ErrorBar,
- /// <summary>
- /// Box plot chart type.
- /// </summary>
- BoxPlot,
- /// <summary>
- /// Renko chart type.
- /// </summary>
- [SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Renko")]
- Renko,
- /// <summary>
- /// ThreeLineBreak chart type.
- /// </summary>
- ThreeLineBreak,
- /// <summary>
- /// Kagi chart type.
- /// </summary>
- [SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Kagi")]
- Kagi,
- /// <summary>
- /// PointAndFigure chart type.
- /// </summary>
- PointAndFigure,
- /// <summary>
- /// Funnel chart type.
- /// </summary>
- Funnel,
- /// <summary>
- /// Pyramid chart type.
- /// </summary>
- Pyramid,
- }
- /// <summary>
- /// Axis Arrow orientation
- /// </summary>
- internal enum ArrowOrientation
- {
- /// <summary>
- /// Arrow direction is Right - Left
- /// </summary>
- Left,
- /// <summary>
- /// Arrow direction is Left - Right
- /// </summary>
- Right,
- /// <summary>
- /// Arrow direction is Bottom - Top
- /// </summary>
- Top,
- /// <summary>
- /// Arrow direction is Top - Bottom
- /// </summary>
- Bottom
- }
- /// <summary>
- /// An enumeration of image alignment.
- /// </summary>
- public enum ChartImageAlignmentStyle
- {
- /// <summary>
- /// The mage is aligned to the top left corner of the chart element.
- /// </summary>
- TopLeft,
- /// <summary>
- /// The image is aligned to the top boundary of the chart element.
- /// </summary>
- Top,
- /// <summary>
- /// The image is aligned to the top right corner of the chart element.
- /// </summary>
- TopRight,
- /// <summary>
- /// The image is aligned to the right boundary of the chart element.
- /// </summary>
- Right,
- /// <summary>
- /// The image is aligned to the bottom right corner of the chart element.
- /// </summary>
- BottomRight,
- /// <summary>
- /// The image is aligned to the bottom boundary of the chart element.
- /// </summary>
- Bottom,
- /// <summary>
- /// The image is aligned to the bottom left corner of the chart element.
- /// </summary>
- BottomLeft,
- /// <summary>
- /// The image is aligned to the left boundary of the chart element.
- /// </summary>
- Left,
- /// <summary>
- /// The image is aligned in the center of the chart element.
- /// </summary>
- Center
- };
- /// <summary>
- /// An enumeration that specifies a background image drawing mode.
- /// </summary>
- public enum ChartImageWrapMode
- {
- /// <summary>
- /// Background image is scaled to fit the entire chart element.
- /// </summary>
- Scaled = WrapMode.Clamp,
- /// <summary>
- /// Background image is tiled to fit the entire chart element.
- /// </summary>
- Tile = WrapMode.Tile,
- /// <summary>
- /// Every other tiled image is reversed around the X-axis.
- /// </summary>
- TileFlipX = WrapMode.TileFlipX,
- /// <summary>
- /// Every other tiled image is reversed around the X-axis and Y-axis.
- /// </summary>
- TileFlipXY = WrapMode.TileFlipXY,
- /// <summary>
- /// Every other tiled image is reversed around the Y-axis.
- /// </summary>
- TileFlipY = WrapMode.TileFlipY,
- /// <summary>
- /// Background image is not scaled.
- /// </summary>
- [SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Unscaled")]
- Unscaled = 100
- };
- /// <summary>
- /// An enumeration that specifies the state of an axis.
- /// </summary>
- public enum AxisEnabled
- {
- /// <summary>
- /// The axis is only enabled if it used to plot a Series.
- /// </summary>
- Auto,
-
- /// <summary>
- /// The axis is always enabled.
- /// </summary>
- True,
-
- /// <summary>
- /// The axis is never enabled.
- /// </summary>
- False
- };
- /// <summary>
- /// An enumeration of units of measurement of an interval.
- /// </summary>
- public enum DateTimeIntervalType
- {
- /// <summary>
- /// Automatically determined by the Chart control.
- /// </summary>
- Auto,
-
- /// <summary>
- /// The interval is numerical.
- /// </summary>
- Number,
-
- /// <summary>
- /// The interval is years.
- /// </summary>
- Years,
-
- /// <summary>
- /// The interval is months.
- /// </summary>
- Months,
-
- /// <summary>
- /// The interval is weeks.
- /// </summary>
- Weeks,
-
- /// <summary>
- /// The interval is days.
- /// </summary>
- Days,
-
- /// <summary>
- /// The interval is hours.
- /// </summary>
- Hours,
-
- /// <summary>
- /// The interval is minutes.
- /// </summary>
- Minutes,
- /// <summary>
- /// The interval is seconds.
- /// </summary>
- Seconds,
-
- /// <summary>
- /// The interval is milliseconds.
- /// </summary>
- Milliseconds,
- /// <summary>
- /// The interval type is not defined.
- /// </summary>
- NotSet,
- }
- /// <summary>
- /// An enumeration that specifies value types for various chart properties
- /// </summary>
- public enum ChartValueType
- {
- /// <summary>
- /// Property type is set automatically by the Chart control.
- /// </summary>
- Auto,
-
- /// <summary>
- /// Double value.
- /// </summary>
- Double,
-
- /// <summary>
- /// Single value.
- /// </summary>
- Single,
-
- /// <summary>
- /// Int32 value.
- /// </summary>
- Int32,
-
- /// <summary>
- /// Int64 value.
- /// </summary>
- Int64,
-
- /// <summary>
- /// UInt32 value.
- /// </summary>
- [SuppressMessage("Microsoft.Naming", "CA1702:CompoundWordsShouldBeCasedCorrectly",
- Justification = "These names are patterned after the standard CLR types for consistency")]
- UInt32,
-
- /// <summary>
- /// UInt64 value.
- /// </summary>
- [SuppressMessage("Microsoft.Naming", "CA1702:CompoundWordsShouldBeCasedCorrectly",
- Justification = "These names are patterned after the standard CLR types for consistency")]
- UInt64,
-
- /// <summary>
- /// String value.
- /// </summary>
- String,
-
- /// <summary>
- /// DateTime value.
- /// </summary>
- DateTime,
- /// <summary>
- /// Date portion of the DateTime value.
- /// </summary>
- Date,
- /// <summary>
- /// Time portion of the DateTime value.
- /// </summary>
- Time,
- /// <summary>
- /// DateTime with offset
- /// </summary>
- DateTimeOffset
- };
- /// <summary>
- /// An enumeration that specifies a hatching style.
- /// </summary>
- public enum ChartHatchStyle
- {
- /// <summary>
- /// No hatching style.
- /// </summary>
- None,
- /// <summary>
- /// Backward diagonal style.
- /// </summary>
- BackwardDiagonal,
- /// <summary>
- /// Cross style.
- /// </summary>
- Cross,
- /// <summary>
- /// Dark downward diagonal style.
- /// </summary>
- DarkDownwardDiagonal,
- /// <summary>
- /// Dark horizontal style.
- /// </summary>
- DarkHorizontal,
- /// <summary>
- /// Dark upward diagonal style.
- /// </summary>
- DarkUpwardDiagonal,
- /// <summary>
- /// Dark vertical style.
- /// </summary>
- DarkVertical,
- /// <summary>
- /// Dashed downward diagonal style.
- /// </summary>
- DashedDownwardDiagonal,
- /// <summary>
- /// Dashed horizontal style.
- /// </summary>
- DashedHorizontal,
- /// <summary>
- /// Dashed upward diagonal style.
- /// </summary>
- DashedUpwardDiagonal,
- /// <summary>
- /// Dashed vertical style.
- /// </summary>
- DashedVertical,
- /// <summary>
- /// Diagonal brick style.
- /// </summary>
- DiagonalBrick,
- /// <summary>
- /// Diagonal cross style.
- /// </summary>
- DiagonalCross,
- /// <summary>
- /// Divot style.
- /// </summary>
- Divot,
- /// <summary>
- /// Dotted diamond style.
- /// </summary>
- DottedDiamond,
- /// <summary>
- /// Dotted grid style.
- /// </summary>
- DottedGrid,
- /// <summary>
- /// Forward diagonal style.
- /// </summary>
- ForwardDiagonal,
- /// <summary>
- /// Horizontal style.
- /// </summary>
- Horizontal,
- /// <summary>
- /// Horizontal brick style.
- /// </summary>
- HorizontalBrick,
- /// <summary>
- /// Large checker board style.
- /// </summary>
- [SuppressMessage("Microsoft.Naming", "CA1702:CompoundWordsShouldBeCasedCorrectly", MessageId = "CheckerBoard")]
- LargeCheckerBoard,
- /// <summary>
- /// Large confetti style.
- /// </summary>
- LargeConfetti,
- /// <summary>
- /// Large grid style.
- /// </summary>
- LargeGrid,
- /// <summary>
- /// Light downward diagonal style.
- /// </summary>
- LightDownwardDiagonal,
- /// <summary>
- /// Light horizontal style.
- /// </summary>
- LightHorizontal,
- /// <summary>
- /// Light upward diagonal style.
- /// </summary>
- LightUpwardDiagonal,
- /// <summary>
- /// Light vertical style.
- /// </summary>
- LightVertical,
- /// <summary>
- /// Narrow horizontal style.
- /// </summary>
- NarrowHorizontal,
- /// <summary>
- /// Narrow vertical style.
- /// </summary>
- NarrowVertical,
- /// <summary>
- /// Outlined diamond style.
- /// </summary>
- OutlinedDiamond,
- /// <summary>
- /// Percent05 style.
- /// </summary>
- Percent05,
- /// <summary>
- /// Percent10 style.
- /// </summary>
- Percent10,
- /// <summary>
- /// Percent20 style.
- /// </summary>
- Percent20,
- /// <summary>
- /// Percent25 style.
- /// </summary>
- Percent25,
- /// <summary>
- /// Percent30 style.
- /// </summary>
- Percent30,
- /// <summary>
- /// Percent40 style.
- /// </summary>
- Percent40,
- /// <summary>
- /// Percent50 style.
- /// </summary>
- Percent50,
- /// <summary>
- /// Percent60 style.
- /// </summary>
- Percent60,
- /// <summary>
- /// Percent70 style.
- /// </summary>
- Percent70,
- /// <summary>
- /// Percent75 style.
- /// </summary>
- Percent75,
- /// <summary>
- /// Percent80 style.
- /// </summary>
- Percent80,
- /// <summary>
- /// Percent90 style.
- /// </summary>
- Percent90,
- /// <summary>
- /// Plaid style.
- /// </summary>
- Plaid,
- /// <summary>
- /// Shingle style.
- /// </summary>
- Shingle,
- /// <summary>
- /// Small checker board style.
- /// </summary>
- [SuppressMessage("Microsoft.Naming", "CA1702:CompoundWordsShouldBeCasedCorrectly", MessageId = "CheckerBoard")]
- SmallCheckerBoard,
- /// <summary>
- /// Small confetti style.
- /// </summary>
- SmallConfetti,
- /// <summary>
- /// Small grid style.
- /// </summary>
- SmallGrid,
- /// <summary>
- /// Solid diamond style.
- /// </summary>
- SolidDiamond,
- /// <summary>
- /// Sphere style.
- /// </summary>
- Sphere,
- /// <summary>
- /// Trellis style.
- /// </summary>
- Trellis,
- /// <summary>
- /// Vertical style.
- /// </summary>
- Vertical,
- /// <summary>
- /// Wave style.
- /// </summary>
- Wave,
- /// <summary>
- /// Weave style.
- /// </summary>
- Weave,
- /// <summary>
- /// Wide downward diagonal style.
- /// </summary>
- WideDownwardDiagonal,
- /// <summary>
- /// Wide upward diagonal style.
- /// </summary>
- WideUpwardDiagonal,
- /// <summary>
- /// ZigZag style.
- /// </summary>
- [SuppressMessage("Microsoft.Naming", "CA1702:CompoundWordsShouldBeCasedCorrectly", MessageId = "ZigZag")]
- [SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Zig")]
- [SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Zag")]
- ZigZag
- };
- /// <summary>
- /// An enumeration that specifies the level of anti-aliasing quality.
- /// </summary>
- public enum TextAntiAliasingQuality
- {
- /// <summary>
- /// Normal anti-aliasing quality.
- /// </summary>
- Normal,
- /// <summary>
- /// High anti-aliasing quality.
- /// </summary>
- High,
- /// <summary>
- /// System default anti-aliasing quality.
- /// </summary>
- SystemDefault
- }
- /// <summary>
- /// An enumeration of anti-aliasing flags.
- /// </summary>
- [Flags]
- public enum AntiAliasingStyles
- {
- /// <summary>
- /// No anti-aliasing.
- /// </summary>
- None = 0,
- /// <summary>
- /// Use anti-aliasing when drawing text.
- /// </summary>
- Text = 1,
- /// <summary>
- /// Use anti-aliasing when drawing grahics primitives (e.g. lines, rectangle)
- /// </summary>
- Graphics = 2,
- /// <summary>
- /// Use anti-alias for everything.
- /// </summary>
- All = Text | Graphics
- };
-
- /// <summary>
- /// An enumeration of marker styles.
- /// </summary>
- public enum MarkerStyle
- {
- /// <summary>
- /// No marker is displayed for the series/data point.
- /// </summary>
- None = 0,
- /// <summary>
- /// A square marker is displayed.
- /// </summary>
- Square = 1,
- /// <summary>
- /// A circle marker is displayed.
- /// </summary>
- Circle = 2,
- /// <summary>
- /// A diamond-shaped marker is displayed.
- /// </summary>
- Diamond = 3,
- /// <summary>
- /// A triangular marker is displayed.
- /// </summary>
- Triangle = 4,
- /// <summary>
- /// A cross-shaped marker is displayed.
- /// </summary>
- Cross = 5,
- /// <summary>
- /// A 4-point star-shaped marker is displayed.
- /// </summary>
- Star4 = 6,
- /// <summary>
- /// A 5-point star-shaped marker is displayed.
- /// </summary>
- Star5 = 7,
- /// <summary>
- /// A 6-point star-shaped marker is displayed.
- /// </summary>
- Star6 = 8,
- /// <summary>
- /// A 10-point star-shaped marker is displayed.
- /// </summary>
- Star10 = 9
- };
- /// <summary>
- /// An enumeration of gradient styles.
- /// </summary>
- public enum GradientStyle
- {
- /// <summary>
- /// No gradient is used.
- /// </summary>
- None,
-
- /// <summary>
- /// Gradient is applied from left to right.
- /// </summary>
- LeftRight,
-
- /// <summary>
- /// Gradient is applied from top to bottom.
- /// </summary>
- TopBottom,
-
- /// <summary>
- /// Gradient is applied from the center outwards.
- /// </summary>
- Center,
-
- /// <summary>
- /// Gradient is applied diagonally from left to right.
- /// </summary>
- DiagonalLeft,
-
- /// <summary>
- /// Gradient is applied diagonally from right to left.
- /// </summary>
- DiagonalRight,
-
- /// <summary>
- /// Gradient is applied horizontally from the center outwards.
- /// </summary>
- HorizontalCenter,
-
- /// <summary>
- /// Gradient is applied vertically from the center outwards.
- /// </summary>
- VerticalCenter
- };
- #endregion
-
- #region ChartElement
- /// <summary>
- /// Common chart helper methods used across different chart elements.
- /// </summary>
- internal class ChartHelper
- {
- #region Fields
- /// <summary>
- /// Maximum number of grid lines per Axis
- /// </summary>
- internal const int MaxNumOfGridlines = 10000;
- #endregion // Fields
- #region Constructor
- /// <summary>
- /// Private constructor to avoid instantiating the class
- /// </summary>
- private ChartHelper() { }
- #endregion // Constructor
- #region Methods
- /// <summary>
- /// Adjust the beginnin of the first interval depending on the type and size.
- /// </summary>
- /// <param name="start">Original start point.</param>
- /// <param name="intervalSize">Interval size.</param>
- /// <param name="type">AxisName of the interval (Month, Year, ...).</param>
- /// <returns>Adjusted interval start position as double.</returns>
- internal static double AlignIntervalStart(double start, double intervalSize, DateTimeIntervalType type)
- {
- return AlignIntervalStart(start, intervalSize, type, null);
- }
- /// <summary>
- /// Adjust the beginnin of the first interval depending on the type and size.
- /// </summary>
- /// <param name="start">Original start point.</param>
- /// <param name="intervalSize">Interval size.</param>
- /// <param name="type">AxisName of the interval (Month, Year, ...).</param>
- /// <param name="series">First series connected to the axis.</param>
- /// <returns>Adjusted interval start position as double.</returns>
- internal static double AlignIntervalStart(double start, double intervalSize, DateTimeIntervalType type, Series series)
- {
- return AlignIntervalStart( start, intervalSize, type, series, true );
- }
- /// <summary>
- /// Adjust the beginnin of the first interval depending on the type and size.
- /// </summary>
- /// <param name="start">Original start point.</param>
- /// <param name="intervalSize">Interval size.</param>
- /// <param name="type">AxisName of the interval (Month, Year, ...).</param>
- /// <param name="series">First series connected to the axis.</param>
- /// <param name="majorInterval">Interval is used for major gridlines or tickmarks.</param>
- /// <returns>Adjusted interval start position as double.</returns>
- internal static double AlignIntervalStart(double start, double intervalSize, DateTimeIntervalType type, Series series, bool majorInterval)
- {
- // Special case for indexed series
- if(series != null && series.IsXValueIndexed)
- {
- if(type == DateTimeIntervalType.Auto ||
- type == DateTimeIntervalType.Number)
- {
- if( majorInterval )
- {
- return 1;
- }
- else
- {
- return 0;
- }
- }
-
- return -(series.Points.Count + 1);
- }
- // Non indexed series
- else
- {
- // Do not adjust start position for these interval type
- if(type == DateTimeIntervalType.Auto ||
- type == DateTimeIntervalType.Number)
- {
- return start;
- }
- // Get the beginning of the interval depending on type
- DateTime newStartDate = DateTime.FromOADate(start);
- // Adjust the months interval depending on size
- if(intervalSize > 0.0 && intervalSize != 1.0)
- {
- if(type == DateTimeIntervalType.Months && intervalSize <= 12.0 && intervalSize > 1)
- {
- // Make sure that the beginning is aligned correctly for cases
- // like quarters and half years
- DateTime resultDate = newStartDate;
- DateTime sizeAdjustedDate = new DateTime(newStartDate.Year, 1, 1, 0, 0, 0);
- while(sizeAdjustedDate < newStartDate)
- {
- resultDate = sizeAdjustedDate;
- sizeAdjustedDate = sizeAdjustedDate.AddMonths((int)intervalSize);
- }
- newStartDate = resultDate;
- return newStartDate.ToOADate();
- }
- }
- // Check interval type
- switch(type)
- {
- case(DateTimeIntervalType.Years):
- int year = (int)((int)(newStartDate.Year / intervalSize) * intervalSize);
- if(year <= 0)
- {
- year = 1;
- }
- newStartDate = new DateTime(year,
- 1, 1, 0, 0, 0);
- break;
- case(DateTimeIntervalType.Months):
- int month = (int)((int)(newStartDate.Month / intervalSize) * intervalSize);
- if(month <= 0)
- {
- month = 1;
- }
- newStartDate = new DateTime(newStartDate.Year,
- month, 1, 0, 0, 0);
- break;
- case(DateTimeIntervalType.Days):
- int day = (int)((int)(newStartDate.Day / intervalSize) * intervalSize);
- if(day <= 0)
- {
- day = 1;
- }
- newStartDate = new DateTime(newStartDate.Year,
- newStartDate.Month, day, 0, 0, 0);
- break;
- case(DateTimeIntervalType.Hours):
- int hour = (int)((int)(newStartDate.Hour / intervalSize) * intervalSize);
- newStartDate = new DateTime(newStartDate.Year,
- newStartDate.Month, newStartDate.Day, hour, 0, 0);
- break;
- case(DateTimeIntervalType.Minutes):
- int minute = (int)((int)(newStartDate.Minute / intervalSize) * intervalSize);
- newStartDate = new DateTime(newStartDate.Year,
- newStartDate.Month,
- newStartDate.Day,
- newStartDate.Hour,
- minute,
- 0);
- break;
- case(DateTimeIntervalType.Seconds):
- int second = (int)((int)(newStartDate.Second / intervalSize) * intervalSize);
- newStartDate = new DateTime(newStartDate.Year,
- newStartDate.Month,
- newStartDate.Day,
- newStartDate.Hour,
- newStartDate.Minute,
- second,
- 0);
- break;
- case(DateTimeIntervalType.Milliseconds):
- int milliseconds = (int)((int)(newStartDate.Millisecond / intervalSize) * intervalSize);
- newStartDate = new DateTime(newStartDate.Year,
- newStartDate.Month,
- newStartDate.Day,
- newStartDate.Hour,
- newStartDate.Minute,
- newStartDate.Second,
- milliseconds);
- break;
- case(DateTimeIntervalType.Weeks):
- // NOTE: Code below was changed to fix issue #5962
- // Elements that have interval set to weeks should be aligned to the
- // nearest Monday no matter how many weeks is the interval.
- //newStartDate = newStartDate.AddDays(-((int)newStartDate.DayOfWeek * intervalSize));
- newStartDate = newStartDate.AddDays(-((int)newStartDate.DayOfWeek));
- newStartDate = new DateTime(newStartDate.Year,
- newStartDate.Month, newStartDate.Day, 0, 0, 0);
- break;
- }
- return newStartDate.ToOADate();
- }
- }
- /// <summary>
- /// Gets interval size as double number.
- /// </summary>
- /// <param name="current">Current value.</param>
- /// <param name="interval">Interval size.</param>
- /// <param name="type">AxisName of the interval (Month, Year, ...).</param>
- /// <returns>Interval size as double.</returns>
- internal static double GetIntervalSize(double current, double interval, DateTimeIntervalType type)
- {
- return GetIntervalSize(
- current,
- interval,
- type,
- null,
- 0,
- DateTimeIntervalType.Number,
- true,
- true);
- }
- /// <summary>
- /// Gets interval size as double number.
- /// </summary>
- /// <param name="current">Current value.</param>
- /// <param name="interval">Interval size.</param>
- /// <param name="type">AxisName of the interval (Month, Year, ...).</param>
- /// <param name="series">First series connected to the axis.</param>
- /// <param name="intervalOffset">Offset size.</param>
- /// <param name="intervalOffsetType">Offset type(Month, Year, ...).</param>
- /// <param name="forceIntIndex">Force Integer indexed</param>
- /// <returns>Interval size as double.</returns>
- internal static double GetIntervalSize(
- double current,
- double interval,
- DateTimeIntervalType type,
- Series series,
- double intervalOffset,
- DateTimeIntervalType intervalOffsetType,
- bool forceIntIndex)
- {
- return GetIntervalSize(
- current,
- interval,
- type,
- series,
- intervalOffset,
- intervalOffsetType,
- forceIntIndex,
- true);
- }
- /// <summary>
- /// Gets interval size as double number.
- /// </summary>
- /// <param name="current">Current value.</param>
- /// <param name="interval">Interval size.</param>
- /// <param name="type">AxisName of the interval (Month, Year, ...).</param>
- /// <param name="series">First series connected to the axis.</param>
- /// <param name="intervalOffset">Offset size.</param>
- /// <param name="intervalOffsetType">Offset type(Month, Year, ...).</param>
- /// <param name="forceIntIndex">Force Integer indexed</param>
- /// <param name="forceAbsInterval">Force Integer indexed</param>
- /// <returns>Interval size as double.</returns>
- internal static double GetIntervalSize(
- double current,
- double interval,
- DateTimeIntervalType type,
- Series series,
- double intervalOffset,
- DateTimeIntervalType intervalOffsetType,
- bool forceIntIndex,
- bool forceAbsInterval)
- {
- // AxisName is not date.
- if( type == DateTimeIntervalType.Number || type == DateTimeIntervalType.Auto )
- {
- return interval;
- }
- // Special case for indexed series
- if(series != null && series.IsXValueIndexed)
- {
- // Check point index
- int pointIndex = (int)Math.Ceiling(current - 1);
- if(pointIndex < 0)
- {
- pointIndex = 0;
- }
- if(pointIndex >= series.Points.Count || series.Points.Count <= 1)
- {
- return interval;
- }
- // Get starting and ending values of the closest interval
- double adjuster = 0;
- double xValue = series.Points[pointIndex].XValue;
- xValue = AlignIntervalStart(xValue, 1, type, null);
- double xEndValue = xValue + GetIntervalSize(xValue, interval, type);
- xEndValue += GetIntervalSize(xEndValue, intervalOffset, intervalOffsetType);
- xValue += GetIntervalSize(xValue, intervalOffset, intervalOffsetType);
- if(intervalOffset < 0)
- {
- xValue = xValue + GetIntervalSize(xValue, interval, type);
- xEndValue = xEndValue + GetIntervalSize(xEndValue, interval, type);
- }
- // The first point in the series
- if(pointIndex == 0 && current < 0)
- {
- // Round the first point value depending on the interval type
- DateTime dateValue = DateTime.FromOADate(series.Points[pointIndex].XValue);
- DateTime roundedDateValue = dateValue;
- switch(type)
- {
- case(DateTimeIntervalType.Years): // Ignore hours,...
- roundedDateValue = new DateTime(dateValue.Year,
- dateValue.Month, dateValue.Day, 0, 0, 0);
- break;
- case(DateTimeIntervalType.Months): // Ignore hours,...
- roundedDateValue = new DateTime(dateValue.Year,
- dateValue.Month, dateValue.Day, 0, 0, 0);
- break;
- case(DateTimeIntervalType.Days): // Ignore hours,...
- roundedDateValue = new DateTime(dateValue.Year,
- dateValue.Month, dateValue.Day, 0, 0, 0);
- break;
- case(DateTimeIntervalType.Hours): //
- roundedDateValue = new DateTime(dateValue.Year,
- dateValue.Month, dateValue.Day, dateValue.Hour,
- dateValue.Minute, 0);
- break;
- case(DateTimeIntervalType.Minutes):
- roundedDateValue = new DateTime(dateValue.Year,
- dateValue.Month,
- dateValue.Day,
- dateValue.Hour,
- dateValue.Minute,
- dateValue.Second);
- break;
- case(DateTimeIntervalType.Seconds):
- roundedDateValue = new DateTime(dateValue.Year,
- dateValue.Month,
- dateValue.Day,
- dateValue.Hour,
- dateValue.Minute,
- dateValue.Second,
- 0);
- break;
- case(DateTimeIntervalType.Weeks):
- roundedDateValue = new DateTime(dateValue.Year,
- dateValue.Month, dateValue.Day, 0, 0, 0);
- break;
- }
- // The first point value is exactly on the interval boundaries
- if(roundedDateValue.ToOADate() == xValue || roundedDateValue.ToOADate() == xEndValue)
- {
- return - current + 1;
- }
- }
- // Adjuster of 0.5 means that position should be between points
- ++pointIndex;
- while(pointIndex < series.Points.Count)
- {
- if(series.Points[pointIndex].XValue >= xEndValue)
- {
- if(series.Points[pointIndex].XValue > xEndValue && !forceIntIndex)
- {
- adjuster = -0.5;
- }
- break;
- }
- ++pointIndex;
- }
- // If last point outside of the max series index
- if(pointIndex == series.Points.Count)
- {
- pointIndex += series.Points.Count/5 + 1;
- }
- double size = (pointIndex + 1) - current + adjuster;
-
- return (size != 0) ? size : interval;
- }
-
- // Non indexed series
- else
- {
- DateTime date = DateTime.FromOADate(current);
- TimeSpan span = new TimeSpan(0);
- if(type == DateTimeIntervalType.Days)
- {
- span = TimeSpan.FromDays(interval);
- }
- else if(type == DateTimeIntervalType.Hours)
- {
- span = TimeSpan.FromHours(interval);
- }
- else if(type == DateTimeIntervalType.Milliseconds)
- {
- span = TimeSpan.FromMilliseconds(interval);
- }
- else if(type == DateTimeIntervalType.Seconds)
- {
- span = TimeSpan.FromSeconds(interval);
- }
- else if(type == DateTimeIntervalType.Minutes)
- {
- span = TimeSpan.FromMinutes(interval);
- }
- else if(type == DateTimeIntervalType.Weeks)
- {
- span = TimeSpan.FromDays(7.0 * interval);
- }
- else if(type == DateTimeIntervalType.Months)
- {
- // Special case handling when current date points
- // to the last day of the month
- bool lastMonthDay = false;
- if(date.Day == DateTime.DaysInMonth(date.Year, date.Month))
- {
- lastMonthDay = true;
- }
- // Add specified amount of months
- date = date.AddMonths((int)Math.Floor(interval));
- span = TimeSpan.FromDays(30.0 * ( interval - Math.Floor(interval) ));
- // Check if last month of the day was used
- if(lastMonthDay && span.Ticks == 0)
- {
- // Make sure the last day of the month is selected
- int daysInMobth = DateTime.DaysInMonth(date.Year, date.Month);
- date = date.AddDays(daysInMobth - date.Day);
- }
- }
- else if(type == DateTimeIntervalType.Years)
- {
- date = date.AddYears((int)Math.Floor(interval));
- span = TimeSpan.FromDays(365.0 * ( interval - Math.Floor(interval) ));
- }
- // Check if an absolute interval size must be returned
- double result = date.Add(span).ToOADate() - current;
- if(forceAbsInterval)
- {
- result = Math.Abs(result);
- }
- return result;
- }
- }
- /// <summary>
- /// Check if series is indexed. IsXValueIndexed flag is set or all X values are zeros.
- /// </summary>
- /// <param name="series">Data series to test.</param>
- /// <returns>True if series is indexed.</returns>
- static internal bool IndexedSeries( Series series)
- {
- // X value indexed flag set
- if (series.IsXValueIndexed)
- {
- return true;
- }
- if (Utilities.CustomPropertyRegistry.IsXAxisQuantitativeChartTypes.Contains(series.ChartType) &&
- series.IsCustomPropertySet(Utilities.CustomPropertyName.IsXAxisQuantitative))
- {
- string attribValue = series[Utilities.CustomPropertyName.IsXAxisQuantitative];
- if (String.Compare(attribValue, "True", StringComparison.OrdinalIgnoreCase) == 0)
- {
- return false;
- }
- }
- // Check if series has all X values set to zero
- return SeriesXValuesZeros(series);
- }
- /// <summary>
- /// Check if all data points in the series have X value set to 0.
- /// </summary>
- /// <param name="series">Data series to check.</param>
- static private bool SeriesXValuesZeros( Series series )
- {
- // Check if X value zeros check was already done
- if(series.xValuesZerosChecked)
- {
- return series.xValuesZeros;
- }
- // Data point loop
- series.xValuesZerosChecked = true;
- series.xValuesZeros = true;
- foreach( DataPoint point in series.Points )
- {
- if( point.XValue != 0.0 )
- {
- // If any data point has value different than 0 return false
- series.xValuesZeros = false;
- break;
- }
- }
- return series.xValuesZeros;
- }
- /// <summary>
- /// Check if any series is indexed. IsXValueIndexed flag is set or all X values are zeros.
- /// </summary>
- /// <param name="common">Reference to common chart classes.</param>
- /// <param name="series">Data series names.</param>
- /// <returns>True if any series is indexed.</returns>
- static internal bool IndexedSeries(CommonElements common, params string[] series)
- {
- // Data series loop
- bool zeroXValues = true;
- foreach (string ser in series)
- {
- Series localSeries = common.DataManager.Series[ser];
- // Check series indexed flag
- if (localSeries.IsXValueIndexed)
- {
- // If flag set in at least one series - all series are indexed
- return true;
- }
- // Check if series has all X values set to zero
- if (zeroXValues && !IndexedSeries(localSeries))
- {
- zeroXValues = false;
- }
- }
- return zeroXValues;
- }
- /// <summary>
- /// Check if all data points in many series have X value set to 0.
- /// </summary>
- /// <param name="common">Reference to common chart classes.</param>
- /// <param name="series">Data series.</param>
- /// <returns>True if all data points have value 0.</returns>
- static internal bool SeriesXValuesZeros(CommonElements common, params string[] series)
- {
- // Data series loop
- foreach( string ser in series )
- {
- // Check one series X values
- if(!SeriesXValuesZeros(common.DataManager.Series[ ser ]))
- {
- return false;
- }
- }
- return true;
- }
- #endregion
- }
- #endregion //ChartElement
- }
|