# NYC geometry study: scope and measurement methods

Study date: 2026-10-18. User-supplied source: `[source model folder]`. The original `.3dm` files are read-only inputs. Reports, CSV measurements, hashes, and scripts are written here instead.

## What is measured and what is sampled

- **Complete per-file census:** every object is traversed for its Rhino geometry type, layer, visibility mode, name presence, and non-tight bounding box. This includes hidden objects. Bounding-box failures are counted.
- **Footprint measurements:** every eligible closed horizontal polyline in the building-footprint role is processed. Open curves, non-polylines, degenerate shapes, and vertical variation over 1 mm (or ten document tolerances, whichever is larger) are excluded with a reason. These records are not verified cadastral buildings or lots.
- **Geometry health and surface properties:** a deterministic reservoir sample of up to 64 objects per layer is checked with Rhino's `IsValid`. Breps are also checked for solid status, naked-edge counts, first-face normal direction, and area. Curves are checked for closure and length. This is a sample, not a complete topology audit; tiny layers may be fully examined.
- **Attributes:** representative object GUIDs, names, and user strings are retained. Absence in these samples does not establish absence throughout the collection.
- **Integrity:** a full-file SHA-256 and size/modification-time comparison are recorded. A hash identifies this observed copy; without a pre-study hash it cannot independently prove the file was never changed before inspection.

No Boolean repairs, joins, source saves, mesh conversions, or edits to the source models are performed. File readers and independent geometry operate outside the active document. A live Rhino excerpt, if created, uses copied and transformed geometry only.

## Runtime and safe execution

The baseline is Rhino `8.35.26251.13001`, CPython `3.9.10`, with RhinoCommon and the installed RhinoAI MCP router. MCP advertised `run_python` and document/viewport query tools; its separate package version was not established. The active document was empty at initial inspection, with millimeter units and tolerance 0.001; those settings are **not** assumed to describe the source files.

The census runs one independent `File3dm` at a time in a background worker. It does not mutate live Rhino documents from that thread. Models are disposed before the next file. Progress and completed evidence are checkpointed after each file. The local memory budget reported by .NET was approximately 33.4 GB; the collection is larger than that, so opening everything simultaneously is deliberately avoided.

The collection was already extracted: no ZIP extraction or new model downloads were needed. The `.rhl` lock file is not geometry and is excluded.

One live tool call returned `rhino_closed`; the following router inventory re-adopted the same Rhino process on a new local endpoint, and the independent file census continued. This is a recorded bridge interruption, not evidence that the source geometry was corrupt or that Rhino crashed. The study does not claim uninterrupted MCP reliability.

## Units and coordinate handling

Each file's declared unit system is read separately. Lengths use Rhino's conversion factor to meters; areas use its square. Raw coordinates, original units, document tolerance, and source GUIDs remain available in the evidence.

The polygon-area calculation subtracts a local origin before applying the shoelace formula. This reduces cancellation at geographic coordinate magnitudes. At most eight eligible footprints per file are independently compared with Rhino `AreaMassProperties.Compute`; those are convenience checks in object traversal order, not randomized accuracy estimates.

Neither a projected coordinate magnitude nor a familiar NYC location establishes a coordinate reference system or vertical datum. The native geographic transform must be preserved until those are independently resolved. Do not mix geographic elevation with height above a building's base.

## Footprint metrics

- `area_m2`: absolute signed area of one closed polyline in XY. Separate rings are not assembled into polygons with holes. Self-intersections are not excluded by a full-population validity test.
- `perimeter_m`: sum of XY segment lengths.
- `bbox_x_m`, `bbox_y_m`: world-axis extents, not intrinsic frontage and depth.
- `compactness`: `4*pi*area/perimeter^2`. A square gives approximately 0.785; it is not the maximum possible value because a circle approaches 1.
- `bbox_fill_ratio`: area divided by the world-axis box area. Rotation alone can reduce it substantially.
- `aligned_long_m`, `aligned_short_m`: extents after aligning to the longest polygon edge. They are an orientation-aware approximation, **not** a minimum-area bounding rectangle.
- `aligned_fill_ratio`: area divided by that aligned rectangle's area. It helps distinguish rotation from irregular outline but cannot identify courtyards, use, or parcel coverage by itself.
- `aligned_aspect_ratio`: aligned long extent divided by aligned short extent.
- `longest_edge_azimuth_deg`: longest-edge orientation in source XY, modulo 180 degrees. It is an unoriented geometric axis, not a surveyed street bearing or geographic north.
- `vertices`: source polyline vertices after removing its repeated closing endpoint. Collinear subdivisions inflate this count; it is not a count of architectural corners.

Quantiles use linear interpolation on sorted observations, including minimum, p10, p25, median, p75, p90, p99, and maximum. Pooled statistics describe this supplied collection, including possible duplicates, not all of NYC.

## Roof-to-footprint height proxies

The extractor normalizes observed layer-name variants into footprint curves, footprint surfaces, roof surfaces, facade surfaces, and other context. It retains original layer paths alongside those roles.

For each Brep roof surface, candidate footprints are indexed in a 100 m spatial grid. A match requires the roof's XY bounding box to fit inside the footprint's bounding box within 0.10 m, its bounding-box center to lie inside the footprint polyline, and roof maximum Z to exceed footprint base Z. Roofs matching multiple footprints are excluded. The tallest accepted roof maximum minus footprint base becomes the footprint's height proxy.

This is a **heuristic association**, not a source building-ID join. Bounding-box centers can lie outside concave roofs; box containment does not prove full polygon containment. Adjacent or nested footprints, podiums, overhangs, courtyards, generalized roofs, and disconnected appendages can cause missing or incorrect associations. A matched footprint can still miss its highest roof. No proxy is silently converted into ground truth, floor count, or usable floor area.

## Evidence navigation and reproducibility

- `inspect_nyc.py`: Rhino-side extraction and helper self-checks; run through the installed Rhino Python bridge.
- `evidence/inventory.json`: initial filenames, sizes, and modification timestamps.
- `evidence/results.json`: completed file summaries and handled extraction failures.
- `evidence/NYC_3DModel_*.json`: source metadata, per-layer census, sampled validation, representative GUIDs, distributions, and area cross-checks.
- `evidence/*-footprints.csv`: individual footprint measurements.
- `evidence/*-height-proxies.csv`: spatially associated height proxies and match counts.
- `evidence/progress.json`: worker checkpoint, not a statement that every deliverable has been reviewed.

Early pilot passes exposed optional creation-date exceptions and several layer-name conventions. Those cases are handled explicitly; a normalization pass regenerates earlier results with the final schema. Invalid creation metadata is recorded as a metadata issue rather than being taken as proof of invalid geometry. Extraction errors and recovery history remain distinguishable from defects in source objects.

## Limits that survive a successful run

No complete manifold/normal/self-intersection audit, parcel-to-building linkage, street-network reconstruction, citywide deduplication, GIS registration proof, contemporary site verification, structural analysis, or printability certification is claimed. No source Grasshopper construction history or architectural intent is recovered from flattened geometry.
