settlemaker 3.0.0 → 3.0.1
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 +162 -277
- package/dist/output/geojson-builder.d.ts +1 -1
- package/dist/output/geojson-builder.js +1 -1
- package/dist/settlemaker.browser.js +1 -1
- package/docs/README.md +54 -0
- package/docs/api.md +175 -0
- package/docs/artwork-integration.md +104 -0
- package/docs/current-symbol-library.md +62 -42
- package/docs/development.md +102 -0
- package/docs/examples/gallery/coastal-city.png +0 -0
- package/docs/examples/gallery/coastal-city.svg +4253 -0
- package/docs/examples/gallery/coastal-village.png +0 -0
- package/docs/examples/gallery/coastal-village.svg +1211 -0
- package/docs/examples/gallery/copperline-city.png +0 -0
- package/docs/examples/gallery/copperline-city.svg +1139 -0
- package/docs/examples/gallery/copperline-village.png +0 -0
- package/docs/examples/gallery/copperline-village.svg +2382 -0
- package/docs/examples/gallery/desert-city.png +0 -0
- package/docs/examples/gallery/desert-city.svg +3509 -0
- package/docs/examples/gallery/desert-village.png +0 -0
- package/docs/examples/gallery/desert-village.svg +455 -0
- package/docs/examples/gallery/fixtures.json +449 -0
- package/docs/examples/gallery/temperate-city-night.png +0 -0
- package/docs/examples/gallery/temperate-city-night.svg +3511 -0
- package/docs/examples/gallery/temperate-city.png +0 -0
- package/docs/examples/gallery/temperate-city.svg +3511 -0
- package/docs/examples/gallery/temperate-village.png +0 -0
- package/docs/examples/gallery/temperate-village.svg +3227 -0
- package/docs/examples/gallery/tropical-city.png +0 -0
- package/docs/examples/gallery/tropical-city.svg +3508 -0
- package/docs/examples/gallery/tropical-village.png +0 -0
- package/docs/examples/gallery/tropical-village.svg +3761 -0
- package/docs/examples/gallery/tundra-city.png +0 -0
- package/docs/examples/gallery/tundra-city.svg +3509 -0
- package/docs/examples/gallery/tundra-village.png +0 -0
- package/docs/examples/gallery/tundra-village.svg +1549 -0
- package/docs/fmg-embed-zoom.md +54 -0
- package/docs/gallery.md +139 -0
- package/docs/geojson.md +188 -0
- package/docs/getting-started.md +157 -0
- package/docs/landscape-character-review.md +55 -0
- package/docs/releases/3.0.1.md +18 -0
- package/docs/scene-schema.md +160 -0
- package/docs/schema-v3.md +38 -0
- package/docs/skins.md +52 -0
- package/docs/test-urls.md +39 -0
- package/docs/url-api.md +252 -0
- package/docs/water-context-v1.md +384 -0
- package/package.json +15 -8
- package/scripts/check-docs.mjs +106 -0
- package/scripts/generate-copperline.mjs +255 -0
- package/scripts/generate-examples.mjs +54 -0
- package/scripts/render-copperline.mjs +36 -0
- package/src/output/geojson-builder.ts +1 -1
- package/symbols/copperline/README.md +10 -3
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
# Embedding and zoom
|
|
2
|
+
|
|
3
|
+
This is guidance for an application hosting the [URL renderer](url-api.md), not
|
|
4
|
+
an API for controlling a cross-origin iframe after loading it. The npm package
|
|
5
|
+
generates SVG; the host page supplies layout, zoom, downloads and diagnostics.
|
|
6
|
+
|
|
7
|
+
## Responsive preview
|
|
8
|
+
|
|
9
|
+
Put the map in a viewport-sized container and scale the SVG with CSS using its
|
|
10
|
+
`viewBox`. City and village roots need not have identical size attributes. Size
|
|
11
|
+
the displayed element explicitly rather than assuming that generated width and
|
|
12
|
+
height attributes alone implement a responsive layout.
|
|
13
|
+
|
|
14
|
+
```css
|
|
15
|
+
html, body, #map { margin: 0; width: 100%; height: 100%; }
|
|
16
|
+
#map svg { display: block; width: 100%; height: 100%; }
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
Keep the full view box as the initial fit if the preview is intended to show the
|
|
20
|
+
entire settlement and its surrounding terrain. Cropping the frame is a host
|
|
21
|
+
presentation decision; it changes what is visible, not the generated settlement.
|
|
22
|
+
There is no `fit=cover` URL parameter in the current library parser.
|
|
23
|
+
|
|
24
|
+
## Host-owned navigation
|
|
25
|
+
|
|
26
|
+
A parent page can pan a larger iframe inside an overflow-hidden container. If it
|
|
27
|
+
uses layout resizing for zoom, the renderer should remain responsive to viewport
|
|
28
|
+
changes without regenerating the settlement. Regeneration on each resize can
|
|
29
|
+
block interaction and does not belong in zoom handling.
|
|
30
|
+
|
|
31
|
+
A host using its own SVG DOM can implement local pan/zoom directly. A cross-origin
|
|
32
|
+
iframe does not expose that DOM to its parent. This contract defines no
|
|
33
|
+
`postMessage` zoom, result, or automatic water-resurvey messages. Specific zoom
|
|
34
|
+
limits and input gestures are application choices, not engine guarantees.
|
|
35
|
+
|
|
36
|
+
## Diagnostics remain visible
|
|
37
|
+
|
|
38
|
+
A renderer must show parse/generation errors and measured-water warnings within
|
|
39
|
+
the page. Some embedded previews disable pointer events, so explanations must be
|
|
40
|
+
readable without hovering or clicking. Do not replace a failed measured-water map
|
|
41
|
+
with a plain dry map. Include required survey coverage when an error supplies it.
|
|
42
|
+
|
|
43
|
+
Map navigation and diagnostics need deliberate layout: a warning should remain
|
|
44
|
+
readable at the initial fit rather than being reduced to an unreadable part of a
|
|
45
|
+
zoomed map. The older expectation of an SVG-only page does not override the
|
|
46
|
+
measured-water diagnostic requirements.
|
|
47
|
+
|
|
48
|
+
## Multiple maps and tiles
|
|
49
|
+
|
|
50
|
+
Use separate image/iframe documents for independent maps. Inline SVGs can share
|
|
51
|
+
conflicting IDs even with different city `clipId` options. See the
|
|
52
|
+
[SVG embedding rules](scene-schema.md#embedding-svg) and
|
|
53
|
+
[local tile helpers](geojson.md#tiling). Preserve `data-bg="paper"` and village
|
|
54
|
+
scale metadata when post-processing output for those helpers.
|
package/docs/gallery.md
ADDED
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
# Gallery
|
|
2
|
+
|
|
3
|
+
These maps were generated with SettleMaker 3.0.1 through the public
|
|
4
|
+
`generateSettlement` API. PNG previews and full SVGs come from the same output.
|
|
5
|
+
The gallery covers all five built-in artwork biomes in both engines, plus Copperline.
|
|
6
|
+
|
|
7
|
+
[Exact inputs and seeds](examples/gallery/fixtures.json) · [Regenerate the gallery](development.md#documentation-checks)
|
|
8
|
+
|
|
9
|
+
Hosted preview links carry the saved inputs; the website's deployed generator may
|
|
10
|
+
differ from this package version. Skins are loaded by the library API, so the
|
|
11
|
+
Copperline examples link to their SVGs rather than an unsupported skin URL.
|
|
12
|
+
|
|
13
|
+
## Ashford — temperate village
|
|
14
|
+
|
|
15
|
+
Roads, individual homes, a green and cultivated fields.
|
|
16
|
+
|
|
17
|
+
Population **300** · seed **2** · engine **village**
|
|
18
|
+
|
|
19
|
+
[](examples/gallery/temperate-village.svg)
|
|
20
|
+
|
|
21
|
+
[Full SVG](examples/gallery/temperate-village.svg) · [Hosted preview](https://settlemaker.com/fmg?i=dZDLasMwEEX_5a5VSNzSBO3a3yghTKJJLCpLQhrXtCb_3nEeDg10pyvuORrNiC_YpcGuL0fYETkVgT1QqGyw90KOw5wHCqHOKQf6IVgpvQbhLge-pdpSlO-7h7Ka7p6SyL0zFR-PqvsYsbuErWMdYrk2-PTRwaIjHzH1e-Gtn26iztc-TQKczCP40sykpOGBrHr8j2xeVzMZ0l5H_YMOXOVKbgwidfpRvNX2kIrTZk65DyQ-RdjnxUKX6dO5Mi2FCwnri6jM6mpOvw)
|
|
22
|
+
|
|
23
|
+
## Thornwall — walled city
|
|
24
|
+
|
|
25
|
+
Native city buildings, denser central wards, greener outskirts and defensive walls.
|
|
26
|
+
|
|
27
|
+
Population **10000** · seed **2** · engine **settlement**
|
|
28
|
+
|
|
29
|
+
[](examples/gallery/temperate-city.svg)
|
|
30
|
+
|
|
31
|
+
[Full SVG](examples/gallery/temperate-city.svg) · [Hosted preview](https://settlemaker.com/fmg?i=dZDBasMwEET_Zc4qNKakRcd-Q24hmE28jUVkSUjrmNbk37tqa5cGqpNGzJsd7Ywr7MbgOOYz7IwUs8C-kS9scHJCHXtYyaPKibwvi0iePmgRwkPyvKjSU5D33xRKmrOm5EjdK1N24axh-xnHb9F2rA02LwYXFzpYDOQCqn8Ubl19CVquf6gBuJl78KlZSYnTHVn0-h_ZbJ9X0seTNv2DTlzkhzwYBBr0n9j1MYe6D_WmmEZP4mLQFo96dJsuftnqXjiTsE5FYda85vYJ)
|
|
32
|
+
|
|
33
|
+
## Qasra — desert village
|
|
34
|
+
|
|
35
|
+
Desert buildings, sparse vegetation and irrigated field textures.
|
|
36
|
+
|
|
37
|
+
Population **300** · seed **2** · engine **village**
|
|
38
|
+
|
|
39
|
+
[](examples/gallery/desert-village.svg)
|
|
40
|
+
|
|
41
|
+
[Full SVG](examples/gallery/desert-village.svg) · [Hosted preview](https://settlemaker.com/fmg?i=dZDBasMwEET_Zc4KJE5oi479g55LMJtom4jKkpDWNa3xv3fdJg4N9KYR84bZGfEBuzE49OUEOyKnIrBvFCobHL2Q47DogUKoi8qBvghWSq9CuMuBr6qeKcrnLYeyJt1ySiL3zFR8PGnc64jDr2gda4nNk8G7jw4WHfmI2d8Lt37-idrvvJoDMJl7cNcspKThjqz6_I9sHh4XMqSjVv2DDlzlQu4NInV6KF6oFlJfTrkPJD5F2O16rVP69GNwXFnHnHQOZo1ppm8)
|
|
42
|
+
|
|
43
|
+
## Qasr — desert city
|
|
44
|
+
|
|
45
|
+
Urban desert architecture, religious buildings and courtyards.
|
|
46
|
+
|
|
47
|
+
Population **10000** · seed **2** · engine **settlement**
|
|
48
|
+
|
|
49
|
+
[](examples/gallery/desert-city.svg)
|
|
50
|
+
|
|
51
|
+
[Full SVG](examples/gallery/desert-city.svg) · [Hosted preview](https://settlemaker.com/fmg?i=dZBRi8IwEIT_yz5HOIt4kkf_gc8iZTV7GtwmIdlatPS_u7279jjBPGXCfMNkeriBXRo4tvkMtocUs4D9Qi5k4OQFHTFYya3KDpnLJBLjAych1CSmSZULBrn_pWDSHJ51jui2hNmHs6btezj-iNqRVlhuDFx9cGChQR9g9LdCtR9fgra7LMYAGMwruKpmUmL3Qha9viOr9edMcjxp1X9oR0V-yYOBgI1-FHZYstpSTC2j-Bi0wIceXdLHb4ejQrrloHsQaU41PAE)
|
|
52
|
+
|
|
53
|
+
## Snowmere — tundra village
|
|
54
|
+
|
|
55
|
+
Snowy dwellings and low tundra vegetation with natural ground instead of arable fields.
|
|
56
|
+
|
|
57
|
+
Population **300** · seed **2** · engine **village**
|
|
58
|
+
|
|
59
|
+
[](examples/gallery/tundra-village.svg)
|
|
60
|
+
|
|
61
|
+
[Full SVG](examples/gallery/tundra-village.svg) · [Hosted preview](https://settlemaker.com/fmg?i=dZDRTgIxEEX_5T7XBFaDpo_8go_GkIGO0NBtm3bqRjb8u7OgSyTxrbe553SmIz5hlwbbVvawI3IqAvtBobLBzgs5DnMeKIQ6pxzoRLBSmgbhPgf-TfVAUb5uHspqunlKIrdmKj7uVfc2YnsNG8c6xPLF4Oijg0VPPmLqN-GNn26iznd4mAQ4m3vwqZtJScMdWfX4H9mtnmcypJ2O-gcduMoP-W4QqddF8RrT0HNhreaUWyDxKcI-Lhb6mz5dOtKiK6TvoTKrqTt_Aw)
|
|
62
|
+
|
|
63
|
+
## Frosthold — tundra city
|
|
64
|
+
|
|
65
|
+
Northern roofs, fortifications and biome-specific ground.
|
|
66
|
+
|
|
67
|
+
Population **10000** · seed **2** · engine **settlement**
|
|
68
|
+
|
|
69
|
+
[](examples/gallery/tundra-city.svg)
|
|
70
|
+
|
|
71
|
+
[Full SVG](examples/gallery/tundra-city.svg) · [Hosted preview](https://settlemaker.com/fmg?i=dZDRTsMwDEX_xc9BYhUClEce-AmEJm_x1gg3jhKHCqr9O-6gnTaJPOVEPjc3meAT_MbBrpUj-AmyFAV_QK7kYB8VAzF4Lc1wROa6QGb8xgWUhsy0UO0x6dclBbPl8MpFMLwQlpiOlvY2we4XtoGswubZwUdMATwMGBPM801pG-eTZO36uzkATu5WfOhWU2W8Matt_zO7x6fVZNlb1St1pKp_5ruDhIM9FF6LVO2Fg81myY1RoyRrcW_LvjPKeUxbCgXtSqhEFtadfgA)
|
|
72
|
+
|
|
73
|
+
## Reedbank — tropical river village
|
|
74
|
+
|
|
75
|
+
A supplied river enables tropical paddy selection; fields follow real parcels.
|
|
76
|
+
|
|
77
|
+
Population **300** · seed **2** · engine **village**
|
|
78
|
+
|
|
79
|
+
[](examples/gallery/tropical-village.svg)
|
|
80
|
+
|
|
81
|
+
[Full SVG](examples/gallery/tropical-village.svg) · [Hosted preview](https://settlemaker.com/fmg?i=dZBBT8MwDIX_i8-d1A0YkCP3XbiiaXIbs1pLkyhxV6Dqf8fdRgeTuPlZ_p6fPcARzLKAqkt7MAPEkATMO7pMBdQsaMnNukfn8qyiwy8EI6lTIdRGRz8qN-jl8-qDUZ2uPimgfSFM7Pdq9zZAdRY7Sxpi-VTAgb0FAy2yh2m-E9rx1PGar1lMBjAWt-D9aiYl9Ddk1vI_crV-nEkXao36B-0py4XcFuCx1UPhlchW6A86GkPsHAoHD-auLPWbHE4zkkLkix0fKZ2vrclLIseeTvIDzOJhovRhz-WUTTu_GrqyZyvNBsx63I76Xd2smcdv)
|
|
82
|
+
|
|
83
|
+
## Palmreach — tropical city
|
|
84
|
+
|
|
85
|
+
Tropical architecture and vegetation in the city engine.
|
|
86
|
+
|
|
87
|
+
Population **10000** · seed **2** · engine **settlement**
|
|
88
|
+
|
|
89
|
+
[](examples/gallery/tropical-city.svg)
|
|
90
|
+
|
|
91
|
+
[Full SVG](examples/gallery/tropical-city.svg) · [Hosted preview](https://settlemaker.com/fmg?i=dZDRisIwEEX_ZZ4jaBGVPPoFvouUsZ21wWkSkqllt_Tfne5uu6xgnnLDnMPNDPAAuzFw7dIN7AAxJAH7gZzJQOUEa2KwkjqNPTLnOUTGL5yDUBuZ5pQb9PL5Z8GoHl5yClgfCZPzN7WdB7j-hLImrbA5GLg7X4OFFp2Hab4TKt304rVds5oEMJpXcFsspIT-hcx6fUcWu_1Ccqi06j-0pyy_5MWAx1Y_CifkNhFWjc7GEDtGccFri7UeXacL32OSQnSTcdS1EKmuGJ8)
|
|
92
|
+
|
|
93
|
+
## Dunewick — coastal village
|
|
94
|
+
|
|
95
|
+
A generated coast from oceanBearing, with coastal buildings and vegetation.
|
|
96
|
+
|
|
97
|
+
Population **300** · seed **2** · engine **village**
|
|
98
|
+
|
|
99
|
+
[](examples/gallery/coastal-village.svg)
|
|
100
|
+
|
|
101
|
+
[Full SVG](examples/gallery/coastal-village.svg) · [Hosted preview](https://settlemaker.com/fmg?i=XY_RbsIwDEX_xc9Bapn2sDyi_cU0ITfxICLEUepQbVX_fW6BIng8lu_x9QgXsK2BrpYD2BEyFwH7g7EnAy4IeoorDxhjv1KO-IdgpVQFoXOOdKf-iEl-Hx7Manp4CqPfEZaQDqr7GqG7wt6Tlti2jYFTSB4sCA8J5kAV2od54hh72cwGmMxL8q19X5ORnV58ivqaaJNRjjB9G0h41r7wqcMhuJOuZs41ogROqmq0RBd42VluLjZ2hOlWHexHM-mvRCrfTv8)
|
|
102
|
+
|
|
103
|
+
## Saltmouth — port city
|
|
104
|
+
|
|
105
|
+
Port infrastructure beside a generated coastline. This is a bearing-based coast, not a measured survey.
|
|
106
|
+
|
|
107
|
+
Population **12000** · seed **2** · engine **settlement**
|
|
108
|
+
|
|
109
|
+
[](examples/gallery/coastal-city.svg)
|
|
110
|
+
|
|
111
|
+
[Full SVG](examples/gallery/coastal-city.svg) · [Hosted preview](https://settlemaker.com/fmg?i=RY69DsIwDITfxXOGUCYy8godEYNpTRvJjaP8gGjVd8dFFMY7n7-7BR7gDgZuNQ3gFoiSCriSKhnofMGeGNwdOat-InPej5Fxxl0UmiLTrvKIobx-bx1GBf0xSbA_EyYfBqVdGmvN0dqrgYCTMqBFLpPUMoK2SKyMxUvQlZq0utTLJ9YJ5g1rYMR0k5paP28-YxpIXekIw7cH3MmuOoyoB9esbw)
|
|
112
|
+
|
|
113
|
+
## Copperline — industrial village
|
|
114
|
+
|
|
115
|
+
The same village planner with a complete replacement skin and industrial artwork.
|
|
116
|
+
|
|
117
|
+
Population **250** · seed **2** · engine **village**
|
|
118
|
+
|
|
119
|
+
[](examples/gallery/copperline-village.svg)
|
|
120
|
+
|
|
121
|
+
[Full SVG](examples/gallery/copperline-village.svg) · [Skin JSON](examples/copperline.skin.json)
|
|
122
|
+
|
|
123
|
+
## Brassworks — steampunk city
|
|
124
|
+
|
|
125
|
+
Copperline machinery and brass materials on the existing city layout and semantic feature types.
|
|
126
|
+
|
|
127
|
+
Population **2000** · seed **2** · engine **settlement**
|
|
128
|
+
|
|
129
|
+
[](examples/gallery/copperline-city.svg)
|
|
130
|
+
|
|
131
|
+
[Full SVG](examples/gallery/copperline-city.svg) · [Skin JSON](examples/copperline.skin.json)
|
|
132
|
+
|
|
133
|
+
## One layout, another palette
|
|
134
|
+
|
|
135
|
+
Thornwall with the same inputs and seed, using `svg.palette: PALETTES.night`.
|
|
136
|
+
City palettes alter presentation; they do not replace all native material tokens.
|
|
137
|
+
Use a skin for complete artwork and material control.
|
|
138
|
+
|
|
139
|
+
[](examples/gallery/temperate-city-night.svg)
|
package/docs/geojson.md
ADDED
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
# GeoJSON, coordinates and identity
|
|
2
|
+
|
|
3
|
+
Both planners return a `FeatureCollection` with a top-level `metadata` foreign
|
|
4
|
+
member. The current `metadata.schema_version` is **4**. Filter features by
|
|
5
|
+
`properties.layer`, then inspect the geometry type and the fields for that engine.
|
|
6
|
+
Do not assume that sharing a schema number makes the two planners interchangeable
|
|
7
|
+
at the individual property level.
|
|
8
|
+
|
|
9
|
+
The return type is the standard GeoJSON `FeatureCollection` type. It does not
|
|
10
|
+
expose every engine-specific foreign member statically. Applications reading
|
|
11
|
+
metadata from external files should validate it before use; the tables below
|
|
12
|
+
describe the generated data.
|
|
13
|
+
|
|
14
|
+
## Coordinate frames
|
|
15
|
+
|
|
16
|
+
| Property | Village | City |
|
|
17
|
+
| --- | --- | --- |
|
|
18
|
+
| `metadata.coordinate_system` | `burg_local_y_down` | `local_origin_y_down` |
|
|
19
|
+
| `metadata.coordinate_units` | `metres` | `settlement_units` |
|
|
20
|
+
| Origin | Original burg position | Local output frame; may include the coastal translation |
|
|
21
|
+
| Axes | x east, y south | x right/east, y down/south |
|
|
22
|
+
| `scale.meters_per_unit` | 1 | Population-based estimate |
|
|
23
|
+
| `scale.source` | `village_metres` | `population_heuristic_v1` |
|
|
24
|
+
| `local_origin_shift` | `{dx: 0, dy: 0, source: 'none'}` | Actual translation and reason |
|
|
25
|
+
|
|
26
|
+
These are **local planar coordinates**, not WGS84 longitude and latitude. A GIS
|
|
27
|
+
or map library expecting geographic GeoJSON needs an explicit placement transform.
|
|
28
|
+
Do not feed them directly into a geographic map and expect correct placement.
|
|
29
|
+
The city scale is an estimate, not a physical survey. This is why measured
|
|
30
|
+
`waterContext` is currently restricted to the village planner.
|
|
31
|
+
|
|
32
|
+
`metadata.local_bounds` has `min_x`, `min_y`, `max_x`, `max_y`. For villages this is
|
|
33
|
+
the drawn tile frame in metres. Village SVG coordinates are translated and scaled
|
|
34
|
+
for display; the root's `data-px-per-metre` records that scale. In particular,
|
|
35
|
+
changing `village.pxPerMetre` does not change GeoJSON coordinates.
|
|
36
|
+
|
|
37
|
+
## Shared metadata
|
|
38
|
+
|
|
39
|
+
| Key | Meaning |
|
|
40
|
+
| --- | --- |
|
|
41
|
+
| `schema_version` | Output structure version, currently 4. |
|
|
42
|
+
| `settlemaker_version` | Package/generator version. Record it with saved maps. |
|
|
43
|
+
| `settlement_generation_version` | City input hash or the village marker `'village'`; not a complete cache key. |
|
|
44
|
+
| `generated_at` | Generation timestamp; differs between otherwise identical runs. |
|
|
45
|
+
| `local_bounds` | Local output extent. |
|
|
46
|
+
| `scale` | `meters_per_unit`, `diameter_meters`, `diameter_local`, `source`. Diameter describes settlement scale, not necessarily the full surrounding frame. |
|
|
47
|
+
| `stable_ids` | Engine-specific ID hints; treat actual IDs as opaque strings. |
|
|
48
|
+
| `poi_density` | `'hamlet'` or `'town'` POI regime. This is not the village/city planner discriminator. |
|
|
49
|
+
| `degraded_flags` | Dropped city walls/citadel requests; empty for villages. |
|
|
50
|
+
| `local_origin_shift` | Output translation. Do not apply it again to already generated output. |
|
|
51
|
+
|
|
52
|
+
City outputs above population 1,000 also carry `building_capacity`:
|
|
53
|
+
`basis: 'ordinary-building-budget'`, `target`, `placed`, `shortfall`, `corePlaced`,
|
|
54
|
+
`outerPlaced`, and `status: 'met' | 'shortfall'`. `corePlaced + outerPlaced = placed`;
|
|
55
|
+
`shortfall = max(0, target - placed)`. These are ordinary-building counts, not a
|
|
56
|
+
certified housed population. The same object is available through
|
|
57
|
+
`Model.getBuildingCapacity()` and `Scene.buildingCapacity`.
|
|
58
|
+
|
|
59
|
+
Village metadata adds `contract_radius_m`, `green_relation`, optional `outline_m`
|
|
60
|
+
and `diagnostics`. The contract circle locates supplied approaches, while
|
|
61
|
+
`local_bounds` describes the drawn frame; they are different extents. Measured
|
|
62
|
+
water diagnostics are returned as `result.waterContextResult` and on the village
|
|
63
|
+
site. Do not assume there is an equivalent top-level GeoJSON field.
|
|
64
|
+
|
|
65
|
+
## City features
|
|
66
|
+
|
|
67
|
+
| `layer` | Geometry | Selected properties |
|
|
68
|
+
| --- | --- | --- |
|
|
69
|
+
| `ward` | Polygon | `wardType` |
|
|
70
|
+
| `building` | Polygon | `building_id`, `wardType` |
|
|
71
|
+
| `street` | LineString | `street_id`, `streetType` (`artery`, `road`, `alley`, `park`), optional `width` |
|
|
72
|
+
| `green` | Polygon | `kind: 'garden'`, `wardType` |
|
|
73
|
+
| `water` | Polygon / MultiPolygon | Water geometry; inspect the emitted geometry type. |
|
|
74
|
+
| `wall` | LineString | `wallType` |
|
|
75
|
+
| `tower` | Point | `wallType` |
|
|
76
|
+
| `entrance` | Point | `entrance_id`, gate type, bearings and matched route information |
|
|
77
|
+
| `pier` | Polygon | `wardType` |
|
|
78
|
+
| `poi` | Point | `poi_id`, `kind`, `ward_type`, `building_id` |
|
|
79
|
+
|
|
80
|
+
City POIs may be attached to an ordinary building, or float at a placed well,
|
|
81
|
+
market, mill or pier. Those floating kinds use `building_id: null`; other adopted
|
|
82
|
+
POIs have a building ID. Ward labels describe attribution, not a guarantee that
|
|
83
|
+
the feature lies inside the corresponding ward polygon. The engine does not
|
|
84
|
+
supply narrative names for streets or POIs.
|
|
85
|
+
|
|
86
|
+
City bridge rendering information is available in `Scene.layers.bridges`;
|
|
87
|
+
there is no matching promise that city GeoJSON contains village-style `crossing`
|
|
88
|
+
features. Likewise, city park/field/vegetation rendering is richer than the
|
|
89
|
+
selected GeoJSON layers above; use the scene when reproducing city presentation.
|
|
90
|
+
|
|
91
|
+
## Village features
|
|
92
|
+
|
|
93
|
+
| `layer` | Geometry | Selected properties |
|
|
94
|
+
| --- | --- | --- |
|
|
95
|
+
| `building` | Polygon | `building_id`, `lot_id`, `glyph`, `occupancy`, `bearing_deg` |
|
|
96
|
+
| `street` | LineString | `street_id`, `streetType`, widths, setback, optional route provenance and role |
|
|
97
|
+
| `green` | Point | `shape`, `variant`, `diameter_m`, `bearing_deg`, `relation`, optional `outline_m` |
|
|
98
|
+
| `field` | Polygon | `field_id`, `glyph`, `furrow_bearing_deg` |
|
|
99
|
+
| `water` | Polygon | `water_id`; interior rings preserve land islands when present |
|
|
100
|
+
| `crossing` | Point | `crossing_id`, `street_id`, `span_m`, `bearing_deg`, `narrow`, optional deck and centreline |
|
|
101
|
+
| `wall` | LineString | `wall_id`, `wallType: 'village_wall'`, `material` |
|
|
102
|
+
| `gate` | Point | `gate_id`, `route_ids` |
|
|
103
|
+
| `junction` | Point | `junction_id`, `street_ids` |
|
|
104
|
+
| `poi` | Point | `poi_id`, `kind`, `glyph`, `bearing_deg` |
|
|
105
|
+
|
|
106
|
+
Village POIs do not carry the city POI `building_id`/`ward_type` contract. A village
|
|
107
|
+
green is a Point plus shape data, whereas a city garden is a Polygon. Village
|
|
108
|
+
wall openings are `gate` features, not city `entrance` features. Consumers must
|
|
109
|
+
branch where these differences matter.
|
|
110
|
+
|
|
111
|
+
### Village road cross-sections
|
|
112
|
+
|
|
113
|
+
| Property | Meaning in metres |
|
|
114
|
+
| --- | --- |
|
|
115
|
+
| `width_m` | Reserved road corridor. |
|
|
116
|
+
| `surface_width_m` | Painted travelled surface. |
|
|
117
|
+
| `setback_m` | Additional distance from corridor edge to parcel frontage. |
|
|
118
|
+
| `surface_clip_m` | Optional polygon limiting paint at a width transition. |
|
|
119
|
+
|
|
120
|
+
The frontage offset from the centreline is `width_m / 2 + setback_m`. A surface
|
|
121
|
+
width is not a parcel reservation. `route_role` can be `approach`, `street` or
|
|
122
|
+
`through`; `streetType` describes the drawn segment's class, which may differ
|
|
123
|
+
from the incoming route class. `route_ids` carries provenance on shared or
|
|
124
|
+
continuing streets. Optional `parent_street_id` records the model's parent lane.
|
|
125
|
+
|
|
126
|
+
Street LineStrings stay continuous for connectivity. To reproduce the map's
|
|
127
|
+
surfaces, clip road paint out of water and apply any `surface_clip_m`. Render
|
|
128
|
+
short bridge decks separately using crossing `deck_m` and `centreline_m` where
|
|
129
|
+
present and `narrow` is true. A continuous line through water alone is not a
|
|
130
|
+
bridge surface. Decks include dry abutments; do not use the Point feature as the
|
|
131
|
+
entire deck geometry.
|
|
132
|
+
|
|
133
|
+
## IDs and persistence
|
|
134
|
+
|
|
135
|
+
Every street feature has its own `street_id`. A supplied route ID can appear on
|
|
136
|
+
multiple approach/continuation features; it identifies external provenance, not
|
|
137
|
+
a unique generated street. Village junctions name the participating street IDs.
|
|
138
|
+
City gate features echo matched input routes in `matched_route_id` and, where
|
|
139
|
+
present, `matched_route_ids`.
|
|
140
|
+
|
|
141
|
+
Do not parse prefixes to discover geometry or engine type. City IDs are allocated
|
|
142
|
+
with prefixes such as `b`, `s`, `p`, `g`; village IDs use their own content-derived
|
|
143
|
+
forms. IDs repeat for identical inputs within a generator version, but are not
|
|
144
|
+
promised stable across releases. Persist user annotations with the generating
|
|
145
|
+
configuration and have a migration strategy if you regenerate after an upgrade.
|
|
146
|
+
|
|
147
|
+
Skins retain semantic IDs and categories. A Copperline power-station drawing can
|
|
148
|
+
occupy a religious-building slot; it does not turn the GeoJSON kind into a new
|
|
149
|
+
industrial feature taxonomy. Store the requested skin and biome separately.
|
|
150
|
+
|
|
151
|
+
## Tiling
|
|
152
|
+
|
|
153
|
+
The package crops an SVG into a local square tile pyramid. It does not assign
|
|
154
|
+
geographic web-map coordinates or rasterize PNG tiles for you. Starting with a
|
|
155
|
+
`result` and its original `burg`:
|
|
156
|
+
|
|
157
|
+
```js
|
|
158
|
+
import {
|
|
159
|
+
parseSvgViewBox, declaredMetersPerUnit, computeTileInfo, cropSvgToTile,
|
|
160
|
+
} from 'settlemaker';
|
|
161
|
+
|
|
162
|
+
const viewBox = parseSvgViewBox(result.svg);
|
|
163
|
+
if (!viewBox) throw new Error('SVG has no usable viewBox');
|
|
164
|
+
const tileInfo = computeTileInfo(
|
|
165
|
+
viewBox,
|
|
166
|
+
burg.population,
|
|
167
|
+
declaredMetersPerUnit(result.svg),
|
|
168
|
+
);
|
|
169
|
+
const rootTileSvg = cropSvgToTile(result.svg, tileInfo, 0, 0, 0);
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
`declaredMetersPerUnit` reads village SVG scale so the tile helper does not
|
|
173
|
+
substitute its population heuristic. City SVGs use the helper's scale estimate
|
|
174
|
+
when no explicit override is supplied. Preserve `data-bg="paper"` if you
|
|
175
|
+
post-process a generated SVG: the cropper uses that rectangle to extend the
|
|
176
|
+
background to the tile bounds.
|
|
177
|
+
|
|
178
|
+
Use `enumerateTiles(tileInfo.maxZoom)` or `totalTileCount` to plan the pyramid,
|
|
179
|
+
and a rasterizer such as your application's SVG image pipeline if you need PNGs.
|
|
180
|
+
Keep your host-map placement transform separate from this local z/x/y scheme.
|
|
181
|
+
|
|
182
|
+
## Version handling
|
|
183
|
+
|
|
184
|
+
Check `metadata.schema_version === 4` for this contract, and tolerate optional
|
|
185
|
+
fields and unfamiliar layers that your application does not use. A future
|
|
186
|
+
breaking structure change needs a new schema version. Additive artwork or road
|
|
187
|
+
fields need not change that number. The old [schema-v3 note](schema-v3.md) is a
|
|
188
|
+
historical migration record, not the schema check for current output.
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
# Getting started
|
|
2
|
+
|
|
3
|
+
SettleMaker is an ES module library. The examples here use Node 24, the runtime
|
|
4
|
+
used to validate the 3.0.x npm release. A source checkout also includes an optional
|
|
5
|
+
Nix development shell; Nix is not required to install or use the npm package.
|
|
6
|
+
|
|
7
|
+
## Node.js
|
|
8
|
+
|
|
9
|
+
```sh
|
|
10
|
+
mkdir my-settlements
|
|
11
|
+
cd my-settlements
|
|
12
|
+
npm init -y
|
|
13
|
+
npm install settlemaker
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
Save the following as `generate.mjs`. The `.mjs` extension enables ESM without
|
|
17
|
+
changing your project's package settings; alternatively use `.js` and set
|
|
18
|
+
`"type": "module"` in your package.json.
|
|
19
|
+
|
|
20
|
+
```js
|
|
21
|
+
import { writeFile } from 'node:fs/promises';
|
|
22
|
+
import { generateSettlement } from 'settlemaker';
|
|
23
|
+
|
|
24
|
+
const burg = {
|
|
25
|
+
name: 'Thornwall', population: 5000, biome: 'temperate',
|
|
26
|
+
port: false, citadel: true, walls: true, plaza: true,
|
|
27
|
+
temple: true, shanty: false, capital: false,
|
|
28
|
+
roadBearings: [20, 145, 270],
|
|
29
|
+
};
|
|
30
|
+
const result = generateSettlement(burg, { seed: 42 });
|
|
31
|
+
await writeFile('thornwall.svg', result.svg);
|
|
32
|
+
await writeFile('thornwall.geojson', JSON.stringify(result.geojson, null, 2));
|
|
33
|
+
console.log(result.kind, result.degradedFlags);
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
```sh
|
|
37
|
+
node generate.mjs
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
Open the SVG in a browser or vector editor. Generation is synchronous; it can take
|
|
41
|
+
noticeable time for large inputs. In an interactive app, run expensive generation
|
|
42
|
+
in a worker so it does not block the UI. There is no asynchronous generator or
|
|
43
|
+
cancellation API in this release.
|
|
44
|
+
|
|
45
|
+
For CommonJS, load the ESM package from an async function:
|
|
46
|
+
|
|
47
|
+
```js
|
|
48
|
+
async function main() {
|
|
49
|
+
const { generateSettlement } = await import('settlemaker');
|
|
50
|
+
// Call generateSettlement with the complete burg object shown above.
|
|
51
|
+
console.log(typeof generateSettlement);
|
|
52
|
+
}
|
|
53
|
+
main().catch(console.error);
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
## TypeScript
|
|
57
|
+
|
|
58
|
+
Declarations are included, and `@types/geojson` is installed transitively.
|
|
59
|
+
For Node ESM projects, use `module: "NodeNext"` and `moduleResolution: "NodeNext"`,
|
|
60
|
+
with a modern target and the `DOM` library if you explicitly configure `lib`:
|
|
61
|
+
URL helpers use Web Platform types. Install `@types/node` in your own project
|
|
62
|
+
when your code imports Node built-ins.
|
|
63
|
+
|
|
64
|
+
```ts
|
|
65
|
+
import { generateSettlement, type AzgaarBurgInput } from 'settlemaker';
|
|
66
|
+
|
|
67
|
+
const burg: AzgaarBurgInput = {
|
|
68
|
+
name: 'Ashford', population: 300,
|
|
69
|
+
port: false, citadel: false, walls: false, plaza: true,
|
|
70
|
+
temple: true, shanty: false, capital: false,
|
|
71
|
+
};
|
|
72
|
+
const result = generateSettlement(burg, { seed: 2 });
|
|
73
|
+
if (result.kind === 'village') {
|
|
74
|
+
console.log(result.model.buildings.length); // VillageModel
|
|
75
|
+
} else {
|
|
76
|
+
console.log(result.model.patches.length); // city Model
|
|
77
|
+
}
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
`GenerationParams` is an interface, not a constructor. For the city pipeline use
|
|
81
|
+
`mapToGenerationParams(burg, seed)` before `new Model(params).generate()`.
|
|
82
|
+
See [lower-level rendering](scene-schema.md#render-an-existing-city-model).
|
|
83
|
+
|
|
84
|
+
## Browser applications
|
|
85
|
+
|
|
86
|
+
With a bundler, use the same package import as Node:
|
|
87
|
+
|
|
88
|
+
```js
|
|
89
|
+
import { generateSettlement } from 'settlemaker';
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
For a page without a bundler, copy
|
|
93
|
+
`node_modules/settlemaker/dist/settlemaker.browser.js` into an asset directory
|
|
94
|
+
served by your application. This standalone ESM bundle includes the runtime
|
|
95
|
+
code and default artwork; it does not fetch SVG files during generation.
|
|
96
|
+
|
|
97
|
+
```html
|
|
98
|
+
<!doctype html>
|
|
99
|
+
<html lang="en">
|
|
100
|
+
<meta charset="utf-8">
|
|
101
|
+
<title>My settlement</title>
|
|
102
|
+
<style>#map svg { display: block; width: 100%; height: auto; }</style>
|
|
103
|
+
<div id="map"></div>
|
|
104
|
+
<script type="module">
|
|
105
|
+
import { generateSettlement } from './assets/settlemaker.browser.js';
|
|
106
|
+
const result = generateSettlement({
|
|
107
|
+
name: 'Ashford', population: 300, biome: 'temperate',
|
|
108
|
+
port: false, citadel: false, walls: false, plaza: true,
|
|
109
|
+
temple: true, shanty: false, capital: false,
|
|
110
|
+
roadBearings: [18, 142, 267],
|
|
111
|
+
}, { seed: 2 });
|
|
112
|
+
document.querySelector('#map').innerHTML = result.svg;
|
|
113
|
+
</script>
|
|
114
|
+
</html>
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
Serve the page over HTTP during development. Use a separate image document or
|
|
118
|
+
iframe for each map when displaying several maps: generated SVGs contain IDs
|
|
119
|
+
that can collide if multiple copies are inserted into the same DOM. See
|
|
120
|
+
[SVG embedding](scene-schema.md#embedding-svg).
|
|
121
|
+
|
|
122
|
+
## Load a portable skin
|
|
123
|
+
|
|
124
|
+
In Node, resolve the example distributed inside the installed package:
|
|
125
|
+
|
|
126
|
+
```js
|
|
127
|
+
import { readFile } from 'node:fs/promises';
|
|
128
|
+
import { createSkin, generateSettlement } from 'settlemaker';
|
|
129
|
+
|
|
130
|
+
const definitionUrl = import.meta.resolve('settlemaker/docs/examples/copperline.skin.json');
|
|
131
|
+
const definition = JSON.parse(await readFile(new URL(definitionUrl), 'utf8'));
|
|
132
|
+
const skin = createSkin(definition);
|
|
133
|
+
const result = generateSettlement({
|
|
134
|
+
name: 'Brassworks', population: 2000, biome: 'steampunk',
|
|
135
|
+
port: false, citadel: false, walls: false, plaza: true,
|
|
136
|
+
temple: true, shanty: false, capital: false,
|
|
137
|
+
roadBearings: [20, 145, 270],
|
|
138
|
+
}, { seed: 42, skin });
|
|
139
|
+
console.log(result.kind, result.svg.length);
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
In a browser, host a skin JSON file with your application, fetch it, check the
|
|
143
|
+
response and pass its parsed JSON to `createSkin`. Create the runtime handle with
|
|
144
|
+
the same loaded module instance that performs generation. To transfer a skin to
|
|
145
|
+
a worker or save it, transfer the definition JSON and load it there; do not
|
|
146
|
+
serialize or move the runtime handle between independently loaded bundles.
|
|
147
|
+
|
|
148
|
+
## Save and reproduce
|
|
149
|
+
|
|
150
|
+
Store the complete burg input, explicit seed, package version, rendering options
|
|
151
|
+
and skin definition/version. The same configuration reproduces the geometry and
|
|
152
|
+
SVG within a package version. Geometry and feature IDs may change on upgrades.
|
|
153
|
+
GeoJSON includes a creation timestamp, so complete JSON strings will differ even
|
|
154
|
+
when the geometry is identical. The city-only `geojson.generatedAt` option can
|
|
155
|
+
fix that timestamp; the village generator has no corresponding option.
|
|
156
|
+
|
|
157
|
+
[Full API](api.md) · [Output coordinates](geojson.md) · [Skin authoring](skins.md)
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
# Landscape character review
|
|
2
|
+
|
|
3
|
+
Historical review of the 2.7.0 artwork pass. Counts and validation below record
|
|
4
|
+
that review, not the current release. See the [current gallery](gallery.md) and
|
|
5
|
+
[artwork integration](artwork-integration.md) for maintained guidance.
|
|
6
|
+
|
|
7
|
+
Reviewed through the public `generateSettlement` API in `output/art-integration/`.
|
|
8
|
+
The river fixtures use coarse centrelines with default meandering enabled;
|
|
9
|
+
straight authored polygons and the straight-channel override are not used for
|
|
10
|
+
these natural rivers. The gallery links the previous release for visual comparison. Source changes are
|
|
11
|
+
in the city-glyphs worktree; this refinement has not been released.
|
|
12
|
+
|
|
13
|
+
## Observed results
|
|
14
|
+
|
|
15
|
+
The gallery includes villages and 10,000-person cities in all five biomes,
|
|
16
|
+
50,000- and 100,000-person temperate cities, a bridge village and a tropical
|
|
17
|
+
river village with rice paddies. All use seed 2 except the bridge fixture (3).
|
|
18
|
+
|
|
19
|
+
Roof coverage is building polygon area / residential ward area, grouped by
|
|
20
|
+
centre-to-edge character. It excludes parks, roads outside wards and farmland;
|
|
21
|
+
it is a visual-density diagnostic, not an occupancy or population claim.
|
|
22
|
+
|
|
23
|
+
| Population | Centre | Middle | Edge | Main parks | Rural house glyphs |
|
|
24
|
+
| --- | --- | --- | --- | --- | --- |
|
|
25
|
+
| 10000 | 71.7% | 61.5% | 43.6% | 3 | 264 |
|
|
26
|
+
| 50000 | 68.3% | 61.1% | 37.2% | 3 | 452 |
|
|
27
|
+
| 100000 | 68.9% | 57.7% | 37.7% | 3 | 1678 |
|
|
28
|
+
|
|
29
|
+
The 10,000-person capacity regression fixture retains its full 953-building
|
|
30
|
+
budget. City planning keeps a 10% local supply reserve before the final census
|
|
31
|
+
trim, with the existing minimum legible building size and capped core intact.
|
|
32
|
+
The metropolis still reports any capacity shortfall instead of inventing housing.
|
|
33
|
+
Gardens are actual parcel backgrounds, exported as additive green features.
|
|
34
|
+
|
|
35
|
+
Village enclosure support lines sit 3.5 metres outside measured roof and porch
|
|
36
|
+
bounds. Intersecting henge reservations enlarge only the affected part of that
|
|
37
|
+
boundary; detached henges do not replace the village perimeter. Roads retain
|
|
38
|
+
real openings and wet wall sections are omitted.
|
|
39
|
+
|
|
40
|
+
## Validation
|
|
41
|
+
|
|
42
|
+
- Full regression report: 1,417 passed, zero failures, `success: true`.
|
|
43
|
+
- New behavioural coverage: species clustering, valid biome plant selections,
|
|
44
|
+
source-identical biome greens, softened crowns, desert versus paddy irrigation,
|
|
45
|
+
ocean-versus-river eligibility, measured wall clearance, city density gradient,
|
|
46
|
+
varied roofs, rural outskirts and garden GeoJSON correspondence.
|
|
47
|
+
- Existing geometry/access, household budgets, POI identities, collision, water,
|
|
48
|
+
determinism and SVG/GeoJSON tests remain active. Tests that assumed one park,
|
|
49
|
+
one housing style, or no nested SVG groups now check the new contracts.
|
|
50
|
+
- 372 saved landscape assets, 210 additional plant seeds, 42 snow comparisons,
|
|
51
|
+
30 seamless tiles, clear farm entrances and live gallery controls passed.
|
|
52
|
+
- 60 green SVGs and 14 generated map SVGs parsed with unique IDs and resolved
|
|
53
|
+
internal references. Golden city renders were inspected and regenerated twice
|
|
54
|
+
to verify byte-for-byte determinism before updating their hashes.
|
|
55
|
+
- TypeScript build, script typecheck and browser bundle passed.
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# 3.0.1 — current documentation and generated examples
|
|
2
|
+
|
|
3
|
+
The npm README and public documentation now describe the 3.0.x library and its
|
|
4
|
+
portable skin system. The README includes regenerated PNG/SVG examples from the
|
|
5
|
+
current public API, with release-pinned links that work on npm and GitHub.
|
|
6
|
+
|
|
7
|
+
New getting-started, API, GeoJSON, gallery and development guides replace the
|
|
8
|
+
outdated entry-point examples and fragmented contract guidance. The URL and city
|
|
9
|
+
scene guides document current options, coordinate/engine differences, rendering
|
|
10
|
+
limits and separate website deployment. Schema v3 is clearly historical.
|
|
11
|
+
|
|
12
|
+
The examples cover five default artwork biomes in both planners and Copperline.
|
|
13
|
+
Documentation checks run the README examples, typecheck snippets and check links,
|
|
14
|
+
anchors and gallery provenance. Public docs and gallery files ship in the package.
|
|
15
|
+
|
|
16
|
+
Generation algorithms and artwork are unchanged from 3.0.0. Exported generator
|
|
17
|
+
metadata reports 3.0.1; GeoJSON schema 4, Scene 2, URL payload 1, skin format 1 and
|
|
18
|
+
water context 1 remain unchanged.
|