1

The entire process is quite a bit more complex than the question, so let me briefly describe it:

An SVG overlay of map features is parsed.

Each path is converted to WKT using SVG-to-WKT and then parsed into a GeoJSON Polygon by Terraformer.

The coordinates of that Polygon are each converted from pixel values to latitude and longitude using the below function pixelToLatLng (I forgot which article I derived that from). The pixel size was completely arbitrary and I don't particularly like that solution, especially as I haven't tested with other SVGs.

function pixelToLatLng(coords) {
    var pixelSize = 0.00002;
    var upperLeftCoord = [151.3358, -32.6615]; // Reference point for SVG viewbox
    var x = upperLeftCoord[0] + (parseFloat(coords[0]) * pixelSize);
    var y = upperLeftCoord[1] + (parseFloat(coords[1]) * pixelSize);
    return [x, y];
}

These values are used to create a Feature and in turn a FeatureCollection which is then added to a Google Maps data layer.

The issue is that the drawn data layers are slightly stretched vertically. I realise this is due to the mercator projection, but I'm having trouble determining what I need to convert and at what point I should do it.

  • I assume your SVG is supposed to have no projection, meaning it is simply a 2D overlay? Can you clarify your objective? Do you want this as an overlay specifically on google maps? I'm unsure if what you want to do is georeference your 2D overlay, of if you already have projected information that you just need to reproject. It might be possible to streamline your workflow and avoid loss of information to get better results. – Senshi Jan 22 '18 at 9:33
  • 1
    @Senshi The objective is to display a masterplan of a property development using the Google Maps API. We intended to just inject the SVG, but performance was a big issue. So I decided to split the SVG into multiple data layers that I could manipulate and style individually. The SVG, when viewed in Illustrator, matches the layout of Google Maps, so perhaps when converting to WKT it assumes the SVG was already projected. Admittedly this process was sort of thrown together as I am learning as I go. If I am making it unnecessarily complicated please let me know. – Bobe Jan 22 '18 at 9:45
  • How did this SVG come into being? Was it created as a simple 2D plan with no projection that you now want to overlay on a basemap, or was it created with a geographic projection already in place? Was a background map used to draw the SVG, and if so, does that background map have a specific projection? Is SVG the only source, or did you transform it into SVG in the first place and have access to other source data formats? SVG is very uncommon to be used for geographic planning. – Senshi Jan 22 '18 at 10:01
  • 1
    When I say SVG I do of course mean an Adobe Illustrator file, but I am only treating it as an SVG. The original SVG (with all the bells and whistles) was created by a third party for the client and supplied to us. We are in the process of stripping it down to make it presentable for the web, so that we can go back to them and they can produce the rest in this manageable format. I don't know what they used as that basis of the plan, I have my account lead investigating that. All I have to go on is that the SVG appears to align with Google Maps before being converted. – Bobe Jan 22 '18 at 10:21
1

Thanks to your expanded comments, I think I found the culprit.

I'll give you my reasoning, as well as a tl;dr in the last paragraph:

If the svg "just fits" when loading it into google maps, then the drawing has very likely been made using the same projection as a source.

I assume the SVG viewbox to be the troublemaker here. You already correctly realized that using an arbitrary pixelSize that "seems to fit" is suspect, as well. It certainly always is odd when dealing with geographic projections.

You indicate [151.3358, -32.6615] as the upper left coordinate for the viewbox. This is odd (why would it be negative?). A quick lookup tells me that if I read this is as a LatLng coord, it'll be in the middle of New York (possible your area of interest?). So the SVG viewbox seems to have been used by your 3rd party creator to take care of the "geographic" transformation.

To properly replicate this, you will need to consider the entire svg viewbox.

SVG uses the viewbox to automatically transform all its contents (relocate & stretch). I assume all your paths are inside this viewbox.

Solution: Check the dimensions of your viewbox. It should have four values: x, y, width, height Calculate the pixel size from that! I'm fairly certain you will see that your viewbox is not a square, but a rectangle. You can use that to calculate the horizontal and vertical scale of your svg. Then, having the proper no-longer-square pixels, you just need to apply the scale to fit your geographic target area (what's the extent North-South and West-East?) which will be the multiplier that you need to use for your code snippet.

function pixelToLatLng(coords, scale_x, scale_y) {
    var upperLeftCoord = [151.3358, -32.6615]; // Reference point for SVG viewbox
    var x = upperLeftCoord[0] + (parseFloat(coords[0]) * scale_x);
    var y = upperLeftCoord[1] + (parseFloat(coords[1]) * scale_y);
    return [x, y];
}

What you have now is a (very simple) affine transformation, a common reprojection technique.

  • I really appreciate your help, but I'm still having trouble. To clarify, the upper left coordinate is a point on the map where I expect the contents of the SVG to be drawn relative to the upper left corner of the viewbox. This is actually swapped around since GeoJSON expects [lng, lat] for some reason. I can calculate the aspect ratio of the viewbox (in my case 1.25), but I don't understand how that replaces the random pixelSize variable, I still need some multiplier to reduce the values. Applying the ratio to the x values now just leaves the layers skewed horizontally. – Bobe Jan 23 '18 at 2:08
  • Whenever you swap x and y (or Lat and Lng), you'll have to swap all of them. Try swapping coords[0] and coords[1] in your original code. – Senshi Jan 23 '18 at 8:20
  • All the coordinates that end up in the GeoJSON are in [long, lat] format. If I swap coords[0] and coords[1] the overlay just flips vertically and horizontally. Right now I'm just trying to figure out how to calculate the adjustment to the coordinates based on the latitude. – Bobe Jan 25 '18 at 4:51

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.