GeoJSON Serialization To easily serialize the library's geometry objects into GeoJSON format, you can use the location-io
package and store the resulting GeoJSON in a file. Use your preferred viewer or store the GeoJSON in a versioned layer and view it through https://platform.here.com/data .
The main entry point of the package is the FeatureCollection class, which you can use to add and serialize features.
You can add:
Geo coordinates as point markers Line strings as geometries or arrows to highlight a line string direction Range based attributes on line strings, with one geometry (or an arrow) for each range Point based attributes on line strings, with one marker at each attribute position Bounding box to highlight a rectangle area on a map Custom marker images Creating a marker To add a marker at a certain location, you can add any geo-coordinate object as a point.
import com. here. platform. location. io. scaladsl. Color
import com. here. platform. location. io. scaladsl. geojson. { FeatureCollection, SimpleStyleProperties}
FeatureCollection( )
. point( coordinates, SimpleStyleProperties( ) . markerColor( Color. Green) )
. writePretty( new FileOutputStream( "point-marker.json" ) )
import com. here. platform. location. io. javadsl. Color ;
import com. here. platform. location. io. javadsl. geojson. FeatureCollection ;
import com. here. platform. location. io. javadsl. geojson. SimpleStyleProperties ;
new FeatureCollection ( )
. point ( coordinates, new SimpleStyleProperties ( ) . markerColor ( Color . GREEN ) )
. writePretty ( new FileOutputStream ( "point-marker.json" ) ) ;
Figure 1. A point marker on the map You can use SimpleStyleProperties or HereProperties and combine them also with your custom properties using the add
method.
For Java, please use the corresponding similar classes from the javadsl
package.
Drawing a road geometry for a vertex The following code will result in a red segment geometry highlighting a vertex.
import com. here. platform. location. integration. optimizedmap. graph. PropertyMaps
import com. here. platform. location. io. scaladsl. Color
import com. here. platform. location. io. scaladsl. geojson. { FeatureCollection, SimpleStyleProperties}
val geometry = PropertyMaps. geometry( optimizedMap, cacheManager)
FeatureCollection( )
. lineString( geometry( vertex) , SimpleStyleProperties( ) . strokeWidth( 5.0 ) . stroke( Color. Red) )
. writePretty( new FileOutputStream( "vertex-geometry.json" ) )
import com. here. platform. location. core. geospatial. GeoCoordinate ;
import com. here. platform. location. core. geospatial. javadsl. LineStringHolder ;
import com. here. platform. location. core. graph. javadsl. PropertyMap ;
import com. here. platform. location. inmemory. graph. Vertex ;
import com. here. platform. location. integration. optimizedmap. graph. javadsl. PropertyMaps ;
import com. here. platform. location. io. javadsl. Color ;
import com. here. platform. location. io. javadsl. geojson. FeatureCollection ;
import com. here. platform. location. io. javadsl. geojson. SimpleStyleProperties ;
PropertyMap < Vertex , LineStringHolder < GeoCoordinate > > geometry =
PropertyMaps . geometry ( optimizedMap, cacheManager) ;
new FeatureCollection ( )
. lineString (
geometry. get ( vertex) , new SimpleStyleProperties ( ) . strokeWidth ( 5.0 ) . stroke ( Color . RED ) )
. writePretty ( new FileOutputStream ( "vertex-geometry.json" ) ) ;
Drawing a range on a road geometry for a vertex Most attributes are referenced using ranges on vertex geometries, and you can use specific methods to highlight them.
import com. here. platform. location. integration. optimizedmap. graph. PropertyMaps
import com. here. platform. location. io. scaladsl. Color
import com. here. platform. location. io. scaladsl. geojson. { FeatureCollection, SimpleStyleProperties}
val geometry = PropertyMaps. geometry( optimizedMap, cacheManager)
FeatureCollection( )
. lineStringRanges( geometry( vertex) ,
Seq( RangeBasedProperty( 0 , 0.5 , Color. Red) ,
RangeBasedProperty( 0.5 , 1.0 , Color. Green) ) ) ( colorRange =>
SimpleStyleProperties( ) . strokeWidth( 5.0 ) . stroke( colorRange. value) )
. writePretty( new FileOutputStream( "vertex-range.json" ) )
import com. here. platform. location. core. geospatial. GeoCoordinate ;
import com. here. platform. location. core. geospatial. javadsl. LineStringHolder ;
import com. here. platform. location. core. graph. RangeBasedProperty ;
import com. here. platform. location. core. graph. javadsl. PropertyMap ;
import com. here. platform. location. inmemory. graph. Vertex ;
import com. here. platform. location. integration. optimizedmap. graph. javadsl. PropertyMaps ;
import com. here. platform. location. io. javadsl. Color ;
import com. here. platform. location. io. javadsl. geojson. FeatureCollection ;
import com. here. platform. location. io. javadsl. geojson. SimpleStyleProperties ;
PropertyMap < Vertex , LineStringHolder < GeoCoordinate > > geometry =
PropertyMaps . geometry ( optimizedMap, cacheManager) ;
new FeatureCollection ( )
. lineStringRanges (
geometry. get ( vertex) ,
Arrays . asList (
new RangeBasedProperty < > ( 0.0 , 0.5 , Color . RED ) ,
new RangeBasedProperty < > ( 0.5 , 1.0 , Color . GREEN ) ) ,
colorRange -> new SimpleStyleProperties ( ) . strokeWidth ( 5.0 ) . stroke ( colorRange. value ( ) ) )
. writePretty ( new FileOutputStream ( "vertex-range.json" ) ) ;
This results in the geometry of the vertex being red for the first half, and green for the second.
Figure 2. Two ranges on a vertex geometry Use arrows to display directional attributes on ranges With the following code you can now show ranged attributes from a property map in a GeoJSON file.
import com. here. platform. location. integration. optimizedmap. geospatial. ProximitySearches
import com. here. platform. location. integration. optimizedmap. graph. PropertyMaps
import com. here. platform. location. io. scaladsl. Color
import com. here. platform. location. io. scaladsl. geojson. { FeatureCollection, SimpleStyleProperties}
val geometry = PropertyMaps. geometry( optimizedMap, cacheManager)
val automobileAccess =
PropertyMaps. roadAccess( optimizedMap, cacheManager, RoadAccess. Automobile)
val proximitySearch = ProximitySearches. vertices( optimizedMap, cacheManager)
proximitySearch
. search( coordinates, 200 )
. foldLeft( FeatureCollection( ) ) ( ( featureCollection, result) =>
featureCollection. arrowRanges( geometry( result. element) , automobileAccess( result. element) ) (
access =>
SimpleStyleProperties( )
. stroke( if ( access. value) Color. Green else Color. Red) ) )
. writePretty( new FileOutputStream( "road-access.json" ) )
import com. here. platform. location. core. geospatial. ElementProjection ;
import com. here. platform. location. core. geospatial. GeoCoordinate ;
import com. here. platform. location. core. geospatial. javadsl. GeoCoordinateHolder ;
import com. here. platform. location. core. geospatial. javadsl. LineStringHolder ;
import com. here. platform. location. core. geospatial. javadsl. ProximitySearch ;
import com. here. platform. location. core. graph. javadsl. PropertyMap ;
import com. here. platform. location. core. graph. javadsl. RangeBasedPropertyMap ;
import com. here. platform. location. inmemory. graph. Vertex ;
import com. here. platform. location. integration. optimizedmap. geospatial. javadsl. ProximitySearches ;
import com. here. platform. location. integration. optimizedmap. graph. RoadAccess ;
import com. here. platform. location. integration. optimizedmap. graph. javadsl. PropertyMaps ;
import com. here. platform. location. io. javadsl. Color ;
import com. here. platform. location. io. javadsl. geojson. FeatureCollection ;
import com. here. platform. location. io. javadsl. geojson. SimpleStyleProperties ;
PropertyMap < Vertex , LineStringHolder < GeoCoordinate > > geometry =
PropertyMaps . geometry ( optimizedMap, cacheManager) ;
RangeBasedPropertyMap < Vertex , Boolean > automobileAccess =
PropertyMaps . roadAccess ( optimizedMap, cacheManager, RoadAccess. Automobile ) ;
ProximitySearch < GeoCoordinateHolder , Vertex > proximitySearch =
ProximitySearches . vertices ( optimizedMap, cacheManager) ;
Iterable < ElementProjection < Vertex > > searchResults = proximitySearch. search ( coordinates, 200 ) ;
FeatureCollection featureCollection = new FeatureCollection ( ) ;
for ( ElementProjection < Vertex > result : searchResults) {
featureCollection. arrowRanges (
geometry. get ( result. getElement ( ) ) ,
automobileAccess. get ( result. getElement ( ) ) ,
access -> new SimpleStyleProperties ( ) . stroke ( access. value ( ) ? Color . GREEN : Color . RED ) ) ;
}
featureCollection. writePretty ( new FileOutputStream ( "road-access.json" ) ) ;
Green arrows highlight roads traversable by cars.
Figure 3. Road acces with arrows Drawing a point based attributes on a road geometry for a vertex Similarly to ranges, attributes can be referred by point-based properties on vertex geometries.
import com. here. platform. location. integration. optimizedmap. graph. PropertyMaps
import com. here. platform. location. io. scaladsl. Color
import com. here. platform. location. io. scaladsl. geojson. { FeatureCollection, SimpleStyleProperties}
val geometry = PropertyMaps. geometry( optimizedMap, cacheManager)
FeatureCollection( )
. lineStringPoints( geometry( vertex) ,
Seq( PointBasedProperty( 0 , Color. Red) ,
PointBasedProperty( 0.5 , Color. Green) ,
PointBasedProperty( 1.0 , Color. Blue) ) ) ( colorPoint =>
SimpleStyleProperties( ) . markerColor( colorPoint. value) )
. writePretty( new FileOutputStream( "vertex-point.json" ) )
import com. here. platform. location. core. geospatial. GeoCoordinate ;
import com. here. platform. location. core. geospatial. javadsl. LineStringHolder ;
import com. here. platform. location. core. graph. PointBasedProperty ;
import com. here. platform. location. core. graph. javadsl. PropertyMap ;
import com. here. platform. location. inmemory. graph. Vertex ;
import com. here. platform. location. integration. optimizedmap. graph. javadsl. PropertyMaps ;
import com. here. platform. location. io. javadsl. Color ;
import com. here. platform. location. io. javadsl. geojson. FeatureCollection ;
import com. here. platform. location. io. javadsl. geojson. SimpleStyleProperties ;
PropertyMap < Vertex , LineStringHolder < GeoCoordinate > > geometry =
PropertyMaps . geometry ( optimizedMap, cacheManager) ;
new FeatureCollection ( )
. lineStringPoints (
geometry. get ( vertex) ,
Arrays . asList (
new PointBasedProperty < > ( 0.0 , Color . RED ) ,
new PointBasedProperty < > ( 0.5 , Color . GREEN ) ,
new PointBasedProperty < > ( 1.0 , Color . BLUE ) ) ,
colorPoint -> new SimpleStyleProperties ( ) . markerColor ( colorPoint. value ( ) ) )
. writePretty ( new FileOutputStream ( "vertex-point.json" ) ) ;
This results in the three point markers over a vertex geometry.
Figure 4. Three points on a vertex geometry Drawing a bounding box to highlight a rectangle area The following code will highlight a map area.
import com. here. platform. location. io. scaladsl. Color
import com. here. platform. location. io. scaladsl. geojson. { FeatureCollection, SimpleStyleProperties}
FeatureCollection( )
. boundingBox( boundingBox, SimpleStyleProperties( ) . fill( Color. Green) . fillOpacity( 0.5 ) )
. writePretty( new FileOutputStream( "bounding-box.json" ) )
import com. here. platform. location. io. javadsl. Color ;
import com. here. platform. location. io. javadsl. geojson. FeatureCollection ;
import com. here. platform. location. io. javadsl. geojson. SimpleStyleProperties ;
new FeatureCollection ( )
. boundingBox ( boundingBox, new SimpleStyleProperties ( ) . fill ( Color . GREEN ) . fillOpacity ( 0.5 ) )
. writePretty ( new FileOutputStream ( "point-marker.json" ) ) ;
This results in a transparent green rectangle on the map.
Figure 5. A bounding box on the map Custom marker symbol images The markerImage
method of HereProperties accepts a valid data URL or a web URL, making it possible to display an external image as marker image.
Images can also be referenced by name through the markerSymbol
method of SimpleStyleProperties ; such names can be defined through the markerSymbolImages
method of FeatureCollection .
import com. here. platform. location. io. scaladsl. geojson. {
FeatureCollection,
MarkerSymbolImages,
SimpleStyleProperties
}
FeatureCollection( )
. markerSymbolImages(
MarkerSymbolImages( )
. add(
"img" ,
"data:image/svg+xml;utf8,<svg width='128' height='128' viewBox='0 0 26 26' version='1.1' xmlns='http://www.w3.org/2000/svg'><g style='fill:rgb(217, 217, 242); stroke:rgba(198, 203, 221, 0.5)' transform='translate(0,5)'><path d='M 5,7 C 4.5,4.5 7.5,1.5 10,3 c 5.5,-5 13,-1.5 12.5,5 4,2 3.5,7.5 -0,7.5 -6,0 -10.5,0 -18.5,0 -5,-0 -4.5,-8.5 1,-8.5 z'/></g></svg>"
) )
. point( coordinates, SimpleStyleProperties( ) . markerSymbol( "img" ) )
. writePretty( new FileOutputStream( "custom-marker.json" ) )
import com. here. platform. location. io. javadsl. geojson. FeatureCollection ;
import com. here. platform. location. io. javadsl. geojson. MarkerSymbolImages ;
import com. here. platform. location. io. javadsl. geojson. SimpleStyleProperties ;
new FeatureCollection ( )
. markerSymbolImages (
new MarkerSymbolImages ( )
. add (
"img" ,
"data:image/svg+xml;utf8,<svg width='128' height='128' viewBox='0 0 26 26' version='1.1' xmlns='http://www.w3.org/2000/svg'><g style='fill:rgb(217, 217, 242); stroke:rgba(198, 203, 221, 0.5)' transform='translate(0,5)'><path d='M 5,7 C 4.5,4.5 7.5,1.5 10,3 c 5.5,-5 13,-1.5 12.5,5 4,2 3.5,7.5 -0,7.5 -6,0 -10.5,0 -18.5,0 -5,-0 -4.5,-8.5 1,-8.5 z'/></g></svg>" ) )
. point ( coordinates, new SimpleStyleProperties ( ) . markerSymbol ( "img" ) )
. writePretty ( new FileOutputStream ( "custom-marker.json" ) ) ;
This results in a cloud logo being shown as marker symbol image.
Figure 6. Cloud logo as custom marker Drawing on top of a background If you add features to an already populated feature collection, the latter will be used as a background for the former.
import com. here. platform. location. inmemory. graph. { Forward, Vertices}
import com. here. platform. location. integration. optimizedmap. geospatial. ProximitySearches
import com. here. platform. location. integration. optimizedmap. graph. PropertyMaps
import com. here. platform. location. io. scaladsl. Color
import com. here. platform. location. io. scaladsl. geojson. { FeatureCollection, SimpleStyleProperties}
val geometry = PropertyMaps. geometry( optimizedMap, cacheManager)
val proximitySearch = ProximitySearches. vertices( optimizedMap, cacheManager)
val searchResults = proximitySearch
. search( coordinates, 200 )
val background = searchResults
. map( result =>
Feature. lineString( geometry( result. element) ,
SimpleStyleProperties( ) . strokeWidth( 8.0 ) . stroke( Color. Gray) ) )
val arrowsOnBackground = searchResults. map( result =>
Feature. arrow(
geometry( result. element) ,
SimpleStyleProperties( )
. stroke( if ( Vertices. directionOf( result. element) == Forward) Color. Blue else Color. Red)
) )
FeatureCollection( background ++ arrowsOnBackground) . writePretty(
new FileOutputStream( "arrows-on-geometries.json" ) )
import com. here. platform. location. core. geospatial. ElementProjection ;
import com. here. platform. location. core. geospatial. GeoCoordinate ;
import com. here. platform. location. core. geospatial. javadsl. LineStringHolder ;
import com. here. platform. location. core. geospatial. javadsl. ProximitySearch ;
import com. here. platform. location. core. graph. javadsl. PropertyMap ;
import com. here. platform. location. inmemory. graph. Vertex ;
import com. here. platform. location. inmemory. graph. Vertices ;
import com. here. platform. location. inmemory. graph. javadsl. Direction ;
import com. here. platform. location. integration. optimizedmap. geospatial. javadsl. ProximitySearches ;
import com. here. platform. location. integration. optimizedmap. graph. javadsl. PropertyMaps ;
import com. here. platform. location. io. javadsl. Color ;
import com. here. platform. location. io. javadsl. geojson. FeatureCollection ;
import com. here. platform. location. io. javadsl. geojson. SimpleStyleProperties ;
PropertyMap < Vertex , LineStringHolder < GeoCoordinate > > geometry =
PropertyMaps . geometry ( optimizedMap, cacheManager) ;
ProximitySearch < GeoCoordinate , Vertex > proximitySearch =
ProximitySearches . vertices ( optimizedMap, cacheManager) ;
Iterable < ElementProjection < Vertex > > searchResults = proximitySearch. search ( coordinates, 200 ) ;
FeatureCollection featureCollection = new FeatureCollection ( ) ;
for ( ElementProjection < Vertex > result : searchResults)
featureCollection. lineString (
geometry. get ( result. element ( ) ) ,
new SimpleStyleProperties ( ) . strokeWidth ( 8.0 ) . stroke ( Color . GRAY ) ) ;
for ( ElementProjection < Vertex > result : searchResults)
featureCollection. arrow (
geometry. get ( result. element ( ) ) ,
new SimpleStyleProperties ( )
. stroke (
Vertices . directionOf ( result. element ( ) ) == Direction . FORWARD
? Color . BLUE
: Color . GREEN ) ) ;
featureCollection. writePretty ( new FileOutputStream ( "arrows-on-geometries.json" ) ) ;
This results in arrows being drawn over road geometry, with forward vertices drawn in blue and backward vertices drawn in red.
Figure 7. Arrows with road geometries in background Write a GeoJSON to a catalog in Spark If you write GeoJSON to a versioned partition, you will be able to see the results on https://platform.here.com/data .
In order to demonstrate this functionality we will use the Data Client Spark Connector , but you can choose to write the resulting GeoJSON using other Data Client methods or the Data Processing Library.
import com. here. platform. data. client. spark. LayerDataFrameWriter. _
import com. here. platform. location. integration. herecommons. geospatial. {
HereTileLevel,
HereTileResolver
}
import com. here. platform. location. integration. optimizedmap. geospatial. ProximitySearches
import com. here. platform. location. integration. optimizedmap. graph. PropertyMaps
import com. here. platform. location. io. scaladsl. Color
import com. here. platform. location. io. scaladsl. geojson. { FeatureCollection, SimpleStyleProperties}
val sparkSession: SparkSession =
SparkSession
. builder( )
. master( "local" )
. appName( "location-io-example" )
. getOrCreate( )
import sparkSession. implicits. _
import sparkSession. sparkContext. _
case class StringConverter( field: String ) extends VersionedDataConverter {
override def serializeGroup( rowMetadata: VersionedRowMetadata, rows: Iterator[ Row] ) =
GroupedData( rowMetadata, rows. next( ) . getAs[ String ] ( field) . getBytes( "UTF-8" ) )
}
parallelize( Seq( ( berlinGeoCoordinates1, Color. Red) , ( berlinGeoCoordinates2, Color. Blue) ) )
. flatMap {
case ( coordinate, color) =>
val proximity =
ProximitySearches. vertices( optimizedMapCatalog, cacheManager)
val geometry = PropertyMaps. geometry( optimizedMapCatalog, cacheManager)
val resolver = new HereTileResolver( HereTileLevel( 12 ) )
proximity
. search( coordinate, 500 )
. map( p => geometry( p. element) )
. map( g => ( resolver. fromCoordinate( g( 0 ) ) , g, color) )
}
. groupBy( _. _1)
. map {
case ( tile, geometriesWithColor) =>
tile. value. toString -> FeatureCollection( geometriesWithColor. map {
case ( _, g, c) => Feature. lineString( g, SimpleStyleProperties( ) . stroke( c) )
} ) . toJson
}
. toDF( "mt_partition" , "geojson" )
. writeLayer( outputCatalogHrn, outputLayer)
. withDataConverter( StringConverter( "geojson" ) )
. save( )
sparkSession. stop( )
In the following example, you start from an RDD
of coordinates and colors, perform a distributed proximity search for geometries around the points in the RDD
, and finally create a one GeoJSON
string for each output partition, using the colors from the input RDD.
The results can be observed in the target catalog, when the layer has HEREtile
partitioning and application/vnd.geo+json
as mime-type.
Figure 8. GeoJSON on the portal