diff --git a/.builds/clang.yml b/.builds/clang.yml
index 5a387c8d8..48db6096e 100644
--- a/.builds/clang.yml
+++ b/.builds/clang.yml
@@ -33,7 +33,7 @@ tasks:
-D CMAKE_C_COMPILER=clang \
-D CMAKE_CXX_COMPILER=clang++ \
-D OPENMP_SUPPORT=OFF \
- -D NINJA_QTGUI=OFF \
+ -D NINJA_GUI=OFF \
..
make -j 3
diff --git a/.builds/fedora.yml b/.builds/fedora.yml
index a6b6f2a66..8fde14d7b 100644
--- a/.builds/fedora.yml
+++ b/.builds/fedora.yml
@@ -27,7 +27,7 @@ tasks:
-D DISABLE_THREDDS_UPDATE=ON \
-D RUN_CFG_TESTS=ON \
-D STABILITY=ON \
- -D NINJA_QTGUI=OFF \
+ -D NINJA_GUI=OFF \
-D CMAKE_BUILD_TYPE=debug \
..
make -j 3
diff --git a/.gitignore b/.gitignore
index 412536450..fb04d8090 100644
--- a/.gitignore
+++ b/.gitignore
@@ -38,17 +38,13 @@ doxy.tag
*.swp
*~
-# Qt Creator files
+# Qt Creator files & user files
*.config
*.creator*
*.files
*.includes
-
-# Weather model files
-*UCAR*
-*NCAR*
-*NCEP*
-*NOMADS*
+*.user
+*.user*
# OpenFOAM
*.dep
diff --git a/CMakeLists.txt b/CMakeLists.txt
index d40274f05..af0b08861 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -15,12 +15,21 @@
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
# DEALINGS IN THE SOFTWARE.
-cmake_minimum_required (VERSION 3.0)
+cmake_minimum_required (VERSION 3.16)
+
+# Check if the user is using VCPKG on Windows
+if(WIN32)
+ if(NOT DEFINED CMAKE_TOOLCHAIN_FILE OR NOT CMAKE_TOOLCHAIN_FILE MATCHES "vcpkg.cmake")
+ message(FATAL_ERROR
+ "WindNinja requires the Visual C++ Package Manager VCPKG.\n"
+ )
+ endif()
+endif(WIN32)
project(WindNinja)
-# let cmake figure out how to set the C++ level
-set(CMAKE_CXX_STANDARD 11)
+# Set C++ version for CMake
+set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED on)
# Needed for FindNetCDF and GET_DATE()
@@ -30,7 +39,7 @@ option(FIRELAB_PACKAGE "Build a windows installer with dlls from the firelab mac
mark_as_advanced(FIRELAB_PACKAGE)
if(FIRELAB_PACKAGE)
- set(NINJA_QTGUI ON)
+ set(NINJA_GUI ON)
set(NINJA_CLI ON)
endif(FIRELAB_PACKAGE)
@@ -82,96 +91,30 @@ set(WINDNINJA_VERSION_NAME WindNinja-${VER_STR})
message(STATUS "VERSION: ${VER_STR}")
message(STATUS "PKG VERSION: ${WINDNINJA_VERSION_NAME}")
-# Locate third party libs
-include(FindBoost)
-set(Boost_DEBUG OFF)
-if(WIN32)
+# Find Dependencies: VCPKG for Windows and ATP for Linux
+if(MSVC)
+ find_package(shapelib CONFIG REQUIRED)
+ find_package(GDAL CONFIG REQUIRED)
+ find_package(netCDF CONFIG REQUIRED)
+ find_package(Boost REQUIRED COMPONENTS date_time program_options unit_test_framework)
+ set(GDAL_LIBRARY GDAL::GDAL)
+ set(NETCDF_LIBRARIES_C netCDF::netcdf)
+ set(Boost_DEBUG OFF)
set(Boost_USE_STATIC_LIBS ON)
-else(WIN32)
+ set(Boost_USE_MULTITHREAD OFF)
+else()
+ include(FindBoost)
+ set(Boost_DEBUG OFF)
set(Boost_USE_STATIC_LIBS OFF)
-endif(WIN32)
-set(Boost_USE_MULTITHREAD OFF)
-find_package(Boost 1.41.1 COMPONENTS date_time program_options
- unit_test_framework REQUIRED)
-
-# All GIS related libs. Windows uses GIS_INTERNALS_HOME
-if(WIN32)
- option(USE_GIS_INTERNALS "Use dependencies (as many as possible) from gisinternals.com" OFF)
- if(USE_GIS_INTERNALS)
- find_path(GIS_INTERNALS_HOME gdal CACHE PATH)
- file(TO_NATIVE_PATH ${GIS_INTERNALS_HOME} GIS_INTERNALS_HOME)
- string(REGEX REPLACE "\\\\" "/" GIS_INTERNALS_HOME "${GIS_INTERNALS_HOME}")
- endif(USE_GIS_INTERNALS)
-endif(WIN32)
-
-option(USE_VCPKG "Use VCPKG for boost and GDAL" )
-if(USE_VCPKG)
- message("Using VCPKG")
- find_package(GDAL CONFIG REQUIRED)
- find_package(NETCDF CONFIG REQUIRED)
-# target_link_libraries(main PRIVATE GDAL::GDAL)
-ELSE(USE_VCPKG)
+ set(Boost_USE_MULTITHREAD OFF)
+ find_package(Boost 1.41.1 COMPONENTS date_time program_options unit_test_framework REQUIRED)
include(FindNetCDF)
include(FindGDAL)
- if(WIN32)
- if(NOT GIS_INTERNALS_HOME)
- find_package(NetCDF REQUIRED)
- find_package(GDAL REQUIRED)
- else(NOT GIS_INTERNALS_HOME)
- find_package(NetCDF)
- find_package(GDAL)
- endif(NOT GIS_INTERNALS_HOME)
- else(WIN32)
- find_package(NetCDF REQUIRED)
- find_package(GDAL REQUIRED)
- endif(WIN32)
-endif(USE_VCPKG)
-option(NINJA_QT5GUI "build Qt5 experimental GUI" OFF)
-if(NINJA_QT5GUI)
- message("building qt5 gui")
- add_subdirectory(src/gui/ui)
-endif(NINJA_QT5GUI)
-
-if(USE_VCPKG)
- set(GDAL_LIBRARY GDAL::GDAL)
- set(NETCDF_LIBRARIES_C netCDF::netcdf)
-ELSE(USE_VCPKG)
- if(WIN32)
- if(NOT NETCDF_INCLUDES-NOTFOUND AND GIS_INTERNALS_HOME)
- set(NETCDF_INCLUDES ${GIS_INTERNALS_HOME}/include CACHE TYPE PATH FORCE)
- set(NETCDF_LIBRARIES NOT_USED CACHE TYPE PATH FORCE)
- set(NETCDF_LIBRARIES_C ${GIS_INTERNALS_HOME}/lib/netcdf.lib CACHE TYPE NAME FORCE)
- set(NETCDF_INCLUDES-FOUND TRUE)
- set(NETCDF_LIBRARIES_C-FOUND TRUE)
- endif(NOT NETCDF_INCLUDES-NOTFOUND AND GIS_INTERNALS_HOME)
- endif(WIN32)
- if(WIN32)
- if(NOT GDAL_INCLUDE_DIR-NOTFOUND AND GIS_INTERNALS_HOME)
- set(GDAL_INCLUDE_DIR ${GIS_INTERNALS_HOME}/include CACHE TYPE PATH FORCE)
- set(GDAL_LIBRARY ${GIS_INTERNALS_HOME}/lib/gdal_i.lib CACHE TYPE NAME FORCE)
- set(GDAL_INCLUDE_DIR-FOUND TRUE)
- set(GDAL_LIBRARY-FOUND TRUE)
- endif(NOT GDAL_INCLUDE_DIR-NOTFOUND AND GIS_INTERNALS_HOME)
- endif(WIN32)
-ENDIF(USE_VCPKG)
+ find_package(NetCDF)
+endif(MSVC)
# Ninja executables
-option(NINJA_QTGUI "Build Qt GUI" ON)
-if(NINJA_QTGUI)
- set(QT_USE_QTMAIN_LIBRARY 1)
- include(FindQt4)
- find_package(Qt4 COMPONENTS QtCore QtGui QtWebKit QtNetwork REQUIRED)
- include(${QT_USE_FILE})
- add_definitions(-DNINJA_GUI)
- if(WIN32)
- option(ENABLE_CONSOLE "Show the console for CLI/GUI runs" OFF)
- option(ENABLE_FIDDLER "Use Fiddler2 proxy to monitor web traffic" OFF)
- endif(WIN32)
- if(ENABLE_FIDDLER)
- add_definitions(-DENABLE_FIDDLER)
- endif(ENABLE_FIDDLER)
-endif(NINJA_QTGUI)
-
+option(NINJA_GUI "Build Qt GUI" ON)
option(NINJA_CLI "Build Command Line Interface" ON)
# Weather related options
@@ -186,30 +129,37 @@ if(WITH_NOMADS_SUPPORT)
if(NOT HAVE_TIMEGM)
add_definitions(-DUSE_INTERNAL_TIME_GM)
endif(NOT HAVE_TIMEGM)
+
option(NOMADS_USE_VSI_READ "Use VSI*L api instead of CPLHTTPFetch" OFF)
if(NOMADS_USE_VSI_READ)
add_definitions(-DNOMADS_USE_VSI_READ)
endif(NOMADS_USE_VSI_READ)
+
option(NOMADS_RTMA "Enable the RTMA forecasts" OFF)
if(NOMADS_RTMA)
add_definitions(-DNOMADS_RTMA)
endif(NOMADS_RTMA)
+
option(NOMADS_EXPER_FORECASTS "Enable NARRE and NEST forecasts." OFF)
if(NOMADS_EXPER_FORECASTS)
add_definitions(-DNOMADS_EXPER_FORECASTS)
endif(NOMADS_EXPER_FORECASTS)
+
option(NOMADS_ENABLE_ASYNC "Enable multi-threading for NOMADS download" ON)
if(NOMADS_ENABLE_ASYNC)
add_definitions(-DNOMADS_ENABLE_ASYNC)
endif(NOMADS_ENABLE_ASYNC)
+
option(NOMADS_USE_IP "Use the ip address for the nomads server, not a host" OFF)
if(NOMADS_USE_IP)
add_definitions(-DNOMADS_USE_IP)
endif(NOMADS_USE_IP)
+
option(NOMADS_ENABLE_3D "Enable 3d initialization using NOMADS data." OFF)
if(NOMADS_ENABLE_3D)
add_definitions(-DNOMADS_ENABLE_3D)
endif(NOMADS_ENABLE_3D)
+
option(NOMADS_INTERNAL_VRT "Use an internal copy of GDALAutoCreateVRT that allows for band subsetting" OFF)
if(NOMADS_INTERNAL_VRT)
add_definitions(-DNOMADS_INTERNAL_VRT)
@@ -232,36 +182,35 @@ if(WITH_LCP_CLIENT)
add_definitions(-DWITH_LCP_CLIENT)
endif(WITH_LCP_CLIENT)
-#disable for exception handling in the GUI and CLI
-option(C_API "Enable WindNinja C API" OFF)
-if(C_API)
- add_definitions(-DC_API)
-endif(C_API)
+# Disable for exception handling in the GUI and CLI
+# option(C_API "Enable WindNinja C API" OFF)
+# if(C_API)
+# add_definitions(-DC_API)
+# endif(C_API)
# Enable phone home and message server startup
option(PHONE_HOME_QUERIES "Enable Phone Home Queries" ON)
-
if (PHONE_HOME_QUERIES)
add_definitions(-DPHONE_HOME_QUERIES_ENABLED)
- message(STATUS "Phone Home Queries are enabled.")
-else()
- message(STATUS "Phone Home Queries are disabled.")
-endif()
+endif(PHONE_HOME_QUERIES)
# OpenFOAM related options
option(NINJAFOAM "Enable OpenFOAM solver" ON)
if(NINJAFOAM)
- add_definitions(-DNINJAFOAM)
+ add_compile_definitions(NINJAFOAM)
if(WIN32 AND FIRELAB_PACKAGE)
- add_definitions(-DFIRELAB_PACKAGE)
+ add_compile_definitions(FIRELAB_PACKAGE)
find_path(FOAM_MINGW_PATH OpenFOAM-2.2.x
DOC "Path to x-compiled OpenFOAM directory")
- if(FOAM_MINGW_PATH-NOTFOUND)
- message(FATAL_ERROR "You must provide a path to a cross-compiled OpenFOAM directory for NINJAFOAM support and package building")
- endif(FOAM_MINGW_PATH-NOTFOUND)
- endif(WIN32 AND FIRELAB_PACKAGE)
-endif(NINJAFOAM)
-string(REGEX REPLACE "\\\\" "/" FOAM_MINGW_PATH "${FOAM_MINGW_PATH}")
+
+ if(NOT FOAM_MINGW_PATH)
+ message(FATAL_ERROR
+ "You must provide a path to a cross-compiled OpenFOAM directory for NINJAFOAM support and package building")
+ endif()
+
+ string(REGEX REPLACE "\\\\" "/" FOAM_MINGW_PATH "${FOAM_MINGW_PATH}")
+ endif()
+endif()
# Miscellaneous options
option(NINJA_SPEED_TESTING "Enable initialization speed dampening" OFF)
@@ -336,18 +285,26 @@ endif(NOT WIN32)
# Optional utilities
option(BUILD_FETCH_DEM "Build a standalone command line interface DEM utility" OFF)
+
option(BUILD_STL_CONVERTER "Build a standalone command line interface for STL file conversions" OFF )
+
option(BUILD_CONVERT_OUTPUT "Build a standalone command line interface for xyz file conversions" OFF )
+
option(BUILD_WRF_TO_KMZ "Build a standalone command line interface for converting WRF output to kmz" OFF )
mark_as_advanced(BUILD_WRF_TO_KMZ)
+
option(BUILD_HRRR_TO_KMZ "Build a standalone command line interface for converting hrrr output runs to kmz, without running full WindNinja" OFF )
mark_as_advanced(BUILD_HRRR_TO_KMZ)
+
option(BUILD_SLOPE_ASPECT_GRID "Build an application for building slope and aspect grids from a dem" OFF)
mark_as_advanced(BUILD_SLOPE_ASPECT_GRID)
+
option(BUILD_FLOW_SEPARATION_GRID "Build an application for building flow separation" OFF)
mark_as_advanced(BUILD_FLOW_SEPARATION_GRID)
+
option(BUILD_SOLAR_GRID "Build a application for building solar grids" OFF)
mark_as_advanced(BUILD_SOLAR_GRID)
+
option(BUILD_SURFACE_INPUT_NODATA_FILLER "Build an application for filling input surface no data values" ON)
mark_as_advanced(BUILD_SURFACE_INPUT_NODATA_FILLER)
@@ -357,8 +314,6 @@ if(NINJA_GDAL_OUTPUT)
add_definitions(-DNINJA_GDAL_OUTPUT)
endif()
-option(FIRE_BEHAVIOR_DATA_INSTALL "Only install files necessary for FireBehaviorModels" OFF)
-
# Recurse into subdirectories
add_subdirectory(src)
@@ -372,6 +327,26 @@ if(BUILD_TESTING)
add_subdirectory(autotest)
endif(BUILD_TESTING)
+# Add the resource files for the .exe icon
+if (MSVC)
+ target_sources(WindNinja PRIVATE ${PROJECT_SOURCE_DIR}/wn-ms-resource.rc)
+endif()
+
+# Run windeployqt6.exe to provide all QT related DLLs
+if(MSVC)
+ find_program(WINDEPLOYQT_EXE
+ NAMES windeployqt6 windeployqt
+ HINTS "${Qt6_DIR}/../../../bin"
+ REQUIRED
+ )
+
+ add_custom_target(deploy_windninja ALL
+ COMMAND "${WINDEPLOYQT_EXE}"
+ "$"
+ DEPENDS WindNinja
+ )
+endif()
+
# Package related options and settings.
option(PACKAGE_DEBUG "Show some information about the package" OFF)
mark_as_advanced(PACKAGE_DEBUG)
@@ -382,18 +357,6 @@ if(CMAKE_SIZEOF_VOID_P MATCHES "8")
if(PACKAGE_DEBUG)
message(STATUS "Building 64-bit installer")
endif(PACKAGE_DEBUG)
-elseif(CMAKE_SIZEOF_VOID_P MATCHES "4")
- set(BUILD_64 FALSE)
- add_definitions(-DNINJA_32BIT=1)
- if(PACKAGE_DEBUG)
- message(STATUS "Building 32-bit installer")
- endif(PACKAGE_DEBUG)
-else(CMAKE_SIZEOF_VOID_P MATCHES "8")
- set(BUILD_64 FALSE)
- add_definitions(-DNINJA_32BIT=1)
- if(PACKAGE_DEBUG)
- message(STATUS "Cannot determine architecture, using 32-bit by default")
- endif(PACKAGE_DEBUG)
endif(CMAKE_SIZEOF_VOID_P MATCHES "8")
if(NOT CMAKE_BUILD_TYPE AND NOT MSVC_IDE)
@@ -410,93 +373,92 @@ if(VERBOSE_CMAKE)
include(CMakePrintSystemInformation)
endif(VERBOSE_CMAKE)
-if(FIRE_BEHAVIOR_DATA_INSTALL)
- #FireBehaviorModels only requires date_time_zonespec.csv and tz_world.zip
- message("Only installing data files necessary for FireBehaviorModels")
- set(fire_behavior_model_files date_time_zonespec.csv tz_world.zip)
- foreach(f ${fire_behavior_model_files})
- install(FILES ${PROJECT_SOURCE_DIR}/data/${f} DESTINATION
- share/windninja COMPONENT apps)
- endforeach(f ${fire_behavior_model_files})
-
-else(FIRE_BEHAVIOR_DATA_INSTALL)
-# install target related files
-set(etc_files missoula_valley.tif
- example_lcp.tif
- cli_domainAverage.cfg
- cli_domainAverage_diurnal.cfg
- cli_pointInitialization_diurnal.cfg
- cli_wxModelInitialization_diurnal.cfg
- cli_momentumSolver_diurnal.cfg)
-foreach(f ${etc_files})
- install(FILES ${PROJECT_SOURCE_DIR}/data/${f} DESTINATION
- etc/windninja/example-files COMPONENT apps)
-endforeach(f ${etc_files})
-
-#add weather station files to example files
-set(wx_station_current_files WXSTATIONS-2018-06-25-1237-missoula_valley/missoula_valley_stations_4.csv
- WXSTATIONS-2018-06-25-1237-missoula_valley/KMSO-2018-06-25_1237-0.csv
- WXSTATIONS-2018-06-25-1237-missoula_valley/PNTM8-2018-06-25_1237-2.csv
- WXSTATIONS-2018-06-25-1237-missoula_valley/TR266-2018-06-25_1237-3.csv
- WXSTATIONS-2018-06-25-1237-missoula_valley/TS934-2018-06-25_1237-1.csv)
-foreach(f ${wx_station_current_files})
- install(FILES ${PROJECT_SOURCE_DIR}/data/${f} DESTINATION
- etc/windninja/example-files/WXSTATIONS-2018-06-25-1237-missoula_valley COMPONENT apps)
-endforeach(f ${wx_station_current_files})
-
-#add weather station time series files
-set(wx_station_ts_files WXSTATIONS-MDT-2018-06-20-2128-2018-06-21-2128-missoula_valley/missoula_valley_stations_4.csv
- WXSTATIONS-MDT-2018-06-20-2128-2018-06-21-2128-missoula_valley/KMSO-MDT-2018-06-20_2128-2018-06-21_2128-0.csv
- WXSTATIONS-MDT-2018-06-20-2128-2018-06-21-2128-missoula_valley/PNTM8-MDT-2018-06-20_2128-2018-06-21_2128-2.csv
- WXSTATIONS-MDT-2018-06-20-2128-2018-06-21-2128-missoula_valley/TR266-MDT-2018-06-20_2128-2018-06-21_2128-3.csv
- WXSTATIONS-MDT-2018-06-20-2128-2018-06-21-2128-missoula_valley/TS934-MDT-2018-06-20_2128-2018-06-21_2128-1.csv)
-foreach(f ${wx_station_ts_files})
- install(FILES ${PROJECT_SOURCE_DIR}/data/${f} DESTINATION
- etc/windninja/example-files/WXSTATIONS-MDT-2018-06-20-2128-2018-06-21-2128-missoula_valley COMPONENT apps)
-endforeach(f ${wx_station_ts_files})
-
-set(share_files date_time_zonespec.csv
- config_options.csv
- tz_world.zip
- landfire.zip
- map.htm
- qt_certs_bundle.pem
- thredds.csv
- surface_data.zip
- srtm_region.geojson
- us_srtm_region.dbf
- us_srtm_region.prj
- us_srtm_region.shp
- us_srtm_region.shx)
-foreach(f ${share_files})
- install(FILES ${PROJECT_SOURCE_DIR}/data/${f} DESTINATION
- share/windninja COMPONENT apps)
-endforeach(f ${share_files})
-
-# Leaflet data
+# Install DEM and configuration files
+set(etc_files
+ missoula_valley.tif
+ example_lcp.tif
+ cli_domainAverage.cfg
+ cli_domainAverage_diurnal.cfg
+ cli_pointInitialization_diurnal.cfg
+ cli_wxModelInitialization_diurnal.cfg
+ cli_momentumSolver_diurnal.cfg)
+list(TRANSFORM etc_files PREPEND ${PROJECT_SOURCE_DIR}/data/)
+install(FILES ${etc_files}
+ DESTINATION etc/windninja/example-files
+ COMPONENT apps)
+
+# Install wxstation current files (add weather station files to example files)
+set(wx_station_current_files
+ missoula_valley_stations_4.csv
+ KMSO-2018-06-25_1237-0.csv
+ PNTM8-2018-06-25_1237-2.csv
+ TR266-2018-06-25_1237-3.csv
+ TS934-2018-06-25_1237-1.csv)
+list(TRANSFORM wx_station_current_files
+ PREPEND ${PROJECT_SOURCE_DIR}/data/WXSTATIONS-2018-06-25-1237-missoula_valley/)
+install(FILES ${wx_station_current_files}
+ DESTINATION etc/windninja/example-files/WXSTATIONS-2018-06-25-1237-missoula_valley
+ COMPONENT apps)
+
+# Install wxstation files (add weather station time series files)
+set(wx_station_ts_files
+ missoula_valley_stations_4.csv
+ KMSO-MDT-2018-06-20_2128-2018-06-21_2128-0.csv
+ PNTM8-MDT-2018-06-20_2128-2018-06-21_2128-2.csv
+ TR266-MDT-2018-06-20_2128-2018-06-21_2128-3.csv
+ TS934-MDT-2018-06-20_2128-2018-06-21_2128-1.csv)
+list(TRANSFORM wx_station_ts_files
+ PREPEND ${PROJECT_SOURCE_DIR}/data/WXSTATIONS-MDT-2018-06-20-2128-2018-06-21-2128-missoula_valley/)
+install(FILES ${wx_station_ts_files}
+ DESTINATION etc/windninja/example-files/WXSTATIONS-MDT-2018-06-20-2128-2018-06-21-2128-missoula_valley
+ COMPONENT apps)
+
+# Install all share files
+set(share_files
+ date_time_zonespec.csv
+ config_options.csv
+ tz_world.zip
+ landfire.zip
+ map.html
+ qt_certs_bundle.pem
+ thredds.csv
+ surface_data.zip
+ srtm_region.geojson
+ us_srtm_region.dbf
+ us_srtm_region.prj
+ us_srtm_region.shp
+ us_srtm_region.shx)
+list(TRANSFORM share_files PREPEND ${PROJECT_SOURCE_DIR}/data/)
+install(FILES ${share_files}
+ DESTINATION share/windninja
+ COMPONENT apps)
+
+# Install Leaflet data
if(WIN32 AND FIRELAB_PACKAGE)
- install(DIRECTORY ${PROJECT_SOURCE_DIR}/data/leaflet DESTINATION share)
-else(WIN32 AND FIRELAB_PACKAGE)
install(DIRECTORY ${PROJECT_SOURCE_DIR}/data/leaflet DESTINATION share/windninja)
endif(WIN32 AND FIRELAB_PACKAGE)
-set(doc_files CLI_instructions.pdf
- displaying_wind_vectors_in_ArcGIS_Pro.pdf
- download_elevation_file.pdf
- fetch_dem_instructions.pdf)
-foreach(f ${doc_files})
- install(FILES ${PROJECT_SOURCE_DIR}/doc/${f} DESTINATION
- share/windninja/doc COMPONENT apps)
-endforeach(f ${doc_files})
-
-set(tutorials tutorials/WindNinja_tutorial1.pdf
- tutorials/WindNinja_tutorial2.pdf
- tutorials/WindNinja_tutorial3.pdf
- tutorials/WindNinja_tutorial4.pdf)
-foreach(f ${tutorials})
- install(FILES ${PROJECT_SOURCE_DIR}/doc/${f} DESTINATION
- share/windninja/doc/tutorials COMPONENT apps)
-endforeach(f ${tutorials})
+# Install all documentation files
+set(doc_files
+ CLI_instructions.pdf
+ displaying_wind_vectors_in_ArcGIS_Pro.pdf
+ download_elevation_file.pdf
+ fetch_dem_instructions.pdf)
+list(TRANSFORM doc_files PREPEND ${PROJECT_SOURCE_DIR}/doc/)
+install(FILES ${doc_files}
+ DESTINATION share/windninja/doc
+ COMPONENT apps)
+
+# Install all tutorial files
+set(tutorial_files
+ WindNinja_tutorial1.pdf
+ WindNinja_tutorial2.pdf
+ WindNinja_tutorial3.pdf
+ WindNinja_tutorial4.pdf)
+list(TRANSFORM tutorial_files PREPEND ${PROJECT_SOURCE_DIR}/doc/tutorials/)
+install(FILES ${tutorial_files}
+ DESTINATION share/windninja/doc/tutorials
+ COMPONENT apps)
# Install the ninjafoam data
install(DIRECTORY ${PROJECT_SOURCE_DIR}/data/ninjafoam DESTINATION share/windninja)
@@ -506,18 +468,45 @@ install(FILES ${PROJECT_SOURCE_DIR}/data/wn-splash.png DESTINATION share/windnin
install(FILES ${PROJECT_SOURCE_DIR}/data/relief.xml DESTINATION share/windninja)
install(FILES ${PROJECT_SOURCE_DIR}/data/topofire_logo.png DESTINATION share/windninja)
-set(ZIPFILES "")
+# Installs specific to Windows NSIS installer
+if(WIN32)
+ # Install DLLS for WindNinja.exe to the bin directory
+ install(
+ DIRECTORY "${CMAKE_BINARY_DIR}/src/gui/"
+ DESTINATION bin
+ FILES_MATCHING
+ PATTERN "*.exe"
+ PATTERN "*.dll"
+ PATTERN "plugins/*"
+ PATTERN "platforms/*"
+ PATTERN "resources/*"
+ PATTERN "*.qm")
+
+ # Installs GDAL data from VCPKG to the gdal-data/data directory
+ install(
+ DIRECTORY "${CMAKE_BINARY_DIR}/vcpkg_installed/x64-windows/share/gdal/"
+ DESTINATION share/windninja/gdal-data/data
+ COMPONENT apps)
+
+ # Installs PROJ data from VCPKG to the proj-data/data directory
+ install(
+ DIRECTORY "${CMAKE_BINARY_DIR}/vcpkg_installed/x64-windows/share/proj/"
+ DESTINATION share/windninja/proj-data/data
+ COMPONENT apps)
+
+ if(NINJAFOAM)
+ install(DIRECTORY "${FOAM_MINGW_PATH}/etc" DESTINATION bin)
+ install(DIRECTORY "${FOAM_MINGW_PATH}/platforms" DESTINATION bin)
+ endif(NINJAFOAM)
+endif(WIN32)
-# GDAL data
-if(WIN32 AND FIRELAB_PACKAGE AND MSVC AND GIS_INTERNALS_HOME)
- install(DIRECTORY "${GIS_INTERNALS_HOME}/bin/gdal-data/" DESTINATION share/windninja/gdal-data/data)
-endif(WIN32 AND FIRELAB_PACKAGE AND MSVC AND GIS_INTERNALS_HOME)
+set(ZIPFILES "")
if(BUILD_TYPE MATCHES "debug")
if(PACKAGE_DEBUG)
message(STATUS "Copying boost date time file into build/src/gui and build/src/cli")
endif(PACKAGE_DEBUG)
- file(COPY "${PROJECT_SOURCE_DIR}/data/date_time_zonespec.csv" DESTINATION "${PROJECT_BINARY_DIR}/src/gui")
+ file(COPY "${PROJECT_SOURCE_DIR}/data/date_time_zonespec.csv" DESTINATION "${PROJECT_BINARY_DIR}/src/gui/qt6")
file(COPY "${PROJECT_SOURCE_DIR}/data/date_time_zonespec.csv" DESTINATION "${PROJECT_BINARY_DIR}/src/cli")
endif(BUILD_TYPE MATCHES "debug")
@@ -549,7 +538,7 @@ CreateDirectory \\\"$SMPROGRAMS\\\\$STARTMENU_FOLDER\\\\Documents\\\"
CreateShortCut \\\"$SMPROGRAMS\\\\$STARTMENU_FOLDER\\\\Tutorials\\\\Tutorial 1.lnk\\\" \\\"$INSTDIR\\\\share\\\\windninja\\\\doc\\\\tutorials\\\\WindNinja_Tutorial1.pdf\\\"
CreateShortCut \\\"$SMPROGRAMS\\\\$STARTMENU_FOLDER\\\\Tutorials\\\\Tutorial 2.lnk\\\" \\\"$INSTDIR\\\\share\\\\windninja\\\\doc\\\\tutorials\\\\WindNinja_Tutorial2.pdf\\\"
CreateShortCut \\\"$SMPROGRAMS\\\\$STARTMENU_FOLDER\\\\Tutorials\\\\Tutorial 3.lnk\\\" \\\"$INSTDIR\\\\share\\\\windninja\\\\doc\\\\tutorials\\\\WindNinja_Tutorial3.pdf\\\"
-CreateShortCut \\\"$SMPROGRAMS\\\\$STARTMENU_FOLDER\\\\Tutorials\\\\Tutorial 4.lnk\\\" \\\"$INSTDIR\\\\share\\\\windninja\\\\doc\\\\tutorials\\\\WindNinja_Tutorial4.pdf\\\"
+CreateShortCut \\\"$SMPROGRAMS\\\\$STARTMENU_FOLDER\\\\Tutorials\\\\Tutorial 4.lnk\\\" \\\"$INSTDIR\\\\share\\\\windninja\\\\doc\\\\tutorials\\\\WindNinja_Tutorial4.pdf\\\"
CreateShortCut \\\"$SMPROGRAMS\\\\$STARTMENU_FOLDER\\\\Documents\\\\CLI Instructions.lnk\\\" \\\"$INSTDIR\\\\share\\\\windninja\\\\doc\\\\CLI_instructions.pdf\\\"
CreateShortCut \\\"$SMPROGRAMS\\\\$STARTMENU_FOLDER\\\\Documents\\\\ArcMap Instructions.lnk\\\" \\\"$INSTDIR\\\\share\\\\windninja\\\\doc\\\\Displaying_wind_vectors_in_ArcMap.pdf\\\"
CreateShortCut \\\"$SMPROGRAMS\\\\$STARTMENU_FOLDER\\\\Documents\\\\DEM Download Instructions.lnk\\\" \\\"$INSTDIR\\\\share\\\\windninja\\\\doc\\\\download_elevation_file.pdf\\\"
@@ -567,74 +556,26 @@ Delete \\\"$SMPROGRAMS\\\\$MUI_TEMP\\\\Example Files.lnk\\\"
RMDir \\\"$SMPROGRAMS\\\\$MUI_TEMP\\\\Tutorials\\\"
RMDir \\\"$SMPROGRAMS\\\\$MUI_TEMP\\\\Documents\\\" ")
-# Build the nsis installer on the firelab machine(s). Not for external use.
-if(FIRELAB_PACKAGE AND WIN32 AND MSVC AND GIS_INTERNALS_HOME)
- # Install the CURL_CA_BUNDLE file from the bin folder, and drop it in data/
- install(FILES ${GIS_INTERNALS_HOME}/bin/curl/curl-ca-bundle.crt DESTINATION
- share/windninja COMPONENT apps)
- # Install the dlls GDAL depends on
- file(GLOB dlls ${GIS_INTERNALS_HOME}/bin/*.dll)
- foreach(dll ${dlls})
- install(PROGRAMS ${dll} DESTINATION bin COMPONENT apps)
- endforeach(dll ${dlls})
- install(PROGRAMS ${GIS_INTERNALS_HOME}/bin/gdal/plugins/gdal_netCDF.dll DESTINATION bin/gdalplugins COMPONENT app)
- get_filename_component(qtbin ${QT_QMAKE_EXECUTABLE} DIRECTORY)
- string(REGEX REPLACE "\\\\" "/" qtbin "${qtbin}")
- if(BUILD_TYPE MATCHES "release")
- install(PROGRAMS "${qtbin}/qtgui4.dll" DESTINATION bin COMPONENT apps)
- install(PROGRAMS "${qtbin}/qtcore4.dll" DESTINATION bin COMPONENT apps)
- install(PROGRAMS "${qtbin}/qtwebkit4.dll" DESTINATION bin COMPONENT apps)
- install(PROGRAMS "${qtbin}/phonon4.dll" DESTINATION bin COMPONENT apps)
- install(PROGRAMS "${qtbin}/qtnetwork4.dll" DESTINATION bin COMPONENT apps)
- install(PROGRAMS "${QT_PLUGINS_DIR}/imageformats/qjpeg4.dll" DESTINATION bin/imageformats)
- else(BUILD_TYPE MATCHES "release")
- install(PROGRAMS "${qtbin}/qtguid4.dll" DESTINATION bin COMPONENT apps)
- install(PROGRAMS "${qtbin}/qtcored4.dll" DESTINATION bin COMPONENT apps)
- install(PROGRAMS "${qtbin}/qtwebkitd4.dll" DESTINATION bin COMPONENT apps)
- install(PROGRAMS "${qtbin}/phonond4.dll" DESTINATION bin COMPONENT apps)
- install(PROGRAMS "${qtbin}/qtnetworkd4.dll" DESTINATION bin COMPONENT apps)
- install(PROGRAMS "${QT_PLUGINS_DIR}/imageformats/qjpegd4.dll" DESTINATION bin/imageformats)
- endif( BUILD_TYPE MATCHES "release")
- # HACK FOR OPENMP
- if(BUILD_64)
- install(PROGRAMS ${MSVC_REDIST_DIR}/x64/Microsoft.VC100.OPENMP/vcomp100.dll DESTINATION bin COMPONENT apps)
- else(BUILD_64)
- install(PROGRAMS ${MSVC_REDIST_DIR}/x86/Microsoft.VC100.OPENMP/vcomp100.dll DESTINATION bin COMPONENT apps)
- endif(BUILD_64)
- if(NINJAFOAM)
- install(DIRECTORY "${FOAM_MINGW_PATH}/etc" DESTINATION bin)
- install(DIRECTORY "${FOAM_MINGW_PATH}/platforms" DESTINATION bin)
- endif(NINJAFOAM)
-endif(FIRELAB_PACKAGE AND WIN32 AND MSVC AND GIS_INTERNALS_HOME)
set(CPACK_COMPONENT_APPS_REQUIRED TRUE)
set(CPACK_COMPONENT_LIBS_HIDDEN TRUE)
set(CPACK_COMPONENT_LIBS_DISABLED TRUE)
set(CPACK_COMPONENT_INCLUDES_HIDDEN TRUE)
set(CPACK_COMPONENT_INCLUDES_DISABLED TRUE)
-# *****************************************************************************
# CPack call
-# *****************************************************************************
include(CPack)
include(CTest)
-# *****************************************************************************
-# CPack groupings
-# *****************************************************************************
+# CPack Groupings
CPACK_ADD_COMPONENT(apps
DISPLAY_NAME "WindNinja"
DESCRIPTION "WindNinja binaries and documentation"
- GROUP Application
- )
+ GROUP Application)
+
CPACK_ADD_COMPONENT(libs
DISPLAY_NAME "WindNinja Libraries"
- DESCRIPTION "Development libraries"
- #GROUP Development
- )
+ DESCRIPTION "Development libraries")
+
CPACK_ADD_COMPONENT(includes
DISPLAY_NAME "WindNinja Headers"
- DESCRIPTION "Development include files"
- #GROUP Development
- )
-
-endif(FIRE_BEHAVIOR_DATA_INSTALL)
+ DESCRIPTION "Development include files")
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
new file mode 100644
index 000000000..fbe84cedd
--- /dev/null
+++ b/CONTRIBUTING.md
@@ -0,0 +1,169 @@
+# Contributing to WindNinja
+
+Thank you for considering to contribute to WindNinja. As a crucial tool used in fire management, we appreciate any support to help the project.
+
+Please see the guides below for common contributions:
+- Ask a question
+- Report an issue
+- Request a feature
+- Write and run tests - coming soon
+
+
+### Explain contributions you are NOT looking for (if any).
+
+Again, defining this up front means less work for you. If someone ignores your guide and submits something you don’t want, you can simply close it and point to your policy.
+
+> Please, don't use the issue tracker for [support questions]. Check whether the #pocoo IRC channel on Freenode can help with your issue. If your problem is not strictly Werkzeug or Flask specific, #python is generally more active. Stack Overflow is also worth considering.
+
+[source: [Flask](https://github.com/pallets/flask/blob/master/CONTRIBUTING.rst)] **Need more inspiration?** [1] [cucumber-ruby](https://github.com/cucumber/cucumber-ruby/blob/master/CONTRIBUTING.md#about-to-create-a-new-github-issue) [2] [Read the Docs](http://read-the-docs.readthedocs.org/en/latest/open-source-philosophy.html#unsupported)
+
+# Ground Rules
+### Set expectations for behavior (yours, and theirs).
+This includes not just how to communicate with others (being respectful, considerate, etc) but also technical responsibilities (importance of testing, project dependencies, etc). Mention and link to your code of conduct, if you have one.
+
+> Responsibilities
+> * Ensure cross-platform compatibility for every change that's accepted. Windows, Mac, Debian & Ubuntu Linux.
+> * Ensure that code that goes into core meets all requirements in this checklist: https://gist.github.com/audreyr/4feef90445b9680475f2
+> * Create issues for any major changes and enhancements that you wish to make. Discuss things transparently and get community feedback.
+> * Don't add any classes to the codebase unless absolutely needed. Err on the side of using functions.
+> * Keep feature versions as small as possible, preferably one new feature per version.
+> * Be welcoming to newcomers and encourage diverse new contributors from all backgrounds. See the [Python Community Code of Conduct](https://www.python.org/psf/codeofconduct/).
+
+[source: [cookiecutter](https://github.com/audreyr/cookiecutter/blob/master/CONTRIBUTING.rst)] **Need more inspiration?** [1] [Celery](https://github.com/celery/celery/blob/master/CONTRIBUTING.rst#community-code-of-conduct) [2] [geocoder](https://github.com/alexreisner/geocoder#contributing)
+
+# Your First Contribution
+Help people who are new to your project understand where they can be most helpful. This is also a good time to let people know if you follow a label convention for flagging beginner issues.
+
+> Unsure where to begin contributing to Atom? You can start by looking through these beginner and help-wanted issues:
+> Beginner issues - issues which should only require a few lines of code, and a test or two.
+> Help wanted issues - issues which should be a bit more involved than beginner issues.
+> Both issue lists are sorted by total number of comments. While not perfect, number of comments is a reasonable proxy for impact a given change will have.
+
+[source: [Atom](https://github.com/atom/atom/blob/master/CONTRIBUTING.md#your-first-code-contribution)] **Need more inspiration?** [1] [Read the Docs](http://docs.readthedocs.org/en/latest/contribute.html#contributing-to-development) [2] [Django](https://docs.djangoproject.com/en/dev/internals/contributing/new-contributors/#first-steps) (scroll down to "Guidelines" as well)
+
+### Bonus points: Add a link to a resource for people who have never contributed to open source before.
+Here are a couple of friendly tutorials you can include: http://makeapullrequest.com/ and http://www.firsttimersonly.com/
+
+> Working on your first Pull Request? You can learn how from this *free* series, [How to Contribute to an Open Source Project on GitHub](https://egghead.io/series/how-to-contribute-to-an-open-source-project-on-github).
+
+[source: [React](https://github.com/facebook/react/blob/master/CONTRIBUTING.md#pull-requests)]
+
+As a side note, it helps to use newcomer-friendly language throughout the rest of your document. Here are a couple of examples from [Active Admin](https://github.com/activeadmin/activeadmin/blob/master/CONTRIBUTING.md):
+
+>At this point, you're ready to make your changes! Feel free to ask for help; everyone is a beginner at first :smile_cat:
+>
+>If a maintainer asks you to "rebase" your PR, they're saying that a lot of code has changed, and that you need to update your branch so it's easier to merge.
+
+# Getting started
+### Give them a quick walkthrough of how to submit a contribution.
+How you write this is up to you, but some things you may want to include:
+
+* Let them know if they need to sign a CLA, agree to a DCO, or get any other legal stuff out of the way
+* If tests are required for contributions, let them know, and explain how to run the tests
+* If you use anything other than GitHub to manage issues (ex. JIRA or Trac), let them know which tools they’ll need to contribute
+
+>For something that is bigger than a one or two line fix:
+
+>1. Create your own fork of the code
+>2. Do the changes in your fork
+>3. If you like the change and think the project could use it:
+ * Be sure you have followed the code style for the project.
+ * Sign the Contributor License Agreement, CLA, with the jQuery Foundation.
+ * Note the jQuery Foundation Code of Conduct.
+ * Send a pull request indicating that you have a CLA on file.
+
+[source: [Requirejs](http://requirejs.org/docs/contributing.html)] **Need more inspiration?** [1] [Active Admin](https://github.com/activeadmin/activeadmin/blob/master/CONTRIBUTING.md#1-where-do-i-go-from-here) [2] [Node.js](https://github.com/nodejs/node/blob/master/CONTRIBUTING.md#code-contributions) [3] [Ember.js](https://github.com/emberjs/ember.js/blob/master/CONTRIBUTING.md#pull-requests)
+
+### If you have a different process for small or "obvious" fixes, let them know.
+
+> Small contributions such as fixing spelling errors, where the content is small enough to not be considered intellectual property, can be submitted by a contributor as a patch, without a CLA.
+>
+>As a rule of thumb, changes are obvious fixes if they do not introduce any new functionality or creative thinking. As long as the change does not affect functionality, some likely examples include the following:
+>* Spelling / grammar fixes
+>* Typo correction, white space and formatting changes
+>* Comment clean up
+>* Bug fixes that change default return values or error codes stored in constants
+>* Adding logging messages or debugging output
+>* Changes to ‘metadata’ files like Gemfile, .gitignore, build scripts, etc.
+>* Moving source files from one directory or package to another
+
+[source: [Chef](https://github.com/chef/chef/blob/master/CONTRIBUTING.md#chef-obvious-fix-policy)] **Need more inspiration?** [1] [Puppet](https://github.com/puppetlabs/puppet/blob/master/CONTRIBUTING.md#making-trivial-changes)
+
+# How to report a bug
+### Explain security disclosures first!
+At bare minimum, include this sentence:
+> If you find a security vulnerability, do NOT open an issue. Email XXXX instead.
+
+If you don’t want to use your personal contact information, set up a “security@” email address. Larger projects might have more formal processes for disclosing security, including encrypted communication. (Disclosure: I am not a security expert.)
+
+> Any security issues should be submitted directly to security@travis-ci.org
+> In order to determine whether you are dealing with a security issue, ask yourself these two questions:
+> * Can I access something that's not mine, or something I shouldn't have access to?
+> * Can I disable something for other people?
+>
+> If the answer to either of those two questions are "yes", then you're probably dealing with a security issue. Note that even if you answer "no" to both questions, you may still be dealing with a security issue, so if you're unsure, just email us at security@travis-ci.org.
+
+[source: [Travis CI](https://github.com/travis-ci/travis-ci/blob/master/CONTRIBUTING.md)] **Need more inspiration?** [1] [Celery](https://github.com/celery/celery/blob/master/CONTRIBUTING.rst#security) [2] [Express.js](https://github.com/expressjs/express/blob/master/Security.md)
+
+### Tell your contributors how to file a bug report.
+You can even include a template so people can just copy-paste (again, less work for you).
+
+> When filing an issue, make sure to answer these five questions:
+>
+> 1. What version of Go are you using (go version)?
+> 2. What operating system and processor architecture are you using?
+> 3. What did you do?
+> 4. What did you expect to see?
+> 5. What did you see instead?
+> General questions should go to the golang-nuts mailing list instead of the issue tracker. The gophers there will answer or ask you to file an issue if you've tripped over a bug.
+
+[source: [Go](https://github.com/golang/go/blob/master/CONTRIBUTING.md#filing-issues)] **Need more inspiration?** [1] [Celery](https://github.com/celery/celery/blob/master/CONTRIBUTING.rst#other-bugs ) [2] [Atom](https://github.com/atom/atom/blob/master/CONTRIBUTING.md#reporting-bugs) (includes template)
+
+# How to suggest a feature or enhancement
+### If you have a particular roadmap, goals, or philosophy for development, share it here.
+This information will give contributors context before they make suggestions that may not align with the project’s needs.
+
+> The Express philosophy is to provide small, robust tooling for HTTP servers, making it a great solution for single page applications, web sites, hybrids, or public HTTP APIs.
+>
+> Express does not force you to use any specific ORM or template engine. With support for over 14 template engines via Consolidate.js, you can quickly craft your perfect framework.
+
+[source: [Express](https://github.com/expressjs/express#philosophy)] **Need more inspiration?** [Active Admin](https://github.com/activeadmin/activeadmin#goals)
+
+### Explain your desired process for suggesting a feature.
+If there is back-and-forth or signoff required, say so. Ask them to scope the feature, thinking through why it’s needed and how it might work.
+
+> If you find yourself wishing for a feature that doesn't exist in Elasticsearch, you are probably not alone. There are bound to be others out there with similar needs. Many of the features that Elasticsearch has today have been added because our users saw the need. Open an issue on our issues list on GitHub which describes the feature you would like to see, why you need it, and how it should work.
+
+[source: [Elasticsearch](https://github.com/elastic/elasticsearch/blob/master/CONTRIBUTING.md#feature-requests)] **Need more inspiration?** [1] [Hoodie](https://github.com/hoodiehq/hoodie/blob/master/CONTRIBUTING.md#feature-requests) [2] [Ember.js](https://github.com/emberjs/ember.js/blob/master/CONTRIBUTING.md#requesting-a-feature)
+
+# Code review process
+### Explain how a contribution gets accepted after it’s been submitted.
+Who reviews it? Who needs to sign off before it’s accepted? When should a contributor expect to hear from you? How can contributors get commit access, if at all?
+
+> The core team looks at Pull Requests on a regular basis in a weekly triage meeting that we hold in a public Google Hangout. The hangout is announced in the weekly status updates that are sent to the puppet-dev list. Notes are posted to the Puppet Community community-triage repo and include a link to a YouTube recording of the hangout.
+> After feedback has been given we expect responses within two weeks. After two weeks we may close the pull request if it isn't showing any activity.
+
+[source: [Puppet](https://github.com/puppetlabs/puppet/blob/master/CONTRIBUTING.md#submitting-changes)] **Need more inspiration?** [1] [Meteor](https://meteor.hackpad.com/Responding-to-GitHub-Issues-SKE2u3tkSiH ) [2] [Express.js](https://github.com/expressjs/express/blob/master/Contributing.md#becoming-a-committer)
+
+# Community
+If there are other channels you use besides GitHub to discuss contributions, mention them here. You can also list the author, maintainers, and/or contributors here, or set expectations for response time.
+
+> You can chat with the core team on https://gitter.im/cucumber/cucumber. We try to have office hours on Fridays.
+
+[source: [cucumber-ruby](https://github.com/cucumber/cucumber-ruby/blob/master/CONTRIBUTING.md#talking-with-other-devs)] **Need more inspiration?**
+ [1] [Chef](https://github.com/chef/chef/blob/master/CONTRIBUTING.md#-developer-office-hours) [2] [Cookiecutter](https://github.com/audreyr/cookiecutter#community)
+
+# BONUS: Code, commit message and labeling conventions
+These sections are not necessary, but can help streamline the contributions you receive.
+
+### Explain your preferred style for code, if you have any.
+
+**Need inspiration?** [1] [Requirejs](http://requirejs.org/docs/contributing.html#codestyle) [2] [Elasticsearch](https://github.com/elastic/elasticsearch/blob/master/CONTRIBUTING.md#contributing-to-the-elasticsearch-codebase)
+
+### Explain if you use any commit message conventions.
+
+**Need inspiration?** [1] [Angular](https://github.com/angular/material/blob/master/.github/CONTRIBUTING.md#submit) [2] [Node.js](https://github.com/nodejs/node/blob/master/CONTRIBUTING.md#step-3-commit)
+
+### Explain if you use any labeling conventions for issues.
+
+**Need inspiration?** [1] [StandardIssueLabels](https://github.com/wagenet/StandardIssueLabels#standardissuelabels) [2] [Atom](https://github.com/atom/atom/blob/master/CONTRIBUTING.md#issue-and-pull-request-labels)
\ No newline at end of file
diff --git a/CONTRIBUTORS b/CONTRIBUTORS
index 513d04777..945a16042 100644
--- a/CONTRIBUTORS
+++ b/CONTRIBUTORS
@@ -31,3 +31,4 @@ Tomàs Margalef
Hannah Gedlaman
Nicholas Kim
Rui Zhang
+Jack Hayward
diff --git a/autotest/CMakeLists.txt b/autotest/CMakeLists.txt
index 744292886..2694b6f37 100644
--- a/autotest/CMakeLists.txt
+++ b/autotest/CMakeLists.txt
@@ -15,7 +15,7 @@
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
# DEALINGS IN THE SOFTWARE.
-#cmake_minimum_required(VERSION 2.6)
+#cmake_minimum_required(VERSION 3.16)
include_directories(${PROJECT_SOURCE_DIR}/src/ninja
${NETCDF_INCLUDES}
@@ -129,11 +129,11 @@ if(WITH_LCP_CLIENT)
endif(WITH_LCP_CLIENT)
# input_points Test Suite
-if(NOT NINJA_QTGUI)
+if(NOT NINJA_GUI)
# This test doesn't work
#add_test(test_input_points_mackay
# ${EXECUTABLE_OUTPUT_PATH}/test_main --run_test=input_points/mackay )
-endif(NOT NINJA_QTGUI)
+endif(NOT NINJA_GUI)
if(NINJA_GDAL_OUTPUT)
add_test(test_gdal_output_shapefile
diff --git a/autotest/api/test_capi_domain_average_wind.c b/autotest/api/test_capi_domain_average_wind.c
index 4898cfd57..98933eb1e 100644
--- a/autotest/api/test_capi_domain_average_wind.c
+++ b/autotest/api/test_capi_domain_average_wind.c
@@ -38,36 +38,42 @@ int main()
* Setting up the simulation
*/
NinjaArmyH* ninjaArmy = NULL;
- const char * comType = "cli"; //communication type is always set to "cli"
- const int nCPUs = 1;
+ const int nCPUs = 3;
+ const char * runType = "C-API autotest";
char ** papszOptions = NULL;
- NinjaErr err = 0;
- err = NinjaInit(papszOptions); //initialize global singletons and environments (GDAL_DATA, etc.)
+ NinjaErr err = 0;
+ err = NinjaInit(runType, papszOptions); //initialize global singletons and environments (GDAL_DATA, etc.)
if(err != NINJA_SUCCESS)
{
- printf("NinjaInit: err = %d\n", err);
+ printf("NinjaInit: err = %d\n", err);
+ }
+
+ /*
+ * Setting up a log file, for ninjaCom, if desired
+ */
+ FILE* multiStream = NULL;
+ multiStream = fopen("/home/atw09001/src/wind/windninja/autotest/api/data/output/ninja.log", "w+");
+ if(multiStream == NULL)
+ {
+ printf("error opening log file\n");
}
/*
* Set up domain average run
*/
/* inputs that do not vary among ninjas in an army */
- const char * demFile = "/home/mason/Documents/Git/WindNinja/windninja/autotest/api/data/missoula_valley.tif";
+ const char * demFile = "/home/atw09001/src/wind/windninja/autotest/api/data/missoula_valley.tif";
const char * initializationMethod = "domain_average";
const char * meshChoice = "coarse";
const char * vegetation = "grass";
const int nLayers = 20; //layers in the mesh
- const int diurnalFlag = 0; //diurnal slope wind parameterization not used
+ const int diurnalFlag = 1; //diurnal slope wind parameterization not used
const double height = 10.0;
const char * heightUnits = "m";
- bool momentumFlag = 0; //we're using the conservation of mass solver
+ //bool momentumFlag = 0; //we're using the conservation of mass solver
+ bool momentumFlag = 1; //we're using the conservation of momentum solver
unsigned int numNinjas = 2; //two ninjas in the ninjaArmy - must be equal to array sizes
- /* inputs that can vary among ninjas in an army */
- const double speedList[] = {5.5, 5.5}; // matches the size of numNinjas
- const char * speedUnits = "mps";
- const double directionList[] = {220, 300}; // matches the size of numNinjas
-
/* inputs specific to output
* Note: Outputs have default values if inputs are not specified (like resolution)
*/
@@ -75,16 +81,55 @@ int main()
const char * units = "m";
const double width = 1.0;
const char * scaling = "equal_color";
- const char * outputPath = "/home/mason/Documents/Git/WindNinja/windninja/autotest/api/data/output";
+ const char * outputPath = "/home/atw09001/src/wind/windninja/autotest/api/data/output";
const bool outputFlag = 1;
- /*
- * Create the army
+ /* inputs that can vary among ninjas in an army */
+ const double speedList[] = {5.5, 5.5}; // matches the size of numNinjas
+ const char * speedUnits = "mps";
+ const double directionList[2] = {220.0, 300.0};
+ const int year[2] = {2023, 2023};
+ const int month[2] = {10, 11};
+ const int day[2] = {10, 11};
+ const int hour[2] = {12, 13};
+ const int minute[2] = {30, 31};
+ const char * timezone = "UTC";
+ const double air[2] = {50.0, 50.0};
+ const char * airUnits = "F";
+ const double cloud[2] = {10.0, 10.0};
+ const char * cloudUnits = "percent";
+
+ const double meshResolution = -1.0; //set to value > 0.0 to override meshChoice with meshResolution value
+ //const double meshResolution = 300.0;
+ const char * meshResolutionUnits = "m";
+
+ bool matchedPoints = true; // for point initialization, but currently required as an input to SetInitializationMethod(). Should the match points pointInitialization algorythm be run, or should it just run as a domainAvgRun on the input wind field. ALWAYS set to true unless you know what you are doing.
+
+ /*
+ * Initialize the army
*/
- ninjaArmy = NinjaMakeDomainAverageArmy(numNinjas, momentumFlag, speedList, speedUnits, directionList, papszOptions);
+ ninjaArmy = NinjaInitializeArmy();
if( NULL == ninjaArmy )
{
- printf("NinjaCreateArmy: ninjaArmy = NULL\n");
+ printf("NinjaInitializeArmy: ninjaArmy = NULL\n");
+ }
+
+ /*
+ * Customize the ninja communication
+ */
+ err = NinjaSetArmyMultiComStream(ninjaArmy, multiStream, papszOptions);
+ if(err != NINJA_SUCCESS)
+ {
+ printf("NinjaSetArmyMultiComStream: err = %d\n", err);
+ }
+
+ /*
+ * Create the army
+ */
+ err = NinjaMakeDomainAverageArmy(ninjaArmy, numNinjas, momentumFlag, speedList, speedUnits, directionList, year, month, day, hour, minute, timezone, air, airUnits, cloud, cloudUnits, papszOptions);
+ if( err != NINJA_SUCCESS)
+ {
+ printf("NinjaMakeDomainAverageArmy: err = %d\n", err);
}
/*
@@ -95,19 +140,13 @@ int main()
/*
* Sets Simulation Variables
*/
- err = NinjaSetCommunication(ninjaArmy, i, comType, papszOptions);
- if(err != NINJA_SUCCESS)
- {
- printf("NinjaSetCommunication: err = %d\n", err);
- }
-
err = NinjaSetNumberCPUs(ninjaArmy, i, nCPUs, papszOptions);
if(err != NINJA_SUCCESS)
{
printf("NinjaSetNumberCPUs: err = %d\n", err);
}
- err = NinjaSetInitializationMethod(ninjaArmy, i, initializationMethod, papszOptions);
+ err = NinjaSetInitializationMethod(ninjaArmy, i, initializationMethod, matchedPoints, papszOptions);
if(err != NINJA_SUCCESS)
{
printf("NinjaSetInitializationMethod: err = %d\n", err);
@@ -154,13 +193,24 @@ int main()
{
printf("NinjaSetUniVegetation: err = %d\n", err);
}
-
- err = NinjaSetMeshResolutionChoice(ninjaArmy, i, meshChoice, papszOptions);
- if(err != NINJA_SUCCESS)
+
+ if( meshResolution > 0.0 )
{
+ err = NinjaSetMeshResolution(ninjaArmy, i, meshResolution, meshResolutionUnits, papszOptions);
+ if(err != NINJA_SUCCESS)
+ {
+ printf("NinjaSetMeshResolution: err = %d\n", err);
+ }
+ }
+ else // meshResolution not set, use meshChoice
+ {
+ err = NinjaSetMeshResolutionChoice(ninjaArmy, i, meshChoice, papszOptions);
+ if(err != NINJA_SUCCESS)
+ {
printf("NinjaSetMeshResolutionChoice: err = %d\n", err);
+ }
}
-
+
err = NinjaSetNumVertLayers(ninjaArmy, i, nLayers, papszOptions);
if(err != NINJA_SUCCESS)
{
@@ -185,6 +235,14 @@ int main()
{
printf("NinjaDestroyRuns: err = %d\n", err);
}
-
+
+ if(multiStream != NULL)
+ {
+ if(fclose(multiStream) != 0)
+ {
+ printf("error closing log file\n");
+ }
+ }
+
return NINJA_SUCCESS;
}
diff --git a/autotest/api/test_capi_fetching.c b/autotest/api/test_capi_fetching.c
index 989a8a35c..68c37311f 100644
--- a/autotest/api/test_capi_fetching.c
+++ b/autotest/api/test_capi_fetching.c
@@ -53,9 +53,9 @@ int main()
/*
* Testing fetching from a DEM bounding box
*/
- const char * demFileBBox = "data/fetch/DEMBBox.tif"; // output file name
- char * fetch_type = "gmted"; // can be srtm, gmted, relief
- double resolution = 30; // 30 m resolution
+ const char * demFileBBox = "/home/atw09001/src/wind/windninja/autotest/api/data/fetch/DEMBBox.tif"; // output file name
+ char * fetch_type = "lcp"; // can be srtm, gmted, relief
+ double resolution = 30.0; // 30 m resolution
double boundsBox [] = {40.07, -104.0, 40.0, -104.07}; // Bounding box (north, east, south, west)
err = NinjaFetchDEMBBox(ninjaArmy, boundsBox, demFileBBox, resolution, fetch_type, papszOptions);
if (err != NINJA_SUCCESS){
@@ -112,8 +112,8 @@ int main()
int hour[2] = {2, 2};
int minute[2] = {2, 2};
int size = 2;
- const char* output_path = "data/fetch/";
- const char* elevation_file = "data/missoula_valley.tif";
+ const char* output_path = "/home/atw09001/src/wind/windninja/autotest/api/data/fetch/";
+ const char* elevation_file = "/home/atw09001/src/wind/windninja/autotest/api/data/missoula_valley.tif";
const char* osTimeZone = "UTC";
bool fetchLatestFlag = 1;
double buffer = 10;
@@ -129,11 +129,11 @@ int main()
/*
* Testing fetching from a DEM point
*/
- double adfPoint[] = {104.0, 40.07}; // Point coordinates (longitude, latitude)
- double adfBuff[] = {30, 30}; // Buffer to store the elevation value
+ double adfPoint[] = {-104.0, 40.07}; // Point coordinates (longitude, latitude)
+ double adfBuff[] = {1.5, 1.5}; // Buffer to store the elevation value
double dfCellSize = 30.0; // Cell size in meters
- char* pszDstFile = "data/fetch/DEMpoint.tif";
- char* fetchType = "gmted";
+ char* pszDstFile = "/home/atw09001/src/wind/windninja/autotest/api/data/fetch/DEMpoint.tif";
+ char* fetchType = "lcp";
err = NinjaFetchDEMPoint(ninjaArmy, adfPoint, adfBuff, units, dfCellSize, pszDstFile, fetchType, papszOptions);
if (err != NINJA_SUCCESS) {
printf("NinjaFetchDemPoint: err = %d\n", err);
diff --git a/cmake/Modules/GetDate.cmake b/cmake/Modules/GetDate.cmake
index 3808bd403..40f9d9362 100644
--- a/cmake/Modules/GetDate.cmake
+++ b/cmake/Modules/GetDate.cmake
@@ -1,4 +1,4 @@
-#cmake_minimum_required(VERSION 2.8)
+#cmake_minimum_required(VERSION 3.16)
macro(GET_DATE)
#
diff --git a/data/leaflet/L.Control.Layers.Tree.css b/data/leaflet/L.Control.Layers.Tree.css
new file mode 100644
index 000000000..aa0334d41
--- /dev/null
+++ b/data/leaflet/L.Control.Layers.Tree.css
@@ -0,0 +1,33 @@
+.leaflet-control-layers-toggle.leaflet-layerstree-named-toggle {
+ margin: 2px 5px;
+ width: auto;
+ height: auto;
+ background-image: none;
+}
+
+.leaflet-layerstree-header input {
+ margin-left: 0px;
+}
+
+.leaflet-layerstree-header label {
+ display: inline-block;
+ cursor: pointer;
+}
+
+.leaflet-layerstree-header-pointer,
+.leaflet-layerstree-expand-collapse {
+ cursor: pointer;
+}
+
+.leaflet-layerstree-children {
+ padding-left: 10px;
+}
+
+.leaflet-layerstree-children-nopad {
+ padding-left: 0px;
+}
+
+.leaflet-layerstree-hide,
+.leaflet-layerstree-nevershow {
+ display: none;
+}
diff --git a/data/leaflet/L.Control.Layers.Tree.js b/data/leaflet/L.Control.Layers.Tree.js
new file mode 100644
index 000000000..cfd08aa19
--- /dev/null
+++ b/data/leaflet/L.Control.Layers.Tree.js
@@ -0,0 +1,530 @@
+(function(global, factory) {
+ typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('leaflet')) :
+ typeof define === 'function' && define.amd ? define(['exports', 'leaflet'], factory) :
+ (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.LayersTree = {}, global.L));
+})(this, (function(_exports, L) { 'use strict';
+
+ /*
+ * Control like L.Control.Layers, but showing layers in a tree.
+ * Do not forget to include the css file.
+ */
+
+ if (typeof L === 'undefined') {
+ throw new Error('Leaflet must be included first');
+ }
+
+ /*
+ * L.Control.Layers.Tree extends L.Control.Layers because it reuses
+ * most of its functionality. Only the HTML creation is different.
+ */
+ L.Control.Layers.Tree = L.Control.Layers.extend({
+ options: {
+ closedSymbol: '+',
+ openedSymbol: '−',
+ spaceSymbol: ' ',
+ selectorBack: false,
+ namedToggle: false,
+ collapseAll: '',
+ expandAll: '',
+ labelIsSelector: 'both',
+ },
+
+ // Class names are error prone texts, so write them once here
+ _initClassesNames: function() {
+ this.cls = {
+ children: 'leaflet-layerstree-children',
+ childrenNopad: 'leaflet-layerstree-children-nopad',
+ hide: 'leaflet-layerstree-hide',
+ closed: 'leaflet-layerstree-closed',
+ opened: 'leaflet-layerstree-opened',
+ space: 'leaflet-layerstree-header-space',
+ pointer: 'leaflet-layerstree-header-pointer',
+ header: 'leaflet-layerstree-header',
+ neverShow: 'leaflet-layerstree-nevershow',
+ node: 'leaflet-layerstree-node',
+ name: 'leaflet-layerstree-header-name',
+ label: 'leaflet-layerstree-header-label',
+ selAllCheckbox: 'leaflet-layerstree-sel-all-checkbox',
+ };
+ },
+
+ initialize: function(baseTree, overlaysTree, options) {
+ this._scrollTop = 0;
+ this._initClassesNames();
+ this._baseTree = null;
+ this._overlaysTree = null;
+ L.Util.setOptions(this, options);
+ L.Control.Layers.prototype.initialize.call(this, null, null, options);
+ this._setTrees(baseTree, overlaysTree);
+ },
+
+ setBaseTree: function(tree) {
+ return this._setTrees(tree);
+ },
+
+ setOverlayTree: function(tree) {
+ return this._setTrees(undefined, tree);
+ },
+
+ addBaseLayer: function(_layer, _name) {
+ throw 'addBaseLayer is disabled';
+ },
+
+ addOverlay: function(_layer, _name) {
+ throw 'addOverlay is disabled';
+ },
+
+ removeLayer: function(_layer) {
+ throw 'removeLayer is disabled';
+ },
+
+ collapse: function() {
+ this._scrollTop = this._sect().scrollTop;
+ return L.Control.Layers.prototype.collapse.call(this);
+ },
+
+ expand: function() {
+ L.Control.Layers.prototype.expand.call(this);
+ this._sect().scrollTop = this._scrollTop;
+ },
+
+ onAdd: function(map) {
+ function changeName(layer) {
+ if (layer._layersTreeName) {
+ toggle.innerHTML = layer._layersTreeName;
+ }
+ }
+
+ var ret = L.Control.Layers.prototype.onAdd.call(this, map);
+ if (this.options.namedToggle) {
+ var toggle = this._container.getElementsByClassName('leaflet-control-layers-toggle')[0];
+ L.DomUtil.addClass(toggle, 'leaflet-layerstree-named-toggle');
+ // Start with this value...
+ map.eachLayer(function(layer) {changeName(layer);});
+ // ... and change it whenever the baselayer is changed.
+ map.on('baselayerchange', function(e) {changeName(e.layer);}, this);
+ }
+ return ret;
+ },
+
+ // Expands the whole tree (base other overlays)
+ expandTree: function(overlay) {
+ var container = overlay ? this._overlaysList : this._baseLayersList;
+ if (container) {
+ this._applyOnTree(container, false);
+ }
+ return this._localExpand();
+ },
+
+ // Collapses the whole tree (base other overlays)
+ collapseTree: function(overlay) {
+ var container = overlay ? this._overlaysList : this._baseLayersList;
+ if (container) {
+ this._applyOnTree(container, true);
+ }
+ return this._localExpand();
+ },
+
+ // Expands the tree, only to show the selected inputs
+ expandSelected: function(overlay) {
+ function iter(el) {
+ // Function to iterate the whole DOM upwards
+ var p = el.parentElement;
+ if (p) {
+ if (L.DomUtil.hasClass(p, that.cls.children) &&
+ !L.DomUtil.hasClass(el, that.cls.childrenNopad)) {
+ L.DomUtil.removeClass(p, hide);
+ }
+
+ if (L.DomUtil.hasClass(p, that.cls.node)) {
+ var h = p.getElementsByClassName(that.cls.header)[0];
+ that._applyOnTree(h, false);
+ }
+ iter(p);
+ }
+ }
+
+ var that = this;
+ var container = overlay ? this._overlaysList : this._baseLayersList;
+ if (!container) return this;
+ var hide = this.cls.hide;
+ var inputs = this._layerControlInputs || container.getElementsByTagName('input');
+ for (var i = 0; i < inputs.length; i++) {
+ // Loop over every (valid) input.
+ var input = inputs[i];
+ if (this._getLayer && !!this._getLayer(input.layerId).overlay != !!overlay) continue;
+ if (input.checked) {
+ // Get out of the header,
+ // to not open the possible (but rare) children
+ iter(input.parentElement.parentElement.parentElement.parentElement);
+ }
+ }
+ return this._localExpand();
+ },
+
+ // "private" methods, not exposed in the API
+ _sect: function() {
+ // to keep compatibility after 1.3 https://github.com/Leaflet/Leaflet/pull/6380
+ return this._section || this._form;
+ },
+
+ _setTrees: function(base, overlays) {
+ var id = 0; // to keep unique id
+ function iterate(tree, output, overlays) {
+ if (tree && tree.layer) {
+ if (!overlays) {
+ tree.layer._layersTreeName = tree.name || tree.label;
+ }
+ output[id++] = tree.layer;
+ }
+ if (tree && tree.children && tree.children.length) {
+ tree.children.forEach(function(child) {
+ iterate(child, output, overlays);
+ });
+ }
+ return output;
+ }
+
+ // We accept arrays, but convert into an object with children
+ function forArrays(input) {
+ if (Array.isArray(input)) {
+ return {noShow: true, children: input};
+ } else {
+ return input;
+ }
+ }
+
+ // Clean everything, and start again.
+ if (this._layerControlInputs) {
+ this._layerControlInputs = [];
+ }
+ for (var i = 0; i < this._layers.length; ++i) {
+ this._layers[i].layer.off('add remove', this._onLayerChange, this);
+ }
+ this._layers = [];
+
+ if (base !== undefined) this._baseTree = forArrays(base);
+ if (overlays !== undefined) this._overlaysTree = forArrays(overlays);
+
+ var bflat = iterate(this._baseTree, {});
+ for (var j in bflat) {
+ this._addLayer(bflat[j], j);
+ }
+
+ var oflat = iterate(this._overlaysTree, {}, true);
+ for (var k in oflat) {
+ this._addLayer(oflat[k], k, true);
+ }
+ return (this._map) ? this._update() : this;
+ },
+
+ // Used to update the vertical scrollbar
+ _localExpand: function() {
+ if (this._map && L.DomUtil.hasClass(this._container, 'leaflet-control-layers-expanded')) {
+ var top = this._sect().scrollTop;
+ this.expand();
+ this._sect().scrollTop = top; // to keep the scroll location
+ this._scrollTop = top;
+ }
+ return this;
+ },
+
+ // collapses or expands the tree in the container.
+ _applyOnTree: function(container, collapse) {
+ var iters = [
+ {cls: this.cls.children, hide: collapse},
+ {cls: this.cls.opened, hide: collapse},
+ {cls: this.cls.closed, hide: !collapse},
+ ];
+ iters.forEach(function(it) {
+ var els = container.getElementsByClassName(it.cls);
+ for (var i = 0; i < els.length; i++) {
+ var el = els[i];
+ if (L.DomUtil.hasClass(el, this.cls.childrenNopad)) {
+ // do nothing
+ } else if (it.hide) {
+ L.DomUtil.addClass(el, this.cls.hide);
+ } else {
+ L.DomUtil.removeClass(el, this.cls.hide);
+ }
+ }
+ }, this);
+ },
+
+ // it is called in the original _update, and shouldn't do anything.
+ _addItem: function(_obj) {
+ },
+
+ // overwrite _update function in Control.Layers
+ _update: function() {
+ if (!this._container) { return this; }
+ L.Control.Layers.prototype._update.call(this);
+ this._addTreeLayout(this._baseTree, false);
+ this._addTreeLayout(this._overlaysTree, true);
+ return this._localExpand();
+ },
+
+ // Create the DOM objects for the tree
+ _addTreeLayout: function(tree, overlay) {
+ if (!tree) return;
+ var container = overlay ? this._overlaysList : this._baseLayersList;
+ this._expandCollapseAll(overlay, this.options.collapseAll, this.collapseTree);
+ this._expandCollapseAll(overlay, this.options.expandAll, this.expandTree);
+ this._iterateTreeLayout(tree, container, overlay, [], tree.noShow);
+ if (this._checkDisabledLayers) {
+ // to keep compatibility
+ this._checkDisabledLayers();
+ }
+ },
+
+ // Create the "Collapse all" or expand, if needed.
+ _expandCollapseAll: function(overlay, text, fn, ctx) {
+ var container = overlay ? this._overlaysList : this._baseLayersList;
+ ctx = ctx ? ctx : this;
+ if (text) {
+ var o = document.createElement('div');
+ o.className = 'leaflet-layerstree-expand-collapse';
+ container.appendChild(o);
+ o.innerHTML = text;
+ o.tabIndex = 0;
+ L.DomEvent.on(o, 'click keydown', function(e) {
+ if (e.type !== 'keydown' || e.keyCode === 32) {
+ o.blur();
+ fn.call(ctx, overlay);
+ this._localExpand();
+ }
+ }, this);
+ }
+ },
+
+ // recursive function to create the DOM children
+ _iterateTreeLayout: function(tree, container, overlay, selAllNodes, noShow) {
+ if (!tree) return;
+ function creator(type, cls, append, innerHTML) {
+ var obj = L.DomUtil.create(type, cls, append);
+ if (innerHTML) obj.innerHTML = innerHTML;
+ return obj;
+ }
+
+ // create the header with it fields
+ var header = creator('div', this.cls.header, container);
+ var sel = creator('span');
+ var entry = creator('span');
+ var closed = creator('span', this.cls.closed, sel, this.options.closedSymbol);
+ var opened = creator('span', this.cls.opened, sel, this.options.openedSymbol);
+ var space = creator('span', this.cls.space, null, this.options.spaceSymbol);
+ if (this.options.selectorBack) {
+ sel.insertBefore(space, closed);
+ header.appendChild(entry);
+ header.appendChild(sel);
+ } else {
+ sel.appendChild(space);
+ header.appendChild(sel);
+ header.appendChild(entry);
+ }
+
+ function updateSelAllCheckbox(ancestor) {
+ var selector = ancestor.querySelector('input[type=checkbox]');
+ var selectedAll = true;
+ var selectedNone = true;
+ var inputs = ancestor.querySelectorAll('input[type=checkbox]');
+ [].forEach.call(inputs, function(inp) { // to work in node for tests
+ if (inp === selector) {
+ // ignore
+ } else if (inp.indeterminate) {
+ selectedAll = false;
+ selectedNone = false;
+ } else if (inp.checked) {
+ selectedNone = false;
+ } else if (!inp.checked) {
+ selectedAll = false;
+ }
+ });
+ if (selectedAll) {
+ selector.indeterminate = false;
+ selector.checked = true;
+ } else if (selectedNone) {
+ selector.indeterminate = false;
+ selector.checked = false;
+ } else {
+ selector.indeterminate = true;
+ selector.checked = false;
+ }
+ }
+
+ function manageSelectorsAll(input, ctx) {
+ selAllNodes.forEach(function(ancestor) {
+ L.DomEvent.on(input, 'click', function(_ev) {
+ updateSelAllCheckbox(ancestor);
+ }, ctx);
+ }, ctx);
+ }
+
+ var selAll;
+ if (tree.selectAllCheckbox) {
+ selAll = this._createCheckboxElement(false);
+ selAll.className += ' ' + this.cls.selAllCheckbox;
+ }
+
+ var hide = this.cls.hide; // To toggle state
+ // create the children group, with the header event click
+ if (tree.children) {
+ var children = creator('div', this.cls.children, container);
+ var sensible = tree.layer ? sel : header;
+ L.DomUtil.addClass(sensible, this.cls.pointer);
+ sensible.tabIndex = 0;
+ L.DomEvent.on(sensible, 'click keydown', function(e) {
+ // leaflet internal flag to prevent click propagation and collapsing tree on mobile browsers
+ if (this._preventClick) {
+ return;
+ }
+ if (e.type === 'keydown' && e.keyCode !== 32) {
+ return;
+ }
+ sensible.blur();
+
+ if (L.DomUtil.hasClass(opened, hide)) {
+ // it is not opened, so open it
+ L.DomUtil.addClass(closed, hide);
+ L.DomUtil.removeClass(opened, hide);
+ L.DomUtil.removeClass(children, hide);
+ } else {
+ // close it
+ L.DomUtil.removeClass(closed, hide);
+ L.DomUtil.addClass(opened, hide);
+ L.DomUtil.addClass(children, hide);
+ }
+ this._localExpand();
+ }, this);
+ if (selAll) {
+ selAllNodes.splice(0, 0, container);
+ }
+ tree.children.forEach(function(child) {
+ var node = creator('div', this.cls.node, children);
+ this._iterateTreeLayout(child, node, overlay, selAllNodes);
+ }, this);
+ if (selAll) {
+ selAllNodes.splice(0, 1);
+ }
+ } else {
+ // no children, so the selector makes no sense.
+ L.DomUtil.addClass(sel, this.cls.neverShow);
+ }
+
+ // make (or not) the label clickable to toggle the layer
+ var labelType;
+ if (tree.layer) {
+ if ((this.options.labelIsSelector === 'both') || // if option is set to both
+ (overlay && this.options.labelIsSelector === 'overlay') || // if an overlay layer and options is set to overlay
+ (!overlay && this.options.labelIsSelector === 'base')) { // if a base layer and option is set to base
+ labelType = 'label';
+ } else { // if option is set to something else
+ labelType = 'span';
+ }
+ } else {
+ labelType = 'span';
+ }
+ // create the input and label
+ var label = creator(labelType, this.cls.label, entry);
+ if (tree.layer) {
+ // now create the element like in _addItem
+ var checked = this._map.hasLayer(tree.layer);
+ var input;
+ var radioGroup = overlay ? tree.radioGroup : 'leaflet-base-layers_' + L.Util.stamp(this);
+ if (radioGroup) {
+ input = this._createRadioElement(radioGroup, checked);
+ } else {
+ input = this._createCheckboxElement(checked);
+ manageSelectorsAll(input, this);
+ }
+ if (this._layerControlInputs) {
+ // to keep compatibility with 1.0.3
+ this._layerControlInputs.push(input);
+ }
+ input.layerId = L.Util.stamp(tree.layer);
+ L.DomEvent.on(input, 'click', this._onInputClick, this);
+ label.appendChild(input);
+ }
+
+ function isText(variable) {
+ return (typeof variable === 'string' || variable instanceof String);
+ }
+
+ function isFunction(functionToCheck) {
+ return functionToCheck && {}.toString.call(functionToCheck) === '[object Function]';
+ }
+
+ function selectAllCheckboxes(select, ctx) {
+ var inputs = container.getElementsByTagName('input');
+ for (var i = 0; i < inputs.length; i++) {
+ var input = inputs[i];
+ if (input.type !== 'checkbox') continue;
+ input.checked = select;
+ input.indeterminate = false;
+ }
+ ctx._onInputClick();
+ }
+ if (tree.selectAllCheckbox) {
+ // selAll is already created
+ label.appendChild(selAll);
+ if (isText(tree.selectAllCheckbox)) {
+ selAll.title = tree.selectAllCheckbox;
+ }
+ L.DomEvent.on(selAll, 'click', function(ev) {
+ ev.stopPropagation();
+ selectAllCheckboxes(selAll.checked, this);
+ }, this);
+ updateSelAllCheckbox(container);
+ manageSelectorsAll(selAll, this);
+ }
+
+ creator('span', this.cls.name, label, tree.label);
+
+ // hide the button which doesn't fit the collapsed state, then hide children conditionally
+ L.DomUtil.addClass(tree.collapsed ? opened : closed, hide);
+ tree.collapsed && children && L.DomUtil.addClass(children, hide);
+
+ if (noShow) {
+ L.DomUtil.addClass(header, this.cls.neverShow);
+ L.DomUtil.addClass(children, this.cls.childrenNopad);
+ }
+
+ var eventeds = tree.eventedClasses;
+ if (!(eventeds instanceof Array)) {
+ eventeds = [eventeds];
+ }
+
+ for (var e = 0; e < eventeds.length; e++) {
+ var evented = eventeds[e];
+ if (evented && evented.className) {
+ var obj = container.querySelector('.' + evented.className);
+ if (obj) {
+ L.DomEvent.on(obj, evented.event || 'click', (function(selectAll) {
+ return function(ev) {
+ ev.stopPropagation();
+ var select = isFunction(selectAll) ? selectAll(ev, container, tree, this._map) : selectAll;
+ if (select !== undefined && select !== null) {
+ selectAllCheckboxes(select, this);
+ }
+ };
+ })(evented.selectAll), this);
+ }
+ }
+ }
+ },
+
+ _createCheckboxElement: function(checked) {
+ var input = document.createElement('input');
+ input.type = 'checkbox';
+ input.className = 'leaflet-control-layers-selector';
+ input.defaultChecked = checked;
+ return input;
+ },
+
+ });
+
+ L.control.layers.tree = function(base, overlays, options) {
+ return new L.Control.Layers.Tree(base, overlays, options);
+ };
+
+}));
diff --git a/data/leaflet/L.KML.js b/data/leaflet/L.KML.js
new file mode 100755
index 000000000..2f05068d9
--- /dev/null
+++ b/data/leaflet/L.KML.js
@@ -0,0 +1,482 @@
+/*!
+ Copyright (c) 2011-2015, Pavel Shramov, Bruno Bergot - MIT licence
+*/
+
+L.KML = L.FeatureGroup.extend({
+
+ initialize: function (kml, kmlOptions) {
+ this._kml = kml;
+ this._layers = {};
+ this._kmlOptions = kmlOptions;
+
+ if (kml) {
+ this.addKML(kml, kmlOptions);
+ }
+ },
+
+ addKML: function (xml, kmlOptions) {
+ var layers = L.KML.parseKML(xml, kmlOptions);
+ if (!layers || !layers.length) return;
+ for (var i = 0; i < layers.length; i++) {
+ this.fire('addlayer', {
+ layer: layers[i]
+ });
+ this.addLayer(layers[i]);
+ }
+ this.latLngs = L.KML.getLatLngs(xml);
+ this.fire('loaded');
+ },
+
+ latLngs: []
+});
+
+L.Util.extend(L.KML, {
+
+ parseKML: function (xml, kmlOptions) {
+ var style = this.parseStyles(xml, kmlOptions);
+ this.parseStyleMap(xml, style);
+ var el = xml.getElementsByTagName('Folder');
+ var layers = [], l;
+ for (var i = 0; i < el.length; i++) {
+ if (!this._check_folder(el[i])) { continue; }
+ l = this.parseFolder(el[i], style);
+ if (l) { layers.push(l); }
+ }
+ el = xml.getElementsByTagName('Placemark');
+ for (var j = 0; j < el.length; j++) {
+ if (!this._check_folder(el[j])) { continue; }
+ l = this.parsePlacemark(el[j], xml, style);
+ if (l) { layers.push(l); }
+ }
+ el = xml.getElementsByTagName('GroundOverlay');
+ for (var k = 0; k < el.length; k++) {
+ l = this.parseGroundOverlay(el[k]);
+ if (l) { layers.push(l); }
+ }
+ return layers;
+ },
+
+ // Return false if e's first parent Folder is not [folder]
+ // - returns true if no parent Folders
+ _check_folder: function (e, folder) {
+ e = e.parentNode;
+ while (e && e.tagName !== 'Folder')
+ {
+ e = e.parentNode;
+ }
+ return !e || e === folder;
+ },
+
+ parseStyles: function (xml, kmlOptions) {
+ var styles = {};
+ var sl = xml.getElementsByTagName('Style');
+ for (var i=0, len=sl.length; i 1) {
+ layer = new L.FeatureGroup(layers);
+ }
+
+ this.addPlacePopup(place, layer);
+ return layer;
+ },
+
+ addPlacePopup: function(place, layer) {
+ var el, i, j, name, descr = '';
+ el = place.getElementsByTagName('name');
+ if (el.length && el[0].childNodes.length) {
+ name = el[0].childNodes[0].nodeValue;
+ }
+ el = place.getElementsByTagName('description');
+ for (i = 0; i < el.length; i++) {
+ for (j = 0; j < el[i].childNodes.length; j++) {
+ descr = descr + el[i].childNodes[j].nodeValue;
+ }
+ }
+
+ if (name) {
+ layer.bindPopup('' + name + ' ' + descr, { className: 'kml-popup'});
+ }
+ },
+
+ parseCoords: function (xml) {
+ var el = xml.getElementsByTagName('coordinates');
+ return this._read_coords(el[0]);
+ },
+
+ parseLineString: function (line, xml, options) {
+ var coords = this.parseCoords(line);
+ if (!coords.length) { return; }
+ return new L.Polyline(coords, options);
+ },
+
+ parseTrack: function (line, xml, options) {
+ var el = xml.getElementsByTagName('gx:coord');
+ if (el.length === 0) { el = xml.getElementsByTagName('coord'); }
+ var coords = [];
+ for (var j = 0; j < el.length; j++) {
+ coords = coords.concat(this._read_gxcoords(el[j]));
+ }
+ if (!coords.length) { return; }
+ return new L.Polyline(coords, options);
+ },
+
+ parsePoint: function (line, xml, options) {
+ var el = line.getElementsByTagName('coordinates');
+ if (!el.length) {
+ return;
+ }
+ var ll = el[0].childNodes[0].nodeValue.split(',');
+ return new L.KMLMarker(new L.LatLng(ll[1], ll[0]), options);
+ },
+
+ parsePolygon: function (line, xml, options) {
+ var el, polys = [], inner = [], i, coords;
+ el = line.getElementsByTagName('outerBoundaryIs');
+ for (i = 0; i < el.length; i++) {
+ coords = this.parseCoords(el[i]);
+ if (coords) {
+ polys.push(coords);
+ }
+ }
+ el = line.getElementsByTagName('innerBoundaryIs');
+ for (i = 0; i < el.length; i++) {
+ coords = this.parseCoords(el[i]);
+ if (coords) {
+ inner.push(coords);
+ }
+ }
+ if (!polys.length) {
+ return;
+ }
+ if (options.fillColor) {
+ options.fill = true;
+ }
+ if (polys.length === 1) {
+ return new L.Polygon(polys.concat(inner), options);
+ }
+ return new L.MultiPolygon(polys, options);
+ },
+
+ getLatLngs: function (xml) {
+ var el = xml.getElementsByTagName('coordinates');
+ var coords = [];
+ for (var j = 0; j < el.length; j++) {
+ // text might span many childNodes
+ coords = coords.concat(this._read_coords(el[j]));
+ }
+ return coords;
+ },
+
+ _read_coords: function (el) {
+ var text = '', coords = [], i;
+ for (i = 0; i < el.childNodes.length; i++) {
+ text = text + el.childNodes[i].nodeValue;
+ }
+ text = text.split(/[\s\n]+/);
+ for (i = 0; i < text.length; i++) {
+ var ll = text[i].split(',');
+ if (ll.length < 2) {
+ continue;
+ }
+ coords.push(new L.LatLng(ll[1], ll[0]));
+ }
+ return coords;
+ },
+
+ _read_gxcoords: function (el) {
+ var text = '', coords = [];
+ text = el.firstChild.nodeValue.split(' ');
+ coords.push(new L.LatLng(text[1], text[0]));
+ return coords;
+ },
+
+ parseGroundOverlay: function (xml) {
+ var latlonbox = xml.getElementsByTagName('LatLonBox')[0];
+ var bounds = new L.LatLngBounds(
+ [
+ latlonbox.getElementsByTagName('south')[0].childNodes[0].nodeValue,
+ latlonbox.getElementsByTagName('west')[0].childNodes[0].nodeValue
+ ],
+ [
+ latlonbox.getElementsByTagName('north')[0].childNodes[0].nodeValue,
+ latlonbox.getElementsByTagName('east')[0].childNodes[0].nodeValue
+ ]
+ );
+ var attributes = {Icon: true, href: true, color: true};
+ function _parse (xml) {
+ var options = {}, ioptions = {};
+ for (var i = 0; i < xml.childNodes.length; i++) {
+ var e = xml.childNodes[i];
+ var key = e.tagName;
+ if (!attributes[key]) { continue; }
+ var value = e.childNodes[0].nodeValue;
+ if (key === 'Icon') {
+ ioptions = _parse(e);
+ if (ioptions.href) { options.href = ioptions.href; }
+ } else if (key === 'href') {
+ options.href = value;
+ } else if (key === 'color') {
+ options.opacity = parseInt(value.substring(0, 2), 16) / 255.0;
+ options.color = '#' + value.substring(6, 8) + value.substring(4, 6) + value.substring(2, 4);
+ }
+ }
+ return options;
+ }
+ var options = {};
+ options = _parse(xml);
+ if (latlonbox.getElementsByTagName('rotation')[0] !== undefined) {
+ var rotation = latlonbox.getElementsByTagName('rotation')[0].childNodes[0].nodeValue;
+ options.rotation = parseFloat(rotation);
+ }
+ return new L.RotatedImageOverlay(options.href, bounds, {opacity: options.opacity, angle: options.rotation});
+ }
+
+});
+
+L.KMLIcon = L.Icon.extend({
+ options: {
+ iconSize: [32, 32],
+ iconAnchor: [16, 16],
+ },
+ _setIconStyles: function (img, name) {
+ L.Icon.prototype._setIconStyles.apply(this, [img, name]);
+ },
+ _createImg: function (src, el) {
+ el = el || document.createElement('img');
+ el.onload = this.applyCustomStyles.bind(this,el)
+ el.src = src;
+ return el;
+ },
+ applyCustomStyles: function(img) {
+ var options = this.options;
+ var width = options.iconSize[0];
+ var height = options.iconSize[1];
+
+ this.options.popupAnchor = [0,(-0.83*height)];
+ if (options.anchorType.x === 'fraction')
+ img.style.marginLeft = (-options.anchorRef.x * width) + 'px';
+ if (options.anchorType.y === 'fraction')
+ img.style.marginTop = ((-(1 - options.anchorRef.y) * height) + 1) + 'px';
+ if (options.anchorType.x === 'pixels')
+ img.style.marginLeft = (-options.anchorRef.x) + 'px';
+ if (options.anchorType.y === 'pixels')
+ img.style.marginTop = (options.anchorRef.y - height + 1) + 'px';
+ }
+});
+
+
+L.KMLMarker = L.Marker.extend({
+ options: {
+ icon: new L.KMLIcon.Default()
+ }
+});
+
+// Inspired by https://github.com/bbecquet/Leaflet.PolylineDecorator/tree/master/src
+L.RotatedImageOverlay = L.ImageOverlay.extend({
+ options: {
+ angle: 0
+ },
+ _reset: function () {
+ L.ImageOverlay.prototype._reset.call(this);
+ this._rotate();
+ },
+ _animateZoom: function (e) {
+ L.ImageOverlay.prototype._animateZoom.call(this, e);
+ this._rotate();
+ },
+ _rotate: function () {
+ if (L.DomUtil.TRANSFORM) {
+ // use the CSS transform rule if available
+ this._image.style[L.DomUtil.TRANSFORM] += ' rotate(' + this.options.angle + 'deg)';
+ } else if (L.Browser.ie) {
+ // fallback for IE6, IE7, IE8
+ var rad = this.options.angle * (Math.PI / 180),
+ costheta = Math.cos(rad),
+ sintheta = Math.sin(rad);
+ this._image.style.filter += ' progid:DXImageTransform.Microsoft.Matrix(sizingMethod=\'auto expand\', M11=' +
+ costheta + ', M12=' + (-sintheta) + ', M21=' + sintheta + ', M22=' + costheta + ')';
+ }
+ },
+ getBounds: function () {
+ return this._bounds;
+ }
+});
diff --git a/data/leaflet/jszip.min.js b/data/leaflet/jszip.min.js
new file mode 100755
index 000000000..ff4cfd5e8
--- /dev/null
+++ b/data/leaflet/jszip.min.js
@@ -0,0 +1,13 @@
+/*!
+
+JSZip v3.10.1 - A JavaScript class for generating and reading zip files
+
+
+(c) 2009-2016 Stuart Knightley
+Dual licenced under the MIT license or GPLv3. See https://raw.github.com/Stuk/jszip/main/LICENSE.markdown.
+
+JSZip uses the library pako released under the MIT license :
+https://github.com/nodeca/pako/blob/main/LICENSE
+*/
+
+!function(e){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=e();else if("function"==typeof define&&define.amd)define([],e);else{("undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:this).JSZip=e()}}(function(){return function s(a,o,h){function u(r,e){if(!o[r]){if(!a[r]){var t="function"==typeof require&&require;if(!e&&t)return t(r,!0);if(l)return l(r,!0);var n=new Error("Cannot find module '"+r+"'");throw n.code="MODULE_NOT_FOUND",n}var i=o[r]={exports:{}};a[r][0].call(i.exports,function(e){var t=a[r][1][e];return u(t||e)},i,i.exports,s,a,o,h)}return o[r].exports}for(var l="function"==typeof require&&require,e=0;e>2,s=(3&t)<<4|r>>4,a=1>6:64,o=2>4,r=(15&i)<<4|(s=p.indexOf(e.charAt(o++)))>>2,n=(3&s)<<6|(a=p.indexOf(e.charAt(o++))),l[h++]=t,64!==s&&(l[h++]=r),64!==a&&(l[h++]=n);return l}},{"./support":30,"./utils":32}],2:[function(e,t,r){"use strict";var n=e("./external"),i=e("./stream/DataWorker"),s=e("./stream/Crc32Probe"),a=e("./stream/DataLengthProbe");function o(e,t,r,n,i){this.compressedSize=e,this.uncompressedSize=t,this.crc32=r,this.compression=n,this.compressedContent=i}o.prototype={getContentWorker:function(){var e=new i(n.Promise.resolve(this.compressedContent)).pipe(this.compression.uncompressWorker()).pipe(new a("data_length")),t=this;return e.on("end",function(){if(this.streamInfo.data_length!==t.uncompressedSize)throw new Error("Bug : uncompressed data size mismatch")}),e},getCompressedWorker:function(){return new i(n.Promise.resolve(this.compressedContent)).withStreamInfo("compressedSize",this.compressedSize).withStreamInfo("uncompressedSize",this.uncompressedSize).withStreamInfo("crc32",this.crc32).withStreamInfo("compression",this.compression)}},o.createWorkerFrom=function(e,t,r){return e.pipe(new s).pipe(new a("uncompressedSize")).pipe(t.compressWorker(r)).pipe(new a("compressedSize")).withStreamInfo("compression",t)},t.exports=o},{"./external":6,"./stream/Crc32Probe":25,"./stream/DataLengthProbe":26,"./stream/DataWorker":27}],3:[function(e,t,r){"use strict";var n=e("./stream/GenericWorker");r.STORE={magic:"\0\0",compressWorker:function(){return new n("STORE compression")},uncompressWorker:function(){return new n("STORE decompression")}},r.DEFLATE=e("./flate")},{"./flate":7,"./stream/GenericWorker":28}],4:[function(e,t,r){"use strict";var n=e("./utils");var o=function(){for(var e,t=[],r=0;r<256;r++){e=r;for(var n=0;n<8;n++)e=1&e?3988292384^e>>>1:e>>>1;t[r]=e}return t}();t.exports=function(e,t){return void 0!==e&&e.length?"string"!==n.getTypeOf(e)?function(e,t,r,n){var i=o,s=n+r;e^=-1;for(var a=n;a>>8^i[255&(e^t[a])];return-1^e}(0|t,e,e.length,0):function(e,t,r,n){var i=o,s=n+r;e^=-1;for(var a=n;a>>8^i[255&(e^t.charCodeAt(a))];return-1^e}(0|t,e,e.length,0):0}},{"./utils":32}],5:[function(e,t,r){"use strict";r.base64=!1,r.binary=!1,r.dir=!1,r.createFolders=!0,r.date=null,r.compression=null,r.compressionOptions=null,r.comment=null,r.unixPermissions=null,r.dosPermissions=null},{}],6:[function(e,t,r){"use strict";var n=null;n="undefined"!=typeof Promise?Promise:e("lie"),t.exports={Promise:n}},{lie:37}],7:[function(e,t,r){"use strict";var n="undefined"!=typeof Uint8Array&&"undefined"!=typeof Uint16Array&&"undefined"!=typeof Uint32Array,i=e("pako"),s=e("./utils"),a=e("./stream/GenericWorker"),o=n?"uint8array":"array";function h(e,t){a.call(this,"FlateWorker/"+e),this._pako=null,this._pakoAction=e,this._pakoOptions=t,this.meta={}}r.magic="\b\0",s.inherits(h,a),h.prototype.processChunk=function(e){this.meta=e.meta,null===this._pako&&this._createPako(),this._pako.push(s.transformTo(o,e.data),!1)},h.prototype.flush=function(){a.prototype.flush.call(this),null===this._pako&&this._createPako(),this._pako.push([],!0)},h.prototype.cleanUp=function(){a.prototype.cleanUp.call(this),this._pako=null},h.prototype._createPako=function(){this._pako=new i[this._pakoAction]({raw:!0,level:this._pakoOptions.level||-1});var t=this;this._pako.onData=function(e){t.push({data:e,meta:t.meta})}},r.compressWorker=function(e){return new h("Deflate",e)},r.uncompressWorker=function(){return new h("Inflate",{})}},{"./stream/GenericWorker":28,"./utils":32,pako:38}],8:[function(e,t,r){"use strict";function A(e,t){var r,n="";for(r=0;r>>=8;return n}function n(e,t,r,n,i,s){var a,o,h=e.file,u=e.compression,l=s!==O.utf8encode,f=I.transformTo("string",s(h.name)),c=I.transformTo("string",O.utf8encode(h.name)),d=h.comment,p=I.transformTo("string",s(d)),m=I.transformTo("string",O.utf8encode(d)),_=c.length!==h.name.length,g=m.length!==d.length,b="",v="",y="",w=h.dir,k=h.date,x={crc32:0,compressedSize:0,uncompressedSize:0};t&&!r||(x.crc32=e.crc32,x.compressedSize=e.compressedSize,x.uncompressedSize=e.uncompressedSize);var S=0;t&&(S|=8),l||!_&&!g||(S|=2048);var z=0,C=0;w&&(z|=16),"UNIX"===i?(C=798,z|=function(e,t){var r=e;return e||(r=t?16893:33204),(65535&r)<<16}(h.unixPermissions,w)):(C=20,z|=function(e){return 63&(e||0)}(h.dosPermissions)),a=k.getUTCHours(),a<<=6,a|=k.getUTCMinutes(),a<<=5,a|=k.getUTCSeconds()/2,o=k.getUTCFullYear()-1980,o<<=4,o|=k.getUTCMonth()+1,o<<=5,o|=k.getUTCDate(),_&&(v=A(1,1)+A(B(f),4)+c,b+="up"+A(v.length,2)+v),g&&(y=A(1,1)+A(B(p),4)+m,b+="uc"+A(y.length,2)+y);var E="";return E+="\n\0",E+=A(S,2),E+=u.magic,E+=A(a,2),E+=A(o,2),E+=A(x.crc32,4),E+=A(x.compressedSize,4),E+=A(x.uncompressedSize,4),E+=A(f.length,2),E+=A(b.length,2),{fileRecord:R.LOCAL_FILE_HEADER+E+f+b,dirRecord:R.CENTRAL_FILE_HEADER+A(C,2)+E+A(p.length,2)+"\0\0\0\0"+A(z,4)+A(n,4)+f+b+p}}var I=e("../utils"),i=e("../stream/GenericWorker"),O=e("../utf8"),B=e("../crc32"),R=e("../signature");function s(e,t,r,n){i.call(this,"ZipFileWorker"),this.bytesWritten=0,this.zipComment=t,this.zipPlatform=r,this.encodeFileName=n,this.streamFiles=e,this.accumulate=!1,this.contentBuffer=[],this.dirRecords=[],this.currentSourceOffset=0,this.entriesCount=0,this.currentFile=null,this._sources=[]}I.inherits(s,i),s.prototype.push=function(e){var t=e.meta.percent||0,r=this.entriesCount,n=this._sources.length;this.accumulate?this.contentBuffer.push(e):(this.bytesWritten+=e.data.length,i.prototype.push.call(this,{data:e.data,meta:{currentFile:this.currentFile,percent:r?(t+100*(r-n-1))/r:100}}))},s.prototype.openedSource=function(e){this.currentSourceOffset=this.bytesWritten,this.currentFile=e.file.name;var t=this.streamFiles&&!e.file.dir;if(t){var r=n(e,t,!1,this.currentSourceOffset,this.zipPlatform,this.encodeFileName);this.push({data:r.fileRecord,meta:{percent:0}})}else this.accumulate=!0},s.prototype.closedSource=function(e){this.accumulate=!1;var t=this.streamFiles&&!e.file.dir,r=n(e,t,!0,this.currentSourceOffset,this.zipPlatform,this.encodeFileName);if(this.dirRecords.push(r.dirRecord),t)this.push({data:function(e){return R.DATA_DESCRIPTOR+A(e.crc32,4)+A(e.compressedSize,4)+A(e.uncompressedSize,4)}(e),meta:{percent:100}});else for(this.push({data:r.fileRecord,meta:{percent:0}});this.contentBuffer.length;)this.push(this.contentBuffer.shift());this.currentFile=null},s.prototype.flush=function(){for(var e=this.bytesWritten,t=0;t=this.index;t--)r=(r<<8)+this.byteAt(t);return this.index+=e,r},readString:function(e){return n.transformTo("string",this.readData(e))},readData:function(){},lastIndexOfSignature:function(){},readAndCheckSignature:function(){},readDate:function(){var e=this.readInt(4);return new Date(Date.UTC(1980+(e>>25&127),(e>>21&15)-1,e>>16&31,e>>11&31,e>>5&63,(31&e)<<1))}},t.exports=i},{"../utils":32}],19:[function(e,t,r){"use strict";var n=e("./Uint8ArrayReader");function i(e){n.call(this,e)}e("../utils").inherits(i,n),i.prototype.readData=function(e){this.checkOffset(e);var t=this.data.slice(this.zero+this.index,this.zero+this.index+e);return this.index+=e,t},t.exports=i},{"../utils":32,"./Uint8ArrayReader":21}],20:[function(e,t,r){"use strict";var n=e("./DataReader");function i(e){n.call(this,e)}e("../utils").inherits(i,n),i.prototype.byteAt=function(e){return this.data.charCodeAt(this.zero+e)},i.prototype.lastIndexOfSignature=function(e){return this.data.lastIndexOf(e)-this.zero},i.prototype.readAndCheckSignature=function(e){return e===this.readData(4)},i.prototype.readData=function(e){this.checkOffset(e);var t=this.data.slice(this.zero+this.index,this.zero+this.index+e);return this.index+=e,t},t.exports=i},{"../utils":32,"./DataReader":18}],21:[function(e,t,r){"use strict";var n=e("./ArrayReader");function i(e){n.call(this,e)}e("../utils").inherits(i,n),i.prototype.readData=function(e){if(this.checkOffset(e),0===e)return new Uint8Array(0);var t=this.data.subarray(this.zero+this.index,this.zero+this.index+e);return this.index+=e,t},t.exports=i},{"../utils":32,"./ArrayReader":17}],22:[function(e,t,r){"use strict";var n=e("../utils"),i=e("../support"),s=e("./ArrayReader"),a=e("./StringReader"),o=e("./NodeBufferReader"),h=e("./Uint8ArrayReader");t.exports=function(e){var t=n.getTypeOf(e);return n.checkSupport(t),"string"!==t||i.uint8array?"nodebuffer"===t?new o(e):i.uint8array?new h(n.transformTo("uint8array",e)):new s(n.transformTo("array",e)):new a(e)}},{"../support":30,"../utils":32,"./ArrayReader":17,"./NodeBufferReader":19,"./StringReader":20,"./Uint8ArrayReader":21}],23:[function(e,t,r){"use strict";r.LOCAL_FILE_HEADER="PK",r.CENTRAL_FILE_HEADER="PK",r.CENTRAL_DIRECTORY_END="PK",r.ZIP64_CENTRAL_DIRECTORY_LOCATOR="PK",r.ZIP64_CENTRAL_DIRECTORY_END="PK",r.DATA_DESCRIPTOR="PK\b"},{}],24:[function(e,t,r){"use strict";var n=e("./GenericWorker"),i=e("../utils");function s(e){n.call(this,"ConvertWorker to "+e),this.destType=e}i.inherits(s,n),s.prototype.processChunk=function(e){this.push({data:i.transformTo(this.destType,e.data),meta:e.meta})},t.exports=s},{"../utils":32,"./GenericWorker":28}],25:[function(e,t,r){"use strict";var n=e("./GenericWorker"),i=e("../crc32");function s(){n.call(this,"Crc32Probe"),this.withStreamInfo("crc32",0)}e("../utils").inherits(s,n),s.prototype.processChunk=function(e){this.streamInfo.crc32=i(e.data,this.streamInfo.crc32||0),this.push(e)},t.exports=s},{"../crc32":4,"../utils":32,"./GenericWorker":28}],26:[function(e,t,r){"use strict";var n=e("../utils"),i=e("./GenericWorker");function s(e){i.call(this,"DataLengthProbe for "+e),this.propName=e,this.withStreamInfo(e,0)}n.inherits(s,i),s.prototype.processChunk=function(e){if(e){var t=this.streamInfo[this.propName]||0;this.streamInfo[this.propName]=t+e.data.length}i.prototype.processChunk.call(this,e)},t.exports=s},{"../utils":32,"./GenericWorker":28}],27:[function(e,t,r){"use strict";var n=e("../utils"),i=e("./GenericWorker");function s(e){i.call(this,"DataWorker");var t=this;this.dataIsReady=!1,this.index=0,this.max=0,this.data=null,this.type="",this._tickScheduled=!1,e.then(function(e){t.dataIsReady=!0,t.data=e,t.max=e&&e.length||0,t.type=n.getTypeOf(e),t.isPaused||t._tickAndRepeat()},function(e){t.error(e)})}n.inherits(s,i),s.prototype.cleanUp=function(){i.prototype.cleanUp.call(this),this.data=null},s.prototype.resume=function(){return!!i.prototype.resume.call(this)&&(!this._tickScheduled&&this.dataIsReady&&(this._tickScheduled=!0,n.delay(this._tickAndRepeat,[],this)),!0)},s.prototype._tickAndRepeat=function(){this._tickScheduled=!1,this.isPaused||this.isFinished||(this._tick(),this.isFinished||(n.delay(this._tickAndRepeat,[],this),this._tickScheduled=!0))},s.prototype._tick=function(){if(this.isPaused||this.isFinished)return!1;var e=null,t=Math.min(this.max,this.index+16384);if(this.index>=this.max)return this.end();switch(this.type){case"string":e=this.data.substring(this.index,t);break;case"uint8array":e=this.data.subarray(this.index,t);break;case"array":case"nodebuffer":e=this.data.slice(this.index,t)}return this.index=t,this.push({data:e,meta:{percent:this.max?this.index/this.max*100:0}})},t.exports=s},{"../utils":32,"./GenericWorker":28}],28:[function(e,t,r){"use strict";function n(e){this.name=e||"default",this.streamInfo={},this.generatedError=null,this.extraStreamInfo={},this.isPaused=!0,this.isFinished=!1,this.isLocked=!1,this._listeners={data:[],end:[],error:[]},this.previous=null}n.prototype={push:function(e){this.emit("data",e)},end:function(){if(this.isFinished)return!1;this.flush();try{this.emit("end"),this.cleanUp(),this.isFinished=!0}catch(e){this.emit("error",e)}return!0},error:function(e){return!this.isFinished&&(this.isPaused?this.generatedError=e:(this.isFinished=!0,this.emit("error",e),this.previous&&this.previous.error(e),this.cleanUp()),!0)},on:function(e,t){return this._listeners[e].push(t),this},cleanUp:function(){this.streamInfo=this.generatedError=this.extraStreamInfo=null,this._listeners=[]},emit:function(e,t){if(this._listeners[e])for(var r=0;r "+e:e}},t.exports=n},{}],29:[function(e,t,r){"use strict";var h=e("../utils"),i=e("./ConvertWorker"),s=e("./GenericWorker"),u=e("../base64"),n=e("../support"),a=e("../external"),o=null;if(n.nodestream)try{o=e("../nodejs/NodejsStreamOutputAdapter")}catch(e){}function l(e,o){return new a.Promise(function(t,r){var n=[],i=e._internalType,s=e._outputType,a=e._mimeType;e.on("data",function(e,t){n.push(e),o&&o(t)}).on("error",function(e){n=[],r(e)}).on("end",function(){try{var e=function(e,t,r){switch(e){case"blob":return h.newBlob(h.transformTo("arraybuffer",t),r);case"base64":return u.encode(t);default:return h.transformTo(e,t)}}(s,function(e,t){var r,n=0,i=null,s=0;for(r=0;r>>6:(r<65536?t[s++]=224|r>>>12:(t[s++]=240|r>>>18,t[s++]=128|r>>>12&63),t[s++]=128|r>>>6&63),t[s++]=128|63&r);return t}(e)},s.utf8decode=function(e){return h.nodebuffer?o.transformTo("nodebuffer",e).toString("utf-8"):function(e){var t,r,n,i,s=e.length,a=new Array(2*s);for(t=r=0;t>10&1023,a[r++]=56320|1023&n)}return a.length!==r&&(a.subarray?a=a.subarray(0,r):a.length=r),o.applyFromCharCode(a)}(e=o.transformTo(h.uint8array?"uint8array":"array",e))},o.inherits(a,n),a.prototype.processChunk=function(e){var t=o.transformTo(h.uint8array?"uint8array":"array",e.data);if(this.leftOver&&this.leftOver.length){if(h.uint8array){var r=t;(t=new Uint8Array(r.length+this.leftOver.length)).set(this.leftOver,0),t.set(r,this.leftOver.length)}else t=this.leftOver.concat(t);this.leftOver=null}var n=function(e,t){var r;for((t=t||e.length)>e.length&&(t=e.length),r=t-1;0<=r&&128==(192&e[r]);)r--;return r<0?t:0===r?t:r+u[e[r]]>t?r:t}(t),i=t;n!==t.length&&(h.uint8array?(i=t.subarray(0,n),this.leftOver=t.subarray(n,t.length)):(i=t.slice(0,n),this.leftOver=t.slice(n,t.length))),this.push({data:s.utf8decode(i),meta:e.meta})},a.prototype.flush=function(){this.leftOver&&this.leftOver.length&&(this.push({data:s.utf8decode(this.leftOver),meta:{}}),this.leftOver=null)},s.Utf8DecodeWorker=a,o.inherits(l,n),l.prototype.processChunk=function(e){this.push({data:s.utf8encode(e.data),meta:e.meta})},s.Utf8EncodeWorker=l},{"./nodejsUtils":14,"./stream/GenericWorker":28,"./support":30,"./utils":32}],32:[function(e,t,a){"use strict";var o=e("./support"),h=e("./base64"),r=e("./nodejsUtils"),u=e("./external");function n(e){return e}function l(e,t){for(var r=0;r>8;this.dir=!!(16&this.externalFileAttributes),0==e&&(this.dosPermissions=63&this.externalFileAttributes),3==e&&(this.unixPermissions=this.externalFileAttributes>>16&65535),this.dir||"/"!==this.fileNameStr.slice(-1)||(this.dir=!0)},parseZIP64ExtraField:function(){if(this.extraFields[1]){var e=n(this.extraFields[1].value);this.uncompressedSize===s.MAX_VALUE_32BITS&&(this.uncompressedSize=e.readInt(8)),this.compressedSize===s.MAX_VALUE_32BITS&&(this.compressedSize=e.readInt(8)),this.localHeaderOffset===s.MAX_VALUE_32BITS&&(this.localHeaderOffset=e.readInt(8)),this.diskNumberStart===s.MAX_VALUE_32BITS&&(this.diskNumberStart=e.readInt(4))}},readExtraFields:function(e){var t,r,n,i=e.index+this.extraFieldsLength;for(this.extraFields||(this.extraFields={});e.index+4>>6:(r<65536?t[s++]=224|r>>>12:(t[s++]=240|r>>>18,t[s++]=128|r>>>12&63),t[s++]=128|r>>>6&63),t[s++]=128|63&r);return t},r.buf2binstring=function(e){return l(e,e.length)},r.binstring2buf=function(e){for(var t=new h.Buf8(e.length),r=0,n=t.length;r>10&1023,o[n++]=56320|1023&i)}return l(o,n)},r.utf8border=function(e,t){var r;for((t=t||e.length)>e.length&&(t=e.length),r=t-1;0<=r&&128==(192&e[r]);)r--;return r<0?t:0===r?t:r+u[e[r]]>t?r:t}},{"./common":41}],43:[function(e,t,r){"use strict";t.exports=function(e,t,r,n){for(var i=65535&e|0,s=e>>>16&65535|0,a=0;0!==r;){for(r-=a=2e3>>1:e>>>1;t[r]=e}return t}();t.exports=function(e,t,r,n){var i=o,s=n+r;e^=-1;for(var a=n;a>>8^i[255&(e^t[a])];return-1^e}},{}],46:[function(e,t,r){"use strict";var h,c=e("../utils/common"),u=e("./trees"),d=e("./adler32"),p=e("./crc32"),n=e("./messages"),l=0,f=4,m=0,_=-2,g=-1,b=4,i=2,v=8,y=9,s=286,a=30,o=19,w=2*s+1,k=15,x=3,S=258,z=S+x+1,C=42,E=113,A=1,I=2,O=3,B=4;function R(e,t){return e.msg=n[t],t}function T(e){return(e<<1)-(4e.avail_out&&(r=e.avail_out),0!==r&&(c.arraySet(e.output,t.pending_buf,t.pending_out,r,e.next_out),e.next_out+=r,t.pending_out+=r,e.total_out+=r,e.avail_out-=r,t.pending-=r,0===t.pending&&(t.pending_out=0))}function N(e,t){u._tr_flush_block(e,0<=e.block_start?e.block_start:-1,e.strstart-e.block_start,t),e.block_start=e.strstart,F(e.strm)}function U(e,t){e.pending_buf[e.pending++]=t}function P(e,t){e.pending_buf[e.pending++]=t>>>8&255,e.pending_buf[e.pending++]=255&t}function L(e,t){var r,n,i=e.max_chain_length,s=e.strstart,a=e.prev_length,o=e.nice_match,h=e.strstart>e.w_size-z?e.strstart-(e.w_size-z):0,u=e.window,l=e.w_mask,f=e.prev,c=e.strstart+S,d=u[s+a-1],p=u[s+a];e.prev_length>=e.good_match&&(i>>=2),o>e.lookahead&&(o=e.lookahead);do{if(u[(r=t)+a]===p&&u[r+a-1]===d&&u[r]===u[s]&&u[++r]===u[s+1]){s+=2,r++;do{}while(u[++s]===u[++r]&&u[++s]===u[++r]&&u[++s]===u[++r]&&u[++s]===u[++r]&&u[++s]===u[++r]&&u[++s]===u[++r]&&u[++s]===u[++r]&&u[++s]===u[++r]&&sh&&0!=--i);return a<=e.lookahead?a:e.lookahead}function j(e){var t,r,n,i,s,a,o,h,u,l,f=e.w_size;do{if(i=e.window_size-e.lookahead-e.strstart,e.strstart>=f+(f-z)){for(c.arraySet(e.window,e.window,f,f,0),e.match_start-=f,e.strstart-=f,e.block_start-=f,t=r=e.hash_size;n=e.head[--t],e.head[t]=f<=n?n-f:0,--r;);for(t=r=f;n=e.prev[--t],e.prev[t]=f<=n?n-f:0,--r;);i+=f}if(0===e.strm.avail_in)break;if(a=e.strm,o=e.window,h=e.strstart+e.lookahead,u=i,l=void 0,l=a.avail_in,u=x)for(s=e.strstart-e.insert,e.ins_h=e.window[s],e.ins_h=(e.ins_h<=x&&(e.ins_h=(e.ins_h<=x)if(n=u._tr_tally(e,e.strstart-e.match_start,e.match_length-x),e.lookahead-=e.match_length,e.match_length<=e.max_lazy_match&&e.lookahead>=x){for(e.match_length--;e.strstart++,e.ins_h=(e.ins_h<=x&&(e.ins_h=(e.ins_h<=x&&e.match_length<=e.prev_length){for(i=e.strstart+e.lookahead-x,n=u._tr_tally(e,e.strstart-1-e.prev_match,e.prev_length-x),e.lookahead-=e.prev_length-1,e.prev_length-=2;++e.strstart<=i&&(e.ins_h=(e.ins_h<e.pending_buf_size-5&&(r=e.pending_buf_size-5);;){if(e.lookahead<=1){if(j(e),0===e.lookahead&&t===l)return A;if(0===e.lookahead)break}e.strstart+=e.lookahead,e.lookahead=0;var n=e.block_start+r;if((0===e.strstart||e.strstart>=n)&&(e.lookahead=e.strstart-n,e.strstart=n,N(e,!1),0===e.strm.avail_out))return A;if(e.strstart-e.block_start>=e.w_size-z&&(N(e,!1),0===e.strm.avail_out))return A}return e.insert=0,t===f?(N(e,!0),0===e.strm.avail_out?O:B):(e.strstart>e.block_start&&(N(e,!1),e.strm.avail_out),A)}),new M(4,4,8,4,Z),new M(4,5,16,8,Z),new M(4,6,32,32,Z),new M(4,4,16,16,W),new M(8,16,32,32,W),new M(8,16,128,128,W),new M(8,32,128,256,W),new M(32,128,258,1024,W),new M(32,258,258,4096,W)],r.deflateInit=function(e,t){return Y(e,t,v,15,8,0)},r.deflateInit2=Y,r.deflateReset=K,r.deflateResetKeep=G,r.deflateSetHeader=function(e,t){return e&&e.state?2!==e.state.wrap?_:(e.state.gzhead=t,m):_},r.deflate=function(e,t){var r,n,i,s;if(!e||!e.state||5>8&255),U(n,n.gzhead.time>>16&255),U(n,n.gzhead.time>>24&255),U(n,9===n.level?2:2<=n.strategy||n.level<2?4:0),U(n,255&n.gzhead.os),n.gzhead.extra&&n.gzhead.extra.length&&(U(n,255&n.gzhead.extra.length),U(n,n.gzhead.extra.length>>8&255)),n.gzhead.hcrc&&(e.adler=p(e.adler,n.pending_buf,n.pending,0)),n.gzindex=0,n.status=69):(U(n,0),U(n,0),U(n,0),U(n,0),U(n,0),U(n,9===n.level?2:2<=n.strategy||n.level<2?4:0),U(n,3),n.status=E);else{var a=v+(n.w_bits-8<<4)<<8;a|=(2<=n.strategy||n.level<2?0:n.level<6?1:6===n.level?2:3)<<6,0!==n.strstart&&(a|=32),a+=31-a%31,n.status=E,P(n,a),0!==n.strstart&&(P(n,e.adler>>>16),P(n,65535&e.adler)),e.adler=1}if(69===n.status)if(n.gzhead.extra){for(i=n.pending;n.gzindex<(65535&n.gzhead.extra.length)&&(n.pending!==n.pending_buf_size||(n.gzhead.hcrc&&n.pending>i&&(e.adler=p(e.adler,n.pending_buf,n.pending-i,i)),F(e),i=n.pending,n.pending!==n.pending_buf_size));)U(n,255&n.gzhead.extra[n.gzindex]),n.gzindex++;n.gzhead.hcrc&&n.pending>i&&(e.adler=p(e.adler,n.pending_buf,n.pending-i,i)),n.gzindex===n.gzhead.extra.length&&(n.gzindex=0,n.status=73)}else n.status=73;if(73===n.status)if(n.gzhead.name){i=n.pending;do{if(n.pending===n.pending_buf_size&&(n.gzhead.hcrc&&n.pending>i&&(e.adler=p(e.adler,n.pending_buf,n.pending-i,i)),F(e),i=n.pending,n.pending===n.pending_buf_size)){s=1;break}s=n.gzindexi&&(e.adler=p(e.adler,n.pending_buf,n.pending-i,i)),0===s&&(n.gzindex=0,n.status=91)}else n.status=91;if(91===n.status)if(n.gzhead.comment){i=n.pending;do{if(n.pending===n.pending_buf_size&&(n.gzhead.hcrc&&n.pending>i&&(e.adler=p(e.adler,n.pending_buf,n.pending-i,i)),F(e),i=n.pending,n.pending===n.pending_buf_size)){s=1;break}s=n.gzindexi&&(e.adler=p(e.adler,n.pending_buf,n.pending-i,i)),0===s&&(n.status=103)}else n.status=103;if(103===n.status&&(n.gzhead.hcrc?(n.pending+2>n.pending_buf_size&&F(e),n.pending+2<=n.pending_buf_size&&(U(n,255&e.adler),U(n,e.adler>>8&255),e.adler=0,n.status=E)):n.status=E),0!==n.pending){if(F(e),0===e.avail_out)return n.last_flush=-1,m}else if(0===e.avail_in&&T(t)<=T(r)&&t!==f)return R(e,-5);if(666===n.status&&0!==e.avail_in)return R(e,-5);if(0!==e.avail_in||0!==n.lookahead||t!==l&&666!==n.status){var o=2===n.strategy?function(e,t){for(var r;;){if(0===e.lookahead&&(j(e),0===e.lookahead)){if(t===l)return A;break}if(e.match_length=0,r=u._tr_tally(e,0,e.window[e.strstart]),e.lookahead--,e.strstart++,r&&(N(e,!1),0===e.strm.avail_out))return A}return e.insert=0,t===f?(N(e,!0),0===e.strm.avail_out?O:B):e.last_lit&&(N(e,!1),0===e.strm.avail_out)?A:I}(n,t):3===n.strategy?function(e,t){for(var r,n,i,s,a=e.window;;){if(e.lookahead<=S){if(j(e),e.lookahead<=S&&t===l)return A;if(0===e.lookahead)break}if(e.match_length=0,e.lookahead>=x&&0e.lookahead&&(e.match_length=e.lookahead)}if(e.match_length>=x?(r=u._tr_tally(e,1,e.match_length-x),e.lookahead-=e.match_length,e.strstart+=e.match_length,e.match_length=0):(r=u._tr_tally(e,0,e.window[e.strstart]),e.lookahead--,e.strstart++),r&&(N(e,!1),0===e.strm.avail_out))return A}return e.insert=0,t===f?(N(e,!0),0===e.strm.avail_out?O:B):e.last_lit&&(N(e,!1),0===e.strm.avail_out)?A:I}(n,t):h[n.level].func(n,t);if(o!==O&&o!==B||(n.status=666),o===A||o===O)return 0===e.avail_out&&(n.last_flush=-1),m;if(o===I&&(1===t?u._tr_align(n):5!==t&&(u._tr_stored_block(n,0,0,!1),3===t&&(D(n.head),0===n.lookahead&&(n.strstart=0,n.block_start=0,n.insert=0))),F(e),0===e.avail_out))return n.last_flush=-1,m}return t!==f?m:n.wrap<=0?1:(2===n.wrap?(U(n,255&e.adler),U(n,e.adler>>8&255),U(n,e.adler>>16&255),U(n,e.adler>>24&255),U(n,255&e.total_in),U(n,e.total_in>>8&255),U(n,e.total_in>>16&255),U(n,e.total_in>>24&255)):(P(n,e.adler>>>16),P(n,65535&e.adler)),F(e),0=r.w_size&&(0===s&&(D(r.head),r.strstart=0,r.block_start=0,r.insert=0),u=new c.Buf8(r.w_size),c.arraySet(u,t,l-r.w_size,r.w_size,0),t=u,l=r.w_size),a=e.avail_in,o=e.next_in,h=e.input,e.avail_in=l,e.next_in=0,e.input=t,j(r);r.lookahead>=x;){for(n=r.strstart,i=r.lookahead-(x-1);r.ins_h=(r.ins_h<>>=y=v>>>24,p-=y,0===(y=v>>>16&255))C[s++]=65535&v;else{if(!(16&y)){if(0==(64&y)){v=m[(65535&v)+(d&(1<>>=y,p-=y),p<15&&(d+=z[n++]<>>=y=v>>>24,p-=y,!(16&(y=v>>>16&255))){if(0==(64&y)){v=_[(65535&v)+(d&(1<>>=y,p-=y,(y=s-a)>3,d&=(1<<(p-=w<<3))-1,e.next_in=n,e.next_out=s,e.avail_in=n>>24&255)+(e>>>8&65280)+((65280&e)<<8)+((255&e)<<24)}function s(){this.mode=0,this.last=!1,this.wrap=0,this.havedict=!1,this.flags=0,this.dmax=0,this.check=0,this.total=0,this.head=null,this.wbits=0,this.wsize=0,this.whave=0,this.wnext=0,this.window=null,this.hold=0,this.bits=0,this.length=0,this.offset=0,this.extra=0,this.lencode=null,this.distcode=null,this.lenbits=0,this.distbits=0,this.ncode=0,this.nlen=0,this.ndist=0,this.have=0,this.next=null,this.lens=new I.Buf16(320),this.work=new I.Buf16(288),this.lendyn=null,this.distdyn=null,this.sane=0,this.back=0,this.was=0}function a(e){var t;return e&&e.state?(t=e.state,e.total_in=e.total_out=t.total=0,e.msg="",t.wrap&&(e.adler=1&t.wrap),t.mode=P,t.last=0,t.havedict=0,t.dmax=32768,t.head=null,t.hold=0,t.bits=0,t.lencode=t.lendyn=new I.Buf32(n),t.distcode=t.distdyn=new I.Buf32(i),t.sane=1,t.back=-1,N):U}function o(e){var t;return e&&e.state?((t=e.state).wsize=0,t.whave=0,t.wnext=0,a(e)):U}function h(e,t){var r,n;return e&&e.state?(n=e.state,t<0?(r=0,t=-t):(r=1+(t>>4),t<48&&(t&=15)),t&&(t<8||15=s.wsize?(I.arraySet(s.window,t,r-s.wsize,s.wsize,0),s.wnext=0,s.whave=s.wsize):(n<(i=s.wsize-s.wnext)&&(i=n),I.arraySet(s.window,t,r-n,i,s.wnext),(n-=i)?(I.arraySet(s.window,t,r-n,n,0),s.wnext=n,s.whave=s.wsize):(s.wnext+=i,s.wnext===s.wsize&&(s.wnext=0),s.whave>>8&255,r.check=B(r.check,E,2,0),l=u=0,r.mode=2;break}if(r.flags=0,r.head&&(r.head.done=!1),!(1&r.wrap)||(((255&u)<<8)+(u>>8))%31){e.msg="incorrect header check",r.mode=30;break}if(8!=(15&u)){e.msg="unknown compression method",r.mode=30;break}if(l-=4,k=8+(15&(u>>>=4)),0===r.wbits)r.wbits=k;else if(k>r.wbits){e.msg="invalid window size",r.mode=30;break}r.dmax=1<>8&1),512&r.flags&&(E[0]=255&u,E[1]=u>>>8&255,r.check=B(r.check,E,2,0)),l=u=0,r.mode=3;case 3:for(;l<32;){if(0===o)break e;o--,u+=n[s++]<>>8&255,E[2]=u>>>16&255,E[3]=u>>>24&255,r.check=B(r.check,E,4,0)),l=u=0,r.mode=4;case 4:for(;l<16;){if(0===o)break e;o--,u+=n[s++]<>8),512&r.flags&&(E[0]=255&u,E[1]=u>>>8&255,r.check=B(r.check,E,2,0)),l=u=0,r.mode=5;case 5:if(1024&r.flags){for(;l<16;){if(0===o)break e;o--,u+=n[s++]<>>8&255,r.check=B(r.check,E,2,0)),l=u=0}else r.head&&(r.head.extra=null);r.mode=6;case 6:if(1024&r.flags&&(o<(d=r.length)&&(d=o),d&&(r.head&&(k=r.head.extra_len-r.length,r.head.extra||(r.head.extra=new Array(r.head.extra_len)),I.arraySet(r.head.extra,n,s,d,k)),512&r.flags&&(r.check=B(r.check,n,d,s)),o-=d,s+=d,r.length-=d),r.length))break e;r.length=0,r.mode=7;case 7:if(2048&r.flags){if(0===o)break e;for(d=0;k=n[s+d++],r.head&&k&&r.length<65536&&(r.head.name+=String.fromCharCode(k)),k&&d>9&1,r.head.done=!0),e.adler=r.check=0,r.mode=12;break;case 10:for(;l<32;){if(0===o)break e;o--,u+=n[s++]<>>=7&l,l-=7&l,r.mode=27;break}for(;l<3;){if(0===o)break e;o--,u+=n[s++]<>>=1)){case 0:r.mode=14;break;case 1:if(j(r),r.mode=20,6!==t)break;u>>>=2,l-=2;break e;case 2:r.mode=17;break;case 3:e.msg="invalid block type",r.mode=30}u>>>=2,l-=2;break;case 14:for(u>>>=7&l,l-=7&l;l<32;){if(0===o)break e;o--,u+=n[s++]<>>16^65535)){e.msg="invalid stored block lengths",r.mode=30;break}if(r.length=65535&u,l=u=0,r.mode=15,6===t)break e;case 15:r.mode=16;case 16:if(d=r.length){if(o>>=5,l-=5,r.ndist=1+(31&u),u>>>=5,l-=5,r.ncode=4+(15&u),u>>>=4,l-=4,286>>=3,l-=3}for(;r.have<19;)r.lens[A[r.have++]]=0;if(r.lencode=r.lendyn,r.lenbits=7,S={bits:r.lenbits},x=T(0,r.lens,0,19,r.lencode,0,r.work,S),r.lenbits=S.bits,x){e.msg="invalid code lengths set",r.mode=30;break}r.have=0,r.mode=19;case 19:for(;r.have>>16&255,b=65535&C,!((_=C>>>24)<=l);){if(0===o)break e;o--,u+=n[s++]<>>=_,l-=_,r.lens[r.have++]=b;else{if(16===b){for(z=_+2;l>>=_,l-=_,0===r.have){e.msg="invalid bit length repeat",r.mode=30;break}k=r.lens[r.have-1],d=3+(3&u),u>>>=2,l-=2}else if(17===b){for(z=_+3;l>>=_)),u>>>=3,l-=3}else{for(z=_+7;l>>=_)),u>>>=7,l-=7}if(r.have+d>r.nlen+r.ndist){e.msg="invalid bit length repeat",r.mode=30;break}for(;d--;)r.lens[r.have++]=k}}if(30===r.mode)break;if(0===r.lens[256]){e.msg="invalid code -- missing end-of-block",r.mode=30;break}if(r.lenbits=9,S={bits:r.lenbits},x=T(D,r.lens,0,r.nlen,r.lencode,0,r.work,S),r.lenbits=S.bits,x){e.msg="invalid literal/lengths set",r.mode=30;break}if(r.distbits=6,r.distcode=r.distdyn,S={bits:r.distbits},x=T(F,r.lens,r.nlen,r.ndist,r.distcode,0,r.work,S),r.distbits=S.bits,x){e.msg="invalid distances set",r.mode=30;break}if(r.mode=20,6===t)break e;case 20:r.mode=21;case 21:if(6<=o&&258<=h){e.next_out=a,e.avail_out=h,e.next_in=s,e.avail_in=o,r.hold=u,r.bits=l,R(e,c),a=e.next_out,i=e.output,h=e.avail_out,s=e.next_in,n=e.input,o=e.avail_in,u=r.hold,l=r.bits,12===r.mode&&(r.back=-1);break}for(r.back=0;g=(C=r.lencode[u&(1<>>16&255,b=65535&C,!((_=C>>>24)<=l);){if(0===o)break e;o--,u+=n[s++]<>v)])>>>16&255,b=65535&C,!(v+(_=C>>>24)<=l);){if(0===o)break e;o--,u+=n[s++]<>>=v,l-=v,r.back+=v}if(u>>>=_,l-=_,r.back+=_,r.length=b,0===g){r.mode=26;break}if(32&g){r.back=-1,r.mode=12;break}if(64&g){e.msg="invalid literal/length code",r.mode=30;break}r.extra=15&g,r.mode=22;case 22:if(r.extra){for(z=r.extra;l>>=r.extra,l-=r.extra,r.back+=r.extra}r.was=r.length,r.mode=23;case 23:for(;g=(C=r.distcode[u&(1<>>16&255,b=65535&C,!((_=C>>>24)<=l);){if(0===o)break e;o--,u+=n[s++]<>v)])>>>16&255,b=65535&C,!(v+(_=C>>>24)<=l);){if(0===o)break e;o--,u+=n[s++]<>>=v,l-=v,r.back+=v}if(u>>>=_,l-=_,r.back+=_,64&g){e.msg="invalid distance code",r.mode=30;break}r.offset=b,r.extra=15&g,r.mode=24;case 24:if(r.extra){for(z=r.extra;l>>=r.extra,l-=r.extra,r.back+=r.extra}if(r.offset>r.dmax){e.msg="invalid distance too far back",r.mode=30;break}r.mode=25;case 25:if(0===h)break e;if(d=c-h,r.offset>d){if((d=r.offset-d)>r.whave&&r.sane){e.msg="invalid distance too far back",r.mode=30;break}p=d>r.wnext?(d-=r.wnext,r.wsize-d):r.wnext-d,d>r.length&&(d=r.length),m=r.window}else m=i,p=a-r.offset,d=r.length;for(hd?(m=R[T+a[v]],A[I+a[v]]):(m=96,0),h=1<>S)+(u-=h)]=p<<24|m<<16|_|0,0!==u;);for(h=1<>=1;if(0!==h?(E&=h-1,E+=h):E=0,v++,0==--O[b]){if(b===w)break;b=t[r+a[v]]}if(k>>7)]}function U(e,t){e.pending_buf[e.pending++]=255&t,e.pending_buf[e.pending++]=t>>>8&255}function P(e,t,r){e.bi_valid>d-r?(e.bi_buf|=t<>d-e.bi_valid,e.bi_valid+=r-d):(e.bi_buf|=t<>>=1,r<<=1,0<--t;);return r>>>1}function Z(e,t,r){var n,i,s=new Array(g+1),a=0;for(n=1;n<=g;n++)s[n]=a=a+r[n-1]<<1;for(i=0;i<=t;i++){var o=e[2*i+1];0!==o&&(e[2*i]=j(s[o]++,o))}}function W(e){var t;for(t=0;t>1;1<=r;r--)G(e,s,r);for(i=h;r=e.heap[1],e.heap[1]=e.heap[e.heap_len--],G(e,s,1),n=e.heap[1],e.heap[--e.heap_max]=r,e.heap[--e.heap_max]=n,s[2*i]=s[2*r]+s[2*n],e.depth[i]=(e.depth[r]>=e.depth[n]?e.depth[r]:e.depth[n])+1,s[2*r+1]=s[2*n+1]=i,e.heap[1]=i++,G(e,s,1),2<=e.heap_len;);e.heap[--e.heap_max]=e.heap[1],function(e,t){var r,n,i,s,a,o,h=t.dyn_tree,u=t.max_code,l=t.stat_desc.static_tree,f=t.stat_desc.has_stree,c=t.stat_desc.extra_bits,d=t.stat_desc.extra_base,p=t.stat_desc.max_length,m=0;for(s=0;s<=g;s++)e.bl_count[s]=0;for(h[2*e.heap[e.heap_max]+1]=0,r=e.heap_max+1;r<_;r++)p<(s=h[2*h[2*(n=e.heap[r])+1]+1]+1)&&(s=p,m++),h[2*n+1]=s,u>=7;n>>=1)if(1&r&&0!==e.dyn_ltree[2*t])return o;if(0!==e.dyn_ltree[18]||0!==e.dyn_ltree[20]||0!==e.dyn_ltree[26])return h;for(t=32;t>>3,(s=e.static_len+3+7>>>3)<=i&&(i=s)):i=s=r+5,r+4<=i&&-1!==t?J(e,t,r,n):4===e.strategy||s===i?(P(e,2+(n?1:0),3),K(e,z,C)):(P(e,4+(n?1:0),3),function(e,t,r,n){var i;for(P(e,t-257,5),P(e,r-1,5),P(e,n-4,4),i=0;i>>8&255,e.pending_buf[e.d_buf+2*e.last_lit+1]=255&t,e.pending_buf[e.l_buf+e.last_lit]=255&r,e.last_lit++,0===t?e.dyn_ltree[2*r]++:(e.matches++,t--,e.dyn_ltree[2*(A[r]+u+1)]++,e.dyn_dtree[2*N(t)]++),e.last_lit===e.lit_bufsize-1},r._tr_align=function(e){P(e,2,3),L(e,m,z),function(e){16===e.bi_valid?(U(e,e.bi_buf),e.bi_buf=0,e.bi_valid=0):8<=e.bi_valid&&(e.pending_buf[e.pending++]=255&e.bi_buf,e.bi_buf>>=8,e.bi_valid-=8)}(e)}},{"../utils/common":41}],53:[function(e,t,r){"use strict";t.exports=function(){this.input=null,this.next_in=0,this.avail_in=0,this.total_in=0,this.output=null,this.next_out=0,this.avail_out=0,this.total_out=0,this.msg="",this.state=null,this.data_type=2,this.adler=0}},{}],54:[function(e,t,r){(function(e){!function(r,n){"use strict";if(!r.setImmediate){var i,s,t,a,o=1,h={},u=!1,l=r.document,e=Object.getPrototypeOf&&Object.getPrototypeOf(r);e=e&&e.setTimeout?e:r,i="[object process]"==={}.toString.call(r.process)?function(e){process.nextTick(function(){c(e)})}:function(){if(r.postMessage&&!r.importScripts){var e=!0,t=r.onmessage;return r.onmessage=function(){e=!1},r.postMessage("","*"),r.onmessage=t,e}}()?(a="setImmediate$"+Math.random()+"$",r.addEventListener?r.addEventListener("message",d,!1):r.attachEvent("onmessage",d),function(e){r.postMessage(a+e,"*")}):r.MessageChannel?((t=new MessageChannel).port1.onmessage=function(e){c(e.data)},function(e){t.port2.postMessage(e)}):l&&"onreadystatechange"in l.createElement("script")?(s=l.documentElement,function(e){var t=l.createElement("script");t.onreadystatechange=function(){c(e),t.onreadystatechange=null,s.removeChild(t),t=null},s.appendChild(t)}):function(e){setTimeout(c,0,e)},e.setImmediate=function(e){"function"!=typeof e&&(e=new Function(""+e));for(var t=new Array(arguments.length-1),r=0;r
-
-
-
-
- Leaflet.draw drawing and editing tools
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/data/map.html b/data/map.html
new file mode 100755
index 000000000..8f5883291
--- /dev/null
+++ b/data/map.html
@@ -0,0 +1,554 @@
+
+
+
+
+
+
+ Leaflet Map
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/scripts/build_deps_rhel7.sh b/scripts/build_deps_rhel7.sh
index d2c415a91..e946ee24e 100644
--- a/scripts/build_deps_rhel7.sh
+++ b/scripts/build_deps_rhel7.sh
@@ -90,7 +90,7 @@ export CXXFLAGS=-std=c++11
ccmake -DCMAKE_LIBRARY_PATH=$PREFIX/lib \
-DCMAKE_INCLUDE_DIR=$PREFIX/include \
-DCMAKE_INSTALL_PREFIX=$PREFIX \
- -DNINJA_QTGUI=OFF \
+ -DNINJA_GUI=OFF \
-DNINJAFOAM=OFF \
-DGDAL_CONFIG=$PREFIX/bin/gdal-config \
-DGDAL_INCLUDE_DIR=$PREFIX/include \
diff --git a/scripts/build_deps_ubuntu_2204.sh b/scripts/build_deps_ubuntu_2204.sh
index 4d529f4f9..bf374aa6b 100755
--- a/scripts/build_deps_ubuntu_2204.sh
+++ b/scripts/build_deps_ubuntu_2204.sh
@@ -19,6 +19,8 @@ sudo apt install -y libfontconfig1-dev \
libopenjp2-7-dev \
libtiff-dev
+# Install qt6 libs
+sudo apt install qt6-base-dev qt6-base-dev-tools qt6-webengine-dev qt6-webengine-dev-tools libqt6webenginecore6-bin
# Install Poppler for PDF support in GDAL
wget https://poppler.freedesktop.org/$POPPLER.tar.xz
@@ -54,13 +56,6 @@ make -j$(nproc)
sudo make install
cd ..
-# Add qt4 libs from ppa
-# See here for more info:
-# https://ubuntuhandbook.org/index.php/2020/07/install-qt4-ubuntu-20-04/
-sudo add-apt-repository ppa:ubuntuhandbook1/ppa
-sudo apt update
-sudo apt install -y libqt4-dev libqtwebkit-dev
-
# Use OpenFOAM 9; OpenFOAM 8 not available for Ubuntu 22.04
# add the dl.openfoam.org repo and install OpenFOAM 9
sudo sh -c "wget -O - https://dl.openfoam.org/gpg.key > /etc/apt/trusted.gpg.d/openfoam.asc"
diff --git a/scripts/firelab_build.bat b/scripts/firelab_build.bat
index 57132c71e..420bd7253 100644
--- a/scripts/firelab_build.bat
+++ b/scripts/firelab_build.bat
@@ -35,7 +35,7 @@ REM -DGDAL_LIBRARY=c:/src/gdal/gdal-1.10.0/lib/gdal_i.lib ^
cmake c:/src/windninja/trunk ^
-G "NMake Makefiles JOM" ^
-DFIRELAB_PACKAGE=ON ^
- -DNINJA_QTGUI=ON ^
+ -DNINJA_GUI=ON ^
-DNINJA_CLI=ON ^
-DENABLE_CONSOLE=FALSE ^
-DOPENMP_SUPPORT=ON ^
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 233d1b8db..3797c367c 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -15,13 +15,13 @@
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
# DEALINGS IN THE SOFTWARE.
-#cmake_minimum_required(VERSION 2.6)
+#cmake_minimum_required(VERSION 3.16)
add_subdirectory(ninja)
-if(NINJA_QTGUI)
+if(NINJA_GUI)
add_subdirectory(gui)
-endif(NINJA_QTGUI)
+endif(NINJA_GUI)
if(NINJA_CLI)
add_subdirectory(cli)
endif(NINJA_CLI)
diff --git a/src/cli/CMakeLists.txt b/src/cli/CMakeLists.txt
index 7376568e8..c8c413d0d 100644
--- a/src/cli/CMakeLists.txt
+++ b/src/cli/CMakeLists.txt
@@ -15,7 +15,7 @@
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
# DEALINGS IN THE SOFTWARE.
-#cmake_minimum_required(VERSION 2.6)
+#cmake_minimum_required(VERSION 3.10)
include_directories(${PROJECT_SOURCE_DIR}/src
${PROJECT_SOURCE_DIR}/src/ninja
@@ -29,14 +29,6 @@ set(LINK_LIBS ${Boost_LIBRARIES}
${NETCDF_LIBRARIES_C}
${CURL_LIBRARIES})
-if(NINJA_QTGUI AND NINJA_CLI)
- set(LINK_LIBS ${LINK_LIBS}
- ${QT_LIBRARIES})
- if(PACKAGE_DEBUG)
- message("CLI Linking to Qt Libraries")
- endif(PACKAGE_DEBUG)
-endif(NINJA_QTGUI AND NINJA_CLI)
-
if(WIN32 OR APPLE)
set(LINK_LIBS ${LINK_LIBS} ${PROJECT_BINARY_DIR}/src/ninja/${CMAKE_CFG_INTDIR}/${CMAKE_STATIC_LIBRARY_PREFIX}ninja${CMAKE_STATIC_LIBRARY_SUFFIX})
else(WIN32 OR APPLE)
@@ -49,7 +41,19 @@ endif()
add_executable(WindNinja_cli cmake_cli.cpp)
+
+if(WIN32)
+ target_link_libraries(WindNinja_cli PRIVATE shapelib::shp GDAL::GDAL)
+endif()
+
target_link_libraries(WindNinja_cli ${LINK_LIBS} $<$:OpenMP::OpenMP_CXX>)
add_dependencies(WindNinja_cli ninja)
+if(MSVC)
+ target_compile_definitions(WindNinja_cli
+ PUBLIC
+ WIN32_LEAN_AND_MEAN
+ )
+endif()
+
install(TARGETS WindNinja_cli DESTINATION bin COMPONENT apps)
diff --git a/src/cli/cmake_cli.cpp b/src/cli/cmake_cli.cpp
index d9e39b8ec..4150005cf 100644
--- a/src/cli/cmake_cli.cpp
+++ b/src/cli/cmake_cli.cpp
@@ -2,7 +2,7 @@
*
* $Id:$
*
- * Project: WindNinja Qt GUI
+ * Project: WindNinja cli
* Purpose: main() function to initiate cli
* Author: Kyle Shannon
*
diff --git a/src/fetch_dem/CMakeLists.txt b/src/fetch_dem/CMakeLists.txt
index 776301a20..9bb0a27e9 100644
--- a/src/fetch_dem/CMakeLists.txt
+++ b/src/fetch_dem/CMakeLists.txt
@@ -15,7 +15,7 @@
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
# DEALINGS IN THE SOFTWARE.
-cmake_minimum_required(VERSION 2.6)
+cmake_minimum_required(VERSION 3.16)
include_directories(${PROJECT_SOURCE_DIR}/src
${PROJECT_SOURCE_DIR}/src/ninja
diff --git a/src/fetch_station/CMakeLists.txt b/src/fetch_station/CMakeLists.txt
index 1d967ad07..2adef421d 100644
--- a/src/fetch_station/CMakeLists.txt
+++ b/src/fetch_station/CMakeLists.txt
@@ -15,7 +15,7 @@
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
# DEALINGS IN THE SOFTWARE.
-cmake_minimum_required(VERSION 2.6)
+cmake_minimum_required(VERSION 3.16)
include_directories(${PROJECT_SOURCE_DIR}/src
${PROJECT_SOURCE_DIR}/src/ninja
diff --git a/src/flow_separation_grid/CMakeLists.txt b/src/flow_separation_grid/CMakeLists.txt
index ebe468c07..2c24ca734 100644
--- a/src/flow_separation_grid/CMakeLists.txt
+++ b/src/flow_separation_grid/CMakeLists.txt
@@ -15,7 +15,7 @@
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
# DEALINGS IN THE SOFTWARE.
-cmake_minimum_required(VERSION 2.6)
+cmake_minimum_required(VERSION 3.16)
include_directories(${PROJECT_SOURCE_DIR}/src/ninja
${GDAL_SYSTEM_INCLUDE} ${GDAL_INCLUDE_DIR})
diff --git a/src/gui/CMakeLists.txt b/src/gui/CMakeLists.txt
deleted file mode 100644
index e78c2ea5a..000000000
--- a/src/gui/CMakeLists.txt
+++ /dev/null
@@ -1,133 +0,0 @@
-# THIS SOFTWARE WAS DEVELOPED AT THE ROCKY MOUNTAIN RESEARCH STATION (RMRS)
-# MISSOULA FIRE SCIENCES LABORATORY BY EMPLOYEES OF THE FEDERAL GOVERNMENT
-# IN THE COURSE OF THEIR OFFICIAL DUTIES. PURSUANT TO TITLE 17 SECTION 105
-# OF THE UNITED STATES CODE, THIS SOFTWARE IS NOT SUBJECT TO COPYRIGHT
-# PROTECTION AND IS IN THE PUBLIC DOMAIN. RMRS MISSOULA FIRE SCIENCES
-# LABORATORY ASSUMES NO RESPONSIBILITY WHATSOEVER FOR ITS USE BY OTHER
-# PARTIES, AND MAKES NO GUARANTEES, EXPRESSED OR IMPLIED, ABOUT ITS QUALITY,
-# RELIABILITY, OR ANY OTHER CHARACTERISTIC.
-#
-# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
-# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
-# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
-# DEALINGS IN THE SOFTWARE.
-
-cmake_minimum_required(VERSION 2.6)
-
-QT4_WRAP_UI(QTUI_H_SRCS WidgetDownloadDEM.ui
- setconfigdialog.ui
- stationFetchWidget.ui)
-
-set(NINJA_GUI_INCLUDES consoleDockWidget.h
- diurnalInput.h
- stabilityInput.h
- fbOutput.h
- googleOutput.h
- latLonWidget.h
- mainWindow.h
- metaWindWidget.h
- nativeSolverInput.h
- ninjafoamInput.h
- outputHeightWidget.h
- outputMetaData.h
- pdfOutput.h
- pointInput.h
- shapeOutput.h
- solvePage.h
- solveThread.h
- splash.h
- surfaceInput.h
- timeZoneWidget.h
- #vec3f.h
- vtkOutput.h
- weatherModel.h
- WidgetDownloadDEM.h
- stationFetchWidget.h
- windInput.h
- windInputTable.h
- WindNinjaTree.h
- GoogleMapsInterface.h
- setconfigdialog.h
- ${QTUI_H_SRCS})
-
-include_directories(${QT_INCLUDES}
- ${Boost_INCLUDE_DIRS}
- ${NETCDF_INCLUDES}
- ${GDAL_SYSTEM_INCLUDE} ${GDAL_INCLUDE_DIR}
- ${CURL_INCLUDE_DIR}
- ${PROJECT_SOURCE_DIR}/src
- ${PROJECT_SOURCE_DIR}/src/ninja
- ${CMAKE_CURRENT_BINARY_DIR})
-
-QT4_WRAP_CPP(NINJA_GUI_INCLUDES_MOC ${NINJA_GUI_INCLUDES})
-QT4_ADD_RESOURCES(NINJA_GUI_RESOURCES ${PROJECT_SOURCE_DIR}/wn-resources.qrc)
-
-set(NINJA_GUI_SOURCES cmake_gui.cpp
- ${PROJECT_SOURCE_DIR}/src/ninja/cli.cpp
- consoleDockWidget.cpp
- diurnalInput.cpp
- stabilityInput.cpp
- fbOutput.cpp
- googleOutput.cpp
- latLonWidget.cpp
- mainWindow.cpp
- metaWindWidget.cpp
- outputHeightWidget.cpp
- outputMetaData.cpp
- nativeSolverInput.cpp
- ninjafoamInput.cpp
- pdfOutput.cpp
- pointInput.cpp
- shapeOutput.cpp
- solvePage.cpp
- solveThread.cpp
- splash.cpp
- surfaceInput.cpp
- timeZoneWidget.cpp
- vec3f.cpp
- vtkOutput.cpp
- weatherModel.cpp
- windInput.cpp
- windInputTable.cpp
- WindNinjaTree.cpp
- WidgetDownloadDEM.cpp
- stationFetchWidget.cpp
- GoogleMapsInterface.cpp
- setconfigdialog.cpp
- ${QTUI_H_SRCS})
-if(WIN32)
- set(NINJA_GUI_SOURCES ${NINJA_GUI_SOURCES}
- ${PROJECT_SOURCE_DIR}/wn-ms-resource.rc)
- add_definitions(-DQT_NO_DEBUG_OUTPUT)
-endif(WIN32)
-
-set(LINK_LIBS ${QT_LIBRARIES}
- ${GDAL_LIBRARY}
- ${Boost_LIBRARIES}
- ${CURL_LIBRARIES}
- ${NETCDF_LIBRARIES_C})
-
-if(WIN32)
- set(LINK_LIBS ${LINK_LIBS} ${PROJECT_BINARY_DIR}/src/ninja/${CMAKE_CFG_INTDIR}/${CMAKE_STATIC_LIBRARY_PREFIX}ninja${CMAKE_STATIC_LIBRARY_SUFFIX})
- if(NOT ENABLE_CONSOLE)
- set(LINK_LIBS ${LINK_LIBS} ${QT_QTMAIN_LIBRARY})
- set(GUI_TYPE WIN32)
- else(NOT ENABLE_CONSOLE)
- set(GUI_TYPE "")
- endif(NOT ENABLE_CONSOLE)
-else(WIN32)
- set(LINK_LIBS ${LINK_LIBS} ${PROJECT_BINARY_DIR}/src/ninja/${CMAKE_SHARED_LIBRARY_PREFIX}ninja${CMAKE_SHARED_LIBRARY_SUFFIX})
-endif(WIN32)
-
-add_executable(WindNinja ${GUI_TYPE}
- ${NINJA_GUI_INCLUDES_MOC}
- ${NINJA_GUI_RESOURCES}
- ${NINJA_GUI_SOURCES})
-
-target_link_libraries(WindNinja ${LINK_LIBS} $<$:OpenMP::OpenMP_CXX>)
-add_dependencies(WindNinja ninja)
-install(TARGETS WindNinja DESTINATION bin COMPONENT apps)
-
diff --git a/src/gui/WidgetDownloadDEM.cpp b/src/gui/WidgetDownloadDEM.cpp
deleted file mode 100644
index 4df8c90c1..000000000
--- a/src/gui/WidgetDownloadDEM.cpp
+++ /dev/null
@@ -1,585 +0,0 @@
-/******************************************************************************
- *
- * $Id: WidgetDownloadDEM.cpp 1757 2012-08-07 18:40:40Z kyle.shannon $
- *
- * Project: WindNinja
- * Purpose: DEM Downloader Window
- * Author: Cody Posey
- *
- ******************************************************************************
- *
- * THIS SOFTWARE WAS DEVELOPED AT THE ROCKY MOUNTAIN RESEARCH STATION (RMRS)
- * MISSOULA FIRE SCIENCES LABORATORY BY EMPLOYEES OF THE FEDERAL GOVERNMENT
- * IN THE COURSE OF THEIR OFFICIAL DUTIES. PURSUANT TO TITLE 17 SECTION 105
- * OF THE UNITED STATES CODE, THIS SOFTWARE IS NOT SUBJECT TO COPYRIGHT
- * PROTECTION AND IS IN THE PUBLIC DOMAIN. RMRS MISSOULA FIRE SCIENCES
- * LABORATORY ASSUMES NO RESPONSIBILITY WHATSOEVER FOR ITS USE BY OTHER
- * PARTIES, AND MAKES NO GUARANTEES, EXPRESSED OR IMPLIED, ABOUT ITS QUALITY,
- * RELIABILITY, OR ANY OTHER CHARACTERISTIC.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *
- *****************************************************************************/
-
-#include "WidgetDownloadDEM.h"
-//#include
-
-WidgetDownloadDEM::WidgetDownloadDEM(QWidget *parent)
- : QWidget(parent)
-{
-
- //------------provide updated SSL certs in case system ones are outdated--------------------------------//
- // qt_certs_bundle.pem generated on a windows system with the latest windows version of openssl installed
- // certutil -generateSSTFromWU roots.sst
- // certutil -split -f roots.sst
- // type NUL > qt_certs_bundle.pem
- // for %f in (*.crt) do (openssl x509 -inform der -in "%f" -out temp.pem && type temp.pem >> qt_certs_bundle.pem && del temp.pem)
- // del *.crt
- // for debugging on working systems, try disabling system certificates for testing, set it to an empty list of certificates
- //QSslSocket::setDefaultCaCertificates(QList());
- // add the data folder SSL Ca certificates to the certificates list
- std::string pathToSslCerts = FindDataPath("qt_certs_bundle.pem");
- QString pathToCerts = QString::fromStdString(pathToSslCerts);
- QSslSocket::addDefaultCaCertificates( pathToCerts, QSsl::Pem, QRegExp::FixedString);
-
- demSelected = false;
-
- setupUi(this);
- setupGM();
- initializeGoogleMapsInterface();
- connectInputs();
- this->readSettings();
-
- progressBar = new QProgressDialog(this);
- progressBar->setWindowModality(Qt::ApplicationModal);
- progressBar->setAutoReset(false);
- progressBar->setAutoClose(false);
-
- boundsError = NULL;
- bufferError = NULL;
- latlngError = NULL;
-
- //These are temporary values to store the points needed for DEM bounds
- double northEast[2];
- double southEast[2];
- double southWest[2];
- double northWest[2];
-
- fetcher = FetchFactory::GetSurfaceFetch(FetchFactory::SRTM,"");
- fetcher->GetCorners(northEast, southEast, southWest, northWest);
- srtm_northBound = northEast[1];
- srtm_eastBound = northEast[0];
- srtm_westBound = southWest[0];
- srtm_southBound = southWest[1];
- delete fetcher;
-
-#ifdef HAVE_GMTED
- fetcher = FetchFactory::GetSurfaceFetch(FetchFactory::WORLD_GMTED,"");
- fetcher->GetCorners(northEast, southEast, southWest, northWest);
- world_gmted_northBound = northEast[1];
- world_gmted_eastBound = northEast[0];
- world_gmted_westBound = southWest[0];
- world_gmted_southBound = southWest[1];
- delete fetcher;
-#endif
-
-#ifdef WITH_LCP_CLIENT
- fetcher = FetchFactory::GetSurfaceFetch(FetchFactory::LCP,"");
- fetcher->GetCorners(northEast, southEast, southWest, northWest);
- lcp_northBound = northEast[1];
- lcp_eastBound = northEast[0];
- lcp_westBound = southWest[0];
- lcp_southBound = southWest[1];
- delete fetcher;
-#endif
-
-#ifndef HAVE_GMTED
- this->cbDEMSource->removeItem(1);
-#endif
-
-#ifndef WITH_LCP_CLIENT
- this->cbDEMSource->removeItem(2);
-#endif
-
- cbDEMSource->setItemData(0, "Partial world coverage Shuttle Radar Topography Mission data (SRTM) at 30 meter resolution. Any existing holes in the data have been filled.", Qt::ToolTipRole);
-#ifdef HAVE_GMTED
- cbDEMSource->setItemData(1, "World coverage Global Multi-resolution Terrain Elevation Data 2010 (GMTED2010) at 250 meter resolution.", Qt::ToolTipRole);
-#endif
-#ifdef WITH_LCP_CLIENT
- cbDEMSource->setItemData(2, "US coverage LANDFIRE 2023 Landscape data at 30 meter resolution.", Qt::ToolTipRole);
-#endif
- updateDEMSource(cbDEMSource->currentIndex());
-
- fileSize = 0;
-
-#ifdef ENABLE_FIDDLER
- QNetworkProxy proxy;
- proxy.setType(QNetworkProxy::HttpProxy);
- proxy.setHostName("127.0.0.1");
- proxy.setPort(8888);
- QNetworkProxy::setApplicationProxy(proxy);
-#endif
-
- this->setWindowFlags(Qt::CustomizeWindowHint | Qt::WindowMinMaxButtonsHint | Qt::WindowCloseButtonHint);
- this->show();
-}
-
-/**
- * @brief Deletes all allocated memory on destruction of class object
- *
- */
-WidgetDownloadDEM::~WidgetDownloadDEM()
-{
- delete progressBar;
- delete fetcher;
- delete latlngError;
- delete bufferError;
- delete boundsError;
- delete gmInterface;
-}
-
-/**
- * @brief Connect all SLOTS and SIGNALS in the Qt GUI
- *
- */
-void WidgetDownloadDEM::connectInputs()
-{
- connect(btnDownloadDEM, SIGNAL(clicked()), this, SLOT(saveDEM()));
- connect(cbDEMSource, SIGNAL(currentIndexChanged(int)), this, SLOT(updateDEMSource(int)));
-}
-
-/**
- * @brief Initialize the google maps interface and interface object
- *
- */
-void WidgetDownloadDEM::initializeGoogleMapsInterface()
-{
- gmInterface = new GoogleMapsInterface();
- this->wvGoogleMaps->page()->mainFrame()->addToJavaScriptWindowObject("GMInterface", gmInterface);
- connect(gmInterface, SIGNAL(zoomExtents()), this, SLOT(zoomToMidpoint()));
-}
-
-/**
- * @brief Clears listeners when changing selection method
- *
- */
-void WidgetDownloadDEM::clearListeners()
-{
- this->wvGoogleMaps->page()->mainFrame()->evaluateJavaScript("clearListeners(); null");
-}
-
-
-/**
- * @brief Sets up the google map
- *
- */
-void WidgetDownloadDEM::setupGM()
-{
- this->wvGoogleMaps->settings()->setAttribute(QWebSettings::JavascriptEnabled, true);
- this->wvGoogleMaps->settings()->setAttribute(QWebSettings::DeveloperExtrasEnabled, true);
- this->wvGoogleMaps->setPage(new QWebPage());
- wvGoogleMaps->page()->setLinkDelegationPolicy(QWebPage::DelegateAllLinks);
- this->wvGoogleMaps->load(QUrl(QString(CPLFormFilename("file:///", (FindDataPath("map.htm").c_str()), NULL))));
-
- //enable QWebInspector for degugging google maps widget
- if(CSLTestBoolean(CPLGetConfigOption("ENABLE_QWEBINSPECTOR", "NO")))
- {
- wvGoogleMaps->page()->settings()->setAttribute(QWebSettings::DeveloperExtrasEnabled, true);
- QWebInspector *i = new QWebInspector(this);
- i->setPage(wvGoogleMaps->page());
- i->setVisible(true);
-
- dlg.setLayout(new QVBoxLayout());
- dlg.layout()->addWidget(i);
- dlg.setModal(false);
- dlg.show();
- dlg.raise();
- dlg.activateWindow();
- }
-}
-
-/**
- * @brief Download and save the current DEM area
- *
- */
-void WidgetDownloadDEM::saveDEM()
-{
- QVariant mbr = wvGoogleMaps->page()->mainFrame()->evaluateJavaScript("mbr()");
- if(mbr.isNull()) {
- qDebug()<<"no mbr";
- QMessageBox mbox;
- mbox.setText("DEM bounding box not set. Select the DEM bounding box by using the bounding box drawing tool on the upper right corner of the map, entering a point and radius, or entering the bounding box coordinates.");
- mbox.exec();
- return;
- }
- QVariantList mbrl = mbr.toList();
- if(mbrl.size() == 0)
- {
- QMessageBox mbox;
- mbox.setText("DEM bounding box not set. Select the DEM bounding box by using the bounding box drawing tool on the upper right corner of the map, entering a point and radius, or entering the bounding box coordinates.");
- mbox.exec();
- return;
- }
- for(int i=0; i < mbrl.size(); i++) {
- qDebug() << mbrl[i];
- }
- northBound = mbrl[3].toDouble();
- southBound = mbrl[2].toDouble();
- eastBound = mbrl[1].toDouble();
- westBound = mbrl[0].toDouble();
- demSelected = true;
-
- QString fileName;
- double boundArray[] = {this->northBound, this->eastBound, this->southBound, this->westBound};
- double *boundBox;
- boundBox = boundArray;
-
- if(northBound == 0.0 || southBound == 0.0 || eastBound == 0.0 || westBound == 0.0)
- {
- QMessageBox noBoundsError;
- noBoundsError.setText("Please Select an Area on the Map");
- noBoundsError.exec();
- }
- else if(!demSelected)
- {
- QMessageBox noBoundsError2;
- noBoundsError2.setText("Please select an area on the map.");
- noBoundsError2.exec();
- }
- //else if(!demBoundsCheck())
- //{
- // QMessageBox demBoundsError;
- // demBoundsError.setText("Area is outside data bounds. Please select new data Source or new Area.");
- // demBoundsError.exec();
- //}
- else if((fileSize/1024) > 50)
- {
- QMessageBox demBoundsError;
- demBoundsError.setText("File size is limited to 50mb. Please select a smaller area.");
- demBoundsError.exec();
- }
- else if(cbDEMSource->currentIndex() == 0 && (CPLGetConfigOption("CUSTOM_SRTM_API_KEY", NULL) == NULL || CPLGetConfigOption("NINJA_GUI_SRTM_API_KEY", NULL) != NULL))
- {
- QMessageBox apiKeyError;
- apiKeyError.setText("API Key not specified. Please specify the environment variables NINJA_GUI_SRTM_API_KEY or CUSTOM_SRTM_API_KEY");
- apiKeyError.exec();
- }
- else
- {
- QFileDialog saveDialog(this, tr("Save File"), demFileDir.absolutePath(), currentSaveAsDesc);
- saveDialog.setDefaultSuffix(currentSuffix);
- saveDialog.setAcceptMode(QFileDialog::AcceptSave);
- if(saveDialog.exec())
- {
- fileName = saveDialog.selectedFiles().at(0);
-
- QByteArray file = fileName.toLocal8Bit();
- demFile = file.data();
-
- progressBar->setLabelText("Downloading File...");
- progressBar->setRange(0,0);
- progressBar->setCancelButtonText("Cancel");
- progressBar->reset();
- bool test = progressBar->wasCanceled();
-
- connect(&futureWatcher, SIGNAL(finished()), this, SLOT(updateProgress()));
- connect(progressBar, SIGNAL(canceled()), this, SLOT(updateProgress()));
-
- futureWatcher.setFuture(QtConcurrent::run(this, &WidgetDownloadDEM::fetchBoundBox, boundBox, demFile, currentResolution));
-
- progressBar->exec();
- }
- }
-}
-
-/**
- * @brief Updates the progress bar and fills no data values
- *
- */
-void WidgetDownloadDEM::updateProgress()
-{
- disconnect(progressBar, SIGNAL(canceled()), this, SLOT(updateProgress()));
- disconnect(&futureWatcher, SIGNAL(finished()), this, SLOT(updateProgress()));
-
- if(progressBar->wasCanceled())
- {
- progressBar->setLabelText("Canceling...");
- progressBar->setCancelButton(0);
- futureWatcher.waitForFinished();
- VSIUnlink(demFile);
- progressBar->cancel();
- }
- else
- {
- futureWatcher.waitForFinished();
- int result = futureWatcher.result();
-
- if(result < 0)
- {
- progressBar->setLabelText("The surface data download failed. \nThis can happen when either the data source doesn't cover your region or the server that provides the surface data is down or under high usage. \nPlease try again later or try a different data source.");
- progressBar->setRange(0,1);
- progressBar->setValue( 0 );
- progressBar->setCancelButtonText("Close");
- VSIUnlink(demFile);
- }
- else
- {
- if(result)
- this->fillNoDataValues(demFile);
-
- progressBar->setValue(1);
- progressBar->setRange(0,100);
- progressBar->setValue(100);
- progressBar->setLabelText("Download Successful");
- progressBar->setCancelButtonText("Close");
-
- this->doneDownloading(demFile);
- }
- }
-}
-
-
-/**
- * @brief Closes the DEM downloader
- *
- */
-void WidgetDownloadDEM::closeDEM()
-{
- this->close();
-}
-
-/**
- * @brief Fetches bounding box for DEM
- *
- * @param boundsBox Lat/Lon Bounds
- * @param fileName Name of saved DEM file
- * @param resolution Resolution for DEM
- */
-int WidgetDownloadDEM::fetchBoundBox(double *boundsBox, const char *fileName, double resolution)
-{
- int result = fetcher->FetchBoundingBox(boundsBox, resolution, fileName, NULL);
-
- return result;
-}
-
-/**
- * @brief Updates the DEM Source
- *
- * @param index Current index of the DEM source combo box
- */
-void WidgetDownloadDEM::updateDEMSource(int index)
-{
- switch(index){
- case 0: //SRTM
- fetcher = FetchFactory::GetSurfaceFetch(FetchFactory::SRTM, FindDataPath("/data"));
- northDEMBound = srtm_northBound;
- southDEMBound = srtm_southBound;
- currentResolution = fetcher->GetXRes();
- currentSuffix = "tif";
- currentSaveAsDesc = "Elevation files (*.tif)";
- break;
-#ifdef HAVE_GMTED
- case 1: //GMTED
- fetcher = FetchFactory::GetSurfaceFetch(FetchFactory::WORLD_GMTED, FindDataPath("/data"));
- northDEMBound = world_gmted_northBound;
- southDEMBound = world_gmted_southBound;
- currentResolution = (fetcher->GetXRes() * 111325); // convert from lat/lon to m
- currentSuffix = "tif";
- currentSaveAsDesc = "Elevation files (*.tif)";
- break;
-#endif
-#ifdef WITH_LCP_CLIENT
- case 2: //LCP
- fetcher = FetchFactory::GetSurfaceFetch(FetchFactory::LCP, FindDataPath("/data"));
- northDEMBound = lcp_northBound;
- southDEMBound = lcp_southBound;
- /* this is in meters */
- currentResolution = fetcher->GetXRes();
- currentSuffix = "tif";
- currentSaveAsDesc = "Landscape files (*.tif)";
- break;
-#endif
- }
-}
-
-/**
- * @brief Checks whether the current selected area is withing the current DEM bounds
- *
- */
-bool WidgetDownloadDEM::demBoundsCheck()
-{
- QString checkBounds;
- QString wktPoly;
- QByteArray byteArray;
- int contains;
- //std::string oFile = FindDataPath( "us_srtm_region.shp" );
- std::string oFile = FindDataPath( "srtm_region.geojson" );
- const char *pszWkt;
- switch(cbDEMSource->currentIndex()){
- case 0: //SRTM
- wktPoly =
- QString("POLYGON( (%1 %2, %3 %4, ").arg(westBound).arg(northBound).arg(eastBound).arg(northBound) +
- QString("%1 %2, %3 %4, ").arg(eastBound).arg(southBound).arg(westBound).arg(southBound) +
- QString("%1 %2) )").arg(westBound).arg(northBound);
- byteArray = wktPoly.toUtf8();
- pszWkt = byteArray.constData();
- contains = NinjaOGRContain(pszWkt, oFile.c_str(), NULL);
- if(contains)
- {
- return true;
- }
- else
- return false;
- case 1: //GMTED
- if(northDEMBound < northBound || southDEMBound > southBound)
- return false;
- else
- return true;
- break;
- case 2: //LCP
- if(northDEMBound < northBound || southDEMBound > southBound)
- return false;
- else
- return true;
- break;
- }
-}
-
-/**
- * @brief Pans to lat/lng point
- *
- */
-void WidgetDownloadDEM::zoomToMidpoint()
-{
- QString midPoint = QString("zoomFitBounds(%1,%2,%3,%4);").arg(southBound).arg(westBound).arg(northBound).arg(eastBound);
- wvGoogleMaps->page()->mainFrame()->evaluateJavaScript(midPoint);
-}
-
-/**
- * @brief Updates area selected for Est File Size and for downloading a DEM
- *
- * @param selected Whether an area has been selected
- */
-void WidgetDownloadDEM::demSelectedUpdate(bool selected)
-{
- demSelected = selected;
-}
-
-/**
- * @brief Uses GDAL utilities to fill any no data values in the file
- *
- * @param file The file containing DEM data
- */
-void WidgetDownloadDEM::fillNoDataValues(const char* file)
-{
- GDALDataset *poDS;
- poDS = (GDALDataset*)GDALOpen(demFile, GA_Update);
- int nNoDataValues;
- if(GDALHasNoData(poDS, 1))
- {
- nNoDataValues = GDALFillBandNoData(poDS, 1, 100);
- /* Should we fill again? */
- if(nNoDataValues)
- {}
- }
- GDALClose((GDALDatasetH)poDS);
-}
-
-/**
- * @brief Saves the current DEM settings
- *
- */
-void WidgetDownloadDEM::writeSettings()
-{
- QSettings settings(QSettings::UserScope, "Firelab", "WindNinja");
- settings.setDefaultFormat(QSettings::IniFormat);
- //Saves DEM Source to settings
- settings.setValue("demSource", cbDEMSource->currentIndex());
- //Saves Current Lat/Lon Positions
- settings.setValue("North", northBound);
- settings.setValue("South", southBound);
- settings.setValue("East", eastBound);
- settings.setValue("West", westBound);
- settings.setValue("Latitude", latitude);
- settings.setValue("Longitude", longitude);
- //Saves Download Path to settings
- settings.setValue("downloadPath", settingsDir.absolutePath());
-}
-
-/**
- * @brief Reads previous DEM settings
- *
- */
-void WidgetDownloadDEM::readSettings()
-{
- QSettings settings(QSettings::UserScope, "Firelab", "WindNinja");
- settings.setDefaultFormat(QSettings::IniFormat);
-
- if(settings.contains("demSource"))
- {
- cbDEMSource->setCurrentIndex(settings.value("demSource").toInt());
- }
- if(settings.contains("inputFileDir"))
- {
- demFileDir = settings.value("inputFileDir").toString();
- }
-
- if(settings.contains("North"))
- {
- northBound = settings.value("North").toDouble();
- }
-
- else
- northBound = 44.0249023401036;
-
- if(settings.contains("South"))
- {
- southBound = settings.value("South").toDouble();
- }
- else
- southBound = 43.7832152227745;
-
- if(settings.contains("East"))
- {
- eastBound = settings.value("East").toDouble();
- }
- else
- eastBound = -113.463446144564;
- if(settings.contains("West"))
- {
- westBound = settings.value("West").toDouble();
- }
- else
- westBound = -113.749693430469;
-
- if(settings.contains("Latitude"))
- {
- latitude = settings.value("Latitude").toDouble();
- }
- else
- latitude = -113.613611;
- if(settings.contains("Longitude"))
- {
- longitude = settings.value("Longitude").toDouble();
- }
- else
- longitude = 43.911944;
-}
-
-/**
- * @brief Handles close events of GUI such as clicking X close icon
- *
- */
-void WidgetDownloadDEM::closeEvent(QCloseEvent *event)
-{
- event->ignore();
- this->writeSettings();
- exitDEM();
- event->accept();
-}
diff --git a/src/gui/WidgetDownloadDEM.h b/src/gui/WidgetDownloadDEM.h
deleted file mode 100644
index c3471d0d5..000000000
--- a/src/gui/WidgetDownloadDEM.h
+++ /dev/null
@@ -1,132 +0,0 @@
-/******************************************************************************
- *
- * $Id: WidgetDownloadDEM.h 1757 2012-08-07 18:40:40Z kyle.shannon $
- *
- * Project: WindNinja
- * Purpose: DEM Downloader Window
- * Author: Cody Posey
- *
- ******************************************************************************
- *
- * THIS SOFTWARE WAS DEVELOPED AT THE ROCKY MOUNTAIN RESEARCH STATION (RMRS)
- * MISSOULA FIRE SCIENCES LABORATORY BY EMPLOYEES OF THE FEDERAL GOVERNMENT
- * IN THE COURSE OF THEIR OFFICIAL DUTIES. PURSUANT TO TITLE 17 SECTION 105
- * OF THE UNITED STATES CODE, THIS SOFTWARE IS NOT SUBJECT TO COPYRIGHT
- * PROTECTION AND IS IN THE PUBLIC DOMAIN. RMRS MISSOULA FIRE SCIENCES
- * LABORATORY ASSUMES NO RESPONSIBILITY WHATSOEVER FOR ITS USE BY OTHER
- * PARTIES, AND MAKES NO GUARANTEES, EXPRESSED OR IMPLIED, ABOUT ITS QUALITY,
- * RELIABILITY, OR ANY OTHER CHARACTERISTIC.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *
- *****************************************************************************/
-
-#ifndef WIGDET_DOWNLOAD_DEM_H_
-#define WIGDET_DOWNLOAD_DEM_H_
-
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include "fetch_factory.h"
-#include "gdal_util.h"
-#include "ninja_conv.h"
-#include
-#include
-#include "ui_WidgetDownloadDEM.h"
-#include "GoogleMapsInterface.h"
-
-#ifndef PI
-#define PI 3.14159
-#endif
-
-class WidgetDownloadDEM : public QWidget, private Ui::WidgetDownloadDEM
-{
- Q_OBJECT
-
-public:
- WidgetDownloadDEM(QWidget *parent = 0);
- ~WidgetDownloadDEM();
- QDir settingsDir;
- void initializeGoogleMapsInterface();
- void setupGM();
- void connectInputs();
- void fillNoDataValues(const char* file);
- void writeSettings();
- void readSettings();
- int fetchBoundBox(double *boundsBox, const char *fileName, double resolution);
-
-protected:
- void closeEvent(QCloseEvent *event);
-
- private slots:
- void clearListeners();
- void saveDEM();
- void updateProgress();
- void updateDEMSource(int index);
- bool demBoundsCheck();
- void zoomToMidpoint();
- void demSelectedUpdate(bool selected);
- void closeDEM();
-
- signals:
- void doneDownloading(const char* file);
- void exitDEM();
-
-
-private:
- QDialog dlg;
-
- double latitude;
- double longitude;
- double northBound;
- double southBound;
- double eastBound;
- double westBound;
- double srtm_southBound;
- double srtm_westBound;
- double srtm_northBound;
- double srtm_eastBound;
- double world_gmted_southBound;
- double world_gmted_westBound;
- double world_gmted_northBound;
- double world_gmted_eastBound;
- double lcp_southBound;
- double lcp_westBound;
- double lcp_northBound;
- double lcp_eastBound;
- double currentResolution;
-
- double northDEMBound;
- double southDEMBound;
-
- double fileSize;
- bool demSelected;
-
- const char *demFile;
- QDir demFileDir;
- QFutureWatcher futureWatcher;
- QProgressDialog *progressBar;
- QMessageBox *boundsError;
- QMessageBox *bufferError;
- QMessageBox *latlngError;
- SurfaceFetch *fetcher;
- GoogleMapsInterface* gmInterface;
- QString currentSaveAsDesc;
- QString currentSuffix;
-};
-
-#endif /* WIGDET_DOWNLOAD_DEM_H_ */
-
diff --git a/src/gui/WidgetDownloadDEM.ui b/src/gui/WidgetDownloadDEM.ui
deleted file mode 100644
index b8ff6a70f..000000000
--- a/src/gui/WidgetDownloadDEM.ui
+++ /dev/null
@@ -1,177 +0,0 @@
-
-
- WidgetDownloadDEM
-
-
-
- 0
- 0
- 820
- 674
-
-
-
- Download elevation file
-
-
-
- :/wn-icon.png :/wn-icon.png
-
-
- -
-
- -
-
-
-
- 0
- 0
-
-
-
- OpenHandCursor
-
-
-
- about:blank
-
-
-
- QPainter::SmoothPixmapTransform|QPainter::TextAntialiasing
-
-
-
-
-
- -
-
- -
-
-
- Data Source
-
-
-
- -
-
-
-
- 0
- 0
-
-
-
-
- 135
- 20
-
-
-
-
- 135
- 20
-
-
-
-
- 8
- 50
- false
-
-
-
- 0
-
-
- 10
-
-
- QComboBox::AdjustToContentsOnFirstShow
-
- -
-
- WORLD SRTM (30m)
-
-
- -
-
- WORLD GMTED (250m)
-
-
- -
-
- Landscape File
-
-
-
-
- -
-
-
-
- 10
- 50
- false
-
-
-
- Download the elevation file.
-
-
- Qt::LeftToRight
-
-
- Download File
-
-
-
- :/server_go.png
-
-
-
- Qt::ToolButtonTextBesideIcon
-
-
-
- -
-
-
- Qt::Horizontal
-
-
-
- 40
- 20
-
-
-
-
-
-
- -
-
-
- <html><head/><body><p>Map data © <a href="https://www.openstreetmap.org/"><span style=" text-decoration: underline; color:#0000ff;">OpenStreetMap </span></a><a href="https://creativecommons.org/licenses/by-sa/2.0/"><span style=" text-decoration: underline; color:#0000ff;">CC-BY-SA</span></a><a href="https://www.openstreetmap.org/"><span style=" text-decoration: underline; color:#0000ff;">, Imagery © </span></a><a href="https://www.mapbox.com/"><span style=" text-decoration: underline; color:#0000ff;">Mapbox</span></a><a href="https://www.openstreetmap.org/"><span style=" text-decoration: underline; color:#0000ff;"></span></a></p></body></html>
-
-
- Qt::TextBrowserInteraction
-
-
-
-
-
-
-
- QWebView
- QWidget
-
-
-
-
-
-
-
-
- slot1()
-
-
diff --git a/src/gui/WindNinjaTree.cpp b/src/gui/WindNinjaTree.cpp
deleted file mode 100644
index 61597e1e0..000000000
--- a/src/gui/WindNinjaTree.cpp
+++ /dev/null
@@ -1,294 +0,0 @@
-/******************************************************************************
- *
- * $Id$
- *
- * Project: WindNinja Qt GUI
- * Purpose: Tree display for selecting input/output widgets.
- * Author: Kyle Shannon
- *
- ******************************************************************************
- *
- * THIS SOFTWARE WAS DEVELOPED AT THE ROCKY MOUNTAIN RESEARCH STATION (RMRS)
- * MISSOULA FIRE SCIENCES LABORATORY BY EMPLOYEES OF THE FEDERAL GOVERNMENT
- * IN THE COURSE OF THEIR OFFICIAL DUTIES. PURSUANT TO TITLE 17 SECTION 105
- * OF THE UNITED STATES CODE, THIS SOFTWARE IS NOT SUBJECT TO COPYRIGHT
- * PROTECTION AND IS IN THE PUBLIC DOMAIN. RMRS MISSOULA FIRE SCIENCES
- * LABORATORY ASSUMES NO RESPONSIBILITY WHATSOEVER FOR ITS USE BY OTHER
- * PARTIES, AND MAKES NO GUARANTEES, EXPRESSED OR IMPLIED, ABOUT ITS QUALITY,
- * RELIABILITY, OR ANY OTHER CHARACTERISTIC.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *
- *****************************************************************************/
-
-#include "WindNinjaTree.h"
-
-WindNinjaTree::WindNinjaTree(QWidget *parent) : QWidget(parent)
-{
- createTree();
- createStack();
- createConnections();
-
- layout = new QVBoxLayout;
- layout->addWidget(tree);
- layout->addWidget(stack);
- setLayout(layout);
-
-}
-
-WindNinjaTree::~WindNinjaTree()
-{
-
-}
-
-void WindNinjaTree::createTree()
-{
- createIcons();
- tree = new QTreeWidget;
- tree->setColumnCount(1);
- createInputItems();
-#ifdef NINJAFOAM
- createSolverMethodItems();
-#endif
- createOutputItems();
-
- mainItem = new QTreeWidgetItem;
- mainItem->setText(0, tr("WindNinja"));
-
- solveItem = new QTreeWidgetItem;
- solveItem->setText(0, tr("Solve"));
- solveItem->setIcon(0, blue);
-
- //add items in gui order
- tree->setHeaderItem(mainItem);
-#ifdef NINJAFOAM
- tree->addTopLevelItem(solverMethodItem);
- solverMethodItem->setExpanded(true);
- solverMethodItem->setSelected(true);
-#endif
- tree->addTopLevelItem(inputItem);
- inputItem->setExpanded(true);
-#ifndef NINJAFOAM
- surfaceItem->setSelected(true);
-#endif
- windItem->setExpanded(true);
- tree->addTopLevelItem(diurnalItem);
- tree->addTopLevelItem(stabilityItem);
- tree->addTopLevelItem(outputItem);
- outputItem->setExpanded(true);
- tree->addTopLevelItem(solveItem);
- solveItem->setExpanded(true);
-
- tree->setMinimumHeight(240);
- //tree->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed);
-}
-
-void WindNinjaTree::createIcons()
-{
- check.addFile(":tick.png");
- cross.addFile(":cross.png");
- caution.addFile(":jason_caution.png");
- blue.addFile(":bullet_blue.png");
- radio.addFile(":radio_bullet_blue.png");
- sun.addFile(":weather_sun.png");
-}
-
-#ifdef NINJAFOAM
-void WindNinjaTree::createSolverMethodItems()
-{
- solverMethodItem = new QTreeWidgetItem;
- solverMethodItem->setIcon(0, blue);
- solverMethodItem->setText(0, tr("Solver"));
-
- nativeSolverItem = new QTreeWidgetItem;
- nativeSolverItem->setText(0, tr("Conservation of Mass"));
- nativeSolverItem->setIcon(0, radio);
-
- solverMethodItem->addChild(nativeSolverItem);
-
- ninjafoamItem = new QTreeWidgetItem;
- ninjafoamItem->setText(0, tr("Conservation of Mass and Momentum"));
- ninjafoamItem->setIcon(0, radio);
-
- solverMethodItem->addChild(ninjafoamItem);
-}
-#endif //NINJAFOAM
-
-void WindNinjaTree::createInputItems()
-{
- inputItem = new QTreeWidgetItem;
- inputItem->setIcon(0, blue);
- inputItem->setText(0, tr("Input"));
-
- //create input children, add them to input item
- //surfaceItem
- surfaceItem = new QTreeWidgetItem;
- surfaceItem->setText(0, tr("Surface Input"));
- surfaceItem->setIcon(0, blue);
-
- diurnalItem = new QTreeWidgetItem;
- diurnalItem->setText(0, tr("Diurnal Input"));
- diurnalItem->setIcon(0, blue);
-
- stabilityItem = new QTreeWidgetItem;
- stabilityItem->setText(0, tr("Stability Input"));
- stabilityItem->setIcon(0, blue);
-
- windItem = new QTreeWidgetItem;
- windItem->setText(0, tr("Wind Input"));
- windItem->setIcon(0, blue);
-
- spdDirItem = new QTreeWidgetItem;
- spdDirItem->setText(0, tr("Domain Average Wind"));
- spdDirItem->setIcon(0, radio);
-
- pointItem = new QTreeWidgetItem;
- pointItem->setText(0, tr("Point Initialization"));
- pointItem->setIcon(0, radio);
-
- modelItem = new QTreeWidgetItem;
- modelItem->setText(0, tr("Weather Model"));
- modelItem->setIcon(0, radio);
-
- windItem->addChild(spdDirItem);
- windItem->addChild(pointItem);
- windItem->addChild(modelItem);
-
- inputItem->addChild(surfaceItem);
- inputItem->addChild(diurnalItem);
- inputItem->addChild(stabilityItem);
- inputItem->addChild(windItem);
-}
-
-void WindNinjaTree::createOutputItems()
-{
- outputItem = new QTreeWidgetItem;
- outputItem->setText(0, tr("Output"));
- outputItem->setIcon(0, blue);
-
- googleItem = new QTreeWidgetItem;
- googleItem->setText(0, tr("Google Earth"));
- googleItem->setIcon(0, blue);
- fbItem = new QTreeWidgetItem;
- fbItem->setText(0, tr("Fire Behavior"));
- fbItem->setIcon(0, blue);
- shapeItem = new QTreeWidgetItem;
- shapeItem->setText(0, tr("Shape Files"));
- shapeItem->setIcon(0, blue);
- pdfItem = new QTreeWidgetItem;
- pdfItem->setText(0, tr("Geospatial PDF Files"));
- pdfItem->setIcon(0, blue);
- vtkItem = new QTreeWidgetItem;
- vtkItem->setText(0, tr("VTK Files"));
- vtkItem->setIcon(0, blue);
-
- outputItem->addChild(googleItem);
- outputItem->addChild(fbItem);
- outputItem->addChild(shapeItem);
- outputItem->addChild(pdfItem);
- outputItem->addChild(vtkItem);
-
-}
-
-void WindNinjaTree::createStack()
-{
-#ifdef NINJAFOAM
- ninjafoam = new ninjafoamInput;
- nativesolver = new nativeSolverInput;
-#endif
- surface = new surfaceInput;
- diurnal = new diurnalInput;
- stability = new stabilityInput;
-
- wind = new windInput;
- point = new pointInput;
- weather = new weatherModel;
- output = new outputMetaData;
- google = new googleOutput;
- fb = new fbOutput;
- shape = new shapeOutput;
- pdf = new pdfOutput(this);
- vtk = new vtkOutput;
- solve = new solvePage;
-
- stack = new QStackedWidget;
-
-#ifdef NINJAFOAM
- stack->addWidget(nativesolver);
- stack->addWidget(ninjafoam);
-#endif
- stack->addWidget(surface);
- stack->addWidget(diurnal);
- stack->addWidget(stability);
-
- stack->addWidget(wind);
- stack->addWidget(point);
- stack->addWidget(weather);
- stack->addWidget(output);
- stack->addWidget(google);
- stack->addWidget(fb);
- stack->addWidget(shape);
- stack->addWidget(pdf);
- stack->addWidget(vtk);
- stack->addWidget(solve);
-
- stack->setMinimumWidth(480);
-}
-
-void WindNinjaTree::createConnections()
-{
- connect(tree, SIGNAL(itemSelectionChanged()), this,
- SLOT(updateInterface()));
-}
-
-void WindNinjaTree::updateInterface()
-{
- QTreeWidgetItem *item;
- item = tree->currentItem();
- //figure out which item is selected, then change the stack widget to the proper
- //input page
- if(item == inputItem)
- stack->setCurrentWidget(surface);
- else if(item == surfaceItem)
- stack->setCurrentWidget(surface);
- else if(item == diurnalItem)
- stack->setCurrentWidget(diurnal);
- else if(item == stabilityItem)
- stack->setCurrentWidget(stability);
-#ifdef NINJAFOAM
- else if(item == nativeSolverItem)
- stack->setCurrentWidget(nativesolver);
- else if(item == ninjafoamItem)
- stack->setCurrentWidget(ninjafoam);
- else if(item == solverMethodItem)
- stack->setCurrentWidget(ninjafoam);
-#endif
- else if(item == windItem)
- stack->setCurrentWidget(wind);
- else if(item == spdDirItem)
- stack->setCurrentWidget(wind);
- else if(item == pointItem)
- stack->setCurrentWidget(point);
- else if(item == modelItem)
- stack->setCurrentWidget(weather);
- else if(item == outputItem)
- stack->setCurrentWidget(output);
- else if(item == googleItem)
- stack->setCurrentWidget(google);
- else if(item == fbItem)
- stack->setCurrentWidget(fb);
- else if(item == shapeItem)
- stack->setCurrentWidget(shape);
- else if(item == pdfItem)
- stack->setCurrentWidget(pdf);
- else if(item == vtkItem)
- stack->setCurrentWidget(vtk);
- else if(item == solveItem)
- stack->setCurrentWidget(solve);
-}
diff --git a/src/gui/WindNinjaTree.h b/src/gui/WindNinjaTree.h
deleted file mode 100644
index d120639e5..000000000
--- a/src/gui/WindNinjaTree.h
+++ /dev/null
@@ -1,139 +0,0 @@
-/******************************************************************************
- *
- * $Id$
- *
- * Project: WindNinja Qt GUI
- * Purpose: Tree display for selecting input/output widgets.
- * Author: Kyle Shannon
- *
- ******************************************************************************
- *
- * THIS SOFTWARE WAS DEVELOPED AT THE ROCKY MOUNTAIN RESEARCH STATION (RMRS)
- * MISSOULA FIRE SCIENCES LABORATORY BY EMPLOYEES OF THE FEDERAL GOVERNMENT
- * IN THE COURSE OF THEIR OFFICIAL DUTIES. PURSUANT TO TITLE 17 SECTION 105
- * OF THE UNITED STATES CODE, THIS SOFTWARE IS NOT SUBJECT TO COPYRIGHT
- * PROTECTION AND IS IN THE PUBLIC DOMAIN. RMRS MISSOULA FIRE SCIENCES
- * LABORATORY ASSUMES NO RESPONSIBILITY WHATSOEVER FOR ITS USE BY OTHER
- * PARTIES, AND MAKES NO GUARANTEES, EXPRESSED OR IMPLIED, ABOUT ITS QUALITY,
- * RELIABILITY, OR ANY OTHER CHARACTERISTIC.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *
- *****************************************************************************/
-
-#ifndef WINDNINJATREE_H
-#define WINDNINJATREE_H
-
-#include
-#include
-#include
-#include
-
-#include "surfaceInput.h"
-#include "diurnalInput.h"
-
-#include "stabilityInput.h"
-
-#ifdef NINJAFOAM
-#include "ninjafoamInput.h"
-#include "nativeSolverInput.h"
-#endif
-
-#include "windInput.h"
-#include "pointInput.h"
-#include "weatherModel.h"
-#include "outputMetaData.h"
-#include "googleOutput.h"
-#include "fbOutput.h"
-#include "shapeOutput.h"
-#include "pdfOutput.h"
-#include "vtkOutput.h"
-#include "solvePage.h"
-
-class WindNinjaTree : public QWidget
-{
- Q_OBJECT
-
- public:
-
- WindNinjaTree(QWidget *parent = 0);
- ~WindNinjaTree();
- //icons
- QIcon check, cross, caution, blue, radio, sun;
- //tree for navigating
- QTreeWidget *tree;
-
- QSplitter *splitter;
- //items
- QTreeWidgetItem *mainItem;
- QTreeWidgetItem *solverMethodItem;
- QTreeWidgetItem *inputItem;
- QTreeWidgetItem *surfaceItem;
-
- //make widgetItem for variable stuff...
- QTreeWidgetItem *windItem;
- QTreeWidgetItem *spdDirItem;
- QTreeWidgetItem *pointItem;
- QTreeWidgetItem *modelItem;
- QTreeWidgetItem *diurnalItem;
- QTreeWidgetItem *stabilityItem;
-#ifdef NINJAFOAM
- QTreeWidgetItem *ninjafoamItem;
- QTreeWidgetItem *nativeSolverItem;
-#endif
-
- //output file items...
- QTreeWidgetItem *outputItem;
- QTreeWidgetItem *googleItem;
- QTreeWidgetItem *fbItem;
- QTreeWidgetItem *shapeItem;
- QTreeWidgetItem *pdfItem;
- QTreeWidgetItem *vtkItem;
-
- QTreeWidgetItem *solveItem;
-
- void createTree();
- void createIcons();
- void createInputItems();
- void createSolverMethodItems();
- void createOutputItems();
- void createStack();
- void createConnections();
-
- //add stack widget to hold the ui widgets
-
- QStackedWidget *stack;
-
- surfaceInput *surface;
- diurnalInput *diurnal;
- stabilityInput *stability;
-#ifdef NINJAFOAM
- ninjafoamInput *ninjafoam;
- nativeSolverInput *nativesolver;
-#endif
- windInput *wind;
- pointInput *point;
- weatherModel *weather;
- outputMetaData *output;
- googleOutput *google;
- fbOutput *fb;
- shapeOutput *shape;
- pdfOutput *pdf;
- vtkOutput *vtk;
- solvePage *solve;
-
- //layout the whole thing
- QVBoxLayout *layout;
-
- public slots:
- void updateInterface();
-
-};
-
-#endif /* WINDNINJATREE_H */
diff --git a/src/gui/consoleDockWidget.cpp b/src/gui/consoleDockWidget.cpp
deleted file mode 100644
index 32dde1eb4..000000000
--- a/src/gui/consoleDockWidget.cpp
+++ /dev/null
@@ -1,79 +0,0 @@
-/******************************************************************************
- *
- * $Id$
- *
- * Project: WindNinja Qt GUI
- * Purpose: Console output window
- * Author: Kyle Shannon
- *
- ******************************************************************************
- *
- * THIS SOFTWARE WAS DEVELOPED AT THE ROCKY MOUNTAIN RESEARCH STATION (RMRS)
- * MISSOULA FIRE SCIENCES LABORATORY BY EMPLOYEES OF THE FEDERAL GOVERNMENT
- * IN THE COURSE OF THEIR OFFICIAL DUTIES. PURSUANT TO TITLE 17 SECTION 105
- * OF THE UNITED STATES CODE, THIS SOFTWARE IS NOT SUBJECT TO COPYRIGHT
- * PROTECTION AND IS IN THE PUBLIC DOMAIN. RMRS MISSOULA FIRE SCIENCES
- * LABORATORY ASSUMES NO RESPONSIBILITY WHATSOEVER FOR ITS USE BY OTHER
- * PARTIES, AND MAKES NO GUARANTEES, EXPRESSED OR IMPLIED, ABOUT ITS QUALITY,
- * RELIABILITY, OR ANY OTHER CHARACTERISTIC.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *
- *****************************************************************************/
-
-#include "consoleDockWidget.h"
-
-/**
- * \brief Construct a default console
- *
- * Set the docking options and default text edit options.
- *
- * \param parent Parent of the new widget
- */
-ConsoleDockWidget::ConsoleDockWidget(QWidget *parent) : QDockWidget(parent)
-{
- setWindowTitle(tr("Console Output"));
- consoleTextEdit = new QTextEdit(this);
- consoleTextEdit->setDocumentTitle(tr("Console Output"));
- consoleTextEdit->setMaximumHeight(80);
- consoleTextEdit->setMinimumWidth(480);
- consoleTextEdit->setSizePolicy(QSizePolicy::Preferred,
- QSizePolicy::Maximum);
- setAllowedAreas(Qt::BottomDockWidgetArea | Qt::RightDockWidgetArea |
- Qt::NoDockWidgetArea);
-
- //connect dockAreaChanged and checkSize()
- connect(this, SIGNAL(topLevelChanged(bool)), this, SLOT(checkSize(bool)));
-
- setWidget(consoleTextEdit);
-}
-
-/**
- * \briefChange the allowable size of the widget if it is floating
- *
- * \param float status
- */
-void ConsoleDockWidget::checkSize(bool floating)
-{
- if(!floating)
- {
- consoleTextEdit->setMaximumHeight(80);
- consoleTextEdit->setMinimumWidth(480);
- consoleTextEdit->setSizePolicy(QSizePolicy::Preferred,
- QSizePolicy::Maximum);
- }
- else
- {
- consoleTextEdit->setMaximumHeight(720);
- consoleTextEdit->setMinimumWidth(480);
- consoleTextEdit->setSizePolicy(QSizePolicy::Preferred,
- QSizePolicy::Preferred);
- }
-}
-
diff --git a/src/gui/consoleDockWidget.h b/src/gui/consoleDockWidget.h
deleted file mode 100644
index d71a4ffc2..000000000
--- a/src/gui/consoleDockWidget.h
+++ /dev/null
@@ -1,63 +0,0 @@
-/******************************************************************************
- *
- * $Id$
- *
- * Project: WindNinja Qt GUI
- * Purpose: Console output window
- * Author: Kyle Shannon
- *
- ******************************************************************************
- *
- * THIS SOFTWARE WAS DEVELOPED AT THE ROCKY MOUNTAIN RESEARCH STATION (RMRS)
- * MISSOULA FIRE SCIENCES LABORATORY BY EMPLOYEES OF THE FEDERAL GOVERNMENT
- * IN THE COURSE OF THEIR OFFICIAL DUTIES. PURSUANT TO TITLE 17 SECTION 105
- * OF THE UNITED STATES CODE, THIS SOFTWARE IS NOT SUBJECT TO COPYRIGHT
- * PROTECTION AND IS IN THE PUBLIC DOMAIN. RMRS MISSOULA FIRE SCIENCES
- * LABORATORY ASSUMES NO RESPONSIBILITY WHATSOEVER FOR ITS USE BY OTHER
- * PARTIES, AND MAKES NO GUARANTEES, EXPRESSED OR IMPLIED, ABOUT ITS QUALITY,
- * RELIABILITY, OR ANY OTHER CHARACTERISTIC.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *
- *****************************************************************************/
-
-#ifndef CONSOLEDOCKWIDGET_H_
-#define CONSOLEDOCKWIDGET_H_
-
-#include
-#include
-#include
-
-/**
- * \brief Console for the GUI
- *
- * Provides a method of transferring information to the user
- * that may not be in need of alerts such as dialogs. Can
- * be useful for debugging.
- */
-class ConsoleDockWidget : public QDockWidget
-{
-
- Q_OBJECT
-
- public:
- ConsoleDockWidget(QWidget *parent = 0);
-
- QString prompt; /*!< Characters that act as a prompt */
-
- QTextEdit *consoleTextEdit; /*!< Holds the edit area */
- QAction *editPromptAction; /*!< Change the prompt */
- QMenu *contextMenu; /*!< Allow the user to print console */
-
- public slots:
- void checkSize(bool floating);
-};
-
-#endif /* CONSOLEDOCKWIDGET_H_ */
-
diff --git a/src/gui/diurnalInput.cpp b/src/gui/diurnalInput.cpp
deleted file mode 100644
index 5b91156b2..000000000
--- a/src/gui/diurnalInput.cpp
+++ /dev/null
@@ -1,53 +0,0 @@
-/******************************************************************************
- *
- * $Id$
- *
- * Project: WindNinja Qt GUI
- * Purpose: OpenGL implementation for viewing DEM inputs
- * Author: Kyle Shannon
- *
- ******************************************************************************
- *
- * THIS SOFTWARE WAS DEVELOPED AT THE ROCKY MOUNTAIN RESEARCH STATION (RMRS)
- * MISSOULA FIRE SCIENCES LABORATORY BY EMPLOYEES OF THE FEDERAL GOVERNMENT
- * IN THE COURSE OF THEIR OFFICIAL DUTIES. PURSUANT TO TITLE 17 SECTION 105
- * OF THE UNITED STATES CODE, THIS SOFTWARE IS NOT SUBJECT TO COPYRIGHT
- * PROTECTION AND IS IN THE PUBLIC DOMAIN. RMRS MISSOULA FIRE SCIENCES
- * LABORATORY ASSUMES NO RESPONSIBILITY WHATSOEVER FOR ITS USE BY OTHER
- * PARTIES, AND MAKES NO GUARANTEES, EXPRESSED OR IMPLIED, ABOUT ITS QUALITY,
- * RELIABILITY, OR ANY OTHER CHARACTERISTIC.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *
- *****************************************************************************/
-
-#include "diurnalInput.h"
-
-/**
- * \brief Construct and layout the diurnalInput widget.
- *
- * This is only a checkable option now.
- *
- * \param parent parent widget
- */
-diurnalInput::diurnalInput(QWidget *parent) : QWidget(parent)
-{
- diurnalGroupBox = new QGroupBox(tr("Use Diurnal Wind"));
- diurnalGroupBox->setCheckable(true);
- diurnalGroupBox->setChecked(false);
- diurnalLayout = new QVBoxLayout;
-
- diurnalGroupBox->setLayout(diurnalLayout);
-
- layout = new QVBoxLayout;
- layout->addWidget(diurnalGroupBox);
- layout->addStretch();
- setLayout(layout);
-}
-
diff --git a/src/gui/diurnalInput.h b/src/gui/diurnalInput.h
deleted file mode 100644
index d805b4386..000000000
--- a/src/gui/diurnalInput.h
+++ /dev/null
@@ -1,72 +0,0 @@
-/******************************************************************************
- *
- * $Id$
- *
- * Project: WindNinja Qt GUI
- * Purpose: OpenGL implementation for viewing DEM inputs
- * Author: Kyle Shannon
- *
- ******************************************************************************
- *
- * THIS SOFTWARE WAS DEVELOPED AT THE ROCKY MOUNTAIN RESEARCH STATION (RMRS)
- * MISSOULA FIRE SCIENCES LABORATORY BY EMPLOYEES OF THE FEDERAL GOVERNMENT
- * IN THE COURSE OF THEIR OFFICIAL DUTIES. PURSUANT TO TITLE 17 SECTION 105
- * OF THE UNITED STATES CODE, THIS SOFTWARE IS NOT SUBJECT TO COPYRIGHT
- * PROTECTION AND IS IN THE PUBLIC DOMAIN. RMRS MISSOULA FIRE SCIENCES
- * LABORATORY ASSUMES NO RESPONSIBILITY WHATSOEVER FOR ITS USE BY OTHER
- * PARTIES, AND MAKES NO GUARANTEES, EXPRESSED OR IMPLIED, ABOUT ITS QUALITY,
- * RELIABILITY, OR ANY OTHER CHARACTERISTIC.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *
- *****************************************************************************/
-
-#ifndef DIURNALINPUT_H_
-#define DIURNALINPUT_H_
-
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-
-#include
-#include
-
-#include "gdal_priv.h"
-#include "ogr_srs_api.h"
-
-#ifndef Q_MOC_RUN
-#include "boost/date_time/local_time/local_time.hpp"
-#include "boost/date_time/posix_time/posix_time_types.hpp"
-#endif
-
-#include "latLonWidget.h"
-#include "timeZoneWidget.h"
-
-#include "qdebug.h"
-
-class diurnalInput : public QWidget
-{
- Q_OBJECT
-
- public:
-
- diurnalInput(QWidget *parent = 0);
- QGroupBox *diurnalGroupBox;
- QVBoxLayout *diurnalLayout;
- QVBoxLayout *layout;
-
-};
-
-#endif /* DIURNALINPUT_H_ */
-
diff --git a/src/gui/fbOutput.cpp b/src/gui/fbOutput.cpp
deleted file mode 100644
index fab279833..000000000
--- a/src/gui/fbOutput.cpp
+++ /dev/null
@@ -1,91 +0,0 @@
-/******************************************************************************
- *
- * $Id$
- *
- * Project: WindNinja Qt GUI
- * Purpose: Fire behavior output selection widget
- * Author: Kyle Shannon
- *
- ******************************************************************************
- *
- * THIS SOFTWARE WAS DEVELOPED AT THE ROCKY MOUNTAIN RESEARCH STATION (RMRS)
- * MISSOULA FIRE SCIENCES LABORATORY BY EMPLOYEES OF THE FEDERAL GOVERNMENT
- * IN THE COURSE OF THEIR OFFICIAL DUTIES. PURSUANT TO TITLE 17 SECTION 105
- * OF THE UNITED STATES CODE, THIS SOFTWARE IS NOT SUBJECT TO COPYRIGHT
- * PROTECTION AND IS IN THE PUBLIC DOMAIN. RMRS MISSOULA FIRE SCIENCES
- * LABORATORY ASSUMES NO RESPONSIBILITY WHATSOEVER FOR ITS USE BY OTHER
- * PARTIES, AND MAKES NO GUARANTEES, EXPRESSED OR IMPLIED, ABOUT ITS QUALITY,
- * RELIABILITY, OR ANY OTHER CHARACTERISTIC.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *
- *****************************************************************************/
-
-#include "fbOutput.h"
-
-/**
- * \brief Create the widget for fire behavior outputs.
- *
- * \param parent parent widget
- */
-fbOutput::fbOutput(QWidget *parent) : QWidget(parent)
-{
- fbGroupBox = new QGroupBox(tr("Create Fire Behavior Files (*.asc)"), this);
- fbGroupBox->setCheckable(true);
- fbGroupBox->setChecked(false);
-
- fbResGroupBox = new QGroupBox(tr("Resolution"), this);
-
- fbResSpinBox = new QDoubleSpinBox(this);
- fbResSpinBox->setRange(1, 5000);
- fbResSpinBox->setDecimals(2);
- fbResSpinBox->setAccelerated(true);
- fbResSpinBox->setValue(200);
- fbResSpinBox->setDisabled(true);
-
- fbMetersRadioButton = new QRadioButton(tr("Meters"), this);
- fbMetersRadioButton->setChecked(true);
- fbMetersRadioButton->setDisabled(true);
- fbFeetRadioButton = new QRadioButton(tr("Feet"));
- fbFeetRadioButton->setDisabled(true);
-
- useMeshResCheckBox = new QCheckBox(tr("Use Mesh Resolution"), this);
- useMeshResCheckBox->setChecked(true);
-
- atmFileCheckBox = new QCheckBox(tr("Create *.atm file(s)"),this);
-
- //connect spinbox and checkbox
- connect(useMeshResCheckBox, SIGNAL(toggled(bool)),
- fbResSpinBox, SLOT(setDisabled(bool)));
- connect(useMeshResCheckBox, SIGNAL(toggled(bool)),
- fbMetersRadioButton, SLOT(setDisabled(bool)));
- connect(useMeshResCheckBox, SIGNAL(toggled(bool)),
- fbFeetRadioButton, SLOT(setDisabled(bool)));
-
- fbResLayout = new QGridLayout;
- fbResLayout->addWidget(fbResSpinBox, 0, 0);
- fbResLayout->addWidget(fbMetersRadioButton, 0, 1);
- fbResLayout->addWidget(fbFeetRadioButton, 0, 2);
- fbResLayout->addWidget(useMeshResCheckBox, 1, 0);
-
- fbResGroupBox->setLayout(fbResLayout);
-
- fbLayout = new QVBoxLayout;
- fbLayout->addWidget(fbResGroupBox);
- fbLayout->addWidget(atmFileCheckBox);
-
- fbGroupBox->setLayout(fbLayout);
-
- mainLayout = new QVBoxLayout;
- mainLayout->addWidget(fbGroupBox);
- mainLayout->addStretch();
-
- setLayout(mainLayout);
-}
-
diff --git a/src/gui/fbOutput.h b/src/gui/fbOutput.h
deleted file mode 100644
index 516908524..000000000
--- a/src/gui/fbOutput.h
+++ /dev/null
@@ -1,63 +0,0 @@
-/******************************************************************************
- *
- * $Id$
- *
- * Project: WindNinja Qt GUI
- * Purpose: Fire behavior output selection widget
- * Author: Kyle Shannon
- *
- ******************************************************************************
- *
- * THIS SOFTWARE WAS DEVELOPED AT THE ROCKY MOUNTAIN RESEARCH STATION (RMRS)
- * MISSOULA FIRE SCIENCES LABORATORY BY EMPLOYEES OF THE FEDERAL GOVERNMENT
- * IN THE COURSE OF THEIR OFFICIAL DUTIES. PURSUANT TO TITLE 17 SECTION 105
- * OF THE UNITED STATES CODE, THIS SOFTWARE IS NOT SUBJECT TO COPYRIGHT
- * PROTECTION AND IS IN THE PUBLIC DOMAIN. RMRS MISSOULA FIRE SCIENCES
- * LABORATORY ASSUMES NO RESPONSIBILITY WHATSOEVER FOR ITS USE BY OTHER
- * PARTIES, AND MAKES NO GUARANTEES, EXPRESSED OR IMPLIED, ABOUT ITS QUALITY,
- * RELIABILITY, OR ANY OTHER CHARACTERISTIC.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *
- *****************************************************************************/
-
-#ifndef FBOUTPUT_H_
-#define FBOUTPUT_H_
-
-#include
-#include
-#include
-#include
-
-#include
-
-#include "WindNinjaInputs.h"
-
-class fbOutput : public QWidget
-{
- Q_OBJECT
-
-public:
- fbOutput(QWidget *parent = 0);
-
- QGroupBox *fbGroupBox;
- QGroupBox *fbResGroupBox;
- QDoubleSpinBox *fbResSpinBox;
- QRadioButton *fbMetersRadioButton, *fbFeetRadioButton;
- QCheckBox *useMeshResCheckBox;
-
- QCheckBox *atmFileCheckBox;
-
- QGridLayout *fbResLayout;
- QVBoxLayout *fbLayout;
- QVBoxLayout *mainLayout;
-};
-
-#endif /* FBOUTPUT_H_ */
-
diff --git a/src/gui/googleOutput.cpp b/src/gui/googleOutput.cpp
deleted file mode 100644
index 78d2b33d4..000000000
--- a/src/gui/googleOutput.cpp
+++ /dev/null
@@ -1,174 +0,0 @@
-/******************************************************************************
- *
- * $Id$
- *
- * Project: WindNinja Qt GUI
- * Purpose: Google earth output selection widgetx
- * Author: Kyle Shannon
- *
- ******************************************************************************
- *
- * THIS SOFTWARE WAS DEVELOPED AT THE ROCKY MOUNTAIN RESEARCH STATION (RMRS)
- * MISSOULA FIRE SCIENCES LABORATORY BY EMPLOYEES OF THE FEDERAL GOVERNMENT
- * IN THE COURSE OF THEIR OFFICIAL DUTIES. PURSUANT TO TITLE 17 SECTION 105
- * OF THE UNITED STATES CODE, THIS SOFTWARE IS NOT SUBJECT TO COPYRIGHT
- * PROTECTION AND IS IN THE PUBLIC DOMAIN. RMRS MISSOULA FIRE SCIENCES
- * LABORATORY ASSUMES NO RESPONSIBILITY WHATSOEVER FOR ITS USE BY OTHER
- * PARTIES, AND MAKES NO GUARANTEES, EXPRESSED OR IMPLIED, ABOUT ITS QUALITY,
- * RELIABILITY, OR ANY OTHER CHARACTERISTIC.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *
- *****************************************************************************/
-
-#include "googleOutput.h"
-
-googleOutput::googleOutput(QWidget *parent) : QWidget(parent)
-{
- googleGroupBox = new QGroupBox(tr("Create Google Earth Files (*.kmz)"));
- googleGroupBox->setCheckable(true);
- googleGroupBox->setChecked(false);
-
- vectorGroupBox = new QGroupBox(tr("Vectors"));
- //vectorGroupBox->setCheckable(true);
- //vectorGroupBox->setChecked(true);
-
- vectorWidthLabel = new QLabel(tr("Line Width"));
-
- vectorWidthDoubleSpinBox = new QDoubleSpinBox;
- vectorWidthDoubleSpinBox->setRange(1.0, 10.0);
- vectorWidthDoubleSpinBox->setDecimals(1);
- vectorWidthDoubleSpinBox->setValue(1.0);
- vectorWidthDoubleSpinBox->setSingleStep(0.1);
- vectorWidthDoubleSpinBox->setAccelerated(true);
-
- applyVectorScaling = new QCheckBox("Apply Vector Scaling");
- applyVectorScaling->setToolTip("Enable vector scaling to increase line width with wind speed.");
- applyVectorScaling->setCheckable(true);
- applyVectorScaling->setChecked(false);
-
- vectorLayout = new QHBoxLayout;
- vectorLayout->addWidget(vectorWidthLabel);
- vectorLayout->addWidget(vectorWidthDoubleSpinBox);
- vectorLayout->addWidget(applyVectorScaling);
- vectorLayout->addStretch();
-
- vectorGroupBox->setLayout(vectorLayout);
-
- legendGroupBox = new QGroupBox(tr("Legend"));
- //legendGroupBox->setCheckable(true);
- //legendGroupBox->setChecked(true);
-
- uniformRangeRadioButton = new QRadioButton;
- uniformRangeRadioButton->setText(tr("Uniform Range"));
- uniformRangeRadioButton->setChecked(true);
- equalCountRadioButton = new QRadioButton;
- equalCountRadioButton->setText(tr("Equal Count"));
-
- legendOptionLayout = new QVBoxLayout;
- legendOptionLayout->addWidget(uniformRangeRadioButton);
- legendOptionLayout->addWidget(equalCountRadioButton);
- // legendOptionLayout->addStretch();
- legendGroupBox->setLayout(legendOptionLayout);
-
- contourCheckBox = new QCheckBox(tr("Contours (beta)"));
-
- contourCheckBox->setChecked(false);
-
- //hide contour check box for now.
- contourCheckBox->setDisabled(true);
-
- applyConsistentColorScale = new QCheckBox(tr("Use Consistent Color Scale"));
- applyConsistentColorScale->setToolTip("Use a consistent color scale across simulations.");
- applyConsistentColorScale->setCheckable(true);
- applyConsistentColorScale->setChecked(false);
-
- optionLayout = new QVBoxLayout;
- optionLayout->addWidget(vectorGroupBox);
- optionLayout->addWidget(legendGroupBox);
- optionLayout->addWidget(applyConsistentColorScale);
- //optionLayout->addWidget(contourCheckBox);
- optionLayout->addStretch();
-
- googleResGroupBox = new QGroupBox(tr("Resolution"));
-
- googleResSpinBox = new QDoubleSpinBox(this);
- googleResSpinBox->setRange(1, 5000);
- googleResSpinBox->setDecimals(2);
- googleResSpinBox->setAccelerated(true);
- googleResSpinBox->setValue(200);
- googleResSpinBox->setDisabled(true);
- //googleResSpinBox->setMaximumSize(googleResSpinBox->sizeHint());
-
- googleMetersRadioButton = new QRadioButton(tr("Meters"));
- googleMetersRadioButton->setChecked(true);
- googleMetersRadioButton->setDisabled(true);
- googleFeetRadioButton = new QRadioButton(tr("Feet"));
- googleFeetRadioButton->setDisabled(true);
-
- useMeshResCheckBox = new QCheckBox(tr("Use Mesh Resolution"));
- useMeshResCheckBox->setChecked(true);
-
- //connect checkbox with spin box
- connect(useMeshResCheckBox, SIGNAL(toggled(bool)),
- googleResSpinBox, SLOT(setDisabled(bool)));
- connect(useMeshResCheckBox, SIGNAL(toggled(bool)),
- googleFeetRadioButton, SLOT(setDisabled(bool)));
- connect(useMeshResCheckBox, SIGNAL(toggled(bool)),
- googleMetersRadioButton, SLOT(setDisabled(bool)));
-
- //color options
- colorblindBox= new QGroupBox(tr("Alternative Color Schemes"));
- colorblindBox->setCheckable(true);
- colorblindBox->setChecked(false);
- inputColorblindComboBox = new QComboBox();
- inputColorblindComboBox->addItem(tr("Default"));
- inputColorblindComboBox->addItem(tr("ROPGW (Red Orange Pink Green White)"));
- inputColorblindComboBox->addItem(tr("Oranges"));
- inputColorblindComboBox->addItem(tr("Blues"));
- inputColorblindComboBox->addItem(tr("Pinks"));
- inputColorblindComboBox->addItem(tr("Greens"));
- inputColorblindComboBox->addItem(tr("Magic Beans"));
- inputColorblindComboBox->addItem(tr("Pink to Green"));
-
- colorLayout=new QGridLayout;
- colorLayout->addWidget(inputColorblindComboBox,0,0);
- colorblindBox->setLayout(colorLayout);
- //end color options
-
- resLayout = new QGridLayout;
- resLayout->addWidget(googleResSpinBox, 0, 0);
- resLayout->addWidget(googleMetersRadioButton, 0, 1);
- resLayout->addWidget(googleFeetRadioButton, 0, 2);
- resLayout->addWidget(useMeshResCheckBox, 1, 0);
-
- googleResGroupBox->setLayout(resLayout);
-
- pageLayout = new QVBoxLayout;
- pageLayout->addLayout(optionLayout);
- pageLayout->addWidget(googleResGroupBox);
- pageLayout->addWidget(colorblindBox);
- pageLayout->addStretch();
-
- googleGroupBox->setLayout(pageLayout);
-
- mainLayout = new QVBoxLayout;
- mainLayout->addWidget(googleGroupBox);
- mainLayout->addStretch();
-
- setLayout(mainLayout);
-}
-
-void googleOutput::setColorScheme(int choice)
-{
- if(choice==1)
- {
-
- }
-}
diff --git a/src/gui/googleOutput.h b/src/gui/googleOutput.h
deleted file mode 100644
index 34ba1ecda..000000000
--- a/src/gui/googleOutput.h
+++ /dev/null
@@ -1,82 +0,0 @@
-/******************************************************************************
- *
- * $Id$
- *
- * Project: WindNinja Qt GUI
- * Purpose: Google earth output selection widgetx
- * Author: Kyle Shannon
- *
- ******************************************************************************
- *
- * THIS SOFTWARE WAS DEVELOPED AT THE ROCKY MOUNTAIN RESEARCH STATION (RMRS)
- * MISSOULA FIRE SCIENCES LABORATORY BY EMPLOYEES OF THE FEDERAL GOVERNMENT
- * IN THE COURSE OF THEIR OFFICIAL DUTIES. PURSUANT TO TITLE 17 SECTION 105
- * OF THE UNITED STATES CODE, THIS SOFTWARE IS NOT SUBJECT TO COPYRIGHT
- * PROTECTION AND IS IN THE PUBLIC DOMAIN. RMRS MISSOULA FIRE SCIENCES
- * LABORATORY ASSUMES NO RESPONSIBILITY WHATSOEVER FOR ITS USE BY OTHER
- * PARTIES, AND MAKES NO GUARANTEES, EXPRESSED OR IMPLIED, ABOUT ITS QUALITY,
- * RELIABILITY, OR ANY OTHER CHARACTERISTIC.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *
- *****************************************************************************/
-
-#ifndef GOOGLEOUTPUT_H
-#define GOOGLEOUTPUT_H
-
-#include
-#include
-#include
-#include
-#include
-#include
-
-#include
-#include
-
-class googleOutput : public QWidget
-{
- Q_OBJECT
-
- public:
- googleOutput(QWidget *parent = 0);
-
- QGroupBox *googleGroupBox;
- QGroupBox *vectorGroupBox;
- QLabel *vectorWidthLabel;
- QDoubleSpinBox *vectorWidthDoubleSpinBox;
- QCheckBox *applyVectorScaling;
- QGroupBox *legendGroupBox;
- QRadioButton *uniformRangeRadioButton,* equalCountRadioButton;
- QCheckBox *applyConsistentColorScale;
- QCheckBox *contourCheckBox;
- QGroupBox *googleResGroupBox;
- QDoubleSpinBox *googleResSpinBox;
- QRadioButton *googleMetersRadioButton, *googleFeetRadioButton;
- QCheckBox *useMeshResCheckBox;
-
- //alternative color Options
- QGroupBox *colorblindBox;
- QComboBox *inputColorblindComboBox;
-
- QGridLayout *colorLayout;
-
- QHBoxLayout *vectorLayout;
- QVBoxLayout *legendOptionLayout;
- QVBoxLayout *optionLayout;
- QGridLayout *resLayout;
- QVBoxLayout *pageLayout;
- QVBoxLayout *mainLayout;
-
- public slots:
- void setColorScheme(int choice);
-
-};
-
-#endif /* GOOGLEOUTPUT_H */
diff --git a/src/gui/latLonWidget.cpp b/src/gui/latLonWidget.cpp
deleted file mode 100644
index 5672790b9..000000000
--- a/src/gui/latLonWidget.cpp
+++ /dev/null
@@ -1,491 +0,0 @@
-/******************************************************************************
- *
- * $Id$
- *
- * Project: WindNinja Qt GUI
- * Purpose: Handle lat/lon dd:mm:ss/dd:mm.mm/dd.dd conversions for diurnal
- * inputs
- * Author: Kyle Shannon
- *
- ******************************************************************************
- *
- * THIS SOFTWARE WAS DEVELOPED AT THE ROCKY MOUNTAIN RESEARCH STATION (RMRS)
- * MISSOULA FIRE SCIENCES LABORATORY BY EMPLOYEES OF THE FEDERAL GOVERNMENT
- * IN THE COURSE OF THEIR OFFICIAL DUTIES. PURSUANT TO TITLE 17 SECTION 105
- * OF THE UNITED STATES CODE, THIS SOFTWARE IS NOT SUBJECT TO COPYRIGHT
- * PROTECTION AND IS IN THE PUBLIC DOMAIN. RMRS MISSOULA FIRE SCIENCES
- * LABORATORY ASSUMES NO RESPONSIBILITY WHATSOEVER FOR ITS USE BY OTHER
- * PARTIES, AND MAKES NO GUARANTEES, EXPRESSED OR IMPLIED, ABOUT ITS QUALITY,
- * RELIABILITY, OR ANY OTHER CHARACTERISTIC.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *
- *****************************************************************************/
-
-#include "latLonWidget.h"
-dmsWidget::dmsWidget( QWidget *parent ) : QWidget( parent )
-{
-
- //latitude
- latGroupBox = new QGroupBox( tr( "Latitude" ), this );
-
- latDegrees = new QSpinBox;
- latDegrees->setRange( -90, 90 );
- latDegrees->setValue( 0 );
- latDegrees->setSuffix( "\x00B0" );
- latDegrees->setAccelerated( true );
-
- latMinutes = new QSpinBox;
- latMinutes->setRange( 0, 60 );
- latMinutes->setValue( 0 );
- latMinutes->setSuffix( "'" );
- latMinutes->setAccelerated( true );
-
- latSeconds = new QDoubleSpinBox;
- latSeconds->setDecimals( 3 );
- latSeconds->setRange( 0, 60 );
- latSeconds->setValue( 0 );
- latSeconds->setSuffix( "\"" );
- latSeconds->setAccelerated( true );
-
- latLayout = new QHBoxLayout;
- latLayout->addWidget( latDegrees );
- latLayout->addWidget( latMinutes );
- latLayout->addWidget( latSeconds );
-
- latGroupBox->setLayout( latLayout );
-
- //longitude
- lonGroupBox = new QGroupBox( tr( "Longitude" ) );
-
- lonDegrees = new QSpinBox;
- lonDegrees->setRange( -180, 180 );
- lonDegrees->setValue( 0 );
- lonDegrees->setSuffix( "\x00B0" );
- lonDegrees->setAccelerated( true );
-
- lonMinutes = new QSpinBox;
- lonMinutes->setRange( 0, 60 );
- lonMinutes->setValue( 0 );
- lonMinutes->setSuffix( "'" );
- lonMinutes->setAccelerated( true );
-
- lonSeconds = new QDoubleSpinBox;
- lonSeconds->setDecimals( 3 );
- lonSeconds->setRange( 0, 60 );
- lonSeconds->setValue( 0 );
- lonSeconds->setSuffix( "\"" );
- lonSeconds->setAccelerated( true );
-
- lonLayout = new QHBoxLayout;
- lonLayout->addWidget( lonDegrees );
- lonLayout->addWidget( lonMinutes );
- lonLayout->addWidget( lonSeconds );
-
- lonGroupBox->setLayout( lonLayout );
-
- layout =new QHBoxLayout;
- layout->addWidget( latGroupBox );
- layout->addWidget( lonGroupBox );
-
- setLayout( layout );
-}
-
-dmWidget::dmWidget( QWidget *parent ) : QWidget( parent )
-{
- //latitude
- latGroupBox = new QGroupBox( tr( "Latitude" ) );
-
- latDegrees = new QSpinBox;
- latDegrees->setRange( -90, 90 );
- latDegrees->setValue( 0 );
- latDegrees->setSuffix( "\x00B0" );
- latDegrees->setAccelerated( true );
-
- latMinutes = new QDoubleSpinBox;
- latMinutes->setDecimals( 5 );
- latMinutes->setRange( 0, 60 );
- latMinutes->setValue( 0 );
- latMinutes->setSuffix( "'" );
- latMinutes->setAccelerated( true );
-
- latLayout = new QHBoxLayout;
- latLayout->addWidget( latDegrees );
- latLayout->addWidget( latMinutes );
-
- latGroupBox->setLayout( latLayout );
-
- //longitude
- lonGroupBox = new QGroupBox( tr( "Longitude" ) );
-
- lonDegrees = new QSpinBox;
- lonDegrees->setRange( -180, 180 );
- lonDegrees->setValue( 0 );
- lonDegrees->setSuffix( "\x00B0" );
- lonDegrees->setAccelerated( true );
-
- lonMinutes = new QDoubleSpinBox;
- lonMinutes->setDecimals( 5 );
- lonMinutes->setRange( 0, 60 );
- lonMinutes->setValue( 0 );
- lonMinutes->setSuffix( "'" );
- lonMinutes->setAccelerated( true );
-
- lonLayout = new QHBoxLayout;
- lonLayout->addWidget( lonDegrees );
- lonLayout->addWidget( lonMinutes );
-
- lonGroupBox->setLayout( lonLayout );
-
- layout = new QHBoxLayout;
- layout->addWidget( latGroupBox );
- layout->addWidget( lonGroupBox );
-
- setLayout( layout );
-}
-
-ddWidget::ddWidget( QWidget *parent ) : QWidget( parent )
-{
- //latitude
- latGroupBox = new QGroupBox( tr( "Latitude" ) );
-
- latDegrees = new QDoubleSpinBox;
- latDegrees->setDecimals( 10 );
- latDegrees->setRange( -90.0, 90.0 );
- latDegrees->setValue( 0 );
- latDegrees->setSuffix( "\x00B0" );
- latDegrees->setAccelerated( true );
-
- latLayout = new QHBoxLayout;
- latLayout->addWidget( latDegrees );
-
- latGroupBox->setLayout( latLayout );
-
- //longitude
- lonGroupBox = new QGroupBox( tr( "Longitude" ) );
-
- lonDegrees = new QDoubleSpinBox;
- lonDegrees->setDecimals( 10 );
- lonDegrees->setRange( -180.0, 180.0 );
- lonDegrees->setValue( 0 );
- lonDegrees->setSuffix( "\x00B0" );
- lonDegrees->setAccelerated( true );
-
- lonLayout = new QHBoxLayout;
- lonLayout->addWidget( lonDegrees );
-
- lonGroupBox->setLayout( lonLayout );
-
- layout = new QHBoxLayout;
- layout->addWidget( latGroupBox );
- layout->addWidget( lonGroupBox );
-
- setLayout( layout );
-}
-
-latLonWidget::latLonWidget( QString title, QWidget *parent ) : QWidget( parent )
-{
- latitude = longitude = 0;
-
- latLonGroupBox = new QGroupBox( title );
-
- latLonFormatGroupBox = new QGroupBox( tr( "Lat/Lon Format" ) );
-
- dmsRadio = new QRadioButton( tr( "DD MM SS.SS" ) );
- dmsRadio->setChecked( true );
- dmRadio = new QRadioButton( tr( "DD MM.MM" ) );
- ddRadio = new QRadioButton( tr( "DD.DD" ) );
-
- stackedWidget = new QStackedWidget( this );
- dms = new dmsWidget;
- dm = new dmWidget;
- dd = new ddWidget;
-
- stackedWidget->addWidget( dms );
- stackedWidget->addWidget( dm );
- stackedWidget->addWidget( dd );
-
- connect( dmsRadio, SIGNAL( toggled( bool ) ),
- this, SLOT( checkLatLonFormat( ) ) );
- connect( dmRadio, SIGNAL( toggled( bool ) ),
- this, SLOT( checkLatLonFormat( ) ) );
- connect( ddRadio, SIGNAL( toggled( bool ) ),
- this, SLOT( checkLatLonFormat( ) ) );
-
- //connect all location spin boxes to the update( ) methods
- //dms lat
- connect( dms->latDegrees, SIGNAL( editingFinished( ) ),
- this, SLOT( updateLatLon( ) ) );
- connect( dms->latMinutes, SIGNAL( editingFinished( ) ),
- this, SLOT( updateLatLon( ) ) );
- connect( dms->latSeconds, SIGNAL( editingFinished( ) ),
- this, SLOT( updateLatLon( ) ) );
- //dms lon
- connect( dms->lonDegrees, SIGNAL( editingFinished( ) ),
- this, SLOT( updateLatLon( ) ) );
- connect( dms->lonMinutes, SIGNAL( editingFinished( ) ),
- this, SLOT( updateLatLon( ) ) );
- connect( dms->lonSeconds, SIGNAL( editingFinished( ) ),
- this, SLOT( updateLatLon( ) ) );
- //dm lat
- connect( dm->latDegrees, SIGNAL( editingFinished( ) ),
- this, SLOT( updateLatLon( ) ) );
- connect( dm->latMinutes, SIGNAL( editingFinished( ) ),
- this, SLOT( updateLatLon( ) ) );
- //dm lon
- connect( dm->lonDegrees, SIGNAL( editingFinished( ) ),
- this, SLOT( updateLatLon( ) ) );
- connect( dm->lonMinutes, SIGNAL( editingFinished( ) ),
- this, SLOT( updateLatLon( ) ) );
-
- //dd lat
- connect( dd->latDegrees, SIGNAL( editingFinished( ) ),
- this, SLOT( updateLatLon( ) ) );
- //dd lon
- connect( dd->lonDegrees, SIGNAL( editingFinished( ) ),
- this, SLOT( updateLatLon( ) ) );
-
- datumComboBox = new QComboBox( this );
- datumComboBox->addItem( "Datum..." );
- datumComboBox->addItem( "WGS84" );
- datumComboBox->addItem( "NAD83" );
- datumComboBox->addItem( "NAD27" );
-
- latLonFormatLayout = new QHBoxLayout;
- latLonFormatLayout->addWidget( dmsRadio );
- latLonFormatLayout->addWidget( dmRadio );
- latLonFormatLayout->addWidget( ddRadio );
-
- latLonFormatGroupBox->setLayout( latLonFormatLayout );
-
- latLonLayout = new QVBoxLayout;
- latLonLayout->addWidget( latLonFormatGroupBox );
- latLonLayout->addWidget( stackedWidget );
- latLonLayout->addWidget( datumComboBox );
- latLonGroupBox->setLayout( latLonLayout );
-
- layout = new QVBoxLayout;
- layout->addWidget( latLonGroupBox );
- setLayout( layout );
-}
-
-void latLonWidget::checkLatLonFormat()
-{
- int index = -1;
- if( dmsRadio->isChecked( ) )
- index = 0;
- else if( dmRadio->isChecked( ) )
- index = 1;
- else if( ddRadio->isChecked( ) )
- index = 2;
- else
- index = 0;
-
- stackedWidget->setCurrentIndex( index );
-}
-
-void latLonWidget::updateLatLon( )
-{
- //check lat/lon format
- if( dmsRadio->isChecked( ) ) {
- latitude = dms2ddLatitude( dms->latDegrees->value( ),
- dms->latMinutes->value( ),
- dms->latSeconds->value( ) );
- longitude = dms2ddLongitude( dms->lonDegrees->value( ),
- dms->lonMinutes->value( ),
- dms->lonSeconds->value( ) );
- updateLatLonWidget( 0 );
- }
- else if( dmRadio->isChecked( ) ) {
- latitude = dm2ddLatitude( dm->latDegrees->value( ),
- dm->latMinutes->value( ) );
- longitude = dm2ddLongitude( dm->lonDegrees->value( ),
- dm->lonMinutes->value( ) );
- updateLatLonWidget( 1 );
- }
- else if( ddRadio->isChecked( ) ) {
- latitude = dd->latDegrees->value( );
- longitude = dd->lonDegrees->value( );
- updateLatLonWidget( 2 );
- }
- //latLonFoundLabel->setText( "" );
-}
-
-double latLonWidget::dms2ddLatitude( int dd, int mm, double ss )
-{
- double x, xx, lat = 0.0;
- double d = dd;
- double m = mm;
- double s = ss;
- if( d >= 0 ){
- xx = s / 60.0;
- m += xx;
- x = m / 60.0;
- lat = d + x;
- }
- else {
- xx = s / 60.0;
- m += xx;
- x = m / 60.0;
- lat = d - x;
- }
- return lat;
-}
-
-double latLonWidget::dms2ddLongitude( int dd, int mm, double ss )
-{
- double d = dd;
- double m = mm;
- double s = ss;
- double x, xx, lon = 0.0;
- if( d >= 0 ) {
- xx = s / 60.0;
- m += xx;
- x = m / 60.0;
- lon = d + x;
- }
- else {
- xx = s / 60.0;
- m += xx;
- x = m / 60.0;
- lon = d - x;
- }
- return lon;
-}
-
-double latLonWidget::dm2ddLatitude( int dd, double mm )
-{
- double x, lat = 0.0;
- double d = dd;
- double m = mm;
-
- if( d >= 0.0 ) {
- x = m / 60.0;
- lat = d + x;
- }
- else {
- x = m / 60.0;
- lat = d - x;
- }
- return lat;
-}
-
-double latLonWidget::dm2ddLongitude( int dd, double mm )
-{
- double x, lon = 0.0;
- double d = dd;
- double m = mm;
-
- if( d >= 0.0 ) {
- x = m / 60.0;
- lon = d + x;
- }
- else {
- x = m / 60.0;
- lon = d - x;
- }
- return lon;
-}
-
-void latLonWidget::updateLatLonWidget( int notMe )
-{
- if( notMe == 0 ) {
- dm->latDegrees->setValue( ( int )latitude );
- dm->latMinutes->setValue( ( fabs( latitude ) - ( int )fabs( latitude ) ) * 60 );
-
- dm->lonDegrees->setValue( ( int )longitude );
- dm->lonMinutes->setValue( ( fabs( longitude ) - ( int )fabs( longitude ) ) * 60 );
-
- dd->latDegrees->setValue( latitude );
- dd->lonDegrees->setValue( longitude );
- }
- else if( notMe == 1 ) {
- double d, m, s;
- d = ( int )latitude;
- m = ( fabs( latitude ) - fabs( d ) ) * 60;
- s = ( m - ( int )m ) * 60;
- m = ( int )m;
-
- dms->latDegrees->setValue( d );
- dms->latMinutes->setValue( m );
- dms->latSeconds->setValue( s );
-
- d = ( int )longitude;
- m = ( fabs( longitude ) - fabs( d ) ) * 60;
- s = ( m - ( int )m ) * 60;
- m = ( int )m;
-
-
- dms->lonDegrees->setValue( d );
- dms->lonMinutes->setValue( m );
- dms->lonSeconds->setValue( s );
-
- dd->latDegrees->setValue( latitude );
- dd->lonDegrees->setValue( longitude );
- }
- else if( notMe == 2 ) {
- dm->latDegrees->setValue( ( int )latitude );
- dm->latMinutes->setValue( ( fabs( latitude ) - ( int )fabs( latitude ) ) * 60 );
-
- dm->lonDegrees->setValue( ( int )longitude );
- dm->lonMinutes->setValue( ( fabs( longitude ) - ( int )fabs( longitude ) ) * 60 );
-
- double d, m, s;
- d = ( int )latitude;
- m = ( fabs( latitude ) - fabs( d ) ) * 60;
- s = ( m - ( int )m ) * 60;
- m = ( int )m;
-
- dms->latDegrees->setValue( d );
- dms->latMinutes->setValue( m );
- dms->latSeconds->setValue( s );
-
- d = ( int )longitude;
- m = ( fabs( longitude ) - fabs( d ) ) * 60;
- s = ( m - ( int )m ) * 60;
- m = ( int )m;
-
- dms->lonDegrees->setValue( d );
- dms->lonMinutes->setValue( m );
- dms->lonSeconds->setValue( s );
- }
- else {
- //update all from internal lat/lon
- //degrees/minutes/seconds
- double d, m, s;
- d = ( int )latitude;
- m = ( fabs( latitude ) - fabs( d ) ) * 60;
- s = ( m - ( int )m ) * 60;
- m = ( int )m;
-
- dms->latDegrees->setValue( d );
- dms->latMinutes->setValue( m );
- dms->latSeconds->setValue( s );
-
- d = ( int )longitude;
- m = ( fabs( longitude ) - fabs( d ) ) * 60;
- s = ( m - ( int )m ) * 60;
- m = ( int )m;
-
- dms->lonDegrees->setValue( d );
- dms->lonMinutes->setValue( m );
- dms->lonSeconds->setValue( s );
-
- //degrees minutes
- dm->latDegrees->setValue( ( int )latitude );
- dm->latMinutes->setValue( ( fabs( latitude ) - ( int )fabs( latitude ) ) * 60 );
-
- dm->lonDegrees->setValue( ( int )longitude );
- dm->lonMinutes->setValue( ( fabs( longitude ) - ( int )fabs( longitude ) ) * 60 );
-
- //decimal degrees
- dd->latDegrees->setValue( latitude );
- dd->lonDegrees->setValue( longitude );
- }
-}
diff --git a/src/gui/latLonWidget.h b/src/gui/latLonWidget.h
deleted file mode 100644
index 06eda7d32..000000000
--- a/src/gui/latLonWidget.h
+++ /dev/null
@@ -1,127 +0,0 @@
-/******************************************************************************
- *
- * $Id$
- *
- * Project: WindNinja Qt GUI
- * Purpose: Handle lat/lon dd:mm:ss/dd:mm.mm/dd.dd conversions for diurnal
- * inputs
- * Author: Kyle Shannon
- *
- ******************************************************************************
- *
- * THIS SOFTWARE WAS DEVELOPED AT THE ROCKY MOUNTAIN RESEARCH STATION (RMRS)
- * MISSOULA FIRE SCIENCES LABORATORY BY EMPLOYEES OF THE FEDERAL GOVERNMENT
- * IN THE COURSE OF THEIR OFFICIAL DUTIES. PURSUANT TO TITLE 17 SECTION 105
- * OF THE UNITED STATES CODE, THIS SOFTWARE IS NOT SUBJECT TO COPYRIGHT
- * PROTECTION AND IS IN THE PUBLIC DOMAIN. RMRS MISSOULA FIRE SCIENCES
- * LABORATORY ASSUMES NO RESPONSIBILITY WHATSOEVER FOR ITS USE BY OTHER
- * PARTIES, AND MAKES NO GUARANTEES, EXPRESSED OR IMPLIED, ABOUT ITS QUALITY,
- * RELIABILITY, OR ANY OTHER CHARACTERISTIC.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *
- *****************************************************************************/
-
-#ifndef LATLONWIDGET_H
-#define LATLONWIDGET_H
-
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-
-#include
-
-class dmsWidget : public QWidget
-{
- Q_OBJECT
-
-public:
- dmsWidget(QWidget *parent = 0);
- QGroupBox *latGroupBox, *lonGroupBox;
- QSpinBox *latDegrees, *lonDegrees;
- QSpinBox *latMinutes, *lonMinutes;
-
- QDoubleSpinBox *latSeconds, *lonSeconds;
-
- QHBoxLayout *latLayout, *lonLayout, *layout;
-
-};
-
-class dmWidget : public QWidget
-{
- Q_OBJECT
-public:
- dmWidget(QWidget *parent = 0);
- QGroupBox *latGroupBox, *lonGroupBox;
- QSpinBox *latDegrees, *lonDegrees;
- QDoubleSpinBox *latMinutes, *lonMinutes;
-
- QHBoxLayout *latLayout, *lonLayout, *layout;
-};
-
-class ddWidget : public QWidget
-{
- Q_OBJECT
-
-public:
- ddWidget(QWidget *parent = 0);
- QGroupBox *latGroupBox, *lonGroupBox;
- QDoubleSpinBox *latDegrees, *lonDegrees;
-
- QHBoxLayout *latLayout, *lonLayout, *layout;
-
-};
-
-class latLonWidget : public QWidget
-{
- Q_OBJECT
-public:
- latLonWidget(QString title, QWidget *parent = 0);
-
- //store lat lon in dd always
- double latitude, longitude;
-
- QGroupBox *latLonGroupBox;
- QGroupBox *latLonFormatGroupBox;
- QLabel *latLonFormatLabel;
- QRadioButton *dmsRadio, *dmRadio, *ddRadio;
-
- //conversions
- double dms2ddLatitude(int, int, double);
- double dms2ddLongitude(int, int, double);
- double dm2ddLatitude(int, double);
- double dm2ddLongitude(int, double);
-
- QStackedWidget *stackedWidget;
-
- dmsWidget *dms;
- dmWidget *dm;
- ddWidget *dd;
-
- QComboBox *datumComboBox;
-
- QHBoxLayout *latLonFormatLayout;
- QVBoxLayout *latLonLayout;
-
- QVBoxLayout *layout;
-
-public slots:
- void checkLatLonFormat();
- void updateLatLon();
- void updateLatLonWidget(int notMe);
-
-};
-
-#endif /* LATLONWIDGET_H */
diff --git a/src/gui/mainWindow.cpp b/src/gui/mainWindow.cpp
deleted file mode 100644
index 3d19431b6..000000000
--- a/src/gui/mainWindow.cpp
+++ /dev/null
@@ -1,3704 +0,0 @@
-/******************************************************************************
- *
- * $Id$
- *
- * Project: WindNinja Qt GUI
- * Purpose: Main window and parent to all other widgets
- * Author: Kyle Shannon
- *
- ******************************************************************************
- *
- * THIS SOFTWARE WAS DEVELOPED AT THE ROCKY MOUNTAIN RESEARCH STATION (RMRS)
- * MISSOULA FIRE SCIENCES LABORATORY BY EMPLOYEES OF THE FEDERAL GOVERNMENT
- * IN THE COURSE OF THEIR OFFICIAL DUTIES. PURSUANT TO TITLE 17 SECTION 105
- * OF THE UNITED STATES CODE, THIS SOFTWARE IS NOT SUBJECT TO COPYRIGHT
- * PROTECTION AND IS IN THE PUBLIC DOMAIN. RMRS MISSOULA FIRE SCIENCES
- * LABORATORY ASSUMES NO RESPONSIBILITY WHATSOEVER FOR ITS USE BY OTHER
- * PARTIES, AND MAKES NO GUARANTEES, EXPRESSED OR IMPLIED, ABOUT ITS QUALITY,
- * RELIABILITY, OR ANY OTHER CHARACTERISTIC.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *
- *****************************************************************************/
-
-#include "mainWindow.h"
-
-mainWindow::mainWindow(QWidget *parent)
-: QMainWindow(parent)
-{
- std::string tzfile = FindDataPath( "date_time_zonespec.csv" );
- if( tzfile == "" )
- {
- throw std::runtime_error( "Could not find supporting data files, " \
- "try setting WINDNINJA_DATA." );
- }
- lineNumber = 1;
- GDALProjRef = "";
-
- progressDialog = new QProgressDialog(this);
- progressDialog->setMinimumDuration(1);
- progressDialog->setAutoClose(false);
- progressDialog->setAutoReset(false);
- progressDialog->setWindowModality(Qt::ApplicationModal);
-
- runProgress = 0;
- totalProgress = 0;
- mainWindow::progressLog;
-
- noGoogleCellSize = 30.0;
-
- //set defaults for some variables
-#ifdef NINJAFOAM
- existingCaseDir = "";
-#endif
- inputFileName = "";
- inputFileDir = "";
- inputFileType = -1;
- shortInputFileName = "";
- prjFileName = "";
- hasPrj = false;
-
- GDALCenterLat = GDALCenterLon = 0;
- hasGDALCenter = false;
-
- tree = new WindNinjaTree;
-
- createConsole();
- createActions();
- createMenus();
-
- createTimers();
-
- createConnections();
-
- setCentralWidget(tree);
-
- //threading
- sThread = new solveThread;
-
- meshCellSize = 200.0;
-
-#ifdef PHONE_HOME_QUERIES_ENABLED
- checkMessages();
-#endif
-
- QString v(NINJA_VERSION_STRING);
- v = "Welcome to WindNinja " + v;
-
-
- writeToConsole(v, Qt::blue);
-
- //get and set working directory for open dialogs and tutorials.
- cwd = QDir::current();
- pwd.setPath(QString::fromStdString(FindNinjaBinDir()));
- //pwd = QDir::current();
- pwd.cdUp();
-
- writeToConsole(cwd.currentPath());
- cwd.cd("../example-files");
- //writeToConsole(cwd.absolutePath());
-
- readSettings();
-
- okToContinueCheck = false;
-
- computeCellSize(tree->surface->meshResComboBox->currentIndex());
-
- checkAllItems();
- army = NULL;
-}
-
-/*
-** Check for version updates, or messages from the server.
-*/
-#ifdef PHONE_HOME_QUERIES_ENABLED
-void mainWindow::checkMessages(void) {
- QMessageBox mbox;
- char *papszMsg = NinjaQueryServerMessages(true);
- if (papszMsg != NULL) {
- if (strcmp(papszMsg, "TRUE\n") == 0) {
- mbox.setText("There is a fatal flaw in Windninja, it must close.");
- mbox.exec();
- delete[] papszMsg;
- abort();
- }
-
- else {
- char *papszMsg = NinjaQueryServerMessages(false);
- if (papszMsg != NULL) {
- mbox.setText(papszMsg);
-
- mbox.exec();
- delete[] papszMsg;
- }
- }
- }
-}
-
-#endif
-
-bool mainWindow::okToContinue()
-{
- if(okToContinueCheck)
- {
- int r = QMessageBox::warning(this, tr("WindNinja"),
- tr("Are you sure you want to exit?"),
- QMessageBox::Yes |
- QMessageBox::No |
- QMessageBox::Cancel);
- if(r == QMessageBox::Yes)
- return true;
- else if(r == QMessageBox::No || r == QMessageBox::Cancel)
- return false;
- else
- return false;
- }
- else
- return true;
-}
-
-void mainWindow::closeEvent(QCloseEvent *event)
-{
- if(okToContinue())
- writeSettings();
- else
- event->ignore();
-}
-
-void mainWindow::writeSettings()
-{
- writeToConsole("Saving settings...");
- QSettings settings(QSettings::UserScope, "Firelab", "WindNinja");
- settings.setDefaultFormat(QSettings::IniFormat);
- //input file path
- writeToConsole(inputFileDir.absolutePath());
- settings.setValue("inputFileDir", inputFileDir.absolutePath());
- //veg choice
- settings.setValue("vegChoice", tree->surface->roughnessComboBox->
- currentIndex());
- //mesh choice
- settings.setValue("meshChoice", tree->surface->meshResComboBox->
- currentIndex());
- //mesh units
- settings.setValue("meshUnits", tree->surface->meshMetersRadioButton->
- isChecked());
- //number of processors
- settings.setValue("nProcessors", tree->solve->numProcSpinBox->value());
-
- //time zone
- settings.setValue("timeZone",
- tree->surface->timeZone->tzComboBox->currentText() );
-
- settings.setValue("pointFile", tree->point->stationFileName );
-
- settings.setValue("customRes", tree->surface->meshResDoubleSpinBox->value());
-
- writeToConsole("Settings saved.");
-}
-
-void mainWindow::readSettings()
-{
- QSettings settings(QSettings::UserScope, "Firelab", "WindNinja");
- settings.setDefaultFormat(QSettings::IniFormat);
- if(settings.contains("inputFileDir"))
- {
- inputFileDir = settings.value("inputFileDir").toString();
- }
- else
- {
- std::string oTmpPath = FindNinjaRootDir();
- inputFileDir = CPLFormFilename(oTmpPath.c_str(), "etc/windninja/example-files", NULL);
- }
- if(settings.contains("vegChoice"))
- {
- tree->surface->roughnessComboBox->
- setCurrentIndex(settings.value("vegChoice").toInt());
- }
- if(settings.contains("meshChoice"))
- {
- int choice = settings.value("meshChoice").toInt();
- tree->surface->meshResComboBox->setCurrentIndex(choice);
- if(choice == 4 && settings.contains("customRes"))
- {
- double r = settings.value("customRes").toDouble();
- tree->surface->meshResDoubleSpinBox->setValue(r);
- }
- }
- if(settings.contains("meshUnits"))
- {
- if(settings.value("meshUnits").toBool())
- tree->surface->meshMetersRadioButton->setChecked(true);
- else
- tree->surface->meshFeetRadioButton->setChecked(true);
- }
- if(settings.contains("nProcessors"))
- {
- tree->solve->numProcSpinBox->
- setValue(settings.value("nProcessors").toInt());
- }
- if(settings.contains("timeZone"))
- {
- QString v = settings.value("timeZone").toString();
- int index = tree->surface->timeZone->tzComboBox->findText(v);
- if(index == -1)
- tree->surface->timeZone->tzCheckBox->setChecked( true );
- index = tree->surface->timeZone->tzComboBox->findText(v);
- if( index == 0 )
- tree->surface->timeZone->tzComboBox->setCurrentIndex(index + 1);
- tree->surface->timeZone->tzComboBox->setCurrentIndex(index);
- }
- else
- {
- tree->surface->timeZone->tzComboBox->setCurrentIndex(2);
- tree->surface->timeZone->tzComboBox->setCurrentIndex(1);
- }
- if(settings.contains("pointFile"))
- {
- QString f = settings.value("pointFile").toString();
- tree->point->stationFileName = f;
- }
-}
-
-void mainWindow::createActions()
-{
- //open surface file action
- openInputFileAction = new QAction(tr("Open &Elevation Input File"), this);
- openInputFileAction->setIcon(QIcon(":folder_page.png"));
- openInputFileAction->setShortcut(tr("Ctrl+D"));
- openInputFileAction->setStatusTip(tr("Open Surface Input File"));
- connect(openInputFileAction, SIGNAL(triggered()),
- this, SLOT(openInputFile()));
-
- //exitAction
- exitAction = new QAction(tr("E&xit"), this);
- exitAction->setIcon(QIcon(":cancel.png"));
- exitAction->setShortcut(tr("Alt+F4"));
- exitAction->setStatusTip(tr("Exit WindNinja"));
- connect(exitAction, SIGNAL(triggered()),
- this, SLOT(close()));
-
- //write console output action
- writeConsoleOutputAction = new QAction(tr("Write console output to file..."), this);
- writeConsoleOutputAction->setIcon(QIcon(":disk.png"));
- writeConsoleOutputAction->setShortcut(tr("Ctrl+W"));
- writeConsoleOutputAction->setStatusTip(tr("Write the console text to disk"));
- connect(writeConsoleOutputAction, SIGNAL(triggered()), this,
- SLOT(writeConsoleOutput()));
-
- //resample data action
- resampleAction = new QAction(tr("&Resample Data"), this);
- resampleAction->setIcon(QIcon(":resample.png"));
- resampleAction->setShortcut(tr("Ctrl+R"));
- resampleAction->setStatusTip(tr("Resample Existing Data"));
- connect(resampleAction, SIGNAL(triggered()), this, SLOT(resampleData()));
-
- //write a blank weather station file for point initialization
-
- writeBlankStationFileAction = new QAction(tr("Write a blank station file"),
- this);
- writeBlankStationFileAction->setIcon(QIcon(":disk.png"));
- writeBlankStationFileAction->setShortcut(tr("Ctrl+Alt+W"));
- writeBlankStationFileAction->setStatusTip(tr("Write a blank station file for point initialization"));
- connect(writeBlankStationFileAction, SIGNAL(triggered()), this,
- SLOT(writeBlankStationFile()));
-
- setConfigAction = new QAction(tr("Set Configuration Option"), this);
- setConfigAction->setIcon(QIcon(":cog_go.png"));
- setConfigAction->setStatusTip(tr("Set advanced runtime configuration options"));
- connect(setConfigAction, SIGNAL(triggered()), this, SLOT(SetConfigOption()));
-
- //wind ninja help action
- windNinjaHelpAction = new QAction(tr("WindNinja &Help"), this);
- windNinjaHelpAction->setIcon(QIcon(":help.png"));
- windNinjaHelpAction->setShortcut(tr("Ctrl+H"));
- windNinjaHelpAction->setStatusTip(tr("Get Help with the WindNinja"));
- connect(windNinjaHelpAction, SIGNAL(triggered()), this,
- SLOT(windNinjaHelp()));
-
- //arcMap action
- displayShapeFileProAction = new QAction(tr("How to Display Shapefiles in ArcGIS Pro"), this);
- displayShapeFileProAction->setIcon(QIcon(":page_white_acrobat.png"));
- connect(displayShapeFileProAction, SIGNAL(triggered()), this,
- SLOT(displayArcGISPro()));
-
- //open wind ninja tutorial 1 action
- tutorial1Action = new QAction(tr("Tutorial &1:The Basics"), this);
- tutorial1Action->setIcon(QIcon(":page_white_acrobat.png"));
- tutorial1Action->setShortcut(tr("Ctrl+1"));
- tutorial1Action->setStatusTip(tr("Get started using the WindNinja"));
- connect(tutorial1Action, SIGNAL(triggered()), this, SLOT(tutorial1()));
-
- //open wind ninja tutorial 2 action
- tutorial2Action = new QAction(tr("Tutorial &2: Diurnal Winds and Non-neutral Stability"), this);
- tutorial2Action->setIcon(QIcon(":page_white_acrobat.png"));
- tutorial2Action->setShortcut(tr("Ctrl+2"));
- tutorial2Action->setStatusTip(tr("Using Diurnal Winds in WindNinja"));
- connect(tutorial2Action, SIGNAL(triggered()), this, SLOT(tutorial2()));
-
- //open wind ninja tutorial 3 action
- tutorial3Action = new QAction(tr("Tutorial &3:Point Initialization"), this);
- tutorial3Action->setIcon(QIcon(":page_white_acrobat.png"));
- tutorial3Action->setShortcut(tr("Ctrl+3"));
- tutorial3Action->setStatusTip(tr("Using Point Initialization in WindNinja"));
- connect(tutorial3Action, SIGNAL(triggered()), this, SLOT(tutorial3()));
-
- //open wind ninja tutorial 4 action
- tutorial4Action = new QAction(tr("Tutorial &4:Weather Model Initialization"), this);
- tutorial4Action->setIcon(QIcon(":page_white_acrobat.png"));
- tutorial4Action->setShortcut(tr("Ctrl+4"));
- tutorial4Action->setStatusTip(tr("Using Weather Model Initialization in WindNinja"));
- connect(tutorial4Action, SIGNAL(triggered()), this, SLOT(tutorial4()));
-
- //dem downloader
- downloadDemAction = new QAction(tr("DEM Download Instructions"), this);
- downloadDemAction->setIcon(QIcon(":page_white_acrobat.png"));
- downloadDemAction->setStatusTip(tr("How to download DEM data with WindNinja"));
- connect(downloadDemAction, SIGNAL(triggered()), this, SLOT(demDownload()));
-
- //dem downloader cli
- fetchDemAction = new QAction(tr("fetch_dem Instructions"), this);
- fetchDemAction->setIcon(QIcon(":page_white_acrobat.png"));
- fetchDemAction->setStatusTip(tr("How to download DEM data with fetch_dem"));
- connect(fetchDemAction, SIGNAL(triggered()), this, SLOT(fetchDem()));
-
-
- //open wind ninja tutorial 4 action
- cliInstructionsAction = new QAction(tr("Command Line Interface Instructions"),
- this);
- cliInstructionsAction->setIcon(QIcon(":page_white_acrobat.png"));
- cliInstructionsAction->setShortcut(tr("Ctrl+l"));
- cliInstructionsAction->setStatusTip(tr("Using the Command Line Interface"));
- connect(cliInstructionsAction, SIGNAL(triggered()),
- this, SLOT(cliInstructions()));
-
- //about wn action
- aboutWindNinjaAction = new QAction(tr("&About WindNinja"), this);
- aboutWindNinjaAction->setIcon(QIcon(":help.png"));
- aboutWindNinjaAction->setShortcut(tr("Ctrl+A"));
- aboutWindNinjaAction->setStatusTip(tr("About the WindNinja"));
- connect(aboutWindNinjaAction, SIGNAL(triggered()), this,
- SLOT(aboutWindNinja()));
-
- //citation wn action
- citeWindNinjaAction = new QAction(tr("&Citation"), this);
- citeWindNinjaAction->setIcon(QIcon(":citation.png"));
- citeWindNinjaAction->setShortcut(tr("Ctrl+T"));
- citeWindNinjaAction->setStatusTip(tr("How to cite WindNinja"));
- connect(citeWindNinjaAction, SIGNAL(triggered()), this,
- SLOT(citeWindNinja()));
-
- //support email action
- supportEmailAction = new QAction(tr("&Email Us"), this);
- supportEmailAction->setIcon(QIcon(":email.png"));
- supportEmailAction->setShortcut(tr("Ctrl+E"));
- supportEmailAction->setStatusTip(tr("Email bugs/comments/questions to the WindNinja team"));
- connect(supportEmailAction, SIGNAL(triggered()), this,
- SLOT(supportEmail()));
-
- submitBugReportAction = new QAction(tr("Submit Bug Report"), this);
- submitBugReportAction->setIcon(QIcon(":bug_link.png"));
- submitBugReportAction->setShortcut(tr("Ctrl+B"));
- submitBugReportAction->setStatusTip(tr("Submit a bug report via GitHub (requires GitHub ID)"));
- connect(submitBugReportAction, SIGNAL(triggered()), this,
- SLOT(bugReport()));
-
- //about qt action
- aboutQtAction = new QAction(tr("About &Qt"), this);
- aboutQtAction->setStatusTip(tr("Show the Qt library's About box"));
- connect(aboutQtAction, SIGNAL(triggered()), qApp, SLOT(aboutQt()));
-
- //test action to test slots.
- testAction = new QAction(tr("Test"), this);
- connect(testAction, SIGNAL(triggered()), this, SLOT(test()));
-}
-
-void mainWindow::createMenus()
-{
- //file menu
- fileMenu = menuBar()->addMenu(tr("&File"));
- fileMenu->addAction(openInputFileAction);
- fileMenu->addSeparator();
- fileMenu->addAction(writeConsoleOutputAction);
- fileMenu->addSeparator();
- fileMenu->addAction(exitAction);
- //options menu, used member in QDockWidget to return QAction to toggle.
- optionsMenu = menuBar()->addMenu(tr("&Options"));
- optionsMenu->addAction(console->toggleViewAction());
-
- //tools menu
- toolsMenu = menuBar()->addMenu(tr("&Tools"));
- //toolsMenu->addAction(resampleAction);
- toolsMenu->addAction(writeBlankStationFileAction);
- toolsMenu->addAction(setConfigAction);
-
- //help/tutorial menus
- helpMenu = menuBar()->addMenu(tr("&Help"));
- shapeSubMenu = helpMenu->addMenu(tr("Displaying Shapefiles"));
- shapeSubMenu->addAction(displayShapeFileProAction);
- QMenu *shapeSubMenu;
- tutorialSubMenu = helpMenu->addMenu(tr("Tutorials"));
- tutorialSubMenu->addAction(tutorial1Action);
- tutorialSubMenu->addAction(tutorial2Action);
- tutorialSubMenu->addAction(tutorial3Action);
- tutorialSubMenu->addAction(tutorial4Action);
- helpMenu->addAction(downloadDemAction);
- helpMenu->addAction(fetchDemAction);
- helpMenu->addAction(cliInstructionsAction);
- helpMenu->addAction(aboutWindNinjaAction);
- helpMenu->addAction(citeWindNinjaAction);
- helpMenu->addAction(supportEmailAction);
- helpMenu->addAction(submitBugReportAction);
-
- //context menu for text edit
- //console->consoleTextEdit->addAction(writeConsoleOutputAction);
- //console->consoleTextEdit->setContextMenuPolicy(Qt::ActionsContextMenu);
-
-
- //helpMenu->addAction(aboutQtAction);
- //helpMenu->addAction(testAction);
-}
-
-/**
- * Create connections for mainWindow
- *
- */
-void mainWindow::createConnections()
-{
- // Connections for DEM Downloader Button
- connect(tree->surface->downloadDEMButton, SIGNAL(clicked()),
- this, SLOT(openDEMDownloader()));
- //
- connect(&fileWatcher, SIGNAL(fileChanged(QString)),
- this, SLOT(inputFileDeleted()));
-
-#ifdef NINJAFOAM
- //Connect input file open button to dialog box
- connect(tree->surface->foamCaseOpenToolButton, SIGNAL(clicked()),
- this, SLOT(openExistingCase()));
-#endif
- //Connect input file open button to dialog box
- connect(tree->surface->inputFileOpenToolButton, SIGNAL(clicked()),
- this, SLOT(openInputFile()));
- //connect signals/slots
- //connect combo to change mesh res
- connect(tree->surface->meshResComboBox, SIGNAL(currentIndexChanged(int)),
- this, SLOT(checkMeshCombo()));
- //also connect the radio button for feet display
- connect(tree->surface->meshMetersRadioButton, SIGNAL(toggled(bool)),
- this, SLOT(checkMeshUnits(bool)));
- //connect the mesh resolution on the surface input page to the output
- //'use mesh resolution' sections.
- connect(tree->surface->meshResDoubleSpinBox, SIGNAL(valueChanged(double)),
- this, SLOT(updateOutRes()));
- //connect the getLatLon button to the fx
- //connect(tree->location->getLatLonToolButton, SIGNAL(clicked()),
- // this, SLOT(getLatLon()));
- //also connect the toggle on the check box on output pages to update
-
- /*
- ** When we update the mesh resolution, update the outputs if the output is
- ** enabled. We also update the output resolutions when the various outputs
- ** are enabled. Additionally when either of the radio buttons are checked.
- */
- connect(tree->google->useMeshResCheckBox, SIGNAL(toggled(bool)), this,
- SLOT(updateOutRes()));
- connect(tree->fb->useMeshResCheckBox, SIGNAL(toggled(bool)), this,
- SLOT(updateOutRes()));
- connect(tree->shape->useMeshResCheckBox, SIGNAL(toggled(bool)), this,
- SLOT(updateOutRes()));
- connect(tree->pdf->useMeshResCheckBox, SIGNAL(toggled(bool)), this,
- SLOT(updateOutRes()));
- connect(tree->google->googleGroupBox, SIGNAL(toggled(bool)), this,
- SLOT(updateOutRes()));
- connect(tree->fb->fbGroupBox, SIGNAL(toggled(bool)), this,
- SLOT(updateOutRes()));
- connect(tree->shape->shapeGroupBox, SIGNAL(toggled(bool)), this,
- SLOT(updateOutRes()));
- connect(tree->pdf->pdfGroupBox, SIGNAL(toggled(bool)), this,
- SLOT(updateOutRes()));
- connect(tree->surface->meshMetersRadioButton, SIGNAL(toggled(bool)), this,
- SLOT(updateOutRes()));
- connect(tree->surface->meshFeetRadioButton, SIGNAL(toggled(bool)), this,
- SLOT(updateOutRes()));
-
- connect(tree->diurnal->diurnalGroupBox, SIGNAL(toggled(bool)),
- tree->wind->windTable, SLOT(enableDiurnalCells(bool)));
- connect(tree->diurnal->diurnalGroupBox, SIGNAL(toggled(bool)),
- this, SLOT(enablePointDate(bool)));
- connect(tree->stability->stabilityGroupBox, SIGNAL(toggled(bool)),
- this, SLOT(enablePointDate(bool)));
- connect(tree->stability->stabilityGroupBox, SIGNAL(toggled(bool)),
- tree->wind->windTable, SLOT(enableStabilityCells(bool)));
-#ifdef NINJAFOAM
- connect(tree->ninjafoam->ninjafoamGroupBox, SIGNAL(toggled(bool)),
- this, SLOT(enableNinjafoamOptions(bool)));
-#endif
- //connect change in tree to the checkers
- connect(tree->tree, SIGNAL(currentItemChanged(QTreeWidgetItem *,
- QTreeWidgetItem *)), this, SLOT(checkAllItems()));
-
- //connect the diurnalGroupBox->toggled to checkers
- connect(tree->diurnal->diurnalGroupBox, SIGNAL(toggled(bool)),
- this, SLOT(checkAllItems()));
- connect(tree->stability->stabilityGroupBox, SIGNAL(toggled(bool)),
- this, SLOT(checkAllItems()));
-#ifdef NINJAFOAM
- //connect the solver method check boxes for mutex
- connect(tree->ninjafoam->ninjafoamGroupBox, SIGNAL(toggled(bool)),
- this, SLOT(checkAllItems()));
- connect(tree->nativesolver->nativeSolverGroupBox, SIGNAL(toggled(bool)),
- this, SLOT(checkAllItems()));
- connect( tree->nativesolver->nativeSolverGroupBox, SIGNAL( toggled( bool ) ),
- this, SLOT( selectNativeSolver( bool ) ) );
- connect( tree->ninjafoam->ninjafoamGroupBox, SIGNAL( toggled( bool ) ),
- this, SLOT( selectNinjafoamSolver( bool ) ) );
-#endif
-
- //connect the speed and direction in each row to the checkers
- for(int i=0;iwind->windTable->nRuns;i++)
- {
- connect(tree->wind->windTable->speed[i], SIGNAL(valueChanged(double)), this,
- SLOT(checkAllItems()));
- connect(tree->wind->windTable->dir[i], SIGNAL(valueChanged(int)), this,
- SLOT(checkAllItems()));
- }
-
- //connect the initialization check boxes to checkers
- connect(tree->wind->windGroupBox, SIGNAL(toggled(bool)),
- this, SLOT(checkAllItems()));
- connect(tree->point->pointGroupBox, SIGNAL(toggled(bool)),
- this, SLOT(checkAllItems()));
- connect(tree->point->pointGroupBox, SIGNAL(toggled(bool)),
- this, SLOT(enablePointDate(bool)));
- connect(tree->weather->weatherGroupBox, SIGNAL(toggled(bool)),
- this, SLOT(checkAllItems()));
-
- //Connects making changes in pointInput to checkers
- //Makes the validation happen instantaneously
- connect(tree->point->treeView,
- SIGNAL(clicked(const QModelIndex &)),
- this,SLOT(checkAllItems()));
- //When the user changes the date time, check to make sure it is sane
- connect(tree->point->startTime,SIGNAL(dateTimeChanged(QDateTime)),this,SLOT(checkAllItems()));
- connect(tree->point->stopTime,SIGNAL(dateTimeChanged(QDateTime)),this,SLOT(checkAllItems()));
-
- connect(tree->point->refreshToolButton,SIGNAL(clicked(bool)),this,SLOT(checkAllItems()));
-
- //connect selection change in weather to checkers
- connect(tree->weather->treeView->selectionModel(),
- SIGNAL(currentChanged(const QModelIndex&, const QModelIndex&)),
- this, SLOT(checkAllItems()));
-
- //connect the output check boxes with the checkers
- connect(tree->google->googleGroupBox, SIGNAL(toggled(bool)),
- this, SLOT(checkAllItems()));
- connect(tree->fb->fbGroupBox, SIGNAL(toggled(bool)),
- this, SLOT(checkAllItems()));
- connect(tree->shape->shapeGroupBox, SIGNAL(toggled(bool)),
- this, SLOT(checkAllItems()));
- connect(tree->pdf->pdfGroupBox, SIGNAL(toggled(bool)),
- this, SLOT(checkAllItems()));
- connect(tree->vtk->vtkGroupBox, SIGNAL(toggled(bool)),
- this, SLOT(checkAllItems()));
-
- //and the spinboxes
- connect(tree->google->googleResSpinBox, SIGNAL(valueChanged(double)),
- this, SLOT(checkAllItems()));
- connect(tree->fb->fbResSpinBox, SIGNAL(valueChanged(double)),
- this, SLOT(checkAllItems()));
- connect(tree->shape->shapeResSpinBox, SIGNAL(valueChanged(double)),
- this, SLOT(checkAllItems()));
- connect(tree->pdf->pdfResSpinBox, SIGNAL(valueChanged(double)),
- this, SLOT(checkAllItems()));
-
- //check the google res, make sure not bad
- connect(tree->google->googleResSpinBox, SIGNAL(valueChanged(double)),
- this, SLOT(checkKmlLimit(double)));
-
- //solve button and solve()
- connect(tree->solve->solveToolButton, SIGNAL(clicked()),
- this, SLOT(solve()));
-
- connect(progressDialog, SIGNAL(canceled()), this, SLOT(cancelSolve()));
-
- connect(tree->solve->solveToolButton, SIGNAL(clicked()), progressDialog,
- SLOT(forceShow()));
-
- //connect double clicks on trees to main action for that item
- connect(tree->tree, SIGNAL(itemDoubleClicked(QTreeWidgetItem*, int)),
- this, SLOT(treeDoubleClick(QTreeWidgetItem*, int)));
-
- //connect inputFileChanged to anything that wants it
- connect(this, SIGNAL(inputFileChanged(QString)),
- tree->weather, SLOT(setInputFile(QString)));
- connect(this, SIGNAL(inputFileChanged(QString)),
- tree->point, SLOT(setInputFile(QString)));
- connect(this,SIGNAL(inputFileChanged(QString)),
- tree->point, SLOT(checkForModelData())); //Update csv list when file changes in point
-//Signal To Point Input what Diurnal Input is doing
- connect(this, SIGNAL(mainDiurnalChanged(bool)),tree->point,SLOT(setDiurnalParam(bool)));
-
- //connect other writeToConsoles to the main writeToConsole
- connect( tree->point, SIGNAL( writeToConsole( QString ) ),
- this, SLOT( writeToConsole( QString ) ) );
-
- //connect timezone combo to weather model tz string
- connect( tree->surface->timeZone, SIGNAL( tzChanged( QString ) ),
- tree->weather, SLOT( updateTz( QString ) ) );
- //connect time zone for station fetch
- connect( tree->surface->timeZone, SIGNAL( tzChanged( QString ) ),
- tree->point, SLOT( updateTz( QString ) ) );
-
- //connect the initialization check boxes to the others for mutex
- connect( tree->wind->windGroupBox, SIGNAL( toggled( bool ) ),
- this, SLOT( selectWindInitialization( bool ) ) );
- connect( tree->point->pointGroupBox, SIGNAL( toggled( bool ) ),
- this, SLOT( selectPointInitialization( bool ) ) );
- connect( tree->weather->weatherGroupBox, SIGNAL( toggled( bool ) ),
- this, SLOT( selectWeatherInitialization( bool ) ) );
-
- //connect change in station file to checkAllItems
- connect( tree->point, SIGNAL( stationFileChanged() ),
- this, SLOT( checkAllItems() ) );
-
- //connect the solve open out path button
- connect( tree->solve->openOutputPathButton, SIGNAL( clicked() ),
- this, SLOT( openOutputPath() ) );
-
- connect( progressDialog, SIGNAL( canceled() ),
- this, SLOT( updateTimer() ) );
-}
-/**
- * Slot to catch a change in initialization method
- *
- * @param pick I am picked
- */
-void mainWindow::selectWindInitialization( bool pick )
-{
- if( pick ) {
- tree->point->pointGroupBox->setChecked( false );
- tree->weather->weatherGroupBox->setChecked( false );
- tree->output->wxModelOutputCheckBox->setDisabled( true );
- checkAllItems();
- }
-}
-
-void mainWindow::selectPointInitialization( bool pick )
-{
- if( pick ) {
- tree->wind->windGroupBox->setChecked( false );
- tree->weather->weatherGroupBox->setChecked( false );
- tree->output->wxModelOutputCheckBox->setDisabled( true );
- checkAllItems();
- }
-}
-
-void mainWindow::selectWeatherInitialization( bool pick )
-{
- if( pick ) {
- tree->wind->windGroupBox->setChecked( false );
- tree->point->pointGroupBox->setChecked( false );
- checkAllItems();
- }
- tree->output->wxModelOutputCheckBox->setEnabled( pick );
-}
-
-#ifdef NINJAFOAM
-void mainWindow::selectNativeSolver( bool pick )
-{
- if( pick ) {
- tree->ninjafoam->ninjafoamGroupBox->setChecked( false );
- checkAllItems();
- }
-}
-
-void mainWindow::selectNinjafoamSolver( bool pick )
-{
- if( pick ) {
- tree->nativesolver->nativeSolverGroupBox->setChecked( false );
- checkAllItems();
- }
-}
-
-void mainWindow::openExistingCase()
-{
- QString dir = QFileDialog::getExistingDirectory(this,
- tr("Open Existing Case"),
- inputFileDir.absolutePath(),
- QFileDialog::ShowDirsOnly | QFileDialog::DontResolveSymlinks);
-
- QString shortName = QFileInfo(dir).fileName();
- tree->surface->foamCaseLineEdit->setText(shortName);
-
- tree->surface->downloadDEMButton->setEnabled(false);
- tree->surface->meshResComboBox->setEnabled(false);
-
-// if(existingCaseDir != QFileInfo(dir).canonicalFilePath())
-// {
-// emit(inputFileChanged(QFileInfo(dir).fileName()));
-// }
-
- existingCaseDir = QFileInfo(dir).canonicalFilePath();
-
- if(dir.isEmpty()){
- existingCaseDir = "";
- tree->surface->downloadDEMButton->setEnabled(true);
- tree->surface->meshResComboBox->setEnabled(true);
- }
-
- if(!dir.isEmpty()){
- //look for DEM that matches the STL basename in the NINJAFOAM_ paraent directory
- char **papszFileList;
- const char *pszFilename;
- const char *pszBasename;
- papszFileList = VSIReadDir( CPLSPrintf("%s/constant/triSurface", existingCaseDir.toStdString().c_str()) );
- //get the basename of the STL
- for(int i=0; isurface->foamCaseLineEdit->setText("");
- tree->surface->downloadDEMButton->setEnabled(true);
- tree->surface->meshResComboBox->setEnabled(true);
- return;
- }
- else{//Else set pszName to the demfilename
- pszFname = CPLStrdup(CPLFormFilename(pszDemPath, pszInputFilename, ""));
- }
-
-//// const char* pszFname = CPLStrdup(CPLFormFilename(pszDemPath, pszInputFilename, ""));pszFname = CPLStrdup(CPLFormFilename(pszDemPath, pszInputFilename, ""));
-
- updateFileInputForCase(pszFname); //Update the dem file name
-
- CSLDestroy( papszFileList );
- CPLFree( (void*)pszBasename );
- CPLFree( (void*)pszDemPath );
- CPLFree( (void*)pszInputFilename );
- CPLFree( (void*)pszFname );
-
- tree->surface->downloadDEMButton->setEnabled(false);
- tree->surface->meshResComboBox->setEnabled(false);
- }
-}
-#endif //NINJAFOAM
-
-//function for finding and opening an input file.
-void mainWindow::openInputFile()
-{
- //writeToConsole(inputFileDir.absolutePath());
- //setCursor(Qt::WaitCursor);
- QString fileName = QFileDialog::getOpenFileName(this,
- tr("Open Elevation Input File"),
- inputFileDir.absolutePath(),
-
- tr("Elevation Input Files (*.asc *.lcp *.tif *.img)"));
-
- if(!fileName.isEmpty())
- {
- cwd = QFileInfo(fileName).dir();
- //use GDAL to check the file
- QString newFile = checkForNoData(fileName);
- if(!newFile.isEmpty())
- {
- fileName = newFile;
- }
-
- if(checkInputFile(fileName) < 0)
- {
- tree->surface->inputFileLineEdit->clear();
- fileName = "";
- return;
- }
-
- QString shortName = QFileInfo(fileName).fileName();
- if(inputFileType == LCP)
- {
- tree->surface->roughnessComboBox->setDisabled(true);
- tree->surface->roughnessComboBox->hide();
- tree->surface->roughnessLabel->show();
- }
- else
- {
- tree->surface->roughnessComboBox->setDisabled(false);
- tree->surface->roughnessComboBox->show();
- tree->surface->roughnessLabel->hide();
- }
-
- tree->surface->inputFileLineEdit->setText(shortName);
-
- tree->surface->meshResComboBox->setEnabled(true);
-
- if(inputFileName != fileName)
- emit(inputFileChanged(fileName));
-
- inputFileName = fileName;
- inputFileDir = QFileInfo(fileName).absolutePath();
- tree->solve->setOutputDir( inputFileDir.absolutePath() );
- shortInputFileName = shortName;
- checkMeshCombo();
- checkInputItem();
- }
-
-#ifdef NINJAFOAM
- if(tree->surface->foamCaseLineEdit->text() != ""){
- tree->surface->meshResComboBox->setEnabled(false);
- }
-#endif
-
-}
-#ifdef NINJAFOAM
-/**
- * Slot to update elevation file input for existing case
- *
- * @param file File associated with existing case
- */
-void mainWindow::updateFileInputForCase(const char* file)
-{
- QString fileName(file);
- fileWatcher.addPath(fileName);
-
- if(!fileName.isEmpty())
- {
- cwd = QFileInfo(fileName).dir();
- //use GDAL to check the file
- if(checkInputFile(fileName) < 0)
- {
- tree->surface->inputFileLineEdit->clear();
- fileName = "";
- return;
- }
-
- QString shortName = QFileInfo(fileName).fileName();
- if(inputFileType == LCP)
- {
- tree->surface->roughnessComboBox->setDisabled(true);
- tree->surface->roughnessComboBox->hide();
- tree->surface->roughnessLabel->show();
- }
- else
- {
- tree->surface->roughnessComboBox->setDisabled(false);
- tree->surface->roughnessComboBox->show();
- tree->surface->roughnessLabel->hide();
- }
-
- tree->surface->inputFileLineEdit->setText(shortName);
-
- tree->surface->meshResComboBox->setEnabled(true);
-
- if(inputFileName != fileName)
- emit(inputFileChanged(fileName));
-
- inputFileName = fileName;
- inputFileDir = QFileInfo(fileName).absolutePath();
- tree->solve->setOutputDir( inputFileDir.absolutePath() );
- shortInputFileName = shortName;
- checkMeshCombo();
- checkInputItem();
- }
-}
-#endif //NINJAFOAM
-
-/**
- * Slot to update elevation file input with downloaded DEM file
- *
- * @param file File created from downloaded DEM
- */
-void mainWindow::updateFileInput(const char* file)
-{
- QString fileName(file);
-
- fileWatcher.addPath(fileName);
-
- if(!fileName.isEmpty())
- {
- cwd = QFileInfo(fileName).dir();
- //use GDAL to check the file
- if(checkInputFile(fileName) < 0)
- {
- tree->surface->inputFileLineEdit->clear();
- fileName = "";
- return;
- }
-
- QString shortName = QFileInfo(fileName).fileName();
- if(inputFileType == LCP)
- {
- tree->surface->roughnessComboBox->setDisabled(true);
- tree->surface->roughnessComboBox->hide();
- tree->surface->roughnessLabel->show();
- }
- else
- {
- tree->surface->roughnessComboBox->setDisabled(false);
- tree->surface->roughnessComboBox->show();
- tree->surface->roughnessLabel->hide();
- }
-
- tree->surface->inputFileLineEdit->setText(shortName);
-
- tree->surface->meshResComboBox->setEnabled(true);
-
- if(inputFileName != fileName)
- emit(inputFileChanged(fileName));
-
- inputFileName = fileName;
- inputFileDir = QFileInfo(fileName).absolutePath();
- shortInputFileName = shortName;
- checkMeshCombo();
- checkInputItem();
- tree->solve->setOutputDir(QFileInfo(fileName).absolutePath());
- }
-}
-
-void mainWindow::inputFileDeleted()
-{
- tree->surface->inputFileLineEdit->clear();
- //emit(inputFileChanged());
- checkMeshCombo();
- checkInputItem();
-}
-
-void mainWindow::openMainWindow()
-{
- this->setEnabled(true);
-}
-
-void mainWindow::createConsole()
-{
- console = new ConsoleDockWidget;
- addDockWidget(Qt::BottomDockWidgetArea, console);
- console->consoleTextEdit->setReadOnly(true);
-
- //set prompt
- prompt = "~>";
- //orange
- orange.setRgb(255, 165, 0);
-
-}
-void mainWindow::setPrompt(QString p)
-{
- prompt = p;
-}
-void mainWindow::writeConsoleOutput()
-{
- QDateTime date(QDateTime::currentDateTime());
- QString fileName = QFileDialog::getSaveFileName
- (this, tr("Save console output as..."), "console-output.txt",
- tr("Text Files (*.txt)"));
- writeToConsole("WindNinja console output from:");
- writeToConsole(date.toString("MM/dd/yyyy hh:mm:ss"));
- if(!fileName.isEmpty())
- {
- std::ofstream fout(fileName.toStdString().c_str(), std::ios::out);
- QString text = console->consoleTextEdit->toPlainText();
- fout << text.toStdString();
- writeToConsole(QString("Console data written to " + fileName + "."), Qt::darkGreen);
- fout.close();
- }
- else
- writeToConsole(QString("Cannot open " + fileName + " for writing."), Qt::red);
-}
-
-//create timers for status bar
-void mainWindow::createTimers()
-{
- runTime = new QTime(0, 0, 0, 0);
- runTime->start();
-}
-
-void mainWindow::updateTimer()
-{
- //elapsedRunTime = runTime->elapsed() / 1000.0;
- writeToConsole("Total Simulation time: " + QString::number(elapsedRunTime, 'f', 2) + " seconds");
-}
-
-void mainWindow::openDEMDownloader()
-{
- demWidget = new WidgetDownloadDEM();
- //demWidget->setAttribute(Qt::WA_DeleteOnClose, true);
- demWidget->settingsDir.setPath(inputFileDir.absolutePath());
- connect(demWidget, SIGNAL(doneDownloading(const char*)), this, SLOT(updateFileInput(const char*)));
- connect(demWidget, SIGNAL(exitDEM()), this, SLOT(openMainWindow()));
- connect(demWidget, SIGNAL(destroyed()), this, SLOT(openMainWindow()));
- this->setEnabled(false);
-}
-
-void mainWindow::test()
-{
-}
-
-void mainWindow::resampleData()
-{}
-
-void mainWindow::writeBlankStationFile()
-{
- QString fileName = QFileDialog::getSaveFileName
- (this, tr("Save station file as..."), "stations.csv",
- tr("Text Files (*.csv)"));
- if(!fileName.isEmpty())
- wxStation::writeBlankStationFile( fileName.toStdString() );
- else
- return;
-}
-
-void mainWindow::windNinjaHelp()
-{}
-
-void mainWindow::tutorial1()
-{
- pwd.cd("share/windninja/doc/tutorials");
- writeToConsole("Opening " + pwd.absoluteFilePath("WindNinja_tutorial1.pdf"));
-
- if(!QDesktopServices::openUrl(QUrl(pwd.absoluteFilePath("WindNinja_tutorial1.pdf"))))
- {
-
- QMessageBox::warning(this, tr("Broken Link."),
- tr("The link to the tutorial is broken, you can get to it through the Start Menu."),
- QMessageBox::Ok | QMessageBox::Default);
- }
- pwd.setPath(QString::fromStdString(FindNinjaBinDir()));
- pwd.cdUp();
-}
-
-void mainWindow::tutorial2()
-{
- pwd.cd("share/windninja/doc/tutorials");
- writeToConsole("Opening " + pwd.absoluteFilePath("WindNinja_tutorial2.pdf"));
-
- if(!QDesktopServices::openUrl(QUrl(pwd.absoluteFilePath("WindNinja_tutorial2.pdf"))))
- {
-
- QMessageBox::warning(this, tr("Broken Link."),
- tr("The link to the tutorial is broken, you can get to it through the Start Menu."),
- QMessageBox::Ok | QMessageBox::Default);
- }
- pwd.setPath(QString::fromStdString(FindNinjaBinDir()));
- pwd.cdUp();
-}
-
-void mainWindow::tutorial3()
-{
- pwd.cd("share/windninja/doc/tutorials");
- writeToConsole("Opening " + pwd.absoluteFilePath("WindNinja_tutorial3.pdf"));
-
- if(!QDesktopServices::openUrl(QUrl(pwd.absoluteFilePath("WindNinja_tutorial3.pdf"))))
- {
-
- QMessageBox::warning(this, tr("Broken Link."),
- tr("The link to the tutorial is broken, you can get to it through the Start Menu."),
- QMessageBox::Ok | QMessageBox::Default);
- }
- pwd.setPath(QString::fromStdString(FindNinjaBinDir()));
- pwd.cdUp();
-}
-
-void mainWindow::tutorial4()
-{
- pwd.cd("share/windninja/doc/tutorials");
- writeToConsole("Opening " + pwd.absoluteFilePath("WindNinja_tutorial4.pdf"));
-
- if(!QDesktopServices::openUrl(QUrl(pwd.absoluteFilePath("WindNinja_tutorial4.pdf"))))
- {
-
- QMessageBox::warning(this, tr("Broken Link."),
- tr("The link to the tutorial is broken, you can get to it through the Start Menu."),
- QMessageBox::Ok | QMessageBox::Default);
- }
- pwd.setPath(QString::fromStdString(FindNinjaBinDir()));
- pwd.cdUp();
-}
-
-void mainWindow::demDownload()
-{
- pwd.cd("share/windninja/doc");
- writeToConsole("Opening " + pwd.absoluteFilePath("download_elevation_file.pdf"));
-
- if(!QDesktopServices::openUrl(QUrl(pwd.absoluteFilePath("download_elevation_file.pdf"))))
- {
-
- QMessageBox::warning(this, tr("Broken Link."),
- tr("The link to the tutorial is broken, you can get to it through the Start Menu."),
- QMessageBox::Ok | QMessageBox::Default);
- }
- pwd.setPath(QString::fromStdString(FindNinjaBinDir()));
- pwd.cdUp();
-}
-
-void mainWindow::fetchDem()
-{
- pwd.cd("share/windninja/doc");
- writeToConsole("Opening " + pwd.absoluteFilePath("fetch_dem_instructions.pdf"));
-
- if(!QDesktopServices::openUrl(QUrl(pwd.absoluteFilePath("fetch_dem_instructions.pdf"))))
- {
-
- QMessageBox::warning(this, tr("Broken Link."),
- tr("The link to the tutorial is broken, you can get to it through the Start Menu."),
- QMessageBox::Ok | QMessageBox::Default);
- }
- pwd.setPath(QString::fromStdString(FindNinjaBinDir()));
- pwd.cdUp();
-}
-
-
-void mainWindow::displayArcGISPro()
-{
- pwd.cd("share/windninja/doc");
- writeToConsole("Opening " + pwd.absoluteFilePath("displaying_wind_vectors_in_ArcGIS_Pro.pdf"));
- if(!QDesktopServices::openUrl(QUrl(pwd.absoluteFilePath("displaying_wind_vectors_in_ArcGIS_Pro.pdf"))))
- {
-
- QMessageBox::warning(this, tr("Broken Link."),
- tr("The link to the tutorial is broken, you can get to it through the Start Menu."),
- QMessageBox::Ok | QMessageBox::Default);
- }
- pwd.setPath(QString::fromStdString(FindNinjaBinDir()));
- pwd.cdUp();
-}
-
-void mainWindow::cliInstructions()
-{
- pwd.cd("share/windninja/doc");
- writeToConsole("Opening " + pwd.absoluteFilePath("CLI_instructions.pdf"));
-
- if(!QDesktopServices::openUrl(QUrl(pwd.absoluteFilePath("CLI_instructions.pdf"))))
- {
-
- QMessageBox::warning(this, tr("Broken Link."),
- tr("The link to the tutorial is broken, you can get to it through the Start Menu."),
- QMessageBox::Ok | QMessageBox::Default);
- }
- pwd.setPath(QString::fromStdString(FindNinjaBinDir()));
- pwd.cdUp();
-}
-
-void mainWindow::supportEmail()
-{
- QDesktopServices::openUrl(QUrl("mailto:wind.ninja.support@gmail.com?subject=[windninja-support]"));
-}
-
-void mainWindow::bugReport()
-{
- QDesktopServices::openUrl(QUrl("https://github.com/firelab/windninja/issues/new"));
-}
-
-void mainWindow::aboutWindNinja()
-{
- QString aboutText = "WindNinja \n";
- aboutText.append("
Version: " + QString(NINJA_VERSION_STRING) + "
");
-
- aboutText.append("
Git Commit: " + QString(NINJA_SCM_VERSION) + "
");
-
- aboutText.append("
Release Date: " + QString(NINJA_RELEASE_DATE) + "");
- aboutText.append("
Developed by: Jason Forthofer " \
- "Natalie Wagenbrenner " \
- "Kyle Shannon " \
- "Loren Atwood " \
- "Mason Willman"); \
- aboutText.append("
Missoula Fire Sciences Laboratory ");
- aboutText.append("Rocky Mountain Research Station ");
- aboutText.append("USDA Forest Service ");
- aboutText.append("5775 Highway 10 W. ");
- aboutText.append("Missoula, MT 59808
");
- aboutText.append("Contributors
");
- aboutText.append("Sponsored By: ");
- aboutText.append("USDA Forest Service ");
- aboutText.append("Center for Environmental Management of Military Lands at Colorado State University ");
- aboutText.append("Joint Fire Sciences Program ");
- aboutText.append("Washington State University");
- aboutText.append("Special Thanks
");
- aboutText.append(" ");
-
- QMessageBox::about(this, tr("About WindNinja"),
- aboutText);
-}
-
-void mainWindow::citeWindNinja()
-{
- QString citeText = "To cite WindNinja in a publication use: ";
-
- citeText.append("Forthofer, J.M., Butler, B.W., Wagenbrenner, N.S., 2014. A comparison ");
- citeText.append("of three approaches for simulating fine-scale surface winds in ");
- citeText.append("support of wildland fire management. Part I. Model formulation and ");
- citeText.append("comparison against measurements. International Journal of Wildland ");
- citeText.append("Fire, 23:969-931. doi: 10.1071/WF12089.");
-
- citeText.append("For additional WindNinja publications visit: ");
- citeText.append("https://ninjastorm.firelab.org/windninja/publications
");
-
- QMessageBox::about(this, tr("Cite WindNinja"),
- citeText);
-}
-
-void mainWindow::writeToConsole(QString message, QColor color)
-{
- console->consoleTextEdit->setTextColor(color);
- console->consoleTextEdit->append(QString::number(lineNumber) + ": " + message);
- lineNumber++;
- //console->consoleTextEdit->append(prompt + message);
-}
-
-void mainWindow::updateOutRes()
-{
- //get res from surface page and store as an int
- double resolution = tree->surface->meshResDoubleSpinBox->value();
- bool useMeters = tree->surface->meshMetersRadioButton->isChecked();
- if (tree->google->useMeshResCheckBox->isChecked() == true) {
- tree->google->googleResSpinBox->setValue(resolution);
- if (useMeters) {
- tree->google->googleMetersRadioButton->setChecked(true);
- } else {
- tree->google->googleFeetRadioButton->setChecked(true);
- }
- }
- if (tree->fb->useMeshResCheckBox->isChecked() == true) {
- tree->fb->fbResSpinBox->setValue(resolution);
- if (useMeters) {
- tree->fb->fbMetersRadioButton->setChecked(true);
- } else {
- tree->fb->fbFeetRadioButton->setChecked(true);
- }
- }
- if (tree->shape->useMeshResCheckBox->isChecked() == true) {
- tree->shape->shapeResSpinBox->setValue(resolution);
- if (useMeters) {
- tree->shape->shapeMetersRadioButton->setChecked(true);
- } else {
- tree->shape->shapeFeetRadioButton->setChecked(true);
- }
- }
- if (tree->pdf->useMeshResCheckBox->isChecked() == true) {
- tree->pdf->pdfResSpinBox->setValue(resolution);
- if (useMeters) {
- tree->pdf->pdfMetersRadioButton->setChecked(true);
- } else {
- tree->pdf->pdfFeetRadioButton->setChecked(true);
- }
- }
-}
-
-//empty fx, need to write it when help is done.
-int mainWindow::openHelp(int target)
-{
- return target;
-}
-
-void mainWindow::checkMeshCombo()
-{
- int choice = tree->surface->meshResComboBox->currentIndex();
- double res = 200;
- //there is a splitter at 3
- if(choice == 4)
- {
- tree->surface->meshResDoubleSpinBox->setEnabled(true);
- }
- else
- {
- if(tree->surface->inputFileLineEdit->text() == "")
- {
- tree->surface->meshResDoubleSpinBox->setValue(res);
- meshCellSize = res;
- tree->surface->meshResDoubleSpinBox->setEnabled(false);
- }
- else
- {
- tree->surface->meshResDoubleSpinBox->setEnabled(false);
- res = computeCellSize(choice);
- if(tree->surface->meshFeetRadioButton->isChecked())
- res *= 3.28083989502;
- tree->surface->meshResDoubleSpinBox->setValue(res);
- meshCellSize = res;
- writeToConsole("Mesh Resolution set to " +
- QString::number(res)); //Note that this is very annoying for pointInitilaization/Station-fetch
- }
- }
-}
-
-void mainWindow::checkMeshUnits(bool checked)
-{
- if(checked)
- checkMeshCombo();
- else
- checkMeshCombo();
-}
-
-double mainWindow::computeCellSize(int index)
-{
- int coarse, medium, fine;
- double meshResolution;
-
- meshResolution = 200.0;
-
-#ifdef NINJAFOAM
- if( tree->ninjafoam->ninjafoamGroupBox->isChecked() ){
- /*ninjafoam: calculate mesh resolution of lower volume in block mesh*/
- coarse = 25000;
- medium = 50000;
- fine = 100000;
- }
- else{
- /* use native mesh */
- coarse = 4000;
- medium = 10000;
- fine = 20000;
- }
-#else
- coarse = 4000;
- medium = 10000;
- fine = 20000;
-#endif //NINJAFOAM
-
- int targetNumHorizCells = fine;
- switch(index)
- {
- case 0:
- targetNumHorizCells = coarse;
- break;
- case 1:
- targetNumHorizCells = medium;
- break;
- case 2:
- targetNumHorizCells = fine;
- break;
- case 3:
- return meshResolution;
- break;
- case 4:
- return meshResolution;
- break;
- default:
- return meshResolution;
- }
-
-#ifdef NINJAFOAM
- if( tree->ninjafoam->ninjafoamGroupBox->isChecked() ){
- /* ninjafoam mesh */
-
- double XLength = GDALXSize * GDALCellSize;
- double YLength = GDALYSize * GDALCellSize;
-
- double dz = GDALMaxValue - GDALMinValue;
- double ZLength = max((0.1 * max(XLength, YLength)), (dz + 0.1 * dz));
- double zmin, zmax;
- zmin = GDALMaxValue + 0.05 * ZLength; //zmin (above highest point in DEM for MDM)
- zmax = GDALMaxValue + ZLength; //zmax
-
- double volume;
- double cellCount;
- double cellVolume;
-
- volume = XLength * YLength * (zmax-zmin); //volume of blockMesh
- cellCount = targetNumHorizCells * 0.5; // cell count in volume 1
- cellVolume = volume/cellCount; // volume of 1 cell in blockMesh
- double side = std::pow(cellVolume, (1.0/3.0)); // length of side of cell in blockMesh
-
- //determine number of rounds of refinement
- int nCellsToAdd = 0;
- int refinedCellCount = 0;
- int nCellsInLowestLayer = int(XLength/side) * int(YLength/side);
- int nRoundsRefinement = 0;
- while(refinedCellCount < (0.5 * targetNumHorizCells)){
- nCellsToAdd = nCellsInLowestLayer * 8; //each cell is divided into 8 cells
- refinedCellCount += nCellsToAdd - nCellsInLowestLayer; //subtract the parent cells
- nCellsInLowestLayer = nCellsToAdd/2; //only half of the added cells are in the lowest layer
- nRoundsRefinement += 1;
- }
- meshResolution = side/(nRoundsRefinement*2.0);
- }
- else{
- /* native windninja mesh */
- double XLength = GDALXSize * GDALCellSize;
- double YLength = GDALYSize * GDALCellSize;
- double nXCells = 2 * std::sqrt((double)targetNumHorizCells) * (XLength / (XLength + YLength));
- double nYCells = 2 * std::sqrt((double)targetNumHorizCells) * (YLength / (XLength + YLength));
-
- double XCellSize = XLength / nXCells;
- double YCellSize = YLength / nYCells;
-
- meshResolution = (XCellSize + YCellSize) / 2;
-
- }
-#else
- double XLength = GDALXSize * GDALCellSize;
- double YLength = GDALYSize * GDALCellSize;
- double nXCells = 2 * std::sqrt((double)targetNumHorizCells) * (XLength / (XLength + YLength));
- double nYCells = 2 * std::sqrt((double)targetNumHorizCells) * (YLength / (XLength + YLength));
-
- double XCellSize = XLength / nXCells;
- double YCellSize = YLength / nYCells;
-
- meshResolution = (XCellSize + YCellSize) / 2;
-
- //noGoogleCellSize = std::sqrt((XLength * YLength) / noGoogleNumCells);
-#endif //NINJAFOAM
-
- return meshResolution;
-}
-
-//open input file as a GDALDataset, return file type enum;
-int mainWindow::checkInputFile(QString fileName)
-{
- GDALProjRef = "";
- hasPrj = false;
- GDALDataset *poInputDS;
- double adfGeoTransform[6];
- writeToConsole("Opening dataset...");
- poInputDS = (GDALDataset*)GDALOpen(fileName.toStdString().c_str(),
- GA_ReadOnly);
- if(poInputDS == NULL)
- {
- writeToConsole("Cannot open the input file.", Qt::red);
- return -1;
- }
-
- GDALDriverName = poInputDS->GetDriver()->GetDescription();
- GDALDriverLongName = poInputDS->GetDriver()->GetMetadataItem(GDAL_DMD_LONGNAME);
- writeToConsole("Reading " + GDALDriverLongName + "...");
-
- //set the file type here
- if(GDALDriverName == "AAIGrid")
- inputFileType = ASC;
- if(GDALDriverName == "LCP")
- inputFileType = LCP;
- if(GDALDriverName == "GTiff")
- {
- int nBandCount = GDALGetRasterCount( poInputDS );
- //if it's a multi-band GeoTIFF, it's an lcp
- if(nBandCount > 1)
- {
- inputFileType = LCP;
- }
- else
- inputFileType = GTIFF;
- }
- if(GDALDriverName == "IMG")
- inputFileType = IMG;
-
- if(inputFileType == LCP)
- {
- tree->surface->roughnessComboBox->setEnabled(false);
- tree->surface->roughnessComboBox->hide();
- tree->surface->roughnessLabel->show();
- }
- else
- {
- tree->surface->roughnessComboBox->setEnabled(true);
- tree->surface->roughnessComboBox->show();
- tree->surface->roughnessLabel->hide();
- }
-
- //get x and y dimension
- GDALXSize = poInputDS->GetRasterXSize();
- GDALYSize = poInputDS->GetRasterYSize();
-
- if(!GDALTestSRS(poInputDS))
- {
- hasPrj = false;
- writeToConsole("Invalid Spatial Reference (prj), "
- "cannot do a simulation with the supplied DEM", red);
- QMessageBox::warning(this, tr("WindNinja"),
- "The DEM does not contain a proper spatial reference "
- "system. WindNinja only supports DEM files "
- "with projected coordinate systems (e.g., UTM)",
- QMessageBox::Ok | QMessageBox::Default);
- GDALClose((GDALDatasetH)poInputDS);
- return -1;
- }
- else
- {
- GDALProjRef = poInputDS->GetProjectionRef();
- const char *pszProjRef;
- OGRSpatialReference oSRS;
- pszProjRef = GDALProjRef.c_str();
- oSRS.importFromWkt((char**)&pszProjRef);
- if(GDALProjRef == "")
- {
- hasPrj = false;
- QMessageBox::warning(this, tr("WindNinja"),
- "The DEM does not contain a proper spatial reference "
- "system. WindNinja only supports DEM files "
- "with projected coordinate systems (e.g., UTM)",
- QMessageBox::Ok | QMessageBox::Default);
- GDALClose((GDALDatasetH)poInputDS);
- return -1;
- }
- /* Check for geographic. Separate case as we may allow support later
- * on.
- */
- else if(oSRS.IsGeographic())
- {
- hasPrj = false;
- QMessageBox::warning(this, tr("WindNinja"),
- "The DEM coordinated system is in a "
- "geographic projection (latitude/longitude). "
- "WindNinja only supports projected "
- "coordinate systems (e.g., UTM)",
- QMessageBox::Ok | QMessageBox::Default);
- writeToConsole("Invalid Spatial Reference (prj), "
- "cannot do a simulation with the supplied DEM", red);
- //tree->surface->inputFileLineEdit->setText("");
- GDALClose((GDALDatasetH)poInputDS);
- return -1;
- }
- else
- {
- hasPrj = true;
- double longitude, latitude;
- if(GDALGetCenter(poInputDS, &longitude, &latitude))
- {
- //set diurnal location, also set DD.DDDDD
- QString oTimeZone = FetchTimeZone(longitude, latitude, NULL).c_str();
- if(oTimeZone != "")
- {
- /* Show all time zones, so we can search all time zones */
- tree->surface->timeZone->tzCheckBox->setChecked(true);
- int nIndex = tree->surface->timeZone->tzComboBox->findText(oTimeZone);
- tree->surface->timeZone->tzComboBox->setCurrentIndex(nIndex);
- }
-
- //emit latLonChanged( ll[0], ll[1], false );
- }
- }
- }
-
- //check for ndv
- //if(!checkForNoData(poInputDS))
- if(GDALHasNoData(poInputDS, 1))
- {
- writeToConsole("The input file contains no data values, cannot use",
- Qt::red);
- GDALClose((GDALDatasetH)poInputDS);
- return -1;
- }
-
- //get the geo-transform
- if(poInputDS->GetGeoTransform(adfGeoTransform) == CE_None)
- {
- double c1, c2;
- c1 = adfGeoTransform[1];
- c2 = adfGeoTransform[5];
- if(abs(c1) == abs(c2))
- GDALCellSize = abs(c1);
- else
- {
- writeToConsole("Invalid cell size, invalid file");
- GDALClose((GDALDatasetH)poInputDS);
- return -1;
- }
- }
-
- //get min/max values
- GDALMaxValue = GDALGetMax(poInputDS);
- GDALMinValue = GDALGetMin(poInputDS);
-
- GDALClose( (GDALDatasetH)poInputDS );
-
- double XLength = GDALXSize * GDALCellSize;
- double YLength = GDALYSize * GDALCellSize;
-
- noGoogleCellSize = std::sqrt((XLength * YLength) / noGoogleNumCells);
-
- writeToConsole("File Opened.", Qt::darkGreen);
- return 0;
-}
-
-bool mainWindow::getLatLon()
-{
- if(hasGDALCenter)
- {
- writeToConsole("The center of your DEM has been found.", Qt::darkGreen);
- writeToConsole("The lat/lon has been set in the diurnal inputs section", Qt::darkGreen);
- checkAllItems();
- return true;
- }
- else
- {
- writeToConsole("Cannot get Lat/Lon center", Qt::red);
- return false;
- }
-}
-
-void mainWindow::openOutputPath()
-{
- if( outputPath.isEmpty() || outputPath == "!set" )
- {
- return;
- }
- else
- {
- QDesktopServices::openUrl( QUrl ( "file:///" + outputPath,
- QUrl::TolerantMode ) );
- }
-}
-
-int mainWindow::solve()
-{
-#ifdef NINJAFOAM
- bool useNinjaFoam = tree->ninjafoam->ninjafoamGroupBox->isChecked();
-#endif
- //disable the open output path button
- tree->solve->openOutputPathButton->setDisabled( true );
-
- //dem file
- std::string demFile = inputFileName.toStdString();
-
-#ifdef NINJAFOAM
- std::string caseFile = existingCaseDir.toStdString();
-#endif
-
- //vegetation/roughness
- int vegIndex = tree->surface->roughnessComboBox->currentIndex();
- WindNinjaInputs::eVegetation vegetation;
- if( inputFileType != LCP ) {
- //get choice from combo
- if(vegIndex == 0)
- vegetation = WindNinjaInputs::grass;
- else if( vegIndex == 1 )
- vegetation = WindNinjaInputs::brush;
- else if( vegIndex == 2 )
- vegetation = WindNinjaInputs::trees;
- }
-
- //mesh
- int meshIndex = tree->surface->meshResComboBox->currentIndex();
- Mesh::eMeshChoice meshChoice;
- double meshRes;
- lengthUnits::eLengthUnits meshUnits;
- bool customMesh = false;
- if( meshIndex == 0 )
- meshChoice = Mesh::coarse;
- else if( meshIndex == 1 )
- meshChoice = Mesh::medium;
- else if( meshIndex == 2 )
- meshChoice = Mesh::fine;
- else {
- meshRes = tree->surface->meshResDoubleSpinBox->value();
- customMesh = true;
- if( tree->surface->meshFeetRadioButton->isChecked() )
- meshUnits = lengthUnits::feet;
- else
- meshUnits = lengthUnits::meters;
- }
-#ifdef NINJAFOAM
- WindNinjaInputs::eNinjafoamMeshChoice ninjafoamMeshChoice;
- if(useNinjaFoam){
- if( meshIndex == 0 )
- ninjafoamMeshChoice = WindNinjaInputs::coarse;
- else if( meshIndex == 1 )
- ninjafoamMeshChoice = WindNinjaInputs::medium;
- else if (meshIndex == 2)
- ninjafoamMeshChoice = WindNinjaInputs::fine;
- else {
- meshRes = tree->surface->meshResDoubleSpinBox->value();
- customMesh = true;
- if( tree->surface->meshFeetRadioButton->isChecked() )
- meshUnits = lengthUnits::feet;
- else
- meshUnits = lengthUnits::meters;
- }
- }
-#endif
-
- //location
- int tzIndex = tree->surface->timeZone->tzComboBox->currentIndex();
- if(tzIndex == -1 && (tree->diurnal->diurnalGroupBox->isChecked() ||
- tree->weather->weatherGroupBox->isChecked()
- || tree->stability->stabilityGroupBox->isChecked()
- ))
- {
- QMessageBox::warning(this, tr("WindNinja"), tr("Could not auto-identify "
- "time zone, please "
- "specify one in Surface"),
- QMessageBox::Ok | QMessageBox::Default);
- progressDialog->setValue( 0 );
- progressDialog->cancel();
- disconnect(progressDialog, SIGNAL(canceled()), this, SLOT(cancelSolve()));
- setCursor(Qt::ArrowCursor);
- return false;
- }
-
- QVariant temp = tree->surface->timeZone->tzComboBox->itemData( tzIndex );
- std::string timeZone = temp.toString().toStdString();
-
- //diurnal
- bool useDiurnal = tree->diurnal->diurnalGroupBox->isChecked();
-
- //stability
- bool useStability = tree->stability->stabilityGroupBox->isChecked();
-
- //initialization method
- WindNinjaInputs::eInitializationMethod initMethod;
- if( tree->wind->windGroupBox->isChecked() )
- initMethod = WindNinjaInputs::domainAverageInitializationFlag;
- else if( tree->point->pointGroupBox->isChecked() )
- initMethod = WindNinjaInputs::pointInitializationFlag;
- else if( tree->weather->weatherGroupBox->isChecked() )
- initMethod = WindNinjaInputs::wxModelInitializationFlag;
-
- //input wind height
- double inHeight = tree->wind->metaWind->inputHeightDoubleSpinBox->value();
- lengthUnits::eLengthUnits inHeightUnits;
- if(tree->wind->metaWind->feetRadioButton->isChecked())
- inHeightUnits = lengthUnits::feet;
- else
- inHeightUnits = lengthUnits::meters;
-
- //speed units and air temp units
- velocityUnits::eVelocityUnits inputSpeedUnits;
- if(tree->wind->windTable->inputSpeedUnits->currentIndex() == 0)
- inputSpeedUnits = velocityUnits::milesPerHour;
- else if(tree->wind->windTable->inputSpeedUnits->currentIndex() == 1)
- inputSpeedUnits = velocityUnits::metersPerSecond;
- else if(tree->wind->windTable->inputSpeedUnits->currentIndex() == 3)
- inputSpeedUnits = velocityUnits::knots;
- else
- inputSpeedUnits = velocityUnits::kilometersPerHour;
-
- temperatureUnits::eTempUnits tempUnits;
- if(tree->wind->windTable->airTempUnits->currentIndex() == 0)
- tempUnits = temperatureUnits::F;
- else if(tree->wind->windTable->airTempUnits->currentIndex() == 1)
- tempUnits = temperatureUnits::C;
-
- //model init
- std::string weatherFile;
- QModelIndex mi = tree->weather->treeView->selectionModel()->currentIndex();
- if( mi.isValid() ) {
- QFileInfo fi( tree->weather->model->fileInfo( mi ) );
- weatherFile = fi.absoluteFilePath().toStdString();
- }
- else
- weatherFile = "";
-
- //output height
- double outHeight = tree->output->outputHeight->outputHeightDoubleSpinBox->value();
- lengthUnits::eLengthUnits outHeightUnits;
- if(tree->output->outputHeight->feetRadioButton->isChecked())
- outHeightUnits = lengthUnits::feet;
- else
- outHeightUnits = lengthUnits::meters;
-
- velocityUnits::eVelocityUnits outputSpeedUnits;
- if(tree->output->outputSpeedUnitsCombo->currentIndex() == 0)
- outputSpeedUnits = velocityUnits::milesPerHour;
- else if(tree->output->outputSpeedUnitsCombo->currentIndex() == 1)
- outputSpeedUnits = velocityUnits::metersPerSecond;
- else if(tree->output->outputSpeedUnitsCombo->currentIndex() == 2)
- outputSpeedUnits = velocityUnits::kilometersPerHour;
- else if(tree->output->outputSpeedUnitsCombo->currentIndex() == 3)
- outputSpeedUnits = velocityUnits::knots;
-
- //clip buffer?
- int clip = tree->output->bufferSpinBox->value();
-
- bool writeWxOutput;
- if( tree->output->wxModelOutputCheckBox->isEnabled() )
- writeWxOutput = tree->output->wxModelOutputCheckBox->isChecked();
-
- //google
- bool writeGoogle = tree->google->googleGroupBox->isChecked();
- double googleRes = tree->google->googleResSpinBox->value();
- double vectorWidth = tree->google->vectorWidthDoubleSpinBox->value();
- lengthUnits::eLengthUnits googleUnits;
- KmlVector::egoogSpeedScaling googleScale;
- //bool writeLegend = tree->google->legendGroupBox->isChecked();
- if(tree->google->googleMetersRadioButton->isChecked())
- googleUnits = lengthUnits::meters;
- else
- googleUnits = lengthUnits::feet;
-
- if(tree->google->uniformRangeRadioButton->isChecked())
- googleScale = KmlVector::equal_interval;
- else
- googleScale = KmlVector::equal_color;
-
- std::string googleScheme;
- bool googVectorScaling = tree->google->applyVectorScaling->isChecked();
- bool googConsistentColorScale = tree->google->applyConsistentColorScale->isChecked();
- if(tree->google->colorblindBox->isChecked())
- {
- std::string googCheckScheme;
- QString QgoogleScheme=tree->google->inputColorblindComboBox->currentText();
- googCheckScheme=QgoogleScheme.toStdString();
-
- if (googCheckScheme=="Default")
- {
- googleScheme="default";
- }
- if (googCheckScheme=="ROPGW (Red Orange Pink Green White)")
- {
- googleScheme="ROPGW";
- }
- if (googCheckScheme=="Oranges")
- {
- googleScheme="oranges";
- }
- if (googCheckScheme=="Blues")
- {
- googleScheme="blues";
- }
- if (googCheckScheme=="Pinks")
- {
- googleScheme="pinks";
- }
- if (googCheckScheme=="Greens")
- {
- googleScheme="greens";
- }
- if (googCheckScheme=="Magic Beans")
- {
- googleScheme="magic_beans";
- }
- if (googCheckScheme=="Pink to Green")
- {
- googleScheme="pink_to_green";
- }
- }
- else
- {
- googleScheme="default";
- }
- //ascii raster fb files
- bool writeFb = tree->fb->fbGroupBox->isChecked();
- double fbRes = tree->fb->fbResSpinBox->value();
- lengthUnits::eLengthUnits fbUnits;
- if(tree->fb->fbMetersRadioButton->isChecked())
- fbUnits = lengthUnits::meters;
- else
- fbUnits = lengthUnits::feet;
- //write atmosphere file?
- bool writeAtm = tree->fb->atmFileCheckBox->isChecked();
- if(writeAtm && writeFb)
- {
- if((outHeight == 20 && outHeightUnits == lengthUnits::feet &&
- outputSpeedUnits == velocityUnits::milesPerHour) ||
- (outHeight == 10 && outHeightUnits == lengthUnits::meters &&
- outputSpeedUnits == velocityUnits::kilometersPerHour))
- {}
- else
- {
- QMessageBox::critical(this, tr("The solver cannot be run"),
- tr("The output wind settings for atm files must "
- "either be 10m for output height and "
- "output speed units in kph, or "
- "20ft for output height and "
- "output speed units in mph."),
- QMessageBox::Ok | QMessageBox::Default);
- progressDialog->setValue( 0 );
- progressDialog->cancel();
- disconnect(progressDialog, SIGNAL(canceled()), this, SLOT(cancelSolve()));
- setCursor(Qt::ArrowCursor);
- return false;
- }
- }
-
- //shape
- bool writeShape = tree->shape->shapeGroupBox->isChecked();
- double shapeRes = tree->shape->shapeResSpinBox->value();
- lengthUnits::eLengthUnits shapeUnits;
- if(tree->shape->shapeMetersRadioButton->isChecked())
- shapeUnits = lengthUnits::meters;
- else
- shapeUnits = lengthUnits::feet;
- //pdf
- bool writePdf = tree->pdf->pdfGroupBox->isChecked();
- double pdfRes = tree->pdf->pdfResSpinBox->value();
- double pdfLineWidth = tree->pdf->vectorWidthDoubleSpinBox->value();
- lengthUnits::eLengthUnits pdfUnits;
- if(tree->pdf->pdfMetersRadioButton->isChecked())
- pdfUnits = lengthUnits::meters;
- else
- pdfUnits = lengthUnits::feet;
- int pdfBase = tree->pdf->backgroundComboBox->currentIndex();
-
- double pdfHeight, pdfWidth;
- int pdfSize = tree->pdf->sizeComboBox->currentIndex();
- // Letter
- if( pdfSize == 0 )
- {
- pdfHeight = 11.0;
- pdfWidth = 8.5;
- }
- // Legal
- else if( pdfSize == 1 )
- {
- pdfHeight = 14.0;
- pdfWidth = 8.5;
- }
- // Tabloid
- else if( pdfSize == 2 )
- {
- pdfHeight = 17.0;
- pdfWidth = 11.0;
- }
- if( tree->pdf->landscapeRadioButton->isChecked() )
- {
- double tmp;
- tmp = pdfWidth;
- pdfWidth = pdfHeight;
- pdfHeight = tmp;
- }
-
- bool writeVTK = tree->vtk->vtkGroupBox->isChecked();
-
- //number of processors
- int nThreads = tree->solve->numProcSpinBox->value();
-
- army = new ninjaArmy();
-
- //count the runs in the wind table
- if( initMethod == WindNinjaInputs::pointInitializationFlag )
- {
- int pointFormat = tree->point->simType;
- std::vector pointFileList = tree->point->stationFileList; //This is for the new way
- std::string pointFile = tree->point->stationFileList[0]; //For Old Format, only can accept 1 file
- std::vector xStartTime = tree->point->startSeries; //Get the start time from pointInput
- std::vector xEndTime = tree->point->endSeries; //Get the Stop time from pointInput
- int numTimeSteps = tree->point->numSteps->value(); //Get the number of steps from pointInput
- bool useTimeList = tree->point->enableTimeseries; //Find out if its a timeseries run or not
- bool writeStationKML = tree->point->writeStationKmlButton->isChecked(); //Write a kml file
- bool writeStationCSV = tree->point->writeStationFileButton->isChecked(); //hidden for now
-
- /*
- * Note that pointFormat is not the same as stationFormat!
- *
- * point Format is based on pointInput::directStationTraffic
- * 0 == old format
- * 1 == new format with time series
- * 2 == new format no time series
- *
- * this is only used in the GUI
- *
- * stationFormat is based on wxStation::GetHeaderVersion
- * 1 == old format
- * 2 == new format, both timeseries and timeseries
- * 3 == csv list that points to list of new format files with time series
- * NOT used in GUI
- * 4 == csv list that points to list of new format files with no time series
- * NOT USED IN GUI
- * based on header only, not actual data!
- * this is used inside the actual simulation
- *
- * A modified version of directstationtraffic has been adapted for CLI use
- * in wxStation::getFirstStationLine
- *
- */
-
- if (pointFormat==0)
- {
- CPLDebug("STATION_FETCH","USING OLD FORMAT...");
- pointInitialization::SetRawStationFilename(pointFile); //Note: When testing this,
- //Only the old format works, so downloaded data, with the date-time column don't yet work!
- /* right now the only option is the old format */
- wxStation::SetStationFormat(wxStation::oldFormat);
- std::vector timeList;
- if(useDiurnal==true || useStability==true) //means that the user is specifying time
- { //Get that time and assign it to the simulation
- std::vector xSingleTime = tree->point->diurnalTimeVec;
- boost::posix_time::ptime singleTime = pointInitialization::generateSingleTimeObject(xSingleTime[0],xSingleTime[1],xSingleTime[2],xSingleTime[3],xSingleTime[4],timeZone);
- timeList.push_back(singleTime);
- }
- else//The user is not giving us time, do what we normally do
- {
- boost::posix_time::ptime noTime;
- timeList.push_back(noTime);
- }
- try{ //Try to run windninja
- army->makePointArmy(timeList,timeZone, pointFile, demFile, true,false);
- }catch (exception& e)
- {
- QMessageBox::critical(this,tr("Failure."),
- "An error occured in makePointArmy() - OldFormat! This is "
- "usually due to a failure in reading a "
- "weather station file. Check your files and "
- "try again - Error Info: "+QString(e.what()),
- QMessageBox::Ok | QMessageBox::Default);
- disconnect(progressDialog, SIGNAL(canceled()), this,
- SLOT(cancelSolve()));
- setCursor(Qt::ArrowCursor); //Restart everything
- progressDialog->cancel();
- progressDialog->hide();
- delete army;
- return false;
- }catch(...){ //catch all exceptions and tell the user, prevent segfaults
-
- QMessageBox::critical(this,tr("Failure."),
- "An error occured in makePointArmy() - OldFormat! This is "
- "usually due to a failure in reading a "
- "weather station file. Check your files and "
- "try again - Error Info: "+QString(pointInitialization::error_msg.c_str()),
- QMessageBox::Ok | QMessageBox::Default);
- disconnect(progressDialog, SIGNAL(canceled()), this,
- SLOT(cancelSolve()));
- setCursor(Qt::ArrowCursor); //Restart everything
- progressDialog->cancel();
- progressDialog->hide();
- delete army;
- return false;
- }
- nRuns = army->getSize();
-
- }
- if (pointFormat==1 || pointFormat==2) //New Format
- {
- wxStation::SetStationFormat(wxStation::newFormat);
- std::vector formatVec;
- std::vector timeList;
- CPLDebug("STATION_FETCH","NEW FORMAT...");
- for (int i=0;imakePointArmy(timeList,timeZone,pointFileList[0],demFile,true,false); //setting pointFileList[0] is just for header checks etc
- }catch (exception& e)
- {
- QMessageBox::critical(this,tr("Failure."),
- "An error occured in makePointArmy() - timeSeries! This is "
- "usually due to a failure in reading a "
- "weather station file. Check your files and "
- "try again - Error Info: "+QString(e.what()),
- QMessageBox::Ok | QMessageBox::Default);
- disconnect(progressDialog, SIGNAL(canceled()), this,
- SLOT(cancelSolve()));
- setCursor(Qt::ArrowCursor);
- progressDialog->cancel();
- progressDialog->hide();
- delete army;
- return false;
- }catch(...){ //catch any and all exceptions and tell the user
-
- QMessageBox::critical(this,tr("Failure."),
- "An error occured in makePointArmy() - timeSeries! This is "
- "usually due to a failure in reading a "
- "weather station file. Check your files and "
- "try again - Error Info: "+QString(pointInitialization::error_msg.c_str()),
- QMessageBox::Ok | QMessageBox::Default);
- disconnect(progressDialog, SIGNAL(canceled()), this,
- SLOT(cancelSolve()));
- setCursor(Qt::ArrowCursor);
- progressDialog->cancel();
- progressDialog->hide();
- delete army;
- return false;
- }
- nRuns = army->getSize();
- }
- if (useTimeList == false)//Current Data/Single Step
- {
- //Get time from file attributes, if its diurnal this matters
- //if not, then it really doesn't matter and who cares
- boost::posix_time::ptime noTime;
- CPLDebug("STATION_FETCH","USING CURRENT WEATHER DATA...");
- std::vector xSingleTime = tree->point->diurnalTimeVec;
- boost::posix_time::ptime singleTime = pointInitialization::generateSingleTimeObject(xSingleTime[0],
- xSingleTime[1],xSingleTime[2],
- xSingleTime[3],xSingleTime[4],timeZone);
- timeList.push_back(singleTime);
- pointInitialization::storeFileNames(pointFileList);
- try{ //try making the army with current data
- army->makePointArmy(timeList,timeZone,pointFileList[0],demFile,true,false);
- }catch (exception& e)
- {
- QMessageBox::critical(this,tr("Failure."),
- "An error occured in makePointArmy() - currentwxdata! This is "
- "usually due to a failure in reading a "
- "weather station file. Check your files and "
- "try again - Error Info: "+QString(e.what()),
- QMessageBox::Ok | QMessageBox::Default);
- disconnect(progressDialog, SIGNAL(canceled()), this,
- SLOT(cancelSolve()));
- setCursor(Qt::ArrowCursor);
- progressDialog->cancel();
- progressDialog->hide();
- delete army;
- return false;
- }catch(...){ //catch any and all exceptions and tell the user
-
- QMessageBox::critical(this,tr("Failure."),
- "An error occured in makePointArmy() - currentwxdata! This is "
- "usually due to a failure in reading a "
- "weather station file. Check your files and "
- "try again - Error Info: "+QString(pointInitialization::error_msg.c_str()),
- QMessageBox::Ok | QMessageBox::Default);
- disconnect(progressDialog, SIGNAL(canceled()), this,
- SLOT(cancelSolve()));
- setCursor(Qt::ArrowCursor);
- progressDialog->cancel();
- progressDialog->hide();
- delete army;
- return false;
- }
- nRuns = army->getSize();
- }
- }
- else
- {
- //Note that This error is not normally reachable if all other error
- //handling works correctly
- CPLDebug("STATION_FETCH","WARNING NOT ALL CSVS ARE OF THE SAME TYPE, CANNOT CONTINUE");
- QMessageBox::critical(this,tr("Failure."),
- "An error occured in deteriming data types This is "
- "usually due to a failure in reading a "
- "weather station file. Check your files and "
- "try again",
- QMessageBox::Ok | QMessageBox::Default);
- disconnect(progressDialog, SIGNAL(canceled()), this,
- SLOT(cancelSolve()));
- setCursor(Qt::ArrowCursor);
- progressDialog->cancel();
- progressDialog->hide();
- delete army;
- return false;
- }
-
-
- }
- if (writeStationKML==true) //Write KMLS for each time step
- {
- std::string outputDir = tree->solve->outputDirectory().toStdString();
- writeToConsole("Writing Weather Station .kml");
- nRuns = army->getSize();
- for (int i_=0;i_getWxStations(i_),
- demFile, (outputDir + "/").c_str(), outputSpeedUnits);
- }
- }
-// if (writeStationCSV==true)
- const char *csvOpt = CPLGetConfigOption("WRITE_CSV","FALSE");
- if(csvOpt!="FALSE") //The only way to write an interpolated CSV is to set a config option
- {
- writeToConsole("Writing Weather Station .csv");
- nRuns = army->getSize();
- QString demBase = QFileInfo(QString(demFile.c_str())).baseName();
- QString demPath = QFileInfo(demFile.c_str()).absoluteDir().absolutePath()+"/";
- std::string csvPath = demPath.toStdString()+demBase.toStdString();
- pointInitialization::writeStationOutFile(army->getWxStations(0),csvPath,"",true);
-
- }
- const char *metaOpt = CPLGetConfigOption("FETCH_METADATA","FALSE");
- if(metaOpt!="FALSE") //set a config option to get the metadata from the DEM
- { //There is also a button for this, that is hidden (see stationFetchWidget)
- writeToConsole("Fetching station metadata for DEM...");
- std::string pathDem = std::string(CPLGetDirname(demFile.c_str()));
- std::string baseDem = std::string(CPLGetBasename(demFile.c_str()));
- std::string baseMeta = baseDem+"-metadata";
- std::string metaPath = std::string(CPLFormFilename(pathDem.c_str(),baseMeta.c_str(),".csv"));
- CPLDebug("STATION_FETCH","Saving Metadata to: %s",metaPath.c_str());
- pointInitialization::fetchMetaData(metaPath,demFile,true);
- }
- }
- else if( initMethod == WindNinjaInputs::domainAverageInitializationFlag )
- {
- nRuns = countRuns();
- //do one run.
- if(nRuns == 0)
- {
- nRuns++;
- }
-#ifdef NINJAFOAM
- army->makeDomainAverageArmy( nRuns, useNinjaFoam);
-#else
- army->makeDomainAverageArmy( nRuns, false);
-#endif
- }
- else if( initMethod == WindNinjaInputs::wxModelInitializationFlag )
- {
- if( !CPLCheckForFile( (char*)weatherFile.c_str(), NULL ) )
- {
- QMessageBox::critical( this, tr( "Invalid forecast file." ),
- tr( "The forecast file does not exist, " \
- "or it cannot be read." ),
- QMessageBox::Ok | QMessageBox::Default );
- disconnect(progressDialog, SIGNAL(canceled()), this, SLOT(cancelSolve()));
- setCursor(Qt::ArrowCursor);
- tree->weather->checkForModelData();
- progressDialog->cancel();
- return false;
- }
-
- std::vector times = tree->weather->timeList();
- /* This can throw a badForecastFile */
- try
- {
-#ifdef NINJAFOAM
- army->makeWeatherModelArmy( weatherFile, timeZone, times, useNinjaFoam );
-#else
- army->makeWeatherModelArmy( weatherFile, timeZone, times, false );
-#endif
- }
- catch( badForecastFile &e )
- {
- QMessageBox::critical( this, tr( "Invalid forecast file." ),
- tr( "The forecast cannot be read." ),
- QMessageBox::Ok | QMessageBox::Default );
- disconnect(progressDialog, SIGNAL(canceled()), this, SLOT(cancelSolve()));
- setCursor(Qt::ArrowCursor);
- tree->weather->checkForModelData();
- progressDialog->cancel();
- progressDialog->hide();
- delete army;
- return false;
- } catch (...) {
- QMessageBox::critical(
- this, tr("Failure."),
- tr("An unknown error occurred in makeWeatherModelArmy(). This is usually "
- "due to a failure in reading the weather model file"),
- QMessageBox::Ok | QMessageBox::Default);
- disconnect(progressDialog, SIGNAL(canceled()), this,
- SLOT(cancelSolve()));
- setCursor(Qt::ArrowCursor);
- tree->weather->checkForModelData();
- progressDialog->cancel();
- progressDialog->hide();
- delete army;
- return false;
- }
- nRuns = army->getSize();
- }
-
- progressDialog->setValue( 0 );
- //set progress dialog and initial value
- progressDialog->setRange(0, nRuns * 100); //Expand the dialog to the number of runs
- runProgress = new int[nRuns]; //I don't think this is needed anymore
-
- std::string outputDir = tree->solve->outputDirectory().toStdString();
- if( outputDir == "" ) {
- // This should never happen, so if it does, fix it.
- progressDialog->cancel();
- progressDialog->hide();
- QMessageBox::critical(
- this, tr("Failure."),
- tr("no output directory specified in solve page"),
- QMessageBox::Ok | QMessageBox::Default);
- disconnect(progressDialog, SIGNAL(canceled()), this,
- SLOT(cancelSolve()));
- setCursor(Qt::ArrowCursor);
- tree->weather->checkForModelData();
- delete army;
- return false;
- }
-
- //fill in the values
- for(int i = 0;i < army->getSize(); i++)
- {
-
- army->setDEM( i, demFile );
-#ifdef NINJAFOAM
- if(caseFile != ""){
- army->setExistingCaseDirectory( i, caseFile );
- }
-#endif
- //set initialization
- if( initMethod != WindNinjaInputs::wxModelInitializationFlag )
- {
- army->setInitializationMethod( i, initMethod, true );
- }
- //set the ninjaCom
- army->setNinjaCommunication( i, i, ninjaComClass::ninjaGUICom );
-
- //set the input file
- //army.readInputFile( i, demFile );
-
- if( inputFileType != LCP )
- {
- army->setUniVegetation( i, vegetation );
- }
- if( initMethod == WindNinjaInputs::pointInitializationFlag ) //Moved to makePointArmy
- {
-
- }
- else if( initMethod == WindNinjaInputs::domainAverageInitializationFlag )
- {
- //get speed
- army->setInputSpeed( i,
- tree->wind->windTable->speed[i]->value(),
- inputSpeedUnits);
- //get direction
- army->setInputDirection( i, tree->wind->windTable->dir[i]->value() );
-
- army->setInputWindHeight ( i, inHeight, inHeightUnits );
- }
-
- //set input output height
- army->setOutputWindHeight( i, outHeight, outHeightUnits );
-
- //set output speed units
- army->setOutputSpeedUnits( i, outputSpeedUnits );
-
- //set clipping
- army->setOutputBufferClipping( i, (double) clip );
-
- army->setOutputPath( i, outputDir.c_str() );
-
- //diurnal, if needed
- army->setDiurnalWinds( i, useDiurnal );
- if( useDiurnal == true )
- {
- if( initMethod == WindNinjaInputs::domainAverageInitializationFlag )
- {
- army->setDateTime( i, tree->wind->windTable->date[i]->date().year(),
- tree->wind->windTable->date[i]->date().month(),
- tree->wind->windTable->date[i]->date().day(),
- tree->wind->windTable->time[i]->time().hour(),
- tree->wind->windTable->time[i]->time().minute(),
- 0, timeZone );
- army->setUniAirTemp( i,
- tree->wind->windTable->airTemp[i]->value(),
- tempUnits );
- army->setUniCloudCover( i,
- tree->wind->windTable->cloudCover[i]->value(),
- coverUnits::percent );
- army->setPosition( i, GDALCenterLat, GDALCenterLon );
- }
- else if( initMethod == WindNinjaInputs::pointInitializationFlag )
- {
- army->setPosition( i, GDALCenterLat, GDALCenterLon );
- }
- else if( initMethod == WindNinjaInputs::wxModelInitializationFlag )
- {
- army->setPosition( i );
- }
- }
- else // initMethod is wxModelInitialization or useDiurnal is false
- {
- army->setPosition( i );
- }
-
- //stability, if needed, check for diurnal also so we don't repeat setters
- if( useStability == true && useDiurnal == false )
- {
- if( initMethod == WindNinjaInputs::domainAverageInitializationFlag )
- {
- army->setDateTime( i, tree->wind->windTable->date[i]->date().year(),
- tree->wind->windTable->date[i]->date().month(),
- tree->wind->windTable->date[i]->date().day(),
- tree->wind->windTable->time[i]->time().hour(),
- tree->wind->windTable->time[i]->time().minute(),
- 0, timeZone );
- army->setUniAirTemp( i,
- tree->wind->windTable->airTemp[i]->value(),
- tempUnits );
- army->setUniCloudCover( i,
- tree->wind->windTable->cloudCover[i]->value(),
- coverUnits::percent );
- army->setPosition( i, GDALCenterLat, GDALCenterLon );
- }
- else if( initMethod == WindNinjaInputs::pointInitializationFlag ) //Moved to makePointArmy
- {
- army->setPosition( i, GDALCenterLat, GDALCenterLon );
- }
- }
- army->setStabilityFlag( i, useStability );
- //set mesh stuff
- if( customMesh )
- {
- army->setMeshResolution( i, meshRes, meshUnits );
- }
- else
- {
-#ifdef NINJAFOAM
- if(useNinjaFoam){
- army->setMeshCount( i, ninjafoamMeshChoice );
- army->setNumberOfIterations( i, 300);
- }
- else
- army->setMeshResolutionChoice( i, meshChoice );
-#else
- army->setMeshResolutionChoice( i, meshChoice );
-#endif
- }
-
- army->setNumVertLayers( i, 20 );
-
- //set the input file
- //army.ninjas[i].readInputFile( demFile );
- //army->setDEM( i, demFile );
- // this is commented out?
- //army.ninjas[i].mesh.compute_domain_height();
-
- //set number of cpus...
- //army.setnumberCPUs(1);
-
- army->setGoogOutFlag (i,writeGoogle);
- army->setGoogLineWidth (i,vectorWidth);
- army->setGoogResolution (i,googleRes,googleUnits);
- army->setGoogSpeedScaling(i,googleScale);
- army->setGoogColor (i,googleScheme,googVectorScaling); //FIX ME
- army->setGoogConsistentColorScale(i,googConsistentColorScale,nRuns);
- army->setShpOutFlag (i,writeShape);
- army->setShpResolution (i,shapeRes,shapeUnits);
- army->setPDFOutFlag (i,writePdf);
- army->setPDFResolution (i,pdfRes,pdfUnits);
- army->setPDFLineWidth (i,pdfLineWidth);
- army->setPDFBaseMap (i,pdfBase);
- army->setPDFSize (i,pdfHeight,pdfWidth,150);
- army->setAsciiOutFlag (i,writeFb);
- army->setAsciiAaigridOutFlag(i,writeFb);
- army->setAsciiProjOutFlag(i,writeFb);
- army->setAsciiResolution (i,fbRes,fbUnits);
- //army->setWriteAtmFile (i,writeAtm );
- army->setVtkOutFlag (i,writeVTK);
-
- if( initMethod == WindNinjaInputs::wxModelInitializationFlag &&
- writeWxOutput == true )
- {
- army->setWxModelGoogOutFlag( i, writeGoogle );
- army->setWxModelShpOutFlag( i, writeShape );
- army->setWxModelAsciiOutFlag( i, writeFb );
- }
-
- //army.setOutputFilenames();
- army->setNinjaComNumRuns( i, nRuns );
- }
-
- army->set_writeFarsiteAtmFile( writeAtm && writeFb );
-
- for( unsigned int i = 0; i < army->getSize(); i++ )
- {
- progressLog.push_back(0); //Initialize the progressLog, which stores the progress of each ninja with a zero for each ninja in the army
- }
-
- totalProgress = 0;
-
- progressDialog->setLabelText("Solving...");
-
- /*
- connect(army.Com, SIGNAL(sendMessage(QString, QColor)),
- this, SLOT(writeToConsole(QString, QColor)),
- Qt::AutoConnection);
- */
- for( unsigned int i = 0; i < army->getSize(); i++ )
- {
- connect( army->getNinjaCom( i ),
- SIGNAL( sendMessage( QString, QColor ) ), this,
- SLOT( updateProgress( QString ) ), Qt::AutoConnection );
-
- connect( army->getNinjaCom( i ),
- SIGNAL( sendProgress( int, int ) ), this,
- SLOT( updateProgress( int, int ) ), Qt::AutoConnection );
-
- connect( army->getNinjaCom( i ),
- SIGNAL( sendMessage(QString, QColor)),
- this, SLOT(writeToConsole(QString, QColor ) ),
- Qt::AutoConnection );
- }
- writeToConsole(QString::number( army->getSize() ) + " runs initialized. Starting solver...");
- //sThread->start();
-
- progressDialog->setValue( 0 );
- runTime->restart();
- connect( progressDialog, SIGNAL(canceled() ),
- this, SLOT( cancelSolve() ) );
-
- progressDialog->setCancelButtonText( "Cancel" );
-
- setCursor( Qt::WaitCursor );
-
- progressDialog->setLabelText( "Running..." );
-
- writeToConsole( "Initializing runs..." );
-
- bool ninjaSuccess = false;
- //ninjaSuccess = sThread->run( nThreads, army );
- //start the army
- try {
- ninjaSuccess = army->startRuns( nThreads );
- }
- catch (bad_alloc& e)
- {
- progressDialog->cancel();
- QMessageBox::warning(this, tr("Exception Caught"),
- tr("WindNinja may have run out of memory. This may be caused by too fine of a mesh resolution."),
- QMessageBox::Ok | QMessageBox::Default);
-
- disconnect(progressDialog, SIGNAL(canceled()), this, SLOT(cancelSolve()));
- setCursor(Qt::ArrowCursor);
- delete army;
- return false;
- }
- catch (cancelledByUser& e)
- {
- progressDialog->cancel();
- QMessageBox::warning(this, tr("Exception Caught"),
- tr(e.what()),
- QMessageBox::Ok | QMessageBox::Default);
- disconnect(progressDialog, SIGNAL(canceled()), this, SLOT(cancelSolve()));
- setCursor(Qt::ArrowCursor);
- delete army;
- return false;
- }
- catch (exception& e)
- {
- progressDialog->cancel();
- QMessageBox::warning(this, tr("Exception Caught"),
- tr(e.what()),
- QMessageBox::Ok | QMessageBox::Default);
- disconnect(progressDialog, SIGNAL(canceled()), this, SLOT(cancelSolve()));
- setCursor(Qt::ArrowCursor);
- delete army;
- return false;
- }
- catch (...)
- {
- progressDialog->cancel();
- QMessageBox::warning(this, tr("Exception Caught"),
- tr("Unknown Exception"),
- QMessageBox::Ok | QMessageBox::Default);
- disconnect(progressDialog, SIGNAL(canceled()), this, SLOT(cancelSolve()));
- setCursor(Qt::ArrowCursor);
- delete army;
- return false;
- }
-
- disconnect(progressDialog, SIGNAL(canceled()), this, SLOT(cancelSolve()));
-
- writeToConsole("Finished with simulations", Qt::darkGreen);
- //updateTimer();
-
- elapsedRunTime = runTime->elapsed() / 1000.0;
- int maxProg = nRuns*100;
- progressDialog->setValue(maxProg);
- progressDialog->setLabelText("Simulations finished");
- progressDialog->setCancelButtonText("Close");
- progressLog.clear(); //Clear the progress bar so that we can do another run later without
- //killing the program
-
- //Everything went okay? enable output path button
- tree->solve->openOutputPathButton->setEnabled( true );
- outputPath = QString::fromStdString( outputDir );
-
- //clear the army
- army->reset();
-
- setCursor(Qt::ArrowCursor);
-
- delete army;
- return ninjaSuccess;
-}
-
-void mainWindow::updateProgress(const QString message)
-{
- progressDialog->setLabelText(message);
-}
-
-void mainWindow::updateProgress(int run, int progress)
-{
- totalProgress = 0; //Initialize the progress bar each time
-// runProgress[run]=progress;
-
- if(progressLog[run]>progress)
- {
-/*
- * If the stored progress is bigger than what we are seeing in the currently emitted progress
- * ignore it
- * this happens for pointInitialization, when the match points is iterating
- * sometimes its next solution is worse and then it would make the progress bar go backwards
- * by ignoring it, the progress bar just stays where it is....
- */
- progressLog[run]=progressLog[run];
- }
- else //Otherwise, store the progress in the progressLog
- {
- progressLog[run]=progress;
- }
- for(int i = 0;i < nRuns;i++) //Iterate over the number of runs and sum up the progress from the Log
- {
- totalProgress+=progressLog[i];
-
- }
- progressDialog->setValue(totalProgress); //Set the progress to what we have summed
-}
-
-int mainWindow::countRuns()
-{
- int runs = 0;
-
- for(int i=0; i < tree->wind->windTable->nRuns; i++)
- {
- if(tree->wind->windTable->speed[i]->value() != 0 || tree->wind->windTable->dir[i]->value() != 0)
- {
- runs = i+1; // i goes from 0 to N-1, runs goes from 1 to N
- }
- }
-
- return runs;
-}
-
-int mainWindow::checkAllItems()
-{
- //check and see if the objects have been visited before changing
- eInputStatus status = green;
-#ifdef NINJAFOAM
- checkSolverMethodItem();
- checkMeshCombo();
-#endif
- checkInputItem();
- checkOutputItem();
- checkSolveItem();
-
- return status;
-}
-
-#ifdef NINJAFOAM
-int mainWindow::checkSolverMethodItem()
-{
- eInputStatus status = blue;
-
- checkNativeSolverItem();
- checkNinjafoamItem();
-
- if(checkNativeSolverItem() == green)
- {
- tree->solverMethodItem->setIcon(0, tree->check);
- tree->solverMethodItem->setToolTip(0, "Using conservation of mass solver");
- checkNinjafoamItem();
- status = green;
- }
- else if(checkNinjafoamItem() == green)
- {
- tree->solverMethodItem->setIcon(0, tree->check);
- tree->solverMethodItem->setToolTip(0, "Using conservation of mass and momentum solver");
- checkNativeSolverItem();
- status = green;
- }
- else
- {
- tree->solverMethodItem->setIcon(0, tree->cross);
- tree->solverMethodItem->setToolTip(0, "Select a solver");
- status = red;
- }
- return status;
-}
-
-int mainWindow::checkNativeSolverItem()
-{
- eInputStatus status = green;
- if(!tree->nativesolver->nativeSolverGroupBox->isChecked())
- {
- tree->nativeSolverItem->setIcon(0, tree->radio);
- tree->nativeSolverItem->setToolTip(0, "Conservation of Mass not selected");
- status = blue;
- }
- else
- {
- tree->nativeSolverItem->setIcon(0, tree->check);
- tree->nativeSolverItem->setToolTip(0, "Conservation of Mass selected");
- status = green;
- }
-
- return status;
-}
-int mainWindow::checkNinjafoamItem()
-{
- eInputStatus status = green;
- if(!tree->ninjafoam->ninjafoamGroupBox->isChecked())
- {
- tree->ninjafoamItem->setIcon(0, tree->radio);
- tree->ninjafoamItem->setToolTip(0, "Conservation of Mass and Momentum not selected");
- status = blue;
- }
- else
- {
- tree->ninjafoamItem->setIcon(0, tree->check);
- tree->ninjafoamItem->setToolTip(0, "Conservation of Mass and Momentum selected");
- status = green;
- }
-
- return status;
-}
-#endif //NINJAFOAM
-
-int mainWindow::checkInputItem()
-{
- eInputStatus status = red;
-
- checkWindItem();
-
- if(checkSurfaceItem() == red && checkWindItem() == red && checkDiurnalItem() == red || checkStabilityItem() == red)
- {
- tree->inputItem->setIcon(0, tree->cross);
- tree->inputItem->setToolTip(0, "Check surface input, wind input, stability input, and diurnal input");
- status = red;
- }
- if(checkSurfaceItem() == red && checkWindItem() == red && checkDiurnalItem() == red )
- {
- tree->inputItem->setIcon(0, tree->cross);
- tree->inputItem->setToolTip(0, "Check surface input, wind input and diurnal input");
- status = red;
- }
- else if(checkSurfaceItem() == red)
- {
- tree->inputItem->setIcon(0, tree->cross);
- tree->inputItem->setToolTip(0, "Check surface input");
- status = red;
- }
- else if(checkDiurnalItem() == red)
- {
- tree->inputItem->setIcon(0, tree->caution);
- tree->inputItem->setToolTip(0, "Check diurnal input");
- status = red;
- }
- else if(checkStabilityItem() == red)
- {
- tree->inputItem->setIcon(0, tree->caution);
- tree->inputItem->setToolTip(0, "Check stability input");
- status = red;
- }
- else if(checkWindItem() == red)
- {
- tree->inputItem->setIcon(0, tree->cross);
- tree->inputItem->setToolTip(0, "Check wind input");
- status = red;
- }
- else
- {
- tree->inputItem->setIcon(0, tree->check);
- tree->inputItem->setToolTip(0, "Valid");
- status = green;
- }
- return status;
-}
-
-int mainWindow::checkSurfaceItem()
-{
- eInputStatus status = red;
- if(inputFileName == "" || !QFile::exists(inputFileName))
- {
- tree->surfaceItem->setIcon(0, tree->cross);
- tree->surfaceItem->setToolTip(0, "The input file cannot be opened");
- status = red;
- }
- else if(!hasPrj)
- {
- tree->surfaceItem->setIcon(0, tree->caution);
- tree->surfaceItem->setToolTip(0, "No projection information");
- status = red;
- }
- else
- {
- tree->surfaceItem->setIcon(0, tree->check);
- tree->surfaceItem->setToolTip(0, "Valid");
- status = green;
- }
- return status;
-}
-
-int mainWindow::checkDiurnalItem()
-{
- eInputStatus status = green;
- if(!tree->diurnal->diurnalGroupBox->isChecked()) {
- tree->diurnalItem->setIcon(0, tree->blue);
- tree->diurnalItem->setToolTip(0, "No Diurnal Input");
- status = blue;
- }
- else
- {
- tree->diurnalItem->setIcon(0, tree->check);
- status = green;
- }
- return status;
-}
-
-int mainWindow::checkStabilityItem()
-{
- eInputStatus status = green;
- if(!tree->stability->stabilityGroupBox->isChecked())
- {
- tree->stabilityItem->setIcon(0, tree->blue);
- tree->stabilityItem->setToolTip(0, "No Stability Input");
- status = blue;
- }
- else
- {
- tree->stabilityItem->setIcon(0, tree->check);
- status = green;
- }
- return status;
-}
-
-int mainWindow::checkWindItem()
-{
- eInputStatus status = blue;
-
- //check all once, just to update icons
- checkSpdDirItem();
- checkPointItem();
- checkWeatherItem();
-
- if( checkSpdDirItem() == blue && checkPointItem() == blue
- && checkWeatherItem() == blue ) {
- tree->windItem->setIcon(0, tree->cross);
- tree->windItem->setToolTip(0, "No initialization selected");
- status = red;
- }
- else if( checkSpdDirItem() == red ) {
- tree->windItem->setIcon(0, tree->cross);
- tree->windItem->setToolTip(0, "Check speed and direction");
- status = red;
- }
- else if( checkSpdDirItem() == amber ) {
- tree->windItem->setIcon(0, tree->caution);
- tree->windItem->setToolTip(0, "No runs have been added, one run will be done at speed = 0, dir = 0");
- status = amber;
- }
- else if( checkPointItem() == red ) {
- tree->windItem->setIcon(0, tree->cross);
- tree->windItem->setToolTip(0, "Check point initialization");
- status = red;
- }
- else if( checkWeatherItem() == red ) {
- tree->windItem->setIcon(0, tree->cross);
- tree->windItem->setToolTip(0, "Check weather model initialization");
- status = red;
- }
- else {
- tree->windItem->setIcon(0, tree->check);
- tree->windItem->setToolTip(0, "Valid");
- status = green;
- }
- return status;
-}
-
-int mainWindow::checkSpdDirItem()
-{
- int runs = countRuns();
- eInputStatus status = blue;
- if( tree->wind->windGroupBox->isChecked() ) {
- if(checkSurfaceItem() != red) {
- if(runs == 0 && tree->diurnal->diurnalGroupBox->isChecked() == false) {
- tree->spdDirItem->setIcon(0, tree->cross);
- tree->spdDirItem->setToolTip(0, "No runs have been added, diurnal is not active");
- status = red;
- }
- else if(runs == 0 && tree->diurnal->diurnalGroupBox->isChecked() == true) {
- tree->spdDirItem->setIcon(0, tree->caution);
- tree->spdDirItem->setToolTip(0, "No runs have been added, one run will be done at speed = 0, dir = 0 while using diurnal");
- status = amber;
- }
- else {
- tree->spdDirItem->setIcon(0, tree->check);
- tree->spdDirItem->setToolTip(0, QString::number(runs) + " runs");
- status = green;
- // override if any 0.0 wind speed runs are detected, warn and run if diurnal, stop if not diurnal
- for(int i=0;iwind->windTable->speed[i]->value() == 0.0)
- {
- if(tree->diurnal->diurnalGroupBox->isChecked() == false) {
- tree->spdDirItem->setIcon(0, tree->cross);
- tree->spdDirItem->setToolTip(0, QString::number(runs) + " runs have been added, but detecting at least one 0.0 wind speed run without diurnal being active");
- status = red;
- } else {
- tree->spdDirItem->setIcon(0, tree->caution);
- tree->spdDirItem->setToolTip(0, QString::number(runs) + " runs have been added, detecting at least one 0.0 wind speed run, diurnal is active so will continue the runs");
- status = amber;
- }
- break;
- }
- }
- }
- }
- else {
- tree->spdDirItem->setIcon(0, tree->cross);
- tree->spdDirItem->setToolTip(0, "Cannot read input file");
- status = red;
- }
- }
- else {
- tree->spdDirItem->setIcon(0, tree->radio);
- tree->spdDirItem->setToolTip(0, "Not used");
- status = blue;
- }
- return status;
-}
-int mainWindow::checkPointItem()
-{
- eInputStatus status = blue;
- if( tree->point->pointGroupBox->isChecked() ) {
- bool shortGo=tree->point->pointGo;
- if (shortGo==false)
- {
- if (tree->point->stationFileList.size()<1)
- {
- status = red;
- tree->pointItem->setIcon(0,tree->cross);
- tree->pointItem->setToolTip(0,"No Stations Selected");
- }
- if (tree->point->stationFileList.size()==1)
- {
- status = red;
- tree->pointItem->setIcon(0,tree->cross);
- tree->pointItem->setToolTip(0,"No Valid Data detected...");
- }
- if (tree->point->stationFileList.size()>=2)
- {
- status = red;
- tree->pointItem->setIcon(0,tree->cross);
- tree->pointItem->setToolTip(0,"Mismatched Data Type selected");
- }
-// if else
-// {
-// status = red;
-// tree->pointItem->setIcon(0,tree->cross);
-// tree->pointItem->setToolTip(0,"Selected options are invald");
-// }
- }
-
- if (shortGo==true)
- {
- //Check to make sure times are reasonable
- QDateTime pStartTime = tree->point->startTime->dateTime();
- QDateTime pStopTime = tree->point->stopTime->dateTime();
- if(pStartTime>pStopTime)
- {
- status = red;
- tree->pointItem->setIcon(0,tree->cross);
- tree->pointItem->setToolTip(0,"Start Time is Greater than Stop Time!");
- }
- else
- {
- status = green;
- tree->pointItem->setIcon(0,tree->check);
- tree->pointItem->setToolTip(0,"Good To Go!");
- }
- }
- std::vector pfL = tree->point->stationFileList;
- for(int i=0;ipointItem->setIcon(0,tree->cross);
- tree->pointItem->setToolTip(0,"File Extension Must be .csv!");
- }
- }
- if (tree->point->simType==0 && pfL.size()>1)
- {
- status = red;
- tree->pointItem->setIcon(0,tree->cross);
- tree->pointItem->setToolTip(0,"Too many Stations Selected for Old Format!");
-
- }
-
-// else {
-// status = green;
-// tree->pointItem->setIcon( 0, tree->check );
-// tree->pointItem->setToolTip( 0, "Valid" );
-// }
- }
- else {
- status = blue;
- tree->pointItem->setIcon( 0, tree->radio );
- tree->pointItem->setToolTip( 0, "Not used" );
- }
- return status;
-}
-
-int mainWindow::checkWeatherItem()
-{
- eInputStatus status = blue;
- wxModelInitialization* model = NULL;
- if( tree->weather->weatherGroupBox->isChecked() ) {
- QFileInfo fi;
- QModelIndex mi = tree->weather->treeView->selectionModel()->currentIndex();
- if( mi.isValid() ) {
- fi = tree->weather->model->fileInfo( mi );
- std::string filename = fi.absoluteFilePath().toStdString();
- char *p, *q; //code gore
- p = strdup( filename.c_str() );
- q = strrchr( p, '/' );
- int n = 0;
- if( !q )
- q = strrchr( p, '\\' );
- if( q )
- {
- if( strlen( q ) > 1 )
- q++;
- if( strlen( q ) > 5 )
- *(q + 4) = '\0';
- n = atoi( q );
- }
- else
- n = atoi( p );
- free( p );
- if( fi.isDir() && n < 2000 )
- {
- status = red;
- tree->modelItem->setIcon( 0, tree->cross );
- tree->modelItem->setToolTip( 0, "Forecast is invalid" );
- return status;
- }
- try {
- model = wxModelInitializationFactory::makeWxInitialization(filename);
- }
- catch( ... ) {
- status = red;
- tree->modelItem->setIcon( 0, tree->cross );
- tree->modelItem->setToolTip( 0, "Forecast is invalid" );
- delete model;
- return status;
- }
-
- if( !fi.exists() ) {
- status = red;
- tree->modelItem->setIcon( 0, tree->cross );
- tree->modelItem->setToolTip( 0, "Forecast does not exist" );
- }
- else {
- status = green;
- tree->modelItem->setIcon( 0, tree->check );
- tree->modelItem->setToolTip( 0, "Valid" );
- }
- }
- else {
- status = red;
- tree->modelItem->setIcon( 0, tree->cross );
- tree->modelItem->setToolTip( 0, "You must select a valid forecast file or path" );
- }
- }
- else {
- tree->modelItem->setIcon( 0, tree->radio );
- tree->modelItem->setToolTip( 0, "Not used" );
- }
- delete model;
- return status;
-}
-
-int mainWindow::checkOutputItem()
-{
- eInputStatus status = green;
- if(checkSurfaceItem() == red)
- {
- tree->outputItem->setIcon(0, tree->cross);
- tree->outputItem->setToolTip(0, "Cannot read input file");
- status = red;
- }
- if(checkGoogleItem() == blue && checkFbItem() == blue && checkShapeItem() == blue && checkVtkItem() == blue &&
- checkPdfItem() == blue)
- {
- tree->outputItem->setIcon(0, tree->cross);
- tree->outputItem->setToolTip(0, "No outputs selected");
- status = red;
- }
- if(checkGoogleItem() == amber || checkFbItem() == amber || checkShapeItem() == amber || checkVtkItem() == amber ||
- checkPdfItem() == amber)
- {
- if(checkGoogleItem() == amber)
- {
- tree->outputItem->setIcon(0, tree->caution);
- tree->outputItem->setToolTip(0, "Check Google ouput");
- status = amber;
- }
- if(checkFbItem() == amber)
- {
- tree->outputItem->setIcon(0, tree->check);
- tree->outputItem->setToolTip(0, "Check fire behavior ouput");
- status = amber;
- }
- if(checkShapeItem() == amber)
- {
- tree->outputItem->setIcon(0, tree->check);
- tree->outputItem->setToolTip(0, "Check shape file ouput");
- status = amber;
- }
- if(checkPdfItem() == amber)
- {
- tree->outputItem->setIcon(0, tree->check);
- tree->outputItem->setToolTip(0, "Check pdf file ouput");
- status = amber;
- }
- if(checkVtkItem() == amber)
- {
- tree->outputItem->setIcon(0, tree->check);
- tree->outputItem->setToolTip(0, "Check vtk file ouput");
- status = amber;
- }
- }
- if(status == green)
- {
- tree->outputItem->setIcon(0, tree->check);
- tree->outputItem->setToolTip(0, "Valid");
- status = green;
- }
- return status;
-}
-
-int mainWindow::checkGoogleItem()
-{
- eInputStatus status = red;
- if(!tree->google->googleGroupBox->isChecked())
- {
- tree->googleItem->setIcon(0, tree->blue);
- tree->googleItem->setToolTip(0, "No output");
- status = blue;
- }
- else
- {
- if(checkSurfaceItem() != red)
- {
- if(noGoogleCellSize > tree->google->googleResSpinBox->value())
- {
- tree->googleItem->setIcon(0, tree->caution);
- tree->googleItem->setToolTip(0, "The resolution of the google file may be too fine.");
- status = amber;
- }
- else if(GDALCellSize > tree->google->googleResSpinBox->value())
- {
- tree->googleItem->setIcon(0, tree->caution);
- tree->googleItem->setToolTip(0, "The output resolution is finer than the DEM resolution");
- status = amber;
- }
- /*
- else if((int)meshCellSize > tree->google->googleResSpinBox->value())
- {
- tree->googleItem->setIcon(0, tree->check);
- tree->googleItem->setToolTip(0, "The output resolutions is finer than the computational mesh");
- status = amber;
- }
- */
- else
- {
- tree->googleItem->setIcon(0, tree->check);
- tree->googleItem->setToolTip(0, "Valid");
- status = green;
- }
- }
- else
- {
- tree->googleItem->setIcon(0, tree->cross);
- tree->googleItem->setToolTip(0, "Cannot read input file");
- status = red;
- }
- }
- return status;
-}
-
-int mainWindow::checkFbItem()
-{
- eInputStatus status = red;
- if(!tree->fb->fbGroupBox->isChecked())
- {
- tree->fbItem->setIcon(0, tree->blue);
- tree->fbItem->setToolTip(0, "No output");
- status = blue;
- }
- else
- {
- if(checkSurfaceItem() == green || checkSurfaceItem() == amber)
- {
- if(GDALCellSize > tree->fb->fbResSpinBox->value())
- {
- tree->fbItem->setIcon(0, tree->caution);
- tree->fbItem->setToolTip(0, "The output resolutions is finer than the DEM resolution");
- status = amber;
- }
-
- else
- {
- tree->fbItem->setIcon(0, tree->check);
- tree->fbItem->setToolTip(0, "Valid");
- status = green;
- }
- }
- else
- {
- tree->fbItem->setIcon(0, tree->cross);
- tree->fbItem->setToolTip(0, "Cannot read input file");
- status = red;
- }
- }
- return status;
-}
-
-int mainWindow::checkShapeItem()
-{
- eInputStatus status = red;
- if(!tree->shape->shapeGroupBox->isChecked())
- {
- tree->shapeItem->setIcon(0, tree->blue);
- tree->shapeItem->setToolTip(0, "No output");
- status = blue;
- }
- else
- {
- if(checkSurfaceItem() == green || checkSurfaceItem() == amber)
- {
- /*
- if((int)meshCellSize > tree->shape->shapeResSpinBox->value())
- {
- tree->shapeItem->setIcon(0, tree->check);
- tree->shapeItem->setToolTip(0, "The output resolutions is finer than the computational mesh");
- status = amber;
- }
- */
- if(GDALCellSize > tree->shape->shapeResSpinBox->value())
- {
- tree->shapeItem->setIcon(0, tree->caution);
- tree->shapeItem->setToolTip(0, "The output resolutions is finer than the DEM resolution");
- status = amber;
- }
- else
- {
- tree->shapeItem->setIcon(0, tree->check);
- tree->shapeItem->setToolTip(0, "Valid");
- status = green;
- }
- }
- else
- {
- tree->shapeItem->setIcon(0, tree->cross);
- tree->shapeItem->setToolTip(0, "Cannot read input file") ;
- status = red;
- }
- }
- return status;
-}
-
-int mainWindow::checkPdfItem()
-{
- eInputStatus status = red;
- if(!tree->pdf->pdfGroupBox->isChecked())
- {
- tree->pdfItem->setIcon(0, tree->blue);
- tree->pdfItem->setToolTip(0, "No output");
- status = blue;
- }
- else
- {
- if(checkSurfaceItem() == green || checkSurfaceItem() == amber)
- {
- /*
- if((int)meshCellSize > tree->pdf->pdfResSpinBox->value())
- {
- tree->pdfItem->setIcon(0, tree->check);
- tree->pdfItem->setToolTip(0, "The output resolutions is finer than the computational mesh");
- status = amber;
- }
- */
- if(GDALCellSize > tree->pdf->pdfResSpinBox->value())
- {
- tree->pdfItem->setIcon(0, tree->caution);
- tree->pdfItem->setToolTip(0, "The output resolutions is finer than the DEM resolution");
- status = amber;
- }
- else
- {
- tree->pdfItem->setIcon(0, tree->check);
- tree->pdfItem->setToolTip(0, "Valid");
- status = green;
- }
- }
- else
- {
- tree->pdfItem->setIcon(0, tree->cross);
- tree->pdfItem->setToolTip(0, "Cannot read input file") ;
- status = red;
- }
- }
- return status;
-}
-
-int mainWindow::checkVtkItem()
-{
- eInputStatus status = red;
- if(!tree->vtk->vtkGroupBox->isChecked())
- {
- tree->vtkItem->setIcon(0, tree->blue);
- tree->vtkItem->setToolTip(0, "No output");
- status = blue;
- }
- else
- {
- if(checkSurfaceItem() == green || checkSurfaceItem() == amber)
- {
- tree->vtkItem->setIcon(0, tree->check);
- tree->vtkItem->setToolTip(0, "Valid");
- status = green;
- }
- else
- {
- tree->vtkItem->setIcon(0, tree->cross);
- tree->vtkItem->setToolTip(0, "Cannot read input file") ;
- status = red;
- }
- }
- return status;
-}
-
-int mainWindow::checkSolveItem()
-{
- eInputStatus status = red;
- if(checkInputItem() != red && checkOutputItem() != red)
- {
- tree->solveItem->setIcon(0, tree->check);
- tree->solveItem->setToolTip(0, "You may start the solver");
- tree->solve->solveToolButton->setEnabled(true);
- status = green;
- }
- //handle if nothing is checked for initialization
- else if( !tree->wind->windGroupBox->isChecked() &&
- !tree->point->pointGroupBox->isChecked() &&
- !tree->weather->weatherGroupBox->isChecked () ) {
- tree->solveItem->setIcon(0, tree->cross);
- tree->solveItem->setToolTip(0, "You must select and initialization method");
- tree->solve->solveToolButton->setEnabled(false);
- status = red;
- }
- else
- {
- tree->solveItem->setIcon(0, tree->cross);
- tree->solveItem->setToolTip(0, "There are errors in the inputs or outputs");
- tree->solve->solveToolButton->setEnabled(false);
- status = red;
- }
- return status;
-}
-
-int mainWindow::checkKmlLimit(double xx)
-{
- eInputStatus status = amber;
- if((int)noGoogleCellSize > tree->google->googleResSpinBox->value())
- {
- writeToConsole("The resolution of the google file may be too fine.", orange);
- status = amber;
- }
- return amber;
-}
-
-void mainWindow::cancelSolve()
-{
- progressDialog->setAutoClose(true);
- progressDialog->setLabelText("Canceling...");
- army->cancel();
-}
-
-void mainWindow::treeDoubleClick(QTreeWidgetItem *item, int column)
-{
- if(item == tree->surfaceItem)
- openInputFile();
- else if(item == tree->diurnalItem)
- {
- if(tree->diurnal->diurnalGroupBox->isChecked())
- tree->diurnal->diurnalGroupBox->setChecked(false);
- else
- tree->diurnal->diurnalGroupBox->setChecked(true);
- }
-#ifdef NINJAFOAM
- else if(item == tree->nativeSolverItem)
- {
- if(tree->nativesolver->nativeSolverGroupBox->isChecked())
- tree->nativesolver->nativeSolverGroupBox->setChecked(false);
- else{
- tree->nativesolver->nativeSolverGroupBox->setChecked(true);
- }
- }
- else if(item == tree->ninjafoamItem)
- {
- if(tree->ninjafoam->ninjafoamGroupBox->isChecked())
- tree->ninjafoam->ninjafoamGroupBox->setChecked(false);
- else{
- tree->ninjafoam->ninjafoamGroupBox->setChecked(true);
- }
- }
-#endif
- else if(item == tree->stabilityItem)
- {
- if(tree->stability->stabilityGroupBox->isChecked())
- tree->stability->stabilityGroupBox->setChecked(false);
- else
- tree->stability->stabilityGroupBox->setChecked(true);
- }
- else if( item == tree->spdDirItem ) {
- if( tree->wind->windGroupBox->isChecked() )
- tree->wind->windGroupBox->setChecked( false );
- else
- tree->wind->windGroupBox->setChecked( true );
- }
- else if( item == tree->pointItem ) {
- if( tree->point->pointGroupBox->isChecked() )
- tree->point->pointGroupBox->setChecked( false );
- else
- tree->point->pointGroupBox->setChecked( true );
- }
- else if( item == tree->modelItem ) {
- if( tree->weather->weatherGroupBox->isChecked() )
- tree->weather->weatherGroupBox->setChecked( false );
- else
- tree->weather->weatherGroupBox->setChecked( true );
- }
- else if(item == tree->googleItem)
- {
- if(tree->google->googleGroupBox->isChecked())
- tree->google->googleGroupBox->setChecked(false);
- else
- tree->google->googleGroupBox->setChecked(true);
- }
- else if(item == tree->fbItem)
- {
- if(tree->fb->fbGroupBox->isChecked())
- tree->fb->fbGroupBox->setChecked(false);
- else
- tree->fb->fbGroupBox->setChecked(true);
- }
- else if(item == tree->shapeItem)
- {
- if(tree->shape->shapeGroupBox->isChecked())
- tree->shape->shapeGroupBox->setChecked(false);
- else
- tree->shape->shapeGroupBox->setChecked(true);
- }
- else if(item == tree->pdfItem)
- {
- if(tree->pdf->pdfGroupBox->isChecked())
- tree->pdf->pdfGroupBox->setChecked(false);
- else
- tree->pdf->pdfGroupBox->setChecked(true);
- }
- else if(item == tree->vtkItem)
- {
- if(tree->vtk->vtkGroupBox->isChecked())
- tree->vtk->vtkGroupBox->setChecked(false);
- else
- tree->vtk->vtkGroupBox->setChecked(true);
- }
- checkAllItems();
- return;
-}
-
-/**
- * \brief Check the input dem for no data and optionally fill
- *
- * Note that if we fail to fix things, we have to close the ds.
- *
- * \return
- *
- */
-QString mainWindow::checkForNoData( QString inputFile )
-{
- QString fileName;
- QString newFile = inputFile;
- GDALDataset *poDS = (GDALDataset*)GDALOpen( inputFile.toStdString().c_str(),
- GA_ReadOnly );
- if( GDALHasNoData( poDS, 1 ) )
- {
- int r = QMessageBox::warning( this, tr ("WindNinja" ),
- tr( "The input dataset contains pixels with no data. "
- "These datasets cannot be used by WindNinja, "
- "would you like to attempt to fill those pixels?" ),
- QMessageBox::Yes |
- QMessageBox::No |
- QMessageBox::Cancel);
- if( r == QMessageBox::Yes )
- {
- fileName = QFileDialog::getSaveFileName( this,
- tr( "Open Elevation Input File" ),
- inputFileDir.absolutePath(),
- tr( "GeoTiff (*.tif)" ) );
- if( fileName.isEmpty() )
- return QString("");
-
- if( !fileName.endsWith( ".tif", Qt::CaseInsensitive ) )
- fileName += ".tif";
- GDALDriverH hDriver = GDALGetDriverByName( "GTiff" );
- GDALDatasetH hNewDS;
- hNewDS = GDALCreateCopy( hDriver, fileName.toStdString().c_str(),
- (GDALDriverH)poDS, FALSE, NULL, NULL,
- NULL );
- GDALRasterBandH hSrcBand, hDstBand;
- hSrcBand = GDALGetRasterBand( (GDALDatasetH)poDS, 1 );
- hDstBand = GDALGetRasterBand( hNewDS, 1 );
- int nSuccess;
- GDALSetRasterNoDataValue( hDstBand,
- GDALGetRasterNoDataValue( hSrcBand, &nSuccess ) );
- int nNoData = GDALFillBandNoData( (GDALDataset*)hNewDS, 1, 100 );
- if( nNoData )
- {
- QMessageBox::warning( this, tr ("WindNinja" ),
- tr( "Could not fill no data pixels, too many pixels "
- "were invalid." ),
- QMessageBox::Ok );
- GDALClose( hNewDS );
- GDALClose( (GDALDatasetH)poDS );
- VSIUnlink( fileName.toStdString().c_str() );
- newFile = "";
- }
- else
- {
- GDALFlushCache( hNewDS );
- GDALClose( hNewDS );
- GDALClose( (GDALDatasetH)poDS );
- newFile = fileName;
- }
- }
- }
- else
- GDALClose( (GDALDatasetH)poDS );
- return newFile;
-}
-
-void mainWindow::enablePointDate(bool enable)
-{
- (void)enable;
- if( tree->point->pointGroupBox->isChecked() )
- {
- if( tree->diurnal->diurnalGroupBox->isChecked()
- || tree->stability->stabilityGroupBox->isChecked()
- )
- {
- //Allows for on the fly changes in diurnal parameters as users select/deselect stations of
- //various types
- emit mainDiurnalChanged(true); //Sets to true so that stability options are also set
- if(tree->point->simType==0) //Only turn on datetimeEdit for single step runs old format
- {
- tree->point->dateTimeEdit->setEnabled( true );
- }
- else
- {
- tree->point->dateTimeEdit->setEnabled(false);
- }
- }
- else
- {
- emit mainDiurnalChanged(false); //Tells pointInput we don't want stability/Diurnal
- tree->point->dateTimeEdit->setEnabled( false );
- }
- }
-}
-
-#ifdef NINJAFOAM
-void mainWindow::enableNinjafoamOptions(bool enable)
-{
- (void)enable;
- if( tree->ninjafoam->ninjafoamGroupBox->isChecked() )
- {
- tree->stability->stabilityGroupBox->setCheckable( false );
- tree->stability->stabilityGroupBox->setChecked( false );
- tree->stability->stabilityGroupBox->setHidden( true );
- tree->stability->ninjafoamConflictLabel->setHidden( false );
-
- tree->wind->windTable->enableDiurnalCells( false );
-
- tree->point->pointGroupBox->setCheckable( false );
- tree->point->pointGroupBox->setChecked( false );
- tree->point->pointGroupBox->setHidden( true );
- tree->point->ninjafoamConflictLabel->setHidden( false );
-
- tree->surface->foamCaseGroupBox->setHidden( false );
- tree->surface->timeZoneGroupBox->setHidden( false );
-
- tree->vtk->vtkLabel->setHidden( false );
- tree->vtk->vtkGroupBox->setHidden( false );
- tree->vtk->vtkGroupBox->setCheckable(true);
- tree->vtk->vtkGroupBox->setChecked( false );
- }
- else{
- tree->diurnal->diurnalGroupBox->setCheckable( true );
- tree->diurnal->diurnalGroupBox->setChecked( false );
- tree->diurnal->diurnalGroupBox->setHidden( false );
-
- tree->stability->stabilityGroupBox->setCheckable( true );
- tree->stability->stabilityGroupBox->setChecked( false );
- tree->stability->stabilityGroupBox->setHidden( false );
- tree->stability->ninjafoamConflictLabel->setHidden( true );
-
- tree->point->pointGroupBox->setCheckable( true );
- tree->point->pointGroupBox->setChecked( false );
- tree->point->pointGroupBox->setHidden( false );
- tree->point->ninjafoamConflictLabel->setHidden( true );
-
- tree->surface->foamCaseGroupBox->setHidden( true );
- tree->surface->timeZoneGroupBox->setHidden( false );
- tree->surface->meshResComboBox->addItem("Custom", 4);
-
- tree->vtk->vtkLabel->setHidden( false );
- tree->vtk->vtkGroupBox->setHidden( false );
- tree->vtk->vtkGroupBox->setCheckable( true );
- tree->vtk->vtkGroupBox->setChecked( false );
- }
-}
-#endif
-
-void mainWindow::SetConfigOption()
-{
- QString key, val;
- int rc;
- SetConfigDialog dialog;
- rc = dialog.exec();
- if( rc == QDialog::Rejected )
- return;
- const char *pszKey, *pszVal;
- key = dialog.GetKey();
- val = dialog.GetVal();
- if( key == "" )
- return;
- if( val == "" )
- pszVal = NULL;
- else
- pszVal = CPLSPrintf( "%s", (char*)val.toLocal8Bit().data() );
- qDebug() << "Setting config option " << key << "to" << val;
- pszKey = CPLSPrintf( "%s", (char*)key.toLocal8Bit().data() );
- CPLSetConfigOption( pszKey, pszVal );
-}
diff --git a/src/gui/mainWindow.h b/src/gui/mainWindow.h
deleted file mode 100644
index c59230f69..000000000
--- a/src/gui/mainWindow.h
+++ /dev/null
@@ -1,301 +0,0 @@
-/******************************************************************************
- *
- * $Id$
- *
- * Project: WindNinja Qt GUI
- * Purpose: Main window and parent to all other widgets
- * Author: Kyle Shannon
- *
- ******************************************************************************
- *
- * THIS SOFTWARE WAS DEVELOPED AT THE ROCKY MOUNTAIN RESEARCH STATION (RMRS)
- * MISSOULA FIRE SCIENCES LABORATORY BY EMPLOYEES OF THE FEDERAL GOVERNMENT
- * IN THE COURSE OF THEIR OFFICIAL DUTIES. PURSUANT TO TITLE 17 SECTION 105
- * OF THE UNITED STATES CODE, THIS SOFTWARE IS NOT SUBJECT TO COPYRIGHT
- * PROTECTION AND IS IN THE PUBLIC DOMAIN. RMRS MISSOULA FIRE SCIENCES
- * LABORATORY ASSUMES NO RESPONSIBILITY WHATSOEVER FOR ITS USE BY OTHER
- * PARTIES, AND MAKES NO GUARANTEES, EXPRESSED OR IMPLIED, ABOUT ITS QUALITY,
- * RELIABILITY, OR ANY OTHER CHARACTERISTIC.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *
- *****************************************************************************/
-
-#ifndef MAINWINDOW_H
-#define MAINWINDOW_H
-
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-
-#include "gdal_priv.h"
-#include "ogr_srs_api.h"
-#include "cpl_string.h"
-#include "gdal_util.h"
-#include "startRuns.h"
-#include "ninja.h"
-#include "ninja_version.h"
-#include "WindNinjaTree.h"
-#include "consoleDockWidget.h"
-#include "solveThread.h"
-#include "ninjaException.h"
-#include "ninjaUnits.h"
-#include "wxStation.h"
-#include "ninjaUnits.h"
-#include "ninjaArmy.h"
-#include "ninja_conv.h"
-
-#include "setconfigdialog.h"
-
-class mainWindow : public QMainWindow
-{
- Q_OBJECT
-
- public:
- mainWindow(QWidget *parent = 0);
-
- //ninja *inputNinja;
-
- ninjaArmy *army;
-
- QProgressDialog *progressDialog;
- int nRuns;
-
- QDir cwd;
- QDir pwd;
-
- QTimer *timer;
-
- int *runProgress;
- int totalProgress;
- std::vector progressLog;
-
- bool okToContinueCheck;
-
- public slots:
- void updateProgress(int run, int progress);
- void updateProgress(const QString message);
- void updateTimer();
- void openDEMDownloader();
-
- public:
- WindNinjaTree *tree;
- ConsoleDockWidget *console;
- QString prompt;
- QColor orange;
-
- enum eInputFileType{
- ASC, LCP, GTIFF, IMG};
-#ifdef NINJAFOAM
- QString existingCaseDir;
-#endif
- QString inputFileName;
- QDir inputFileDir;
- QString shortInputFileName;
- QString outputPath;
- int inputFileType;
- bool hasPrj;
- QString prjFileName;
- double meshCellSize;
-
- enum eInputStatus{
- blue, green, amber, red};
-
- int lineNumber;
-
- //GDAL values
- QString GDALDriverName, GDALDriverLongName;
- std::string GDALProjRef;
- bool hasGDALCenter;
- double GDALCenterLat;
- double GDALCenterLon;
- int GDALXSize, GDALYSize;
- double GDALCellSize, GDALNoData;
- double GDALMaxValue, GDALMinValue;
-
- //threshold for no-googling = 400000
-
- static const int noGoogleNumCells = 400000;
- double noGoogleCellSize;
- //threads
- solveThread *sThread;
-
- signals:
- void inputFileChanged(QString newFile);
- void mainDiurnalChanged(bool dC);
-
- public slots:
-
-#ifdef PHONE_HOME_QUERIES_ENABLED
- void checkMessages();
-#endif
-#ifdef NINJAFOAM
- void openExistingCase();
- void updateFileInputForCase(const char* file);
-#endif
- void openInputFile();
- void updateFileInput(const char* file);
- void inputFileDeleted();
- void openMainWindow();
- double computeCellSize(int index);
- int checkInputFile(QString fileName);
- void checkMeshCombo();
- void checkMeshUnits(bool checked);
- void updateOutRes();
- void setPrompt(QString p);
- void writeToConsole(QString message, QColor color = Qt::black);
-
- void writeConsoleOutput();
- void resampleData();
- void writeBlankStationFile();
- void windNinjaHelp();
- void displayArcGISPro();
- void tutorial1();
- void tutorial2();
- void tutorial3();
- void tutorial4();
- void demDownload();
- void fetchDem();
- void cliInstructions();
- void aboutWindNinja();
- void citeWindNinja();
- void supportEmail();
- void bugReport();
- int openHelp(int target = 0);
-
- void treeDoubleClick(QTreeWidgetItem *item, int column);
-
- bool getLatLon();
-
- void test();
-
- int solve();
- void cancelSolve();
- int countRuns();
-
- void openOutputPath();
-
- //functions for checking inputItems
- int checkInputItem();
- int checkSurfaceItem();
- int checkDiurnalItem();
- int checkStabilityItem();
-#ifdef NINJAFOAM
- int checkNativeSolverItem();
- int checkNinjafoamItem();
- int checkSolverMethodItem();
- void selectNativeSolver( bool pick );
- void selectNinjafoamSolver( bool pick );
-#endif
- int checkWindItem();
- int checkSpdDirItem();
- int checkPointItem();
- int checkWeatherItem();
- int checkOutputItem();
- int checkGoogleItem();
- int checkFbItem();
- int checkShapeItem();
- int checkPdfItem();
- int checkVtkItem();
- int checkSolveItem();
- int checkAllItems();
-
- int checkKmlLimit(double);
-
- bool okToContinue();
-
- //initialization mutual exclusion
- void selectWindInitialization( bool pick );
- void selectPointInitialization( bool pick );
- void selectWeatherInitialization( bool pick );
- void enablePointDate(bool enable);
-#ifdef NINJAFOAM
- void enableNinjafoamOptions(bool enable);
-#endif
-
- void SetConfigOption();
-
- protected:
- void closeEvent(QCloseEvent *event);
-
- private:
- QAction *openInputFileAction;
- QAction *exitAction;
- QAction *editPromptAction;
- QAction *writeConsoleOutputAction;
- QAction *rddsAction;
- QAction *writeBlankStationFileAction;
- QAction *setConfigAction;
- QAction *rddsInstructAction;
- QAction *resampleAction;
- QAction *windNinjaHelpAction;
- QAction *tutorial1Action, *tutorial2Action;
- QAction *tutorial3Action, *tutorial4Action;
- QAction *downloadDemAction;
- QAction *fetchDemAction;
- QAction *displayShapeFileViewAction;
- QAction *displayShapeFileProAction;
- QAction *cliInstructionsAction;
- QAction *aboutWindNinjaAction;
- QAction *aboutQtAction;
- QAction *citeWindNinjaAction;
- QAction *supportEmailAction;
- QAction *submitBugReportAction;
-
- //test action connected to test slot
- QAction *testAction;
-
- //Menus for the interface main window
- QMenu *fileMenu;
- QMenu *optionsMenu;
- QMenu *toolsMenu;
- QMenu *helpMenu;
- QMenu *tutorialSubMenu;
- QMenu *shapeSubMenu;
-
- QLabel *statusLabel;
-
- QTime *runTime;
-
- double elapsedRunTime;
-
- //create various entities in there own functions.
-
- void createMenus();
- void createActions();
- void createTimers();
- void createConnections();
- void createConsole();
- void createTreeView();
- void readSettings();
- void writeSettings();
- QString checkForNoData( QString fileName );
-
- QVBoxLayout *mainLayout;
-
- QFileSystemWatcher fileWatcher;
- WidgetDownloadDEM *demWidget;
-};
-
-#endif /* MAINWINDOW_H */
-
diff --git a/src/gui/mainwindow.ui b/src/gui/mainwindow.ui
deleted file mode 100644
index e623b385a..000000000
--- a/src/gui/mainwindow.ui
+++ /dev/null
@@ -1,583 +0,0 @@
-
-
- MainWindow
-
-
-
- 0
- 0
- 530
- 846
-
-
-
- MainWindow
-
-
-
- -
-
-
-
- 0
- 0
-
-
-
-
- WindNinja
-
-
- -
-
- Input
-
- -
-
- Surface
-
-
- -
-
- Location
-
-
- -
-
- Diurnal
-
-
- -
-
- Wind Input
-
- -
-
- Domain Average Initialization
-
-
- -
-
- Point Initialization
-
-
- -
-
- Weather Model Initialization
-
-
-
-
- -
-
- Output
-
- -
-
- Google Earth
-
-
- -
-
- Fire Behavior
-
-
- -
-
- Shape Files
-
-
- -
-
- VTK
-
-
-
- -
-
- Solve
-
-
-
-
- -
-
-
- Input
-
-
-
- -
-
-
-
- 0
- 0
-
-
-
- 5
-
-
-
- -
-
- -
-
-
-
- 0
- 0
-
-
-
- Longitude
-
-
-
- -
-
-
-
- 0
- 0
-
-
-
-
- -
-
-
- Qt::Horizontal
-
-
-
- 40
- 20
-
-
-
-
-
-
- -
-
- -
-
-
-
- 0
- 0
-
-
-
- Latitude
-
-
-
- -
-
-
-
- 0
- 0
-
-
-
-
- -
-
-
- Qt::Horizontal
-
-
-
- 40
- 20
-
-
-
-
-
-
- -
-
-
- Qt::Vertical
-
-
-
- 20
- 40
-
-
-
-
-
-
-
-
- -
-
-
- Use Diurnal Model
-
-
-
- -
-
-
- Qt::Vertical
-
-
-
- 20
- 40
-
-
-
-
-
-
-
-
- -
-
-
-
-
-
-
- -
-
- -
-
-
- -
-
-
- Read Station File
-
-
-
-
-
-
-
-
-
- -
-
-
- Qt::Vertical
-
-
-
- 20
- 40
-
-
-
-
- -
-
- -
-
-
- -
-
-
- -
-
-
- Download Forecast
-
-
-
-
-
- -
-
-
-
- 1
-
-
-
-
-
-
-
-
-
- -
-
- -
-
-
- Elevation File
-
-
-
- -
-
-
-
- 0
- 0
-
-
-
-
- -
-
-
- Open Elevation File
-
-
- Qt::ToolButtonTextBesideIcon
-
-
-
-
-
- -
-
- -
-
-
- Vegetation
-
-
-
- -
-
- -
-
- Grass
-
-
- -
-
- Brush
-
-
- -
-
- Trees
-
-
-
-
- -
-
-
- Qt::Horizontal
-
-
-
- 40
- 20
-
-
-
-
-
-
- -
-
- -
-
-
- Mesh Resolution
-
-
-
- -
-
- -
-
- Coarse
-
-
- -
-
- Medium
-
-
- -
-
- Fine
-
-
- -
-
- Custom
-
-
-
-
- -
-
-
- true
-
-
- 5000.000000000000000
-
-
- 100.000000000000000
-
-
-
- -
-
-
- Meters
-
-
- true
-
-
-
- -
-
-
- Feet
-
-
-
-
-
- -
-
-
- Qt::Vertical
-
-
-
- 20
- 40
-
-
-
-
-
-
-
-
-
-
-
-
-
- 8
-
-
-
- -
-
-
-
- 0
- 0
-
-
-
-
-
-
-
-
-
- toolBar
-
-
- TopToolBarArea
-
-
- false
-
-
-
-
-
- Open &Elevation File
-
-
-
-
- Write &Console Output to File
-
-
-
-
- Exit
-
-
-
-
- Console Output
-
-
-
-
- Open RDDS Website
-
-
-
-
- Write Blank Station File
-
-
-
-
-
- Marble::LatLonEdit
- QWidget
-
-
-
-
-
-
diff --git a/src/gui/metaWindWidget.cpp b/src/gui/metaWindWidget.cpp
deleted file mode 100644
index 015bbf8f5..000000000
--- a/src/gui/metaWindWidget.cpp
+++ /dev/null
@@ -1,100 +0,0 @@
-/******************************************************************************
- *
- * $Id$
- *
- * Project: WindNinja Qt GUI
- * Purpose: Input for global wind input variables
- * Author: Kyle Shannon
- *
- ******************************************************************************
- *
- * THIS SOFTWARE WAS DEVELOPED AT THE ROCKY MOUNTAIN RESEARCH STATION (RMRS)
- * MISSOULA FIRE SCIENCES LABORATORY BY EMPLOYEES OF THE FEDERAL GOVERNMENT
- * IN THE COURSE OF THEIR OFFICIAL DUTIES. PURSUANT TO TITLE 17 SECTION 105
- * OF THE UNITED STATES CODE, THIS SOFTWARE IS NOT SUBJECT TO COPYRIGHT
- * PROTECTION AND IS IN THE PUBLIC DOMAIN. RMRS MISSOULA FIRE SCIENCES
- * LABORATORY ASSUMES NO RESPONSIBILITY WHATSOEVER FOR ITS USE BY OTHER
- * PARTIES, AND MAKES NO GUARANTEES, EXPRESSED OR IMPLIED, ABOUT ITS QUALITY,
- * RELIABILITY, OR ANY OTHER CHARACTERISTIC.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *
- *****************************************************************************/
-
-#include "metaWindWidget.h"
-
-metaWindWidget::metaWindWidget(QWidget *parent) : QWidget(parent)
-{
- metaWindGroupBox = new QGroupBox(tr("Options"));
-
- //input Height widgets
- inputHeightGroupBox = new QGroupBox(tr("Input Wind Height"));
-
- inputHeightComboBox = new QComboBox;
- inputHeightComboBox->addItem(tr("20ft-US"));
- inputHeightComboBox->addItem(tr("10m-SI"));
- inputHeightComboBox->addItem(tr("Custom"));
-
- inputHeightDoubleSpinBox = new QDoubleSpinBox;
- inputHeightDoubleSpinBox->setRange(0, 100000); //Increased from 100
- inputHeightDoubleSpinBox->setValue(20.00);
- inputHeightDoubleSpinBox->setAccelerated(true);
- inputHeightDoubleSpinBox->setDisabled(true);
-
- feetRadioButton = new QRadioButton(tr("Feet"));
- feetRadioButton->setChecked(true);
- feetRadioButton->setDisabled(true);
- meterRadioButton = new QRadioButton(tr("Meters"));
- meterRadioButton->setDisabled(true);
-
- inputHeightLayout = new QHBoxLayout;
- inputHeightLayout->addWidget(inputHeightComboBox);
- inputHeightLayout->addWidget(inputHeightDoubleSpinBox);
- inputHeightLayout->addWidget(feetRadioButton);
- inputHeightLayout->addWidget(meterRadioButton);
- inputHeightLayout->addStretch();
-
- inputHeightGroupBox->setLayout(inputHeightLayout);
-
- connect(inputHeightComboBox, SIGNAL(currentIndexChanged(int)),
- this, SLOT(checkInputHeight(int)));
-
- layout = new QVBoxLayout;
- layout->addWidget(inputHeightGroupBox);
-
- setLayout(layout);
-}
-
-void metaWindWidget::checkInputHeight(int choice)
-{
- if(choice == 0)
- {
- inputHeightDoubleSpinBox->setValue(20.00);
- inputHeightDoubleSpinBox->setDisabled(true);
- feetRadioButton->setChecked(true);
- feetRadioButton->setDisabled(true);
- meterRadioButton->setDisabled(true);
- }
- else if(choice == 1)
- {
- inputHeightDoubleSpinBox->setValue(10.00);
- inputHeightDoubleSpinBox->setDisabled(true);
- meterRadioButton->setChecked(true);
- feetRadioButton->setDisabled(true);
- meterRadioButton->setDisabled(true);
- }
- else if(choice == 2)
- {
- inputHeightDoubleSpinBox->setEnabled(true);
- feetRadioButton->setEnabled(true);
- feetRadioButton->setChecked(true);
- inputHeightDoubleSpinBox->setValue(0.00);
- meterRadioButton->setEnabled(true);
- }
-}
diff --git a/src/gui/metaWindWidget.h b/src/gui/metaWindWidget.h
deleted file mode 100644
index 755546190..000000000
--- a/src/gui/metaWindWidget.h
+++ /dev/null
@@ -1,79 +0,0 @@
-/******************************************************************************
- *
- * $Id$
- *
- * Project: WindNinja Qt GUI
- * Purpose: Input for global wind input variables
- * Author: Kyle Shannon
- *
- ******************************************************************************
- *
- * THIS SOFTWARE WAS DEVELOPED AT THE ROCKY MOUNTAIN RESEARCH STATION (RMRS)
- * MISSOULA FIRE SCIENCES LABORATORY BY EMPLOYEES OF THE FEDERAL GOVERNMENT
- * IN THE COURSE OF THEIR OFFICIAL DUTIES. PURSUANT TO TITLE 17 SECTION 105
- * OF THE UNITED STATES CODE, THIS SOFTWARE IS NOT SUBJECT TO COPYRIGHT
- * PROTECTION AND IS IN THE PUBLIC DOMAIN. RMRS MISSOULA FIRE SCIENCES
- * LABORATORY ASSUMES NO RESPONSIBILITY WHATSOEVER FOR ITS USE BY OTHER
- * PARTIES, AND MAKES NO GUARANTEES, EXPRESSED OR IMPLIED, ABOUT ITS QUALITY,
- * RELIABILITY, OR ANY OTHER CHARACTERISTIC.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *
- *****************************************************************************/
-
-#ifndef METAWINDWIDGET_H
-#define METAWINDWIDGET_H
-
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-
-#include
-
-#include "gdal_priv.h"
-#include "ogr_srs_api.h"
-
-#include "latLonWidget.h"
-
-#ifndef Q_MOC_RUN
-#include "ninja.h"
-#endif
-
-class metaWindWidget : public QWidget
-{
- Q_OBJECT
-
- public:
-
- metaWindWidget(QWidget *parent = 0);
-
- QGroupBox *metaWindGroupBox;
- //input height
- QGroupBox *inputHeightGroupBox;
- QComboBox *inputHeightComboBox;
- QDoubleSpinBox *inputHeightDoubleSpinBox;
- QRadioButton *feetRadioButton, *meterRadioButton;
-
- //layouts
- QHBoxLayout *inputHeightLayout;
-
- QVBoxLayout *layout;
-
- public slots:
- void checkInputHeight(int choice);
-
-};
-
-#endif /* METAWINDWIDGET_H */
diff --git a/src/gui/move_icon.png b/src/gui/move_icon.png
deleted file mode 100644
index bcb510f07..000000000
Binary files a/src/gui/move_icon.png and /dev/null differ
diff --git a/src/gui/nativeSolverInput.cpp b/src/gui/nativeSolverInput.cpp
deleted file mode 100644
index 3a415b0d6..000000000
--- a/src/gui/nativeSolverInput.cpp
+++ /dev/null
@@ -1,61 +0,0 @@
-/******************************************************************************
- *
- * $Id: stabilityInput.cpp 1304 2012-01-20 21:07:12Z kyle.shannon $
- *
- * Project: WindNinja Qt GUI
- * Purpose: native solver interface
- * Author: Kyle Shannon
- *
- ******************************************************************************
- *
- * THIS SOFTWARE WAS DEVELOPED AT THE ROCKY MOUNTAIN RESEARCH STATION (RMRS)
- * MISSOULA FIRE SCIENCES LABORATORY BY EMPLOYEES OF THE FEDERAL GOVERNMENT
- * IN THE COURSE OF THEIR OFFICIAL DUTIES. PURSUANT TO TITLE 17 SECTION 105
- * OF THE UNITED STATES CODE, THIS SOFTWARE IS NOT SUBJECT TO COPYRIGHT
- * PROTECTION AND IS IN THE PUBLIC DOMAIN. RMRS MISSOULA FIRE SCIENCES
- * LABORATORY ASSUMES NO RESPONSIBILITY WHATSOEVER FOR ITS USE BY OTHER
- * PARTIES, AND MAKES NO GUARANTEES, EXPRESSED OR IMPLIED, ABOUT ITS QUALITY,
- * RELIABILITY, OR ANY OTHER CHARACTERISTIC.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *
- *****************************************************************************/
-
-#include "nativeSolverInput.h"
-
-/**
- * Construct and layout the nativeSolverInput widget. This is only a checkable
- * option now.
- *
- * @param parent parent widget
- */
-nativeSolverInput::nativeSolverInput(QWidget *parent) : QWidget(parent)
-{
- nativeSolverGroupBox = new QGroupBox(tr("Conservation of Mass"));
- nativeSolverGroupBox->setCheckable(true);
- nativeSolverGroupBox->setChecked(true);
-
- nativeSolverLabel = new QLabel(tr("This is the native WindNinja solver. It solves a conservation of mass equation,\n"
- "but not a conservation of momentum equation. This solver is fast-running, \n"
- "but may give less accurate wind predictions in regions where momentum effects are\n"
- "important, for example on the lee side of terrain obstacles.\n"
- ), this);
-
- nativeSolverLayout = new QVBoxLayout;
-
- nativeSolverGroupBox->setLayout(nativeSolverLayout);
-
- layout = new QVBoxLayout;
- layout->addWidget(nativeSolverGroupBox);
- layout->addWidget(nativeSolverLabel);
- layout->addStretch();
- setLayout(layout);
-
-
-}
diff --git a/src/gui/nativeSolverInput.h b/src/gui/nativeSolverInput.h
deleted file mode 100644
index 2b117443c..000000000
--- a/src/gui/nativeSolverInput.h
+++ /dev/null
@@ -1,44 +0,0 @@
-#ifndef NATIVESOLVERINPUT_H
-#define NATIVESOLVERINPUT_H
-
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-
-#include
-#include
-
-#include "gdal_priv.h"
-#include "ogr_srs_api.h"
-
-#ifndef Q_MOC_RUN
-#include "boost/date_time/local_time/local_time.hpp"
-#include "boost/date_time/posix_time/posix_time_types.hpp"
-#endif
-
-#include "latLonWidget.h"
-#include "timeZoneWidget.h"
-
-#include "qdebug.h"
-
-class nativeSolverInput : public QWidget
-{
- Q_OBJECT
-
- public:
-
- nativeSolverInput(QWidget *parent = 0);
- QGroupBox *nativeSolverGroupBox;
- QVBoxLayout *nativeSolverLayout;
- QVBoxLayout *layout;
- QLabel *nativeSolverLabel;
-
-
-};
-
-#endif /* NATIVESOLVERINPUT_H */
diff --git a/src/gui/ninjafoamInput.cpp b/src/gui/ninjafoamInput.cpp
deleted file mode 100644
index beae42503..000000000
--- a/src/gui/ninjafoamInput.cpp
+++ /dev/null
@@ -1,66 +0,0 @@
-/******************************************************************************
- *
- * $Id: stabilityInput.cpp 1304 2012-01-20 21:07:12Z kyle.shannon $
- *
- * Project: WindNinja Qt GUI
- * Purpose: NinjaFOAM interface
- * Author: Kyle Shannon
- *
- ******************************************************************************
- *
- * THIS SOFTWARE WAS DEVELOPED AT THE ROCKY MOUNTAIN RESEARCH STATION (RMRS)
- * MISSOULA FIRE SCIENCES LABORATORY BY EMPLOYEES OF THE FEDERAL GOVERNMENT
- * IN THE COURSE OF THEIR OFFICIAL DUTIES. PURSUANT TO TITLE 17 SECTION 105
- * OF THE UNITED STATES CODE, THIS SOFTWARE IS NOT SUBJECT TO COPYRIGHT
- * PROTECTION AND IS IN THE PUBLIC DOMAIN. RMRS MISSOULA FIRE SCIENCES
- * LABORATORY ASSUMES NO RESPONSIBILITY WHATSOEVER FOR ITS USE BY OTHER
- * PARTIES, AND MAKES NO GUARANTEES, EXPRESSED OR IMPLIED, ABOUT ITS QUALITY,
- * RELIABILITY, OR ANY OTHER CHARACTERISTIC.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *
- *****************************************************************************/
-
-#include "ninjafoamInput.h"
-
-/**
- * Construct and layout the ninjafoamInput widget. This is only a checkable
- * option now.
- *
- * @param parent parent widget
- */
-ninjafoamInput::ninjafoamInput(QWidget *parent) : QWidget(parent)
-{
- ninjafoamGroupBox = new QGroupBox(tr("Conservation of Mass and Momentum"));
- ninjafoamGroupBox->setCheckable(true);
- ninjafoamGroupBox->setChecked(false);
-
- ninjafoamLabel = new QLabel(tr("This solver conserves both mass and momentum. It is based on the OpenFOAM\n"
- "CFD toolbox. This solver should give more accurate wind predictions in regions where\n"
- "momentum effects are important, such as on the lee side of terrain obstacles. Because\n"
- "this solver is more computationally intensive than the conservation of mass solver,\n"
- "simulation times will be longer. Typical simulation times for this solver range from\n"
- "10-30 min, but will depend on your domain, resolution, and computational\n"
- "resources. Note that some options (e.g., point initialization and non-neutral\n"
- "stability) are not available for this solver at this time. We plan to make these options\n"
- "available in future releases."
- ), this);
-
- ninjafoamLayout = new QVBoxLayout;
-
- ninjafoamGroupBox->setLayout(ninjafoamLayout);
-
- layout = new QVBoxLayout;
- layout->addWidget(ninjafoamGroupBox);
- layout->addWidget(ninjafoamLabel);
- layout->addStretch();
- setLayout(layout);
-
-
-}
diff --git a/src/gui/ninjafoamInput.h b/src/gui/ninjafoamInput.h
deleted file mode 100644
index 2beee89a9..000000000
--- a/src/gui/ninjafoamInput.h
+++ /dev/null
@@ -1,43 +0,0 @@
-#ifndef NINJAFOAMINPUT_H
-#define NINJAFOAMINPUT_H
-
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-
-#include
-#include
-
-#include "gdal_priv.h"
-#include "ogr_srs_api.h"
-
-#ifndef Q_MOC_RUN
-#include "boost/date_time/local_time/local_time.hpp"
-#include "boost/date_time/posix_time/posix_time_types.hpp"
-#endif
-
-#include "latLonWidget.h"
-#include "timeZoneWidget.h"
-
-#include "qdebug.h"
-
-class ninjafoamInput : public QWidget
-{
- Q_OBJECT
-
- public:
-
- ninjafoamInput(QWidget *parent = 0);
- QGroupBox *ninjafoamGroupBox;
- QVBoxLayout *ninjafoamLayout;
- QVBoxLayout *layout;
- QLabel *ninjafoamLabel;
-
-};
-
-#endif /* NINJAFOAMINPUT_H */
diff --git a/src/gui/outputHeightWidget.cpp b/src/gui/outputHeightWidget.cpp
deleted file mode 100644
index b8bc9350c..000000000
--- a/src/gui/outputHeightWidget.cpp
+++ /dev/null
@@ -1,98 +0,0 @@
-/******************************************************************************
- *
- * $Id$
- *
- * Project: WindNinja Qt GUI
- * Purpose: Output wind option widget
- * Author: Kyle Shannon
- *
- ******************************************************************************
- *
- * THIS SOFTWARE WAS DEVELOPED AT THE ROCKY MOUNTAIN RESEARCH STATION (RMRS)
- * MISSOULA FIRE SCIENCES LABORATORY BY EMPLOYEES OF THE FEDERAL GOVERNMENT
- * IN THE COURSE OF THEIR OFFICIAL DUTIES. PURSUANT TO TITLE 17 SECTION 105
- * OF THE UNITED STATES CODE, THIS SOFTWARE IS NOT SUBJECT TO COPYRIGHT
- * PROTECTION AND IS IN THE PUBLIC DOMAIN. RMRS MISSOULA FIRE SCIENCES
- * LABORATORY ASSUMES NO RESPONSIBILITY WHATSOEVER FOR ITS USE BY OTHER
- * PARTIES, AND MAKES NO GUARANTEES, EXPRESSED OR IMPLIED, ABOUT ITS QUALITY,
- * RELIABILITY, OR ANY OTHER CHARACTERISTIC.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *
- *****************************************************************************/
-
-#include "outputHeightWidget.h"
-
-outputHeightWidget::outputHeightWidget(QWidget *parent) : QWidget(parent)
-{
- //create output height sections for tree/gui
- outputHeightGroupBox = new QGroupBox(tr("Output Height"));
-
- outputHeightComboBox = new QComboBox;
- outputHeightComboBox->addItem(tr("20ft-US"));
- outputHeightComboBox->addItem(tr("10m-SI"));
- outputHeightComboBox->addItem(tr("Custom"));
-
- outputHeightDoubleSpinBox = new QDoubleSpinBox;
- outputHeightDoubleSpinBox->setRange(0, 10000); //Increased from 100
- outputHeightDoubleSpinBox->setValue(20.00);
- outputHeightDoubleSpinBox->setAccelerated(true);
- outputHeightDoubleSpinBox->setDisabled(true);
-
- feetRadioButton = new QRadioButton(tr("Feet"));
- feetRadioButton->setChecked(true);
-
- meterRadioButton = new QRadioButton(tr("Meters"));
-
- layout = new QHBoxLayout;
- layout->addWidget(outputHeightComboBox);
- layout->addWidget(outputHeightDoubleSpinBox);
- layout->addWidget(feetRadioButton);
- layout->addWidget(meterRadioButton);
- layout->addStretch();
-
- outputHeightGroupBox->setLayout(layout);
-
- mainLayout = new QVBoxLayout;
- mainLayout->addWidget(outputHeightGroupBox);
-
- setLayout(mainLayout);
-
- //signal/slot connection
- connect(outputHeightComboBox, SIGNAL(currentIndexChanged(int)),
- this, SLOT(checkOutputHeight(int)));
-}
-
-void outputHeightWidget::checkOutputHeight(int choice)
-{
- if(choice == 0)
- {
- outputHeightDoubleSpinBox->setValue(20.00);
- outputHeightDoubleSpinBox->setDisabled(true);
- feetRadioButton->setChecked(true);
- feetRadioButton->setDisabled(true);
- meterRadioButton->setDisabled(true);
- }
- else if(choice == 1)
- {
- outputHeightDoubleSpinBox->setValue(10.00);
- outputHeightDoubleSpinBox->setDisabled(true);
- meterRadioButton->setChecked(true);
- feetRadioButton->setDisabled(true);
- meterRadioButton->setDisabled(true);
- }
- else if(choice == 2)
- {
- outputHeightDoubleSpinBox->setEnabled(true);
- feetRadioButton->setEnabled(true);
- feetRadioButton->setChecked(true);
- outputHeightDoubleSpinBox->setValue(0.00);
- meterRadioButton->setEnabled(true);
- }
-}
diff --git a/src/gui/outputMetaData.cpp b/src/gui/outputMetaData.cpp
deleted file mode 100644
index b506ddb53..000000000
--- a/src/gui/outputMetaData.cpp
+++ /dev/null
@@ -1,87 +0,0 @@
-/******************************************************************************
- *
- * $Id$
- *
- * Project: WindNinja
- * Purpose: Meta output information
- * Author: Kyle Shannon
- *
- ******************************************************************************
- *
- * THIS SOFTWARE WAS DEVELOPED AT THE ROCKY MOUNTAIN RESEARCH STATION (RMRS)
- * MISSOULA FIRE SCIENCES LABORATORY BY EMPLOYEES OF THE FEDERAL GOVERNMENT
- * IN THE COURSE OF THEIR OFFICIAL DUTIES. PURSUANT TO TITLE 17 SECTION 105
- * OF THE UNITED STATES CODE, THIS SOFTWARE IS NOT SUBJECT TO COPYRIGHT
- * PROTECTION AND IS IN THE PUBLIC DOMAIN. RMRS MISSOULA FIRE SCIENCES
- * LABORATORY ASSUMES NO RESPONSIBILITY WHATSOEVER FOR ITS USE BY OTHER
- * PARTIES, AND MAKES NO GUARANTEES, EXPRESSED OR IMPLIED, ABOUT ITS QUALITY,
- * RELIABILITY, OR ANY OTHER CHARACTERISTIC.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *
- *****************************************************************************/
-
-#include "outputMetaData.h"
-
-/**
- * Constructor for outputMetaData, sets layouts and attributes
- *
- * @param parent parent widget
- */
-outputMetaData::outputMetaData( QWidget *parent ) : QWidget( parent )
-{
-
- outputHeight = new outputHeightWidget( this );
-
- bufferLabel = new QLabel( tr( "Clip output by: " ), this );
- bufferSpinBox = new QSpinBox( this );
- bufferSpinBox->setRange( 0, 49 );
- bufferSpinBox->setSingleStep( 5 );
- bufferSpinBox->setSuffix( "%" );
-
- bufferLayout = new QHBoxLayout();
- bufferLayout->addWidget( bufferLabel );
- bufferLayout->addWidget( bufferSpinBox );
- bufferLayout->addStretch();
-
- outputSpeedUnitsLabel = new QLabel( "Output Speed Units:", this );
-
- outputSpeedUnitsCombo = new QComboBox( this );
- outputSpeedUnitsCombo->addItem( "mph" );
- outputSpeedUnitsCombo->addItem( "m/s" );
- outputSpeedUnitsCombo->addItem( "kph" );
- outputSpeedUnitsCombo->addItem( "kts" );
-
- outputSpeedUnitsLayout = new QHBoxLayout();
- outputSpeedUnitsLayout->addWidget( outputSpeedUnitsLabel );
- outputSpeedUnitsLayout->addWidget( outputSpeedUnitsCombo );
- outputSpeedUnitsLayout->addStretch();
-
- wxModelOutputCheckBox = new QCheckBox( tr( "Write Raw Weather Model Output" ),
- this );
- wxModelOutputCheckBox->setDisabled( true );
- wxModelOutputCheckBox->setChecked( true );
-
- layout = new QVBoxLayout();
- layout->addWidget( outputHeight );
- layout->addLayout( outputSpeedUnitsLayout );
- layout->addLayout( bufferLayout );
- layout->addWidget( wxModelOutputCheckBox );
- layout->addStretch();
- setLayout( layout );
-}
-
-outputMetaData::~outputMetaData()
-{
-
-}
-
-
-
-
diff --git a/src/gui/outputMetaData.h b/src/gui/outputMetaData.h
deleted file mode 100644
index a31a260e0..000000000
--- a/src/gui/outputMetaData.h
+++ /dev/null
@@ -1,64 +0,0 @@
-/******************************************************************************
- *
- * $Id$
- *
- * Project: WindNinja
- * Purpose: Meta output information
- * Author: Kyle Shannon
- *
- ******************************************************************************
- *
- * THIS SOFTWARE WAS DEVELOPED AT THE ROCKY MOUNTAIN RESEARCH STATION (RMRS)
- * MISSOULA FIRE SCIENCES LABORATORY BY EMPLOYEES OF THE FEDERAL GOVERNMENT
- * IN THE COURSE OF THEIR OFFICIAL DUTIES. PURSUANT TO TITLE 17 SECTION 105
- * OF THE UNITED STATES CODE, THIS SOFTWARE IS NOT SUBJECT TO COPYRIGHT
- * PROTECTION AND IS IN THE PUBLIC DOMAIN. RMRS MISSOULA FIRE SCIENCES
- * LABORATORY ASSUMES NO RESPONSIBILITY WHATSOEVER FOR ITS USE BY OTHER
- * PARTIES, AND MAKES NO GUARANTEES, EXPRESSED OR IMPLIED, ABOUT ITS QUALITY,
- * RELIABILITY, OR ANY OTHER CHARACTERISTIC.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *
- *****************************************************************************/
-
-#ifndef OUTPUT_META_DATA_H
-#define OUTPUT_META_DATA_H
-
-#include
-#include
-#include
-#include
-#include
-
-#include "outputHeightWidget.h"
-
-class outputMetaData : public QWidget
-{
- Q_OBJECT
-
- public:
- outputMetaData( QWidget *parent = 0 );
- ~outputMetaData();
-
- outputHeightWidget *outputHeight; /**< Output wind Heigth Widget */
-
- QLabel *bufferLabel; /**< Describe the buffer */
- QSpinBox *bufferSpinBox; /**< Set buffer size in % */
-
- QLabel *outputSpeedUnitsLabel;
- QComboBox *outputSpeedUnitsCombo;
-
- QCheckBox *wxModelOutputCheckBox; /**< Write out the raw wx model data */
-
- QHBoxLayout *outputSpeedUnitsLayout;
- QHBoxLayout *bufferLayout; /**< layout for buffer info */
- QVBoxLayout *layout; /**< main layout */
-};
-
-#endif /* OUTPUT_META_DATA_H */
diff --git a/src/gui/pdfOutput.cpp b/src/gui/pdfOutput.cpp
deleted file mode 100644
index fcbe21140..000000000
--- a/src/gui/pdfOutput.cpp
+++ /dev/null
@@ -1,133 +0,0 @@
-/******************************************************************************
- *
- * Project: WindNinja Qt GUI
- * Purpose: PDF output selection widgetx
- * Author: Kyle Shannon
- *
- ******************************************************************************
- *
- * THIS SOFTWARE WAS DEVELOPED AT THE ROCKY MOUNTAIN RESEARCH STATION (RMRS)
- * MISSOULA FIRE SCIENCES LABORATORY BY EMPLOYEES OF THE FEDERAL GOVERNMENT
- * IN THE COURSE OF THEIR OFFICIAL DUTIES. PURSUANT TO TITLE 17 SECTION 105
- * OF THE UNITED STATES CODE, THIS SOFTWARE IS NOT SUBJECT TO COPYRIGHT
- * PROTECTION AND IS IN THE PUBLIC DOMAIN. RMRS MISSOULA FIRE SCIENCES
- * LABORATORY ASSUMES NO RESPONSIBILITY WHATSOEVER FOR ITS USE BY OTHER
- * PARTIES, AND MAKES NO GUARANTEES, EXPRESSED OR IMPLIED, ABOUT ITS QUALITY,
- * RELIABILITY, OR ANY OTHER CHARACTERISTIC.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *
- *****************************************************************************/
-
-#include "pdfOutput.h"
-
-pdfOutput::pdfOutput(QWidget *parent) : QWidget(parent)
-{
- pdfGroupBox = new QGroupBox(tr("Create Geospatial PDF Files (*.pdf)"));
- pdfGroupBox->setCheckable(true);
- pdfGroupBox->setChecked(false);
-
- vectorGroupBox = new QGroupBox(tr("Vectors"));
-
- vectorWidthLabel = new QLabel(tr("Line Width"));
-
- vectorWidthDoubleSpinBox = new QDoubleSpinBox;
- vectorWidthDoubleSpinBox->setRange(1.0, 10.0);
- vectorWidthDoubleSpinBox->setDecimals(1);
- vectorWidthDoubleSpinBox->setValue(1.0);
- vectorWidthDoubleSpinBox->setSingleStep(0.1);
- vectorWidthDoubleSpinBox->setAccelerated(true);
-
- vectorLayout = new QHBoxLayout;
- vectorLayout->addWidget(vectorWidthLabel);
- vectorLayout->addWidget(vectorWidthDoubleSpinBox);
- vectorLayout->addStretch();
-
- vectorGroupBox->setLayout(vectorLayout);
-
- pdfResGroupBox = new QGroupBox(tr("Resolution"));
-
- pdfResSpinBox = new QDoubleSpinBox(this);
- pdfResSpinBox->setRange(1, 5000);
- pdfResSpinBox->setDecimals(2);
- pdfResSpinBox->setAccelerated(true);
- pdfResSpinBox->setValue(200);
- pdfResSpinBox->setDisabled(true);
-
- pdfMetersRadioButton = new QRadioButton(tr("Meters"));
- pdfMetersRadioButton->setChecked(true);
- pdfMetersRadioButton->setDisabled(true);
- pdfFeetRadioButton = new QRadioButton(tr("Feet"));
- pdfFeetRadioButton->setDisabled(true);
-
- useMeshResCheckBox = new QCheckBox(tr("Use Mesh Resolution"));
- useMeshResCheckBox->setChecked(true);
-
- backgroundLabel = new QLabel(tr("Basemap"), this);
-
- backgroundComboBox = new QComboBox(this);
- backgroundComboBox->addItem(tr("TopoFire topo maps"));
- backgroundComboBox->addItem(tr("Hillshade"));
-
- // Size names dictated by https://en.wikipedia.org/wiki/Paper_size
- sizeLabel = new QLabel(tr("Size"), this);
- sizeComboBox = new QComboBox(this);
- sizeComboBox->addItem(tr("Letter-8 1/2 x 11"));
- sizeComboBox->addItem(tr("Legal - 8 1/2 x 14"));
- sizeComboBox->addItem(tr("Tabloid - 11 x 17"));
-
- portraitRadioButton = new QRadioButton(tr("Portrait"), this);
- landscapeRadioButton = new QRadioButton(tr("Landscape"), this);
- portraitRadioButton->setChecked(true);
-
- orientLayout = new QVBoxLayout;
- orientLayout->addWidget(portraitRadioButton);
- orientLayout->addWidget(landscapeRadioButton);
-
- sizeLayout = new QHBoxLayout;
- sizeLayout->addWidget(sizeLabel);
- sizeLayout->addWidget(sizeComboBox);
- sizeLayout->addLayout(orientLayout);
-
- //connect checkbox with spin box
- connect(useMeshResCheckBox, SIGNAL(toggled(bool)),
- pdfResSpinBox, SLOT(setDisabled(bool)));
- connect(useMeshResCheckBox, SIGNAL(toggled(bool)),
- pdfFeetRadioButton, SLOT(setDisabled(bool)));
- connect(useMeshResCheckBox, SIGNAL(toggled(bool)),
- pdfMetersRadioButton, SLOT(setDisabled(bool)));
-
- backgroundLayout = new QHBoxLayout;
- backgroundLayout->addWidget(backgroundLabel);
- backgroundLayout->addWidget(backgroundComboBox);
- backgroundLayout->addStretch();
-
- resLayout = new QGridLayout;
- resLayout->addWidget(pdfResSpinBox, 0, 0);
- resLayout->addWidget(pdfMetersRadioButton, 0, 1);
- resLayout->addWidget(pdfFeetRadioButton, 0, 2);
- resLayout->addWidget(useMeshResCheckBox, 1, 0);
-
- pdfResGroupBox->setLayout(resLayout);
-
- pageLayout = new QVBoxLayout;
- pageLayout->addWidget(vectorGroupBox);
- pageLayout->addLayout(backgroundLayout);
- pageLayout->addLayout(sizeLayout);
- pageLayout->addWidget(pdfResGroupBox);
- pageLayout->addStretch();
-
- pdfGroupBox->setLayout(pageLayout);
-
- mainLayout = new QVBoxLayout;
- mainLayout->addWidget(pdfGroupBox);
- mainLayout->addStretch();
-
- setLayout(mainLayout);
-}
diff --git a/src/gui/pdfOutput.h b/src/gui/pdfOutput.h
deleted file mode 100644
index 1b72ad4a5..000000000
--- a/src/gui/pdfOutput.h
+++ /dev/null
@@ -1,74 +0,0 @@
-/******************************************************************************
- *
- * Project: WindNinja Qt GUI
- * Purpose: PDF output selection widgetx
- * Author: Kyle Shannon
- *
- ******************************************************************************
- *
- * THIS SOFTWARE WAS DEVELOPED AT THE ROCKY MOUNTAIN RESEARCH STATION (RMRS)
- * MISSOULA FIRE SCIENCES LABORATORY BY EMPLOYEES OF THE FEDERAL GOVERNMENT
- * IN THE COURSE OF THEIR OFFICIAL DUTIES. PURSUANT TO TITLE 17 SECTION 105
- * OF THE UNITED STATES CODE, THIS SOFTWARE IS NOT SUBJECT TO COPYRIGHT
- * PROTECTION AND IS IN THE PUBLIC DOMAIN. RMRS MISSOULA FIRE SCIENCES
- * LABORATORY ASSUMES NO RESPONSIBILITY WHATSOEVER FOR ITS USE BY OTHER
- * PARTIES, AND MAKES NO GUARANTEES, EXPRESSED OR IMPLIED, ABOUT ITS QUALITY,
- * RELIABILITY, OR ANY OTHER CHARACTERISTIC.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *
- *****************************************************************************/
-
-#ifndef PDFOUTPUT_H
-#define PDFOUTPUT_H
-
-#include
-#include
-#include
-#include
-#include
-#include
-
-#include
-#include
-
-class pdfOutput : public QWidget
-{
-Q_OBJECT
-
-public:
- pdfOutput(QWidget *parent = 0);
-
- QGroupBox *pdfGroupBox;
- QGroupBox *vectorGroupBox;
- QLabel *vectorWidthLabel;
- QDoubleSpinBox *vectorWidthDoubleSpinBox;
- QGroupBox *pdfResGroupBox;
- QDoubleSpinBox *pdfResSpinBox;
- QRadioButton *pdfMetersRadioButton, *pdfFeetRadioButton;
- QCheckBox *useMeshResCheckBox;
- QLabel *backgroundLabel;
- QComboBox *backgroundComboBox;
-
- QLabel *sizeLabel;
- QComboBox *sizeComboBox;
- QRadioButton *portraitRadioButton;
- QRadioButton *landscapeRadioButton;
-
- QHBoxLayout *vectorLayout;
- QVBoxLayout *optionLayout;
- QGridLayout *resLayout;
- QHBoxLayout *backgroundLayout;
- QVBoxLayout *orientLayout;
- QHBoxLayout *sizeLayout;
- QVBoxLayout *pageLayout;
- QVBoxLayout *mainLayout;
-};
-
-#endif /* PDFOUTPUT_H */
diff --git a/src/gui/pointInput.cpp b/src/gui/pointInput.cpp
deleted file mode 100644
index 2e81d5955..000000000
--- a/src/gui/pointInput.cpp
+++ /dev/null
@@ -1,1051 +0,0 @@
-/******************************************************************************
- *
- * $Id$
- *
- * Project: WindNinja Qt GUI
- * Purpose: Point initialization input.
- * Author: Kyle Shannon
- *
- ******************************************************************************
- *
- * THIS SOFTWARE WAS DEVELOPED AT THE ROCKY MOUNTAIN RESEARCH STATION (RMRS)
- * MISSOULA FIRE SCIENCES LABORATORY BY EMPLOYEES OF THE FEDERAL GOVERNMENT
- * IN THE COURSE OF THEIR OFFICIAL DUTIES. PURSUANT TO TITLE 17 SECTION 105
- * OF THE UNITED STATES CODE, THIS SOFTWARE IS NOT SUBJECT TO COPYRIGHT
- * PROTECTION AND IS IN THE PUBLIC DOMAIN. RMRS MISSOULA FIRE SCIENCES
- * LABORATORY ASSUMES NO RESPONSIBILITY WHATSOEVER FOR ITS USE BY OTHER
- * PARTIES, AND MAKES NO GUARANTEES, EXPRESSED OR IMPLIED, ABOUT ITS QUALITY,
- * RELIABILITY, OR ANY OTHER CHARACTERISTIC.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *
- *****************************************************************************/
-
-/**
- * @file pointInput.cpp
- * @author Kyle Shannon
- */
-
-#include "pointInput.h"
-static int wxStationFormat;
-
-pointInput::pointInput( QWidget *parent ) : QWidget( parent )
-{
- pointGroupBox = new QGroupBox( "Point Initialization", this );
- pointGroupBox->setCheckable( true );
- pointGroupBox->setChecked(false);
-
- pointGo=false; //Very Imptortant!
- enableTimeseries=false; //bool for mainwindow
-
- newForm = new QWidget();
-
-//####################################################
-// Some General Buttons #
-//####################################################
-
- //dateTimeEdit is the way of setting the simulation time for old format runs
- dateTimeEdit = new QDateTimeEdit( newForm );
- dateTimeEdit->setDateTime( QDateTime::currentDateTime() );
- dateTimeEdit->setCalendarPopup( true );
- dateTimeEdit->setDisplayFormat( "MM/dd/yyyy HH:mm" );
- dateTimeEdit->setEnabled( false ); //This is for Old Format Diurnal Simulations
- dateTimeEdit->setVisible(false);
- dateTimeEdit->setToolTip("Set date and time for single time step diurnal/stability simulations");
-
- diurnalLabel = new QLabel(this); //A Label for dateTimeEdit
- diurnalLabel->setText("Set Simulation Time: ");
- diurnalLabel->setVisible(false);
-
- oneStepTimeLabel = new QLabel(this); //Label for 1 step datetime runs
- oneStepTimeLabel->setText("Simulation time set to:");
- oneStepTimeLabel->setVisible(false);
-
- writeStationFileButton = new QCheckBox( this ); //This writes an interpolated csv of the weather data (we might not want this)
- writeStationFileButton->setText( tr( "Write Station File" ) );
- writeStationFileButton->setIcon( QIcon( ":weather_clouds.png" ) );
- writeStationFileButton->setToolTip("Time Series: Writes an Interpolated CSV for each time step\nSingle Step: Writes a CSV of inputted weather data.");
-
- writeStationKmlButton = new QCheckBox( this ); //This writes a KML of the weather stations (1 per run)
- writeStationKmlButton->setText( tr( "Write Station Kml" ) );
- writeStationKmlButton->setIcon( QIcon( ":weather_cloudy.png" ) );
- writeStationKmlButton->setToolTip("Time Series: Writes a KML for each time step with time interpolated station data.\nSingle Step: Writes a KML of weather station data.");
-
- widgetButton = new QToolButton( this ); //This opens the station fetch downloader Widget (formerly doTest)
- widgetButton->setText( tr( "Download data" ));
- widgetButton->setIcon(QIcon(":server_go.png"));
- widgetButton->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
- widgetButton->setToolTip("Download weather station data from the Mesonet API.");
-
-//####################################################
-// The Main Box and directory stuff #
-//####################################################
-
- sfModel = new QDirModel(this); //Creates the directory model
- sfModel->setReadOnly(true); //probably can be true, but i don't know
- sfModel->setSorting(QDir::Time); //Sort by time created
-
- treeView = new QTreeView(this); //Creates the box where the sfModel goes
- treeView->setVisible(true);
- treeView->setModel(sfModel); //Sets the model to the thing above
- treeView->header()->setStretchLastSection(true); //Makes it look nice
- treeView->setAnimated(true); //Fancy stuff
- treeView->setColumnHidden(1, true);
- treeView->setColumnHidden(2, true);
- treeView->setAlternatingRowColors( false );
- treeView->setSelectionMode(QAbstractItemView::MultiSelection); //Allows multiple files to be selected
- treeView->setSelectionBehavior(QAbstractItemView::SelectRows); //Select entire row when we do select something
-
- treeLabel = new QLabel(tr("Select Weather Stations")); //Label for Tree and sfModel
- treeLabel->setToolTip("Select Weather Stations from available files.\n"
- "Click a file to add it to the list of included stations\n"
- "Click it again to remove it from the included stations.\n"
- "Available formats are time series, one step runs with time data,\n"
- "and one step runs without time data (old format)");
-
-//####################################################
-// Tool buttons and other things #
-//####################################################
- ClippyToolLayout = new QHBoxLayout; //Layout for info and toolbox
-
- refreshToolButton = new QToolButton(this); //This refreshes the tree so that new files will populate
- refreshToolButton->setText(tr("Refresh Weather Stations"));
- refreshToolButton->setIcon(QIcon(":arrow_rotate_clockwise.png"));
- refreshToolButton->setToolTip(tr("Refresh Stations stored on disk in the DEM directory."));
- refreshToolButton->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
- refreshToolButton->setVisible(true);
-
- clippit = new QLabel(tr("")); //This gets updated with important information about the simulation as station files are chosen
- clippit->setVisible(false);
-
- timeLine = new QFrame(this); //Adds a horizontal line
- timeLine->setFrameShape(QFrame::HLine);
- timeLine->setFrameShadow(QFrame::Sunken);
-
- timeLine2 = new QFrame(this); //Adds a horizontal line
- timeLine2->setFrameShape(QFrame::HLine);
- timeLine2->setFrameShadow(QFrame::Sunken);
-
- ClippyToolLayout->addStretch(); //Moves it over to the other side
- ClippyToolLayout->addWidget(refreshToolButton);
-// ClippyToolLayout->addWidget(clippit);
-
-//####################################################
-//Stuff for timeseries runs... #
-//####################################################
- startTime = new QDateTimeEdit(QDateTime::currentDateTime()); //Initializes the start and stop time boxes for timeseries
- stopTime = new QDateTimeEdit(QDateTime::currentDateTime());
-
- startTime->setDateTime(QDateTime::currentDateTime().addDays(-1)); //Set default to be yesterday
- startTime->setMaximumDateTime(QDateTime::currentDateTime().addSecs(-3600)); //Prevent time from overlapping with right now
- stopTime->setMaximumDateTime(QDateTime::currentDateTime()); //No Future simulations
-
- startTime->setDisplayFormat( "MM/dd/yyyy HH:mm" );
- stopTime->setDisplayFormat( "MM/dd/yyyy HH:mm" );
-
- startTime->setToolTip("Enter the simulation start time");
- stopTime->setToolTip("Enter the simulation stop time");
-
- startTime->setCalendarPopup(true);
- stopTime->setCalendarPopup(true);
-
- numSteps = new QSpinBox; //Number of timesteps box
- numSteps->setValue(24);
- numSteps->setMinimum(1);
- numSteps->setMaximum(99999);//Hopefully big enough
- numSteps->setToolTip("Enter the number of time steps");
-
- startTime->setVisible(true); //Some visibility settings so that the default thing the user sees is a timeseries
- stopTime->setVisible(true);
-
- startTime->setEnabled(false); //Disables timeseries options until the user does something
- stopTime->setEnabled(false);
-
- numSteps->setVisible(true); //Same as above for time step options
- numSteps->setEnabled(false);
-
- timeBoxLayout = new QHBoxLayout; //Layout setup
- startLayout = new QVBoxLayout;
- stopLayout = new QVBoxLayout;
- stepLayout = new QVBoxLayout;
-
- startLabel = new QLabel(tr("Start Time")); //Labels for timeseries
- stopLabel = new QLabel(tr("Stop Time"));
- stepLabel = new QLabel(tr("Number of Time Steps"));
- startLabel->setVisible(true);
- stopLabel->setVisible(true);
- stepLabel->setVisible(true);
-
- startLayout->addWidget(startLabel); //Labels are vertically stacked onto timeboxes and then horizontally set up
- startLayout->addWidget(startTime);
-
- stopLayout->addWidget(stopLabel);
- stopLayout->addWidget(stopTime);
-
- stepLayout->addWidget(stepLabel);
- stepLayout->addWidget(numSteps);
-
- timeBoxLayout->addLayout(startLayout); //Add all the vertial labels to a horizontal grouping
- timeBoxLayout->addLayout(stopLayout);
- timeBoxLayout->addLayout(stepLayout);
-
-//-------------------------------------------------
-// Add some new layouts
-//-------------------------------------------------
- vTreeLayout = new QVBoxLayout; //Adds everything to a vertical layout
-
- hDownloaderLayout = new QHBoxLayout; //Holds the label for the tree & download button
- hDownloaderLayout->addWidget(treeLabel); //Adds label
- hDownloaderLayout->addWidget(widgetButton); //adds Download Button to top of page
-
- vTreeLayout->addLayout(hDownloaderLayout); //adds hDownloaderLayout sublayout to the overal system
- vTreeLayout->addWidget(treeView); //Add the big box
- vTreeLayout->addLayout(ClippyToolLayout); //Add the refresh tool button
- vTreeLayout->addWidget(timeLine); //Add a line to space it out
- vTreeLayout->addLayout(timeBoxLayout); //Add the timeseries stuff
-//####################################################
-//add in old format and other layout options #
-//####################################################
-
- buttonLayout = new QHBoxLayout;
- buttonLayout->addWidget( writeStationFileButton );
- writeStationFileButton->setVisible( false ); //This was disabled in the original PI, leave it in for now, but the is now controlled by a config_option
- buttonLayout->addWidget( writeStationKmlButton );
- buttonLayout->addStretch();
-
- diurnalTimeLayout = new QHBoxLayout; //Create a layout for the old format diurnal options
- diurnalTimeLayout->addWidget(diurnalLabel); //Add all the parts
- diurnalTimeLayout->addWidget(dateTimeEdit,1);
- diurnalTimeLayout->addWidget(oneStepTimeLabel);
-// diurnalTimeLayout->addStretch(-1);
-
- pointLayout = new QVBoxLayout;
-
- pointLayout->addLayout(vTreeLayout); //add the above layout to the main window layouyt
-
- pointLayout->addLayout(diurnalTimeLayout);
-
- pointLayout->addStretch();
- pointLayout->addWidget(timeLine2); //Add another line
- pointLayout->addLayout( buttonLayout ); //Add the kml button at the bottom
-
- pointGroupBox->setLayout( pointLayout ); //Set the layout to all of this
-
- ninjafoamConflictLabel = new QLabel(tr("The point initialization option is not currently available for the momentum solver.\n"),
- this);
- ninjafoamConflictLabel->setHidden(true);
-
- layout = new QVBoxLayout;
- layout->addWidget( pointGroupBox );
- layout->addWidget(ninjafoamConflictLabel);
- setLayout( layout ); //done
-
- checkForModelData();//On load check for model data to filter out directories and stuff we don't want
-
-//####################################################
-// Connect Signls to Slots #
-//####################################################
- connect( widgetButton ,SIGNAL( clicked () ), this,
- SLOT(openStationFetchWidget())); //Opens the Downloader Connector
- connect(refreshToolButton, SIGNAL(clicked()), //Refreshes new Format, deselects files
- this, SLOT(checkForModelData()));
- connect(startTime,SIGNAL(dateTimeChanged(QDateTime)),this,SLOT(updateStartTime(QDateTime))); //update time into a vector from the timeboxes
- connect(stopTime,SIGNAL(dateTimeChanged(QDateTime)),this,SLOT(updateStopTime(QDateTime)));
- connect(stopTime,SIGNAL(dateTimeChanged(QDateTime)),this,SLOT(watchStopTime()));//Watch the times to make sure the user can't do crazy things
- connect(startTime,SIGNAL(dateTimeChanged(QDateTime)),this,SLOT(watchStartTime()));
- connect(treeView->selectionModel(),
- SIGNAL(selectionChanged(const QItemSelection &,const QItemSelection &)),
- this, SLOT(readStationFiles(const QItemSelection &,const QItemSelection &))); //Update the selected stations when a user clicks something
- connect(numSteps,SIGNAL(valueChanged(int)),this,SLOT(setOneStepTimeseries())); //watch the number of steps incase it goes to 1
- stationFileName = ""; //Sets a default
-}
-
-pointInput::~pointInput()
-{
-
-}
-
-/**
- * @brief pointInput::readStationFiles
- * Reads the files on disk that the user selects
- *
- * x is the previously selected data
- * y is the new selected data
- *
- * These two are not used explicitly but are necessary to link up the
- * model with this function, as they trigger the checking to occur
- *
- * How this function works:
- * 1. get a list of the stations the user selects from the UI
- * 2. get what file type it is from directStationTraffic
- * a. this will also update the user on what the station type is
- * 3. if all selected files are the same type, set the simulation type and tell mainwindow that they are good
- * if they are not all the same type, warn the user and mainwindow and wait for the user to change something
- *
- * @param x
- * @param y
- */
-void pointInput::readStationFiles(const QItemSelection &x ,const QItemSelection &y)
-{
- QModelIndexList idx = x.indexes(); //Don't need these, probably delete later
- QModelIndexList idy = y.indexes();
- QModelIndexList idx0 = treeView->selectionModel()->selectedRows(); //Get the number of files selected
-
- std::vector selectedStations; //The good stations
- std::vector finalTypes; //What type they are
- CPLDebug("STATION_FETCH","========================================");
- CPLDebug("STATION_FETCH","NUMBER OF SELECTED STATIONS: %i",idx0.count());
-
- for(int i=0;ifileInfo(idx0[i]).isDir()==true) //If its a directory, make it so that it can't be selected
- {
- CPLDebug("STATION_FETCH","IGNORING SELECTED DIRECTORY!");
- treeView->selectionModel()->select(idx0[i],QItemSelectionModel::Deselect | QItemSelectionModel::Rows);//Deselct entire row by calling ::Rows otherwise it looks messy
- }
- else //if its not a directory, add it to the list of available files
- {
- selectedStations.push_back(sfModel->fileInfo(idx0[i]).absoluteFilePath().toStdString());
- }
- }
-
- for (int i=0;i setInt(finalTypes.begin(),finalTypes.end()); //This is a sanity check to see if the stations that we are reading are all the same type
- std::vector vecInt(setInt.begin(),setInt.end());
-
- CPLDebug("STATION_FETCH","Unique Data Types (bad if >1) %lu",vecInt.size());
- for(int j=0;j1) //Set the simulation type to -1 -> user selects different file types
- {
- simType = -1;
- displayInformation(-1); //Display some information to the console
- }
- if (vecInt.size()==1) //Set the sim type to whatever it is
- {
- simType = vecInt[0];
- displayInformation(vecInt[0]);
- }
- else //we probably failed to open it because its a bad file
- {
- simType = -1;
- displayInformation(-1);
- }
-}
-
-/**
- * @brief Figures out what format belongs to what file based on the presence of date time
- * data and header information
- * Turns options on and off for the gui based on what the file formats are, such as
- * enables timeseries when there is a timeseries. Suggests time series data ranges.
- * prevents timeseries when there is no way it is a timeseries
- * * *
- * Possible options to be returned from directStationTraffic:
- * a. 0 : OLD FORMAT <-1 Step
- * b. 1 : NEW FORMAT, Time Series <- Multiple Steps
- * c. 2 : NEW FORMAT, NO Time Series <- 1 Step
- * d. -1 : Something bad happened, not sure what at this point
- * @param xFileName <- the file name of the wxStation to be read from disk.
- * @return see above
- */
-int pointInput::directStationTraffic(const char* xFileName)
-{
- //Get the header version from a wxStation function that does this for us
- int stationHeader = wxStation::GetHeaderVersion(xFileName);
- CPLDebug("STATION_FETCH","HEADER TYPE: %i",stationHeader);
- int instant = 0;
- std::string idx3;
- stringstream ssidx;
-
- if(stationHeader!=1) //Station header is different than what we return
- {
- //Determine whether it is a timeseries or not...
- OGRDataSourceH hDS;
- OGRLayer *poLayer;
- OGRFeature *poFeature;
- OGRFeatureDefn *poFeatureDefn;
- OGRFieldDefn *poFieldDefn;
- OGRLayerH hLayer;
-
- hDS = OGROpen( xFileName, FALSE, NULL );
-
- if(hDS == NULL)
- {
- writeToConsole("Cannot open station file!");
- return -1; //very bad!
- }
-
- poLayer = (OGRLayer*)OGR_DS_GetLayer( hDS, 0 );
- hLayer=OGR_DS_GetLayer(hDS,0);
- OGR_L_ResetReading(hLayer);
- poLayer->ResetReading();
-
- GIntBig iBig = 1;
- GIntBig idx0 = poLayer->GetFeatureCount();
- GIntBig idx1 = idx0-iBig;
- GIntBig idx2;
-
- idx2 = poLayer->GetFeatureCount();
-
- CPLDebug("STATION_FETCH","Number of Time Entries: %llu",idx2); //How many lines are on disk
- QString qFileName = QFileInfo(xFileName).fileName();
- writeToConsole(QString(qFileName+" has: "+QString::number(idx2)+" time entries")); //tell the user in the console
- const char* emptyChair; //Muy Importante!
-
- poFeature = poLayer->GetFeature(iBig);
- if (poFeature==NULL)
- {
- writeToConsole("No Stations Found in file!");
- return -1; //If there are no stations in the csv!
- }
- // startTime = poFeature->GetFieldAsString(15);
- std::string start_datetime(poFeature->GetFieldAsString(15));
- poFeature = poLayer->GetFeature(idx2);
- std::string stop_datetime(poFeature->GetFieldAsString(15));
-
- CPLDebug("STATION_FETCH","STATION START TIME: %s",start_datetime.c_str());
- CPLDebug("STATION_FETCH","STATION END TIME: %s",stop_datetime.c_str());
-
- if (start_datetime.empty()==true && stop_datetime.empty()==true)
- {
- //Means that there is not a time series
- CPLDebug("STATION_FETCH", "File cannot be used for Time Series");
- instant = 1;
- }
- if (start_datetime.empty()==false && stop_datetime.empty()==false) //Definately some sort of time series
- {
- CPLDebug("STATION_FETCH","File can be used for Times Series");
- CPLDebug("STATION_FETCH","Suggesting Potentially Reasonable Time Series Parameters...");
-
- ///// check whether the times are valid HERE, while we still have access to file index, last selected file information, and error type information
- QString q_time_format = "yyyy-MM-ddTHH:mm:ssZ";
- if( start_datetime.length() < q_time_format.toStdString().length() )
- {
- QMessageBox::critical(this, tr("Failure."), "station start_time "+QString(start_datetime.c_str())+" is invalid length!", QMessageBox::Ok | QMessageBox::Default);
- // need to deselect the last selected station file as well
- deselectStationFile(xFileName);
- return -1;
- }
- if( stop_datetime.length() < q_time_format.toStdString().length() )
- {
- QMessageBox::critical(this, tr("Failure."), "station stop_time "+QString(stop_datetime.c_str())+" is invalid length!", QMessageBox::Ok | QMessageBox::Default);
- // need to deselect the last selected station file as well
- deselectStationFile(xFileName);
- return -1;
- }
- if( start_datetime[4] != '-' || start_datetime[7] != '-' || start_datetime[10] != 'T' || start_datetime[13] != ':' || start_datetime[16] != ':' || start_datetime[19] != 'Z')
- {
- QMessageBox::critical(this, tr("Failure."), "station start_time "+QString(start_datetime.c_str())+" has invalid format!", QMessageBox::Ok | QMessageBox::Default);
- // need to deselect the last selected station file as well
- deselectStationFile(xFileName);
- return -1;
- }
- if( stop_datetime[4] != '-' || stop_datetime[7] != '-' || stop_datetime[10] != 'T' || stop_datetime[13] != ':' || stop_datetime[16] != ':' || stop_datetime[19] != 'Z')
- {
- QMessageBox::critical(this, tr("Failure."), "station stop_time "+QString(stop_datetime.c_str())+" has invalid format!", QMessageBox::Ok | QMessageBox::Default);
- // need to deselect the last selected station file as well
- deselectStationFile(xFileName);
- return -1;
- }
-
- readStationTime(start_datetime,stop_datetime,idx2); //Turns the Start and Stop times into local timess......
- ssidx<setEnabled(false); //Hide these things because its an old format run
- stopTime->setEnabled(false);
- numSteps->setEnabled(false);
-
- //Try flipping the UI
- startLabel->setVisible(false); //Hide all the timesries stuff
- stopLabel->setVisible(false);
- stepLabel->setVisible(false);
-
- startTime->setVisible(false);
- stopTime->setVisible(false);
- numSteps->setVisible(false);
-
- dateTimeEdit->setVisible(true); //show the date time box to set the sim time
- diurnalLabel->setVisible(true);
- oneStepTimeLabel->setVisible(false); // hide the 1 step time box thing for instant==1
-
- //Update Diurnal Time
- if (isDiurnalChecked==true)
- {
- dateTimeEdit->setEnabled(true); //enable the diurnal Box
- updateSingleTime(dateTimeEdit->dateTime()); //set the time from the diurnal box
- }
-
-
- return 0;
- }
- if (stationHeader == 2 && instant == 0)
- {
- //new Foramt w/ Time Series
- //Turn on Several options for controlling time series in the GUI
- enableTimeseries=true;
- startTime->setEnabled(true);
- stopTime->setEnabled(true);
- numSteps->setEnabled(true);
- updateStartTime(startTime->dateTime());
- updateStopTime(stopTime->dateTime());
-
- //try flipping the UI
- startLabel->setVisible(true);
- stopLabel->setVisible(true);
- stepLabel->setVisible(true);
-
- startTime->setVisible(true);
- stopTime->setVisible(true);
- numSteps->setVisible(true);
-
- dateTimeEdit->setVisible(false); //hide the single step stuff
- diurnalLabel->setVisible(false);
- oneStepTimeLabel->setVisible(false);
- return 1;
- }
- if (stationHeader == 2 && instant == 1)
- {
- //new Format no Time Series
- //Prevent users from using time series with 1 step
- enableTimeseries=false;
- startTime->setEnabled(false);
- stopTime->setEnabled(false);
- numSteps->setEnabled(false);
-
- //Try flipping the UI
- startLabel->setVisible(false);
- stopLabel->setVisible(false);
- stepLabel->setVisible(false);
-
- startTime->setVisible(false);
- stopTime->setVisible(false);
- numSteps->setVisible(false);
-
- dateTimeEdit->setVisible(false);
- diurnalLabel->setVisible(false);
- dateTimeEdit->setEnabled(false);
-
- const char *optChangeTime = CPLGetConfigOption("CHANGE_DATE_TIME","FALSE"); //Allow the user the change the datetime via config option
- if(optChangeTime!="FALSE")
- {
- QString time_format = "yyyy-MM-ddTHH:mm:ss";
- QString optXTime = QString::fromAscii(optChangeTime);
- QDateTime opt_time_obj = QDateTime::fromString(optXTime,time_format);
- updateSingleTime(opt_time_obj);
- QString oneStepText = "Simulation time set to: "+optXTime;
- oneStepTimeLabel->setText(oneStepText);
- oneStepTimeLabel->setVisible(true); // to this label in the GUI
- }
- else
- {
- //Reads the sim time from the file the user provides;
- QDateTime singleRunTime = readNinjaNowName(xFileName); //Read in the date time
- updateSingleTime(singleRunTime); //update it globally
- QString runTimeText = singleRunTime.toString(); //Print it out for the user
- QString oneStepText = "Simulation time set to: "+runTimeText;
- oneStepTimeLabel->setText(oneStepText);
- oneStepTimeLabel->setVisible(true); // to this label in the GUI
- }
- return 2;
-
- }
- if (stationHeader == 3)
- {
- //Invalid header type for GUI run...
- return -1;
- }
- if (stationHeader == 4)
- {
- //Invalid header type for GUI run...
- return -1;
- }
- else
- {
- //Something wrong with the station...
- return -1;
- }
-}
-/**
- * @brief pointInput::readStationTime: Takes in times read from disk, turns them into
- * Qt datetime objects, then updates the gui with suggested ranges of times based on available disk data
- * tries to stop users from picking frivolous time ranges (maybe). Also suggests a number of timesteps based on
- * available data.
- * @param start_time
- * @param stop_time
- * @param xSteps
- */
-void pointInput::readStationTime(string start_time, string stop_time, int xSteps)
-{
- QString q_time_format = "yyyy-MM-ddTHH:mm:ssZ";
-
- //// convert the input start and stop times into boost local date time objects, so convert from UTC time to local time
-
- blt::time_zone_ptr tz; // Initialize time zone
- tz = globalTimeZoneDB.time_zone_from_region(tzString.toStdString()); // Get time zone from database
-
- // parse the start time into date and time parts
- int start_year = atoi(start_time.substr(0, 4).c_str());
- int start_month = atoi(start_time.substr(5, 2).c_str());
- int start_day = atoi(start_time.substr(8, 2).c_str());
- int start_hour = atoi(start_time.substr(11, 2).c_str());
- int start_minute = atoi(start_time.substr(14, 2).c_str());
- int start_sec = atoi(start_time.substr(17, 2).c_str());
-
- // parse the start time into date and time parts
- int stop_year = atoi(stop_time.substr(0, 4).c_str());
- int stop_month = atoi(stop_time.substr(5, 2).c_str());
- int stop_day = atoi(stop_time.substr(8, 2).c_str());
- int stop_hour = atoi(stop_time.substr(11, 2).c_str());
- int stop_minute = atoi(stop_time.substr(14, 2).c_str());
- int stop_sec = atoi(stop_time.substr(17, 2).c_str());
-
- // make intermediate start and stop dates for generating ptime objects
- bg::date startTime_date(start_year,start_month,start_day);
- bg::date stopTime_date(stop_year,stop_month,stop_day);
- bpt::time_duration startTime_duration(start_hour,start_minute,start_sec,0);
- bpt::time_duration stopTime_duration(stop_hour,stop_minute,stop_sec,0);
-
- // these are UTC times
- bpt::ptime startTime_ptime(startTime_date,startTime_duration);
- bpt::ptime stopTime_ptime(stopTime_date,stopTime_duration);
-
- // this constructor generates local times from UTC times
- blt::local_date_time boost_local_startTime( startTime_ptime, tz );
- blt::local_date_time boost_local_stopTime( stopTime_ptime, tz );
-
-
- //// convert the boost local date time objects into QDateTime objects
-
- std::string os_time_format = "%Y-%m-%dT%H:%M:%SZ"; // this is the ostringstream format string that replicates the above QDateTime format string
-
- bpt::time_facet* facet;
- facet = new bpt::time_facet();
-
- facet->format(os_time_format.c_str());
-
-
- // calculate the start_time QDate
- std::ostringstream os;
- os.imbue(std::locale(std::locale::classic(), facet));
- //os << boost_local_startTime.utc_time();
- os << boost_local_startTime.local_time();
- QString loc_start_time_qStr = QString::fromStdString( os.str() );
- os.str(""); // reset for parsing the next time
- os.clear();
- QDateTime loc_start_time = QDateTime::fromString(loc_start_time_qStr,q_time_format);
-
- // calculate the end_time QDate
- os.imbue(std::locale(std::locale::classic(), facet));
- //os << boost_local_stopTime.utc_time();
- os << boost_local_stopTime.local_time();
- QString loc_end_time_qStr = QString::fromStdString( os.str() );
- os.str(""); // reset for parsing the next time
- os.clear();
- QDateTime loc_end_time = QDateTime::fromString(loc_end_time_qStr,q_time_format);
-
- CPLDebug("STATION_FETCH","qdate start_local = %s",loc_start_time.toString(q_time_format).toStdString().c_str());
- CPLDebug("STATION_FETCH","qdate end_local = %s",loc_end_time.toString(q_time_format).toStdString().c_str());
-
-
- //// now use the final local time QDate start and stop times
- writeToConsole("Start Time (local): "+loc_start_time.toString()); //Tell console what the
- writeToConsole("Stop Time (local): "+loc_end_time.toString()); //Local time is
-
- startTime->setDateTime(loc_start_time);
- stopTime->setDateTime(loc_end_time); //Updates date time based on disk information
-
- updateTimeSteps(); //Calculate how many steps we can do between the start and stop time
-}
-/**
- * @brief pointInput::displayInformation
- * Displays important stuff to the user based on what they select
- * Warns them if they select 2 types of files that are incompatible.
- * @param dataType
- */
-void pointInput::displayInformation(int dataType)
-{
- CPLDebug("STATION_FETCH","Data Format: %i",dataType);
- if(dataType == 0)
- {
- clippit->setText("Run Type: Old Format");
- pointGo=true;
- if (isDiurnalChecked==true)
- {
- dateTimeEdit->setEnabled(true);
- }
- if (stationFileList.size()>1)
- {
- clippit->setText("Too many stations selected for data type");
- }
- }
- if(dataType == 1)
- {
- clippit->setText("Run Type: Time Series");
- pointGo=true;
- if (dateTimeEdit->isEnabled())
- {
- dateTimeEdit->setEnabled(false);
- }
- }
- if(dataType == 2)
- {
- clippit->setText("Run Type: Single Step");
- pointGo=true;
- }
- if (dataType == -1 && stationFileList.size()==0) //Special Case
- {
- clippit->setText("No Stations Selected...");
- pointGo=false;
- }
- if (dataType == -1 && stationFileList.size()==1) //Case of 1 file that is crap
- {
- clippit->setText("No Valid Data detected in file...");
-
- pointGo=false;
- }
- if (dataType==-1 && stationFileList.size()>=2)
- {
- clippit->setText("MULTIPLE TYPES SELECTED, CANNOT PROCEED!");
-
- pointGo=false;
- }
-// else if(dataType == -1)
-// {
-// clippit->setText("MULTIPLE TYPES SELECTED, CANNOT PROCEED!");
-// pointGo=false;
-// }
-}
-/**
- * @brief pointInput::readNinjaNowName
- * @param fileName
- * This is for current step new format runs
- * we need time if the user turnsl on diurnal/stability input
- * Read the Time from the date created attribute attached to the file
- *
- * @return
- */
-QDateTime pointInput::readNinjaNowName(const char *fileName)
-{
- CPLDebug("STATION_FETCH","Reading 1 step Station start Time");
- QDateTime qxDate = QFileInfo(fileName).created(); //Get when the file was created because that is when the simulation time is
- return qxDate;
-}
-/**
- * @brief pointInput::setOneStepTimeseries
- * If one step is set, diable stop time
- * and only use start time
- */
-void pointInput::setOneStepTimeseries()
-{
- if(numSteps->value()==1)
- {
- CPLDebug("STATION_FETCH","One Step Set for Timeseries, greying out stop time!");
- stopTime->setEnabled(false);
- stopTime->setToolTip("Stop time is disabled for 1 time step simulations");
- }
- else
- {
- stopTime->setEnabled(true);
- stopTime->setToolTip("Enter the simulation stop time");
- }
-}
-
-
-/**
- * @brief pointInput::setWxStationFormat
- * sets the format of the wxStation
- * not used right now
- * @param format
- */
-void pointInput::setWxStationFormat(int format)
-{
- wxStationFormat = format;
-}
-
-void pointInput::selChanged(const QItemSelection &x, const QItemSelection &y) //Generic test function, delete once everything is good
-{
- CPLDebug("STATION_FETCH","TEST");
-}
-
-void pointInput::openMainWindow() //This is for opening and closing the station-fetch widget
-{
- this->setEnabled(true);
-}
-
-/** Allows mainwindow to update the timezone from the DEM or as provided by the user
- * @brief pointInput::updateTz
- * @param tz
- */
-
-void pointInput::updateTz(QString tz)
-{
- tzString = tz;
-}
-
-/** Pairs start and stop times to what the stationFetchWidget does.
- * @brief pointInput::pairStartTime
- * @param xDate
- */
-void pointInput::pairStartTime(QDateTime xDate) //These functions take the start and stop time from the widget
-//and populate the timeseries objects in the gUI
-{
- startTime->setDateTime(xDate);
-}
-void pointInput::pairStopTime(QDateTime xDate)
-{
- stopTime->setDateTime(xDate);
-}
-/** Groups all the different timseries parts to be enabled/disabled at the same time based on
- * user options
- * @brief pointInput::pairTimeSeries
- * @param curIndex
- */
-void pointInput::pairTimeSeries(int curIndex)
-{
- if(curIndex==0)
- {
- enableTimeseries=true;
- startTime->setEnabled(false);
- stopTime->setEnabled(false);
- numSteps->setEnabled(false);
- }
- if(curIndex==1)
- {
- enableTimeseries=true;
- startTime->setEnabled(true);
- stopTime->setEnabled(true);
- numSteps->setEnabled(true);
- }
-}
-/**
- * @brief pointInput::watchStopTime
- * corrects user selecting stop time behind start time!
- */
-void pointInput::watchStopTime() //Stop time cannot be farther in the future than the stop time
-{
- if(stopTime->dateTime()dateTime())
- {
- writeToConsole("Start Time is greater than Stop Time!");
- CPLDebug("STATION_FETCH","START TIME > END TIME, FIXING START TIME!");
- startTime->setDateTime(stopTime->dateTime().addSecs(-3600));
- }
-}
-/**
- * @brief pointInput::watchStartTime
- * corrects the stop time if the user picks a start time farther in the future than the stop
- * time
- */
-void pointInput::watchStartTime() //Stop time cannot be farther in the future than the stop time
-{
- if(stopTime->dateTime()dateTime())
- {
- writeToConsole("Start Time is greater than Stop Time!");
- CPLDebug("STATION_FETCH","START TIME > END TIME, FIXING STOP TIME!");
- stopTime->setDateTime(startTime->dateTime().addSecs(3600));
- }
-}
-/** Updates the timeseries start time based on user requests
- * @brief pointInput::updateStartTime
- * @param xDate
- */
-void pointInput::updateStartTime(QDateTime xDate)
-{
- startSeries.clear(); //delete whatever is stored in the vector
- int year,month,day,hour,minute;
- year = xDate.date().year();
- month = xDate.date().month();
- day = xDate.date().day();
- hour = xDate.time().hour();
- minute = xDate.time().minute();
-
- updateTimeSteps(); //when we change the time, update the math on the time steps
- CPLDebug("STATION_FETCH","UPDATED START TIME: %i %i %i %i %i",year,month,day,hour,minute);
-
- startSeries.push_back(year);
- startSeries.push_back(month);
- startSeries.push_back(day);
- startSeries.push_back(hour);
- startSeries.push_back(minute);
-}
-/** Updates the time for stopping the simulation based on user requests
- * @brief pointInput::updateStopTime
- * @param xDate
- */
-void pointInput::updateStopTime(QDateTime xDate)
-{
- endSeries.clear(); //delete whatever is stored in the vector
- int year,month,day,hour,minute;
- year = xDate.date().year();
- month = xDate.date().month();
- day = xDate.date().day();
- hour = xDate.time().hour();
- minute = xDate.time().minute();
-
- updateTimeSteps(); //when we change the time, update the math on the time steps
-
- CPLDebug("STATION_FETCH","UPDATED STOP TIME: %i %i %i %i %i",year,month,day,hour,minute);
-
- endSeries.push_back(year);
- endSeries.push_back(month);
- endSeries.push_back(day);
- endSeries.push_back(hour);
- endSeries.push_back(minute);
-}
-/**
- * @brief pointInput::updateSingleTime
- * @param xDate
- *
- * For single step runs, set the simulation time based on the read station file time,
- * see also:
- * readNinjaNowName()
- *
- */
-void pointInput::updateSingleTime(QDateTime xDate)
-{
- int year,month,day,hour,minute;
- year = xDate.date().year();
- month = xDate.date().month();
- day = xDate.date().day();
- hour = xDate.time().hour();
- minute = xDate.time().minute();
-
- CPLDebug("STATION_FETCH","UPDATED SINGLE STEP TIME: %i %i %i %i %i",year,month,day,hour,minute);
-
- diurnalTimeVec.push_back(year);
- diurnalTimeVec.push_back(month);
- diurnalTimeVec.push_back(day);
- diurnalTimeVec.push_back(hour);
- diurnalTimeVec.push_back(minute);
-
-}
-/**
- * @brief pointInput::updateTimeSteps
- * Suggest a number of time steps based on the
- * start and stop time
- *
- * this function sets the number of time steps to the number of
- * hours between the start and stop time
- *
- * if its less than 2 hours,
- * suggest two steps
- *
- * the user can then change this if they really want
- *
- */
-void pointInput::updateTimeSteps()
-{
- CPLDebug("STATION_FETCH","Updating Suggested Time steps....");
- int u_start = startTime->dateTime().toTime_t();
- int u_stop = stopTime->dateTime().toTime_t();
-
- if ( u_start == u_stop ) {
-
- numSteps->setValue(1);
-
- } else {
-
- int u_diff = (u_stop - u_start)/(3600); //calculate the number of hours between the start and stop times
-
- if(u_diff<=2) //if its less than 2 hours, make it 2
- {
- u_diff = 2;
- }
-
- numSteps->setValue(u_diff);
-
- }
-}
-/**
- * @brief pointInput::openStationFetchWidget
- * Opens the downloader widget to download station files
- */
-void pointInput::openStationFetchWidget()
-{
- xWidget = new stationFetchWidget();
- QSignalMapper *signalMapper;
- connect(xWidget, SIGNAL(exitWidget()),this, SLOT(openMainWindow())); //Launches Widget Connector
- connect(xWidget, SIGNAL(destroyed()),this,SLOT(openMainWindow())); //Some sort of deconstructor thing
- this->setEnabled(false); //disable the main window
- xWidget->setInputFile(demFileName); //give the widget the dem file
- xWidget->updatetz(tzString); //give the widget the time zone as a string
- connect(xWidget, SIGNAL(exitWidget()),this, SLOT(checkForModelData())); //Launches Widget Connector
- connect(xWidget->startEdit,SIGNAL(dateTimeChanged(const QDateTime)),this,SLOT(pairStartTime(const QDateTime))); //connect the various time boxes to eachother
- connect(xWidget->endEdit,SIGNAL(dateTimeChanged(const QDateTime)),this,SLOT(pairStopTime(const QDateTime)));
- connect(xWidget->timeLoc,SIGNAL(currentIndexChanged(int)),this,SLOT(pairTimeSeries(int))); //Connects What the user does in the widget
- //to what the timeseries checkbox does
-}
-/** Allows mainwindow to update pointInput with changes to the DEM
- * @brief pointInput::setInputFile
- * @param file
- */
-void pointInput::setInputFile( QString file )
-{
- demFileName = file;
- cwd = QFileInfo(file).absolutePath();
-}
-/** Allows mainWindow to update pointInput with changes in diurnal/stability options
- * @brief pointInput::setDiurnalParam
- * @param diurnalCheck
- */
-void pointInput::setDiurnalParam(bool diurnalCheck)
-{
- isDiurnalChecked = diurnalCheck;//Note that this works for stability too
- CPLDebug("STATION_FETCH","DIURNAL/STABILITY STATUS: %i",isDiurnalChecked);
-}
-
-void pointInput::deselectStationFile(const char* stationFileName)
-{
- QModelIndex QFileIdx = sfModel->index(stationFileName);
- if( QFileIdx.isValid() )
- {
- treeView->selectionModel()->select(QFileIdx, QItemSelectionModel::Deselect | QItemSelectionModel::Rows);
- }
-}
-
-/**
- * *@brief pointInput::checkForModelData
- * Applies filters to the tree
- * Also clears selection when the user clicks it
- */
-void pointInput::checkForModelData()
-{
- stationFileList.clear(); //Clear the list
- treeView->selectionModel()->clear(); //Clear the models selections
- pointGo = false; //Set the pointInput bool to false just to be extra explicit
- QDir wd(cwd);
- QStringList filters;
- filters<<"*.csv"; //Only show CSV
- filters<<"WXSTATIONS-*"; //Add downloadable directories to filters
- sfModel->setNameFilters(filters);
- sfModel->setFilter(QDir::Dirs | QDir::Files | QDir::NoDotAndDotDot); //QDir::Dir specifies to add filters to directories
- treeView->setRootIndex(sfModel->index(wd.absolutePath()));
- treeView->resizeColumnToContents(0);
-}
diff --git a/src/gui/pointInput.h b/src/gui/pointInput.h
deleted file mode 100644
index 7225b3e83..000000000
--- a/src/gui/pointInput.h
+++ /dev/null
@@ -1,189 +0,0 @@
-/******************************************************************************
- *
- * $Id$
- *
- * Project: WindNinja Qt GUI
- * Purpose: Point initialization input.
- * Author: Kyle Shannon
- *
- ******************************************************************************
- *
- * THIS SOFTWARE WAS DEVELOPED AT THE ROCKY MOUNTAIN RESEARCH STATION (RMRS)
- * MISSOULA FIRE SCIENCES LABORATORY BY EMPLOYEES OF THE FEDERAL GOVERNMENT
- * IN THE COURSE OF THEIR OFFICIAL DUTIES. PURSUANT TO TITLE 17 SECTION 105
- * OF THE UNITED STATES CODE, THIS SOFTWARE IS NOT SUBJECT TO COPYRIGHT
- * PROTECTION AND IS IN THE PUBLIC DOMAIN. RMRS MISSOULA FIRE SCIENCES
- * LABORATORY ASSUMES NO RESPONSIBILITY WHATSOEVER FOR ITS USE BY OTHER
- * PARTIES, AND MAKES NO GUARANTEES, EXPRESSED OR IMPLIED, ABOUT ITS QUALITY,
- * RELIABILITY, OR ANY OTHER CHARACTERISTIC.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *
- *****************************************************************************/
-
-#ifndef POINT_INPUT_H
-#define POINT_INPUT_H
-
-#include
-#include
-
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-
-#include
-
-#include "latLonWidget.h"
-#include "wxStation.h"
-#include "ninjaUnits.h"
-#include "stationFetchWidget.h"
-#include
-
-#include
-#include
-
-#include
-
-#include
-
-class pointInput : public QWidget
-{
- Q_OBJECT
-
- public:
-
- pointInput( QWidget *parent = 0 );
- ~pointInput();
-
- QString demFileName;
- QString stationFileName;
- std::vector stationFileList;
- std::vector stationFileTypes;
- int simType;
- bool pointGo;
- int isDiurnalChecked;
- bool enableTimeseries;
-
- QHBoxLayout *diurnalTimeLayout;
- QDateTimeEdit *dateTimeEdit;
- QLabel *diurnalLabel;
- QLabel *oneStepTimeLabel;
-
- QCheckBox *writeStationFileButton;
- QCheckBox *writeStationKmlButton;
- QToolButton *widgetButton;
-
- QGroupBox *pointGroupBox;
-
- QHBoxLayout *buttonLayout;
- QVBoxLayout *pointLayout;
- QVBoxLayout *layout;
- QLabel *ninjafoamConflictLabel;
-
- //TreeBox Stuff
-
- QLabel *treeLabel;
-
- QTreeView *treeView;
- QVBoxLayout *vTreeLayout;
- QHBoxLayout *hDownloaderLayout; //Put the downloader up near the top of the page
- QWidget *newForm;
-
- //Station Fetch Directory Stuff
-
- QDir cwd;
- QDirModel *sfModel;
- //Handlers
- QHBoxLayout *ClippyToolLayout;
- QToolButton *refreshToolButton;
- QLabel *clippit; //displays vital information
-
- QFrame *timeLine; //Creates a fancy line to seprate things out
- QFrame *timeLine2; //Creates another fancy line...
-
- std::vector vx; //For file names
-
- //endDirectoryChecking
- //Time series stuff
- QDateTimeEdit *startTime;
- QDateTimeEdit *stopTime;
- QHBoxLayout *timeBoxLayout;
- QSpinBox *numSteps;
-
- QVBoxLayout *startLayout;
- QVBoxLayout *stopLayout;
- QVBoxLayout *stepLayout;
-
- QLabel *startLabel;
- QLabel *stopLabel;
- QLabel *stepLabel;
-
- std::vector startSeries;
- std::vector endSeries; //Global Storage for start and stop times
-
- std::vector diurnalTimeVec;
-
- //End Timeseries stuff
-
- stationFetchWidget *xWidget;
- QString tzString;
-
- void deselectStationFile(const char* stationFileName);
-
- public slots:
- void updateTz(QString tz);
- void checkForModelData();
- int directStationTraffic(const char* xFileName);
- void readStationTime(std::string start_time, std::string stop_time, int xSteps);
- static void setWxStationFormat(int format); //I don't Think I need this anymore (delete later)
- void displayInformation(int dataType);
- QDateTime readNinjaNowName(const char* fileName);
- void setOneStepTimeseries();
-
- private slots:
- void readStationFiles(const QItemSelection &x ,const QItemSelection &y);
- void selChanged(const QItemSelection &x ,const QItemSelection &y); //Test Function
- void setInputFile( QString file );
- void setDiurnalParam(bool diurnalCheck);
- void openMainWindow();
- void openStationFetchWidget();
-
- void pairStartTime(QDateTime xDate);
- void pairStopTime(QDateTime xDate);
- void pairTimeSeries(int curIndex);
- void updateTimeSteps();
-
- void updateSingleTime(QDateTime xDate);
- void updateStartTime(QDateTime xDate);
- void updateStopTime(QDateTime xDate);
- void watchStopTime();
- void watchStartTime();
-
- signals:
- void writeToConsole( QString message );
- void stationFileChanged();
-
-friend class stationFetchWidget;
-};
-
-#endif /* POINT_INPUT_H */
diff --git a/src/gui/qt6/CMakeLists.txt b/src/gui/qt6/CMakeLists.txt
new file mode 100755
index 000000000..0331b5f01
--- /dev/null
+++ b/src/gui/qt6/CMakeLists.txt
@@ -0,0 +1,81 @@
+cmake_minimum_required(VERSION 3.16)
+
+set(CMAKE_AUTOUIC ON)
+set(CMAKE_AUTOMOC ON)
+set(CMAKE_AUTORCC ON)
+
+find_package(QT NAMES Qt6 REQUIRED COMPONENTS Widgets)
+find_package(Qt6 REQUIRED COMPONENTS
+ Core
+ Widgets
+ WebEngineWidgets
+ WebChannel
+)
+
+set(PROJECT_SOURCES
+ main.cpp
+ mainWindow.cpp
+ mainWindow.h
+ mainWindow.ui
+)
+
+if(${QT_VERSION_MAJOR} GREATER_EQUAL 6)
+ qt_add_executable(WindNinja
+ MANUAL_FINALIZATION
+ ${PROJECT_SOURCES}
+ ${CMAKE_SOURCE_DIR}/wn-resources.qrc
+ appState.h
+ appState.cpp
+ splashScreen.h
+ splashScreen.cpp
+ surfaceInput.h
+ surfaceInput.cpp
+ setConfigurationDialogOption.h
+ setConfigurationDialogOption.cpp
+ setConfigurationDialogOption.ui
+ menuBar.h
+ menuBar.cpp
+ mapBridge.h
+ mapBridge.cpp
+ surfaceInput.h
+ surfaceInput.cpp
+ serverBridge.h
+ serverBridge.cpp
+ domainAverageInput.h
+ domainAverageInput.cpp
+ pointInitializationInput.h
+ pointInitializationInput.cpp
+ weatherModelInput.h
+ weatherModelInput.cpp
+ outputs.h
+ outputs.cpp
+ )
+else()
+ add_executable(WindNinja
+ ${PROJECT_SOURCES}
+ )
+endif()
+
+if(WIN32)
+ target_link_libraries(WindNinja PRIVATE shapelib::shp GDAL::GDAL)
+endif()
+
+target_link_libraries(WindNinja PRIVATE Qt${QT_VERSION_MAJOR}::Widgets PRIVATE Qt${QT_VERSION_MAJOR}::WebEngineWidgets PRIVATE ninja)
+target_link_libraries(WindNinja PRIVATE Qt6::Core)
+
+target_link_libraries(WindNinja
+ PRIVATE Qt${QT_VERSION_MAJOR}::Widgets
+ PRIVATE Qt${QT_VERSION_MAJOR}::WebEngineWidgets
+ PRIVATE Qt${QT_VERSION_MAJOR}::WebChannel
+ PRIVATE ninja
+)
+
+include(GNUInstallDirs)
+install(TARGETS WindNinja
+ LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
+ RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
+)
+
+if(QT_VERSION_MAJOR EQUAL 6)
+ qt_finalize_executable(WindNinja)
+endif()
diff --git a/src/gui/qt6/appState.cpp b/src/gui/qt6/appState.cpp
new file mode 100644
index 000000000..f777cbf78
--- /dev/null
+++ b/src/gui/qt6/appState.cpp
@@ -0,0 +1,477 @@
+ /******************************************************************************
+ *
+ * $Id$
+ *
+ * Project: WindNinja Qt GUI
+ * Purpose: Stores the states for inputs in the GUI
+ * Author: Mason Willman
+ *
+ ******************************************************************************
+ *
+ * THIS SOFTWARE WAS DEVELOPED AT THE ROCKY MOUNTAIN RESEARCH STATION (RMRS)
+ * MISSOULA FIRE SCIENCES LABORATORY BY EMPLOYEES OF THE FEDERAL GOVERNMENT
+ * IN THE COURSE OF THEIR OFFICIAL DUTIES. PURSUANT TO TITLE 17 SECTION 105
+ * OF THE UNITED STATES CODE, THIS SOFTWARE IS NOT SUBJECT TO COPYRIGHT
+ * PROTECTION AND IS IN THE PUBLIC DOMAIN. RMRS MISSOULA FIRE SCIENCES
+ * LABORATORY ASSUMES NO RESPONSIBILITY WHATSOEVER FOR ITS USE BY OTHER
+ * PARTIES, AND MAKES NO GUARANTEES, EXPRESSED OR IMPLIED, ABOUT ITS QUALITY,
+ * RELIABILITY, OR ANY OTHER CHARACTERISTIC.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ *****************************************************************************/
+
+#include "appState.h"
+
+AppState& AppState::instance()
+{
+ static AppState s;
+ return s;
+}
+
+AppState::AppState()
+ : tickIcon(":/tick.png"),
+ warnIcon(":/jason_caution.png"),
+ crossIcon(":/cross.png"),
+ bulletIcon(":/bullet_blue.png")
+{}
+
+void AppState::setUi(Ui::MainWindow* mainWindowUi)
+{
+ ui = mainWindowUi;
+}
+
+void AppState::setState()
+{
+ updateSolverMethodologyState();
+ updateSurfaceInputState();
+ updateDiurnalInputState();
+ updateStabilityInputState();
+ updateDomainAverageInputState();
+ updatePointInitializationInputState();
+ updateWeatherModelInputState();
+ updateGoogleEarthOutputState();
+ updateFireBehaviorOutputState();
+ updateShapeFilesOutputState();
+ updateGeoSpatialPDFFilesOutputState();
+ updateVTKFilesOutputState();
+}
+
+void AppState::updateSolverMethodologyState()
+{
+ if (isMassSolverToggled)
+ {
+ isSolverMethodologyValid = true;
+ ui->treeWidget->topLevelItem(0)->setIcon(0, tickIcon);
+ ui->treeWidget->topLevelItem(0)->setToolTip(0, "Using Conservation of Mass Selected");
+ ui->treeWidget->topLevelItem(0)->child(0)->setIcon(0, tickIcon);
+ ui->treeWidget->topLevelItem(0)->child(0)->setToolTip(0, "Conservation of Mass Selected");
+ ui->treeWidget->topLevelItem(0)->child(1)->setIcon(0, bulletIcon);
+ ui->treeWidget->topLevelItem(0)->child(1)->setToolTip(0, "Conservation of Mass and Momentum Not Selected");
+ }
+ else if (isMomentumSolverToggled)
+ {
+ isSolverMethodologyValid = true;
+ ui->treeWidget->topLevelItem(0)->setToolTip(1, "Conservation of Mass and Momentum Selected");
+ ui->treeWidget->topLevelItem(0)->setIcon(0, tickIcon);
+ ui->treeWidget->topLevelItem(0)->child(1)->setIcon(0, tickIcon);
+ ui->treeWidget->topLevelItem(0)->child(1)->setToolTip(0, "Conservation of Mass and Momentum Selected");
+ ui->treeWidget->topLevelItem(0)->child(0)->setIcon(0, bulletIcon);
+ ui->treeWidget->topLevelItem(0)->child(0)->setToolTip(0, "Conservation of Mass Not Selected");
+ }
+ else
+ {
+ isSolverMethodologyValid = false;
+ ui->treeWidget->topLevelItem(0)->setIcon(0, crossIcon);
+ ui->treeWidget->topLevelItem(0)->setToolTip(0,"Select a Solver");
+ ui->treeWidget->topLevelItem(0)->child(0)->setIcon(0, bulletIcon);
+ ui->treeWidget->topLevelItem(0)->child(0)->setToolTip(0, "Conservation of Mass Not Selected");
+ ui->treeWidget->topLevelItem(0)->child(1)->setIcon(0, bulletIcon);
+ ui->treeWidget->topLevelItem(0)->child(1)->setToolTip(0, "Conservation of Mass and Momentum Not Selected");
+ }
+
+ updateOverallState();
+}
+
+void AppState::updateSurfaceInputState()
+{
+ if (ui->elevationInputFileLineEdit->text() != "")
+ {
+ isSurfaceInputValid = true;
+ ui->treeWidget->topLevelItem(1)->child(0)->setIcon(0, tickIcon);
+ ui->treeWidget->topLevelItem(1)->child(0)->setToolTip(0, "Valid");
+ }
+ else
+ {
+ isSurfaceInputValid = false;
+ ui->treeWidget->topLevelItem(1)->child(0)->setIcon(0, crossIcon);
+ ui->treeWidget->topLevelItem(1)->child(0)->setToolTip(0, "Input File Cannot be Detected");
+ }
+ updateInputState();
+ updateGoogleEarthOutputState();
+}
+
+void AppState::updateDiurnalInputState()
+{
+ if (isDiurnalInputToggled)
+ {
+ ui->treeWidget->topLevelItem(1)->child(1)->setIcon(0, tickIcon);
+ ui->treeWidget->topLevelItem(1)->child(1)->setToolTip(0, "Valid");
+ }
+ else
+ {
+ ui->treeWidget->topLevelItem(1)->child(1)->setIcon(0, bulletIcon);
+ ui->treeWidget->topLevelItem(1)->child(1)->setToolTip(0, "No Diurnal Input");
+ }
+}
+
+void AppState::updateStabilityInputState()
+{
+ if (isStabilityInputToggled)
+ {
+ ui->treeWidget->topLevelItem(1)->child(2)->setIcon(0, tickIcon);
+ ui->treeWidget->topLevelItem(1)->child(2)->setToolTip(0, "Valid");
+ }
+ else
+ {
+ ui->treeWidget->topLevelItem(1)->child(2)->setIcon(0, bulletIcon);
+ ui->treeWidget->topLevelItem(1)->child(2)->setToolTip(0, "No Stability Input");
+ }
+}
+
+void AppState::updateDomainAverageInputState()
+{
+ if(isDomainAverageInitializationToggled)
+ {
+ if(DomainAvgTableNumRuns == 0)
+ {
+ if(ui->diurnalCheckBox->isChecked() == false)
+ {
+ ui->treeWidget->topLevelItem(1)->child(3)->child(0)->setIcon(0, crossIcon);
+ ui->treeWidget->topLevelItem(1)->child(3)->child(0)->setToolTip(0, "No runs have been added, diurnal is not active");
+ isDomainAverageInitializationValid = false;
+ }
+ else // if(ui->diurnalCheckBox->isChecked() == true)
+ {
+ ui->treeWidget->topLevelItem(1)->child(3)->child(0)->setIcon(0, warnIcon);
+ ui->treeWidget->topLevelItem(1)->child(3)->child(0)->setToolTip(0, "No runs have been added, one run will be done at speed = 0, dir = 0 while using diurnal");
+ isDomainAverageInitializationValid = true;
+ }
+ }
+ else // if(DomainAvgTableNumRuns != 0)
+ {
+ if(DomainAvgTableNumZeroRuns == 0)
+ {
+ ui->treeWidget->topLevelItem(1)->child(3)->child(0)->setIcon(0, tickIcon);
+ ui->treeWidget->topLevelItem(1)->child(3)->child(0)->setToolTip(0, QString::number(DomainAvgTableNumRuns)+" runs");
+ isDomainAverageInitializationValid = true;
+ }
+ else // if(DomainAvgTableNumZeroRuns != 0)
+ {
+ if(ui->diurnalCheckBox->isChecked() == true)
+ {
+ ui->treeWidget->topLevelItem(1)->child(3)->child(0)->setIcon(0, warnIcon);
+ ui->treeWidget->topLevelItem(1)->child(3)->child(0)->setToolTip(0, QString::number(DomainAvgTableNumRuns)+" runs have been added, detecting "+QString::number(DomainAvgTableNumZeroRuns)+" zero wind speed runs, diurnal is active so will continue the runs");
+ isDomainAverageInitializationValid = true;
+ }
+ else // if(ui->diurnalCheckBox->isChecked() == false)
+ {
+ ui->treeWidget->topLevelItem(1)->child(3)->child(0)->setIcon(0, crossIcon);
+ ui->treeWidget->topLevelItem(1)->child(3)->child(0)->setToolTip(0, QString::number(DomainAvgTableNumRuns)+" runs have been added, but detecting "+QString::number(DomainAvgTableNumZeroRuns)+" zero wind speed runs without diurnal being active");
+ isDomainAverageInitializationValid = false;
+ }
+ }
+ }
+ }
+ else
+ {
+ ui->treeWidget->topLevelItem(1)->child(3)->child(0)->setIcon(0, bulletIcon);
+ ui->treeWidget->topLevelItem(1)->child(3)->child(0)->setToolTip(0, "Not Selected");
+ isDomainAverageInitializationValid = false;
+ }
+
+ updateInputState();
+}
+
+void AppState::updatePointInitializationInputState()
+{
+ if (isPointInitializationToggled && isStationFileSelectionValid && isStationFileSelected)
+ {
+ ui->treeWidget->topLevelItem(1)->child(3)->child(1)->setIcon(0, tickIcon);
+ ui->treeWidget->topLevelItem(1)->child(3)->child(1)->setToolTip(0, "Valid");
+ isPointInitializationValid = true;
+ }
+ else if(isPointInitializationToggled && !isStationFileSelected)
+ {
+ ui->treeWidget->topLevelItem(1)->child(3)->child(1)->setIcon(0, crossIcon);
+ ui->treeWidget->topLevelItem(1)->child(3)->child(1)->setToolTip(0, "No Station File Selected");
+ isPointInitializationValid = false;
+ }
+ else if(isPointInitializationToggled && !isStationFileSelectionValid)
+ {
+ ui->treeWidget->topLevelItem(1)->child(3)->child(1)->setIcon(0, crossIcon);
+ ui->treeWidget->topLevelItem(1)->child(3)->child(1)->setToolTip(0, "Conflicting Files Selected");
+ isPointInitializationValid = false;
+ }
+ else
+ {
+ ui->treeWidget->topLevelItem(1)->child(3)->child(1)->setIcon(0, bulletIcon);
+ ui->treeWidget->topLevelItem(1)->child(3)->child(1)->setToolTip(0, "Not Selected");
+ isPointInitializationValid = false;
+ }
+
+ updateInputState();
+}
+
+void AppState::updateWeatherModelInputState()
+{
+ if (isWeatherModelInitializationToggled && isWeatherModelForecastValid)
+ {
+ isWeatherModelInitializationValid = true;
+ ui->treeWidget->topLevelItem(1)->child(3)->child(2)->setIcon(0, tickIcon);
+ ui->treeWidget->topLevelItem(1)->child(3)->child(2)->setToolTip(0, "Valid");
+ }
+ else if (isWeatherModelInitializationToggled && !isWeatherModelForecastValid)
+ {
+ isWeatherModelInitializationValid = false;
+ ui->treeWidget->topLevelItem(1)->child(3)->child(2)->setIcon(0, crossIcon);
+ ui->treeWidget->topLevelItem(1)->child(3)->child(2)->setToolTip(0, "Forecast is Invalid");
+ }
+ else
+ {
+ isWeatherModelInitializationValid = false;
+ ui->treeWidget->topLevelItem(1)->child(3)->child(2)->setIcon(0, bulletIcon);
+ ui->treeWidget->topLevelItem(1)->child(3)->child(2)->setToolTip(0, "Not Selected");
+ }
+
+ updateInputState();
+}
+
+void AppState::updateGoogleEarthOutputState()
+{
+ if(ui->googleEarthCheckBox->isChecked())
+ {
+ if(isSurfaceInputValid)
+ {
+ isGoogleEarthValid = true;
+ ui->treeWidget->topLevelItem(2)->child(0)->setIcon(0, tickIcon);
+ ui->treeWidget->topLevelItem(2)->setToolTip(0, "");
+ }
+ else
+ {
+ isGoogleEarthValid = false;
+ ui->treeWidget->topLevelItem(2)->setIcon(0, crossIcon);
+ ui->treeWidget->topLevelItem(2)->setToolTip(0, "Cannot read DEM File");
+ ui->treeWidget->topLevelItem(2)->child(0)->setIcon(0, crossIcon);
+ ui->treeWidget->topLevelItem(2)->child(0)->setToolTip(0, "Cannot read DEM File");
+ }
+ }
+ else
+ {
+ isGoogleEarthValid = false;
+ ui->treeWidget->topLevelItem(2)->child(0)->setIcon(0, bulletIcon);
+ ui->treeWidget->topLevelItem(2)->setToolTip(0, "Not Selected");
+ }
+
+ updateOutputState();
+}
+
+void AppState::updateFireBehaviorOutputState()
+{
+ if(isFireBehaviorToggled)
+ {
+ if(isSurfaceInputValid)
+ {
+ isFireBehaviorValid = true;
+ ui->treeWidget->topLevelItem(2)->child(1)->setIcon(0, tickIcon);
+ ui->treeWidget->topLevelItem(2)->setToolTip(0, "");
+ }
+ else
+ {
+ isFireBehaviorValid = false;
+ ui->treeWidget->topLevelItem(2)->setIcon(0, crossIcon);
+ ui->treeWidget->topLevelItem(2)->setToolTip(0, "Cannot read DEM File");
+ ui->treeWidget->topLevelItem(2)->child(1)->setIcon(0, crossIcon);
+ ui->treeWidget->topLevelItem(2)->child(1)->setToolTip(0, "Cannot read DEM File");
+ }
+ }
+ else
+ {
+ isFireBehaviorValid = false;
+ ui->treeWidget->topLevelItem(2)->child(1)->setIcon(0, bulletIcon);
+ ui->treeWidget->topLevelItem(2)->child(1)->setToolTip(0, "Not Selected");
+ }
+
+ updateOutputState();
+}
+
+void AppState::updateShapeFilesOutputState()
+{
+ if(isShapeFilesToggled)
+ {
+ if(isSurfaceInputValid)
+ {
+ isShapeFilesValid = true;
+ ui->treeWidget->topLevelItem(2)->child(2)->setIcon(0, tickIcon);
+ ui->treeWidget->topLevelItem(2)->setToolTip(0, "");
+ }
+ else
+ {
+ isShapeFilesValid = false;
+ ui->treeWidget->topLevelItem(2)->setIcon(0, crossIcon);
+ ui->treeWidget->topLevelItem(2)->setToolTip(0, "Cannot read DEM File");
+ ui->treeWidget->topLevelItem(2)->child(2)->setIcon(0, crossIcon);
+ ui->treeWidget->topLevelItem(2)->child(2)->setToolTip(0, "Cannot read DEM File");
+ }
+ }
+ else
+ {
+ isShapeFilesValid = false;
+ ui->treeWidget->topLevelItem(2)->child(2)->setIcon(0, bulletIcon);
+ ui->treeWidget->topLevelItem(2)->child(2)->setToolTip(0, "Not Selected");
+ }
+
+ updateOutputState();
+}
+
+void AppState::updateGeoSpatialPDFFilesOutputState()
+{
+ if(isGeoSpatialPDFFilesToggled)
+ {
+ if(isSurfaceInputValid)
+ {
+ isGeoSpatialPDFFilesValid = true;
+ ui->treeWidget->topLevelItem(2)->child(3)->setIcon(0, tickIcon);
+ ui->treeWidget->topLevelItem(2)->setToolTip(0, "");
+ }
+ else
+ {
+ isGeoSpatialPDFFilesValid = false;
+ ui->treeWidget->topLevelItem(2)->setIcon(0, crossIcon);
+ ui->treeWidget->topLevelItem(2)->setToolTip(0, "Cannot read DEM File");
+ ui->treeWidget->topLevelItem(2)->child(3)->setIcon(0, crossIcon);
+ ui->treeWidget->topLevelItem(2)->child(3)->setToolTip(0, "Cannot read DEM File");
+ }
+ }
+ else
+ {
+ isGeoSpatialPDFFilesValid = false;
+ ui->treeWidget->topLevelItem(2)->child(3)->setIcon(0, bulletIcon);
+ ui->treeWidget->topLevelItem(2)->child(3)->setToolTip(0, "Not Selected");
+ }
+
+ updateOutputState();
+}
+
+void AppState::updateVTKFilesOutputState()
+{
+ if(isVTKFilesToggled)
+ {
+ if(isSurfaceInputValid)
+ {
+ isVTKFilesValid = true;
+ ui->treeWidget->topLevelItem(2)->child(4)->setIcon(0, tickIcon);
+ ui->treeWidget->topLevelItem(2)->setToolTip(0, "");
+ }
+ else
+ {
+ isVTKFilesValid = false;
+ ui->treeWidget->topLevelItem(2)->setIcon(0, crossIcon);
+ ui->treeWidget->topLevelItem(2)->setToolTip(0, "Cannot read DEM File");
+ ui->treeWidget->topLevelItem(2)->child(4)->setIcon(0, crossIcon);
+ ui->treeWidget->topLevelItem(2)->child(4)->setToolTip(0, "Cannot read DEM File");
+ }
+ }
+ else
+ {
+ isVTKFilesValid = false;
+ ui->treeWidget->topLevelItem(2)->child(4)->setIcon(0, bulletIcon);
+ ui->treeWidget->topLevelItem(2)->child(4)->setToolTip(0, "Not Selected");
+ }
+
+ updateOutputState();
+}
+
+void AppState::updateInputState()
+{
+ if (isDomainAverageInitializationValid || isPointInitializationValid || isWeatherModelInitializationValid)
+ {
+ isWindInputValid = true;
+ ui->treeWidget->topLevelItem(1)->child(3)->setIcon(0, tickIcon);
+ ui->treeWidget->topLevelItem(1)->child(3)->setToolTip(0, "Valid");
+ }
+ else
+ {
+ isWindInputValid = false;
+ ui->treeWidget->topLevelItem(1)->child(3)->setIcon(0, crossIcon);
+ ui->treeWidget->topLevelItem(1)->child(3)->setToolTip(0, "No Initialization Method Selected");
+ }
+
+ if (isSurfaceInputValid && isWindInputValid)
+ {
+ isInputValid = true;
+ ui->treeWidget->topLevelItem(1)->setIcon(0, tickIcon);
+ ui->treeWidget->topLevelItem(1)->setToolTip(0, "Valid");
+ }
+ else if (!isSurfaceInputValid && !isWindInputValid)
+ {
+ isInputValid = false;
+ ui->treeWidget->topLevelItem(1)->setIcon(0, crossIcon);
+ ui->treeWidget->topLevelItem(1)->setToolTip(0, "Check Surface Input");
+ }
+ else if (!isSurfaceInputValid)
+ {
+ isInputValid = false;
+ ui->treeWidget->topLevelItem(1)->setIcon(0, crossIcon);
+ ui->treeWidget->topLevelItem(1)->setToolTip(0, "Check Surface Input");
+ }
+ else if (!isWindInputValid)
+ {
+ isInputValid = false;
+ ui->treeWidget->topLevelItem(1)->setIcon(0, crossIcon);
+ ui->treeWidget->topLevelItem(1)->setToolTip(0, "Check Wind Input");
+ }
+
+ updateOverallState();
+}
+
+void AppState::updateOutputState()
+{
+ if(isGoogleEarthValid || isFireBehaviorValid || isShapeFilesValid || isGeoSpatialPDFFilesValid || isVTKFilesValid)
+ {
+ isOutputValid = true;
+ ui->treeWidget->topLevelItem(2)->setIcon(0, tickIcon);
+ ui->treeWidget->topLevelItem(2)->setToolTip(0, "Valid");
+ }
+ else
+ {
+ ui->treeWidget->topLevelItem(2)->setIcon(0, crossIcon);
+ ui->treeWidget->topLevelItem(2)->setToolTip(0, "No Output Selected");
+ }
+
+ updateOverallState();
+}
+
+void AppState::updateOverallState()
+{
+ if (isSolverMethodologyValid && isInputValid && isOutputValid)
+ {
+ ui->numberOfProcessorsSolveButton->setEnabled(true);
+ ui->numberOfProcessorsSolveButton->setToolTip("");
+ ui->treeWidget->topLevelItem(3)->setIcon(0, tickIcon);
+ ui->treeWidget->topLevelItem(3)->setToolTip(0, "");
+ }
+ else
+ {
+ ui->numberOfProcessorsSolveButton->setEnabled(false);
+ ui->numberOfProcessorsSolveButton->setToolTip("Solver Methodology and Inputs must be passing to solve.");
+ ui->treeWidget->topLevelItem(3)->setIcon(0, crossIcon);
+ ui->treeWidget->topLevelItem(3)->setToolTip(0, "There are errors in the inputs or outputs");
+ }
+}
diff --git a/src/gui/qt6/appState.h b/src/gui/qt6/appState.h
new file mode 100644
index 000000000..a9adf4272
--- /dev/null
+++ b/src/gui/qt6/appState.h
@@ -0,0 +1,111 @@
+ /******************************************************************************
+ *
+ * $Id$
+ *
+ * Project: WindNinja Qt GUI
+ * Purpose: Stores the states for inputs in the GUI
+ * Author: Mason Willman
+ *
+ ******************************************************************************
+ *
+ * THIS SOFTWARE WAS DEVELOPED AT THE ROCKY MOUNTAIN RESEARCH STATION (RMRS)
+ * MISSOULA FIRE SCIENCES LABORATORY BY EMPLOYEES OF THE FEDERAL GOVERNMENT
+ * IN THE COURSE OF THEIR OFFICIAL DUTIES. PURSUANT TO TITLE 17 SECTION 105
+ * OF THE UNITED STATES CODE, THIS SOFTWARE IS NOT SUBJECT TO COPYRIGHT
+ * PROTECTION AND IS IN THE PUBLIC DOMAIN. RMRS MISSOULA FIRE SCIENCES
+ * LABORATORY ASSUMES NO RESPONSIBILITY WHATSOEVER FOR ITS USE BY OTHER
+ * PARTIES, AND MAKES NO GUARANTEES, EXPRESSED OR IMPLIED, ABOUT ITS QUALITY,
+ * RELIABILITY, OR ANY OTHER CHARACTERISTIC.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ *****************************************************************************/
+
+#ifndef APPSTATE_H
+#define APPSTATE_H
+
+#include "ui_mainWindow.h"
+#include
+
+class AppState : public QObject
+{
+ Q_OBJECT
+
+public:
+ static AppState& instance();
+ void setUi(Ui::MainWindow* mainWindowUi);
+ void setState();
+
+ bool isSolverMethodologyValid = false;
+ bool isMassSolverToggled = false;
+ bool isMomentumSolverToggled = false;
+
+ bool isInputValid = false;
+ bool isSurfaceInputValid = false;
+ bool isDiurnalInputToggled = false;
+ bool isStabilityInputToggled = false;
+
+ bool isWindInputValid = false;
+ bool isDomainAverageInitializationToggled = false;
+ int DomainAvgTableNumRuns = 0;
+ int DomainAvgTableNumZeroRuns = 0;
+ bool isDomainAverageInitializationValid = false;
+ bool isPointInitializationToggled = false;
+ bool isStationFileSelected = false;
+ bool isStationFileSelectionValid = false;
+ bool isPointInitializationValid = false;
+ bool isWeatherModelInitializationToggled = false;
+ bool isWeatherModelForecastValid = false;
+ bool isWeatherModelInitializationValid = false;
+
+ bool isOutputValid = false;
+ bool isGoogleEarthToggled = false;
+ bool isGoogleEarthValid = false;
+ bool isFireBehaviorToggled = false;
+ bool isFireBehaviorValid = false;
+ bool isShapeFilesToggled = false;
+ bool isShapeFilesValid = false;
+ bool isGeoSpatialPDFFilesToggled = false;
+ bool isGeoSpatialPDFFilesValid = false;
+ bool isVTKFilesToggled = false;
+ bool isVTKFilesValid = false;
+
+ bool isSolverReady = false;
+
+public slots:
+ void updateSolverMethodologyState();
+ void updateSurfaceInputState();
+ void updateDiurnalInputState();
+ void updateStabilityInputState();
+ void updateDomainAverageInputState();
+ void updatePointInitializationInputState();
+ void updateWeatherModelInputState();
+ void updateGoogleEarthOutputState();
+ void updateFireBehaviorOutputState();
+ void updateShapeFilesOutputState();
+ void updateGeoSpatialPDFFilesOutputState();
+ void updateVTKFilesOutputState();
+
+private:
+ Ui::MainWindow *ui;
+
+ QIcon tickIcon;
+ QIcon warnIcon;
+ QIcon crossIcon;
+ QIcon bulletIcon;
+
+ AppState();
+ AppState(const AppState&) = delete;
+ AppState& operator=(const AppState&) = delete;
+ void updateInputState();
+ void updateOutputState();
+ void updateOverallState();
+};
+
+#endif // APPSTATE_H
diff --git a/src/gui/qt6/domainAverageInput.cpp b/src/gui/qt6/domainAverageInput.cpp
new file mode 100644
index 000000000..a55ca24f2
--- /dev/null
+++ b/src/gui/qt6/domainAverageInput.cpp
@@ -0,0 +1,204 @@
+ /******************************************************************************
+ *
+ * $Id$
+ *
+ * Project: WindNinja Qt GUI
+ * Purpose: Handles GUI related logic for the Domain Average Page
+ * Author: Mason Willman
+ *
+ ******************************************************************************
+ *
+ * THIS SOFTWARE WAS DEVELOPED AT THE ROCKY MOUNTAIN RESEARCH STATION (RMRS)
+ * MISSOULA FIRE SCIENCES LABORATORY BY EMPLOYEES OF THE FEDERAL GOVERNMENT
+ * IN THE COURSE OF THEIR OFFICIAL DUTIES. PURSUANT TO TITLE 17 SECTION 105
+ * OF THE UNITED STATES CODE, THIS SOFTWARE IS NOT SUBJECT TO COPYRIGHT
+ * PROTECTION AND IS IN THE PUBLIC DOMAIN. RMRS MISSOULA FIRE SCIENCES
+ * LABORATORY ASSUMES NO RESPONSIBILITY WHATSOEVER FOR ITS USE BY OTHER
+ * PARTIES, AND MAKES NO GUARANTEES, EXPRESSED OR IMPLIED, ABOUT ITS QUALITY,
+ * RELIABILITY, OR ANY OTHER CHARACTERISTIC.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ *****************************************************************************/
+
+#include "domainAverageInput.h"
+#include "ui_mainWindow.h"
+
+DomainAverageInput::DomainAverageInput(Ui::MainWindow* ui, QObject* parent)
+ : QObject(parent),
+ ui(ui)
+{
+ setupDomainAverageTableWidgets();
+ ui->domainAverageTable->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch);
+
+ connect(ui->inputWindHeightComboBox, &QComboBox::currentIndexChanged, this, &DomainAverageInput::windHeightComboBoxCurrentIndexChanged);
+ connect(ui->clearTableButton, &QPushButton::clicked, this, &DomainAverageInput::clearTableButtonClicked);
+ connect(ui->domainAverageTable, &QTableWidget::cellChanged, this, &DomainAverageInput::domainAverageTableCheckRows);
+ connect(ui->diurnalCheckBox, &QCheckBox::clicked, this, &DomainAverageInput::domainAverageTableCheckRows);
+ connect(ui->stabilityCheckBox, &QCheckBox::clicked, this, &DomainAverageInput::domainAverageTableCheckRows);
+ connect(ui->domainAverageGroupBox, &QGroupBox::toggled, this, &DomainAverageInput::domainAverageGroupBoxToggled);
+ connect(ui->domainAverageGroupBox, &QGroupBox::toggled, this, &DomainAverageInput::domainAverageTableCheckRows);
+ connect(this, &DomainAverageInput::updateState, &AppState::instance(), &AppState::updateDomainAverageInputState);
+}
+
+int DomainAverageInput::countNumRuns()
+{
+ int numActiveRows = 0;
+ for(int rowIdx = 0; rowIdx < ui->domainAverageTable->rowCount(); rowIdx++)
+ {
+ if(speedSpins[rowIdx]->value() != 0.0 || dirSpins[rowIdx]->value() != 0.0)
+ {
+ //numActiveRows = numActiveRows + 1; // this method skips adding up the in between 0.0, 0.0 spd, dir rows
+ numActiveRows = rowIdx + 1; // last active row, as a 1 to N count, rather than as a 0 to N-1 rowIdx, this method properly grabs the in between 0.0, 0.0 spd, dir rows
+ }
+ }
+
+ return numActiveRows;
+}
+
+void DomainAverageInput::domainAverageTableCheckRows()
+{
+ int numRuns = countNumRuns();
+
+ int numZeroRuns = 0;
+ for(int runIdx = 0; runIdx < numRuns; runIdx++)
+ {
+ if(speedSpins[runIdx]->value() == 0.0)
+ {
+ numZeroRuns = numZeroRuns + 1;
+ }
+ }
+
+ AppState::instance().DomainAvgTableNumRuns = numRuns;
+ AppState::instance().DomainAvgTableNumZeroRuns = numZeroRuns;
+
+ emit updateState();
+}
+
+void DomainAverageInput::clearTableButtonClicked()
+{
+ // AppState::instance().DomainAvgTableNumRuns and AppState::instance().DomainAvgTableNumZeroRuns are set
+ // and updateState() is emitted here, by the call to the domainAverageTableCheckRows() function
+
+ speedSpins.clear();
+ dirSpins.clear();
+ timeEdits.clear();
+ dateEdits.clear();
+ cloudSpins.clear();
+ airTempSpins.clear();
+
+ ui->domainAverageTable->clearContents();
+
+ setupDomainAverageTableWidgets();
+
+ domainAverageTableCheckRows();
+}
+
+void DomainAverageInput::windHeightComboBoxCurrentIndexChanged(int index)
+{
+ switch(index)
+ {
+ case 0:
+ ui->inputWindHeightSpinBox->setValue(20.00);
+ ui->inputWindHeightSpinBox->setEnabled(false);
+ ui->inputWindHeightUnitsComboBox->setCurrentIndex(0);
+ break;
+
+ case 1:
+ ui->inputWindHeightSpinBox->setValue(10.00);
+ ui->inputWindHeightSpinBox->setEnabled(false);
+ ui->inputWindHeightUnitsComboBox->setCurrentIndex(1);
+ break;
+
+ case 2:
+ ui->inputWindHeightSpinBox->setValue(0.00);
+ ui->inputWindHeightSpinBox->setEnabled(true);
+ ui->inputWindHeightUnitsComboBox->setEnabled(true);
+ break;
+ }
+}
+
+void DomainAverageInput::domainAverageGroupBoxToggled()
+{
+ AppState& state = AppState::instance();
+ state.isDomainAverageInitializationToggled = ui->domainAverageGroupBox->isChecked();
+
+ if (state.isDomainAverageInitializationToggled)
+ {
+ ui->pointInitializationGroupBox->setChecked(false);
+ ui->weatherModelGroupBox->setChecked(false);
+ state.isPointInitializationToggled = ui->pointInitializationGroupBox->isChecked();
+ state.isWeatherModelInitializationToggled = ui->weatherModelGroupBox->isChecked();
+ }
+
+ emit updateState();
+}
+
+void DomainAverageInput::setupDomainAverageTableWidgets()
+{
+ QTableWidget* table = ui->domainAverageTable;
+ int rows = table->rowCount();
+
+ speedSpins.resize(rows);
+ dirSpins.resize(rows);
+ timeEdits.resize(rows);
+ dateEdits.resize(rows);
+ cloudSpins.resize(rows);
+ airTempSpins.resize(rows);
+
+ for(int row = 0; row < rows; row++)
+ {
+ speedSpins[row] = new QDoubleSpinBox(table);
+ speedSpins[row]->setRange(0.0, 500.0);
+ speedSpins[row]->setDecimals(2);
+ table->setCellWidget(row, 0, speedSpins[row]);
+
+ dirSpins[row] = new QDoubleSpinBox(table);
+ dirSpins[row]->setRange(0.0, 359.9);
+ dirSpins[row]->setDecimals(0);
+ table->setCellWidget(row, 1, dirSpins[row]);
+
+ timeEdits[row] = new QTimeEdit(QTime::currentTime(), table);
+ timeEdits[row]->setDisplayFormat("HH:mm");
+ table->setCellWidget(row, 2, timeEdits[row]);
+
+ dateEdits[row] = new QDateEdit(QDate::currentDate(), table);
+ dateEdits[row]->setCalendarPopup(true);
+ dateEdits[row]->setDisplayFormat("MM/dd/yyyy");
+ table->setCellWidget(row, 3, dateEdits[row]);
+
+ cloudSpins[row] = new QDoubleSpinBox(table);
+ cloudSpins[row]->setRange(0.0, 100.0);
+ cloudSpins[row]->setDecimals(0);
+ table->setCellWidget(row, 4, cloudSpins[row]);
+
+ airTempSpins[row] = new QDoubleSpinBox(table);
+ airTempSpins[row]->setRange(-40.0, 200.0);
+ airTempSpins[row]->setDecimals(0);
+ airTempSpins[row]->setValue(72.0);
+ table->setCellWidget(row, 5, airTempSpins[row]);
+
+ connect(speedSpins[row], &QDoubleSpinBox::valueChanged, this, &DomainAverageInput::domainAverageTableCheckRows);
+ connect(dirSpins[row], &QDoubleSpinBox::valueChanged, this, &DomainAverageInput::domainAverageTableCheckRows);
+ connect(timeEdits[row], &QTimeEdit::timeChanged, this, &DomainAverageInput::domainAverageTableCheckRows);
+ connect(dateEdits[row], &QDateEdit::dateChanged, this, &DomainAverageInput::domainAverageTableCheckRows);
+ connect(cloudSpins[row], &QDoubleSpinBox::valueChanged, this, &DomainAverageInput::domainAverageTableCheckRows);
+ connect(airTempSpins[row], &QDoubleSpinBox::valueChanged, this, &DomainAverageInput::domainAverageTableCheckRows);
+ }
+
+ bool enabled = ui->diurnalCheckBox->isChecked() || ui->stabilityCheckBox->isChecked();
+ for(int row = 0; row < rows; row++)
+ {
+ timeEdits[row]->setEnabled(enabled);
+ dateEdits[row]->setEnabled(enabled);
+ cloudSpins[row]->setEnabled(enabled);
+ airTempSpins[row]->setEnabled(enabled);
+ }
+}
+
diff --git a/src/gui/GoogleMapsInterface.h b/src/gui/qt6/domainAverageInput.h
similarity index 55%
rename from src/gui/GoogleMapsInterface.h
rename to src/gui/qt6/domainAverageInput.h
index f9fb7d08b..4c1f92542 100644
--- a/src/gui/GoogleMapsInterface.h
+++ b/src/gui/qt6/domainAverageInput.h
@@ -1,10 +1,10 @@
-/******************************************************************************
+ /******************************************************************************
*
- * $Id: GoogleMapsInterface.h 1757 2012-08-07 18:40:40Z kyle.shannon $
+ * $Id$
*
- * Project: WindNinja
- * Purpose: Class for creating an interface between javascript and Qt
- * Author: Cody Posey
+ * Project: WindNinja Qt GUI
+ * Purpose: Handles GUI related logic for the Domain Average Page
+ * Author: Mason Willman
*
******************************************************************************
*
@@ -26,28 +26,43 @@
* DEALINGS IN THE SOFTWARE.
*
*****************************************************************************/
-#ifndef GOOGLE_MAPS_INTERFACE_H_
-#define GOOGLE_MAPS_INTERFACE_H_
+
+#ifndef DOMAINAVERAGEINPUT_H
+#define DOMAINAVERAGEINPUT_H
+
+#include "appState.h"
+#include "ui_mainWindow.h"
#include
-class GoogleMapsInterface : public QObject
+class DomainAverageInput: public QObject
{
Q_OBJECT
+signals:
+ void updateState();
+
public:
- GoogleMapsInterface(QObject *parent = 0);
+ DomainAverageInput(Ui::MainWindow* ui, QObject* parent = nullptr);
-signals:
- void latlngChanged(double lat, double lng);
- void latlngChangedGUI(double lat, double lng);
- void plotUserPoint();
- void zoomExtents();
- void boundsChanged(double northBound, double southBound, double eastBound, double westBound);
- void boundsChangedGUI(double northBound, double southBound, double eastBound, double westBound);
- void bufferChanged();
- void areaSelected(bool selected);
- void geocodeError();
-};
+ int countNumRuns();
+
+ QVector speedSpins;
+ QVector dirSpins;
+ QVector timeEdits;
+ QVector dateEdits;
+ QVector cloudSpins;
+ QVector airTempSpins;
+
+private slots:
+ void setupDomainAverageTableWidgets();
+ void domainAverageTableCheckRows();
+ void clearTableButtonClicked();
+ void domainAverageGroupBoxToggled();
+ void windHeightComboBoxCurrentIndexChanged(int index);
-#endif /* GOOGLE_MAPS_INTERFACE_H_ */
+private:
+ Ui::MainWindow *ui;
+
+};
+#endif // DOMAINAVERAGEINPUT_H
diff --git a/src/gui/cmake_gui.cpp b/src/gui/qt6/main.cpp
old mode 100644
new mode 100755
similarity index 55%
rename from src/gui/cmake_gui.cpp
rename to src/gui/qt6/main.cpp
index f82f6d4d0..948b97bfb
--- a/src/gui/cmake_gui.cpp
+++ b/src/gui/qt6/main.cpp
@@ -1,10 +1,10 @@
-/******************************************************************************
+ /******************************************************************************
*
* $Id$
*
* Project: WindNinja Qt GUI
* Purpose: main() function to initiate Qt GUI
- * Author: Kyle Shannon
+ * Author: Mason Willman
*
******************************************************************************
*
@@ -27,63 +27,62 @@
*
*****************************************************************************/
-#include "cli.h"
-
+#include "mainWindow.h"
+#include "windninja.h"
#include
+#include
#include
#include
-#include
-#include
-#include
+#include
+#include
+#include
#include
-#include "mainWindow.h"
-#include "splash.h"
+#include
+#include
+#include "splashScreen.h"
-#include "ninjaArmy.h"
-#include "ninjaException.h"
-#include "ninja_conv.h"
-#include "ninja_init.h"
-#include "gdal.h"
-#include "ogr_api.h"
-
-#ifdef _OPENMP
-omp_lock_t netCDF_lock;
-#endif
int main(int argc, char *argv[])
{
+ setbuf(stdout, nullptr);
+
int result;
-#ifdef _OPENMP
- omp_init_lock (&netCDF_lock);
-#endif
- if(argc > 1)
+ char ** papszOptions = NULL;
+ const char * runType = "gui";
+ NinjaErr ninjaErr = 0;
+ ninjaErr = NinjaInit(runType, papszOptions);
+ if(ninjaErr != NINJA_SUCCESS)
{
- CPLSetConfigOption( "NINJA_DISABLE_CALL_HOME", "ON" );
- result = windNinjaCLI(argc, argv);
-#ifdef _OPENMP
- omp_destroy_lock (&netCDF_lock);
-#endif
- return result;
+ qDebug() << "NinjaInit: ninjaErr =" << ninjaErr;
}
- NinjaInitialize("gui");
-
- QApplication app(argc, argv);
-
- //set application name/version in User-Agent header
+ QApplication a(argc, argv);
+ QIcon icon(":/wn-icon.png");
QString ver = NINJA_VERSION_STRING;
- app.setApplicationName(QString("WindNinja"));
- app.setApplicationVersion(ver);
+ a.setWindowIcon(icon);
+ a.setApplicationName(QString("WindNinja"));
+ a.setApplicationVersion(ver);
+ a.setStyle(QStyleFactory::create("Fusion"));
- app.setWindowIcon(QIcon(":wn-icon.png"));
+ MainWindow* w = nullptr;
+ try
+ {
+ w = new MainWindow;
+ }
+ catch (...)
+ {
+ QMessageBox::critical(nullptr, "Initialization Error",
+ "WindNinja failed to initialize. Most likely cause is failure to find data "
+ "dependencies. Try setting the environment variable WINDNINJA_DATA");
+ return 1;
+ }
QPixmap bigSplashPixmap(":wn-splash.png");
- //resampled one
QSize splashSize(1200, 320);
QPixmap smallSplashPixmap;
smallSplashPixmap = bigSplashPixmap.scaled(splashSize,
- Qt::KeepAspectRatioByExpanding);
+ Qt::KeepAspectRatioByExpanding);
QStringList list;
list << "Loading WindNinja " + ver + "...";
list << "Loading mesh generator...";
@@ -91,30 +90,10 @@ int main(int argc, char *argv[])
list << "Loading preconditioner...";
list << "WindNinja " + ver + " loaded.";
- mainWindow *mw;
- QMessageBox mbox;
- try
- {
- mw = new mainWindow;
- }
- catch(...)
- {
- mbox.setText("WindNinja failed to initialize. Most "
- "likely cause is failure to find data "
- "dependencies. Try setting the environment "
- "variable WINDNINJA_DATA");
- mbox.exec();
- return 1;
- }
- splashScreen *splash = new splashScreen(smallSplashPixmap, list, 1000);
+ SplashScreen *splash = new SplashScreen(smallSplashPixmap, list, 1000);
splash->display();
- //QObject::connect(splash, SIGNAL(done()), mw, SLOT(checkMessages()));
- QObject::connect(splash, SIGNAL(done()), mw, SLOT(show()));
- result = app.exec();
-
-#ifdef _OPENMP
- omp_destroy_lock (&netCDF_lock);
-#endif
+ QObject::connect(splash, SIGNAL(done()), w, SLOT(show()));
+ result = a.exec();
return result;
}
diff --git a/src/gui/qt6/mainWindow.cpp b/src/gui/qt6/mainWindow.cpp
new file mode 100644
index 000000000..cb1c262dc
--- /dev/null
+++ b/src/gui/qt6/mainWindow.cpp
@@ -0,0 +1,1724 @@
+/******************************************************************************
+ *
+ * $Id$
+ *
+ * Project: WindNinja Qt GUI
+ * Purpose: Main Window that handles GUI scraping and state changes
+ * Author: Mason Willman
+ *
+ ******************************************************************************
+ *
+ * THIS SOFTWARE WAS DEVELOPED AT THE ROCKY MOUNTAIN RESEARCH STATION (RMRS)
+ * MISSOULA FIRE SCIENCES LABORATORY BY EMPLOYEES OF THE FEDERAL GOVERNMENT
+ * IN THE COURSE OF THEIR OFFICIAL DUTIES. PURSUANT TO TITLE 17 SECTION 105
+ * OF THE UNITED STATES CODE, THIS SOFTWARE IS NOT SUBJECT TO COPYRIGHT
+ * PROTECTION AND IS IN THE PUBLIC DOMAIN. RMRS MISSOULA FIRE SCIENCES
+ * LABORATORY ASSUMES NO RESPONSIBILITY WHATSOEVER FOR ITS USE BY OTHER
+ * PARTIES, AND MAKES NO GUARANTEES, EXPRESSED OR IMPLIED, ABOUT ITS QUALITY,
+ * RELIABILITY, OR ANY OTHER CHARACTERISTIC.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ *****************************************************************************/
+
+#include "mainWindow.h"
+
+MainWindow::MainWindow(QWidget *parent)
+ : QMainWindow(parent),
+ ui(new Ui::MainWindow)
+{
+ ui->setupUi(this);
+ resize(1200, 700);
+ ui->treeWidget->expandAll();
+
+ AppState& state = AppState::instance();
+ state.setUi(ui);
+ ui->massSolverCheckBox->setChecked(true);
+ ui->treeWidget->setMouseTracking(true);
+ state.isMassSolverToggled = true;
+
+ lineNumber = 1;
+
+ serverBridge = new ServerBridge();
+ serverBridge->checkMessages();
+
+ QWebEngineProfile::defaultProfile()->settings()->setAttribute(QWebEngineSettings::LocalContentCanAccessRemoteUrls, true);
+ QWebEngineProfile::defaultProfile()->settings()->setAttribute(QWebEngineSettings::LocalContentCanAccessFileUrls, true);
+ QString dataPath = QString::fromUtf8(CPLGetConfigOption("WINDNINJA_DATA", ""));
+ QString mapPath = QDir(dataPath).filePath("map.html");
+ webEngineView = new QWebEngineView(ui->mapPanelWidget);
+ webChannel = new QWebChannel(webEngineView->page());
+ mapBridge = new MapBridge(this);
+ webChannel->registerObject(QStringLiteral("bridge"), mapBridge);
+ webEngineView->page()->setWebChannel(webChannel);
+
+ QUrl url = QUrl::fromLocalFile(mapPath);
+ webEngineView->setUrl(url);
+ QVBoxLayout *layout = new QVBoxLayout();
+ layout->setContentsMargins(0, 0, 0, 0);
+ layout->addWidget(webEngineView);
+ ui->mapPanelWidget->setLayout(layout);
+ menuBar = new MenuBar(ui, this);
+ surfaceInput = new SurfaceInput(ui, webEngineView, this);
+ domainAverageInput = new DomainAverageInput(ui, this);
+ pointInitializationInput = new PointInitializationInput(ui, this);
+ weatherModelInput = new WeatherModelInput(ui, this);
+ outputs = new Outputs(ui, this);
+
+ ui->treeWidget->topLevelItem(0)->setData(0, Qt::UserRole, 1);
+ ui->treeWidget->topLevelItem(0)->child(0)->setData(0, Qt::UserRole, 1);
+ ui->treeWidget->topLevelItem(0)->child(1)->setData(0, Qt::UserRole, 2);
+ ui->treeWidget->topLevelItem(1)->setData(0, Qt::UserRole, 3);
+ ui->treeWidget->topLevelItem(1)->child(0)->setData(0, Qt::UserRole, 3);
+ ui->treeWidget->topLevelItem(1)->child(1)->setData(0, Qt::UserRole, 4);
+ ui->treeWidget->topLevelItem(1)->child(2)->setData(0, Qt::UserRole, 5);
+ ui->treeWidget->topLevelItem(1)->child(3)->setData(0, Qt::UserRole, 6);
+ QTreeWidgetItem *windInputItem = ui->treeWidget->topLevelItem(1)->child(3);
+ windInputItem->child(0)->setData(0, Qt::UserRole, 6);
+ windInputItem->child(1)->setData(0, Qt::UserRole, 7);
+ windInputItem->child(2)->setData(0, Qt::UserRole, 8);
+ ui->treeWidget->topLevelItem(2)->setData(0, Qt::UserRole, 9);
+ ui->treeWidget->topLevelItem(2)->child(0)->setData(0, Qt::UserRole, 10);
+ ui->treeWidget->topLevelItem(2)->child(1)->setData(0, Qt::UserRole, 11);
+ ui->treeWidget->topLevelItem(2)->child(2)->setData(0, Qt::UserRole, 12);
+ ui->treeWidget->topLevelItem(2)->child(3)->setData(0, Qt::UserRole, 13);
+ ui->treeWidget->topLevelItem(2)->child(4)->setData(0, Qt::UserRole, 14);
+ ui->treeWidget->topLevelItem(3)->setData(0, Qt::UserRole, 15);
+
+ connectSignals();
+
+ ui->treeWidget->topLevelItem(0)->setSelected(true);
+ ui->inputsStackedWidget->setCurrentIndex(1); // setSelected shows the blank page, have to have this to show proper page
+
+ int nCPUs = QThread::idealThreadCount();
+ ui->availableProcessorsLabel->setText("Available Processors: " + QString::number(nCPUs));
+ ui->numberOfProcessorsSpinBox->setMaximum(nCPUs);
+ ui->numberOfProcessorsSpinBox->setValue(nCPUs);
+
+ QString version(NINJA_VERSION_STRING);
+ version = "Welcome to WindNinja " + version;
+ writeToConsole(version, Qt::blue);
+ writeToConsole("WINDNINJA_DATA=" + dataPath);
+
+ state.setState();
+}
+
+MainWindow::~MainWindow()
+{
+ delete serverBridge;
+ delete ui;
+}
+
+void MainWindow::connectSignals()
+{
+ connect(ui->massSolverCheckBox, &QCheckBox::clicked, this, &MainWindow::massSolverCheckBoxClicked);
+ connect(ui->momentumSolverCheckBox, &QCheckBox::clicked, this, &MainWindow::momentumSolverCheckBoxClicked);
+ connect(ui->diurnalCheckBox, &QCheckBox::clicked, this, &MainWindow::diurnalCheckBoxClicked);
+ connect(ui->stabilityCheckBox, &QCheckBox::clicked, this, &MainWindow::stabilityCheckBoxClicked);
+ connect(ui->treeWidget, &QTreeWidget::itemDoubleClicked, this, &MainWindow::treeWidgetItemDoubleClicked);
+ connect(ui->numberOfProcessorsSolveButton, &QPushButton::clicked, this, &MainWindow::solveButtonClicked);
+ connect(ui->outputDirectoryButton, &QPushButton::clicked, this, &MainWindow::outputDirectoryButtonClicked);
+ connect(ui->treeWidget, &QTreeWidget::itemSelectionChanged, this, &MainWindow::treeWidgetItemSelectionChanged);
+
+ connect(menuBar, &MenuBar::writeToConsoleSignal, this, &MainWindow::writeToConsole);
+ connect(mapBridge, &MapBridge::boundingBoxReceived, surfaceInput, &SurfaceInput::boundingBoxReceived);
+ connect(surfaceInput, &SurfaceInput::updateTreeView, pointInitializationInput, &PointInitializationInput::updateTreeView);
+ connect(surfaceInput, &SurfaceInput::updateTreeView, weatherModelInput, &WeatherModelInput::updateTreeView);
+ connect(weatherModelInput, &WeatherModelInput::updateState, &AppState::instance(), &AppState::updateWeatherModelInputState);
+ connect(webEngineView, &QWebEngineView::loadFinished, this, &MainWindow::readSettings);
+
+ connect(this, &MainWindow::updateDirunalState, &AppState::instance(), &AppState::updateDiurnalInputState);
+ connect(this, &MainWindow::updateStabilityState, &AppState::instance(), &AppState::updateStabilityInputState);
+ connect(this, &MainWindow::updateMetholodyState, &AppState::instance(), &AppState::updateSolverMethodologyState);
+ connect(this, &MainWindow::updateProgressValueSignal, this, &MainWindow::updateProgressValue, Qt::QueuedConnection);
+ connect(this, &MainWindow::updateProgressMessageSignal, this, &MainWindow::updateProgressMessage, Qt::QueuedConnection);
+ connect(this, &MainWindow::writeToConsoleSignal, this, &MainWindow::writeToConsole, Qt::QueuedConnection);
+
+ connect(surfaceInput, &SurfaceInput::writeToConsoleSignal, this, &MainWindow::writeToConsole, Qt::QueuedConnection);
+ connect(pointInitializationInput, &PointInitializationInput::writeToConsoleSignal, this, &MainWindow::writeToConsole, Qt::QueuedConnection);
+ connect(weatherModelInput, &WeatherModelInput::writeToConsoleSignal, this, &MainWindow::writeToConsole, Qt::QueuedConnection);
+}
+
+void MainWindow::writeToConsole(QString message, QColor color)
+{
+ // if( ui->consoleDockWidget->isFloating() && color == Qt::white )
+ // {
+ // color = Qt::black;
+ // }
+
+ ui->consoleTextEdit->setTextColor(color);
+ ui->consoleTextEdit->append(QString::number(lineNumber) + ": " + message);
+ ui->consoleTextEdit->repaint();
+ lineNumber++;
+}
+
+void MainWindow::updateProgressMessage(const QString message)
+{
+ progressDialog->setLabelText(message);
+}
+
+void MainWindow::updateProgressValue(int run, int progress)
+{
+ // update the stored progress value for the current run
+ if( runProgress[run] > progress )
+ {
+ // if the stored progress is bigger than what we are seeing in the currently emitted progress
+ // ignore it. This happens for pointInitialization, when the match points is iterating,
+ // sometimes its next solution is worse and then it would make the progress bar go backwards
+ // by ignoring it, the progress bar just stays where it is
+ runProgress[run] = runProgress[run];
+ }
+ else
+ {
+ // otherwise, store the progress for the current run
+ runProgress[run] = progress;
+ }
+
+ // update the total progress value
+ // calculate the total progress from scratch each time, summing up the progress from each run
+ totalProgress = 0; // Initialize the progress bar each time
+ for(unsigned int i = 0; i < runProgress.size(); i++)
+ {
+ totalProgress = totalProgress + runProgress[i];
+ }
+
+ // update the progress bar
+ progressDialog->setValue(totalProgress);
+}
+
+static void comMessageHandler(const char *pszMessage, void *pUser)
+{
+ MainWindow *self = static_cast(pUser);
+
+ std::string msg = pszMessage;
+ if( msg.substr(msg.size()-1, 1) == "\n")
+ {
+ msg = msg.substr(0, msg.size()-1);
+ }
+
+ int runNumber = -1;
+ sscanf(msg.c_str(), "Run %d", &runNumber);
+
+ size_t pos;
+ size_t startPos;
+ size_t endPos;
+ std::string clipStr;
+
+ int runProgress;
+ endPos = msg.find("% complete");
+ if( endPos != msg.npos )
+ {
+ clipStr = msg.substr(0, endPos);
+ //std::cout << "clipStr = \"" << clipStr << "\"" << std::endl;
+ pos = clipStr.rfind(": ");
+ startPos = pos+2;
+ clipStr = clipStr.substr(startPos);
+ //std::cout << "clipStr = \"" << clipStr << "\"" << std::endl;
+ runProgress = atoi(clipStr.c_str());
+
+ emit self->updateProgressValueSignal(runNumber, runProgress);
+ }
+
+//"Run 1 ERROR: Multiple runs were requested with the same input parameters."
+//"Run 0 ERROR: Exception caught: I WANT CHOCOLATE!!! Yum."
+//"Run 0: Exception caught: Simulation was cancelled by the user."
+//"Run 1: Exception canceled by user caught: Simulation was cancelled by the user."
+
+ if( msg.find("Exception caught: ") != msg.npos || msg.find("ERROR: ") != msg.npos || msg.find("Exception canceled by user caught: ") != msg.npos )
+ {
+ if( msg.find("Exception caught: ") != msg.npos )
+ {
+ pos = msg.find("Exception caught: ");
+ startPos = pos+18;
+ }
+ else if( msg.find("Exception canceled by user caught: ") != msg.npos )
+ {
+ pos = msg.find("Exception canceled by user caught: ");
+ startPos = pos+35;
+ }
+ else // if( msg.find("ERROR: ") != msg.npos )
+ {
+ pos = msg.find("ERROR: ");
+ startPos = pos+7;
+ }
+ clipStr = msg.substr(startPos);
+ //std::cout << "clipStr = \"" << clipStr << "\"" << std::endl;
+ //emit self->updateProgressMessageSignal(QString::fromStdString(clipStr));
+ //emit self->writeToConsoleSignal(QString::fromStdString(clipStr));
+ if( clipStr == "Simulation was cancelled by the user." )
+ {
+ emit self->updateProgressMessageSignal(QString::fromStdString("Simulation cancelled"));
+ emit self->writeToConsoleSignal(QString::fromStdString("Simulation cancelled by user"), QColor(255, 140, 0));
+ }
+ else if( clipStr == "Cannot determine exception type." )
+ {
+ emit self->updateProgressMessageSignal(QString::fromStdString("Simulation ended with unknown error"));
+ emit self->writeToConsoleSignal(QString::fromStdString("unknown solver error"), Qt::red);
+ }
+ else
+ {
+ emit self->updateProgressMessageSignal(QString::fromStdString("Simulation ended in error:\n"+clipStr));
+ emit self->writeToConsoleSignal(QString::fromStdString("Solver error: "+clipStr), Qt::red);
+ }
+ }
+ else if( msg.find("Warning: ") != msg.npos )
+ {
+ if( msg.find("Warning: ") != msg.npos )
+ {
+ pos = msg.find("Warning: ");
+ startPos = pos+9;
+ }
+ clipStr = msg.substr(startPos);
+ //std::cout << "clipStr = \"" << clipStr << "\"" << std::endl;
+ //emit self->updateProgressMessageSignal(QString::fromStdString(clipStr));
+ //emit self->writeToConsoleSignal(QString::fromStdString(clipStr));
+ emit self->updateProgressMessageSignal(QString::fromStdString("Solver ended in warning:\n"+clipStr));
+ emit self->writeToConsoleSignal(QString::fromStdString("Solver warning: "+clipStr), QColor(255, 140, 0));
+ }
+ else
+ {
+ emit self->updateProgressMessageSignal(QString::fromStdString(msg));
+ emit self->writeToConsoleSignal(QString::fromStdString(msg));
+ }
+}
+
+void MainWindow::cancelSolve()
+{
+ progressDialog->setLabelText("Canceling...");
+ //qDebug() << "Canceling...";
+ //writeToConsole( "Canceling...", QColor(255, 140, 0));
+
+ char **papszOptions = nullptr;
+ ninjaErr = NinjaCancel(ninjaArmy, papszOptions);
+ if( ninjaErr != NINJA_SUCCESS )
+ {
+ qDebug() << "NinjaCancel: ninjaErr =" << ninjaErr;
+ }
+}
+
+void MainWindow::treeWidgetItemSelectionChanged()
+{
+ int column = ui->treeWidget->currentColumn();
+ int pageIndex = ui->treeWidget->selectedItems().first()->data(column, Qt::UserRole).toInt(); // assume 0 since no multi selection
+ ui->inputsStackedWidget->setCurrentIndex(pageIndex);
+}
+
+void MainWindow::massSolverCheckBoxClicked()
+{
+ AppState& state = AppState::instance();
+
+ if (state.isMomentumSolverToggled)
+ {
+ ui->momentumSolverCheckBox->setChecked(false);
+ state.isMomentumSolverToggled = ui->momentumSolverCheckBox->isChecked();
+ }
+ state.isMassSolverToggled = ui->massSolverCheckBox->isChecked();
+
+ if(!ui->elevationInputFileLineEdit->text().isEmpty())
+ {
+ ui->meshResolutionSpinBox->setValue(surfaceInput->computeMeshResolution(ui->meshResolutionComboBox->currentIndex(), ui->momentumSolverCheckBox->isChecked()));
+ surfaceInput->updateMeshResolutionByUnits();
+ }
+ emit updateMetholodyState();
+}
+
+void MainWindow::momentumSolverCheckBoxClicked()
+{
+ AppState& state = AppState::instance();
+
+ if (state.isMassSolverToggled)
+ {
+ ui->massSolverCheckBox->setChecked(false);
+ state.isMassSolverToggled = ui->massSolverCheckBox->isChecked();
+ }
+ state.isMomentumSolverToggled = ui->momentumSolverCheckBox->isChecked();
+
+ if(!ui->elevationInputFileLineEdit->text().isEmpty())
+ {
+ ui->meshResolutionSpinBox->setValue(surfaceInput->computeMeshResolution(ui->meshResolutionComboBox->currentIndex(), ui->momentumSolverCheckBox->isChecked()));
+ surfaceInput->updateMeshResolutionByUnits();
+ }
+ emit updateMetholodyState();
+}
+
+void MainWindow::diurnalCheckBoxClicked()
+{
+ AppState& state = AppState::instance();
+ state.isDiurnalInputToggled = ui->diurnalCheckBox->isChecked();
+
+ bool enabled = ui->diurnalCheckBox->isChecked() || ui->stabilityCheckBox->isChecked();
+ for(int row = 0; row < ui->domainAverageTable->rowCount(); row++)
+ {
+ domainAverageInput->timeEdits[row]->setEnabled(enabled);
+ domainAverageInput->dateEdits[row]->setEnabled(enabled);
+ domainAverageInput->cloudSpins[row]->setEnabled(enabled);
+ domainAverageInput->airTempSpins[row]->setEnabled(enabled);
+ }
+
+ emit updateDirunalState();
+}
+
+void MainWindow::stabilityCheckBoxClicked()
+{
+ AppState& state = AppState::instance();
+ state.isStabilityInputToggled = ui->stabilityCheckBox->isChecked();
+
+ bool enabled = ui->diurnalCheckBox->isChecked() || ui->stabilityCheckBox->isChecked();
+ for(int row = 0; row < ui->domainAverageTable->rowCount(); row++)
+ {
+ domainAverageInput->timeEdits[row]->setEnabled(enabled);
+ domainAverageInput->dateEdits[row]->setEnabled(enabled);
+ domainAverageInput->cloudSpins[row]->setEnabled(enabled);
+ domainAverageInput->airTempSpins[row]->setEnabled(enabled);
+ }
+
+ emit updateStabilityState();
+}
+
+void MainWindow::outputDirectoryButtonClicked()
+{
+ QString currentPath = ui->outputDirectoryLineEdit->text();
+ QString dirPath = QFileDialog::getExistingDirectory(this, "Select a directory", currentPath, QFileDialog::ShowDirsOnly | QFileDialog::DontResolveSymlinks);
+
+ if (!dirPath.isEmpty())
+ {
+ ui->outputDirectoryLineEdit->setText(dirPath);
+ ui->outputDirectoryLineEdit->setToolTip(dirPath);
+ } else
+ {
+ ui->outputDirectoryLineEdit->setText(currentPath);
+ ui->outputDirectoryLineEdit->setToolTip(currentPath);
+ }
+}
+
+void MainWindow::solveButtonClicked()
+{
+ AppState& state = AppState::instance();
+
+ maxProgress = 100;
+ //progressDialog = new QProgressDialog("Initializing Runs...", "Cancel", 0, maxProgress, ui->centralwidget);
+ progressDialog = new QProgressDialog(ui->centralwidget);
+ progressDialog->setRange(0, maxProgress);
+ progressDialog->setValue(0);
+ progressDialog->setLabelText("Initializing Runs...");
+ progressDialog->setCancelButtonText("Cancel");
+
+ progressDialog->setWindowModality(Qt::WindowModal);
+ progressDialog->setMinimumDuration(0);
+ progressDialog->setAutoClose(false);
+ progressDialog->setAutoReset(false);
+
+ progressDialog->setMinimumSize(380, 100);
+ progressDialog->show();
+
+ ninjaErr = NINJA_SUCCESS;
+
+ int numNinjas = 0;
+ ninjaArmy = nullptr;
+ char **papszOptions = nullptr;
+ const char *initializationMethod = nullptr;
+
+ ninjaArmy = NinjaInitializeArmy();
+
+ ninjaErr = NinjaSetArmyComMessageHandler(ninjaArmy, &comMessageHandler, this, papszOptions);
+ if(ninjaErr != NINJA_SUCCESS)
+ {
+ qDebug() << "NinjaSetArmyComMessageHandler(): ninjaErr =" << ninjaErr;
+ }
+
+ if (state.isDomainAverageInitializationValid)
+ {
+ initializationMethod = "domain_average";
+ QList speeds;
+ QList directions;
+ QList years;
+ QList months;
+ QList days;
+ QList hours;
+ QList minutes;
+ QList cloudCovers;
+ QList airTemps;
+
+ QString DEMTimeZone = ui->timeZoneComboBox->currentText();
+
+ numNinjas = domainAverageInput->countNumRuns();
+
+ // countNumRuns() returns 0 when ALL rows are 0.0, 0.0 spd, dir rows,
+ // but if diurnal is checked, we actually DO want to run that first 0.0, 0.0 spd, dir row as a single run
+ if(numNinjas == 0 && ui->diurnalCheckBox->isChecked() == true)
+ {
+ numNinjas = 1;
+ }
+
+ for(int runIdx = 0; runIdx < numNinjas; runIdx++)
+ {
+ speeds << domainAverageInput->speedSpins[runIdx]->value();
+ directions << domainAverageInput->dirSpins[runIdx]->value();
+
+ // always grab the values from the diurnal/stability inputs,
+ // whether they are the default values, or whatever the user has changed them to be
+
+ // constructs using machine local time, may need to convert from machine local time to UTC time
+ QDateTime currentDateTime = QDateTime(domainAverageInput->dateEdits[runIdx]->date(), domainAverageInput->timeEdits[runIdx]->time());
+
+ years << currentDateTime.date().year();
+ months << currentDateTime.date().month();
+ days << currentDateTime.date().day();
+ hours << currentDateTime.time().hour();
+ minutes << currentDateTime.time().minute();
+
+ cloudCovers << domainAverageInput->cloudSpins[runIdx]->value();
+ airTemps << domainAverageInput->airTempSpins[runIdx]->value();
+ }
+
+ bool momentumFlag = ui->momentumSolverCheckBox->isChecked();
+ QString speedUnits = ui->tableSpeedUnits->currentText();
+ QString airTempUnits = ui->tableTempUnits->currentText().remove("°");
+ QString cloudCoverUnits = "percent";
+ if(ninjaErr == NINJA_SUCCESS)
+ {
+ ninjaErr = NinjaMakeDomainAverageArmy(ninjaArmy, numNinjas, momentumFlag, speeds.data(), speedUnits.toUtf8().constData(), directions.data(), years.data(), months.data(), days.data(), hours.data(), minutes.data(), DEMTimeZone.toUtf8().data(), airTemps.data(), airTempUnits.toUtf8().constData(), cloudCovers.data(), cloudCoverUnits.toUtf8().constData(), papszOptions);
+ //ninjaErr = NinjaMakeDomainAverageArmy(ninjaArmy, -1, momentumFlag, speeds.data(), speedUnits.toUtf8().constData(), directions.data(), years.data(), months.data(), days.data(), hours.data(), minutes.data(), DEMTimeZone.toUtf8().data(), airTemps.data(), airTempUnits.toUtf8().constData(), cloudCovers.data(), cloudCoverUnits.toUtf8().constData(), papszOptions); // catches error as expected, now it triggers the NinjaMakeDomainAverageArmy() single messaging error, instead of the double messaging makeDomainAverageArmy() error.
+ //ninjaErr = NinjaMakeDomainAverageArmy(ninjaArmy, 0, momentumFlag, speeds.data(), speedUnits.toUtf8().constData(), directions.data(), years.data(), months.data(), days.data(), hours.data(), minutes.data(), DEMTimeZone.toUtf8().data(), airTemps.data(), airTempUnits.toUtf8().constData(), cloudCovers.data(), cloudCoverUnits.toUtf8().constData(), papszOptions); // catches error as expected, now it triggers the NinjaMakeDomainAverageArmy() single messaging error, instead of the double messaging makeDomainAverageArmy() error.
+ //ninjaErr = NinjaMakeDomainAverageArmy(ninjaArmy, numNinjas, momentumFlag, speeds.data(), speedUnits.toUtf8().constData(), directions.data(), years.data(), months.data(), days.data(), hours.data(), minutes.data(), "fudge", airTemps.data(), airTempUnits.toUtf8().constData(), cloudCovers.data(), cloudCoverUnits.toUtf8().constData(), papszOptions); // requires the try/catch form of IF_VALID_INDEX_TRY in ninjaArmy.h, but then catches error as expected, well it technically throws two separate error messages, but both are caught properly
+ if(ninjaErr != NINJA_SUCCESS)
+ {
+ qDebug() << "NinjaMakeDomainAverageArmy: ninjaErr =" << ninjaErr;
+ }
+ }
+ }
+ else if (state.isPointInitializationValid)
+ {
+ initializationMethod = "point";
+
+ NinjaToolsH* ninjaTools = NinjaMakeTools();
+
+ ninjaErr = NinjaSetToolsComMessageHandler(ninjaTools, &comMessageHandler, this, papszOptions);
+ if(ninjaErr != NINJA_SUCCESS)
+ {
+ qDebug() << "NinjaSetToolsComMessageHandler(): ninjaErr =" << ninjaErr;
+ }
+
+ QVector stationFiles = pointInitializationInput->getStationFiles();
+ QString DEMTimeZone = ui->timeZoneComboBox->currentText();
+ QByteArray timeZoneBytes = ui->timeZoneComboBox->currentText().toUtf8();
+
+ std::vector stationFilesBytes;
+ stationFilesBytes.reserve(stationFiles.size());
+ std::vector stationFileNames;
+ stationFileNames.reserve(stationFiles.size());
+ for (int i = 0; i < stationFiles.size(); i++)
+ {
+ stationFilesBytes.push_back(stationFiles[i].toUtf8());
+ stationFileNames.push_back(stationFilesBytes.back().constData());
+ }
+
+ QString DEMPath = ui->elevationInputFileLineEdit->property("fullpath").toString();
+ bool momentumFlag = ui->momentumSolverCheckBox->isChecked();
+
+ if(ui->pointInitializationTreeView->property("timeSeriesFlag").toBool())
+ {
+ QDateTime start = ui->weatherStationDataStartDateTimeEdit->dateTime();
+ QDateTime end = ui->weatherStationDataEndDateTimeEdit->dateTime();
+
+ QVector year = { start.date().year(), end.date().year() };
+ QVector month = { start.date().month(), end.date().month() };
+ QVector day = { start.date().day(), end.date().day() };
+ QVector hour = { start.time().hour(), end.time().hour() };
+ QVector minute = { start.time().minute(), end.time().minute() };
+
+ // runs fine for the single time run, as expected,
+ // and, errors and is properly caught for the multi-time run
+ /*QVector year = {start.date().year(), start.date().year()};
+ QVector month = {start.date().month(), start.date().month()};
+ QVector day = {start.date().day(), start.date().day()};
+ QVector hour = {start.time().hour(), start.time().hour()};
+ QVector minute = {start.time().minute(), start.time().minute()};*/
+
+ // runs fine for the single time run, as expected,
+ // and, errors and is properly caught for the multi-time run
+ /*QVector year = {end.date().year(), end.date().year()};
+ QVector month = {end.date().month(), end.date().month()};
+ QVector day = {end.date().day(), end.date().day()};
+ QVector hour = {end.time().hour(), end.time().hour()};
+ QVector minute = {end.time().minute(), end.time().minute()};*/
+
+ // runs fine for the single time run, as expected,
+ // and, errors and is properly caught for the multi-time run
+ /*QVector year = {start.date().year(), start.date().year()-1};
+ QVector month = {start.date().month(), start.date().month()};
+ QVector day = {start.date().day(), start.date().day()};
+ QVector hour = {start.time().hour(), start.time().hour()};
+ QVector minute = {start.time().minute(), start.time().minute()};*/
+
+ // runs fine for the single time run, as expected,
+ // and, errors and is properly caught for the multi-time run
+ // which is interesting because the download without an additional hour time difference should also error but does not always error,
+ // so this implies the time checking for the run from this, is more strict, and better
+ /*QVector year = {start.date().year(), start.date().year()};
+ QVector month = {start.date().month(), start.date().month()};
+ QVector day = {start.date().day(), start.date().day()};
+ QVector hour = {start.time().hour(), start.time().hour()-1};
+ QVector minute = {start.time().minute(), start.time().minute()};*/
+
+ // errors for both the single time run AND the multi-time run,
+ // and errors are properly caught for both cases
+ /*QVector year = {end.date().year()+1, end.date().year()};
+ QVector month = {end.date().month(), end.date().month()};
+ QVector day = {end.date().day(), end.date().day()};
+ QVector hour = {end.time().hour(), end.time().hour()};
+ QVector minute = {end.time().minute(), end.time().minute()};*/
+
+ // errors for both the single time run AND the multi-time run,
+ // and errors are properly caught for both cases
+ /*QVector year = {end.date().year(), end.date().year()};
+ QVector month = {end.date().month(), end.date().month()};
+ QVector day = {end.date().day(), end.date().day()};
+ QVector hour = {end.time().hour()+1, end.time().hour()};
+ QVector minute = {end.time().minute(), end.time().minute()};*/
+
+ int nTimeSteps = ui->weatherStationDataTimestepsSpinBox->value();
+ //int nTimeSteps = 1; // runs fine for the single time, properly throws an error for multi-times, well the error implies out of index but maybe not at the proper step ("NinjaSetNumberCPUS", "Run 0: ERROR: Exception caught: invalid index 1". But the error is at least properly caught.
+ //int nTimeSteps = 2; // runs fine for 2 timestep multi-times, but for 1 timestep multi-times, an error is getting thrown, but apparently the solver isn't stopping because it is an error on just one single thread???? Quirky behavior that is not good. "ERROR 4: : No such file or directory, Run 1: ERROR: Exception caught: Cannot open input file for reading in ninja::readInputFile()." but then it continues with the run0 info to completion, then it ends hanging because it didn't stop at the error message and it finds it DID have some kind of error at the end. Ugh. I do see that it printed red, so it SAW that it was an error message, but I guess it wasn't a THROWN error message or something? So it didn't properly stop the solver?? Not sure what is going on here.
+
+ QVector outYear(nTimeSteps);
+ QVector outMonth(nTimeSteps);
+ QVector outDay(nTimeSteps);
+ QVector outHour(nTimeSteps);
+ QVector outMinute(nTimeSteps);
+
+ if(nTimeSteps == 1)
+ {
+ int startYear = year[0];
+ int startMonth = month[0];
+ int startDay = day[0];
+ int startHour = hour[0];
+ int startMinute = minute[0];
+
+ int endYear, endMonth, endDay, endHour, endMinute;
+
+ ninjaErr = NinjaGenerateSingleTimeObject(
+ ninjaTools,
+ startYear, startMonth, startDay, startHour, startMinute,
+ timeZoneBytes.constData(),
+ &endYear, &endMonth, &endDay, &endHour, &endMinute
+ );
+ //ninjaErr = NinjaGenerateSingleTimeObject(
+ // ninjaTools,
+ // startYear, startMonth, startDay, startHour, startMinute,
+ // "fudge",
+ // &endYear, &endMonth, &endDay, &endHour, &endMinute
+ // ); // breaks HARD, a smart pointer failing on assert somewhere along the pipeline, not sure if that occurs here, or later down the pipeline. And it gets past the try/catch error handling stuff, hrm.
+ if(ninjaErr != NINJA_SUCCESS)
+ {
+ qDebug() << "NinjaGenerateSingleTimeObject: ninjaErr =" << ninjaErr;
+ }
+
+ outYear[0] = endYear;
+ outMonth[0] = endMonth;
+ outDay[0] = endDay;
+ outHour[0] = endHour;
+ outMinute[0] = endMinute;
+ }
+ else
+ {
+ ninjaErr = NinjaGetTimeList(
+ ninjaTools,
+ year.data(), month.data(), day.data(),
+ hour.data(), minute.data(),
+ outYear.data(), outMonth.data(), outDay.data(),
+ outHour.data(), outMinute.data(),
+ nTimeSteps, timeZoneBytes.data()
+ );
+ //ninjaErr = NinjaGetTimeList(
+ // ninjaTools,
+ // year.data(), month.data(), day.data(),
+ // hour.data(), minute.data(),
+ // outYear.data(), outMonth.data(), outDay.data(),
+ // outHour.data(), outMinute.data(),
+ // 1, timeZoneBytes.data()
+ // ); // catches error as expected, though month or date out of range wasn't quite the error I was expecting
+ //ninjaErr = NinjaGetTimeList(
+ // ninjaTools,
+ // year.data(), month.data(), day.data(),
+ // hour.data(), minute.data(),
+ // outYear.data(), outMonth.data(), outDay.data(),
+ // outHour.data(), outMinute.data(),
+ // nTimeSteps, "fudge"
+ // ); // breaks HARD, a smart pointer failing on assert somewhere along the pipeline, not sure if that occurs here, or later down the pipeline. And it gets past the try/catch error handling stuff, hrm.
+ if(ninjaErr != NINJA_SUCCESS)
+ {
+ qDebug() << "NinjaGetTimeList: ninjaErr =" << ninjaErr;
+ }
+ }
+
+ if(ninjaErr == NINJA_SUCCESS)
+ {
+ numNinjas = ui->weatherStationDataTimestepsSpinBox->value();
+
+ ninjaErr = NinjaMakePointArmy( ninjaArmy,
+ outYear.data(), outMonth.data(), outDay.data(),
+ outHour.data(), outMinute.data(), nTimeSteps,
+ DEMTimeZone.toUtf8().data(), stationFileNames.data(),
+ stationFileNames.size(), DEMPath.toUtf8().data(),
+ true, momentumFlag, papszOptions
+ );
+ //ninjaErr = NinjaMakePointArmy( ninjaArmy,
+ // outYear.data(), outMonth.data(), outDay.data(),
+ // outHour.data(), outMinute.data(), -1,
+ // DEMTimeZone.toUtf8().data(), stationFileNames.data(),
+ // stationFileNames.size(), DEMPath.toUtf8().data(),
+ // true, momentumFlag, papszOptions
+ // ); // catches error as expected, now it triggers the NinjaMakePointArmy() single messaging error, instead of the double messaging makePointArmy() error, and instead of the single unexpected month or date out of range error that was seen for this case.
+ //ninjaErr = NinjaMakePointArmy( ninjaArmy,
+ // outYear.data(), outMonth.data(), outDay.data(),
+ // outHour.data(), outMinute.data(), 0,
+ // DEMTimeZone.toUtf8().data(), stationFileNames.data(),
+ // stationFileNames.size(), DEMPath.toUtf8().data(),
+ // true, momentumFlag, papszOptions
+ // ); // catches error as expected, now it triggers the NinjaMakePointArmy() single messaging error, instead of the double messaging makePointArmy() error.
+ //ninjaErr = NinjaMakePointArmy( ninjaArmy,
+ // outYear.data(), outMonth.data(), outDay.data(),
+ // outHour.data(), outMinute.data(), nTimeSteps,
+ // DEMTimeZone.toUtf8().data(), stationFileNames.data(),
+ // -1, DEMPath.toUtf8().data(),
+ // true, momentumFlag, papszOptions
+ // ); // catches error as expected, now it triggers the NinjaMakePointArmy() single messaging error, instead of the double messaging makePointArmy() error.
+ //ninjaErr = NinjaMakePointArmy( ninjaArmy,
+ // outYear.data(), outMonth.data(), outDay.data(),
+ // outHour.data(), outMinute.data(), nTimeSteps,
+ // DEMTimeZone.toUtf8().data(), stationFileNames.data(),
+ // 0, DEMPath.toUtf8().data(),
+ // true, momentumFlag, papszOptions
+ // ); // catches error as expected, now it triggers the NinjaMakePointArmy() single messaging error, instead of the double messaging makePointArmy() error.
+ //ninjaErr = NinjaMakePointArmy( ninjaArmy,
+ // outYear.data(), outMonth.data(), outDay.data(),
+ // outHour.data(), outMinute.data(), nTimeSteps,
+ // DEMTimeZone.toUtf8().data(), stationFileNames.data(),
+ // stationFileNames.size(), "fudge",
+ // true, momentumFlag, papszOptions
+ // ); // um, it warns that the dem doesn't exist, but then continues on without throwing an error or a ninjaCom, so the solver continues as if everything is normal. The warning is "ERROR 4: fudge: No such file or directory" four times, yet still it continues as if nothing went wrong.
+ //ninjaErr = NinjaMakePointArmy( ninjaArmy,
+ // outYear.data(), outMonth.data(), outDay.data(),
+ // outHour.data(), outMinute.data(), nTimeSteps,
+ // "fudge", stationFileNames.data(),
+ // stationFileNames.size(), DEMPath.toUtf8().data(),
+ // true, momentumFlag, papszOptions
+ // ); // no error or warning messages are thrown, just runs as if the dem timezone is good enough
+ //ninjaErr = NinjaMakePointArmy( ninjaArmy,
+ // outYear.data(), outMonth.data(), outDay.data(),
+ // outHour.data(), outMinute.data(), nTimeSteps,
+ // DEMTimeZone.toUtf8().data(), stationFileNames.data(),
+ // stationFileNames.size(), DEMPath.toUtf8().data(),
+ // true, true, papszOptions
+ // ); // catches error as expected
+ if(ninjaErr != NINJA_SUCCESS)
+ {
+ qDebug() << "NinjaMakePointArmy: ninjaErr =" << ninjaErr;
+ }
+ }
+
+ if(ninjaErr != NINJA_SUCCESS)
+ {
+ // do cleanup before the return, similar to finishedSolve()
+
+// ninjaErr = NinjaDestroyTools(ninjaTools, papszOptions);
+// if(ninjaErr != NINJA_SUCCESS)
+// {
+// printf("NinjaDestroyTools: ninjaErr = %d\n", ninjaErr);
+// }
+ }
+ }
+ else
+ {
+ int year, month, day, hour, minute;
+ QDateTime date = ui->weatherStationDataLabel->property("simulationTime").toDateTime();
+ year = date.date().year();
+ month = date.date().month();
+ day = date.date().day();
+ hour = date.time().hour();
+ minute = date.time().minute();
+
+ //year = -1; // catches error as expected
+ //year = 0; // catches error as expected
+ //year = 1235; // catches error as expected
+ //year = 2035; // um, apparently this one is an allowable year, it runs like normal without an error thrown, even though it probably shouldn't
+
+ //month = -1; // catches error as expected
+ //month = 0; // catches error as expected
+ //month = 14; // catches error as expected
+
+ //day = -1; // catches error as expected
+ //day = 0; // catches error as expected
+ //day = 33; // catches error as expected
+
+ //hour = -1; // this one SHOULD error, but runs fine somehow, no errors thrown. Probably wraps around or sets it to a value of 0 or something.
+ //hour = 26; // this one SHOULD error, but runs fine somehow, no errors thrown. Probably wraps around or sets it to a value of 0 or something.
+
+ //minute = -1; // this one SHOULD error, but runs fine somehow, no errors thrown. Probably wraps around or sets it to a value of 0 or something.
+ //minute = 78; // this one SHOULD error, but runs fine somehow, no errors thrown. Probably wraps around or sets it to a value of 0 or something.
+
+ int outYear, outMonth, outDay, outHour, outMinute;
+
+ ninjaErr = NinjaGenerateSingleTimeObject(
+ ninjaTools,
+ year, month, day, hour, minute,
+ timeZoneBytes.constData(),
+ &outYear, &outMonth, &outDay, &outHour, &outMinute
+ );
+ //ninjaErr = NinjaGenerateSingleTimeObject(
+ // ninjaTools,
+ // year, month, day, hour, minute,
+ // "fudge",
+ // &outYear, &outMonth, &outDay, &outHour, &outMinute
+ // ); // breaks HARD, a smart pointer failing on assert somewhere along the pipeline, not sure if that occurs here, or later down the pipeline. And it gets past the try/catch error handling stuff, hrm.
+ if (ninjaErr != NINJA_SUCCESS)
+ {
+ qDebug() << "NinjaGenerateSingleTimeObject: ninjaErr =" << ninjaErr;
+ }
+
+ QVector yearVec = { outYear };
+ QVector monthVec = { outMonth };
+ QVector dayVec = { outDay };
+ QVector hourVec = { outHour };
+ QVector minuteVec = { outMinute };
+
+ numNinjas = 1;
+ int nTimeSteps = 1;
+
+ if(ninjaErr == NINJA_SUCCESS)
+ {
+ ninjaErr = NinjaMakePointArmy( ninjaArmy,
+ yearVec.data(), monthVec.data(), dayVec.data(),
+ hourVec.data(), minuteVec.data(), nTimeSteps,
+ DEMTimeZone.toUtf8().data(),
+ stationFileNames.data(),
+ static_cast(stationFileNames.size()),
+ DEMPath.toUtf8().data(),
+ true, momentumFlag, papszOptions
+ );
+ //ninjaErr = NinjaMakePointArmy( ninjaArmy,
+ // yearVec.data(), monthVec.data(), dayVec.data(),
+ // hourVec.data(), minuteVec.data(), -1,
+ // DEMTimeZone.toUtf8().data(),
+ // stationFileNames.data(),
+ // static_cast(stationFileNames.size()),
+ // DEMPath.toUtf8().data(),
+ // true, momentumFlag, papszOptions
+ //); // catches error as expected, now it triggers the NinjaMakePointArmy() single messaging error, instead of the double messaging makePointArmy() error, and instead of the single unexpected month or date out of range error that was seen for this case.
+ //ninjaErr = NinjaMakePointArmy( ninjaArmy,
+ // yearVec.data(), monthVec.data(), dayVec.data(),
+ // hourVec.data(), minuteVec.data(), 0,
+ // DEMTimeZone.toUtf8().data(),
+ // stationFileNames.data(),
+ // static_cast(stationFileNames.size()),
+ // DEMPath.toUtf8().data(),
+ // true, momentumFlag, papszOptions
+ //); // catches error as expected, now it triggers the NinjaMakePointArmy() single messaging error, instead of the double messaging makePointArmy() error.
+ //ninjaErr = NinjaMakePointArmy( ninjaArmy,
+ // yearVec.data(), monthVec.data(), dayVec.data(),
+ // hourVec.data(), minuteVec.data(), nTimeSteps,
+ // DEMTimeZone.toUtf8().data(),
+ // stationFileNames.data(),
+ // -1,
+ // DEMPath.toUtf8().data(),
+ // true, momentumFlag, papszOptions
+ //); // catches error as expected, now it triggers the NinjaMakePointArmy() single messaging error, instead of the double messaging makePointArmy() error.
+ //ninjaErr = NinjaMakePointArmy( ninjaArmy,
+ // yearVec.data(), monthVec.data(), dayVec.data(),
+ // hourVec.data(), minuteVec.data(), nTimeSteps,
+ // DEMTimeZone.toUtf8().data(),
+ // stationFileNames.data(),
+ // 0,
+ // DEMPath.toUtf8().data(),
+ // true, momentumFlag, papszOptions
+ //); // catches error as expected, now it triggers the NinjaMakePointArmy() single messaging error, instead of the double messaging makePointArmy() error.
+ //ninjaErr = NinjaMakePointArmy( ninjaArmy,
+ // yearVec.data(), monthVec.data(), dayVec.data(),
+ // hourVec.data(), minuteVec.data(), nTimeSteps,
+ // DEMTimeZone.toUtf8().data(),
+ // stationFileNames.data(),
+ // static_cast(stationFileNames.size()),
+ // "fudge",
+ // true, momentumFlag, papszOptions
+ //); // um, it warns that the dem doesn't exist, but then continues on without throwing an error or a ninjaCom, so the solver continues as if everything is normal. The warning is "ERROR 4: fudge: No such file or directory" four times, yet still it continues as if nothing went wrong.
+ //ninjaErr = NinjaMakePointArmy( ninjaArmy,
+ // yearVec.data(), monthVec.data(), dayVec.data(),
+ // hourVec.data(), minuteVec.data(), nTimeSteps,
+ // "fudge",
+ // stationFileNames.data(),
+ // static_cast(stationFileNames.size()),
+ // DEMPath.toUtf8().data(),
+ // true, momentumFlag, papszOptions
+ //); // no error or warning messages are thrown, just runs as if the dem timezone is good enough
+ //ninjaErr = NinjaMakePointArmy( ninjaArmy,
+ // yearVec.data(), monthVec.data(), dayVec.data(),
+ // hourVec.data(), minuteVec.data(), nTimeSteps,
+ // DEMTimeZone.toUtf8().data(),
+ // stationFileNames.data(),
+ // static_cast(stationFileNames.size()),
+ // DEMPath.toUtf8().data(),
+ // true, true, papszOptions
+ //); // catches error as expected
+ if(ninjaErr != NINJA_SUCCESS)
+ {
+ qDebug() << "NinjaMakePointArmy ninjaErr =" << ninjaErr;
+ }
+ }
+ }
+ }
+ else //if (state.isWeatherModelInitializationValid)
+ {
+ QModelIndexList selectedIndexes = ui->weatherModelTimeTreeView->selectionModel()->selectedIndexes();
+ int timeListSize = selectedIndexes.count();
+ numNinjas = timeListSize;
+ initializationMethod = "wxmodel";
+ std::string timeZone = ui->timeZoneComboBox->currentText().toStdString();
+
+ QModelIndex index = ui->weatherModelFileTreeView->currentIndex();
+ QFileSystemModel *model = qobject_cast(ui->weatherModelFileTreeView->model());
+ std::string filePath = model->filePath(index).toStdString();
+
+ // Allocate the char** array
+ const char **inputTimeList = new const char*[timeListSize];
+
+ for (int i = 0; i < timeListSize; ++i)
+ {
+ QString qstr = selectedIndexes[i].data().toString();
+ std::string str = qstr.toStdString();
+ inputTimeList[i] = strdup(str.c_str()); // allocate and copy each string
+ }
+
+ ninjaErr = NinjaMakeWeatherModelArmy(ninjaArmy, filePath.c_str(), timeZone.c_str(), inputTimeList, timeListSize, ui->momentumSolverCheckBox->isChecked(), papszOptions);
+ //ninjaErr = NinjaMakeWeatherModelArmy(ninjaArmy, filePath.c_str(), timeZone.c_str(), inputTimeList, -1, ui->momentumSolverCheckBox->isChecked(), papszOptions); // catches error as expected, now it triggers the NinjaMakeWeatherModelArmy() single messaging error, instead of the double messaging makeWeatherArmy() error.
+ //ninjaErr = NinjaMakeWeatherModelArmy(ninjaArmy, filePath.c_str(), timeZone.c_str(), inputTimeList, 0, ui->momentumSolverCheckBox->isChecked(), papszOptions); // catches error as expected, now it triggers the NinjaMakeWeatherModelArmy() single messaging error, instead of the double messaging makeWeatherArmy() error.
+ //ninjaErr = NinjaMakeWeatherModelArmy(ninjaArmy, "fudge", timeZone.c_str(), inputTimeList, timeListSize, ui->momentumSolverCheckBox->isChecked(), papszOptions); // catches error as expected
+ //ninjaErr = NinjaMakeWeatherModelArmy(ninjaArmy, filePath.c_str(), "fudge", inputTimeList, timeListSize, ui->momentumSolverCheckBox->isChecked(), papszOptions); // catches error as expected
+ if(ninjaErr != NINJA_SUCCESS)
+ {
+ qDebug() << "NinjaMakeWeatherModelArmy ninjaErr =" << ninjaErr;
+ }
+ }
+
+ if(ninjaErr != NINJA_SUCCESS)
+ {
+ progressDialog->setValue(maxProgress);
+ progressDialog->setCancelButtonText("Close");
+
+ // do cleanup before the return, similar to finishedSolve()
+
+ //disconnect(progressDialog, SIGNAL(canceled()), this, SLOT(cancelSolve()));
+
+ char **papszOptions = nullptr;
+ int ninjaErr = NinjaDestroyArmy(ninjaArmy, papszOptions);
+ if(ninjaErr != NINJA_SUCCESS)
+ {
+ printf("NinjaDestroyRuns: ninjaErr = %d\n", ninjaErr);
+ }
+
+ // clear the progress values for the next set of runs
+ //runProgress.clear();
+
+ //futureWatcher->deleteLater();
+
+ return;
+ }
+
+ writeToConsole(QString::number( numNinjas ) + " runs initialized. Starting solver...");
+
+ maxProgress = numNinjas*100;
+
+ progressDialog->setRange(0, maxProgress);
+ progressDialog->setValue(0);
+ progressDialog->setLabelText("Solving...");
+
+ progressDialog->setCancelButtonText("Cancel");
+ connect( progressDialog, SIGNAL( canceled() ), this, SLOT( cancelSolve() ) );
+
+ // initialize the progress values for the current set of runs
+ totalProgress = 0;
+ for(unsigned int i = 0; i < numNinjas; i++)
+ {
+ runProgress.push_back(0);
+ }
+
+ futureWatcher = new QFutureWatcher(this);
+
+ bool retVal = prepareArmy(ninjaArmy, numNinjas, initializationMethod);
+ if( retVal == false )
+ {
+ progressDialog->setValue(maxProgress);
+ progressDialog->setCancelButtonText("Close");
+
+ // do cleanup before the return, similar to finishedSolve()
+
+ disconnect(progressDialog, SIGNAL(canceled()), this, SLOT(cancelSolve()));
+
+ char **papszOptions = nullptr;
+ int ninjaErr = NinjaDestroyArmy(ninjaArmy, papszOptions);
+ if(ninjaErr != NINJA_SUCCESS)
+ {
+ printf("NinjaDestroyRuns: ninjaErr = %d\n", ninjaErr);
+ }
+
+ // clear the progress values for the next set of runs
+ runProgress.clear();
+
+ futureWatcher->deleteLater();
+
+ return;
+ }
+
+ // set progress dialog initial value and initial text for the set of runs
+ progressDialog->setValue(0);
+ progressDialog->setLabelText("Running...");
+
+ qDebug() << "Initializing runs...";
+ writeToConsole( "Initializing runs..." );
+
+ connect(futureWatcher, &QFutureWatcher::finished, this, &MainWindow::finishedSolve);
+
+ QFuture future = QtConcurrent::run(&MainWindow::startSolve, this, ui->numberOfProcessorsSpinBox->value());
+ futureWatcher->setFuture(future);
+
+}
+
+void MainWindow::treeWidgetItemDoubleClicked(QTreeWidgetItem *item, int column)
+{
+ if (item->text(0) == "Conservation of Mass")
+ {
+ ui->massSolverCheckBox->click();
+ }
+ else if (item->text(0) == "Conservation of Mass and Momentum")
+ {
+ ui->momentumSolverCheckBox->click();
+ }
+ else if (item->text(0) == "Diurnal Input")
+ {
+ ui->diurnalCheckBox->click();
+ }
+ else if (item->text(0) == "Stability Input")
+ {
+ ui->stabilityCheckBox->click();
+ }
+ else if (item->text(0) == "Domain Average Wind")
+ {
+ ui->domainAverageGroupBox->setChecked(!ui->domainAverageGroupBox->isChecked());
+ }
+ else if (item->text(0) == "Point Initialization")
+ {
+ ui->pointInitializationGroupBox->setChecked(!ui->pointInitializationGroupBox->isChecked());
+ }
+ else if (item->text(0) == "Weather Model")
+ {
+ ui->weatherModelGroupBox->setChecked(!ui->weatherModelGroupBox->isChecked());
+ }
+ else if (item->text(0) == "Surface Input")
+ {
+ ui->elevationInputFileOpenButton->click();
+ }
+ else if (item->text(0) == "Google Earth")
+ {
+ ui->googleEarthCheckBox->setChecked(!ui->googleEarthCheckBox->isChecked());
+ }
+ else if (item->text(0) == "Fire Behavior")
+ {
+ ui->fireBehaviorGroupBox->setChecked(!ui->fireBehaviorGroupBox->isChecked());
+ }
+ else if (item->text(0) == "Shape Files")
+ {
+ ui->shapeFilesGroupBox->setChecked(!ui->shapeFilesGroupBox->isChecked());
+ }
+ else if (item->text(0) == "Geospatial PDF Files")
+ {
+ ui->geospatialPDFFilesGroupBox->setChecked(!ui->geospatialPDFFilesGroupBox->isChecked());
+ }
+ else if (item->text(0) == "VTK Files")
+ {
+ ui->VTKFilesCheckBox->click();
+ }
+}
+
+bool MainWindow::prepareArmy(NinjaArmyH *ninjaArmy, int numNinjas, const char* initializationMethod)
+{
+ OutputPDFSize PDFSize;
+ switch(ui->sizeDimensionsComboBox->currentIndex())
+ {
+ case 0:
+ PDFSize.PDFHeight = 11.0;
+ PDFSize.PDFWidth = 8.5;
+ PDFSize.PDFDpi = 150;
+ break;
+ case 1:
+ PDFSize.PDFHeight = 14.0;
+ PDFSize.PDFWidth = 8.5;
+ PDFSize.PDFDpi = 150;
+ break;
+ case 2:
+ PDFSize.PDFHeight = 17.0;
+ PDFSize.PDFWidth = 11.0;
+ PDFSize.PDFDpi = 150;
+ break;
+ }
+ if (ui->sizeOrientationComboBox->currentIndex() == 1)
+ {
+ std::swap(PDFSize.PDFHeight, PDFSize.PDFWidth);
+ }
+
+ char **papszOptions = nullptr;
+
+ // can this one even be tested?? The way it is organized also makes it tough to setup a ninjaCom message
+ ninjaErr = NinjaSetAsciiAtmFile(ninjaArmy, ui->fireBehaviorResolutionCheckBox->isChecked(), papszOptions);
+ if(ninjaErr != NINJA_SUCCESS)
+ {
+ qDebug() << "NinjaSetAsciiAtmFile: ninjaErr =" << ninjaErr;
+ return false;
+ }
+
+ for(unsigned int i=0; ipointInitializationGroupBox->isChecked())
+ {
+ if(ui->pointInitializationWriteStationKMLCheckBox->isChecked())
+ {
+ // function needs MAJOR rework to get the testing to work, direct call to non-ninjaArmy function makes this process tougher
+ ninjaErr = NinjaSetStationKML(ninjaArmy, i, ui->elevationInputFileLineEdit->property("fullpath").toString().toUtf8().constData(), ui->outputDirectoryLineEdit->text().toUtf8().constData(), ui->outputSpeedUnitsComboBox->currentText().toUtf8().constData(), papszOptions);
+ //ninjaErr = NinjaSetStationKML(ninjaArmy, i+10, ui->elevationInputFileLineEdit->property("fullpath").toString().toUtf8().constData(), ui->outputDirectoryLineEdit->text().toUtf8().constData(), ui->outputSpeedUnitsComboBox->currentText().toUtf8().constData(), papszOptions); // test error handling // function needs reorganized to handle this test
+ //ninjaErr = NinjaSetStationKML(ninjaArmy, i, ui->elevationInputFileLineEdit->property("fullpath").toString().toUtf8().constData(), ui->outputDirectoryLineEdit->text().toUtf8().constData(), "fudge", papszOptions); // test error handling // ran, but the functions need reorganized for proper messaging
+ //ninjaErr = NinjaSetStationKML(ninjaArmy, i, ui->elevationInputFileLineEdit->property("fullpath").toString().toUtf8().constData(), "fudge", ui->outputSpeedUnitsComboBox->currentText().toUtf8().constData(), papszOptions); // test error handling // function needs reorganized to handle this test
+ //ninjaErr = NinjaSetStationKML(ninjaArmy, i, "fudge", ui->outputDirectoryLineEdit->text().toUtf8().constData(), ui->outputSpeedUnitsComboBox->currentText().toUtf8().constData(), papszOptions); // test error handling // function needs reorganized to handle this test
+ if(ninjaErr != NINJA_SUCCESS)
+ {
+ printf("NinjaSetStationKML: ninjaErr = %d\n", ninjaErr);
+ return false;
+ }
+ }
+ }
+
+ ninjaErr = NinjaSetNumberCPUs(ninjaArmy, i, ui->numberOfProcessorsSpinBox->value(), papszOptions);
+ //ninjaErr = NinjaSetNumberCPUs(ninjaArmy, i+10, ui->numberOfProcessorsSpinBox->value(), papszOptions); // test error handling
+ //ninjaErr = NinjaSetNumberCPUs(ninjaArmy, i, -1, papszOptions); // test error handling // requires the try/catch form of IF_VALID_INDEX_TRY in ninjaArmy.h
+ if(ninjaErr != NINJA_SUCCESS)
+ {
+ qDebug() << "NinjaSetNumberCPUs: ninjaErr =" << ninjaErr;
+ return false;
+ }
+
+ ninjaErr = NinjaSetInitializationMethod(ninjaArmy, i, initializationMethod, ui->pointInitializationGroupBox->isChecked(), papszOptions);
+ //ninjaErr = NinjaSetInitializationMethod(ninjaArmy, i+10, initializationMethod, ui->pointInitializationGroupBox->isChecked(), papszOptions); // test error handling // hrm, ninjaCom isn't triggering for this one, though the error returns, leading to it hanging without a proper message.
+ //ninjaErr = NinjaSetInitializationMethod(ninjaArmy, i, "fudge", ui->pointInitializationGroupBox->isChecked(), papszOptions); // test error handling
+ if(ninjaErr != NINJA_SUCCESS)
+ {
+ qDebug() << "NinjaSetInitializationMethod: ninjaErr =" << ninjaErr;
+ return false;
+ }
+
+ ninjaErr = NinjaSetDem(ninjaArmy, i, ui->elevationInputFileLineEdit->property("fullpath").toString().toUtf8().constData(), papszOptions);
+ //ninjaErr = NinjaSetDem(ninjaArmy, i+10, ui->elevationInputFileLineEdit->property("fullpath").toString().toUtf8().constData(), papszOptions);
+ //ninjaErr = NinjaSetDem(ninjaArmy, i, "fudge", papszOptions); // test error handling // requires the try/catch form of IF_VALID_INDEX_TRY in ninjaArmy.h
+ if(ninjaErr != NINJA_SUCCESS)
+ {
+ qDebug() << "NinjaSetDem: ninjaErr =" << ninjaErr;
+ return false;
+ }
+
+ ninjaErr = NinjaSetPosition(ninjaArmy, i, papszOptions); // if setting up ninja.cpp function call to simply throw, this breaks, this requires the try/catch form of IF_VALID_INDEX_TRY in ninjaArmy.h
+ //ninjaErr = NinjaSetPosition(ninjaArmy, i+10, papszOptions); // test error handling
+ if(ninjaErr != NINJA_SUCCESS)
+ {
+ qDebug() << "NinjaSetPosition: ninjaErr =" << ninjaErr;
+ return false;
+ }
+
+ ninjaErr = NinjaSetInputWindHeight(ninjaArmy, i, ui->inputWindHeightSpinBox->value(), ui->inputWindHeightUnitsComboBox->itemData(ui->inputWindHeightUnitsComboBox->currentIndex()).toString().toUtf8().constData(), papszOptions);
+ //ninjaErr = NinjaSetInputWindHeight(ninjaArmy, i+10, ui->inputWindHeightSpinBox->value(), ui->inputWindHeightUnitsComboBox->itemData(ui->inputWindHeightUnitsComboBox->currentIndex()).toString().toUtf8().constData(), papszOptions); // test error handling // hrm, ninjaCom isn't triggering for this one, though the error returns, leading to it hanging without a proper message.
+ //ninjaErr = NinjaSetInputWindHeight(ninjaArmy, i, ui->inputWindHeightSpinBox->value(), "fudge", papszOptions); // test error handling
+ //ninjaErr = NinjaSetInputWindHeight(ninjaArmy, i, -1, ui->inputWindHeightUnitsComboBox->itemData(ui->inputWindHeightUnitsComboBox->currentIndex()).toString().toUtf8().constData(), papszOptions); // test error handling
+ if(ninjaErr != NINJA_SUCCESS)
+ {
+ qDebug() << "NinjaSetInputWindHeight: ninjaErr =" << ninjaErr;
+ return false;
+ }
+
+ ninjaErr = NinjaSetDiurnalWinds(ninjaArmy, i, ui->diurnalCheckBox->isChecked(), papszOptions);
+ //ninjaErr = NinjaSetDiurnalWinds(ninjaArmy, i+10, ui->diurnalCheckBox->isChecked(), papszOptions); // test error handling
+ if(ninjaErr != NINJA_SUCCESS)
+ {
+ qDebug() << "NinjaSetDiurnalWinds: ninjaErr =" << ninjaErr;
+ return false;
+ }
+
+ if(ui->vegetationStackedWidget->currentIndex() == 0)
+ {
+ ninjaErr = NinjaSetUniVegetation(ninjaArmy, i, ui->vegetationComboBox->currentText().toLower().toUtf8().constData(), papszOptions);
+ //ninjaErr = NinjaSetUniVegetation(ninjaArmy, i+10, ui->vegetationComboBox->currentText().toLower().toUtf8().constData(), papszOptions); // test error handling // hrm, ninjaCom isn't triggering for this one, though the error returns, leading to it hanging without a proper message.
+ //ninjaErr = NinjaSetUniVegetation(ninjaArmy, i, "fudge", papszOptions); // test error handling
+ if(ninjaErr != NINJA_SUCCESS)
+ {
+ qDebug() << "NinjaSetUniVegetation: ninjaErr =" << ninjaErr;
+ return false;
+ }
+ }
+
+ if(ui->meshResolutionComboBox->currentIndex() == 3) // custom res
+ {
+ ninjaErr = NinjaSetMeshResolution(ninjaArmy, i, ui->meshResolutionSpinBox->value(), ui->meshResolutionUnitsComboBox->itemData(ui->meshResolutionUnitsComboBox->currentIndex()).toString().toUtf8().constData(), papszOptions);
+ if(ninjaErr != NINJA_SUCCESS)
+ {
+ qDebug() << "NinjaSetMeshResolution: ninjaErr =" << ninjaErr;
+ return false;
+ }
+ } else
+ {
+ ninjaErr = NinjaSetMeshResolutionChoice(ninjaArmy, i, ui->meshResolutionComboBox->currentText().toLower().toUtf8().constData(), papszOptions);
+ //ninjaErr = NinjaSetMeshResolutionChoice(ninjaArmy, i+10, ui->meshResolutionComboBox->currentText().toLower().toUtf8().constData(), papszOptions); // test error handling // hrm, ninjaCom isn't triggering for this one, though the error returns, leading to it hanging without a proper message.
+ //ninjaErr = NinjaSetMeshResolutionChoice(ninjaArmy, i, "fudge", papszOptions); // test error handling
+ if(ninjaErr != NINJA_SUCCESS)
+ {
+ qDebug() << "NinjaSetMeshResolutionChoice: ninjaErr =" << ninjaErr;
+ return false;
+ }
+ }
+
+ ninjaErr = NinjaSetNumVertLayers(ninjaArmy, i, 20, papszOptions);
+ //ninjaErr = NinjaSetNumVertLayers(ninjaArmy, i+10, 20, papszOptions); // test error handling
+ //ninjaErr = NinjaSetNumVertLayers(ninjaArmy, i, -1, papszOptions); // test error handling // requires the try/catch form of IF_VALID_INDEX_TRY in ninjaArmy.h
+ if(ninjaErr != NINJA_SUCCESS)
+ {
+ qDebug() << "NinjaSetNumVertLayers: ninjaErr =" << ninjaErr;
+ return false;
+ }
+
+ bool retVal = setOutputFlags(ninjaArmy, i, numNinjas, PDFSize);
+ if( retVal == false )
+ {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+bool MainWindow::setOutputFlags(NinjaArmyH* ninjaArmy,
+ int i,
+ int numNinjas,
+ OutputPDFSize PDFSize)
+{
+ char **papszOptions = nullptr;
+ int ninjaErr;
+
+ ninjaErr = NinjaSetOutputPath(ninjaArmy, i, ui->outputDirectoryLineEdit->text().toUtf8().constData(), papszOptions);
+ //ninjaErr = NinjaSetOutputPath(ninjaArmy, i+10, ui->outputDirectoryLineEdit->text().toUtf8().constData(), papszOptions); // test error handling
+ if (ninjaErr != NINJA_SUCCESS)
+ {
+ qDebug() << "NinjaSetOutputPath: ninjaErr =" << ninjaErr;
+ return false;
+ }
+
+ ninjaErr = NinjaSetOutputWindHeight(ninjaArmy, i, ui->outputWindHeightSpinBox->value(), ui->outputWindHeightUnitsComboBox->itemData(ui->outputWindHeightUnitsComboBox->currentIndex()).toString().toUtf8().constData(), papszOptions);
+ //ninjaErr = NinjaSetOutputWindHeight(ninjaArmy, i+10, ui->outputWindHeightSpinBox->value(), ui->outputWindHeightUnitsComboBox->itemData(ui->outputWindHeightUnitsComboBox->currentIndex()).toString().toUtf8().constData(), papszOptions); // test error handling // hrm, ninjaCom isn't triggering for this one, though the error returns, leading to it hanging without a proper message.
+ //ninjaErr = NinjaSetOutputWindHeight(ninjaArmy, i, ui->outputWindHeightSpinBox->value(), "fudge", papszOptions); // test error handling
+ //ninjaErr = NinjaSetOutputWindHeight(ninjaArmy, i, -1, ui->outputWindHeightUnitsComboBox->itemData(ui->outputWindHeightUnitsComboBox->currentIndex()).toString().toUtf8().constData(), papszOptions); // test error handling
+ if (ninjaErr != NINJA_SUCCESS)
+ {
+ qDebug() << "NinjaSetOutputWindHeight: ninjaErr =" << ninjaErr;
+ return false;
+ }
+
+ ninjaErr = NinjaSetOutputSpeedUnits(ninjaArmy, i, ui->outputSpeedUnitsComboBox->currentText().toUtf8().constData(), papszOptions);
+ //ninjaErr = NinjaSetOutputSpeedUnits(ninjaArmy, i+10, ui->outputSpeedUnitsComboBox->currentText().toUtf8().constData(), papszOptions); // test error handling // hrm, ninjaCom isn't triggering for this one, though the error returns, leading to it hanging without a proper message.
+ //ninjaErr = NinjaSetOutputSpeedUnits(ninjaArmy, i, "fudge", papszOptions); // test error handling
+ if (ninjaErr != NINJA_SUCCESS)
+ {
+ qDebug() << "NinjaSetOutputSpeedUnits: ninjaErr =" << ninjaErr;
+ return false;
+ }
+
+ ninjaErr = NinjaSetOutputBufferClipping(ninjaArmy, i, ui->clipOutputSpinBox->value(), papszOptions);
+ //ninjaErr = NinjaSetOutputBufferClipping(ninjaArmy, i+10, ui->clipOutputSpinBox->value(), papszOptions); // test error handling, looks good
+ //ninjaErr = NinjaSetOutputBufferClipping(ninjaArmy, i, -1, papszOptions); // test error handling
+ //ninjaErr = NinjaSetOutputBufferClipping(ninjaArmy, i, 50, papszOptions); // test error handling, message might need improved, but it IS an error, as it should be
+ if (ninjaErr != NINJA_SUCCESS)
+ {
+ qDebug() << "NinjaSetOutputBufferClipping: ninjaErr =" << ninjaErr;
+ return false;
+ }
+
+ ninjaErr = NinjaSetGoogOutFlag(ninjaArmy, i, ui->googleEarthCheckBox->isChecked(), papszOptions);
+ //ninjaErr = NinjaSetGoogOutFlag(ninjaArmy, i+10, ui->googleEarthCheckBox->isChecked(), papszOptions); // test error handling
+ if (ninjaErr != NINJA_SUCCESS)
+ {
+ qDebug() << "NinjaSetGoogOutFlag: ninjaErr =" << ninjaErr;
+ return false;
+ }
+
+ ninjaErr = NinjaSetGoogResolution(ninjaArmy, i, ui->googleEarthMeshResolutionSpinBox->value(), ui->googleEarthMeshResolutionComboBox->itemData(ui->googleEarthMeshResolutionComboBox->currentIndex()).toString().toUtf8().constData(), papszOptions);
+ //ninjaErr = NinjaSetGoogResolution(ninjaArmy, i+10, ui->googleEarthMeshResolutionSpinBox->value(), ui->googleEarthMeshResolutionComboBox->itemData(ui->googleEarthMeshResolutionComboBox->currentIndex()).toString().toUtf8().constData(), papszOptions); // test error handling // hrm, ninjaCom isn't triggering for this one, though the error returns, leading to it hanging without a proper message.
+ //ninjaErr = NinjaSetGoogResolution(ninjaArmy, i, ui->googleEarthMeshResolutionSpinBox->value(), "fudge", papszOptions); // test error handling
+ if (ninjaErr != NINJA_SUCCESS)
+ {
+ qDebug() << "NinjaSetGoogResolution: ninjaErr =" << ninjaErr;
+ return false;
+ }
+
+ ninjaErr = NinjaSetGoogSpeedScaling(ninjaArmy, i, ui->legendComboBox->itemData(ui->legendComboBox->currentIndex()).toString().toUtf8().constData(), papszOptions);
+ //ninjaErr = NinjaSetGoogSpeedScaling(ninjaArmy, i+10, ui->legendComboBox->itemData(ui->legendComboBox->currentIndex()).toString().toUtf8().constData(), papszOptions); // test error handling // hrm, ninjaCom isn't triggering for this one, though the error returns, leading to it hanging without a proper message.
+ //ninjaErr = NinjaSetGoogSpeedScaling(ninjaArmy, i, "fudge", papszOptions); // test error handling
+ if (ninjaErr != NINJA_SUCCESS)
+ {
+ qDebug() << "NinjaSetGoogSpeedScaling: ninjaErr =" << ninjaErr;
+ return false;
+ }
+
+ ninjaErr = NinjaSetGoogLineWidth(ninjaArmy, i, ui->googleEarthVectorsSpinBox->value(), papszOptions);
+ //ninjaErr = NinjaSetGoogLineWidth(ninjaArmy, i+10, ui->googleEarthVectorsSpinBox->value(), papszOptions); // test error handling
+ //ninjaErr = NinjaSetGoogLineWidth(ninjaArmy, i, -1, papszOptions); // test error handling // requires the try/catch form of IF_VALID_INDEX_TRY in ninjaArmy.h
+ //ninjaErr = NinjaSetGoogLineWidth(ninjaArmy, i, 101, papszOptions); // test error handling
+ if (ninjaErr != NINJA_SUCCESS)
+ {
+ qDebug() << "NinjaSetGoogLineWidth: ninjaErr =" << ninjaErr;
+ return false;
+ }
+
+ ninjaErr = NinjaSetGoogColor(ninjaArmy, i, ui->alternativeColorSchemeComboBox->itemData(ui->alternativeColorSchemeComboBox->currentIndex()).toString().toUtf8().constData(), ui->googleEarthVectorScalingCheckBox->isChecked(), papszOptions);
+ //ninjaErr = NinjaSetGoogColor(ninjaArmy, i+10, ui->alternativeColorSchemeComboBox->itemData(ui->alternativeColorSchemeComboBox->currentIndex()).toString().toUtf8().constData(), ui->googleEarthVectorScalingCheckBox->isChecked(), papszOptions); // test error handling
+ ////ninjaErr = NinjaSetGoogColor(ninjaArmy, i, "fudge", ui->googleEarthVectorScalingCheckBox->isChecked(), papszOptions); // test error handling // requires the try/catch form of IF_VALID_INDEX_TRY in ninjaArmy.h // actually, the colorScheme string appears to not even be checked
+ if (ninjaErr != NINJA_SUCCESS)
+ {
+ qDebug() << "NinjaSetGoogColor: ninjaErr =" << ninjaErr;
+ return false;
+ }
+
+ ninjaErr = NinjaSetGoogConsistentColorScale(ninjaArmy, i, ui->legendCheckBox->isChecked(), numNinjas, papszOptions);
+ //ninjaErr = NinjaSetGoogConsistentColorScale(ninjaArmy, i+10, ui->legendCheckBox->isChecked(), numNinjas, papszOptions); // test error handling
+ if (ninjaErr != NINJA_SUCCESS)
+ {
+ qDebug() << "NinjaSetGoogConsistentColorScale: ninjaErr =" << ninjaErr;
+ return false;
+ }
+
+ ninjaErr = NinjaSetAsciiOutFlag(ninjaArmy, i, ui->fireBehaviorGroupBox->isChecked(), papszOptions);
+ //ninjaErr = NinjaSetAsciiOutFlag(ninjaArmy, i+10, ui->fireBehaviorGroupBox->isChecked(), papszOptions); // test error handling
+ if (ninjaErr != NINJA_SUCCESS)
+ {
+ qDebug() << "NinjaSetAsciiOutFlag: ninjaErr =" << ninjaErr;
+ return false;
+ }
+
+ ninjaErr = NinjaSetAsciiResolution(ninjaArmy, i, ui->fireBehaviorMeshResolutionSpinBox->value(), ui->fireBehaviorMeshResolutionComboBox->itemData(ui->fireBehaviorMeshResolutionComboBox->currentIndex()).toString().toUtf8().constData(), papszOptions);
+ //ninjaErr = NinjaSetAsciiResolution(ninjaArmy, i+10, ui->fireBehaviorMeshResolutionSpinBox->value(), ui->fireBehaviorMeshResolutionComboBox->itemData(ui->fireBehaviorMeshResolutionComboBox->currentIndex()).toString().toUtf8().constData(), papszOptions); // test error handling // hrm, ninjaCom isn't triggering for this one, though the error returns, leading to it hanging without a proper message.
+ //ninjaErr = NinjaSetAsciiResolution(ninjaArmy, i, ui->fireBehaviorMeshResolutionSpinBox->value(), "fudge", papszOptions); // test error handling
+ if (ninjaErr != NINJA_SUCCESS)
+ {
+ qDebug() << "NinjaSetAsciiResolution: ninjaErr =" << ninjaErr;
+ return false;
+ }
+
+ ninjaErr = NinjaSetShpOutFlag(ninjaArmy, i, ui->shapeFilesGroupBox->isChecked(), papszOptions);
+ //ninjaErr = NinjaSetShpOutFlag(ninjaArmy, i+10, ui->shapeFilesGroupBox->isChecked(), papszOptions); // test error handling
+ if (ninjaErr != NINJA_SUCCESS)
+ {
+ qDebug() << "NinjaSetShpOutFlag: ninjaErr =" << ninjaErr;
+ return false;
+ }
+
+ ninjaErr = NinjaSetShpResolution(ninjaArmy, i, ui->shapeFilesMeshResolutionSpinBox->value(), ui->shapeFilesMeshResolutionComboBox->itemData(ui->shapeFilesMeshResolutionComboBox->currentIndex()).toString().toUtf8().constData(), papszOptions);
+ //ninjaErr = NinjaSetShpResolution(ninjaArmy, i+10, ui->shapeFilesMeshResolutionSpinBox->value(), ui->shapeFilesMeshResolutionComboBox->itemData(ui->shapeFilesMeshResolutionComboBox->currentIndex()).toString().toUtf8().constData(), papszOptions); // test error handling // hrm, ninjaCom isn't triggering for this one, though the error returns, leading to it hanging without a proper message.
+ //ninjaErr = NinjaSetShpResolution(ninjaArmy, i, ui->shapeFilesMeshResolutionSpinBox->value(), "fudge", papszOptions); // test error handling
+ if (ninjaErr != NINJA_SUCCESS)
+ {
+ qDebug() << "NinjaSetShpResolution: ninjaErr =" << ninjaErr;
+ return false;
+ }
+
+ ninjaErr = NinjaSetPDFOutFlag(ninjaArmy, i, ui->geospatialPDFFilesGroupBox->isChecked(), papszOptions);
+ //ninjaErr = NinjaSetPDFOutFlag(ninjaArmy, i+10, ui->geospatialPDFFilesGroupBox->isChecked(), papszOptions); // test error handling
+ if (ninjaErr != NINJA_SUCCESS)
+ {
+ qDebug() << "NinjaSetPDFOutFlag: ninjaErr =" << ninjaErr;
+ return false;
+ }
+
+ ninjaErr = NinjaSetPDFLineWidth(ninjaArmy, i, ui->geospatialPDFFilesVectorsSpinBox->value(), papszOptions);
+ //ninjaErr = NinjaSetPDFLineWidth(ninjaArmy, i+10, ui->geospatialPDFFilesVectorsSpinBox->value(), papszOptions); // test error handling
+ if (ninjaErr != NINJA_SUCCESS)
+ {
+ qDebug() << "NinjaSetPDFLineWidth: ninjaErr =" << ninjaErr;
+ return false;
+ }
+
+ ninjaErr = NinjaSetPDFBaseMap(ninjaArmy, i, ui->basemapComboBox->currentIndex(), papszOptions);
+ //ninjaErr = NinjaSetPDFBaseMap(ninjaArmy, i+10, ui->basemapComboBox->currentIndex(), papszOptions); // test error handling
+ if (ninjaErr != NINJA_SUCCESS)
+ {
+ qDebug() << "NinjaSetPDFBaseMap: ninjaErr =" << ninjaErr;
+ return false;
+ }
+
+ ninjaErr = NinjaSetPDFDEM(ninjaArmy, i, ui->elevationInputFileLineEdit->property("fullpath").toString().toUtf8().constData(), papszOptions);
+ //ninjaErr = NinjaSetPDFDEM(ninjaArmy, i+10, ui->elevationInputFileLineEdit->property("fullpath").toString().toUtf8().constData(), papszOptions); // test error handling
+ ////ninjaErr = NinjaSetPDFDEM(ninjaArmy, i, "fudge", papszOptions); // test error handling // the dem string is not even checked
+ if (ninjaErr != NINJA_SUCCESS)
+ {
+ qDebug() << "NinjaSetPDFDEM: ninjaErr =" << ninjaErr;
+ return false;
+ }
+
+ ninjaErr = NinjaSetPDFSize(ninjaArmy, i, PDFSize.PDFHeight, PDFSize.PDFWidth, PDFSize.PDFDpi, papszOptions);
+ //ninjaErr = NinjaSetPDFSize(ninjaArmy, i+10, PDFSize.PDFHeight, PDFSize.PDFWidth, PDFSize.PDFDpi, papszOptions); // test error handling
+ if (ninjaErr != NINJA_SUCCESS)
+ {
+ qDebug() << "NinjaSetPDFSize: ninjaErr =" << ninjaErr;
+ return false;
+ }
+
+ ninjaErr = NinjaSetPDFResolution(ninjaArmy, i, ui->geospatialPDFFilesMeshResolutionSpinBox->value(), ui->geospatialPDFFilesMeshResolutionComboBox->itemData(ui->geospatialPDFFilesMeshResolutionComboBox->currentIndex()).toString().toUtf8().constData(), papszOptions);
+ //ninjaErr = NinjaSetPDFResolution(ninjaArmy, i+10, ui->geospatialPDFFilesMeshResolutionSpinBox->value(), ui->geospatialPDFFilesMeshResolutionComboBox->itemData(ui->geospatialPDFFilesMeshResolutionComboBox->currentIndex()).toString().toUtf8().constData(), papszOptions); // test error handling // hrm, ninjaCom isn't triggering for this one, though the error returns, leading to it hanging without a proper message.
+ //ninjaErr = NinjaSetPDFResolution(ninjaArmy, i, ui->geospatialPDFFilesMeshResolutionSpinBox->value(), "fudge", papszOptions); // test error handling
+ if (ninjaErr != NINJA_SUCCESS)
+ {
+ qDebug() << "NinjaSetPDFResolution: ninjaErr =" << ninjaErr;
+ return false;
+ }
+
+ ninjaErr = NinjaSetVtkOutFlag(ninjaArmy, i, ui->VTKFilesCheckBox->isChecked(), papszOptions);
+ //ninjaErr = NinjaSetVtkOutFlag(ninjaArmy, i+10, ui->VTKFilesCheckBox->isChecked(), papszOptions); // test error handling
+ if (ninjaErr != NINJA_SUCCESS)
+ {
+ qDebug() << "NinjaSetVtkOutFlag: ninjaErr =" << ninjaErr;
+ return false;
+ }
+
+ if(ui->rawWeatherModelOutputCheckBox->isCheckable() && ui->rawWeatherModelOutputCheckBox->isChecked())
+ {
+ ninjaErr = NinjaSetWxModelGoogOutFlag(ninjaArmy, i, ui->googleEarthCheckBox->isChecked(), papszOptions);
+ if (ninjaErr != NINJA_SUCCESS)
+ {
+ qDebug() << "NinjaSetWxModelGoogOutFlag: ninjaErr =" << ninjaErr;
+ return false;
+ }
+
+ ninjaErr = NinjaSetWxModelShpOutFlag(ninjaArmy, i, ui->shapeFilesGroupBox->isChecked(), papszOptions);
+ if (ninjaErr != NINJA_SUCCESS)
+ {
+ qDebug() << "NinjaSetWxModelShpOutFlag: ninjaErr =" << ninjaErr;
+ return false;
+ }
+
+ ninjaErr = NinjaSetWxModelAsciiOutFlag(ninjaArmy, i, ui->fireBehaviorGroupBox->isChecked(), papszOptions);
+ if (ninjaErr != NINJA_SUCCESS)
+ {
+ qDebug() << "NinjaSetWxModelAsciiOutFlag: ninjaErr =" << ninjaErr;
+ return false;
+ }
+ }
+
+ return true;
+}
+
+int MainWindow::startSolve(int numProcessors)
+{
+ char **papszOptions = nullptr;
+ return NinjaStartRuns(ninjaArmy, ui->numberOfProcessorsSpinBox->value(), papszOptions);
+}
+
+void MainWindow::finishedSolve()
+{
+ // get the return value of the QtConcurrent::run() function
+ int result = futureWatcher->future().result();
+
+ // ninjaCom handles most of the progress dialog, cli, and console window messaging now
+ if( result == 1 ) // simulation properly finished
+ {
+ progressDialog->setValue(maxProgress);
+ progressDialog->setLabelText("Simulations finished");
+ progressDialog->setCancelButtonText("Close");
+
+ qDebug() << "Finished with simulations";
+ writeToConsole("Finished with simulations", Qt::darkGreen);
+ }
+ //else if( result == NINJA_E_CANCELLED ) // the proper way to do this, but checking progressDialog->wasCanceled() seems way safer
+ else if( progressDialog->wasCanceled() ) // simulation was cancelled
+ {
+ progressDialog->setValue(maxProgress);
+ progressDialog->setCancelButtonText("Close");
+ }
+ else // simulation ended in some known error
+ {
+ progressDialog->setValue(maxProgress);
+ progressDialog->setCancelButtonText("Close");
+ }
+
+ disconnect(progressDialog, SIGNAL(canceled()), this, SLOT(cancelSolve()));
+
+ // one more process to do after finishedSolve() stuff
+ plotKmzOutputs();
+
+ char **papszOptions = nullptr;
+ int ninjaErr = NinjaDestroyArmy(ninjaArmy, papszOptions);
+ if(ninjaErr != NINJA_SUCCESS)
+ {
+ printf("NinjaDestroyRuns: ninjaErr = %d\n", ninjaErr);
+ }
+
+ // clear the progress values for the next set of runs
+ runProgress.clear();
+
+ futureWatcher->deleteLater();
+}
+
+void MainWindow::plotKmzOutputs()
+{
+ // get the return value of the QtConcurrent::run() function
+ int result = futureWatcher->future().result();
+
+ if(result == 1 && !progressDialog->wasCanceled() && ui->googleEarthCheckBox->isChecked() == true)
+ {
+ // enable QWebInspector for degugging the google maps widget
+ if(CSLTestBoolean(CPLGetConfigOption("ENABLE_QWEBINSPECTOR", "NO")))
+ {
+ QWidget* inspectorWindow = new QWidget(this);
+ inspectorWindow->setWindowTitle("Web Inspector - Developer Tools");
+ inspectorWindow->setMinimumSize(800, 600);
+
+ QWebEngineView* inspectorView = new QWebEngineView(inspectorWindow);
+ inspectorView->page()->setInspectedPage(webEngineView->page());
+
+ QVBoxLayout* layout = new QVBoxLayout(inspectorWindow);
+ layout->addWidget(inspectorView);
+ layout->setContentsMargins(0, 0, 0, 0);
+
+ inspectorWindow->show();
+ }
+
+ // vars to be filled
+ int numRuns = 0;
+ char **kmzFilenames = NULL;
+ int numStationKmls = 0;
+ char **stationKmlFilenames = NULL;
+ char **weatherModelKmzFilenames = NULL;
+
+ char **papszOptions = nullptr;
+ ninjaErr = NinjaGetRunKmzFilenames(ninjaArmy, &numRuns, &kmzFilenames, &numStationKmls, &stationKmlFilenames, &weatherModelKmzFilenames, papszOptions);
+ if(ninjaErr != NINJA_SUCCESS)
+ {
+ printf("NinjaGetRunKmzFilenames: ninjaErr = %d\n", ninjaErr);
+ }
+
+ std::vector kmzFilenamesStr;
+ std::vector stationKmlFilenamesStr;
+ std::vector wxModelKmzFilenamesStr;
+
+ kmzFilenamesStr.reserve(numRuns);
+ wxModelKmzFilenamesStr.reserve(numRuns);
+ for(int i = 0; i < numRuns; i++)
+ {
+ kmzFilenamesStr.emplace_back(kmzFilenames[i]);
+ wxModelKmzFilenamesStr.emplace_back(weatherModelKmzFilenames[i]);
+ }
+
+ stationKmlFilenamesStr.reserve(numStationKmls);
+ for(int j = 0; j < numStationKmls; j++)
+ {
+ stationKmlFilenamesStr.emplace_back(stationKmlFilenames[j]);
+ }
+
+ outputKmzFilenames.push_back(std::move( kmzFilenamesStr ));
+ outputStationKmlFilenames.push_back(std::move( stationKmlFilenamesStr ));
+ outputWxModelKmzFilenames.push_back(std::move( wxModelKmzFilenamesStr ));
+
+ for(int i = 0; i < numRuns; i++)
+ {
+ // plot the output kmz of the run
+ QString outFileStr = QString::fromStdString(kmzFilenames[i]);
+ qDebug() << "kmz outFile =" << outFileStr;
+ QFile outFile(outFileStr);
+
+ outFile.open(QIODevice::ReadOnly);
+ QByteArray data = outFile.readAll();
+ QString base64 = data.toBase64();
+
+ bool timeSeries = !ui->domainAverageGroupBox->isChecked();
+
+ webEngineView->page()->runJavaScript(
+ "loadKmzFromBase64('"+base64+"', "+(timeSeries ? "true" : "false")+");"
+ );
+
+ // if it is a point initialization run, and station kmls were created for the run,
+ // plot the station kmls of the first run
+ // (first run, because station kmls are SHARED across runs)
+ // if(ui->pointInitializationGroupBox->isChecked() && ui->pointInitializationWriteStationKMLCheckBox->isChecked() && i == 0)
+ // {
+ // for(int j = 0; j < numStationKmls; j++)
+ // {
+ // QString outFileStr = QString::fromStdString(stationKmlFilenames[j]);
+ // qDebug() << "station kml outFile =" << outFileStr;
+ // QFile outFile(outFileStr);
+
+ // outFile.open(QIODevice::ReadOnly);
+ // QByteArray data = outFile.readAll();
+ // QString base64 = data.toBase64();
+
+ // webEngineView->page()->runJavaScript("loadKmzFromBase64('"+base64+"')");
+ // }
+ // }
+
+ // // if it is a weather model run, and weather model kmzs were created for the run,
+ // // plot the weather model kmz of the run
+ if(ui->weatherModelGroupBox->isChecked() && ui->googleEarthCheckBox->isChecked())
+ {
+ QString outFileStr = QString::fromStdString(weatherModelKmzFilenames[i]);
+ qDebug() << "wx model kmz outFile =" << outFileStr;
+ QFile outFile(outFileStr);
+
+ outFile.open(QIODevice::ReadOnly);
+ QByteArray data = outFile.readAll();
+ QString base64 = data.toBase64();
+
+ webEngineView->page()->runJavaScript("loadOutputFromBase64('"+base64+"')");
+ }
+ }
+
+ ninjaErr = NinjaDestroyRunKmzFilenames(numRuns, kmzFilenames, numStationKmls, stationKmlFilenames, weatherModelKmzFilenames, papszOptions);
+ if(ninjaErr != NINJA_SUCCESS)
+ {
+ printf("NinjaDestroyRunKmzFilenames: ninjaErr = %d\n", ninjaErr);
+ }
+
+ } // if(result == 1 && !progressDialog->wasCanceled() && ui->googleEarthCheckBox->isChecked() == true)
+}
+
+void MainWindow::writeSettings()
+{
+ writeToConsole("Saving settings...");
+
+ QSettings settings(QSettings::UserScope, "Firelab", "WindNinja");
+ settings.setDefaultFormat(QSettings::IniFormat);
+ //qDebug() << "settings filename =" << settings.fileName();
+
+ //input file path
+ settings.setValue("inputFileDir", ui->elevationInputFileLineEdit->property("fullpath"));
+
+ //momentum flag
+ settings.setValue("momentumFlag", ui->momentumSolverCheckBox->isChecked());
+ //veg choice
+ settings.setValue("vegChoice", ui->vegetationComboBox->currentIndex());
+ //mesh choice
+ settings.setValue("meshChoice", ui->meshResolutionComboBox->currentIndex());
+ //mesh units
+ settings.setValue("meshUnits", ui->meshResolutionUnitsComboBox->currentIndex());
+ //number of processors
+ settings.setValue("nProcessors", ui->numberOfProcessorsSpinBox->value());
+
+ //time zone
+ //settings.setValue("timeZone", ui->timeZoneComboBox->currentIndex());
+
+ //settings.setValue("pointFile", tree->point->stationFileName );
+
+ //if(ui->meshResolutionComboBox->currentIndex() == 3) // custom res
+ //{
+ // settings.setValue("customRes", ui->meshResolutionSpinBox->value());
+ //}
+ // need to write it every time, the past value will get left there without getting updated otherwise, doesn't delete past settings values
+ settings.setValue("customRes", ui->meshResolutionSpinBox->value());
+
+ writeToConsole("Settings saved.");
+}
+
+void MainWindow::readSettings()
+{
+ QSettings settings(QSettings::UserScope, "Firelab", "WindNinja");
+ settings.setDefaultFormat(QSettings::IniFormat);
+
+ if(settings.contains("inputFileDir"))
+ {
+ if(QFile::exists(settings.value("inputFileDir").toString()))
+ {
+ ui->elevationInputFileLineEdit->setText(settings.value("inputFileDir").toString());
+ }
+ }
+ else
+ {
+ // std::string oTmpPath = FindNinjaRootDir();
+ // inputFileDir = CPLFormFilename(oTmpPath.c_str(), "etc/windninja/example-files", NULL);
+ }
+
+ // TODO: some of the following might be overriding the values computed by inputFileDir, when the other way around might be better
+ if(settings.contains("momentumFlag"))
+ {
+ bool momentumFlag = settings.value("momentumFlag").toBool();
+ if(momentumFlag == true)
+ {
+ ui->momentumSolverCheckBox->setChecked(true);
+ emit momentumSolverCheckBoxClicked();
+ }
+ }
+ if(settings.contains("vegChoice"))
+ {
+ ui->vegetationComboBox->setCurrentIndex(settings.value("vegChoice").toInt());
+ }
+ if(settings.contains("meshUnits")) // putting this after loading meshChoice results in overwriting the value by an extra set of units
+ {
+ ui->meshResolutionUnitsComboBox->setCurrentIndex(settings.value("meshUnits").toInt());
+ }
+ if(settings.contains("meshChoice"))
+ {
+ int choice = settings.value("meshChoice").toInt();
+ ui->meshResolutionComboBox->setCurrentIndex(choice);
+ if(choice == 3)
+ {
+ if(!settings.contains("customRes"))
+ {
+ qDebug() << "Error. WindNinja settings does not contain \"customRes\"";
+ }
+ ui->meshResolutionSpinBox->setValue(settings.value("customRes").toDouble());
+ }
+ }
+ if(settings.contains("nProcessors"))
+ {
+ ui->numberOfProcessorsSpinBox->setValue(settings.value("nProcessors").toInt());
+ }
+ // won't we want the timezone of the dem every time, to avoid accidentally doing a weird combination of time zones?
+ if(settings.contains("timeZone"))
+ {
+ // QString v = settings.value("timeZone").toString();
+ // int index = tree->surface->timeZone->tzComboBox->findText(v);
+ // if(index == -1)
+ // tree->surface->timeZone->tzCheckBox->setChecked( true );
+ // index = tree->surface->timeZone->tzComboBox->findText(v);
+ // if( index == 0 )
+ // tree->surface->timeZone->tzComboBox->setCurrentIndex(index + 1);
+ // true->surface->timeZone->tzComboBox->setCurrentIndex(index);
+ }
+ else
+ {
+ // tree->surface->timeZone->tzComboBox->setCurrentIndex(2);
+ // tree->surface->timeZone->tzComboBox->setCurrentIndex(1);
+ }
+ if(settings.contains("pointFile"))
+ {
+ // QString f = settings.value("pointFile").toString();
+ // tree->point->stationFileName = f;
+ }
+}
+
+void MainWindow::showEvent(QShowEvent *event)
+{
+ QMainWindow::showEvent(event);
+
+}
+
+void MainWindow::closeEvent(QCloseEvent *event)
+{
+ writeSettings();
+ QMainWindow::closeEvent(event);
+}
diff --git a/src/gui/qt6/mainWindow.h b/src/gui/qt6/mainWindow.h
new file mode 100644
index 000000000..a7cd74518
--- /dev/null
+++ b/src/gui/qt6/mainWindow.h
@@ -0,0 +1,166 @@
+/******************************************************************************
+ *
+ * $Id$
+ *
+ * Project: WindNinja Qt GUI
+ * Purpose: Main Window that handles GUI scraping and state changes
+ * Author: Mason Willman
+ *
+ ******************************************************************************
+ *
+ * THIS SOFTWARE WAS DEVELOPED AT THE ROCKY MOUNTAIN RESEARCH STATION (RMRS)
+ * MISSOULA FIRE SCIENCES LABORATORY BY EMPLOYEES OF THE FEDERAL GOVERNMENT
+ * IN THE COURSE OF THEIR OFFICIAL DUTIES. PURSUANT TO TITLE 17 SECTION 105
+ * OF THE UNITED STATES CODE, THIS SOFTWARE IS NOT SUBJECT TO COPYRIGHT
+ * PROTECTION AND IS IN THE PUBLIC DOMAIN. RMRS MISSOULA FIRE SCIENCES
+ * LABORATORY ASSUMES NO RESPONSIBILITY WHATSOEVER FOR ITS USE BY OTHER
+ * PARTIES, AND MAKES NO GUARANTEES, EXPRESSED OR IMPLIED, ABOUT ITS QUALITY,
+ * RELIABILITY, OR ANY OTHER CHARACTERISTIC.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ *****************************************************************************/
+
+#ifndef MAINWINDOW_H
+#define MAINWINDOW_H
+
+#include "outputs.h"
+#include "surfaceInput.h"
+#include "menuBar.h"
+#include "domainAverageInput.h"
+#include "pointInitializationInput.h"
+#include "mapBridge.h"
+#include "serverBridge.h"
+#include "weatherModelInput.h"
+#include "ui_mainWindow.h"
+#include "appState.h"
+#include "windninja.h"
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include