public final class Plane implements Trackable


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

Summary

Nested types

public final class Plane.Label

A semantic description of a Plane.

public final class Plane.State implements Trackable.State

The representation of the current state of a Plane.

public final class Plane.Type

A simple summary of the normal vector of a Plane.

Public methods

@NonNull AnchorCreateResult

Creates an Anchor that is attached to this trackable, using the given initial pose in the world coordinate space.

@NonNull StateFlow<@NonNull Plane.State>

The current state of the Plane.

final @NonNull Plane.Type

The Type of the Plane.

static final @NonNull StateFlow<@NonNull Collection<@NonNull Plane>>

Emits the planes that are currently being tracked in the session.

Extension functions

final @NonNull Flowable<@NonNull Plane.State>

The current state of the Plane.

Public methods

createAnchor

public @NonNull AnchorCreateResult createAnchor(@NonNull Pose pose)

Creates an Anchor that is attached to this trackable, using the given initial pose in the world coordinate space.

getState

public @NonNull StateFlow<@NonNull Plane.StategetState()

The current state of the Plane.

import androidx.lifecycle.Lifecycle
import androidx.lifecycle.repeatOnLifecycle
import androidx.xr.arcore.Plane
import androidx.xr.runtime.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()
        }
    }
}

getType

Added in 1.0.0-alpha09
public final @NonNull Plane.Type getType()

The Type of the Plane.

subscribe

Added in 1.0.0-alpha09
public static final @NonNull StateFlow<@NonNull Collection<@NonNull Plane>> subscribe(@NonNull Session session)

Emits the planes that are currently being tracked in the session.

Only Planes that are TrackingState.TRACKING will be emitted in the Collection. Instances of the same Plane will remain between subsequent emits to the StateFlow as long as they remain tracking.

Throws
kotlin.IllegalStateException

if Session.config is set to Config.PlaneTrackingMode.DISABLED @sample androidx.xr.arcore.samples.getPlanes

Extension functions

RxJava3PlaneKt.getStateAsFlowable

public final @NonNull Flowable<@NonNull Plane.StateRxJava3PlaneKt.getStateAsFlowable(@NonNull Plane receiver)

The current state of the Plane.