Skip to content

Add latitude, longitude to Berlin-Center network#64

Open
michael-markl wants to merge 2 commits intobstabler:masterfrom
michael-markl:master
Open

Add latitude, longitude to Berlin-Center network#64
michael-markl wants to merge 2 commits intobstabler:masterfrom
michael-markl:master

Conversation

@michael-markl
Copy link
Copy Markdown

@michael-markl michael-markl commented Feb 11, 2026

Hi there.

This adds (actual) coordinates in the form of latitude, longitude to the Berlin-Center network.

Method

We (@philippwarode and me), annotated some coordinates manually to map from the existing X and Y coordinates to latitude and longitude.

The following script does the conversion (using a "least squared" projection):

import pandas as pd
import numpy as np

file_path = "berlin-center_node.tntp"
df = pd.read_csv(file_path, sep='\\s+', names=["Node", "X", "Y"], header=0, index_col=False)


point_pairs = [
    (
        (30.3472, 15.5548),
        (52.48451118111, 13.4795021186)
    ),
    (
        (15.0876, 23.8881),
        (52.6089911679386, 13.12120813435784)
    ),
    (
        (21.9021, 5.9863),
        (52.3486098110478, 13.27550789714637)
    ),
    (
        (22.5198, 16.915),
        (52.5064096135837, 13.294727326071)
    ),
    (
        (29.1741, 20.9011),
        (52.56221199420036, 13.45425618012204)
    )
]

def compute_transformation_matrix():
    # Calculate the coefficients for the affine transformation
    A = np.array([(x,y,1) for ((x,y), _) in point_pairs])
    B = np.array([latlon for (_, latlon) in point_pairs])

    # Solve for the transformation matrix
    solution, residuals, rank, singular_values = np.linalg.lstsq(A, B, rcond=None)
    return solution

transformation_matrix = compute_transformation_matrix()
print("Transformation Matrix:\n", transformation_matrix)

def transform_xy_to_lat_lon(point):
    # Apply the transformation
    x, y = point
    lat = transformation_matrix[0, 0] * x + transformation_matrix[1, 0] * y + transformation_matrix[2, 0]
    lon = transformation_matrix[0, 1] * x + transformation_matrix[1, 1] * y + transformation_matrix[2, 1]

    # We round the numbers to avoid bloating the file.
    # We round to 7 decimals since the input has 6 significant digits, and the whole number part and the first 
    # decimal of both latitude and longitude are mostly constant.
    lat = round(lat, 7)
    lon = round(lon, 7)

    return lat, lon

# Apply the transformation to the x, y coordinates in the DataFrame
df["Lat"], df["Lon"] = zip(*df[["X", "Y"]].apply(transform_xy_to_lat_lon, axis=1))

# Append a column with header ";" and fill it with ";" for the TNTP format
df.insert(5, ";", ";")

df.to_csv("berlin-center_node_fixed.tntp", sep='\t', index=False)

This is the printed transformation matrix:

 [[-2.64907129e-04  2.37143766e-02]
 [ 1.44469375e-02  4.14005018e-04]
 [ 5.22679252e+01  1.27535993e+01]]

Result

Here's an image that shows the mapped coordinates on top of the OSM map.

And here a cropped image, with a smaller region.

@michael-markl michael-markl marked this pull request as ready for review February 11, 2026 19:34
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant