/// <summary> /// Creates a 3D Z-rotation matrix. /// </summary> /// <remarks>For a right-handed 3D system (like WPF), a positive angle value results in a counter-clockwise rotation around the axis. For a left-handed 3D system, a positive angle value results in a clockwise rotation around the axis.</remarks> /// <param name="angle">Angle value in degree.</param> /// <param name="handedness">The handedness of the coordinate system (optional). Under WPF, the defaut value is Right-handed.</param> /// <returns>A Matrix3D object.</returns> public static Matrix3D GetZRotationMatrix(double angle, Handedness3D handedness = Handedness3D.RightHanded) { //var m = new Matrix3D(); //m.Rotate(new Quaternion(new Vector3D(0, 0, 1), angle)); //return m; // var radianAngle = GeometryHelper.DegreeToRadian(angle); double radianAngle = 0.0; if (handedness == Handedness3D.LeftHanded) { radianAngle = (2 * Math.PI) - GeometryHelper.DegreeToRadian(angle); } else { radianAngle = GeometryHelper.DegreeToRadian(angle); } return(new Matrix3D { M11 = Math.Cos(radianAngle), M21 = -Math.Sin(radianAngle), M12 = Math.Sin(radianAngle), M22 = Math.Cos(radianAngle) }); }
/// <summary> /// Creates a 3D Y-rotation matrix. /// </summary> /// <remarks>For a left-handed 3D system (the default in Silverlight projections), a positive angle value results in a clockwise rotation around the axis. For a right-handed 3D system, a positive angle value results in a counter-clockwise rotation around the axis.</remarks> /// <param name="angle">Angle value in degree.</param> /// <param name="handedness">The handedness of the coordinate system (optional). Under Silverlight, the defaut value is Left-handed.</param> /// <returns>A Matrix3D object.</returns> public static Matrix3D GetYRotationMatrix(double angle, Handedness3D handedness = Handedness3D.LeftHanded) { //var m = new Matrix3D(); //m.Rotate(new Quaternion(new Vector3D(0, 1, 0), angle)); //return m; double radianAngle = 0.0; // angle inverted in respect to the relative orientation of Z to X if (handedness == Handedness3D.LeftHanded) { radianAngle = GeometryHelper.DegreeToRadian(angle); } else { radianAngle = (2 * Math.PI) - GeometryHelper.DegreeToRadian(angle); } return(new Matrix3D { M11 = Math.Cos(radianAngle), M31 = -Math.Sin(radianAngle), M13 = Math.Sin(radianAngle), M33 = Math.Cos(radianAngle) }); }
/// <summary> /// Rounds a vertex of a triangle. /// </summary> /// <param name="pA">First point.</param> /// <param name="pB">Second point. Vertex to round</param> /// <param name="pC">Third point.</param> /// <param name="roundingRate">Vertex rounding rate. The value must be comprized between 0.0 and 0.5.</param> /// <returns></returns> public static Point3DCollection RoundCorner(Point3D pA, Point3D pB, Point3D pC, double roundingRate) { if (!((pA.Z == pB.Z) && (pB.Z == pC.Z)) ) { throw new ArgumentOutOfRangeException("pA"); } if ((roundingRate < 0.0) || (roundingRate > 0.5) ) { throw new ArgumentOutOfRangeException("roundingRate"); } Point3DCollection points = new Point3DCollection(); int roundingDefinition = (int)(roundingRate * 40.0); Vector3D v1 = new Vector3D(); v1 = pA - pB; v1.X = Math.Round(v1.X, 3); v1.Y = Math.Round(v1.Y, 3); v1.Z = Math.Round(v1.Z, 3); Point3D p1 = Point3D.Add(pB, Vector3D.Multiply(v1, roundingRate)); Vector3D v2 = new Vector3D(); v2 = pC - pB; v2.X = Math.Round(v2.X, 3); v2.Y = Math.Round(v2.Y, 3); v2.Z = Math.Round(v2.Z, 3); Point3D p2 = Point3D.Add(pB, Vector3D.Multiply(v2, roundingRate)); // v1 is the normal vector for the linear curve // v1.X*x + v1.Y*y + c1 = 0; // p1 is owned by this curve so double c1 = -(v1.X * p1.X) - (v1.Y * p1.Y); // same for v2 and p2 double c2 = -(v2.X * p2.X) - (v2.Y * p2.Y); // center for the arc that owns p1 and p2 Point3D center = new Point3D(); if (v1.Y == 0.0) { if (v1.X == 0.0) { throw new InvalidOperationException(); } center.X = -c1 / v1.X; if (v2.Y == 0.0) { throw new InvalidOperationException(); } else { center.Y = (-c2 - v2.X * center.X) / v2.Y; } } else { if (v2.Y == 0.0) { if (v2.X == 0.0) { throw new InvalidOperationException(); } center.X = -c2 / v2.X; } else { center.X = (c1 / v1.Y - c2 / v2.Y) / (v2.X / v2.Y - v1.X / v1.Y); } center.Y = (-c1 - v1.X * center.X) / v1.Y; } center.Z = pB.Z; // angle of the arc between p1 and p2 // 360 - 180 - Vector3D.AngleBetween(v1, v2) double angleArc = GeometryHelper.DegreeToRadian(180 - Vector3D.AngleBetween(v1, v2)); // angle of each part double angleStep = angleArc / roundingDefinition; Vector3D vRadius = p1 - center; double angleBaseDeg = Vector3D.AngleBetween(new Vector3D(1, 0, 0), vRadius); // necessar adjustment because of Vector3D.AngleBetween() - see documentation if (p1.Y < 0.0) { angleBaseDeg = 360 - angleBaseDeg; } double angleBase = GeometryHelper.DegreeToRadian(angleBaseDeg); points.Add(p1); // points of the arc for (int j = 1; j <= roundingDefinition - 1; j++) { double angle = angleBase + (angleStep * j); Point3D p = new Point3D(); p.X = center.X + Math.Cos(angle) * vRadius.Length; p.Y = center.Y + Math.Sin(angle) * vRadius.Length; p.Z = pB.Z; points.Add(p); } points.Add(p2); return(points); }