Mapping Longitude and Latitude with TopoJSON and D3

Currently utilizing the UK Geo JSON found at this link to generate a UK SVG Map.

The goal is to plot longitude and latitude points onto this map.

The GeometryCollection place is being added to the map in the following manner:

 data.objects.places = {
        type: "GeometryCollection",
        geometries: [
            {
                type: "Point",
                coordinates: [-0.127758, 51.507351], // London
                properties: {
                    name: "London - Testing"
                }
            }
        ]
    };

However, the coordinates are not aligning correctly.

JavaScript code for visualization purposes:

var width = 960;
var height = 1000;

var projection = d3.geo.albers()
        .center([0, 55.4])
        .rotate([4.4, 0])
        .parallels([50, 60])
        .scale(4000)
        .translate([width / 2, height / 2]);

var path = d3.geo.path().projection(projection);

var svg = d3.select("body").append("svg")
        .attr("width", width)
        .attr("height", height);

d3.json("topo_eer.json", function(error, data) {

    // Create path for the UK
    svg.selectAll(".subunit")
            .data(topojson.feature(data, data.objects.eer).features)
            .enter().append("path")
            .attr("class", function(d) { return "subunit " + d.id; })
            .attr("d", path);

    // Path around regions
    svg.append("path")
            .datum(topojson.mesh(data, data.objects.eer, function(a, b) { return a !== b; }))
            .attr("d", path)
            .attr("class", "subunit-boundary");

    // Add places to our data
    data.objects.places = {
        type: "GeometryCollection",
        geometries: [
            {
                type: "Point",
                coordinates: [-0.127758, 51.507351], // London
                properties: {
                    name: "London - Testing"
                }
            }
        ]
    };

    // try plotting a point
    svg.append("path")
            .datum(topojson.feature(data, data.objects.places))
            .attr("d", path)
            .attr("class", "place-online");

    console.log(data);

});

Answer №1

When dealing with TopoJSON, it's important to note that the numbers in the coordinates are not the actual latitude/longitude values and require transformation. This specific function helps transform the quantized topology into absolute coordinates:

function alterPosition(topology, point) {
    point = point.slice();
    point[0] = point[0] * topology.transform.scale[0] + topology.transform.translate[0],
    point[1] = point[1] * topology.transform.scale[1] + topology.transform.translate[1]
    return point;
};

The necessary information for this transformation can be found at the end of the TopoJSON file you provided:

"transform":
    {"scale":
        [0.000818229038834542,0.0005946917122888551],
    "translate":[-6.418556211736409,49.8647494628352]
    }

With this transformation function as a guide, creating a reverse function is straightforward:

function reverseTransformPoint(topology, point) {
    point = point.slice();
    point[0] = (point[0] - topology.transform.translate[0]) / (topology.transform.scale[0]),
    point[1] = (point[1] - topology.transform.translate[1]) / (topology.transform.scale[1]) 
    return point;
};

After testing this new function using London's coordinates, I received the following array:

[7688.309645789168, 2762.1059840278253]

Feel free to test this on your own set of coordinates to verify its effectiveness.

An alternative approach involves overlaying the TopoJSON with a GeoJSON, which operates using an absolute coordinate system.

For additional details, refer to the API documentation: https://github.com/mbostock/topojson-specification/blob/master/README.md#22-geometry-objects

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

In Angular 2, you can include a routerLink in a child component that directs to the root

Currently, I am developing a web application using Angular 2 Beta 8 and encountering an issue with nested routes while utilizing the routerLink directive. The structure of the router is as follows: AppCmp |-> NewItemFormCmp |-> UserDashboardCmp ...

Invoke a function or variable based on a string parameter within a JavaScript/React function dynamically

I am currently exploring ways to dynamically call a function based on a string or reference a variable using a string. For example: import React, {useState} from 'react' const array = [ { text: 'count1', setFunctionName: &apo ...

Different techniques for retrieving elements generated by ng-repeat from their containing parent

Let's keep it simple - imagine we have a directive called headSlides. This directive's template includes an image that is being repeated using ng-repeat: <img class="bg" ng-repeat="image in images" ng-src="{{image.src}}"> I need to access ...

Ajax sending numerous requests to the API

Recently, I began my journey of learning Javascript and decided to interact with my Django API through Ajax requests. To achieve this, I created a search bar that triggers the API call after a one-second delay following a keyup action. input.addEventListe ...

Using Svelte to effectively connect to a specified object within an array

Check out this code snippet: <script> let data = [ {id: 1, first: "x"}, {id: 2, second: "y"} ]; </script> <input type="text" bind:value={data.first}/> If you modify the value in the input field and ...

Issues with Gulp and Browser Sync integration

Encountering errors while running Gulp with Browser Sync in Chrome: NonESPMessageInterface --- nonEspMessageInterface.js:8 TypeError: Cannot read property 'insertBefore' of null --- angular.js:13708 Checklist message was invalid, from origin # ...

Display or conceal a field depending on the user's input

I need to display a checkbox only when the firstname matches abc or if the email is [email protected]. var x = abc; //will be dynamic var y = abc @gmail.com jQuery("#firstname").on('change', (function(avalue) { return function(e) { ...

Troubleshooting Bootstrap 3.0: Issues with nav-tabs not toggling

I have set up my navigation tabs using Bootstrap 3 in the following way: <ul class="nav nav-tabs pull-right projects" role="tablist" style="margin-top:20px;"> <li class="active"><a role="tab" data-toggle="tab" href="#progress">In Pr ...

implementing a webpage enhancement that enables loading content asynchronously

I find myself puzzled. Lately, I've delved into learning Spring MVC through the development of a web application designed to display live sports scores in real-time. The core functionalities are already in place, but I'm unsure about how to creat ...

Sort subcategories based on the selected category from the dropdown menu

I'm feeling a bit stuck at the moment. My goal is to show specific subcategories when a particular category is chosen from the dropdown menu. For example, let's say we have these categories: Cate1 Cate2 Under Cate1, we can find: Sub1 Sub2 an ...

React JS does not allow TextField and Select to change

I am relatively new to full stack development and I am currently working on a project to enhance my understanding of frontend development with React JS. While working on this project, I have been using Redux without any issues so far. However, I am facing ...

RxJS Observables trigger the onCompleted function after completing a series of asynchronous actions

I have been attempting to design an observable that generates values from various asynchronous actions, particularly HTTP requests from a Jenkins server, which will notify a subscriber once all the actions are finished. However, it seems like there might b ...

What is the best way to transfer an argument from a parsed JSON value to an onclick function?

In our dataset, we have a specific table that contains valuable information. My main objective is to transfer an argument extracted from parsed JSON data to a separate JavaScript function known as newStory(value['stories']) using the onclick meth ...

React Hooks: In useEffect(), unable to modify parent component's state

Within my component, I have a form for users to input a title, description, and images. This component is nested within its parent component, and I want the form data to be saved if the user switches sections and returns later without losing their progress ...

Creating Kotlin classes to utilize Gson for converting JSON responses into class objects

I have recently delved into learning Android development, with a current focus on understanding how to consume REST API's. The particular service I am tinkering with, namely The Movie Database, returns responses structured like this: { "certi ...

What is the correct method for asynchronously loading CSS files in web development?

On a mission to enhance my website's performance, I set out to achieve the perfect score on PageSpeed Insights. Everything was going smoothly until I encountered an issue with CSS delivery. I initially achieved a flawless result by utilizing the prel ...

Assign a value to a HubSpot hidden form field by utilizing Javascript

I have a snippet of JavaScript code placed in the head section of my website: <!-- Form ID Setter --> <script> document.querySelector('input[name=form_submission_id]').value = new Date(); </script> My objective is to automat ...

Is the for loop programmed to stop at the first match?

I've been working on filtering a txt file using nodejs. Here's my code snippet: const fs = require('fs') let list = fs.readFileSync('./newmR.txt', 'utf-8').split('\r\n') console.log(list.length) ...

Improve your JavaScript form by implementing a time loading feature!

I am currently developing a sign-up form using native JavaScript and Ajax. The form utilizes an Ajax function to transmit data to a PHP engine, which then performs database queries. My main concern is implementing a loading function in JavaScript that can ...

Creating a render function that includes the img.src parameter requires careful thought and consideration

I am currently working on a dilemma where I need to dynamically adjust the height and width of an image in my render() function every time there is a state change. Here is the code snippet: render() { const imageURL = photos[this.state.currentImage]. ...