/**
* A class to mediate between the different patterns and handle their objects.
*
* @class MapDesign (MapDesign)
*/
var MapDesign = function() {
this.featureToDisplay = "ha_dwellin"; //must set with UI
this.selectedValue; //toAdd
this.vectorSourceTypeName = "CGIS:householdsPGIS";
this.wardSourceTypeName = "CGIS:wardsPGIS";
this.vectorSource;
this.wardsSource;
this.symbolSource;
this.tileLayer;
//Layers are made object (not primitives) to pass as reference to other classes
this.wardsVectorLayer = { layer: 'value' };
this.featureLayer = { layer: 'value' };
this.symbolLayer = { layer: 'value' };
this.numClasses = 5;
this.readyLayerCount = 0;
this.map;
this.mapDisplayType;
this.defaultMap;
this.dotDensity;
this.chloro;
this.heatmap;
this.uniqueAttributeValues = [];
this.vectorLayerClasses = [];
this.colorPerClass = [];
this.propsymbol;
this.wizardMapArray = []; //Array to hold concrete products.
this.colorSchemeArray = [];
this.colorSchemeIterationCounter = 0;
this.ccMapArray = [];
this.classAndClassficationIterationCounter = 0;
this.loadSources();
this.concreteMapBuilder;
this.classifyArray = [];
this.equal_Interval;
this.quantile;
this.naturalBreaks;
this.classifiedArray = [];
this.numberOfClasses = 5;
this.mapValuesKeyNames = [];
this.currentMapIndex = 0;
this.currentClassificationMethod = "QUANTILE";
this.currentStandardisationMethod = "area";
this.standardisationObject;
};
/**
* Standardises numerical data
*
* @param {string} method The standardisation method to be used
*/
MapDesign.prototype.standardise = function(method) {
//Code to call strategy method
this.standardisationObject = new StandardiseMethod();
var ratio = "ratio";
var rate = "rate";
var density = "density";
var area = "area";
switch (method) {
case ratio:
// standardisation.ratioBasedStandardisation(this.vectorSource, this.wardsSource, this.keyName, );
break;
case rate:
// standardisation.rateBasedStandardisation(this.vectorSource, this.wardsSource, this.keyName, );
break;
case density:
this.standardisationObject.densityBasedStandardisation(this.vectorSource, this.wardsSource, this.mapValuesKeyNames, this.currentMapIndex);
break;
case area:
this.standardisationObject.areaBasedStandardisation(this.vectorSource, this.wardsSource, this.mapValuesKeyNames, this.currentMapIndex);
break;
default:
this.standardisationObject.defaultStandardisation(this.vectorSource, this.wardsSource, this.mapValuesKeyNames, this.currentMapIndex);
break;
}
};
// Creates an array of unique values for a attribute which's name is passed
MapDesign.prototype.getContinousValues = function(attributeTitle) {
var tempVectorLayerClasses = [];
this.vectorSource.forEachFeature(function(feature) {
tempVectorLayerClasses.push(feature.get(attributeTitle));
});
if (tempVectorLayerClasses.length <= 0) {
console.log("No attribute values found");
}
return tempVectorLayerClasses;
}
/**
* Classifies numerical data
*
* @param {ol.source} source Specifies the source
* @param {string} propertyKeyName Specifies the name of the property key name
* @param {string} method Specifies the method to be used
* @param {number} numberOfClasses Specifies the number of classes
* @param {number} mapType Specifies the type of map
*/
MapDesign.prototype.classify = function(source, propertyKeyName, method, numberOfClasses, mapType) {
//Code to classify the data
var method1 = "EQUALINTERVAL";
var method2 = "QUANTILE";
var method3 = "NATURALBREAKS";
var boundary = true; //true if classification refers to boundary , false if classification refers to index
//getting the bounds of each classification method;
switch (method.toUpperCase()) {
case method1:
if (mapType == 1) {
this.equal_Interval = new EqualInterval();
this.classifyArray = this.equal_Interval.EqualIntervalExecute(source, propertyKeyName, numberOfClasses);
boundary = true;
} else {
this.equal_Interval = new EqualInterval(); /* this.wardsSource, this.mapValuesKeyNames[this.currentMapIndex], this.currentClassificationMethod, sessionStorage.getItem('numClasses')*/
this.classifiedArray = this.equal_Interval.EqualIntervalExecuteWards(this.wardsSource, this.mapValuesKeyNames, this.currentMapIndex, numberOfClasses);
return;
}
break;
case method2:
if (mapType == 1) {
this.quantile = new Quantile();
this.classifyArray = this.quantile.QuantileExecute(source, propertyKeyName, numberOfClasses);
boundary = false;
} else {
this.quantile = new Quantile(); /* this.wardsSource, this.mapValuesKeyNames[this.currentMapIndex], this.currentClassificationMethod, sessionStorage.getItem('numClasses')*/
this.classifyArray = this.quantile.QuantileExecuteWards(this.wardsSource, this.mapValuesKeyNames, this.currentMapIndex, numberOfClasses);
boundary = false;
var count = this.classifyArray[0];
var counter = 0;
this.classifiedArray = [];
for (var k = 0; k < this.classifyArray.length; k++) {
count = parseInt(this.classifyArray[k]);
for (counter; counter < count; counter++) {
this.classifiedArray.push(k);
//setVectorLayerClasses[counter] = true;
}
counter = count;
}
return;
}
break;
case method3:
if (mapType == 1) {
this.naturalBreaks = new NaturalBreaks();
this.classifiedArray = this.naturalBreaks.NaturalBreaksExecute(source, propertyKeyName, numberOfClasses);
} else {
this.naturalBreaks = new NaturalBreaks();
this.classifiedArray = this.naturalBreaks.NaturalBreaksExecuteWards(this.wardsSource, this.mapValuesKeyNames, this.currentMapIndex, numberOfClasses);
return;
}
break;
default:
/* this.equal_Interval = new EqualInterval();
this.classifyArray = this.equal_Interval.EqualIntervalExecute(source, propertyKeyName, numberOfClasses);
console.log("default " + this.classifyArray);
boundary = true;*/
this.quantile = new Quantile(); /* this.wardsSource, this.mapValuesKeyNames[this.currentMapIndex], this.currentClassificationMethod, sessionStorage.getItem('numClasses')*/
this.classifyArray = this.quantile.QuantileExecuteWards(this.wardsSource, this.mapValuesKeyNames, this.currentMapIndex, numberOfClasses);
boundary = false;
var count = this.classifyArray[0];
var counter = 0;
this.classifiedArray = [];
for (var k = 0; k < this.classifyArray.length; k++) {
count = parseInt(this.classifyArray[k]);
for (counter; counter < count; counter++) {
this.classifiedArray.push(k);
//setVectorLayerClasses[counter] = true;
}
counter = count;
}
break;
}
var tempVectorLayerClasses = [];
tempVectorLayerClasses = this.getContinousValues(this.featureToDisplay);
var setVectorLayerClasses = new Array(tempVectorLayerClasses.length);
for (var k = 0; k < setVectorLayerClasses.length; k++) {
setVectorLayerClasses[k] = false;
}
if (tempVectorLayerClasses.length != this.classifyArray.length) { // classify array returned is either bounded or index and needs to be manipulated.
if (boundary) {
for (var i = 0; i < tempVectorLayerClasses.length; i++) {
for (var k = 0; k < this.classifyArray.length; k++) {
if (tempVectorLayerClasses[i] <= this.classifyArray[k] && setVectorLayerClasses[i] == false) {
setVectorLayerClasses[i] = true;
var old = tempVectorLayerClasses[i];
tempVectorLayerClasses[i] = k;
}
}
}
} else { //classify array uses indexes
var count = this.classifyArray[0];
var counter = 0;
for (var k = 0; k < this.classifyArray.length; k++) {
count = parseInt(this.classifyArray[k]);
for (counter; counter < count; counter++) {
tempVectorLayerClasses[counter] = k;
//setVectorLayerClasses[counter] = true;
}
counter = count;
}
}
this.classifiedArray = [];
this.classifiedArray = tempVectorLayerClasses;
var oldArray = this.getContinousValues(this.featureToDisplay);
return tempVectorLayerClasses;
}
return tempVectorLayerClasses;
};
MapDesign.prototype.render = function() {
//render code
};
/**
* Gets the vector source.
*
* @return {ol.source} The vector source.
*/
MapDesign.prototype.getVectorSource = function() {
return this.vectorSource;
};
/**
* Gets the wards source.
*
* @return {ol.source} The wards source.
*/
MapDesign.prototype.getWardsSource = function() {
return this.wardsSource;
};
/**
* Sets the vector source.
*
* @param {ol.source} source The source
*/
MapDesign.prototype.setVectorSource = function(source) {
this.vectorSource = source;
};
/**
* Sets the ward source.
*
* @param {ol.source} source The source
*/
MapDesign.prototype.setWardsSource = function(source) {
this.wardsSource = source;
};
/**
* Loads the sources from the dataset linked to GeoServer.
*/
MapDesign.prototype.loadSources = function() {
if (this.vectorSource == undefined) {
this.createVectorSource(this.vectorSourceTypeName); //Put in the data set as param, using default for now.
}
if (this.wardsSource == undefined) {
this.creatwardsSource(this.wardSourceTypeName);
}
this.initializeMap();
this.createWardLayer();
this.createFeatureLayer();
//this.createTileLayer();
//this.map.addLayer(this.wardsVectorLayer);
//this.map.addLayer(this.featureLayer);
if (this.vectorSource.getState() != 'ready') {
this.vectorSource.on('change', function(evt) {
var source = evt.target;
var mapToCreate;
if (source.getState() == 'ready') {
this.defaultMap = new defaultMapCreator();
this.dotDensity = new DotDensityCreator();
this.chloro = new chloroplethCreator();
this.heatmap = new HeatMapCreator();
this.propsymbol = new PropSymbolCreator();
}
});
} else {
if (this.defaultMap == undefined) {
this.defaultMap = new defaultMapCreator();
this.dotDensity = new DotDensityCreator();
this.chloro = new chloroplethCreator();
this.heatmap = new HeatMapCreator();
this.propsymbol = new PropSymbolCreator();
}
}
};
/**
* Determines if source's are ready, and has been fully loaded on the user side.
*
* @param {number} mapType The map type
* @param {number} pageToLoad The page to load
* @param {Function} callback The callback
* @return {boolean} True if source ready, False otherwise.
*/
MapDesign.prototype.isSourceReady = function(mapType, pageToLoad, callback) {
this.removeLayers();
if (this.vectorSource != undefined && this.vectorSource.getState() == 'ready') {
this.createWardLayer();
//this.calculateColorClass(5); //Get classcount from DOM / local (implies writing set function)
// if not default map loadWards:
if (mapType != 0) {
this.loadWards();
// this.createWardLayer();
this.createVectorSource(this.vectorSourceTypeName);
this.createFeatureLayer();
}
this.recursiveCreate(mapType, pageToLoad, callback);
return true;
} else {
return false;
}
};
/**
* Waits till features ready before creating the map. It uses the factory design patterns as well as stratergy patterns to classify the map
*
* @param {number} mapType The map type
* @param {number} pageToLoad The page to load
* @param {Function} callback The callback
*/
MapDesign.prototype.recursiveCreate = function(mapType, pageToLoad, callback) {
if (mapType != 0 && (this.wardsSource == undefined || this.vectorSource == undefined || this.wardsSource.getFeatures().length <= 0 || this.vectorSource.getFeatures().length <= 0)) {
// console.log("A source is not ready, waiting 1s and retrying");
// console.log("WSc=" + this.wardsSource.getFeatures().length + "VSc=" + this.vectorSource.getFeatures().length);
var that = this;
setTimeout(function() {
that.recursiveCreate(mapType, pageToLoad, callback);
}, 1000);
return;
}
if (mapType == 1 || mapType == 3 || mapType == 4) {
this.getUniqueDiscreteValues(this.featureToDisplay);
//this.calculateColorClass(this.numberOfClasses);
}
this.mapValuesKeyNames.push("");
if (mapType != 0) {
this.currentMapIndex = this.currentMapIndex + 1;
}
var currMap;
var mapZoomFactor = 1.3;
if (pageToLoad == 5) { //final map to be generated
if (sessionStorage.getItem('isDiscrete') == 'true') {
isDiscrete = true;
} else {
isDiscrete = false;
}
if (isDiscrete == false) {
if (sessionStorage.getItem('classificationAndClassSelected') == "0" || sessionStorage.getItem('classificationAndClassSelected') == "1" ||
sessionStorage.getItem('classificationAndClassSelected') == "2") {
this.currentClassificationMethod = "EQUALINTERVAL";
} else if (sessionStorage.getItem('classificationAndClassSelected') == "3" || sessionStorage.getItem('classificationAndClassSelected') == "4" || sessionStorage.getItem('classificationAndClassSelected') == "5") {
this.currentClassificationMethod = "QUANTILE";
} else if (sessionStorage.getItem('classificationAndClassSelected') == "6" || sessionStorage.getItem('classificationAndClassSelected') == "7" || sessionStorage.getItem('classificationAndClassSelected') == "8") {
this.currentClassificationMethod = "NATURALBREAKS";
}
if (sessionStorage.getItem('classificationAndClassSelected') == "0" || sessionStorage.getItem('classificationAndClassSelected') == "3" || sessionStorage.getItem('classificationAndClassSelected') == "6") {
var doStandardise = true;
if (doStandardise && mapType != 1 && mapType != 2) {
this.standardise(this.currentStandardisationMethod); //GET FROM DOM
if (!isDiscrete) {
this.classify(this.wardsSource, this.mapValuesKeyNames[this.currentMapIndex], this.currentClassificationMethod, sessionStorage.getItem('numClasses'), parseInt(sessionStorage.getItem('mapTypeSelected')));
}
} else {
if (mapType == 1) {
this.classify(this.vectorSource, this.featureToDisplay, this.currentClassificationMethod, sessionStorage.getItem('numClasses'), parseInt(sessionStorage.getItem('mapTypeSelected')));
};
}
this.generateColorSchemes(sessionStorage.getItem('numClasses'), parseInt(sessionStorage.getItem('colorSchemeSelected')));
} else if (sessionStorage.getItem('classificationAndClassSelected') == "1" || sessionStorage.getItem('classificationAndClassSelected') == "4" || sessionStorage.getItem('classificationAndClassSelected') == "7") {
var doStandardise = true;
if (doStandardise && mapType != 1 && mapType != 2) {
this.standardise(this.currentStandardisationMethod); //GET FROM DOM
if (!isDiscrete) {
this.classify(this.wardsSource, this.mapValuesKeyNames[this.currentMapIndex], this.currentClassificationMethod, 5, parseInt(sessionStorage.getItem('mapTypeSelected')));
}
} else {
if (mapType == 1) {
this.classify(this.vectorSource, this.featureToDisplay, this.currentClassificationMethod, 5, parseInt(sessionStorage.getItem('mapTypeSelected')));
};
}
this.generateColorSchemes(5, parseInt(sessionStorage.getItem('colorSchemeSelected')));
} else if (sessionStorage.getItem('classificationAndClassSelected') == "2" || sessionStorage.getItem('classificationAndClassSelected') == "5" || sessionStorage.getItem('classificationAndClassSelected') == "8") {
var doStandardise = true;
if (doStandardise && mapType != 1 && mapType != 2) {
this.standardise(this.currentStandardisationMethod); //GET FROM DOM
if (!isDiscrete) {
this.classify(this.wardsSource, this.mapValuesKeyNames[this.currentMapIndex], this.currentClassificationMethod, 7, parseInt(sessionStorage.getItem('mapTypeSelected')));
}
} else {
if (mapType == 1) {
this.classify(this.vectorSource, this.featureToDisplay, this.currentClassificationMethod, 7, parseInt(sessionStorage.getItem('mapTypeSelected')));
};
}
this.generateColorSchemes(7, parseInt(sessionStorage.getItem('colorSchemeSelected')));
}
} else {
this.generateColorSchemes(5, parseInt(sessionStorage.getItem('colorSchemeSelected')));
this.numberOfClasses = 5;
}
if (isDiscrete == true && mapType == 1) {
var mouseWheelInt = new ol.interaction.MouseWheelZoom();
var dragPanInt = new ol.interaction.DragPan();
this.colorSchemeArray[parseInt(sessionStorage.getItem("colorSchemeSelected"))].addInteraction(mouseWheelInt);
this.colorSchemeArray[parseInt(sessionStorage.getItem("colorSchemeSelected"))].addInteraction(dragPanInt);
mouseWheelInt.setActive(true);
dragPanInt.setActive(true);
this.map.setTarget("");
this.colorSchemeArray[parseInt(sessionStorage.getItem("colorSchemeSelected"))].setTarget("map");
this.generateColorSchemes(5, parseInt(sessionStorage.getItem('colorSchemeSelected')));
currMap = this.colorSchemeArray[parseInt(sessionStorage.getItem("colorSchemeSelected"))];
if (currMap != undefined && currMap.getView().getZoom() == 3) {
var extent = this.wardsSource.getExtent();
currMap.getView().fit(extent, currMap.getSize());
currMap.getView().setZoom(currMap.getView().getZoom() * 1.015);
}
} else {
switch (parseInt(mapType)) {
case 1:
this.dotDensity.createMap(this.map, this.vectorSource, this.colorPerClass, this.featureToDisplay, this.featureLayer, this.selectedValue, isDiscrete, this.numberOfClasses, this.classifiedArray);
this.map.addLayer(this.wardsVectorLayer.layer);
break;
case 2:
this.heatmap.createMap(this.map, this.vectorSource, this.featureLayer);
this.map.addLayer(this.wardsVectorLayer.layer);
break;
case 3:
this.chloro.createMap(this.map, this.vectorSource, this.wardsSource, this.colorPerClass, this.numberOfClasses, this.featureToDisplay, this.selectedValue, this.wardsVectorLayer, this.featureLayer, this.classifiedArray, this.mapValuesKeyNames[this.currentMapIndex], isDiscrete);
break;
case 4:
this.propsymbol.createMap(this.map, this.vectorSource, this.wardsSource, this.symbolSource, this.colorPerClass, this.featureToDisplay, this.selectedValue, this, this.symbolLayer, isDiscrete, this.mapValuesKeyNames[this.currentMapIndex]);
this.map.addLayer(this.wardsVectorLayer.layer);
break;
}
currMap = this.map;
if (currMap != undefined && currMap.getView().getZoom() == 3) {
var extent = this.wardsSource.getExtent();
currMap.getView().fit(extent, currMap.getSize());
currMap.getView().setZoom(currMap.getView().getZoom() * 1.015);
}
}
}
if (pageToLoad == 4) {
if (sessionStorage.getItem('isDiscrete') == 'true') {
isDiscrete = true;
} else {
isDiscrete = false;
}
//this.generateColorSchemes(this.numberOfClasses, parseInt(sessionStorage.getItem('colorSchemeSelected')));
if (isDiscrete == false) {
if (this.classAndClassficationIterationCounter == 0 || this.classAndClassficationIterationCounter == 1 || this.classAndClassficationIterationCounter == 2) {
this.currentClassificationMethod = "EQUALINTERVAL";
} else if (this.classAndClassficationIterationCounter == 3 || this.classAndClassficationIterationCounter == 4 || this.classAndClassficationIterationCounter == 5) {
this.currentClassificationMethod = "QUANTILE";
} else if (this.classAndClassficationIterationCounter == 6 || this.classAndClassficationIterationCounter == 7 || this.classAndClassficationIterationCounter == 8) {
this.currentClassificationMethod = "NATURALBREAKS";
}
if (this.classAndClassficationIterationCounter == 0 || this.classAndClassficationIterationCounter == 3 || this.classAndClassficationIterationCounter == 6) {
var doStandardise = true;
if (doStandardise && mapType != 1 && mapType != 2) {
this.standardise(this.currentStandardisationMethod); //GET FROM DOM
if (!isDiscrete) {
this.classify(this.wardsSource, this.mapValuesKeyNames[this.currentMapIndex], this.currentClassificationMethod, sessionStorage.getItem('numClasses'), parseInt(sessionStorage.getItem('mapTypeSelected')));
}
} else {
if (mapType == 1) {
this.classify(this.vectorSource, this.featureToDisplay, this.currentClassificationMethod, sessionStorage.getItem('numClasses'), parseInt(sessionStorage.getItem('mapTypeSelected')));
};
}
this.numberOfClasses = parseInt(sessionStorage.getItem('numClasses'));
this.generateColorSchemes(sessionStorage.getItem('numClasses'), parseInt(sessionStorage.getItem('colorSchemeSelected')));
} else if (this.classAndClassficationIterationCounter == 1 || this.classAndClassficationIterationCounter == 4 || this.classAndClassficationIterationCounter == 7) {
var doStandardise = true;
if (doStandardise && mapType != 1 && mapType != 2) {
this.standardise(this.currentStandardisationMethod); //GET FROM DOM
if (!isDiscrete) {
this.classify(this.wardsSource, this.mapValuesKeyNames[this.currentMapIndex], this.currentClassificationMethod, 5, parseInt(sessionStorage.getItem('mapTypeSelected')));
}
} else {
if (mapType == 1) {
this.classify(this.vectorSource, this.featureToDisplay, this.currentClassificationMethod, 5, parseInt(sessionStorage.getItem('mapTypeSelected')));
};
}
this.numberOfClasses = 5;
this.generateColorSchemes(this.numberOfClasses, parseInt(sessionStorage.getItem('colorSchemeSelected')));
} else if (this.classAndClassficationIterationCounter == 2 || this.classAndClassficationIterationCounter == 5 || this.classAndClassficationIterationCounter == 8) {
var doStandardise = true;
if (doStandardise && mapType != 1 && mapType != 2) {
this.standardise(this.currentStandardisationMethod); //GET FROM DOM
if (!isDiscrete) {
this.classify(this.wardsSource, this.mapValuesKeyNames[this.currentMapIndex], this.currentClassificationMethod, 7, parseInt(sessionStorage.getItem('mapTypeSelected')));
}
} else {
if (mapType == 1) {
this.classify(this.vectorSource, this.featureToDisplay, this.currentClassificationMethod, 7, parseInt(sessionStorage.getItem('mapTypeSelected')));
};
}
this.numberOfClasses = 7;
this.generateColorSchemes(this.numberOfClasses, parseInt(sessionStorage.getItem('colorSchemeSelected')));
}
} else {
this.generateColorSchemes(5, parseInt(sessionStorage.getItem('colorSchemeSelected')));
this.numberOfClasses = 5;
}
switch (parseInt(mapType)) {
case 1:
this.dotDensity.createMap(this.ccMapArray[this.classAndClassficationIterationCounter], this.vectorSource, this.colorPerClass, this.featureToDisplay, this.featureLayer, this.selectedValue, isDiscrete, this.numberOfClasses, this.classifiedArray);
this.ccMapArray[this.classAndClassficationIterationCounter].addLayer(this.wardsVectorLayer.layer);
break;
case 2:
this.heatmap.createMap(this.ccMapArray[this.classAndClassficationIterationCounter], this.vectorSource, this.featureLayer);
this.ccMapArray[this.classAndClassficationIterationCounter].addLayer(this.wardsVectorLayer.layer);
break;
case 3:
this.chloro.createMap(this.ccMapArray[this.classAndClassficationIterationCounter], this.vectorSource, this.wardsSource, this.colorPerClass, this.numberOfClasses, this.featureToDisplay, this.selectedValue, this.wardsVectorLayer, this.featureLayer, this.classifiedArray, this.mapValuesKeyNames[this.currentMapIndex], isDiscrete);
break;
case 4:
this.propsymbol.createMap(this.ccMapArray[this.classAndClassficationIterationCounter], this.vectorSource, this.wardsSource, this.symbolSource, this.colorPerClass, this.featureToDisplay, this.selectedValue, this, this.symbolLayer, isDiscrete, this.mapValuesKeyNames[this.currentMapIndex]);
this.ccMapArray[this.classAndClassficationIterationCounter].addLayer(this.wardsVectorLayer.layer);
break;
}
currMap = this.ccMapArray[this.classAndClassficationIterationCounter];
if (currMap != undefined && currMap.getView().getZoom() == 8) {
var extent = this.wardsSource.getExtent();
currMap.getView().fit(extent, currMap.getSize());
currMap.getView().setZoom(currMap.getView().getZoom() * mapZoomFactor);
}
++this.classAndClassficationIterationCounter;
if (callback)
callback();
}
if (pageToLoad == 3) {
if (sessionStorage.getItem('isDiscrete') == 'true') {
isDiscrete = true;
} else {
isDiscrete = false;
}
if (isDiscrete == false) {
var doStandardise = true;
if (doStandardise && mapType != 1 && mapType != 2) {
this.standardise(this.currentStandardisationMethod); //GET FROM DOM
if (!isDiscrete) {
this.classify(this.wardsSource, this.mapValuesKeyNames[this.currentMapIndex], this.currentClassificationMethod, this.numberOfClasses, parseInt(sessionStorage.getItem('mapTypeSelected')));
}
} else {
if (mapType == 1) {
this.classify(this.vectorSource, this.featureToDisplay, this.currentClassificationMethod, this.numberOfClasses, parseInt(sessionStorage.getItem('mapTypeSelected')));
};
}
}
this.generateColorSchemes(this.numberOfClasses, this.colorSchemeIterationCounter);
switch (parseInt(mapType)) {
case 1:
this.dotDensity.createMap(this.colorSchemeArray[this.colorSchemeIterationCounter], this.vectorSource, this.colorPerClass, this.featureToDisplay, this.featureLayer, this.selectedValue, isDiscrete, this.numberOfClasses, this.classifiedArray);
this.colorSchemeArray[this.colorSchemeIterationCounter].addLayer(this.wardsVectorLayer.layer);
break;
case 2:
this.heatmap.createMap(this.colorSchemeArray[this.colorSchemeIterationCounter], this.vectorSource, this.featureLayer);
this.colorSchemeArray[this.colorSchemeIterationCounter].addLayer(this.wardsVectorLayer.layer);
break;
case 3:
this.chloro.createMap(this.colorSchemeArray[this.colorSchemeIterationCounter], this.vectorSource, this.wardsSource, this.colorPerClass, this.numberOfClasses, this.featureToDisplay, this.selectedValue, this.wardsVectorLayer, this.featureLayer, this.classifiedArray, this.mapValuesKeyNames[this.currentMapIndex], isDiscrete);
break;
case 4:
this.propsymbol.createMap(this.colorSchemeArray[this.colorSchemeIterationCounter], this.vectorSource, this.wardsSource, this.symbolSource, this.colorPerClass, this.featureToDisplay, this.selectedValue, this, this.symbolLayer, isDiscrete, this.mapValuesKeyNames[this.currentMapIndex]);
this.colorSchemeArray[this.colorSchemeIterationCounter].addLayer(this.wardsVectorLayer.layer);
break;
}
currMap = this.colorSchemeArray[this.classAndClassficationIterationCounter];
if (currMap != undefined && currMap.getView().getZoom() == 8) {
var extent = this.wardsSource.getExtent();
currMap.getView().fit(extent, currMap.getSize());
currMap.getView().setZoom(currMap.getView().getZoom() * mapZoomFactor);
}
++this.colorSchemeIterationCounter;
if (callback)
callback();
}
if (pageToLoad == 2) {
if (sessionStorage.getItem('isDiscrete') == 'true') {
isDiscrete = true;
} else {
isDiscrete = false;
}
if (isDiscrete == false) {
var doStandardise = true;
if (doStandardise && mapType != 1 && mapType != 2) {
this.standardise(this.currentStandardisationMethod); //GET FROM DOM
if (!isDiscrete) {
this.classify(this.wardsSource, this.mapValuesKeyNames[this.currentMapIndex], this.currentClassificationMethod, this.numberOfClasses, mapType);
}
} else {
if (mapType == 1) {
this.classify(this.vectorSource, this.featureToDisplay, this.currentClassificationMethod, this.numberOfClasses, mapType);
};
}
}
this.generateColorSchemes(this.numberOfClasses, 1);
switch (mapType) {
case 1:
this.dotDensity.createMap(this.wizardMapArray[0], this.vectorSource, this.colorPerClass, this.featureToDisplay, this.featureLayer, this.selectedValue, isDiscrete, this.numberOfClasses, this.classifiedArray);
this.wizardMapArray[0].addLayer(this.wardsVectorLayer.layer);
currMap = this.wizardMapArray[0];
break;
case 2:
this.heatmap.createMap(this.wizardMapArray[1], this.vectorSource, this.featureLayer);
this.wizardMapArray[1].addLayer(this.wardsVectorLayer.layer);
currMap = this.wizardMapArray[1];
break;
case 3:
this.chloro.createMap(this.wizardMapArray[2], this.vectorSource, this.wardsSource, this.colorPerClass, this.numberOfClasses, this.featureToDisplay, this.selectedValue, this.wardsVectorLayer, this.featureLayer, this.classifiedArray, this.mapValuesKeyNames[this.currentMapIndex], isDiscrete);
currMap = this.wizardMapArray[2];
break;
case 4:
this.propsymbol.createMap(this.wizardMapArray[3], this.vectorSource, this.wardsSource, this.symbolSource, this.colorPerClass, this.featureToDisplay, this.selectedValue, this, this.symbolLayer, isDiscrete, this.mapValuesKeyNames[this.currentMapIndex]);
this.wizardMapArray[3].addLayer(this.wardsVectorLayer.layer);
currMap = this.wizardMapArray[3];
break;
}
if (currMap != undefined && currMap.getView().getZoom() == 8) {
var extent = this.wardsSource.getExtent();
currMap.getView().fit(extent, currMap.getSize());
currMap.getView().setZoom(currMap.getView().getZoom() * mapZoomFactor);
}
var temp = mapType + 1;
if (callback)
callback(temp);
} else if (pageToLoad == 1) {
this.generateColorSchemes(5, 0);
var doStandardise = true;
if (doStandardise) {
// this.standardise(this.currentStandardisationMethod); //GET FROM DOM
}
var isDiscrete = false;
if (!isDiscrete) {}
switch (mapType) {
case 0:
this.defaultMap.createMap(this.map);
for (var i = 0; i < 4; i++) {
this.defaultMap.createMap(this.wizardMapArray[i]);
}
for (var i = 0; i < 6; i++) {
this.defaultMap.createMap(this.colorSchemeArray[i]);
}
for (var i = 0; i < 9; i++) {
this.defaultMap.createMap(this.ccMapArray[i]);
}
break;
case 1:
this.dotDensity.createMap(this.map, this.vectorSource, this.colorPerClass, this.featureToDisplay, this.featureLayer, this.selectedValue);
this.removeLayers();
this.mapTypeWizard1.addLayer(this.featureLayer.layer);
this.mapTypeWizard1.addLayer(this.wardsVectorLayer.layer);
break;
case 2:
this.heatmap.createMap(this.map, this.vectorSource, this.featureLayer);
this.mapTypeWizard2.addLayer(this.featureLayer.layer);
this.mapTypeWizard2.addLayer(this.wardsVectorLayer.layer);
this.removeLayers();
break;
case 3:
this.chloro.createMap(this.map, this.vectorSource, this.wardsSource, this.colorPerClass, 5, this.featureToDisplay, this.selectedValue, this.wardsVectorLayer, this.featureLayer);
this.removeLayers();
break;
case 4:
this.propsymbol.createMap(this.mapTypeWizard4, this.vectorSource, this.wardsSource, this.WizardwardsSource, this.colorPerClass, this.featureToDisplay, this.selectedValue, this, this.symbolLayer);
this.mapTypeWizard4.addLayer(this.wardsVectorLayer.layer);
this.removeLayers();
break;
}
this.map.addLayer(this.wardsVectorLayer.layer);
}
}
/**
* Removes the layers of a map.
*/
MapDesign.prototype.removeLayers = function() {
if (this.wardsSource != undefined) {
var boundriesFeatures = this.wardsSource.getFeatures();
for (var i = 0; i < boundriesFeatures.length; i++) {
boundriesFeatures[i].setStyle();
}
}
if (this.symbolSource != undefined) {
//TODO clear features
var symbolFeatures = this.symbolSource.getFeatures();
for (var i = 0; i < symbolFeatures.length; i++) {
symbolFeatures[i].setStyle();
}
symbolSource.clear();
}
this.map.removeLayer(this.symbolLayer.layer);
this.map.removeLayer(this.featureLayer.layer);
this.map.removeLayer(this.wardsVectorLayer.layer);
};
/**
* Requests a geojson feature object from geoserver and creates a point vector source.
*
* @param {string} typeName The type name
*/
MapDesign.prototype.createVectorSource = function(typeName) {
this.vectorSource = new ol.source.Vector({
format: new ol.format.GeoJSON(),
url: function(extent) {
return 'http://localhost:8080/geoserver/wfs?service=WFS&' +
'version=1.1.0&request=GetFeature&typename=' + typeName + '&' +
'outputFormat=application/json&srsname=EPSG:4326&maxFeatures=3000&EPSG:4326';
},
strategy: ol.loadingstrategy.bbox
});
};
// Requests a geojson feature object from geoserver and creates a wards vector source.
//
// @param {string} typeName The type name
//
MapDesign.prototype.creatwardsSource = function(typeName) {
this.wardsSource = new ol.source.Vector({
format: new ol.format.GeoJSON(),
url: function(extent) {
return 'http://localhost:8080/geoserver/wfs?service=WFS&' +
'version=1.1.0&request=GetFeature&typename=' + typeName + '&' +
'outputFormat=application/json&srsname=EPSG:4326&EPSG:4326';
},
strategy: ol.loadingstrategy.bbox
});
this.WizardwardsSource = new ol.source.Vector({
format: new ol.format.GeoJSON(),
url: function(extent) {
return 'http://localhost:8080/geoserver/wfs?service=WFS&' +
'version=1.1.0&request=GetFeature&typename=GIS:wards&' +
'outputFormat=application/json&srsname=EPSG:4326&EPSG:4326';
},
strategy: ol.loadingstrategy.bbox
});
};
/**
* Loads boundaries with styles
*/
MapDesign.prototype.loadWards = function() {
this.wardsVectorLayer.layer = new ol.layer.Vector({
source: this.wardsSource,
style: new ol.style.Style({
fill: new ol.style.Fill({
color: 'rgba(0, 0, 0, 0.05)'
}),
stroke: new ol.style.Stroke({
color: 'rgba(0, 0, 0, 0.6)',
width: 1
}),
image: new ol.style.Circle({
radius: 20,
stroke: new ol.style.Stroke({
color: 'rgba(0,0,0,0.9)',
width: 4
}),
fill: new ol.style.Fill({
color: 'rgba(0, 0, 0, 0.6)'
})
})
})
});
};
/**
* Creates a point feature layer and adds it to the page 2 maps
*/
MapDesign.prototype.createFeatureLayer = function() {
this.featureLayer.layer = new ol.layer.Vector({
source: this.vectorSource,
style: new ol.style.Style({
visible: false
})
});
this.map.addLayer(this.featureLayer.layer);
this.wizardMapArray[0].addLayer(this.featureLayer.layer);
this.wizardMapArray[1].addLayer(this.featureLayer.layer);
this.wizardMapArray[2].addLayer(this.featureLayer.layer);
this.wizardMapArray[3].addLayer(this.featureLayer.layer);
};
/**
* Creates a boundaries layer.
*/
MapDesign.prototype.createWardLayer = function() {
this.wardsVectorLayer.layer = new ol.layer.Vector({
source: this.wardsSource,
style: new ol.style.Style({
visible: false
})
});
};
/**
* Creates a symbol layer.
*/
MapDesign.prototype.createSymbolLayer = function() {
var symbolSource = new ol.source.Vector({});
this.symbolLayer.layer = new ol.layer.Vector({
source: symbolSource
});
};
/**
* Creates map with default interaction properties
*/
MapDesign.prototype.initializeMap = function() {
this.map = new ol.Map({
layers: [],
target: 'map',
controls: [],
interactions: ol.interaction.defaults({
doubleClickZoom: true,
dragAndDrop: false,
keyboardPan: false,
keyboardZoom: false,
mouseWheelZoom: true,
pointer: false,
select: false,
dragPan: true
}),
view: new ol.View({
projection: 'EPSG:4326',
center: [10, 0], //map.getView().getCenter()
zoom: 3
})
});
for (var i = 0; i < (19); i++) {
if (i < 4) {
this.wizardMapArray.push(new ol.Map({
layers: [],
target: '',
controls: [],
interactions: ol.interaction.defaults({
doubleClickZoom: false,
dragAndDrop: false,
keyboardPan: false,
keyboardZoom: false,
mouseWheelZoom: false,
pointer: false,
select: false,
dragPan: false
}),
view: new ol.View({
projection: 'EPSG:4326',
center: [28.5, -25.6], //map.getView().getCenter()
zoom: 8
})
}));
} else if (i >= 4 && i < 10) {
this.colorSchemeArray.push(new ol.Map({
layers: [],
target: '',
controls: [],
interactions: ol.interaction.defaults({
doubleClickZoom: false,
dragAndDrop: false,
keyboardPan: false,
keyboardZoom: false,
mouseWheelZoom: false,
pointer: false,
select: false,
dragPan: false
}),
view: new ol.View({
projection: 'EPSG:4326',
center: [28.5, -25.6], //map.getView().getCenter()
zoom: 8
})
}));
} else if (i >= 10 && i < 19) {
this.ccMapArray.push(new ol.Map({
layers: [],
target: '',
controls: [],
interactions: ol.interaction.defaults({
doubleClickZoom: false,
dragAndDrop: false,
keyboardPan: false,
keyboardZoom: false,
mouseWheelZoom: false,
pointer: false,
select: false,
dragPan: false
}),
view: new ol.View({
projection: 'EPSG:4326',
center: [28.5, -25.6], //map.getView().getCenter()
zoom: 8
})
}));
}
}
};
/**
* Sets the map display type.
*
* @param {<type>} mapType The map type
*/
MapDesign.prototype.setMapDisplayType = function(mapType) {
this.mapDisplayType = mapType;
};
/**
* Gets the map.
*
* @return {<type>} The map.
*/
MapDesign.prototype.getMap = function() {
return this.map;
}
/**
* Gets the vector classes.
*
* @return {<type>} The vector classes.
*/
MapDesign.prototype.getVectorClasses = function() {
return this.vectorLayerClasses;
}
//
// Creates an array of unique values for a attribute which's name is passed
//
// @param {string} attributeTitle The attribute title
// @return {string[]} The unique discrete values.
//
MapDesign.prototype.getUniqueDiscreteValues = function(attributeTitle) {
var tempVectorLayerClasses = [];
this.vectorSource.forEachFeature(function(feature) {
if (tempVectorLayerClasses.indexOf(feature.get(attributeTitle)) == -1) {
tempVectorLayerClasses.push(feature.get(attributeTitle));
}
});
if (tempVectorLayerClasses.length <= 0) {
console.log("No attribute values found");
}
this.vectorLayerClasses = tempVectorLayerClasses;
return tempVectorLayerClasses;
}
/**
* Creates map elements by utilising the builder pattern. Elements created include map heading, map legend, and meta data.
*/
MapDesign.prototype.createMapElements = function() {
if (this.concreteMapBuilder == undefined) {
this.concreteMapBuilder = new ConcreteMapBuilder();
}
this.concreteMapBuilder.buildMapHeading();
this.concreteMapBuilder.buildMapLegend(this.numberOfClasses, this.colorPerClass, this.vectorLayerClasses, this.selectedValue);
// this.concreteMapBuilder.buildMapScale();
this.concreteMapBuilder.buildMapNorthArrow();
this.concreteMapBuilder.buildMapMetaData();
}
/**
* Adds sources to be able to list unique attribute values and calls the list function
*/
MapDesign.prototype.listUniqueAttributeValues = function() {
if (this.vectorSource == undefined) {
this.createVectorSource(this.vectorSourceTypeName);
this.createFeatureLayer();
this.loadSources();
} else {
if (this.vectorSource.getFeatures().length <= 0) {
this.createFeatureLayer();
}
}
if (this.vectorSource.getState() != 'ready') {
this.vectorSource.on('change', function(evt) {
var source = evt.target;
if (source.getState() == 'ready') {
this.recursiveWaitAndList();
}
});
} else {
this.recursiveWaitAndList();
}
}
/**
* Waits till point source is ready and adds a list of unique values to the html dropdown element
*/
MapDesign.prototype.recursiveWaitAndList = function() {
if (this.vectorSource == undefined || this.vectorSource.getFeatures().length <= 0) {
var that = this;
setTimeout(function() {
that.recursiveWaitAndList();
}, 500);
return;
} else {
// set featureToDsiplay
this.uniqueAttributeValues = this.getUniqueDiscreteValues($("#attr option:selected").html());
this.setAttribute();
//populate attribute values in select
document.getElementById("attrValue").innerHTML = "";
document.getElementById("attrValue").innerHTML = " <option style = \"display:none\" disabled selected value = \"1\">Select an Attribute</option><br>";
for (var i = 0; i < this.uniqueAttributeValues.length; i++) {
// check if value not null
if (this.uniqueAttributeValues[i] != undefined && this.uniqueAttributeValues[i].trim()) {
document.getElementById("attrValue").innerHTML += "<option value = \"" + i + 1 + "\" >" + this.uniqueAttributeValues[i] + "</option><br>";
}
}
//store specifications in DOM - session storage
var attributeValuesObject = this.toObject(this.uniqueAttributeValues);
sessionStorage.setItem('attributeValues', JSON.stringify(attributeValuesObject));
// this.vectorSource.clear();
// this.vectorSource = undefined;
}
}
/**
* Generates different color schemes based on the paramaters
*
* @param {number} classCount The number of classes to seperate the selected spectrum
* @param {number} schemeToGenerate The color scheme to generate
*/
MapDesign.prototype.generateColorSchemes = function(classCount, schemeToGenerate) {
if (classCount <= 0) {
console.log("Color classes not specified");
return;
}
this.colorPerClass = [];
switch (schemeToGenerate) {
case 0: //Single hue progression
var split = 100 / classCount;
for (var i = 0; i < classCount; i++) {
var temp = [0, 100, (i * split)];
this.colorPerClass.push(temp);
}
break;
case 1: //full spectural color progression
var split = 360 / classCount;
for (var i = 0; i < classCount; i++) {
var temp = [(i * split), 100, 50];
this.colorPerClass.push(temp);
}
break;
case 2: //Bi-polor(red v green) color progression
if (classCount % 2 == 0) {
var split = 50 / classCount;
for (var i = classCount; i > 0; i--) {
var temp = [0, 100, 50 + (i * split)];
var temp2 = [240, 100, 50 + (i * split)];
this.colorPerClass.unshift(temp);
this.colorPerClass.push(temp2);
}
} else {
this.colorPerClass.push([240, 100, 100]);
var split = 50 / classCount;
for (var i = classCount - 1; i > 0; i--) {
var temp = [0, 100, 50 + (i * split)];
var temp2 = [240, 100, 50 + (i * split)];
this.colorPerClass.unshift(temp);
this.colorPerClass.push(temp2);
}
}
break;
case 3:
var split = 100 / classCount;
for (var i = 0; i < classCount; i++) {
var temp = [0, 0, (i * split)];
this.colorPerClass.push(temp);
}
break;
case 4:
var split = 180 / classCount;
for (var i = 0; i < classCount; i++) {
var temp = [(i * split), 100, 50];
this.colorPerClass.push(temp);
}
break;
case 5:
var split = 180 / classCount;
for (var i = 0; i < classCount; i++) {
var temp = [180 + (i * split), 100, 50];
this.colorPerClass.push(temp);
}
break;
}
};
// Cite: https://stackoverflow.com/questions/3357553/how-do-i-store-an-array-in-localstorage/10109307#10109307
MapDesign.prototype.toObject = function(arr) {
var object = {};
for (var i = 0; i < arr.length; ++i)
object[i] = arr[i];
return object;
}
/**
* Sets the dataset.
*/
MapDesign.prototype.setDataset = function() {
this.vectorSourceTypeName = $("#dataset option:selected").html();
}
/**
* Sets the boundaries.
*/
MapDesign.prototype.setBoundaries = function() {
this.wardSourceTypeName = $("#boundary option:selected").html();
}
/**
* Sets the attribute.
*/
MapDesign.prototype.setAttribute = function() {
this.featureToDisplay = $("#attr option:selected").html();
}
/**
* Sets the attribute value.
*/
MapDesign.prototype.setAttrValue = function() {
this.selectedValue = $("#attrValue option:selected").html();
}
/**
* Logs map layers.
*/
MapDesign.prototype.logMapLayers = function() {
console.log(this.map.getLayers());
}
/**
* resets the map counter
*/
MapDesign.prototype.resetMapCounter = function() {
this.currentMapIndex = 0;
}
/**
* Loads a map legend.
*/
MapDesign.prototype.loadMapLegend = function() {
this.createMapElements();
}