Rotate() method failing to rotate 3D cylinder

TeeChart for Microsoft Visual Studio .NET, Xamarin Studio (Android, iOS & Forms) & Monodevelop.
Post Reply
BrayanSosa
Newbie
Newbie
Posts: 7
Joined: Tue Sep 12, 2017 12:00 am

Rotate() method failing to rotate 3D cylinder

Post by BrayanSosa » Mon Jun 03, 2024 4:48 pm

I am trying to create a 3D TeeChart that contains a Cylinder in the center. I want said cylinder to rotate around in the direction the mouse moves every time the user holds left click and drags. I want the cylinders center to remain the same while everything else rotates around it if that makes any sense. I am trying to use the Rotate() method to achieve this however my cylinder is staying still. Here is the current code that I have:

using System;
using System.Windows;
using System.Windows.Input;
using System.Windows.Media;
using Steema.TeeChart.WPF;
using Steema.TeeChart.WPF.Styles;
using Steema.TeeChart.WPF.Drawing;

namespace tubo_MCB_TCP.GUI.Instruments
{
public partial class GraphingFor3D : Window
{
private bool isRotating = false;
private Point previousMousePosition;
private double cylinderRotation = 0;

public GraphingFor3D()
{
InitializeComponent();
InitializeTeeChart();
}

private void InitializeTeeChart()
{
try
{
// Configure TeeChart settings
TeeChart.Panel.Color = Colors.Black;
TeeChart.Aspect.View3D = true;
TeeChart.Aspect.Chart3DPercent = 100;
TeeChart.Aspect.Zoom = 60;
TeeChart.Chart.Header.Visible = false;
TeeChart.Axes.Top.Visible = false;

// Subscribe to the AfterDraw event
TeeChart.AfterDraw += TeeChart_AfterDraw;

// Set titles for X, Y, and Z axes
TeeChart.Axes.Bottom.Title.Text = "X Axis";
TeeChart.Axes.Bottom.Title.Font.Color = Colors.White;
TeeChart.Axes.Bottom.AxisPen.Color = Colors.White;
TeeChart.Axes.Bottom.Automatic = false;
TeeChart.Axes.Bottom.Visible = true;

TeeChart.Axes.Left.Title.Text = "Y Axis";
TeeChart.Axes.Left.Title.Font.Color = Colors.White;
TeeChart.Axes.Left.Automatic = false;
TeeChart.Axes.Left.AxisPen.Color = Colors.White;
TeeChart.Axes.Left.Visible = true;

TeeChart.Axes.Depth.Title.Text = "Z Axis";
TeeChart.Axes.Depth.Title.Font.Color = Colors.White;
TeeChart.Axes.Depth.AxisPen.Color = Colors.White;
TeeChart.Axes.Depth.Automatic = false;
TeeChart.Axes.Depth.Visible = true;

TeeChart.MouseLeftButtonDown += TeeChart_MouseLeftButtonDown;
TeeChart.MouseLeftButtonUp += TeeChart_MouseLeftButtonUp;
TeeChart.MouseMove += TeeChart_MouseMove;

TeeChart.Invalidate();
}
catch (Exception ex)
{
// Handle the exception (log or display it)
MessageBox.Show($"An error occurred: {ex.Message}", "Error", MessageBoxButton.OK, MessageBoxImage.Error);
}
}

private void TeeChart_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
isRotating = true;
previousMousePosition = e.GetPosition(TeeChart);
Console.WriteLine("Mouse left button down");
}

private void TeeChart_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
isRotating = false;
Console.WriteLine("Mouse left button up");
}

private void TeeChart_MouseMove(object sender, MouseEventArgs e)
{
if (isRotating)
{
Point currentMousePosition = e.GetPosition(TeeChart);
Vector delta = currentMousePosition - previousMousePosition;

cylinderRotation = (cylinderRotation + delta.X) % 360;

Console.WriteLine($"Cylinder Rotation: {cylinderRotation}");

previousMousePosition = currentMousePosition;

TeeChart.InvalidateVisual(); // Force the TeeChart to redraw
}
}

// Event handler for drawing the cylinder
private void TeeChart_AfterDraw(object sender, Steema.TeeChart.WPF.Drawing.Graphics3D g)
{
// Define the center and size of the cylinder
int centerX = (int)(TeeChart.Chart.ChartBounds.Width / 2);
int centerY = (int)(TeeChart.Chart.ChartBounds.Height / 2);
int centerZ = 50; // Adjust Z-axis translation as needed
int width = 400; // Modify as needed
int height = 200; // Modify as needed

// Translate to the center of the cylinder
g.Translate(centerX, centerY, centerZ); // Adjust for Z-axis translation

// Apply rotation to the graphics object around the Z-axis
g.Rotate((int)cylinderRotation);

// Define the rectangle representing the base of the cylinder
Rect cylinderRect = new Rect(centerX - width / 2, centerY - height / 2, width, height);

// Draw the cylinder
g.Cylinder(false, cylinderRect, 10, 50, true);

g.Invalidate();
}
}
}

Here is my XAML in case that it is needed as well:
<Window x:Class="tubo_MCB_TCP.GUI.Instruments.GraphingFor3D"
xmlns="http://schemas.microsoft.com/winfx/2006 ... esentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/marku ... ility/2006"
xmlns:local="clr-namespace:tubo_MCB_TCP.GUI.Instruments"
xmlns:chart="clr-namespace:Steema.TeeChart.WPF;assembly=TeeChart.WPF"
xmlns:forms="clr-namespace:System.Windows.Forms;assembly=System.Windows.Forms"
xmlns:drawing="clr-namespace:System.Drawing;assembly=System.Drawing"
mc:Ignorable="d"
Title="GraphingFor3D" Height="634" Width="856">
<Grid>
<chart:TChart Name="TeeChart" HorizontalAlignment="Left" Height="531" Margin="83,10,0,0" VerticalAlignment="Top" Width="680"/>
</Grid>
</Window>


I have tried using a matrix to move it, using the Transform() method, but that would fully move my cylinder instead of rotating it in place. Am I missing something to my current code, I know 3D charts in itself can't be rotated, but I thought that it was possible to rotate a cylinder(), please let me know if you would like more information or if you need me to explain myself more, to better assist me. Thank you!

Marc
Site Admin
Site Admin
Posts: 1256
Joined: Thu Oct 16, 2003 4:00 am
Location: Girona
Contact:

Re: Rotate() method failing to rotate 3D cylinder

Post by Marc » Tue Jun 04, 2024 10:37 am

Hello,

Re.
I know 3D charts in itself can't be rotated
TeeChart's 3D charts do support rotation. If you require the chart to rotate too, the simplest way is to plot the cylinder as you have with the start orientation you require and use the TeeChart Rotate Tool to rotate the entire chart with the cylinder.

eg.

Code: Select all

Steema.TeeChart.Tools.Rotate rotate1 = new Steema.TeeChart.Tools.Rotate();
tChart1.Tools.Add(this.rotate1);
rotate1.Active = true;
Let us know if that's not your goal.

With thanks.
Regards,
Marc Meumann
Steema Support

BrayanSosa
Newbie
Newbie
Posts: 7
Joined: Tue Sep 12, 2017 12:00 am

Re: Rotate() method failing to rotate 3D cylinder

Post by BrayanSosa » Tue Jun 04, 2024 2:11 pm

I like this feature and will probably still be implementing it, however I was more looking to rotate just the cylinder while having the chart still locked in place.

Marc
Site Admin
Site Admin
Posts: 1256
Joined: Thu Oct 16, 2003 4:00 am
Location: Girona
Contact:

Re: Rotate() method failing to rotate 3D cylinder

Post by Marc » Wed Jun 05, 2024 11:31 am

Hello,

I'll check for an alternative way of doing what you require. g.Translate is not implemented in the class and its presence will be reviewed. I'll followup to this thread.

Regards,
Marc
Steema Support

BrayanSosa
Newbie
Newbie
Posts: 7
Joined: Tue Sep 12, 2017 12:00 am

Re: Rotate() method failing to rotate 3D cylinder

Post by BrayanSosa » Wed Jun 05, 2024 2:46 pm

I appreciate that, thank you very much :)

Marc
Site Admin
Site Admin
Posts: 1256
Joined: Thu Oct 16, 2003 4:00 am
Location: Girona
Contact:

Re: Rotate() method failing to rotate 3D cylinder

Post by Marc » Thu Jun 06, 2024 11:13 am

Hello,

There is likely a way to achieving what you require by using Graphic's Transform and Matrix; we'll check on that to see whether something can be 'built-in' to TeeChart. Meanwhile, a colleague has suggested a lighter approach that may suffice:

- To superimpose two charts, rendering only the custom cylinder on the top (overlaying) chart and plotting whatever charting contents is required on the bottom (overlaid) chart. This works fine for wpf as the charts fully respect transparency.

The result, using a part of your sample code, would look like this:

cylinder.gif
cylinder.gif (94.79 KiB) Viewed 9202 times
The page XAML for these grid positioned charts is:

Code: Select all

<teechart:TChart Name="Chart2" Grid.Row="1" Grid.ColumnSpan="3" Margin="128,0,26,0" />
<teechart:TChart Name="Chart1" Grid.Row="1" Grid.ColumnSpan="3" Margin="128,0,26,0" />
Note that Chart1, where the cylinder will be rendered, is the second Chart.

The C# code looks like this, including parts of the OnAfterDraw event that you posted:

Code: Select all

//In this case, setting Chart1.CurrentTheme = ThemeType.Report; hides unused Walls and Axes, otherwise you can hide them by setting them to Visible false.

public void setupCharts()
{
    //********* chart2 ********

    Chart2.Header.Text = "Bottom Chart2";
    Chart2.Header.CustomPosition = true;
    Chart2.Header.Left = 400;
    Chart2.Header.Top = 10;

    var Chart2Line1 = new Steema.TeeChart.WPF.Styles.Line(Chart2.Chart)
    {
        Title = "Example Chart2Line1",
        Color = Color.FromRgb(0xfa, 0x68, 0x00),
    };

	Chart2Line1.FillSampleValues(5);
            
    //********* chart1 ********

    Chart1.AfterDraw += Chart1_AfterDraw;

    Chart1.Visibility = Visibility.Visible;

    Chart1.Aspect.View3D = false;

    Chart1.Header.Text = "Top Chart1";
    Chart1.Header.CustomPosition = true;
    Chart1.Header.Left = 10;
    Chart1.Header.Top = 10;

    Chart1.Panel.Brush.Transparency = 100;

    Chart1.CurrentTheme = ThemeType.Report;

    Steema.TeeChart.WPF.Tools.Rotate rotate2 = new Steema.TeeChart.WPF.Tools.Rotate();
    Chart1.Tools.Add(rotate2);
    rotate2.Active = true;
}

private void Chart1_AfterDraw(object sender, Graphics3D g)
{
    int centerX = (int)(Chart2.Chart.ChartBounds.Width / 2);
    int centerY = (int)(Chart2.Chart.ChartBounds.Height / 2);
    int width = 400; // Modify as needed
    int height = 200; // Modify as needed

    System.Windows.Rect cylinderRect = new System.Windows.Rect(centerX - width / 2, centerY - height / 2, width, height);

	g.Pen.Visible = false;
    // Draw the cylinder
    g.Cylinder(false, cylinderRect, 0, 150, true);

}
Note that the cylinder generated in this way is not full 3D and if rotated beyond the front 180º plane will start to show deficiencies. We will continue to examine alternative techniques.

Regards,
Marc
Steema Support

Post Reply