From 7058ffa19dde75c14eb89270c1a57926c0bce4cc Mon Sep 17 00:00:00 2001 From: Aijana Schumann Date: Mon, 31 Aug 2020 13:24:43 +0200 Subject: Add networkMap Add NetworkMap to odlux Issue-ID: CCSDK-2560 Signed-off-by: Aijana Schumann Change-Id: I204bcace9d12f8a26edfa347ee9b7d292c52f030 --- .../apps/networkMapApp/src/utils/mapLayers.ts | 398 +++++++++++++++++++++ .../odlux/apps/networkMapApp/src/utils/mapUtils.ts | 135 +++++++ .../wt/odlux/apps/networkMapApp/src/utils/utils.ts | 25 ++ 3 files changed, 558 insertions(+) create mode 100644 sdnr/wt/odlux/apps/networkMapApp/src/utils/mapLayers.ts create mode 100644 sdnr/wt/odlux/apps/networkMapApp/src/utils/mapUtils.ts create mode 100644 sdnr/wt/odlux/apps/networkMapApp/src/utils/utils.ts (limited to 'sdnr/wt/odlux/apps/networkMapApp/src/utils') diff --git a/sdnr/wt/odlux/apps/networkMapApp/src/utils/mapLayers.ts b/sdnr/wt/odlux/apps/networkMapApp/src/utils/mapLayers.ts new file mode 100644 index 000000000..e11d96493 --- /dev/null +++ b/sdnr/wt/odlux/apps/networkMapApp/src/utils/mapLayers.ts @@ -0,0 +1,398 @@ +/** + * ============LICENSE_START======================================================================== + * ONAP : ccsdk feature sdnr wt odlux + * ================================================================================================= + * Copyright (C) 2020 highstreet technologies GmbH Intellectual Property. All rights reserved. + * ================================================================================================= + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License + * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + * or implied. See the License for the specific language governing permissions and limitations under + * the License. + * ============LICENSE_END========================================================================== + */ + +import * as mapboxgl from 'mapbox-gl'; +import { Feature } from 'model/Feature'; + + +export const addBaseLayers = (map: mapboxgl.Map, selectedPoint: Feature|null, selectedLine: Feature|null) => { + + const boundingBox = map.getBounds(); + map.addSource('lines', { + type: 'geojson', + data: { type: "FeatureCollection", features: [] } + }); + + const features = selectedLine !== null ? [selectedLine] : []; + + map.addSource('selectedLine', { + type: 'geojson', + data: { type: "FeatureCollection", features: features } + }); + + map.addSource('points', { + type: 'geojson', + data: { type: "FeatureCollection", features: [] } + }); + + const selectedPointFeature = selectedPoint !== null ? [selectedPoint] : []; + + + map.addSource('selectedPoints', { + type: 'geojson', + data: { type: "FeatureCollection", features: selectedPointFeature } + + }); + + map.addLayer({ + 'id': 'lines', + 'type': 'line', + 'source': 'lines', + 'layout': { + 'line-join': 'round', + 'line-cap': 'round' + }, + 'paint': { + 'line-color': '#888', + 'line-width': 2 + } + }); + + map.addLayer({ + 'id': 'selectedLine', + 'type': 'line', + 'source': 'selectedLine', + 'layout': { + 'line-join': 'round', + 'line-cap': 'round' + }, + 'paint': { + 'line-color': '#888', + 'line-width': 4 + } + }); + + + + map.addLayer({ + id: 'points', + source: 'points', + type: 'circle', + paint: { + 'circle-color': '#11b4da', + 'circle-radius': 7, + 'circle-stroke-width': 1, + 'circle-stroke-color': '#fff' + } + }); + + map.addLayer({ + id: 'selectedPoints', + source: 'selectedPoints', + type: 'circle', + paint: { + 'circle-color': '#116bda', + 'circle-radius': 9, + 'circle-stroke-width': 1, + 'circle-stroke-color': '#fff' + } + }); + + map.addSource("alarmedPoints", { + type: 'geojson', + data: {type:"FeatureCollection", features:[]} + }) + + map.addLayer({ + id: 'alarmedPoints', + source: 'alarmedPoints', + type: 'circle', + paint: { + 'circle-color': '#CC0000', + 'circle-radius': 9, + 'circle-stroke-width': 1, + 'circle-stroke-color': '#fff' + } + }); +} + +export const removeBaseLayers = (map: mapboxgl.Map) => { + + map.removeLayer("points"); + map.removeLayer("lines"); + map.removeLayer('selectedPoints'); + map.removeLayer('selectedLine'); + + map.removeSource("points"); + map.removeSource("lines"); + map.removeSource('selectedPoints'); + map.removeSource('selectedLine'); +} + +let checkedLayers = false; + +const createFilter = (type:'street lamp'|'high rise building'|'data center', selectedSiteId?:string) =>{ + + return selectedSiteId === undefined ? ['==', 'type', type] : ["all", ['==', 'type', type], ['!=', 'id', selectedSiteId]] +} + +export const showIconLayers = (map: mapboxgl.Map, show: boolean, selectedSiteId?: string) => { + + const zoom = map.getZoom(); + + if(show){ + + if (zoom > 11) { + + const bounds = map.getBounds(); + + if(map.getLayer('points')!== undefined && map.getLayer('point-lamps')===undefined && !checkedLayers){ + + // if sites don't have a type don't change layers to icons + const elements = map.queryRenderedFeatures( undefined,{ + layers: ['points'], filter:['has', 'type'] + }); + checkedLayers=true; + + if(elements.length>0 && elements.length<1000){ + + if (map.getLayer('point-lamps') === undefined) { + map.removeLayer('points'); + + map.setLayoutProperty('selectedPoints', 'visibility', 'none'); + + map.addLayer({ + 'id': 'point-lamps', + 'type': 'symbol', + 'source': 'points', + 'layout': { + 'icon-allow-overlap': true, + 'icon-image': 'lamp', + 'icon-size': 0.1 + + }, + 'filter': createFilter("street lamp", selectedSiteId), + }); + + map.addLayer({ + 'id': 'point-building', + 'type': 'symbol', + 'source': 'points', + 'filter': createFilter("high rise building", selectedSiteId), + 'layout': { + 'icon-allow-overlap': true, + 'icon-image': 'house', + 'icon-size': 0.1 + } + }); + + map.addLayer({ + 'id': 'point-data-center', + 'type': 'symbol', + 'source': 'points', + 'filter': createFilter("data center", selectedSiteId), + 'layout': { + 'icon-allow-overlap': true, + 'icon-image': 'data-center', + 'icon-size': 0.1 + } }); + + map.addLayer({ + id: 'point-remaining', + source: 'points', + type: 'circle', + 'filter': ['==', 'type', ''], + paint: { + 'circle-color': '#11b4da', + 'circle-radius': 7, + 'circle-stroke-width': 1, + 'circle-stroke-color': '#fff' + } + }); + + map.addLayer({ + 'id': 'select-point-lamps', + 'type': 'symbol', + 'source': 'selectedPoints', + 'layout': { + 'icon-allow-overlap': true, + 'icon-image': 'lamp', + 'icon-size': 0.15 + + }, + 'filter': ['==', 'type', 'street lamp'], + }); + + map.addLayer({ + 'id': 'select-point-buildings', + 'type': 'symbol', + 'source': 'selectedPoints', + 'filter': ['==', 'type', 'high rise building'], + 'layout': { + 'icon-allow-overlap': true, + 'icon-image': 'house', + 'icon-size': 0.15 + } + }); + + map.addLayer({ + 'id': 'select-point-data-center', + 'type': 'symbol', + 'source': 'selectedPoints', + 'filter': ['==', 'type', 'data center'], + 'layout': { + 'icon-allow-overlap': true, + 'icon-image': 'data-center', + 'icon-size': 0.15 + } + }); + } + } + } + + } else { + swapLayersBack(map); + } +}else{ + swapLayersBack(map); + +} + +} + +export const swapLayersBack = (map: mapboxgl.Map) =>{ + checkedLayers=false; + if (map.getLayer('points') === undefined) { + + map.setLayoutProperty('selectedPoints', 'visibility', 'visible'); + + map.removeLayer('point-building'); + map.removeLayer('point-lamps'); + map.removeLayer('point-data-center'); + map.removeLayer('point-remaining'); + map.removeLayer('select-point-data-center'); + map.removeLayer('select-point-buildings'); + map.removeLayer('select-point-lamps'); + + + + map.addLayer({ + id: 'points', + source: 'points', + type: 'circle', + paint: { + 'circle-color': '#11b4da', + 'circle-radius': 7, + 'circle-stroke-width': 1, + 'circle-stroke-color': '#fff' + } + }); + + map.moveLayer('points', map.getLayer('selectedPoints').id) + + + } +} + +const addClusterLayers = (map: mapboxgl.Map, data: any) => { + map.addSource('clusters', { + type: 'geojson', + data: data + }); + + map.addSource('selectedLine', { + type: 'geojson', + data: { type: "FeatureCollection", features: [] } + }); + + map.addSource('selectedPoints', { + type: 'geojson', + data: { type: "FeatureCollection", features: [] } + + }); + + map.addLayer({ + id: 'clusters', + type: 'circle', + source: 'clusters', + filter: ['has', 'count'], + paint: { + 'circle-color': [ + 'step', + ['get', 'count'], + '#51bbd6', + 100, + '#f1f075', + 750, + '#f28cb1' + ], + 'circle-radius': [ + 'step', + ['get', 'count'], + 20, + 100, + 30, + 750, + 40 + ] + } + }); + + + map.addLayer({ + id: 'cluster-count', + type: 'symbol', + source: 'clusters', + filter: ['has', 'count'], + layout: { + 'text-field': '{count}', + 'text-font': ['Roboto Bold'], + 'text-size': 12 + } + }); + + map.addLayer({ + 'id': 'selectedLine', + 'type': 'line', + 'source': 'selectedLine', + 'layout': { + 'line-join': 'round', + 'line-cap': 'round' + }, + 'paint': { + 'line-color': '#888', + 'line-width': 4 + } + }); + + map.addLayer({ + id: 'unclustered-points', + source: 'clusters', + filter: ['!', ['has', 'count'],], + type: 'circle', + paint: { + 'circle-color': '#11b4da', + 'circle-radius': 7, + 'circle-stroke-width': 1, + 'circle-stroke-color': '#fff' + } + }); + + map.addLayer({ + id: 'selectedPoints', + source: 'selectedPoints', + type: 'circle', + paint: { + 'circle-color': '#116bda', + 'circle-radius': 9, + 'circle-stroke-width': 1, + 'circle-stroke-color': '#fff' + } + }); + +} \ No newline at end of file diff --git a/sdnr/wt/odlux/apps/networkMapApp/src/utils/mapUtils.ts b/sdnr/wt/odlux/apps/networkMapApp/src/utils/mapUtils.ts new file mode 100644 index 000000000..34cdc0638 --- /dev/null +++ b/sdnr/wt/odlux/apps/networkMapApp/src/utils/mapUtils.ts @@ -0,0 +1,135 @@ +/** + * ============LICENSE_START======================================================================== + * ONAP : ccsdk feature sdnr wt odlux + * ================================================================================================= + * Copyright (C) 2020 highstreet technologies GmbH Intellectual Property. All rights reserved. + * ================================================================================================= + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License + * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + * or implied. See the License for the specific language governing permissions and limitations under + * the License. + * ============LICENSE_END========================================================================== + */ + +const EARTHRADIUSM = 6378137; + +type updatedCoordinates = { south: number, west: number, north: number, east: number }; + + + + +export const addDistance = (south: number, west: number, north: number, east: number, distanceKm: number): updatedCoordinates => { + + const distanceInM = distanceKm * 1000; + + const dLat = distanceInM / EARTHRADIUSM; + const dLon = distanceInM / (EARTHRADIUSM * Math.cos(Math.PI * (north + south) / 360)); + + const latOffset = dLat * 180 / Math.PI; + const lonOffset = dLon * 180 / Math.PI; + + const newEast = checkLongitude(east + lonOffset); + const newWest = checkLongitude(west - lonOffset); + const newNorth = checkLatitude(north + latOffset); + const newSouth = checkLatitude(south - latOffset); + + return { east: newEast, north: newNorth, south: newSouth, west: newWest }; + +} + + +//taken from https://www.movable-type.co.uk/scripts/latlong.html +export const calculateMidPoint = (lat1: number, lon1: number, lat2: number, lon2: number) =>{ + + const dLon = degrees_to_radians(lon2 - lon1); + + //convert to radians + lat1 = degrees_to_radians(lat1); + lat2 = degrees_to_radians(lat2); + lon1 = degrees_to_radians(lon1); + + const Bx = Math.cos(lat2) * Math.cos(dLon); + const By = Math.cos(lat2) * Math.sin(dLon); + const lat3 = Math.atan2(Math.sin(lat1) + Math.sin(lat2), Math.sqrt((Math.cos(lat1) + Bx) * (Math.cos(lat1) + Bx) + By * By)); + const lon3 = lon1 + Math.atan2(By, Math.cos(lat1) + Bx); + + return [radians_to_degrees(lon3), radians_to_degrees(lat3)]; +} + + +export const LatLonToDMS = (value:number, isLon:boolean=false) =>{ + const absoluteValue = Math.abs(value); + const d = Math.floor(absoluteValue); + const m = Math.floor((absoluteValue -d)* 60); + const s = (absoluteValue - d - m / 60 ) * 3600; + const dms=`${d}° ${m}' ${s.toFixed(2)}"` + + const sign = Math.sign(value); + + if(isLon){ + return (sign === -1 || sign === -0 ) ? dms + " W" : dms + " E"; + }else{ + return (sign === -1 || sign === -0 ) ? dms + " S" : dms + " N"; + } +} + +// Because features come from tiled vector data, feature geometries may be split +// or duplicated across tile boundaries and, as a result, features may appear +// multiple times in query results. + +//taken from https://docs.mapbox.com/mapbox-gl-js/example/filter-features-within-map-view/ + +export const getUniqueFeatures = (array: mapboxgl.MapboxGeoJSONFeature[], comparatorProperty:string) =>{ + var existingFeatureKeys: any = {}; + + var uniqueFeatures = array.filter(function(el) { + if (existingFeatureKeys[el.properties![comparatorProperty]]) { + return false; + } else { + existingFeatureKeys[el.properties![comparatorProperty]] = true; + return true; + } + }); + + return uniqueFeatures; + } + +const radians_to_degrees = (radians:number) =>{ + + var pi = Math.PI; + return radians * (180/pi); +} + + const degrees_to_radians = (degrees: number) => + { + return degrees * (Math.PI/180); + } + + +const checkLatitude = (lat: number) => { + + if (lat > 90) + return 90; + else if (lat < -90) + return -90; + else + return lat; + +} + +const checkLongitude = (lon: number) => { + if (lon > 180) + return 180; + else if (lon < -180) + return -180; + else + return lon; +} + + + diff --git a/sdnr/wt/odlux/apps/networkMapApp/src/utils/utils.ts b/sdnr/wt/odlux/apps/networkMapApp/src/utils/utils.ts new file mode 100644 index 000000000..20c4e5aad --- /dev/null +++ b/sdnr/wt/odlux/apps/networkMapApp/src/utils/utils.ts @@ -0,0 +1,25 @@ +/** + * ============LICENSE_START======================================================================== + * ONAP : ccsdk feature sdnr wt odlux + * ================================================================================================= + * Copyright (C) 2020 highstreet technologies GmbH Intellectual Property. All rights reserved. + * ================================================================================================= + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License + * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + * or implied. See the License for the specific language governing permissions and limitations under + * the License. + * ============LICENSE_END========================================================================== + */ + +import { link } from "../model/link"; +import { site } from "../model/site"; + + +export function isSite(data: link | site): data is site { + return (data as site).geoLocation !== undefined; +} \ No newline at end of file -- cgit 1.2.3-korg