/// <summary> /// Constructs a B-Spline based on a set of <paramref name="nodes"/> and <paramref name="values"/>; /// </summary> /// <param name="nodes"> /// length must be at least 2, and equal to the length of <paramref name="values"/>; /// </param> /// <param name="values"> /// length must be at least 2, and equal to the length of <paramref name="nodes"/>; /// </param> /// <param name="d"> /// Coordinate axis, on which the <paramref name="nodes"/> /// <list type="bullet"> /// <item>0: <paramref name="nodes"/> are values on the x - Axis</item> /// <item>1: <paramref name="nodes"/> are values on the y - Axis</item> /// <item>2: <paramref name="nodes"/> are values on the z - Axis</item> /// </list> /// </param> /// <param name="oobb"> /// </param> public Spline1D(double[] nodes, double[] values, int d, OutOfBoundsBehave oobb = Spline1D.OutOfBoundsBehave.Extrapolate) { if (nodes.Length != values.Length) { throw new ArgumentException("Node and Value array must have the same length."); } this.values = values.CloneAs(); this.nodes = nodes.CloneAs(); dim = d; m_oobb = oobb; }
/// <summary> /// Constructs a B-Spline based on a set of <paramref name="nodes"/> and <paramref name="values"/>; /// </summary> /// <param name="nodes"> /// length must be at least 2, and equal to the length of <paramref name="values"/>; /// </param> /// <param name="values"> /// length must be at least 2, and equal to the length of <paramref name="nodes"/>; /// </param> /// <param name="d"> /// Coordinate axis, on which the <paramref name="nodes"/> /// <list type="bullet"> /// <item>0: <paramref name="nodes"/> are values on the x - Axis</item> /// <item>1: <paramref name="nodes"/> are values on the y - Axis</item> /// <item>2: <paramref name="nodes"/> are values on the z - Axis</item> /// </list> /// </param> /// <param name="oobb"> /// </param> public Spline(double[] nodes, double[] values, int d, OutOfBoundsBehave oobb) { M = new double[nodes.Length]; this.nodes = nodes; this.values = values; dim = d; m_oobb = oobb; double[] h = new double[nodes.Length - 1]; double[,] A = new double[nodes.Length, 3]; //stores the coefficients of the equation system with unknown M (A*M = b) double[] b = new double[nodes.Length]; //stores the solution vector of the equation system ConstructorCommon(ref h, ref A, ref b); }
/// <summary> /// This function parses an XmlElement in order to extract the nodes and values for the spline /// </summary> /// <param name="xmlelem"> /// the given XmlElement, normally the "spline" element /// </param> private void parse(XmlElement xmlelem) { XmlNodeList children = xmlelem.ChildNodes; int actualCount = 0; int countDepaxisComments = 0; double[] xTmp = new double[children.Count * 2]; double[] yTmp = new double[children.Count * 2]; char[] separator = new char[] { ' ', '\t', '\n', '\r' }; NumberFormatInfo provider = new NumberFormatInfo(); provider.NumberDecimalSeparator = "."; foreach (XmlNode child in children) { if (child.NodeType == XmlNodeType.Element) { if (child.Name == "depaxis") { XmlNodeList depaxisChildren = child.ChildNodes; foreach (XmlNode depaxisChild in depaxisChildren) { //the element depaxis cannot have any children, otherwise an exception is thrown if (depaxisChild.NodeType == XmlNodeType.Comment) { countDepaxisComments++; } else { if (depaxisChild.NodeType != XmlNodeType.Text) { throw new ApplicationException("The element depaxis should contain 'x', 'y' or 'z'!"); } else { string[] depChild = depaxisChild.InnerText.Split(separator, StringSplitOptions.RemoveEmptyEntries); string depAxis = depChild[0].ToLower(); switch (depAxis) { case "x": this.dim = 0; break; case "y": this.dim = 1; break; case "z": this.dim = 2; break; default: throw new ApplicationException("The element depaxis should contain 'x', 'y' or 'z'!"); } } } } if (depaxisChildren.Count - countDepaxisComments != 1) { throw new ApplicationException("The element depaxis can contain only 'x', 'y', 'z'!"); } } else if (child.Name == "pt") { // we extract the values of a pt element, storing them into xTmp and yTmp // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ string tmp = child.InnerText; string[] tmpValues = tmp.Split(separator, StringSplitOptions.RemoveEmptyEntries); xTmp[actualCount] = Convert.ToDouble(tmpValues[0], provider); yTmp[actualCount] = Convert.ToDouble(tmpValues[1], provider); actualCount = actualCount + 1; } else if (child.Name == "OutOfBoundsBehave") { // // XmlNodeList depaxisChildren = child.ChildNodes; if (depaxisChildren.Count - countDepaxisComments != 1) { throw new ApplicationException("The no Childs allowed for element 'OutOfBoundsBehave';"); } m_oobb = (OutOfBoundsBehave)Enum.Parse(typeof(OutOfBoundsBehave), child.InnerText); } else { throw new ApplicationException("unknown child element '" + child.Name + "' for spline;"); } } } this.nodes = new double[actualCount]; this.values = new double[actualCount]; double isAscending = 0; //copy the values from xTmp and yTmp to this.nodes and this.values this.nodes[0] = xTmp[0]; this.values[0] = yTmp[0]; for (int i = 1; i < actualCount; i++) { this.nodes[i] = xTmp[i]; this.values[i] = yTmp[i]; isAscending = this.nodes[i] - this.nodes[i - 1]; //if the interpolating nodes are not in ascending order, an exception is thrown if (isAscending <= 0) { throw new ApplicationException("The nodes of the spline must be given in a strictly ascending order!"); } isAscending = 0; } }