using FastReport.Utils;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Windows.Forms;
namespace FastReport
{
partial class PolyLineObject : IHasEditor
{
//Current selected point, for move
//internal PolyLineObjectToolBar toolbar; //deprecated
#region Private Fields
private PolyPoint currentPoint;
private PolyPoint drawSelectedPointLine;
private int drawSelectedPointLineNumber;
private int selectedPoint;
#endregion Private Fields
#region Public Properties
///
public override float Height
{
get { return base.Height; }
set
{
if (base.Height == 0)
{
base.Height = value;
return;
}
if (IsSelected)
{
if (SelectionMode == PolygonSelectionMode.MoveAndScale)
{
float oldHeight = base.Height;
if (oldHeight == value) return;
if (pointsCollection.Count < 2)
return;
float scaleY = value / oldHeight;
if (float.IsInfinity(scaleY))
return;
if (float.IsNaN(scaleY))
return;
if (scaleY == 0)
return;
center.Y = center.Y * scaleY;
foreach (PolyPoint point in pointsCollection)
{
point.ScaleY(scaleY);
}
base.Height = value;
}
else
RecalculateBounds();
}
else
base.Height = value;
}
}
///
public override float Width
{
get { return base.Width; }
set
{
if (base.Width == 0)
{
base.Width = value;
return;
}
if (IsSelected)
{
if (SelectionMode == PolygonSelectionMode.MoveAndScale)
{
float oldWidth = base.Width;
if (oldWidth == value) return;
if (pointsCollection.Count < 2)
return;
float scaleX = value / oldWidth;
if (float.IsInfinity(scaleX))
return;
if (float.IsNaN(scaleX))
return;
if (scaleX == 0)
return;
center.X = center.X * scaleX;
foreach (PolyPoint point in pointsCollection)
{
point.ScaleX(scaleX);
}
base.Width = value;
}
else
RecalculateBounds();
}
else
base.Width = value;
}
}
#endregion Public Properties
#region Internal Properties
internal PolygonSelectionMode SelectionMode
{
get
{
return polygonSelectionMode;
}
set
{
if (value != polygonSelectionMode)
{
polygonSelectionMode = value;
try
{
if (IsSelected)
{
Report.Designer.SelectionChanged(this);
}
}
catch
{
}
polygonSelectionMode = value;
}
}
}
#endregion Internal Properties
#region Public Methods
///
/// Add point to end of polyline and recalculate bounds after add.
/// Can be first point.
/// Deprecated, use insert point
///
/// local x - relative to left-top point
/// local y - relative to left-top point
[Obsolete]
public void AddPointToEnd(float localX, float localY)
{
insertPoint(pointsCollection.Count, localX, localY, 1);
if (Report != null)
if (Report.Designer != null)
Report.Designer.SetModified(this, "Change");
}
///
/// Add point to start of polyline and recalculate bounds after add
/// Can be first point
/// Deprecated, use insert point
///
/// local x - relative to left-top point
/// local y - relative to left-top point
[Obsolete]
public void AddPointToStart(float localX, float localY)
{
insertPoint(0, localX, localY, 1);
if (Report != null)
if (Report.Designer != null)
Report.Designer.SetModified(this, "Change");
}
///
public override void CheckNegativeSize(FRMouseEventArgs e)
{
// do nothing
}
///
public override void DrawSelection(FRPaintEventArgs e)
{
if (SelectionMode == PolygonSelectionMode.AddToLine && drawSelectedPointLineNumber >= 0 && pointsCollection.Count > 0)
{
if (drawSelectedPointLine != null)
{
float absLeft = AbsLeft;
float absTop = AbsTop;
Pen p = e.Cache.GetPen(Color.DarkGray, 1, DashStyle.Solid);
if (drawSelectedPointLineNumber > 0 && drawSelectedPointLineNumber - 1 < pointsCollection.Count || this is PolygonObject)
{
e.Graphics.DrawLine(p, GetPointF(drawSelectedPointLine, e.ScaleX, e.ScaleY, absLeft, absTop), GetPointF(drawSelectedPointLineNumber - 1, e.ScaleX, e.ScaleY, absLeft, absTop));
}
if (drawSelectedPointLineNumber < pointsCollection.Count || this is PolygonObject)
{
e.Graphics.DrawLine(p, GetPointF(drawSelectedPointLine, e.ScaleX, e.ScaleY, absLeft, absTop), GetPointF(drawSelectedPointLineNumber, e.ScaleX, e.ScaleY, absLeft, absTop));
}
}
}
if (SelectionMode == PolygonSelectionMode.MoveAndScale)
{
base.DrawSelection(e);
}
else
{
Pen help_p = e.Cache.GetPen(Color.Black, 1, DashStyle.Dash);
if (Page == null)
return;
bool firstSelected = Report.Designer.SelectedObjects.IndexOf(this) == 0;
Pen p = firstSelected ? Pens.Black : Pens.White;
Brush b = firstSelected ? Brushes.White : Brushes.Black;
SelectionPoint[] selectionPoints = GetSelectionPoints();
IGraphics g = e.Graphics;
SelectionPoint lastPoint = null;
float m = Report.Designer.DpiMultiplier();
foreach (SelectionPoint pt in selectionPoints)
{
switch (pt.sizingPoint)
{
case SizingPoint.LeftTop:
{
float x = pt.x * e.ScaleX;
float y = pt.y * e.ScaleY;
g.FillEllipse(Brushes.White, x - 5 * m, y - 5 * m, 10 * m, 10 * m);
g.FillEllipse(Brushes.Red, x - 3 * m, y - 3 * m, 6 * m, 6 * m);
g.DrawEllipse(Pens.Gray, x - 3 * m, y - 3 * m, 6 * m, 6 * m);
lastPoint = pt;
}
break;
case SizingPoint.RightTop:
{
float x = pt.x * e.ScaleX;
float y = pt.y * e.ScaleY;
if (lastPoint != null)
{
e.Graphics.DrawLine(help_p, lastPoint.x * e.ScaleX, lastPoint.y * e.ScaleY, x, y);
}
g.FillEllipse(Brushes.White, x - 3 * m, y - 3 * m, 6 * m, 6 * m);
g.FillEllipse(Brushes.Blue, x - 2 * m, y - 2 * m, 4 * m, 4 * m);
g.DrawEllipse(Pens.Gray, x - 2 * m, y - 2 * m, 4 * m, 4 * m);
}
break;
default:
lastPoint = pt;
DrawSelectionPoint(e, p, b, pt.x, pt.y);
break;
}
}
}
}
///
/// Replace points with star
///
/// Minimum value is 3
public void DrawStar(int spikes)
{
if (spikes < 3) spikes = 3;
const float outerRadius = 50;
const float innerRadius = 30;
float rot = (float)(Math.PI / 2 * 3);
const float cx = 0;
const float cy = 0;
float x = cx;
float y = cy;
float step = (float)(Math.PI / spikes);
base.Width = 100;
base.Height = 100;
center = new PointF(50, 50);
pointsCollection.Clear();
pointsCollection.Add(new PolyPoint(cx, cy - outerRadius));
for (int i = 0; i < spikes; i++)
{
x = cx + (float)Math.Cos(rot) * outerRadius;
y = cy + (float)Math.Sin(rot) * outerRadius;
pointsCollection.Add(new PolyPoint(x, y));
rot += step;
x = cx + (float)Math.Cos(rot) * innerRadius;
y = cy + (float)Math.Sin(rot) * innerRadius;
pointsCollection.Add(new PolyPoint(x, y));
rot += step;
}
}
///
public override SizeF GetPreferredSize()
{
return new SizeF(0, 0);
}
///
public override void HandleKeyDown(Control sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.Delete)
{
if (SelectionMode != PolygonSelectionMode.MoveAndScale)
{
if (pointsCollection.Count > 0)
{
DeletePointByIndex(selectedPoint);
selectedPoint--;
Report.Designer.Refresh();
e.Handled = true;
}
}
}
if (!e.Handled)
base.HandleKeyDown(sender, e);
}
///
public override void HandleMouseDown(FRMouseEventArgs e)
{
//if (toolbar.IsVisible && this.IsSelected)
//{
// if (toolbar.ClickPublic(new PointF(AbsLeft, AbsTop < 20 ? 20 : AbsTop), new PointF(e.x, e.y)))
// {
// e.handled = true;
// return;
// }
//}
if (e.button == MouseButtons.Left && currentPoint == null && this.IsSelected)
{
float absLeft = AbsLeft;
float absTop = AbsTop;
PointF mousePoint = new PointF(e.x, e.y);
PointF mousePointAligned = new PointF((int)((e.x - absLeft - center.X) / Page.SnapSize.Width) * Page.SnapSize.Width, (int)((e.y - absTop - center.Y) / Page.SnapSize.Height) * Page.SnapSize.Height);
switch (SelectionMode)
{
case PolygonSelectionMode.Normal:
for (int i = 0; i < pointsCollection.Count; i++)
{
PolyPoint point = pointsCollection[i];
if (point.LeftCurve != null && PointInSelectionPoint(absLeft + point.X + center.X + point.LeftCurve.X, absTop + point.Y + center.Y + point.LeftCurve.Y, mousePoint))
{
currentPoint = point.LeftCurve;
e.mode = WorkspaceMode2.Custom;
e.handled = true;
break;
}
else if (point.RightCurve != null && PointInSelectionPoint(absLeft + point.X + center.X + point.RightCurve.X, absTop + point.Y + center.Y + point.RightCurve.Y, mousePoint))
{
currentPoint = point.RightCurve;
e.mode = WorkspaceMode2.Custom;
e.handled = true;
break;
}
else if (PointInSelectionPoint(absLeft + point.X + center.X, absTop + point.Y + center.Y, mousePoint))
{
currentPoint = point;
e.mode = WorkspaceMode2.Custom;
e.handled = true;
break;
}
}
break;
case PolygonSelectionMode.AddToLine:
for (int i = 0; i < pointsCollection.Count; i++)
{
PolyPoint point = pointsCollection[i];
if (PointInSelectionPoint(absLeft + point.X + center.X, absTop + point.Y + center.Y, mousePoint))
{
currentPoint = point;
e.mode = WorkspaceMode2.Custom;
e.handled = true;
break;
}
}
if (!e.handled)
{
e.handled = true;
PolyPoint result = InsertPointByLocation(mousePointAligned.X, mousePointAligned.Y, 25);
if (result != null)
{
e.mode = WorkspaceMode2.Custom;
currentPoint = result;
}
}
break;
case PolygonSelectionMode.AddBezier:
for (int i = 0; i < pointsCollection.Count; i++)
{
PolyPoint point = pointsCollection[i];
if (point.LeftCurve != null)
{
if (PointInSelectionPoint(absLeft + point.X + center.X + point.LeftCurve.X, absTop + point.Y + center.Y + point.LeftCurve.Y, mousePoint))
{
currentPoint = point.LeftCurve;
e.mode = WorkspaceMode2.Custom;
e.handled = true;
break;
}
}
else if (i == selectedPoint)
{
if (i > 0 || (this is PolygonObject))
{
PolyPoint pseudoPoint = GetPseudoPoint(point, pointsCollection[i - 1]);
if (PointInSelectionPoint(absLeft + pseudoPoint.X + center.X, absTop + pseudoPoint.Y + center.Y, mousePoint))
{
pseudoPoint.X -= point.X;
pseudoPoint.Y -= point.Y;
point.LeftCurve = pseudoPoint;
currentPoint = pseudoPoint;
e.mode = WorkspaceMode2.Custom;
e.handled = true;
break;
}
}
}
if (point.RightCurve != null)
{
if (PointInSelectionPoint(absLeft + point.X + center.X + point.RightCurve.X, absTop + point.Y + center.Y + point.RightCurve.Y, mousePoint))
{
currentPoint = point.RightCurve;
e.mode = WorkspaceMode2.Custom;
e.handled = true;
break;
}
}
else
{
if (i < pointsCollection.Count || (this is PolygonObject))
{
PolyPoint pseudoPoint = GetPseudoPoint(point, pointsCollection[i + 1]);
if (PointInSelectionPoint(absLeft + pseudoPoint.X + center.X, absTop + pseudoPoint.Y + center.Y, mousePoint))
{
pseudoPoint.X -= point.X;
pseudoPoint.Y -= point.Y;
point.RightCurve = pseudoPoint;
currentPoint = pseudoPoint;
e.mode = WorkspaceMode2.Custom;
e.handled = true;
break;
}
}
}
if (PointInSelectionPoint(absLeft + point.X + center.X, absTop + point.Y + center.Y, mousePoint))
{
currentPoint = point;
e.mode = WorkspaceMode2.Custom;
e.handled = true;
break;
}
}
break;
case PolygonSelectionMode.Delete:
for (int i = 0; i < pointsCollection.Count; i++)
{
PolyPoint point = pointsCollection[i];
if (point.LeftCurve != null && PointInSelectionPoint(absLeft + point.X + center.X + point.LeftCurve.X, absTop + point.Y + center.Y + point.LeftCurve.Y, mousePoint))
{
point.LeftCurve = null;
currentPoint = null;
e.mode = WorkspaceMode2.None;
e.handled = true;
return;
}
else if (point.RightCurve != null && PointInSelectionPoint(absLeft + point.X + center.X + point.RightCurve.X, absTop + point.Y + center.Y + point.RightCurve.Y, mousePoint))
{
point.RightCurve = null;
currentPoint = null;
e.mode = WorkspaceMode2.None;
e.handled = true;
return;
}
else if (PointInSelectionPoint(absLeft + point.X + center.X, absTop + point.Y + center.Y, mousePoint))
{
RemovePointAt(i);
currentPoint = null;
if (i < selectedPoint)
selectedPoint--;
e.mode = WorkspaceMode2.None;
e.handled = true;
return;
}
}
break;
case PolygonSelectionMode.MoveAndScale:
if (pointsCollection.Count < 2)
{
for (int i = 0; i < pointsCollection.Count; i++)
{
PolyPoint point = pointsCollection[i];
if (PointInSelectionPoint(absLeft + point.X + center.X, absTop + point.Y + center.Y, mousePoint))
{
currentPoint = point;
e.mode = WorkspaceMode2.Custom;
e.handled = true;
break;
}
}
}
break;
}
}
if (!e.handled)
base.HandleMouseDown(e);
}
///
public override void HandleMouseMove(FRMouseEventArgs e)
{
if (currentPoint != null)
{
currentPoint.X += e.delta.X;
currentPoint.Y += e.delta.Y;
//points[currentPoint] = point;
RecalculateBounds();
e.mode = WorkspaceMode2.Custom;
e.handled = true;
}
if (!e.handled && SelectionMode == PolygonSelectionMode.AddToLine)
{
PolyPoint mousePointAligned = new PolyPoint((int)((e.x - AbsLeft - center.X) / Page.SnapSize.Width) * Page.SnapSize.Width, (int)((e.y - AbsTop - center.Y) / Page.SnapSize.Height) * Page.SnapSize.Height);
drawSelectedPointLineNumber = GetBestPointPosition(mousePointAligned.X, mousePointAligned.Y);
if (drawSelectedPointLine == null || !drawSelectedPointLine.Near(mousePointAligned))
{
drawSelectedPointLine = mousePointAligned;
Report.Designer.Refresh();
}
}
else
{
drawSelectedPointLineNumber = -1;
}
if (!e.handled)
{
base.HandleMouseMove(e);
}
if (e.handled)
{
e.cursor = Cursors.Cross;
}
if (IsSelected)
{
switch (SelectionMode)
{
case PolygonSelectionMode.AddToLine:
case PolygonSelectionMode.AddBezier:
e.handled = true;
e.mode = WorkspaceMode2.Custom;
break;
}
}
//if (toolbar != null && toolbar.IsVisible)
//{
// //toolbar.MouseMove(e.x, e.y);
//}
}
///
public override void HandleMouseUp(FRMouseEventArgs e)
{
if (currentPoint != null)
{
RecalculateBounds();
int index = pointsCollection.IndexOf(currentPoint);
if (index >= 0)
selectedPoint = index;
currentPoint = null;
if (Report != null)
if (Report.Designer != null)
Report.Designer.SetModified(this, "Change");
}
if (IsSelected)
{
int mode = (int)SelectionMode;
if (0 < mode)
{
e.handled = true;
}
}
if (!e.handled)
base.HandleMouseUp(e);
}
///
/// Insert point to desired place of polyline
/// Recalculate bounds after insert
///
/// Index of place from zero to count
/// local x - relative to left-top point
/// local y - relative to left-top point
public void InsertPointByIndex(int index, float localX, float localY)
{
insertPoint(index, localX, localY, 0);
if (Report != null)
if (Report.Designer != null)
Report.Designer.SetModified(this, "Change");
}
///
/// Insert point to near line
/// Recalculate bounds after insert
///
/// local x - relative to left-top point
/// local y - relative to left-top point
/// depricated
/// Index of inserted point
public PolyPoint InsertPointByLocation(float localX, float localY, float maxDistance)
{
PolyPoint result;
int pointNumber = -1;
if (pointsCollection.Count == 0)
{
result = addPoint(0, 0, 0);
pointNumber = 0;
}
else
{
pointNumber = GetBestPointPosition(localX, localY);
result = insertPoint(pointNumber, localX, localY, 1);
}
RecalculateBounds();
if (pointNumber >= 0)
if (Report != null)
if (Report.Designer != null)
Report.Designer.SetModified(this, "Change");
return result;
}
///
public bool InvokeEditor()
{
if (IsSelected)
{
if (SelectionMode == PolygonSelectionMode.MoveAndScale)
{
Report report = Report;
if (report != null)
{
SelectionMode = PolygonSelectionMode.Normal;
}
return true;
}
else if (SelectionMode == PolygonSelectionMode.Normal)
{
Report report = Report;
if (report != null)
{
SelectionMode = PolygonSelectionMode.MoveAndScale;
}
return true;
}
}
return false;
}
///
public override void OnAfterInsert(InsertFrom source)
{
base.OnAfterInsert(source);
if (Report != null)
{
SelectedObjectCollection selectionObjects = Report.Designer.SelectedObjects;
selectionObjects.Clear();
selectionObjects.Add(this);
}
if (pointsCollection.Count < 2)
SelectionMode = PolygonSelectionMode.AddToLine;
if (pointsCollection.Count > 1)
SelectionMode = PolygonSelectionMode.MoveAndScale;
}
///
public override void OnBeforeInsert(int flags)
{
float rotation = (float)((flags & 0xF) / 8.0 * Math.PI);
int numberOfEdges = (flags & 0xF0) >> 4;
if (numberOfEdges >= 5)
{
float x, y;
pointsCollection.Clear();
for (int i = 0; i < numberOfEdges; i++)
{
base.Width = 100;
base.Height = 100;
x = 50 + (float)(50 * Math.Cos(rotation + 2 * Math.PI * i / numberOfEdges));
y = 50 + (float)(50 * Math.Sin(rotation + 2 * Math.PI * i / numberOfEdges));
pointsCollection.Add(new PolyPoint(x, y));
}
}
else
{
pointsCollection.Add(new PolyPoint(0, 0));
Width = 5;
Height = 5;
}
}
///
public override bool PointInObject(PointF point)
{
using (Pen pen = new Pen(Color.Black, 10))
using (GraphicsPath path = new GraphicsPath())
{
float absLeft = AbsLeft;
float absTop = AbsTop;
if (pointsCollection.Count > 1 && currentPoint == null)
for (int i = 0; i < pointsCollection.Count - 1; i++)
{
PolyPoint prev = pointsCollection[i];
PolyPoint next = pointsCollection[i + 1];
path.AddLine(absLeft + prev.X + center.X, absTop + prev.Y + center.Y, absLeft + next.X + center.X, absTop + next.Y + center.Y);
}
else
path.AddLine(absLeft - 1 + CenterX, absTop - 1 + CenterY, AbsRight + 1 + CenterX, AbsBottom + 1 + CenterY);
return path.IsOutlineVisible(point, pen);
}
}
///
/// Delete point from polyline by index
/// Recalculate bounds after remove
///
/// Index of point in polyline
public void RemovePointAt(int index)
{
deletePoint(index);
if (Report != null)
if (Report.Designer != null)
Report.Designer.SetModified(this, "Change");
}
///
public override void SelectionChanged()
{
base.SelectionChanged();
if (!IsSelected)
SelectionMode = PolygonSelectionMode.MoveAndScale;
}
#endregion Public Methods
#region Protected Methods
///
/// Delete point from polyline by index.
/// Recalculate bounds.
///
/// Index of point in polyline
protected void DeletePointByIndex(int index)
{
pointsCollection.Remove(index);
RecalculateBounds();
}
///
protected override void DrawSelectionPoint(FRPaintEventArgs e, Pen p, Brush b, float x, float y)
{
if (SelectionMode == PolygonSelectionMode.MoveAndScale)
{
base.DrawSelectionPoint(e, p, b, x, y);
}
else
{
IGraphics g = e.Graphics;
x = (float)Math.Round(x * e.ScaleX);
y = (float)Math.Round(y * e.ScaleY);
float m = Report.Designer.DpiMultiplier();
RectangleF rect = new RectangleF(x - 3 * m, y - 3 * m, 6 * m, 6 * m);
g.FillEllipse(b, rect);
g.DrawEllipse(p, rect);
}
}
///
protected override SelectionPoint[] GetSelectionPoints()
{
List selectionPoints = new List();
if (pointsCollection.Count == 0)
{
return new SelectionPoint[] {
new SelectionPoint(AbsLeft + CenterX, AbsTop + CenterY,SizingPoint.None)
};
}
if (SelectionMode == PolygonSelectionMode.MoveAndScale && pointsCollection.Count > 1)
{
return base.GetSelectionPoints();
}
if (pointsCollection.Count > 0)
selectedPoint = (pointsCollection.Count + selectedPoint) % pointsCollection.Count;
float absLeft = AbsLeft;
float absTop = AbsTop;
for (int i = 0; i < pointsCollection.Count; i++)
{
PolyPoint point = pointsCollection[i];
selectionPoints.Add(new SelectionPoint(point.X + absLeft + center.X, point.Y + absTop + center.Y,
i == selectedPoint ? SizingPoint.LeftTop : SizingPoint.RightBottom));
if (SelectionMode != PolygonSelectionMode.AddToLine)
{
if (point.LeftCurve != null)
{
selectionPoints.Add(new SelectionPoint(point.X + absLeft + center.X + point.LeftCurve.X, point.Y + absTop + center.Y + point.LeftCurve.Y, SizingPoint.RightTop));
}
else if (SelectionMode == PolygonSelectionMode.AddBezier && i == selectedPoint)
{
if (i > 0 || (this is PolygonObject))
{
PolyPoint pseudoPoint = GetPseudoPoint(point, pointsCollection[i - 1]);
selectionPoints.Add(new SelectionPoint(pseudoPoint.X + absLeft + center.X, pseudoPoint.Y + absTop + center.Y, SizingPoint.RightTop));
}
}
if (point.RightCurve != null)
{
selectionPoints.Add(new SelectionPoint(point.X + absLeft + center.X + point.RightCurve.X, point.Y + absTop + center.Y + point.RightCurve.Y, SizingPoint.RightTop));
}
else if (SelectionMode == PolygonSelectionMode.AddBezier && i == selectedPoint)
{
if (i < pointsCollection.Count - 1 || (this is PolygonObject))
{
PolyPoint pseudoPoint = GetPseudoPoint(point, pointsCollection[i + 1]);
selectionPoints.Add(new SelectionPoint(pseudoPoint.X + absLeft + center.X, pseudoPoint.Y + absTop + center.Y, SizingPoint.RightTop));
}
}
}
}
return selectionPoints.ToArray();
}
#endregion Protected Methods
#region Private Methods
private void DrawDesign0(FRPaintEventArgs e)
{
if (IsSelected && SelectionMode == PolyLineObject.PolygonSelectionMode.MoveAndScale)
{
Pen pen = e.Cache.GetPen(Color.Gray, 1, DashStyle.Dot);
e.Graphics.DrawRectangle(pen, AbsLeft * e.ScaleX, AbsTop * e.ScaleY, Width * e.ScaleX, Height * e.ScaleY);
}
}
private void DrawDesign1(FRPaintEventArgs e)
{
}
///
/// Returns best new point position based on mouse
///
///
private int GetBestPointPosition(float localX, float localY)
{
if (pointsCollection.Count > 0)
{
selectedPoint = (pointsCollection.Count + selectedPoint) % pointsCollection.Count;
//add near select point
//check if point is first or last
if (selectedPoint == pointsCollection.Count - 1 && !(this is PolygonObject))
{
return pointsCollection.Count;
}
else if (selectedPoint == 0 && !(this is PolygonObject))
{
return 0;
}
else
{
PolyPoint local = new PolyPoint(localX, localY);
PolyPoint pLeft = pointsCollection[selectedPoint - 1];
PolyPoint pCenter = pointsCollection[selectedPoint];
PolyPoint pRight = pointsCollection[selectedPoint + 1];
//float pLeft_pLocal =
// ((pLeft.X + CenterX - localX) * (pLeft.X + CenterX - localX) + (pLeft.Y + CenterY - localY) * (pLeft.Y + CenterY - localY));
//float pRight_pLocal =
// ((pRight.X + CenterX - localX) * (pRight.X + CenterX - localX) + (pRight.Y + CenterY - localY) * (pRight.Y + CenterY - localY));
//float pLeft_pCenter = ((pLeft.X - pCenter.X) * (pLeft.X - pCenter.X) + (pLeft.Y - pCenter.Y) * (pLeft.Y - pCenter.Y));
//float pRight_pCenter = ((pRight.X - pCenter.X) * (pRight.X - pCenter.X) + (pRight.Y - pCenter.Y) * (pRight.Y - pCenter.Y));
//float distance1 = pLeft_pLocal/ pLeft_pCenter;
//float distance2 = pRight_pLocal / pRight_pCenter;
float distance1 = MATH_pnt_seg_dist(local, pLeft, pCenter);
float distance2 = MATH_pnt_seg_dist(local, pCenter, pRight);
if (distance1 < distance2)
{
return selectedPoint;
}
else
{
return selectedPoint + 1;
}
}
}
return 0;
}
private PointF GetPointF(int index, float scaleX, float scaleY, float absLeft, float absTop)
{
return GetPointF(pointsCollection[index], scaleX, scaleY, absLeft, absTop);
}
private PointF GetPointF(PolyPoint point, float scaleX, float scaleY, float absLeft, float absTop)
{
return new PointF(
(point.X + absLeft + center.X) * scaleX,
(point.Y + absTop + center.Y) * scaleY
);
}
private void InitDesign()
{
currentPoint = null;
SelectionMode = PolygonSelectionMode.MoveAndScale;
//toolbar = new PolyLineObjectToolBar(this);
}
private float MATH_dot(float aX, float aY, float bX, float bY)
{
return aX * bX + aY * bY;
}
private float MATH_length_squared(PolyPoint a, PolyPoint b)
{
return (a.X - b.X) * (a.X - b.X) + (a.Y - b.Y) * (a.Y - b.Y);
}
private float MATH_pnt_seg_dist(PolyPoint p, PolyPoint v, PolyPoint w)
{
// Return minimum distance between line segment vw and point p
float l2 = MATH_length_squared(v, w); // i.e. |w-v|^2 - avoid a sqrt
if (l2 == 0.0) return MATH_length_squared(p, v); // v == w case
// Consider the line extending the segment, parameterized as v + t (w - v).
// We find projection of point p onto the line.
// It falls where t = [(p-v) . (w-v)] / |w-v|^2
// We clamp t from [0,1] to handle points outside the segment vw.
float t = Math.Max(0, Math.Min(1, MATH_dot(p.X - v.X, p.Y - v.Y, w.X - v.X, w.Y - v.Y) / l2));
PolyPoint projection = new PolyPoint(v.X + t * (w.X - v.X), v.Y + t * (w.Y - v.Y)); // Projection falls on the segment
return MATH_length_squared(p, projection);
}
#endregion Private Methods
}
}