I am working with the leaflet api.Where User draw a polyline and latlongs saved in variables.
I been looking for a leaflet function which suppose to take latlongs and calculate pixels.Found the layerPoint function but as i have low understanding of leaflet, can't use the function.
I have used 2 variables to store two latlng parameter, but didn't understand how to use them in layerPoint function.
Script
var polyline = new L.Polyline([]);
var aa;
var bb;
function getDist(e) {
// New marker on coordinate, add it to the map
// Add coordinate to the polyline
polyline.addLatLng(e.latlng).addTo(map).bindPopup();
var ccc = prompt('1st or 2nd');
if (ccc == '1') { aa = e.latlng}
else if (ccc == '2') { bb = e.latlng; convertIt();
}
}
function convertIt(e)
{
var getit = e.latLngToPoint(latlng, map.getZoom());
}
If someone can help, please do help.thanks for your time
latLngToPoint is a method on L.Map. You need to pass a latLng as a parameter to your convertIt function, then return map.latLngToPoint(e), assuming you keep e as the parameter name for convertIt.
Related
I'm trying to put a marker at the center point of these coordinates. After calculating the bounds, I use getCenter() to give me the coordinates. But it returns "LatLng(-93.20448, 38.902475)" in longitude latitude direction, so using them in the marker doesn't work. It needs lat lon. I realize I'm not understanding something but what is it that I don't understand.
var bounds = L.latLngBounds([[-94.778092, 39.967458], [-91.630869, 39.967458], [-91.630869, 37.8374921], [-94.778092, 37.8374921], [-94.778092, 39.967458]]);
var middle = bounds.getCenter(); alert(middle); // LatLng(-93.20448, 38.902475)
var mk5 = new L.marker(new L.latLng( 38.902475, -93.20448 );
How I can delete the polyline line between 2 specific marker.
I have many polyline connected with many marker . But i want to delete any sspecific line on double click .
How Can I do that ?
I am using leaflet to draw the polyline.
here suppose I want to delete the polyline between marker 3 and 4 on double click. what will be procedure to do that.
Thank you.
I tried something like this but its not working , Can anybody please help me where is the mistakes ?
//polyline delete on double click
for (var i = 0; i < $scope.polycoords.length; i++) {
var polyline = $scope.polycoords[i];
$scope.polycoords[i].on('click', function (e) {
console.log("sdd",polyline._leaflet_id);
for (var j = 0; j < $scope.polycoords.length; j++) {
if($scope.polycoords[i]._leaflet_id = $scope.polycoords[j]._leaflet_id){
console.log($scope.polycoords[j])
var polyline = $scope.polycoords[j];
map.removeLayer(polyline);
}
}
});
}
polyline.on('dblclick', function (e) {
map.removeLayer(this);
});
Edit
This is going to work because based on your other question here on SO, I know that you create a different polyline for each line. But for anyone else that creates a single polyline with all the coordinates together, this solution will delete the whole polyline, not just a part of it.
I built a map with Leaflet (inside a Qlikview extension) with many markers.
I want my users go to the map and when they double click on a marker, it displays coordinates.
With the following code, when I click on a marker, I have always coordinates of last marker fetched, not the selected one.
I want to put coordinates in latSel e lonSel variables.
for (var i=0,k=_this.Data.Rows.length;i<k;i++){
var row = _this.Data.Rows [i];
var latitude = parseFloat(row[0].text.replace(",","."));
var longitude = parseFloat(row[1].text.replace(",","."));
//Check to see coordinates are valid
if (latitude != NaN && latitude !='' && latitude <= 90 && latitude >= -90 && longitude != NaN && longitude !='' && longitude <= 180 && latitude >= -180) {
var latlng = new L.LatLng(latitude, longitude);
var poptext = 'Lat & Long:'+latlng+'<br/>'+ row[2].text +'<br/>'+ 'Measure: ' + row[4].text;
var marker = L.marker(latlng).addTo(map).bindPopup(poptext);
marker.on('dblclick', function(e){
latSel = marker.getLatLng().lat;
lonSel = marker.getLatLng().lng
//_this.Data.SelectTextsInColumn(0, true, latSel);
alert("latitude = " + latSel);
});
} else {
//
}
}
What I'm doing wrong?
Thanks in advance.
Assigning onClick listeners in loops can be a bit tricky (search for "javascript onclick loop" in your favourite search engine and you will find some solutions).
Instead of using the marker variable, in Leaflet you can use the variable this inside the callback which refers back to the marker, like so:
marker.on('dblclick', function(e){
latSel = this.getLatLng().lat;
lonSel = this.getLatLng().lng;
alert(latSel);
});
See demo code here: http://plnkr.co/edit/RU3SsoI6A16AYOQAq0xV?p=preview
I've been playing with the google earth API. I thought it would be neat to draw some lines between places from a relative 3D viewpoint. I've searched through the GE documentation and searched on google for answers but didn't find anything that led me down the correct path, so I thought I'd post some code and perhaps get some insight.
The following code plots two places and then draws a line between those places. Unfortunately the line that gets drawn splices the earth. Is there a method to make it wrap to the contour of the earth when drawn in 3D like this? I've attempted to vary the line height placement with a varying degree of success, but at the cost of accuracy and overall visual appeal when the line doesn't appear to connect the places.
function init() {
google.earth.createInstance('map3d', initCB, failureCB);
}
function initCB(instance) {
ge = instance;
ge.getWindow().setVisibility(true);
//---------------------------------PLACES
// Create the placemark.
var placemark = ge.createPlacemark('');
placemark.setName("Location 1");
// Set the placemark's location.
var point = ge.createPoint('');
point.setLatitude(39.96028);
point.setLongitude(-82.979736);
placemark.setGeometry(point);
// Add the placemark to Earth.
ge.getFeatures().appendChild(placemark);
// Create the placemark.
var placemark2 = ge.createPlacemark('');
placemark2.setName("Hop #2");
// Set the placemark's location.
var point2 = ge.createPoint('');
point2.setLatitude(25.7615);
point2.setLongitude(-80.2939);
placemark2.setGeometry(point2);
// Add the placemark to Earth.
ge.getFeatures().appendChild(placemark2);
//---------------------------------FOCUS
var lookAt = ge.createLookAt('');
lookAt.setLatitude(39.96028);
lookAt.setLongitude(-82.979736);
lookAt.setRange(1000000.0);
lookAt.setAltitude(0);
lookAt.setTilt(45);
ge.getView().setAbstractView(lookAt);
//---------------------------------LINES
// Create the placemark
var lineStringPlacemark = ge.createPlacemark('');
// Create the LineString
var lineString = ge.createLineString('');
lineStringPlacemark.setGeometry(lineString);
// Add LineString points
lineString.getCoordinates().pushLatLngAlt(39.96028, -82.979736, 0);
lineString.getCoordinates().pushLatLngAlt(25.7615, -80.2939, 0);
//lineString.setAltitudeMode(ge.ALTITUDE_CLAMP_TO_GROUND);
//lineString.setAltitudeMode(ge.ALTITUDE_RELATIVE_TO_GROUND);
lineString.setAltitudeMode(ge.absolute);
// Create a style and set width and color of line
lineStringPlacemark.setStyleSelector(ge.createStyle(''));
var lineStyle = lineStringPlacemark.getStyleSelector().getLineStyle();
lineStyle.setWidth(2);
lineStyle.getColor().set('9900ffff'); // aabbggrr format
// Add the feature to Earth
ge.getFeatures().appendChild(lineStringPlacemark);
}
function failureCB(errorCode) {
}
google.setOnLoadCallback(init);
You will want to set tesselation, and optionally extrude, on your linestring to true.
See https://developers.google.com/kml/documentation/kmlreference#tessellate and https://developers.google.com/kml/documentation/kmlreference#extrude for details
For the API, your syntax would be something like
lineStringPlacemark.setTessellate(true);
lineStringPlacemark.setExtrude(true);
There's some additional API examples on this at https://developers.google.com/earth/documentation/geometries
I'm using mapbox-gl-draw to add move-able features to my map. In addition to movability functionality, I am needing rotate/transform -ability functionality for the features akin to Leaflet.Path.Transform.
At current, would my only option to achieve be to create a custom mode?
e.g. something like:
map.on('load', function() {
Draw.changeMode('transform');
});
I am not able to convert my map and it's features to mapbox-gl-leaflet in order to implement Leaflet.Path.Transform as losing rotation / bearing / pitch support is not an option.
Long answer incoming. (see http://mapster.me/mapbox-gl-draw-rotate-mode and http://npmjs.com/package/mapbox-gl-draw-rotate-mode for some final products, https://github.com/mapstertech/mapbox-gl-draw-rotate-mode)
I've been working on something similar for a custom project, and not using a draw library. My project involves some pretty regularly sized objects, not very complex polygons, so the solution might be too simple for you but it may be the right path. I just have rotate and move.
Doing movement isn't too hard geographically. Here's some help to get you started. A basic JSBin is up at https://jsbin.com/yoropolewo/edit?html,output with some drag functionality (too tired to do rotate too).
First, register the necessary click events to have a dragging event. You can listen on the specific Mapbox layers for a mousedown, then on the whole document for a mousemove and mouseup.
To do individual shape rotation, you need to ensure that you are referring to the right feature. In this example I assume there's just one feature in the source data, but that's probably too simple for most uses, so you have to extrapolate. The source data is what we affect when we setData() later on. There are obviously numerous ways to do what I'm doing here, but I'm trying to be clear.
var currentDragging = false;
var currentDraggingFeature = false;
var currentDraggingType = false;
var firstDragEvent = false;
map.on('mousedown','my-layer-id',function(e) {
currentDragging = 'my-source-id'; // this must correspond to the source-id of the layer
currentDraggingFeature = e.features[0]; // you may have to filter this to make sure it's the right feature
currentDraggingType = 'move'; // rotation or move
firstDragEvent = map.unproject([e.originalEvent.layerX,e.originalEvent.layerY]);
});
window.addEventListener('mousemove',dragEvent);
window.addEventListener('mouseup',mouseUpEvent);
You will need a function, then, that takes an initial point, a distance, and a rotation, and returns a point back to you. Like this:
Number.prototype.toRad = function() {
return this * Math.PI / 180;
}
Number.prototype.toDeg = function() {
return this * 180 / Math.PI;
}
function getPoint(point, brng, dist) {
dist = dist / 63.78137; // this number depends on how you calculate the distance
brng = brng.toRad();
var lat1 = point.lat.toRad(), lon1 = point.lng.toRad();
var lat2 = Math.asin(Math.sin(lat1) * Math.cos(dist) +
Math.cos(lat1) * Math.sin(dist) * Math.cos(brng));
var lon2 = lon1 + Math.atan2(Math.sin(brng) * Math.sin(dist) *
Math.cos(lat1),
Math.cos(dist) - Math.sin(lat1) *
Math.sin(lat2));
if (isNaN(lat2) || isNaN(lon2)) return null;
return [lon2.toDeg(),lat2.toDeg()];
}
Now, the key is the unproject method in Mapbox GL JS, so you can move between x/y coordinates on the mouse and lng/lat on your map. Then, using the map.getSource().setData() function to set a new geoJSON.
I am turning the x/y into coordinates immediately here but you can do it at any point. Something like the following for moving:
function moveEvent(e) {
// In the case of move, you are just translating the points based on distance and angle of the drag
// Exactly how your translate your points here can depend on the shape
var geoPoint = map.unproject([e.layerX,e.layerY]);
var xDrag = firstDragEvent.lng - geoPoint.lng;
var yDrag = firstDragEvent.lat - geoPoint.lat;
var distanceDrag = Math.sqrt( xDrag*xDrag + yDrag*yDrag );
var angle = Math.atan2(xDrag, yDrag) * 180 / Math.PI;
// Once you have this information, you loop over the coordinate points you have and use a function to find a new point for each
var newFeature = JSON.parse(JSON.stringify(currentDraggingFeature));
if(newFeature.geometry.type==='Polygon') {
var newCoordinates = [];
newFeature.geometry.coordinates.forEach(function(coords) {
newCoordinates.push(getPoint(coords,distanceDrag,angle));
});
newFeature.geometry.coordinates = newCoordinates;
}
map.getSource(currentDragging).setData(newFeature);
}
Rotating is a little harder because you want the shape to rotate around a central point, and you need to know the distance of each point to that central point in order to do that. If you have a simple square polygon this calculation would be easy. If not, then using something like this would be helpful (Finding the center of Leaflet polygon?):
var getCentroid2 = function (arr) {
var twoTimesSignedArea = 0;
var cxTimes6SignedArea = 0;
var cyTimes6SignedArea = 0;
var length = arr.length
var x = function (i) { return arr[i % length][0] };
var y = function (i) { return arr[i % length][1] };
for ( var i = 0; i < arr.length; i++) {
var twoSA = x(i)*y(i+1) - x(i+1)*y(i);
twoTimesSignedArea += twoSA;
cxTimes6SignedArea += (x(i) + x(i+1)) * twoSA;
cyTimes6SignedArea += (y(i) + y(i+1)) * twoSA;
}
var sixSignedArea = 3 * twoTimesSignedArea;
return [ cxTimes6SignedArea / sixSignedArea, cyTimes6SignedArea / sixSignedArea];
}
Once you have the ability to know the polygon's center, you're golden:
function rotateEvent(e) {
// In the case of rotate, we are keeping the same distance from the center but changing the angle
var findPolygonCenter = findCenter(currentDraggingFeature);
var geoPoint = map.unproject([e.layerX,e.layerY]);
var xDistanceFromCenter = findPolygonCenter.lng - geoPoint.lng;
var yDistanceFromCenter = findPolygonCenter.lat - geoPoint.lat;
var angle = Math.atan2(xDistanceFromCenter, yDistanceFromCenter) * 180 / Math.PI;
var newFeature = JSON.parse(JSON.stringify(currentDraggingFeature));
if(newFeature.geometry.type==='Polygon') {
var newCoordinates = [];
newFeature.geometry.coordinates.forEach(function(coords) {
var xDist = findPolygonCenter.lng - coords[0];
var yDist = findPolygonCenter.lat - coords[1];
var distanceFromCenter = Math.sqrt( xDist*xDist + yDist*yDist );
var rotationFromCenter = Math.atan2(xDist, yDist) * 180 / Math.PI;
newCoordinates.push(
getPoint(coords,distanceFromCenter,rotationFromCenter+angle)
);
});
newFeature.geometry.coordinates = newCoordinates;
}
}
Of course, throughout, ensure that your coordinates are being passed and returned correctly from functions. Some of this code may have incorrect levels of arrays in it. It's very easy to run into bugs with the lat/lng object versus the geoJSON arrays.
I hope the explanation is brief but clear enough, and that you understand logically what we are doing to reorient these points. That's the main point, the exact code is details.
Maybe I should just make a module or fork GL Draw...