{{announcement.body}}
{{announcement.title}}

Requesting a HERE Map Image With HTTP and Golang

DZone 's Guide to

Requesting a HERE Map Image With HTTP and Golang

In this post, we cover how to use Golang and HTTP requests to the HERE API to integrate an interactive map into an application.

· Web Dev Zone ·
Free Resource

HERE Map API

At events, I often get asked about generating map images using server-side technologies, or basically any technology that isn't client facing like JavaScript, Android, and iOS. For example, a common request is around providing criteria for a map to be generated as part of a script, report, or similar. Let me show you how.

HERE does have a REST API known as the HERE Map Image API and it is consumed through HTTP requests. This API can generate standard map images or map images that include map objects such as polylines, polygons, or similar. Essentially, if you can produce it with the JavaScript SDK on an interactive map, you can produce it on a map image.

While REST APIs can be consumed in pretty much any technology, we're going to have a look at using the Go programming language to create map images. To get a better idea of what we hope to accomplish, take the following image:

HERE Map API

We're going to request a map image that contains a polygon. We'll be able to specify the sizing information for this image as well.

Understanding the HERE Map Image API

Before we jump into the Go code, we should probably understand a little more about the HERE Map Image API. Since this is a REST API, there will be different endpoints for accomplishing different things. A list of those possible endpoints can be found here. For this example, we'll be focusing on the region endpoint.

Try executing the following command with cURL after swapping out the app id and app code with your own:

curl https://image.maps.api.here.com/mia/1.6/region?a0=37.739700%2C-121.425200%2C37.797400%2C-121.216100%2C37.639100%2C-120.996900%2C37.739700%2C-121.425200&app_code=APP_CODE_HERE&app_id=APP_ID_HERE&h=720&ppi=320&w=1280&z=11

Generating an app id and app code is free and can be done in the HERE Developer Portal. After executing the command, you'll notice that it created exactly what we saw in the prior image at the top of this tutorial.

The request made use of a few parameters. The a0 parameter represents the area to draw the polygon. It represents each of the points in the shape. The w parameter represents the output image width, along with h being for height. The ppi represents the resolution and z represents the zoom on the map. The a0 is probably the most complicated part of this request.

So now we should probably make something useful out of this API.

Developing an Application With the Go Programming Language

We won't be doing anything fancy in our Golang application. We'll just be constructing a request and sending it. Most of the setup will be around the data model for our polygon, to make things a little easier on the developer.

Take the following data structures:

type Point struct {
    Latitude  float64
    Longitude float64
}

type Polygon struct {
    Points []Point
}

Instead of forcing someone to create that ugly a0 string by hand, we're going to create some cleaner looking data structures, as seen above. With the data structures in place, the following can be done in our main function:

func main() {
    polygon := Polygon{
        Points: []Point{
            Point{Latitude: 37.7397, Longitude: -121.4252},
            Point{Latitude: 37.7974, Longitude: -121.2161},
            Point{Latitude: 37.6391, Longitude: -120.9969},
            Point{Latitude: 37.7397, Longitude: -121.4252},
        },
    }
}

Great, so we have the points for our polygon. The problem is that our a0 parameter still expects a string. We can create some classic toString functions to take care of this.

func (point *Point) toString() string {
    return fmt.Sprintf("%f,%f", point.Latitude, point.Longitude)
}

The above function will take a point and turn it into a string where the axis is delimited by a comma. With the point being converted into a string, the entire slice of points needs to be converted. The following toString function can be created:

func (polygon *Polygon) toString() string {
    var result string
    var points []string
    for _, point := range polygon.Points {
        points = append(points, point.toString())
    }
    result = strings.Join(points, ",")
    return result
}

In the above function, we are looping through each of our points, converting them into strings, and then joining the slice of strings into one string delimited by a comma.

If we wanted to, we could do the following:

func main() {
    polygon := Polygon{
        Points: []Point{
            Point{Latitude: 37.7397, Longitude: -121.4252},
            Point{Latitude: 37.7974, Longitude: -121.2161},
            Point{Latitude: 37.6391, Longitude: -120.9969},
            Point{Latitude: 37.7397, Longitude: -121.4252},
        },
    }
    fmt.Println(polygon.toString())
}

Now that the data is properly formatted, it is time to create a request. It is best to create a separate function for this, maybe calling it a GetMapWithPolygon function like the following:

func GetMapWithPolygon(output string, geometry string) {
    endpoint, _ := url.Parse("https://image.maps.api.here.com/mia/1.6/region")
    queryParams := endpoint.Query()
    queryParams.Set("app_id", "APP-ID-HERE")
    queryParams.Set("app_code", "APP-CODE-HERE")
    queryParams.Set("ppi", "320")
    queryParams.Set("w", "1280")
    queryParams.Set("h", "720")
    queryParams.Set("z", "11")
    queryParams.Set("a0", geometry)
    endpoint.RawQuery = queryParams.Encode()
    response, err := http.Get(endpoint.String())
    if err != nil {
        fmt.Printf("The HTTP request failed with error %s\n", err)
    } else {
        f, _ := os.Create(output)
        data, _ := ioutil.ReadAll(response.Body)
        f.Write(data)
        defer f.Close()
    }

While long, the above function is just creating a URL string with query parameters. Each of the query parameters is what we've already seen in the raw request. For more information on consuming data from web services with Go, check out a tutorial I wrote titled, Consume RESTful API Endpoints within a Golang Application.

After executing the request, if it didn't fail, an output file is created and the response body is saved directly to the file. The response body should be image data.

func main() {
    polygon := Polygon{
        Points: []Point{
            Point{Latitude: 37.7397, Longitude: -121.4252},
            Point{Latitude: 37.7974, Longitude: -121.2161},
            Point{Latitude: 37.6391, Longitude: -120.9969},
            Point{Latitude: 37.7397, Longitude: -121.4252},
        },
    }
    GetMapWithPolygon("map.jpg", polygon.toString())
}

The above main function makes use of the new GetMapWithPolygon polygon function.

Conclusion

You just saw how to use the HERE Map Image API with the Go programming language. This example was probably a bit overkill because it is only a single request to a REST API, but it is a common question that I receive at events. Knowing how to generate map images as needed can be a useful ability.

Topics:
web dev ,golang tutorials ,http tutorial ,api integration ,web application development

Published at DZone with permission of

Opinions expressed by DZone contributors are their own.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}