Commit af9b4503 authored by Eric Duminil's avatar Eric Duminil
Browse files

Adding WKT validation.

Only valid polygons will be imported
parent 8d32adbe
No related merge requests found
Showing with 72 additions and 54 deletions
+72 -54
...@@ -14,7 +14,7 @@ ...@@ -14,7 +14,7 @@
--> -->
<script type="text/javascript" src="script/proj4.js"></script> <script type="text/javascript" src="script/proj4.js"></script>
<script type="text/javascript" src="script/jquery-1.4.2.min.js"></script> <script type="text/javascript" src="script/jquery-1.4.2.min.js"></script>
<!-- OpenLayers v3.4.0. API doc : http://openlayers.org/en/v3.4.0/apidoc/ --> <!-- OpenLayers v3.4.0. API doc : https://geoadmin.github.io/ol3/apidoc/ -->
<script src="script/ol.js" type="text/javascript"></script> <script src="script/ol.js" type="text/javascript"></script>
<link rel="stylesheet" href="style/ol.css" type="text/css" /> <link rel="stylesheet" href="style/ol.css" type="text/css" />
<script src="script/turf.js" type="text/javascript"></script> <script src="script/turf.js" type="text/javascript"></script>
......
...@@ -11,13 +11,13 @@ const regionChooser = (function(){ ...@@ -11,13 +11,13 @@ const regionChooser = (function(){
const dataPanel = $('#dataPanel'); const dataPanel = $('#dataPanel');
const wgs84Sphere = new ol.Sphere(6378137); const wgs84Sphere = new ol.Sphere(6378137);
var features_by_project; var features_by_project;
publicScope.init = function(){ publicScope.init = function(){
//NOTE: Only called from JavaFX. At startup, or when Repo has been changed. //NOTE: Only called from JavaFX. At startup, or when Repo has been changed.
kml_source.clear(); kml_source.clear();
document.getElementById("select_repository").style.visibility = "visible"; document.getElementById("select_repository").style.visibility = "visible";
} }
if (fromJavaFX){ if (fromJavaFX){
document.documentElement.className = 'wait'; document.documentElement.className = 'wait';
} }
...@@ -54,7 +54,7 @@ const regionChooser = (function(){ ...@@ -54,7 +54,7 @@ const regionChooser = (function(){
console.warn(srsName + " isn't defined by Proj4js!") console.warn(srsName + " isn't defined by Proj4js!")
} }
}; };
var map = new ol.Map({ var map = new ol.Map({
target : 'map', target : 'map',
layers : [ osm_layer, kml_layer, intersections_layer ], layers : [ osm_layer, kml_layer, intersections_layer ],
...@@ -79,7 +79,7 @@ const regionChooser = (function(){ ...@@ -79,7 +79,7 @@ const regionChooser = (function(){
feature["source"] = "CityGML"; feature["source"] = "CityGML";
feature["status"] = "original"; feature["status"] = "original";
}); });
var features = Array.from(kml_source.getFeatures()); var features = Array.from(kml_source.getFeatures());
// Sort projects // Sort projects
features.sort((a, b) => a.project.localeCompare(b.project)); features.sort((a, b) => a.project.localeCompare(b.project));
...@@ -142,70 +142,70 @@ const regionChooser = (function(){ ...@@ -142,70 +142,70 @@ const regionChooser = (function(){
updateGMLPolygons(); updateGMLPolygons();
}); });
var sourceProj = map.getView().getProjection(); var sourceProj = map.getView().getProjection();
function showLinkToDownload(feature, jsonIntersection, polygonArea){ function showLinkToDownload(feature, jsonIntersection, polygonArea){
var intersection = geoJsonFormat.readFeature(jsonIntersection); var intersection = geoJsonFormat.readFeature(jsonIntersection);
var intersectionArea = intersection.getGeometry().getArea(); var intersectionArea = intersection.getGeometry().getArea();
var citygml_percentage = Math.round(intersectionArea / feature["area"] * 100); var citygml_percentage = Math.round(intersectionArea / feature["area"] * 100);
var sketch_percentage = Math.round(intersectionArea / polygonArea * 100); var sketch_percentage = Math.round(intersectionArea / polygonArea * 100);
intersections.addFeature(intersection); intersections.addFeature(intersection);
li = document.createElement('li'); li = document.createElement('li');
li.feature = feature; li.feature = feature;
li.onmouseover = function(){ regionChooser.highlightPolygon(this.feature) }; li.onmouseover = function(){ regionChooser.highlightPolygon(this.feature) };
li.onmouseout = function(){ regionChooser.resetHighlight(this.feature) }; li.onmouseout = function(){ regionChooser.resetHighlight(this.feature) };
let label = li.appendChild(document.createElement('label')); let label = li.appendChild(document.createElement('label'));
var text = feature.name; var text = feature.name;
let checkbox = document.createElement('input'); let checkbox = document.createElement('input');
checkbox.type = 'checkbox' checkbox.type = 'checkbox'
checkbox.className = "select_citygml"; checkbox.className = "select_citygml";
checkbox.feature = feature; checkbox.feature = feature;
checkbox.setAttribute('onclick', "regionChooser.isDownloadPossible()"); checkbox.setAttribute('onclick', "regionChooser.isDownloadPossible()");
text += " (" + citygml_percentage + "%"; text += " (" + citygml_percentage + "%";
if (sketch_percentage == 100) { if (sketch_percentage == 100) {
text += ", all inside"; text += ", all inside";
} }
label.textContent = text + ")\n"; label.textContent = text + ")\n";
label.prepend(checkbox); label.prepend(checkbox);
// append to DOM element, not to jQuery object // append to DOM element, not to jQuery object
dataPanel[0].appendChild(li); dataPanel[0].appendChild(li);
} }
publicScope.highlightPolygon = function(feature) { publicScope.highlightPolygon = function(feature) {
feature.setStyle(styles.highlighted); feature.setStyle(styles.highlighted);
} }
publicScope.resetHighlight = function(feature) { publicScope.resetHighlight = function(feature) {
refreshStyle(feature); refreshStyle(feature);
} }
refreshStyle = function(feature, status){ refreshStyle = function(feature, status){
if (status){ if (status){
feature.status = status; feature.status = status;
} }
feature.setStyle(styles[feature.status]); feature.setStyle(styles[feature.status]);
} }
publicScope.isDownloadPossible = function(){ publicScope.isDownloadPossible = function(){
kml_source.getFeatures().forEach(f => refreshStyle(f, "original")); kml_source.getFeatures().forEach(f => refreshStyle(f, "original"));
selectedFeatures = getSelectedGMLs(); selectedFeatures = getSelectedGMLs();
selectedFeatures.forEach(f => refreshStyle(f, "selected")); selectedFeatures.forEach(f => refreshStyle(f, "selected"));
document.getElementById("download_region_button").disabled = (selectedFeatures.length == 0); document.getElementById("download_region_button").disabled = (selectedFeatures.length == 0);
} }
function getSelectedGMLs(){ function getSelectedGMLs(){
return Array.from(document.querySelectorAll("input.select_citygml")).filter(c => c.checked).map(c => c.feature); return Array.from(document.querySelectorAll("input.select_citygml")).filter(c => c.checked).map(c => c.feature);
} }
function findIntersection(feature, polygon) { function findIntersection(feature, polygon) {
try { try {
return turf.intersect(polygon, feature["geoJSON"]); return turf.intersect(polygon, feature["geoJSON"]);
...@@ -219,7 +219,7 @@ const regionChooser = (function(){ ...@@ -219,7 +219,7 @@ const regionChooser = (function(){
var polygonArea = sketch.getGeometry().getArea(); var polygonArea = sketch.getGeometry().getArea();
var intersection_found = false; var intersection_found = false;
intersections.clear(); intersections.clear();
Object.keys(features_by_project).forEach(function(project) { Object.keys(features_by_project).forEach(function(project) {
features = features_by_project[project]; features = features_by_project[project];
features_and_intersections = features.map(f=> [f, findIntersection(f,polygon)]).filter(l => l[1] !== undefined); features_and_intersections = features.map(f=> [f, findIntersection(f,polygon)]).filter(l => l[1] !== undefined);
...@@ -229,7 +229,7 @@ const regionChooser = (function(){ ...@@ -229,7 +229,7 @@ const regionChooser = (function(){
features_and_intersections.forEach(l => showLinkToDownload(l[0], l[1], polygonArea)); features_and_intersections.forEach(l => showLinkToDownload(l[0], l[1], polygonArea));
} }
}); });
if (intersection_found) { if (intersection_found) {
document.getElementById("download_region").style.visibility = 'visible'; document.getElementById("download_region").style.visibility = 'visible';
} }
...@@ -242,13 +242,13 @@ const regionChooser = (function(){ ...@@ -242,13 +242,13 @@ const regionChooser = (function(){
publicScope.display = function(text){ publicScope.display = function(text){
dataPanel.append(text + "<br/>\n"); dataPanel.append(text + "<br/>\n");
} }
publicScope.downloadStart = function(){ publicScope.downloadStart = function(){
document.getElementById("download_region_button").disabled = true; document.getElementById("download_region_button").disabled = true;
document.documentElement.className = 'wait'; document.documentElement.className = 'wait';
dataPanel.prepend("<h2 id='download_start' class='ok'>Extracting region...</h2><br/>\n"); dataPanel.prepend("<h2 id='download_start' class='ok'>Extracting region...</h2><br/>\n");
} }
publicScope.downloadFinished = function(count){ publicScope.downloadFinished = function(count){
document.documentElement.className = ''; // Stop waiting document.documentElement.className = ''; // Stop waiting
document.getElementById("download_start").remove(); document.getElementById("download_start").remove();
...@@ -262,21 +262,21 @@ const regionChooser = (function(){ ...@@ -262,21 +262,21 @@ const regionChooser = (function(){
button.disabled = false; button.disabled = false;
} }
} }
publicScope.downloadFromSelectedCityGMLs = function() { publicScope.downloadFromSelectedCityGMLs = function() {
var features = getSelectedGMLs(); var features = getSelectedGMLs();
var project = features[0].get("project"); var project = features[0].get("project");
var srsName = features[0].get("srsName"); var srsName = features[0].get("srsName");
if (!features.every( f => f.get("project") === project)){ if (!features.every( f => f.get("project") === project)){
dataPanel.prepend("<h2 class='error'>Sorry, the CityGML files should all belong to the same project.</h2><br/>\n"); dataPanel.prepend("<h2 class='error'>Sorry, the CityGML files should all belong to the same project.</h2><br/>\n");
return; return;
} }
if (!features.every( f => f.get("srsName") === srsName)){ if (!features.every( f => f.get("srsName") === srsName)){
dataPanel.prepend("<h2 class='error'>Sorry, the CityGML files should all be written with the same coordinate system.</h2><br/>\n"); dataPanel.prepend("<h2 class='error'>Sorry, the CityGML files should all be written with the same coordinate system.</h2><br/>\n");
} }
var citygmlNames = features.map(f => f.get("name")); var citygmlNames = features.map(f => f.get("name"));
if (proj4.defs(srsName)){ if (proj4.defs(srsName)){
console.log("Selected region is written in " + srsName + " coordinate system."); console.log("Selected region is written in " + srsName + " coordinate system.");
...@@ -295,20 +295,20 @@ const regionChooser = (function(){ ...@@ -295,20 +295,20 @@ const regionChooser = (function(){
var area = Math.abs(wgs84Sphere.geodesicArea(coordinates)); var area = Math.abs(wgs84Sphere.geodesicArea(coordinates));
//NOTE: Could show m², ha or km² depending on magnitude //NOTE: Could show m², ha or km² depending on magnitude
dataPanel.append("<h3 class='clean'>Area : " + (area / 10000).toFixed(1) + " ha\n"); dataPanel.append("<h3 class='clean'>Area : " + (area / 10000).toFixed(1) + " ha\n");
dataPanel.append('<div style="visibility:hidden" id="download_region">' + dataPanel.append('<div style="visibility:hidden" id="download_region">' +
'<button type="button" onclick="regionChooser.downloadFromSelectedCityGMLs()" id="download_region_button" disabled>Download Region</button><br/>\n' + '<button type="button" onclick="regionChooser.downloadFromSelectedCityGMLs()" id="download_region_button" disabled>Download Region</button><br/>\n' +
'<a href="#" onclick="regionChooser.selectAllOrNone(true);">(Select All)</a>\n' + '<a href="#" onclick="regionChooser.selectAllOrNone(true);">(Select All)</a>\n' +
'<a href="#" onclick="regionChooser.selectAllOrNone(false);">(Select None)</a>\n'+ '<a href="#" onclick="regionChooser.selectAllOrNone(false);">(Select None)</a>\n'+
'</div>\n'); '</div>\n');
findIntersections(); findIntersections();
dataPanel.append('<button type="button" onclick="regionChooser.copyCoordinatesToClipboard()" id="get_wgs84">Copy coordinates</button><br/>\n') dataPanel.append('<button type="button" onclick="regionChooser.copyCoordinatesToClipboard()" id="get_wgs84" style="position:fixed; bottom:0;">Copy coordinates</button><br/>\n')
} }
draw.on('drawend', function() { draw.on('drawend', function() {
displayInfo(); displayInfo();
draw.setActive(false); draw.setActive(false);
}); });
// With OpenLayers 3.9, draw_interaction.removeLastPoint(); might be better. // With OpenLayers 3.9, draw_interaction.removeLastPoint(); might be better.
document.addEventListener('keydown', function(e) { document.addEventListener('keydown', function(e) {
//NOTE: e.key isn't defined in JavaFX Browser //NOTE: e.key isn't defined in JavaFX Browser
...@@ -336,7 +336,7 @@ const regionChooser = (function(){ ...@@ -336,7 +336,7 @@ const regionChooser = (function(){
focusOnMap(); focusOnMap();
} }
} }
function sketchAsWKT(srsName) { function sketchAsWKT(srsName) {
var wktFormat = new ol.format.WKT(); var wktFormat = new ol.format.WKT();
return wktFormat.writeFeature(sketch, { return wktFormat.writeFeature(sketch, {
...@@ -344,24 +344,24 @@ const regionChooser = (function(){ ...@@ -344,24 +344,24 @@ const regionChooser = (function(){
featureProjection : ol.proj.get('EPSG:3857') featureProjection : ol.proj.get('EPSG:3857')
}); });
} }
function focusOnMap() { function focusOnMap() {
document.getElementById("map").focus(); document.getElementById("map").focus();
} }
var fxapp = undefined; var fxapp = undefined;
publicScope.setFxApp = function(app){ publicScope.setFxApp = function(app){
fxapp = app; fxapp = app;
console.log = function(message){ console.log = function(message){
fxapp.log(message); fxapp.log(message);
} }
console.warn = function(message){ console.warn = function(message){
fxapp.warning(message); fxapp.warning(message);
} }
} }
function displayHelp(){ function displayHelp(){
dataPanel.empty(); dataPanel.empty();
dataPanel.append("<h2 class='info'>Welcome to Region Chooser!<br><br>\n"); dataPanel.append("<h2 class='info'>Welcome to Region Chooser!<br><br>\n");
...@@ -375,27 +375,45 @@ const regionChooser = (function(){ ...@@ -375,27 +375,45 @@ const regionChooser = (function(){
dataPanel.append("<br>\n"); dataPanel.append("<br>\n");
dataPanel.append("More info is available in the "); dataPanel.append("More info is available in the ");
dataPanel.append("<a href='http://simstadt.hft-stuttgart.de/related-softwares/region-chooser/'>SimStadt documentation</a><br>\n"); dataPanel.append("<a href='http://simstadt.hft-stuttgart.de/related-softwares/region-chooser/'>SimStadt documentation</a><br>\n");
dataPanel.append("<form id='importWKT'>\n" + dataPanel.append("<form id='importWKT' style='position:fixed; bottom:0;'>\n" +
"<input id='wktPolygon' type='text' placeholder='WKT Polygon' value='POLYGON ((30 10, 40 40, 20 40, 10 20, 30 10))'></input>\n" + "<input id='wktPolygon' type='text' placeholder='WKT Polygon' " +
"<input type='submit' value='Import Polygon'></input>\n" + "required pattern=' *POLYGON\\(\\([\\-0-9\., ]+\\)\\) *' " +
"title='Please input a valid WKT Polygon. Example : POLYGON((9.961675 49.807053, 9.951375 49.798521, 9.969486 49.797746, 9.961675 49.807053)) '/>\n" +
"<input type='submit' value='Import Polygon'/>\n" +
"</form>\n"); "</form>\n");
document.getElementById('importWKT').addEventListener('submit', importWKT); document.getElementById('importWKT').addEventListener('submit', importWKT);
} }
importWKT = function(e){ importWKT = function(e){
e.preventDefault(); // to avoid refresh
//TODO: DRY, possibly with other events //TODO: DRY, possibly with other events
//TODO: Allow WKT as parameter for GUI? //TODO: Allow WKT as parameter for GUI?
console.log("Let's import WKT Polygon : " + wktPolygon);
var wktPolygon = document.getElementById("wktPolygon").value; var wktPolygon = document.getElementById("wktPolygon").value;
console.log("Try to import WKT geometry : " + wktPolygon);
var wktFormat = new ol.format.WKT(); var wktFormat = new ol.format.WKT();
var feature = wktFormat.readFeature(wktPolygon, {
dataProjection : ol.proj.get('EPSG:4326'),
featureProjection : ol.proj.get('EPSG:3857')
});
//TODO: Check if import was succesful try{
var feature = wktFormat.readFeature(wktPolygon, {
dataProjection : ol.proj.get('EPSG:4326'),
featureProjection : ol.proj.get('EPSG:3857')
});
} catch (e){
console.error("Couldn't import geometry!");
dataPanel.prepend("<h2 class='error'>Couldn't import geometry!</h2><br/>\n");
return false;
}
// Assuming the linear ring is closed
var coordinatesCount = feature.getGeometry().getLinearRing(0).getCoordinates().length - 1;
if (coordinatesCount < 2){
dataPanel.prepend("<h2 class='error'>There should be at least 2 points in WKT polygon</h2><br/>\n");
return false;
}
sketch = feature; sketch = feature;
updateGMLPolygons(); updateGMLPolygons();
...@@ -408,7 +426,7 @@ const regionChooser = (function(){ ...@@ -408,7 +426,7 @@ const regionChooser = (function(){
displayInfo(); displayInfo();
draw.setActive(false); draw.setActive(false);
e.preventDefault(); // to avoid refresh dataPanel.prepend("<h2 class='ok'>WKT Polygon succesfully imported!</h2><br/>");
} }
...@@ -419,16 +437,16 @@ const regionChooser = (function(){ ...@@ -419,16 +437,16 @@ const regionChooser = (function(){
document.documentElement.className = ''; // Stop waiting document.documentElement.className = ''; // Stop waiting
console.log("Ready!"); console.log("Ready!");
} }
publicScope.selectAllOrNone = function(allOrNone) { publicScope.selectAllOrNone = function(allOrNone) {
document.querySelectorAll("input.select_citygml").forEach(c => c.checked = allOrNone); document.querySelectorAll("input.select_citygml").forEach(c => c.checked = allOrNone);
publicScope.isDownloadPossible(); publicScope.isDownloadPossible();
} }
publicScope.selectRepository = function() { publicScope.selectRepository = function() {
fxapp.selectRepository(); fxapp.selectRepository();
} }
publicScope.copyCoordinatesToClipboard = function(){ publicScope.copyCoordinatesToClipboard = function(){
var geom = sketch.getGeometry().clone().transform(sourceProj, 'EPSG:4326'); var geom = sketch.getGeometry().clone().transform(sourceProj, 'EPSG:4326');
var wgs84Coords = geom.getLinearRing(0).getCoordinates(); var wgs84Coords = geom.getLinearRing(0).getCoordinates();
...@@ -437,7 +455,7 @@ const regionChooser = (function(){ ...@@ -437,7 +455,7 @@ const regionChooser = (function(){
wktPolygon += wgs84Coords.map(([lon, lat]) => lon.toFixed(precision) + " " + lat.toFixed(precision)).join(", "); wktPolygon += wgs84Coords.map(([lon, lat]) => lon.toFixed(precision) + " " + lat.toFixed(precision)).join(", ");
utils.copyToClipboard(wktPolygon + "))", dataPanel); utils.copyToClipboard(wktPolygon + "))", dataPanel);
} }
publicScope.showRepositoryName = function(path) { publicScope.showRepositoryName = function(path) {
document.getElementById("repo_path").textContent = path; document.getElementById("repo_path").textContent = path;
} }
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment