Core Module

This section provides you with additional information to help you accomplish your specific objectives using the core module of the Location Library.

The core module contains key interfaces and algorithms for working with location data in general and the road network in particular.

  • Geospatial operations and queries
    • Operations to manipulate geo- and projected coordinates, line strings, and bounding boxes
    • Proximity search to find elements that are close to a given point
  • Path matching that takes a sequence of locations recorded by a vehicle (typically GPS positions) and tries to reconstruct the path taken by the vehicle
  • Property maps that provide access to the relevant attributes for each vertex or edge.

libraryDependencies ++= Seq(
  "" %% "location-core" % "0.21.139"
dependencies {
    compile group: '', name: 'location-core_2.11', version:'0.21.139'

Data Model Abstractions

The geospatial sub-package defines the abstractions for geometry types used in the algorithms (Scala-specific).

The following operations abstract the Location Library from the user types:

This allows you to use your own types with the Location Library.

In case you don't have your own type for geocoordinates, coordinates or bounding boxes, the Location Library provides minimal implementations:

For representing simple line strings, using a sequence of GeoCoordinates is supported.

If you want to use your type as an input to the Location Library, you can define as follows:

case class MyPosition(eventId: String, latitude: Double, longitude: Double)
class MyPosition {
  MyPosition(final String eventId, final double latitude, final double longitude) {
    this.eventId = eventId;
    this.latitude = latitude;
    this.longitude = longitude;

  final String eventId;
  final double latitude;
  final double longitude;

Instead of converting the custom input type to the types provided by the Location Library, you can define accessors for your type as follows:


implicit object MyPositionOperations extends GeoCoordinateOperations[MyPosition] {
  override def latitude(c: MyPosition): Double = c.latitude

  override def longitude(c: MyPosition): Double = c.longitude

import java.util.Arrays;
import java.util.List;

class MyPositionAdapter implements GeoCoordinateAdapter<MyPosition> {
  public double getLongitude(final MyPosition instance) {
    return instance.longitude;

  public double getLatitude(final MyPosition instance) {
    return instance.latitude;

Similarly, you can define the required operations for your bounding box or line string type:

case class MyTrip(tripId: String, events: Seq[MyPosition])

implicit object MyTripOperations extends LineStringOperations[MyTrip] {
  override type Point = MyPosition
  override implicit val PointGeoCoordinateOperations: GeoCoordinateOperations[Point] =

  override def points(lineString: MyTrip): Seq[MyPosition] =
class MyTrip {
  String tripId;
  List<MyPosition> events;

class MyTripAdapter implements LineStringAdapter<MyTrip, MyPosition> {
  public List<MyPosition> getPoints(final MyTrip lineString) {

The following paragraph and the examples demonstrate how to use these abstractions.

Geospatial Operations

After you have implemented the abstractions defined in the previous paragraphs, you can apply various functions to your existing data types with location information.

For example, when computing the compass heading between two WGS-84 coordinates, you can use your custom type:

val start = MyPosition("Start", 52.53062, 13.38531)
val end = MyPosition("End", 52.53088, 13.38515)

println(f"Your heading is: ${GeoCoordinates.heading(start, end)}%1.1f°")
final MyPosition start = new MyPosition("Start", 52.53062, 13.38531);
final MyPosition end = new MyPosition("End", 52.53088, 13.38515);

final double heading = GeoCoordinates.getInstance(new MyPositionAdapter()).heading(start, end);

System.out.format("Your heading is: %1.1f°%n", heading);
Your heading is: 339.5°

Similarly, if you have a segment geometry and want to compute the projection of a point onto that geometry together with the distance, you would use the following code:

// Optimized Map for Location Library types
import{LineString, Point}

// Optimized Map types implicits

// Create the geometry of a pedestrian path following the Spree river, using HERE Types
val geometry: LineString = LineString(
  Seq(Point(52.51464, 13.40091),
      Point(52.51546, 13.40027),
      Point(52.51573, 13.40009),
      Point(52.51591, 13.40001)))

// A position of the user type
val position = MyPosition("Current", 52.51537, 13.40114)

// Project your point on the HERE geometry
val projection = LineStrings.pointProjection[MyPosition, LineString](

  "The nearest point is: " +
    f"${projection.nearest.latitude}%1.5f, ${projection.nearest.longitude}%1.5f")
// Create the geometry of a pedestrian path following the Spree river, using custom types
final MyTrip geometry = new MyTrip(); =
        new MyPosition("1", 52.51464, 13.40091),
        new MyPosition("2", 52.51546, 13.40027),
        new MyPosition("3", 52.51573, 13.40009),
        new MyPosition("4", 52.51591, 13.40001));

// A position of the user type
final MyPosition position = new MyPosition("Current", 52.51537, 13.40114);

// Project your point on the geometry
final ElementProjection<MyTrip> projection =
    LineStrings.getInstance(new MyTripAdapter(), new MyPositionAdapter())
        .pointProjection(position, geometry, GeoProjections.sinusoidal());

    "The nearest point is: %1.5f, %1.5f%n",
    projection.getNearest().getLatitude(), projection.getNearest().getLongitude());

The projection contains the fraction representing the position of the projected point on the line string as well. You can access this fraction as follows:

val fraction = projection.fraction
println(f"The nearest point is ${fraction * 100}%1.0f%% of the way along the segment")
final double fraction = projection.getFraction();
    "The nearest point is %1.0f%% of the way along the segment%n", fraction * 100);

results matching ""

    No results matching ""