I need to draw a square polygon of 100x100 screenpixels whereever I click on the Google map (Amsterdam, lat 52, lng 4), on every zoomlevel, with e.latlng at the center of the polygon. I tried to figure it out using fromLatLngToPoint, fromPointToLatLng, scale and worldCoordinates, but I can't get the polygon drawn. If someone likes this puzzle I would appreciate the solution very much.
(I want to use this as a simple start to edit the polygon to a more complex shape, not using the DrawingManager)
I tried:
google.maps.event.addListener(map, 'click', function(e) {
var scale = Math.pow(2, map.getZoom());
var nw = new google.maps.LatLng(map.getBounds().getNorthEast().lat(),map.getBounds().getSouthWest().lng());
var worldCoordinateNW = map.getProjection().fromLatLngToPoint(nw);
var worldCoordinate = map.getProjection().fromLatLngToPoint(e.latLng);
var deX = Math.floor((worldCoordinate.x - worldCoordinateNW.x) * scale);
var deY = Math.floor((worldCoordinate.y - worldCoordinateNW.y) * scale);
// so far so good, deX and deY give the centerpixel
var deNW = map.getProjection().fromPointToLatLng(new google.maps.Point(deX-50,deY-50));
var deNO = map.getProjection().fromPointToLatLng(new google.maps.Point(deX+50,deY-50));
var deZO = map.getProjection().fromPointToLatLng(new google.maps.Point(deX+50,deY+50));
var deZW = map.getProjection().fromPointToLatLng(new google.maps.Point(deX-50,deY+50));
var dePathArray = [deNW, deNO, deZO, deZW];
deObjectNew = new google.maps.Polygon({
paths: dePathArray,
strokeColor: '#000000',
strokeWeight: 1,
fillColor: "#FF0000",
fillOpacity: 0.3,
});
deObjectNew.setMap(map);
});
Got it:
var deNW = deKaart.getProjection().fromPointToLatLng(new google.maps.Point((deX-50)/scale+worldCoordinateNW.x,(deY-50)/scale+worldCoordinateNW.y));
var deNO = deKaart.getProjection().fromPointToLatLng(new google.maps.Point((deX+50)/scale+worldCoordinateNW.x,(deY-50)/scale+worldCoordinateNW.y));
var deZO = deKaart.getProjection().fromPointToLatLng(new google.maps.Point((deX+50)/scale+worldCoordinateNW.x,(deY+50)/scale+worldCoordinateNW.y));
var deZW = deKaart.getProjection().fromPointToLatLng(new google.maps.Point((deX-50)/scale+worldCoordinateNW.x,(deY+50)/scale+worldCoordinateNW.y));
Related
Edit: Working solution.
(Works with the changes made by DevBab).
Extra: added an option to style the Polygon. (var polyStyle)
var url = 'http://reverse.geocoder.cit.api.here.com/6.2/reversegeocode.json' +
'?app_id='+ app_id +
'&app_code=' + app_code +
'&prox=' + lat +','+ lng +',1000' +
'&mode=retrieveAddresses&maxresults=1' +
'&level=county'+
'&additionaldata=IncludeShapeLevel,county';
$.getJSON(url,function (data) {
var location = data.Response.View[0].Result[0].Location;
var wktShape = location.Shape.Value;
var polyStyle = {
strokeColor: 'red',
fillColor: 'rgba(255, 255, 255, 0.3',
lineWidth: 2
};
var geoPoint = H.util.wkt.toGeometry(wktShape);
map.addObject(new H.map.Polygon(geoPoint,{style:polyStyle}));
});
You are creating a polygon, not a marker, so modify this:
map.addObject(new H.map.Marker(geoPoint));
by that:
map.addObject(new H.map.Polygon(geoPoint));
Im trying to draw a line with arrow using paperjs but it does not produce the desired output.
http://jsfiddle.net/1j6nLa7c/
$(document).ready(function(){
paper.install(window)
paper.setup('myCanvas')
x1 = 100;
y1 = 100;
r = 100;
theta = .7;
var path = new Path();
path.strokeColor = 'black';
var start = new Point(100, 100);
path.moveTo(start);
path.lineTo(x1+r*Math.cos(theta), y1+r*Math.sin(theta));
path.simplify(300)
var vector = path.getPointAt(path.length).subtract(path.getPointAt(path.length-25))
var arrowVector = vector.normalize(18);
var path2 = new Path({
segments: [path.getPointAt(path.length) + arrowVector.rotate(145), path.getPointAt(path.length), path.getPointAt(path.length) + arrowVector.rotate(-145)],
fillColor: 'black',
strokeWidth: 6,
});
path2.scale(1.3);
})
Here's some code that creates an arrow. The object is initialized with mouse down point and draws an arrow with the tip at the point the mouse is dragged to.
function Arrow (mouseDownPoint) {
this.start = mouseDownPoint;
this.headLength = 20;
this.tailLength = 9;
this.headAngle = 35;
this.tailAngle = 110
}
Arrow.prototype.draw = function (point) {
var end = point;
var arrowVec = this.start.subtract(end);
// parameterize {headLength: 20, tailLength: 6, headAngle: 35, tailAngle: 110}
// construct the arrow
var arrowHead = arrowVec.normalize(this.headLength);
var arrowTail = arrowHead.normalize(this.tailLength);
var p3 = end; // arrow point
var p2 = end.add(arrowHead.rotate(-this.headAngle)); // leading arrow edge angle
var p4 = end.add(arrowHead.rotate(this.headAngle)); // ditto, other side
var p1 = p2.add(arrowTail.rotate(this.tailAngle)); // trailing arrow edge angle
var p5 = p4.add(arrowTail.rotate(-this.tailAngle)); // ditto
// specify all but the last segment, closed does that
this.path = new paper.Path(this.start, p1, p2, p3, p4, p5);
this.path.closed = true;
this.path.strokeWidth = 1
this.path.strokColor = 'black'
this.path.fillColor = 'black'
return this.path
}
I like the tapered tail but you can get rid of that by fiddling with the constructor lengths.
Here's a sketch with the mouse handling
I have a bounds to a place and created a polygon of that place.
How can I generate a random point inside the bounds of that polygon?
One way of doing it. This will calculate the bounds of the polygon, then guess a random point inside that bounds, if the point is contained by the polygon, it will put a marker there.
// calculate the bounds of the polygon
var bounds = new google.maps.LatLngBounds();
for (var i=0; i < polygon.getPath().getLength(); i++) {
bounds.extend(polygon.getPath().getAt(i));
}
var sw = bounds.getSouthWest();
var ne = bounds.getNorthEast();
// Guess 100 random points inside the bounds,
// put a marker at the first one contained by the polygon and break out of the loop
for (var i = 0; i < 100; i++) {
var ptLat = Math.random() * (ne.lat() - sw.lat()) + sw.lat();
var ptLng = Math.random() * (ne.lng() - sw.lng()) + sw.lng();
var point = new google.maps.LatLng(ptLat,ptLng);
if (google.maps.geometry.poly.containsLocation(point,polygon)) {
var marker = new google.maps.Marker({position:point, map:map});
break;
}
}
working fiddle
working fiddle with up to 100 random points
var polygon;
function initialize() {
var map = new google.maps.Map(document.getElementById("map"),
{
zoom: 4,
center: new google.maps.LatLng(22.7964, 79.8456),
mapTypeId: google.maps.MapTypeId.HYBRID
});
var coords =
[
new google.maps.LatLng(18.979026,72.949219), //Mumbai
new google.maps.LatLng(28.613459,77.255859), //Delhi
new google.maps.LatLng(22.512557,88.417969), //Kolkata
new google.maps.LatLng(12.940322,77.607422) //Bengaluru
];
polygon = new google.maps.Polygon({
paths: coords,
strokeColor: "#0000FF",
strokeOpacity: 0.8,
strokeWeight: 2,
fillColor: "#0000FF",
fillOpacity: 0.26
});
polygon.setMap(map);
var bounds = new google.maps.LatLngBounds();
for (var i=0; i < polygon.getPath().getLength(); i++) {
bounds.extend(polygon.getPath().getAt(i));
}
var sw = bounds.getSouthWest();
var ne = bounds.getNorthEast();
for (var i = 0; i < 100; i++) {
var ptLat = Math.random() * (ne.lat() - sw.lat()) + sw.lat();
var ptLng = Math.random() * (ne.lng() - sw.lng()) + sw.lng();
var point = new google.maps.LatLng(ptLat,ptLng);
if (google.maps.geometry.poly.containsLocation(point,polygon)) {
var marker = new google.maps.Marker({position:point, map:map});
var infowindow = new google.maps.InfoWindow({});
google.maps.event.addListener(marker, "click", function(evt) {
infowindow.setContent(marker.getPosition().toUrlValue(6));
infowindow.open(map, marker);
});
break;
}
}
}
google.maps.event.addDomListener(window, 'load', initialize);
<script src="https://maps.googleapis.com/maps/api/js?libraries=geometry&key=AIzaSyCkUOdZ5y7hMm0yrcCQoCvLwzdM6M8s5qk"></script>
<div id="map" style="width: 530px; height: 500px">
</div>
I'm writing a code which will:
-- Load a map and center it on a KML
-- Draw a polygon based on the bounds of the map.
Here below the code. I get an error
Uncaught TypeError: Cannot call method 'getNorthEast' of undefined
function initialize()
{
var mapOptions =
{
zoom: 19,
mapTypeId: google.maps.MapTypeId.ROADMAP //higer zoom
};
var KML1 = new google.maps.KmlLayer(
{
clickable: false,
url: 'https://s3.amazonaws.com/navizon.its.fp/1001/f43l9uvts1_a.kml' //kml link for the floor-plan
});
var map = new google.maps.Map(document.getElementById('map-canvas'), mapOptions);
KML1.setMap(map);
var bounds = new google.maps.LatLngBounds();
bounds = map.getBounds();
var ne = bounds.getNorthEast();
var sw = bounds.getSouthWest();
var QLat = Math.abs((ne.lat()-sw.lat())/5);
var QLng = Math.abs((sw.lng()-ne.lng())/5);
var swLat = sw.lat()+QLat;
var swLng = sw.lng()+QLng;
var neLat = ne.lat()-QLat;
var neLng = ne.lng()-QLng;
ne = new google.maps.LatLng(neLat,neLng);
sw = new google.maps.LatLng(swLat,swLng);
var Coords = [
ne, new google.maps.LatLng(ne.lat(), sw.lng()),
sw, new google.maps.LatLng(sw.lat(), ne.lng()), ne
];
surface = new google.maps.Polygon(
{
paths: Coords,
strokeColor: '#00AAFF',
strokeOpacity: 0.6,
strokeWeight: 2,
fillColor: '#00CC66',
fillOpacity: 0.15,
editable: true,
draggable: true,
geodesic:true
});
surface.setMap(map);
google.maps.event.addListener(surface, 'mousemove', ciao) //add listener for changes
//$("#results").append(coordinates[0]);
//Let's update area and price as the poly changes
function ciao(event)
{
var vertices = this.getPath();
// Iterate over the vertices.
for (var i =0; i < vertices.getLength(); i++) {
var xy = vertices.getAt(i);
Coords = []
Coords.push(xy);
};
}
}
Any Suggestion?
Thanks,
Daniele
You need to put all the code that depends on the map bounds inside the event listener.
var surface = null;
function initialize()
{
var mapOptions =
{
zoom: 19,
mapTypeId: google.maps.MapTypeId.ROADMAP //higer zoom
};
var KML1 = new google.maps.KmlLayer(
{
clickable: false,
url: 'https://s3.amazonaws.com/navizon.its.fp/1001/f43l9uvts1_a.kml' //kml link for the floor-plan
});
var map = new google.maps.Map(document.getElementById('map-canvas'), mapOptions);
KML1.setMap(map);
google.maps.event.addListener(map,'bounds_changed', function()
{
var bounds = new google.maps.LatLngBounds();
bounds = map.getBounds();
var ne = bounds.getNorthEast();
var sw = bounds.getSouthWest();
var QLat = Math.abs((ne.lat()-sw.lat())/5);
var QLng = Math.abs((sw.lng()-ne.lng())/5);
var swLat = sw.lat()+QLat;
var swLng = sw.lng()+QLng;
var neLat = ne.lat()-QLat;
var neLng = ne.lng()-QLng;
ne = new google.maps.LatLng(neLat,neLng);
sw = new google.maps.LatLng(swLat,swLng);
var Coords = [
ne, new google.maps.LatLng(ne.lat(), sw.lng()),
sw, new google.maps.LatLng(sw.lat(), ne.lng()), ne
];
surface = new google.maps.Polygon(
{
paths: Coords,
strokeColor: '#00AAFF',
strokeOpacity: 0.6,
strokeWeight: 2,
fillColor: '#00CC66',
fillOpacity: 0.15,
editable: true,
draggable: true,
geodesic:true
});
surface.setMap(map);
}); // end of listener callbck
google.maps.event.addListener(surface, 'mousemove', ciao) //add listener for changes
//$("#results").append(coordinates[0]);
//Let's update area and price as the poly changes
function ciao(event)
{
var vertices = this.getPath();
// Iterate over the vertices.
for (var i =0; i < vertices.getLength(); i++) {
var xy = vertices.getAt(i);
Coords = []
Coords.push(xy);
};
}
} // end of initialize
i need the current distance between the marker and the map bounds to decide: draw the tipbox left, right, over or under the marker.
I set the position of the tipbox with these lines of code:
Label.prototype.draw = function() {
var projection = this.getProjection();
var position = projection.fromLatLngToDivPixel(this.get('position'));
// position of tipbox, depends on margin to map boaunds
var div = this.div_;
var mapWidth = parseInt($('#mapBox').css('width'));
var mapHeight = parseInt($('#mapBox').css('height'));
div.style.left = (position.x-(parseInt(div.style.width)/2)) + 'px';
div.style.top = position.y + 'px';
div.style.display = 'inline';
$('.tipBox-inner').html(''+position.x);
};
But if i drag the page, the position.x or position.y return the same number of pixels. As you can see on the image, the x position is at 300px(!). I would draw the tipbox in top of the marker, if the marker is at the bottom of page and so on.
Ok i found a solution myself. I get the distance(px) to margin in the mouseover-Event of the marker:
google.maps.event.addListener(marker, 'mouseover', function(event) {
label = new Label({
map: map
});
label.bindTo('position', marker, 'position');
var pixel = label.getProjection().fromLatLngToContainerPixel(event.latLng);
label.set('mouseX', pixel.x);
label.set('mouseY', pixel.y);
});
Now i can use mouseX and mouseY in draw-functionf of the Label with this.get('mouseX')