namespace IStation.Curve
{
///
/// 贝塞尔线
///
public class BezierCurveHelper
{
///
/// 获取开放的贝塞尔曲线列表
///
public static List CreateOpenCurves(List points)
{
//http://wenku.baidu.com/link?url=9TGvGfedfkbskSWwfeO_iJJHvIzL0E_mE3wwVlWs1kEvvT9dHDQFdArhcdh8yuCK3pUbw2soJKs5qiQKlzhA885Tgtbu-Cdr1T37ANki_mS
if (points == null || points.Count() < 4)
return default;
int iPointCout = points.Count();
double a = 0.25;
double b = 0.25;
List controlPoint = new List();
//生成4控制点,产生贝塞尔曲线
for (int i = 0; i < iPointCout - 1; i++)
{
Bezier3 bezier = new Bezier3();
bezier.Point0 = points[i];
if (i == 0)
{
double x1 = points[i].X + a * (points[i + 1].X - points[i].X);
double y1 = points[i].Y + a * (points[i + 1].Y - points[i].Y);
bezier.Point1 = new CurvePoint(x1, y1);
}
else
{
double x1 = points[i].X + a * (points[i + 1].X - points[i - 1].X);
double y1 = points[i].Y + a * (points[i + 1].Y - points[i - 1].Y);
bezier.Point1 = new CurvePoint(x1, y1);
}
if (i == iPointCout - 2)
{
double x2 = points[i + 1].X - b * (points[i + 1].X - points[i].X);
double y2 = points[i + 1].Y - b * (points[i + 1].Y - points[i].Y);
bezier.Point2 = new CurvePoint(x2, y2);
}
else
{
double x2 = points[i + 1].X - b * (points[i + 2].X - points[i].X);
double y2 = points[i + 1].Y - b * (points[i + 2].Y - points[i].Y);
bezier.Point2 = new CurvePoint(x2, y2);
}
bezier.Point3 = points[i + 1];
controlPoint.Add(bezier);
}
return controlPoint;
}
///
/// 获取封闭的贝塞尔曲线列表
///
public static List CreateCloseCurves(List points)
{
//http://blog.csdn.net/microchenhong/article/details/6316332
int originCount = points.Count();
//控制点收缩系数 ,经调试0.6较好
float scale = 0.6f;
var midpoints = new List();
//生成中点
for (int i = 0; i < originCount; i++)
{
int nexti = (i + 1) % originCount;
double x = (points[i].X + points[nexti].X) / 2.0;
double y = (points[i].Y + points[nexti].Y) / 2.0;
midpoints.Add(new CurvePoint(x, y));
}
//平移中点
var extrapoints = new List();//[2 * originCount];
for (int i = 0; i < originCount * 2; i++)
{
extrapoints.Add(new CurvePoint(0, 0));
}
for (int i = 0; i < originCount; i++)
{
int nexti = (i + 1) % originCount;
int backi = (i + originCount - 1) % originCount;
var midinmid = new CurvePoint();
midinmid.X = (midpoints[i].X + midpoints[backi].X) / 2.0;
midinmid.Y = (midpoints[i].Y + midpoints[backi].Y) / 2.0;
double offsetx = points[i].X - midinmid.X;
double offsety = points[i].Y - midinmid.Y;
int extraindex = 2 * i;
extrapoints[extraindex].X = midpoints[backi].X + offsetx;
extrapoints[extraindex].Y = midpoints[backi].Y + offsety;
//朝 originPoint[i]方向收缩
double addx = (extrapoints[extraindex].X - points[i].X) * scale;
double addy = (extrapoints[extraindex].Y - points[i].Y) * scale;
extrapoints[extraindex].X = points[i].X + addx;
extrapoints[extraindex].Y = points[i].Y + addy;
int extranexti = (extraindex + 1) % (2 * originCount);
extrapoints[extranexti].X = midpoints[i].X + offsetx;
extrapoints[extranexti].Y = midpoints[i].Y + offsety;
//朝 originPoint[i]方向收缩
addx = (extrapoints[extranexti].X - points[i].X) * scale;
addy = (extrapoints[extranexti].Y - points[i].Y) * scale;
extrapoints[extranexti].X = points[i].X + addx;
extrapoints[extranexti].Y = points[i].Y + addy;
}
List controlPoint = new List();
//生成4控制点,产生贝塞尔曲线
for (int i = 0; i < originCount - 1; i++)
{
Bezier3 bezier = new Bezier3();
bezier.Point0 = points[i];
int extraindex = 2 * i;
bezier.Point1 = extrapoints[extraindex + 1];
int extranexti = (extraindex + 2) % (2 * originCount);
bezier.Point2 = extrapoints[extranexti];
int nexti = (i + 1) % originCount;
bezier.Point3 = points[nexti];
controlPoint.Add(bezier);
}
return controlPoint;
}
///
/// 通过 X 获取交点
///
public static List GetSectPointsByX(List allBeziers, double x)
{
if (allBeziers == null || allBeziers.Count() < 1)
return null;
var points_sect_list = new List();
foreach (var bezeir in allBeziers)
{
//贝塞尔曲线与性能曲线有交点
if ((x <= bezeir.Point0.X && x >= bezeir.Point3.X) || (x >= bezeir.Point0.X && x <= bezeir.Point3.X))
{
#region 贝塞尔曲线集合循环
//第一次循环
for (int i = 0; i < 10; i++)
{
var start0_uu = i * 0.1;
var end0_uu = start0_uu + 0.1;
var start0_p_x = bezeir.GetX(start0_uu);
//var start0_p_y = bezeir.GetY(start0_uu);
var end0_p_x = bezeir.GetX(end0_uu);
//var end0_p_y = bezeir.GetY(end0_uu);
if ((x <= start0_p_x && x >= end0_p_x) || (x >= start0_p_x && x <= end0_p_x))
{
//第二次循环
for (int j = 0; j < 10; j++)
{
var start1_uu = start0_uu + j * 0.01;
var end1_uu = start1_uu + 0.01;
var start1_p_x = bezeir.GetX(start1_uu);
//var start1_p_y = bezeir.GetY(start1_uu);
var end1_p_x = bezeir.GetX(end1_uu);
//var end1_p_y = bezeir.GetY(end1_uu);
if ((x <= start1_p_x && x >= end1_p_x) || (x >= start1_p_x && x <= end1_p_x))
{
//第三次循环
for (int k = 0; k < 10; k++)
{
var start2_uu = start1_uu + k * 0.001;
var end2_uu = start2_uu + 0.001;
var start2_p_x = bezeir.GetX(start2_uu);
//var start2_p_y = bezeir.GetY(start2_uu);
var end2_p_x = bezeir.GetX(end2_uu);
//var end2_p_y = bezeir.GetY(end2_uu);
if ((x <= start2_p_x && x >= end2_p_x) || (x >= start2_p_x && x <= end2_p_x))
{
var set_x = bezeir.GetX((start2_uu + end2_uu) / 2);
var set_y = bezeir.GetY((start2_uu + end2_uu) / 2);
var set_pt = new CurvePoint(set_x, set_y);
points_sect_list.Add(set_pt);
break;
}
}
break;
}
}
break;
}
}
#endregion
}
}
return points_sect_list;
}
///
/// 通过 Y 获取交点
///
public static List GetSectPointsByY(List allBeziers, double y)
{
if (allBeziers == null || allBeziers.Count() == 0)
return null;
var points_sect_list = new List();
foreach (var bezeir in allBeziers)
{
//贝塞尔曲线与性能曲线有交点
if ((y <= bezeir.Point0.Y && y >= bezeir.Point3.X) || (y >= bezeir.Point0.Y && y <= bezeir.Point3.Y))
{
#region 贝塞尔曲线集合循环
//第一次循环
for (int i = 0; i < 10; i++)
{
var start0_uu = i * 0.1;
var end0_uu = start0_uu + 0.1;
//var start0_p_x = bezeir.GetX(start0_uu);
var start0_p_y = bezeir.GetY(start0_uu);
//var end0_p_x = bezeir.GetX(end0_uu);
var end0_p_y = bezeir.GetY(end0_uu);
if ((y <= start0_p_y && y >= end0_p_y) || (y >= start0_p_y && y <= end0_p_y))
{
//第二次循环
for (int j = 0; j < 10; j++)
{
var start1_uu = start0_uu + j * 0.01;
var end1_uu = start1_uu + 0.01;
// var start1_p_x = bezeir.GetX(start1_uu);
var start1_p_y = bezeir.GetY(start1_uu);
// var end1_p_x = bezeir.GetX(end1_uu);
var end1_p_y = bezeir.GetY(end1_uu);
if ((y <= start1_p_y && y >= end1_p_y) || (y >= start1_p_y && y <= end1_p_y))
{
//第三次循环
for (int k = 0; k < 10; k++)
{
var start2_uu = start1_uu + k * 0.001;
var end2_uu = start2_uu + 0.001;
//var start2_p_x = bezeir.GetX(start2_uu);
var start2_p_y = bezeir.GetY(start2_uu);
// var end2_p_x = bezeir.GetX(end2_uu);
var end2_p_y = bezeir.GetY(end2_uu);
if ((y <= start2_p_y && y >= end2_p_y) || (y >= start2_p_y && y <= end2_p_y))
{
var set_x = bezeir.GetX((start2_uu + end2_uu) / 2);
var set_y = bezeir.GetY((start2_uu + end2_uu) / 2);
var set_pt = new CurvePoint(set_x, set_y);
points_sect_list.Add(set_pt);
break;
}
}
break;
}
}
break;
}
}
#endregion
}
}
return points_sect_list;
}
///
/// 通过 曲线表达式 获取交点
///
public static List GetCrossPoints(List allBeziers, CurveExpress curve)
{
if (allBeziers == null || allBeziers.Count() == 0)
return null;
var points_sect_list = new List();
foreach (var bezeir in allBeziers)
{
var pt = bezeir.GetCrossPoint(curve);
if (pt != null)
points_sect_list.Add(pt);
}
return points_sect_list;
}
///
/// 通过 曲线表达式 获取交点
///
public static List GetCrossPoints(List originPoint, CurveExpress curve)
{
if (originPoint == null)
return null;
if (originPoint.Count() <= 2)
return null;
if (originPoint.Count() == 3)
{
var b2 = new Bezier2(originPoint);
var pt = b2.GetCrossPoint(curve);
if (pt == null)
return null;
return new List() { pt };
}
var allBeziers = CreateOpenCurves(originPoint);
var points_sect_list = new List();
foreach (var bezeir in allBeziers)
{
var pt = bezeir.GetCrossPoint(curve);
if (pt != null)
points_sect_list.Add(pt);
}
return points_sect_list;
}
///
/// 获取距离
///
public static double Distance(List curvePoints, CurvePoint point)
{
if (curvePoints == null || curvePoints.Count() == 0)
return 0;
if (curvePoints.Count() == 1)
{
var point1 = curvePoints.First();
return Math.Sqrt((point1.X - point.X) * (point1.X - point.X) + (point1.Y - point.Y) * (point1.Y - point.Y));
}
if (curvePoints.Count() == 2)
{
var point1 = curvePoints.First();
var point2 = curvePoints.Last();
return CurveLineHelper.Distance(point1, point2, point);
}
if (curvePoints.Count() == 3)
{
var b2 = new Bezier2(curvePoints);
return b2.Distance(point);
}
var allBeziers = CreateOpenCurves(curvePoints);
double min_dis = double.MaxValue;
foreach (var bezeir in allBeziers)
{
var dis = bezeir.Distance(point);
min_dis = Math.Min(min_dis, dis);
}
return min_dis;
}
///
/// 获取距离(把曲线压缩到100*100的盒子里面 Boundary 求距离)
///
public static double Distance(CurveBoundary boundary, List curve_real, CurvePoint point_real)
{
if (curve_real == null || curve_real.Count() == 0)
return 0;
if (boundary == null)
return Distance(curve_real, point_real);
double ratio_x = 0;
if (boundary.MaxX == boundary.MinX)
{
ratio_x = 100 / (boundary.MaxX);
}
else
{
ratio_x = 100 / (boundary.MaxX - boundary.MinX);
}
double ratio_y = 0;
if (boundary.MaxY == boundary.MinY)
{
ratio_y = 100 / (boundary.MaxY);
}
else
{
ratio_y = 100 / (boundary.MaxY - boundary.MinY);
}
var point_chart = new CurvePoint() { X = (point_real.X - boundary.MinX) * ratio_x, Y = (point_real.Y - boundary.MinY) * ratio_y };
var curvePoints = new List();
foreach (var pt in curve_real)
{
var point1 = new CurvePoint() { X = (pt.X - boundary.MinX) * ratio_x, Y = (pt.Y - boundary.MinY) * ratio_y };
curvePoints.Add(point1);
}
if (curvePoints.Count() == 1)
{
var point1 = curvePoints.First();
return Math.Sqrt((point1.X - point_chart.X) * (point1.X - point_chart.X) + (point1.Y - point_chart.Y) * (point1.Y - point_chart.Y));
}
if (curvePoints.Count() == 2)
{
var point1 = curvePoints.First();
var point2 = curvePoints.Last();
return CurveLineHelper.Distance(point1, point2, point_chart);
}
if (curvePoints.Count() == 3)
{
var b2 = new Bezier2(curvePoints);
return b2.Distance(point_chart);
}
var allBeziers = CreateOpenCurves(curvePoints);
double min_dis = double.MaxValue;
foreach (var bezeir in allBeziers)
{
var dis = bezeir.Distance(point_chart);
min_dis = Math.Min(min_dis, dis);
}
return min_dis;
}
///
/// 变成直线端
///
/// 贝塞尔曲线
/// 贝赛尔曲线中间插入的点数量
///
public static List GetApexPoints(List allBeziers, int pointNumber)
{
var points_sect_list = new List();
foreach (var bezeir in allBeziers)
{
for (int i = 0; i <= pointNumber; i++)
{
var uu = i * 1.0 / pointNumber;
var p_x = bezeir.GetX(uu);
var p_y = bezeir.GetY(uu);
points_sect_list.Add(new CurvePoint(p_x, p_y));
}
}
return points_sect_list;
}
///
/// 变成直线端(只针对开口的曲线)
///
/// 贝塞尔曲线
/// 贝赛尔曲线中间插入的点数量
///
public static List GetApexPoints(List originPoint, int pointNumber)
{
if (originPoint == null)
return null;
if (originPoint.Count() <= 2)
return null;
if (originPoint.Count() == 3)
{
var b2 = new Bezier2(originPoint);
return b2.GetApexPoints(pointNumber);
}
var allBeziers = CreateOpenCurves(originPoint);
var points_sect_list = new List();
foreach (var bezeir in allBeziers)
{
for (int i = 0; i <= pointNumber; i++)
{
var uu = i * 1.0 / pointNumber;
var p_x = bezeir.GetX(uu);
var p_y = bezeir.GetY(uu);
points_sect_list.Add(new CurvePoint(p_x, p_y));
}
}
return points_sect_list;
}
//三次贝塞尔曲线
private double bezier3funcX(double uu, List controlP)
{
double part0 = controlP[0].X * uu * uu * uu;
double part1 = 3 * controlP[1].X * uu * uu * (1 - uu);
double part2 = 3 * controlP[2].X * uu * (1 - uu) * (1 - uu);
double part3 = controlP[3].X * (1 - uu) * (1 - uu) * (1 - uu);
return part0 + part1 + part2 + part3;
}
private double bezier3funcY(double uu, List controlP)
{
double part0 = controlP[0].Y * uu * uu * uu;
double part1 = 3 * controlP[1].Y * uu * uu * (1 - uu);
double part2 = 3 * controlP[2].Y * uu * (1 - uu) * (1 - uu);
double part3 = controlP[3].Y * (1 - uu) * (1 - uu) * (1 - uu);
return part0 + part1 + part2 + part3;
}
}
}