4

I want to create a 3D Graph in 4 quadrants form in C#.NET. For instant, I could do as shown below. If you see the corner of the chart begins with (-150, -200). I wish to start with (0,0) and the extend into 4 quadrant form.

enter image description here

Kindly enlighten me how can I transform this 3D graph in 4 quadrant form ?

Below is the corresponding code:

void prepare3dChart(Chart chart, ChartArea ca)
    {
        ca.Area3DStyle.Enable3D = true;  
        Series s = new Series();
        chart.Series.Add(s);
        s.ChartType = SeriesChartType.Bubble;  
        s.MarkerStyle = MarkerStyle.Diamond;
        s["PixelPointWidth"] = "100";
        s["PixelPointGapDepth"] = "1";

        chart.ApplyPaletteColors();

        addTestData(chart);
    }
    void addTestData(Chart chart)
    {
        Random rnd = new Random(9);
        double x = 0, y = 0, z = 0;
        for (int i = 0; i < 100; i++)
        {
            AddXY3d(chart.Series[0], x, y, z);          
            x = Math.Sin(i / 11f) * 88 + rnd.Next(3);
            y = Math.Cos(i / 10f) * 88 + rnd.Next(5);
            z = (Math.Sqrt(i * 2f) * 88 + rnd.Next(6));
        }
    }
    int AddXY3d(Series s, double xVal, double yVal, double zVal)
    {
        int p = s.Points.AddXY(xVal, yVal, zVal);           
        s.Points[p].Color = Color.Transparent;
        return p;
    }
    private void chart1_PostPaint(object sender, ChartPaintEventArgs e)
    {
        Chart chart = sender as Chart;

        if (chart.Series.Count < 1) return;
        if (chart.Series[0].Points.Count < 1) return;

        ChartArea ca = chart.ChartAreas[0];

        List<List<PointF>> data = new List<List<PointF>>();
        foreach (Series s in chart.Series)
            data.Add(GetPointsFrom3D(ca, s, s.Points.ToList(), e.ChartGraphics));

        renderLines(data, e.ChartGraphics.Graphics, chart, true);  
        renderPoints(data, e.ChartGraphics.Graphics, chart, 6);  
    }
    List<PointF> GetPointsFrom3D(ChartArea ca, Series s,
                         List<DataPoint> dPoints, ChartGraphics cg)
    {
        var p3t = dPoints.Select(x => new Point3D((float)ca.AxisX.ValueToPosition(x.XValue),
            (float)ca.AxisY.ValueToPosition(x.YValues[0]),
            (float)ca.AxisY.ValueToPosition(x.YValues[1]))).ToArray();
        ca.TransformPoints(p3t.ToArray());

        return p3t.Select(x => cg.GetAbsolutePoint(new PointF(x.X, x.Y))).ToList();
    }
    void renderLines(List<List<PointF>> data, Graphics graphics, Chart chart, bool curves)
    {
        for (int i = 0; i < chart.Series.Count; i++)
        {
            if (data[i].Count > 1)
                using (Pen pen = new Pen(Color.FromArgb(64, chart.Series[i].Color), 2.5f))
                    if (curves) graphics.DrawCurve(pen, data[i].ToArray());
                    else graphics.DrawLines(pen, data[i].ToArray());
        }
    }

    void renderPoints(List<List<PointF>> data, Graphics graphics, Chart chart, float width)
    {
        for (int s = 0; s < chart.Series.Count; s++)
        {
            Series S = chart.Series[s];
            for (int p = 0; p < S.Points.Count; p++)
                using (SolidBrush brush = new SolidBrush(Color.FromArgb(64, S.Color)))
                    graphics.FillEllipse(brush, data[s][p].X - width / 2,
                                         data[s][p].Y - width / 2, width, width);
        }
    }

I want my 3D graph to have 4 quadrants like this: enter image description here

Thanks @TaW. I got the code right.

   void prepare3dChart(Chart chart, ChartArea ca)
    {
        ca.Area3DStyle.Enable3D = true;
        ca.BackColor = Color.Transparent;

        ca.AxisX.Minimum = -300;
        ca.AxisX.Maximum = 300;
        ca.AxisY.Minimum = -300;
        ca.AxisY.Maximum = 300;

        ca.AxisX.Crossing = 0;  // move both axes..
        ca.AxisY.Crossing = 0;  // to the middle

        ca.AxisX.Interval = 50;
        ca.AxisY.Interval = 50;

        ca.AxisX.MajorGrid.LineColor = Color.LightGray;
        ca.AxisY.MajorGrid.LineColor = Color.LightGray;

        chart.Series.Clear();
        Series s = new Series();
        chart.Series.Add(s);
        s.ChartType = SeriesChartType.Bubble;  
        s.MarkerStyle = MarkerStyle.Diamond;
        s["PixelPointWidth"] = "100";
        s["PixelPointGapDepth"] = "1";

        chart.ApplyPaletteColors();

        addTestData(chart);
    }

enter image description here

user2587
  • 149
  • 10
  • Since some of your data are in the negative the automatic axes go there too. You can always set their Minimum to `0`. What do you mean by _extend into 4 quadrant form_ ? – TaW Sep 26 '18 at 08:56
  • I have updated the question. The graph should finally look like the above. can this be done in C#.NET ? – user2587 Sep 26 '18 at 09:21
  • More precisely to say that I want to display the graph in 3D Cartesian coordinate system. – user2587 Sep 26 '18 at 09:34

2 Answers2

6

You can style the chart easily to look like this by moving both axes to the middle; this is done by setting their Crossings:

enter image description here

The code used is this:

ChartArea ca = chart1.ChartAreas[0];

ca.BackColor = Color.Transparent;

ca.AxisX.Minimum = -300;
ca.AxisX.Maximum = 300;
ca.AxisY.Minimum = -300;
ca.AxisY.Maximum = 300;

ca.AxisX.Crossing = 0;  // move both axes..
ca.AxisY.Crossing = 0;  // to the middle

ca.AxisX.Interval = 100;
ca.AxisY.Interval = 100;

ca.AxisX.MajorGrid.LineColor = Color.LightGray;
ca.AxisY.MajorGrid.LineColor = Color.LightGray;

Note that the real problem with MSChart in 3d-mode always remains the z-axis because there really isn't one. (If anybody is interested in how one can simulate it by having a lot of series see here. My example uses 32 series..)

You could draw it yourself, using the built-in function for the 3d conversions (TransformPoints) but this is a lot of tedious work, especially when it comes to labelling..

TaW
  • 53,122
  • 8
  • 69
  • 111
0

Graph in 3D Cartesion System

The updated code :

  void prepare3dChart(Chart chart, ChartArea ca)
    {
        ca.Area3DStyle.Enable3D = true;
        ca.BackColor = Color.Transparent;

        ca.AxisX.Minimum = -300;
        ca.AxisX.Maximum = 300;
        ca.AxisY.Minimum = -300;
        ca.AxisY.Maximum = 300;

        ca.AxisX.Crossing = 0;  // move both axes..
        ca.AxisY.Crossing = 0;  // to the middle

        ca.AxisX.Interval = 50;
        ca.AxisY.Interval = 50;

        ca.AxisX.MajorGrid.LineColor = Color.LightGray;
        ca.AxisY.MajorGrid.LineColor = Color.LightGray;

        chart.Series.Clear();
        Series s = new Series();
        chart.Series.Add(s);
        s.ChartType = SeriesChartType.Bubble;  
        s.MarkerStyle = MarkerStyle.Diamond;
        s["PixelPointWidth"] = "100";
        s["PixelPointGapDepth"] = "1";

        chart.ApplyPaletteColors();

        addTestData(chart);
    }
user2587
  • 149
  • 10
  • Not sure if this should be an answer, as it mostly copies my code. Maybe adding the final code to your question would be more appropriate..? – TaW Sep 26 '18 at 10:34
  • There is no option to upload image in comment. So I uploaded in 'Answer' along with the final code. – user2587 Sep 26 '18 at 10:40
  • 1
    I meant to update the question with the code and the final image.. 1+ for the question, event though all the hard stuff was in place already. (From some [code I wrote](https://stackoverflow.com/questions/40244699/how-to-plot-a-3d-graph-to-represent-an-object-in-space/40245156?s=1|18.9681#40245156) a while ago ;-) – TaW Sep 26 '18 at 10:46
  • 1
    One of my colleague used your code. I asked him. :) – user2587 Sep 26 '18 at 10:55