Erik Booij
Erik Booij

Reputation: 135

How to draw a certain complex shape with the Google Maps Javascript API v3

I would like to draw a shape which consists of a circle with a certain diameter and a rectangle with the same center, but less wide and longer.

An example is the grey shape in the right top corner of this image: http://nl.ivao.aero/extern/pictures/AIRSP004.jpg

Now I could obviously use a seperate circle and rectangle on top of eachother, but that wouldn't yield the results I'm looking for since the overlapping part would have double opacity and/or an ugly border on the internal overlapping part.

Is there a possibility to create such a "complex" shape/polygon? Or a way to fake it without having the aforementioned problem of double opacity?

EDIT:

This is the code I came up with, fully based on Dr.Molle's answer.

Screenshot of the result: Groningen Airport Eelde CTR

var CTRs = [{
    name: 'Eelde CTR',
    segments: [{
        type: 'point',
        coords: {"lat":53.041097,"lng":6.271475}
    },{
        type: 'curve',
        start: {"lat":53.105131,"lng":6.406608},
        end: {"lat":53.223394,"lng":6.658117},
        center: {"lat":53.125000,"lng":6.583333},
        radius: 6.5
    },{
        type: 'point',
        coords: {"lat":53.286983,"lng":6.794394}
    },{
        type: 'point',
        coords: {"lat":53.208306,"lng":6.896883}
    },{
        type: 'curve',
        start: {"lat":53.144606,"lng":6.760219},
        end: {"lat":53.026556,"lng":6.508892},
        center: {"lat":53.125000,"lng":6.583333},
        radius: 6.5
    },{
        type: 'point',
        coords: {"lat":52.962414,"lng":6.373378}
    }]
}];

function drawCTRs()
{
    for ( var i = 0; i < CTRs.length; i++ )
    {
        drawAirspace(CTRs[i]);
    }
}

function circleSegment(start, end, center, radius, points)
{
    points = points || 180;
    var a = [];
    var startHeading    = ( google.maps.geometry.spherical.computeHeading(center, start) + 360 ) % 360;
    var endHeading      = ( google.maps.geometry.spherical.computeHeading(center, end) + 360 ) % 360;
    var heading         = startHeading;
        radius         *= 1852;

    var headingIncr     = Math.abs((((endHeading - startHeading) + 360) % 360) / points);

    for ( var i = 0; i < points; i++, heading += headingIncr )
    {
        heading = heading % 360;
        a.push(new google.maps.geometry.spherical.computeOffset(center, radius, heading));
    }

    return a;
}

function drawAirspace( airspace )
{
    var path = [];
    for ( var i = 0; i < airspace.segments.length; i++ )
    {
        if ( airspace.segments[i].type == 'point' )
        {
            path.push(new google.maps.LatLng(airspace.segments[i].coords.lat, airspace.segments[i].coords.lng));
        } else if ( airspace.segments[i].type == 'curve' )
        {
            path = path.concat(circleSegment(
                new google.maps.LatLng(airspace.segments[i].start.lat, airspace.segments[i].start.lng),
                new google.maps.LatLng(airspace.segments[i].end.lat, airspace.segments[i].end.lng),
                new google.maps.LatLng(airspace.segments[i].center.lat, airspace.segments[i].center.lng),
                airspace.segments[i].radius,
                100
            ));
        }
    }

    var airspaceOverlay = new google.maps.Polygon({
        paths: path,
        map: map,
        title: airspace.name,
        strokeColor: '#770000',
        strokeWeight: 2,
        fillColor: '#770000',
        fillOpacity: .2
    })
}

Upvotes: 0

Views: 777

Answers (1)

Dr.Molle
Dr.Molle

Reputation: 117314

First you'll need to get the points for the circle to be able to create a polygon that looks like a circle(See: How to draw a circle using polygon in GoogleMaps)

Based on this path it's not hard to break the circle and add custom points. Modified function based on the linked answer:

function circlePath(center,radius,points){
   var a=[],p=360/points,d=0,pp;
   for(var i=0;i<points;++i,d+=p){
       pp=google.maps.geometry.spherical.computeOffset(center,radius,d);

    if(d%180==20){
     a.push(google.maps.geometry.spherical.computeOffset(pp,radius*.7,45+(d-(d%180))));
     i+=44;d+=(44*p);
    }
    else if(d%180==65){
     a.push(google.maps.geometry.spherical.computeOffset(pp,radius*.7,45+(d-(d%180))));  
    }
    else{
     a.push(pp);
    }

   }
   return a;
 }

Demo: http://jsfiddle.net/doktormolle/1nmcd2nv/

Upvotes: 2

Related Questions