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 @@
-->
<script type="text/javascript" src="script/proj4.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>
<link rel="stylesheet" href="style/ol.css" type="text/css" />
<script src="script/turf.js" type="text/javascript"></script>
......
......@@ -11,13 +11,13 @@ const regionChooser = (function(){
const dataPanel = $('#dataPanel');
const wgs84Sphere = new ol.Sphere(6378137);
var features_by_project;
publicScope.init = function(){
//NOTE: Only called from JavaFX. At startup, or when Repo has been changed.
kml_source.clear();
document.getElementById("select_repository").style.visibility = "visible";
}
if (fromJavaFX){
document.documentElement.className = 'wait';
}
......@@ -54,7 +54,7 @@ const regionChooser = (function(){
console.warn(srsName + " isn't defined by Proj4js!")
}
};
var map = new ol.Map({
target : 'map',
layers : [ osm_layer, kml_layer, intersections_layer ],
......@@ -79,7 +79,7 @@ const regionChooser = (function(){
feature["source"] = "CityGML";
feature["status"] = "original";
});
var features = Array.from(kml_source.getFeatures());
// Sort projects
features.sort((a, b) => a.project.localeCompare(b.project));
......@@ -142,70 +142,70 @@ const regionChooser = (function(){
updateGMLPolygons();
});
var sourceProj = map.getView().getProjection();
function showLinkToDownload(feature, jsonIntersection, polygonArea){
var intersection = geoJsonFormat.readFeature(jsonIntersection);
var intersectionArea = intersection.getGeometry().getArea();
var citygml_percentage = Math.round(intersectionArea / feature["area"] * 100);
var sketch_percentage = Math.round(intersectionArea / polygonArea * 100);
intersections.addFeature(intersection);
li = document.createElement('li');
li.feature = feature;
li.onmouseover = function(){ regionChooser.highlightPolygon(this.feature) };
li.onmouseout = function(){ regionChooser.resetHighlight(this.feature) };
let label = li.appendChild(document.createElement('label'));
var text = feature.name;
let checkbox = document.createElement('input');
checkbox.type = 'checkbox'
checkbox.className = "select_citygml";
checkbox.feature = feature;
checkbox.setAttribute('onclick', "regionChooser.isDownloadPossible()");
text += " (" + citygml_percentage + "%";
if (sketch_percentage == 100) {
text += ", all inside";
}
label.textContent = text + ")\n";
label.prepend(checkbox);
// append to DOM element, not to jQuery object
dataPanel[0].appendChild(li);
}
publicScope.highlightPolygon = function(feature) {
feature.setStyle(styles.highlighted);
}
publicScope.resetHighlight = function(feature) {
refreshStyle(feature);
}
refreshStyle = function(feature, status){
if (status){
feature.status = status;
}
feature.setStyle(styles[feature.status]);
}
publicScope.isDownloadPossible = function(){
kml_source.getFeatures().forEach(f => refreshStyle(f, "original"));
selectedFeatures = getSelectedGMLs();
selectedFeatures.forEach(f => refreshStyle(f, "selected"));
document.getElementById("download_region_button").disabled = (selectedFeatures.length == 0);
}
function getSelectedGMLs(){
return Array.from(document.querySelectorAll("input.select_citygml")).filter(c => c.checked).map(c => c.feature);
}
function findIntersection(feature, polygon) {
try {
return turf.intersect(polygon, feature["geoJSON"]);
......@@ -219,7 +219,7 @@ const regionChooser = (function(){
var polygonArea = sketch.getGeometry().getArea();
var intersection_found = false;
intersections.clear();
Object.keys(features_by_project).forEach(function(project) {
features = features_by_project[project];
features_and_intersections = features.map(f=> [f, findIntersection(f,polygon)]).filter(l => l[1] !== undefined);
......@@ -229,7 +229,7 @@ const regionChooser = (function(){
features_and_intersections.forEach(l => showLinkToDownload(l[0], l[1], polygonArea));
}
});
if (intersection_found) {
document.getElementById("download_region").style.visibility = 'visible';
}
......@@ -242,13 +242,13 @@ const regionChooser = (function(){
publicScope.display = function(text){
dataPanel.append(text + "<br/>\n");
}
publicScope.downloadStart = function(){
document.getElementById("download_region_button").disabled = true;
document.documentElement.className = 'wait';
dataPanel.prepend("<h2 id='download_start' class='ok'>Extracting region...</h2><br/>\n");
}
publicScope.downloadFinished = function(count){
document.documentElement.className = ''; // Stop waiting
document.getElementById("download_start").remove();
......@@ -262,21 +262,21 @@ const regionChooser = (function(){
button.disabled = false;
}
}
publicScope.downloadFromSelectedCityGMLs = function() {
var features = getSelectedGMLs();
var project = features[0].get("project");
var srsName = features[0].get("srsName");
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");
return;
}
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");
}
var citygmlNames = features.map(f => f.get("name"));
if (proj4.defs(srsName)){
console.log("Selected region is written in " + srsName + " coordinate system.");
......@@ -295,20 +295,20 @@ const regionChooser = (function(){
var area = Math.abs(wgs84Sphere.geodesicArea(coordinates));
//NOTE: Could show m², ha or km² depending on magnitude
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' +
'<a href="#" onclick="regionChooser.selectAllOrNone(true);">(Select All)</a>\n' +
'<a href="#" onclick="regionChooser.selectAllOrNone(false);">(Select None)</a>\n'+
'</div>\n');
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() {
displayInfo();
draw.setActive(false);
});
// With OpenLayers 3.9, draw_interaction.removeLastPoint(); might be better.
document.addEventListener('keydown', function(e) {
//NOTE: e.key isn't defined in JavaFX Browser
......@@ -336,7 +336,7 @@ const regionChooser = (function(){
focusOnMap();
}
}
function sketchAsWKT(srsName) {
var wktFormat = new ol.format.WKT();
return wktFormat.writeFeature(sketch, {
......@@ -344,24 +344,24 @@ const regionChooser = (function(){
featureProjection : ol.proj.get('EPSG:3857')
});
}
function focusOnMap() {
document.getElementById("map").focus();
}
var fxapp = undefined;
publicScope.setFxApp = function(app){
fxapp = app;
console.log = function(message){
fxapp.log(message);
}
console.warn = function(message){
fxapp.warning(message);
}
}
function displayHelp(){
dataPanel.empty();
dataPanel.append("<h2 class='info'>Welcome to Region Chooser!<br><br>\n");
......@@ -375,27 +375,45 @@ const regionChooser = (function(){
dataPanel.append("<br>\n");
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("<form id='importWKT'>\n" +
"<input id='wktPolygon' type='text' placeholder='WKT Polygon' value='POLYGON ((30 10, 40 40, 20 40, 10 20, 30 10))'></input>\n" +
"<input type='submit' value='Import Polygon'></input>\n" +
dataPanel.append("<form id='importWKT' style='position:fixed; bottom:0;'>\n" +
"<input id='wktPolygon' type='text' placeholder='WKT Polygon' " +
"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");
document.getElementById('importWKT').addEventListener('submit', importWKT);
}
importWKT = function(e){
e.preventDefault(); // to avoid refresh
//TODO: DRY, possibly with other events
//TODO: Allow WKT as parameter for GUI?
console.log("Let's import WKT Polygon : " + wktPolygon);
var wktPolygon = document.getElementById("wktPolygon").value;
console.log("Try to import WKT geometry : " + wktPolygon);
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;
updateGMLPolygons();
......@@ -408,7 +426,7 @@ const regionChooser = (function(){
displayInfo();
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(){
document.documentElement.className = ''; // Stop waiting
console.log("Ready!");
}
publicScope.selectAllOrNone = function(allOrNone) {
document.querySelectorAll("input.select_citygml").forEach(c => c.checked = allOrNone);
publicScope.isDownloadPossible();
}
publicScope.selectRepository = function() {
fxapp.selectRepository();
}
publicScope.copyCoordinatesToClipboard = function(){
var geom = sketch.getGeometry().clone().transform(sourceProj, 'EPSG:4326');
var wgs84Coords = geom.getLinearRing(0).getCoordinates();
......@@ -437,7 +455,7 @@ const regionChooser = (function(){
wktPolygon += wgs84Coords.map(([lon, lat]) => lon.toFixed(precision) + " " + lat.toFixed(precision)).join(", ");
utils.copyToClipboard(wktPolygon + "))", dataPanel);
}
publicScope.showRepositoryName = function(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