OrbPro2 a Cesium distribution

RfObstructionPort

new Cesium.RfObstructionPort(options)

The structure half of the RF solver's profile construction: a pluggable, camera-independent source of BUILDING and structure heights, rasterized onto the exact grid the terrain field already occupies. WHY THIS EXISTS (owner directive 2026-08-08, verbatim): "Also, I want to see the RF shader work with obstructions like buildings, etc." The coverage solve's path profile was terrain only. A 200 m tower block between a transmitter and a street does not exist as far as ITU-R P.526 is concerned if the profile it marches is a bare heightfield, so an urban solve painted a clear link straight through Midtown. The diffraction math already handles an arbitrary sequence of obstacles; what was missing was the obstacles. This port supplies them. WHY IT IS NOT A 3D TILES GEOMETRY READ, which is the first thing anyone proposes and the reason this file is a port rather than a helper: 1. There is no CPU-side triangle geometry to read. `GltfLoader`'s `loadAttributesAsTypedArray` is FALSE for b3dm/i3dm content (`Model/B3dmLoader.js:71-72`, `Model/I3dmLoader.js:84-85`); tile vertex data is uploaded to GPU buffers and the typed arrays are released. A tileset in memory is not a heightfield you can index. 2. Every native path that DOES answer "how high is the structure here" goes through rendering. `Cesium3DTileset.enableCollision` (`Cesium3DTileset.js:935`, consumed at `:2842`) feeds `Scene.pickFromRay`, and `Scene.sampleHeightMostDetailed` is a per position GPU readback. Both depend on what has been drawn, which makes the answer depend on where the camera is looking — the exact resident-tile trap ProviderAccessPort was built to escape, and a coverage raster that changes when the user pans is not a measurement. 3. A 262,144-sample field cannot afford a readback per sample regardless. So the obstruction model is VECTOR: footprint polygons carrying heights, the form the data actually has at its origin (OSM `building` ways with `height` / `building:levels`, municipal building-footprint datasets, a CAD export, an operator's own site plan). Rasterizing footprints is deterministic, camera-independent, costs O(vertices + covered posts), and — because the SAME footprints can be handed to the native Entity API as extruded polygons — what the user SEES is provably what the solver READ. THE ONE-COPY CONTRACT. A source holds its footprint vertices as ECEF `Float64Array`s built ONCE at construction. A read transforms them into the request's local ENU frame and scanline-fills the caller's own `Float32Array`. No per-read object allocation per footprint, no intermediate rasters, and the output buffer is the one the solver goes on to composite with terrain. SAMPLING DISCIPLINE, inherited from the terrain half and non-negotiable: - The obstruction field is rasterized on the SAME posts, at the SAME spacing, in the SAME frame as the terrain field it will be composited with. Two fields sampled differently disagree, and the solver's worst historical defect (2026-08-08) was exactly that disagreement. - A post is inside a footprint or it is not. There is NO dilation, no max-of-neighbours, no "grow by one cell to be safe". A max filter over posts is a morphological dilation that widens every structure by a cell in all four directions and biases every path pessimistic; it was removed from the terrain path for that reason and it is not coming back here. - Structures smaller than a post are not resolved. That is a RESOLUTION statement, reported in the descriptor as such, not a licence to smear.
Name Type Description
options object optional
Name Type Description
sources Array.<RfObstructionPort.Source> optional Sources to register up front.
Example:
const port = new Cesium.RfObstructionPort({
  sources: [Cesium.RfObstructionPort.fromGeoJson(buildingFootprints)],
});
const coverage = await Cesium.Analysis.computeRfCoverage({
  scene, txPosition, obstructions: port, profileResolution: 512,
});
See:

Members

static Cesium.RfObstructionPort.HeightReference : number

What a source's heights are measured from. ABOVE_GROUND is the default because it is what building data actually carries: OSM `height` and `building:levels`, a municipal footprint layer's storey count, a site plan's parapet height — all of them are above the ground the building stands on, and the port composites them onto the terrain field the solver has already sampled. ELLIPSOID exists for the sources that are genuinely absolute (a photogrammetric DSM, a surveyed antenna tip).

static constant Cesium.RfObstructionPort.NO_DATA : number

No-data sentinel for the obstruction field: a post with no structure over it. -FLT_MAX, NOT the -DBL_MAX ProviderAccessPort uses. The two ports follow the same reasoning — a sentinel must have exactly one encoding and must never be a real height — but they carry different buffers, and copying the constant across without checking the type is a silent, total failure: this field is a `Float32Array`, because it composites post for post with the `Float32Array` terrain field, and `-Number.MAX_VALUE` is not representable in f32. Writing it rounds to `-Infinity`, after which EVERY `value === NO_DATA` test in the port is false, every post reads as covered, and the provenance reports 100 % of a city with no buildings in it. That is not a hypothetical — it is what this constant was on first run, caught by the empty-port test asserting the sentinel rather than assuming it.

readonly featureCount : number

Total footprint count across every registered source.

readonly signature : string

A deterministic fingerprint of the registered sources. The RF solver caches a whole coverage state by signature. Obstructions are part of the physics, so they are part of that signature: without this, a solve run after a source was registered would be served the terrain-only raster out of the cache. It is also the mechanism by which a solve with NO sources stays bit-identical to the pre-obstruction engine — the fingerprint of an empty port is a constant.
The registered sources, in registration order. A later source never replaces an earlier one — every source contributes and the field keeps the MAXIMUM, because two datasets covering the same block describe the same skyline from different surveys and the taller reading is the one that blocks.

Methods

static Cesium.RfObstructionPort.fromEntities(entities, options)RfObstructionPort.Source

Builds a source from extruded polygon ENTITIES already in the scene. This is the seam that makes the picture honest. A demo that draws its buildings with the native Entity API and hands the SAME entity collection to this source cannot show a shadow that disagrees with the geometry the user is looking at, because there is one dataset and the solver read it. Height is `extrudedHeight - height` when both are present, so a building whose base is lifted off the ground contributes its own extent rather than its absolute top. `heightReference` on the entity decides whether that extent is above ground or above the ellipsoid.
Name Type Description
entities EntityCollection | Array.<Entity>
options object optional
Name Type Default Description
time JulianDate optional Time at which to evaluate the properties. Defaults to now — building geometry is not usually time-dynamic, and a source that is must be re-created when it changes.
defaultHeight number 8.0 optional
ellipsoid Ellipsoid Ellipsoid.WGS84 optional
id string "entity-footprints" optional
Returns:

static Cesium.RfObstructionPort.fromFootprints(options)RfObstructionPort.Source

Builds a source from explicit footprint polygons.
Name Type Description
options object
Name Type Default Description
footprints Array.<object> Each `{positions, height, baseHeight}`. `positions` is a ring, or an array of rings (outline first, courtyards after), of Cartographic, Cartesian3 or `[longitudeDegrees, latitudeDegrees]` pairs. `height` is metres above ground unless `heightReference` says otherwise.
heightReference number RfObstructionPort.HeightReference.ABOVE_GROUND optional
defaultHeight number 8.0 optional Height for a footprint that carries none.
ellipsoid Ellipsoid Ellipsoid.WGS84 optional
id string "footprints" optional
name string optional
Returns:

static Cesium.RfObstructionPort.fromGeoJson(geoJson, options)RfObstructionPort.Source

Builds a source from GeoJSON building footprints. Reads `Polygon` and `MultiPolygon` geometries (and the same inside a `Feature`/`FeatureCollection`). Heights come from the feature's properties: `height`, then `render_height`, then `building:levels` x `levelHeight`, then `defaultHeight`.
Name Type Description
geoJson object A Feature, FeatureCollection or bare geometry.
options object optional
Name Type Default Description
heightProperty string "height" optional
levelsProperty string "building:levels" optional
levelHeight number 3.2 optional Metres per storey.
defaultHeight number 8.0 optional Height for a feature with no height at all.
requireHeight boolean false optional Drop features with no height instead of giving them `defaultHeight`.
heightReference number RfObstructionPort.HeightReference.ABOVE_GROUND optional
ellipsoid Ellipsoid Ellipsoid.WGS84 optional
id string "geojson-footprints" optional
Returns:

static Cesium.RfObstructionPort.resolve(value)RfObstructionPort|undefined

Coerces whatever a caller passed for `obstructions` into a port. Accepts a port (returned as-is), a single source, an array of sources, or `undefined`/`false` (no obstructions at all, which must remain the exact pre-obstruction behaviour).
Name Type Description
value RfObstructionPort | RfObstructionPort.Source | Array.<RfObstructionPort.Source> optional
Returns:

readObstructionAt(request, result)object

Reads structure tops at ARBITRARY points rather than on a grid. The coverage raster marches a grid; a point-to-point path profile walks a geodesic, which is not axis-aligned in anybody's ENU frame and cannot be served by a rasterized field without resampling it. Two APIs of the same analysis disagreeing about whether a building exists is worse than either answer alone, so both go through this port — the grid read above, and this one.
Name Type Description
request object
Name Type Description
east Float64Array | Array.<number> Local-frame east of each point, metres.
north Float64Array | Array.<number> Local-frame north of each point, metres.
groundHeights Float32Array | Array.<number> optional Terrain height at each point, ellipsoid-relative; required for ABOVE_GROUND sources.
result Float32Array optional
Returns:
`{heights, covered, sources}` — ellipsoid-relative tops, RfObstructionPort.NO_DATA where nothing stands.

readObstructionField(request, result)object

Rasterizes every registered source onto the requested grid. The grid is the caller's, described exactly as the RF solver's profile field describes itself: an `width` x `height` array of posts at CELL CENTRES in a local east-north-up frame, so post (x, y) sits at `minEast + (x + 0.5) * cellWidth`, `minNorth + (y + 0.5) * cellHeight`. Being handed the caller's geometry rather than inventing one is the whole point: the obstruction field and the terrain field must be the same samples.
Name Type Description
request object
Name Type Description
width number Posts along east.
height number Posts along north.
minEast number Local-frame east of the grid's west edge, metres.
minNorth number Local-frame north of the grid's south edge, metres.
cellWidth number Post spacing along east, metres.
cellHeight number Post spacing along north, metres.
inverseTransform Matrix4 World -> local ENU.
groundHeights Float32Array optional Terrain height at each post, ellipsoid-relative. Required for ABOVE_GROUND sources; without it they have nothing to stand on and contribute nothing.
result Float32Array optional Optional output buffer of `width * height`.
Returns:
`{heights, covered, featureCount, sources, strategy}` — `heights` is ellipsoid-relative structure TOPS, with RfObstructionPort.NO_DATA at every post no structure covers.
Registers an obstruction source.
Name Type Description
source RfObstructionPort.Source
Returns:
The registered source.

removeSource(source)boolean

Removes a previously registered source.
Name Type Description
source RfObstructionPort.Source
Returns:
true if it was registered.

Type Definitions

Cesium.RfObstructionPort.Source

A registered obstruction source. The port owns compositing and provenance; a source owns nothing but "which posts do I cover, and how high am I there". Implement this to plug in a dataset the built-in factories do not cover — a municipal DSM raster, a CAD site plan, a wasm module reading a tiled vector store — without the solver learning anything about it.
Properties:
Name Type Attributes Description
id string <optional>
Stable identifier, reported in provenance and used in the port's cache fingerprint.
name string <optional>
Human-readable label.
featureCount number <optional>
How many structures the source holds.
signature string <optional>
A CONTENT-derived fingerprint. Two sources over the same data must produce the same string, and mutating the data must change it — the RF solver's coverage cache is keyed on it.
isReady function <optional>
Return `false` to be skipped this read (data still loading). Absent means always ready.
rasterize function Fill the grid described by the request; return `{covered, featureCount}`.
sample function <optional>
Fill scattered points. Optional: a source without it contributes to coverage rasters but not to point-to-point path profiles.
Need help? The fastest way to get answers is from the community and team on the Cesium Forum.