EnvelopeSettings( CoordinateReferenceSystem crs ) { this.crs = crs; this.min = new double[crs.getDimension()]; this.max = new double[crs.getDimension()]; Arrays.fill( this.min, Double.NaN ); Arrays.fill( this.max, Double.NaN ); }
/** * Creates a PointValue, and enforces consistency between the CRS and coordinate dimensions. */ public static PointValue pointValue( CoordinateReferenceSystem crs, double... coordinate ) { if ( crs.getDimension() != coordinate.length ) { throw new IllegalArgumentException( format( "Cannot create point, CRS %s expects %d dimensions, but got coordinates %s", crs, crs.getDimension(), Arrays.toString( coordinate ) ) ); } return new PointValue( crs, coordinate ); }
@Override void initValueAsHighest( ValueGroup valueGroups ) { // These coordinates will generate the largest value on the spacial curve double[] limit = new double[crs.getDimension()]; Arrays.fill(limit, Double.NEGATIVE_INFINITY); limit[0] = Double.POSITIVE_INFINITY; writePoint( crs, limit ); }
@Override void initValueAsLowest( ValueGroup valueGroups ) { double[] limit = new double[crs.getDimension()]; Arrays.fill(limit, Double.NEGATIVE_INFINITY); writePoint( crs, limit ); }
@Override public void writePoint( CoordinateReferenceSystem crs, double[] coordinate ) { checkArgument( coordinate.length == crs.getDimension(), "Dimension for %s is %d, got %d", crs.getName(), crs.getDimension(), coordinate.length ); buf.putInt( crs.getCode() ); for ( int i = 0; i < crs.getDimension(); i++ ) { buf.putDouble( coordinate[i] ); } }
private static PointValue readPoint( ByteBuffer chunk, int offset ) { final int crsCode = chunk.getInt( offset ); offset += Integer.BYTES; final CoordinateReferenceSystem crs = CoordinateReferenceSystem.get( crsCode ); final double[] coordinate = new double[crs.getDimension()]; for ( int i = 0; i < coordinate.length; i++ ) { coordinate[i] = chunk.getDouble( offset ); offset += Double.BYTES; } return pointValue( crs, coordinate ); }
private static PointArray readPointArray( ByteBuffer bb, int offset ) { final int len = bb.getInt( offset ); offset += Integer.BYTES; final PointValue[] array = new PointValue[len]; for ( int i = 0; i < len; i++ ) { final PointValue point = readPoint( bb, offset ); array[i] = point; offset += Integer.BYTES + point.getCoordinateReferenceSystem().getDimension() * Double.BYTES; } return pointArray( array ); }
@Override public double distance( PointValue p1, PointValue p2 ) { assert p1.getCoordinateReferenceSystem().getDimension() == dimension; assert p2.getCoordinateReferenceSystem().getDimension() == dimension; return pythagoras( p1.coordinate(), p2.coordinate() ); }
if ( index >= crs.getDimension() ) throw new IllegalArgumentException( "Invalid spatial coordinate key for " + crs.getDimension() + "D: " + fields[1] );
@Override public List<ConfigOptions> getConfigOptions() { ArrayList<ConfigOptions> crsSettings = (ArrayList<ConfigOptions>) LoadableConfig.super.getConfigOptions(); for ( CoordinateReferenceSystem crs : CoordinateReferenceSystem.all() ) { for ( int dim = 0; dim < crs.getDimension(); dim++ ) { for ( String rangeName : new String[]{"minimum", "maximum"} ) { String descriptionHeader = String.format( "The %s %s value for the index extents for %dD %s spatial index", rangeName, COORDS[dim], crs.getDimension(), crs.getName().replace( "_3D", "" ) ); String descriptionBody = "The 2D to 1D mapping function divides all 2D space into discrete tiles, and orders these using a space filling curve designed " + "to optimize the requirement that tiles that are close together in this ordered list are also close together in 2D space. " + "This requires that the extents of the 2D space be known in advance and never changed. If you do change these settings, you " + "need to recreate any affected index in order for the settings to apply, otherwise the index will retain the previous settings."; Setting<Double> setting = makeCRSRangeSetting( crs, dim, rangeName.substring( 0, 3 ) ); ((BaseSetting<Double>) setting).setInternal( true ); ((BaseSetting<Double>) setting).setDescription( descriptionHeader + ". " + descriptionBody.replaceAll( " 2D ", String.format( " %dD", crs.getDimension() ) ) ); crsSettings.add( new ConfigOptions( setting ) ); } } } return crsSettings; } }
/** * This method builds the default index configuration object for the specified CRS and other config options. * Currently we only support a SingleSpaceFillingCurveSettings which is the best option for cartesian, but * not necessarily the best for geographic coordinate systems. */ static SpaceFillingCurveSettings fromConfig( int maxBits, EnvelopeSettings envelopeSettings ) { // Currently we support only one type of index, but in future we could support different types for different CRS return new SpaceFillingCurveSettings.SettingsFromConfig( envelopeSettings.getCrs().getDimension(), maxBits, envelopeSettings.asEnvelope() ); }
@Override public double distance( PointValue p1, PointValue p2 ) assert p1.getCoordinateReferenceSystem().getDimension() == dimension; assert p2.getCoordinateReferenceSystem().getDimension() == dimension; double[] c1Coord = p1.coordinate(); double[] c2Coord = p2.coordinate();
@Override public List<Pair<PointValue,PointValue>> boundingBox( PointValue center, double distance ) { assert center.getCoordinateReferenceSystem().getDimension() == dimension; double[] coordinates = center.coordinate(); double[] min = new double[dimension]; double[] max = new double[dimension]; for ( int i = 0; i < dimension; i++ ) { min[i] = coordinates[i] - distance; max[i] = coordinates[i] + distance; } CoordinateReferenceSystem crs = center.getCoordinateReferenceSystem(); return Collections.singletonList( Pair.of( Values.pointValue( crs, min ), Values.pointValue( crs, max ) ) ); } }
private Pair<PointValue,PointValue> boundingBoxOf( double minLon, double maxLon, double minLat, double maxLat, PointValue center, double distance ) { CoordinateReferenceSystem crs = center.getCoordinateReferenceSystem(); int dimension = center.getCoordinateReferenceSystem().getDimension(); double[] min = new double[dimension]; double[] max = new double[dimension]; min[0] = minLon; min[1] = minLat; max[0] = maxLon; max[1] = maxLat; if ( dimension > 2 ) { double[] coordinates = center.coordinate(); for ( int i = 2; i < dimension; i++ ) { min[i] = coordinates[i] - distance; max[i] = coordinates[i] + distance; } } return Pair.of( Values.pointValue( crs, min ), Values.pointValue( crs, max ) ); } }
Envelope asEnvelope() { int dimension = crs.getDimension(); assert dimension >= 2; double[] min = new double[dimension]; double[] max = new double[dimension]; int cartesianStartIndex = 0; if ( crs.isGeographic() ) { // Geographic CRS default to extent of the earth in degrees min[0] = minOrDefault( 0, DEFAULT_MIN_LONGITUDE ); max[0] = maxOrDefault( 0, DEFAULT_MAX_LONGITUDE ); min[1] = minOrDefault( 1, DEFAULT_MIN_LATITUDE ); max[1] = maxOrDefault( 1, DEFAULT_MAX_LATITUDE ); cartesianStartIndex = 2; // if geographic index has higher than 2D, then other dimensions are cartesian } for ( int i = cartesianStartIndex; i < dimension; i++ ) { min[i] = minOrDefault( i, DEFAULT_MIN_EXTENT ); max[i] = maxOrDefault( i, DEFAULT_MAX_EXTENT ); } return new Envelope( min, max ); }
if ( crs.getDimension() != coordinates.length ) throw new InvalidValuesArgumentException( "Cannot create point with " + crs.getDimension() + "D coordinate reference system and " + coordinates.length + " coordinates. Please consider using equivalent " + coordinates.length + "D coordinate reference system" );
@Override void initValueAsHighest( ValueGroup valueGroups ) { // These coordinates will generate the largest value on the spacial curve double[] limit = new double[crs.getDimension()]; Arrays.fill(limit, Double.NEGATIVE_INFINITY); limit[0] = Double.POSITIVE_INFINITY; writePoint( crs, limit ); }
@Override void initValueAsLowest( ValueGroup valueGroups ) { double[] limit = new double[crs.getDimension()]; Arrays.fill(limit, Double.NEGATIVE_INFINITY); writePoint( crs, limit ); }
@Override public double distance( PointValue p1, PointValue p2 ) { assert p1.getCoordinateReferenceSystem().getDimension() == dimension; assert p2.getCoordinateReferenceSystem().getDimension() == dimension; return pythagoras( p1.coordinate(), p2.coordinate() ); }
/** * This method builds the default index configuration object for the specified CRS and other config options. * Currently we only support a SingleSpaceFillingCurveSettings which is the best option for cartesian, but * not necessarily the best for geographic coordinate systems. */ static SpaceFillingCurveSettings fromConfig( int maxBits, EnvelopeSettings envelopeSettings ) { // Currently we support only one type of index, but in future we could support different types for different CRS return new SpaceFillingCurveSettings.SettingsFromConfig( envelopeSettings.getCrs().getDimension(), maxBits, envelopeSettings.asEnvelope() ); }