示例#1
0
        /// <summary>
        /// for substitute tiles -
        /// makes a subset of features out of existing features, adds it to cache (under this tile name),
        /// so the next time this tile is called a cache-resident subset is ready for use
        /// </summary>
        public void CreateFeaturesSubset()
        {
            Features tileFeatures = TileCache.getFeatures(this, m_baseName);

            if (!m_tileFeatures.HasLoaded)
            {
#if DEBUG
                LibSys.StatusBar.Trace("IP: Tile::CreateFeaturesSubset() - " + m_baseName + " - not loaded yet " + m_tileFeatures);
#endif
                return;
            }
            if (tileFeatures.HasLoaded)
            {
#if DEBUG
                LibSys.StatusBar.Trace("IP: Tile::CreateFeaturesSubset() - " + m_baseName + " - found in cache " + tileFeatures);
#endif
            }
            else
            {
                GeoCoord bottomRight = m_bottomRight.Clone();
                bottomRight.Normalize();
                GeoCoord topLeft = m_topLeft.Clone();
                topLeft.Normalize();
                double rightLng = bottomRight.Lng;
                double leftLng  = topLeft.Lng;
                if (rightLng <= -180.0d)
                {
                    rightLng += 360.0d;
                }
                double bottomLat = bottomRight.Lat;
                double topLat    = topLeft.Lat;

                //LibSys.StatusBar.Trace("IP: Tile::CreateFeaturesSubset() - " + m_baseName + " - copying features related to lng:" + leftLng + "<" + rightLng + " lat:" + bottomLat + "<" + topLat + " from " + m_tileFeatures.BaseName);

                // we are not cloning the lo assuming that lo's belonging to a tile are not reappearing
                // in any other tile. That also means that we need to cut selection rectangles correctly.

                foreach (LiveObject lo in m_tileFeatures.List)
                {
                    if (lo.Location.Lat <= topLat && lo.Location.Lat >= bottomLat &&
                        lo.Location.Lng >= leftLng && lo.Location.Lng <= rightLng)
                    {
                        try
                        {
                            //LibSys.StatusBar.WriteLine(" --- " + lo);
                            tileFeatures.Add(lo);
                        }
                        catch (Exception e)
                        {
                        }
                    }
                }

                tileFeatures.HasLoaded = true;
                tileFeatures.IsEmpty   = false;
            }
            m_tileFeatures = tileFeatures;
            //LibSys.StatusBar.Trace("OK: Tile::CreateFeaturesSubset() - " + m_baseName + " result: " + m_tileFeatures);
            //TileCache.ListFeaturesCache();
        }
示例#2
0
        public static event DownloadProgressHandler ProgressCallback;           // needed for WebDownload, stays empty here

        public static void setMappingCacheLocation(string path)
        {
            Project.setMappingCacheLocation(path);
            m_mapsPath = Project.GetMapsTempPath();

            TileCache.Clear();                  // release all files

            TerraserverCache.setMappingCacheLocation();
        }
示例#3
0
 public void Dispose()
 {
     //LibSys.StatusBar.Trace("TileTerra:Dispose() baseName=" + m_baseName);
     if (m_tileBackdrop != null)
     {
         TileCache.BackdropMarkUnused(m_baseName);
         m_tileBackdrop = null;
     }
 }
示例#4
0
        public void backdropArrived(Backdrop backdrop)
        {
            // the backdrop may arrive when this tile has been phased out due to TileSet.ReTile()
            // this tile then hangs around as a means to pass backdrop to TileSet, which is supposed
            // to find appropriate location for the backdrop.
#if DEBUG
            LibSys.StatusBar.Trace("Tile::backdropArrived() - backdrop=" + backdrop);
#endif
            m_tileBackdrop = backdrop;
            if (m_tileBackdrop.IsEmpty)
            {
                // more likely, need to use substitute is discovered here.
                if (MayUseSubstitute && !UseSubstitute)
                {
                    // get substitute backdrop:
                    m_useSubstitute = true;
#if DEBUG
                    LibSys.StatusBar.Trace("Tile::backdropArrived() - requesting substitute " + m_substituteName);
#endif
                    m_tileBackdrop = TileCache.getBackdrop(this, m_substituteName);                     // may be Empty, never null
                    if (m_tileBackdrop.IsEmpty)
                    {
#if DEBUG
                        LibSys.StatusBar.Trace("Tile::backdropArrived() - got empty substitute " + m_substituteName);
#endif
                        m_isEmpty = true;
                    }
                    else if (m_tileBackdrop.HasImage)
                    {
#if DEBUG
                        LibSys.StatusBar.Trace("Tile::backdropArrived() - got good substitute " + m_tileBackdrop);
#endif
                        CalculateSubstituteRectangle();                          // may instead set IsEmpty
                    }
                    else
                    {
#if DEBUG
                        LibSys.StatusBar.Trace("Tile::backdropArrived() - will wait for substitute ");
#endif
                        return;                                 // waiting for substitute backdrop image to arrive
                    }
                }
                else
                {
                    m_isEmpty = true;
                }
            }
            else if (UseSubstitute && m_tileBackdrop.HasImage)
            {
                CalculateSubstituteRectangle();                  // may instead set IsEmpty
            }
            m_tileSet.tileBackdropArrived(this);
        }
示例#5
0
        public void featuresArrived(Features features)
        {
            // the Features may arrive when this tile has been phased out due to TileSet.ReTile()
            // this tile then hangs around as a means to pass Features to TileSet, which is supposed
            // to find appropriate location for the Features.
#if DEBUG
            LibSys.StatusBar.Trace("featuresArrived() - features=" + features);
#endif
            m_tileFeatures = features;
            if (m_tileFeatures.IsEmpty)
            {
                // more likely, need to use substitute is discovered here.
                if (MayUseSubstitute)
                {
                    // get substitute features:
#if DEBUG
                    LibSys.StatusBar.Trace("Tile::featuresArrived() - requesting substitute " + m_substituteName);
#endif
                    m_tileFeatures = TileCache.getFeatures(this, m_substituteName);                     // may be Empty, never null
                    if (m_tileFeatures.IsEmpty)
                    {
#if DEBUG
                        LibSys.StatusBar.Trace("Tile::featuresArrived() - got empty substitute " + m_substituteName);
#endif
                    }
                    else
                    {
#if DEBUG
                        LibSys.StatusBar.Trace("Tile::featuresArrived() - copying relevant features");
#endif
                        CreateFeaturesSubset();
                        ProvokeFeaturesPutOnMap();                                      // provoke PutOnMap on the next Tile_Paint()
                    }
                }
            }
            else
            {
                ProvokeFeaturesPutOnMap();                              // provoke PutOnMap on the next Tile_Paint()
            }
            m_tileSet.tileFeaturesArrived(this);
        }
示例#6
0
        private void ReTile()
        {
            //LibSys.StatusBar.Trace("IP: ReTile()  drawableReady=" + Project.drawableReady);

            if (!Project.drawableReady)                 // when starting, we get several resize events with different sizes, as
            // layout settles. We want to ignore these and retile after the first paint.
            {
                return;
            }

            // what is the picture area in degrees?
            // use CameraManager.m_coverageXDegrees, m_coverageYDegrees for span in degrees

            // what is appropriate tile resolution?
            double cameraHeightKm = (m_cameraManager.Location.Elev) / 1000.0d;                  // km
            string tileScale;

            // each tile scale has it's threshold, after which the next tile scale is used.
            // the idea is to use the tile while it maps closely to 1:1 in pixels, and when
            // the mapping requires magnification (i.e. x tile 1200x1200 --> 1300x1300 on the picture),
            // then use the next level
            if (cameraHeightKm > 5000.0d)
            {
                m_tileResolutionDegreesH = 360.0d;                      // degrees per tile
                m_tileResolutionDegreesV = 180.0d;                      // degrees per tile
                tileScale = "w";
            }
            else if (cameraHeightKm > 2000.0d)
            {
                m_tileResolutionDegreesH = 40.0d;                       // degrees per tile
                m_tileResolutionDegreesV = 50.0d;                       // degrees per tile
                tileScale = "y";
            }
            //else if(cameraHeightKm > 900.0d)
            else if (cameraHeightKm > 370.0d)
            {
                m_tileResolutionDegreesH = 10.0d;                       // degrees per tile
                m_tileResolutionDegreesV = 10.0d;                       // degrees per tile
                tileScale = "x";
            }

            /*
             * else if(cameraHeightKm > 370.0d)
             * {
             *      m_tileResolutionDegreesH = 4.0d;	// degrees per tile
             *      m_tileResolutionDegreesV = 4.0d;	// degrees per tile
             *      tileScale = "z";
             * }
             */
            else if (cameraHeightKm > 100.0d)
            {
                m_tileResolutionDegreesH = 1.0d;                        // degrees per tile
                m_tileResolutionDegreesV = 1.0d;                        // degrees per tile
                tileScale = "";
            }
            else
            {
                m_tileResolutionDegreesH = 0.5d;                        // degrees per tile
                m_tileResolutionDegreesV = 0.5d;                        // degrees per tile
                tileScale = "a";
            }

            // how many tiles v*h do we need to cover the picture area?
            GeoCoord topLeftTileCorner     = getTopLeftTileCorner(m_cameraManager.CoverageTopLeft, tileScale, m_tileResolutionDegreesH, m_tileResolutionDegreesV);
            GeoCoord bottomRightTileCorner = getBottomRightTileCorner(m_cameraManager.CoverageBottomRight, tileScale, m_tileResolutionDegreesH, m_tileResolutionDegreesV);

#if DEBUG
            LibSys.StatusBar.Trace("TileSet:ReTile() topLeftTileCorner=" + topLeftTileCorner + " bottomRightTileCorner=" + bottomRightTileCorner);
#endif
            m_hCount = (int)((bottomRightTileCorner.Lng - topLeftTileCorner.Lng) / m_tileResolutionDegreesH);
            m_vCount = (int)((topLeftTileCorner.Lat - bottomRightTileCorner.Lat) / m_tileResolutionDegreesV);

            // world tile is replicated, if 180 meridian is in the picture:
            bool doWorldOffset = false;
            switch (tileScale)
            {
            case "w":
                if (m_cameraManager.CoverageBottomRight.Lng > 180.0d)
                {
                    m_hCount++;
                    doWorldOffset = true;
                }
                else if (m_cameraManager.CoverageTopLeft.Lng < -180.0d)
                {
                    topLeftTileCorner.Lng -= 360.0d;                                    // left tile starts there
                    m_hCount++;
                    doWorldOffset = true;
                }
                break;
            }

#if DEBUG
            LibSys.StatusBar.Trace("TileSet:ReTile() m_vCount=" + m_vCount + " m_hCount=" + m_hCount + " doWorldOffset=" + doWorldOffset);
#endif

            // calculate meters per pixel for selected tile scale:
            m_xMetersPerPixel = m_cameraManager.MetersPerPixelX();
            m_yMetersPerPixel = m_cameraManager.MetersPerPixelY();
#if DEBUG
            LibSys.StatusBar.Trace("TileSet:ReTile() m_xMetersPerPixel=" + m_xMetersPerPixel + " m_yMetersPerPixel=" + m_yMetersPerPixel);
            LibSys.StatusBar.Trace("TileSet:ReTile() ----------------- before " + TileCache.ToString());
#endif

            double topLeftLat = topLeftTileCorner.Lat;
            cleanTiles();
            lock (tilesLock)
            {
                m_tiles = new Tile[m_vCount, m_hCount];
                for (int vv = 0; vv < m_vCount; vv++)
                {
                    double topLeftLng = topLeftTileCorner.Lng;
                    for (int hh = 0; hh < m_hCount; hh++)
                    {
                        GeoCoord topLeft     = new GeoCoord(topLeftLng, topLeftLat, 0.0d);
                        GeoCoord bottomRight = new GeoCoord(topLeftLng + m_tileResolutionDegreesH,
                                                            topLeftLat - m_tileResolutionDegreesV, 0.0d);
                        m_tiles[vv, hh] = new Tile(this, tileScale, topLeft, bottomRight);
                        m_tiles[vv, hh].init();
                        switch (tileScale)
                        {
                        case "w":
                            // world tiles use doWorldOffset around 180 meridian:
                            if (doWorldOffset && hh > 0)
                            {
                                int offsetX = m_tiles[vv, hh].getFrameRectangle().Width;
                                m_tiles[vv, hh].Offset = new Point(offsetX, 0);
                            }
                            break;

                        default:
                            m_tiles[vv, hh].Offset = new Point(0, 0);
                            break;
                        }
#if DEBUG
                        LibSys.StatusBar.Trace("    hh=" + hh + " ---- offset=" + m_tiles[vv, hh].getOffset());
#endif

                        topLeftLng += m_tileResolutionDegreesH;
                    }
                    topLeftLat -= m_tileResolutionDegreesV;
                }
            }             // lock
#if DEBUG
            LibSys.StatusBar.Trace("TileSet:ReTile() ----------------- after " + TileCache.ToString());
#endif
            TileCache.purge();
            double safeHeight = ((double)Project.CAMERA_HEIGHT_SAFE) * 1000.0d;
            if (m_cameraManager.Elev < safeHeight && (!Project.allowUnreasonableZoom && IsAllSubstitutes || IsEmpty))
            {
                // we get here if all tiles are already in cache, and all are empty.
                LibSys.StatusBar.Trace("TileSet:ReTile() - all tiles empty - repositioning");
                m_cameraManager.Elev = safeHeight;
            }
        }
示例#7
0
        private bool m_triedReload = false;                     // limits reload attempts

        public void Tile_Paint(object sender, PaintEventArgs e)
        {
            //LibSys.StatusBar.Trace("Tile_Paint(): " + m_baseName + " painting to " + e.ClipRectangle);

            try
            {
                Rectangle destRect = getFrameRectangle();
                int       www      = 0;
                int       hhh      = 0;
                //LibSys.StatusBar.Trace("Tile_Paint(): tileImage=" + m_tileBackdrop);
                if (m_tileBackdrop != null && !m_tileBackdrop.IsEmpty && m_tileBackdrop.HasImage)
                {
                    //int compensate = 2;
                    //destRect.Inflate(compensate, compensate);
                    //destRect.Offset(-compensate / 2, -compensate / 2);

                    if (UseSubstitute)
                    {
                        int offX = m_substituteRectangle.X;
                        int offY = m_substituteRectangle.Y;
                        www = m_substituteRectangle.Width;
                        hhh = m_substituteRectangle.Height;
                        e.Graphics.DrawImage(m_tileBackdrop.Image, destRect, offX, offY, www, hhh,
                                             System.Drawing.GraphicsUnit.Pixel);
                    }
                    else
                    {
                        www = m_tileBackdrop.Width;
                        hhh = m_tileBackdrop.Height;
                        //LibSys.StatusBar.Trace("Tile_Paint(): tileImage w=" + www + " h=" + hhh);
                        // destRect = e.ClipRectangle;
                        e.Graphics.DrawImage(m_tileBackdrop.Image, destRect, 0, 0, www, hhh,
                                             System.Drawing.GraphicsUnit.Pixel);
                    }
                    if (Project.drawGrid)
                    {
                        DrawGrid(e.Graphics, destRect, www, hhh, null);
                    }
                }
                else
                {
                    if (m_tileBackdrop != null && m_tileBackdrop.ImageCorrupted)
                    {
                        DrawGrid(e.Graphics, destRect, www, hhh, "BAD JPG");
                        if (!m_triedReload)
                        {
                            m_triedReload = true;
                            TileCache.resetBackdrop(this, m_baseName);                                          // try reloading
                        }
                    }
                    else
                    {
                        DrawGrid(e.Graphics, destRect, www, hhh, "NOT LOADED");
                    }
                }
            }
            catch (Exception eee)
            {
                LibSys.StatusBar.Error("Tile:Tile_Paint(): " + m_baseName + " " + eee);
            }
        }
示例#8
0
        public void init()
        {
            GeoCoord topLeft = m_topLeft.Clone();

            topLeft.Normalize();
            GeoCoord bottomRight = m_bottomRight.Clone();

            bottomRight.Normalize();

            int iLat = (int)Math.Ceiling(topLeft.Lat);
            int iLng = (int)Math.Floor(topLeft.Lng);

            m_siLng = iLng;
            m_siLat = iLat;
            if (m_tileScale.Equals("z"))
            {
                // HACK:
                // compensate for the shift in z-level tiles
                // (their names point to the center, not the top left corner:
                iLat -= 2;
                iLng += 2;
            }
            string latDir = iLat < 0 ? "s" : "n";
            string lngDir = iLng < 0 ? "w" : "e";

            iLat = Math.Abs(iLat);
            iLng = Math.Abs(iLng);

            switch (m_tileScale)
            {
            case "w":
                m_level    = 0;
                m_baseName = "world_good";
                break;

            case "y":
                m_level = 1;
                if (iLat == 60 && latDir.Equals("s"))
                {
                    m_tileBackdrop = null;
                    return;
                }
                else
                {
                    string sLng = ("" + iLng).PadLeft(3, '0');
                    string sLat = "" + iLat;
                    m_baseName = m_tileScale + sLng + lngDir + sLat + latDir;
                }
                break;

            case "x":
                m_level    = 2;
                m_baseName = m_tileScale + iLng + lngDir + iLat + latDir;
                break;

            case "z":
                m_level    = 3;
                m_baseName = m_tileScale + iLng + lngDir + iLat + latDir;
                break;

            default:
                m_level = 4;
                iLat    = (int)Math.Floor(bottomRight.Lat);
                iLng    = (int)Math.Ceiling(bottomRight.Lng);
                if (iLng == -180)
                {
                    // edge correction needed around Lng=180
                    iLng = 180;
                }
                latDir     = iLat < 0 ? "s" : "n";
                lngDir     = iLng <= 0 ? "w" : "e";
                m_siLng    = iLng;
                m_siLat    = iLat;
                iLat       = Math.Abs(iLat);
                iLng       = Math.Abs(iLng);
                m_baseName = m_tileScale + iLng + lngDir + iLat + latDir;
                break;

            case "a":
                m_level = 5;
                iLat    = (int)Math.Floor(bottomRight.Lat);
                iLng    = (int)Math.Ceiling(bottomRight.Lng);
                if (iLng == -180)
                {
                    // edge correction needed around Lng=180
                    iLng = 180;
                }
                latDir  = iLat < 0 ? "s" : "n";
                lngDir  = iLng <= 0 ? "w" : "e";
                m_siLng = iLng;
                m_siLat = iLat;
                iLat    = Math.Abs(iLat);
                iLng    = Math.Abs(iLng);
                // figure out quadrant and correct the tile scale letter:
                double ty = topLeft.Lat - Math.Floor(topLeft.Lat);
                double tx = topLeft.Lng - Math.Floor(topLeft.Lng);

                if (ty > 0.01d && tx > 0.01d)
                {
                    m_tileScale = "d";
                    m_aShiftX   = 1;
                    m_aShiftY   = 1;
                }
                else if (tx > 0.01d)
                {
                    m_tileScale = "b";
                    m_aShiftX   = 1;
                }
                else if (ty > 0.01d)
                {
                    m_tileScale = "c";
                    m_aShiftY   = 1;
                }
                m_baseName = m_tileScale + iLng + lngDir + iLat + latDir;
                break;
            }

            if (MayUseSubstitute)
            {
                // calculate substitute backdrop parameters, just in case real backdrop will be missing:
                int substLat = (int)Math.Floor(bottomRight.Lat);
                if (substLat >= 0)
                {
                    substLat = substLat / 10 + 1;
                }
                else if (substLat < 0 && substLat >= -10)
                {
                    substLat = 0;
                    latDir   = "n";
                }
                else
                {
                    substLat = (int)Math.Ceiling(bottomRight.Lat + 0.0001d);
                    substLat = substLat / 10;
                }
                substLat = substLat * 10;

                int substLng = (int)Math.Ceiling(bottomRight.Lng);
                if (substLng > 0)
                {
                    substLng = (int)Math.Floor(topLeft.Lng);
                    substLng = substLng / 10;
                }
                else if (substLng == 0)
                {
                    // edge correction needed around Lng=0
                    substLng = 1;
                }
                else if (substLng == -180)
                {
                    // edge correction needed around Lng=180
                    substLng = 17;
                }
                else
                {
                    substLng = substLng / 10 - 1;
                }
                substLng = substLng * 10;

                m_substLng       = substLng;
                m_substLat       = substLat;
                substLat         = Math.Abs(substLat);
                substLng         = Math.Abs(substLng);
                m_substituteName = "x" + substLng + lngDir + substLat + latDir;
#if DEBUG
                LibSys.StatusBar.Trace("Tile::init() m_substituteName=" + m_substituteName);
                LibSys.StatusBar.Trace("siLng=" + m_siLng + " m_substLng=" + m_substLng + " siLat=" + m_siLat + " m_substLat=" + m_substLat);
#endif
            }

            //LibSys.StatusBar.Trace("Tile:init() baseName=" + m_baseName);
            m_tileBackdrop = TileCache.getBackdrop(this, m_baseName);                           // may be Empty, never null
            if (m_tileBackdrop.IsEmpty)
            {
                // unlikely, but we may know immediately that we need to use substitute, if feasible:
                if (MayUseSubstitute)
                {
                    // get substitute backdrop:
                    m_useSubstitute = true;
                    //LibSys.StatusBar.Trace("Tile::init() - requesting backdrop substitute " + m_substituteName);
                    m_tileBackdrop = TileCache.getBackdrop(this, m_substituteName);                     // may be Empty, never null
                    if (m_tileBackdrop.IsEmpty)
                    {
                        m_isEmpty = true;
                    }
                    else if (m_tileBackdrop.HasImage)
                    {
                        CalculateSubstituteRectangle();                          // may instead set IsEmpty
                    }
                    // else wait for arrival...
                }
                else
                {
                    m_isEmpty = true;
                }
            }
            m_tileFeatures = TileCache.getFeatures(this, m_baseName);                           // may be Empty, never null
            if (m_tileFeatures.IsEmpty)
            {
                // unlikely, but we may know immediately that we need to use substitute, if feasible:
                if (MayUseSubstitute)
                {
                    // get substitute features:
#if DEBUG
                    LibSys.StatusBar.Trace("Tile::init() - requesting features substitute " + m_substituteName);
#endif
                    m_tileFeatures = TileCache.getFeatures(this, m_substituteName);                     // may be Empty, never null
                    if (m_tileFeatures.HasLoaded)
                    {
                        CreateFeaturesSubset();
                        ProvokeFeaturesPutOnMap();                                      // provoke PutOnMap on the next Tile_Paint()
                    }
                    else
                    {
#if DEBUG
                        LibSys.StatusBar.Trace("Tile::init() - " + m_baseName + " - features hasn't loaded -  nothing to copy...");
#endif
                    }
                    // wait for arrival...
                }
            }
            else
            {
                ProvokeFeaturesPutOnMap();                              // provoke PutOnMap on the next Tile_Paint()
            }
        }