Reputation: 29
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;
}
[proof]
rotate 33
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)
};
}
Upvotes: 2
Views: 85
Reputation: 54433
Here is one example of how you can do it. It..
DataPoint center
around which you want to rotate the graphicangle
by which it shall be rotatedSeries
s1
and s2
, the first being the source and the latter the rotated target.RotatePoint
from Fraser's anwser, slightly updated for PointF
.Here is the result for rotating around the 5th point by 33 degrees:
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);
}
Upvotes: 2