如何计算wpf中形状的方向

时间:2016-01-21 19:05:05

标签: c# wpf

下面的代码片段在路径末尾生成一条曲线和箭头,如下图所示,使用C#在wpf中看到。您所要做的就是为函数提供起点和终点。您将在下图中看到左侧的红色箭头与路径错误对齐。右侧的红色箭头正确对齐,但我不确定如何计算正确的方向?有没有人有关于我如何做到这一点的建议或解决方案?图像中的绿点表示在函数中生成的点。

谢谢。

enter image description here

// 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);
}

在路径末端生成箭头,同时将其定向到起点。

// 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);
}

1 个答案:

答案 0 :(得分:1)

免责声明:我不是数学专家......所以这可能都是错的。

你需要弄清线的末端曲线的斜率。如果你在时间t = 0.95使用贝塞尔曲线的参数方程(你可能需要调整这个值),然后在时间t = 1.0(这就是this.End)然后再减去它们,你会得到你的东西需要(最后曲线的斜率)。

要计算它,请参阅Quadratic Bezier Curve: Calculate Point - 您需要立方答案(第二个答案)。

在GenerateCurvedLine中,计算箭头方向,如下所示:

var t = 0.95;
var x1 = (1 - t) * (1 - t) * (1 - t) * this.Start.X
        + 3 * (1 - t) * (1 - t) * t * secondPoint.X
        + 3 * (1 - t) * t * t * thirdPoint.X
        + t * t * t * this.End.X;
var y1 = (1 - t) * (1 - t) * (1 - t) * this.Start.Y
        + 3 * (1 - t) * (1 - t) * t * secondPoint.Y
        + 3 * (1 - t) * t * t * thirdPoint.Y
        + t * t * t * this.End.Y;
arrowDir = new Vector(this.End.X - x1, this.End.Y - y1);

在GenerateArrowHeadGeometry中,使用上面的arrowDir而不是startDir。

FYI - t(时间)对于曲线上的点,范围从0到1。 0将是this.Start和1将是this.End。因此,t = 0.95将接近曲线的末端。