using System;
using System.Collections.Generic;
using System.Windows;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Media;
namespace SketchAssistantWPF
{
public class InternalLine
{
///
/// list saving all the points of the line in the order of the path from start to end point
///
private List linePoints;
///
/// unique identifier of this Line object
///
private int identifier;
///
/// flag showing if this is only a temporary line
///
private bool isTemporary;
///
/// A collection of the original Points defining the line.
///
private PointCollection pointColl;
///
/// Indicates if this is a single point.
///
public bool isPoint { get; private set; }
///
/// The location of the point, if this is a point
///
public Point point { get; private set; }
///
/// The length of the line
///
private double length = -1;
///
/// The constructor for lines which are only temporary.
/// If you want nice lines use the other constructor.
///
/// The points of the line
public InternalLine(List points)
{
linePoints = new List(points);
pointColl = new PointCollection(linePoints);
isTemporary = true;
}
///
/// The constructor for lines, which will be more resource efficient
/// and have the ability to populate deletion matrixes.
///
/// The points of the line
/// The identifier of the line
public InternalLine(List points, int id)
{
linePoints = new List(points);
pointColl = new PointCollection(linePoints);
identifier = id;
CleanPoints();
isTemporary = false;
}
///
/// A function to make temporary lines non-temporary.
///
/// The id of the line.
public void MakePermanent(int id)
{
if (isTemporary)
{
identifier = id;
CleanPoints();
isTemporary = false;
}
}
public List GetPoints()
{
return linePoints;
}
public int GetID()
{
return identifier;
}
public PointCollection GetPointCollection()
{
return pointColl;
}
///
/// Get the length of the line.
///
/// The length of the line.
public double GetLength()
{
if(length < 0)
{
length = 0;
for(int i = 0; i < linePoints.Count - 1; i++)
{
var a = linePoints[i]; var b = linePoints[i + 1];
length += Math.Sqrt(Math.Pow((a.X - b.X),2) + Math.Pow((a.Y - b.Y), 2));
}
}
return length;
}
///
/// A function that will take two matrixes and populate them with the line data of this line object
///
/// The Matrix of booleans, in which is saved wether there is a line at this position.
/// The Matrix of Lists of integers, in which is saved which lines are at this position
public void PopulateMatrixes(bool[,] boolMatrix, HashSet[,] listMatrix)
{
if (!isTemporary)
{
foreach (Point currPoint in linePoints)
{
if (currPoint.X >= 0 && currPoint.Y >= 0 &&
currPoint.X < boolMatrix.GetLength(0) && currPoint.Y < boolMatrix.GetLength(1))
{
boolMatrix[(int) currPoint.X, (int) currPoint.Y] = true;
if (listMatrix[(int) currPoint.X, (int) currPoint.Y] == null)
{
listMatrix[(int) currPoint.X, (int) currPoint.Y] = new HashSet();
}
listMatrix[(int) currPoint.X, (int) currPoint.Y].Add(identifier);
}
}
}
}
///
/// Removes duplicate points from the line object
///
private void CleanPoints()
{
if (linePoints.Any())
{
//check if its a point
var localIsPoint = linePoints.All(o => o.X == linePoints.First().X && o.Y == linePoints.First().Y);
if (!localIsPoint) {
List newList = new List();
List tempList = new List();
//Since Point is non-nullable, we must ensure the nullPoints,
//which we remove can not possibly be points of the original given line.
int nullValue = (int) linePoints[0].X + 1;
//Fill the gaps between points
for (int i = 0; i < linePoints.Count - 1; i++)
{
nullValue += (int) linePoints[i + 1].X;
List partialList = GeometryCalculator.BresenhamLineAlgorithm(linePoints[i], linePoints[i + 1]);
tempList.AddRange(partialList);
}
Point nullPoint = new Point(nullValue, 0);
//Set duplicate points to the null point
for (int i = 1; i < tempList.Count; i++)
{
if ((tempList[i].X == tempList[i - 1].X) && (tempList[i].Y == tempList[i - 1].Y))
{
tempList[i - 1] = nullPoint;
}
}
//remove the null points
foreach (Point tempPoint in tempList)
{
if (tempPoint.X != nullValue)
{
newList.Add(tempPoint);
}
}
linePoints = new List(newList);
}
else
{
isPoint = true;
point = linePoints.First();
linePoints.Clear();
linePoints.Add(point);
}
}
}
}
}