2

I am using MSchart to plot serie into it, i need to rotate Curve (serie of datapoint) X degrees, P1 is fisrt click (mouseDown) and P2 second click (mouseUp), the angle between P1 and P2 represent the angle to rotate (i have this calculated), the problem is the curve deform when i apply different methods to do this

for (int x = 1; x < curve.nPoints; x++)
{   
     double X0 = curve.get_array_X[x];
     double Y0 = curve.get_array_Y[x];

     System.Windows.Media.Matrix m = new System.Windows.Media.Matrix();
     m.Rotate(45 * (Math.PI / 180.0));
     System.Windows.Vector v = new System.Windows.Vector(X0, Y0);
     v = System.Windows.Vector.Multiply(v, m);
     sAus.Points.AddXY(v.X, v.Y);
}

and this other code

public Series nueva(float X, float Y)
    {
        Series sAus = new Series(curvaActual.Tag);
        int nearest1 = curvaActual.FindNearestXCV(new DataPoint(chartWorking1.ChartAreas[0].AxisX.PixelPositionToValue(X),
                                 chartWorking1.ChartAreas[0].AxisY.PixelPositionToValue(Y)).XValue,
                                 new DataPoint(chartWorking1.ChartAreas[0].AxisX.PixelPositionToValue(X), chartWorking1.ChartAreas[0].AxisY.PixelPositionToValue(Y)).YValues[0], 0, curvaActual.nPoints);
        int nearest2 = curvaActual.FindNearestXCV(new DataPoint(chartWorking1.ChartAreas[0].AxisX.PixelPositionToValue(X),
                                      chartWorking1.ChartAreas[0].AxisY.PixelPositionToValue(Y)).XValue,
                                      new DataPoint(chartWorking1.ChartAreas[0].AxisX.PixelPositionToValue(X), chartWorking1.ChartAreas[0].AxisY.PixelPositionToValue(Y)).YValues[0], 0, curvaActual.nPoints);

        double x1 = (double)curvaActual.get_array_X[nearest1];
        double y1 = (double)curvaActual.get_array_Y[nearest1];


        double x2 = (double)curvaActual.get_array_X[nearest2];
        double y2 = (double)curvaActual.get_array_Y[nearest2];
        double pendiente = Math.Atan2(y2 - y1, x2 - x1);
        double anguloF = pendiente;
        double deg = Math.PI * 45 / 180.0;
        double coseno = Math.Cos(deg);
        double seno = Math.Sin(deg);

        double[] arrayX = new double[curvaActual.nPoints];
        double[] arrayY = new double[curvaActual.nPoints];

        for (int x = 1; x < curvaActual.nPoints; x++)
        {

            PointF rotatedPoint = RotatePoint(new PointF((float)curvaActual.get_array_X[x], (float)curvaActual.get_array_Y[x]), new PointF((float)curvaActual.get_array_X[x - 1], (float)curvaActual.get_array_Y[x - 1]), 45);
            double angleRotatedPoint = angleFromPoint(rotatedPoint, new PointF((float)curvaActual.get_array_X[x - 1], (float)curvaActual.get_array_Y[x - 1]));


            PointF pointROtado = RotatePoint(new PointF((float)curvaActual.get_array_X[x], (float)curvaActual.get_array_Y[x]), new PointF((float)0, (float)0), 45);
            sAus.Points.AddXY((double)pointROtado.X, (double)pointROtado.Y);

        }

        return sAus;
    }

[enter image description here]

[proof]

original serie enter image description here

rotate 33

enter image description here

using your code (modify point to pointF)

void rotateSeries(Series src, Series tgt, DataPoint center, float angle)
    {

        PointF c = new PointF((float)center.XValue, (float)center.YValues[0]);

        tgt.Points.Clear();
        foreach (DataPoint dp in src.Points)
        {
            PointF p0 = new PointF((float)dp.XValue, (float)dp.YValues[0]);
            PointF p = RotatePoint(p0, c, angle);
            tgt.Points.AddXY(p.X, p.Y);
        }
    }
    static PointF RotatePoint(PointF pointToRotate, PointF centerPoint, double angleInDegrees)
    {
        double angleInRadians = angleInDegrees * (Math.PI / 180);
        double cosTheta = Math.Cos(angleInRadians);
        double sinTheta = Math.Sin(angleInRadians);
        return new PointF
        {
            X = (float)
                (cosTheta * (pointToRotate.X - centerPoint.X) -
                sinTheta * (pointToRotate.Y - centerPoint.Y) + centerPoint.X),
            Y = (float)
                (sinTheta * (pointToRotate.X - centerPoint.X) +
                cosTheta * (pointToRotate.Y - centerPoint.Y) + centerPoint.Y)
        };
    }
  • Welcome to StackOverflow! Please provide the code that you've tried that fails. – noelicus May 25 '17 at 08:41
  • Hm. Is the last imge done with my function? What does it look like when it is dsplayed along with the orginal series? (In the same chartarea, so they have a common set of axes..) - Also: Why do you go from 1 instead of 0?? Doesn't that miss one point? (Thanks for catching the PointF error;! ;-) – TaW May 25 '17 at 11:24
  • Yes, i use your function, yes is same axes and displayed in the same chart area. I dont know what happend...i think the problem is i am not in First Quadrant (0,0) – Jesús Álvarez May 25 '17 at 12:33
  • With 90 degrees work perfectly, you think that we need to add the previous angle to the angle we need to rotate? – Jesús Álvarez May 25 '17 at 12:39
  • Um, don't you always rotate the original series?? what do you meant by quadrant? negative values?Neither seems to matter here . (Just tested) - I do not see how the original graph is created!? At the moment I suspect your problems there.. – TaW May 25 '17 at 13:23
  • i dont know what is the problem, my chart us simply chart, and series are simply series of datapoint – Jesús Álvarez May 25 '17 at 14:54
  • Well a chart is a chart but beyond that in a chart hardly anything is simple. The way datapoints are added is often cause of confusion. - Try this: Add a button with the code in my post to make use of the rotateSeries method. This makes sure the rotated series will be using the data of the original series instead of trying to import them from some other source. – TaW May 25 '17 at 18:07

1 Answers1

2

Here is one example of how you can do it. It..

  • assumes you have found the DataPoint center around which you want to rotate the graphic
  • assumes you have calculated the angle by which it shall be rotated
  • uses two Series s1 and s2, the first being the source and the latter the rotated target.
  • uses a version of RotatePoint from Fraser's anwser, slightly updated for PointF.

Here is the result for rotating around the 5th point by 33 degrees:

enter image description here

private void button1_Click(object sender, EventArgs e)
{
    rotateSeries(s1, s2, s1.Points[4], 33);
}

void rotateSeries(Series src, Series tgt, DataPoint center, float angle)
{

    PointF c = new PointF((float)center.XValue, (float)center.YValues[0]);

    tgt.Points.Clear();
    foreach (DataPoint dp in src.Points)
    {
        PointF p0 = new Point((float)dp.XValue, (float)dp.YValues[0]);
        PointF p = RotatePoint(p0, c, angle);
        tgt.Points.AddXY(p.X, p.Y);
    }
}

static PointF RotatePoint(PointF pointToRotate, PointF centerPoint, double angleInDegrees)
{
    double angleInRadians = angleInDegrees * (Math.PI / 180);
    double cosTheta = Math.Cos(angleInRadians);
    double sinTheta = Math.Sin(angleInRadians);
    return new PointF
    {
        X = (float)
            (cosTheta * (pointToRotate.X - centerPoint.X) -
            sinTheta * (pointToRotate.Y - centerPoint.Y) + centerPoint.X),
        Y = (float)
            (sinTheta * (pointToRotate.X - centerPoint.X) +
            cosTheta * (pointToRotate.Y - centerPoint.Y) + centerPoint.Y)
    };
}

If you want to use the MouseClick to determine the angle you can use the Points from the e parameter directly. But to find out the center you will need to convert the pixel coordinates to chart value coordinates.

Here is a call you can use during the MouseClick event:

DataPoint clickedValuePoint(ChartArea ca, Point pt)
{
    return new DataPoint(ca.AxisX.PixelPositionToValue(pt.X), 
                         ca.AxisY.PixelPositionToValue(pt.Y));
}

Now let's see it at work, using a DataPoint:

DataPoint centerPoint = null;

private void chart1_MouseClick(object sender, MouseEventArgs e)
{
    ChartArea ca = chart1.ChartAreas[0];
    centerPoint = clickedValuePoint(ca, e.Location);

    rotateSeries(s1, s2, centerPoint, 33);
}

enter image description here

TaW
  • 53,122
  • 8
  • 69
  • 111