【Flutter】ポリゴン多角星の描画（CustomPaint応用編）

※本記事は下記のZenn本にまとめました。

https://zenn.dev/cxj/books/07def04506182d
# 正多角形

点を収集できれば、いくら角あっても描けます。
下記のように三角形の頂点を収集すれば、addPolygonで三角形を描くことができます。
![](https://storage.googleapis.com/zenn-user-upload/e619b85e6e21-20230210.png)

ブルー枠線は正三角形の外接円であり、正三角形の場合、その3点は外接円の0°、120°、240°です。三角関数の正弦、余弦でその点の座標を算出します。
```dart
    for (int i = 0; i < count; i++) {
      // 0°、120°、240°
      double perRad = 2 * pi / count * i;
      points.add(Offset(radius * cos(perRad), radius * sin(perRad)));
    }
```

点の集合取得できれば、path.addPolygon関数で正三角形を描画できます。
```dart
    Path path = Path();
    Paint paint = Paint()
      ..color = Colors.red
      ..strokeWidth = 2
      ..style = PaintingStyle.stroke;
    int count = 3;
    double radius = 100;
    List<Offset> points = [];
    for (int i = 0; i < count; i++) {
      // 始点は0°
      double perRad = 2 * pi / count * i;
      points.add(Offset(radius * cos(perRad), radius * sin(perRad)));
    }
    path.addPolygon(points, true);
    canvas.drawPath(path, paint);
```
では、同じ方法で上記count値で外接円を均等で分けて、その点を収集できれば、正多角形の描画もできます。
|正四角形|正五角形|正六角形|正十角形|
|--|--|--|--|
|![](https://storage.googleapis.com/zenn-user-upload/c6b8184ad659-20230210.png)|![](https://storage.googleapis.com/zenn-user-upload/79a69adf55a0-20230210.png)|![](https://storage.googleapis.com/zenn-user-upload/b2b097e159e1-20230210.png)|![](https://storage.googleapis.com/zenn-user-upload/f75a736470cf-20230210.png)|

※上記例は始点0°となっています。もし多角形の向きを調整したい場合、その始点を調整すれば、簡単にできます。
```dart
// 偏移値
double offset = -pi / 2;
points.add(
  Offset(
    radius * cos(perRad + offset),
    radius * sin(perRad + offset),
  ),
);
```
![](https://storage.googleapis.com/zenn-user-upload/9d4e8e10c4bb-20230210.png)

# star
上記の方法で多角形描けましたので、同じ方法で二つの多角形を描いて、点と点を連結すれば、星になるでしょう。
![](https://storage.googleapis.com/zenn-user-upload/e09615249dea-20230211.png)

```dart
    int count = 5;
    double outRadius = 100;
    double innerRadius = 50;
    List<Offset> points = [];
    for (int i = 0; i < count; i++) {
      double perRad = 2 * pi / count * i;
      points.add(Offset(outRadius * cos(perRad), outRadius * sin(perRad - pi / 2)));
      points.add(Offset(innerRadius * cos(perRad), innerRadius * sin(perRad - pi / 2)));
    }
    path.addPolygon(points, true);
```
では、その内部の円を右へちょっと偏移すれば、綺麗になります。
![](https://storage.googleapis.com/zenn-user-upload/12a63ae23e17-20230211.png)

```dart
    for (int i = 0; i < count; i++) {
      double perRad = 2 * pi / count * i;
      points.add(Offset(outRadius * cos(perRad - pi / 2), outRadius * sin(perRad - pi / 2)));
      points.add(
        Offset(
          innerRadius * cos(perRad - pi / 2 + offset),
          innerRadius * sin(perRad - pi / 2 + offset),
        ),
      );
    }
    path.addPolygon(points, true);
```

# n角星
五角星描けましたので、その偏移値 **β** と **n** の関係分かれば、n角星も描けると思います。

~~~
n 角形の内角の和の式は， 180°×n －360°
~~~

下記 **α** は正五角形内角の１つですから、**α=(180°×5 －360°)/5=108°**。
従って、**β=180°-108°/2-90°=36°**。

~~~
β=180°-(180°*n －360°)/n/2-90°
β=180°/n
~~~

![](https://storage.googleapis.com/zenn-user-upload/0eaf3e6d5235-20230211.png)

偏移値は **pi / count**となります。

```dart
    int count = 5;
    double outRadius = 100;
    double innerRadius = 50;
    double offset = pi / count;
    List<Offset> points = [];
    for (int i = 0; i < count; i++) {
      // 始点は0°
      double perRad = 2 * pi / count * i;
      points.add(Offset(outRadius * cos(perRad - pi / 2), outRadius * sin(perRad - pi / 2)));
      points.add(
        Offset(
          innerRadius * cos(perRad - pi / 2 + offset),
          innerRadius * sin(perRad - pi / 2 + offset),
        ),
      );
    }
    path.addPolygon(points, true);
```

countを10にすると下記のような10角星できました。
![](https://storage.googleapis.com/zenn-user-upload/9567a0b13bed-20230211.png)