123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971 |
- using FastReport.Utils;
- using System;
- using System.Collections;
- using System.Collections.Generic;
- using System.ComponentModel;
- using System.Drawing;
- using System.Drawing.Drawing2D;
- using System.Globalization;
- using System.Linq;
- using System.Text;
- namespace FastReport
- {
- /// <summary>
- /// Represents a poly line object.
- /// </summary>
- /// <remarks>
- /// Use the <b>Border.Width</b>, <b>Border.Style</b> and <b>Border.Color</b> properties to set
- /// the line width, style and color.
- /// </remarks>
- public partial class PolyLineObject : ReportComponentBase
- {
- #region Protected Internal Fields
- /// <summary>
- /// do not set this value, internal use only
- /// </summary>
- protected internal PolygonSelectionMode polygonSelectionMode;
- #endregion Protected Internal Fields
- #region Private Fields
- private PointF center;
- private PolyPointCollection pointsCollection;
- private FloatCollection dashPattern;
- #endregion Private Fields
- #region Public Properties
- /// <summary>
- /// Gets or sets collection of values for custom dash pattern.
- /// </summary>
- /// <remarks>
- /// Each element should be a non-zero positive number.
- /// If the number is negative or zero, that number is replaced by one.
- /// </remarks>
- [Category("Appearance")]
- public FloatCollection DashPattern
- {
- get { return dashPattern; }
- set { dashPattern = value; }
- }
- /// <summary>
- /// Return points collection.
- /// You can modify the collection for change this object.
- /// </summary>
- public PolyPointCollection Points
- {
- get
- {
- return pointsCollection;
- }
- }
- /// <summary>
- /// Returns origin of coordinates relative to the top left corner
- /// </summary>
- [Browsable(false)]
- public float CenterX { get { return center.X; } set { center.X = value; } }
- /// <summary>
- /// Returns origin of coordinates relative to the top left corner
- /// </summary>
- [Browsable(false)]
- public float CenterY { get { return center.Y; } set { center.Y = value; } }
- /// <summary>
- /// Return points array of line
- /// deprecated
- /// </summary>
- [Browsable(false)]
- [Obsolete]
- public PointF[] PointsArray
- {
- get
- {
- List<PointF> result = new List<PointF>();
- foreach (PolyPoint point in pointsCollection)
- {
- result.Add(new PointF(point.X, point.Y));
- }
- return result.ToArray();
- }
- }
- /// <summary>
- /// Return point types array. 0 - Start of line, 1 - Keep on line
- /// deprecated
- /// </summary>
- [Browsable(false)]
- [Obsolete]
- public byte[] PointTypesArray
- {
- get
- {
- List<byte> result = new List<byte>();
- result.Add(0);
- for (int i = 1; i < pointsCollection.Count; i++)
- result.Add(1);
- return result.ToArray();
- }
- }
- #endregion Public Properties
- #region Public Constructors
- /// <summary>
- /// Initializes a new instance of the <see cref="LineObject"/> class with default settings.
- /// </summary>
- public PolyLineObject()
- {
- FlagSimpleBorder = true;
- FlagUseFill = false;
- pointsCollection = new PolyPointCollection();
- center = PointF.Empty;
- dashPattern = new FloatCollection();
- InitDesign();
- }
- #endregion Public Constructors
- #region Public Methods
- /// <inheritdoc/>
- public override void Assign(Base source)
- {
- base.Assign(source);
- PolyLineObject src = source as PolyLineObject;
- pointsCollection = src.pointsCollection.Clone();
- center = src.center;
- DashPattern.Assign(src.DashPattern);
- //recalculateBounds();
- }
- /// <inheritdoc/>
- public override void Deserialize(FRReader reader)
- {
- base.Deserialize(reader);
- pointsCollection.Clear();
- if (reader.HasProperty("PolyPoints"))
- {
- string polyPoints = reader.ReadStr("PolyPoints");
- foreach (string str in polyPoints.Split('|'))
- {
- string[] point = str.Split('\\');
- if (point.Length == 3)
- {
- float f1 = float.Parse(point[0].Replace(',', '.'), CultureInfo.InvariantCulture);
- float f2 = float.Parse(point[1].Replace(',', '.'), CultureInfo.InvariantCulture);
- pointsCollection.Add(new PolyPoint(f1, f2));
- }
- }
- }
- else if (reader.HasProperty("PolyPoints_v2"))
- {
- string polyPoints = reader.ReadStr("PolyPoints_v2");
- foreach (string str in polyPoints.Split('|'))
- {
- PolyPoint point = new PolyPoint();
- point.Deserialize(str);
- pointsCollection.Add(point);
- }
- }
- if (reader.HasProperty("CenterX"))
- center.X = reader.ReadFloat("CenterX");
- if (reader.HasProperty("CenterY"))
- center.Y = reader.ReadFloat("CenterY");
- //recalculateBounds();
- }
- /// <inheritdoc/>
- public override void Draw(FRPaintEventArgs e)
- {
- switch (pointsCollection.Count)
- {
- case 0:
- case 1:
- IGraphics g = e.Graphics;
- float x = AbsLeft + CenterX;
- float y = AbsTop + CenterY;
- if (pointsCollection.Count == 1)
- {
- x += pointsCollection[0].X;
- y += pointsCollection[0].Y;
- }
- g.DrawLine(Pens.Black, x * e.ScaleX - 6, y * e.ScaleY, x * e.ScaleX + 6, y * e.ScaleY);
- g.DrawLine(Pens.Black, x * e.ScaleX, y * e.ScaleY - 6, x * e.ScaleX, y * e.ScaleY + 6);
- break;
- default:
- DoDrawPoly(e);
- DrawDesign0(e);
- break;
- }
- DrawDesign1(e);
- }
- /// <summary>
- /// Calculate GraphicsPath for draw to page
- /// </summary>
- /// <param name="pen">Pen for lines</param>
- /// <param name="left">Left boundary</param>
- /// <param name="top">Top boundary</param>
- /// <param name="right">Right boundary</param>
- /// <param name="bottom">Bottom boundary</param>
- /// <param name="scaleX">scale by width</param>
- /// <param name="scaleY">scale by height</param>
- /// <returns>Always returns a non-empty path</returns>
- public GraphicsPath GetPath(Pen pen, float left, float top, float right, float bottom, float scaleX, float scaleY)
- {
- if (pointsCollection.Count == 0)
- {
- GraphicsPath result = new GraphicsPath();
- result.AddLine(left * scaleX, top * scaleX, (right + 1) * scaleX, (bottom + 1) * scaleX);
- return result;
- }
- else if (pointsCollection.Count == 1)
- {
- GraphicsPath result = new GraphicsPath();
- left = left + CenterX + pointsCollection[0].X;
- top = top + CenterY + pointsCollection[0].Y;
- result.AddLine(left * scaleX, top * scaleX, (left + 1) * scaleX, (top + 1) * scaleX);
- return result;
- }
- List<PointF> aPoints = new List<PointF>();
- List<byte> pointTypes = new List<byte>();
- PolyPoint prev = null;
- PolyPoint point = pointsCollection[0];
- aPoints.Add(new PointF((point.X + left + center.X) * scaleX, (point.Y + top + center.Y) * scaleY));
- pointTypes.Add(0);
- int count = pointsCollection.Count;
- if (this is PolygonObject)
- {
- count++;
- }
- for (int i = 1; i < count; i++)
- {
- prev = point;
- point = pointsCollection[i];
- //is bezier?
- if (prev.RightCurve != null || point.LeftCurve != null)
- {
- if (prev.RightCurve != null)
- {
- aPoints.Add(new PointF((prev.X + left + center.X + prev.RightCurve.X) * scaleX, (prev.Y + top + center.Y + prev.RightCurve.Y) * scaleY));
- pointTypes.Add(3);
- }
- else
- {
- PolyPoint pseudo = GetPseudoPoint(prev, point);
- aPoints.Add(new PointF((pseudo.X + left + center.X) * scaleX, (pseudo.Y + top + center.Y) * scaleY));
- pointTypes.Add(3);
- }
- if (point.LeftCurve != null)
- {
- aPoints.Add(new PointF((point.X + left + center.X + point.LeftCurve.X) * scaleX, (point.Y + top + center.Y + point.LeftCurve.Y) * scaleY));
- pointTypes.Add(3);
- }
- else
- {
- PolyPoint pseudo = GetPseudoPoint(point, prev);
- aPoints.Add(new PointF((pseudo.X + left + center.X) * scaleX, (pseudo.Y + top + center.Y) * scaleY));
- pointTypes.Add(3);
- }
- aPoints.Add(new PointF((point.X + left + center.X) * scaleX, (point.Y + top + center.Y) * scaleY));
- pointTypes.Add(3);
- }
- else
- {
- aPoints.Add(new PointF((point.X + left + center.X) * scaleX, (point.Y + top + center.Y) * scaleY));
- pointTypes.Add(1);
- }
- }
- return new GraphicsPath(aPoints.ToArray(), pointTypes.ToArray());
- }
- /// <summary>
- /// Recalculate position and size of element
- /// </summary>
- public void RecalculateBounds()
- {
- if (pointsCollection.Count > 0)
- {
- // init
- PolyPoint prev = null;
- PolyPoint point = pointsCollection[0];
- float left = point.X;
- float top = point.Y;
- float right = point.X;
- float bottom = point.Y;
- int count = pointsCollection.Count;
- if (this is PolygonObject)
- count++;
- // stage 1 calculate min bounds
- foreach (PolyPoint pnt in pointsCollection)
- {
- if (pnt.X < left)
- left = pnt.X;
- else if (pnt.X > right)
- right = pnt.X;
- if (pnt.Y < top)
- top = pnt.Y;
- else if (pnt.Y > bottom)
- bottom = pnt.Y;
- }
- // stage 2 check if one of bezier way point is outside
- for (int i = 1; i < count; i++)
- {
- prev = point;
- point = pointsCollection[i];
- bool haveToCalculate = false;
- PolyPoint p_1 = null;
- PolyPoint p_2 = null;
- if (prev.RightCurve != null)
- {
- p_1 = new PolyPoint(prev.X + prev.RightCurve.X, prev.Y + prev.RightCurve.Y);
- if (p_1.X < left)
- haveToCalculate = true;
- else if (p_1.X > right)
- haveToCalculate = true;
- if (p_1.Y < top)
- haveToCalculate = true;
- else if (p_1.Y > bottom)
- haveToCalculate = true;
- }
- if (point.LeftCurve != null)
- {
- p_2 = new PolyPoint(point.X + point.LeftCurve.X, point.Y + point.LeftCurve.Y);
- if (p_2.X < left)
- haveToCalculate = true;
- else if (p_2.X > right)
- haveToCalculate = true;
- if (p_2.Y < top)
- haveToCalculate = true;
- else if (p_2.Y > bottom)
- haveToCalculate = true;
- }
- if (haveToCalculate)
- {
- if (p_1 == null)
- p_1 = GetPseudoPoint(prev, point);
- if (p_2 == null)
- p_2 = GetPseudoPoint(point, prev);
- // now calculate extrema
- // x
- float delta = RecalculateBounds_Delta(prev.X, p_1.X, p_2.X, point.X);
- if (delta > 0)
- {
- delta = (float)Math.Sqrt(delta);
- float t_1 = RecalculateBounds_Solve(prev.X, p_1.X, p_2.X, point.X, -delta);
- if (0 < t_1 && t_1 < 1)
- {
- float x = RecalculateBounds_Value(prev.X, p_1.X, p_2.X, point.X, t_1);
- if (x < left)
- left = x;
- else if (x > right)
- right = x;
- }
- float t_2 = RecalculateBounds_Solve(prev.X, p_1.X, p_2.X, point.X, delta);
- if (0 < t_2 && t_2 < 1)
- {
- float x = RecalculateBounds_Value(prev.X, p_1.X, p_2.X, point.X, t_2);
- if (x < left)
- left = x;
- else if (x > right)
- right = x;
- }
- }
- // y
- delta = RecalculateBounds_Delta(prev.Y, p_1.Y, p_2.Y, point.Y);
- if (delta > 0)
- {
- delta = (float)Math.Sqrt(delta);
- float t_1 = RecalculateBounds_Solve(prev.Y, p_1.Y, p_2.Y, point.Y, -delta);
- if (0 < t_1 && t_1 < 1)
- {
- float y = RecalculateBounds_Value(prev.Y, p_1.Y, p_2.Y, point.Y, t_1);
- if (y < top)
- top = y;
- else if (y > bottom)
- bottom = y;
- }
- float t_2 = RecalculateBounds_Solve(prev.Y, p_1.Y, p_2.Y, point.Y, delta);
- if (0 < t_2 && t_2 < 1)
- {
- float y = RecalculateBounds_Value(prev.Y, p_1.Y, p_2.Y, point.Y, t_2);
- if (y < top)
- top = y;
- else if (y > bottom)
- bottom = y;
- }
- }
- }
- }
- // update
- float centerX = center.X;
- float centerY = center.Y;
- center.X = -left;
- center.Y = -top;
- base.Left += left + centerX;
- base.Top += top + centerY;
- base.Height = bottom - top;
- base.Width = right - left;
- }
- else
- {
- CenterX = 0;
- CenterY = 0;
- base.Width = 5;
- base.Height = 5;
- }
- }
- private float RecalculateBounds_Delta(float p_0, float p_1, float p_2, float p_3)
- {
- return p_1 * p_1 - p_0 * p_2 - p_1 * p_2 + p_2 * p_2 + p_0 * p_3 - p_1 * p_3;
- }
- private float RecalculateBounds_Solve(float p_0, float p_1, float p_2, float p_3, float deltaSqrt)
- {
- return (p_0 - 2 * p_1 + p_2 + deltaSqrt) / (p_0 - 3 * p_1 + 3 * p_2 - p_3);
- }
- private float RecalculateBounds_Value(float p_0, float p_1, float p_2, float p_3, float t)
- {
- float t1 = 1 - t;
- return p_0 * t1 * t1 * t1 + 3 * p_1 * t1 * t1 * t + 3 * p_2 * t1 * t * t + p_3 * t * t * t;
- }
- /// <inheritdoc/>
- public override void Serialize(FRWriter writer)
- {
- Border.SimpleBorder = true;
- base.Serialize(writer);
- PolyLineObject c = writer.DiffObject as PolyLineObject;
- StringBuilder sb = new StringBuilder(pointsCollection.Count * 10);
- foreach (PolyPoint point in pointsCollection)
- {
- point.Serialize(sb);
- sb.Append("|");
- }
- if (sb.Length > 0)
- sb.Length--;
- writer.WriteStr("PolyPoints_v2", sb.ToString());
- writer.WriteFloat("CenterX", center.X);
- writer.WriteFloat("CenterY", center.Y);
- if (DashPattern?.Count > 0)
- writer.WriteValue("DashPattern", DashPattern);
- }
- public void SetPolyLine(PointF[] newPoints)
- {
- pointsCollection.Clear();
- if (newPoints != null)
- {
- CenterX = 0;
- CenterY = 0;
- foreach (PointF point in newPoints)
- {
- pointsCollection.Add(new PolyPoint(point.X, point.Y));
- }
- }
- float l = Left;
- float t = Top;
- RecalculateBounds();
- Left = l;
- Top = t;
- }
- #endregion Public Methods
- #region Internal Methods
- internal void DoDrawPoly(FRPaintEventArgs e)
- {
- IGraphics g = e.Graphics;
- Report report = Report;
- if (report != null && report.SmoothGraphics)
- {
- g.InterpolationMode = InterpolationMode.HighQualityBicubic;
- g.SmoothingMode = SmoothingMode.AntiAlias;
- }
- drawPoly(e);
- if (report != null && report.SmoothGraphics)
- {
- g.InterpolationMode = InterpolationMode.Default;
- g.SmoothingMode = SmoothingMode.Default;
- }
- }
- #endregion Internal Methods
- #region Protected Methods
- /// <summary>
- /// Add point to end of polyline, need to recalculate bounds after add
- /// First point must have zero coordinate and zero type.
- /// Recalculate bounds.
- /// Method is slow do not use this.
- /// </summary>
- /// <param name="localX">local x - relative to left-top point</param>
- /// <param name="localY">local y - relative to left-top point</param>
- /// <param name="pointType">depreceted</param>
- protected PolyPoint addPoint(float localX, float localY, byte pointType)
- {
- PolyPoint result;
- pointsCollection.Add(result = new PolyPoint(localX, localY));
- RecalculateBounds();
- return result;
- }
- /// <summary>
- /// Delete point from polyline by index.
- /// Recalculate bounds.
- /// Method is slow do not use this.
- /// </summary>
- /// <param name="index">Index of point in polyline</param>
- protected void deletePoint(int index)
- {
- pointsCollection.Remove(index);
- RecalculateBounds();
- }
- /// <summary>
- /// Draw polyline path to graphics
- /// </summary>
- /// <param name="e">Event arguments</param>
- protected virtual void drawPoly(FRPaintEventArgs e)
- {
- Pen pen;
- if (polygonSelectionMode == PolygonSelectionMode.MoveAndScale)
- pen = e.Cache.GetPen(Border.Color, Border.Width * e.ScaleX, Border.DashStyle);
- else pen = e.Cache.GetPen(Border.Color, 1, DashStyle.Solid);
- DrawUtils.SetPenDashPatternOrStyle(DashPattern, pen, Border);
- using (GraphicsPath path = GetPath(pen, AbsLeft, AbsTop, AbsRight, AbsBottom, e.ScaleX, e.ScaleY))
- e.Graphics.DrawPath(pen, path);
- }
- /// <summary>
- /// Insert point to desired place of polyline
- /// recalculateBounds();
- /// Method is slow do not use this
- /// </summary>
- /// <param name="index">Index of place from zero to count</param>
- /// <param name="localX">local x - relative to left-top point</param>
- /// <param name="localY">local y - relative to left-top point</param>
- /// <param name="pointType">deprecated</param>
- protected PolyPoint insertPoint(int index, float localX, float localY, byte pointType)
- {
- PolyPoint result;
- pointsCollection.Insert(index, result = new PolyPoint(localX, localY));
- RecalculateBounds();
- return result;
- }
- #endregion Protected Methods
- #region Private Methods
- private float getDistance(float px, float py, float px0, float py0, float px1, float py1, out int index)
- {
- float vx = px1 - px0;
- float vy = py1 - py0;
- float wx = px - px0;
- float wy = py - py0;
- float c1 = vx * wx + vy * wy;
- if (c1 <= 0) { index = -1; return (px0 - px) * (px0 - px) + (py0 - py) * (py0 - py); }
- float c2 = vx * vx + vy * vy;
- if (c2 <= c1) { index = 1; return (px1 - px) * (px1 - px) + (py1 - py) * (py1 - py); }
- float b = c1 / c2;
- index = 0;
- float bx = px0 + vx * b;
- float by = py0 + vy * b;
- return (bx - px) * (bx - px) + (by - py) * (by - py);
- }
- private PolyPoint GetPseudoPoint(PolyPoint start, PolyPoint end)
- {
- float vecX = end.X - start.X;
- float vecY = end.Y - start.Y;
- float distance = (float)Math.Sqrt(vecX * vecX + vecY * vecY);
- vecX = vecX / 3;
- vecY = vecY / 3;
- return new PolyPoint(start.X + vecX, start.Y + vecY);
- }
- #endregion Private Methods
- #region Protected Internal Enums
- protected internal enum PolygonSelectionMode : int
- {
- MoveAndScale,
- Normal,
- AddToLine,
- AddBezier,
- Delete
- }
- #endregion Protected Internal Enums
- #region Public Classes
- /// <summary>
- /// Represent a point for polygon object
- /// </summary>
- public class PolyPoint
- {
- #region Private Fields
- private static readonly NumberFormatInfo invariant;
- private PolyPoint left;
- private PolyPoint right;
- private float x;
- private float y;
- #endregion Private Fields
- #region Public Properties
- public PolyPoint LeftCurve
- {
- get { return left; }
- set { left = value; }
- }
- public PolyPoint RightCurve
- {
- get { return right; }
- set { right = value; }
- }
- public float X
- {
- get { return x; }
- set { x = value; }
- }
- public float Y
- {
- get { return y; }
- set { y = value; }
- }
- #endregion Public Properties
- #region Public Constructors
- static PolyPoint()
- {
- invariant = new NumberFormatInfo();
- invariant.NumberGroupSeparator = String.Empty;
- invariant.NumberDecimalSeparator = ".";
- }
- public PolyPoint()
- {
- }
- public PolyPoint(float x, float y)
- {
- this.x = x;
- this.y = y;
- }
- #endregion Public Constructors
- #region Public Methods
- public void Deserialize(string s)
- {
- string[] strs = s.Split('/');
- int index = 0;
- Deserialize(strs, ref index);
- if (index < strs.Length)
- {
- if (strs[index] == "L")
- {
- index++;
- LeftCurve = new PolyPoint();
- LeftCurve.Deserialize(strs, ref index);
- }
- if (index < strs.Length)
- {
- if (strs[index] == "R")
- {
- index++;
- RightCurve = new PolyPoint();
- RightCurve.Deserialize(strs, ref index);
- }
- }
- }
- }
- public bool Near(PolyPoint p)
- {
- return (p != null) && (Math.Abs(x - p.x) < 0.0001) && (Math.Abs(y - p.y) < 0.0001);
- }
- public void ScaleX(float scale)
- {
- x *= scale;
- if (LeftCurve != null)
- LeftCurve.X *= scale;
- if (RightCurve != null)
- RightCurve.X *= scale;
- }
- public void ScaleY(float scale)
- {
- y *= scale;
- if (LeftCurve != null)
- LeftCurve.Y *= scale;
- if (RightCurve != null)
- RightCurve.Y *= scale;
- }
- public void Serialize(StringBuilder sb)
- {
- sb.Append(Round(x)).Append("/").Append(Round(y));
- if (LeftCurve != null)
- {
- sb.Append("/L/").Append(Round(LeftCurve.X)).Append("/").Append(Round(LeftCurve.Y));
- }
- if (RightCurve != null)
- {
- sb.Append("/R/").Append(Round(RightCurve.X)).Append("/").Append(Round(RightCurve.Y));
- }
- }
- public override string ToString()
- {
- return "(" + Round(x) + ";" + Round(y) + ")";
- }
- #endregion Public Methods
- #region Private Methods
- private void Deserialize(string[] strs, ref int index)
- {
- for (int i = 0; i < 2 && index < strs.Length; i++)
- {
- switch (i)
- {
- case 0:
- Single.TryParse(strs[index], NumberStyles.Float, invariant, out x);
- break;
- case 1:
- Single.TryParse(strs[index], NumberStyles.Float, invariant, out y);
- break;
- }
- index++;
- }
- }
- private string Round(float value)
- {
- return Convert.ToString(Math.Round(value, 4), invariant);
- }
- internal PolyPoint Clone()
- {
- PolyPoint result = new PolyPoint(x, y);
- if (LeftCurve != null)
- result.LeftCurve = LeftCurve.Clone();
- if (RightCurve != null)
- result.RightCurve = RightCurve.Clone();
- return result;
- }
- #endregion Private Methods
- }
- public class PolyPointCollection : IEnumerable<PolyPoint>
- {
- #region Private Fields
- private List<PolyPoint> points;
- #endregion Private Fields
- #region Public Indexers
- public PolyPoint this[int index]
- {
- get
- {
- index = NormalizeIndex(index);
- return points[index];
- }
- set
- {
- index = NormalizeIndex(index);
- points[index] = value;
- }
- }
- #endregion Public Indexers
- #region Public Properties
- public int Count
- {
- get
- {
- return points.Count;
- }
- }
- public bool IsReadOnly
- {
- get
- {
- return false;
- }
- }
- #endregion Public Properties
- #region Public Constructors
- public PolyPointCollection()
- {
- points = new List<PolyPoint>();
- }
- #endregion Public Constructors
- #region Public Methods
- public void Add(PolyPoint item)
- {
- points.Add(item);
- }
- public void Clear()
- {
- points.Clear();
- }
- public PolyPointCollection Clone()
- {
- PolyPointCollection result = new PolyPointCollection();
- result.points = new List<PolyPoint>();
- foreach (PolyPoint point in points)
- {
- result.points.Add(point.Clone());
- }
- return result;
- }
- public IEnumerator<PolyPoint> GetEnumerator()
- {
- return points.GetEnumerator();
- }
- IEnumerator IEnumerable.GetEnumerator()
- {
- return points.GetEnumerator();
- }
- public int IndexOf(PolyPoint currentPoint)
- {
- return points.IndexOf(currentPoint);
- }
- public void Insert(int index, PolyPoint item)
- {
- int count = points.Count;
- if (count > 0)
- {
- while (index < 0)
- index += count;
- while (index > count)
- index -= count;
- }
- points.Insert(index, item);
- }
- public void Remove(int index)
- {
- index = NormalizeIndex(index);
- points.RemoveAt(index);
- }
- #endregion Public Methods
- #region Private Methods
- private int NormalizeIndex(int index)
- {
- int count = points.Count;
- if (count == 0)
- return 0;
- if (index >= 0 && index < count)
- return index;
- while (index < 0)
- index += count;
- while (index >= count)
- index -= count;
- return index;
- }
- #endregion Private Methods
- }
- #endregion Public Classes
- }
- }
|