placenamelayer.java

来自「world wind java sdk 源码」· Java 代码 · 共 1,493 行 · 第 1/4 页

JAVA
1,493
字号
            {
                String msg = Logging.getMessage("nullValue.AngleIsNull");
                Logging.logger().severe(msg);
                throw new IllegalArgumentException(msg);
            }
            return (int) ((latitude.getDegrees() + 90d) / delta.getDegrees());
        }

        static int computeColumn(Angle delta, Angle longitude)
        {
            if (delta == null || longitude == null)
            {
                String msg = Logging.getMessage("nullValue.AngleIsNull");
                Logging.logger().severe(msg);
                throw new IllegalArgumentException(msg);
            }
            return (int) ((longitude.getDegrees() + 180d) / delta.getDegrees());
        }

        static Angle computeRowLatitude(int row, Angle delta)
        {
            if (delta == null)
            {
                String msg = Logging.getMessage("nullValue.AngleIsNull");
                Logging.logger().severe(msg);
                throw new IllegalArgumentException(msg);
            }
            return Angle.fromDegrees(-90d + delta.getDegrees() * row);
        }

        static Angle computeColumnLongitude(int column, Angle delta)
        {
            if (delta == null)
            {
                String msg = Logging.getMessage("nullValue.AngleIsNull");
                Logging.logger().severe(msg);
                throw new IllegalArgumentException(msg);
            }
            return Angle.fromDegrees(-180 + delta.getDegrees() * column);
        }

        public Integer getHashInt()
        {
            return hashInt;
        }

        int computeHash()
        {
            return this.getFileCachePath() != null ? this.getFileCachePath().hashCode() : 0;
        }

        @Override
        public boolean equals(Object o)
        {
            if (this == o)
                return true;
            if (o == null || getClass() != o.getClass())
                return false;

            final Tile tile = (Tile) o;

            return !(this.getFileCachePath() != null ? !this.getFileCachePath().equals(tile.getFileCachePath()) : tile.getFileCachePath() != null);
        }

        String getFileCachePath()
        {
            if (this.fileCachePath == null)
                this.fileCachePath = this.placeNameService.createFileCachePathFromTile(this.row, this.column);

            return this.fileCachePath;
        }


        PlaceNameService getPlaceNameService()
        {
            return placeNameService;
        }

        java.net.URL getRequestURL() throws java.net.MalformedURLException
        {
            return this.placeNameService.createServiceURLFromSector(this.sector);
        }


        Sector getSector()
        {
            return sector;
        }

        public int hashCode()
        {
            return this.hashInt;
        }

        boolean isTileInMemoryWithData()
        {
            //todo switched to string
            Tile t = (Tile) WorldWind.getMemoryCache(Tile.class.getName()).getObject(this.getHashInt());
            if (t ==null || t.getDataChunk() == null)
                return false;
            else
                return true;
        }

        public boolean isTileLocalOrAbsent()
        {
            if (this.getPlaceNameService().isResourceAbsent(
                this.getPlaceNameService().getTileNumber(this.row, this.column)))
                return true;    // tile is absent

            URL url = WorldWind.getDataFileStore().findFile(this.getFileCachePath(), false);
            return url != null; // tile is already in cache
        }

        public Vec4 getCentroidPoint(Globe globe)
        {
            if (globe == null)
            {
                String msg = Logging.getMessage("nullValue.GlobeIsNull");
                Logging.logger().severe(msg);
                throw new IllegalArgumentException(msg);
            }

            if (this.centroid == null)
            {
                LatLon c = this.getSector().getCentroid();
                this.centroid = globe.computePointFromPosition(c.getLatitude(), c.getLongitude(), 0);
            }

            return this.centroid;
        }

        public double getPriority()
        {
            return priority;
        }

        public void setPriority(double priority)
        {
            this.priority = priority;
        }
    }

    private Tile[] buildTiles(PlaceNameService placeNameService, NavigationTile navTile)
    {
        final Angle dLat = placeNameService.getTileDelta().getLatitude();
        final Angle dLon = placeNameService.getTileDelta().getLongitude();

        // Determine the row and column offset from the global tiling origin for the southwest tile corner
        int firstRow = Tile.computeRow(dLat, navTile.navSector.getMinLatitude());
        int firstCol = Tile.computeColumn(dLon, navTile.navSector.getMinLongitude());
        int lastRow = Tile.computeRow(dLat, navTile.navSector.getMaxLatitude().subtract(dLat));
        int lastCol = Tile.computeColumn(dLon, navTile.navSector.getMaxLongitude().subtract(dLon));

        int nLatTiles = lastRow - firstRow + 1;
        int nLonTiles = lastCol - firstCol + 1;

        Tile[] tiles = new Tile[nLatTiles * nLonTiles];

        Angle p1 = Tile.computeRowLatitude(firstRow, dLat);
        for (int row = 0; row <= lastRow-firstRow; row++)
        {
            Angle p2;
            p2 = p1.add(dLat);

            Angle t1 = Tile.computeColumnLongitude(firstCol, dLon);
            for (int col = 0; col <= lastCol-firstCol; col++)
            {
                Angle t2;
                t2 = t1.add(dLon);
                //Need offset row and column to correspond to total ro/col numbering
                tiles[col + row * nLonTiles] = new Tile(placeNameService, new Sector(p1, p2, t1, t2), row+firstRow, col+firstCol);
                t1 = t2;
            }
            p1 = p2;
        }

        return tiles;
    }
    
    // ============== Place Name Data Structures ======================= //
    // ============== Place Name Data Structures ======================= //
    // ============== Place Name Data Structures ======================= //

    private static class PlaceNameChunk implements Cacheable
    {
        final PlaceNameService placeNameService;
        final CharBuffer textArray;
        final int[] textIndexArray;
        final double[] latlonArray;
        final int numEntries;
        final long estimatedMemorySize;

        PlaceNameChunk(PlaceNameService service, CharBuffer text, int[] textIndices,
            double[] positions, int numEntries)
        {
            this.placeNameService = service;
            this.textArray = text;
            this.textIndexArray = textIndices;
            this.latlonArray = positions;
            this.numEntries = numEntries;
            this.estimatedMemorySize = this.computeEstimatedMemorySize();
        }

        long computeEstimatedMemorySize()
        {
            long result = 0;
            if (!textArray.isDirect())
                result += (Character.SIZE / 8) * textArray.capacity();
            result += (Integer.SIZE / 8) * textIndexArray.length;
            result += (Double.SIZE / 8) * latlonArray.length;
            return result;
        }

        Position getPosition(int index)
        {
            int latlonIndex = 2 * index;
            return Position.fromDegrees(latlonArray[latlonIndex], latlonArray[latlonIndex + 1], 0);
        }

        PlaceNameService getPlaceNameService()
        {
            return this.placeNameService;
        }

        CharSequence getText(int index)
        {
            int beginIndex = textIndexArray[index];
            int endIndex = (index + 1 < numEntries) ? textIndexArray[index + 1] : textArray.length();
            return this.textArray.subSequence(beginIndex, endIndex);
        }

        public long getSizeInBytes()
        {
            return this.estimatedMemorySize;
        }

        private Iterable<GeographicText> makeIterable(DrawContext dc)
        {
            //get dispay dist for this service for use in label annealing
            double maxDisplayDistance = this.getPlaceNameService().getMaxDisplayDistance();
            ArrayList<GeographicText> list = new ArrayList<GeographicText>();
            for (int i = 0; i < this.numEntries; i++)
            {
                CharSequence str = getText(i);
                Position pos = getPosition(i);
                GeographicText text = new UserFacingText(str, pos);
                text.setFont(this.placeNameService.getFont());
                text.setColor(this.placeNameService.getColor());
                text.setBackgroundColor(this.placeNameService.getBackgroundColor());
                text.setVisible(isNameVisible(dc, this.placeNameService, pos));
                text.setPriority(maxDisplayDistance);
                list.add(text);
            }
            return list;
        }
    }

    // ============== Rendering ======================= //
    // ============== Rendering ======================= //
    // ============== Rendering ======================= //

    private final GeographicTextRenderer placeNameRenderer = new GeographicTextRenderer();

    @Override
    protected void doRender(DrawContext dc)
    {

        this.referencePoint = this.computeReferencePoint(dc);

        int serviceCount = this.placeNameServiceSet.getServiceCount();
        for (int i = 0; i < serviceCount; i++)
        {
            PlaceNameService placeNameService = this.placeNameServiceSet.getService(i);
            if (!isServiceVisible(dc, placeNameService))
                continue;

            double minDistSquared = placeNameService.getMinDisplayDistance() * placeNameService.getMinDisplayDistance();
            double maxDistSquared = placeNameService.getMaxDisplayDistance() * placeNameService.getMaxDisplayDistance();

            if (isSectorVisible(dc, placeNameService.getMaskingSector(), minDistSquared, maxDistSquared))
            {
                    ArrayList<Tile> baseTiles = new ArrayList<Tile>();
                    NavigationTile navTile = this.navTiles.get(i);
                    //drill down into tiles to find bottom level navTiles visible
                    List<NavigationTile> list=navTile.navTilesVisible(dc, minDistSquared, maxDistSquared);
                    for(NavigationTile nt: list)
                    {
                        baseTiles.addAll(nt.getTiles());
                    }

                    for (Tile tile : baseTiles)
                    {
                        try
                        {
                            drawOrRequestTile(dc, tile, minDistSquared, maxDistSquared);
                        }
                        catch (Exception e)
                        {
                            Logging.logger().log(Level.FINE, Logging.getMessage("layers.PlaceNameLayer.ExceptionRenderingTile"),
                                e);
                        }
                    }
            }
        }

        this.sendRequests();
        this.requestQ.clear();
    }

    private Vec4 computeReferencePoint(DrawContext dc)
    {
        if (dc.getViewportCenterPosition() != null)
            return dc.getGlobe().computePointFromPosition(dc.getViewportCenterPosition());

        java.awt.geom.Rectangle2D viewport = dc.getView().getViewport();
        int x = (int) viewport.getWidth() / 2;
        for (int y = (int) (0.5 * viewport.getHeight()); y >= 0; y--)
        {
            Position pos = dc.getView().computePositionFromScreenPoint(x, y);
            if (pos == null)
                continue;

            return dc.getGlobe().computePointFromPosition(pos.getLatitude(), pos.getLongitude(), 0d);
        }

        return null;
    }

    protected Vec4 getReferencePoint()
    {
        return this.referencePoint;
    }

    private void drawOrRequestTile(DrawContext dc, Tile tile, double minDisplayDistanceSquared,
        double maxDisplayDistanceSquared)
    {
        if (!isTileVisible(dc, tile, minDisplayDistanceSquared, maxDisplayDistanceSquared))
            return;
        
        if (tile.isTileInMemoryWithData())
        {
            PlaceNameChunk placeNameChunk = tile.getDataChunk();
            if (placeNameChunk.numEntries > 0)
            {
                Iterable<GeographicText> renderIter = placeNameChunk.makeIterable(dc);
                this.placeNameRenderer.render(dc, renderIter);
            }
            return;
        }

        // Tile's data isn't available, so request it
        if (!tile.getPlaceNameService().isResourceAbsent(tile.getPlaceNameService().getTileNumber(
                tile.row, tile.column)))
        {
            this.requestTile(dc, tile);
        }
    }

    private static boolean isServiceVisible(DrawContext dc, PlaceNameService placeNameService)
    {
        if (!placeNameService.isEnabled())
            return false;
        //noinspection SimplifiableIfStatement
        if (dc.getVisibleSector() != null && !placeNameService.getMaskingSector().intersects(dc.getVisibleSector()))
            return false;

        return placeNameService.getExtent(dc).intersects(dc.getView().getFrustumInModelCoordinates());
    }


    private static boolean isSectorVisible(DrawContext dc, Sector sector, double minDistanceSquared,
        double maxDistanceSquared)
    {

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?