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

> Discover how Arnis's tag-based algorithm sets map element processing priority. Learn how buildings get prioritized over highways for efficient rendering.

- Repository: [Louis Erbkamm/arnis](https://github.com/louis-e/arnis)
- Tags: internals
- Published: 2026-03-20

---

**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`](https://github.com/louis-e/arnis/blob/main/src/osm_parser.rs). This array lists six specific OSM tags in order of descending importance:

```rust
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)](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.

```rust
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)](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`](https://github.com/louis-e/arnis/blob/main/src/main.rs)), the sort ensures correct ground-level construction:

```rust
.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)](https://github.com/louis-e/arnis/blob/main/src/main.rs#L162))*

The GUI rendering system ([`src/gui.rs`](https://github.com/louis-e/arnis/blob/main/src/gui.rs)) applies identical logic to maintain visual consistency during preview:

```rust
.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)](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:

```rust
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:

```rust
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`](https://github.com/louis-e/arnis/blob/main/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`](https://github.com/louis-e/arnis/blob/main/src/main.rs) and [`src/gui.rs`](https://github.com/louis-e/arnis/blob/main/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`](https://github.com/louis-e/arnis/blob/main/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`](https://github.com/louis-e/arnis/blob/main/src/osm_parser.rs), these unmatched elements effectively become background details that fill remaining space without interfering with critical infrastructure.