The code snippet below generates a curve line and arrow at the end of the path, as seen in the image below in wpf using C#. All you have to do is supply the function a starting and end point. You'll see in the image below that the Red Arrow on the left is incorrectly aligned to the path. The Red Arrow on the right is aligned correctly, however I'm not sure how to calculate the correct orientation? Does anyone have advice or a solution on how i could do this? The green points in the image demonstrate the points being generated in the function.
Thank you.
// Return the shape's path and arrow geometry.
protected override Geometry DefiningGeometry
{
get
{
GeometryGroup group = new GeometryGroup();
// Used for curvey lines
GenerateCurvedLine(group);
//GeneratedCurvedArrow(group);
// Used for straight lines
//GeneratedStraightLine(group);
GenerateArrowHeadGeometry(group);
// Return cached geometry.
return group;
}
}
// Generate the geometry for a curved line connecting the start and end points.
private void GenerateCurvedLine(GeometryGroup geometryGroup)
{
//Calculate points between start and end plugs
Point secondPoint = new Point(this.Start.X, this.Start.Y + 50);
Point thirdPoint = new Point(this.End.X, this.End.Y - 50);
// Build geometry for the curvey line.
PathFigure curvedPath = new PathFigure();
curvedPath.IsClosed = false;
curvedPath.IsFilled = false;
curvedPath.StartPoint = this.Start;
curvedPath.Segments.Add(new BezierSegment(secondPoint, thirdPoint, this.End, true));
PathGeometry pathGeometry = new PathGeometry();
pathGeometry.Figures.Add(curvedPath);
geometryGroup.Children.Add(pathGeometry);
}
Generates the Arrow at the end of the path, while orienting it towards the starting point.
// Generate the geometry for the three optional arrow symbol at the end of the path.
private void GenerateArrowHeadGeometry(GeometryGroup geometryGroup)
{
EllipseGeometry ellipse = new EllipseGeometry(this.Start, DotSize, DotSize);
geometryGroup.Children.Add(ellipse);
Vector startDir = this.End - this.Start;
startDir.Normalize();
Point basePoint = this.End - (startDir * ArrowHeadLength);
Vector crossDir = new Vector(-startDir.Y, startDir.X);
Point[] arrowHeadPoints = new Point[3];
arrowHeadPoints[0] = this.End;
arrowHeadPoints[1] = basePoint - (crossDir * (ArrowHeadWidth / 2));
arrowHeadPoints[2] = basePoint + (crossDir * (ArrowHeadWidth / 2));
// Build geometry for the arrow head.
PathFigure arrowHeadFig = new PathFigure();
arrowHeadFig.IsClosed = true;
arrowHeadFig.IsFilled = true;
arrowHeadFig.StartPoint = arrowHeadPoints[1];
arrowHeadFig.Segments.Add(new LineSegment(arrowHeadPoints[0], true));
arrowHeadFig.Segments.Add(new LineSegment(arrowHeadPoints[2], true));
PathGeometry pathGeometry = new PathGeometry();
pathGeometry.Figures.Add(arrowHeadFig);
geometryGroup.Children.Add(pathGeometry);
}