Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .vscode/settings.json
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this file shouldn't have snuck in here

Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"dart.flutterSdkPath": "/usr/local/flutter/flutter/3.38.3"
}
33 changes: 33 additions & 0 deletions lib/samples/add_building_scene_layer/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
# Add building scene layer

Add a layer to a local scene to visualize and interact with 3D building models developed using Building Information Modeling (BIM) tools.

![Image of add building scene layer](add_building_scene_layer.png)

## Use case

Building Scene Layers allow you to display and analyze detailed building models created from 3D BIM data. Unlike 3D object scene layers, which represent all features within a single layer, Building Scene Layers are organized into a hierarchy of sublayers representing individual building components such as walls, light fixtures, and mechanical systems. These sublayers are often grouped by disciplines like Architectural, Mechanical, or Structural. This structure enables deeper interaction and analysis of both interior and exterior features, providing insight into how a building is designed, used, and situated in its spatial context.

## How to use the sample

When loaded, the sample displays a scene with a Building Scene Layer. By default, the Overview sublayer is visible, showing the building's exterior shell. Use the "Full Model" toggle to switch to the Full Model sublayer, which reveals the building's components. Pan around and zoom in to observe the detailed features such as walls, light fixtures, mechanical systems, and more, both outside and inside the building.

## How it works

1. Create a local scene object with the `ArcGISScene.withBasemapStyle(BasemapStyle, SceneViewingMode)` constructor.
2. Create an `ArcGISTiledElevationSource` object and add it to the local scene's base surface.
3. Create a `BuildingSceneLayer` and add it to the local scene's operational layers.
4. Create a `ArcGISLocalSceneView` object to display the scene.
5. Set the local scene to the `ArcGISLocalSceneView`.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Steps 4 & 5 are a little weird -- the scene isn't added to the ArcGISLocalSceneView, it's added to the ArcGISLocalSceneViewController. I'm not sure if that's a little too nuanced to worry about, though.

FilterBuildingSceneLayer just has a single step to cover both:

2. Create a LocalSceneView and add the scene.


## Relevant API

* ArcGISLocalSceneView
* ArcGISScene
* ArcGISTiledElevationSource
* BuildingSceneLayer
* BuildingSublayer

## Tags

3D, buildings, elevation, layers, scene, surface
33 changes: 33 additions & 0 deletions lib/samples/add_building_scene_layer/README.metadata.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
{
"category": "Layers",
"description": "Add a layer to a local scene to visualize and interact with 3D building models developed using Building Information Modeling (BIM) tools.",
"ignore": false,
"images": [
"add_building_scene_layer.png"
],
"keywords": [
"3D",
"buildings",
"elevation",
"layers",
"scene",
"surface",
"ArcGISLocalSceneView",
"ArcGISScene",
"ArcGISTiledElevationSource",
"BuildingSceneLayer",
"BuildingSublayer"
],
"redirect_from": [],
"relevant_apis": [
"ArcGISLocalSceneView",
"ArcGISScene",
"ArcGISTiledElevationSource",
"BuildingSceneLayer",
"BuildingSublayer"
],
"snippets": [
"add_building_scene_layer.dart"
],
"title": "Add building scene layer"
}
146 changes: 146 additions & 0 deletions lib/samples/add_building_scene_layer/add_building_scene_layer.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,146 @@
// Copyright 2025 Esri
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//

import 'package:arcgis_maps/arcgis_maps.dart';
import 'package:arcgis_maps_sdk_flutter_samples/common/common.dart';
import 'package:flutter/material.dart';

class AddBuildingSceneLayer extends StatefulWidget {
const AddBuildingSceneLayer({super.key});

@override
State<AddBuildingSceneLayer> createState() => _AddBuildingSceneLayerState();
}

class _AddBuildingSceneLayerState extends State<AddBuildingSceneLayer>
with SampleStateSupport {
// Create a controller for the local scene view.
final _localSceneViewController = ArcGISLocalSceneView.createController();
// A flag for when the local scene view is ready and controls can be used.
var _ready = false;

late final BuildingSublayer _overviewSublayer;
late final BuildingSublayer _fullModelSublayer;
var _showFullModel = false;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

these three should have comments


@override
Widget build(BuildContext context) {
return Scaffold(
body: SafeArea(
top: false,
left: false,
right: false,
child: Stack(
children: [
Column(
children: [
Expanded(
// Add a map view to the widget tree and set a controller.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not a map view

child: ArcGISLocalSceneView(
controllerProvider: () => _localSceneViewController,
onLocalSceneViewReady: onLocalSceneViewReady,
),
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
// A button to perform a task.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

update comment

ElevatedButton(
onPressed: toggleModelView,
child: Text(_showFullModel ? 'Overview' : 'Full Model'),
),
],
),
],
),
// Display a progress indicator and prevent interaction until state is ready.
LoadingIndicator(visible: !_ready),
],
),
),
);
}

Future<void> onLocalSceneViewReady() async {
// Initialize the Scene.
final scene = await _initializeScene();

// Load the BuildingSceneLayer.
final buildingSceneLayer = BuildingSceneLayer.withUri(
Uri.parse(
'https://www.arcgis.com/home/item.html?id=669f6279c579486eb4a0acc7eb59d7ca',
),
);
await buildingSceneLayer.load();

// Add the BuildingSceneLayer to the Scene.
scene.operationalLayers.add(buildingSceneLayer);

// Extract the overview and full model sublayers
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

period

_overviewSublayer = buildingSceneLayer.sublayers.firstWhere(
(sublayer) => sublayer.name == 'Overview',
);
_fullModelSublayer = buildingSceneLayer.sublayers.firstWhere(
(sublayer) => sublayer.name == 'Full Model',
);

// Add the Scene to the LocalSceneViewController.
_localSceneViewController.arcGISScene = scene;

// Set an initial viewpoint camera.
final viewpointCamera = Camera.withLocation(
location: ArcGISPoint(
x: -13045109,
y: 4036614,
z: 511,
spatialReference: SpatialReference.webMercator,
),
heading: 343,
pitch: 64,
roll: 0,
);
_localSceneViewController.setViewpointCamera(viewpointCamera);

// Set the ready state variable to true to enable the sample UI.
setState(() => _ready = true);
}

Future<ArcGISScene> _initializeScene() async {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There's no awaiting going on, so this can be

ArcGISScene _initializeScene() {

// Create a Scene with a topographic basemap style.
final scene = ArcGISScene.withBasemapStyle(
BasemapStyle.arcGISTopographic,
viewingMode: SceneViewingMode.local,
);

// Add an ElevationSource to the Scene.
final elevationSource = ArcGISTiledElevationSource.withUri(
Uri.parse(
'https://elevation3d.arcgis.com/arcgis/rest/services/WorldElevation3D/Terrain3D/ImageServer',
),
);
scene.baseSurface.elevationSources.add(elevationSource);

return scene;
}

Future<void> toggleModelView() async {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

likewise

void toggleModelView() {

// Toggle the visibilities for the sublayers.
_overviewSublayer.isVisible = _showFullModel;
_fullModelSublayer.isVisible = !_showFullModel;

// Set the state for the new full model visibility.
setState(() => _showFullModel = !_showFullModel);
}
}
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading