I have a Bing map with drawing manager enabled for users to draw shapes (mostly one polygon at a time). I want to be able to get the details of the drawn polygon so I can save it in the database.
The below function can access the shapes but returns the coordinates only
function getShapes()
{
var shapes = drawingManager.getPrimitives();
if (shapes && shapes.length > 0)
{
var rings = shapes[0].getRings();
alert('Retrieved ' + rings[0] + ' from the drawing manager.');
}
else
{
alert('No shapes in the drawing manager.');
}
}
result is:
Retrieved [MapLocation (35.17314901376581, 44.72432011035158)],[MapLocation (35.10324034213123, 44.73015659716798)],[MapLocation (35.12346106720259, 44.90525120166017)],[MapLocation (35.18633788986748, 44.88362186816408)],[MapLocation (35.17314901376581, 44.72432011035158)] from the drawing manager.
How can I get the exact drawn shape details not just the coordinates?
Remove getRings() and you will have the shape object. The Get Rings function retudrrns the coordinates of a polygon.
Related
I have a Leaflet based mapping solution that uses ArcGIS map configuration supplied by a user (I have no idea what it will be, they will customize it with their own ArcGIS services). The issue is that the projection can be pretty much anything, and I will need to use Proj4Leaflet to configure the CRS of the map accordingly. The problem I'm running into is I'm not sure how to calculate the scale/resolution array. The user is inputting these values: projection key, Proj4 string, origin, bounds, zoom levels.
So, for example (yes I know EPSG:3857 is standard and I could just use L.CRS.EPSG3857 but it serves as a good example of how to set the same thing up using Proj4Leaflet):
Projection key = EPSG:3857
Proj4 string = +proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 +lon_0=0.0 +x_0=0.0 +y_0=0 +k=1.0 +units=m +nadgrids=#null +wktext +no_defs
Origin = [0,0]
Bounds = [[-20026376.39, -20048966.10], [20026376.39, 20048966.10]]
Zoom levels = 18
With that I think I have enough to set up a L.Proj.CRS for it:
var crs = new L.Proj.CRS("EPSG:3857", "+proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 +lon_0=0.0 +x_0=0.0 +y_0=0 +k=1.0 +units=m +nadgrids=#null +wktext +no_defs",
{
resolutions : [?????],
origin : [0,0],
bounds : [[-20026376.39, -20048966.10], [20026376.39, 20048966.10]]
});
I have everything I need apart from the resolutions array, I am not sure exactly how to go about setting that up based on the data given and having a hard time finding answers to get me pointed in the right direction.
So bottom line, the only way I found to calculate resolutions is if it is a mercator projection and we know the longitude extents of it and the tile size. Otherwise the resolutions will need to be looked up at the ArcGIS Server tile server REST endpoint. Thus for my project I will need the user to supply the array themselves and cannot calculate it for them.
In the case of the mercator projection, I came up with this function that does the trick:
function parseResolutionsFromZoomLevels(zoomLevels, tileSize, mapWGS84Extent)
{
var metersPerExtent = 40075008/360;
var mapWGS84Meters = mapWGS84Extent*metersPerExtent;
var resolutionArray = [];
for (var i=0; i<zoomLevels; i++)
{
var tilesAtZoom = Math.pow(2,i);
var pixelsAtZoom = tilesAtZoom*tileSize;
resolutionArray.push(mapWGS84Meters/pixelsAtZoom);
}
return resolutionArray;
}
Hope this helps anyone else that happens to encounter this same situation.
I have just started getting used to using Unity's new tilemap tool (UnityEngine.Tilemaps).
One issue I am having is that I don't know how to get the x,y coordinates of a placed tile via script. I am trying to move a scriptableObject on the tilemap in script to a new location that the player clicks, but I don't know how to get the coordinates of the clicked tile location. There doesn't seem to be any position property for the Tile class (the Tile knows nothing about its location), so the Tilemap must have the answer. I was not able to find anything in the Unity documentation for how to get the Vector3 coordinates for a selected tile in the Tilemap.
If you have access to the Tile instance you can use its transform (or the raycast hit from the click) to get its world position and than get the tile coordinates via the WorldToCell method of your Grid component (look at the documentation).
EDIT:
Unity seems to not instantiate the tiles but instead uses only one tile object to manage all tiles of that type, i wasn't aware of that.
To get the correct position you have to calculate it yourself. Here is an example of how to get the tile position at the mouse cursor if the grid is positioned at the xy-plane with z = 0
// get the grid by GetComponent or saving it as public field
Grid grid;
// save the camera as public field if you using not the main camera
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
// get the collision point of the ray with the z = 0 plane
Vector3 worldPoint = ray.GetPoint(-ray.origin.z / ray.direction.z);
Vector3Int position = grid.WorldToCell(worldPoint);
I couldn't find a way to get the Grid's position from mouse click, so instead I used a Raycast to Vector3, and then converted that to coordinates via the WorldToCell method of the Grid component as per Shirotha's suggestion. This allows me to move the selected GameObject to a new position.
public class ClickableTile : MonoBehaviour
{
public NormalTile normalTile;
public Player selectedUnit;
private void OnMouseUp()
{
// left click - get info from selected tile
if (Input.GetMouseButtonUp(0))
{
// get mouse click's position in 2d plane
Vector3 pz = Camera.main.ScreenToWorldPoint(Input.mousePosition);
pz.z = 0;
// convert mouse click's position to Grid position
GridLayout gridLayout = transform.parent.GetComponentInParent<GridLayout>();
Vector3Int cellPosition = gridLayout.WorldToCell(pz);
// set selectedUnit to clicked location on grid
selectedUnit.setLocation(cellPosition);
Debug.Log(cellPosition);
}
}
}
On an aside, I know how to get the Grid location, but now how to query it. I need to get the GridSelection static object from Grid, and then get its position.
I'm getting the error below when trying to run getBounds() and contains() with a Circle shape.
leaflet.js:7 Uncaught TypeError: Cannot read property 'layerPointToLatLng' of undefined
I'm able to use it with the other shapes, but the circle is being stubborn. I tried this solution from another question, but no success.
Here's the code I have for the polygon and rectangle shapes:
drawnLayers.eachLayer(function(l) {
if (type == 'circle') {
// console.log(l.getBounds().contains(layer.getBounds()));
} else {
if (l.getBounds().contains(layer.getBounds())) {
isDonut = true;
l._latlngs.push(layer.getLatLngs());
l.redraw();
$('#map-info').append("<br>New Polygon: <pre>" +
JSON.stringify(l.getLatLngs(), null, 2) + '</pre>');
}
}
});
l.getBounds().contains(layer.getBounds())
getBounds() is a method specific only to polyline/polygon/rectangle in leaflet 0.7.x
It was added to circle shapes as of version 1.0.0 - see leaflet reference versions
To solve the problem you have 2 options
use some other methods for circles like getRadius() and compute by yourself if the shape contains your other shape
upgrade your leaflet library
Personally I would upgrade the leaflet library to 1.0.3 (which I did very easy and without any compatibility issues on my project)
I am trying to determine the marker/s currently shown in a mapview. I have researched the following the method:
self.mapView.bounds.contains(markers[0].position)
But the contains command accepts CGPoint or CGRect. In other platforms except Swift, contains can accept the marker's position.
How do I convert the marker's position to be accepted by contains?
Use the mapview's current projection. Use the projection's method called containsCoordinate to check if you marker's position is inside the projection, i.e. currently visible.
So something like:
let coord = marker.position
let isVisible = self.mapview.projection.containsCoordinate(coord)
https://developers.google.com/maps/documentation/ios-sdk/reference/interface_g_m_s_projection.html#aa6ad29e6831e40f00435c3aaeda8e08a
In MapKit:
I assume with Marker you mean an MKAnnotation. Instead of using the bounds of the mapView you should use the visibleMapRect and see if it contains the coordinates of the Marker in MKMapPoints. This is the code I used:
let markerPoint = MKMapPointForCoordinate(markers[0].coordinate)
if MKMapRectContainsPoint(mapView.visibleMapRect, markerPoint) {
print("Found")
} else {
print("Not found")
}
Only when the coordinates of the markers are visible (in other words, the marker is being displayed), this will print "Found". If off-screen, it will print "Not found".
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