public Spline2D(bool closed, bool periodic, List <Point2D> controlPoints, List <double> knots) { Periodic = periodic; int n = controlPoints.Count() - 1; FitPoints = new List <Point2D>(); HasFitPoints = false; NurbsData = new NurbsData(controlPoints, knots, 3, closed); }
public override void ToX(XElement xe) { xe.Add(new XAttribute("Periodic", Periodic)); xe.Add(new XAttribute("HasFitPoints", HasFitPoints)); xe.Add(NurbsData.ToX()); if (HasFitPoints) { var e = new XElement("FitPoints", new XAttribute("TangentsExist", TangentsExist)); xe.Add(e); if (TangentsExist) { e.Add(new XAttribute("Start", StartTangent.ToString())); e.Add(new XAttribute("End", EndTangent.ToString())); } foreach (var pt in FitPoints) { e.Add(pt.ToX("Point")); } } MakeLayer(xe); }
public override void FromX(XElement xe) { Periodic = bool.Parse(xe.Attribute("Periodic").Value); NurbsData = new NurbsData(); NurbsData.FromX(xe.Element("NurbsData")); HasFitPoints = bool.Parse(xe.Attribute("HasFitPoints").Value); if (HasFitPoints) { var fpts = xe.Element("FitPoints"); FitPoints = new List <Point2D>(); foreach (var pt in fpts.Elements()) { FitPoints.Add(XParser.Parse <Point2D>(pt)); } TangentsExist = bool.Parse(fpts.Attribute("TangentsExist").Value); if (TangentsExist) { StartTangent = Vector2D.Parse(fpts.Attribute("Start").Value); EndTangent = Vector2D.Parse(fpts.Attribute("End").Value); } } }
internal KnotCollection(NurbsData owner) { _owner = owner; _knots = new List <double>(); }
/// <summary> /// 获取参数对应点 /// </summary> /// <param name="par">参数</param> /// <returns>参数对应点</returns> public override Point2D GetPointAtParam(double par) { return(NurbsData.GetPointAtParam(par)); }
/// <summary> /// 插值点反求控制点 /// </summary> /// <param name="closed"></param> /// <param name="fitPoints"></param> public Spline2D(bool closed, IEnumerable <Point2D> fitPoints) { Periodic = false; HasFitPoints = true; FitPoints = new List <Point2D>(fitPoints); //参数区间数 int n = FitPoints.Count - 1; //参数化 List <double> knots = new List <double>(); knots.Add(0); double totalLength = 0; for (int i = 0; i < n; i++) { totalLength += (FitPoints[i + 1] - FitPoints[i]).Length; knots.Add(totalLength); } if (closed) { totalLength += (FitPoints[0] - FitPoints[FitPoints.Count - 1]).Length; knots.Add(totalLength); } NurbsData = new NurbsData(knots, 3, closed); if (closed) { //构建矩阵方程组 double[,] mat = new double[n + 1, n + 1]; for (int i = 0; i < n + 1; i++) { var par = NurbsData.Knots[i + Degree]; int span = NurbsData.Knots.FindSpan(par); var nn = NurbsData.Knots.BasicFuns(span, par); for (int j = 0; j < Degree; j++) { mat[i, (span - Degree + j) % (n + 1)] = nn[j]; } } var fpts = new List <Point2D>(FitPoints); //求解 GeoUtils.Inverse(ref mat, n + 1); for (int i = 0; i < n + 1; i++) { NurbsData.AddControlPoint(new Point2D()); for (int j = 0; j < n + 1; j++) { NurbsData.ControlPoints[i] += fpts[j] * mat[i, j]; } } } else { //构建矩阵方程组 double[,] mat = new double[n + 3, n + 3]; //计算插值点的非零幂基函数值 for (int i = 1; i < n; i++) { var par = NurbsData.Knots[i + Degree]; int span = NurbsData.Knots.FindSpan(par); var nn = NurbsData.Knots.BasicFuns(span, par); for (int j = 0; j < Degree; j++) { mat[i + 1, span - Degree + j] = nn[j]; } } mat[1, 0] = mat[n + 1, n + 2] = 1; //使用自由边界条件,即端点处二阶导数为0 var t1 = totalLength / NurbsData.Knots[Degree + 1]; var t2 = totalLength / NurbsData.Knots[Degree + 2]; mat[0, 0] = t1; mat[0, 1] = -t1 - t2; mat[0, 2] = t2; t1 = totalLength / (totalLength - NurbsData.Knots[n + Degree - 2]); t2 = totalLength / (totalLength - NurbsData.Knots[n + Degree - 1]); mat[n + 2, n] = t1; mat[n + 2, n + 1] = -t1 - t2; mat[n + 2, n + 2] = t2; var fpts = new List <Point2D>(); fpts.Add(Point2D.Origin); fpts.AddRange(FitPoints); fpts.Add(Point2D.Origin); //求解 GeoUtils.Inverse(ref mat, n + 3); for (int i = 0; i < n + 3; i++) { NurbsData.AddControlPoint(new Point2D()); for (int j = 0; j < n + 3; j++) { NurbsData.ControlPoints[i] += fpts[j] * mat[i, j]; } } } }