{"id":1054,"date":"2016-05-01T21:40:26","date_gmt":"2016-05-02T04:40:26","guid":{"rendered":"http:\/\/www.patrickmatte.com\/?p=1054"},"modified":"2023-11-03T15:04:44","modified_gmt":"2023-11-03T22:04:44","slug":"earth-made-of-dots","status":"publish","type":"post","link":"https:\/\/www.patrickmatte.com\/?p=1054","title":{"rendered":"Earth made of dots"},"content":{"rendered":"<div class=\"text\">\n<div class=\"columnLeft\">\nI was hired to create this WebGL prototype of a globe made of evenly spaced dots that light up as you fly to any of the 236 countries on the planet.<br \/>\n<!--\nThe first challenge for this project was to create a map of all the countries made up with evenly spaced dots. The second challenge was to fly to each country and highlight the dots that make up each country.\n\nI started by searching for some data about the boundaries of every country on the planet. I found <a href='https:\/\/www.google.com\/fusiontables\/data?docid=1uL8KJV0bMb7A8-SkrIe0ko2DMtSypHX52DatEE4#rows:id=1'>this CSV file<\/a> on google which I converted to json with <a href=\"http:\/\/www.csvjson.com\/csv2json\">csv2json<\/a> It includes a list of latitude and longitude points for the boundaries of all the countries mainlands and islands.\n\nNext, in order to be able to fly out to every country, I needed to know the center of each country. Instead of trying to calculate the center of each country by looking at the country's border, I simply looped through the 236 countries included in the boundaries CSV file and queried the google geocoding API with the name of each country to get the latitude and longitude.\n\nSo now that I had all the data I needed for the countries, I could start creating the map of dots. I figured that the easiest way to do this was to use a geodesic sphere because it is made of very similar triangles. Fortunately, three.js has a great geodesic sphere object so I didn't have to figure out an equation to create the triangles. All I had to do was to create a sphere, then loop through all its vertices and create a little plane at the same position and use a circle as the texture for that plane. Since every dot would have to be highlighted, I planned ahead and created a canvas with two dots of different color. I set the plane's texture indices to include only the circle on the left. To highlight a dot, I would just modify the indices of each planes so they show only the circle of the right.\n\nNow that I had a sphere with dots all over it, I needed to filter out the dots which are not part of countries. I found this black and white image of all the oceans and rivers on earth, I looped through all the dots on the globe and mapped their positions on the image and checked the darkness of the pixel on the image, if the pixel was at least 50% gray, I would put the dot on the sphere, otherwise ignore it. This solution worked but in the end, I figured that I should have used the country borders to filter out the dots but I was afraid that the 236 countries might not represent all of the earth land.\n--><\/div>\n<div class=\"columnRight\">\n<!--\nSo finally I had a globe with the countries made of dots. Almost done. All that was left to do was to highlight the dots for each country. I had to loop through all the dots of the globe, find their latitude and longitude and see if they were contained in the country's boundary. I found out that the Canvas API already has a method to detect if a point is contained inside a complex polygon. All you have to do is to create a path with a canvas context, then call context.isPointInPath(x, y). This method was so handy, I just had to convert the latitude and longitude of each dot on the sphere to the x and y point on a flat 2D canvas, so latitude 90 and longitude -180 was equal to (0px,0px) on the canvas. Looping through all the islands of the earth for each dot on the globe was a long process for large countries like USA, Russia and Canada, sometimes it would freeze the app for up to five seconds so it didn't work well in real-time. I ended up creating a json file that included an array of dots that composed every country, highlighting any country was then done in a split-second.\n\nThe process was a little complex but in the end, everything worked out pretty well, you can fly to any of the 236 countries and it will light up when you get there, given it's big enough to have a dot on the globe.\n--><\/div>\n<\/div>\n<div id=\"entry-header\" style=\"position:relative; padding-top:56.25%;\">\n<iframe class=\"fixedRatio\" src=\"https:\/\/patrickmatte.com\/work\/space150\/globe\/\" frameborder=\"0\" webkitallowfullscreen=\"\" mozallowfullscreen=\"\" allowfullscreen=\"\"><\/iframe><\/div>\n","protected":false},"excerpt":{"rendered":"<p>I was hired to create this WebGL prototype of a globe made of evenly spaced dots that light up as you fly to any of the 236 countries on the planet.<\/p>\n","protected":false},"author":1,"featured_media":1079,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[53],"tags":[31,63,45,65,64],"class_list":["post-1054","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-projects","tag-3d","tag-canvas","tag-javascript","tag-threejs","tag-webgl"],"_links":{"self":[{"href":"https:\/\/www.patrickmatte.com\/index.php?rest_route=\/wp\/v2\/posts\/1054"}],"collection":[{"href":"https:\/\/www.patrickmatte.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.patrickmatte.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.patrickmatte.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.patrickmatte.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=1054"}],"version-history":[{"count":13,"href":"https:\/\/www.patrickmatte.com\/index.php?rest_route=\/wp\/v2\/posts\/1054\/revisions"}],"predecessor-version":[{"id":1239,"href":"https:\/\/www.patrickmatte.com\/index.php?rest_route=\/wp\/v2\/posts\/1054\/revisions\/1239"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.patrickmatte.com\/index.php?rest_route=\/wp\/v2\/media\/1079"}],"wp:attachment":[{"href":"https:\/\/www.patrickmatte.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=1054"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.patrickmatte.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=1054"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.patrickmatte.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=1054"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}