Ticket T1171392
Visible to All Users

Chart3D for WPF - How to control Chart 3D Rotation with slider?

created 2 years ago (modified 2 years ago)

I am trying to have a TrackBarEdit slider control the rotation angle about the X axis of 3D Chart. I have a TrackBarEdit element that uses the EditValueChanged event to call the following method:

C#
private void RotationSliderChangedEvent(object sender, DevExpress.Xpf.Editors.EditValueChangedEventArgs e) { AxisAngleRotation3D AxisRotationX = new AxisAngleRotation3D(new Vector3D(1, 0, 0), RotationSlider.Value); AxisAngleRotation3D AxisRotationY = new AxisAngleRotation3D(new Vector3D(0, 1, 0), Vector3D.AngleBetween(new Vector3D(0, 1, 0), MainChart3D.ContentTransform.Transform(new Vector3D(0, 1, 0)))); AxisAngleRotation3D AxisRotationZ = new AxisAngleRotation3D(new Vector3D(0, 0, 1), Vector3D.AngleBetween(new Vector3D(0, 0, 1), MainChart3D.ContentTransform.Transform(new Vector3D(0, 0, 1)))); MainChart3D.ContentTransform = RotateGraph(AxisRotationX, AxisRotationY, AxisRotationZ); } private Transform3D RotateGraph(params AxisAngleRotation3D[] rotations) { Transform3DGroup transform = new Transform3DGroup(); foreach (AxisAngleRotation3D axisRotation in rotations) { transform.Children.Add(new RotateTransform3D(axisRotation)); } return transform; }

MainChart3D is my Chart3DControl element. However, when moving the slider, the chart moves wildly, even though it is correctly calculating the angle of the three axes. What I am doing incorrectly here, and what is the proper way to get the angle and axis for a rotation matrix in this way? Thank you in advance.

Answers approved by DevExpress Support

created 2 years ago

Hello Colby,

I tested your algorithm of rotation angle calculation and noticed that a chart "shakes" during rotation. As I understand it, you only need to change the angle of the X-axis, but in your calculations, the angle of Y and Z axes is also modified, which leads to "shaking":

C#
Debug.WriteLine(AxisRotationY.Angle + " - " + AxisRotationZ.Angle);

After I left Y and Z angle values fixed, the X-axis angle changes smoothly. I attached a simple project to illustrate this.

Please try it and let us know if this meets your requirements. If it doesn't, you need to modify your calculation algorithm so that the angles of Y and Z axes also change smoothly.

    Show previous comments (3)
    DevExpress Support Team 2 years ago

      Hello,

      We do not have an algorithm that allows us to obtain rotation angles from Matrix3D. Since this is a common programming tasks, we cannot help you with this due to our Limitations on DevExpress Support Services.

      However, I searched the Internet for some theory for you. What you are trying to calculate is Euler angles. It is not an easy task to calculate them based on Matrix3D: Maths - Conversion Matrix to Euler.

      Through online resources I found and tested the following algorithm:

      C#
      public void GetEulerAnglesFromMatrix3D(Matrix3D matrix) { double trace = matrix.M11 + matrix.M22 + matrix.M33; double s, w, x, y, z; if (trace > 0) { s = 0.5 / Math.Sqrt(trace + 1.0); w = 0.25 / s; x = (matrix.M23 - matrix.M32) * s; y = (matrix.M31 - matrix.M13) * s; z = (matrix.M12 - matrix.M21) * s; } else if (matrix.M11 > matrix.M22 && matrix.M11 > matrix.M33) { s = 2.0 * Math.Sqrt(1.0 + matrix.M11 - matrix.M22 - matrix.M33); w = 0.25 * s; x = (matrix.M12 + matrix.M21) / s; y = (matrix.M13 + matrix.M31) / s; z = (matrix.M23 - matrix.M32) / s; } else if (matrix.M22 > matrix.M33) { s = 2.0 * Math.Sqrt(1.0 + matrix.M22 - matrix.M11 - matrix.M33); w = (matrix.M12 + matrix.M21) / s; x = 0.25 * s; y = (matrix.M23 + matrix.M32) / s; z = (matrix.M31 - matrix.M13) / s; } else { s = 2.0 * Math.Sqrt(1.0 + matrix.M33 - matrix.M11 - matrix.M22); w = (matrix.M13 + matrix.M31) / s; x = (matrix.M23 + matrix.M32) / s; y = 0.25 * s; z = (matrix.M12 - matrix.M21) / s; } double rollDegrees = Math.Atan2(2.0 * (w * x + y * z), 1.0 - 2.0 * (x * x + y * y)) * 180.0 / Math.PI; double pitchDegrees = Math.Asin(2.0 * (w * y - z * x)) * 180.0 / Math.PI; double yawDegrees = Math.Atan2(2.0 * (w * z + x * y), 1.0 - 2.0 * (y * y + z * z)) * 180.0 / Math.PI; Console.WriteLine($"Roll: {rollDegrees} Pitch: {pitchDegrees} Yaw: {yawDegrees}"); }

      And although it works for narrow usage cases, in my tests it returned incorrect results at large angles.

      While we can't help you more with this task, I hope you find this information helpful for getting you started.

        Igor,

        Thank you for all the help. Although a good portion of my questions were unrelated to DevExpress specific tools, and had more to do with manipulation of Windows Matrix3D implementations, you were quick with your response and solutions. You offered a great level of customer support, and definitely went above and beyond with the research you did regarding Euler angles and using Matrix.RotateAt. This goes a long way from a consumer point of view, and I really appreciate all the help. Take care.

        DevExpress Support Team 2 years ago

          Hello Colby,

          Thank you for your kind words. Please feel free to contact us if you have further questions. We will be happy to assist you.

          Disclaimer: The information provided on DevExpress.com and affiliated web properties (including the DevExpress Support Center) is provided "as is" without warranty of any kind. Developer Express Inc disclaims all warranties, either express or implied, including the warranties of merchantability and fitness for a particular purpose. Please refer to the DevExpress.com Website Terms of Use for more information in this regard.

          Confidential Information: Developer Express Inc does not wish to receive, will not act to procure, nor will it solicit, confidential or proprietary materials and information from you through the DevExpress Support Center or its web properties. Any and all materials or information divulged during chats, email communications, online discussions, Support Center tickets, or made available to Developer Express Inc in any manner will be deemed NOT to be confidential by Developer Express Inc. Please refer to the DevExpress.com Website Terms of Use for more information in this regard.