/// <summary> /// Constructs a new rotation transformation with Sin and Cos radians angle, rotation center and rotation axis. /// </summary> /// <param name="sinAngle">Sin radians angle.</param> /// <param name="cosAngle">Cos radians angle.</param> /// <param name="axis">Axis direction.</param> /// <param name="origin">Rotation center.</param> /// <returns>A transformation matrix which rotates geometry around an anchor.</returns> private static Transform Rotation(double sinAngle, double cosAngle, Vector3 axis, Point3 origin) { double sAngle = sinAngle; double cAngle = cosAngle; GSharkMath.KillNoise(ref sAngle, ref cAngle); Transform transform = Identity(); double oneMinusCosAngle = 1 - cosAngle; transform[0][0] = axis[0] * axis[0] * oneMinusCosAngle + cAngle; transform[0][1] = axis[0] * axis[1] * oneMinusCosAngle - axis[2] * sAngle; transform[0][2] = axis[0] * axis[2] * oneMinusCosAngle + axis[1] * sAngle; transform[1][0] = axis[1] * axis[0] * oneMinusCosAngle + axis[2] * sAngle; transform[1][1] = axis[1] * axis[1] * oneMinusCosAngle + cAngle; transform[1][2] = axis[1] * axis[2] * oneMinusCosAngle - axis[0] * sAngle; transform[2][0] = axis[2] * axis[0] * oneMinusCosAngle - axis[1] * sAngle; transform[2][1] = axis[2] * axis[1] * oneMinusCosAngle + axis[0] * sAngle; transform[2][2] = axis[2] * axis[2] * oneMinusCosAngle + cAngle; if (!origin.Equals(new Point3(0, 0, 0))) { transform[0][3] = -((transform[0][0] - 1) * origin[0] + transform[0][1] * origin[1] + transform[0][2] * origin[2]); transform[1][3] = -(transform[1][0] * origin[0] + (transform[1][1] - 1) * origin[1] + transform[1][2] * origin[2]); transform[2][3] = -(transform[2][0] * origin[0] + transform[2][1] * origin[1] + (transform[2][2] - 1) * origin[2]); } transform[3][0] = transform[3][1] = transform[3][0] = 0.0; transform[3][3] = 1; return(transform); }
/// <summary> /// Checks the validity of the input knot vector.<br/> /// Confirm the relations between degree (p), number of control points(n+1), and the number of knots (m+1).<br/> /// Refer to The NURBS Book (2nd Edition), p.50 for details.<br/> /// <br/> /// More specifically, this method checks if the knot vector is of the following structure:<br/> /// The knot knots must be non-decreasing and of length (degree + 1) * 2 or greater<br/> /// </summary> /// <param name="degree">The degree of the curve.</param> /// <param name="numberOfControlPts"></param> /// <returns>Whether the knots are valid.</returns> public bool IsValid(int degree, int numberOfControlPts) { if (Count == 0) { return(false); } if (Count < (degree + 1) * 2) { return(false); } // Check the formula: m = p + n + 1 if (numberOfControlPts + degree + 1 - Count != 0) { return(false); } for (int i = 0; i < Count; i++) { if (!GSharkMath.IsValidDouble(this[i])) { return(false); } } bool hasMultiplicity = Multiplicity(0) > 1 || Multiplicity(this.Count - 1) > 1; double rep = this[0]; for (int i = 0; i < Count; i++) { if (hasMultiplicity) { if (i < degree + 1) { if (Math.Abs(this[i] - rep) > GSharkMath.Epsilon) { return(false); } } if (i > Count - degree - 1 && i < Count) { if (Math.Abs(this[i] - rep) > GSharkMath.Epsilon) { return(false); } } } if (this[i] < rep - GSharkMath.Epsilon) { return(false); } rep = this[i]; } return(true); }
/// <summary> /// Converts normalized parameter to interval value, or pair of values. /// </summary> /// <param name="normalizedParameter">The normalized parameter between 0 and 1.</param> /// <returns>Interval parameter t0*(1.0-normalizedParameter) + t1*normalizedParameter.</returns> public double ParameterAt(double normalizedParameter) { return(!GSharkMath.IsValidDouble(normalizedParameter) ? GSharkMath.UnsetValue : (1.0 - normalizedParameter) * T0 + normalizedParameter * T1); }