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 2490 2007-08-02 18:24:12Z dcollins $
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 protected void doRender(DrawContext dc
)
424 boolean enableDepthTest
= this.isEnableDepthTest(dc
);
426 int serviceCount
= this.placeNameServiceSet
.getServiceCount();
427 for (int i
= 0; i
< serviceCount
; i
++)
429 PlaceNameService placeNameService
= this.placeNameServiceSet
.getService(i
);
430 if (!isServiceVisible(dc
, placeNameService
))
433 double minDist
= placeNameService
.getMinDisplayDistance();
434 double maxDist
= placeNameService
.getMaxDisplayDistance();
435 double minDistSquared
= minDist
* minDist
;
436 double maxDistSquared
= maxDist
* maxDist
;
438 Tile
[] tiles
= this.tiles
.get(i
);
439 for (Tile tile
: tiles
)
443 drawOrRequestTile(dc
, tile
, minDistSquared
, maxDistSquared
, enableDepthTest
);
447 Logging
.logger().log(Level
.FINE
, Logging
.getMessage("layers.PlaceNameLayer.ExceptionRenderingTile"),
456 private boolean isEnableDepthTest(DrawContext dc
)
458 Position eyePos
= dc
.getView().getEyePosition();
462 double altitude
= eyePos
.getElevation();
463 return altitude
< (dc
.getVerticalExaggeration() * dc
.getGlobe().getMaxElevation());
466 private void drawOrRequestTile(DrawContext dc
, Tile tile
, double minDisplayDistanceSquared
,
467 double maxDisplayDistanceSquared
, boolean enableDepthTest
)
469 if (!isTileVisible(dc
, tile
, minDisplayDistanceSquared
, maxDisplayDistanceSquared
))
472 Object cacheObj
= this.memoryCache
.getObject(tile
);
473 if (cacheObj
== null)
475 this.requestTile(this.readQueue
, tile
);
479 if (!(cacheObj
instanceof PlaceNameChunk
))
482 PlaceNameChunk placeNameChunk
= (PlaceNameChunk
) cacheObj
;
483 Iterator
<PlaceName
> renderIter
= placeNameChunk
.createRenderIterator(dc
);
484 placeNameRenderer
.render(dc
, renderIter
, enableDepthTest
);
487 private static boolean isServiceVisible(DrawContext dc
, PlaceNameService placeNameService
)
489 if (!placeNameService
.isEnabled())
491 //noinspection SimplifiableIfStatement
492 if (dc
.getVisibleSector() != null && !placeNameService
.getSector().intersects(dc
.getVisibleSector()))
495 return placeNameService
.getExtent(dc
).intersects(dc
.getView().getFrustumInModelCoordinates());
498 private static boolean isTileVisible(DrawContext dc
, Tile tile
, double minDistanceSquared
,
499 double maxDistanceSquared
)
501 if (!tile
.getSector().intersects(dc
.getVisibleSector()))
504 View view
= dc
.getView();
505 Position eyePos
= view
.getEyePosition();
509 Angle lat
= clampAngle(eyePos
.getLatitude(), tile
.getSector().getMinLatitude(),
510 tile
.getSector().getMaxLatitude());
511 Angle lon
= clampAngle(eyePos
.getLongitude(), tile
.getSector().getMinLongitude(),
512 tile
.getSector().getMaxLongitude());
513 Vec4 p
= dc
.getGlobe().computePointFromPosition(lat
, lon
, 0d
);
514 double distSquared
= dc
.getView().getEyePoint().distanceToSquared3(p
);
515 //noinspection RedundantIfStatement
516 if (minDistanceSquared
> distSquared
|| maxDistanceSquared
< distSquared
)
522 private static boolean isNameVisible(DrawContext dc
, PlaceNameService service
, Position namePosition
)
524 double elevation
= dc
.getVerticalExaggeration() * namePosition
.getElevation();
525 Vec4 namePoint
= dc
.getGlobe().computePointFromPosition(namePosition
.getLatitude(),
526 namePosition
.getLongitude(), elevation
);
527 Vec4 eyeVec
= dc
.getView().getEyePoint();
529 double dist
= eyeVec
.distanceTo3(namePoint
);
530 return dist
>= service
.getMinDisplayDistance() && dist
<= service
.getMaxDisplayDistance();
533 private static Angle
clampAngle(Angle a
, Angle min
, Angle max
)
535 return a
.compareTo(min
) < 0 ? min
: (a
.compareTo(max
) > 0 ? max
: a
);
538 // ============== Image Reading and Downloading ======================= //
539 // ============== Image Reading and Downloading ======================= //
540 // ============== Image Reading and Downloading ======================= //
542 private static final int MAX_REQUESTS
= 64;
543 private final Queue
<Tile
> downloadQueue
= new LinkedBlockingQueue
<Tile
>(MAX_REQUESTS
);
544 private final Queue
<Tile
> readQueue
= new LinkedBlockingQueue
<Tile
>(MAX_REQUESTS
);
546 private static class RequestTask
implements Runnable
548 final PlaceNameLayer layer
;
551 RequestTask(PlaceNameLayer layer
, Tile tile
)
558 public boolean equals(Object o
)
562 if (o
== null || this.getClass() != o
.getClass())
565 final RequestTask other
= (RequestTask
) o
;
567 // Don't include layer in comparison so that requests are shared among layers
568 return !(this.tile
!= null ?
!this.tile
.equals(other
.tile
) : other
.tile
!= null);
572 public int hashCode()
574 return (this.tile
!= null ?
this.tile
.hashCode() : 0);
581 if (this.layer
.memoryCache
.getObject(this.tile
) != null)
584 final java
.net
.URL tileURL
= WorldWind
.getDataFileCache().findFile(tile
.getFileCachePath(), false);
587 if (this.layer
.loadTile(this.tile
, tileURL
))
589 tile
.getPlaceNameService().unmarkResourceAbsent(tile
.getPlaceNameService().getTileNumber(
592 this.layer
.firePropertyChange(AVKey
.LAYER
, null, this);
596 // Assume that something's wrong with the file and delete it.
597 WorldWind
.getDataFileCache().removeFile(tileURL
);
598 tile
.getPlaceNameService().markResourceAbsent(tile
.getPlaceNameService().getTileNumber(tile
.row
,
600 String message
= Logging
.getMessage("generic.DeletedCorruptDataFile", tileURL
);
601 Logging
.logger().fine(message
);
607 this.layer
.requestTile(this.layer
.downloadQueue
, this.tile
);
610 public String
toString()
612 return this.tile
.toString();
616 private static class DownloadPostProcessor
implements RetrievalPostProcessor
618 final PlaceNameLayer layer
;
621 private DownloadPostProcessor(PlaceNameLayer layer
, Tile tile
)
627 public java
.nio
.ByteBuffer
run(Retriever retriever
)
629 if (retriever
== null)
631 String msg
= Logging
.getMessage("nullValue.RetrieverIsNull");
632 Logging
.logger().fine(msg
);
633 throw new IllegalArgumentException(msg
);
636 if (!retriever
.getState().equals(Retriever
.RETRIEVER_STATE_SUCCESSFUL
))
639 if (!(retriever
instanceof URLRetriever
))
644 if (retriever
instanceof HTTPRetriever
)
646 HTTPRetriever httpRetriever
= (HTTPRetriever
) retriever
;
647 if (httpRetriever
.getResponseCode() == java
.net
.HttpURLConnection
.HTTP_NO_CONTENT
)
649 // Mark tile as missing to avoid further attempts
650 tile
.getPlaceNameService().markResourceAbsent(tile
.getPlaceNameService().getTileNumber(tile
.row
,
656 URLRetriever urlRetriever
= (URLRetriever
) retriever
;
657 java
.nio
.ByteBuffer buffer
= urlRetriever
.getBuffer();
661 final java
.io
.File cacheFile
= WorldWind
.getDataFileCache().newFile(this.tile
.getFileCachePath());
662 if (cacheFile
== null)
664 String msg
= Logging
.getMessage("generic.CantCreateCacheFile", this.tile
.getFileCachePath());
665 Logging
.logger().fine(msg
);
669 if (cacheFile
.exists())
670 return buffer
; // info is already here; don't need to do anything
674 WWIO
.saveBuffer(buffer
, cacheFile
);
675 this.layer
.firePropertyChange(AVKey
.LAYER
, null, this);
680 catch (java
.io
.IOException e
)
682 Logging
.logger().log(Level
.FINE
, Logging
.getMessage(
683 "layers.PlaceNameLayer.ExceptionSavingRetrievedFile", this.tile
.getFileCachePath()), e
);
690 private static class GMLPlaceNameSAXHandler
extends org
.xml
.sax
.helpers
.DefaultHandler
692 static final String GML_FEATURE_MEMBER
= "gml:featureMember";
693 static final String TOPP_FULL_NAME_ND
= "topp:full_name_nd";
694 static final String TOPP_LATITUDE
= "topp:latitude";
695 static final String TOPP_LONGITUDE
= "topp:longitude";
696 final LinkedList
<String
> internedQNameStack
= new LinkedList
<String
>();
697 boolean inBeginEndPair
= false;
698 StringBuilder latBuffer
= new StringBuilder();
699 StringBuilder lonBuffer
= new StringBuilder();
701 StringBuilder textArray
= new StringBuilder();
702 int[] textIndexArray
= new int[16];
703 double[] latlonArray
= new double[16];
706 GMLPlaceNameSAXHandler()
710 PlaceNameChunk
createPlaceNameChunk(PlaceNameService service
)
712 return new PlaceNameChunk(service
, this.textArray
, this.textIndexArray
, this.latlonArray
, this.numEntries
);
717 int textIndex
= this.textArray
.length();
718 this.textIndexArray
= append(this.textIndexArray
, this.numEntries
, textIndex
);
719 this.inBeginEndPair
= true;
724 double lat
= this.parseDouble(this.latBuffer
);
725 double lon
= this.parseDouble(this.lonBuffer
);
726 int numLatLon
= 2 * this.numEntries
;
727 this.latlonArray
= this.append(this.latlonArray
, numLatLon
, lat
);
729 this.latlonArray
= this.append(this.latlonArray
, numLatLon
, lon
);
731 this.latBuffer
.delete(0, this.latBuffer
.length());
732 this.lonBuffer
.delete(0, this.lonBuffer
.length());
733 this.inBeginEndPair
= false;
737 double parseDouble(StringBuilder sb
)
742 value
= Double
.parseDouble(sb
.toString());
744 catch (NumberFormatException e
)
746 Logging
.logger().log(Level
.FINE
,
747 Logging
.getMessage("layers.PlaceNameLayer.ExceptionAttemptingToReadFile", ""), e
);
752 int[] append(int[] array
, int index
, int value
)
754 if (index
>= array
.length
)
755 array
= this.resizeArray(array
);
756 array
[index
] = value
;
760 int[] resizeArray(int[] oldArray
)
762 int newSize
= 2 * oldArray
.length
;
763 int[] newArray
= new int[newSize
];
764 System
.arraycopy(oldArray
, 0, newArray
, 0, oldArray
.length
);
768 double[] append(double[] array
, int index
, double value
)
770 if (index
>= array
.length
)
771 array
= this.resizeArray(array
);
772 array
[index
] = value
;
776 double[] resizeArray(double[] oldArray
)
778 int newSize
= 2 * oldArray
.length
;
779 double[] newArray
= new double[newSize
];
780 System
.arraycopy(oldArray
, 0, newArray
, 0, oldArray
.length
);
784 public void characters(char ch
[], int start
, int length
)
786 if (!this.inBeginEndPair
)
789 // Top of QName stack is an interned string,
790 // so we can use pointer comparison.
791 String internedTopQName
= this.internedQNameStack
.getFirst();
793 StringBuilder sb
= null;
794 if (TOPP_LATITUDE
== internedTopQName
)
796 else if (TOPP_LONGITUDE
== internedTopQName
)
798 else if (TOPP_FULL_NAME_ND
== internedTopQName
)
802 sb
.append(ch
, start
, length
);
805 public void startElement(String uri
, String localName
, String qName
, org
.xml
.sax
.Attributes attributes
)
807 // Don't validate uri, localName or attributes because they aren't used.
808 // Intern the qName string so we can use pointer comparison.
809 String internedQName
= qName
.intern();
810 if (GML_FEATURE_MEMBER
== internedQName
)
812 this.internedQNameStack
.addFirst(internedQName
);
815 public void endElement(String uri
, String localName
, String qName
)
817 // Don't validate uri or localName because they aren't used.
818 // Intern the qName string so we can use pointer comparison.
819 String internedQName
= qName
.intern();
820 if (GML_FEATURE_MEMBER
== internedQName
)
822 this.internedQNameStack
.removeFirst();
826 private boolean loadTile(Tile tile
, java
.net
.URL url
)
828 PlaceNameChunk placeNameChunk
= readTile(tile
, url
);
829 if (placeNameChunk
== null)
832 this.memoryCache
.add(tile
, placeNameChunk
);
836 private static PlaceNameChunk
readTile(Tile tile
, java
.net
.URL url
)
838 java
.io
.InputStream is
= null;
842 String path
= url
.getFile();
843 path
= path
.replaceAll("%20", " "); // TODO: find a better way to get a path usable by FileInputStream
845 java
.io
.FileInputStream fis
= new java
.io
.FileInputStream(path
);
846 java
.io
.BufferedInputStream buf
= new java
.io
.BufferedInputStream(fis
);
847 is
= new java
.util
.zip
.GZIPInputStream(buf
);
849 GMLPlaceNameSAXHandler handler
= new GMLPlaceNameSAXHandler();
850 javax
.xml
.parsers
.SAXParserFactory
.newInstance().newSAXParser().parse(is
, handler
);
851 return handler
.createPlaceNameChunk(tile
.getPlaceNameService());
855 Logging
.logger().log(Level
.FINE
,
856 Logging
.getMessage("layers.PlaceNameLayer.ExceptionAttemptingToReadFile", url
.toString()), e
);
865 catch (java
.io
.IOException e
)
867 Logging
.logger().log(Level
.FINE
,
868 Logging
.getMessage("layers.PlaceNameLayer.ExceptionAttemptingToReadFile", url
.toString()), e
);
875 private void requestTile(Queue
<Tile
> queue
, Tile tile
)
877 if (tile
.getPlaceNameService().isResourceAbsent(tile
.getPlaceNameService().getTileNumber(
878 tile
.row
, tile
.column
)))
880 if (!queue
.contains(tile
))
884 private void sendRequests()
887 // Send threaded read tasks.
888 while (!WorldWind
.getTaskService().isFull() && (tile
= this.readQueue
.poll()) != null)
890 WorldWind
.getTaskService().addTask(new RequestTask(this, tile
));
892 // Send retriever tasks.
893 while (!WorldWind
.getRetrievalService().isFull() && (tile
= this.downloadQueue
.poll()) != null)
898 url
= tile
.getRequestURL();
900 catch (java
.net
.MalformedURLException e
)
902 String message
= Logging
.getMessage("layers.PlaceNameLayer.ExceptionAttemptingToDownloadFile", tile
);
903 Logging
.logger().log(Level
.FINE
, message
, e
);
906 WorldWind
.getRetrievalService().runRetriever(new HTTPRetriever(url
, new DownloadPostProcessor(this, tile
)));