@Override public void encodeGeometryColumn( GeometryDescriptor gatt, String prefix, int srid, Hints hints, StringBuffer sql) { boolean geography = "geography".equals(gatt.getUserData().get(JDBCDataStore.JDBC_NATIVE_TYPENAME)); if (geography) { sql.append("encode(ST_AsBinary("); encodeColumnName(prefix, gatt.getLocalName(), sql); sql.append("),'base64')"); } else { boolean force2D = hints != null && hints.containsKey(Hints.FEATURE_2D) && Boolean.TRUE.equals(hints.get(Hints.FEATURE_2D)); if (force2D) { sql.append("encode(ST_AsBinary(ST_Force_2D("); encodeColumnName(prefix, gatt.getLocalName(), sql); sql.append(")),'base64')"); } else { sql.append("encode(ST_AsEWKB("); encodeColumnName(prefix, gatt.getLocalName(), sql); sql.append("),'base64')"); } } }
static { // getting default hints final Hints defaultHints = GeoTools.getDefaultHints(); // check if someone asked us to use a specific precision model final Object o = defaultHints.get(Hints.JTS_PRECISION_MODEL); final PrecisionModel pm; if (o != null) pm = (PrecisionModel) o; else { pm = new PrecisionModel(); } GFACTORY = new GeometryFactory(pm, 0); // Register manually the GTCrop operation, in web containers JAI registration may fails GTCropDescriptor.register(); }
/** Constructs an authority factory using the specified hints and priority. */ protected FactoryUsingWKT(final Hints userHints, final int priority) { super(userHints, priority); factories = ReferencingFactoryContainer.instance(userHints); Object hint = null; if (userHints != null) { hint = userHints.get(Hints.CRS_AUTHORITY_EXTRA_DIRECTORY); } if (hint instanceof File) { directory = (File) hint; } else if (hint instanceof String) { directory = new File((String) hint); } else { directory = null; } hints.put(Hints.CRS_AUTHORITY_EXTRA_DIRECTORY, directory); // Disposes the cached property file after at least 15 minutes of inactivity. setTimeout(15 * 60 * 1000L); }
/** Hints constructor for FactoryRegistry */ public JTSComplexFactory(Hints hints) { this((CoordinateReferenceSystem) hints.get(Hints.CRS)); }
/** * Load a specified a raster as a portion of the granule describe by this {@link * GranuleDescriptor}. * * @param imageReadParameters the {@link ImageReadParam} to use for reading. * @param index the index to use for the {@link ImageReader}. * @param cropBBox the bbox to use for cropping. * @param mosaicWorldToGrid the cropping grid to world transform. * @param request the incoming request to satisfy. * @param hints {@link Hints} to be used for creating this raster. * @return a specified a raster as a portion of the granule describe by this {@link * GranuleDescriptor}. * @throws IOException in case an error occurs. */ public GranuleLoadingResult loadRaster( final ImageReadParam imageReadParameters, final int index, final ReferencedEnvelope cropBBox, final MathTransform2D mosaicWorldToGrid, final RasterLayerRequest request, final Hints hints) throws IOException { if (LOGGER.isLoggable(java.util.logging.Level.FINER)) { final String name = Thread.currentThread().getName(); LOGGER.finer( "Thread:" + name + " Loading raster data for granuleDescriptor " + this.toString()); } ImageReadParam readParameters = null; int imageIndex; final ReferencedEnvelope bbox = inclusionGeometry != null ? new ReferencedEnvelope( granuleBBOX.intersection(inclusionGeometry.getEnvelopeInternal()), granuleBBOX.getCoordinateReferenceSystem()) : granuleBBOX; boolean doFiltering = false; if (filterMe) { doFiltering = Utils.areaIsDifferent(inclusionGeometry, baseGridToWorld, granuleBBOX); } // intersection of this tile bound with the current crop bbox final ReferencedEnvelope intersection = new ReferencedEnvelope( bbox.intersection(cropBBox), cropBBox.getCoordinateReferenceSystem()); if (intersection.isEmpty()) { if (LOGGER.isLoggable(java.util.logging.Level.FINE)) { LOGGER.fine( new StringBuilder("Got empty intersection for granule ") .append(this.toString()) .append(" with request ") .append(request.toString()) .append(" Resulting in no granule loaded: Empty result") .toString()); } return null; } ImageInputStream inStream = null; ImageReader reader = null; try { // // get info about the raster we have to read // // get a stream assert cachedStreamSPI != null : "no cachedStreamSPI available!"; inStream = cachedStreamSPI.createInputStreamInstance( granuleUrl, ImageIO.getUseCache(), ImageIO.getCacheDirectory()); if (inStream == null) return null; // get a reader and try to cache the relevant SPI if (cachedReaderSPI == null) { reader = ImageIOExt.getImageioReader(inStream); if (reader != null) cachedReaderSPI = reader.getOriginatingProvider(); } else reader = cachedReaderSPI.createReaderInstance(); if (reader == null) { if (LOGGER.isLoggable(java.util.logging.Level.WARNING)) { LOGGER.warning( new StringBuilder("Unable to get s reader for granuleDescriptor ") .append(this.toString()) .append(" with request ") .append(request.toString()) .append(" Resulting in no granule loaded: Empty result") .toString()); } return null; } // set input reader.setInput(inStream); // Checking for heterogeneous granules if (request.isHeterogeneousGranules()) { // create read parameters readParameters = new ImageReadParam(); // override the overviews controller for the base layer imageIndex = ReadParamsController.setReadParams( request.getRequestedResolution(), request.getOverviewPolicy(), request.getDecimationPolicy(), readParameters, request.rasterManager, overviewsController); } else { imageIndex = index; readParameters = imageReadParameters; } // get selected level and base level dimensions final GranuleOverviewLevelDescriptor selectedlevel = getLevel(imageIndex, reader); // now create the crop grid to world which can be used to decide // which source area we need to crop in the selected level taking // into account the scale factors imposed by the selection of this // level together with the base level grid to world transformation AffineTransform2D cropWorldToGrid = new AffineTransform2D(selectedlevel.gridToWorldTransformCorner); cropWorldToGrid = (AffineTransform2D) cropWorldToGrid.inverse(); // computing the crop source area which lives into the // selected level raster space, NOTICE that at the end we need to // take into account the fact that we might also decimate therefore // we cannot just use the crop grid to world but we need to correct // it. final Rectangle sourceArea = CRS.transform(cropWorldToGrid, intersection).toRectangle2D().getBounds(); // gutter if (selectedlevel.baseToLevelTransform.isIdentity()) sourceArea.grow(2, 2); XRectangle2D.intersect( sourceArea, selectedlevel.rasterDimensions, sourceArea); // make sure roundings don't bother us // is it empty?? if (sourceArea.isEmpty()) { if (LOGGER.isLoggable(java.util.logging.Level.FINE)) { LOGGER.fine( "Got empty area for granuleDescriptor " + this.toString() + " with request " + request.toString() + " Resulting in no granule loaded: Empty result"); } return null; } else if (LOGGER.isLoggable(java.util.logging.Level.FINER)) { LOGGER.finer( "Loading level " + imageIndex + " with source region: " + sourceArea + " subsampling: " + readParameters.getSourceXSubsampling() + "," + readParameters.getSourceYSubsampling() + " for granule:" + granuleUrl); } // Setting subsampling int newSubSamplingFactor = 0; final String pluginName = cachedReaderSPI.getPluginClassName(); if (pluginName != null && pluginName.equals(ImageUtilities.DIRECT_KAKADU_PLUGIN)) { final int ssx = readParameters.getSourceXSubsampling(); final int ssy = readParameters.getSourceYSubsampling(); newSubSamplingFactor = ImageIOUtilities.getSubSamplingFactor2(ssx, ssy); if (newSubSamplingFactor != 0) { if (newSubSamplingFactor > maxDecimationFactor && maxDecimationFactor != -1) { newSubSamplingFactor = maxDecimationFactor; } readParameters.setSourceSubsampling(newSubSamplingFactor, newSubSamplingFactor, 0, 0); } } // set the source region readParameters.setSourceRegion(sourceArea); final RenderedImage raster; try { // read raster = request .getReadType() .read( readParameters, imageIndex, granuleUrl, selectedlevel.rasterDimensions, reader, hints, false); } catch (Throwable e) { if (LOGGER.isLoggable(java.util.logging.Level.FINE)) { LOGGER.log( java.util.logging.Level.FINE, "Unable to load raster for granuleDescriptor " + this.toString() + " with request " + request.toString() + " Resulting in no granule loaded: Empty result", e); } return null; } // use fixed source area sourceArea.setRect(readParameters.getSourceRegion()); // // setting new coefficients to define a new affineTransformation // to be applied to the grid to world transformation // ----------------------------------------------------------------------------------- // // With respect to the original envelope, the obtained planarImage // needs to be rescaled. The scaling factors are computed as the // ratio between the cropped source region sizes and the read // image sizes. // // place it in the mosaic using the coords created above; double decimationScaleX = ((1.0 * sourceArea.width) / raster.getWidth()); double decimationScaleY = ((1.0 * sourceArea.height) / raster.getHeight()); final AffineTransform decimationScaleTranform = XAffineTransform.getScaleInstance(decimationScaleX, decimationScaleY); // keep into account translation to work into the selected level raster space final AffineTransform afterDecimationTranslateTranform = XAffineTransform.getTranslateInstance(sourceArea.x, sourceArea.y); // now we need to go back to the base level raster space final AffineTransform backToBaseLevelScaleTransform = selectedlevel.baseToLevelTransform; // now create the overall transform final AffineTransform finalRaster2Model = new AffineTransform(baseGridToWorld); finalRaster2Model.concatenate(CoverageUtilities.CENTER_TO_CORNER); final double x = finalRaster2Model.getTranslateX(); final double y = finalRaster2Model.getTranslateY(); if (!XAffineTransform.isIdentity(backToBaseLevelScaleTransform, Utils.AFFINE_IDENTITY_EPS)) finalRaster2Model.concatenate(backToBaseLevelScaleTransform); if (!XAffineTransform.isIdentity(afterDecimationTranslateTranform, Utils.AFFINE_IDENTITY_EPS)) finalRaster2Model.concatenate(afterDecimationTranslateTranform); if (!XAffineTransform.isIdentity(decimationScaleTranform, Utils.AFFINE_IDENTITY_EPS)) finalRaster2Model.concatenate(decimationScaleTranform); // keep into account translation factors to place this tile finalRaster2Model.preConcatenate((AffineTransform) mosaicWorldToGrid); final Interpolation interpolation = request.getInterpolation(); // paranoiac check to avoid that JAI freaks out when computing its internal layouT on images // that are too small Rectangle2D finalLayout = ImageUtilities.layoutHelper( raster, (float) finalRaster2Model.getScaleX(), (float) finalRaster2Model.getScaleY(), (float) finalRaster2Model.getTranslateX(), (float) finalRaster2Model.getTranslateY(), interpolation); if (finalLayout.isEmpty()) { if (LOGGER.isLoggable(java.util.logging.Level.INFO)) LOGGER.info( "Unable to create a granuleDescriptor " + this.toString() + " due to jai scale bug creating a null source area"); return null; } ROI granuleLoadingShape = null; if (granuleROIShape != null) { final Point2D translate = mosaicWorldToGrid.transform(new DirectPosition2D(x, y), (Point2D) null); AffineTransform tx2 = new AffineTransform(); tx2.preConcatenate( AffineTransform.getScaleInstance( ((AffineTransform) mosaicWorldToGrid).getScaleX(), -((AffineTransform) mosaicWorldToGrid).getScaleY())); tx2.preConcatenate( AffineTransform.getScaleInstance( ((AffineTransform) baseGridToWorld).getScaleX(), -((AffineTransform) baseGridToWorld).getScaleY())); tx2.preConcatenate( AffineTransform.getTranslateInstance(translate.getX(), translate.getY())); granuleLoadingShape = (ROI) granuleROIShape.transform(tx2); } // apply the affine transform conserving indexed color model final RenderingHints localHints = new RenderingHints( JAI.KEY_REPLACE_INDEX_COLOR_MODEL, interpolation instanceof InterpolationNearest ? Boolean.FALSE : Boolean.TRUE); if (XAffineTransform.isIdentity(finalRaster2Model, Utils.AFFINE_IDENTITY_EPS)) { return new GranuleLoadingResult(raster, granuleLoadingShape, granuleUrl, doFiltering); } else { // // In case we are asked to use certain tile dimensions we tile // also at this stage in case the read type is Direct since // buffered images comes up untiled and this can affect the // performances of the subsequent affine operation. // final Dimension tileDimensions = request.getTileDimensions(); if (tileDimensions != null && request.getReadType().equals(ReadType.DIRECT_READ)) { final ImageLayout layout = new ImageLayout(); layout.setTileHeight(tileDimensions.width).setTileWidth(tileDimensions.height); localHints.add(new RenderingHints(JAI.KEY_IMAGE_LAYOUT, layout)); } else { if (hints != null && hints.containsKey(JAI.KEY_IMAGE_LAYOUT)) { final Object layout = hints.get(JAI.KEY_IMAGE_LAYOUT); if (layout != null && layout instanceof ImageLayout) { localHints.add( new RenderingHints(JAI.KEY_IMAGE_LAYOUT, ((ImageLayout) layout).clone())); } } } if (hints != null && hints.containsKey(JAI.KEY_TILE_CACHE)) { final Object cache = hints.get(JAI.KEY_TILE_CACHE); if (cache != null && cache instanceof TileCache) localHints.add(new RenderingHints(JAI.KEY_TILE_CACHE, (TileCache) cache)); } if (hints != null && hints.containsKey(JAI.KEY_TILE_SCHEDULER)) { final Object scheduler = hints.get(JAI.KEY_TILE_SCHEDULER); if (scheduler != null && scheduler instanceof TileScheduler) localHints.add(new RenderingHints(JAI.KEY_TILE_SCHEDULER, (TileScheduler) scheduler)); } boolean addBorderExtender = true; if (hints != null && hints.containsKey(JAI.KEY_BORDER_EXTENDER)) { final Object extender = hints.get(JAI.KEY_BORDER_EXTENDER); if (extender != null && extender instanceof BorderExtender) { localHints.add(new RenderingHints(JAI.KEY_BORDER_EXTENDER, (BorderExtender) extender)); addBorderExtender = false; } } // border extender if (addBorderExtender) { localHints.add(ImageUtilities.BORDER_EXTENDER_HINTS); } // boolean hasScaleX=!(Math.abs(finalRaster2Model.getScaleX()-1) < // 1E-2/(raster.getWidth()+1-raster.getMinX())); // boolean hasScaleY=!(Math.abs(finalRaster2Model.getScaleY()-1) < // 1E-2/(raster.getHeight()+1-raster.getMinY())); // boolean hasShearX=!(finalRaster2Model.getShearX() == 0.0); // boolean hasShearY=!(finalRaster2Model.getShearY() == 0.0); // boolean hasTranslateX=!(Math.abs(finalRaster2Model.getTranslateX()) < // 0.01F); // boolean hasTranslateY=!(Math.abs(finalRaster2Model.getTranslateY()) < // 0.01F); // boolean isTranslateXInt=!(Math.abs(finalRaster2Model.getTranslateX() - // (int) finalRaster2Model.getTranslateX()) < 0.01F); // boolean isTranslateYInt=!(Math.abs(finalRaster2Model.getTranslateY() - // (int) finalRaster2Model.getTranslateY()) < 0.01F); // // boolean isIdentity = finalRaster2Model.isIdentity() && // !hasScaleX&&!hasScaleY &&!hasTranslateX&&!hasTranslateY; // // TODO how can we check that the a skew is harmelss???? // if(isIdentity){ // // TODO check if we are missing anything like tiling or such that // comes from hints // return new GranuleLoadingResult(raster, granuleLoadingShape, // granuleUrl, doFiltering); // } // // // TOLERANCE ON PIXELS SIZE // // // Check and see if the affine transform is in fact doing // // a Translate operation. That is a scale by 1 and no rotation. // // In which case call translate. Note that only integer translate // // is applicable. For non-integer translate we'll have to do the // // affine. // // If the hints contain an ImageLayout hint, we can't use // // TranslateIntOpImage since it isn't capable of dealing with that. // // Get ImageLayout from renderHints if any. // ImageLayout layout = RIFUtil.getImageLayoutHint(localHints); // if ( !hasScaleX && // !hasScaleY && // !hasShearX&& // !hasShearY&& // isTranslateXInt&& // isTranslateYInt&& // layout == null) { // // It's a integer translate // return new GranuleLoadingResult(new TranslateIntOpImage(raster, // localHints, // (int) finalRaster2Model.getShearX(), // (int) // finalRaster2Model.getShearY()),granuleLoadingShape, granuleUrl, doFiltering); // } ImageWorker iw = new ImageWorker(raster); iw.setRenderingHints(localHints); iw.affine(finalRaster2Model, interpolation, request.getBackgroundValues()); return new GranuleLoadingResult( iw.getRenderedImage(), granuleLoadingShape, granuleUrl, doFiltering); } } catch (IllegalStateException e) { if (LOGGER.isLoggable(java.util.logging.Level.WARNING)) { LOGGER.log( java.util.logging.Level.WARNING, new StringBuilder("Unable to load raster for granuleDescriptor ") .append(this.toString()) .append(" with request ") .append(request.toString()) .append(" Resulting in no granule loaded: Empty result") .toString(), e); } return null; } catch (org.opengis.referencing.operation.NoninvertibleTransformException e) { if (LOGGER.isLoggable(java.util.logging.Level.WARNING)) { LOGGER.log( java.util.logging.Level.WARNING, new StringBuilder("Unable to load raster for granuleDescriptor ") .append(this.toString()) .append(" with request ") .append(request.toString()) .append(" Resulting in no granule loaded: Empty result") .toString(), e); } return null; } catch (TransformException e) { if (LOGGER.isLoggable(java.util.logging.Level.WARNING)) { LOGGER.log( java.util.logging.Level.WARNING, new StringBuilder("Unable to load raster for granuleDescriptor ") .append(this.toString()) .append(" with request ") .append(request.toString()) .append(" Resulting in no granule loaded: Empty result") .toString(), e); } return null; } finally { try { if (request.getReadType() != ReadType.JAI_IMAGEREAD && inStream != null) { inStream.close(); } } finally { if (request.getReadType() != ReadType.JAI_IMAGEREAD && reader != null) { reader.dispose(); } } } }
public AbstractMappingFeatureIterator( AppSchemaDataAccess store, FeatureTypeMapping mapping, Query query, Query unrolledQuery, boolean removeQueryLimitIfDenormalised, boolean hasPostFilter) throws IOException { this.store = store; this.attf = new AppSchemaFeatureFactoryImpl(); this.mapping = mapping; // validate and initialise resolve options Hints hints = query.getHints(); ResolveValueType resolveVal = (ResolveValueType) hints.get(Hints.RESOLVE); boolean resolve = ResolveValueType.ALL.equals(resolveVal) || ResolveValueType.LOCAL.equals(resolveVal); if (!resolve && resolveVal != null && !ResolveValueType.NONE.equals(resolveVal)) { throw new IllegalArgumentException( "Resolve:" + resolveVal.getName() + " is not supported in app-schema!"); } Integer atd = (Integer) hints.get(Hints.ASSOCIATION_TRAVERSAL_DEPTH); resolveDepth = resolve ? atd == null ? 0 : atd : 0; resolveTimeOut = (Integer) hints.get(Hints.RESOLVE_TIMEOUT); namespaces = mapping.getNamespaces(); namespaceAwareFilterFactory = new FilterFactoryImplNamespaceAware(namespaces); Object includeProps = query.getHints().get(Query.INCLUDE_MANDATORY_PROPS); includeMandatory = includeProps instanceof Boolean && ((Boolean) includeProps).booleanValue(); if (mapping.isDenormalised()) { // we need to disable the max number of features retrieved so we can // sort them manually just in case the data is denormalised. Do this // by overriding the max features for this query just before executing // it. Note that the original maxFeatures value was copied to // this.requestMaxFeatures in the constructor and will be re-applied after // the rows have been returned if (removeQueryLimitIfDenormalised) { this.dataMaxFeatures = 1000000; if (hasPostFilter) { // true max features will be handled in PostFilteringMappingFeatureIterator this.requestMaxFeatures = 1000000; } else { this.requestMaxFeatures = query.getMaxFeatures(); } } else { this.dataMaxFeatures = query.getMaxFeatures(); this.requestMaxFeatures = query.getMaxFeatures(); } } else { this.requestMaxFeatures = query.getMaxFeatures(); this.dataMaxFeatures = query.getMaxFeatures(); } if (unrolledQuery == null) { unrolledQuery = getUnrolledQuery(query); if (query instanceof JoiningQuery && unrolledQuery instanceof JoiningQuery) { ((JoiningQuery) unrolledQuery).setRootMapping(((JoiningQuery) query).getRootMapping()); } } // NC - property names if (query != null && query.getProperties() != null) { setPropertyNames(query.getProperties()); } else { setPropertyNames(null); // we need the actual property names (not surrogates) to do // this... } xpathAttributeBuilder = new XPath(); xpathAttributeBuilder.setFeatureFactory(attf); initialiseSourceFeatures(mapping, unrolledQuery, query.getCoordinateSystemReproject()); xpathAttributeBuilder.setFilterFactory(namespaceAwareFilterFactory); }