How Arnis Determines Map Element Processing Priority: The Tag-Based Algorithm Explained

Arnis uses a deterministic tag-based priority array to sort OpenStreetMap elements, ensuring features like buildings and entrances are processed before highways and waterways by assigning lower index values to higher-priority tags.

The louis-e/arnis repository converts OpenStreetMap data into Minecraft worlds, requiring a strict processing order to prevent visual artifacts like roads floating above buildings. The algorithm that determines this sequence is implemented as a simple yet effective constant array lookup in Rust, guaranteeing consistent rendering across the main pipeline and GUI components.

The Priority Algorithm Implementation

Arnis decides the rendering order of OSM elements through a linear tag-matching priority system defined in the core parser module.

Defining the Priority Order

The priority hierarchy is hardcoded as a constant array in src/osm_parser.rs. This array lists six specific OSM tags in order of descending importance:

const PRIORITY_ORDER: [&str; 6] = [
    "entrance", "building", "highway", "waterway", "water", "barrier",
];

(source: [src/osm_parser.rs](https://github.com/louis-e/arnis/blob/main/src/osm_parser.rs#L998-L1004))

Elements tagged with values appearing earlier in this array receive higher processing priority. For example, "building" holds index 1, ensuring it processes before "highway" at index 2.

Calculating Element Priority

The get_priority function walks the PRIORITY_ORDER array and returns the zero-based index of the first matching tag found on the element. If no tags match, it returns the array length, assigning the element the lowest possible priority.

pub fn get_priority(element: &ProcessedElement) -> usize {
    for (i, &tag) in PRIORITY_ORDER.iter().enumerate() {
        if element.tags().contains_key(tag) {
            return i;
        }
    }
    PRIORITY_ORDER.len()
}

(source: [src/osm_parser.rs](https://github.com/louis-e/arnis/blob/main/src/osm_parser.rs#L1002-L1012))

Lower return values indicate higher priority. An entrance (index 0) processes before a building (index 1), which processes before a highway (index 2).

Applying Priority in the Processing Pipeline

Before world generation begins, Arnis sorts every ProcessedElement using the priority value returned from get_priority. This sort operation appears in multiple locations to ensure consistent ordering.

In the main generation pipeline (src/main.rs), the sort ensures correct ground-level construction:

.sort_by_key(|e: &osm_parser::ProcessedElement| osm_parser::get_priority(e));

(source: [src/main.rs](https://github.com/louis-e/arnis/blob/main/src/main.rs#L162))

The GUI rendering system (src/gui.rs) applies identical logic to maintain visual consistency during preview:

.sort_by_key(|e: &osm_parser::ProcessedElement| osm_parser::get_priority(e));

(source: [src/gui.rs](https://github.com/louis-e/arnis/blob/main/src/gui.rs#L948-L956))

Practical Code Examples

Sorting a Vector of Processed Elements

When working with the Arnis parser directly, you can sort elements using the priority function to maintain correct rendering order:

use arnis::osm_parser::{ProcessedElement, get_priority};

fn sort_elements(mut elems: Vec<ProcessedElement>) -> Vec<ProcessedElement> {
    // Elements with tags that appear earlier in PRIORITY_ORDER get a lower index
    elems.sort_by_key(|e| get_priority(e));
    elems
}

Determining Individual Element Priority

To inspect where a specific element ranks in the processing queue:

let elem: ProcessedElement = /* ... */;
let priority = arnis::osm_parser::get_priority(&elem);
println!("Element priority: {}", priority);

A return value of 0 indicates highest priority (entrance), while 6 indicates lowest priority (unmatched tags or barriers).

Why Processing Priority Matters

The specific sequence in PRIORITY_ORDER ensures visual coherence in the generated Minecraft world. By processing buildings before highways, roads naturally overlay building foundations rather than floating above them. Similarly, placing entrances at index 0 ensures doorways and access points are established before surrounding structures are finalized.

This deterministic approach prevents z-fighting and layering artifacts that would occur if elements processed in random or alphabetical order. The algorithm executes in O(n) time complexity where n is the length of PRIORITY_ORDER (constant 6), making it extremely efficient even when processing millions of OSM nodes.

Summary

  • Tag-based priority: Arnis uses a constant array PRIORITY_ORDER in src/osm_parser.rs containing six OSM tags ranked by visual importance.
  • Linear lookup: The get_priority function returns the first matching tag's index, with lower values indicating higher processing priority.
  • Consistent sorting: Both src/main.rs and src/gui.rs sort elements using .sort_by_key(|e| get_priority(e)) before rendering.
  • Visual hierarchy: Buildings (index 1) process before highways (index 2), ensuring proper ground-level construction in the final Minecraft world.

Frequently Asked Questions

How does Arnis handle map elements that match multiple priority tags?

Arnis assigns priority based on the first match in the PRIORITY_ORDER array. If an element contains both "building" and "highway" tags, it receives the building priority (index 1) because "building" appears before "highway" in the constant array. The algorithm stops checking after finding the first match to ensure deterministic, predictable ordering.

Can I modify the processing priority order in Arnis?

Yes, you can customize the rendering sequence by modifying the PRIORITY_ORDER constant in src/osm_parser.rs. Changing the array order directly affects which features render first. For example, moving "waterway" before "building" would cause rivers and canals to generate underneath structures. However, modifying this array requires recompiling the Rust source code, as the priority list is compile-time constant.

Why does Arnis process entrances before buildings?

Entrances receive the highest priority (index 0) to ensure that doorways, gates, and access points are established before the structures containing them are generated. This sequencing prevents entrance coordinates from being overwritten or blocked by building generation logic, maintaining navigable access points in the final Minecraft world according to the OpenStreetMap source data.

What happens to OSM elements that don't match any priority tags?

Elements lacking tags for "entrance", "building", "highway", "waterway", "water", or "barrier" receive a default priority equal to the array length (6). This assigns them the lowest processing priority, causing them to render after all prioritized elements. According to the source code in src/osm_parser.rs, these unmatched elements effectively become background details that fill remaining space without interfering with critical infrastructure.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →