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;
}