import { FeaturesDataSource , MapViewFeature , MapViewMultiPointFeature , MapViewPolygonFeature } from "@here/harp-features-datasource" ; import { GeoBox , GeoCoordinates , GeoPolygon , mercatorProjection } from "@here/harp-geoutils" ; import { geoCoordLikeToGeoPointLike } from "@here/harp-geoutils/lib/coordinates/GeoCoordLike" ; import { MapControls , MapControlsUI } from "@here/harp-map-controls" ; import { BoundsGenerator , CameraUtils , CopyrightElementHandler , MapView } from "@here/harp-mapview" ; import { VectorTileDataSource } from "@here/harp-vectortile-datasource" ; import { GUI , GUIController } from "dat.gui" ; import { apikey } from "../config" ; export namespace BoundsExample { function initMapView ( id ) { const canvas = document . getElementById ( id ) as HTMLCanvasElement ; const BERLIN = new GeoCoordinates ( 52.5186234 , 13.373993 ) ; const map = new MapView ( { canvas , projection : mercatorProjection , tileWrappingEnabled : false , theme : { extends : "resources/berlin_tilezen_night_reduced.json" , styles : { geojson : [ { when : [ "all" , [ "==" , [ "geometry-type" ] , "Polygon" ] , [ "==" , [ "get" , "name" ] , "bounds" ] ] , technique : "fill" , renderOrder : 10003 , attr : { color : [ "get" , "color" ] , opacity : 0.2 , lineWidth : 1 , lineColor : "#ff0000" , enabled : true } } , { when : [ "all" , [ "==" , [ "geometry-type" ] , "Polygon" ] , [ "==" , [ "get" , "name" ] , "bbox" ] ] , technique : "solid-line" , renderOrder : 10005 , attr : { color : "#0ff" , lineWidth : "5px" } } , { when : [ "all" , [ "==" , [ "geometry-type" ] , "Point" ] , [ "==" , [ "get" , "name" ] , "bbox" ] ] , technique : "circles" , renderOrder : 10006 , attr : { color : "#00f" , size : 20 } } , { when : "$geometryType == 'point'" , technique : "circles" , renderOrder : 10004 , attr : { color : "#f0f" , size : 10 } } ] } } , target : BERLIN , zoomLevel : 8 , tilt : 45 , heading : - 80 } ) ; map . renderLabels = false ; CopyrightElementHandler . install ( "copyrightNotice" , map ) ; const mapControls = new MapControls ( map ) ; mapControls . maxTiltAngle = 180 ; const ui = new MapControlsUI ( mapControls , { zoomLevel : "input" , projectionSwitch : true } ) ; canvas . parentElement ! . appendChild ( ui . domElement ) ; map . resize ( window . innerWidth , window . innerHeight ) ; window . addEventListener ( "resize" , ( ) => { map . resize ( window . innerWidth , window . innerHeight ) ; } ) ; addVectorTileDataSource ( map ) ; return map ; } let viewpoly ; let cornerpoints ; let bboxFeature ; let bboxPolygonFeature ; function updateBoundsFeatures ( polygon , featuresDataSource ) { const corners = polygon . coordinates ; if ( corners && corners . length > 0 ) { corners . push ( ( corners [ 0 ] as GeoCoordinates ) . clone ( ) ) ; } const polygonArray = [ ] ; const pointArray = [ ] ; polygonArray . push ( pointArray ) ; corners . forEach ( corner => { if ( corner === null ) { return ; } pointArray . push ( geoCoordLikeToGeoPointLike ( corner ) as number [ ] ) ; } ) ; if ( viewpoly ) { featuresDataSource ?. remove ( viewpoly ) ; } viewpoly = new MapViewPolygonFeature ( polygonArray , { name : "bounds" , height : 10000 , color : "#ffff00" } ) ; featuresDataSource ?. add ( viewpoly ) ; if ( cornerpoints ) { featuresDataSource ?. remove ( cornerpoints ) ; } cornerpoints = new MapViewMultiPointFeature ( pointArray , { name : "cornerpoints" } ) ; featuresDataSource ?. add ( cornerpoints ) ; } function updateBoundingBoxFeatures ( geoPolygon , featuresDataSource , isVisible = true ) { if ( bboxFeature ) { featuresDataSource ?. remove ( bboxFeature ) ; } if ( bboxPolygonFeature ) { featuresDataSource ?. remove ( bboxPolygonFeature ) ; } if ( isVisible ) { const geoBBox = geoPolygon . getGeoBoundingBox ( ) as GeoBox ; const geoBBoxCornerArray = [ ] ; [ new GeoCoordinates ( geoBBox ?. south , geoBBox ?. west , 70 ) , new GeoCoordinates ( geoBBox ?. south , geoBBox ?. east , 70 ) , new GeoCoordinates ( geoBBox ?. north , geoBBox ?. east , 70 ) , new GeoCoordinates ( geoBBox ?. north , geoBBox ?. west , 70 ) , new GeoCoordinates ( geoBBox ?. south , geoBBox ?. west , 70 ) ] . forEach ( point => { if ( ! point ) { return ; } geoBBoxCornerArray . push ( [ point . longitude , point . latitude , point . altitude as number ] ) ; } ) ; const centroid = geoPolygon . getCentroid ( ) as GeoCoordinates ; bboxFeature = new MapViewMultiPointFeature ( [ [ centroid . longitude , centroid . latitude , 70 ] ] . concat ( geoBBoxCornerArray ) , { name : "bbox" } ) ; featuresDataSource ?. add ( bboxFeature ) ; bboxPolygonFeature = new MapViewPolygonFeature ( [ geoBBoxCornerArray ] , { name : "bbox" } ) ; featuresDataSource ?. add ( bboxPolygonFeature ) ; } } function addVectorTileDataSource ( map ) { const omvDataSource = new VectorTileDataSource ( { baseUrl : "https://vector.hereapi.com/v2/vectortiles/base/mc" , authenticationCode : apikey } ) ; map . addDataSource ( omvDataSource ) ; return map ; } function addFeaturesDataSource ( map , featureList ) { const featuresDataSource = new FeaturesDataSource ( { name : "featureDataSource" , styleSetName : "geojson" , features : featureList , gatherFeatureAttributes : true } ) ; map . addDataSource ( featuresDataSource ) ; return featuresDataSource ; } function addButton ( gui , name , callback ) { return gui . add ( { [ name ] : callback } , name ) ; } function initGUI ( map , boundsGenerator , viewBoundsDataSource ) { const gui = new GUI ( ) ; gui . width = 350 ; let bounds ; const options = { bbox : false , wrap : false , ppalPointX : 0 , ppalPointY : 0 } ; addButton ( gui , "Draw view bounds polygon" , ( ) => { bounds = boundsGenerator . generate ( ) ; if ( bounds ) { updateBoundsFeatures ( bounds , viewBoundsDataSource ) ; updateBoundingBoxFeatures ( bounds , viewBoundsDataSource , options . bbox ) ; } } ) ; addButton ( gui , "Look at bounds bbox" , ( ) => { map . lookAt ( { bounds : bounds ?. getGeoBoundingBox ( ) } ) ; } ) ; addButton ( gui , "Look at bounds polygon" , ( ) => { map . lookAt ( { bounds } ) ; } ) ; gui . add ( options , "bbox" ) . onChange ( ( enabled ) => { if ( bounds ) { updateBoundingBoxFeatures ( bounds , viewBoundsDataSource , enabled ) ; } } ) . name ( "Show polygon's bbox" ) ; gui . add ( options , "wrap" ) . onChange ( ( enabled ) => { map . tileWrappingEnabled = enabled ; map . update ( ) ; } ) . name ( "Repeat world (planar)" ) ; const ppFolder = gui . addFolder ( "Principal point (NDC)" ) ; ppFolder . add ( options , "ppalPointX" , - 1 , 1 , 0.1 ) . onChange ( ( x ) => { CameraUtils . setPrincipalPoint ( map . camera , { x , y : CameraUtils . getPrincipalPoint ( map . camera ) . y } ) ; map . update ( ) ; } ) . name ( "x" ) ; ppFolder . add ( options , "ppalPointY" , - 1 , 1 , 0.1 ) . onChange ( ( y ) => { CameraUtils . setPrincipalPoint ( map . camera , { x : CameraUtils . getPrincipalPoint ( map . camera ) . x , y } ) ; map . update ( ) ; } ) . name ( "y" ) ; addButton ( gui , "Log camera settings" , ( ) => { console . log ( "target: " , map . target , " tilt: " , map . tilt , " heading: " , map . heading , " zoom: " , map . zoomLevel , " canvassize: " , map . canvas . height , map . canvas . width , "near: " , map . camera . near , "far: " , map . camera . far ) ; } ) ; } export const mapView = initMapView ( "mapCanvas" ) ; const boundsGenerator = new BoundsGenerator ( mapView ) ; const viewBoundsDataSource = addFeaturesDataSource ( mapView , [ ] ) ; initGUI ( mapView , boundsGenerator , viewBoundsDataSource ) ; }