# nonzero winding rule

[browser](../..) ⟩ [canvas](..) ⟩ [path]() ⟩ nonzero winding rule

{% tabs %}
{% tab title="💾 程式" %}
![left: both clockwise, middle: counter/clockwise, right: both counterclockwise](https://2527454625-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MfvEFZnSBhKT6fJmus0%2Fuploads%2FUw8JjptAxqdekEo0byNi%2Fnonzero%20winding%20rule.png?alt=media\&token=ce482524-a027-4ea6-9e1e-b359dd51c04f)

:floppy\_disk: replit: [nonzero winding rule](https://replit.com/@pegasusroe/canvas-polygon#index.html)

⬆️ 需要： [drawoncanvas2d](../+ext/drawoncanvas2d "mention"), [polygon](../examples/polygon "mention")

```javascript
// Define a regular polygon
// parameters: 
// - c: canvas drawing context
// - n: number of sides
// - x, y, r: centered at (x,y), radius r.
// - angle: starting angle
function polygon(c, n, x, y, r, angle = 0, counterclockwise = false) {
    
    // Begin a new subpath at first vertex
    c.moveTo(x + r * Math.sin(angle), y - r * Math.cos(angle));

    let delta = 2 * Math.PI / n * (counterclockwise ? -1 : 1);

    // Angular distance between vertices
    for (let i = 1; i < n; i++) {
        angle += delta;
        c.lineTo(x + r * Math.sin(angle), y - r * Math.cos(angle));
    }
    
    c.closePath(); // back to the first 
}

// draw on <canvas>
drawOnCanvas2D('#playground', (ctx) => {

    // Start a new path and add polygon subpaths 
    ctx.beginPath(); 
    polygon(ctx, 3, 50, 70, 50); // Triangle 
    polygon(ctx, 4, 150, 60, 50, Math.PI/4); // Square 
    polygon(ctx, 5, 255, 55, 50); // Pentagon 
    polygon(ctx, 6, 365, 53, 50, Math.PI/6); // Hexagon 
    polygon(ctx, 4, 365, 53, 20, Math.PI/4, true); // Small square inside the hexagon

    ctx.fillStyle = "red"; // fill color
    ctx.strokeStyle = "black"; // stroke color
    ctx.lineWidth = 8; // stroke width

    ctx.fill(); // Fill the shapes 
    ctx.stroke(); // And stroke their outlines
});

drawOnCanvas2D('#play2', (ctx) => {

    // Start a new path and add polygon subpaths 
    ctx.beginPath(); 
    polygon(ctx, 4, 50, 50, 50, Math.PI/4); // Square 
    polygon(ctx, 4, 75, 75, 50, Math.PI/4); // Small square inside the hexagon

    ctx.fillStyle = "pink"; // fill color
    ctx.strokeStyle = "black"; // stroke color
    ctx.lineWidth = 8; // stroke width

    ctx.fill(); // Fill the shapes 
    ctx.stroke(); // And stroke their outlines

    // Start a new path and add polygon subpaths 
    ctx.beginPath(); 
    polygon(ctx, 4, 200, 50, 50, Math.PI/4); // Square 
    polygon(ctx, 4, 225, 75, 50, Math.PI/4, true); // Small square inside the hexagon

    ctx.fillStyle = "#ccffcc"; // fill color
    ctx.fill(); // Fill the shapes 
    ctx.stroke(); // And stroke their outlines

    // Start a new path and add polygon subpaths 
    ctx.beginPath(); 
    polygon(ctx, 4, 350, 50, 50, Math.PI/4, true); // Square 
    polygon(ctx, 4, 375, 75, 50, Math.PI/4, true); // Small square inside the hexagon

    ctx.fillStyle = "#ccf"; // fill color
    ctx.fill(); // Fill the shapes 
    ctx.stroke(); // And stroke their outlines
});
```
{% endtab %}

{% tab title="📗 參考" %}
* [ ] 台部落 ⟩ [奇偶規則和非零纏繞規則](https://www.twblogs.net/a/5e53ceb9bd9eee211683113d)
* [ ] OpenFL ⟩ [Defining winding rules](https://books.openfl.org/openfl-developers-guide/using-the-drawing-api/advanced-use-of-the-drawing-api/defining-winding-rules.html)
{% endtab %}
{% endtabs %}
