A spatial graph—Yog.Graph enriched with coordinate system metadata
and an optional spatial bounding box.
Implements Enumerable (iterates over {id, data} node tuples) and
Inspect (compact #Meridian.Graph<...> representation).
Fields
graph— the underlyingYog.Graph.t()crs— coordinate reference system identifier (default"EPSG:4326")srid— numeric SRID when available (default4326)bounds— bounding geometry (%Geo.Polygon{}ornil)
Examples
iex> g = Meridian.Graph.new()
iex> g.crs
"EPSG:4326"
iex> g.srid
4326
iex> g = Meridian.Graph.new() |> Meridian.Graph.add_node(1, %{name: "A"})
iex> Enum.to_list(g)
[{1, %{name: "A"}}]
Summary
Functions
Adds a spatial edge to the graph.
Adds a spatial edge to the graph, raising on error.
Ensures both endpoint nodes exist, then adds an edge.
Adds a spatial node to the graph.
Adds multiple nodes from an enumerable of {id, data} tuples or a map.
Returns the number of edges in the spatial graph.
Returns all edges as a list of {from, to, weight} tuples.
Wraps an existing Yog.Graph as a spatial graph.
Checks if a node has a :geometry key in its data.
Checks if the graph contains a node with the given ID.
Returns the kind of the underlying graph (:directed or :undirected).
Merges another spatial graph into this one.
Creates a new empty spatial graph.
Returns the data associated with a node, or nil if the node does not exist.
Returns the number of nodes in the spatial graph.
Returns all nodes as a map of id => data.
Recomputes the bounding box from all node geometries.
Removes an edge from the graph.
Removes a node and all its connected edges.
Unwraps a Meridian.Graph to its underlying Yog.Graph.
Updates a node's data by merging the given map into the existing data.
Types
@type crs() :: String.t()
@type srid() :: pos_integer() | nil
@type t() :: %Meridian.Graph{ bounds: Geo.Polygon.t() | nil, crs: crs(), graph: Yog.Graph.t(), srid: srid() }
Functions
@spec add_edge(t(), Yog.node_id(), Yog.node_id(), any()) :: {:ok, t()} | {:error, String.t()}
Adds a spatial edge to the graph.
Examples
iex> g = Meridian.Graph.new()
iex> g = g |> Meridian.Graph.add_node(:a, %{}) |> Meridian.Graph.add_node(:b, %{})
iex> {:ok, g} = Meridian.Graph.add_edge(g, :a, :b, %{distance: 10.5})
iex> g.graph.out_edges[:a][:b]
%{distance: 10.5}
@spec add_edge!(t(), Yog.node_id(), Yog.node_id(), any()) :: t()
Adds a spatial edge to the graph, raising on error.
@spec add_edge_ensure(t(), Yog.node_id(), Yog.node_id(), any(), any()) :: t()
Ensures both endpoint nodes exist, then adds an edge.
If from or to is not already in the graph, it is created with the
supplied default node data. Existing nodes are left unchanged.
@spec add_node(t(), Yog.node_id(), map()) :: t()
Adds a spatial node to the graph.
data should typically contain a :geometry key with a Geo struct.
Examples
iex> g = Meridian.Graph.new()
iex> point = %Geo.Point{coordinates: {-73.9857, 40.7484}}
iex> g = Meridian.Graph.add_node(g, :nyc, %{geometry: point, name: "NYC"})
iex> Meridian.Graph.node(g, :nyc).name
"NYC"
@spec add_nodes(t(), Enumerable.t()) :: t()
Adds multiple nodes from an enumerable of {id, data} tuples or a map.
Examples
iex> g = Meridian.Graph.new()
iex> g = Meridian.Graph.add_nodes(g, a: %{geometry: %Geo.Point{coordinates: {0.0, 0.0}}})
iex> Meridian.Graph.node_count(g)
1
@spec edge_count(t()) :: non_neg_integer()
Returns the number of edges in the spatial graph.
@spec edges(t()) :: [{Yog.node_id(), Yog.node_id(), any()}]
Returns all edges as a list of {from, to, weight} tuples.
@spec from_yog( Yog.Graph.t(), keyword() ) :: t()
Wraps an existing Yog.Graph as a spatial graph.
Examples
iex> yog = Yog.undirected() |> Yog.add_edge_ensure(1, 2, 10)
iex> g = Meridian.Graph.from_yog(yog, crs: "EPSG:4326")
iex> g.graph == yog
true
@spec has_geometry?(t(), Yog.node_id()) :: boolean()
Checks if a node has a :geometry key in its data.
@spec has_node?(t(), Yog.node_id()) :: boolean()
Checks if the graph contains a node with the given ID.
@spec kind(t()) :: :directed | :undirected
Returns the kind of the underlying graph (:directed or :undirected).
Merges another spatial graph into this one.
Both graphs must share the same CRS. Nodes and edges from other are
added; in case of node ID collisions, other's data wins.
Examples
iex> a = Meridian.Graph.new() |> Meridian.Graph.add_node(1, %{name: "A"})
iex> b = Meridian.Graph.new() |> Meridian.Graph.add_node(2, %{name: "B"}) |> Meridian.Graph.add_edge_ensure(2, 1, 5)
iex> merged = Meridian.Graph.merge(a, b)
iex> Meridian.Graph.node_count(merged)
2
iex> Meridian.Graph.edge_count(merged)
1
Creates a new empty spatial graph.
Options
:kind—:directed(default) or:undirected:crs— CRS identifier string, defaults to"EPSG:4326":srid— numeric SRID, defaults to4326
Examples
iex> g = Meridian.Graph.new()
iex> g.graph.kind
:directed
iex> g = Meridian.Graph.new(kind: :undirected, crs: "EPSG:3857")
iex> g.crs
"EPSG:3857"
@spec node(t(), Yog.node_id()) :: any() | nil
Returns the data associated with a node, or nil if the node does not exist.
@spec node_count(t()) :: non_neg_integer()
Returns the number of nodes in the spatial graph.
@spec nodes(t()) :: %{required(Yog.node_id()) => any()}
Returns all nodes as a map of id => data.
Recomputes the bounding box from all node geometries.
@spec remove_edge(t(), Yog.node_id(), Yog.node_id()) :: t()
Removes an edge from the graph.
@spec remove_node(t(), Yog.node_id()) :: t()
Removes a node and all its connected edges.
@spec to_yog(t()) :: Yog.Graph.t()
Unwraps a Meridian.Graph to its underlying Yog.Graph.
Examples
iex> g = Meridian.Graph.new() |> Meridian.Graph.add_node(1, "A")
iex> %Yog.Graph{} = Meridian.Graph.to_yog(g)
@spec update_node(t(), Yog.node_id(), map()) :: t()
Updates a node's data by merging the given map into the existing data.
Returns the updated graph. If the node does not exist, it is created.
Examples
iex> g = Meridian.Graph.new() |> Meridian.Graph.add_node(:a, %{name: "A"})
iex> g = Meridian.Graph.update_node(g, :a, %{tags: [:highway]})
iex> Meridian.Graph.node(g, :a).tags
[:highway]