I'm drawing an area on Google Maps using the Geometry API. I want to know if it is possible to draw a repeating element onto an area that is dynamic in size?
For example, if I draw my area to look like this:
Then I want to be able to hit 'Next Step' and see something like this, with the rectangles drawn in the area, but only if they will fit. i.e., they have to be 'full' rectangles, not part rectangles:
The only problem is, I'm not entirely sure how to go about this. I would use HTML5 <canvas>
but unfortunately, this needs to be as browser-friendly as possible, but if it has to be <canvas>
then so be it!
I'm drawing an area on Google Maps using the Geometry API. I want to know if it is possible to draw a repeating element onto an area that is dynamic in size?
For example, if I draw my area to look like this:
Then I want to be able to hit 'Next Step' and see something like this, with the rectangles drawn in the area, but only if they will fit. i.e., they have to be 'full' rectangles, not part rectangles:
The only problem is, I'm not entirely sure how to go about this. I would use HTML5 <canvas>
but unfortunately, this needs to be as browser-friendly as possible, but if it has to be <canvas>
then so be it!
- This is really unrelated to answering your question, but out of sheer curiosity, if I may, why would you want to do that? – Andrei Cristian Prodan Commented Nov 19, 2012 at 16:32
- @AndreiCristianProdan At clients request.. – user1211577 Commented Nov 19, 2012 at 17:07
- Haha, yeah but what does he want to acomplish, for what purpose. Maybe you can find a workaround if you know the purpose. – Andrei Cristian Prodan Commented Nov 19, 2012 at 17:09
- @AndreiCristianProdan, the purpose is exactly this unfortunately 8-), I need to be able to draw the maximum number of rectangles in the selected area as a visual aid for a process in an online application we're building. – user1211577 Commented Nov 19, 2012 at 17:43
- Are the included rectangles a fixed size? – david strachan Commented Nov 19, 2012 at 18:59
2 Answers
Reset to default 14Although I didn't use canvas, how about this code?
function onPolygonComplete(polygon) {
var bounds, paths, sw, ne, ystep, xstep,
boxH, boxW, posArry, flag, pos,
x, y, i, box, maxBoxCnt;
//Delete old boxes.
boxes.forEach(function(box, i) {
box.setMap(null);
delete box;
});
//Calculate the bounds that contains entire polygon.
bounds = new google.maps.LatLngBounds();
paths = polygon.getPath();
paths.forEach(function(latlng, i){
bounds.extend(latlng);
});
//Calculate the small box size.
maxBoxCnt = 8;
sw = bounds.getSouthWest();
ne = bounds.getNorthEast();
ystep = Math.abs(sw.lat() - ne.lat()) / maxBoxCnt;
boxH = Math.abs(sw.lat() - ne.lat()) / (maxBoxCnt + 1);
xstep = Math.abs(sw.lng() - ne.lng()) / maxBoxCnt;
boxW = Math.abs(sw.lng() - ne.lng()) / (maxBoxCnt + 1);
for (y = 0; y < maxBoxCnt; y++) {
for (x = 0; x < maxBoxCnt; x++) {
//Detect that polygon is able to contain a small box.
bounds = new google.maps.LatLngBounds();
posArry = [];
posArry.push(new google.maps.LatLng(sw.lat() + ystep * y, sw.lng() + xstep * x));
posArry.push(new google.maps.LatLng(sw.lat() + ystep * y, sw.lng() + xstep * x + boxW));
posArry.push(new google.maps.LatLng(sw.lat() + ystep * y + boxH, sw.lng() + xstep * x));
posArry.push(new google.maps.LatLng(sw.lat() + ystep * y + boxH, sw.lng() + xstep * x + boxW));
flag = true;
for (i = 0; i < posArry.length; i++) {
pos = posArry[i];
if (flag) {
flag = google.maps.geometry.poly.containsLocation(pos, polygon);
bounds.extend(pos);
}
}
//Draw a small box.
if (flag) {
box = new google.maps.Rectangle({
bounds : bounds,
map : mapCanvas,
strokeColor: '#00ffff',
strokeOpacity: 0.5,
strokeWeight: 1,
fillColor: '#00ffff',
fillOpacity : 0.5,
clickable: false
});
boxes.push(box);
}
}
}
}
This code works like this image.
I wrote a page that explains the code. http://googlemaps.googlermania.com/google_maps_api_v3/en/poly_containsLocation.html
@Joshua M
Sorry for keeping you wait.
Ok, the new code is below.
You can specify the small box size at var boxSize = new google.maps.Size(10, 20);
<!DOCTYPE html>
<html>
<head>
<script src="http://maps.googleapis.com/maps/api/js?sensor=false&libraries=geometry"></script>
<script type='text/javascript'>
var mapCanvas, boxes = new google.maps.MVCArray();
function initialize() {
var mapDiv = document.getElementById("map_canvas");
mapCanvas = new google.maps.Map(mapDiv, {
center : new google.maps.LatLng(37.422191,-122.084585),
mapTypeId : google.maps.MapTypeId.SATELLITE,
zoom : 19,
tilt : 0
});
//Encoded path
var encodedPath = "eblcFnuchVv@D@q@P?a@eD]AC~@b@DCz@a@A";
var points = google.maps.geometry.encoding.decodePath(encodedPath);
//Draw a polygon
var polygonOpts = {
paths : points,
strokeWeight : 6,
strokeColor : "#FF0000",
strokeOpacity : 1,
//fillColor : "blue",
fillOpacity : 0,
map : mapCanvas,
editable : true
};
var poly = new google.maps.Polygon(polygonOpts);
var proc = function() {
onPolygonComplete(poly);
};
google.maps.event.addListener(mapCanvas, "projection_changed", proc);
google.maps.event.addListener(poly.getPath(), 'insert_at', proc);
google.maps.event.addListener(poly.getPath(), 'remove_at', proc);
google.maps.event.addListener(poly.getPath(), 'set_at', proc);
}
function onDrawMgr_complete(polygon) {
var path = polygon.getPath();
console.log(google.maps.geometry.encoding.encodePath(path));
}
function onPolygonComplete(polygon) {
var bounds, paths, sw, ne, ystep, xstep, boxH, boxW, posArry, flag, pos, x, y, i, box;
//Delete old boxes.
boxes.forEach(function(box, i) {
box.setMap(null);
delete box;
});
//Calculate the bounds that contains entire polygon.
bounds = new google.maps.LatLngBounds();
paths = polygon.getPath();
paths.forEach(function(latlng, i) {
bounds.extend(latlng);
});
var projection = mapCanvas.getProjection();
var zoom = mapCanvas.getZoom();
var powBase = Math.pow(2, zoom);
//Calculate the small box size.
sw = bounds.getSouthWest();
ne = bounds.getNorthEast();
var swPoint = projection.fromLatLngToPoint(sw);
var nePoint = projection.fromLatLngToPoint(ne);
var boxSize = new google.maps.Size(10, 20); //in pixels.
boxSize.width /= powBase;
boxSize.height /= powBase;
var maxX = Math.floor(Math.abs((swPoint.x - nePoint.x)) / boxSize.width);
var maxY = Math.floor(Math.abs((swPoint.y - nePoint.y)) / boxSize.height);
for ( y = 0; y < maxY; y++) {
for (x = 0; x < maxX; x++) {
//Detect that polygon is able to contain a small box.
bounds = new google.maps.LatLngBounds();
posArry = [];
posArry.push(new google.maps.Point(swPoint.x + boxSize.width * x, swPoint.y - boxSize.height * y));
posArry.push(new google.maps.Point(swPoint.x + boxSize.width * x, swPoint.y - boxSize.height * (y + 1)));
posArry.push(new google.maps.Point(swPoint.x + boxSize.width * (x + 1), swPoint.y - boxSize.height * y));
posArry.push(new google.maps.Point(swPoint.x + boxSize.width * (x + 1), swPoint.y - boxSize.height * (y + 1)));
var flag = true;
for (var i = 0; i < posArry.length; i++) {
pos = projection.fromPointToLatLng(posArry[i]);
if (flag) {
flag = google.maps.geometry.poly.containsLocation(pos, polygon);
bounds.extend(pos);
}
}
if (flag) {
box = new google.maps.Rectangle({
bounds : bounds,
map : mapCanvas,
strokeColor : 'green',
strokeOpacity : 1,
strokeWeight : 1,
fillColor : 'yellow',
fillOpacity : 0.5,
clickable : false
});
boxes.push(box);
}
}
}
}
google.maps.event.addDomListener(window, "load", initialize);
</script>
<style type="text/css">
window,html,#map_canvas{
width : 700px;
height : 500px;
}
</style>
</head>
<body>
<div id="map_canvas"/>
</body>
</html>