Ejemplo n.º 1
0
    ///////////////////////////////////////////

    static async Task RequestHeight(BoundingBox regionBounds)
    {
        var request = new ElevationRequest()
        {
            Bounds      = regionBounds,
            Row         = 32,
            Col         = 32,
            BingMapsKey = _ApiKey
        };
        Response response = await request.Execute();

        if (response.StatusCode != 200)
        {
            Log.Warn("Bing Maps API error:\n" + string.Join('\n', response.ErrorDetails));
            return;
        }

        ElevationData data = response.ResourceSets[0].Resources[0] as ElevationData;

        Color[] heights = new Color[32 * 32];
        for (int y = 0; y < 32; y++)
        {
            for (int x = 0; x < 32; x++)
            {
                // Mount everest is 8,848m tall
                heights[x + (31 - y) * 32] = Color.White * (data.Elevations[x + y * 32] / 9000.0f);
            }
        }
        mapHeight = new Tex(TexType.ImageNomips, TexFormat.Rgba128);
        mapHeight.SetColors(32, 32, heights);
        mapHeight.AddressMode = TexAddress.Clamp;

        Geo.BoundsToWorld(regionBounds, regionBounds, out mapHeightSize, out mapHeightCenter);
        terrain.SetHeightData(mapHeight, mapHeightSize * worldScale, mapHeightCenter * worldScale);
    }
Ejemplo n.º 2
0
    public IEnumerator CreateTerrainZoom(int zoom)
    {
        Terrain t1 = GetComponent <Terrain>();

        t1.basemapDistance = 10000;
        Latlong       RBLl   = HarvenSin.pixelToLatlong(new Vector2(512 * 16, 512 * 16), latlongLT, zoom);
        ElevationData evData = new ElevationData();

        //string ElvURL = "http://dev.virtualearth.net/REST/v1/Elevation/Bounds?bounds="+ RBLl.lati+","+latlongLT.longti+","+latlongLT.lati+","+ RBLl.longti+"&rows=32&cols=32&heights=ellipsoid&key="+bingKey;
        //yield return StartCoroutine(evData.GetDataFormUrl(ElvURL));
        yield return(StartCoroutine(evData.GetElv(latlongLT, zoom)));

        float[,] heightmap = evData.GetHeightMap();
        //float[,] heightmap = evData.GetHeightMap(32, 32);
        t1.terrainData.heightmapResolution = evData.size;
        t1.terrainData.SetHeights(0, 0, heightmap);
        //yield return StartCoroutine(GetImageFormTile(latlongLT,16,16,19));
        yield return(StartCoroutine(ImageDataP.GetImageFormUrl(latlongLT, 16, 16, zoom)));

        SplatPrototype[] sp = new SplatPrototype[1];
        t1.terrainData.size = new Vector3((float)HarvenSin.Distance(latlongLT.lati, latlongLT.longti, latlongLT.lati, RBLl.longti) * 1000, 10000f, (float)HarvenSin.Distance(RBLl.lati, latlongLT.longti, latlongLT.lati, latlongLT.longti) * 1000f);
        sp[0] = CreateSplatPrototype(imageCombined, new Vector2(t1.terrainData.size.x, t1.terrainData.size.z), new Vector2(0f, 0f));
        File.WriteAllBytes("Assets/TerrainTexture/test.jpg", imageCombined.EncodeToJPG());//output Texture
        t1.terrainData.splatPrototypes = sp;
    }
Ejemplo n.º 3
0
        public static Vertices3[] MakeRegularMesh(ref ElevationData evData)
        {
            evData.Elev[0] = 1;
            int ratio = 32768 / evData.TileSize;
            //  min = double.MaxValue;
            //   max = double.MinValue;
            double fact = (evData.MaxElevation - evData.MinElevation) / 32768;

            Vertices3[] vertices = new Vertices3[evData.TileSize * evData.TileSize];

            for (int i = 0; i < evData.TileSize; i++)
            {
                for (int j = 0; j < evData.TileSize; j++)
                {
                    var pos = j + (i * evData.TileSize);
                    var elv = evData.Elev[pos];
                    //     if (elv < min)
                    //      min = elv;
                    //   if (elv > max)
                    //    max = elv;
                    vertices[i] = new Vertices3((ushort)(32767 - (i * ratio)), (ushort)(32767 - (j * ratio)), ConvertRange(evData.MinElevation, evData.MaxElevation, elv));
                }
            }

            return(vertices);
        }
Ejemplo n.º 4
0
        /// <summary>
        /// Setup GridSize for tile
        /// </summary>
        private void Initialise()
        {
            QMTileResponse.ResultStatus = RequestErrorStatus.FailedToBuildQuantizedMeshTile;
            ResultStatus = RequestErrorStatus.FailedToBuildQuantizedMeshTile;

            // Determine the QM tile resolution by the zoom level
            if (OverrideGridSize != QMConstants.NoGridSize)
            {
                TileGridSize = OverrideGridSize;
            }
            else
            {
                if (TileZ >= QMConstants.HighResolutionLevel)
                {
                    TileGridSize = QMConstants.HighResolutionGridSize;
                }
                else if (TileZ >= QMConstants.MidResolutionLevel)
                {
                    TileGridSize = QMConstants.MidResolutionGridSize;
                }
                else
                {
                    TileGridSize = QMConstants.FlatResolutionGridSize;
                }
            }

            // Setup for return. In most cases you want to at least return an empty tile
            ElevData = new ElevationData(LowestElevation, TileGridSize); // elevation grid
        }
Ejemplo n.º 5
0
        /// <summary>
        /// Creates a demo tile. Useful for development
        /// </summary>
        /// <returns></returns>
        private bool BuildDemoTile()
        {
            _log.LogDebug($"#Tile.({TileX},{TileY}) Returning demo tile. (X:{TileX}, Y:{TileX},{TileY}, Z:{TileZ}), GridSize{QMConstants.DemoResolutionGridSize}");
            // Even empty tiles must have header info correctly calculated
            if (ElevData.GridSize == QMConstants.NoGridSize)
            {
                ElevData = new ElevationData(LowestElevation, QMConstants.DemoResolutionGridSize); // elevation grid
            }
            ElevData.MakeDemoTile(TileBoundaryLL);

            QMTileBuilder tileBuilder = new QMTileBuilder()
            {
                TileData = ElevData,
                GridSize = ElevData.GridSize
            };

            if (!tileBuilder.BuildQuantizedMeshTile())
            {
                _log.LogError($"Tile.({TileX},{TileY}) failed to build demo tile. Error code: {tileBuilder.BuildTileFaultCode}");
                return(false);
            }

            QMTileResponse.ResultStatus = RequestErrorStatus.OK;
            QMTileResponse.data         = tileBuilder.QuantizedMeshTile; // return QM tile in response
            ResultStatus = RequestErrorStatus.OK;
            return(true);
        }
Ejemplo n.º 6
0
        /// <summary>
        /// No data so return an empty tile
        /// </summary>
        /// <returns></returns>
        private bool BuildEmptyTile()
        {
            _log.LogDebug($"#Tile#.({TileX},{TileY}) Execute End. Returning empty tile. Zoom:{TileZ}, GridSize{QMConstants.FlatResolutionGridSize}");
            // Even empty tiles must have header info correctly calculated
            if (ElevData.GridSize == QMConstants.NoGridSize)
            {
                ElevData = new ElevationData(LowestElevation, QMConstants.FlatResolutionGridSize); // elevation grid
            }
            ElevData.MakeEmptyTile(TileBoundaryLL, HasLighting);
            if (ElevData.HasLighting)
            {
                ComputeNormalMap();
            }

            QMTileBuilder tileBuilder = new QMTileBuilder()
            {
                TileData = ElevData,
                GridSize = ElevData.GridSize
            };

            if (!tileBuilder.BuildQuantizedMeshTile())
            {
                _log.LogError($"Tile.({TileX},{TileY}) failed to build empty tile. Error code: {tileBuilder.BuildTileFaultCode}");
                return(false);
            }

            QMTileResponse.ResultStatus = RequestErrorStatus.OK;
            QMTileResponse.data         = tileBuilder.QuantizedMeshTile; // return QM tile in response
            ResultStatus = RequestErrorStatus.OK;
            return(true);
        }
Ejemplo n.º 7
0
        public void GenerateElevationProfile3(GpsLocation myLocation, double visibility, ElevationProfileData elevationData, Action <int> onProgressChange)
        {
            _elevationProfileData = new ElevationProfileData(myLocation, visibility);

            int progress = 0;

            foreach (var group in elevationData.GetData())
            {
                progress++;
                onProgressChange(progress);

                var points = group.GetPoints()
                             .Where(i => i.Distance > MIN_DISTANCE && i.Distance < visibility * 1000)
                             .OrderBy(i => i.Distance);

                //Select visible points
                List <GpsLocation> tmpVisiblePoints = new List <GpsLocation>();
                double             maxViewAngle     = -90;
                foreach (var point in points)
                {
                    if (point.VerticalViewAngle > maxViewAngle)
                    {
                        tmpVisiblePoints.Add(point);
                        maxViewAngle = point.VerticalViewAngle.Value;
                    }
                }

                //Change order (now from the furthest to the nearest)
                tmpVisiblePoints.Reverse();

                //... and ignore points on descending slope
                GpsLocation lastPoint      = null;
                GpsLocation lastAddedPoint = null;
                var         ed             = new ElevationData(group.Angle);
                foreach (var point in tmpVisiblePoints)
                {
                    if (lastPoint == null)
                    {
                        ed.Add(point);
                        lastAddedPoint = point;
                        lastPoint      = point;
                        continue;
                    }

                    //TODO: comment-out the folowing if for full rendering
                    var distanceDiff = lastPoint.Distance.Value - point.Distance.Value;
                    if (distanceDiff < lastPoint.Distance / 100 + 50)
                    {
                        lastPoint = point;
                        continue;
                    }

                    ed.Add(point);
                    lastAddedPoint = point;
                    lastPoint      = point;
                }
                _elevationProfileData.Add(ed);
            }
        }
Ejemplo n.º 8
0
    ///////////////////////////////////////////

    public static async Task RequestHeight(string apiKey, BoundingBox regionBounds, Action <Tex, Vec3, Vec2> OnReceivedHeight)
    {
        // Here's an elevation request! This doesn't provide an image, rather,
        // it gives us a grid of height values. It's limited to a maximum of
        // 1024 values per request, so we're only asking for a grid of 32x32
        // elevations.
        // However! This request does work exactly within the bounds provided,
        // so we're getting what we expect from the results of this request.
        // Details about the request can be found here:
        // https://github.com/microsoft/BingMapsRESTToolkit/blob/master/Docs/API%20Reference.md#ElevationRequest
        ElevationRequest request = new ElevationRequest()
        {
            Bounds      = regionBounds,
            Row         = 32,
            Col         = 32,
            BingMapsKey = apiKey
        };
        Response response = await ServiceManager.GetResponseAsync(request);

        // StatusCode is a web response status code, where 200-299 means
        // success. Details here:
        // https://developer.mozilla.org/en-US/docs/Web/HTTP/Status
        if (response.StatusCode < 200 || response.StatusCode >= 300)
        {
            Log.Warn("Bing Maps API error:\n" + string.Join('\n', response.ErrorDetails));
            return;
        }

        // Convert the elevation data we've received into a grayscale heightmap texture!
        ElevationData data = response.ResourceSets[0].Resources[0] as ElevationData;

        Color[] heights = new Color[32 * 32];
        for (int y = 0; y < 32; y++)
        {
            for (int x = 0; x < 32; x++)
            {
                float height = data.Elevations[x + y * 32] / Geo.EarthTallest;
                // Height data is provided upside-down, so we're flipping it with
                // this index on the Y axis.
                heights[x + (31 - y) * 32] = Color.White * height;
            }
        }

        // Create a texture from the elevation data! We're storing it as
        // Rgba128 to preserve floating point precision in the height values.
        Tex texture = new Tex(TexType.ImageNomips, TexFormat.Rgba128);

        texture.SetColors(32, 32, heights);
        texture.AddressMode = TexAddress.Clamp;

        // Our bounds should be correct, but we still need it in StereoKit
        // units, so convert!
        Geo.BoundsToWorld(regionBounds, regionBounds, out Vec3 size, out Vec2 center);

        // Done! Pass the results back.
        OnReceivedHeight(texture, size, center);
    }
Ejemplo n.º 9
0
        // todo work out bounding sphere

        public static void ComputeHeaderInfo(ref ElevationData evlData)
        {
            int m = 0;

            for (int y = 0; y < evlData.GridSize; y++)
            {
                for (int x = 0; x < evlData.GridSize; x++)
                {
                    //   vertices.AddVertex(m, (ushort)(x * ratio), (ushort)(y * ratio), QuantizeHeight(evlData.MinElevation, evlData.MaxElevation, evlData.Elev[m]));
                    m++;
                }
            }
        }
Ejemplo n.º 10
0
        public ElevationData ParseElevationData(byte[] fileData, int offset, int dbp)
        {
            _byteReader.Seek(offset + dbp + 28);
            var elevationData = new ElevationData()
            {
                BlockType   = _byteReader.ReadString(fileData, 1),
                Name        = _byteReader.ReadString(fileData, 3),
                Size        = _byteReader.ReadShort(fileData),
                Atmos       = _byteReader.ReadShort(fileData),
                Calibration = _byteReader.ReadFloat(fileData),
            };

            _dataLogger.Log("Location 5 - End of Elevation Data - at byte location - " + _byteReader.Offset);
            _dataLogger.Log(JsonConvert.SerializeObject(elevationData));

            return(elevationData);
        }
Ejemplo n.º 11
0
        public VertexData MakeQuantizedMesh(ref ElevationData evlData)
        {
            int        ratio    = 32767 / evlData.GridSize;
            VertexData vertices = new VertexData((uint)evlData.GridSize, (uint)evlData.GridSize);
            // data flows sw to se and up
            int  m        = 0;
            bool firstRow = true;

            for (int y = 0; y <= evlData.GridSize; y++)
            {
                for (int x = 0; x <= evlData.GridSize; x++)
                {
                    vertices.AddVertex(m, (ushort)(x * ratio), (ushort)(y * ratio), QuantizeHeight(evlData.MinimumHeight, evlData.MaximumHeight, evlData.Elev[m]));
                    m++;
                }
            }
            return(vertices);
        }
Ejemplo n.º 12
0
        public void TileBuilder_BuildTile()
        {
            LLBoundingBox TileBoundaryLL = MapGeo.TileXYZToRectLL(0, 0, 20, out var yFlip);
            ElevationData elevData       = new ElevationData(0, 5);

            elevData.MakeEmptyTile(TileBoundaryLL, false);
            QMTileBuilder tileBuilder = new QMTileBuilder()
            {
                TileData = elevData,
                GridSize = elevData.GridSize
            };

            var res = tileBuilder.BuildQuantizedMeshTile();

            res.Should().Be(true);
            tileBuilder.QuantizedMeshTile.Should().HaveCountGreaterOrEqualTo(162);
            tileBuilder.QuantizedMeshTile.Should().HaveCountLessOrEqualTo(164);
        }
Ejemplo n.º 13
0
        private IEnumerator AddTerrain(Place place)
        {
            // Store current place
            this._place = place;

            // Convert lat/long to Google/Bing/AGOL tile.
            var tile = this._place.Location.ToTile(this._place.Level);

            // Get children.
            var children = tile.GetChildren(CHILDREN_LEVEL);

            // Elevation and texture variables.
            ElevationData el = null;

            Texture2D[] textures = new Texture2D[children.Length];
            yield return(null);

            // Retrieve elevation.
            this.StartCoroutine(Elevation.GetHeights(tile, elevation =>
            {
                el = elevation;
                // Construct terrain if both elevation and textures downloaded.
                if (textures.All(t => t != null))
                {
                    this.StartCoroutine(this.BuildTerrain(el, textures));
                }
            }));
            yield return(null);

            // Retrieve imagery.
            foreach (var child in children)
            {
                this.StartCoroutine(Imagery.GetTexture(child, texture =>
                {
                    textures[Array.IndexOf(children, child)] = texture;
                    // Construct terrain if both elevation and textures downloaded.
                    if (el != null && textures.All(t => t != null))
                    {
                        this.StartCoroutine(this.BuildTerrain(el, textures));
                    }
                }));
            }
        }
Ejemplo n.º 14
0
 /// <summary>
 /// Make tile header record
 /// </summary>
 private void MakeHeader(ref ElevationData evData)
 {
     // todo fill in all fields correctly
     Header = new TerrainTileHeader()
     {
         CenterX                = -4869750.60295,
         CenterY                = 517839.417383868,
         CenterZ                = -4005385.98852821,
         MinimumHeight          = evData.MinElevation,
         MaximumHeight          = evData.MaxElevation,
         BoundingSphereCenterX  = -4869750.60295,
         BoundingSphereCenterY  = 517839.417383868,
         BoundingSphereCenterZ  = -4005385.98852821,
         BoundingSphereRadius   = 832547.176047396,
         HorizonOcclusionPointX = -0.775337351286795,
         HorizonOcclusionPointY = 0.0824478037997883,
         HorizonOcclusionPointZ = -0.639862876673674
     };
 }
Ejemplo n.º 15
0
        public static VertexData MakeQuantizedMesh(ref ElevationData evlData)
        {
            // This ratio is an integer and represents the grids intervals in a range from 0 to 32767
            // GridSize should always be an odd number for best result
            int ratio = QMConstants.TileValueRange / (evlData.GridSize - 1);

            VertexData vertices = new VertexData((uint)evlData.GridSize, (uint)evlData.GridSize);
            // data flows sw to se and up
            int m = 0;

            for (int y = 0; y < evlData.GridSize; y++)
            {
                for (int x = 0; x < evlData.GridSize; x++)
                {
                    vertices.AddVertex(m, (ushort)(x * ratio), (ushort)(y * ratio), QuantizeHeight(evlData.MinimumHeight, evlData.MaximumHeight, evlData.ElevGrid[m]));
                    m++;
                }
            }
            return(vertices);
        }
Ejemplo n.º 16
0
        public VertexData MakeFakeMesh(ref ElevationData evlData)
        {
            // Simple routine to convert or grid of float elevations into a format suitable for a quantized mesh of unsigned short ints

            VertexData vertices = new VertexData((uint)evlData.GridSize, (uint)evlData.GridSize);

            try
            {
                double ratio = 32767 / (double)(evlData.GridSize - 1);

                // data flows sw to se and up
                int m = 0;
                for (int y = 0; y < evlData.GridSize; y++)
                {
                    for (int x = 0; x < evlData.GridSize; x++)
                    {
                        try
                        {
                            // todo ratio is wrong
                            vertices.AddVertex(m, (ushort)(x * ratio), (ushort)(y * ratio),
                                               QuantizeHeight(evlData.MinimumHeight, evlData.MaximumHeight, evlData.Elev[m]));
                        }
                        catch (Exception ex1)
                        {
                            System.Diagnostics.Debug.WriteLine($"**** MakeFakeMesh Error *********:{ex1}");
                        }
                        m++;
                    }
                }
            }
            catch (Exception ex)
            {
#if DEBUG
                System.Diagnostics.Debug.WriteLine($"**** MakeFakeMesh Error *********:{ex}");
#endif
            }

            return(vertices);
        }
Ejemplo n.º 17
0
        private ElevationData GetElevationDataForAngle(ushort angle, GpsLocation myLocation, double maxDistance, ElevationTileCollection etc)
        {
            var ed = new ElevationData(angle);

            for (double d = 500; d < maxDistance; d += Math.Min(100, d / 100))
            {
                var x = GpsUtils.QuickGetGeoLocation(myLocation, d, angle);
                //int size = d < 5000 ? 1 : 3;
                int size = Math.Min(((int)d / 20000) + 1, 4);//0-20:1 20-40:2 40-60:3 60-100:4
                if (etc.TryGetElevation(x, out var elevation, size))
                {
                    x.Altitude = elevation;
                    x.Distance = d;
                    x.Bearing  = angle;
                    x.GetVerticalViewAngle(myLocation);

                    ed.Add(x);
                }
            }

            return(ed);
        }
Ejemplo n.º 18
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="bbox"></param>
        /// <returns></returns>
        private ElevationData MakeTileDEM(LLBoundingBox bbox)
        {
            // Steps
            // Using bounding box get elevation data for tile
            // Calculate header info

            Vector3[]     ecefPoints;
            ElevationData ed = GetData(bbox, out ecefPoints);

            // Work out bounding sphere
            TileInfo tileInfo = new TileInfo();
            var      hdr      = tileInfo.CalculateHeaderInfo(ref ecefPoints, false);

            ed.CenterX = hdr.CenterX;
            ed.CenterY = hdr.CenterY;
            ed.CenterZ = hdr.CenterZ;
            ed.BoundingSphereCenterX = hdr.CenterX;
            ed.BoundingSphereCenterY = hdr.CenterY;
            ed.BoundingSphereCenterZ = hdr.CenterZ;
            ed.BoundingSphereRadius  = hdr.BoundingSphereRadius;

            // Work out HorizonOcclusionPoint
            var hop = HorizonOcclusionPoint.FromPoints(ecefPoints, tileInfo.BoundingSphere);

            ed.HorizonOcclusionPointX = hop.X;
            ed.HorizonOcclusionPointY = hop.Y;
            ed.HorizonOcclusionPointZ = hop.Z;

            /* Quicker cheat method untested
             * ed.HorizonOcclusionPointX = hdr.CenterX;
             * ed.HorizonOcclusionPointY = hdr.CenterY;
             * ed.HorizonOcclusionPointZ = maxElev;
             */

            // todo lighting

            return(ed);
        }
Ejemplo n.º 19
0
        public static VertexData MakeRegularQMesh(ref ElevationData evData)
        {
            evData.Elev[0] = 1;
            int        ratio    = 32768 / evData.TileSize;
            double     fact     = (evData.MaxElevation - evData.MinElevation) / 32768;
            VertexData vertices = new VertexData((uint)evData.TileSize, (uint)evData.TileSize);

            for (int i = 0; i < evData.TileSize; i++)
            {
                for (int j = 0; j < evData.TileSize; j++)
                {
                    var pos = j + (i * evData.TileSize);
                    var elv = evData.Elev[pos];
                    //     if (elv < min)
                    //      min = elv;
                    //   if (elv > max)
                    //    max = elv;
                    vertices.AddVertex(pos, (ushort)(32767 - (i * ratio)), (ushort)(32767 - (j * ratio)), ConvertRange(evData.MinElevation, evData.MaxElevation, elv));
                }
            }

            return(vertices);
        }
Ejemplo n.º 20
0
        public async Task <byte[]> QuantizeDEMAsync(ElevationData ed)
        {
            //  throw new NotImplementedException();

            VertexData verts = QuantizeMesh.MakeRegularQMesh(ref ed);

            // Assemble tile data
            MakeHeader(ref ed);
            MakeVertexData(ed.TileSize, ref verts);
            MakeIndexData();
            MakeEdgeIndicesData();


            //   var newTerrain = new TerrainTile();
            var ms = new MemoryStream();

            using (BinaryWriter writer = new BinaryWriter(ms))
            //      using (BinaryWriter writer = new BinaryWriter(File.Open(outFile, FileMode.Create)))
            {
                // write header
                writer.Write(Header.CenterX);
                writer.Write(Header.CenterY);
                writer.Write(Header.CenterZ);
                writer.Write(Header.MinimumHeight);
                writer.Write(Header.MaximumHeight);
                writer.Write(Header.BoundingSphereCenterX);
                writer.Write(Header.BoundingSphereCenterY);
                writer.Write(Header.BoundingSphereCenterZ);
                writer.Write(Header.BoundingSphereRadius);
                writer.Write(Header.HorizonOcclusionPointX);
                writer.Write(Header.HorizonOcclusionPointY);
                writer.Write(Header.HorizonOcclusionPointZ);


                // write vertex data
                EncodeVertexBuffer(VertexData); // quantize
                writer.Write(VertexData.vertexCount);
                for (int i = 0; i < VertexData.vertexCount; i++)
                {
                    writer.Write(VertexData.u[i]); // longitude
                }
                for (int i = 0; i < VertexData.vertexCount; i++)
                {
                    writer.Write(VertexData.v[i]); // latitude
                }
                for (int i = 0; i < VertexData.vertexCount; i++)
                {
                    writer.Write(VertexData.height[i]); //heights
                }
                // write triangle indices
                EncodeIndices(IndexData16);
                writer.Write(IndexData16.triangleCount);
                for (int i = 0; i < IndexData16.triangleCount * 3; i++)
                {
                    writer.Write(IndexData16.indices[i]);
                }

                // write west indices
                writer.Write(EdgeIndices16.westVertexCount);
                for (int i = 0; i < EdgeIndices16.westVertexCount; i++)
                {
                    writer.Write(EdgeIndices16.westIndices[i]);
                }

                // write south indices
                writer.Write(EdgeIndices16.southVertexCount);
                for (int i = 0; i < EdgeIndices16.southVertexCount; i++)
                {
                    writer.Write(EdgeIndices16.southIndices[i]);
                }

                // write east indices
                writer.Write(EdgeIndices16.eastVertexCount);
                for (int i = 0; i < EdgeIndices16.eastVertexCount; i++)
                {
                    writer.Write(EdgeIndices16.eastIndices[i]);
                }

                // write north indices
                writer.Write(EdgeIndices16.northVertexCount);
                for (int i = 0; i < EdgeIndices16.northVertexCount; i++)
                {
                    writer.Write(EdgeIndices16.northIndices[i]);
                }

                // todo normals

                // var bytes = File.ReadAllBytes(ms);


//        using (FileStream fs = new FileStream(outFile, FileMode.Create))
                //       using (GZipStream zipStream = new GZipStream(fs, CompressionMode.Compress, false))
                //      {
                //       zipStream.Write(ms.ToArray(), 0, ms.ToArray().Length);// .Write(bytes, 0, bytes.Length);
                //    }


                byte[] buffer = ms.ToArray(); // new byte[100];

                return(buffer);
            }
        }
Ejemplo n.º 21
0
        /*
         * https://cesium.com/blog/2013/05/09/computing-the-horizon-occlusion-point/
         * private computeMagnitude(ellipsoid, position, scaledSpaceDirectionToPoint)
         * {
         * var scaledSpacePosition = ellipsoid.transformPositionToScaledSpace(position);
         * var magnitudeSquared = scaledSpacePosition.magnitudeSquared();
         * var magnitude = Math.sqrt(magnitudeSquared);
         * var direction = scaledSpacePosition.divideByScalar(magnitude);
         *
         * // For the purpose of this computation, points below the ellipsoid
         * // are considered to be on it instead.
         * magnitudeSquared = Math.max(1.0, magnitudeSquared);
         * magnitude = Math.max(1.0, magnitude);
         *
         * var cosAlpha = direction.dot(scaledSpaceDirectionToPoint);
         * var sinAlpha = direction.cross(scaledSpaceDirectionToPoint).magnitude();
         * var cosBeta = 1.0 / magnitude;
         * var sinBeta = Math.sqrt(magnitudeSquared - 1.0) * cosBeta;
         *
         * return 1.0 / (cosAlpha * cosBeta - sinAlpha * sinBeta);
         * }
         */

        /// <summary>
        /// By LatLon
        /// </summary>
        /// <param name="bb"></param>
        /// <returns></returns>
        private ElevationData MakeTileDEM(LLBoundingBox bb)
        {
            // todo we also need to comput header info for the quantized mesh


            Vector2 v;

            v.X = 0;
            v.Y = 0;
            int x2         = 0;
            int y2         = 0;
            int PixelCount = GridSize - 1;


            var DoRandom = false;
            int HgtMode  = 2;

            float minElev = float.PositiveInfinity;
            float maxElev = float.NegativeInfinity;

            Random rnd = new Random();

            ElevationData ed = new ElevationData(GridSize);

            var midPt = bb.GetCenter();
            //  var pt2 =  Coord.geo_to_ecef(new Vector3( MapUtil.Deg2Rad(midPt.Longitude), MapUtil.Deg2Rad(midPt.Latitude),0)); // zero elevation for now
            var pt = MapUtil.LatLonToEcef(midPt.Latitude, midPt.Longitude, 0); // zero elevation for now

            Vector3[] ecefPoints = new Vector3[GridSize * GridSize];

            try
            {
                // we are going to walk up from sw to ne for returning dem in latlon coordinates
                var yRange = bb.North - bb.South;
                var xRange = bb.East - bb.West;
                var xStep  = xRange / PixelCount;
                var yStep  = yRange / PixelCount;


                int   i   = 0;
                float hgt = 0;
                for (int y = 0; y < GridSize; y++)
                {
                    for (int x = 0; x < GridSize; x++)
                    {
                        var lat = bb.South + (y * yStep);
                        var lon = bb.West + (x * xStep);
                        v = MapProject(lat, lon); // MapProject is lat long


                        if (v.X >= Width)
                        {
                            v.X = Width - 1;
                        }
                        if (v.Y >= Depth)
                        {
                            v.Y = Depth - 1;
                        }
                        if (v.X < 0)
                        {
                            v.X = 0;
                        }
                        if (v.Y < 0)
                        {
                            v.Y = 0;
                        }

                        x2 = (int)v.X;
                        y2 = (int)v.Y;

                        //hgt = 0;
                        // if (i == 4)
                        //  hgt = 100;

                        if (HgtMode == 1)
                        {
                            ed.Elev[i] = rnd.Next(1, 8000);
                        }
                        else if (HgtMode == 2)
                        {
                            ed.Elev[i] = 0;
                            if (lat >= -43.548006 & lat <= -43.547679)
                            {
                                if (lon >= 172.632951 & lon <= 172.633542)
                                {
                                    ed.Elev[i] = (float)10.0;
                                }
                            }
                        }
                        else
                        {
                            hgt        = Map.GetPixel(x2, y2).GetBrightness(); // 0=black, 1= white
                            ed.Elev[i] = MapUtil.Lerp(0, 1, ElevMin, ElevMax, hgt);
                        }

                        if (ed.Elev[i] < minElev)
                        {
                            minElev = ed.Elev[i];
                        }

                        if (ed.Elev[i] > maxElev)
                        {
                            maxElev = ed.Elev[i];
                        }

                        // Make ecef point list for later calculations
                        ecefPoints[i] = Coord.geo_to_ecef(new Vector3()
                        {
                            X = MapUtil.Deg2Rad(lon), Y = MapUtil.Deg2Rad(lat), Z = ed.Elev[i]
                        });


                        i++;
                    }
                }
            }
            catch (Exception ex)
            {
#if DEBUG
                System.Diagnostics.Debug.WriteLine($"**** MakeTileDEM Exception ****:{ex} v:{v} x2{x2} y2{y2} ");
// file writer        System.Diagnostics.Trace.WriteLine($"**** MakeTileDEM Exception *********:{ex} v:{v} x2{x2} y2{y2} ");
#endif
            }

            // todo now make a ecfc array to calculate header info
            TileInfo tileInfo = new TileInfo();
            var      hdr      = tileInfo.CalculateHeaderInfo(ref ecefPoints, false);
            ed.CenterX = hdr.CenterX;
            ed.CenterY = hdr.CenterY;
            ed.CenterZ = hdr.CenterZ;
            ed.BoundingSphereCenterX = hdr.CenterX;
            ed.BoundingSphereCenterY = hdr.CenterY;
            ed.BoundingSphereCenterZ = hdr.CenterZ;
            ed.BoundingSphereRadius  = hdr.BoundingSphereRadius;
            ed.MaximumHeight         = maxElev;
            ed.MinimumHeight         = minElev;


            var hop = HorizonOcclusionPoint.FromPoints(ecefPoints, tileInfo.BoundingSphere);
            ed.HorizonOcclusionPointX = hop.X;
            ed.HorizonOcclusionPointY = hop.Y;
            ed.HorizonOcclusionPointZ = hop.Z;


            /*
             * // FIXME: is there a better choice for a horizon occlusion point?
             * // Currently it's the center of tile elevated to bbox's max Z
             * header.horizon_occlusion = c;
             * header.horizon_occlusion.z = bbox.max.z;
             *
             *
             * ed.HorizonOcclusionPointX = hdr.CenterX;
             * ed.HorizonOcclusionPointY = hdr.CenterY;
             * ed.HorizonOcclusionPointZ = maxElev;
             */
            return(ed);
        }
Ejemplo n.º 22
0
        private IEnumerator AddTerrain(Place place)
        {
            // Store current place
            this._place = place;

            // Convert lat/long to Google/Bing/AGOL tile.
            var tile = this._place.Location.ToTile(this._place.Level);

            // Get children.
            //var children = tile.GetChildren(CHILDREN_LEVEL);

            var children = tile.GetNeighbor(CHILDREN_LEVEL);

            // Elevation and texture variables.
            ElevationData el = null;

            Texture2D[] textures = new Texture2D[children.Length];
            yield return(null);

            // Retrieve elevation.

            if (currentDimension == "3D")
            {
                this.StartCoroutine(Elevation.GetHeights(tile, elevation =>
                {
                    el = elevation;
                    // Construct terrain if both elevation and textures downloaded.
                    if (textures.All(t => t != null))
                    {
                        this.StartCoroutine(this.BuildTerrain(el, textures));
                    }
                }));
                yield return(null);
            }

            // Retrieve imagery.
            foreach (var child in children)
            {
                this.StartCoroutine(Imagery.GetTexture(child, currentStyle, texture =>
                {
                    textures[Array.IndexOf(children, child)] = texture;
                    // Construct terrain if both elevation and textures downloaded.
                    //if (el != null && textures.All(t => t != null))
                    if (textures.All(t => t != null))
                    {
                        this.StartCoroutine(this.BuildTerrain(el, textures));
                    }
                }));
            }
            //add 2

            /*
             * if (needupdate)
             * {
             *  this.StartCoroutine(this.Updatemap(updateURL));
             *  //destroy all exist building,erase the items form
             *  GameObject[] gameObjects = GameObject.FindGameObjectsWithTag("Rotate");
             *  for (var i = 0; i < gameObjects.Length; i++)
             *  {
             *      Destroy(gameObjects[i]);
             *  }
             *  //StartCoroutine(Eraseitems(queryURL));
             * }
             */
        }
Ejemplo n.º 23
0
        public async override Task <ElevationData> GetDemLL(double lonMin, double latMin, double lonMax, double latMax)
        {
            // create grid of uniform heights
            var dem = new ElevationData();

            dem.MinimumHeight = float.MaxValue;
            dem.MaximumHeight = float.MinValue;
            dem.GridSize      = GridSize;
            float hgt;

            dem.Elev = new float[GridSize * GridSize];
            // elevation order will be from sw, se, and up
            // old standard example form Cesium code for tilesize 1, 2 triangles. slopes from nw to se
            if (GridSize == 2)
            {
                dem.Elev[0]       = 100;
                dem.Elev[1]       = 200;
                dem.Elev[2]       = 0;
                dem.Elev[3]       = 100;
                dem.MinimumHeight = 0;
                dem.MaximumHeight = 400;
            }
            else if (GridSize == 3)
            {
                dem.Elev[0]       = 0;
                dem.Elev[1]       = 0;
                dem.Elev[2]       = 0;
                dem.Elev[3]       = 0;
                dem.Elev[4]       = 100;
                dem.Elev[5]       = 0;
                dem.Elev[6]       = 0;
                dem.Elev[7]       = 0;
                dem.Elev[8]       = 0;
                dem.MinimumHeight = 0;
                dem.MaximumHeight = 100;
            }
            else
            {
                //Basic slope. Todo staircase
                hgt = 0;
                int pos = 0;
                for (int y = 0; y < GridSize; y++)
                {
                    for (int x = 0; x < GridSize; x++)
                    {
                        if (x == 0 || y == 0)
                        {
                            dem.Elev[pos] = 0;
                        }
                        else
                        {
                            dem.Elev[pos] = hgt;
                        }
                        if (hgt < dem.MinimumHeight)
                        {
                            dem.MinimumHeight = hgt;
                        }
                        if (hgt > dem.MaximumHeight)
                        {
                            dem.MaximumHeight = hgt;
                        }
                        pos++;
                    }

                    if (y > GridSize / 2)
                    {
                        hgt = hgt + (float)-0.5;
                    }
                    else
                    {
                        hgt = hgt + (float)0.5;
                    }
                }
            }

            return(dem);
        }
Ejemplo n.º 24
0
        private ElevationData GetData(LLBoundingBox bbox, out Vector3[] ecefPoints)
        {
            //todo get data from TRex
            //Boolean dataAvailable = true;
            // if ((lat >= -43.548006 & lat <= -43.547679) & (lon >= 172.632951 & lon <= 172.633542))
            ElevationData ed;

            LLBoundingBox data           = new LLBoundingBox(172.632951, -43.548006, 172.633542, -43.547679);
            bool          dataAvailable  = data.East >= bbox.West && data.West <= bbox.East && data.North >= bbox.South && data.South <= bbox.North;
            LLBoundingBox data2          = new LLBoundingBox(-0.124629, 51.500745, 1.0, 51.6);
            bool          dataAvailable2 = data2.East >= bbox.West && data2.West <= bbox.East && data2.North >= bbox.South && data2.South <= bbox.North;

            int _gridSize;

            if (dataAvailable | dataAvailable2)
            {
                _gridSize = GridSize;
            }
            else
            {
                _gridSize = 2;
            }
            ed         = new ElevationData(_gridSize);
            ecefPoints = new Vector3[_gridSize * _gridSize];

            int PixelCount = _gridSize - 1;

            var    yRange  = bbox.North - bbox.South;
            var    xRange  = bbox.East - bbox.West;
            var    xStep   = xRange / PixelCount;
            var    yStep   = yRange / PixelCount;
            float  minElev = float.PositiveInfinity;
            float  maxElev = float.NegativeInfinity;
            Random rnd     = new Random();
            int    i       = 0;
            float  hgt     = 0;
            var    HgtMode = 2;

            for (int y = 0; y < GridSize; y++)
            {
                for (int x = 0; x < GridSize; x++)
                {
                    var lat = bbox.South + (y * yStep);
                    var lon = bbox.West + (x * xStep);


                    if (HgtMode == 1)
                    {
                        ed.Elev[i] = rnd.Next(1, 8000);
                    }
                    else if (HgtMode == 2)
                    {
                        if ((lat >= -43.548006 & lat <= -43.547679) & (lon >= 172.632951 & lon <= 172.633542))
                        {
                            ed.Elev[i] = (float)10.0;
                        }
                        else if ((lat >= 51.500745 & lat <= 51.6) & (lon >= -0.124629 & lon <= 1.0))
                        {
                            ed.Elev[i] = rnd.Next(1, 10);
                        }
                        else
                        {
                            ed.Elev[i] = 0;
                        }
                    }

                    if (ed.Elev[i] < minElev)
                    {
                        minElev = ed.Elev[i];
                    }

                    if (ed.Elev[i] > maxElev)
                    {
                        maxElev = ed.Elev[i];
                    }

                    // Make ecef point list for later header calculations
                    ecefPoints[i] = Coord.geo_to_ecef(new Vector3()
                    {
                        X = MapUtil.Deg2Rad(lon), Y = MapUtil.Deg2Rad(lat), Z = ed.Elev[i]
                    });

                    i++;
                }
            }

            ed.MaximumHeight = maxElev;
            ed.MinimumHeight = minElev;
            return(ed);
        }
Ejemplo n.º 25
0
        private IEnumerator BuildTerrain(ElevationData elevation, Texture2D[] textures)
        {
            GameObject tc = GameObject.Find("terrain");

            if (tc != null)
            {
                GameObject.Destroy(tc);
            }
            yield return(null);

            // Center position of terrain.
            var position = this.transform.position;

            position -= new Vector3(SIZE / 2, 0, SIZE / 2);

            // Create terrain game object.
            GameObject terrainObject = new GameObject("terrain");

            terrainObject.transform.position = position;
            terrainObject.transform.parent   = this.transform;
            yield return(null);

            // Create terrain data.
            TerrainData terrainData = new TerrainData();

            terrainData.heightmapResolution = 33;
            terrainData.size = new Vector3(SIZE, HEIGHT, SIZE);
            terrainData.alphamapResolution = 32;
            terrainData.baseMapResolution  = 1024;
            terrainData.SetDetailResolution(1024, 8);
            yield return(null);

            // Tiles per side.
            var dimension = (int)Math.Sqrt(textures.Length);

            // Splat maps.
            var splats = new List <SplatPrototype>();

            foreach (var texture in textures)
            {
                splats.Add(new SplatPrototype()
                {
                    tileOffset = new Vector2(0, 0),
                    tileSize   = new Vector2(
                        SIZE / dimension,
                        SIZE / dimension
                        ),
                    texture = texture
                });
                yield return(null);
            }
            terrainData.splatPrototypes = splats.ToArray();
            terrainData.RefreshPrototypes();
            yield return(null);

            // Get tile
            var tile = this._place.Location.ToTile(this._place.Level);

            // Construct height map.
            float[,] data = new float[
                terrainData.heightmapWidth,
                terrainData.heightmapHeight
                            ];
            for (int x = 0; x < terrainData.heightmapWidth; x++)
            {
                for (int y = 0; y < terrainData.heightmapHeight; y++)
                {
                    // Scale elevation from 257x257 to 33x33
                    var x2 = Convert.ToInt32((double)x * 256 / (terrainData.heightmapWidth - 1));
                    var y2 = Convert.ToInt32((double)y * 256 / (terrainData.heightmapHeight - 1));

                    // Find index in Esri elevation array
                    var id = y2 * 257 + x2;

                    // Absolute height in map units.
                    var h1 = elevation.Heights[id];

                    // Height in model units.
                    var h2 = SIZE * (h1 - elevation.Min) / tile.Size;

                    // Apply exaggeration.
                    var h3 = h2 * VERTICAL_EXAGGERATION;

                    // Apply base offset.
                    var h4 = h3 + TERRAIN_BASE_HEIGHT;

                    // Final height.
                    data[terrainData.heightmapHeight - 1 - y, x] = h4;
                }
            }
            terrainData.SetHeights(0, 0, data);
            yield return(null);

            // Add alpha mapping
            //float[,,] maps = terrainData.GetAlphamaps(0, 0, terrainData.alphamapWidth, terrainData.alphamapHeight);
            var maps = new float[
                terrainData.alphamapWidth,
                terrainData.alphamapHeight,
                textures.Length
                       ];

            for (int y = 0; y < terrainData.alphamapHeight; y++)
            {
                for (int x = 0; x < terrainData.alphamapWidth; x++)
                {
                    // Convert alpha coordinates into tile index. Left to right, bottom to top.
                    var tilex = x / (terrainData.alphamapWidth / dimension);
                    var tiley = y / (terrainData.alphamapHeight / dimension);
                    var index = (dimension - tiley - 1) * dimension + tilex;
                    for (int t = 0; t < textures.Length; t++)
                    {
                        maps[y, x, t] = index == t ? 1f : 0f;
                    }
                }
            }
            terrainData.SetAlphamaps(0, 0, maps);
            yield return(null);

            // Create terrain collider.
            TerrainCollider terrainCollider = terrainObject.AddComponent <TerrainCollider>();

            terrainCollider.terrainData = terrainData;
            yield return(null);

            // Add terrain component.
            Terrain terrain = terrainObject.AddComponent <Terrain>();

            terrain.terrainData = terrainData;
            yield return(null);

            // Calculate mesh vertices and triangles.
            List <Vector3> vertices  = new List <Vector3>();
            List <int>     triangles = new List <int>();

            // Distance between vertices
            var step = SIZE / 32f;

            // Front
            for (int x = 0; x < terrainData.heightmapWidth; x++)
            {
                vertices.Add(new Vector3(x * step, 0f, 0f));
                vertices.Add(new Vector3(x * step, data[0, x], 0f));
            }
            yield return(null);

            // Right
            for (int z = 0; z < terrainData.heightmapHeight; z++)
            {
                vertices.Add(new Vector3(SIZE, 0f, z * step));
                vertices.Add(new Vector3(SIZE, data[z, terrainData.heightmapWidth - 1], z * step));
            }
            yield return(null);

            // Back
            for (int x = 0; x < terrainData.heightmapWidth; x++)
            {
                var xr = terrainData.heightmapWidth - 1 - x;
                vertices.Add(new Vector3(xr * step, 0f, SIZE));
                vertices.Add(new Vector3(xr * step, data[terrainData.heightmapHeight - 1, xr], SIZE));
            }
            yield return(null);

            // Left
            for (int z = 0; z < terrainData.heightmapHeight; z++)
            {
                var zr = terrainData.heightmapHeight - 1 - z;
                vertices.Add(new Vector3(0f, 0f, zr * step));
                vertices.Add(new Vector3(0f, data[zr, 0], zr * step));
            }
            yield return(null);

            // Quads
            for (int i = 0; i < vertices.Count / 2 - 1; i++)
            {
                triangles.AddRange(new int[] {
                    2 * i + 0,
                    2 * i + 1,
                    2 * i + 2,
                    2 * i + 2,
                    2 * i + 1,
                    2 * i + 3
                });
            }

            // Create single mesh for all four sides
            GameObject side = new GameObject("side");

            side.transform.position = position;
            side.transform.parent   = terrainObject.transform;
            yield return(null);

            // Create mesh
            Mesh mesh = new Mesh()
            {
                vertices  = vertices.ToArray(),
                triangles = triangles.ToArray()
            };

            mesh.RecalculateNormals();
            mesh.RecalculateBounds();
            yield return(null);

            MeshFilter meshFilter = side.AddComponent <MeshFilter>();

            meshFilter.mesh = mesh;
            yield return(null);

            MeshRenderer meshRenderer = side.AddComponent <MeshRenderer>();

            meshRenderer.material = new Material(Shader.Find("Standard"))
            {
                color = new Color32(0, 128, 128, 100)
            };
            yield return(null);

            MeshCollider meshCollider = side.AddComponent <MeshCollider>();

            yield return(null);

            buttonObject = Instantiate(buttonZoomPrefab, terrainObject.transform.position + new Vector3(0, 0.2f, 0), Quaternion.Euler(0, -90, 0)) as StableMenu;
            buttonObject.transform.parent = terrain.transform;
            yield return(null);
        }