예제 #1
0
        private void TaskLoad(QuadTreeNode node)
        {
            try
            {
                var featureData = new GSFeatureDataNode();
                DataByNode[node]     = featureData;
                featureData.Features = ReadFeatures(node);

                foreach (var feature in featureData.Features)
                {
                    var     geographicCoordinates = new GeographicCoordinates(feature.Geometry.Centroid.Y, feature.Geometry.Centroid.X);
                    var     cartesianCoordinates  = geographicCoordinates.TransformedWith(Database.Projection);
                    float   elev     = Database.TerrainElevationAtLocation(geographicCoordinates);
                    Vector3 position = new Vector3((float)cartesianCoordinates.X, elev, (float)cartesianCoordinates.Y);
                    featureData.PositionByFeature[feature] = position;
                }
            }
            catch (Exception e)
            {
                Debug.LogException(e);
            }

            node.IsLoaded  = true;
            node.IsLoading = false;
        }
예제 #2
0
    void AddFeature(NetTopologySuite.Features.Feature feature, Color color, float elev)
    {
        Vector3[] points = null;
        if (feature.Geometry is NetTopologySuite.Geometries.LineString)
        {
            var linear = (NetTopologySuite.Geometries.LineString)feature.Geometry;
            if (!linear.IsValid)
            {
                return;
            }
            points = new Vector3[linear.Count];
            for (int i = 0; i < points.Length; ++i)
            {
                var geographicCoordinates = new GeographicCoordinates(linear[i].Y, linear[i].X);
                var cartesianCoordinates  = geographicCoordinates.TransformedWith(Database.Projection);
                points[i] = new Vector3((float)cartesianCoordinates.X, elev, (float)cartesianCoordinates.Y);
            }
        }
        if (points == null)
        {
            return;
        }
        var featureGameObject = new GameObject();

        featureGameObject.transform.SetParent(Database.gameObject.transform);
        LineRenderer lineRenderer = featureGameObject.AddComponent <LineRenderer>();

        lineRenderer.positionCount = points.Length;
        lineRenderer.SetPositions(points);
        lineRenderer.startWidth     = 0.1f;
        lineRenderer.endWidth       = 0.1f;
        lineRenderer.startColor     = color;
        lineRenderer.endColor       = color;
        lineRenderer.sharedMaterial = LineMaterial;
    }
예제 #3
0
    public void HandleGlobeClick(GameObject sender, double lat, double lon)
    {
        if (cdbDatabase == null)
        {
            return;
        }
        if (lat < cdbDatabase.GeographicBounds.MinimumCoordinates.Latitude)
        {
            return;
        }
        if (lat > cdbDatabase.GeographicBounds.MaximumCoordinates.Latitude)
        {
            return;
        }
        if (lon < cdbDatabase.GeographicBounds.MinimumCoordinates.Longitude)
        {
            return;
        }
        if (lon > cdbDatabase.GeographicBounds.MaximumCoordinates.Longitude)
        {
            return;
        }

        ModeButton.UpdateState(2);
        OnFileSelect2(path);
        var geographicCoordinates = new GeographicCoordinates(lat, lon);
        var cartesianCoordinates  = geographicCoordinates.TransformedWith(cdbDatabase.Projection);

        UserObject.transform.position = new Vector3((float)cartesianCoordinates.X, 20f, (float)cartesianCoordinates.Y);
        cdbDatabase.SetLODBracketsForDetail();
        SetDetailMode.Invoke(true);
        OptionsCanvas.GetComponent <Options>().uiControlsCanvas.SetActive(OptionsCanvas.GetComponent <Options>().uiControlsCheckmark.activeSelf);

        sender.SetActive(false);
    }
예제 #4
0
        public float TerrainElevationAtLocation(GeographicCoordinates location)
        {
            foreach (var elem in ActiveTiles)
            {
                Tile tile = elem.Value;
                if (location.Latitude < tile.GeographicBounds.MinimumCoordinates.Latitude)
                {
                    continue;
                }
                if (location.Longitude < tile.GeographicBounds.MinimumCoordinates.Longitude)
                {
                    continue;
                }
                if (location.Latitude > tile.GeographicBounds.MaximumCoordinates.Latitude)
                {
                    continue;
                }
                if (location.Longitude > tile.GeographicBounds.MaximumCoordinates.Longitude)
                {
                    continue;
                }

                var point           = location.TransformedWith(Projection);
                var cartesianBounds = tile.GeographicBounds.TransformedWith(Projection);

                double spcX = (cartesianBounds.MaximumCoordinates.X - cartesianBounds.MinimumCoordinates.X) / tile.MeshDimension;
                double spcZ = (cartesianBounds.MaximumCoordinates.Y - cartesianBounds.MinimumCoordinates.Y) / tile.MeshDimension;
                double orgX = cartesianBounds.MinimumCoordinates.X;
                double orgZ = cartesianBounds.MinimumCoordinates.Y;

                float xComponent = (float)point.X - (float)orgX;
                float zComponent = (float)point.Y - (float)orgZ;

                int xIndex = Math.Min(tile.MeshDimension - 2, (int)Math.Floor(xComponent / spcX));
                int zIndex = Math.Min(tile.MeshDimension - 2, (int)Math.Floor(zComponent / spcZ));

                int[]     indices  = new int[4];
                Vector3[] vertices = new Vector3[4];
                indices[0] = zIndex * tile.MeshDimension + xIndex;
                indices[1] = indices[0] + 1;
                indices[2] = indices[0] + tile.MeshDimension;
                indices[3] = indices[0] + tile.MeshDimension + 1;
                for (int i = 0; i < indices.Length; ++i)
                {
                    vertices[i] = tile.vertices[indices[i]];
                }
                ref Vector3 a = ref vertices[0];
                ref Vector3 b = ref vertices[1];
예제 #5
0
        // This is the old, faster version that gets elevation at SW corner of a triangle pair.
        // TODO: if we want to keep this around for quick but inaccurate lookups, we could rename it appropriately
        public float TerrainElevationAtLocation(GeographicCoordinates location)
        {
            var tiles = ActiveTiles();

            foreach (var tile in tiles)
            {
                if (location.Latitude < tile.GeographicBounds.MinimumCoordinates.Latitude)
                {
                    continue;
                }
                if (location.Longitude < tile.GeographicBounds.MinimumCoordinates.Longitude)
                {
                    continue;
                }
                if (location.Latitude > tile.GeographicBounds.MaximumCoordinates.Latitude)
                {
                    continue;
                }
                if (location.Longitude > tile.GeographicBounds.MaximumCoordinates.Longitude)
                {
                    continue;
                }

                var point    = location.TransformedWith(Projection);
                var bounds   = tile.GeographicBounds.TransformedWith(Projection);
                var spacingX = (bounds.MaximumCoordinates.X - bounds.MinimumCoordinates.X) / tile.MeshDimension;
                var spacingY = (bounds.MaximumCoordinates.Y - bounds.MinimumCoordinates.Y) / tile.MeshDimension;
                int indexX   = (int)((point.X - bounds.MinimumCoordinates.X) / spacingX);
                int indexY   = (int)((point.Y - bounds.MinimumCoordinates.Y) / spacingY);
                int index    = (indexY * tile.MeshDimension) + indexX;
                if (index >= tile.vertices.Length)
                {
                    index = tile.vertices.Length - 1;
                }
                var vertex = tile.vertices[index];
                return(vertex.y);
            }
            return(float.MaxValue);
        }
예제 #6
0
        ////////////////////////////////////////////////////////////////////////////////

        public void QuadTreeDataUpdate(QuadTreeNode node)       // QuadTreeDelegate
        {
#if UNITY_EDITOR
            if (node.IsActive)
            {
                var sw   = node.GeographicBounds.MinimumCoordinates;
                var ne   = node.GeographicBounds.MaximumCoordinates;
                var se   = new GeographicCoordinates(sw.Latitude, ne.Longitude);
                var nw   = new GeographicCoordinates(ne.Latitude, sw.Longitude);
                var swc  = sw.TransformedWith(Database.Projection);
                var sec  = se.TransformedWith(Database.Projection);
                var nwc  = nw.TransformedWith(Database.Projection);
                var nec  = ne.TransformedWith(Database.Projection);
                var elev = 100.0f;
                var swv  = new Vector3((float)swc.X, elev, (float)swc.Y);
                var sev  = new Vector3((float)sec.X, elev, (float)sec.Y);
                var nwv  = new Vector3((float)nwc.X, elev, (float)nwc.Y);
                var nev  = new Vector3((float)nec.X, elev, (float)nec.Y);
                Debug.DrawLine(swv, sev);
                Debug.DrawLine(swv, nwv);
                Debug.DrawLine(nwv, nev);
                Debug.DrawLine(sev, nev);
            }
#endif

            if (!node.IsActive)
            {
                return;
            }

            if (!node.IsLoaded)
            {
                return;
            }

            if (Database.SystemMemoryLimitExceeded)
            {
                return;
            }

            //if (HasLoadedDecendents(node))
            //    return;

            var maxdist = Database.LODSwitchByObject[this].MaxDistance * Database.Projection.Scale;

            GSFeatureDataNode featureData = null;
            if (!DataByNode.TryGetValue(node, out featureData))
            {
                return;
            }
            for (int i = 0; i < 1; ++i)
            {
                if (featureData.Features.Count < 1)
                {
                    return;
                }

                if (Time.frameCount % 10 != 0)
                {
                    var tempList = new List <GameObject>();
                    foreach (var go in featureData.LoadingGameObjects)
                    {
                        if (!go.GetComponent <Model>().Loaded)
                        {
                            tempList.Add(go);
                        }
                    }
                    featureData.LoadingGameObjects = tempList;
                }
                if (featureData.LoadingGameObjects.Count > 4)
                {
                    return;
                }

                int index   = featureData.Features.Count - 1;
                var feature = featureData.Features[index];
                var dist2   = (featureData.PositionByFeature[feature] - featureData.CameraPosition).sqrMagnitude;
                if (dist2 > maxdist * maxdist)
                {
                    return;
                }

                lock (featureData.Features)
                {
                    featureData.Features.RemoveAt(index);
                }

                try
                {
                    var modelGameObject = GenerateModel(node, feature);
                    if (modelGameObject != null)
                    {
                        featureData.GameObjects.Add(modelGameObject);
                        featureData.LoadingGameObjects.Add(modelGameObject);
                    }
                }
                catch (Exception e)
                {
                    Debug.LogException(e);
                }
            }
        }
예제 #7
0
        protected void Start()
        {
            if (Feature.Geometry == null)
            {
                Debug.LogErrorFormat("feature {0} has no geometry!!!", name);
                gameObject.SetActive(false);
                return;
            }
            if (!Feature.Geometry.IsSimple)
            {
                Debug.LogWarningFormat("feature {0} geometry is not simple!!!", name);
            }

            transform.SetPositionAndRotation(Vector3.zero, Quaternion.identity);

            var attributeNames  = new List <string>(Feature.Attributes.GetNames());
            var attributeValues = new List <object>(Feature.Attributes.GetValues());

            for (int i = 0; i < attributeNames.Count; i++)
            {
                Attributes[attributeNames[i]] = attributeValues[i];
            }

            // Copy the attributes into a field viewable from the inspector (for easy copy/paste debugging)
            string str = "";

            for (int i = 0; i < attributeNames.Count; i++)
            {
                str += string.Format("{0}: {1}\n", attributeNames[i], attributeValues[i].ToString());
            }
            //var multiPolygon = Feature.Geometry as NetTopologySuite.Geometries.MultiPolygon;
            //if (multiPolygon != null)
            //    str += "MP\n";
            textAttributes = str;

            name = GetName();

            int id = -1;

            GetId(out id);
            if (id == contiguousUSA_Id) // skip contiguous US airspace that seems to be in every airspace shapefile
            {
                gameObject.SetActive(false);
                return;
            }

            Rebuild();

            if (textInfo != null)
            {
                textInfo.text  = name;
                textInfo.color = new Color(0.5f, 0.5f, 0.5f, 1f);

                if (vertices != null && vertices.Length > 0)
                {
                    var     geographicCoordinates = new GeographicCoordinates(Feature.Geometry.Centroid.Y, Feature.Geometry.Centroid.X);
                    var     cartesianCoordinates  = geographicCoordinates.TransformedWith(Database.Projection);
                    Vector3 vec = new Vector3((float)cartesianCoordinates.X, vertices[0].y, (float)cartesianCoordinates.Y);
                    textInfo.transform.position   = vec;
                    textInfo.transform.localScale = Vector3.one;
                }
            }
        }
예제 #8
0
        private bool ProcessGeometry(GeoAPI.Geometries.IGeometry geometry, float top, float bottom, GameObject node)
        {
            int index = 0;

            vertices = new Vector3[geometry.Coordinates.Length];
            if (vertices.Length < 3)
            {
                return(false);
            }

            Vector3 referenceVec = Vector3.zero;

            foreach (var coordinate in geometry.Coordinates)
            {
                var     geographicCoordinates = new GeographicCoordinates(coordinate.Y, coordinate.X);
                var     cartesianCoordinates  = geographicCoordinates.TransformedWith(Database.Projection);
                Vector3 vec = new Vector3((float)cartesianCoordinates.X, top, (float)cartesianCoordinates.Y);

                if (index == 0)
                {
                    referenceVec = vec;
                }
                else
                {
                    float distSq = Vector3.SqrMagnitude(vec - referenceVec);
                    if (distSq > 250f * LOD * LOD)
                    {
                        referenceVec = vec;
                    }
                    else
                    {
                        continue;
                    }
                }

                vertices[index] = vec;

                index++;
            }

            Array.Resize(ref vertices, index);

            // We have a poly which needs triangulation
            var triangulatorInput = new List <Vector2>();
            var scratch           = new List <Vector3>();

            for (int i = 0; i < vertices.Length; i++)
            {
                if (i != vertices.Length - 1) // skip the last vertex so that triangulator plays nicely
                {
                    triangulatorInput.Add(new Vector2(vertices[i].x, vertices[i].z));
                }
            }
            for (int i = 0; i < vertices.Length - 1; i++)
            {
                scratch.Add(new Vector3(vertices[i].x, top, vertices[i].z));
            }
            for (int i = 0; i < vertices.Length - 1; i++)
            {
                scratch.Add(new Vector3(vertices[i].x, bottom, vertices[i].z));
            }

            // Store off the side vertices
            sideTriangles = new int[3 * scratch.Count];
            int j = 0;

            for (int i = 0; i < sideTriangles.Length; i += 6, j++)
            {
                sideTriangles[i + 0] = j;
                sideTriangles[i + 1] = j + scratch.Count / 2;
                if (j + 1 == scratch.Count / 2)
                {
                    j = -1;
                }
                sideTriangles[i + 2] = j + 1;

                sideTriangles[i + 3] = sideTriangles[i + 2];
                sideTriangles[i + 4] = sideTriangles[i + 1];
                sideTriangles[i + 5] = j + scratch.Count / 2 + 1;
            }

            var triangulator = new Triangulator();
            var result       = new List <Vector2>();

            triangulator.Process(triangulatorInput, ref result);
            if (result.Count == 0 || result.Count % 3 != 0)
            {
                Debug.LogError(string.Format("{0}: triangulation failed!", name));
                return(false);
            }

            // Add vertices for top and bottom caps
            vertices = new Vector3[2 * result.Count];

            int v = 0;

            for (int i = 0; i < result.Count; i++, v++)
            {
                vertices[v].Set(result[i].x, top, result[i].y);
            }
            for (int i = 0; i < result.Count; i++, v++)
            {
                vertices[v].Set(result[i].x, bottom, result[i].y);
            }

            // Correct the side triangles list to match the new array
            for (int i = 0; i < sideTriangles.Length; i++)
            {
                int sideTriIndex = sideTriangles[i];
                if (sideTriIndex > scratch.Count)
                {
                    sideTriIndex = sideTriIndex - scratch.Count;
                }
                Vector3 sideVec = scratch[sideTriIndex];
                for (int verticesIndex = 0; verticesIndex < vertices.Length; verticesIndex++)
                {
                    Vector3 verticesVec = vertices[verticesIndex];
                    if (Mathf.Approximately(sideVec.x, verticesVec.x) && Mathf.Approximately(sideVec.y, verticesVec.y) && Mathf.Approximately(sideVec.z, verticesVec.z))
                    {
                        sideTriangles[i] = verticesIndex;
                        break;
                    }
                }
            }

            var mesh = node.GetComponent <MeshFilter>().mesh;

            mesh.vertices = vertices;

            int topCapTriangleCount    = mesh.vertices.Length / 2 / 3;
            int bottomCapTriangleCount = topCapTriangleCount;
            int sideTriangleCount      = sideTriangles.Length / 3;
            int totalTriangleCount     = topCapTriangleCount + bottomCapTriangleCount + sideTriangleCount;

            triangles = new int[3 * totalTriangleCount];

            // Top cap
            int start = 0;
            int end   = 3 * topCapTriangleCount;

            for (int i = start; i < end; i++)
            {
                triangles[i] = end - 1 - i; // start at the back, for winding purposes
            }
            // Bottom cap
            start = end;
            end   = start + 3 * bottomCapTriangleCount;
            for (int i = start; i < end; i++)
            {
                triangles[i] = i;
            }

            // Sides
            start = end;
            end   = start + 3 * sideTriangleCount;
            j     = 0;
            for (int i = start; i < end; i++, j++)
            {
                triangles[i] = sideTriangles[j];
            }

            mesh.triangles = triangles;

            normals = new Vector3[vertices.Length];
            for (int i = 0; i < normals.Length; ++i)
            {
                normals[i] = Vector3.up;
            }

            mesh.normals = normals;

            return(true);
        }