mirror of
https://gitee.com/akwkevin/aistudio.-wpf.-diagram
synced 2026-03-03 00:00:57 +08:00
86 lines
3.4 KiB
C#
86 lines
3.4 KiB
C#
using System;
|
||
using System.Collections.Generic;
|
||
using System.Text;
|
||
using System.Windows;
|
||
using System.Windows.Media;
|
||
|
||
namespace AIStudio.Wpf.DiagramDesigner
|
||
{
|
||
public class SegmentHelper
|
||
{
|
||
/// <summary>
|
||
/// 获得贝塞尔曲线
|
||
/// </summary>
|
||
/// <param name="currentPt">当前点</param>
|
||
/// <param name="lastPt">上一个点</param>
|
||
/// <param name="nextPt1">下一个点1</param>
|
||
/// <param name="nextPt2">下一个点2</param>
|
||
/// <returns></returns>
|
||
public static BezierSegment GetBezierSegment(Point currentPt, Point lastPt, Point nextPt1, Point nextPt2)
|
||
{
|
||
//计算中点
|
||
var lastC = GetCenterPoint(lastPt, currentPt);
|
||
var nextC1 = GetCenterPoint(currentPt, nextPt1); //贝塞尔控制点
|
||
var nextC2 = GetCenterPoint(nextPt1, nextPt2);
|
||
|
||
//计算相邻中点连线跟目的点的垂足
|
||
//效果并不算太好,因为可能点在两个线上或者线的延长线上,计算会有误差
|
||
//所以就直接使用中点平移方法。
|
||
//var C1 = GetFootPoint(lastC, nextC1, currentPt);
|
||
//var C2 = GetFootPoint(nextC1, nextC2, nextPt1);
|
||
|
||
|
||
//计算“相邻中点”的中点
|
||
var c1 = GetCenterPoint(lastC, nextC1);
|
||
var c2 = GetCenterPoint(nextC1, nextC2);
|
||
|
||
|
||
//计算【"中点"的中点】需要的点位移
|
||
var controlPtOffset1 = currentPt - c1;
|
||
var controlPtOffset2 = nextPt1 - c2;
|
||
|
||
//移动控制点
|
||
var controlPt1 = nextC1 + controlPtOffset1;
|
||
var controlPt2 = nextC1 + controlPtOffset2;
|
||
|
||
//如果觉得曲线幅度太大,可以将控制点向当前点靠近一定的系数。
|
||
controlPt1 = controlPt1 + 0 * (currentPt - controlPt1);
|
||
controlPt2 = controlPt2 + 0 * (nextPt1 - controlPt2);
|
||
|
||
var bzs = new BezierSegment(controlPt1, controlPt2, nextPt1, true);
|
||
return bzs;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 过c点做A和B连线的垂足
|
||
/// </summary>
|
||
/// <param name="aPoint"></param>
|
||
/// <param name="bPoint"></param>
|
||
/// <param name="cPoint"></param>
|
||
/// <returns></returns>
|
||
private static Point GetFootPoint(Point aPoint, Point bPoint, Point cPoint)
|
||
{
|
||
//设三点坐标是A,B,C,AB构成直线,C是线外的点
|
||
//三点对边距离是a,b,c,垂足为D,
|
||
//根据距离推导公式得:AD距离是(b平方-a平方+c平方)/2c
|
||
//本人数学不好,可能没考虑点c在线ab上的情况
|
||
var offsetADist = (Math.Pow(cPoint.X - aPoint.X, 2) + Math.Pow(cPoint.Y - aPoint.Y, 2) - Math.Pow(bPoint.X - cPoint.X, 2) - Math.Pow(bPoint.Y - cPoint.Y, 2) + Math.Pow(aPoint.X - bPoint.X, 2) + Math.Pow(aPoint.Y - bPoint.Y, 2)) / (2 * GetDistance(aPoint, bPoint));
|
||
|
||
var v = bPoint - aPoint;
|
||
var distab = GetDistance(aPoint, bPoint);
|
||
var offsetVector = v * offsetADist / distab;
|
||
return aPoint + offsetVector;
|
||
}
|
||
|
||
private static Point GetCenterPoint(Point pt1, Point pt2)
|
||
{
|
||
return new Point((pt1.X + pt2.X) / 2, (pt1.Y + pt2.Y) / 2);
|
||
}
|
||
|
||
private static double GetDistance(Point pt1, Point pt2)
|
||
{
|
||
return Math.Sqrt(Math.Pow(pt1.X - pt2.X, 2) + Math.Pow(pt1.Y - pt2.Y, 2));
|
||
}
|
||
}
|
||
}
|