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