private void writeArrayHeaderTo( byte[] bytes ) { bytes[0] = (byte) PropertyType.GEOMETRY.intValue(); bytes[1] = (byte) geometryType; bytes[2] = (byte) dimension; bytes[3] = (byte) crs.getTable().getTableId(); bytes[4] = (byte) (crs.getCode() >> 8 & 0xFFL); bytes[5] = (byte) (crs.getCode() & 0xFFL); }
@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] ); } }
@Override public boolean equals( Value other ) { if ( other instanceof PointValue ) { PointValue pv = (PointValue) other; return Arrays.equals( this.coordinate, pv.coordinate ) && this.getCoordinateReferenceSystem().equals( pv.getCoordinateReferenceSystem() ); } return false; }
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 ); }
@Override public int compareTo( PointValue other ) { int cmpCRS = Integer.compare( this.crs.getCode(), other.crs.getCode() ); if ( cmpCRS != 0 ) { return cmpCRS; } // TODO: This is unnecessary and can be an assert. Is it even correct? This implies e.g. that all 2D points are before all 3D regardless of x and y if ( this.coordinate.length > other.coordinate.length ) { return 1; } else if ( this.coordinate.length < other.coordinate.length ) { return -1; } for ( int i = 0; i < coordinate.length; i++ ) { int cmpVal = Double.compare( this.coordinate[i], other.coordinate[i] ); if ( cmpVal != 0 ) { return cmpVal; } } return 0; }
private GeometryHeader( int geometryType, int dimension, int crsTableId, int crsCode ) { this( geometryType, dimension, CoordinateReferenceSystem.get( crsTableId, crsCode ) ); }
@Override public void writePoint( CoordinateReferenceSystem crs, double[] coordinate ) { if ( !isArray ) { setType( Types.GEOMETRY ); updateCurve( crs.getTable().getTableId(), crs.getCode() ); Types.GEOMETRY.write( this, spaceFillingCurve.derivedValueFor( coordinate ), coordinate ); } else { if ( currentArrayOffset == 0 ) { updateCurve( crs.getTable().getTableId(), crs.getCode() ); } else if ( this.long1 != crs.getTable().getTableId() || this.long2 != crs.getCode() ) { throw new IllegalStateException( format( "Tried to assign a geometry array containing different coordinate reference systems, first:%s, violating:%s at array position:%d", CoordinateReferenceSystem.get( (int) long1, (int) long2 ), crs, currentArrayOffset ) ); } Types.GEOMETRY_ARRAY.write( this, currentArrayOffset++, spaceFillingCurve.derivedValueFor( coordinate ), coordinate ); } }
@Override public String toString() { String coordString = coordinate.length == 2 ? format( "x: %s, y: %s", coordinate[0], coordinate[1] ) : format( "x: %s, y: %s, z: %s", coordinate[0], coordinate[1], coordinate[2] ); return format( "point({%s, crs: '%s'})", coordString, getCoordinateReferenceSystem().getName() ); //TODO: Use getTypeName -> Breaking change }
if ( !crs.isGeographic() ) throw new InvalidValuesArgumentException( "A " + CoordinateReferenceSystem.Cartesian.getName() + " point must contain 'x' and 'y'" ); throw new InvalidValuesArgumentException( "A " + CoordinateReferenceSystem.Cartesian_3D.getName() + " point must contain 'x', 'y' and 'z'" ); throw new InvalidValuesArgumentException( "A " + CoordinateReferenceSystem.WGS84.getName() + " point must contain 'latitude' and 'longitude'" ); "A " + CoordinateReferenceSystem.WGS84_3D.getName() + " point must contain 'latitude', 'longitude' and 'height'" ); 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 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; } }
public static Setting<Double> makeCRSRangeSetting( CoordinateReferenceSystem crs, int dim, String rangeKey ) { double defaultCartesianExtent = 1000000; double[] defaultGeographicExtents = new double[]{180, 90, defaultCartesianExtent}; String[] keyFields = new String[]{PREFIX, crs.getName().toLowerCase(), String.valueOf( COORDS[dim] ), rangeKey}; double defValue = crs.isGeographic() ? defaultGeographicExtents[dim] : defaultCartesianExtent; defValue = rangeKey.equals( "min" ) ? -1 * defValue : defValue; return setting( String.join( ".", keyFields ), DOUBLE, String.valueOf( defValue ) ); }
@Override public void writePoint( CoordinateReferenceSystem crs, double[] coordinate ) throws RuntimeException { append( "{geometry: {type: \"Point\", coordinates: " ); append( Arrays.toString(coordinate) ); append( ", crs: {type: link, properties: {href: \"" ); append( crs.getHref() ); append( "\", code: " ); append( Integer.toString( crs.getCode() ) ); append( "}}}}" ); }
@Override public String newSpatial( CoordinateReferenceSystem crs ) { for ( int i = 0; i < coordinateReferenceSystems.length; i++ ) { if ( coordinateReferenceSystems[i].equals( crs ) ) { int count = counters[i].incrementAndGet(); if ( count > 1 ) { throw new IllegalStateException( "called new on same crs multiple times" ); } break; } } return crs.toString(); } }
private static Value calculateDistance( PointValue p1, PointValue p2 ) { if ( p1.getCoordinateReferenceSystem().equals( p2.getCoordinateReferenceSystem() ) ) { return doubleValue( p1.getCoordinateReferenceSystem().getCalculator().distance( p1, p2 ) ); } else { return NO_VALUE; } }
private static CoordinateReferenceSystem findSpecifiedCRS( PointBuilder fields ) { String crsValue = fields.crs; int sridValue = fields.srid; if ( crsValue != null && sridValue != -1 ) { throw new InvalidValuesArgumentException( "Cannot specify both CRS and SRID" ); } else if ( crsValue != null ) { return CoordinateReferenceSystem.byName( crsValue ); } else if ( sridValue != -1 ) { return CoordinateReferenceSystem.get( sridValue ); } else { return null; } }
CoordinateReferenceSystem crs = CoordinateReferenceSystem.byName( fields[0] ); EnvelopeSettings envelopeSettings = env.computeIfAbsent( crs, EnvelopeSettings::new ); int index = "xyz".indexOf( fields[1].toLowerCase() ); if ( index >= crs.getDimension() ) throw new IllegalArgumentException( "Invalid spatial coordinate key for " + crs.getDimension() + "D: " + fields[1] );
@Override Value get( PointValue value ) { return Values.stringValue( value.getCoordinateReferenceSystem().toString() ); } },
@Test void shouldCalculateCartesianDistance3D() { CoordinateReferenceSystem crs = CoordinateReferenceSystem.Cartesian_3D; assertThat( "", crs.getCalculator().distance( cart( 0.0, 0.0, 0.0 ), cart( 1.0, 0.0, 0.0 ) ), equalTo( 1.0 ) ); assertThat( "", crs.getCalculator().distance( cart( 0.0, 0.0, 0.0 ), cart( 0.0, 1.0, 0.0 ) ), equalTo( 1.0 ) ); assertThat( "", crs.getCalculator().distance( cart( 0.0, 0.0, 0.0 ), cart( 0.0, 0.0, 1.0 ) ), equalTo( 1.0 ) ); assertThat( "", crs.getCalculator().distance( cart( 0.0, 0.0, 0.0 ), cart( 0.0, 1.0, 1.0 ) ), closeTo( 1.41, 0.01 ) ); assertThat( "", crs.getCalculator().distance( cart( 0.0, 0.0, 0.0 ), cart( 1.0, 1.0, 1.0 ) ), closeTo( 1.73, 0.01 ) ); assertThat( "", crs.getCalculator().distance( cart( -1000000.0, -1000000.0, -1000000.0 ), cart( 1000000.0, 1000000.0, 1000000.0 ) ), closeTo( 3464102.0, 1.0 ) ); }