Example 5 — Gear Wheel

Created: 2026-05-27 · Updated: 2026-05-27

Advanced Snippet Editor

The most complex example: a gear wheel is created through three consecutive Boolean operations on a star shape and circles. Demonstrates how to chain result shapes and support all available tooth counts.


Result


Available Tooth Counts

PowerPoint only provides specific star shapes — not all tooth counts are possible:

Teeth MsoAutoShapeType
4 msoShape4pointStar
5 msoShape5pointStar
6 msoShape6pointStar
7 msoShape7pointStar
8 msoShape8pointStar
10 msoShape10pointStar
12 msoShape12pointStar (default)
16 msoShape16pointStar
24 msoShape24pointStar
32 msoShape32pointStar

Why no 20 teeth?

PowerPoint provides no 20-point star — there is no corresponding MsoAutoShapeType value.
20, 28, etc. are therefore not possible.
Full list of all shapes: MsoAutoShapeType on learn.microsoft.com


Code

/* PARAMS */
string tooths    = "12";   // 4|5|6|7|8|10|12|16|24|32
float  left      = 100f;
float  top       = 80f;
float  size      = 200f;
var    fillColor = System.Drawing.Color.FromArgb(52, 73, 94);
var    lineColor = System.Drawing.Color.FromArgb(30, 45, 60);
/* END PARAMS */

int fillRgb = System.Drawing.ColorTranslator.ToOle(fillColor);
int lineRgb = System.Drawing.ColorTranslator.ToOle(lineColor);

float cx        = left + size / 2f;
float cy        = top  + size / 2f;
float sizeSmall = size * 0.5713f;
float sizeBig   = size * 0.7143f;
float sizeHole  = size * 0.3136f;

void ApplyStyle(dynamic sh)
{
    sh.Fill.ForeColor.RGB = fillRgb;
    sh.Fill.Transparency  = 0f;
    sh.Line.Weight        = 1.5f;
    sh.Line.ForeColor.RGB = lineRgb;
    sh.Line.Transparency  = 0f;
    sh.Line.DashStyle     = MsoLineDashStyle.msoLineSolid;
    sh.Line.Style         = MsoLineStyle.msoLineSingle;
}

MsoAutoShapeType starType;
float adj;
switch (tooths)
{
    case  "4": starType = MsoAutoShapeType.msoShape4pointStar;  adj = 0.25f;    break;
    case  "5": starType = MsoAutoShapeType.msoShape5pointStar;  adj = 0.25f;    break;
    case  "6": starType = MsoAutoShapeType.msoShape6pointStar;  adj = 0.25f;    break;
    case  "7": starType = MsoAutoShapeType.msoShape7pointStar;  adj = 0.25f;    break;
    case  "8": starType = MsoAutoShapeType.msoShape8pointStar;  adj = 0.22781f; break;
    case "10": starType = MsoAutoShapeType.msoShape10pointStar; adj = 0.23f;    break;
    case "12": starType = MsoAutoShapeType.msoShape12pointStar; adj = 0.21753f; break;
    case "16": starType = MsoAutoShapeType.msoShape16pointStar; adj = 0.22f;    break;
    case "24": starType = MsoAutoShapeType.msoShape24pointStar; adj = 0.21f;    break;
    case "32": starType = MsoAutoShapeType.msoShape32pointStar; adj = 0.20f;    break;
    default:   starType = MsoAutoShapeType.msoShape12pointStar; adj = 0.21753f; break;
}

// 1. Star
var oStar = ppptools.AddShape(starType, cx - size/2f, cy - size/2f, size, size);
oStar.Adjustments[1] = adj;
ApplyStyle(oStar);

// 2. Small circle + Union → round off teeth valleys
var oSmall = ppptools.AddOval(cx - sizeSmall/2f, cy - sizeSmall/2f, sizeSmall, sizeSmall);
ApplyStyle(oSmall);
oStar.Select(MsoTriState.msoTrue);
oSmall.Select(MsoTriState.msoFalse);
ppptools.Union();
dynamic oUnion = ppptools.GetSelected();

// 3. Large circle + Intersect → limit outer shape
var oBig = ppptools.AddOval(cx - sizeBig/2f, cy - sizeBig/2f, sizeBig, sizeBig);
ApplyStyle(oBig);
oUnion.Select(MsoTriState.msoTrue);
oBig.Select(MsoTriState.msoFalse);
ppptools.Intersect();
dynamic oIntersect = ppptools.GetSelected();

// 4. Hole circle + Combine → punch out center
var oHole = ppptools.AddOval(cx - sizeHole/2f, cy - sizeHole/2f, sizeHole, sizeHole);
ApplyStyle(oHole);
oIntersect.Select(MsoTriState.msoTrue);
oHole.Select(MsoTriState.msoFalse);
ppptools.Combine();

foreach (dynamic sh in ppptools.GetSelectedRange())
{
    sh.Name = "GearWheel_" + tooths;
    ApplyStyle(sh);
}

Step-by-Step Explanation

1. The ApplyStyle Helper Function

void ApplyStyle(dynamic sh)
{
    sh.Fill.ForeColor.RGB = fillRgb;
    ...
}

Instead of repeating the styling for each of the four shapes, it is encapsulated in a local function. This saves code and ensures all intermediate shapes are consistently styled — which matters for Boolean operations (inconsistently styled shapes can produce unexpected results).

Why void ApplyStyle(dynamic sh) instead of Action<dynamic> applyStyle?
Action<> is in the System namespace, which is not automatically imported in Roslyn. Local functions work without issue. See Scripting Rules.

2. Tooth Count Selection: switch (tooths) with adj

MsoAutoShapeType starType;
float adj;
switch (tooths)
{
    case "12": starType = MsoAutoShapeType.msoShape12pointStar; adj = 0.21753f; break;
    ...
}

Each star shape has a different optimal inner radius ratio (adj). This value controls how far the valleys between the star's points reach inward. The adjustment is applied in the next step:

oStar.Adjustments[1] = adj;

Adjustments is a 1-based index array for shape-specific parameters. For stars, [1] controls the inner radius / outer radius ratio.

3. Operation 1: Union — Round Off the Tooth Valleys

// Small circle (57.13% of size) + Union with star
var oSmall = ppptools.AddOval(cx - sizeSmall/2f, cy - sizeSmall/2f, sizeSmall, sizeSmall);
oStar.Select(MsoTriState.msoTrue);
oSmall.Select(MsoTriState.msoFalse);
ppptools.Union();
dynamic oUnion = ppptools.GetSelected();

A circle slightly smaller than the star's outer circumscribed circle (sizeSmall = size * 0.5713f) is merged with the star. This fills in the valleys between the teeth — the tooth tips remain while the indentations become rounder.

Important: The result is immediately stored in dynamic oUnion, since the originals (oStar, oSmall) no longer exist after the operation.

4. Operation 2: Intersect — Constrain the Outer Shape

// Large circle (71.43% of size) + Intersect
var oBig = ppptools.AddOval(cx - sizeBig/2f, cy - sizeBig/2f, sizeBig, sizeBig);
oUnion.Select(MsoTriState.msoTrue);
oBig.Select(MsoTriState.msoFalse);
ppptools.Intersect();
dynamic oIntersect = ppptools.GetSelected();

A large circle (sizeBig = size * 0.7143f) is intersected with the Union result: only the area that lies within both shapes remains. This rounds off the sharp tooth tips — the gear wheel gets its characteristic rounded tooth crowns.

5. Operation 3: Combine — Punch Out the Center Hole

// Hole circle (31.36% of size) + Combine
var oHole = ppptools.AddOval(cx - sizeHole/2f, cy - sizeHole/2f, sizeHole, sizeHole);
oIntersect.Select(MsoTriState.msoTrue);
oHole.Select(MsoTriState.msoFalse);
ppptools.Combine();

Finally, the center hole is created: a small circle (sizeHole = size * 0.3136f) is punched out of the gear wheel using Combine.

The Three Size Proportions

Variable Formula Purpose
sizeSmall size * 0.5713 Fills valleys → rounds tooth roots inward
sizeBig size * 0.7143 Constrains tooth tips → rounds tooth crowns outward
sizeHole size * 0.3136 Center hole diameter

These proportions were determined empirically and produce a visually balanced gear wheel for all available tooth counts.


What's Special About This Example

  • Three chained Boolean operations — each takes the previous result as input. Intermediate results are stored in dynamic variables.
  • dynamic oUnion = ... ShapeRange[1] — after each Boolean op, the result is immediately captured before the next selection replaces it.
  • Adjustments[1] — shape-specific parameter that controls the star's inner radius ratio. Different values per tooth count produce evenly proportioned teeth.
  • Why no 20-tooth gear? — PowerPoint has no msoShape20pointStar. Also missing: 9, 11, 13, etc.
  • ApplyStyle on intermediate shapes too — so that Boolean operations consistently inherit the formatting properties from the input shapes.

Back: Example 4 — Hole (Combine) · Advanced Snippet Editor Overview