예제 #1
0
        void addNewSub(int idxx, int idxy)
        {
            if (subCurve.Find(p => p.idxx == idxx && p.idxy == idxy) == null)
            {
                EarthData newearthdata;

                string modelkey = string.Format("{0}.{1}.{2}", layer + 1, idxx, idxy);
                if (!MapHelper.models.TryGetValue(modelkey, out newearthdata))
                {
                    newearthdata = new EarthData(earthmanager, this, idxx, idxy);

                    if (MapHelper.models.Count > 500)
                    {
                        MapHelper.models.Remove(MapHelper.models.Keys.ElementAt(0));
                    }
                    MapHelper.models.Add(modelkey, newearthdata);
                }
                else
                {
                    newearthdata.parent     = this;
                    newearthdata.handled    = false;
                    newearthdata.prehandled = false;
                    newearthdata.curStatus  = EStatus.none;
                    newearthdata.oprStatus  = EStatus.none;
                    newearthdata.operate    = EOperate.none;
                }



                subCurve.Add(newearthdata);
            }
        }
예제 #2
0
        /// <summary>判断弧面的四角点是否有面向相机,并且与视锥体相交</summary>
        private bool isFaceAndIntersect(EarthData node)
        {
            Vector3 vecDir = earth.camera.cameraDirection - earth.camera.cameraPosition;

            Vector3[] normals = node.normals;
            bool      isface  = false;

            for (int i = 0; i < normals.Length; i++)
            {
                if (Vector3.Dot(normals[i], vecDir) < 0)
                {
                    isface = true;
                    break;
                }
            }

            if (isface)
            {
                //BoundingFrustum cameraFrustum = new BoundingFrustum(global.camera.view * global.camera.projection);
                //BoundingFrustum cameraFrustum = new BoundingFrustum(global.camera.view * Matrix.CreatePerspectiveFieldOfView(MathHelper.PiOver4*1.2f, (float)global.ScreenWidth / global.ScreenHeight, 0.1f, 100f));
                //if (cameraFrustum.Intersects(node.boundingBox))
                if (earth.camera.cameraFrustum.Intersects(node.boundingBox))
                {
                    return(true);
                }
            }



            return(false);
        }
예제 #3
0
        ///<summary>获得tile的屏幕2D点</summary>
        public static Vector2[] GetTileCorner(EarthData node, Earth earth)
        {
            Vector2[] v2s = new Vector2[node.normals.Length];
            for (int i = 0; i < node.normals.Length; i++)
            {
                v2s[i] = Helpler.GetProjectPoint2D(node.normals[i], earth.camera.view, earth.camera.projection, earth.global.ScreenWidth, earth.global.ScreenHeight);
            }

            return(v2s);
        }
예제 #4
0
        ///<summary>获得tile的屏幕rect</summary>
        public static Rect GetTileRect(EarthData node, Earth earth)
        {
            Vector2[] v2s = new Vector2[node.normals.Length];
            for (int i = 0; i < node.normals.Length; i++)
            {
                v2s[i] = Helpler.GetProjectPoint2D(node.normals[i], earth.camera.view, earth.camera.projection, earth.global.ScreenWidth, earth.global.ScreenHeight);
            }

            double minx = v2s.Min(p => p.X); double miny = v2s.Min(p => p.Y);
            double maxx = v2s.Max(p => p.X); double maxy = v2s.Max(p => p.Y);

            return(new Rect(minx, miny, maxx - minx, maxy - miny));
        }
예제 #5
0
        public EarthManager(Earth pearth)
        {
            datas                       = new EarthData(this, null, 0, 0);
            earth                       = pearth;
            bworker.DoWork             += new DoWorkEventHandler(bworker_DoWork);
            bworker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bworker_RunWorkerCompleted);


            //==== 初始化c#相机
            float tmp = 1.001f * Para.scalepara;

            earth.camera = new Camera(new Vector3(2175.563f, 4090f, 4384f) * tmp, new Vector3(0, 0, 0), Vector3.Up, earth);

            //==== 初始化d3d相机

            initEarth();
        }
예제 #6
0
        internal EarthData(EarthManager Earthmanager, EarthData Parent, int idxX, int idxY)
        {
            earthmanager = Earthmanager;
            parent       = Parent;
            if (Parent == null)
            {
                layer = 0;
            }
            else
            {
                layer = parent.layer + 1;
            }
            idxx    = idxX;
            idxy    = idxY;
            quadkey = MapHelper.TileXYToQuadKey(layer, idxx, idxy);

            id       = string.Format("{0}_{1}_{2}", layer, idxx, idxy);
            hashcode = id.GetHashCode();
        }
예제 #7
0
        ///<summary>获取瓦片节点的高度列表</summary>
        internal static List <float> getHeigList(EarthData node)
        {
            List <float> result = new List <float>();

            float  jd, wd;
            double spanjd = node.range.Width / node.terrainSliceCount;

            for (int j = 0; j < node.terrainSliceCount + 1; j++)
            {
                for (int i = 0; i < node.terrainSliceCount + 1; i++)
                {
                    jd = (float)(node.range.X + spanjd * i);
                    double tileLength = 2.0 * Math.PI / Math.Pow(2, node.layer); //2*pi/power(2,layer)  假定半径为1, 平面地图坐标系下该层划分块的长和宽度
                    wd = (float)((Math.Atan(Math.Exp(Math.PI - (node.idxy + (float)j / node.terrainSliceCount) * tileLength)) * 2 - Math.PI / 2) / Math.PI * 180);
                    result.Add(getHigh(jd, wd, node.earthmanager.TerrainMinHeight, node.earthmanager.TerrainDropHeight));
                }
            }
            return(result);
        }
예제 #8
0
 public EarthData searchNode(int zlayer, int zidxx, int zidxy)
 {
     if (layer == zlayer && idxx == zidxx && idxy == zidxy)
     {
         return(this);
     }
     else
     {
         EarthData result = null;
         foreach (EarthData item in subCurve)
         {
             result = item.searchNode(zlayer, zidxx, zidxy);
             if (result != null)
             {
                 return(result);
             }
         }
         return(result);
     }
 }
예제 #9
0
        /// <summary>
        /// 遍历进行操作
        /// </summary>
        /// <param name="node"></param>
        private void update(EarthData node)  //遍历进行更新操作
        {
            while (node.subCurve.Count(p => !p.handled) > 0)
            {
                update(node.subCurve.First(p => !p.handled));
            }


            switch (node.operate)
            {
            case EOperate.节点模型删除:
                //mapTiles.Remove(node.id);
                //Earth.DelMapTile(node.layer,node.idxx,node.idxy);
                node.parent.subCurve.Remove(node);
                node.parent = null;
                break;

            case EOperate.节点删除:
                node.parent.subCurve.Remove(node);
                node.parent = null;
                break;

            case EOperate.模型删除:
                //mapTiles.Remove(node.id);
                //Earth.DelMapTile(node.layer,node.idxx,node.idxy);
                node.curStatus = node.oprStatus;
                break;

            case EOperate.模型加入:
                //mapTiles.Add(node.id, updateTiles[node.id]);
            {
                if (node.mustModelStatus == EMeshStatus.维)
                {
                    int    count  = node.terrainHeigList.Count;
                    IntPtr ipHigh = Marshal.AllocCoTaskMem(Marshal.SizeOf(node.terrainHeigList[0]) * count);          //传递点序列结构数组指针
                    for (int i = 0; i < count; i++)
                    {
                        Marshal.StructureToPtr(node.terrainHeigList[i], (IntPtr)(ipHigh.ToInt32() + i * Marshal.SizeOf(node.terrainHeigList[i])), false);
                    }
                    D3DManager.AddMapTile(earth.earthkey, node.hashcode, node.layer, node.idxx, node.idxy, node.mustModelStatus == EMeshStatus.维, node.terrainSliceCount, ipHigh);          // 当isshowterrain为true且terrainspan与原值不同,将会重建地形mesh
                    Marshal.FreeCoTaskMem(ipHigh);
                }
                else
                {
                    D3DManager.AddMapTile(earth.earthkey, node.hashcode, node.layer, node.idxx, node.idxy, false, 0, IntPtr.Zero);          //isShowTerrain为false时,不会更改地形相关数据,仅为开关控制
                }
            }
                node.curStatus = node.oprStatus;
                break;

            case EOperate.模型更新:
            {
                if (node.mustModelStatus == EMeshStatus.维)
                {
                    int    count  = node.terrainHeigList.Count;
                    IntPtr ipHigh = Marshal.AllocCoTaskMem(Marshal.SizeOf(node.terrainHeigList[0]) * count);          //传递点序列结构数组指针
                    for (int i = 0; i < count; i++)
                    {
                        Marshal.StructureToPtr(node.terrainHeigList[i], (IntPtr)(ipHigh.ToInt32() + i * Marshal.SizeOf(node.terrainHeigList[i])), false);
                    }
                    D3DManager.AddMapTile(earth.earthkey, node.hashcode, node.layer, node.idxx, node.idxy, node.mustModelStatus == EMeshStatus.维, node.terrainSliceCount, ipHigh);          // 当isshowterrain为true且terrainspan与原值不同,将会重建地形mesh
                    Marshal.FreeCoTaskMem(ipHigh);
                }
                else
                {
                    D3DManager.AddMapTile(earth.earthkey, node.hashcode, node.layer, node.idxx, node.idxy, false, 0, IntPtr.Zero);          //isShowTerrain为false时,不会更改地形相关数据,仅为开关控制
                }
            }

                //D3DManager.AddMapTile(earth.earthkey, node.hashcode, node.layer, node.idxx, node.idxy);


                //models.Remove(node.model);
                //node.updateModel();
                //models.Add(node.model);
                //node.curStatus = node.oprStatus;
                break;

            case EOperate.none:
                node.curStatus = node.oprStatus;
                break;
            }
            node.operate = EOperate.none;
            node.handled = true;
        }
예제 #10
0
        ///<summary>迭代遍历刷新,设置操作指令和状态</summary>
        private void scan(EarthData node)
        {
            if (earth.global.maxlayer < node.layer)
            {
                earth.global.maxlayer = node.layer; earth.global.maxlayertileinfo = string.Format("{0}-{1}-{2}", node.layer, node.idxx, node.idxy);
            }

            node.handled       = false;
            node.prehandled    = false;
            node.tileStatus    = ETileStatus.可见;
            node.isShowTerrain = false;
            node.info          = "0";
            //Rect rectViewport = new Rect(-1000, -1000, earth.global.ScreenWidth + 2000, earth.global.ScreenHeight + 2000);
            Rect   rectViewport = new Rect(0, 0, earth.global.ScreenWidth, earth.global.ScreenHeight);
            double LimitWH      = 400;

            if ((earth.earthManager.mapType == EMapType.卫星 && node.layer + 1 <= Config.satmaxLayer) || (earth.earthManager.mapType != EMapType.卫星 && node.layer + 1 <= Config.roadmaxLayer))//下一级不大于允许最大级
            {
                node.info = "1";
                //===判断可见性
                //int ycount = (int)Math.Pow(2, node.layer);
                //double angle = 360.0 / ycount;



                if ((node.layer < (earthpara.SceneMode == ESceneMode.地球? 3:earthpara.StartLayer) || isFaceAndIntersect(node)))   //检测是否面向相机或层级小于2且与视锥体相交
                {
                    //首先考虑换一种验证大小面积的方法,用屏幕转换为地面,与块对比,这种方法与现用的块转换屏幕相反,(块转换屏幕在斜视下不可得,因为块平面与相机近平面相交了)

                    //新判断方式,以瓦片的实际经纬与屏幕映射相比较来判定
                    if (node.range.Contains(earth.camera.curCamearaViewRange.rect))   //块包括屏幕
                    {
                        node.setExpand();
                        foreach (EarthData item in node.subCurve)
                        {
                            scan(item);
                        }
                    }
                    else if (node.range.IntersectsWith(earth.camera.curCamearaViewRange.rect)) //块与屏幕相交
                    {
                        bool handle = false;
                        foreach (var rec in earth.camera.curCamearaViewRange.rects)
                        {
                            if (node.range.IntersectsWith(rec))
                            {
                                if (node.range.Width > 0.3 * rec.Width)  //zh注:以后可以优化,通过预先计算纬度带的屏高,以计算面积来判定是否分拆
                                {
                                    node.setExpand();
                                    foreach (EarthData item in node.subCurve)
                                    {
                                        scan(item);
                                    }
                                }
                                else
                                {
                                    node.setFold();
                                    node.isShowTerrain = true;  //地形注:只有可见才可以显示地形
                                }
                                handle = true;
                                break;
                            }
                        }
                        if (!handle) //指在矩形中的梯形的其余部分,未真正与屏幕相交
                        {
                            node.setFold();
                        }
                    }
                    else //不相交, 应不出现
                    {
                        node.setFold();
                    }

                    #region ===== 旧的判断方式 =====
                    //node.info = "2";
                    //Rect rectsub = MapHelper.GetTileRect(node,earth.global);
                    //node.rect = rectsub;
                    //if (rectsub.Contains(rectViewport) || node.layer < (earthpara.SceneMode == ESceneMode.地球 ? 3 : earthpara.StartLayer)) //弧面包含屏幕, 转下一层级
                    //{
                    //    node.info = "3";
                    //    node.setExpand();
                    //    foreach (EarthData item in node.subCurve)
                    //        scan(item);
                    //}
                    //else
                    //{
                    //    node.info = "4";
                    //    if (rectViewport.IntersectsWith(rectsub)) //相交
                    //    {
                    //        node.info = "5";

                    //        if (rectsub.Width * rectsub.Height > LimitWH * LimitWH || rectsub.Width>1000 )//用面积判断是否切分
                    //        {
                    //            node.info = "6";
                    //            node.setExpand();
                    //            foreach (EarthData item in node.subCurve)
                    //                scan(item);
                    //        }
                    //        else
                    //        {
                    //            node.info = "7";
                    //            node.tileStatus = ETileStatus.部分可见;
                    //            node.isShowTerrain = true;
                    //            node.setFold();
                    //            node.texture = "box3";
                    //        }
                    //    }
                    //    else //不相交, 此,原本不应出现,三3D相交,2D不相交,计算上有问题,由于3D包围盒
                    //    {
                    //        if (rectsub.Width > 5000)
                    //        {
                    //            node.setExpand();
                    //            foreach (EarthData item in node.subCurve)
                    //                scan(item);
                    //        }
                    //        else
                    //        {
                    //            node.info = "8";
                    //            node.tileStatus = ETileStatus.部分可见;
                    //            node.isShowTerrain = true;
                    //            //node.setDelete();
                    //            node.setFold();
                    //            node.texture = "box2";
                    //        }
                    //    }
                    //}

                    #endregion
                }
                else //不可见
                {
                    //node.setDelete();
                    node.setFold();


                    node.texture = "box";
                }
            }
            else //最小级
            {
                node.info = "a";
                //node.setDelete();
                node.setFold();
                node.texture = "box4";
            }
        }