# Plane

Artifact: [androidx.xr.arcore:arcore](https://developer.android.com/jetpack/androidx/releases/xr-arcore) [View Source](https://cs.android.com/search?q=file:androidx/xr/arcore/Plane.kt+class:androidx.xr.arcore.Plane) Added in [1.0.0](https://developer.android.com/jetpack/androidx/releases/xr-arcore#1.0.0)

*** ** * ** ***


```
public final class Plane implements Anchorable<@NonNull Plane.State>
```

<br />

*** ** * ** ***

Describes the system's current best knowledge of a real-world planar surface.

## Summary

| ### Nested types |
|---|
| `public final class https://developer.android.com/reference/androidx/xr/arcore/Plane.State implements https://developer.android.com/reference/androidx/xr/arcore/Trackable.State` The representation of the current state of a `https://developer.android.com/reference/androidx/xr/arcore/Plane`. |

| ### Public methods |
|---|---|
| `@https://developer.android.com/reference/androidx/annotation/NonNull https://developer.android.com/reference/androidx/xr/arcore/AnchorResult` | `https://developer.android.com/reference/androidx/xr/arcore/Plane#createAnchor(androidx.xr.runtime.math.Pose)(@https://developer.android.com/reference/androidx/annotation/NonNull https://developer.android.com/reference/androidx/xr/runtime/math/Pose pose)` Creates an `https://developer.android.com/reference/androidx/xr/arcore/Anchor` attached to this trackable. |
| `@https://developer.android.com/reference/androidx/annotation/NonNull https://kotlinlang.org/api/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.flow/-state-flow/index.html<@https://developer.android.com/reference/androidx/annotation/NonNull https://developer.android.com/reference/androidx/xr/arcore/Plane.State>` | `https://developer.android.com/reference/androidx/xr/arcore/Plane#getState()()` the current `https://developer.android.com/reference/androidx/xr/arcore/Plane.State` of the plane |
| `final @https://developer.android.com/reference/androidx/annotation/NonNull https://developer.android.com/reference/androidx/xr/arcore/PlaneType` | `https://developer.android.com/reference/androidx/xr/arcore/Plane#getType()()` the `https://developer.android.com/reference/androidx/xr/arcore/PlaneType` of the plane |
| `static final @https://developer.android.com/reference/androidx/annotation/NonNull https://kotlinlang.org/api/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.flow/-state-flow/index.html<@https://developer.android.com/reference/androidx/annotation/NonNull https://developer.android.com/reference/java/util/Collection.html<@https://developer.android.com/reference/androidx/annotation/NonNull https://developer.android.com/reference/androidx/xr/arcore/Plane>>` | `https://developer.android.com/reference/androidx/xr/arcore/Plane#subscribe(androidx.xr.runtime.Session)(@https://developer.android.com/reference/androidx/annotation/NonNull https://developer.android.com/reference/androidx/xr/runtime/Session session)` Emits the planes that are currently being tracked in the `https://developer.android.com/reference/androidx/xr/arcore/Plane.Companion#subscribe(androidx.xr.runtime.Session)`. |
| `@https://developer.android.com/reference/androidx/annotation/NonNull https://developer.android.com/reference/java/lang/String.html` | `https://developer.android.com/reference/androidx/xr/arcore/Plane#toString()()` Returns a string representation of `https://developer.android.com/reference/androidx/xr/arcore/Plane` for debugging. |

## Public methods

### createAnchor

```
public @NonNull AnchorResult createAnchor(@NonNull Pose pose)
```

Creates an `https://developer.android.com/reference/androidx/xr/arcore/Anchor` attached to this trackable.

| Parameters |
|---|---|
| `@https://developer.android.com/reference/androidx/annotation/NonNull https://developer.android.com/reference/androidx/xr/runtime/math/Pose pose` | the initial `https://developer.android.com/reference/androidx/xr/runtime/math/Pose` of the `https://developer.android.com/reference/androidx/xr/arcore/Anchor` |

| Throws |
|---|---|
| `https://kotlinlang.org/api/core/kotlin-stdlib/kotlin/-illegal-state-exception/index.html` | if `https://developer.android.com/reference/androidx/xr/runtime/Session#config()` is set to `https://developer.android.com/reference/androidx/xr/runtime/PlaneTrackingMode#DISABLED()` |

### getState

```
public @NonNull StateFlow<@NonNull Plane.State> getState()
```

the current `https://developer.android.com/reference/androidx/xr/arcore/Plane.State` of the plane

### getType

Added in [1.0.0](https://developer.android.com/jetpack/androidx/releases/xr-arcore#1.0.0)

```
public final @NonNull PlaneType getType()
```

the `https://developer.android.com/reference/androidx/xr/arcore/PlaneType` of the plane

### subscribe

Added in [1.0.0](https://developer.android.com/jetpack/androidx/releases/xr-arcore#1.0.0)

```
public static final @NonNull StateFlow<@NonNull Collection<@NonNull Plane>> subscribe(@NonNull Session session)
```

Emits the planes that are currently being tracked in the `https://developer.android.com/reference/androidx/xr/arcore/Plane.Companion#subscribe(androidx.xr.runtime.Session)`.

Only `https://developer.android.com/reference/androidx/xr/arcore/Plane`s that are `https://developer.android.com/reference/androidx/xr/arcore/TrackingState#TRACKING()` will be emitted in the `https://kotlinlang.org/api/core/kotlin-stdlib/kotlin.collections/-collection/index.html`. Instances of the same `https://developer.android.com/reference/androidx/xr/arcore/Plane` will remain between subsequent emits to the `https://kotlinlang.org/api/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.flow/-state-flow/index.html` as long as they remain tracking.

```kotlin
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.repeatOnLifecycle
import androidx.xr.arcore.Plane
import androidx.xr.arcore.TrackingState
import androidx.xr.runtime.math.Pose
import androidx.xr.scenecore.scene

// Use a coroutine to listen to changes to the set of detected planes.
yourCoroutineScope.launch {
    val activePlanes = mutableMapOf<Plane, Job>()

    lifecycle.repeatOnLifecycle(Lifecycle.State.RESUMED) {
        val supervisor = SupervisorJob()
        val supervisorScope = CoroutineScope(yourCoroutineScope.coroutineContext + supervisor)
        try {
            Plane.subscribe(session).collect { planes ->
                // The list of detected planes has changed.
                for (plane in planes) {

                    // If a plane doesn't exist in our set of active planes, set up a
                    // coroutine to respond to its state changes.
                    if (!activePlanes.contains(plane)) {
                        val job = supervisorScope.launch {
                            plane.state.collect {
                                // if the plane is not currently reporting as tracked, then
                                // we don't want to render it.
                                if (it.trackingState != TrackingState.TRACKING) return@collect

                                // Transform the pose from its original coordinate space to
                                // one suitable for rendering to the display.
                                val pose =
                                    it.centerPose.let { p ->
                                        session.scene.perceptionSpace.transformPoseTo(
                                            p,
                                            session.scene.activitySpace,
                                        )
                                    }

                                // This function is where you'll actually render the plane
                                // to the display.
                                renderFunction(pose, it.extents, it.vertices, it.label)
                            }
                        }
                        activePlanes[plane] = job
                    }

                    // Likewise, if a plane exists in the `activePlanes` map, but not in our
                    // `planes` list, it needs to be removed, and its corresponding job
                    // canceled.
                    for (plane in activePlanes.keys.toList()) {
                        if (planes.none { it == plane }) {
                            activePlanes.remove(plane)?.cancel()
                        }
                    }
                }
            }
        } finally {
            // cancel any coroutines still running.
            supervisor.cancel()
            activePlanes.clear()
        }
    }
}
```

| Parameters |
|---|---|
| `@https://developer.android.com/reference/androidx/annotation/NonNull https://developer.android.com/reference/androidx/xr/runtime/Session session` | the `https://developer.android.com/reference/androidx/xr/runtime/Session` to track planes from |

| Throws |
|---|---|
| `https://kotlinlang.org/api/core/kotlin-stdlib/kotlin/-illegal-state-exception/index.html` | if `https://developer.android.com/reference/androidx/xr/runtime/Session#config()` is set to `https://developer.android.com/reference/androidx/xr/runtime/PlaneTrackingMode#DISABLED()` |

### toString

```
public @NonNull String toString()
```

Returns a string representation of `https://developer.android.com/reference/androidx/xr/arcore/Plane` for debugging.

Note: Not intended for production use.