How can i get buildings height?

For now, i only get error that buildings not found.

async function extractOSMBuildingsData() {
try {
// Create a tileset without adding it to the scene
const tileset = await Cesium.Cesium3DTileset.fromIonAssetId(96188);

    // Explicitly check and log the tileset
    console.log('Root tile:', tileset.root);
    console.log('Child tiles:', tileset.root.children);

    // Explicitly wait for the tileset to be ready
    await tileset.readyPromise;

    // Enhanced function to extract buildings
    function extractBuildings(tile) {
        const buildings = [];

        function processContent(content) {
            if (!content) {
                console.warn('Tile content is empty');
                return [];
            }

            const extractedBuildings = [];

            // Extended methods to extract buildings
            const extractionStrategies = [
                // Strategy 1: Using featuresLength and getFeature
                () => {
                    if (typeof content.featuresLength === 'number' && content.getFeature) {
                        console.log(`Attempting extraction via featuresLength: ${content.featuresLength}`);
                        
                        return Array.from(
                            { length: content.featuresLength }, 
                            (_, i) => {
                                try {
                                    const feature = content.getFeature(i);
                                    return processSingleFeature(feature);
                                } catch (err) {
                                    console.warn(`Error extracting feature ${i}:`, err);
                                    return null;
                                }
                            }
                        ).filter(Boolean);
                    }
                    return [];
                },
                
                // Strategy 2: Direct access to features
                () => {
                    if (Array.isArray(content.features)) {
                        console.log('Extraction via content.features');
                        return content.features
                            .map(processSingleFeature)
                            .filter(Boolean);
                    }
                    return [];
                },
                
                // Strategy 3: Extraction via geometryInstances
                () => {
                    if (Array.isArray(content.geometryInstances)) {
                        console.log('Extraction via geometryInstances');
                        return content.geometryInstances
                            .map(instance => processSingleFeature(instance))
                            .filter(Boolean);
                    }
                    return [];
                }
            ];

            // Function to process a single building
            function processSingleFeature(feature) {
                if (!feature) return null;

                // Methods to obtain height
                const heightMethods = [
                    () => feature.height,
                    () => feature.properties?.height,
                    () => feature.properties?.['building:height'],
                    () => feature.getProperty?.('height'),
                    () => feature.getProperty?.('building:height'),
                    () => feature.geometryInstances?.[0]?.attributes?.height?.componentDatatype
                ];

                const height = heightMethods.reduce(
                    (acc, method) => acc || method(), 
                    null
                );

                // Methods to obtain geometry
                const getBoundingGeometry = () => {
                    const geometryMethods = [
                        () => feature.boundingVolume,
                        () => feature.boundingBox,
                        () => feature.region,
                        () => feature.boundingVolume?.boundingBox
                    ];

                    return geometryMethods.reduce(
                        (acc, method) => acc || method(), 
                        null
                    );
                };

                const boundingGeometry = getBoundingGeometry();

                // Extended coordinate extraction
                let coordinates = null;
                if (boundingGeometry) {
                    coordinates = {
                        west: boundingGeometry.west ?? boundingGeometry.minimumX,
                        south: boundingGeometry.south ?? boundingGeometry.minimumY,
                        east: boundingGeometry.east ?? boundingGeometry.maximumX,
                        north: boundingGeometry.north ?? boundingGeometry.maximumY,
                        minimumHeight: boundingGeometry.minimumHeight,
                        maximumHeight: boundingGeometry.maximumHeight
                    };
                }

                // Logging for debugging
                if (height || coordinates) {
                    console.log('Building extracted:', { 
                        height, 
                        coordinates 
                    });
                }

                // Return the building object if any data is available
                return height || coordinates 
                    ? { height, coordinates } 
                    : null;
            }

            // Apply extraction strategies
            for (let strategy of extractionStrategies) {
                const extractedFromStrategy = strategy();
                if (extractedFromStrategy.length > 0) {
                    extractedBuildings.push(...extractedFromStrategy);
                    break;  // Successful strategy
                }
            }

            return extractedBuildings;
        }

        // Process the current tile's content
        let tileBuildings = [];
        if (tile.content) {
            tileBuildings.push(...processContent(tile.content));
        }

        // Recursively process child tiles
        if (tile.children && tile.children.length > 0) {
            tile.children.forEach(childTile => {
                tileBuildings.push(...extractBuildings(childTile));
            });
        }

        return tileBuildings;
    }

    async function loadAllTileContents(tile) {
        if (!tile) return null;

        console.log('Loading tile:', tile);

        // Check and log child tiles
        if (tile.children && tile.children.length > 0) {
            console.log('Number of child tiles:', tile.children.length);
            for (const childTile of tile.children) {
                console.log('Processing child tile');
                await loadAllTileContents(childTile);
            }
        }

        // Force content loading
        return new Promise((resolve) => {
            // If content already exists, return it immediately
            if (tile.content) {
                resolve(tile.content);
                return;
            }

            // Check for the presence of readyPromise
            if (!tile.readyPromise) {
                console.warn('Tile is missing readyPromise');
                resolve(null);
                return;
            }

            // Wait for loading with a timeout
            const loadTimeout = setTimeout(() => {
                console.warn('Tile not loaded within 5 seconds');
                resolve(null);
            }, 10000);

            // Safely handle readyPromise
            tile.readyPromise
                .then((content) => {
                    clearTimeout(loadTimeout);
                    resolve(content);
                })
                .catch((error) => {
                    clearTimeout(loadTimeout);
                    console.error('Error loading tile:', error);
                    resolve(null);
                });
        });
    }

    // Load content of all tiles
    await loadAllTileContents(tileset.root);

    // Extract buildings
    const buildings = extractBuildings(tileset.root);

    console.log('Total buildings extracted:', buildings.length);
    console.log('Sample buildings:', buildings.slice(0, 5));

    return { tileset, buildings };

} catch (error) {
    console.error('Full error in extractOSMBuildingsData:', error);
    throw error;
}

}

async function createDetailedTerrainProjection(miniViewer, viewer, buildings) {
if (!buildings || buildings.length === 0) {
console.error(‘No buildings found’);
return null;
}

const camera = miniViewer.camera;
const rectangle = camera.computeViewRectangle(viewer.scene.globe.ellipsoid);

if (!rectangle) {
    console.warn('No valid rectangle for projection');
    return null;
}

const detailedPositions = [];

// Process each building
for (const building of buildings) {
  // Get the min/max height of the building
  const { minHeight, maxHeight } = await getBuildingHeightRange(building);

  // Add points for this building considering the maximum height
  for (let i = 0; i <= 30; i++) {
    const lon = Cesium.Math.lerp(building.boundingBox.west, building.boundingBox.east, i / 30);
    const lat = Cesium.Math.lerp(building.boundingBox.south, building.boundingBox.north, i / 30);
    
    const heightOffset = 50;
    detailedPositions.push(
      Cesium.Cartesian3.fromRadians(
        lon, 
        lat, 
        maxHeight + heightOffset
      )
    );
  }
}

const planeInstance = new Cesium.GeometryInstance({
  geometry: new Cesium.PolygonGeometry({
    polygonHierarchy: new Cesium.PolygonHierarchy(detailedPositions),
    perPositionHeight: true,
    vertexFormat: Cesium.MaterialAppearance.VERTEX_FORMAT
  })
});

return planeInstance;

}

Hi @teeasy, thanks for the question.

Can you explain a little more about what goal you’re trying to achieve?

You may want to take a look at this sandcastle which shows how to style the osm buildings based on their features. Or this one for extracting information like their height Cesium Sandcastle