High-Level API

The high-level API of the Location Library provides a way to instantiate various kinds of path matchers and a number of factory methods to help you directly implement your algorithms using the following interfaces:

  • ProximitySearch To find topology segments (vertices) from coordinates.
    ProximitySearches
  • DirectedGraph To navigate the topology with an efficient data structure.
    Graphs
  • PropertyMap To access road, navigation, advanced navigation, and ADAS attributes.
    PropertyMaps

Setting things up

The library will download and cache, on demand, the map tiles of the Optimized Map for Location Library needed by the algorithms.

The following code snippets demonstrate how to use Location Library factory methods and optimizedMap Catalog for various purposes.

The following imports are shared by all the snippets:

Scala
Java
import com.here.platform.location.dataloader.core.Catalog
import com.here.platform.location.dataloader.core.caching.CacheManager
import com.here.platform.location.inmemory.graph.Vertex
import com.here.platform.location.dataloader.core.Catalog;
import com.here.platform.location.dataloader.core.caching.CacheManager;

The following snippets assume that optimizedMap catalog and cacheManager are initialized, for example:

Scala
Java
import com.here.platform.location.dataloader.standalone.StandaloneCatalogFactory

val cacheManager = CacheManager.withLruCache()

val catalogFactory = new StandaloneCatalogFactory

try {
  val optimizedMap = catalogFactory.create(optimizedMapHRN, optimizedMapVersion)

  // your code that uses the Optimized Map catalog
  println(
    s"optimized map catalog initialized: ${optimizedMap.hrn}, version ${optimizedMap.version}")
} finally {
  catalogFactory.terminate()
}
import com.here.platform.location.dataloader.standalone.StandaloneCatalogFactory;
final CacheManager cacheManager = CacheManager.withLruCache();

final StandaloneCatalogFactory catalogFactory = new StandaloneCatalogFactory();

try {
  final Catalog optimizedMap = catalogFactory.create(optimizedMapHRN, optimizedMapVersion);

  // your code that uses the Optimized Map catalog
  System.out.format(
      "optimized map catalog initialized: %s, version %d",
      optimizedMap.hrn(), optimizedMap.version());

} finally {
  catalogFactory.terminate();
}

For more information on how to initialize the Catalog and the CacheManager, see the Optimized Map Integration Module and Data loaders sections.

Create Path Matchers

To resolve sequences of recorded geographical coordinates to paths on the road topology graph, you can use a path matcher. The path matcher will return information about the position on the road that most likely corresponds to each input point, and the most likely connection (transition) between points.

Path matching
Figure 1. Path matching

Note

Dense and sparse traces of probe data

The sequence of recorded geographical coordinates is called trace or probe trace. The path matchers distinguish between dense and sparse traces. Dense traces are characterized by distances between consecutive probes that are short compared to lengths of the road segments in the map. Typically, probes collected every 1 to 5 seconds are considered dense.

Include the following imports to use the PathMatchers factory:

Scala
Java
import com.here.platform.location.core.geospatial.GeoCoordinate
import com.here.platform.location.core.mapmatching._
import com.here.platform.location.integration.optimizedmap.mapmatching.PathMatchers
import com.here.platform.location.core.geospatial.GeoCoordinate;
import com.here.platform.location.core.mapmatching.NoTransition;
import com.here.platform.location.core.mapmatching.javadsl.PathMatcher;
import com.here.platform.location.inmemory.graph.Vertex;
import com.here.platform.location.integration.optimizedmap.mapmatching.javadsl.PathMatchers;

In order to create path matchers, you can use various methods:

  • The unrestrictedPathMatcher creates a map matcher that produces results independent from any driving restriction, and is suitable for dense GPS traces (at least one point every 5 seconds).

    Scala
    Java
    val unrestrictedPathMatcher: PathMatcher[GeoCoordinate, Vertex, NoTransition] =
      PathMatchers.unrestrictedPathMatcher(optimizedMap, cacheManager)
    final PathMatcher<GeoCoordinate, Vertex, NoTransition> unrestrictedPathMatcher =
        PathMatchers.unrestrictedPathMatcher(optimizedMap, cacheManager);

    The unrestrictedPathMatcher is the most effective method to match to the most probably driven path for dense probes, and all vehicle types. You will not necessarily be able to follow this path by driving, but you can use the results to derive warnings about driving errors.

    The unrestrictedPathMatcher may introduce disconnections when consecutive points are not on directly connected topology segments, as it does not use any routing algorithm to compute the transitions.

    The unrestrictedPathMatcherWithTransitions variant will make a bigger effort to reconnect points with a simple shortest path algorithm.

  • The carPathMatcherWithTransitions takes most car driving restrictions into consideration, and is a path matcher specifically configured for cars and sparse data, but will also work on dense data. For example, this path matcher will only match input points to vertices that are accessible by cars according to the roadAccess property.

    The carPathMatcherWithTransitions works better than the unrestrictedPathMatcherWithTransitions for sparse data because it will route between points using a shortest path algorithm that takes into consideration road access and turn restrictions. In some situations, when consecutive points are too far apart (several kilometers), they could be considered unreachable and hence one of them could be matched to Unknown.

    Scala
    Java
    val carPathMatcherWithTransitions: PathMatcher[GeoCoordinate, Vertex, Seq[Vertex]] =
      PathMatchers.carPathMatcherWithTransitions(optimizedMap, cacheManager)
    final PathMatcher<GeoCoordinate, Vertex, List<Vertex>> carPathMatcherWithTransitions =
        PathMatchers.carPathMatcherWithTransitions(optimizedMap, cacheManager);

    The carPathMatcher variant is similar but is only suitable for dense data, where the distances between consecutive probes are short compared to vertex lengths in the map.

    Scala
    Java
    val carPathMatcher: PathMatcher[GeoCoordinate, Vertex, NoTransition] =
      PathMatchers.carPathMatcher(optimizedMap, cacheManager)
    final PathMatcher<GeoCoordinate, Vertex, NoTransition> carPathMatcher =
        PathMatchers.carPathMatcher(optimizedMap, cacheManager);

Note

For more details about the path matcher output, see the API Guide.

  • For advanced scenarios, you can construct an HMMPathMatcher directly, to specify desired path matcher dependencies.

    Scala
    Java
    import com.here.platform.location.core.geospatial.{
      ElementProjection,
      GeoCoordinate,
      GreatCircleDistanceCalculator
    }
    import com.here.platform.location.core.mapmatching._
    import com.here.platform.location.inmemory.geospatial.TileId
    import com.here.platform.location.inmemory.graph.VertexIndex
    import com.here.platform.location.integration.optimizedmap.graph.{
      Graphs,
      PropertyMaps,
      RoadAccess
    }
    import com.here.platform.location.integration.optimizedmap.mapmatching.{
      EmissionProbabilityStrategies,
      PathMatchers,
      TransitionProbabilityStrategies
    }
    
    val origin = GeoCoordinate(0, 0)
    val originCandidate =
      IndexedSeq(OnRoad(ElementProjection(Vertex(TileId(1), VertexIndex(0)), origin, 0, 0.0)))
    
    class CustomCandidateGenerator extends CandidateGenerator[GeoCoordinate, Vertex] {
      override def generate(observation: GeoCoordinate): IndexedSeq[MatchResult[Vertex]] =
        if (observation == origin) originCandidate else IndexedSeq.empty
    }
    
    val customPathMatcher: PathMatcher[GeoCoordinate, Vertex, Seq[Vertex]] =
      PathMatchers.newHMMPathMatcher(
        new CustomCandidateGenerator,
        EmissionProbabilityStrategies.usingDistance,
        TransitionProbabilityStrategies.directDistance(
          Graphs.from(optimizedMap, cacheManager),
          PropertyMaps.length(optimizedMap, cacheManager),
          PropertyMaps.roadAccess(optimizedMap, cacheManager, RoadAccess.Automobile),
          GreatCircleDistanceCalculator
        )
      )
    import com.here.platform.location.core.geospatial.ElementProjection;
    import com.here.platform.location.core.geospatial.GeoCoordinate;
    import com.here.platform.location.core.geospatial.GreatCircleDistanceCalculator;
    import com.here.platform.location.core.mapmatching.MatchResult;
    import com.here.platform.location.core.mapmatching.OnRoad;
    import com.here.platform.location.core.mapmatching.javadsl.CandidateGenerator;
    import com.here.platform.location.core.mapmatching.javadsl.PathMatcher;
    import com.here.platform.location.inmemory.graph.Vertex;
    import com.here.platform.location.integration.optimizedmap.graph.RoadAccess;
    import com.here.platform.location.integration.optimizedmap.graph.javadsl.Graphs;
    import com.here.platform.location.integration.optimizedmap.graph.javadsl.PropertyMaps;
    import com.here.platform.location.integration.optimizedmap.mapmatching.javadsl.EmissionProbabilityStrategies;
    import com.here.platform.location.integration.optimizedmap.mapmatching.javadsl.PathMatchers;
    import com.here.platform.location.integration.optimizedmap.mapmatching.javadsl.TransitionProbabilityStrategies;
    final GeoCoordinate origin = new GeoCoordinate(0, 0);
    final List<MatchResult<Vertex>> originCandidate = new ArrayList<>();
    originCandidate.add(new OnRoad<>(new ElementProjection<>(new Vertex(1, 0), origin, 0, 0.0)));
    
    final CandidateGenerator<GeoCoordinate, Vertex> customCandidateGenerator =
        observation -> {
          if (observation.equals(origin)) return originCandidate;
          else return new ArrayList<>();
        };
    
    final PathMatcher<GeoCoordinate, Vertex, List<Vertex>> customPathMatcher =
        PathMatchers.newHMMPathMatcher(
            customCandidateGenerator,
            EmissionProbabilityStrategies.usingDistance(),
            TransitionProbabilityStrategies.distanceWithTransitions(
                Graphs.from(optimizedMap, cacheManager),
                PropertyMaps.length(optimizedMap, cacheManager),
                PropertyMaps.roadAccess(optimizedMap, cacheManager, RoadAccess.Automobile),
                GreatCircleDistanceCalculator.getInstance()));

In order to associate places in the real world with vertices in the routing graph, ProximitySearch allows you to search for vertices within a certain distance from a point on the map.

Scala
Java
// Implicit GeoCoordinateOperations for com.here.schema.geometry.v2.geometry.Point
import com.here.platform.location.core.geospatial.{ElementProjection, ProximitySearch}
import com.here.platform.location.integration.heremapcontent.geospatial.Implicits._
import com.here.platform.location.integration.optimizedmap.geospatial.ProximitySearches

val brandenburgerTor = com.here.schema.geometry.v2.geometry.Point(52.516268, 13.377700)
val radiusInMeters = 1000.0
val proximitySearch: ProximitySearch[Vertex] =
  ProximitySearches.vertices(optimizedMap, cacheManager)

val vertices: Iterable[ElementProjection[Vertex]] =
  proximitySearch.search(brandenburgerTor, radiusInMeters)

val closestFewVertices = vertices.toSeq
  .sortBy(_.distanceInMeters)
  .take(5)
  .map(_.element)

println(s"The closest vertices within $radiusInMeters meters of")
println(brandenburgerTor)
println("are:")
closestFewVertices.foreach(println)
import com.here.platform.location.core.geospatial.ElementProjection;
import com.here.platform.location.core.geospatial.GeoCoordinate;
import com.here.platform.location.core.geospatial.javadsl.GeoCoordinateAdapter;
import com.here.platform.location.core.geospatial.javadsl.ProximitySearch;
import com.here.platform.location.inmemory.graph.Vertex;
import com.here.platform.location.integration.optimizedmap.geospatial.javadsl.ProximitySearches;
import com.here.schema.geometry.v2.GeometryOuterClass.Point;
final GeoCoordinateAdapter<Point> hereMapContentPointAdapter =
    new GeoCoordinateAdapter<Point>() {
      @Override
      public double getLatitude(final Point p) {
        return p.getLatitude();
      }

      @Override
      public double getLongitude(final Point p) {
        return p.getLongitude();
      }
    };

final Point brandenburgerTor =
    Point.newBuilder().setLatitude(52.516268).setLongitude(13.377700).build();

final double radiusInMeters = 1000.0;

final ProximitySearch<Point, Vertex> proximitySearch =
    ProximitySearches.vertices(optimizedMap, cacheManager, hereMapContentPointAdapter);

final Iterable<ElementProjection<Vertex>> vertices =
    proximitySearch.search(brandenburgerTor, radiusInMeters);

final List<ElementProjection<Vertex>> closestFewVertices =
    StreamSupport.stream(vertices.spliterator(), false)
        .sorted(Comparator.comparingDouble(ElementProjection::distanceInMeters))
        .limit(5)
        .collect(Collectors.toList());

System.out.format("The closest vertices within %f meters of %n", radiusInMeters);
System.out.format(
    "(%f, %f)%n", brandenburgerTor.getLatitude(), brandenburgerTor.getLongitude());
System.out.println("are:");
closestFewVertices.forEach(v -> System.out.format("%s%n", v));

Retrieving the closest point is a simple but fast technique to perform map matching. The following code snippet shows how to retrieve information about the closest result:

Scala
Java
val closest = vertices.toSeq.minBy(_.distanceInMeters)

println(
  s"The closest point is ${closest.nearest} " +
    s"on vertex ${closest.element} " +
    s"${closest.fraction * 100}% along its length. " +
    s"It is ${closest.distanceInMeters}m away from $brandenburgerTor.")
final ElementProjection<Vertex> closest =
    StreamSupport.stream(vertices.spliterator(), false)
        .min(Comparator.comparingDouble(ElementProjection::distanceInMeters))
        .get();

System.out.format(
    "The closest point is %s on vertex %s %f%% along its length. ",
    closest.nearest(), closest.element(), closest.fraction() * 100);
System.out.format("It is %fm away from %s.%n", closest.distanceInMeters(), brandenburgerTor);

The HERE Workspace Examples for Java and Scala Developers contains a full example called PointMatcherExample that uses a ProximitySearch to perform map matching. This example is located in location/scala/standalone (location/java/standalone for the version written in Java).

Note

For more accurate map matching, use a fully fledged path matcher.

Multiple Results for Each Vertex

Since the geometries of the vertices are not always rectilinear, in some cases you may want to get one ElementProjection for each segment of the geometry (the segment between consecutive pairs of points). In these cases, the following code snippet will return multiple projections for the same vertex, one for each segment of the line string of the geometry:

Scala
Java
import com.here.platform.location.core.geospatial.GeoCoordinate

val hairpinTurn = GeoCoordinate(46.55091, 11.81564)
val geometrySegmentProximitySearch: ProximitySearch[Vertex] =
  ProximitySearches.vertexGeometrySegments(optimizedMap, cacheManager)

val closestProjections: Iterable[ElementProjection[Vertex]] =
  geometrySegmentProximitySearch.search(hairpinTurn, 50 /* meters */ )

println(s"The projections on the geometry segments within 50 meters of")
println(hairpinTurn)
println("are:")
closestProjections.foreach(println)
final GeoCoordinate hairpinTurn = new GeoCoordinate(46.55091, 11.81564);
final ProximitySearch<GeoCoordinate, Vertex> geometrySegmentProximitySearch =
    ProximitySearches.vertexGeometrySegments(optimizedMap, cacheManager);

final Iterable<ElementProjection<Vertex>> closestProjections =
    geometrySegmentProximitySearch.search(hairpinTurn, 50 /* meters */);

System.out.format(
    "The projections on the geometry segments within 50 meters of %s %n", hairpinTurn);
System.out.println("are:");
closestProjections.forEach(System.out::println);

Note

The following image shows the results from the ProximitySearches.vertices. The search only returns the closest point for each vertex: One result per vertex

By using the ProximitySearches.vertexGeometrySegments variant, you have the option to get more than one projection for each vertex: One result for each geometry segment

Graphs

You can navigate the road topology and geometry of the Here Map Content using a graph abstraction. Each vertex of the graph represents a road (topology segment) in a direction, and each edge a physical connection between roads as explained in the Routing Graph section.

The following code snippet demonstrates how to create a graph that lazily loads data from the routinggraph layer of the Optimized Map for Location Library:

Scala
Java
import com.here.platform.location.core.graph.DirectedGraph
import com.here.platform.location.inmemory.graph.{Edge, Vertex}
import com.here.platform.location.integration.optimizedmap.graph.Graphs

val graph: DirectedGraph[Vertex, Edge] = Graphs.from(optimizedMap, cacheManager)
import com.here.platform.location.core.graph.javadsl.DirectedGraph;
import com.here.platform.location.inmemory.graph.Edge;
import com.here.platform.location.inmemory.graph.Vertex;
import com.here.platform.location.integration.optimizedmap.graph.javadsl.Graphs;
final DirectedGraph<Vertex, Edge> graph = Graphs.from(optimizedMap, cacheManager);

Note

There are always two vertices associated with a road topology segment, one for each physical direction of travel. PropertyMaps can be used to gather attributes to make decisions, for example PropertyMaps.roadAccess described below can be used to derive information about the direction of travel for various modes of transport.

You can obtain a vertex's outgoing edges of a graph and their target vertices as follows:

Scala
Java
val outDegree = graph.outDegree(vertex)
val neighbors: Iterable[Vertex] =
  graph.outEdgeIterator(vertex).map(graph.target).toIterable

println(s"The $vertex has $outDegree outgoing edges to the following vertices:")
println(neighbors)
final int outDegree = graph.getOutDegree(vertex);
final List<Vertex> neighbors = new ArrayList<>(outDegree);
graph.getOutEdgeIterator(vertex).forEachRemaining(edge -> neighbors.add(graph.getTarget(edge)));

System.out.format(
    "The %s has %d outgoing edges to the following vertices:%n", vertex, outDegree);

neighbors.forEach(v -> System.out.format("%s%n", v));

The following example shows how to create a graph to navigate the road topology backwards:

Scala
Java
val reversedGraph: DirectedGraph[Vertex, Edge] = Graphs.reversedFrom(optimizedMap, cacheManager)
final DirectedGraph<Vertex, Edge> reversedGraph =
    Graphs.reversedFrom(optimizedMap, cacheManager);

For more information about reversed graphs, see the Graphs.reversedFrom method documentation.

Property Maps

Scala
Java
import com.here.platform.location.core.graph.{
  PropertyMap,
  RangeBasedProperty,
  RangeBasedPropertyMap
}
import com.here.platform.location.integration.optimizedmap.graph.PropertyMaps
import com.here.platform.location.core.graph.javadsl.PropertyMap;
import com.here.platform.location.integration.optimizedmap.graph.javadsl.PropertyMaps;

The Location Library provides property maps for several use cases:

  • Convert between HERE Map Content references and vertices of the Optimized Map for Location Library

    Scala
    Java
    import com.here.platform.location.integration.optimizedmap.geospatial.HereMapContentReference
    
    val backwardMap: PropertyMap[Vertex, HereMapContentReference] =
      PropertyMaps.vertexToHereMapContentReference(optimizedMap, cacheManager)
    
    val reference: HereMapContentReference = backwardMap(vertex)
    
    val forwardMap: PropertyMap[HereMapContentReference, Vertex] =
      PropertyMaps.hereMapContentReferenceToVertex(optimizedMap, cacheManager)
    
    assert(forwardMap(reference) == vertex)
    import com.here.platform.location.inmemory.graph.Vertex;
    import com.here.platform.location.integration.optimizedmap.geospatial.HereMapContentReference;
    final PropertyMap<Vertex, HereMapContentReference> backwardMap =
        PropertyMaps.vertexToHereMapContentReference(optimizedMap, cacheManager);
    
    final HereMapContentReference reference = backwardMap.get(vertex);
    
    final PropertyMap<HereMapContentReference, Vertex> forwardMap =
        PropertyMaps.hereMapContentReferenceToVertex(optimizedMap, cacheManager);
    
    assert forwardMap.get(reference) == vertex;
  • Retrieve the geometry associated with a vertex

    Scala
    Java
    import com.here.platform.location.inmemory.geospatial.PackedLineString
    
    val geometryMap: PropertyMap[Vertex, PackedLineString] =
      PropertyMaps.geometry(optimizedMap, cacheManager)
    
    val geometry: PackedLineString = geometryMap(vertex)
    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 java.util.List;
    final PropertyMap<Vertex, LineStringHolder<GeoCoordinate>> geometryMap =
        PropertyMaps.geometry(optimizedMap, cacheManager);
    
    final List<GeoCoordinate> geometry = geometryMap.get(vertex).getPoints();
  • Retrieve the length of a vertex

    Scala
    Java
    val lengthMap: PropertyMap[Vertex, Double] =
      PropertyMaps.length(optimizedMap, cacheManager)
    
    val length: Double = lengthMap(vertex)
    final PropertyMap<Vertex, Double> lengthMap = PropertyMaps.length(optimizedMap, cacheManager);
    
    final double length = lengthMap.get(vertex);
  • Determine whether a position on a vertex is accessible to a particular vehicle type

    Scala
    Java
    import com.here.platform.location.core.graph.RangeBasedProperty
    import com.here.platform.location.integration.optimizedmap.graph.RoadAccess
    
    val carAccessMap: RangeBasedPropertyMap[Vertex, Boolean] =
      PropertyMaps.roadAccess(optimizedMap, cacheManager, RoadAccess.Automobile)
    
    val isAccessibleByCars: Option[RangeBasedProperty[Boolean]] = carAccessMap(vertex, offset = 0.5)
    import com.here.platform.location.core.graph.javadsl.RangeBasedProperty;
    import com.here.platform.location.core.graph.javadsl.RangeBasedPropertyMap;
    import com.here.platform.location.inmemory.graph.Vertex;
    import com.here.platform.location.integration.optimizedmap.graph.RoadAccess;
    import com.here.platform.location.integration.optimizedmap.graph.javadsl.PropertyMaps;
    
    import java.util.Optional;
    final RangeBasedPropertyMap<Vertex, Boolean> carAccessMap =
        PropertyMaps.roadAccess(optimizedMap, cacheManager, RoadAccess.Automobile);
    
    final double offset = 0.5;
    final Optional<RangeBasedProperty<Boolean>> isAccessibleByCars =
        carAccessMap.get(vertex, offset);
  • Retrieve the speed with which traffic is usually flowing through the vertex (free-flow speed)

    Scala
    Java
    val freeFlowSpeedMap: RangeBasedPropertyMap[Vertex, Int] =
      PropertyMaps.freeFlowSpeed(optimizedMap, cacheManager)
    
    val minimumFreeFlowSpeedKmh: Int = freeFlowSpeedMap(vertex).map(_.value).min
    import com.here.platform.location.core.graph.javadsl.RangeBasedProperty;
    import com.here.platform.location.core.graph.javadsl.RangeBasedPropertyMap;
    import com.here.platform.location.inmemory.graph.Vertex;
    import com.here.platform.location.integration.optimizedmap.graph.javadsl.PropertyMaps;
    
    import java.util.Collections;
    import java.util.Comparator;
    final RangeBasedPropertyMap<Vertex, Integer> freeFlowSpeedMap =
        PropertyMaps.freeFlowSpeed(optimizedMap, cacheManager);
    
    final int minimumFreeFlowSpeedKmh =
        Collections.min(
                freeFlowSpeedMap.get(vertex), Comparator.comparing(RangeBasedProperty::value))
            .value();
  • Determine whether the turn represented by a given edge is restricted for a particular vehicle type

    Scala
    Java
    import com.here.platform.location.inmemory.graph.Edge
    import com.here.platform.location.integration.optimizedmap.graph.AccessRestriction
    
    val carTurnRestrictionsMap: PropertyMap[Edge, Boolean] =
      PropertyMaps.turnRestrictions(optimizedMap, cacheManager, AccessRestriction.Automobile)
    
    val isRestrictedForCars: Boolean = carTurnRestrictionsMap(edge)
    import com.here.platform.location.compilation.heremapcontent.javadsl.AttributeAccessor;
    import com.here.platform.location.compilation.heremapcontent.javadsl.AttributeAccessors;
    import com.here.platform.location.core.graph.javadsl.RangeBasedProperty;
    import com.here.platform.location.core.graph.javadsl.RangeBasedPropertyMap;
    import com.here.platform.location.inmemory.graph.Vertex;
    import com.here.platform.location.integration.optimizedmap.graph.javadsl.PropertyMaps;
    import com.here.schema.rib.v2.common_attributes.SpeedLimitAttribute;
    import com.here.schema.rib.v2.navigation_attributes_partition.NavigationAttributesPartition;
    
    import java.util.List;
    // Note: use the factory method that corresponds to the HERE Map Content layer,
    // for example `navigationAttribute` for compiling the attributes from 'navigation-attributes'
    // layer:
    final AttributeAccessor<NavigationAttributesPartition, Integer> speedLimitAccessor =
        AttributeAccessors.forHereMapContentSegmentAnchor(
            NavigationAttributesPartition::speedLimit, SpeedLimitAttribute::value);
    
    final RangeBasedPropertyMap<Vertex, Integer> speedLimitMap =
        PropertyMaps.navigationAttribute(
            optimizedMap, "speed-limit", hereMapContent, cacheManager, speedLimitAccessor);
    final List<RangeBasedProperty<Integer>> speedLimits = speedLimitMap.get(vertex);
  • Retrieve road attributes, such as

    Scala
    Java
    import com.here.platform.location.integration.optimizedmap.roadattributes._
    
    val roadAttributes = PropertyMaps.RoadAttributes(optimizedMap, cacheManager)
    
    val functionalClasses: Seq[RangeBasedProperty[FunctionalClass]] =
      roadAttributes.functionalClass(vertex)
    
    val overpassUnderpasses: Seq[RangeBasedProperty[OverpassUnderpass]] =
      roadAttributes.overpassUnderpass(vertex)
    
    val officialCountryCodes: Seq[RangeBasedProperty[OfficialCountryCode]] =
      roadAttributes.officialCountryCode(vertex)
    
    val physicalAttributes: Seq[RangeBasedProperty[PhysicalAttribute]] =
      roadAttributes.physicalAttribute(vertex)
    
    val roadClasses: Seq[RangeBasedProperty[RoadClass]] = roadAttributes.roadClass(vertex)
    
    val specialTrafficAreaCategories: Seq[RangeBasedProperty[SpecialTrafficAreaCategory]] =
      roadAttributes.specialTrafficAreaCategory(vertex)
    import com.here.platform.location.core.graph.javadsl.RangeBasedProperty;
    import com.here.platform.location.core.graph.javadsl.RangeBasedPropertyMap;
    import com.here.platform.location.inmemory.graph.Vertex;
    import com.here.platform.location.integration.optimizedmap.graph.javadsl.PropertyMaps;
    import com.here.platform.location.integration.optimizedmap.roadattributes.*;
    
    import java.util.List;
    final PropertyMaps.RoadAttributes roadAttributes =
        new PropertyMaps.RoadAttributes(optimizedMap, cacheManager);
    
    final RangeBasedPropertyMap<Vertex, FunctionalClass> functionalClass =
        roadAttributes.functionalClass();
    final List<RangeBasedProperty<FunctionalClass>> functionalClasses = functionalClass.get(vertex);
    
    final RangeBasedPropertyMap<Vertex, OverpassUnderpass> overpassUnderpass =
        roadAttributes.overpassUnderpass();
    final List<RangeBasedProperty<OverpassUnderpass>> overpassUnderpasses =
        overpassUnderpass.get(vertex);
    
    final RangeBasedPropertyMap<Vertex, OfficialCountryCode> officialCountryCode =
        roadAttributes.officialCountryCode();
    final List<RangeBasedProperty<OfficialCountryCode>> officialCountryCodes =
        officialCountryCode.get(vertex);
    
    final RangeBasedPropertyMap<Vertex, PhysicalAttribute> physicalAttribute =
        roadAttributes.physicalAttribute();
    final List<RangeBasedProperty<PhysicalAttribute>> physicalAttributes =
        physicalAttribute.get(vertex);
    
    final RangeBasedPropertyMap<Vertex, RoadClass> roadClass = roadAttributes.roadClass();
    final List<RangeBasedProperty<RoadClass>> roadClasses = roadClass.get(vertex);
    
    final RangeBasedPropertyMap<Vertex, SpecialTrafficAreaCategory> specialTrafficAreaCategory =
        roadAttributes.specialTrafficAreaCategory();
    final List<RangeBasedProperty<SpecialTrafficAreaCategory>> specialTrafficAreaCategories =
        specialTrafficAreaCategory.get(vertex);
  • Retrieve navigation attributes, such as

    and an experimental API for TrafficMessageChannelCodes

    Scala
    Java
    import com.here.platform.location.integration.optimizedmap.navigationattributes._
    
    val navigationAttributes = PropertyMaps.NavigationAttributes(optimizedMap, cacheManager)
    
    val intersectionInternalCategories: Seq[RangeBasedProperty[IntersectionInternalCategory]] =
      navigationAttributes.intersectionInternalCategory(vertex)
    val laneCategories: Seq[RangeBasedProperty[LaneCategory]] =
      navigationAttributes.laneCategory(vertex)
    val throughLaneCounts: Seq[RangeBasedProperty[Int]] =
      navigationAttributes.throughLaneCount(vertex)
    val physicalLaneCounts: Seq[RangeBasedProperty[Int]] =
      navigationAttributes.physicalLaneCount(vertex)
    val localRoads: Seq[RangeBasedProperty[LocalRoad]] =
      navigationAttributes.localRoad(vertex)
    val roadUsages: Seq[RangeBasedProperty[RoadUsage]] =
      navigationAttributes.roadUsage(vertex)
    val lowMobilities: Seq[RangeBasedProperty[LowMobility]] =
      navigationAttributes.lowMobility(vertex)
    val roadDividers: Seq[RangeBasedProperty[RoadDivider]] =
      navigationAttributes.roadDivider(vertex)
    val speedCategories: Seq[RangeBasedProperty[SpeedCategory]] =
      navigationAttributes.speedCategory(vertex)
    val speedLimit: Seq[RangeBasedProperty[SpeedLimit]] =
      navigationAttributes.speedLimit(vertex)
    val supplementalGeometries: Seq[RangeBasedProperty[SupplementalGeometry]] =
      navigationAttributes.supplementalGeometry(vertex)
    val travelDirection: Seq[RangeBasedProperty[TravelDirection]] =
      navigationAttributes.travelDirection(vertex)
    val urban: Seq[RangeBasedProperty[Boolean]] =
      navigationAttributes.urban(vertex)
    val specialExplication: Option[SpecialExplication] =
      navigationAttributes.specialExplication(edge)
    val throughRoute: Option[ThroughRoute] =
      navigationAttributes.throughRoute(edge)
    
    // EXPERIMENTAL API
    // May be changed or removed from one version to the next.
    val tmcCodes: Seq[RangeBasedProperty[Set[TrafficMessageChannelCode]]] =
      navigationAttributes.trafficMessageChannelCodes(vertex)
    import com.here.platform.location.core.graph.javadsl.PropertyMap;
    import com.here.platform.location.core.graph.javadsl.RangeBasedProperty;
    import com.here.platform.location.core.graph.javadsl.RangeBasedPropertyMap;
    import com.here.platform.location.inmemory.graph.Edge;
    import com.here.platform.location.inmemory.graph.Vertex;
    import com.here.platform.location.integration.optimizedmap.commonattributes.SpeedLimit;
    import com.here.platform.location.integration.optimizedmap.graph.javadsl.PropertyMaps;
    import com.here.platform.location.integration.optimizedmap.navigationattributes.*;
    
    import java.util.List;
    import java.util.Optional;
    import java.util.Set;
    final PropertyMaps.NavigationAttributes navigationAttributes =
        new PropertyMaps.NavigationAttributes(optimizedMap, cacheManager);
    
    final RangeBasedPropertyMap<Vertex, IntersectionInternalCategory> intersectionInternalCategory =
        navigationAttributes.intersectionInternalCategory();
    final List<RangeBasedProperty<IntersectionInternalCategory>> intersectionInternalCategories =
        intersectionInternalCategory.get(vertex);
    
    final RangeBasedPropertyMap<Vertex, LaneCategory> laneCategory =
        navigationAttributes.laneCategory();
    final List<RangeBasedProperty<LaneCategory>> laneCategories = laneCategory.get(vertex);
    
    final RangeBasedPropertyMap<Vertex, RoadUsage> roadUsage = navigationAttributes.roadUsage();
    final List<RangeBasedProperty<RoadUsage>> roadUsages = roadUsage.get(vertex);
    
    final RangeBasedPropertyMap<Vertex, Integer> throughLaneCount =
        navigationAttributes.throughLaneCount();
    final List<RangeBasedProperty<Integer>> throughLaneCounts = throughLaneCount.get(vertex);
    
    final RangeBasedPropertyMap<Vertex, Integer> physicalLaneCount =
        navigationAttributes.physicalLaneCount();
    final List<RangeBasedProperty<Integer>> physicalLaneCounts = physicalLaneCount.get(vertex);
    
    final RangeBasedPropertyMap<Vertex, LocalRoad> localRoad = navigationAttributes.localRoad();
    final List<RangeBasedProperty<LocalRoad>> localRoads = localRoad.get(vertex);
    
    final RangeBasedPropertyMap<Vertex, LowMobility> lowMobility =
        navigationAttributes.lowMobility();
    final List<RangeBasedProperty<LowMobility>> lowMobilities = lowMobility.get(vertex);
    
    final RangeBasedPropertyMap<Vertex, RoadDivider> roadDivider =
        navigationAttributes.roadDivider();
    final List<RangeBasedProperty<RoadDivider>> roadDividers = roadDivider.get(vertex);
    
    final RangeBasedPropertyMap<Vertex, SpeedCategory> speedCategory =
        navigationAttributes.speedCategory();
    final List<RangeBasedProperty<SpeedCategory>> speedCategories = speedCategory.get(vertex);
    
    final RangeBasedPropertyMap<Vertex, SpeedLimit> speedLimit = navigationAttributes.speedLimit();
    final List<RangeBasedProperty<SpeedLimit>> speedLimits = speedLimit.get(vertex);
    
    final RangeBasedPropertyMap<Vertex, SupplementalGeometry> supplementalGeometry =
        navigationAttributes.supplementalGeometry();
    final List<RangeBasedProperty<SupplementalGeometry>> supplementalGeometries =
        supplementalGeometry.get(vertex);
    
    final RangeBasedPropertyMap<Vertex, TravelDirection> travelDirection =
        navigationAttributes.travelDirection();
    final List<RangeBasedProperty<TravelDirection>> travelDirections = travelDirection.get(vertex);
    
    final RangeBasedPropertyMap<Vertex, Boolean> urban = navigationAttributes.urban();
    final List<RangeBasedProperty<Boolean>> urbans = urban.get(vertex);
    
    final PropertyMap<Edge, Optional<SpecialExplication>> specialExplication =
        navigationAttributes.specialExplication();
    final Optional<SpecialExplication> specialExplications = specialExplication.get(edge);
    
    final PropertyMap<Edge, Optional<ThroughRoute>> throughRoute =
        navigationAttributes.throughRoute();
    final Optional<ThroughRoute> throughRoutes = throughRoute.get(edge);
    
    // EXPERIMENTAL API
    // May be changed or removed from one version to the next.
    final RangeBasedPropertyMap<Vertex, Set<TrafficMessageChannelCode>> trafficMessageChannelCodes =
        navigationAttributes.trafficMessageChannelCodes();
    final List<RangeBasedProperty<Set<TrafficMessageChannelCode>>> tmcCodes =
        trafficMessageChannelCodes.get(vertex);
  • Retrieve advanced navigation attributes, such as

    Scala
    Java
    import com.here.platform.location.integration.optimizedmap.advancednavigationattributes._
    
    val advancedNavigationAttributes =
      PropertyMaps.AdvancedNavigationAttributes(optimizedMap, cacheManager)
    
    val railwayCrossings: Seq[PointBasedProperty[RailwayCrossing]] =
      advancedNavigationAttributes.railwayCrossing(vertex)
    
    val speedLimit: Seq[RangeBasedProperty[SpeedLimit]] =
      advancedNavigationAttributes.speedLimit(vertex)
    
    val gradeCategory: Seq[RangeBasedProperty[GradeCategory]] =
      advancedNavigationAttributes.gradeCategory(vertex)
    
    val scenic: Seq[RangeBasedProperty[Scenic]] =
      advancedNavigationAttributes.scenic(vertex)
    import com.here.platform.location.core.graph.javadsl.PointBasedProperty;
    import com.here.platform.location.core.graph.javadsl.PointBasedPropertyMap;
    import com.here.platform.location.core.graph.javadsl.RangeBasedProperty;
    import com.here.platform.location.core.graph.javadsl.RangeBasedPropertyMap;
    import com.here.platform.location.inmemory.graph.Vertex;
    import com.here.platform.location.integration.optimizedmap.advancednavigationattributes.GradeCategory;
    import com.here.platform.location.integration.optimizedmap.advancednavigationattributes.RailwayCrossing;
    import com.here.platform.location.integration.optimizedmap.advancednavigationattributes.Scenic;
    import com.here.platform.location.integration.optimizedmap.commonattributes.SpeedLimit;
    import com.here.platform.location.integration.optimizedmap.graph.javadsl.PropertyMaps;
    
    import java.util.List;
    final PropertyMaps.AdvancedNavigationAttributes advancedNavigationAttributes =
        new PropertyMaps.AdvancedNavigationAttributes(optimizedMap, cacheManager);
    
    final PointBasedPropertyMap<Vertex, RailwayCrossing> railwayCrossing =
        advancedNavigationAttributes.railwayCrossing();
    final List<PointBasedProperty<RailwayCrossing>> railwayCrossings = railwayCrossing.get(vertex);
    
    final RangeBasedPropertyMap<Vertex, SpeedLimit> speedLimit =
        advancedNavigationAttributes.speedLimit();
    final List<RangeBasedProperty<SpeedLimit>> speedLimits = speedLimit.get(vertex);
    
    final RangeBasedPropertyMap<Vertex, GradeCategory> gradeCategory =
        advancedNavigationAttributes.gradeCategory();
    final List<RangeBasedProperty<GradeCategory>> gradeCategories = gradeCategory.get(vertex);
    
    final RangeBasedPropertyMap<Vertex, Scenic> scenic = advancedNavigationAttributes.scenic();
    final List<RangeBasedProperty<Scenic>> scenics = scenic.get(vertex);
  • Retrieve ADAS attributes, such as

    Scala
    Java
    import com.here.platform.location.integration.optimizedmap.adasattributes._
    
    val adasAttributes = PropertyMaps.AdasAttributes(optimizedMap, cacheManager)
    
    val builtUpAreaRoad: Seq[RangeBasedProperty[BuiltUpAreaRoad]] =
      adasAttributes.builtUpAreaRoad(vertex)
    
    val linkAccuracy: Seq[RangeBasedProperty[Int]] = adasAttributes.linkAccuracy(vertex)
    
    val slope: Seq[PointBasedProperty[Slope]] = adasAttributes.slope(vertex)
    
    val curvatureHeading: Seq[PointBasedProperty[CurvatureHeading]] =
      adasAttributes.curvatureHeading(vertex)
    
    val edgeCurvatureHeading: Option[CurvatureHeading] =
      adasAttributes.edgeCurvatureHeading(edge)
    
    val elevation: Seq[PointBasedProperty[Elevation]] =
      adasAttributes.elevation(vertex)
    import com.here.platform.location.core.graph.javadsl.*;
    import com.here.platform.location.inmemory.graph.Edge;
    import com.here.platform.location.inmemory.graph.Vertex;
    import com.here.platform.location.integration.optimizedmap.adasattributes.BuiltUpAreaRoad;
    import com.here.platform.location.integration.optimizedmap.adasattributes.CurvatureHeading;
    import com.here.platform.location.integration.optimizedmap.adasattributes.Elevation;
    import com.here.platform.location.integration.optimizedmap.adasattributes.Slope;
    import com.here.platform.location.integration.optimizedmap.graph.javadsl.PropertyMaps;
    
    import java.util.List;
    import java.util.Optional;
    final PropertyMaps.AdasAttributes adasAttributes =
        new PropertyMaps.AdasAttributes(optimizedMap, cacheManager);
    
    final RangeBasedPropertyMap<Vertex, BuiltUpAreaRoad> builtUpAreaRoad =
        adasAttributes.builtUpAreaRoad();
    final List<RangeBasedProperty<BuiltUpAreaRoad>> builtUpAreaRoads = builtUpAreaRoad.get(vertex);
    
    final RangeBasedPropertyMap<Vertex, Integer> linkAccuracy = adasAttributes.linkAccuracy();
    final List<RangeBasedProperty<Integer>> linkAccuracies = linkAccuracy.get(vertex);
    
    final PointBasedPropertyMap<Vertex, Slope> slope = adasAttributes.slope();
    final List<PointBasedProperty<Slope>> slopes = slope.get(vertex);
    
    final PointBasedPropertyMap<Vertex, CurvatureHeading> curvatureHeading =
        adasAttributes.curvatureHeading();
    final List<PointBasedProperty<CurvatureHeading>> curvatureHeadings =
        curvatureHeading.get(vertex);
    
    final PropertyMap<Edge, Optional<CurvatureHeading>> edgeCurvatureHeading =
        adasAttributes.edgeCurvatureHeading();
    final Optional<CurvatureHeading> edgeCurvatureHeadings = edgeCurvatureHeading.get(edge);
    
    final PointBasedPropertyMap<Vertex, Elevation> elevation = adasAttributes.elevation();
    final List<PointBasedProperty<Elevation>> elevations = elevation.get(vertex);
  • Retrieve many of the HERE Map Content attributes of a vertex by compiling them on-the-fly. The Location Library supports on-the-fly compilation of segment attributes with the segment anchor types "Point", "Single-Segment" and "Multi-Segment".

    If you know that the segment anchors for the attribute in question don't overlap, you can use the following API to compile it.

    Scala
    Java
    // Note: use the factory method that corresponds to the HERE Map Content layer,
    // for example `navigationAttribute` for compiling the attributes from 'navigation-attributes' layer:
    
    import com.here.platform.location.compilation.heremapcontent.{
      AttributeAccessor,
      AttributeAccessors
    }
    import com.here.platform.location.core.graph.RangeBasedProperty
    import com.here.schema.rib.v2.common_attributes.SpeedLimitAttribute
    import com.here.schema.rib.v2.navigation_attributes_partition.NavigationAttributesPartition
    
    val speedLimitAccessor: AttributeAccessor[NavigationAttributesPartition, Int] =
      AttributeAccessors
        .forHereMapContentSegmentAnchor[NavigationAttributesPartition, SpeedLimitAttribute, Int](
          _.speedLimit,
          _.value)
    
    val speedLimitMap: RangeBasedPropertyMap[Vertex, Int] =
      PropertyMaps.navigationAttribute(
        optimizedMap,
        "speed-limit",
        hereMapContent,
        cacheManager,
        speedLimitAccessor
      )
    
    val speedLimits: Seq[RangeBasedProperty[Int]] = speedLimitMap(vertex)
    import com.here.platform.location.compilation.heremapcontent.javadsl.AttributeAccessor;
    import com.here.platform.location.compilation.heremapcontent.javadsl.AttributeAccessors;
    import com.here.platform.location.core.graph.javadsl.RangeBasedProperty;
    import com.here.platform.location.core.graph.javadsl.RangeBasedPropertyMap;
    import com.here.platform.location.inmemory.graph.Vertex;
    import com.here.platform.location.integration.optimizedmap.graph.javadsl.PropertyMaps;
    import com.here.schema.rib.v2.common_attributes.SpeedLimitAttribute;
    import com.here.schema.rib.v2.navigation_attributes_partition.NavigationAttributesPartition;
    
    import java.util.List;
    // Note: use the factory method that corresponds to the HERE Map Content layer,
    // for example `navigationAttribute` for compiling the attributes from 'navigation-attributes'
    // layer:
    final AttributeAccessor<NavigationAttributesPartition, Integer> speedLimitAccessor =
        AttributeAccessors.forHereMapContentSegmentAnchor(
            NavigationAttributesPartition::speedLimit, SpeedLimitAttribute::value);
    
    final RangeBasedPropertyMap<Vertex, Integer> speedLimitMap =
        PropertyMaps.navigationAttribute(
            optimizedMap, "speed-limit", hereMapContent, cacheManager, speedLimitAccessor);
    final List<RangeBasedProperty<Integer>> speedLimits = speedLimitMap.get(vertex);

    For attributes with overlapping ranges, there is another method you can use:

    Scala
    Java
    import com.here.platform.location.compilation.heremapcontent.{
      AttributeAccessor,
      AttributeAccessors
    }
    import com.here.platform.location.core.graph.RangeBasedProperty
    import com.here.schema.rib.v2.advanced_navigation_attributes.SpecialSpeedSituationCondition
    import com.here.schema.rib.v2.advanced_navigation_attributes_partition.AdvancedNavigationAttributesPartition
    
    val specialSpeedLimitAccessor: AttributeAccessor[AdvancedNavigationAttributesPartition, Int] =
      AttributeAccessors
        .forHereMapContentSegmentAnchor[AdvancedNavigationAttributesPartition,
                                        SpecialSpeedSituationCondition,
                                        Int](_.specialSpeedSituation, _.specialSpeedLimit)
    
    val specialSpeedLimitMap: PropertyMap[Vertex, Seq[RangeBasedProperty[Int]]] =
      PropertyMaps.overlappingRangeBasedProperty(
        optimizedMap,
        "special-speed-limit",
        cacheManager,
        HereMapContentLayers.AdvancedNavigationAttributes.tileLoader(hereMapContent, cacheManager),
        HereMapContentLayers.AdvancedNavigationAttributes.partitionResolver(optimizedMap,
                                                                            cacheManager),
        specialSpeedLimitAccessor
      )
    
    val specialSpeedLimits: Seq[RangeBasedProperty[Int]] = specialSpeedLimitMap(vertex)
    import com.here.platform.location.compilation.heremapcontent.javadsl.AttributeAccessor;
    import com.here.platform.location.compilation.heremapcontent.javadsl.AttributeAccessors;
    import com.here.platform.location.core.graph.javadsl.PropertyMap;
    import com.here.platform.location.core.graph.javadsl.RangeBasedProperty;
    import com.here.platform.location.inmemory.graph.Vertex;
    import com.here.platform.location.integration.heremapcontent.HereMapContentLayers;
    import com.here.platform.location.integration.optimizedmap.graph.javadsl.PropertyMaps;
    import com.here.schema.rib.v2.advanced_navigation_attributes.SpecialSpeedSituationCondition;
    import com.here.schema.rib.v2.advanced_navigation_attributes_partition.AdvancedNavigationAttributesPartition;
    
    import java.util.List;
    final AttributeAccessor<AdvancedNavigationAttributesPartition, Integer>
        specialSpeedLimitAccessor =
            AttributeAccessors.forHereMapContentSegmentAnchor(
                AdvancedNavigationAttributesPartition::specialSpeedSituation,
                SpecialSpeedSituationCondition::specialSpeedLimit);
    
    final PropertyMap<Vertex, List<RangeBasedProperty<Integer>>> specialSpeedLimitMap =
        PropertyMaps.overlappingRangeBasedProperty(
            optimizedMap,
            "special-speed-limit",
            cacheManager,
            HereMapContentLayers.AdvancedNavigationAttributes()
                .tileLoader(hereMapContent, cacheManager),
            HereMapContentLayers.AdvancedNavigationAttributes()
                .partitionResolver(optimizedMap, cacheManager),
            specialSpeedLimitAccessor);
    final List<RangeBasedProperty<Integer>> specialSpeedLimits = specialSpeedLimitMap.get(vertex);

Note

In the Here Map Content layers some attributes have a unique value for each section of a topology segment (e.g. number of lanes or functional class). Others may have multiple overlapping values (e.g. time dependent attributes that have multiple values in the same spot, that apply during different times). Attributes are "non-overlapping" if they have at most a single value for each location, and they are "overlapping" if they can have multiple different values that apply to the same location.

results matching ""

    No results matching ""