Plot.Axis.cs 31 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702
  1. /*
  2. * This file contains code related to Axes including:
  3. * - Unit/Pixel conversions
  4. * - Configuring axis limits and boundaries
  5. * - Axis labels (XLabel, YLabel, Title, etc)
  6. * - Adding multiple axes
  7. * - Grid lines
  8. * - Tick marks
  9. * - Tick labels
  10. */
  11. using System;
  12. using System.Drawing;
  13. using System.Linq;
  14. namespace ScottPlot
  15. {
  16. public partial class Plot
  17. {
  18. #region shortcuts: primary axes
  19. /// <summary>
  20. /// Axis on the bottom edge of the plot
  21. /// </summary>
  22. public Renderable.Axis XAxis => settings.XAxis;
  23. /// <summary>
  24. /// Axis on the top edge of the plot
  25. /// </summary>
  26. public Renderable.Axis XAxis2 => settings.XAxis2;
  27. /// <summary>
  28. /// Axis on the left edge of the plot
  29. /// </summary>
  30. public Renderable.Axis YAxis => settings.YAxis;
  31. /// <summary>
  32. /// Axis on the right edge of the plot
  33. /// </summary>
  34. public Renderable.Axis YAxis2 => settings.YAxis2;
  35. #endregion
  36. #region shortcuts: axis label, tick, and grid
  37. /// <summary>
  38. /// Set the label for the vertical axis to the right of the plot (XAxis)
  39. /// </summary>
  40. /// <param name="label">new text</param>
  41. /// <param name="color"></param>
  42. /// <param name="size"></param>
  43. /// <param name="bold"></param>
  44. /// <param name="fontName"></param>
  45. public void XLabel(string label, Color? color = null, float? size = null, bool? bold = null, string fontName = null)
  46. {
  47. XAxis.Label(label, color, size, bold, fontName);
  48. }
  49. /// <summary>
  50. /// Set the label for the vertical axis to the right of the plot (YAxis2)
  51. /// </summary>
  52. /// <param name="label">new text</param>
  53. /// <param name="color"></param>
  54. /// <param name="size"></param>
  55. /// <param name="bold"></param>
  56. /// <param name="fontName"></param>
  57. public void YLabel(string label, Color? color = null, float? size = null, bool? bold = null, string fontName = null)
  58. {
  59. YAxis.Label(label, color, size, bold, fontName);
  60. }
  61. /// <summary>
  62. /// Set the label for the horizontal axis above the plot (XAxis2)
  63. /// </summary>
  64. /// <param name="label">new text</param>
  65. /// <param name="bold">controls font weight</param>
  66. public void Title(string label, bool bold = true) => XAxis2.Label(label, bold: bold);
  67. /// <summary>
  68. /// Configure color and visibility of the frame that outlines the data area.
  69. /// Note that the axis lines of all 4 primary axes touch each other,
  70. /// giving the appearance of a rectangle framing the data area.
  71. /// This method allows the user to customize these lines as a group or individually.
  72. /// </summary>
  73. /// <param name="visible">visibility of the frames for the 4 primary axes</param>
  74. /// <param name="color">color for the 4 primary axis lines</param>
  75. /// <param name="left">visibility of the left axis (YAxis) line</param>
  76. /// <param name="right">visibility of the right axis (YAxis2) line</param>
  77. /// <param name="bottom">visibility of the bottom axis (XAxis) line</param>
  78. /// <param name="top">visibility of the top axis (XAxis2) line</param>
  79. public void Frame(bool? visible = null, Color? color = null, bool? left = null, bool? right = null, bool? bottom = null, bool? top = null)
  80. {
  81. var primaryAxes = new Renderable.Axis[] { XAxis, XAxis2, YAxis, YAxis2 };
  82. foreach (var axis in primaryAxes)
  83. axis.Line(visible, color);
  84. YAxis.Line(visible: left);
  85. YAxis2.Line(visible: right);
  86. XAxis.Line(visible: bottom);
  87. XAxis2.Line(visible: top);
  88. }
  89. /// <summary>
  90. /// Give the plot a frameless appearance by setting the size of all axes to zero.
  91. /// This causes the data area to go right up to the edge of the plot.
  92. /// </summary>
  93. public void Frameless()
  94. {
  95. foreach (var axis in settings.Axes)
  96. axis.Hide();
  97. }
  98. /// <summary>
  99. /// 小刻度开关
  100. /// </summary>
  101. /// <param name="isShow"></param>
  102. public void MinorTickVisible(Boolean isShow)
  103. {
  104. foreach (var axis in settings.Axes)
  105. axis.ConfigMinorTick(isShow);
  106. }
  107. /// <summary>
  108. /// 十字线开关
  109. /// </summary>
  110. /// <param name="isShow"></param>
  111. public void GridCrosslineVisible(Boolean isShow)
  112. {
  113. foreach (var axis in settings.Axes)
  114. axis.ConfigGridCrossline(isShow);
  115. }
  116. /// <summary>
  117. /// Customize basic options for the primary X and Y axes.
  118. /// Call XAxis.Grid() and YAxis.Grid() to further customize grid settings.
  119. /// </summary>
  120. /// <param name="enable">sets visibility of X and Y grid lines</param>
  121. /// <param name="color">sets color of of X and Y grid lines</param>
  122. /// <param name="lineStyle">defines the style for X and Y grid lines</param>
  123. public void Grid(bool? enable = null, Color? color = null, LineStyle? lineStyle = null)
  124. {
  125. if (enable.HasValue)
  126. {
  127. XAxis.Grid(enable.Value);
  128. YAxis.Grid(enable.Value);
  129. }
  130. XAxis.MajorGrid(color: color, lineStyle: lineStyle);
  131. YAxis.MajorGrid(color: color, lineStyle: lineStyle);
  132. XAxis.MinorGrid(color: color, lineStyle: lineStyle);
  133. YAxis.MinorGrid(color: color, lineStyle: lineStyle);
  134. XAxis.MinorTick(color);
  135. YAxis.MinorTick(color);
  136. }
  137. /// <summary>
  138. /// Set padding around the data area by defining the minimum size and padding for all axes
  139. /// </summary>
  140. /// <param name="left">YAxis size (in pixels) that defines the area to the left of the plot</param>
  141. /// <param name="right">YAxis2 size (in pixels) that defines the area to the right of the plot</param>
  142. /// <param name="bottom">XAxis size (in pixels) that defines the area to the bottom of the plot</param>
  143. /// <param name="top">XAxis2 size (in pixels) that defines the area to the top of the plot</param>
  144. /// <param name="padding">Customize the default padding between axes and the edge of the plot</param>
  145. public void Layout(float? left = null, float? right = null, float? bottom = null, float? top = null, float? padding = 5)
  146. {
  147. YAxis.Layout(padding, left);
  148. YAxis2.Layout(padding, right);
  149. XAxis.Layout(padding, bottom);
  150. XAxis2.Layout(padding, top);
  151. }
  152. /// <summary>
  153. /// Adjust this axis layout based on the layout of a source plot
  154. /// </summary>
  155. /// <param name="sourcePlot">plot to use for layout reference</param>
  156. /// <param name="horizontal">if true, horizontal layout will be matched</param>
  157. /// <param name="vertical">if true, vertical layout will be matched</param>
  158. public void MatchLayout(Plot sourcePlot, bool horizontal = true, bool vertical = true)
  159. {
  160. if (!sourcePlot.GetSettings(showWarning: false).AllAxesHaveBeenSet)
  161. sourcePlot.AxisAuto();
  162. if (!settings.AllAxesHaveBeenSet)
  163. AxisAuto();
  164. var sourceSettings = sourcePlot.GetSettings(false);
  165. if (horizontal)
  166. {
  167. YAxis.SetSize(sourceSettings.YAxis.GetSize());
  168. YAxis2.SetSize(sourceSettings.YAxis2.GetSize());
  169. }
  170. if (vertical)
  171. {
  172. XAxis.SetSize(sourceSettings.XAxis.GetSize());
  173. XAxis2.SetSize(sourceSettings.XAxis2.GetSize());
  174. }
  175. }
  176. /// <summary>
  177. /// Manually define X axis tick labels using consecutive integer positions (0, 1, 2, etc.)
  178. /// </summary>
  179. /// <param name="labels">new tick labels for the X axis</param>
  180. public void XTicks(string[] labels) => XTicks(DataGen.Consecutive(labels.Length), labels);
  181. /// <summary>
  182. /// Manually define X axis tick positions and labels
  183. /// </summary>
  184. /// <param name="positions">positions on the X axis</param>
  185. /// <param name="labels">new tick labels for the X axis</param>
  186. public void XTicks(double[] positions = null, string[] labels = null) =>
  187. XAxis.ManualTickPositions(positions, labels);
  188. /// <summary>
  189. /// Manually define Y axis tick labels using consecutive integer positions (0, 1, 2, etc.)
  190. /// </summary>
  191. /// <param name="labels">new tick labels for the Y axis</param>
  192. public void YTicks(string[] labels) => YTicks(DataGen.Consecutive(labels.Length), labels);
  193. /// <summary>
  194. /// Manually define Y axis tick positions and labels
  195. /// </summary>
  196. /// <param name="positions">positions on the Y axis</param>
  197. /// <param name="labels">new tick labels for the Y axis</param>
  198. public void YTicks(double[] positions = null, string[] labels = null) =>
  199. YAxis.ManualTickPositions(positions, labels);
  200. /// <summary>
  201. /// Set the culture to use for number-to-string converstion for tick labels of all axes.
  202. /// </summary>
  203. /// <param name="culture">standard culture</param>
  204. public void SetCulture(System.Globalization.CultureInfo culture)
  205. {
  206. foreach (var axis in settings.Axes)
  207. axis.SetCulture(culture);
  208. }
  209. /// <summary>
  210. /// Set the culture to use for number-to-string converstion for tick labels of all axes.
  211. /// This overload allows you to manually define every format string,
  212. /// allowing extensive customization of number and date formatting.
  213. /// </summary>
  214. /// <param name="shortDatePattern"></param>
  215. /// <param name="decimalSeparator">Separates the decimal digits</param>
  216. /// <param name="numberGroupSeparator">Separates large numbers ito groups of digits for readability</param>
  217. /// <param name="decimalDigits">Number of digits after the numberDecimalSeparator</param>
  218. /// <param name="numberNegativePattern">Appearance of negative numbers</param>
  219. /// <param name="numberGroupSizes">Sizes of decimal groups which are separated by the numberGroupSeparator</param>
  220. public void SetCulture(string shortDatePattern = null, string decimalSeparator = null, string numberGroupSeparator = null,
  221. int? decimalDigits = null, int? numberNegativePattern = null, int[] numberGroupSizes = null)
  222. {
  223. foreach (var axis in settings.Axes)
  224. axis.SetCulture(shortDatePattern, decimalSeparator, numberGroupSeparator, decimalDigits, numberNegativePattern, numberGroupSizes);
  225. }
  226. #endregion
  227. #region Axis creation
  228. /// <summary>
  229. /// Create and return an additional axis
  230. /// </summary>
  231. /// <param name="edge">Edge of the plot the new axis will belong to</param>
  232. /// <param name="axisIndex">Only plottables with the same axis index will use this axis</param>
  233. /// <param name="title">defualt label to use for the axis</param>
  234. /// <param name="color">defualt color to use for the axis</param>
  235. /// <returns>The axis that was just created and added to the plot. You can further customize it by interacting with it.</returns>
  236. public Renderable.Axis AddAxis(Renderable.Edge edge, int axisIndex, string title = null, Color? color = null)
  237. {
  238. if (axisIndex <= 1)
  239. throw new ArgumentException("The default axes already occupy indexes 0 and 1. Additional axes require higher indexes.");
  240. Renderable.Axis axis;
  241. if (edge == Renderable.Edge.Left)
  242. axis = new Renderable.AdditionalLeftAxis(axisIndex, title);
  243. else if (edge == Renderable.Edge.Right)
  244. axis = new Renderable.AdditionalRightAxis(axisIndex, title);
  245. else if (edge == Renderable.Edge.Bottom)
  246. axis = new Renderable.AdditionalBottomAxis(axisIndex, title);
  247. else if (edge == Renderable.Edge.Top)
  248. axis = new Renderable.AdditionalTopAxis(axisIndex, title);
  249. else
  250. throw new NotImplementedException("unsupported edge");
  251. if (color.HasValue)
  252. axis.Color(color.Value);
  253. settings.Axes.Add(axis);
  254. return axis;
  255. }
  256. #endregion
  257. #region coordinate/pixel conversions
  258. /// <summary>
  259. /// Return the coordinate (in coordinate space) for the given pixel
  260. /// </summary>
  261. /// <param name="xPixel">horizontal pixel location</param>
  262. /// <param name="yPixel">vertical pixel location</param>
  263. /// <returns>point in coordinate space</returns>
  264. public (double x, double y) GetCoordinate(float xPixel, float yPixel) =>
  265. (settings.XAxis.Dims.GetUnit(xPixel), settings.YAxis.Dims.GetUnit(yPixel));
  266. /// <summary>
  267. /// Return the X position (in coordinate space) for the given pixel column
  268. /// </summary>
  269. /// <param name="xPixel">horizontal pixel location</param>
  270. /// <returns>horizontal position in coordinate space</returns>
  271. public double GetCoordinateX(float xPixel) => settings.XAxis.Dims.GetUnit(xPixel);
  272. /// <summary>
  273. /// Return the Y position (in coordinate space) for the given pixel row
  274. /// </summary>
  275. /// <param name="yPixel">vertical pixel location</param>
  276. /// <returns>vertical position in coordinate space</returns>
  277. public double GetCoordinateY(float yPixel) => settings.YAxis.Dims.GetUnit(yPixel);
  278. /// <summary>
  279. /// Return the pixel for the given point in coordinate space
  280. /// </summary>
  281. /// <param name="x">horizontal coordinate</param>
  282. /// <param name="y">vertical coordinate</param>
  283. /// <returns>pixel location</returns>
  284. public (float xPixel, float yPixel) GetPixel(double x, double y) =>
  285. (settings.XAxis.Dims.GetPixel(x), settings.YAxis.Dims.GetPixel(y));
  286. /// <summary>
  287. /// Return the horizontal pixel location given position in coordinate space
  288. /// </summary>
  289. /// <param name="x">horizontal coordinate</param>
  290. /// <returns>horizontal pixel position</returns>
  291. public float GetPixelX(double x) => settings.XAxis.Dims.GetPixel(x);
  292. /// <summary>
  293. /// Return the vertical pixel location given position in coordinate space
  294. /// </summary>
  295. /// <param name="y">vertical coordinate</param>
  296. /// <returns>vertical pixel position</returns>
  297. public float GetPixelY(double y) => settings.YAxis.Dims.GetPixel(y);
  298. /// <summary>
  299. /// xMin 左边界
  300. /// xMax 右边界
  301. /// yMin 上边界
  302. /// yMax 下边界
  303. /// </summary>
  304. /// <returns></returns>
  305. public (double xLeft, double xRight, double yTop, double yBottom) GetZoomUnitArea() => settings.ZoomUnitArea;
  306. #endregion
  307. #region axis limits: get and set
  308. /// <summary>
  309. /// Returns the current limits for a given pair of axes.
  310. /// </summary>
  311. /// <param name="xAxisIndex">which axis index to reference</param>
  312. /// <param name="yAxisIndex">which axis index to reference</param>
  313. /// <returns>current limits</returns>
  314. public AxisLimits GetAxisLimits(int xAxisIndex = 0, int yAxisIndex = 0)
  315. {
  316. (double xMin, double xMax) = settings.GetXAxis(xAxisIndex).Dims.RationalLimits();
  317. (double yMin, double yMax) = settings.GetYAxis(yAxisIndex).Dims.RationalLimits();
  318. return new AxisLimits(xMin, xMax, yMin, yMax);
  319. }
  320. /// <summary>
  321. /// Set limits for the a given pair of axes
  322. /// </summary>
  323. /// <param name="xMin">lower limit of the horizontal axis</param>
  324. /// <param name="xMax">upper limit of the horizontal axis</param>
  325. /// <param name="yMin">lower limit of the vertical axis</param>
  326. /// <param name="yMax">upper limit of the vertical axis</param>
  327. /// <param name="xAxisIndex">index of the axis the horizontal limits apply to</param>
  328. /// <param name="yAxisIndex">index of the axis the vertical limits apply to</param>
  329. public void SetAxisLimits(
  330. double? xMin = null, double? xMax = null,
  331. double? yMin = null, double? yMax = null,
  332. int xAxisIndex = 0, int yAxisIndex = 0)
  333. {
  334. bool notAllAxesDefined = xMin is null || xMax is null || yMin is null || yMax is null;
  335. if (notAllAxesDefined)
  336. settings.AxisAutoUnsetAxes();
  337. settings.AxisSet(xMin, xMax, yMin, yMax, xAxisIndex, yAxisIndex);
  338. }
  339. /// <summary>
  340. /// Set limits for the primary X axis
  341. /// </summary>
  342. /// <param name="xMin">lower limit of the horizontal axis</param>
  343. /// <param name="xMax">upper limit of the horizontal axis</param>
  344. public void SetAxisLimitsX(double xMin, double xMax) => SetAxisLimits(xMin, xMax, null, null);
  345. /// <summary>
  346. /// Set limits for the primary Y axis
  347. /// </summary>
  348. /// <param name="yMin">lower limit of the vertical axis</param>
  349. /// <param name="yMax">upper limit of the vertical axis</param>
  350. public void SetAxisLimitsY(double yMin, double yMax) => SetAxisLimits(null, null, yMin, yMax);
  351. /// <summary>
  352. /// Set limits for a pair of axes
  353. /// </summary>
  354. /// <param name="limits">new limits</param>
  355. /// <param name="xAxisIndex">index of the axis the horizontal limits apply to</param>
  356. /// <param name="yAxisIndex">index of the axis the vertical limits apply to</param>
  357. public void SetAxisLimits(AxisLimits limits, int xAxisIndex = 0, int yAxisIndex = 0) =>
  358. settings.AxisSet(limits, xAxisIndex, yAxisIndex);
  359. /// <summary>
  360. /// Set limits of the view for the primary axes.
  361. /// View limits define the boundaries of axis limits.
  362. /// You cannot zoom, pan, or set axis limits beyond view limits.
  363. /// </summary>
  364. /// <param name="xMin">lower limit of the horizontal axis</param>
  365. /// <param name="xMax">upper limit of the horizontal axis</param>
  366. /// <param name="yMin">lower limit of the vertical axis</param>
  367. /// <param name="yMax">upper limit of the vertical axis</param>
  368. public void SetViewLimits(
  369. double xMin = double.NegativeInfinity, double xMax = double.PositiveInfinity,
  370. double yMin = double.NegativeInfinity, double yMax = double.PositiveInfinity)
  371. {
  372. settings.XAxis.Dims.SetBounds(xMin, xMax);
  373. settings.YAxis.Dims.SetBounds(yMin, yMax);
  374. }
  375. #endregion
  376. #region axis limits: fit to plottable data
  377. /// <summary>
  378. /// Automatically adjust axis limits to fit the data
  379. /// </summary>
  380. /// <param name="horizontalMargin">amount of space to the left and right of the data (as a fraction of its width)</param>
  381. /// <param name="verticalMargin">amount of space above and below the data (as a fraction of its height)</param>
  382. public void AxisAuto(double horizontalMargin = .05, double verticalMargin = .1) =>
  383. settings.AxisAutoAll(horizontalMargin, verticalMargin);
  384. /// <summary>
  385. /// Automatically adjust axis limits to fit the data
  386. /// </summary>
  387. /// <param name="margin">amount of space to the left and right of the data (as a fraction of its width)</param>
  388. public void AxisAutoX(double margin = .05)
  389. {
  390. if (settings.Plottables.Count == 0)
  391. {
  392. SetAxisLimits(yMin: -10, yMax: 10);
  393. return;
  394. }
  395. AxisLimits originalLimits = GetAxisLimits();
  396. AxisAuto(horizontalMargin: margin);
  397. SetAxisLimits(yMin: originalLimits.YMin, yMax: originalLimits.YMax);
  398. }
  399. /// <summary>
  400. /// Automatically adjust axis limits to fit the data (with a little extra margin)
  401. /// </summary>
  402. /// <param name="margin">amount of space above and below the data (as a fraction of its height)</param>
  403. public void AxisAutoY(double margin = .1)
  404. {
  405. if (settings.Plottables.Count == 0)
  406. {
  407. SetAxisLimits(xMin: -10, xMax: 10);
  408. return;
  409. }
  410. AxisLimits originalLimits = GetAxisLimits();
  411. AxisAuto(horizontalMargin: margin);
  412. SetAxisLimits(xMin: originalLimits.XMin, xMax: originalLimits.XMax);
  413. }
  414. #endregion
  415. #region axis limits: scaling
  416. /// <summary>
  417. /// Adjust axis limits to achieve a certain pixel scale (units per pixel)
  418. /// </summary>
  419. /// <param name="unitsPerPixelX">zoom so 1 pixel equals this many horizontal units in coordinate space</param>
  420. /// <param name="unitsPerPixelY">zoom so 1 pixel equals this many vertical units in coordinate space</param>
  421. public void AxisScale(double? unitsPerPixelX = null, double? unitsPerPixelY = null)
  422. {
  423. if (unitsPerPixelX != null)
  424. {
  425. double spanX = unitsPerPixelX.Value * settings.DataWidth;
  426. SetAxisLimits(xMin: settings.XAxis.Dims.Center - spanX / 2, xMax: settings.XAxis.Dims.Center + spanX / 2);
  427. }
  428. if (unitsPerPixelY != null)
  429. {
  430. double spanY = unitsPerPixelY.Value * settings.DataHeight;
  431. SetAxisLimits(xMin: settings.YAxis.Dims.Center - spanY / 2, xMax: settings.YAxis.Dims.Center + spanY / 2);
  432. }
  433. }
  434. /// <summary>
  435. /// Lock X and Y axis scales (units per pixel) together to protect symmetry of circles and squares
  436. /// </summary>
  437. /// <param name="enable">if true, scales are locked such that zooming one zooms the other</param>
  438. /// <param name="scaleMode">defines behavior for how to adjust axis limits to achieve equal scales</param>
  439. public void AxisScaleLock(bool enable, EqualScaleMode scaleMode = EqualScaleMode.PreserveY)
  440. {
  441. settings.AxisAutoUnsetAxes();
  442. settings.EqualScaleMode = enable ? scaleMode : EqualScaleMode.Disabled;
  443. settings.LayoutAuto();
  444. settings.EnforceEqualAxisScales();
  445. }
  446. #endregion
  447. #region axis limits: pan and zoom
  448. /// <summary>
  449. /// Zoom in or out. The amount of zoom is defined as a fraction of the current axis span.
  450. /// </summary>
  451. /// <param name="xFrac">horizontal zoom (>1 means zoom in)</param>
  452. /// <param name="yFrac">vertical zoom (>1 means zoom in)</param>
  453. /// <param name="zoomToX">if defined, zoom will be centered at this point</param>
  454. /// <param name="zoomToY">if defined, zoom will be centered at this point</param>
  455. /// <param name="xAxisIndex">index of the axis to zoom</param>
  456. /// <param name="yAxisIndex">index of the axis to zoom</param>
  457. public void AxisZoom(
  458. double xFrac = 1, double yFrac = 1,
  459. double? zoomToX = null, double? zoomToY = null,
  460. int xAxisIndex = 0, int yAxisIndex = 0)
  461. {
  462. var xAxis = settings.GetXAxis(xAxisIndex);
  463. var yAxis = settings.GetYAxis(yAxisIndex);
  464. if (xAxis.Dims.HasBeenSet == false || yAxis.Dims.HasBeenSet == false)
  465. settings.AxisAutoAll();
  466. xAxis.Dims.Zoom(xFrac, zoomToX ?? xAxis.Dims.Center);
  467. yAxis.Dims.Zoom(yFrac, zoomToY ?? yAxis.Dims.Center);
  468. }
  469. /// <summary>
  470. /// Pan the primary X and Y axis without affecting zoom
  471. /// </summary>
  472. /// <param name="dx">horizontal distance to pan (in coordinate units)</param>
  473. /// <param name="dy">vertical distance to pan (in coordinate units)</param>
  474. public void AxisPan(double dx = 0, double dy = 0)
  475. {
  476. if (!settings.AllAxesHaveBeenSet)
  477. settings.AxisAutoAll();
  478. settings.XAxis.Dims.Pan(dx);
  479. settings.XAxis.Dims.Pan(dy);
  480. }
  481. #endregion
  482. #region obsolete
  483. [Obsolete("Use SetAxisLimits() and GetAxisLimits()", true)]
  484. public AxisLimits AxisLimits(int xAxisIndex = 0, int yAxisIndex = 0) => throw new NotImplementedException();
  485. [Obsolete("use GetCoordinateX()", true)]
  486. public double CoordinateFromPixelX(float pixelX) => throw new NotImplementedException();
  487. [Obsolete("use GetCoordinateY()", true)]
  488. public double CoordinateFromPixelY(float pixelY) => throw new NotImplementedException();
  489. [Obsolete("use GetCoordinateX()", true)]
  490. public double CoordinateFromPixelX(double pixelX) => throw new NotImplementedException();
  491. [Obsolete("use GetCoordinateY()", true)]
  492. public double CoordinateFromPixelY(double pixelY) => throw new NotImplementedException();
  493. [Obsolete("use GetCoordinate(), GetCoordinateX() or GetCoordinateY()", true)]
  494. public System.Drawing.PointF CoordinateFromPixel(int pixelX, int pixelY) => throw new NotImplementedException();
  495. [Obsolete("use GetCoordinate(), GetCoordinateX() or GetCoordinateY()", true)]
  496. public System.Drawing.PointF CoordinateFromPixel(float pixelX, float pixelY) => throw new NotImplementedException();
  497. [Obsolete("use GetCoordinate(), GetCoordinateX() or GetCoordinateY()", true)]
  498. public System.Drawing.PointF CoordinateFromPixel(double pixelX, double pixelY) => throw new NotImplementedException();
  499. [Obsolete("use GetCoordinate(), GetCoordinateX() or GetCoordinateY()", true)]
  500. public System.Drawing.PointF CoordinateFromPixel(System.Drawing.Point pixel) => throw new NotImplementedException();
  501. [Obsolete("use GetCoordinate(), GetCoordinateX() or GetCoordinateY()", true)]
  502. public System.Drawing.PointF CoordinateFromPixel(System.Drawing.PointF pixel) => throw new NotImplementedException();
  503. [Obsolete("use GetPixel, GetPixelX(), or GetPixelY()", true)]
  504. public System.Drawing.PointF CoordinateToPixel(System.Drawing.PointF location) => throw new NotImplementedException();
  505. [Obsolete("use GetPixel, GetPixelX(), or GetPixelY()", true)]
  506. public System.Drawing.PointF CoordinateToPixel(double locationX, double locationY) => throw new NotImplementedException();
  507. [Obsolete("use GetPixelX()", true)]
  508. public float CoordinateToPixelX(double locationX) => throw new NotImplementedException();
  509. [Obsolete("use GetPixelY()", true)]
  510. public float CoordinateToPixelY(double locationY) => throw new NotImplementedException();
  511. [Obsolete("use GetAxisLimits() and SetAxisLimits()", true)]
  512. public AxisLimits Axis(double? x1 = null, double? x2 = null, double? y1 = null, double? y2 = null)
  513. => throw new NotImplementedException();
  514. [Obsolete("use GetAxisLimits() and SetAxisLimits()", true)]
  515. public void Axis(double[] axisLimits, int xAxisIndex = 0, int yAxisIndex = 0) => throw new NotImplementedException();
  516. [Obsolete("use GetAxisLimits() and SetAxisLimits()", true)]
  517. public double[] Axis(double? x1 = null, double? x2 = null, double? y1 = null, double? y2 = null, double? _ = null) => null;
  518. [Obsolete("use GetAxisLimits() and SetAxisLimits()", true)]
  519. public double[] Axis(double[] axisLimits) => null;
  520. [Obsolete("use GetAxisLimits() and SetAxisLimits()", true)]
  521. public void MatchAxis(Plot sourcePlot, bool horizontal = true, bool vertical = true) => throw new NotImplementedException();
  522. [Obsolete("use GetAxisLimits() and SetAxisLimits()", true)]
  523. public void Axis(AxisLimits limits, int xAxisIndex = 0, int yAxisIndex = 0) => throw new NotImplementedException();
  524. [Obsolete("use AxisScaleLock()", true)]
  525. public bool EqualAxis;
  526. [Obsolete("Use AxisAuto()", true)]
  527. public double[] AutoAxis() => null;
  528. [Obsolete("Use AxisAuto()", true)]
  529. public double[] AutoScale() => null;
  530. [Obsolete("Individual axes (e.g., XAxis and YAxis) have their own tick configuration methods", true)]
  531. public void Ticks(
  532. bool? displayTicksX = null,
  533. bool? displayTicksY = null,
  534. bool? displayTicksXminor = null,
  535. bool? displayTicksYminor = null,
  536. bool? displayTickLabelsX = null,
  537. bool? displayTickLabelsY = null,
  538. Color? color = null,
  539. bool? useMultiplierNotation = null,
  540. bool? useOffsetNotation = null,
  541. bool? useExponentialNotation = null,
  542. bool? dateTimeX = null,
  543. bool? dateTimeY = null,
  544. bool? rulerModeX = null,
  545. bool? rulerModeY = null,
  546. bool? invertSignX = null,
  547. bool? invertSignY = null,
  548. string fontName = null,
  549. float? fontSize = null,
  550. float? xTickRotation = null,
  551. bool? logScaleX = null,
  552. bool? logScaleY = null,
  553. string numericFormatStringX = null,
  554. string numericFormatStringY = null,
  555. bool? snapToNearestPixel = null,
  556. int? baseX = null,
  557. int? baseY = null,
  558. string prefixX = null,
  559. string prefixY = null,
  560. string dateTimeFormatStringX = null,
  561. string dateTimeFormatStringY = null
  562. ) => throw new NotImplementedException();
  563. #endregion
  564. public void SetTickLabelColor(Color color)
  565. {
  566. foreach (var axis in settings.Axes)
  567. {
  568. axis.TickLabelStyle(color:color);
  569. }
  570. }
  571. /// <summary>
  572. /// 设置垂直标记参数
  573. /// </summary>
  574. /// <param name="position"></param>
  575. /// <param name="scale"></param>
  576. /// <param name="prefix"></param>
  577. /// <param name="scaleUnit"></param>
  578. /// <param name="interval"></param>
  579. /// <param name="isUnitPrefix"></param>
  580. /// <param name="tickDecimalPlaces"></param>
  581. public void ResetChannelParameter(Double position, Double scale, String prefix, String scaleUnit, Int32 interval = 1000,Boolean isUnitPrefix = true, Int32 tickDecimalPlaces = 4)
  582. {
  583. YAxis.Dims.Update(position, scale, prefix, scaleUnit, interval, isUnitPrefix, tickDecimalPlaces);
  584. }
  585. /// <summary>
  586. /// 设置水平标记参数
  587. /// </summary>
  588. /// <param name="position"></param>
  589. /// <param name="scale"></param>
  590. /// <param name="prefix"></param>
  591. /// <param name="scaleUnit"></param>
  592. /// <param name="interval"></param>
  593. /// <param name="isUnitPrefix"></param>
  594. /// <param name="tickDecimalPlaces"></param>
  595. public void ResetTimebaseParameter(Double position, Double scale, String prefix, String scaleUnit,/* Color color,*/ Int32 interval = 1000, Boolean isUnitPrefix = true, Int32 tickDecimalPlaces = 4)
  596. {
  597. XAxis.Dims.Update(position, scale, prefix, scaleUnit, interval, isUnitPrefix, tickDecimalPlaces);
  598. }
  599. }
  600. }