MapComposeのPolylineを動的に追加する

# JetpackCompose+MapComposeにPolylineを動的に追加する
[前回](https://qiita.com/jozuko_dev/items/b1d2b8ced3993e801959)は、MapComposeにMarkerを動的に追加しました。
今回は、Polylineを追加します。

まずは、地図上のタップ位置に対してPolylineを伸ばしていきます。
次に、スクリーン座標を地図座標表に変換してから、Polyline化していきます。

## 環境
AndroidStudio：Flamingo | 2022.2.1 Patch 2
OS：macOS

ライブラリは前回と一緒ですね。
```gradle:build.gradle
    implementation platform('androidx.compose:compose-bom:2022.10.00')
    implementation 'androidx.compose.ui:ui'
    implementation 'androidx.compose.ui:ui-graphics'
    implementation 'androidx.compose.ui:ui-tooling-preview'
    implementation 'androidx.compose.material3:material3'
    implementation 'androidx.navigation:navigation-compose:2.7.0-beta01'
    implementation platform('com.google.firebase:firebase-bom:32.1.1')
    implementation 'com.google.maps.android:maps-compose:2.11.4'
    implementation 'com.google.android.gms:play-services-maps:18.1.0'
```

## Step1.Polylineを追加する
地図上のタップ位置をPolyline描画します。

まず、Polylineのpoints座標を保持するState定義を追加します。

:::note warn
Markerの時とは異なり、Stateの定義には「mutableStateOf」を使用します。
誤） val markerItems = remember { mutableStateListOf<LatLng>() }

正） var polylineItems by remember { mutableStateOf<List<LatLng>>(listOf()) }
:::

```kotlin:GoogleMapsScreen.kt
var polylineItems by remember { mutableStateOf<List<LatLng>>(listOf()) }
```

次に、マップのonMapClickで一覧更新を行う記述を追加します。
```kotlin:GoogleMapsScreen.kt
GoogleMap(
    modifier = modifier,
    cameraPositionState = cameraPositionState,
    onMapLoaded = onMapLoaded,
    onMapClick = { latLng ->
        polylineItems = polylineItems + latLng
    },
) {
```

最後に、ポイントが2点以上となったらPolylineを描画するように記述します。
```kotlin:GoogleMapsScreen.kt
GoogleMap(/* ... */) {
    /* ... */
    if (polylineItems.count() > 1) {
        Polyline(
            points = polylineItems,
        )
    }
}
```

## いざ実行
ここまでの[コードはこちら](https://github.com/jozuko/ComposeTutorial/blob/a0b30bcc2f8037143413db8bdccb19b3dce68940/app/src/main/java/com/jozu/jetpack/compose/tutorial/screen/GoogleMapsScreen.kt)
![map_polyline_1_AdobeExpress.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3491965/c9b13a4f-3ca6-b750-1bca-2e54376e73f9.gif)

## Step2.スクリーン座標を取得する
まず、スクリーンのタップ位置座標を取得するために、GoogleMapと同じ大きさ・同じ位置のBoxを配置します。

:::note warn
検証を目的にBoxを配置しています。
BoxをGoogleMapの上に配置することで、GoogleMapが拾っていたイベントをすべてBoxが取得するようになりますので、GoogleMapのズームやカメラ移動などは一切効かない状態になります。
:::

```kotlin:GoogleMapsScreen.kt
Column {
    Box(modifier = Modifier.weight(1f).fillMaxSize()) {
        GoogleMap(
            modifier = Modifier.matchParentSize(),
            /* ... */
        )

        // GoogleMapと同じサイズ・位置のBox
        Box(modifier = Modifier.matchParentSize())
    }
    Buttons(
        modifier = Modifier.fillMaxWidth(),
        /* ... */
    )
}
```
GoogleMap（）の下の行に追加したBoxが、タップイベントを拾うためのBoxです。
このBoxのmodifierにpointerInputを追加します。
```kotlin:GoogleMapsScreen.kt
Box(
    modifier = Modifier
        .matchParentSize()
        .pointerInput(Unit) {
            detectTapGestures(
                onPress = { offset ->
                    if (!cameraPositionState.isMoving) {
                        val pressedLatLng = cameraPositionState.projection?.fromScreenLocation(Point(offset.x.toInt(), offset.y.toInt()))
                        if (pressedLatLng != null) {
                            polylineItems = polylineItems + pressedLatLng
                        }
                    }
                },
            )
        },
)
```
cameraPositionState.projection?.fromScreenLocationがスクリーン座標と緯度経度の変換を行う関数です。

## いざ実行
[コードはこちら](https://github.com/jozuko/ComposeTutorial/blob/b769ccd60f3418ed09eb9bb37d01552b1892c2f3/app/src/main/java/com/jozu/jetpack/compose/tutorial/screen/GoogleMapsScreen.kt)
![map_polyline_2_AdobeExpress.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3491965/d67f679a-1a47-6609-d20c-c5cff44a71cf.gif)