diff --git a/bdtopo/src/main/groovy/org/orbisgis/geoclimate/bdtopo/InputDataFormatting.groovy b/bdtopo/src/main/groovy/org/orbisgis/geoclimate/bdtopo/InputDataFormatting.groovy index dff26d248e..bf72aa9065 100644 --- a/bdtopo/src/main/groovy/org/orbisgis/geoclimate/bdtopo/InputDataFormatting.groovy +++ b/bdtopo/src/main/groovy/org/orbisgis/geoclimate/bdtopo/InputDataFormatting.groovy @@ -20,11 +20,9 @@ package org.orbisgis.geoclimate.bdtopo import groovy.transform.BaseScript -import net.postgis.jdbc.geometry.LineString import org.locationtech.jts.geom.Geometry import org.locationtech.jts.geom.Polygon import org.orbisgis.data.H2GIS -import org.orbisgis.data.api.dataset.ISpatialTable import org.orbisgis.data.jdbc.JdbcDataSource import org.orbisgis.geoclimate.Geoindicators @@ -164,7 +162,7 @@ String formatBuildingLayer(JdbcDataSource datasource, String building, String zo height_roof = height_wall } //Update NB_LEV, HEIGHT_WALL and HEIGHT_ROOF - def formatedHeight = formatHeightsAndNbLevels(height_wall, height_roof, nb_lev, h_lev_min, + def formatedHeight = Geoindicators.WorkflowGeoIndicators.formatHeightsAndNbLevels(height_wall, height_roof, nb_lev, h_lev_min, feature_type, building_type_level) def zIndex = 0 @@ -753,63 +751,6 @@ String formatVegetationLayer(JdbcDataSource datasource, String vegetation, Strin return outputTableName } - -/** - * Rule to guarantee the height wall, height roof and number of levels values - * @param heightWall value - * @param heightRoof value - * @param nbLevels value - * @param h_lev_min value - * @return a map with the new values - */ -static Map formatHeightsAndNbLevels(def heightWall, def heightRoof, def nbLevels, def h_lev_min, - def buildingType, def levelBuildingTypeMap) { - //Use the BDTopo values - if (heightWall != 0 && heightRoof != 0 && nbLevels != 0) { - return [heightWall: heightWall, heightRoof: heightRoof, nbLevels: nbLevels, estimated: false] - } - //Initialisation of heights and number of levels - // Update height_wall - boolean estimated = false - if (heightWall == 0) { - if (!heightRoof || heightRoof == 0) { - if (nbLevels == 0) { - nbLevels = levelBuildingTypeMap[buildingType] - if (!nbLevels) { - nbLevels = 1 - } - heightWall = h_lev_min * nbLevels - heightRoof = heightWall - estimated = true - } else { - heightWall = h_lev_min * nbLevels - heightRoof = heightWall - } - } else { - heightWall = heightRoof - nbLevels = Math.max(Math.floor(heightWall / h_lev_min), 1) - } - } else if (heightWall == heightRoof) { - if (nbLevels == 0) { - nbLevels = Math.max(Math.floor(heightWall / h_lev_min), 1) - } - } - // Control of heights and number of levels - // Check if height_roof is lower than height_wall. If yes, then correct height_roof - else if (heightWall > heightRoof) { - heightRoof = heightWall - if (nbLevels == 0) { - nbLevels = Math.max(Math.floor(heightWall / h_lev_min), 1) - } - } else if (heightRoof > heightWall) { - if (nbLevels == 0) { - nbLevels = Math.max(Math.floor(heightRoof / h_lev_min), 1) - } - } - return [heightWall: heightWall, heightRoof: heightRoof, nbLevels: nbLevels, estimated: estimated] - -} - /** * This process is used to transform the BDTopo impervious table into a table that matches the constraints * of the geoClimate Input Model diff --git a/geoindicators/src/main/groovy/org/orbisgis/geoclimate/geoindicators/WorkflowGeoIndicators.groovy b/geoindicators/src/main/groovy/org/orbisgis/geoclimate/geoindicators/WorkflowGeoIndicators.groovy index bb9c4795f6..dd60d25e28 100644 --- a/geoindicators/src/main/groovy/org/orbisgis/geoclimate/geoindicators/WorkflowGeoIndicators.groovy +++ b/geoindicators/src/main/groovy/org/orbisgis/geoclimate/geoindicators/WorkflowGeoIndicators.groovy @@ -1225,7 +1225,7 @@ Map computeAllGeoIndicators(JdbcDataSource datasource, String zone, String build def indicatorUse = inputParameters.indicatorUse //Estimate height - if (inputParameters.buildingHeightModelName && datasource.getRowCount(building) > 0) { + if (inputParameters.buildingHeightModelName && datasource.getRowCount(buildingEstimateTableName) > 0) { def start = System.currentTimeMillis() enableTableCache() def buildingTableName @@ -1424,7 +1424,7 @@ Map estimateBuildingHeight(JdbcDataSource datasource, String zone, String buildi FROM $buildingIndicatorsForHeightEst a RIGHT JOIN $building_estimate b ON a.id_build=b.id_build - WHERE b.ESTIMATED = true AND a.ID_RSU IS NOT NULL;""".toString() + WHERE a.ID_RSU IS NOT NULL;""".toString() info "Collect building indicators to estimate the height" @@ -1435,7 +1435,7 @@ Map estimateBuildingHeight(JdbcDataSource datasource, String zone, String buildi prefixName) def buildingTableName = "BUILDING_TABLE_WITH_RSU_AND_BLOCK_ID" - def nbBuildingEstimated + int nbBuildingEstimated =0 def buildEstimatedHeight if (datasource.getTable(gatheredScales).isEmpty()) { info "No building height to estimate" @@ -1462,11 +1462,11 @@ Map estimateBuildingHeight(JdbcDataSource datasource, String zone, String buildi datasource.createIndex(buildEstimatedHeight, "id_build") - def newEstimatedHeigthWithIndicators = "NEW_BUILDING_INDICATORS_${UUID.randomUUID().toString().replaceAll("-", "_")}" + def formatedBuildEstimatedHeight = "INPUT_BUILDING_REFORMATED_${UUID.randomUUID().toString().replaceAll("-", "_")}" //Use build table indicators - datasource.execute """DROP TABLE IF EXISTS $newEstimatedHeigthWithIndicators; - CREATE TABLE $newEstimatedHeigthWithIndicators as + datasource.execute """DROP TABLE IF EXISTS $formatedBuildEstimatedHeight; + CREATE TABLE $formatedBuildEstimatedHeight as SELECT a.THE_GEOM, a.ID_BUILD,a.ID_SOURCE, CASE WHEN b.HEIGHT_ROOF IS NULL THEN a.HEIGHT_WALL ELSE 0 END AS HEIGHT_WALL , COALESCE(b.HEIGHT_ROOF, a.HEIGHT_ROOF) AS HEIGHT_ROOF, @@ -1476,14 +1476,13 @@ Map estimateBuildingHeight(JdbcDataSource datasource, String zone, String buildi //We must format only estimated buildings //Apply format on the new abstract table - def epsg = datasource."$newEstimatedHeigthWithIndicators".srid; - buildingTableName = formatEstimatedBuilding(datasource, newEstimatedHeigthWithIndicators, epsg) - - + def epsg = datasource.getSrid(formatedBuildEstimatedHeight) + buildingTableName = formatEstimatedBuilding(datasource, formatedBuildEstimatedHeight, epsg) //Drop intermediate tables datasource.execute """DROP TABLE IF EXISTS $estimated_building_with_indicators, - $newEstimatedHeigthWithIndicators, $buildEstimatedHeight, + $formatedBuildEstimatedHeight, $buildEstimatedHeight, $gatheredScales""".toString() + } return ["building" : buildingTableName, @@ -2164,13 +2163,14 @@ String formatEstimatedBuilding(JdbcDataSource datasource, String inputTableName, if (inputSpatialTable.rowCount > 0) { def columnNames = inputSpatialTable.columns queryMapper += " ${columnNames.join(",")} FROM $inputTableName" - datasource.withBatch(100) { stmt -> datasource.eachRow(queryMapper) { row -> def heightRoof = row.height_roof - def heightWall = heightRoof def type = row.type - def nbLevels = Math.floor(heightRoof / h_lev_min) + def formatedData = formatHeightsAndNbLevels(null, heightRoof, 0, h_lev_min, + type, null) + def nbLevels = formatedData.nbLevels + def heightWall = formatedData.heightWall stmt.addBatch """ INSERT INTO ${outputTableName} values( ST_GEOMFROMTEXT('${row.the_geom}',$epsg), @@ -2194,6 +2194,63 @@ String formatEstimatedBuilding(JdbcDataSource datasource, String inputTableName, } +/** + * Rule to guarantee the height wall, height roof and number of levels values + * @param heightWall value + * @param heightRoof value + * @param nbLevels value + * @param h_lev_min value + * @return a map with the new values + */ +static Map formatHeightsAndNbLevels(def heightWall, def heightRoof, def nbLevels, def h_lev_min, + def buildingType, def levelBuildingTypeMap) { + //Use the BDTopo values + if (heightWall != 0 && heightRoof != 0 && nbLevels != 0) { + return [heightWall: heightWall, heightRoof: heightRoof, nbLevels: nbLevels, estimated: false] + } + //Initialisation of heights and number of levels + // Update height_wall + boolean estimated = false + if (heightWall == 0) { + if (!heightRoof || heightRoof == 0) { + if (nbLevels == 0) { + nbLevels = levelBuildingTypeMap[buildingType] + if (!nbLevels) { + nbLevels = 1 + } + heightWall = h_lev_min * nbLevels + heightRoof = heightWall + estimated = true + } else { + heightWall = h_lev_min * nbLevels + heightRoof = heightWall + } + } else { + heightWall = heightRoof + nbLevels = Math.max(Math.floor(heightWall / h_lev_min), 1) + } + } else if (heightWall == heightRoof) { + if (nbLevels == 0) { + nbLevels = Math.max(Math.floor(heightWall / h_lev_min), 1) + } + } + // Control of heights and number of levels + // Check if height_roof is lower than height_wall. If yes, then correct height_roof + else if (heightWall > heightRoof) { + heightRoof = heightWall + if (nbLevels == 0) { + nbLevels = Math.max(Math.floor(heightWall / h_lev_min), 1) + } + } else if (heightRoof > heightWall) { + if (nbLevels == 0) { + nbLevels = Math.max(Math.floor(heightRoof / h_lev_min), 1) + } + } + return [heightWall: heightWall, heightRoof: heightRoof, nbLevels: nbLevels, estimated: estimated] + +} + + /** * This utility method checks if a model exists * - the model name must have the extension .model diff --git a/geoindicators/src/main/groovy/org/orbisgis/geoclimate/geoindicators/WorkflowUtilities.groovy b/geoindicators/src/main/groovy/org/orbisgis/geoclimate/geoindicators/WorkflowUtilities.groovy index 7db81a817a..f678650bcf 100644 --- a/geoindicators/src/main/groovy/org/orbisgis/geoclimate/geoindicators/WorkflowUtilities.groovy +++ b/geoindicators/src/main/groovy/org/orbisgis/geoclimate/geoindicators/WorkflowUtilities.groovy @@ -243,7 +243,7 @@ def saveToGeojson(def outputTable, def filePath, H2GIS h2gis_datasource, def out */ def saveToCSV(def outputTable, def filePath, def h2gis_datasource, def deleteOutputData) { if (outputTable && h2gis_datasource.hasTable(outputTable)) { - h2gis_datasource.save("(SELECT ID_BUILD, ID_SOURCE FROM $outputTable WHERE estimated=true)", filePath, deleteOutputData) + h2gis_datasource.save("(SELECT ID_BUILD, ID_SOURCE FROM $outputTable)", filePath, deleteOutputData) info "${outputTable} has been saved in ${filePath}." } } \ No newline at end of file diff --git a/osm/src/main/groovy/org/orbisgis/geoclimate/osm/InputDataFormatting.groovy b/osm/src/main/groovy/org/orbisgis/geoclimate/osm/InputDataFormatting.groovy index 3f2c393a4b..a62cee53ea 100644 --- a/osm/src/main/groovy/org/orbisgis/geoclimate/osm/InputDataFormatting.groovy +++ b/osm/src/main/groovy/org/orbisgis/geoclimate/osm/InputDataFormatting.groovy @@ -23,8 +23,8 @@ import groovy.json.JsonSlurper import groovy.transform.BaseScript import org.locationtech.jts.geom.Geometry import org.locationtech.jts.geom.Polygon -import org.orbisgis.data.api.dataset.ISpatialTable import org.orbisgis.data.jdbc.JdbcDataSource +import org.orbisgis.geoclimate.Geoindicators import java.util.regex.Pattern @@ -38,7 +38,6 @@ import java.util.regex.Pattern * @param building The name of the raw buildings table in the DB * @param zone an envelope to reduce the study area * @param urban_areas used to improved the building type - * @param building The name of the raw buildings table in the DB * @param hLevMin Minimum building level height * @param jsonFilename Name of the json formatted file containing the filtering parameters * @return outputTableName The name of the final buildings table @@ -56,8 +55,7 @@ Map formatBuildingLayer(JdbcDataSource datasource, String building, String zone DROP TABLE if exists ${outputEstimateTableName}; CREATE TABLE ${outputEstimateTableName} ( id_build INTEGER, - ID_SOURCE VARCHAR, - estimated boolean) + ID_SOURCE VARCHAR) """.toString() datasource """ @@ -101,7 +99,7 @@ Map formatBuildingLayer(JdbcDataSource datasource, String building, String zone def heightRoof = getHeightRoof(height, heightPattern) def heightWall = getHeightWall(heightRoof, roof_height) def nbLevels = getNbLevels(b_lev, roof_lev) - def formatedHeight = formatHeightsAndNbLevels(heightWall, heightRoof, nbLevels, h_lev_min, type, typeAndLevel) + def formatedHeight = Geoindicators.WorkflowGeoIndicators.formatHeightsAndNbLevels(heightWall, heightRoof, nbLevels, h_lev_min, type, typeAndLevel) def zIndex = getZIndex(row.'layer') String roof_shape = row.'roof:shape' @@ -125,13 +123,13 @@ Map formatBuildingLayer(JdbcDataSource datasource, String building, String zone ${roof_shape ? "'" + roof_shape + "'" : null}) """.toString() - stmt.addBatch """ + if(formatedHeight.estimated) { + stmt.addBatch """ INSERT INTO ${outputEstimateTableName} values( $id_build, - '${row.id}', - ${formatedHeight.estimated}) + '${row.id}') """.toString() - + } id_build++ } } @@ -759,57 +757,6 @@ static float getHeightWall(height, r_height) { return result } -/** - * Rule to guarantee the height wall, height roof and number of levels values - * @param heightWall value - * @param heightRoof value - * @param nbLevels value - * @param h_lev_min value - * @return a map with the new values - */ -static Map formatHeightsAndNbLevels(def heightWall, def heightRoof, def nbLevels, def h_lev_min, def buildingType, def levelBuildingTypeMap) { - //Use the OSM values - if (heightWall != 0 && heightRoof != 0 && nbLevels != 0) { - return [heightWall: heightWall, heightRoof: heightRoof, nbLevels: nbLevels, estimated: false] - } - //Initialisation of heights and number of levels - // Update height_wall - boolean estimated = false - if (heightWall == 0) { - if (heightRoof == 0) { - if (nbLevels == 0) { - nbLevels = levelBuildingTypeMap[buildingType] - if (!nbLevels) { - nbLevels = 1 - } - heightWall = h_lev_min * nbLevels - heightRoof = heightWall - estimated = true - } else { - heightWall = h_lev_min * nbLevels - heightRoof = heightWall - } - } else { - heightWall = heightRoof - nbLevels = Math.floor(heightWall / h_lev_min) - } - } else if (heightWall == heightRoof) { - if (nbLevels == 0) { - nbLevels = Math.floor(heightWall / h_lev_min) - } - } - // Control of heights and number of levels - // Check if height_roof is lower than height_wall. If yes, then correct height_roof - else if (heightWall > heightRoof) { - heightRoof = heightWall - if (nbLevels == 0) { - nbLevels = Math.floor(heightWall / h_lev_min) - } - } - return [heightWall: heightWall, heightRoof: heightRoof, nbLevels: nbLevels, estimated: estimated] -} - - /** * This function defines the value of the column height_roof according to the values of height and b_height * @param row The row of the raw table to examine diff --git a/osm/src/main/groovy/org/orbisgis/geoclimate/osm/WorkflowOSM.groovy b/osm/src/main/groovy/org/orbisgis/geoclimate/osm/WorkflowOSM.groovy index 9caa77d4dc..4223aa2b25 100644 --- a/osm/src/main/groovy/org/orbisgis/geoclimate/osm/WorkflowOSM.groovy +++ b/osm/src/main/groovy/org/orbisgis/geoclimate/osm/WorkflowOSM.groovy @@ -1065,7 +1065,7 @@ def saveTablesInDatabase(JdbcDataSource output_datasource, JdbcDataSource h2gis_ } else { output_datasource.execute """CREATE TABLE $output_table(ID_BUILD INTEGER, ID_SOURCE VARCHAR, ID_ZONE VARCHAR)""".toString() } - IOMethods.exportToDataBase(h2gis_datasource.getConnection(), "(SELECT ID_BUILD, ID_SOURCE, '$id_zone' as ID_ZONE from $h2gis_table_to_save where estimated=true)".toString(), + IOMethods.exportToDataBase(h2gis_datasource.getConnection(), "(SELECT ID_BUILD, ID_SOURCE, '$id_zone' as ID_ZONE from $h2gis_table_to_save)".toString(), output_datasource.getConnection(), output_table, 2, 100); } } diff --git a/osm/src/test/groovy/org/orbisgis/geoclimate/osm/InputDataFormattingTest.groovy b/osm/src/test/groovy/org/orbisgis/geoclimate/osm/InputDataFormattingTest.groovy index f48807995a..12919615f5 100644 --- a/osm/src/test/groovy/org/orbisgis/geoclimate/osm/InputDataFormattingTest.groovy +++ b/osm/src/test/groovy/org/orbisgis/geoclimate/osm/InputDataFormattingTest.groovy @@ -259,18 +259,18 @@ class InputDataFormattingTest { assertEquals 1038, h2GIS.getTable(buildingLayer).rowCount assertTrue h2GIS.firstRow("select count(*) as count from ${buildingLayer} where NB_LEV is null").count == 0 assertTrue h2GIS.firstRow("select count(*) as count from ${buildingLayer} where NB_LEV<0").count == 0 + assertTrue h2GIS.firstRow("select count(*) as count from ${buildingLayer} where NB_LEV=0").count == 0 assertTrue h2GIS.firstRow("select count(*) as count from ${buildingLayer} where HEIGHT_WALL is null").count == 0 assertTrue h2GIS.firstRow("select count(*) as count from ${buildingLayer} where HEIGHT_WALL<0").count == 0 assertTrue h2GIS.firstRow("select count(*) as count from ${buildingLayer} where HEIGHT_ROOF is null").count == 0 assertTrue h2GIS.firstRow("select count(*) as count from ${buildingLayer} where HEIGHT_ROOF<0").count == 0 - assertEquals 1038, h2GIS.getTable(buildingLayers.building_estimated).rowCount - assertTrue h2GIS.firstRow("select count(*) as count from ${buildingLayers.building_estimated} where ESTIMATED = false").count == 4 - assertTrue h2GIS.firstRow("select count(*) as count from ${buildingLayers.building} join ${buildingLayers.building_estimated} using (id_build, id_source) where 1=1").count == 1038 + assertEquals 1033, h2GIS.getTable(buildingLayers.building_estimated).rowCount + assertTrue h2GIS.firstRow("select count(*) as count from ${buildingLayers.building} join ${buildingLayers.building_estimated} using (id_build, id_source) where 1=1").count == 1033 //Buildings without estimation state buildingLayers = OSM.InputDataFormatting.formatBuildingLayer(h2GIS, extractData.building) assertEquals 1038, h2GIS.getTable(buildingLayers.building).rowCount - assertEquals 1038, h2GIS.getTable(buildingLayers.building_estimated).rowCount + assertEquals 1033, h2GIS.getTable(buildingLayers.building_estimated).rowCount } diff --git a/osm/src/test/groovy/org/orbisgis/geoclimate/osm/WorflowOSMTest.groovy b/osm/src/test/groovy/org/orbisgis/geoclimate/osm/WorflowOSMTest.groovy index 5224077ed8..b933adac14 100644 --- a/osm/src/test/groovy/org/orbisgis/geoclimate/osm/WorflowOSMTest.groovy +++ b/osm/src/test/groovy/org/orbisgis/geoclimate/osm/WorflowOSMTest.groovy @@ -653,7 +653,7 @@ class WorflowOSMTest extends WorkflowAbstractTest { //def nominatim = org.orbisgis.geoclimate.osmtools.OSMTools.Utilities.getNominatimData("Redon") // location = nominatim.bbox - location=[50, 8.6, 50.2, 8.8] + location=[43.725068,7.297883,43.727635,7.301284] def osm_parmeters = [ "description" : "Example of configuration file to run the OSM workflow and store the result in a folder", @@ -675,7 +675,7 @@ class WorflowOSMTest extends WorkflowAbstractTest { ["distance" : 0, "rsu_indicators" : [ - "indicatorUse": ["LCZ"] //, "UTRF", "TEB"] + "indicatorUse": ["LCZ", "UTRF"] //, "UTRF", "TEB"] ]/*,"grid_indicators": [ "x_size": 200, @@ -783,6 +783,36 @@ class WorflowOSMTest extends WorkflowAbstractTest { OSM.WorkflowOSM.workflow(configFile) } + + @Test + void testEstimateBuildingWithAllInputHeight() { + String directory = folder.absolutePath + File.separator + "test_building_height" + File dirFile = new File(directory) + dirFile.delete() + dirFile.mkdir() + def osm_parmeters = [ + "geoclimatedb": [ + "folder": dirFile.absolutePath, + "name" : "geoclimate_chain_db", + "delete": false + ], + "input" : [ + "locations": [[43.726898,7.298452,43.727677,7.299632]]], + "output" : [ + "folder": ["path" : directory, + "tables": ["building", "zone"]]], + "parameters" : + ["distance" : 0, + rsu_indicators: ["indicatorUse" : ["LCZ"]] + ] + ] + Map process = OSM.WorkflowOSM.workflow(osm_parmeters) + def tableNames = process.values() + def building = tableNames.building[0] + H2GIS h2gis = H2GIS.open("${directory + File.separator}geoclimate_chain_db;AUTO_SERVER=TRUE") + assertTrue h2gis.firstRow("select count(*) as count from $building where HEIGHT_WALL>0 and HEIGHT_ROOF>0").count > 0 + } + /** * Create a configuration file * @param osmParameters diff --git a/osm/src/test/resources/org/orbisgis/geoclimate/osm/redon.osm b/osm/src/test/resources/org/orbisgis/geoclimate/osm/redon.osm index 185c34c4d1..9597a3eb33 100644 --- a/osm/src/test/resources/org/orbisgis/geoclimate/osm/redon.osm +++ b/osm/src/test/resources/org/orbisgis/geoclimate/osm/redon.osm @@ -16330,9 +16330,11 @@ - + + + @@ -16348,6 +16350,7 @@ + @@ -64311,4 +64314,4 @@ - \ No newline at end of file +