Explore road cross-sections
Move a section cut along a road alignment to compare the road profile at different distances along the route.
Open in new tab
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8"><meta name="viewport" content="width=device-width,initial-scale=1">
<title>Explore road cross-sections</title>
<meta name="description" content="Move a section cut along a road alignment to compare the road profile at different distances along the route.">
<style>
html, body { height: 100%; margin: 0; }
#example-viewer-mount { position: fixed; inset: 0; }
bim-grid#ifc-viewer { display: block; position: absolute; inset: 0; width: 100%; height: 100%; min-width: 0; min-height: 0; }
.example-ui { position: fixed; z-index: 10; box-sizing: border-box; color: #253041; font: 12px/1.4 system-ui, sans-serif; }
.example-ui.example-task { right: 10px; bottom: 64px; width: 224px; max-width: calc(100vw - 64px); display: grid; gap: 6px; padding: 10px; background: #fff; border: 1px solid #dfe3e8; border-radius: 4px; box-shadow: 0 1px 5px #14203310; }
.example-ui :is(h2, p) { margin: 0; }
.example-ui h2 { font-size: 13px; line-height: 1.3; font-weight: 650; }
.example-ui p { color: #5a6575; }
.example-ui.example-credit { right: 8px; bottom: 32px; width: max-content; max-width: calc(100vw - 64px); padding: 2px 5px; background: #ffffffdf; border-radius: 2px; font-size: 9px; text-align: right; overflow-wrap: anywhere; }
.example-ui.example-credit a { color: #566171; }
@media (max-width: 600px) {
.example-ui.example-task { right: 8px; padding: 8px; }
}
</style>
<!-- generated:example-seo:start -->
<link rel="canonical" href="https://viewer.flinker.app/examples/infra_Road/index.html">
<meta name="robots" content="index,follow">
<meta property="og:title" content="Explore road cross-sections">
<meta property="og:description" content="Move a section cut along a road alignment to compare the road profile at different distances along the route.">
<meta property="og:url" content="https://viewer.flinker.app/examples/infra_Road/index.html"><meta property="og:type" content="article">
<meta property="og:site_name" content="Flinker IFC Viewer"><meta property="og:image" content="https://viewer.flinker.app/examples/infra_Road/thumbnail.webp">
<meta name="twitter:card" content="summary_large_image"><meta name="twitter:title" content="Explore road cross-sections">
<meta name="twitter:description" content="Move a section cut along a road alignment to compare the road profile at different distances along the route."><meta name="twitter:image" content="https://viewer.flinker.app/examples/infra_Road/thumbnail.webp">
<script type="application/ld+json">{"@context":"https://schema.org","@type":"TechArticle","headline":"Explore road cross-sections","description":"Move a section cut along a road alignment to compare the road profile at different distances along the route.","url":"https://viewer.flinker.app/examples/infra_Road/index.html","mainEntityOfPage":"https://viewer.flinker.app/examples/infra_Road/index.html","image":"https://viewer.flinker.app/examples/infra_Road/thumbnail.webp","inLanguage":"en","author":{"@type":"Organization","name":"Flinker","url":"https://www.flinker.app/"}}</script>
<!-- generated:example-seo:end -->
<script type="application/json" id="example-data">
{
"category": "Infrastructure",
"formats": [
"IFC"
],
"capabilities": [
"Alignments",
"Roads",
"Sections"
],
"audience": "BIM workflow",
"order": 9
}
</script>
</head>
<body>
<main id="example-viewer-mount" aria-label="Model viewer"><bim-grid id="ifc-viewer"></bim-grid></main>
<aside class="example-ui example-task" aria-label="Inspect a road cross-section">
<h2>Inspect a road cross-section</h2>
<p>Open <strong>Sections</strong> (scissors) on the left toolbar → <strong>Tracciato</strong> under Alignments. Enable <strong>Cross-section at station</strong>, then enter <strong>Station / KP (m)</strong> or use <strong>Next station</strong> to move the cut. Select a component, then click <strong>1 element selected</strong> at the top left to open <strong>Properties</strong>.</p>
</aside>
<div class="example-ui example-credit" aria-label="Sample source and license"><a href="https://github.com/buildingSMART/IFC4.x-IF/blob/75c7c7aa6c523e76a01cb4cf9542f896956fb92d/IFC-files/IFCRoad-ItalyWG/buildingSMART%20Italy_IFCRoad%20WG.zip" target="_blank" rel="noopener noreferrer">buildingSMART Italy</a> · <a href="https://github.com/buildingSMART/IFC4.x-IF/tree/75c7c7aa6c523e76a01cb4cf9542f896956fb92d/IFC-files" target="_blank" rel="noopener noreferrer">Source documentation</a></div>
<template id="example-guide">
<h2 data-example-title>Explore road cross-sections</h2>
<p data-example-description>Move a section cut along a road alignment to compare the road profile at different distances along the route.</p>
<h3>Try it</h3><ol><li>Open Sections (scissors) on the left toolbar and click Tracciato under Alignments.</li><li>Enable Cross-section at station, then enter a distance in Station / KP (m) to move the cut along the road alignment.</li><li>Use Next station or enter another distance to compare road profiles.</li></ol><h2>Developer integration</h2><p>Import the road sample with <code>viewer.add()</code>. The SDK supplies alignment navigation and sections. Chainage values refer to the source alignment.</p><p>Copy this folder and serve it over HTTP, for example <code>python -m http.server 8080</code>. Open <code>http://localhost:8080/</code>; the SDK and sample downloads require internet access.</p>
</template>
<template id="example-notices">
<h2>Sources and license notices</h2><p><a href="https://github.com/buildingSMART/IFC4.x-IF/blob/75c7c7aa6c523e76a01cb4cf9542f896956fb92d/IFC-files/IFCRoad-ItalyWG/buildingSMART%20Italy_IFCRoad%20WG.zip" target="_blank" rel="noopener noreferrer" title="buildingSMART Italy IFCRoad WG.zip">buildingSMART Italy IFCRoad working group</a></p>
<p>buildingSMART Italy IFCRoad working group, published by buildingSMART International. The archive is downloaded from the pinned upstream revision; the extracted IFC is imported unchanged. <a href="https://github.com/buildingSMART/IFC4.x-IF/tree/75c7c7aa6c523e76a01cb4cf9542f896956fb92d/IFC-files" target="_blank" rel="noopener noreferrer">Source documentation</a>. No dataset license is stated in the repository documentation.</p>
</template>
<script type="module">
// Example-only download feedback. All file parsing remains in the published SDK.
async function loadExampleFile(name, url, load = blob => viewer.add(name, blob), size = 0) {
const show = stage => viewer.setMessage(name + ': ' + stage, { type: 'loading' });
const chunks = [], chunkSize = 4 * 1024 * 1024;
let offset = 0, attempts = 0, action = 'download', type = '';
try {
await show('Downloading');
while (!size || offset < size) {
try {
const end = Math.min(offset + chunkSize, size || Infinity) - 1;
const response = await fetch(url, {
headers: { Range: 'bytes=' + offset + '-' + end },
cache: 'no-store', signal: AbortSignal.timeout(60000),
});
if (!response.ok) {
await response.body?.cancel();
// GitHub raw hides Content-Range from browser JavaScript: probe EOF.
if (response.status === 416 && offset && !size) break;
throw Object.assign(new Error('HTTP ' + response.status), { retry: [408, 429].includes(response.status) || response.status >= 500 });
}
const range = response.headers.get('content-range')?.match(/^bytes (\d+)-(\d+)\/(\d+)$/);
if (range && Number(range[1]) !== offset) throw new TypeError('Unexpected byte range');
size ||= Number(range?.[3]) || 0;
const bytes = await response.arrayBuffer();
const expected = response.status === 206 ? (size ? Math.min(chunkSize, size - offset) : 0) : size;
if (!bytes.byteLength || (expected && bytes.byteLength !== expected) || (response.status === 206 && bytes.byteLength > chunkSize))
throw new TypeError('Incomplete download at byte ' + offset);
if (response.status === 200) chunks.length = 0; // Server ignored Range.
chunks.push(bytes);
offset = response.status === 200 ? bytes.byteLength : offset + bytes.byteLength;
type = response.headers.get('content-type') || '';
attempts = 0;
if (response.status === 200) break;
await show('Downloading' + (size ? ' ' + Math.round(offset / size * 100) + '%' : ''));
}
catch (error) {
if (error.retry === false || ++attempts === 3) throw error;
await show('Retrying download');
await new Promise(resolve => setTimeout(resolve, 500 * 2 ** (attempts - 1)));
}
}
action = 'open';
const result = await load(new Blob(chunks, { type }), show);
if (result?.isError) throw new Error('The viewer could not open the file');
await viewer.setMessage(null);
return result;
}
catch (error) {
throw new Error('Could not ' + action + ' ' + name + (action === 'download' ? ' from ' + url : '') + ': ' + error.message, { cause: error });
}
}
import JSZip from "https://cdn.jsdelivr.net/npm/jszip@3.10.1/+esm";
import { Viewer } from "https://cdn.flinker.app/ifc-viewer/v4.0.3/ifc-viewer.es.js";
const viewer = new Viewer("#ifc-viewer");
window.exampleViewer = viewer;
document.body.dataset.exampleState = 'loading';
const ROAD_ZIP_URL = "https://raw.githubusercontent.com/buildingSMART/IFC4.x-IF/75c7c7aa6c523e76a01cb4cf9542f896956fb92d/IFC-files/IFCRoad-ItalyWG/buildingSMART%20Italy_IFCRoad%20WG.zip";
await viewer.ready;
try {
await loadExampleFile("buildingSMART Italy IFCRoad WG.zip", ROAD_ZIP_URL, async (blob, stage) => {
stage("Extracting archive");
const zip = await JSZip.loadAsync(await blob.arrayBuffer());
const ifcEntry = Object.values(zip.files).find(f => !f.dir && f.name.toLowerCase().endsWith(".ifc"));
if (!ifcEntry)
throw new Error("No IFC file found in the road zip archive.");
const ifcBuffer = await ifcEntry.async("uint8array");
const fileName = ifcEntry.name.split("/").pop() || "buildingSMART Italy IFCRoad WG.ifc";
await stage("Opening file");
return await viewer.add(fileName, ifcBuffer);
});
document.body.dataset.exampleState = 'loaded';
}
catch (error) {
document.body.dataset.exampleState = 'error';
await viewer.setMessage(error instanceof Error ? error.message : String(error), { type: 'error' });
}
</script>
</body>
</html>
How it works
Try it
- Open Sections (scissors) on the left toolbar and click Tracciato under Alignments.
- Enable Cross-section at station, then enter a distance in Station / KP (m) to move the cut along the road alignment.
- Use Next station or enter another distance to compare road profiles.
Developer integration
Import the road sample with viewer.add(). The SDK supplies alignment navigation and sections. Chainage values refer to the source alignment.
Copy this folder and serve it over HTTP, for example python -m http.server 8080. Open http://localhost:8080/; the SDK and sample downloads require internet access.
Sources and license notices
buildingSMART Italy IFCRoad working group
buildingSMART Italy IFCRoad working group, published by buildingSMART International. The archive is downloaded from the pinned upstream revision; the extracted IFC is imported unchanged. Source documentation. No dataset license is stated in the repository documentation.