I'm really afraid my help could be not very useful. I'm presenting a complete solution based on .NET and C#. The problem is way too simple: just a combination of two rotations. If you did not know how to calculate that, I would afraid just using the code would also be a problem. Anyway, let's try.
First of all, define a floating-point type to work with and a 2D vector with just a vector sum:
using Real = System.Double;
public struct Vector2d {
public Vector2d(Real x, Real y) { this.x = x; this.y = y; }
public static Vector2d operator +(Vector2d left, Vector2d right) {
return new Vector2d(left.X + right.X, left.Y + right.Y);
}
public Real X { get { return x; } }
public Real Y { get { return y; } }
Real x, y;
}
Now, define rotation, and only around the center {0, 0}. We will need to translate the coordinate system (using '+' defined above) anyway when we sum the rotations.
public class Rotation {
public Rotation(Real radius, Real angularVelocity, Real phase) { Initialize(radius, angularVelocity, phase); }
public Rotation(Real radius, Real angularVelocity) { Initialize(radius, angularVelocity, 0); }
public Vector2d GetPosition(Real time) {
return new Vector2d(
radius * System.Math.Cos(time * angularVelocity + initialPhase),
radius * System.Math.Sin(time * angularVelocity + initialPhase));
}
Real radius, angularVelocity, initialPhase;
void Initialize(Real radius, Real angularVelocity, Real phase) {
this.radius = radius;
this.angularVelocity = angularVelocity;
this.initialPhase = phase;
}
}
Now, I'm going to define the complex motion. Instead of definition of just two rotations, I'll define the hierarchy of unlimited rotating coordinate system: one rotation defines the center of another coordinate system, that one is also rotating, etc. In you case you will use just the array of two elements, one representing a main circle, another one — a planetary circle. So, this one will represent the hierarchy of unlimited members:
public class ComplexRotationCalculator {
public ComplexRotationCalculator(Vector2d center, params Rotation[] systems) {
this.center = center;
this.systems = systems;
}
public ComplexRotationCalculator(params Rotation[] systems) {
this.center = new Vector2d(0, 0);
this.systems = systems;
}
public Vector2d GetPosition(Real time) {
Vector2d result = center;
foreach(Rotation rotation in systems)
result += rotation.GetPosition(time);
return result;
}
public Vector2d[] GetTrajectory(Real step, uint pointNumber) {
Vector2d[] trajectory = new Vector2d[pointNumber];
for (uint index = 0; index < pointNumber; ++index)
trajectory[index] = GetPosition(index * step);
return trajectory;
}
return trajectory;
}
Vector2d center;
Rotation[] systems;
}
Basically, that's it. You can use the final
GetPosition
for rendering graphics immediately, or generate an array of points via
GetTrajectory
. This trajectory can be later imported anywhere to make the picture. I suggest to forget all the interpolations we discussed and just generate points with the step which is small enough to give an accurate picture. The speed of calculation is very high, so you can calculate many thousands of points without virtually any wait.
Let's show, for example, how to render with
System.Graphics
, which can be used along or with
System.Drawing.Forms
or anything like that. Let's add the namespace and the function calculating the trajectory in terms of points defined in this library:
using System.Drawing;
public class ComplexRotationCalculator {
public System.Drawing.PointF[] GetPointTrajectory(Real step, uint pointNumber) {
System.Drawing.PointF[] trajectory = new System.Drawing.PointF[pointNumber];
for (uint index = 0; index < pointNumber; ++index) {
Vector2d vector = GetPosition(index * step);
trajectory[index] = new System.Drawing.PointF(
(float)vector.X,
(float)vector.Y);
}
return trajectory;
}
}
Again, this rendering can be used immediately to show the rendered graphics on screen in the handle of the event
Paint
or, better yet, overridden method
OnPaint
of some control. For simplicity, I'll show rendering of some bitmap and saving it to a file:
class Sample {
static void RenderTrajectory(Graphics graphics, Pen pen, PointF[] trajectory) {
graphics.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.High;
graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
graphics.DrawLines(pen, trajectory);
}
static void RenderTrajectoryBitmap(Pen pen, int width, int heigh, string filename, PointF[] trajectory) {
Bitmap bitmap = new Bitmap(width, heigh, System.Drawing.Imaging.PixelFormat.Format32bppRgb);
RenderTrajectory(Graphics.FromImage(bitmap), pen, trajectory);
bitmap.Save(filename);
}
public void Run() {
ComplexRotationCalculator calc = new ComplexRotationCalculator(
new Vector2d(300, 300),
new Rotation[] { new Rotation(200d, 1d), new Rotation(30d, 16d), });
PointF[] trajectory = calc.GetPointTrajectory(0.001, 36000);
RenderTrajectoryBitmap(Pens.White, 600, 600, "test.png", trajectory);
}
}
For further detail of rendering using
System.Drawing
and
System.Windows.Forms
, please see my past answers:
What kind of playful method is Paint? (DataGridViewImageCell.Paint(...))[
^],
Drawing Lines between mdi child forms[
^],
capture the drawing on a panel[
^].
For WPF rendering, please see:
http://msdn.microsoft.com/en-us/library/ms747393.aspx[
^].
—SA