private void OnGUI() { if (GUI.Button(new Rect(5, 5, 100, 30), "Calc")) { // Calculate the distance in km between locations. float distance = OnlineMapsUtils.DistanceBetweenPoints(userCoordinares, markerCoordinates).magnitude; Debug.Log("Distance: " + distance); int zoom = 15; int maxX = 1 << zoom; // Calculate the tile position of locations. Vector2 userTile = OnlineMapsUtils.LatLongToTilef(userCoordinares, zoom); Vector2 markerTile = OnlineMapsUtils.LatLongToTilef(markerCoordinates, zoom); // Calculate the angle between locations. float angle = OnlineMapsUtils.Angle2D(userTile, markerTile); if (Mathf.Abs(userTile.x - markerTile.x) > maxX / 2) { angle = 360 - angle; } Debug.Log("Angle: " + angle); // Calculate relative angle between locations. float relativeAngle = angle - compassTrueHeading; Debug.Log("Relative angle: " + relativeAngle); } }
/// <summary> /// Determines if the marker at the specified coordinates. /// </summary> /// <param name="positionLatLng"> /// Position. /// </param> /// <param name="zoom"> /// The zoom. /// </param> /// <returns> /// True if the marker in position, false if not. /// </returns> public bool HitTest(Vector2 positionLatLng, int zoom) { if (OnlineMapsControlBase.instance is OnlineMapsTileSetControl) { OnlineMapsVector2i pos = OnlineMapsUtils.LatLongToTilef(position, zoom) * OnlineMapsUtils.tileSize; float w = width * scale; float h = height * scale; pos = GetAlignedPosition(pos); Vector2 mPos = OnlineMapsUtils.LatLongToTilef(positionLatLng, zoom) * OnlineMapsUtils.tileSize; return(mPos.x >= pos.x + w * (markerColliderRect.x + 0.5f) && mPos.x <= pos.x + w * (markerColliderRect.xMax + 0.5f) && mPos.y >= pos.y + w * (markerColliderRect.y + 0.5f) && mPos.y <= pos.y + h * (markerColliderRect.yMax + 0.5f)); } else { OnlineMapsVector2i pos = OnlineMapsUtils.LatLongToTilef(position, zoom) * OnlineMapsUtils.tileSize; int w = width; int h = height; pos = GetAlignedPosition(pos); Vector2 mPos = OnlineMapsUtils.LatLongToTilef(positionLatLng, zoom) * OnlineMapsUtils.tileSize; return(mPos.x >= pos.x + w * (markerColliderRect.x + 0.5f) && mPos.x <= pos.x + w * (markerColliderRect.xMax + 0.5f) && mPos.y >= pos.y + w * (markerColliderRect.y + 0.5f) && mPos.y <= pos.y + h * (markerColliderRect.yMax + 0.5f)); } }
private Vector2 GetCoords2D(Vector2 position) { RaycastHit2D hit = Physics2D.GetRayIntersection(Camera.main.ScreenPointToRay(position), Mathf.Infinity); if (hit.collider == null || hit.collider.gameObject != gameObject) { return(Vector2.zero); } if (cl2D == null) { return(Vector2.zero); } Vector3 size = (cl2D.bounds.max - new Vector3(hit.point.x, hit.point.y)); size.x = size.x / cl2D.bounds.size.x; size.y = size.y / cl2D.bounds.size.y; Vector2 r = new Vector3((size.x - .5f), (size.y - .5f)); int countX = api.width / OnlineMapsUtils.tileSize; int countY = api.height / OnlineMapsUtils.tileSize; Vector2 p = OnlineMapsUtils.LatLongToTilef(api.position, api.zoom); p.x -= countX * r.x; p.y += countY * r.y; return(OnlineMapsUtils.TileToLatLong(p, api.zoom)); }
private void OnGUI() { // On click button, starts movement if (GUI.Button(new Rect(5, 5, 100, 30), "Goto marker")) { // from current map position fromPosition = OnlineMaps.instance.position; // to GPS position; toPosition = OnlineMaps.instance.GetComponent <OnlineMapsLocationService>().position; // calculates tile positions Vector2 fromTile = OnlineMapsUtils.LatLongToTilef(fromPosition, OnlineMaps.instance.zoom); Vector2 toTile = OnlineMapsUtils.LatLongToTilef(toPosition, OnlineMaps.instance.zoom); // if tile offset < 4, then start smooth movement if ((fromTile - toTile).magnitude < 4) { // set relative position 0 angle = 0; // start movement isMovement = true; } else // too far { OnlineMaps.instance.position = toPosition; } } }
public void Add(OnlineMapsMarker marker) { markers.Add(marker); center = markers.Aggregate(Vector2.zero, (current, m) => current + m.position) / markers.Count; instance.position = center; tilePosition = OnlineMapsUtils.LatLongToTilef(center, zoom); instance.label = "Group. Count: " + markers.Count; }
private Rect GetMarkerRect(OnlineMapsMarker marker) { const int s = OnlineMapsUtils.tileSize; Vector2 p = OnlineMapsUtils.LatLongToTilef(marker.position, bufferZoom); p.x -= bufferPosition.x; p.y -= bufferPosition.y; OnlineMapsVector2i ip = marker.GetAlignedPosition(new OnlineMapsVector2i((int)(p.x * s), (int)(p.y * s))); return(new Rect(ip.x, ip.y, marker.width, marker.height)); }
private void GroupMarkers() { List <MarkerGroup> groups = new List <MarkerGroup>(); for (int zoom = 20; zoom >= 3; zoom--) { List <OnlineMapsMarker> ms = markers.Select(m => m).ToList(); for (int j = 0; j < ms.Count - 1; j++) { OnlineMapsMarker marker = ms[j]; MarkerGroup group = null; Vector2 pos = OnlineMapsUtils.LatLongToTilef(marker.position, zoom); int k = j + 1; while (k < ms.Count) { OnlineMapsMarker marker2 = ms[k]; Vector2 pos2 = OnlineMapsUtils.LatLongToTilef(marker2.position, zoom); if ((pos - pos2).magnitude < distance) { if (group == null) { group = new MarkerGroup(zoom, groupTexture); groups.Add(group); group.Add(marker); if (marker.range.min == 3) { marker.range.min = zoom + 1; } } group.Add(marker2); if (marker2.range.min == 3) { marker2.range.min = zoom + 1; } ms.RemoveAt(k); pos = group.tilePosition; } else { k++; } } } } foreach (MarkerGroup g in groups) { g.Apply(font); } }
/// <summary> /// Converts geographical coordinate to position in the scene relative to the top-left corner of the map in map space. /// </summary> /// <param name="coords">Geographical coordinate</param> /// <returns>Scene position (in map space)</returns> public virtual Vector2 GetPosition(Vector2 coords) { Vector2 pos = OnlineMapsUtils.LatLongToTilef(coords, api.zoom); Vector2 topLeft = OnlineMapsUtils.LatLongToTilef(api.topLeftPosition, api.zoom); pos -= topLeft; int maxX = 1 << api.zoom; if (pos.x < -maxX / 2) { pos.x += maxX; } return(new Vector2(pos.x * OnlineMapsUtils.tileSize, pos.y * OnlineMapsUtils.tileSize)); }
private void UpdateMesh() { _bufferPosition = null; _alpha = alpha; int w1 = api.tilesetWidth / OnlineMapsUtils.tileSize; int h1 = api.tilesetHeight / OnlineMapsUtils.tileSize; int subMeshVX = 1; int subMeshVZ = 1; Vector2 subMeshSize = new Vector2(api.tilesetSize.x / w1, api.tilesetSize.y / h1); Vector2 topLeftPosition = api.topLeftPosition; Vector2 bottomRightPosition = api.bottomRightPosition; Vector2 tlPos = OnlineMapsUtils.LatLongToTilef(topLeftPosition, api.zoom); Vector2 pos = tlPos - bufferPosition; int maxX = (2 << api.zoom) / 2; if (pos.x >= maxX) { pos.x -= maxX; } Vector3 startPos = new Vector3(subMeshSize.x * pos.x, 0, -subMeshSize.y * pos.y); int w = w1 + 2; int h = h1 + 2; for (int y = 0; y < h; y++) { for (int x = 0; x < w; x++) { UpdateMapSubMesh(x, y, w, h, subMeshSize, subMeshVX, subMeshVZ, startPos, 0, topLeftPosition, bottomRightPosition); } } overlayMesh.vertices = vertices; overlayMesh.uv = uv; for (int i = 0; i < overlayMesh.subMeshCount; i++) { overlayMesh.SetTriangles(overlayMesh.GetTriangles(i), i); } overlayMesh.RecalculateBounds(); }
protected static List <Vector3> GetLocalPoints(List <OnlineMapsOSMNode> nodes) { OnlineMaps api = OnlineMaps.instance; Vector2 startTilePos = OnlineMapsUtils.LatLongToTilef(api.topLeftPosition, api.buffer.apiZoom); List <Vector3> localPoints = new List <Vector3>(); float sw = OnlineMapsUtils.tileSize * api.tilesetSize.x / api.tilesetWidth; float sh = OnlineMapsUtils.tileSize * api.tilesetSize.y / api.tilesetHeight; for (int i = 0; i < nodes.Count; i++) { Vector2 p = OnlineMapsUtils.LatLongToTilef(nodes[i], api.buffer.apiZoom) - startTilePos; localPoints.Add(new Vector3(-p.x * sw, 0, p.y * sh)); } return(localPoints); }
private bool HasWater(float lat, float lng) { // Convert geo coordinates to tile coordinates Vector2 tilef = OnlineMapsUtils.LatLongToTilef(lng, lat, 3); const int countTileRowCol = 8; // Convert tile coordinates to texture coordinates (UV) tilef.x /= countTileRowCol; tilef.y /= countTileRowCol; // Check pixel color Color color = mapForDetectWater.GetPixelBilinear(tilef.x, 1 - tilef.y); Debug.Log(tilef); /*Debug.Log ("pixel color = " + color); * Debug.Log ("water color = " + waterColor);*/ return(color == waterColor); }
private Rect GetRect() { OnlineMaps api = OnlineMaps.instance; Rect controlRect = api.control.GetRect(); Rect uvRect = api.control.uvRect; controlRect.width /= uvRect.width; controlRect.height /= uvRect.height; controlRect.x -= controlRect.width * uvRect.x; controlRect.y -= controlRect.height * uvRect.y; Vector2 topLeft = OnlineMapsUtils.LatLongToTilef(api.buffer.topLeftPosition, api.buffer.apiZoom) * OnlineMapsUtils.tileSize; Vector2 pos = GetAlignedPosition(OnlineMapsUtils.LatLongToTilef(position, api.buffer.apiZoom) * OnlineMapsUtils.tileSize); float scaleX = (controlRect.width / api.width); float scaleY = (controlRect.height / api.height); pos -= topLeft; pos.x = Mathf.RoundToInt(pos.x * scaleX + controlRect.x); pos.y = Mathf.RoundToInt(controlRect.yMax - (pos.y + height) * scaleY); return(new Rect(pos.x, pos.y, width * scaleX, height * scaleY)); }
/// <summary> /// Updates billboard markers. /// </summary> protected void UpdateMarkersBillboard() { if (markersGameObject == null) { InitMarkersMesh(); } if (markerBillboards == null) { markerBillboards = new Dictionary <int, OnlineMapsMarkerBillboard>(); } double tlx, tly, brx, bry; api.GetTopLeftPosition(out tlx, out tly); api.GetBottomRightPosition(out brx, out bry); if (brx < tlx) { brx += 360; } int maxX = (2 << api.buffer.apiZoom) / 2; double px, py; OnlineMapsUtils.LatLongToTiled(tlx, tly, api.zoom, out px, out py); float yScale = GetBestElevationYScale(tlx, tly, brx, bry); Bounds mapBounds = cl.bounds; Vector3 positionOffset = transform.position - mapBounds.min; Vector3 size = mapBounds.size; size = transform.rotation * size; if (api.target == OnlineMapsTarget.tileset) { positionOffset.x -= size.x; } foreach (KeyValuePair <int, OnlineMapsMarkerBillboard> billboard in markerBillboards) { billboard.Value.used = false; } foreach (OnlineMapsMarker marker in api.markers) { if (!marker.enabled || !marker.range.InRange(api.zoom)) { continue; } float mx = marker.position.x; if (!(((mx > tlx && mx < brx) || (mx + 360 > tlx && mx + 360 < brx) || (mx - 360 > tlx && mx - 360 < brx)) && marker.position.y < tly && marker.position.y > bry)) { continue; } int markerHashCode = marker.GetHashCode(); OnlineMapsMarkerBillboard markerBillboard = null; if (!markerBillboards.ContainsKey(markerHashCode)) { markerBillboard = OnlineMapsMarkerBillboard.Create(marker); markerBillboard.transform.parent = markersGameObject.transform; markerBillboards.Add(markerHashCode, markerBillboard); } else { markerBillboard = markerBillboards[markerHashCode]; } float sx = size.x / api.width * marker2DSize * marker.scale; float sz = size.z / api.height * marker2DSize * marker.scale; float s = Mathf.Max(sx, sz); markerBillboard.transform.localScale = new Vector3(-s, s, s); Vector2 p = OnlineMapsUtils.LatLongToTilef(marker.position, api.buffer.apiZoom); p.x = Mathf.Repeat(p.x - (float)px, maxX); p.y -= (float)py; float x = -p.x / api.width * OnlineMapsUtils.tileSize * size.x + positionOffset.x; float z = p.y / api.height * OnlineMapsUtils.tileSize * size.z - positionOffset.z; float y = GetElevationValue(x, z, yScale, tlx, tly, brx, bry); markerBillboard.transform.localPosition = transform.rotation * new Vector3(x, y, z); markerBillboard.used = true; } List <int> keysForRemove = new List <int>(); foreach (KeyValuePair <int, OnlineMapsMarkerBillboard> billboard in markerBillboards) { if (!billboard.Value.used) { billboard.Value.Dispose(); keysForRemove.Add(billboard.Key); } } foreach (int key in keysForRemove) { markerBillboards.Remove(key); } }
private void SetMarkerToBuffer(OnlineMapsMarker marker, Vector2 startPos, Vector2 endPos) { const int s = OnlineMapsUtils.tileSize; float mx = marker.position.x; if (!(((mx > startPos.x && mx < endPos.x) || (mx + 360 > startPos.x && mx + 360 < endPos.x) || (mx - 360 > startPos.x && mx - 360 < endPos.x)) && marker.position.y < startPos.y && marker.position.y > endPos.y)) { return; } #if !UNITY_WEBGL int maxCount = 20; while (marker.locked && maxCount > 0) { Thread.Sleep(1); maxCount--; } #endif marker.locked = true; Vector2 p = OnlineMapsUtils.LatLongToTilef(marker.position, bufferZoom); p -= bufferPosition; int maxX = 1 << bufferZoom; if (p.x < 0) { p.x += maxX; } else if (p.x > maxX) { p.x -= maxX; } OnlineMapsVector2i ip = marker.GetAlignedPosition(new OnlineMapsVector2i((int)(p.x * s), (int)(p.y * s))); Color[] markerColors = marker.colors; if (markerColors == null || markerColors.Length == 0) { return; } int markerWidth = marker.width; int markerHeight = marker.height; for (int y = 0; y < marker.height; y++) { if (ip.y + y < 0 || ip.y + y >= height) { continue; } int my = (markerHeight - y - 1) * markerWidth; for (int x = 0; x < marker.width; x++) { if (ip.x + x < 0 || ip.x + x >= width) { continue; } try { SetColorToBuffer(markerColors[my + x], ip, y, x); } catch { } } } marker.locked = false; }
private void UpdateMesh() { OnlineMapsTileSetControl control = OnlineMapsTileSetControl.instance; if (tilesetCollider == null) { tilesetCollider = control.GetComponent <Collider>(); } Bounds bounds = tilesetCollider.bounds; // Clear overlay mesh overlayMesh.Clear(true); // Init verticles and normals float y = bounds.max.y + 0.5f; overlayMesh.vertices = new[] { new Vector3(bounds.min.x, y, bounds.min.z), new Vector3(bounds.min.x, y, bounds.max.z), new Vector3(bounds.max.x, y, bounds.max.z), new Vector3(bounds.max.x, y, bounds.min.z) }; overlayMesh.normals = new[] { Vector3.up, Vector3.up, Vector3.up, Vector3.up }; // Init overlay UV OnlineMaps api = OnlineMaps.instance; Vector2 topLeftPosition = api.topLeftPosition; Vector2 bottomRightPosition = api.bottomRightPosition; Vector2 topLeftTile = OnlineMapsUtils.LatLongToTilef(topLeftPosition, api.zoom); Vector2 bottomRightTile = OnlineMapsUtils.LatLongToTilef(bottomRightPosition, api.zoom); int maxTileCount = 1 << api.zoom; float uvX1 = topLeftTile.x / maxTileCount; float uvX2 = bottomRightTile.x / maxTileCount; if (uvX1 > uvX2) { uvX2 += 1; } float uvY1 = 1 - topLeftTile.y / maxTileCount; float uvY2 = 1 - bottomRightTile.y / maxTileCount; overlayMesh.uv = new[] { new Vector2(uvX2, uvY1), new Vector2(uvX2, uvY2), new Vector2(uvX1, uvY2), new Vector2(uvX1, uvY1) }; // Init triangles overlayMesh.SetTriangles(new[] { 0, 1, 2, 0, 2, 3 }, 0); overlayMesh.RecalculateBounds(); overlayMesh.RecalculateNormals(); }
protected void FillPoly(Color[] buffer, OnlineMapsVector2i bufferPosition, int bufferWidth, int bufferHeight, int zoom, List <Vector2> points, Color color) { if (color.a == 0) { return; } List <Vector2> bufferPoints = new List <Vector2>(); float minX = float.MaxValue; float maxX = float.MinValue; float minY = float.MaxValue; float maxY = float.MinValue; foreach (Vector2 point in points) { Vector2 bufferPoint = (OnlineMapsUtils.LatLongToTilef(point, zoom) - bufferPosition) * OnlineMapsUtils.tileSize; if (bufferPoint.x < minX) { minX = bufferPoint.x; } if (bufferPoint.x > maxX) { maxX = bufferPoint.x; } if (bufferPoint.y < minY) { minY = bufferPoint.y; } if (bufferPoint.y > maxY) { maxY = bufferPoint.y; } bufferPoints.Add(bufferPoint); } float stY = Mathf.Clamp(minY, 0, bufferHeight); float stX = Mathf.Clamp(minX, 0, bufferWidth); float endY = Mathf.Clamp(maxY, 0, bufferHeight); float endX = Mathf.Clamp(maxX, 0, bufferWidth); int lengthX = Mathf.RoundToInt(endX - stX); int lengthY = Mathf.RoundToInt(endY - stY); Vector2 start = new Vector2(stX, stY); Color clr = new Color(color.r, color.g, color.b, 1); for (int y = 0; y < lengthY; y++) { float bufferY = y + start.y; for (int x = 0; x < lengthX; x++) { float bufferX = x + start.x; if (OnlineMapsUtils.IsPointInPolygon(bufferPoints, bufferX, bufferY)) { int bufferIndex = (int)bufferY * bufferWidth + (int)bufferX; if (color.a == 1) { buffer[bufferIndex] = color; } else { buffer[bufferIndex] = Color.Lerp(buffer[bufferIndex], clr, color.a); } } } } }
private void UpdateBuildingsPosition() { Bounds bounds = new Bounds(); Vector2 topLeftPosition = OnlineMaps.instance.topLeftPosition; Vector2 bottomRightPosition = OnlineMaps.instance.bottomRightPosition; bounds.min = new Vector3(topLeftPosition.x, bottomRightPosition.y); bounds.max = new Vector3(bottomRightPosition.x, topLeftPosition.y); List <string> unusedKeys = new List <string>(); bool useElevation = OnlineMapsTileSetControl.instance.useElevation; foreach (KeyValuePair <string, OnlineMapsBuildingBase> building in buildings) { if (!bounds.Intersects(building.Value.boundsCoords)) { unusedKeys.Add(building.Key); } else { if (useElevation) { Vector3 newPosition = OnlineMapsTileSetControl.instance.GetWorldPositionWithElevation(building.Value.centerCoordinates, topLeftPosition, bottomRightPosition); building.Value.transform.position = newPosition; } else { Vector3 newPosition = OnlineMapsTileSetControl.instance.GetWorldPosition(building.Value.centerCoordinates); building.Value.transform.position = newPosition; } } } List <string> usedKeys = new List <string>(); List <string> destroyKeys = new List <string>(); double px, py; api.GetPosition(out px, out py); OnlineMapsUtils.LatLongToTiled(px, py, api.zoom, out px, out py); float maxDistance = Mathf.Sqrt(Mathf.Pow(api.width / 2 / OnlineMapsUtils.tileSize, 2) + Mathf.Pow(api.height / 2 / OnlineMapsUtils.tileSize, 2)) * 2; foreach (KeyValuePair <string, OnlineMapsBuildingBase> building in unusedBuildings) { OnlineMapsBuildingBase value = building.Value; if (bounds.Intersects(value.boundsCoords)) { usedKeys.Add(building.Key); Vector3 newPosition = OnlineMapsTileSetControl.instance.GetWorldPosition(value.centerCoordinates); value.transform.position = newPosition; } else { Vector2 buildingTilePos = OnlineMapsUtils.LatLongToTilef(value.centerCoordinates, api.zoom); if ((buildingTilePos - new Vector2((float)px, (float)py)).magnitude > maxDistance) { destroyKeys.Add(building.Key); } } } foreach (string key in unusedKeys) { OnlineMapsBuildingBase value = buildings[key]; value.gameObject.SetActive(false); unusedBuildings.Add(key, value); buildings.Remove(key); } foreach (string key in usedKeys) { OnlineMapsBuildingBase value = unusedBuildings[key]; if (maxActiveBuildings > 0 && buildings.Count >= maxActiveBuildings) { break; } if (OnShowBuilding != null && !OnShowBuilding(value)) { continue; } value.gameObject.SetActive(true); buildings.Add(key, value); unusedBuildings.Remove(key); } foreach (string key in destroyKeys) { OnlineMapsBuildingBase value = unusedBuildings[key]; if (OnBuildingDispose != null) { OnBuildingDispose(value); } DestroyImmediate(value.gameObject); unusedBuildings.Remove(key); } if (destroyKeys.Count > 0) { OnlineMaps.instance.needGC = true; } }