@tileflow/dev 0.1.0-alpha.38 → 0.1.0-alpha.39
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +9 -21
- package/dist/artifacts.js +4 -4
- package/dist/{chunk-MRFNAWWR.js → chunk-AVJMTXW5.js} +57 -22
- package/dist/{chunk-54VM4SNV.js → chunk-C4VPHZ3F.js} +1 -1
- package/dist/{chunk-UTRO4IBQ.js → chunk-FOMTSCOP.js} +1 -1
- package/dist/{chunk-7C4F6GAX.js → chunk-RTU7TD4M.js} +4 -2
- package/dist/fonts.js +2 -2
- package/dist/icons.js +2 -2
- package/dist/preview.js +4 -2
- package/dist/server.js +4 -4
- package/package.json +4 -5
- package/docs/artifact-lifecycle.md +0 -152
- package/docs/beacon-map-audits.md +0 -145
- package/docs/bounded-pmtiles-resource-inspection.md +0 -21
- package/docs/bounded-vector-feature-inspection.md +0 -99
- package/docs/building-models.md +0 -218
- package/docs/layers-inspection.md +0 -92
- package/docs/local-comparison-workbench-and-compiler-inspection.md +0 -130
- package/docs/map-design-diagnostics.md +0 -76
- package/docs/native-artifacts.md +0 -287
- package/docs/native-icons.md +0 -129
- package/docs/structured-config-inspection-and-diagnostics.md +0 -39
|
@@ -1,145 +0,0 @@
|
|
|
1
|
-
# Beacon map audits (legacy)
|
|
2
|
-
|
|
3
|
-
The Beacon scoring and tour interface has been replaced by **Diagnostics**. See
|
|
4
|
-
[Map design diagnostics](./map-design-diagnostics.md) for the current workflow. This document
|
|
5
|
-
describes historical audit reports; its scores are not comparable with Diagnostics findings.
|
|
6
|
-
|
|
7
|
-
Open `tileflow preview`, select **Beacon**, choose **Desktop** or **Mobile** and
|
|
8
|
-
**Active tour** (default), **Quick check** or **All zooms**, then **Run audit**. The report includes 48 checks grouped into Rendering (9), Loading
|
|
9
|
-
(8), Legibility (8), Accessibility (8), Cartography (7) and Integrity (8). Expand a result for its
|
|
10
|
-
measured value, target, evidence and suggested fix. Findings open Layers, Tiles or Debug. **Copy
|
|
11
|
-
context for agent** copies the bounded report; it does not upload it.
|
|
12
|
-
|
|
13
|
-
## Scope and restoration
|
|
14
|
-
|
|
15
|
-
Active tour follows a deterministic route through the current view, London, New York, Tokyo,
|
|
16
|
-
Nairobi and São Paulo. Each location has an overview and a detailed view, with zoom, bearing and
|
|
17
|
-
pitch changes within the map's camera limits. Destinations outside explicit map bounds are skipped
|
|
18
|
-
and listed in coverage. The current theme stays active; this route does not cover every theme.
|
|
19
|
-
|
|
20
|
-
The tour has a 60-second budget: up to 55 seconds for navigation and sampling, with the remainder
|
|
21
|
-
reserved for diagnostics. Each stop measures a 1.2-second flight, waits up to two seconds for tiles,
|
|
22
|
-
then samples up to 2.4 seconds of continuous settled repaints. On a responsive map the run usually
|
|
23
|
-
takes 45–60 seconds. Slow loading can exhaust the budget: remaining views are explicitly unmeasured,
|
|
24
|
-
not passed. Synchronous analysis and restoration may add a small overhead. Reduced-motion settings
|
|
25
|
-
replace flights with jumps; the report does not claim an animated navigation measurement then.
|
|
26
|
-
|
|
27
|
-
**Tour measurements** lists the actual camera, moving/settled p95 frame intervals, sample counts,
|
|
28
|
-
remaining tile wait after navigation, and total readiness including navigation for each view.
|
|
29
|
-
Loading scores use the remaining wait, excluding scripted animation; any timed-out view fails
|
|
30
|
-
readiness. A p95 requires at least 30 intervals; coverage flags fewer than 60 settled
|
|
31
|
-
intervals. A view that did not finish loading before sampling receives no settled performance score.
|
|
32
|
-
The rendering check uses the worst qualifying per-view p95, so a slow location is not hidden by an
|
|
33
|
-
average across fast locations. Long stalls are retained. These measurements include browser
|
|
34
|
-
scheduling and other work on the machine, rather than isolated GPU execution time.
|
|
35
|
-
|
|
36
|
-
Quick check samples the current camera and concrete theme for about three seconds. It is useful
|
|
37
|
-
for static style checks and a short settled rendering sample. All zooms visits each integer zoom
|
|
38
|
-
from 0 through 22 within map limits at the same geographic centre, for every registered theme and
|
|
39
|
-
time-of-day variant. It waits up to five seconds for readiness and samples 150 ms per view. This
|
|
40
|
-
exhaustive scope can take several minutes; it is not the one-minute navigation benchmark. Use
|
|
41
|
-
**New audit** from a result to change scope or viewport.
|
|
42
|
-
|
|
43
|
-
Desktop uses an actual 1280×800 CSS iframe viewport; Mobile uses 390×844. The iframe is scaled to
|
|
44
|
-
fit the workspace. CPU, GPU and network are those of the current computer: this is not phone
|
|
45
|
-
hardware emulation. No cache clearing, network throttling or cold navigation occurs.
|
|
46
|
-
|
|
47
|
-
Camera, viewport, pixel ratio, overlays and scene are restored after completion or cancellation.
|
|
48
|
-
Moving the map interrupts the audit and keeps the user's camera. Leaving Beacon cancels the run.
|
|
49
|
-
A map replacement invalidates the run. Reports and preview changes stay local and in memory.
|
|
50
|
-
|
|
51
|
-
## Measurements and limits
|
|
52
|
-
|
|
53
|
-
- **Rendering:** inter-render p95 during continuous repaints (moving and settled windows for Active tour), native overdraw samples (saturating at
|
|
54
|
-
8 passes), eligible layer count, intercepted WebGL draw calls, CPU placement time, data-driven
|
|
55
|
-
paint-rule count, custom-renderer CPU submission time, and an observable GPU allocation estimate.
|
|
56
|
-
CPU submission is not GPU execution time. Readbacks and feature inspection are outside the frame
|
|
57
|
-
sample. GPU memory excludes inaccessible allocations; a low estimate is informational.
|
|
58
|
-
- **Loading:** unused source-layer MVT message bytes, original map-load event time, individual tile
|
|
59
|
-
sizes when exposed, view readiness, per-view transfer and request counts, compression and cache
|
|
60
|
-
observations. PMTiles archive ranges are not individual tile sizes. Resource Timing cannot prove
|
|
61
|
-
Cache-Control policy. Cached audit views are not a fresh visitor estimate.
|
|
62
|
-
- **Legibility:** observed text-placement rejections, line-label candidates, nearby repeated label
|
|
63
|
-
anchors, a scored text-size budget, approximate density, halos, configured line curvature and
|
|
64
|
-
requested language-field coverage. Rejections can result from collisions, offscreen placement or
|
|
65
|
-
line fit; the report does not pretend to know the renderer's exact rejection cause.
|
|
66
|
-
- **Accessibility:** sampled text contrast in current/night/other themes, color-vision simulation
|
|
67
|
-
heuristics, static non-text contrast, categorical color-only rules, the system motion preference,
|
|
68
|
-
and sampled label retention after temporarily setting the real canvas ratio to 3×. Contrast uses
|
|
69
|
-
evaluated colors and supported flat fill/halo backgrounds. Raster, 3D and unresolved backgrounds
|
|
70
|
-
are excluded. This is diagnostic evidence, not accessibility certification.
|
|
71
|
-
- **Cartography:** enabled zoom-range gaps, potential abrupt layer entry, road and place hierarchy
|
|
72
|
-
heuristics, scored size-rule continuity, unchanged eligible-layer counts and sampled fill coverage.
|
|
73
|
-
Naming-based hierarchy checks explicitly identify their inferred roles and exclude unmatched IDs.
|
|
74
|
-
- **Integrity:** missing icon references, actual theme coverage, hidden-layer source residency,
|
|
75
|
-
cached missing glyphs, unresolved expressions, locally unmatched filters, style-spec validation
|
|
76
|
-
and retained runtime/resource errors. Resident data is bounded; zero local matches does not mean
|
|
77
|
-
a filter never matches globally.
|
|
78
|
-
|
|
79
|
-
Samples are bounded to 4,000 rendered query results, 100 labels and 64 resident vector tiles per
|
|
80
|
-
view; feature expression checks use up to 24 candidates spread across the bounded source sample per
|
|
81
|
-
layer. Filter evidence counts only the candidates actually evaluated. Geometry is discarded after
|
|
82
|
-
observation. All-zoom style snapshots are shared per theme. Custom renderer and private MapLibre
|
|
83
|
-
observations are version-isolated and can be unavailable on unsupported renderers.
|
|
84
|
-
|
|
85
|
-
## Scores and useful comparisons
|
|
86
|
-
|
|
87
|
-
Category scores average checks with a measured score. Overall score averages measured categories.
|
|
88
|
-
Informational and unavailable checks are excluded. Legibility and Cartography show a numeric score
|
|
89
|
-
when eligible samples exist, together with the specific score basis and sample count. Each currently
|
|
90
|
-
has one scored benchmark; its other checks remain diagnostic. Their scores do not assess the entire
|
|
91
|
-
visual quality of a map.
|
|
92
|
-
A category with no measurable scores shows **—**. For numeric
|
|
93
|
-
budgets, meeting the displayed target scores 100; exceeding it by up to 1.5× scores 70, by up to 2×
|
|
94
|
-
scores 45, and beyond that scores 0. Minimum targets invert the ratio. Structural counts and cartographic heuristics are explicitly marked **Diagnostic · not scored**.
|
|
95
|
-
These include expression counts, rejected candidates, localized name fields, halos, fill coverage
|
|
96
|
-
and locally unmatched filters. They remain visible as evidence without asserting a defect.
|
|
97
|
-
Error scoring includes only resources and runtime errors observed during the audit, not prior session failures. A high score does not establish global map quality.
|
|
98
|
-
|
|
99
|
-
The two quality benchmarks use an explicit percentage, rather than the generic budget tiers:
|
|
100
|
-
|
|
101
|
-
- **Legibility / Text-size budget:** percentage of sampled labels whose evaluated `text-size` is
|
|
102
|
-
at least 10 CSS px. The threshold is a design budget, not an accessibility standard.
|
|
103
|
-
The bounded sample rotates between rendered symbol layers so dense POI layers do not monopolize it.
|
|
104
|
-
Font metrics, formatted section scaling, script, perspective and final glyph rasterization are not measured.
|
|
105
|
-
Unresolved expressions are excluded; their renderer fallback does not count as a passing size.
|
|
106
|
-
- **Cartography / Size-rule continuity:** percentage of sampled layer/view size rules without a
|
|
107
|
-
jump exceeding both 1 px and 25% of the smaller size (with a 1 px denominator floor). For line
|
|
108
|
-
width, text size and circle radius, evaluate immediately around the actual zoom stops at
|
|
109
|
-
`stop ± 0.0001`, within the layer and camera zoom bounds. Continuous interpolation and physical
|
|
110
|
-
width scaling pass, even when sizes double between integer zooms. Changes at layer entry/exit,
|
|
111
|
-
filtered-out features and stops with opacity at or below 1% on either side are excluded.
|
|
112
|
-
Each ready view checks up to 128 visible layers, four feature contexts per layer and 128 stops
|
|
113
|
-
per rule. Missing or oversized evaluations are excluded. This measures authored rule continuity,
|
|
114
|
-
not final GPU pixels, label placement or transition animations. Intentional steps can exceed
|
|
115
|
-
the budget and should be reviewed before changing them.
|
|
116
|
-
|
|
117
|
-
Only views that finished loading contribute to these scores. Each check exports `sample` with
|
|
118
|
-
`passed`, `total`, `skipped` and `unit`; category `scoreBasis` identifies what its number represents.
|
|
119
|
-
An observed outlier remains a warning even when rounding produces a high percentage. Findings
|
|
120
|
-
include the layer and camera, with the exact zoom stop for a size jump. No eligible samples means
|
|
121
|
-
unavailable, never an automatic 100. Repeated features in different views are separate observations.
|
|
122
|
-
|
|
123
|
-
Repeat with the same view, scope, device, cache conditions and browser load when comparing changes.
|
|
124
|
-
Review the evidence before acting on a warning. Copying findings supplies an agent with concrete
|
|
125
|
-
layer IDs, camera context, measured values, coverage limits and suggested investigation steps.
|
|
126
|
-
|
|
127
|
-
## Reproducible reports and future automation
|
|
128
|
-
|
|
129
|
-
Reports use `version: 4`, `scoring: "measured-evidence-v3"` and identify the deterministic tour as `protocol: "active-tour-v1"`.
|
|
130
|
-
Scenarios carry stable IDs, location, actual camera, theme, frame sample counts, p95, long-frame
|
|
131
|
-
fraction, maximum frame interval, `tileWaitMs` after navigation, end-to-end `readyMs` and observed
|
|
132
|
-
network transfer. Policy v2 excludes scripted camera time from loading scores; v1 included it.
|
|
133
|
-
Policy v3 adds the sampled text-size and rule-continuity benchmarks described above; v2 left both
|
|
134
|
-
categories entirely diagnostic. Old reports retain their original scores and must be rerun to use v3.
|
|
135
|
-
`plannedViews` and
|
|
136
|
-
`budgetExhausted` distinguish completed coverage from a partial run. Camera, viewport, DPR, duration
|
|
137
|
-
and warnings accompany the scores. Change the protocol identifier when its itinerary or sampling
|
|
138
|
-
rules change. The scoring policy is versioned separately: do not compare aggregate scores across
|
|
139
|
-
policies. The original Active tour itinerary, timing windows and thresholds for measured frame
|
|
140
|
-
performance are unchanged. There is no CI runner or GitHub integration in this feature.
|
|
141
|
-
|
|
142
|
-
For future comparisons, keep protocol, map revision, initial view, browser/device, viewport, theme,
|
|
143
|
-
DPR and cache conditions fixed. A single one-minute run is a diagnostic sample; repeated runs on a
|
|
144
|
-
controlled worker are needed before setting regression gates. The tour does not clear caches,
|
|
145
|
-
emulate mobile hardware, or prove worldwide coverage from six locations.
|
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
# Bounded PMTiles resource inspection
|
|
2
|
-
|
|
3
|
-
Start with the [@tileflow/dev guide](https://github.com/tileflow/tileflow-sdk/blob/main/packages/dev/README.md) for installation and a complete first example.
|
|
4
|
-
|
|
5
|
-
Node tooling can inspect one local PMTiles archive without reading it completely:
|
|
6
|
-
|
|
7
|
-
```ts
|
|
8
|
-
import {inspectTileflowPmtiles} from '@tileflow/dev/tilesets';
|
|
9
|
-
|
|
10
|
-
const inspection = await inspectTileflowPmtiles('./data/stores.pmtiles', {
|
|
11
|
-
includeValues: ['category', 'status'],
|
|
12
|
-
});
|
|
13
|
-
```
|
|
14
|
-
|
|
15
|
-
Inspection schema 1 separates the authoritative PMTiles header and TileJSON `vector_layers` metadata
|
|
16
|
-
from deterministic bounded MVT observations. Each sampled field reports present/missing feature
|
|
17
|
-
counts, observed primitive types, capped distinct-value cardinality, numeric min/max, and explicit
|
|
18
|
-
truncation. Values are returned only for requested portable field names, with at most 32 requested
|
|
19
|
-
fields, 16 values per field, and 256 characters per string. Sampling reads at most eight tiles,
|
|
20
|
-
20,000 features, or 24 MB of tile data; `sample: false` returns only authoritative metadata and does
|
|
21
|
-
not accept `includeValues`.
|
|
@@ -1,99 +0,0 @@
|
|
|
1
|
-
# Bounded vector-feature inspection
|
|
2
|
-
|
|
3
|
-
Start with the [@tileflow/dev guide](https://github.com/tileflow/tileflow-sdk/blob/main/packages/dev/README.md) for installation and a complete first example.
|
|
4
|
-
|
|
5
|
-
Custom Node tooling can inspect only the features visible near a configured camera without opening
|
|
6
|
-
a browser:
|
|
7
|
-
|
|
8
|
-
```ts
|
|
9
|
-
import {inspectTileflowFeatures} from '@tileflow/dev/inspect';
|
|
10
|
-
|
|
11
|
-
const internalCatalog = artifacts.project;
|
|
12
|
-
const inspection = await inspectTileflowFeatures(internalCatalog, 'madrid', {
|
|
13
|
-
center: [-3.6927512, 40.4086555],
|
|
14
|
-
zoom: 16,
|
|
15
|
-
sourceLayers: ['poi'],
|
|
16
|
-
properties: ['name', 'category', 'type', 'icon', 'filter_rank', 'size_rank'],
|
|
17
|
-
width: 512,
|
|
18
|
-
height: 512,
|
|
19
|
-
limit: 100,
|
|
20
|
-
});
|
|
21
|
-
```
|
|
22
|
-
|
|
23
|
-
The inspector supports ordinary HTTP(S) vector sources and TileJSON. It bounds viewport, tile
|
|
24
|
-
count, individual/total bytes, scanned and returned features, property count/string lengths, and
|
|
25
|
-
request time; results are deduplicated and sorted deterministically. Output contains projected
|
|
26
|
-
properties, geometry summaries, safe origin/path metadata, and the configured source revision or
|
|
27
|
-
`null`. It never emits URL queries, credentials, hidden properties, response bodies, or absolute
|
|
28
|
-
paths. PMTiles and authenticated provider adapters are not currently supported by this primitive.
|
|
29
|
-
|
|
30
|
-
Deployment adapters can compile the same sources without writing them to disk:
|
|
31
|
-
|
|
32
|
-
```ts
|
|
33
|
-
import {compileTileflowIconPackages} from '@tileflow/dev/icons';
|
|
34
|
-
|
|
35
|
-
const internalCatalog = artifacts.project;
|
|
36
|
-
const result = await compileTileflowIconPackages(internalCatalog, {
|
|
37
|
-
cwd: process.cwd(),
|
|
38
|
-
target: 'hosted',
|
|
39
|
-
});
|
|
40
|
-
```
|
|
41
|
-
|
|
42
|
-
Streets declares `[streetsIcons]` and keeps light/dark image-token targets in that one closure.
|
|
43
|
-
Baedeker, Cívica, 1777, Siegfried, Soundings, and Blueprint declare only
|
|
44
|
-
`[baedekerIcons]`, `[civicaIcons]`, `[map1777Icons]`, `[siegfriedIcons]`,
|
|
45
|
-
`[soundingsIcons]`, and `[blueprintIcons]`, respectively. No official root composes another map's assets even though all
|
|
46
|
-
use the semantic compiler ABI. Baedeker's directory contains eight original travel-atlas patterns;
|
|
47
|
-
its browser-derived Mapterhorn contours use runtime terrain tiles and are not part of the icon
|
|
48
|
-
package. Soundings owns twenty-seven original nautical symbols and
|
|
49
|
-
patterns. Blueprint owns four technical blueprint patterns and one schematic POI node; its
|
|
50
|
-
unbundled Mapterhorn contours remain runtime terrain, and its text uses the canonical Noto Sans
|
|
51
|
-
glyph provider. An application map may inherit a root's exact array, replace it, clear it with `[]`,
|
|
52
|
-
or compose it explicitly with a spread.
|
|
53
|
-
`modules.poi.icons: false` or a disabled POI module suppresses POI icon layers without moving asset
|
|
54
|
-
ownership into dev. POI density is the numeric producer threshold 1–5; it is not an asset-provider
|
|
55
|
-
preset.
|
|
56
|
-
|
|
57
|
-
The hosted target enforces repository containment, portable icon IDs, safe SVG
|
|
58
|
-
references, deterministic ordering, and the public package limits. Package-owned directories are
|
|
59
|
-
trusted only inside their declared owning package and are exempt from config working-tree
|
|
60
|
-
containment. It returns deduplicated generated files plus a canonical manifest/content hash. Upload
|
|
61
|
-
only those generated files: source icons and absolute paths remain local.
|
|
62
|
-
|
|
63
|
-
The version-1 manifest includes `renderedIcons` in the exact sorted `iconNames` order. Each entry
|
|
64
|
-
contains SHA-256 digests for the normalized 1x and 2x RGBA cell. The digest framing includes its
|
|
65
|
-
density and dimensions, zeroes RGB only where alpha is zero, and excludes filenames/source bytes.
|
|
66
|
-
The package content hash still covers the complete canonical manifest, including all four encoded
|
|
67
|
-
file hashes. Consumers can therefore distinguish a visible per-icon change from an atlas-layout or
|
|
68
|
-
encoding-only package change without receiving the original SVG/raster file.
|
|
69
|
-
|
|
70
|
-
`compileTileflowIconPackages` retains the exact RGBA cells used to assemble each atlas, so its
|
|
71
|
-
pixel digests describe delivered pixels rather than a second render. Hosted upload services must
|
|
72
|
-
decode the submitted PNGs and reconstruct those digests independently; client-authored manifest
|
|
73
|
-
analysis is not authoritative.
|
|
74
|
-
|
|
75
|
-
Custom Node tooling can inspect the same local pipeline without walking or decoding source files a
|
|
76
|
-
second time:
|
|
77
|
-
|
|
78
|
-
```ts
|
|
79
|
-
import {inspectTileflowIconCatalogs} from '@tileflow/dev/icons';
|
|
80
|
-
|
|
81
|
-
const internalCatalog = artifacts.project;
|
|
82
|
-
const inspection = await inspectTileflowIconCatalogs(internalCatalog, {
|
|
83
|
-
cwd: process.cwd(),
|
|
84
|
-
mapNames: ['madrid'],
|
|
85
|
-
});
|
|
86
|
-
```
|
|
87
|
-
|
|
88
|
-
The result keeps one catalog per distinct ordered directory composition, the exact winning source
|
|
89
|
-
for every final ID, explicit same-ID replacements, config-relative source metadata, exact atlas rectangles,
|
|
90
|
-
both manifest pixel digests, and the shared compiled package. `icons: []` is represented as an
|
|
91
|
-
absent catalog. This is a local-authoring integration surface: use the hosted compilation target
|
|
92
|
-
separately for deployment compatibility, and project only the metadata needed by an external
|
|
93
|
-
protocol rather than serializing generated byte arrays accidentally.
|
|
94
|
-
|
|
95
|
-
This package is public, but it is an integration layer. Styling primitives live in
|
|
96
|
-
`@tileflow/core`, official maps and their source assets live in `@tileflow/maps`, and React
|
|
97
|
-
rendering lives in `@tileflow/react`.
|
|
98
|
-
|
|
99
|
-
Docs: https://tileflow.dev/docs
|
package/docs/building-models.md
DELETED
|
@@ -1,218 +0,0 @@
|
|
|
1
|
-
# Prepare recolorable building models
|
|
2
|
-
|
|
3
|
-
Custom buildings and landmarks use the same preparation path. Export uncompressed glTF 2.0
|
|
4
|
-
binaries in metres, Y up, with the origin on the ground. The default scene's triangles and node
|
|
5
|
-
transforms are read. Building preparation retains physical materials and embedded PNG/JPEG
|
|
6
|
-
textures. Animations, skins and morph targets are not evaluated; export their static geometry.
|
|
7
|
-
|
|
8
|
-
## Separate colour from architectural role
|
|
9
|
-
|
|
10
|
-
A material's name is the part it belongs to: an architectural part, `surface`, `secondary`,
|
|
11
|
-
`glass`, `accent` or `roof`, or a part of the model's own, such as `water`, `vegetation`, `wood` or
|
|
12
|
-
`stone`. Names are lower-case words joined by hyphens or underscores, at most 32 characters, and a
|
|
13
|
-
level names at most 16 parts; materials of the same part share its name. The map colours a part
|
|
14
|
-
through `buildings.threeDimensional.modelColors` under its name; a part it does not colour keeps
|
|
15
|
-
its material's colour. Name pools `water`, planting `vegetation` and timber `wood` where they fit:
|
|
16
|
-
Streets colours these from its water and tree colours in every theme. A GLB whose materials name
|
|
17
|
-
only `bark`, `leaves`, `fronds` or `stem` is a tree model, not a building model.
|
|
18
|
-
|
|
19
|
-
The optional `material.extras.tileflow.lightingRole` selects lighting independently:
|
|
20
|
-
|
|
21
|
-
```json
|
|
22
|
-
{
|
|
23
|
-
"name": "accent",
|
|
24
|
-
"extras": {
|
|
25
|
-
"tileflow": {
|
|
26
|
-
"lightingRole": "door"
|
|
27
|
-
}
|
|
28
|
-
},
|
|
29
|
-
"pbrMetallicRoughness": {
|
|
30
|
-
"baseColorFactor": [0.8, 0.8, 0.8, 1]
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
```
|
|
34
|
-
|
|
35
|
-
This door can take the map's `accent` colour while receiving its `door` lighting profile. Accepted
|
|
36
|
-
roles are `unclassified`, `wall`, `door`, `roof`, `window`, `lamp` and `logo`. A role describes
|
|
37
|
-
geometry; it does not turn on light by itself. The map supplies emission through
|
|
38
|
-
`buildings.threeDimensional.modelLighting`.
|
|
39
|
-
|
|
40
|
-
A material without an explicit role takes its part's default:
|
|
41
|
-
|
|
42
|
-
| Part | Lighting role |
|
|
43
|
-
| -------------------------------- | -------------- |
|
|
44
|
-
| `surface`, `secondary`, `accent` | `wall` |
|
|
45
|
-
| `glass` | `window` |
|
|
46
|
-
| `roof` | `roof` |
|
|
47
|
-
| Any other part | `unclassified` |
|
|
48
|
-
|
|
49
|
-
A part names a colour, not a material: physical properties and emission remain controlled by the
|
|
50
|
-
authored material and its independent lighting role.
|
|
51
|
-
|
|
52
|
-
Doors, lamps and logos require an explicit role. Use `unclassified` for a part that must not inherit
|
|
53
|
-
a role. Invalid role names fail preparation. An exporter's numeric material suffix, such as
|
|
54
|
-
`surface.001`, is ignored.
|
|
55
|
-
|
|
56
|
-
Keep a stone relief in a wall role when it should receive the wall's lighting. A part of its own,
|
|
57
|
-
such as `stone`, can distinguish its colour without creating a separate light source. Mark roof geometry as
|
|
58
|
-
roof even when it shares a colour with a facade.
|
|
59
|
-
|
|
60
|
-
## Physical materials
|
|
61
|
-
|
|
62
|
-
The importer retains these glTF 2.0 channels independently of part and role:
|
|
63
|
-
|
|
64
|
-
| Channel | Inputs |
|
|
65
|
-
| ------------------ | --------------------------------------------------------------------------------- |
|
|
66
|
-
| Base colour | Linear `baseColorFactor`, linear `COLOR_0` RGB/RGBA, sRGB base-colour texture |
|
|
67
|
-
| Reflection | `metallicFactor`, `roughnessFactor`, texture blue/green channels |
|
|
68
|
-
| Surface normal | Tangent-space normal texture and `scale`; tangent basis from geometry and UVs |
|
|
69
|
-
| Ambient visibility | Occlusion texture red channel and `strength`, multiplied by geometric visibility |
|
|
70
|
-
| Emission | Linear `emissiveFactor`, sRGB emissive texture, `KHR_materials_emissive_strength` |
|
|
71
|
-
| Coverage | `OPAQUE`, `MASK` with `alphaCutoff`, or `BLEND`; `doubleSided` |
|
|
72
|
-
| Unlit | `KHR_materials_unlit` |
|
|
73
|
-
|
|
74
|
-
`TEXCOORD_0`, `TEXCOORD_1`, glTF sampler wrapping/filtering and `KHR_texture_transform` are retained.
|
|
75
|
-
`TEXCOORD_1` must lie between zero and one, since prepared files store it with sixteen bits.
|
|
76
|
-
Every referenced channel must have its declared UV set. UV and colour seams survive welding.
|
|
77
|
-
Colour textures and lit output use the scene's gamma-2.2 transfer approximation.
|
|
78
|
-
Role emission mixes the complete material radiance toward its target, including authored emission.
|
|
79
|
-
Images must be embedded in buffer views or PNG/JPEG data URIs; preparation never fetches external
|
|
80
|
-
images. Other image formats and physical-material extensions are not supported.
|
|
81
|
-
|
|
82
|
-
Each level accepts at most 256 distinct materials, 32 textures, 4096 pixels per image dimension
|
|
83
|
-
and 16,777,216 decoded image pixels in total. The complete prepared file remains limited to 16 MiB.
|
|
84
|
-
Invalid references, missing UVs and image headers that disagree with their dimensions fail preparation.
|
|
85
|
-
|
|
86
|
-
Without overrides, a physical model retains its authored material. `modelLighting` can tint and
|
|
87
|
-
override roughness/metallicity by role. Explicit `modelColors` take precedence over role tints;
|
|
88
|
-
textures and vertex colours still modulate the chosen colour. Keep vertex colours neutral when
|
|
89
|
-
they should not affect recolouring.
|
|
90
|
-
|
|
91
|
-
Colour and normal textures, metallic reflection and alpha coverage use the browser's physical
|
|
92
|
-
model path. Ambient visibility never attenuates solar light or emission. Masked pixels also leave
|
|
93
|
-
holes in dynamic solar shadows; blended surfaces cast an alpha-tested shadow at 0.5. Transparent
|
|
94
|
-
material ranges draw back to front after opaque surfaces; intersecting transparent triangles are
|
|
95
|
-
not sorted individually.
|
|
96
|
-
|
|
97
|
-
## Explicit area emitters
|
|
98
|
-
|
|
99
|
-
A `door` role lights the surface. To project its spill, declare a rectangle in
|
|
100
|
-
`node.extras.tileflow.emitters`. This glTF fragment uses node-local metres and Y up:
|
|
101
|
-
|
|
102
|
-
```json
|
|
103
|
-
{
|
|
104
|
-
"extras": {
|
|
105
|
-
"tileflow": {
|
|
106
|
-
"emitters": [
|
|
107
|
-
{
|
|
108
|
-
"start": [-1, 0, 0],
|
|
109
|
-
"end": [1, 0, 0],
|
|
110
|
-
"height": 3,
|
|
111
|
-
"depth": 0.2,
|
|
112
|
-
"role": "door",
|
|
113
|
-
"part": "accent"
|
|
114
|
-
}
|
|
115
|
-
]
|
|
116
|
-
}
|
|
117
|
-
}
|
|
118
|
-
}
|
|
119
|
-
```
|
|
120
|
-
|
|
121
|
-
`start` and `end` form the horizontal lower edge. The spill faces the right of that edge when
|
|
122
|
-
viewed from above. `height` sets the rectangle's height; optional `depth` narrows the spill around
|
|
123
|
-
recessed jambs. Node transforms apply to the emitter. Its role supplies emission and its part, by name,
|
|
124
|
-
supplies the fallback colour. No emitter is inferred from material colour or geometry.
|
|
125
|
-
|
|
126
|
-
Each level accepts 128 emitters. Each projects a four-triangle, depth-tested spill with reach
|
|
127
|
-
`clamp(1.3 * height, 4, 10)` metres. This authored effect does not cast a new light or shadow onto
|
|
128
|
-
other meshes. It follows the model's visibility and theme; zero emission removes it.
|
|
129
|
-
|
|
130
|
-
## Ambient visibility
|
|
131
|
-
|
|
132
|
-
Preparation estimates local ambient visibility with deterministic, cosine-weighted hemisphere
|
|
133
|
-
samples, a two-metre reach and a two-millimetre origin bias. A spatial hierarchy limits
|
|
134
|
-
intersection work. Nearby occluders contribute more than distant ones. Each level is prepared
|
|
135
|
-
independently, including occlusion between its distinct primitives. Footprint meshes do not
|
|
136
|
-
occlude.
|
|
137
|
-
|
|
138
|
-
The near and mid levels carry visibility in an occlusion texture. Preparation lays the level's
|
|
139
|
-
triangles flat in one atlas: connected triangles facing within 20 degrees of each other share a
|
|
140
|
-
chart, curved strips are cut where they would waste their rectangle, and charts under two texels
|
|
141
|
-
share a palette of uniform grey texels. Shade detail grows with the square root of the level's
|
|
142
|
-
surface: about 89·A^0.54 texels of visible shade for A square metres, so a large building takes
|
|
143
|
-
coarser shade per metre than a small one. The near level's atlas budget allows for packing and
|
|
144
|
-
has two floors: 65,536 texels, so small detailed buildings keep their mouldings distinct, and
|
|
145
|
-
1.3 texels a metre, so towers keep each storey's mullions and slabs apart. It takes at most
|
|
146
|
-
524,288 texels; the mid level takes a quarter of it. The density is the highest at which
|
|
147
|
-
the atlas fits its budget. Each texel averages four points inside it, 12 rays each with turned
|
|
148
|
-
patterns; points hidden just behind other surfaces are skipped. The atlas is a greyscale JPEG of
|
|
149
|
-
quality 35, about a tenth of a byte a texel, on the second UV set, and becomes
|
|
150
|
-
every material's occlusion texture. Vertices are split where charts meet; triangles keep their
|
|
151
|
-
order.
|
|
152
|
-
|
|
153
|
-
Contact shade therefore follows the surface instead of spreading between distant vertices. A
|
|
154
|
-
level whose materials already use an occlusion texture or the second UV set, or whose charts
|
|
155
|
-
cannot fit the budget, and the far level keep 48-sample visibility on their vertices.
|
|
156
|
-
|
|
157
|
-
The result travels independently of colour. Do not bake ambient occlusion into `COLOR_0`: colour
|
|
158
|
-
also affects direct sunlight and emission. The runtime applies prepared visibility only to the
|
|
159
|
-
ambient contribution; solar visibility still comes from the dynamic shadow map.
|
|
160
|
-
|
|
161
|
-
`threeDimensional.modelOcclusion` controls strength from zero to one and defaults to `0.75`.
|
|
162
|
-
`threeDimensional.occlusion: false` also disables model ambient occlusion. Changing these
|
|
163
|
-
runtime controls does not prepare the geometry again.
|
|
164
|
-
|
|
165
|
-
Preparation cost grows with texels, rays and nearby geometry; a large landmark's near level takes
|
|
166
|
-
seconds to tens of seconds. It is paid when a raw model is prepared, never per frame. A texture
|
|
167
|
-
used only for occlusion is uploaded with one channel, at most 0.7 MB with mipmaps for a near level.
|
|
168
|
-
Visibility describes opaque geometry at rest; it does not follow moving parts, other models, the
|
|
169
|
-
ground or surrounding buildings.
|
|
170
|
-
|
|
171
|
-
## Files and compatibility
|
|
172
|
-
|
|
173
|
-
Use `<id>.glb`, optionally `<id>.mid.glb` and `<id>.far.glb`. A mesh whose material is `footprint`
|
|
174
|
-
defines the area replaced by the model and is not drawn. Otherwise preparation derives a footprint.
|
|
175
|
-
See the [Core building guide](https://github.com/tileflow/tileflow-sdk/blob/main/packages/core/docs/buildings-3d.md)
|
|
176
|
-
for placement and limits.
|
|
177
|
-
|
|
178
|
-
Prepared files retain a 16-byte vertex:
|
|
179
|
-
|
|
180
|
-
| Bytes | Content |
|
|
181
|
-
| ----- | ------------------------------------- |
|
|
182
|
-
| 0–5 | Quantized position |
|
|
183
|
-
| 6–7 | Padding |
|
|
184
|
-
| 8–10 | Normal |
|
|
185
|
-
| 11 | Padding |
|
|
186
|
-
| 12 | Part, an index into the level's parts |
|
|
187
|
-
| 13 | Shade within that part |
|
|
188
|
-
| 14 | Ambient visibility, 0–255 |
|
|
189
|
-
| 15 | Architectural lighting role, 0–6 |
|
|
190
|
-
|
|
191
|
-
Each level node's `extras.tileflow.parts` lists the names its part indices count through. Older
|
|
192
|
-
files without that list count through `surface`, `secondary`, `glass`, `accent` and `roof`. The
|
|
193
|
-
model root's `extras.tileflow.lightingRoles: 1` declares the last byte; older files without that
|
|
194
|
-
marker take each part's default role. Existing fully exposed visibility values stay fully exposed;
|
|
195
|
-
reprepare the original GLBs to obtain geometric occlusion. The occlusion texture splits vertices
|
|
196
|
-
along its charts without moving them or changing their normals or parts.
|
|
197
|
-
|
|
198
|
-
Roles and visibility survive meshoptimizer compression. The existing `_PAINT` accessor and vertex
|
|
199
|
-
stride are retained; the role occupies previously unused padding. Prepared files are an SDK
|
|
200
|
-
transport format, while material extras are the authoring interface.
|
|
201
|
-
|
|
202
|
-
Physical data is optional `extras.tileflow.surface` metadata on each level, with `version: 2`.
|
|
203
|
-
Three accessors address two streams: a 24-byte float stream holding UV0 and linear vertex RGBA,
|
|
204
|
-
and a 4-byte stream holding UV1 as normalised sixteen-bit values, so UV1 lies between zero and
|
|
205
|
-
one. Runtimes that read the earlier `version: 1` layout cannot read it, and current runtimes no
|
|
206
|
-
longer read `version: 1`: prepare models again with the matching Dev release.
|
|
207
|
-
The metadata also holds material draw ranges, channel references, embedded images and emitters.
|
|
208
|
-
Ranges preserve each source mesh's vertical emission bounds independently of its material.
|
|
209
|
-
The original primitive layout remains unchanged. Older readers draw its geometry and part
|
|
210
|
-
colours; they ignore the optional physical data. New readers preserve the legacy shading path
|
|
211
|
-
when physical data is absent. Reprepare source GLBs to obtain the new channels.
|
|
212
|
-
|
|
213
|
-
The auxiliary stream costs 32 bytes per retained vertex on the GPU. Each resident texture uses
|
|
214
|
-
four bytes per pixel, or one when only occlusion reads it, plus about one third for mipmaps when
|
|
215
|
-
enabled. Decoded images stay available
|
|
216
|
-
for context restoration until the model is evicted. Physical materials add one draw per material
|
|
217
|
-
range per colour/shadow pass; explicit emitters add one four-triangle draw each. No environment
|
|
218
|
-
cube map or screen-space effect is required.
|
|
@@ -1,92 +0,0 @@
|
|
|
1
|
-
# Layers inspection
|
|
2
|
-
|
|
3
|
-
Open the local preview and select **Layers**. The panel inspects the current map without changing its
|
|
4
|
-
authored style. **By module** groups physical layers using compiler contributions; shared layers retain
|
|
5
|
-
every owner. **Draw order** lists the renderer's public layer sequence, latest draw calls first.
|
|
6
|
-
Custom runtime layers are included even though they are absent from Style JSON. Inspector overlays
|
|
7
|
-
are excluded. Unknown ownership is labeled **Unattributed**, rather than guessed from an ID.
|
|
8
|
-
|
|
9
|
-
Press **I** or the element-picker icon and click an element on the map. Its layer becomes selected in
|
|
10
|
-
Layers and **Rules**, the first detail tab, opens with values evaluated for the picked feature. The
|
|
11
|
-
picked feature is a snapshot from that click; changing the layer or artifact/scene revision clears it.
|
|
12
|
-
Inspect no longer has a separate top-level tab. Legacy `tab=inspect` links resolve to Layers.
|
|
13
|
-
|
|
14
|
-
Enable **Visible only** beside the organization buttons to hide hidden/out-of-zoom layers and vector
|
|
15
|
-
layers with no rendered features in the current viewport. The filter combines with search and both
|
|
16
|
-
organization modes, and refreshes after camera movement, style changes and tile loading. One viewport
|
|
17
|
-
query serves the whole list after a 250 ms pause. During movement the last result remains stable;
|
|
18
|
-
failed queries do not classify layers as empty. Custom, raster and background layers remain listed
|
|
19
|
-
when their visibility cannot be measured; explicit hidden runtime state is excluded. This is a
|
|
20
|
-
rendered-feature filter, not a measurement of final pixels, transparency or occlusion.
|
|
21
|
-
|
|
22
|
-
Search by ID, semantic target, module, type, source or source-layer. Click anywhere on a row, or use
|
|
23
|
-
Up/Down and Home/End from a focused row. Selection stays in Layers and is retained in the `layer` URL
|
|
24
|
-
parameter. If a selected ID disappears, its detail shows that absence and keeps the ID for when it
|
|
25
|
-
returns. The Layers tab remains in the existing `tab=layers` parameter.
|
|
26
|
-
|
|
27
|
-
## Read the evidence
|
|
28
|
-
|
|
29
|
-
Open **Diagnosis** in the selected layer's detail tabs. With a picked feature or a
|
|
30
|
-
Data sample, it explains the filter result and any evaluated zero-size or zero-opacity components.
|
|
31
|
-
A zero component is not proof that the whole layer is invisible. Diagnostics findings can open a
|
|
32
|
-
specific paint, layout or filter declaration directly in Rules, highlighting its row.
|
|
33
|
-
|
|
34
|
-
- **Diagnosis** reports presence, declared visibility, the inclusive minimum/exclusive maximum zoom
|
|
35
|
-
range, source loading, shared source tiles and viewport-query observations. Pixel visibility,
|
|
36
|
-
occlusion, transparency and depth are explicitly unmeasured. Later draw calls do not necessarily
|
|
37
|
-
cover every earlier layer. Runtime 3D controllers report only the state and statistics they expose.
|
|
38
|
-
- **Rules** shows paint and layout values inline, without expandable rows, alongside their zoom,
|
|
39
|
-
feature, feature-state, global-state and image dependencies. Values use the current zoom and the
|
|
40
|
-
picked feature or selected data sample. Edit a value and press Enter or leave the field to preview
|
|
41
|
-
it; color pickers update live while open. Enumerations and booleans use selectors. Invalid values
|
|
42
|
-
show an error and leave the map unchanged. Edits override the entire physical layer across zooms,
|
|
43
|
-
including when a picked feature supplied the evaluated value. Each modified rule has a reset
|
|
44
|
-
button that restores its original expression or renderer default. Paint checkboxes temporarily
|
|
45
|
-
remove a declaration from the renderer so its default applies. The disabled row stays visible and
|
|
46
|
-
crossed out, showing its retained value at the current view; re-enabling restores the exact saved
|
|
47
|
-
expression or override. Toggles share edit history and appear in copied context. Implicit defaults
|
|
48
|
-
cannot be disabled; edit one to create an explicit rule first. **Undo** and **Redo** beside the
|
|
49
|
-
three-dot menu share the temporary style history. **Reset all changes** in that menu restores
|
|
50
|
-
temporary style and geometry edits and clears their history. Reload clears temporary edits;
|
|
51
|
-
config, source data and build artifacts stay unchanged. Filters remain read-only. Copy context includes the raw rules and temporary edits.
|
|
52
|
-
Evaluation does not reproduce placement, transitions or final pixel colors.
|
|
53
|
-
- **Data** queries only the selected layer after the viewport settles. At most 80 returned fragments
|
|
54
|
-
are retained; the renderer's query itself may return more. Fragments can duplicate logical features
|
|
55
|
-
across tile boundaries or world copies. Zero results are not proof that a filter excluded all data.
|
|
56
|
-
Unsupported custom/raster/background queries are unavailable, not zero. Choose an actual sample
|
|
57
|
-
to inspect its properties, or use **Use for rules** to evaluate that fragment in Rules. Inline
|
|
58
|
-
source data is excluded from source details.
|
|
59
|
-
- **Origin** preserves sidecar owners, targets, slots and operations. Semantic module paths do not
|
|
60
|
-
establish exact source-file or line provenance; token paths appear only if explicitly supplied.
|
|
61
|
-
|
|
62
|
-
## Follow a layer through the map
|
|
63
|
-
|
|
64
|
-
Hover or keyboard-focus a layer row to highlight its sampled geometry live in the current map view.
|
|
65
|
-
Click a row to keep that layer highlighted. Hovering another row temporarily replaces the highlight;
|
|
66
|
-
leaving restores the clicked layer, or clears the preview when no row was clicked. Closing the panel
|
|
67
|
-
clears both previews. Hover and click work with the element-picker mode on or off. The camera stays unchanged. The preview refreshes when map movement settles or source tiles
|
|
68
|
-
change, even when the hovered layer differs from the selected layer. Hover is coalesced over 80 ms;
|
|
69
|
-
queries are cached for the current view. There is no separate **Highlight on map** button.
|
|
70
|
-
|
|
71
|
-
Overlays retain at most 30 fragments and 25,000 vertices. They use separate scratch sources and never
|
|
72
|
-
change original paint, layout, source data or feature state. A highlight outlines queried geometry;
|
|
73
|
-
it is not a reconstruction of glyphs, symbols or 3D meshes. Hidden, out-of-zoom, custom and raster
|
|
74
|
-
layers without queryable rendered geometry report that limitation instead of moving the camera.
|
|
75
|
-
|
|
76
|
-
**Tiles** inspects tiles grouped by source. Tile costs belong to the shared source, not to a
|
|
77
|
-
single style layer. Sprite and font links in Rules open Assets. Other inspection tabs remain usable
|
|
78
|
-
while compilation or tile loading continues; obsolete scheduled measurements are discarded.
|
|
79
|
-
|
|
80
|
-
## Give an agent context
|
|
81
|
-
|
|
82
|
-
**Copy context** opens a frozen preview in Markdown or JSON. Add an optional investigation question,
|
|
83
|
-
then copy it. The packet includes the selected ID, map/theme, generation, scene revision, camera,
|
|
84
|
-
viewport, rules, provenance, diagnostic evidence, source, runtime state, recent changes and temporary
|
|
85
|
-
edits. It retains at most eight feature property samples, excludes their geometries and inline source
|
|
86
|
-
data, removes credentials and query strings from source URLs, and reports projection omissions.
|
|
87
|
-
Nothing is sent to an agent automatically.
|
|
88
|
-
|
|
89
|
-
While Layers is active, the same observation replaces stale feature selection in the local
|
|
90
|
-
`tileflow inspect session --url http://127.0.0.1:3333 --json` context. The CLI applies an additional
|
|
91
|
-
bounded projection and reports omitted paths. Temporary edits are observations; capture commands
|
|
92
|
-
still use the compiled map rather than reproducing scratch edits.
|