How CoordTransformer Converts Geographic Latitude and Longitude to Minecraft XZ Coordinates in Arnis
CoordTransformer converts geographic latitude and longitude to Minecraft XZ coordinates by calculating relative positions within a geographic bounding box and scaling them by ground distance factors to produce Minecraft block coordinates.
Arnis is an open-source project that generates Minecraft worlds from real-world OpenStreetMap data. The CoordTransformer module in src/coordinate_system/transformation.rs handles the critical task to convert geographic latitude and longitude to Minecraft XZ coordinates, bridging real-world geographic data with Minecraft's Cartesian plane.
The Three-Stage Conversion Process
The transformation operates in three distinct stages: initializing the transformer with geographic bounds, computing relative positions and scale factors, and transforming individual points to Minecraft XZ coordinates.
Stage 1: Initializing the Transformer with Geographic Bounds
The process begins with CoordTransformer::llbbox_to_xzbbox, which takes an LLBBox (latitude/longitude bounding box) and a user-defined scale factor. This method establishes the transformation parameters by:
- Using
geo_distanceto compute the ground distance in meters between the bounding box's opposite corners for both latitude (north-south) and longitude (east-west) axes. - Multiplying these distances by the
scalefactor to createscale_factor_xandscale_factor_z, which represent how many Minecraft blocks correspond to real-world meters. - Storing the bounding box dimensions (
len_lat,len_lng) and minimum corner coordinates (min_lat,min_lng) for subsequent relative calculations.
// src/coordinate_system/transformation.rs#L23-L50
pub fn llbbox_to_xzbbox(
llbbox: &LLBBox,
scale: f64,
) -> Result<(CoordTransformer, XZBBox), String> {
let (scale_factor_z, scale_factor_x) = geo_distance(llbbox.min(), llbbox.max());
let scale_factor_z: f64 = scale_factor_z.floor() * scale;
let scale_factor_x: f64 = scale_factor_x.floor() * scale;
// ...
Ok((
Self {
len_lat: llbbox.max().lat() - llbbox.min().lat(),
len_lng: llbbox.max().lng() - llbbox.min().lng(),
scale_factor_x,
scale_factor_z,
min_lat: llbbox.min().lat(),
min_lng: llbbox.min().lng(),
},
xzbbox,
))
}
Stage 2: Computing Relative Positions and Scale Factors
Once the transformer is initialized, it retains the geographic bounds and scale factors. The scale_factor_x corresponds to the east-west (longitude) axis, while scale_factor_z corresponds to the north-south (latitude) axis. These factors convert real-world meter distances into Minecraft block counts based on the user-provided scale.
Stage 3: Transforming Individual Points to Minecraft XZ
The CoordTransformer::transform_point method converts individual LLPoint instances to XZPoint coordinates through relative positioning:
- Calculate relative position: Compute where the point lies within the bounding box as a percentage (0.0 to 1.0) of the total width and height.
- Invert the Z-axis: Subtract the latitude percentage from 1.0 because Minecraft's Z-axis increases southward while latitude increases northward.
- Apply scale factors: Multiply the relative positions by
scale_factor_xandscale_factor_zto obtain Minecraft block coordinates. - Convert to integers: Cast the results to
i32to produce discrete block positions.
// src/coordinate_system/transformation.rs#L53-L62
pub fn transform_point(&self, llpoint: LLPoint) -> XZPoint {
let rel_x: f64 = (llpoint.lng() - self.min_lng) / self.len_lng;
let rel_z: f64 = 1.0 - (llpoint.lat() - self.min_lat) / self.len_lat;
let x: i32 = (rel_x * self.scale_factor_x) as i32;
let z: i32 = (rel_z * self.scale_factor_z) as i32;
XZPoint::new(x, z)
}
Implementation Details and Code Structure
The llbbox_to_xzbbox Method
This constructor method in src/coordinate_system/transformation.rs serves as the entry point for creating a coordinate transformer. It validates the geographic bounding box and computes the scale factors using the Haversine-based geo_distance function to determine real-world distances between coordinates.
The transform_point Method
This method performs the actual coordinate conversion. It handles the axis inversion necessary to reconcile geographic coordinate systems (where latitude increases northward) with Minecraft's coordinate system (where Z decreases northward). The method returns an XZPoint containing i32 values suitable for Minecraft block placement.
Legacy Compatibility Function
The codebase maintains lat_lon_to_minecraft_coords as a standalone function for backward compatibility and verification purposes. The test suite asserts that transform_point produces identical results to this legacy implementation, ensuring functional equivalence while providing a more object-oriented interface.
// src/coordinate_system/transformation.rs#L99-L120
pub fn lat_lon_to_minecraft_coords(
lat: f64,
lon: f64,
bbox: LLBBox,
scale_factor_z: f64,
scale_factor_x: f64,
) -> (i32, i32) {
// Legacy implementation for comparison
}
Practical Usage Example
The following example demonstrates how to initialize a CoordTransformer and convert geographic coordinates to Minecraft XZ coordinates:
use arnis::coordinate_system::{
geographic::{LLBBox, LLPoint},
transformation::CoordTransformer,
};
fn main() -> Result<(), Box<dyn std::error::Error>> {
// Define the geographic area to map (e.g., Munich city centre)
let llbbox = LLBBox::new(
LLPoint::new(48.1351, 11.5760)?, // min lat, min lng
LLPoint::new(48.1551, 11.5960)?, // max lat, max lng
)?;
// Build a transformer with a desired scale (1 Minecraft block ≈ 1 metre)
let scale = 1.0;
let (transformer, _xz_bbox) = CoordTransformer::llbbox_to_xzbbox(&llbbox, scale)?;
// Convert a latitude/longitude inside the bbox to Minecraft X‑Z
let point = LLPoint::new(48.1450, 11.5860)?;
let xz = transformer.transform_point(point);
println!("Minecraft coordinates: X = {}, Z = {}", xz.x, xz.z);
Ok(())
}
You can also verify the results using the legacy helper function:
let (scale_factor_z, scale_factor_x) = arnis::coordinate_system::transformation::geo_distance(
llbbox.min(),
llbbox.max(),
);
let (x, z) = arnis::coordinate_system::transformation::lat_lon_to_minecraft_coords(
point.lat(),
point.lng(),
llbbox,
scale_factor_z.floor() * scale,
scale_factor_x.floor() * scale,
);
assert_eq!((xz.x, xz.z), (x, z));
Key Source Files
| File | Role |
|---|---|
src/coordinate_system/transformation.rs |
Contains CoordTransformer, llbbox_to_xzbbox, transform_point, distance helpers, and the legacy conversion function. |
src/coordinate_system/geographic/llpoint.rs |
Represents a single latitude/longitude point (LLPoint). |
src/coordinate_system/geographic/llbbox.rs |
Bounding-box wrapper (LLBBox) used to define the geographic extents. |
src/coordinate_system/cartesian/xzpoint.rs |
Simple struct for Minecraft X‑Z coordinates (XZPoint). |
src/coordinate_system/cartesian/xzbbox/mod.rs |
Defines the Minecraft‑world bounding box (XZBBox). |
These components together enable Arnis to map real-world map data onto Minecraft worlds with precise, reproducible coordinate transformations.
Summary
- CoordTransformer serves as the core engine to convert geographic latitude and longitude to Minecraft XZ coordinates in the Arnis project.
- The three-stage process involves initializing the transformer with a geographic bounding box, computing ground distance scale factors using
geo_distance, and applying relative positioning calculations viatransform_point. - Axis inversion is handled automatically: latitude increases northward in geographic coordinates, but the Z-axis increases southward in Minecraft, requiring the
1.0 - relative_latcalculation. transform_pointreturnsi32block coordinates directly suitable for Minecraft world generation.- Legacy compatibility is maintained through
lat_lon_to_minecraft_coords, which validates the modern implementation against historical behavior.
Frequently Asked Questions
How does CoordTransformer handle the scale factor between real-world meters and Minecraft blocks?
The scale factor is applied during the initialization phase in llbbox_to_xzbbox. The method calculates the ground distance in meters between the geographic bounding box corners using geo_distance, then multiplies these distances by the user-provided scale parameter to produce scale_factor_x and scale_factor_z. A scale of 1.0 means one Minecraft block equals approximately one real-world meter.
Why does the Z coordinate calculation subtract the relative latitude from 1.0?
Minecraft's coordinate system defines the Z-axis as positive toward the south, while geographic latitude increases toward the north. To reconcile these opposing directions, transform_point calculates the relative position as (lat - min_lat) / len_lat, then inverts it with 1.0 - relative_lat. This ensures that northern geographic coordinates map to lower Z values in Minecraft, maintaining correct directional orientation.
Can I use the legacy conversion function instead of CoordTransformer?
Yes, the legacy function lat_lon_to_minecraft_coords remains available in src/coordinate_system/transformation.rs for backward compatibility. However, the modern CoordTransformer approach is recommended because it encapsulates the bounding box and scale factors within a reusable struct, eliminating the need to pass these parameters repeatedly for each point conversion. The test suite verifies that both methods produce identical results.
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:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →