2 Copyright (C) 2001, 2006 United States Government as represented by
3 the Administrator of the National Aeronautics and Space Administration.
6 package gov
.nasa
.worldwind
.layers
.placename
;
8 import com
.sun
.opengl
.util
.BufferUtil
;
9 import gov
.nasa
.worldwind
.*;
10 import gov
.nasa
.worldwind
.avlist
.AVKey
;
11 import gov
.nasa
.worldwind
.cache
.*;
12 import gov
.nasa
.worldwind
.geom
.*;
13 import gov
.nasa
.worldwind
.layers
.AbstractLayer
;
14 import gov
.nasa
.worldwind
.pick
.PlaceName
;
15 import gov
.nasa
.worldwind
.render
.*;
16 import gov
.nasa
.worldwind
.retrieve
.*;
17 import gov
.nasa
.worldwind
.util
.*;
18 import gov
.nasa
.worldwind
.view
.View
;
22 import java
.util
.List
;
23 import java
.util
.Queue
;
24 import java
.util
.concurrent
.LinkedBlockingQueue
;
25 import java
.util
.logging
.Level
;
28 * @author Paul Collins
29 * @version $Id: PlaceNameLayer.java 2980 2007-09-22 01:07:06Z tgaskins $
31 public class PlaceNameLayer
extends AbstractLayer
33 private final PlaceNameServiceSet placeNameServiceSet
;
34 private final List
<Tile
[]> tiles
= new ArrayList
<Tile
[]>();
35 private final MemoryCache memoryCache
;
38 * @param placeNameServiceSet the set of PlaceNameService objects that PlaceNameLayer will render.
39 * @throws IllegalArgumentException if <code>placeNameServiceSet</code> is null
41 public PlaceNameLayer(PlaceNameServiceSet placeNameServiceSet
)
43 if (placeNameServiceSet
== null)
45 String message
= Logging
.getMessage("nullValue.PlaceNameServiceSetIsNull");
46 Logging
.logger().fine(message
);
47 throw new IllegalArgumentException(message
);
50 String cacheName
= Tile
.class.getName();
51 if (WorldWind
.getMemoryCacheSet().containsCache(cacheName
))
53 this.memoryCache
= WorldWind
.getMemoryCache(cacheName
);
57 long size
= Configuration
.getLongValue(AVKey
.PLACENAME_LAYER_CACHE_SIZE
, 2000000L);
58 this.memoryCache
= new BasicMemoryCache((long) (0.85 * size
), size
);
59 this.memoryCache
.setName("Placenames");
60 WorldWind
.getMemoryCacheSet().addCache(cacheName
, this.memoryCache
);
63 this.placeNameServiceSet
= placeNameServiceSet
.deepCopy();
64 for (int i
= 0; i
< this.placeNameServiceSet
.getServiceCount(); i
++)
66 tiles
.add(i
, buildTiles(this.placeNameServiceSet
.getService(i
)));
70 public final PlaceNameServiceSet
getPlaceNameServiceSet()
72 return this.placeNameServiceSet
;
75 // ============== Tile Assembly ======================= //
76 // ============== Tile Assembly ======================= //
77 // ============== Tile Assembly ======================= //
79 private static class Tile
81 final PlaceNameService placeNameService
;
87 String fileCachePath
= null;
89 double extentVerticalExaggeration
= Double
.MIN_VALUE
;
91 static int computeRow(Angle delta
, Angle latitude
)
93 if (delta
== null || latitude
== null)
95 String msg
= Logging
.getMessage("nullValue.AngleIsNull");
96 Logging
.logger().severe(msg
);
97 throw new IllegalArgumentException(msg
);
99 return (int) ((latitude
.getDegrees() + 90d
) / delta
.getDegrees());
102 static int computeColumn(Angle delta
, Angle longitude
)
104 if (delta
== null || longitude
== null)
106 String msg
= Logging
.getMessage("nullValue.AngleIsNull");
107 Logging
.logger().severe(msg
);
108 throw new IllegalArgumentException(msg
);
110 return (int) ((longitude
.getDegrees() + 180d
) / delta
.getDegrees());
113 static Angle
computeRowLatitude(int row
, Angle delta
)
117 String msg
= Logging
.getMessage("nullValue.AngleIsNull");
118 Logging
.logger().severe(msg
);
119 throw new IllegalArgumentException(msg
);
121 return Angle
.fromDegrees(-90d
+ delta
.getDegrees() * row
);
124 static Angle
computeColumnLongitude(int column
, Angle delta
)
128 String msg
= Logging
.getMessage("nullValue.AngleIsNull");
129 Logging
.logger().severe(msg
);
130 throw new IllegalArgumentException(msg
);
132 return Angle
.fromDegrees(-180 + delta
.getDegrees() * column
);
135 Tile(PlaceNameService placeNameService
, Sector sector
, int row
, int column
)
137 this.placeNameService
= placeNameService
;
138 this.sector
= sector
;
140 this.column
= column
;
141 this.hash
= this.computeHash();
146 return this.getFileCachePath() != null ?
this.getFileCachePath().hashCode() : 0;
150 public boolean equals(Object o
)
154 if (o
== null || this.getClass() != o
.getClass())
157 final Tile other
= (Tile
) o
;
159 return this.getFileCachePath() != null ?
!this.getFileCachePath().equals(other
.getFileCachePath()) :
160 other
.getFileCachePath() != null;
163 Extent
getExtent(DrawContext dc
)
167 String message
= Logging
.getMessage("nullValue.DrawContextIsNull");
168 Logging
.logger().fine(message
);
169 throw new IllegalArgumentException(message
);
172 if (this.extent
== null || this.extentVerticalExaggeration
!= dc
.getVerticalExaggeration())
174 this.extentVerticalExaggeration
= dc
.getVerticalExaggeration();
175 this.extent
= Sector
.computeBoundingCylinder(dc
.getGlobe(), this.extentVerticalExaggeration
,
182 String
getFileCachePath()
184 if (this.fileCachePath
== null)
185 this.fileCachePath
= this.placeNameService
.createFileCachePathFromTile(this.row
, this.column
);
187 return this.fileCachePath
;
190 PlaceNameService
getPlaceNameService()
192 return placeNameService
;
195 java
.net
.URL
getRequestURL() throws java
.net
.MalformedURLException
197 return this.placeNameService
.createServiceURLFromSector(this.sector
);
205 public int hashCode()
211 private Tile
[] buildTiles(PlaceNameService placeNameService
)
213 final Sector sector
= placeNameService
.getSector();
214 final Angle dLat
= placeNameService
.getTileDelta().getLatitude();
215 final Angle dLon
= placeNameService
.getTileDelta().getLongitude();
217 // Determine the row and column offset from the global tiling origin for the southwest tile corner
218 int firstRow
= Tile
.computeRow(dLat
, sector
.getMinLatitude());
219 int firstCol
= Tile
.computeColumn(dLon
, sector
.getMinLongitude());
220 int lastRow
= Tile
.computeRow(dLat
, sector
.getMaxLatitude().subtract(dLat
));
221 int lastCol
= Tile
.computeColumn(dLon
, sector
.getMaxLongitude().subtract(dLon
));
223 int nLatTiles
= lastRow
- firstRow
+ 1;
224 int nLonTiles
= lastCol
- firstCol
+ 1;
226 Tile
[] tiles
= new Tile
[nLatTiles
* nLonTiles
];
228 Angle p1
= Tile
.computeRowLatitude(firstRow
, dLat
);
229 for (int row
= firstRow
; row
<= lastRow
; row
++)
234 Angle t1
= Tile
.computeColumnLongitude(firstCol
, dLon
);
235 for (int col
= firstCol
; col
<= lastCol
; col
++)
240 tiles
[col
+ row
* nLonTiles
] = new Tile(placeNameService
, new Sector(p1
, p2
, t1
, t2
), row
, col
);
249 // ============== Place Name Data Structures ======================= //
250 // ============== Place Name Data Structures ======================= //
251 // ============== Place Name Data Structures ======================= //
253 private static class PlaceNameChunk
implements Cacheable
255 final PlaceNameService placeNameService
;
256 final StringBuilder textArray
;
257 final int[] textIndexArray
;
258 final double[] latlonArray
;
259 final int numEntries
;
260 final long estimatedMemorySize
;
262 PlaceNameChunk(PlaceNameService service
, StringBuilder text
, int[] textIndices
,
263 double[] positions
, int numEntries
)
265 this.placeNameService
= service
;
266 this.textArray
= text
;
267 this.textIndexArray
= textIndices
;
268 this.latlonArray
= positions
;
269 this.numEntries
= numEntries
;
270 this.estimatedMemorySize
= this.computeEstimatedMemorySize();
273 long computeEstimatedMemorySize()
276 result
+= BufferUtil
.SIZEOF_SHORT
* textArray
.capacity();
277 result
+= BufferUtil
.SIZEOF_INT
* textIndexArray
.length
;
278 result
+= BufferUtil
.SIZEOF_DOUBLE
* latlonArray
.length
;
282 Position
getPosition(int index
)
284 int latlonIndex
= 2 * index
;
285 return Position
.fromDegrees(latlonArray
[latlonIndex
], latlonArray
[latlonIndex
+ 1], 0);
288 PlaceNameService
getPlaceNameService()
290 return this.placeNameService
;
293 String
getText(int index
)
295 int beginIndex
= textIndexArray
[index
];
296 int endIndex
= (index
+ 1 < numEntries
) ? textIndexArray
[index
+ 1] : textArray
.length();
297 return this.textArray
.substring(beginIndex
, endIndex
);
300 public long getSizeInBytes()
302 return this.estimatedMemorySize
;
305 Iterator
<PlaceName
> createRenderIterator(final DrawContext dc
)
307 return new Iterator
<PlaceName
>()
309 PlaceNameImpl placeNameProxy
= new PlaceNameImpl();
312 public boolean hasNext()
314 return index
< (PlaceNameChunk
.this.numEntries
- 1);
317 public PlaceName
next()
320 throw new NoSuchElementException();
321 this.updateProxy(placeNameProxy
, ++index
);
322 return placeNameProxy
;
327 throw new UnsupportedOperationException();
330 void updateProxy(PlaceNameImpl proxy
, int index
)
332 proxy
.text
= getText(index
);
333 proxy
.position
= getPosition(index
);
334 proxy
.font
= placeNameService
.getFont();
335 proxy
.color
= placeNameService
.getColor();
336 proxy
.visible
= isNameVisible(dc
, placeNameService
, proxy
.position
);
342 private static class PlaceNameImpl
implements PlaceName
354 public String
getText()
359 public void setText(String text
)
361 throw new UnsupportedOperationException();
364 public Position
getPosition()
366 return this.position
;
369 public void setPosition(Position position
)
371 throw new UnsupportedOperationException();
374 public Font
getFont()
379 public void setFont(Font font
)
381 throw new UnsupportedOperationException();
384 public Color
getColor()
389 public void setColor(Color color
)
391 throw new UnsupportedOperationException();
394 public boolean isVisible()
399 public void setVisible(boolean visible
)
401 throw new UnsupportedOperationException();
404 public WWIcon
getIcon()
409 public void setIcon(WWIcon icon
)
411 throw new UnsupportedOperationException();
415 // ============== Rendering ======================= //
416 // ============== Rendering ======================= //
417 // ============== Rendering ======================= //
419 private final PlaceNameRenderer placeNameRenderer
= new PlaceNameRenderer();
422 public void dispose() // override if disposal is a supported operation
426 if (this.placeNameRenderer
!= null)
427 this.placeNameRenderer
.dispose();
431 protected void doRender(DrawContext dc
)
433 boolean enableDepthTest
= this.isEnableDepthTest(dc
);
435 int serviceCount
= this.placeNameServiceSet
.getServiceCount();
436 for (int i
= 0; i
< serviceCount
; i
++)
438 PlaceNameService placeNameService
= this.placeNameServiceSet
.getService(i
);
439 if (!isServiceVisible(dc
, placeNameService
))
442 double minDist
= placeNameService
.getMinDisplayDistance();
443 double maxDist
= placeNameService
.getMaxDisplayDistance();
444 double minDistSquared
= minDist
* minDist
;
445 double maxDistSquared
= maxDist
* maxDist
;
447 Tile
[] tiles
= this.tiles
.get(i
);
448 for (Tile tile
: tiles
)
452 drawOrRequestTile(dc
, tile
, minDistSquared
, maxDistSquared
, enableDepthTest
);
456 Logging
.logger().log(Level
.FINE
, Logging
.getMessage("layers.PlaceNameLayer.ExceptionRenderingTile"),
465 private boolean isEnableDepthTest(DrawContext dc
)
467 Position eyePos
= dc
.getView().getEyePosition();
471 double altitude
= eyePos
.getElevation();
472 return altitude
< (dc
.getVerticalExaggeration() * dc
.getGlobe().getMaxElevation());
475 private void drawOrRequestTile(DrawContext dc
, Tile tile
, double minDisplayDistanceSquared
,
476 double maxDisplayDistanceSquared
, boolean enableDepthTest
)
478 if (!isTileVisible(dc
, tile
, minDisplayDistanceSquared
, maxDisplayDistanceSquared
))
481 Object cacheObj
= this.memoryCache
.getObject(tile
);
482 if (cacheObj
== null)
484 this.requestTile(this.readQueue
, tile
);
488 if (!(cacheObj
instanceof PlaceNameChunk
))
491 PlaceNameChunk placeNameChunk
= (PlaceNameChunk
) cacheObj
;
492 Iterator
<PlaceName
> renderIter
= placeNameChunk
.createRenderIterator(dc
);
493 placeNameRenderer
.render(dc
, renderIter
, enableDepthTest
);
496 private static boolean isServiceVisible(DrawContext dc
, PlaceNameService placeNameService
)
498 if (!placeNameService
.isEnabled())
500 //noinspection SimplifiableIfStatement
501 if (dc
.getVisibleSector() != null && !placeNameService
.getSector().intersects(dc
.getVisibleSector()))
504 return placeNameService
.getExtent(dc
).intersects(dc
.getView().getFrustumInModelCoordinates());
507 private static boolean isTileVisible(DrawContext dc
, Tile tile
, double minDistanceSquared
,
508 double maxDistanceSquared
)
510 if (!tile
.getSector().intersects(dc
.getVisibleSector()))
513 View view
= dc
.getView();
514 Position eyePos
= view
.getEyePosition();
518 Angle lat
= clampAngle(eyePos
.getLatitude(), tile
.getSector().getMinLatitude(),
519 tile
.getSector().getMaxLatitude());
520 Angle lon
= clampAngle(eyePos
.getLongitude(), tile
.getSector().getMinLongitude(),
521 tile
.getSector().getMaxLongitude());
522 Vec4 p
= dc
.getGlobe().computePointFromPosition(lat
, lon
, 0d
);
523 double distSquared
= dc
.getView().getEyePoint().distanceToSquared3(p
);
524 //noinspection RedundantIfStatement
525 if (minDistanceSquared
> distSquared
|| maxDistanceSquared
< distSquared
)
531 private static boolean isNameVisible(DrawContext dc
, PlaceNameService service
, Position namePosition
)
533 double elevation
= dc
.getVerticalExaggeration() * namePosition
.getElevation();
534 Vec4 namePoint
= dc
.getGlobe().computePointFromPosition(namePosition
.getLatitude(),
535 namePosition
.getLongitude(), elevation
);
536 Vec4 eyeVec
= dc
.getView().getEyePoint();
538 double dist
= eyeVec
.distanceTo3(namePoint
);
539 return dist
>= service
.getMinDisplayDistance() && dist
<= service
.getMaxDisplayDistance();
542 private static Angle
clampAngle(Angle a
, Angle min
, Angle max
)
544 return a
.compareTo(min
) < 0 ? min
: (a
.compareTo(max
) > 0 ? max
: a
);
547 // ============== Image Reading and Downloading ======================= //
548 // ============== Image Reading and Downloading ======================= //
549 // ============== Image Reading and Downloading ======================= //
551 private static final int MAX_REQUESTS
= 64;
552 private final Queue
<Tile
> downloadQueue
= new LinkedBlockingQueue
<Tile
>(MAX_REQUESTS
);
553 private final Queue
<Tile
> readQueue
= new LinkedBlockingQueue
<Tile
>(MAX_REQUESTS
);
555 private static class RequestTask
implements Runnable
557 final PlaceNameLayer layer
;
560 RequestTask(PlaceNameLayer layer
, Tile tile
)
567 public boolean equals(Object o
)
571 if (o
== null || this.getClass() != o
.getClass())
574 final RequestTask other
= (RequestTask
) o
;
576 // Don't include layer in comparison so that requests are shared among layers
577 return !(this.tile
!= null ?
!this.tile
.equals(other
.tile
) : other
.tile
!= null);
581 public int hashCode()
583 return (this.tile
!= null ?
this.tile
.hashCode() : 0);
590 if (this.layer
.memoryCache
.getObject(this.tile
) != null)
593 final java
.net
.URL tileURL
= WorldWind
.getDataFileCache().findFile(tile
.getFileCachePath(), false);
596 if (this.layer
.loadTile(this.tile
, tileURL
))
598 tile
.getPlaceNameService().unmarkResourceAbsent(tile
.getPlaceNameService().getTileNumber(
601 this.layer
.firePropertyChange(AVKey
.LAYER
, null, this);
605 // Assume that something's wrong with the file and delete it.
606 WorldWind
.getDataFileCache().removeFile(tileURL
);
607 tile
.getPlaceNameService().markResourceAbsent(tile
.getPlaceNameService().getTileNumber(tile
.row
,
609 String message
= Logging
.getMessage("generic.DeletedCorruptDataFile", tileURL
);
610 Logging
.logger().fine(message
);
616 this.layer
.requestTile(this.layer
.downloadQueue
, this.tile
);
619 public String
toString()
621 return this.tile
.toString();
625 private static class DownloadPostProcessor
implements RetrievalPostProcessor
627 final PlaceNameLayer layer
;
630 private DownloadPostProcessor(PlaceNameLayer layer
, Tile tile
)
636 public java
.nio
.ByteBuffer
run(Retriever retriever
)
638 if (retriever
== null)
640 String msg
= Logging
.getMessage("nullValue.RetrieverIsNull");
641 Logging
.logger().fine(msg
);
642 throw new IllegalArgumentException(msg
);
645 if (!retriever
.getState().equals(Retriever
.RETRIEVER_STATE_SUCCESSFUL
))
648 if (!(retriever
instanceof URLRetriever
))
653 if (retriever
instanceof HTTPRetriever
)
655 HTTPRetriever httpRetriever
= (HTTPRetriever
) retriever
;
656 if (httpRetriever
.getResponseCode() == java
.net
.HttpURLConnection
.HTTP_NO_CONTENT
)
658 // Mark tile as missing to avoid further attempts
659 tile
.getPlaceNameService().markResourceAbsent(tile
.getPlaceNameService().getTileNumber(tile
.row
,
665 URLRetriever urlRetriever
= (URLRetriever
) retriever
;
666 java
.nio
.ByteBuffer buffer
= urlRetriever
.getBuffer();
670 final java
.io
.File cacheFile
= WorldWind
.getDataFileCache().newFile(this.tile
.getFileCachePath());
671 if (cacheFile
== null)
673 String msg
= Logging
.getMessage("generic.CantCreateCacheFile", this.tile
.getFileCachePath());
674 Logging
.logger().fine(msg
);
678 if (cacheFile
.exists())
679 return buffer
; // info is already here; don't need to do anything
683 WWIO
.saveBuffer(buffer
, cacheFile
);
684 this.layer
.firePropertyChange(AVKey
.LAYER
, null, this);
689 catch (java
.io
.IOException e
)
691 Logging
.logger().log(Level
.FINE
, Logging
.getMessage(
692 "layers.PlaceNameLayer.ExceptionSavingRetrievedFile", this.tile
.getFileCachePath()), e
);
699 private static class GMLPlaceNameSAXHandler
extends org
.xml
.sax
.helpers
.DefaultHandler
701 static final String GML_FEATURE_MEMBER
= "gml:featureMember";
702 static final String TOPP_FULL_NAME_ND
= "topp:full_name_nd";
703 static final String TOPP_LATITUDE
= "topp:latitude";
704 static final String TOPP_LONGITUDE
= "topp:longitude";
705 final LinkedList
<String
> internedQNameStack
= new LinkedList
<String
>();
706 boolean inBeginEndPair
= false;
707 StringBuilder latBuffer
= new StringBuilder();
708 StringBuilder lonBuffer
= new StringBuilder();
710 StringBuilder textArray
= new StringBuilder();
711 int[] textIndexArray
= new int[16];
712 double[] latlonArray
= new double[16];
715 GMLPlaceNameSAXHandler()
719 PlaceNameChunk
createPlaceNameChunk(PlaceNameService service
)
721 return new PlaceNameChunk(service
, this.textArray
, this.textIndexArray
, this.latlonArray
, this.numEntries
);
726 int textIndex
= this.textArray
.length();
727 this.textIndexArray
= append(this.textIndexArray
, this.numEntries
, textIndex
);
728 this.inBeginEndPair
= true;
733 double lat
= this.parseDouble(this.latBuffer
);
734 double lon
= this.parseDouble(this.lonBuffer
);
735 int numLatLon
= 2 * this.numEntries
;
736 this.latlonArray
= this.append(this.latlonArray
, numLatLon
, lat
);
738 this.latlonArray
= this.append(this.latlonArray
, numLatLon
, lon
);
740 this.latBuffer
.delete(0, this.latBuffer
.length());
741 this.lonBuffer
.delete(0, this.lonBuffer
.length());
742 this.inBeginEndPair
= false;
746 double parseDouble(StringBuilder sb
)
751 value
= Double
.parseDouble(sb
.toString());
753 catch (NumberFormatException e
)
755 Logging
.logger().log(Level
.FINE
,
756 Logging
.getMessage("layers.PlaceNameLayer.ExceptionAttemptingToReadFile", ""), e
);
761 int[] append(int[] array
, int index
, int value
)
763 if (index
>= array
.length
)
764 array
= this.resizeArray(array
);
765 array
[index
] = value
;
769 int[] resizeArray(int[] oldArray
)
771 int newSize
= 2 * oldArray
.length
;
772 int[] newArray
= new int[newSize
];
773 System
.arraycopy(oldArray
, 0, newArray
, 0, oldArray
.length
);
777 double[] append(double[] array
, int index
, double value
)
779 if (index
>= array
.length
)
780 array
= this.resizeArray(array
);
781 array
[index
] = value
;
785 double[] resizeArray(double[] oldArray
)
787 int newSize
= 2 * oldArray
.length
;
788 double[] newArray
= new double[newSize
];
789 System
.arraycopy(oldArray
, 0, newArray
, 0, oldArray
.length
);
793 public void characters(char ch
[], int start
, int length
)
795 if (!this.inBeginEndPair
)
798 // Top of QName stack is an interned string,
799 // so we can use pointer comparison.
800 String internedTopQName
= this.internedQNameStack
.getFirst();
802 StringBuilder sb
= null;
803 if (TOPP_LATITUDE
== internedTopQName
)
805 else if (TOPP_LONGITUDE
== internedTopQName
)
807 else if (TOPP_FULL_NAME_ND
== internedTopQName
)
811 sb
.append(ch
, start
, length
);
814 public void startElement(String uri
, String localName
, String qName
, org
.xml
.sax
.Attributes attributes
)
816 // Don't validate uri, localName or attributes because they aren't used.
817 // Intern the qName string so we can use pointer comparison.
818 String internedQName
= qName
.intern();
819 if (GML_FEATURE_MEMBER
== internedQName
)
821 this.internedQNameStack
.addFirst(internedQName
);
824 public void endElement(String uri
, String localName
, String qName
)
826 // Don't validate uri or localName because they aren't used.
827 // Intern the qName string so we can use pointer comparison.
828 String internedQName
= qName
.intern();
829 if (GML_FEATURE_MEMBER
== internedQName
)
831 this.internedQNameStack
.removeFirst();
835 private boolean loadTile(Tile tile
, java
.net
.URL url
)
837 PlaceNameChunk placeNameChunk
= readTile(tile
, url
);
838 if (placeNameChunk
== null)
841 this.memoryCache
.add(tile
, placeNameChunk
);
845 private static PlaceNameChunk
readTile(Tile tile
, java
.net
.URL url
)
847 java
.io
.InputStream is
= null;
851 String path
= url
.getFile();
852 path
= path
.replaceAll("%20", " "); // TODO: find a better way to get a path usable by FileInputStream
854 java
.io
.FileInputStream fis
= new java
.io
.FileInputStream(path
);
855 java
.io
.BufferedInputStream buf
= new java
.io
.BufferedInputStream(fis
);
856 is
= new java
.util
.zip
.GZIPInputStream(buf
);
858 GMLPlaceNameSAXHandler handler
= new GMLPlaceNameSAXHandler();
859 javax
.xml
.parsers
.SAXParserFactory
.newInstance().newSAXParser().parse(is
, handler
);
860 return handler
.createPlaceNameChunk(tile
.getPlaceNameService());
864 Logging
.logger().log(Level
.FINE
,
865 Logging
.getMessage("layers.PlaceNameLayer.ExceptionAttemptingToReadFile", url
.toString()), e
);
874 catch (java
.io
.IOException e
)
876 Logging
.logger().log(Level
.FINE
,
877 Logging
.getMessage("layers.PlaceNameLayer.ExceptionAttemptingToReadFile", url
.toString()), e
);
884 private void requestTile(Queue
<Tile
> queue
, Tile tile
)
886 if (tile
.getPlaceNameService().isResourceAbsent(tile
.getPlaceNameService().getTileNumber(
887 tile
.row
, tile
.column
)))
889 if (!queue
.contains(tile
))
893 private void sendRequests()
896 // Send threaded read tasks.
897 while (!WorldWind
.getTaskService().isFull() && (tile
= this.readQueue
.poll()) != null)
899 WorldWind
.getTaskService().addTask(new RequestTask(this, tile
));
901 // Send retriever tasks.
902 while (!WorldWind
.getRetrievalService().isFull() && (tile
= this.downloadQueue
.poll()) != null)
907 url
= tile
.getRequestURL();
909 catch (java
.net
.MalformedURLException e
)
911 String message
= Logging
.getMessage("layers.PlaceNameLayer.ExceptionAttemptingToDownloadFile", tile
);
912 Logging
.logger().log(Level
.FINE
, message
, e
);
915 WorldWind
.getRetrievalService().runRetriever(new HTTPRetriever(url
, new DownloadPostProcessor(this, tile
)));