From cd33f24df94dff529d6c2cf64f9453bdd1897068 Mon Sep 17 00:00:00 2001 From: LS Date: Wed, 29 Jul 2026 10:33:11 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E5=A2=9E=E5=8A=A0=20GeoJsonPrimitive?= =?UTF-8?q?=20=E6=8A=80=E8=83=BD=E4=B8=8E=E7=A4=BA=E4=BE=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 基于 CesiumJS 1.142 的实验性 GeoJsonPrimitive API,补充大规模静态 GeoJSON 直接转换为 BufferPrimitiveCollections 的使用指导。 新增点线面与拾取示例,覆盖 fromUrl、fromGeoJson、源要素 ID、属性查询及与 GeoJsonDataSource 的选型边界;同步更新 Skill 描述、功能目录、示例索引和中英文项目说明。 调整示例生成器以保留仓库维护的 GeoJsonPrimitive 案例,并加入 AGENTS.md 记录项目用途、内容结构、验证方式及生成约束。 --- AGENTS.md | 25 ++++++ README.md | 4 +- SKILL.md | 10 +-- _build-examples.mjs | 21 ++++- catalog.md | 1 + examples.md | 2 +- .../2.3.23\343\200\201GeoJsonPrimitive.js" | 86 +++++++++++++++++++ examples/README.md | 3 +- patterns.md | 43 ++++++++++ 9 files changed, 183 insertions(+), 12 deletions(-) create mode 100644 AGENTS.md create mode 100644 "examples/2.3.23\343\200\201GeoJsonPrimitive.js" diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 0000000..255ff3f --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,25 @@ +# Repository Guide + +## Purpose + +- This repository is an Agent Skill, not an installable Cesium application or npm package. `SKILL.md` is the agent entrypoint; `index.html` is only the standalone GitHub Pages installation hub. +- The skill helps agents produce native, current CesiumJS demos from about 185 modernized upstream examples. Read `SKILL.md` before changing guidance because it owns the supported API and output rules. + +## Content Map + +- Route a feature through `catalog.md`, then inspect the matching `examples/*.js`; `examples/README.md` is the generated full index. +- `examples/*.js` are script bodies, not runnable pages. Use `templates.md` when turning one into HTML. +- Use `migration.md` for old Cesium API leftovers, `webgl2.md` for shader work, `patterns.md` for common native API patterns, and `scripts/` for the few maintained reusable helpers. +- Most files in `examples/` are mechanically migrated from upstream HTML. Treat their `AUTO-MIGRATED` warning literally: review nested `await`, removed `readyPromise` chains, external script/data dependencies, primitive insertion, and camera framing before reusing code. `examples/000.js` is an intentional stub. + +## Commands And Verification + +- There is no dependency install, test, lint, formatter, typecheck, or site build command in this repository. +- Check a changed standalone script with `node --check "path/to/file.js"`; check the generator with `node --check _build-examples.mjs`. Browser/Cesium behavior still requires a runnable HTML page and real external assets or tokens. +- Do not run `node _build-examples.mjs` from a normal standalone clone. It expects upstream HTML at `../../../examples/cesiumEx` relative to this repo, and once that source exists it deletes every `.js` and `.md` in `examples/` before regenerating them. + +## Change Constraints + +- Keep `SKILL.md`, `catalog.md`, `examples.md`, and `examples/README.md` consistent when feature routing or the generated example inventory changes. +- Preserve the skill package's Markdown/JavaScript-only example model. A requested runnable demo belongs in the user's target workspace; do not add demo HTML under `examples/`. +- Keep tokens and environment-specific URLs as placeholders. Existing generated examples may still contain legacy/private endpoints; their presence is not approval to copy them into maintained guidance or helpers. diff --git a/README.md b/README.md index 774f3af..5e0601c 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ An Agent Skill for **native CesiumJS 1.142** examples. -Works with Cursor, Codex, Claude, and other Agent Skills–compatible tools. Helps generate Viewer, imagery, terrain, 3D Tiles, materials, and effects using native `Cesium.*` APIs. +Works with Cursor, Codex, Claude, and other Agent Skills–compatible tools. Helps generate Viewer, imagery, terrain, 3D Tiles, high-performance GeoJSON primitives, materials, and effects using native `Cesium.*` APIs. **Website:** [https://opencesium.github.io/Cesium-Skills/](https://opencesium.github.io/Cesium-Skills/) — one-stop hub to get & install community Cesium Skills. @@ -77,7 +77,7 @@ Example logic is adapted from [Cesium-Examples](https://github.com/jiawanlong/Ce 基于 **最新 CesiumJS 1.142** 的原生 Cesium 示例 Skill。 -适用于 Cursor、Codex、Claude 等支持 Agent Skills 的工具:生成 Viewer、影像、地形、3D Tiles、材质与特效等原生 `Cesium.*` 代码。 +适用于 Cursor、Codex、Claude 等支持 Agent Skills 的工具:生成 Viewer、影像、地形、3D Tiles、高性能 GeoJSON Primitive、材质与特效等原生 `Cesium.*` 代码。 **站点:** [https://opencesium.github.io/Cesium-Skills/](https://opencesium.github.io/Cesium-Skills/) — 一站式获取 & 安装社区版 Cesium Skills。 diff --git a/SKILL.md b/SKILL.md index a3a932d..3a0a267 100644 --- a/SKILL.md +++ b/SKILL.md @@ -2,10 +2,10 @@ name: cesium-skills description: >- Writes native CesiumJS demos for the latest stable Cesium API (async terrain, - 3D Tiles, imagery, WebGL2 shaders/effects). Use when creating or migrating - Cesium Viewer, layers, terrain, Cesium3DTileset, models, CustomShader, - PostProcessStage, materials, particles, or when old Cesium 1.x / WebGL1 demos - break. Do not use for non-Cesium GIS or mars3d/SuperMap wrappers. + 3D Tiles, imagery, GeoJsonPrimitive, WebGL2 shaders/effects). Use when creating + or migrating Cesium Viewer, layers, terrain, Cesium3DTileset, models, + CustomShader, PostProcessStage, materials, particles, or when old Cesium 1.x / + WebGL1 demos break. Do not use for non-Cesium GIS or mars3d/SuperMap wrappers. --- # Cesium Skills (native, latest API) @@ -84,7 +84,7 @@ Helper: [scripts/createViewer.js](scripts/createViewer.js). | Viewer / camera / events / coords | `examples/1.*.js` + [patterns.md](patterns.md) | | Imagery | `examples/2.1.*.js` | | Terrain | `examples/2.2.*.js` + [migration.md](migration.md) | -| Entity / GeoJSON | `examples/2.3.*.js` | +| Entity / GeoJSON | `examples/2.3.*.js`; for large static GeoJSON start with `examples/2.3.23、GeoJsonPrimitive.js` + [patterns.md](patterns.md) | | glTF / 3D Tiles / CustomShader | `examples/2.4.*.js`, `examples/3.1.*.js` | | Analysis / measure / video | `examples/4.*.js` | | Fog / particles / radar / fence | `examples/5.*.js` + [webgl2.md](webgl2.md) | diff --git a/_build-examples.mjs b/_build-examples.mjs index a3cf15b..18161f6 100644 --- a/_build-examples.mjs +++ b/_build-examples.mjs @@ -10,6 +10,14 @@ const __dirname = path.dirname(fileURLToPath(import.meta.url)); const ROOT = path.resolve(__dirname, '../../..'); const SRC = path.join(ROOT, 'examples', 'cesiumEx'); const OUT = path.join(__dirname, 'examples'); +const MAINTAINED_EXAMPLES = [ + { + file: '2.3.23、GeoJsonPrimitive.js', + label: 'Maintained: GeoJsonPrimitive (Cesium 1.142+)', + after: '2.3.22、切换2维bug.html', + }, +]; +const MAINTAINED_EXAMPLE_FILES = MAINTAINED_EXAMPLES.map((example) => example.file); const SKIP_NAME = /^(examples|editor|demo|test|gdb|show_converted|MOON|韩国|实时|流水|管线|隧道|楼栋|真实道路|二三维|视频投影|格网脉冲|获取3dtiles|在Cesium|grid|grid2|grid_)/i; @@ -151,9 +159,9 @@ function main() { } fs.mkdirSync(OUT, { recursive: true }); - // clean previous generated js (keep nothing else in examples/) + // Keep repository-maintained examples that have no upstream HTML source. for (const f of fs.readdirSync(OUT)) { - if (f.endsWith('.js') || f.endsWith('.md')) { + if ((f.endsWith('.js') || f.endsWith('.md')) && !MAINTAINED_EXAMPLE_FILES.includes(f)) { fs.unlinkSync(path.join(OUT, f)); } } @@ -217,10 +225,17 @@ function main() { fs.writeFileSync(path.join(OUT, outName), body, 'utf8'); index.push(`| \`${file}\` | [\`${outName}\`](${outName}) |`); + for (const example of MAINTAINED_EXAMPLES) { + if (file === example.after && fs.existsSync(path.join(OUT, example.file))) { + index.push(`| ${example.label} | [\`${example.file}\`](${example.file}) |`); + } + } } index.push(''); - index.push(`Generated: **${files.length}** demos (${ok} with script body, ${empty} stubs).`); + index.push( + `Generated: **${files.length}** upstream demos (${ok} with script body, ${empty} ${empty === 1 ? 'stub' : 'stubs'}), plus **${MAINTAINED_EXAMPLES.length} maintained** demo.` + ); index.push(''); index.push('## Migration applied automatically'); index.push(''); diff --git a/catalog.md b/catalog.md index 9ae8658..5b8094d 100644 --- a/catalog.md +++ b/catalog.md @@ -23,6 +23,7 @@ Online gallery (legacy): https://jiawanlong.github.io/Cesium-Examples/ | XYZ / TMS / WMS / WMTS / Tianditu / Mapbox | `examples/2.1.*.js` | | Terrain | `examples/2.2.*.js` | | Entity / GeoJSON / cluster / CZML | `examples/2.3.*.js` | +| Large static GeoJSON / GeoJsonPrimitive / buffer primitives | `examples/2.3.23、GeoJsonPrimitive.js` + [patterns.md](patterns.md#geojsonprimitive-experimental-1142) | | glTF models | `examples/2.4.*.js` | | 3D Tiles / CustomShader / flatten | `examples/3.1.*.js`, `7.2.*.js` | | Excavate / viewshed / flood / buffer / sun / cut-fill / profile | `examples/4.1.*.js` | diff --git a/examples.md b/examples.md index 2e23c15..1e231f0 100644 --- a/examples.md +++ b/examples.md @@ -23,7 +23,7 @@ For anything beyond a trivial Viewer page: | `1.x` | Basics: camera, events, coords, popup, MVT… | | `2.1.x` | Imagery services | | `2.2.x` | Terrain | -| `2.3.x` | Entity / GeoJSON / cluster | +| `2.3.x` | Entity / GeoJSON / cluster; `2.3.23` covers `GeoJsonPrimitive` | | `2.4.x` | glTF models | | `3.1.x` | 3D Tiles + CustomShader | | `4.1.x`–`4.3.x` | Analysis / measure / video | diff --git "a/examples/2.3.23\343\200\201GeoJsonPrimitive.js" "b/examples/2.3.23\343\200\201GeoJsonPrimitive.js" new file mode 100644 index 0000000..7b7e0da --- /dev/null +++ "b/examples/2.3.23\343\200\201GeoJsonPrimitive.js" @@ -0,0 +1,86 @@ +/** + * GeoJsonPrimitive example for CesiumJS 1.142+. + * Paste into a page with #map + Cesium loaded, or adapt into your app. + * GeoJsonPrimitive is experimental and may change without standard deprecation. + */ +'use strict'; + +(async function () { + const viewer = new Cesium.Viewer('map', { + baseLayer: false, + baseLayerPicker: false, + animation: false, + timeline: false, + infoBox: false, + selectionIndicator: false, + }); + + const geoJson = { + type: 'FeatureCollection', + features: [ + { + type: 'Feature', + id: 'station-1', + properties: { name: '监测点' }, + geometry: { type: 'Point', coordinates: [116.39, 39.91, 100] }, + }, + { + type: 'Feature', + id: 'route-1', + properties: { name: '巡检路线' }, + geometry: { + type: 'LineString', + coordinates: [ + [116.34, 39.88, 100], + [116.39, 39.91, 100], + [116.44, 39.89, 100], + ], + }, + }, + { + type: 'Feature', + id: 'zone-1', + properties: { name: '作业区' }, + geometry: { + type: 'Polygon', + coordinates: [[ + [116.36, 39.93, 100], + [116.42, 39.93, 100], + [116.42, 39.97, 100], + [116.36, 39.97, 100], + [116.36, 39.93, 100], + ]], + }, + }, + ], + }; + + const geoJsonPrimitive = Cesium.GeoJsonPrimitive.fromGeoJson(geoJson, { + allowPicking: true, + }); + viewer.scene.primitives.add(geoJsonPrimitive); + + console.log('GeoJSON feature count:', geoJsonPrimitive.featureCount); + console.log('Source IDs:', geoJsonPrimitive.ids); + + const handler = new Cesium.ScreenSpaceEventHandler(viewer.scene.canvas); + handler.setInputAction((movement) => { + const picked = viewer.scene.pick(movement.position); + if (picked?.parentPrimitive !== geoJsonPrimitive) return; + + const featureId = picked.primitive.featureId; + console.log('Picked source ID:', geoJsonPrimitive.getId(featureId)); + console.log('Picked properties:', geoJsonPrimitive.getProperties(featureId)); + }, Cesium.ScreenSpaceEventType.LEFT_CLICK); + + viewer.camera.setView({ + destination: Cesium.Cartesian3.fromDegrees(116.39, 39.925, 18000), + orientation: { + heading: 0, + pitch: Cesium.Math.toRadians(-90), + roll: 0, + }, + }); +})().catch(function (error) { + console.error(error); +}); diff --git a/examples/README.md b/examples/README.md index eede471..2a580f5 100644 --- a/examples/README.md +++ b/examples/README.md @@ -66,6 +66,7 @@ No HTML is shipped in this skill. Agent: **Read** the matching `.js` before gene | `2.3.20、字体图标缩放.html` | [`2.3.20、字体图标缩放.js`](2.3.20、字体图标缩放.js) | | `2.3.21、各种entity.html` | [`2.3.21、各种entity.js`](2.3.21、各种entity.js) | | `2.3.22、切换2维bug.html` | [`2.3.22、切换2维bug.js`](2.3.22、切换2维bug.js) | +| Maintained: GeoJsonPrimitive (Cesium 1.142+) | [`2.3.23、GeoJsonPrimitive.js`](2.3.23、GeoJsonPrimitive.js) | | `2.3.3、entity面.html` | [`2.3.3、entity面.js`](2.3.3、entity面.js) | | `2.3.4、图标.html` | [`2.3.4、图标.js`](2.3.4、图标.js) | | `2.3.5、海量图标.html` | [`2.3.5、海量图标.js`](2.3.5、海量图标.js) | @@ -191,7 +192,7 @@ No HTML is shipped in this skill. Agent: **Read** the matching `.js` before gene | `Cesium融合Three.html` | [`Cesium融合Three.js`](Cesium融合Three.js) | | `s3m.html` | [`s3m.js`](s3m.js) | -Generated: **185** demos (184 with script body, 1 stubs). +Generated: **185** upstream demos (184 with script body, 1 stub), plus **1 maintained** demo. ## Migration applied automatically diff --git a/patterns.md b/patterns.md index 05b2799..1bacecc 100644 --- a/patterns.md +++ b/patterns.md @@ -151,6 +151,49 @@ viewer.entities.add({ - glb on Entity → `model: { uri, scale, runAnimations }` - GeoJSON → `await Cesium.GeoJsonDataSource.load(url)` then `viewer.dataSources.add(...)` +### GeoJsonPrimitive (experimental, 1.142+) + +Use `GeoJsonPrimitive` for large, mostly static GeoJSON when Entity/DataSource +overhead is unnecessary. It converts point, line, and polygon geometries directly +into buffer primitive collections and is added to `viewer.scene.primitives`. +Keep `GeoJsonDataSource` for Entity styling, clustering, time-dynamic properties, +ground clamping, and DataSource lifecycle integration. + +```javascript +const geoJsonPrimitive = await Cesium.GeoJsonPrimitive.fromUrl( + './data/features.geojson', + { allowPicking: true } +); +viewer.scene.primitives.add(geoJsonPrimitive); + +console.log(geoJsonPrimitive.featureCount); +console.log(geoJsonPrimitive.points); // undefined when the source has no points + +const handler = new Cesium.ScreenSpaceEventHandler(viewer.scene.canvas); +handler.setInputAction((movement) => { + const picked = viewer.scene.pick(movement.position); + if (picked?.parentPrimitive !== geoJsonPrimitive) return; + + const featureId = picked.primitive.featureId; + console.log(geoJsonPrimitive.getId(featureId)); + console.log(geoJsonPrimitive.getProperties(featureId)); +}, Cesium.ScreenSpaceEventType.LEFT_CLICK); +``` + +When the object is already parsed, use the synchronous +`Cesium.GeoJsonPrimitive.fromGeoJson(geoJson, options)`. Source feature IDs and +properties are available through `ids` / `getId()` and `properties` / +`getProperties()`. One source feature may create multiple buffer primitives that +share the same generated integer `featureId`. The `points`, `polylines`, and +`polygons` properties are each optional because collections are created only for +geometry types present in the input. + +Supported inputs are `FeatureCollection`, `Feature`, the standard point/line/ +polygon geometry types (including their `Multi*` forms), and +`GeometryCollection`. Coordinates are longitude/latitude degrees with optional +height. This API is experimental in Cesium 1.142 and may change without the +normal deprecation process. Full example: [examples/2.3.23、GeoJsonPrimitive.js](examples/2.3.23、GeoJsonPrimitive.js). + ### Circle wave material ```javascript