# catalog/operations/vector/spatial_containment.yaml

id: vector_spatial_containment
name: Spatial Containment Hierarchy
description: >
  Build a parent-child hierarchy based on spatial containment relationships.
  Determines which features contain (or mostly contain) other features,
  creating a hierarchical structure (e.g., Z1 major drainages containing Z2 sub-drainages).
version: 1.0.0
category: vector
type: vector-to-vector
default_implementation: native

inputs:
  - name: parent_features
    type: vector
    format: geojson
    geometry: Polygon
    description: Candidate parent features (larger, containing features)
    required: true

  - name: child_features
    type: vector
    format: geojson
    geometry: Polygon
    description: Candidate child features (smaller, contained features)
    required: true

# Structural op — operates on any pair of vector polygon sets.
requires: {}

outputs:
  - name: children_with_parents
    type: vector
    format: geojson
    geometry: Polygon
    description: Child features with parent_id and parent_name attributes

  - name: hierarchy_edges
    type: vector
    format: geoparquet
    geometry: null
    description: Parent-child relationships as graph edges
    properties:
      child_id:
        type: string
      parent_id:
        type: string
      containment_ratio:
        type: number
        description: Fraction of child area contained by parent (0-1)
      relationship:
        type: string
        enum: [contains, mostly_contains, overlaps]

params:
  parent_id_column:
    type: string
    default: id
    description: Column in parent_features containing unique identifier

  parent_name_column:
    type: string
    default: name
    description: Column in parent_features containing name

  child_id_column:
    type: string
    default: id
    description: Column in child_features containing unique identifier

  min_containment_ratio:
    type: number
    default: 0.5
    min: 0.0
    max: 1.0
    description: >
      Minimum fraction of child area that must be within parent
      for a containment relationship. 0.5 = majority containment.

  output_parent_id_column:
    type: string
    default: parent_id
    description: Output column for parent identifier

  output_parent_name_column:
    type: string
    default: parent_name
    description: Output column for parent name

  allow_multiple_parents:
    type: boolean
    default: false
    description: >
      If true, a child can have multiple parents (creates multiple edges).
      If false, assign to single best-matching parent.

cache_policy:
  ttl_days: 30
  invalidate_on: [source_update, param_change]

# backends: audited 2026-08-14 (defect 50). A key means a runtime that DISPATCHES this op —
# folia-engine `dispatch_op` (products/sdk/folia-engine/src/lib.rs), a `registerOp`/OP_TABLE
# entry in packages/compute, `_BUILTIN_OP_MAP` in folia/compute.py, or a backend manifest
# (folia/backends/*/backend.yaml).
backends:
  js:
    function: vector_spatial_containment
    dispatch: packages/compute/src/ops/wasm-bridge.ts
  python:
    function: geo.vector.spatial_containment
    dispatch: folia/compute.py _BUILTIN_OP_MAP

display_hints:
  map:
    renderer: maplibre
    type: fill
    paint:
      fill-color: "rgba(32, 178, 170, 0.3)"
      fill-outline-color: "#20B2AA"
  table:
    renderer: tanstack-table

ui:
  icon: sitemap
  color: "#20B2AA"
