Bxx
Bxx

Reputation: 1625

Google Static Map - Draw a Circle

Trying to create a static map with a circle like this

enter image description here

In the path parameter I do not understand how to obtain the enc part. This appears to be some encoded path that includes the lat/long and size of the circle.

https://maps.googleapis.com/maps/api/staticmap?
center=51.44208,5.47308&
zoom=14&
size=693x648&
path=color:blue|fillcolor:0x00d2c196|weight:1|
enc%3Aad_yHofn%60%40JyFh%40sF%60AcFxAmElBqD~BoCnCiBtC_AzCUzCTvC~%40lChB~BnCnBpDxAlE%60AbFf%40rFLxFMxFg%40rFaAbFyAlEoBpD_CnCmChBwC~%40%7BCT%7BCUuC_AoCiB_CoCmBqDyAmEaAcFi%40sFKyF%3F%3F

Link to Google's documentation

**EDIT: Found these:

Drawing a circle Google Static Maps

Encoded Polyline Algorithm Format

Upvotes: 2

Views: 9041

Answers (3)

Dinidiniz
Dinidiniz

Reputation: 811

All the answers with GMapCircle could create a huge URL that will make Google respond with an error. If you have 2 or more circles, will get impossible to create this static map.

To create a circle, I did a small hack, instead of a real circle what I did was just a really small line, but with brush size the same of the circle diameter. What will happen is that it will look like a circle.

My GMapCircle function:

function GMapCircle(color, lat,lng,rad, zoom){
     var staticMapSrc = '&path=color:0x' + color + '|weight:' + parseInt(rad*Math.pow(2, zoom)/72223);

     staticMapSrc += "|" + lat.toFixed(4) + "," + lng.toFixed(4);
                staticMapSrc += "|" + lat.toFixed(4) + "," + (lng + 0.0001).toFixed(4);
     return staticMapSrc
}

In the above function, I add a small 0.0001 value to the longitude just to make a line, but so small that what will matter is the size of the brush (weight).

The weight (the size of the brush) depends of the diameter you want (rad) and it will decrease with your zoom.

This will create small lines for each circle you want that will look like a circle. I can fit almost 200 circles with this code without making the URL too long.

Upvotes: 0

Lauren ten Hoor
Lauren ten Hoor

Reputation: 93

I have rewritten it in javascript (as an Angular Service).

import { Injectable } from "@angular/core";
import { HttpClient } from "@angular/common/http";
import { environment } from "environments/environment";

@Injectable({
    providedIn: "root",
})
export class StaticMapService {
    constructor(private httpClient: HttpClient) {}

    getStaticMapBase64(
        lat: number,
        lng: number,
        radius: string,
        zoom: number
    ): Promise<string> {
        return new Promise((resolve) => {
            this.httpClient
                .get(`https://maps.googleapis.com/maps/api/staticmap`, {
                    params: {
                        key: environment.googleMapsApiKey,
                        center: `${lat},${lng}`,
                        size: `640x480`,
                        zoom: `${zoom}`,
                        path: `fillcolor:0xff00002D|color:0xf96332ff|enc:${this.drawCirclePath(
                            lat,
                            lng,
                            radius
                        )}`,
                    },
                    responseType: "blob",
                })
                .toPromise()
                .then((imgBlob) => {
                    const reader = new FileReader();
                    reader.readAsDataURL(imgBlob);
                    reader.onloadend = function () {
                        resolve(reader.result.toString());
                    };
                });
        });
    }

    private drawCirclePath(lat, lng, radius, detail = 8) {
        let R = 6371;

        let pi = Math.PI;

        lat = (lat * pi) / 180;
        lng = (lng * pi) / 180;
        let d = radius / R;

        let points: any = [];
        let i = 0;

        for (i = 0; i <= 360; i += detail) {
            let brng = (i * pi) / 180;

            let plat = Math.asin(
                Math.sin(lat) * Math.cos(d) +
                    Math.cos(lat) * Math.sin(d) * Math.cos(brng)
            );
            let plng =
                ((lng +
                    Math.atan2(
                        Math.sin(brng) * Math.sin(d) * Math.cos(lat),
                        Math.cos(d) - Math.sin(lat) * Math.sin(plat)
                    )) *
                    180) /
                pi;
            plat = (plat * 180) / pi;

            let currentPoints: any = [plat, plng];
            points.push(currentPoints);
        }

        return this.createEncodings(points);
    }

    private createEncodings(coords) {
        var i = 0;

        var plat = 0;
        var plng = 0;

        var encoded_points = "";

        for (i = 0; i < coords.length; ++i) {
            var lat = coords[i][0];
            var lng = coords[i][1];

            encoded_points += this.encodePoint(plat, plng, lat, lng);

            plat = lat;
            plng = lng;
        }

        return encoded_points;
    }

    private encodePoint(plat, plng, lat, lng) {
        var dlng = 0;
        var dlat = 0;

        var late5 = Math.round(lat * 1e5);
        var plate5 = Math.round(plat * 1e5);

        var lnge5 = Math.round(lng * 1e5);
        var plnge5 = Math.round(plng * 1e5);

        dlng = lnge5 - plnge5;
        dlat = late5 - plate5;

        return this.encodeSignedNumber(dlat) + this.encodeSignedNumber(dlng);
    }

    private encodeSignedNumber(num) {
        var sgn_num = num << 1;

        if (num < 0) {
            sgn_num = ~sgn_num;
        }

        return this.encodeNumber(sgn_num);
    }

    private encodeNumber(num) {
        var encodeString = "";

        while (num >= 0x20) {
            encodeString += String.fromCharCode((0x20 | (num & 0x1f)) + 63);
            num >>= 5;
        }
        encodeString += String.fromCharCode(num + 63);

        return encodeString;
    }
}

Upvotes: 4

Bxx
Bxx

Reputation: 1625

Here's what I came up with:

function funcStaticMapWithCircle($lat, $lng) {

    //$lat & $lng are center of circle

    $mapCentLat =   $lat + 0.002;
    $mapCentLng =   $lng - 0.011;
    $mapW =         600;
    $mapH =         600;
    $zoom =         14;

    $circRadius =       0.75;         //Radius in km
    $circRadiusThick =  1;
    $circFill =         '00BFFF';
    $circFillOpacity =  '60';
    $circBorder =       'red';

    $encString = GMapCircle($lat,$lng,$circRadius); //Encoded polyline string


    $src =  'https://maps.googleapis.com/maps/api/staticmap?';
    $src .= 'center=' .$mapCentLat. ',' .$mapCentLng. '&';
    $src .= 'zoom=' .$zoom. '&';
    $src .= 'size=' .$mapW. 'x' .$mapH.'&';
    $src .= 'maptype=roadmap&';
    $src .= 'style=feature:water|element:geometry.fill|color:0x9bd3ff&';
    $src .= 'path=';
    $src .= 'color:0x' .$circBorder. '00|';
    $src .= 'fillcolor:0x' .$circFill.$circFillOpacity. '|';
    $src .= 'weight:' .$circRadiusThick. '|';
    $src .= 'enc:' .$encString;


    return $src;
}

GMapCircle function is from: Drawing a circle Google Static Maps

Upvotes: 3

Related Questions