private LineOrArrow InterpretAsPolyline(DragState state, List<Section> sections)
{
var shape = new LineOrArrow { Style = Control.LineStyle };
shape.FromAnchor = state.StartAnchor;
LineSegmentT prevLine = new LineSegmentT(), curLine;
for (int i = 0; i < sections.Count; i++)
{
int angleMod8 = sections[i].AngleMod8;
var startSS = sections[i].StartSS;
var endSS = sections[i].EndSS;
Vector<float> vector = Mod8Vectors[angleMod8];
Vector<float> perpVector = vector.Rot90();
bool isStartLine = i == 0;
bool isEndLine = i == sections.Count - 1;
if (isStartLine)
{
if (shape.FromAnchor != null)
startSS = shape.FromAnchor.Point;
}
if (isEndLine)
{
if ((shape.ToAnchor = Control.GetBestAnchor(endSS, angleMod8 + 4)) != null)
endSS = shape.ToAnchor.Point;
// Also consider forming a closed shape
else if (shape.Points.Count > 1
&& shape.Points[0].Sub(endSS).Length() <= DiagramControl.AnchorSnapDistance
&& Math.Abs(vector.Cross(shape.Points[1].Sub(shape.Points[0]))) > 0.001f)
endSS = shape.Points[0];
}
if (isStartLine)
curLine = startSS.To(startSS.Add(vector));
else
{
curLine = endSS.Sub(vector).To(endSS);
PointT? itsc = prevLine.ComputeIntersection(curLine, LineType.Infinite);
if (itsc.HasValue)
startSS = itsc.Value;
}
shape.Points.Add(startSS);
if (isEndLine)
{
if (isStartLine)
{
Debug.Assert(shape.Points.Count == 1);
var adjustedStart = startSS.ProjectOntoInfiniteLine(endSS.Sub(vector).To(endSS));
var adjustedEnd = endSS.ProjectOntoInfiniteLine(curLine);
if (shape.FromAnchor != null)
{
if (shape.ToAnchor != null)
{
// Both ends anchored => do nothing, allow unusual angle
}
else
{
// Adjust endpoint to maintain angle
endSS = adjustedEnd;
}
}
else
{
if (shape.ToAnchor != null)
// End anchored only => alter start point
shape.Points[0] = adjustedStart;
else
{
// Neither end anchored => use average line
shape.Points[0] = startSS.To(adjustedStart).Midpoint();
endSS = endSS.To(adjustedEnd).Midpoint();
}
}
}
shape.Points.Add(endSS);
}
prevLine = curLine;
}
shape.FromArrow = Control.FromArrow;
shape.ToArrow = Control.ToArrow;
return shape;
}