2 * ============LICENSE_START=======================================================
4 * ================================================================================
5 * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved.
6 * Copyright © 2017-2018 Amdocs
7 * ================================================================================
8 * Licensed under the Apache License, Version 2.0 (the "License");
9 * you may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
12 * http://www.apache.org/licenses/LICENSE-2.0
14 * Unless required by applicable law or agreed to in writing, software
15 * distributed under the License is distributed on an "AS IS" BASIS,
16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 * See the License for the specific language governing permissions and
18 * limitations under the License.
19 * ============LICENSE_END=========================================================
21 import React, {Component} from 'react';
22 import { PropTypes } from 'prop-types';
23 import {geoAlbersUsa, geoEquirectangular, geoPath} from 'd3-geo';
24 import {feature, mesh} from 'topojson';
33 } from './MapConstants.js';
34 import usMapJson from './mapJson/usJson.json';
35 import worldMapJson from './mapJson/worldJson.json';
37 class TopographicMap extends Component {
39 width: PropTypes.number,
40 height: PropTypes.number,
41 pointArray: PropTypes.array,
42 currentProjection: PropTypes.string
45 static defaultProps = {
49 currentProjection: PROJECTION_TYPES.ALBERS_USA
56 landFeatures: undefined,
57 boundaryMesh: undefined,
61 this.setCurrentProjection = this.setCurrentProjection.bind(this);
62 this.processAndRenderMapData = this.processAndRenderMapData.bind(this);
63 this.generateLandFeatures = this.generateLandFeatures.bind(this);
64 this.generateBoundaryMesh = this.generateBoundaryMesh.bind(this);
65 this.generatePlotPointArray = this.generatePlotPointArray.bind(this);
66 this.extractNestedObjectInJson = this.extractNestedObjectInJson.bind(this);
67 this.areArraysEqual = this.areArraysEqual.bind(this);
69 this.setCurrentProjection(props.currentProjection);
70 this.projection.translate([this.props.width / 2, this.props.height / 2]);
71 this.path = geoPath().projection(this.projection);
72 this.didProjectionTypeChange = true;
73 this.isMapMounted = false;
76 componentWillReceiveProps(nextProps) {
77 if (!this.areArraysEqual(this.props.pointArray, nextProps.pointArray)) {
78 if (this.props.currentProjection !== nextProps.currentProjection) {
79 this.didProjectionTypeChange = true;
80 this.setCurrentProjection(nextProps.currentProjection);
82 if (this.isMapMounted) {
83 this.processAndRenderMapData(nextProps.pointArray);
89 this.isMapMounted = true;
90 this.processAndRenderMapData(this.props.pointArray);
93 setCurrentProjection(projectionType) {
94 switch (projectionType) {
95 case PROJECTION_TYPES.ALBERS_USA:
96 this.projection = geoAlbersUsa();
99 case PROJECTION_TYPES.EQUIRECTANGULAR:
100 this.projection = geoEquirectangular();
104 // TODO -> FE logging should be a thing at some point. Maybe a log call
110 processAndRenderMapData(plotPointArray) {
111 let landFeatures = this.state.landFeatures;
112 let boundaryMesh = this.state.boundaryMesh;
113 let plotPoints = this.state.plotPoints;
115 switch (this.props.currentProjection) {
116 case PROJECTION_TYPES.ALBERS_USA:
117 if (this.didProjectionTypeChange) {
119 this.generateLandFeatures(usMapJson,
120 MAP_OBJECT_KEYS.ALBERS_USA_LAND_KEYS);
122 this.generateBoundaryMesh(usMapJson,
123 MAP_OBJECT_KEYS.ALBERS_USA_BOUNDARY_KEYS);
124 this.didProjectionTypeChange = false;
126 plotPoints = this.generatePlotPointArray(plotPointArray);
128 case PROJECTION_TYPES.EQUIRECTANGULAR:
129 if (this.didProjectionTypeChange) {
131 this.generateLandFeatures(worldMapJson,
132 MAP_OBJECT_KEYS.EQUIRECTANGULAR_LAND_KEYS);
134 this.generateBoundaryMesh(worldMapJson,
135 MAP_OBJECT_KEYS.EQUIRECTANGULAR_BOUNDARY_KEYS);
136 this.didProjectionTypeChange = false;
138 plotPoints = this.generatePlotPointArray(plotPointArray);
142 // TODO -> FE logging should be a thing at some point. Maybe a log call
147 this.setState(() => {
149 landFeatures: landFeatures,
150 boundaryMesh: boundaryMesh,
151 plotPoints: plotPoints
156 generateLandFeatures(jsonData, featureKeys) {
157 let featureType = this.extractNestedObjectInJson(jsonData, featureKeys);
158 let landFeature = undefined;
159 if (featureType !== undefined) {
160 let landFeaturePath = this.path(feature(jsonData, featureType));
161 let landFeatureProps = {
162 className: 'land-features',
164 key: LAND_FEATURE_KEY
167 React.createElement(PLOT_POINT_SHAPES.PATH, landFeatureProps);
172 generateBoundaryMesh(jsonData, boundaryKeys) {
173 let boundaryType = this.extractNestedObjectInJson(jsonData, boundaryKeys);
174 let boundary = undefined;
175 if (boundaryType !== undefined) {
176 let boundaryPath = this.path(mesh(jsonData, boundaryType, (a, b) => {
179 let boundaryProps = {
180 className: 'boundary-mesh',
182 key: BOUNDARY_MESH_KEY
184 boundary = React.createElement(PLOT_POINT_SHAPES.PATH, boundaryProps);
189 generatePlotPointArray(pointArray) {
190 let generatedPoints = [];
191 if (pointArray !== undefined && pointArray.length > 0) {
192 generatedPoints = pointArray.map((longLat, index) => {
193 let projectedLongLat = this.projection(
194 [longLat.longitude, longLat.latitude]);
195 let plotPointProps = {
196 className: 'plot-point',
198 cx: projectedLongLat[0],
199 cy: projectedLongLat[1],
200 key: PLOT_POINT_KEY_BASE + index,
202 return React.createElement(PLOT_POINT_SHAPES.CIRCLE, plotPointProps);
205 return generatedPoints;
209 let {landFeatures, boundaryMesh, plotPoints} = this.state;
210 let {width, height} = this.props;
213 <div width={width} height={height}>
214 <svg width={width} height={height}>
225 extractNestedObjectInJson(jsonData, keysArray) {
226 let subObject = undefined;
227 if (jsonData !== undefined && keysArray !== undefined) {
228 subObject = jsonData[keysArray[0]];
229 if (subObject !== undefined) {
230 for (let i = 1; i < keysArray.length; i++) {
231 subObject = subObject[keysArray[i]];
238 areArraysEqual(arrayOne, arrayTwo) {
239 if (arrayOne.length !== arrayTwo.length) {
242 for (let i = 0; i < arrayOne.length; i++) {
243 if (arrayOne[i] instanceof Array && arrayTwo instanceof Array) {
244 if (!this.areArraysEqual(arrayOne[i], arrayTwo[i])) {
248 else if (arrayOne[i] !== arrayTwo[i]) {
256 export default TopographicMap;