Title: Draw gears in C#
This example uses the following DrawGear method to draw gears.
// Draw a gear.
private void DrawGear(Graphics gr, Brush axle_brush,
Brush gear_brush, Pen gear_pen, PointF center,
float radius, float tooth_length, int num_teeth,
float axle_radius, bool start_with_tooth)
{
float dtheta = (float)(Math.PI / num_teeth);
// dtheta in degrees.
float dtheta_degrees = (float)(dtheta * 180 / Math.PI);
const float chamfer = 2;
float tooth_width = radius * dtheta - chamfer;
float alpha = tooth_width / (radius + tooth_length);
float alpha_degrees = (float)(alpha * 180 / Math.PI);
float phi = (dtheta - alpha) / 2;
// Set theta for the beginning of the first tooth.
float theta;
if (start_with_tooth) theta = dtheta / 2;
else theta = -dtheta / 2;
// Make rectangles to represent
// the gear's inner and outer arcs.
RectangleF inner_rect = new RectangleF(
center.X - radius, center.Y - radius,
2 * radius, 2 * radius);
RectangleF outer_rect = new RectangleF(
center.X - radius - tooth_length,
center.Y - radius - tooth_length,
2 * (radius + tooth_length), 2 * (radius + tooth_length));
// Make a path representing the gear.
GraphicsPath path = new GraphicsPath();
for (int i = 0; i < num_teeth; i++)
{
// Move across the gap between teeth.
float degrees = (float)(theta * 180 / Math.PI);
path.AddArc(inner_rect, degrees, dtheta_degrees);
theta += dtheta;
// Move across the tooth's outer edge.
degrees = (float)((theta + phi) * 180 / Math.PI);
path.AddArc(outer_rect, degrees, alpha_degrees);
theta += dtheta;
}
path.CloseFigure();
// Draw the gear.
gr.FillPath(gear_brush, path);
gr.DrawPath(gear_pen, path);
gr.FillEllipse(axle_brush,
center.X - axle_radius, center.Y - axle_radius,
2 * axle_radius, 2 * axle_radius);
}
The code first defines some variables to make drawing easier. It sets dtheta to the angle spanned by each tooth.
The value chamfer gives the amount by which a tooth's end is narrower than its base. This makes the tooth taper slightly. (In real gears the tooth may also have curved sides to make it fit better with other teeth, but straight edges are good enough for this.)
The tooth_width variable holds the desired width of the tooth at its end. This is the width at the base minus the chamfer amount.
The value alpha holds the angle subtended by the end of the tooth. The value phi holds half the difference between dtheta and alpha. This gives the angle between the base and the end of the tooth. (See the picture on the right.)
With these values, you should be able to follow the geometry of the gear-drawing code.
Next the code sets an initial angle theta. If the gear should start with a tooth (as opposed to a gap between two teeth) on the right, the code sets theta equal to dtheta / 2 so drawing begins above the gear's horizontal center. If the gear should begin with a gap on its right edge, the code sets theta equal to -dtheta / 2 so drawing begins below the gear's horizontal center.
The code then enters a loop to draw the gear's teeth. It starts drawing each tooth by drawing a gap between teeth. It then draws the tooth itself. The initial value for theta determines whether the first tooth's gap begins above the horizontal centerline (so a tooth falls on the centerline) or below the horizontal centerline (so a gap falls on the centerline).
The code calls CloseFigure to close the GraphicsPath object by connecting its last point to its first point. Finally the code fills and draws the path that defines the gear.
The program uses the following code to draw gears on the picGears PictureBox.
// Draw the gear.
private void picGears_Paint(object sender, PaintEventArgs e)
{
// Draw smoothly.
e.Graphics.SmoothingMode = SmoothingMode.AntiAlias;
const float radius = 50;
const float tooth_length = 10;
float x = picGears.ClientSize.Width / 2 -
radius - tooth_length - 1;
float y = picGears.ClientSize.Height / 3;
DrawGear(e.Graphics, Brushes.Black, Brushes.LightBlue,
Pens.Blue, new PointF(x, y),
radius, tooth_length, 10, 5, true);
x += 2 * radius + tooth_length + 2;
DrawGear(e.Graphics, Brushes.Black, Brushes.LightGreen,
Pens.Green, new PointF(x, y),
radius, tooth_length, 10, 5, false);
y += 2 * radius + tooth_length + 2;
DrawGear(e.Graphics, Brushes.Black, Brushes.Pink,
Pens.Red, new PointF(x, y),
radius, tooth_length, 10, 5, true);
}
You'll have to do some calculations to draw gears positioned correctly so they look like they are interlocked.
Download the example to experiment with it and to see additional details.
|