Class CachedRendererJFX
- All Implemented Interfaces:
GTRendererJFX
Canvas
using the JavaFX GraphicsContext API, with a built-in caching layer
to reduce display latency during pan and zoom interactions.
Rendering pipeline
Iterates over the MapContent layers and handles each type:
FeatureLayer— vector layers with SLD-based symbolization (polygon, line, point symbolizers); geometries are converted to JavaFX path commands via JTSCoordinateSequencetraversal.FXTiledWMSLayer— preferred WMS fast path: for WMS-R endpoints (tile-cached WMS), the buffer envelope is split into PM-grid-aligned tiles and oneGetMapis issued per tile. Server returns cached bytes per tile; responses load in parallel via JavaFX asyncImage; the URL cache is shared with WMTS tiles. RequiresEPSG:3857; falls back to the single-request path otherwise.WMSLayer— raster layers fetched from a WMS server via aGetMaprequest; the response image is loaded asynchronously and drawn onto the canvas when available.FXWMTSMapLayer— preferred WMTS fast path: each tile is fetched independently via JavaFX asyncImageloading (parallel HTTP) and drawn on arrival; per-tile URL cache (seewmsImageCache) makes repeated pans hit memory only.WMTSMapLayer— fallback WMTS path for stock layers that don't expose their server: theGridCoverage2DReaderis read on a background thread (sequential tile fetch inside the reader) and the resulting image is drawn when available.
Overpaint buffer
Each render request paints a larger world area than strictly needed
(controlled by OVERPAINT_FACTOR): the rendered region extends
0.5×width and 0.5×height
beyond the visible envelope on every side. A WritableImage snapshot
of this buffer is retained after each render.
Subsequent paint(org.geotools.map.MapContent, double, double, org.geotools.geometry.jts.ReferencedEnvelope) calls whose target area falls entirely within
the buffered region are served instantly by cropping and scaling the
snapshot. A buffer refresh is only triggered when the view has consumed
more than half of the overpaint margin in any direction (see
needsBufferRefresh(org.geotools.geometry.jts.ReferencedEnvelope)).
Tile cache (two tiers)
WMS GetMap and WMTS GetTile responses are cached by
request URL across two layers:
- Memory — access-order LRU map whose budget is expressed in
decoded bytes (see
DEFAULT_WMS_CACHE_BYTESandCachedRendererJFX(long)). Byte-sized budgeting keeps real memory use predictable regardless of tile content density (ocean vs. urban PNGs decompress to the same RGBA size). Synchronous hits. - Disk — persistent PNG store under
DEFAULT_PERSISTENT_CACHE_DIR(overridable via thePERSISTENT_CACHE_DIR_PROPERTYsystem property). Active by default; toggle viasetPersistentCacheActive(boolean)or globally viaPERSISTENT_CACHE_PROPERTY. A memory miss probes the filesystem before going to the network, so the second launch of an application opens with previously-rendered tiles already available.
Thread model
paint(org.geotools.map.MapContent, double, double, org.geotools.geometry.jts.ReferencedEnvelope) must be called on the JavaFX application thread.
stopRendering() may be called from any thread.
Usage
CachedRendererJFX renderer = new CachedRendererJFX();
pane.getChildren().add(renderer.getCanvas());
renderer.paint(mapContent, 800, 600, envelope);
// call renderer.dispose() when the pane is discarded
- Author:
- Julien SEINTURIER - Université de Toulon / CNRS LIS umr 7020
-
Field Summary
FieldsModifier and TypeFieldDescriptionstatic final PathDefault location of the persistent (disk) tile cache:<java.io.tmpdir>/.geotools/cache.static final longDefault decoded-byte budget for the WMS/WMTS tile image cache: 128 MB, which holds ~500 PM tiles at 256×256 RGBA once decoded.static final intDeprecated.Dimensioning in entry count drifts with tile content density.static final doubleFraction of the view width/height added on each side when rendering the overpaint buffer. 0.5 means the buffer covers 2× the visible width and 2× the visible height, giving a full "screen" of margin in every direction before a re-render is needed.static final StringName of the system property that overrides the persistent cache directory.static final StringName of the system property that controls whether the persistent disk cache is enabled by default in newly-constructed renderers. -
Constructor Summary
ConstructorsConstructorDescriptionCreates a renderer using the default 134217728L-byte tile cache.CachedRendererJFX(int wmsCacheSize) Deprecated.Dimensioning in entry count makes real memory use unpredictable.CachedRendererJFX(long wmsCacheBytes) Creates a renderer with a custom tile cache byte budget. -
Method Summary
Modifier and TypeMethodDescriptionvoidRemoves every file undergetPersistentCacheDirectory()asynchronously, so the FX thread is never blocked on disk I/O.voidClears the WMS image URL cache.voiddispose()Releases resources held by this renderer.doubleGet the rolling average wall-clock load time across all successfully-completed async image loads, in milliseconds.longGet the number of completed buffer refresh cycles since construction (or last reset).longGet the current cumulative decoded footprint of the tile cache, in bytes.doubleGet the fraction of user-visible cache lookups served from cache, in[0.0, 1.0].longGet the number of tile cache lookups that returned a ready image (user-visible render paths only — prefetch and adjacent-level placeholder lookups are excluded to keep the metric reflective of actual render latency).longGet the configured maximum cumulative decoded footprint of the tile cache, in bytes.longGet the number of tile cache lookups that missed and triggered an async fetch.javafx.scene.canvas.CanvasReturns the displayCanvas.Get the filesystem directory where persistent cache entries are stored.intGet the current number of async image loads in flight (includes both main-render and prefetch loads).voidDiscards the overpaint buffer, forcing a full re-render on the nextpaint(org.geotools.map.MapContent, double, double, org.geotools.geometry.jts.ReferencedEnvelope)call.booleanGet whether the persistent disk cache is currently active.voidpaint(org.geotools.map.MapContent content, double w, double h, org.geotools.geometry.jts.ReferencedEnvelope area) Renders the map content onto the display canvas at the given size and world envelope.Returns a one-line human-readable summary of all perf counters, suitable for logging, a status-bar overlay, or ad-hoc debugging.voidResets all performance counters to zero.voidsetPersistentCacheActive(boolean active) Enables or disables the persistent (on-disk) tile cache.voidOverrides the persistent cache directory for this renderer.voidSignals the current render to stop after the current feature.
-
Field Details
-
OVERPAINT_FACTOR
public static final double OVERPAINT_FACTORFraction of the view width/height added on each side when rendering the overpaint buffer. 0.5 means the buffer covers 2× the visible width and 2× the visible height, giving a full "screen" of margin in every direction before a re-render is needed.- See Also:
-
DEFAULT_WMS_CACHE_BYTES
public static final long DEFAULT_WMS_CACHE_BYTESDefault decoded-byte budget for the WMS/WMTS tile image cache: 128 MB, which holds ~500 PM tiles at 256×256 RGBA once decoded. Generous enough to cover the current view, its overpaint margin, and several zoom levels worth of prefetched (prefetchTimer) neighbors without evicting still-relevant entries.Dimensioning in bytes rather than entry count prevents the cache's real memory footprint from drifting with tile content density. A PNG of an urban tile decodes to the same 256 KB in RGBA as an ocean tile, even though their compressed sizes differ wildly.
- See Also:
-
DEFAULT_WMS_CACHE_SIZE
Deprecated.Dimensioning in entry count drifts with tile content density. PreferDEFAULT_WMS_CACHE_BYTESand the byte-budget constructorCachedRendererJFX(long).Number of WMS response images kept in the LRU URL cache.- See Also:
-
DEFAULT_PERSISTENT_CACHE_DIR
Default location of the persistent (disk) tile cache:<java.io.tmpdir>/.geotools/cache. Survives JVM restarts so the second launch of an application finds previously-fetched tiles already available. Cleared viaclearPersistentCache(). -
PERSISTENT_CACHE_PROPERTY
Name of the system property that controls whether the persistent disk cache is enabled by default in newly-constructed renderers.-Dorg.geotools.renderer.cached.persistant=true— enable (same as default).-Dorg.geotools.renderer.cached.persistant=false— disable globally.- property not set — enabled (default behavior).
setPersistentCacheActive(boolean)take precedence afterward.- See Also:
-
PERSISTENT_CACHE_DIR_PROPERTY
Name of the system property that overrides the persistent cache directory. When set to a usable filesystem path (existing directory or a path that can be created), the renderer stores its disk cache there instead ofDEFAULT_PERSISTENT_CACHE_DIR. When unset, blank, pointing at a non-directory, or otherwise unusable, the default applies and a warning is logged.Read once per renderer at construction time.
- See Also:
-
-
Constructor Details
-
CachedRendererJFX
public CachedRendererJFX()Creates a renderer using the default 134217728L-byte tile cache. -
CachedRendererJFX
public CachedRendererJFX(long wmsCacheBytes) Creates a renderer with a custom tile cache byte budget.- Parameters:
wmsCacheBytes- maximum cumulative decoded size of cached tile images, in bytes; pass 0 to disable caching. Typical values range from 32 MB (very light use) to 512 MB (heavy pan/zoom sessions).
-
CachedRendererJFX
Deprecated.Dimensioning in entry count makes real memory use unpredictable. PreferCachedRendererJFX(long).Creates a renderer with an entry-count cache budget.- Parameters:
wmsCacheSize- maximum number of WMS response images to keep in the LRU cache; pass 0 to disable caching. Translated internally to a byte budget viaESTIMATED_TILE_BYTES.
-
-
Method Details
-
getCanvas
public javafx.scene.canvas.Canvas getCanvas()Returns the displayCanvas. Add it to the JavaFX scene graph to show the rendered map.- Specified by:
getCanvasin interfaceGTRendererJFX- Returns:
- the display canvas
-
paint
public void paint(org.geotools.map.MapContent content, double w, double h, org.geotools.geometry.jts.ReferencedEnvelope area) Renders the map content onto the display canvas at the given size and world envelope.- If the requested area is fully covered by the overpaint buffer, the display is updated immediately from the cached snapshot (zero latency — no WMS request, no vector pass). A buffer refresh is only scheduled when the view has consumed more than half the overpaint margin in any direction.
- On a buffer miss, a full buffer render is performed synchronously for vector layers, then the display is updated from the fresh buffer.
Must be called on the JavaFX application thread.
- Specified by:
paintin interfaceGTRendererJFX- Parameters:
content- the map content to renderw- target width in pixelsh- target height in pixelsarea- the world-coordinate envelope to display
-
stopRendering
public void stopRendering()Signals the current render to stop after the current feature. Safe to call from any thread.- Specified by:
stopRenderingin interfaceGTRendererJFX
-
invalidateBuffer
public void invalidateBuffer()Discards the overpaint buffer, forcing a full re-render on the nextpaint(org.geotools.map.MapContent, double, double, org.geotools.geometry.jts.ReferencedEnvelope)call. Call this when the map content changes in a way that makes the buffer invalid (layer added / removed, style change, etc.). -
clearWmsCache
public void clearWmsCache()Clears the WMS image URL cache. Subsequent WMS requests will fetch fresh images from the server. No-op if WMS caching was disabled at construction time. -
setPersistentCacheActive
public void setPersistentCacheActive(boolean active) Enables or disables the persistent (on-disk) tile cache. When enabled, every successful HTTP tile fetch is also written toDEFAULT_PERSISTENT_CACHE_DIRas a PNG, and memory-cache misses probe the disk before issuing an HTTP request — so the second launch of the application finds previously-rendered tiles instantly.The renderer's initial state is governed by the system property
PERSISTENT_CACHE_PROPERTY; this setter overrides that default for the lifetime of this instance.Disabling does not delete existing files on disk; for that, call
clearPersistentCache(). In-flight async loads are unaffected.- Parameters:
active-trueif the persistent caching has to be activated andfalseotherwise
-
isPersistentCacheActive
public boolean isPersistentCacheActive()Get whether the persistent disk cache is currently active.- Returns:
trueif the persistent cache is active andfalseotherwise
-
getPersistentCacheDirectory
Get the filesystem directory where persistent cache entries are stored.- Returns:
- the persistent cache directory
-
setPersistentCacheDirectory
Overrides the persistent cache directory for this renderer. Subsequent disk reads and writes targetdirinstead of the previous location; pre-existing files at the old directory are not migrated and remain accessible only after another override orclearPersistentCache()on the old path.The directory itself is not created here — that happens lazily on the first write so this setter is filesystem-side-effect free.
- Parameters:
dir- the new cache directory; must not benull- Throws:
IllegalArgumentException- ifdirisnullor points at an existing entry that is not a directory
-
clearPersistentCache
public void clearPersistentCache()Removes every file undergetPersistentCacheDirectory()asynchronously, so the FX thread is never blocked on disk I/O. The directory itself is preserved. No-op if the directory doesn't exist. -
getCacheHits
public long getCacheHits()Get the number of tile cache lookups that returned a ready image (user-visible render paths only — prefetch and adjacent-level placeholder lookups are excluded to keep the metric reflective of actual render latency).- Returns:
- the number of tile cache lookups
-
getCacheMisses
public long getCacheMisses()Get the number of tile cache lookups that missed and triggered an async fetch.- Returns:
- the number of tile cache lookups that missed
-
getCacheHitRate
public double getCacheHitRate()Get the fraction of user-visible cache lookups served from cache, in[0.0, 1.0]. Returns0.0before the first lookup. A steady-state value above ~0.7 indicates the cache is well-sized and the prefetch / placeholder optimizations are pulling their weight.- Returns:
- The fraction of user-visible cache lookups served from cache
-
getBufferRefreshCount
public long getBufferRefreshCount()Get the number of completed buffer refresh cycles since construction (or last reset).- Returns:
- The number of completed buffer refresh cycles since construction
-
getTilesInFlight
public int getTilesInFlight()Get the current number of async image loads in flight (includes both main-render and prefetch loads). Drops to 0 between renders when the network catches up; a persistently high value suggests the server is too slow or the prefetch cap is too aggressive.- Returns:
- the current number of async image loads in flight
-
getAverageTileLoadMs
public double getAverageTileLoadMs()Get the rolling average wall-clock load time across all successfully-completed async image loads, in milliseconds. Excludes canceled/errored/stale loads so it reflects the server's effective response time, not client churn. Returns0.0before the first successful load.- Returns:
- the rolling average wall-clock load time across all successfully-complete async image loads
-
getCacheBytes
public long getCacheBytes()Get the current cumulative decoded footprint of the tile cache, in bytes.- Returns:
- the current cumulative decoded footprint of the tile cache, in bytes
-
getCacheMaxBytes
public long getCacheMaxBytes()Get the configured maximum cumulative decoded footprint of the tile cache, in bytes.- Returns:
- the configured maximum cumulative decoded footprint of the tile cache, in bytes
-
resetCounters
public void resetCounters()Resets all performance counters to zero. Useful for measuring a specific operation (e.g. "how many tiles and buffer refreshes did this zoom-out consume?") without the noise of prior activity. -
perfSummary
Returns a one-line human-readable summary of all perf counters, suitable for logging, a status-bar overlay, or ad-hoc debugging. Example output:hits=142 misses=18 hitRate=88.7% refreshes=9 inFlight=0 avgLoad=76.3ms cache=34.2/128.0MB
- Returns:
- a one-line human-readable summary of all perf counters
-
dispose
public void dispose()Releases resources held by this renderer. After calling this method the renderer must not be used.
-