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, PropTypes} from 'react';
22 import {geoAlbersUsa, geoEquirectangular, geoPath} from 'd3-geo';
23 import {feature, mesh} from 'topojson';
32 } from './MapConstants.js';
33 import usMapJson from './mapJson/usJson.json';
34 import worldMapJson from './mapJson/worldJson.json';
36 class TopographicMap extends Component {
38 width: PropTypes.number,
39 height: PropTypes.number,
40 pointArray: PropTypes.array,
41 currentProjection: PropTypes.string
44 static defaultProps = {
48 currentProjection: PROJECTION_TYPES.ALBERS_USA
55 landFeatures: undefined,
56 boundaryMesh: undefined,
60 this.setCurrentProjection = this.setCurrentProjection.bind(this);
61 this.processAndRenderMapData = this.processAndRenderMapData.bind(this);
62 this.generateLandFeatures = this.generateLandFeatures.bind(this);
63 this.generateBoundaryMesh = this.generateBoundaryMesh.bind(this);
64 this.generatePlotPointArray = this.generatePlotPointArray.bind(this);
65 this.extractNestedObjectInJson = this.extractNestedObjectInJson.bind(this);
66 this.areArraysEqual = this.areArraysEqual.bind(this);
68 this.setCurrentProjection(props.currentProjection);
69 this.projection.translate([this.props.width / 2, this.props.height / 2]);
70 this.path = geoPath().projection(this.projection);
71 this.didProjectionTypeChange = true;
72 this.isMapMounted = false;
75 componentWillReceiveProps(nextProps) {
76 if (!this.areArraysEqual(this.props.pointArray, nextProps.pointArray)) {
77 if (this.props.currentProjection !== nextProps.currentProjection) {
78 this.didProjectionTypeChange = true;
79 this.setCurrentProjection(nextProps.currentProjection);
81 if (this.isMapMounted) {
82 this.processAndRenderMapData(nextProps.pointArray);
88 this.isMapMounted = true;
89 this.processAndRenderMapData(this.props.pointArray);
92 setCurrentProjection(projectionType) {
93 switch (projectionType) {
94 case PROJECTION_TYPES.ALBERS_USA:
95 this.projection = geoAlbersUsa();
98 case PROJECTION_TYPES.EQUIRECTANGULAR:
99 this.projection = geoEquirectangular();
103 // TODO -> FE logging should be a thing at some point. Maybe a log call
109 processAndRenderMapData(plotPointArray) {
110 let landFeatures = this.state.landFeatures;
111 let boundaryMesh = this.state.boundaryMesh;
112 let plotPoints = this.state.plotPoints;
114 switch (this.props.currentProjection) {
115 case PROJECTION_TYPES.ALBERS_USA:
116 if (this.didProjectionTypeChange) {
118 this.generateLandFeatures(usMapJson,
119 MAP_OBJECT_KEYS.ALBERS_USA_LAND_KEYS);
121 this.generateBoundaryMesh(usMapJson,
122 MAP_OBJECT_KEYS.ALBERS_USA_BOUNDARY_KEYS);
123 this.didProjectionTypeChange = false;
125 plotPoints = this.generatePlotPointArray(plotPointArray);
127 case PROJECTION_TYPES.EQUIRECTANGULAR:
128 if (this.didProjectionTypeChange) {
130 this.generateLandFeatures(worldMapJson,
131 MAP_OBJECT_KEYS.EQUIRECTANGULAR_LAND_KEYS);
133 this.generateBoundaryMesh(worldMapJson,
134 MAP_OBJECT_KEYS.EQUIRECTANGULAR_BOUNDARY_KEYS);
135 this.didProjectionTypeChange = false;
137 plotPoints = this.generatePlotPointArray(plotPointArray);
141 // TODO -> FE logging should be a thing at some point. Maybe a log call
146 this.setState(() => {
148 landFeatures: landFeatures,
149 boundaryMesh: boundaryMesh,
150 plotPoints: plotPoints
155 generateLandFeatures(jsonData, featureKeys) {
156 let featureType = this.extractNestedObjectInJson(jsonData, featureKeys);
157 let landFeature = undefined;
158 if (featureType !== undefined) {
159 let landFeaturePath = this.path(feature(jsonData, featureType));
160 let landFeatureProps = {
161 className: 'land-features',
163 key: LAND_FEATURE_KEY
166 React.createElement(PLOT_POINT_SHAPES.PATH, landFeatureProps);
171 generateBoundaryMesh(jsonData, boundaryKeys) {
172 let boundaryType = this.extractNestedObjectInJson(jsonData, boundaryKeys);
173 let boundary = undefined;
174 if (boundaryType !== undefined) {
175 let boundaryPath = this.path(mesh(jsonData, boundaryType, (a, b) => {
178 let boundaryProps = {
179 className: 'boundary-mesh',
181 key: BOUNDARY_MESH_KEY
183 boundary = React.createElement(PLOT_POINT_SHAPES.PATH, boundaryProps);
188 generatePlotPointArray(pointArray) {
189 let generatedPoints = [];
190 if (pointArray !== undefined && pointArray.length > 0) {
191 generatedPoints = pointArray.map((longLat, index) => {
192 let projectedLongLat = this.projection(
193 [longLat.longitude, longLat.latitude]);
194 let plotPointProps = {
195 className: 'plot-point',
197 cx: projectedLongLat[0],
198 cy: projectedLongLat[1],
199 key: PLOT_POINT_KEY_BASE + index,
201 return React.createElement(PLOT_POINT_SHAPES.CIRCLE, plotPointProps);
204 return generatedPoints;
208 let {landFeatures, boundaryMesh, plotPoints} = this.state;
209 let {width, height} = this.props;
212 <div width={width} height={height}>
213 <svg width={width} height={height}>
224 extractNestedObjectInJson(jsonData, keysArray) {
225 let subObject = undefined;
226 if (jsonData !== undefined && keysArray !== undefined) {
227 subObject = jsonData[keysArray[0]];
228 if (subObject !== undefined) {
229 for (let i = 1; i < keysArray.length; i++) {
230 subObject = subObject[keysArray[i]];
237 areArraysEqual(arrayOne, arrayTwo) {
238 if (arrayOne.length !== arrayTwo.length) {
241 for (let i = 0; i < arrayOne.length; i++) {
242 if (arrayOne[i] instanceof Array && arrayTwo instanceof Array) {
243 if (!this.areArraysEqual(arrayOne[i], arrayTwo[i])) {
247 else if (arrayOne[i] !== arrayTwo[i]) {
255 export default TopographicMap;