カスタムレンダラ プラグインをローカルで開発およびテストする場合は、まず Custom data using custom JavaScript translators to GeoJSON オプションを使用して Web アプリジェネレータをインストールする必要があります。 次に renderer.plugin.template.js 、生成されたサンプルアプリケーションで使用できるようになるファイルを拡張します。
以下の例に従って、レンダラ プラグインの能力開発スキルを練習してください。
トポロジジオメトリのプラグインの例
この例では、 HERE Map Content ( HMC )トポロジパーティションのカスタムレンダリングを使用しています。 この例では、道路セグメントとノードを視覚化して、さまざまなプラグイン機能を示します。
/**
* Renderer plugin to convert JSON data to GeoJSON.
*
* Generated GeoJSON must be created according to GeoJSON Specification:
* https://tools.ietf.org/html/rfc7946
*
* This template is an example of plugin to generate the GeoJSON object based on decoded partition
* content (the same data structure as in Decoded Data panel).
*
* In order to use renderer plugin this file must be placed into project root directory and
* parameter `externalRendererPluginName` must be passed into constructor:
*
* ```
* const geoJsonDataSource = new GeoJsonDataSource({
* dataStore: {
* hrn: HRN.fromString("Your HRN string"),
* getBearerToken: tokenResolver.getBearerToken.bind(tokenResolver),
* layer: "Layer name"
* },
* externalRendererPluginName: "renderer.plugin.template"
* });
* ```
*
* Renderer plugin must return an object with one of these functions in it:
*
* ```
* getGeoJSON: function (params) { ... }
* getGeoJSONAsync: async function (params) { ... }
* ```
*
* Both synchronous \`getGeoJSON\` and async \`getGeoJSONAsync\` functions return an object with
* GeoJSON data.
*
* Only one of these functions must be declared, if both are present plugin will not be used.
*/(()=>{"use strict";/** @type {RendererPlugin} */const plugin ={/**
* Generates GeoJSON from RIB topology layer data.
*
* @param {object} params.logger Logger to log information to console.
* @param {object} params.layer All properties as well as dataUrl, name, partitioning and
* originalConfiguration.
* @param {object} params.decodeResult Input RIB Navigation Attributes data.
* @param {object} params.mapUtils Various converters like `mercatorConverter`,
* `heretileToQuad`, `hdmapCoordinateToLonLat`, etc.
* @param {object} params.geometryDataProviders Various geometry data providers to map data.
* @returns {object} An object with generated GeoJSON data.
*/getGeoJSON(params){// Destructuring of `params` object.const{ logger, decodeResult }= params;const data = decodeResult.data;if(!data.node &&!data.segment){thrownewError("Source data does not have node and segment lists. Make sure you are passing correct data to the renderer.");}var result ={"type":"FeatureCollection","features":[]};// Process segments in the tile if any exist.
result.features = result.features.concat(processSegments(data.segment));
logger.info("Segments successfully processed: "+ data.segment.length);// Process nodes in the tile. They will be rendered on top of the segments since they were added to the// FeatureCollection afterwards.
result.features = result.features.concat(processNodes(data.node));
logger.info("Nodes successfully processed: "+ data.node.length);// return object with GeoJSONreturn{contentType:"application/vnd.geo+json; charset=utf-8",body: result
};}};return plugin;functionprocessNodes(nodes){var list =[];for(var i =0; i < nodes.length; i++){
list.push(createNodeFeature(nodes[i], i));}return list;}functioncreateNodeFeature(node, index){return{type:"Feature",properties:{protobufRef:`node[${index}]`,tooltip:`<b>Node Identifier:</b><br>${node.identifier}<br><br><b>Geometry:</b><br>Latitude: ${node.geometry.latitude}<br>Longitude: ${node.geometry.longitude}`,style:{color:"#FAD87A"}},geometry:{type:"Polygon",coordinates:convertCoordinateToShape(node.geometry.longitude, node.geometry.latitude)}};}functionconvertCoordinateToShape(lon, lat){var coordinateList =[];var distance =0.000025;// Creates rectangle from point
coordinateList.push([lon - distance, lat + distance]);// Upper-left corner.
coordinateList.push([lon + distance, lat + distance]);// Upper-right corner.
coordinateList.push([lon + distance, lat - distance]);// Lower-right corner.
coordinateList.push([lon - distance, lat - distance]);// Lower-left corner.
coordinateList.push([lon - distance, lat + distance]);// End ring with upper-left corner.return[coordinateList];}functionprocessSegments(segments){var list =[];for(var i =0; i < segments.length; i++){
list.push(processLineStringArray(segments[i], i));}return list;}functionprocessLineStringArray(segment, index){var feature ={type:"Feature",properties:{protobufRef:`segment[${index}]`,identifier: segment.identifier,length: segment.length,style:{color:"#1EE0FF"},width:1},geometry:{type:"LineString",coordinates:[]}};for(var i =0; i < segment.geometry.point.length; i++){var point = segment.geometry.point[i];
feature.geometry.coordinates.push([point.longitude, point.latitude]);}return feature;}})();
制限速度属性プラグインの例
このレンダラ プラグインは、制限速度の行を含む GeoJSON 出力を生成します。 制限速度情報は HERE Map Content Roads-Navigation Attributes レイヤーから取得され、道路ジオメトリは HERE Map Content トポロジジオメトリレイヤーから取得されます。
/*
* Copyright (C) 2017-2020 HERE Global B.V. and its affiliate(s). All rights reserved.
*
* This software and other materials contain proprietary information controlled by HERE and are
* protected by applicable copyright legislation. Any use and utilization of this software and other
* materials and disclosure to any third parties is conditional upon having a separate agreement
* with HERE for the access, use, utilization or disclosure of this software. In the absence of such
* agreement, the use of the software is not allowed.
*//**
* Renderer plugin to convert JSON data to GeoJSON.
*
* Generated GeoJSON must be created according to GeoJSON Specification:
* https://tools.ietf.org/html/rfc7946
*
* This template is an example of plugin to generate the GeoJSON object based on decoded partition
* content (the same data structure as in Decoded Data panel).
*
* In order to use renderer plugin this file must be placed into project root directory and
* parameter `externalRendererPluginName` must be passed into constructor:
*
* ```
* const geoJsonDataSource = new GeoJsonDataSource({
* dataStore: {
* hrn: HRN.fromString("Your HRN string"),
* getBearerToken: tokenResolver.getBearerToken.bind(tokenResolver),
* layer: "Layer name"
* },
* externalRendererPluginName: "renderer.plugin.template"
* });
* ```
*
* Renderer plugin must return an object with one of these functions in it:
*
* ```
* getGeoJSON: function (params) { ... }
* getGeoJSONAsync: async function (params) { ... }
* ```
*
* Both synchronous \`getGeoJSON\` and async \`getGeoJSONAsync\` functions return an object with
* GeoJSON data.
*
* Only one of these functions must be declared, if both are present plugin will not be used.
*/(()=>{"use strict";let geometryDataProvider;// An instance of geometry data provider.let loggerInstance;// An instance of logger.// Thresholds and colors for different speed limit values.constMEDIUM_LIMIT_LOW_VALUE=50;constMEDIUM_LIMIT_HIGH_VALUE=80;constCOLOR_SPEEDLIMIT_LOW="#bf212f";constCOLOR_SPEEDLIMIT_MEDIUM="#e18c1e";constCOLOR_SPEEDLIMIT_HIGH="#27b376";constHOVER_SPEEDLIMIT_LOW="#e52838";constHOVER_SPEEDLIMIT_MEDIUM="#ffa423";constHOVER_SPEEDLIMIT_HIGH="#2fd98f";/** @type {RendererPlugin} */const plugin ={/**
* Asynchronously generates GeoJSON from RIB Navigation Attributes data.
*
* @param {object} params.logger Logger to log information to console.
* @param {object} params.layer All properties as well as dataUrl, name, partitioning and
* originalConfiguration.
* @param {object} params.decodeResult Input RIB Navigation Attributes data.
* @param {object} params.mapUtils Various converters like `mercatorConverter`,
* `heretileToQuad`, `hdmapCoordinateToLonLat`, etc.
* @param {object} params.geometryDataProviders Various geometry data providers to map data.
* @returns {Promise} A promise which resolves with generated GeoJSON data.
*/asyncgetGeoJSONAsync(params){// Destructuring of `params` object.const{ logger, decodeResult, geometryDataProviders }= params;// This is an async function so it must return a Promise.// Save an instance of logger so it can be used by other functions within the scope of// this plugin.
loggerInstance = logger;// Get an instance of geometry data provider from `geometryDataProviders`.// Please note that this is an asynchronous call.
geometryDataProvider =await geometryDataProviders.getSegmentAnchorDataProvider();// Validate input data.if(!decodeResult.data.speed_limit &&!decodeResult.data.segment_anchor){
loggerInstance.error("Source data does not have speed limits data. Make sure you are passing correct data to the renderer.");thrownewError();}// Create result object.const result ={"type":"FeatureCollection","features":awaitprocessSpeedLimits(decodeResult.data)};// Resolve promise with generated GeoJSON.return{contentType:"application/geo+json; charset=utf-8",body: result
};}};return plugin;/**
* Creates speed limits geometry.
* Please note that this function is async.
*/asyncfunctionprocessSpeedLimits(data){const result =[];// Preliminary sort source data by speed limit value.
data.speed_limit.sort((item1, item2)=> item1.value < item2.value);// Iterate over speed limit items.let speedLimitItemIndex =0;for(const speedLimitItem of data.speed_limit){const style =getLineStyle(speedLimitItem);// Iterate over `SegmentAnchor`s of speed limit item.let segmentAnchorIndex =0;for(const anchorIndex of speedLimitItem.segment_anchor_index){// First, get actual `SegmentAnchor` from pool.const anchor = data.segment_anchor[anchorIndex];// Then, retrieve line coordinates from geometry data provider.const coordinates =await geometryDataProvider.getSegmentAnchorCoordinates(anchor);if(coordinates.length ===0){
loggerInstance.warn(`Can't retrieve geometry for SegmentAnchor #${anchorIndex}`);}// Create a `LineString` feature for speed limit segment
result.push({type:"Feature",properties:{// `protobufRef` is a path pointing to original data propertyprotobufRef:`speed_limit[${speedLimitItemIndex}].segment_anchor_index[${segmentAnchorIndex}]`,speedLimit: speedLimitItem.value,
style,// apply visual styles to featurewidth:4,// `title` will be shown in tooltip when mouse is moved over the featuretitle: speedLimitItem.value +" km/h"},geometry:{type:"LineString",
coordinates
}});
segmentAnchorIndex++;}
speedLimitItemIndex++;};return result;}/**
* Returns line style based on speed limit value.
*
* @param {object} speedLimitItem Speed limit item.
* @returns {string} String with line color.
*/functiongetLineStyle(speedLimitItem){if(speedLimitItem.value <MEDIUM_LIMIT_LOW_VALUE){return{color:COLOR_SPEEDLIMIT_LOW,hoverColor:HOVER_SPEEDLIMIT_LOW};}elseif(speedLimitItem.value <MEDIUM_LIMIT_HIGH_VALUE){return{color:COLOR_SPEEDLIMIT_MEDIUM,hoverColor:HOVER_SPEEDLIMIT_MEDIUM};}else{return{color:COLOR_SPEEDLIMIT_HIGH,hoverColor:HOVER_SPEEDLIMIT_HIGH};}}})();
getGeoJSONAsync:function(params){...// Get an instance of geometry data provider.const roadSegmentsProvider =await params.geometryDataProviders.getRoadSegmentsDataProvider();// Get an array of all road segments from data provider for current partition.const roadSegments =await roadSegmentsProvider.getRoadSegmentsForTile(params.decodeResult.partitionId);...}
注
この例では、プラグインがソース params.decodeResult.partitionId データを使用して、 HERE Map Content パーティションと同じパーティションを参照します。