Complete Qt6 migration: full clean build green across groups G1-G12 incl. runtime plugin set

new_docker_build.sh gains Group 12 (212 GUI/Data plugins); fixes LtsUtilsGuiDds visibility (LTO-stripped exports), LtsProjectionWorkstation unity name shadow, 6 unity-off dirs (dup file-scope statics, ddsftc INTERFACE sources) and reconfigures BUILD_FILTERMANAGEMENT/BUILD_PLUGINS_SERVICEMONITOR=ON
This commit is contained in:
berrux-dev committed 2026-10-20 09:36:57 +02:00
1 parent 2b957d1edb
commit 598fc2560e
1718 files changed
+126739 -18495

No files matched your search

@@ -0,0 +1,15 @@
#
# @RDE_HEADER@
# Small hack to provide the missing smybol to 'typeinfo for std::bad_array_new_length@Qt_5'
# $Id$
# $HeadURL$
# $Author$
#
IF(UNIX)
NGL_ADD_LIBRARY(WS SV AAR ArcGISQt5Hack SHARED arcgisqt5hack.cpp arcgisqt5hack.version) # SV,AAR for CES - expand polygon
NGL_TARGET_LINK_LIBRARIES(ArcGISQt5Hack PRIVATE "-Wl,--version-script,${CMAKE_CURRENT_SOURCE_DIR}/arcgisqt5hack.version")
ELSE()
NGL_ADD_LIBRARY(WS SV AAR ArcGISQt5Hack STATIC arcgisqt5hack.cpp) # SV,AAR for CES - expand polygon
ENDIF()
NGL_INSTALL_TARGET(ArcGISQt5Hack)
@@ -0,0 +1,21 @@
/**
* @RDE_HEADER@
* Small hack to provide the missing smybol to 'typeinfo for std::bad_array_new_length@Qt_5'
* $Id$
* $HeadURL$
* $Author$
*/
#ifdef WIN32
__declspec(dllexport) int foo42(int) { return 42;} // just a dummy to get windows build running
#else
#include <new>
extern "C++"
{
__attribute__((visibility("default"))) void operator delete(void* ptr, std::size_t) noexcept
{
::operator delete(ptr);
}
}
#endif
@@ -0,0 +1,3 @@
Qt_5 {
*;
};
@@ -1,36 +1,556 @@
#
# $Id$
# $HeadURL$
# $Author$
#
# Minimal CMakeLists.txt for Qt6 migration - only Symbology subdirectory
# Full migration pending
# Qt6 + ArcGIS 300 migration.
#
# The full situationMap map-layer target is restored here from the legacy
# CMakeLists (Map / MapImpl / MapObjects / GraphicalObjects / LayerAggregation
# / Rubberbands / Utils / MathUtils source groups), adapted Qt5->Qt6 and gated
# on BUILD_ARCGIS to match the migrated Symbology convention: the top-level
# CMakeLists does FIND_PACKAGE(ArcGIS REQUIRED) under IF(BUILD_ARCGIS), so
# ArcGIS::ArcGIS only exists there. The subdir targets that are themselves
# ArcGIS-dependent (MapObjectsImpl / FunctionDialog / Portal / SymbologyGui)
# gate their own library on BUILD_ARCGIS; the non-ArcGIS subdirs (Common,
# ElevationMap, Symbology, SymbologyXML, ArcGISQt5Hack, SideBar, GeometryModel)
# build unconditionally.
#
# The unit-test subdirs (Tests / EvalApps / UnitTests / UnitTestsGeoModel /
# ModuleTests) and the test-only situationMap_static variant are intentionally
# not restored: they are not linked by the app and are not needed for the
# Situation view to load.
# Only migrate Symbology for now
# During development: (instead top CMakeLists.txt"
IF(NOT MSVC)
SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wextra")
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wextra")
ENDIF()
OPTION(BUILD_SITMAP_UNIT_TESTS "Build situation map unit tests" ON)
SET(GraphicalObjects_SRCS
GraphicalObjects/abstract_graphical_object.cpp
GraphicalObjects/ellipse_parameters.cpp
GraphicalObjects/graphical_object_attributes.h
GraphicalObjects/graphical_object_attributes.cpp
GraphicalObjects/graphical_object_ellipse.cpp
GraphicalObjects/graphical_object_multi_path.cpp
GraphicalObjects/graphical_object_path.cpp
GraphicalObjects/graphical_object_picture_marker.cpp
GraphicalObjects/graphical_object_range.cpp
GraphicalObjects/graphical_object_text.cpp
GraphicalObjects/tactical_appearance.cpp
GraphicalObjects/graphical_object_cube.cpp
GraphicalObjects/graphical_object_scene_marker.cpp
GraphicalObjects/graphical_object_model_scene_marker.cpp
GraphicalObjects/graphical_object_renderer_attributes.cpp
)
SET(GraphicalObjects_HDRS
GraphicalObjects/abstract_graphical_object.h
GraphicalObjects/ellipse_parameters.h
GraphicalObjects/graphical_object_ellipse.h
GraphicalObjects/graphical_object_multi_path.h
GraphicalObjects/graphical_object_picture_marker.h
GraphicalObjects/graphical_object_path.h
GraphicalObjects/graphical_object_range.h
GraphicalObjects/graphical_object_text.h
GraphicalObjects/stub_graphical_object.h
GraphicalObjects/tactical_appearance.h
GraphicalObjects/graphical_object_cube.h
GraphicalObjects/graphical_object_scene_marker.h
GraphicalObjects/graphical_object_model_scene_marker.h
GraphicalObjects/graphical_object_renderer_attributes.cpp
)
QT6_ADD_RESOURCES(GraphicalObjects_SRCS Resources/situation_map.qrc)
SET(Map_SRCS
Map/bounding_box.cpp
Map/fill_style.cpp
Map/line_style.cpp
Map/map.cpp
Map/map_notifier.cpp
Map/map_settings.cpp
Map/map_initializer.cpp
Map/object_container.cpp
Map/object_factory.cpp
Map/operator_map_settings.cpp
# Map/point3D.cpp
Map/party_id_to_color_functor.cpp
# Map/scene_marker_data.cpp
Map/situation_map_utils.cpp
Map/terrain_profile_parameter.cpp
Map/text_style.cpp
Map/geometry_model_renderer.cpp
Map/viewshed_parameter.cpp
)
SET(Map_HDRS
Map/situation_map_ahtc.ini
Map/situation_map_defaults.ini
Map/situation_map_guez.ini
Map/situation_map_qatar.ini
Map/situation_map_guez_tablet.ini
Map/situation_map_ahtc_tablet.ini
Map/abstract_effect_simulation.h
Map/abstract_map_object.h
Map/bounding_box.h
Map/camera.h
Map/camera.cpp
Map/coord_translation_functor.h
# Map/drop_event_manager.h
Map/fill_style.h
Map/generic_object_factory.h
Map/grid.h
Map/map.h
Map/map_notifier.h
Map/map_settings.h
Map/map_initializer.h
Map/measurement.h
Map/layer_factory.h
Map/layer_parameter.h
Map/layer_parameter.cpp
Map/location_display.h
Map/line_style.h
Map/object_container.h
Map/object_factory.h
Map/object_indicator.h
Map/operator_map_settings.h
Map/overview_map_handler.h
Map/party_id_to_color_functor.h
Map/pixel_based_textbox_handler.h
Map/point3D.h
# Map/scene_marker_data.cpp
Map/sidc_symbol.h
Map/sight_fan.h
Map/situation_map_utils.h
Map/situation_map_types.h
Map/terrain_profile_parameter.h
Map/terrain_profile.h
Map/text_style.h
Map/viewpoint2D.h
Map/viewpoint2D.cpp
Map/viewshed_parameter.h
Map/viewshed.h
Map/camera.h
Map/camera.cpp
Map/overlay_handler.h
Map/geometry_model_renderer.h
)
SET(MapImpl_SRCS
MapImpl/abstract_effect_simulation_impl.cpp
MapImpl/abstract_effect_simulation_impl.h
MapImpl/abstract_map_object_impl.cpp
MapImpl/abstract_map_object_impl.h
MapImpl/coordinate_translation.cpp
MapImpl/coordinate_translation_thread.cpp
MapImpl/grid_impl.cpp
MapImpl/jump_point_model.cpp
MapImpl/jump_point_custom_view.cpp
MapImpl/jump_point_widget.cpp
MapImpl/logical_layer.cpp
MapImpl/layer_factory_impl.cpp
MapImpl/layer_control_widget.cpp
MapImpl/screen_location_elevation_helper_base.cpp
MapImpl/location_display_impl.cpp
MapImpl/location_to_elevation_helper.cpp
MapImpl/location_to_elevation_bulk.cpp
MapImpl/map_impl.cpp
MapImpl/map_layer.cpp
MapImpl/measurement_impl.cpp
MapImpl/object_container_impl.cpp
MapImpl/object_indicator_impl.cpp
MapImpl/overview_map_handler_impl.cpp
MapImpl/pixel_based_textbox_handler_impl.cpp
MapImpl/screen_to_location_helper.cpp
MapImpl/sidc_symbol_impl.cpp
MapImpl/sight_fan_impl.cpp
MapImpl/terrain_profile_impl.cpp
MapImpl/terrain_profile_processor.cpp
# MapImpl/tms_layer.cpp
MapImpl/viewshed_base.cpp
MapImpl/viewshed_analysis.cpp
MapImpl/viewshed_geo_processing.cpp
MapImpl/viewshed_base.cpp
MapImpl/viewshed_impl.cpp
MapImpl/jump_point_namer.cpp
MapImpl/geometry_model_renderer_esri.cpp
MapImpl/overlay_handler_impl.cpp
)
SET(MapImpl_HDRS
MapImpl/abstract_effect_simulation_impl.h
MapImpl/abstract_map_object_impl.h
MapImpl/coordinate_translation.h
MapImpl/coordinate_translation_thread.h
MapImpl/coord_translation_functor_impl.h
MapImpl/geometry_model_renderer_esri.h
MapImpl/grid_impl.cpp
MapImpl/grid_impl.h
MapImpl/jump_point_model.h
MapImpl/jump_point_custom_view.h
MapImpl/jump_point_widget.h
MapImpl/logical_layer.h
MapImpl/layer_control_widget.h
MapImpl/layer_factory_impl.h
MapImpl/screen_location_elevation_helper_base.h
MapImpl/location_display_impl.h
MapImpl/location_to_elevation_helper.h
MapImpl/location_to_elevation_bulk.h
MapImpl/map_impl.h
MapImpl/map_layer.h
MapImpl/measurement_impl.h
MapImpl/object_container_impl.h
MapImpl/object_indicator_impl.h
MapImpl/overview_map_handler_impl.h
MapImpl/overlay_handler_impl.h
MapImpl/pixel_based_textbox_handler_impl.h
MapImpl/screen_to_location_helper.h
MapImpl/sidc_symbol_impl.h
MapImpl/sight_fan_impl.h
MapImpl/terrain_profile_impl.h
MapImpl/terrain_profile_processor.h
# MapImpl/tms_layer.h
MapImpl/viewshed_base.h
MapImpl/viewshed_analysis.h
MapImpl/viewshed_geo_processing.h
MapImpl/viewshed_impl.h
MapImpl/jump_point_namer.h
)
SET(MapObj_SRCS
MapObjects/geometry.cpp
)
SET(MapObj_HDRS
MapObjects/abstract_multi_point_map_object.h
MapObjects/abstract_single_point_map_object.h
MapObjects/air_support.h
MapObjects/area_fire.h
MapObjects/biological_agent.h
MapObjects/building_outline.h
MapObjects/chemical_agent.h
MapObjects/cube.h
MapObjects/danger_area.h
MapObjects/functional_area.h
MapObjects/geo_image.h
MapObjects/geometry.h
MapObjects/hit_line.h
MapObjects/line_of_sight.h
MapObjects/map_object_attributes.h
MapObjects/map_object_indicator.h
MapObjects/mine.h
MapObjects/mine_field.h
MapObjects/nuclear_agent.h
MapObjects/participant.h
MapObjects/polygon.h
MapObjects/polyline.h
MapObjects/single_fire.h
# MapObjects/single_fire_central.h
MapObjects/sound_area.h
MapObjects/text.h
MapObjects/virtual_mine.h
#situation_map_objects_export.h
)
SET (LayerAggregation_SRCS
LayerAggregation/layer_aggregation_widget.cpp
LayerAggregation/participant_aggregation_dialog.cpp
)
SET (LayerAggregation_HDRS
LayerAggregation/layer_aggregation_widget.h
LayerAggregation/participant_aggregation_dialog.h
)
SET(Rubberbands_SRCS
Rubberbands/abstract_event_dispatcher.cpp
Rubberbands/drawable_ellipse.cpp
Rubberbands/drawable_line.cpp
Rubberbands/drawable_painter_path.cpp
Rubberbands/drawable_smooth_path.cpp
Rubberbands/event_delegater.cpp
Rubberbands/event_dispatcher.cpp
Rubberbands/event_mouse_navigator.cpp
Rubberbands/gestures.cpp
Rubberbands/rubberband_base.cpp
Rubberbands/rubberband.cpp
Rubberbands/rubberband_3d.cpp
Rubberbands/rubberband_arrow.cpp
Rubberbands/rubberband_corridor.cpp
Rubberbands/rubberband_drawable.cpp
Rubberbands/rubberband_factory.cpp
Rubberbands/rubberband_frame_handle.cpp
Rubberbands/rubberband_free_hand.cpp
Rubberbands/rubberband_ellipse.cpp
Rubberbands/rubberband_ellipse_handle.cpp
Rubberbands/rubberband_handle.cpp
Rubberbands/rubberband_handle_proxy.cpp
Rubberbands/rubberband_internal.cpp
Rubberbands/rubberband_line_handle.cpp
Rubberbands/rubberband_multi_point_feature.cpp
Rubberbands/rubberband_multi_ellipse_feature.cpp
Rubberbands/rubberband_multi_point_feature_3d.cpp
Rubberbands/rubberband_point_handle.cpp
Rubberbands/rubberband_point_cluster.cpp
Rubberbands/rubberband_point_feature.cpp
Rubberbands/rubberband_point_feature_3d.cpp
Rubberbands/rubberband_polyline_width.cpp
Rubberbands/rubberband_rectangle.cpp
Rubberbands/rubberband_smooth_line.cpp
Rubberbands/rubberband_state_select.cpp
Rubberbands/rubberband_transform.cpp
Rubberbands/rubberband_transform_move.cpp
Rubberbands/rubberband_transform_rotate.cpp
Rubberbands/rubberband_transform_scale.cpp
Rubberbands/transient_tactical_symbol.cpp
)
SET(Rubberbands_HDRS
Rubberbands/abstract_event_dispatcher.h
Rubberbands/drawable_ellipse.h
Rubberbands/drawable_line.h
Rubberbands/drawable_painter_path.h
Rubberbands/drawable_smooth_path.h
Rubberbands/event_delegater.h
Rubberbands/event_dispatcher.h
Rubberbands/event_mouse_navigator.h
Rubberbands/gestures.h
Rubberbands/rubberband_free_hand.h
Rubberbands/rubberband_base.h
Rubberbands/rubberband_base_internal.h
Rubberbands/rubberband.h
Rubberbands/rubberband_3d.h
Rubberbands/rubberband_arrow.h
Rubberbands/rubberband_corridor.h
Rubberbands/rubberband_drawable.h
Rubberbands/rubberband_ellipse.h
Rubberbands/rubberband_ellipse_handle.h
Rubberbands/rubberband_factory.h
Rubberbands/rubberband_frame_handle.h
Rubberbands/rubberband_handle.h
Rubberbands/rubberband_handle_proxy.h
Rubberbands/rubberband_internal.h
Rubberbands/rubberband_line_handle.h
Rubberbands/rubberband_multi_point_feature.h
Rubberbands/rubberband_multi_ellipse_feature.h
Rubberbands/rubberband_multi_point_feature_3d.h
Rubberbands/rubberband_point_cluster.h
Rubberbands/rubberband_point_feature.h
Rubberbands/rubberband_point_feature_3d.h
Rubberbands/rubberband_point_handle.h
Rubberbands/rubberband_polyline_width.h
Rubberbands/rubberband_rectangle.h
Rubberbands/rubberband_smooth_line.h
Rubberbands/rubberband_state_select.h
Rubberbands/rubberband_transform.h
Rubberbands/rubberband_transform_move.h
Rubberbands/rubberband_transform_rotate.h
Rubberbands/rubberband_transform_scale.h
Rubberbands/transient_tactical_symbol.h
)
SET(Utils_SRCS
situation_map_export.h
Utils/movement_track.cpp
Utils/movement_track_manager.cpp
Utils/terrain_profile_dialog.cpp
)
SET(Utils_HDRS
Utils/movement_track.h
Utils/movement_track_manager.h
Utils/terrain_profile_dialog.h
)
SET(MathUtils_SRCS
MathUtils/clipper.cpp
MathUtils/curve.cpp
MathUtils/geometry_engine.cpp
MathUtils/matrix2d.cpp
MathUtils/path_rasterer.cpp
MathUtils/simple_helper.cpp
)
SET(MathUtils_HDRS
MathUtils/clipper.hpp
MathUtils/curve.h
MathUtils/geometry_engine.h
MathUtils/matrix2d.h
MathUtils/math_const.h
MathUtils/path_rasterer.h
MathUtils/simple_helper.h
)
NGL_WRAP_UI(Utils_HDRS
MapImpl/jump_point_custom_view.ui
Utils/terrain_profile_dialog.ui
)
NGL_WRAP_UI(MapImpl_SRCS
MapImpl/jump_point_namer.ui
)
SOURCE_GROUP(GraphicalObjects FILES ${GraphicalObjects_SRCS} ${GraphicalObjects_HDRS})
SOURCE_GROUP(Map FILES ${Map_SRCS} ${Map_HDRS} ${MapImpl_SRCS} ${MapImpl_HDRS})
SOURCE_GROUP(MapObjects FILES ${MapObj_HDRS})
SOURCE_GROUP(LayerAggregation FILES ${LayerAggregation_SRCS} ${LayerAggregation_HDRS})
SOURCE_GROUP(Rubberband FILES ${Rubberbands_SRCS} ${Rubberbands_HDRS})
SOURCE_GROUP(Utils FILES ${Utils_SRCS} ${Utils_HDRS})
SOURCE_GROUP(MathUtils FILES ${MathUtils_SRCS} ${MathUtils_HDRS})
SOURCE_GROUP(SideBar FILES ${SideBar_SRCS} ${SideBar_HDRS})
IF(BUILD_ARCGIS)
NGL_ADD_LIBRARY(WS situationMap SHARED
# ${FunctionDialog_SRCS}
${Map_SRCS} ${Map_HDRS} ${MapImpl_SRCS}
${MapObj_SRCS} ${MapObj_HDRS}
${GraphicalObjects_SRCS} ${GraphicalObjects_HDRS}
${LayerAggregation_SRCS} ${LayerAggregation_HDRS}
${Rubberbands_SRCS}
${Utils_SRCS} ${Utils_HDRS}
${MathUtils_SRCS} ${MathUtils_HDRS}
)
NGL_TARGET_INCLUDE_DIRECTORIES(situationMap
PUBLIC
${CMAKE_CURRENT_SOURCE_DIR}/..
)
NGL_TARGET_LINK_LIBRARIES(situationMap
PRIVATE
NGLLogger
ArcGIS::ArcGIS
Qt6::Concurrent
Qt6::Network
Qt6::PrintSupport
Qt6::OpenGL # Qt6: ArcGIS SDK MapGraphicsView/SceneGraphicsView use QOpenGLPaintDevice
Qt6::OpenGLWidgets # Qt6: ArcGIS SDK uses QOpenGLWidget (separate lib in Qt6)
LtsCoordTrans
ArcGISQt5Hack
PUBLIC
Qt6::Core
Qt6::Widgets
LtsUtilsCoreHeaderOnly # QPoint3D
LtsWidgets
LtsDataView
situationMapCommon
situationMapElevationMap
situationMapSideBar
advancedSymbology
situationMapGeometryModel
ngltools
)
# Copy on LIBchanges:
IF(TARGET situationMap)
SET(SYMBOLE_CSV symbole2.csv)
ADD_CUSTOM_COMMAND(TARGET situationMap POST_BUILD
COMMAND ${CMAKE_COMMAND}
ARGS -E copy_if_different ${CMAKE_CURRENT_SOURCE_DIR}/FunctionDialog/${SYMBOLE_CSV} $<TARGET_FILE_DIR:situationMap>/${SYMBOLE_CSV}
)
# copy ini to build-dir/share/Lts/situation_map/:
SET(INI_DEST_DIR ${CMAKE_BINARY_DIR}/share/Lts/situation_map)
SET(SITUATIONMAPSETTINGS_INI situation_map_defaults.ini)
SET(SITUATIONMAPSETTINGS_INI_PATH Map/${SITUATIONMAPSETTINGS_INI})
ADD_CUSTOM_COMMAND(TARGET situationMap POST_BUILD
COMMAND ${CMAKE_COMMAND}
ARGS -E copy_if_different ${CMAKE_CURRENT_SOURCE_DIR}/${SITUATIONMAPSETTINGS_INI_PATH} ${INI_DEST_DIR}/${SITUATIONMAPSETTINGS_INI}
)
SET(SITUATIONMAPSETTINGS_INI situation_map_defaults.ini)
SET(SITUATIONMAPSETTINGS_INI_PATH Map/${SITUATIONMAPSETTINGS_INI})
#check if we need to change it
IF(BUILD_RPM AND DEFINED _pname)
IF(UNIX AND "${_pname}" STREQUAL "guez")
MESSAGE("Install situationmap ini for GUEZ")
SET(SITUATIONMAPSETTINGS_INI_PATH Map/situation_map_guez.ini)
SET(TABLET_SITUATIONMAPSETTINGS_INI_PATH Map/situation_map_guez_tablet.ini)
ElseIF(UNIX AND "${_pname}" STREQUAL "ahtc")
MESSAGE("Install situationmap ini for AHTC")
SET(SITUATIONMAPSETTINGS_INI_PATH Map/situation_map_ahtc.ini)
SET(TABLET_SITUATIONMAPSETTINGS_INI_PATH Map/situation_map_ahtc_tablet.ini)
ElseIF(UNIX AND "${_pname}" STREQUAL "l400p2")
MESSAGE("Install situationmap ini for L400P2")
SET(SITUATIONMAPSETTINGS_INI_PATH Map/situation_map_land400.ini)
SET(TABLET_SITUATIONMAPSETTINGS_INI_PATH Map/situation_map_l400p2_tablet.ini)
ElseIF(UNIX AND "${_pname}" STREQUAL "qatar")
MESSAGE("Install situationmap ini for Qatar")
SET(SITUATIONMAPSETTINGS_INI_PATH Map/situation_map_qatar.ini)
SET(TABLET_SITUATIONMAPSETTINGS_INI_PATH Map/situation_map_qatar_tablet.ini)
ElseIF(UNIX AND "${_pname}" STREQUAL "qatarmout")
MESSAGE("Install situationmap ini for Qatar Mout")
SET(SITUATIONMAPSETTINGS_INI_PATH Map/situation_map_qatarmout.ini)
SET(TABLET_SITUATIONMAPSETTINGS_INI_PATH Map/situation_map_qatar_tablet.ini)
ElseIF(UNIX AND "${_pname}" STREQUAL "commaster")
MESSAGE("Install situationmap ini for ComMaster/Luxemburg")
SET(SITUATIONMAPSETTINGS_INI_PATH Map/situation_map_luxemburg.ini)
SET(TABLET_SITUATIONMAPSETTINGS_INI_PATH Map/situation_map_luxemburg_tablet.ini)
ENDIF()
ENDIF()
#now that we set the situation map ini if neccecsary we install it depending of the tablet build or not
IF(TABLET_MODE)
NGL_INSTALL(WS FILES ${TABLET_SITUATIONMAPSETTINGS_INI_PATH} DESTINATION "./share/Lts/situation_map" RENAME ${SITUATIONMAPSETTINGS_INI})
ELSE()
NGL_INSTALL(WS FILES ${SITUATIONMAPSETTINGS_INI_PATH} DESTINATION "./share/Lts/situation_map" RENAME ${SITUATIONMAPSETTINGS_INI})
ENDIF()
ENDIF()
NGL_INSTALL_TARGET(situationMap)
ENDIF() # BUILD_ARCGIS
# Choose logical order instead of alphabetical.
# UnitTest should be performed BEFORE ModuleTest
ADD_SUBDIRECTORY(ArcGISQt5Hack)
ADD_SUBDIRECTORY(Common)
ADD_SUBDIRECTORY(SymbologyXML)
ADD_SUBDIRECTORY(Symbology)
# ElevationMapManager compatibility stub (src/ + include/ scaffolding) needed by LtsElevation
ADD_SUBDIRECTORY(ElevationMap)
ADD_SUBDIRECTORY(Symbology)
ADD_SUBDIRECTORY(SymbologyGui)
ADD_SUBDIRECTORY(SymbologyXML)
ADD_SUBDIRECTORY(MapObjectsImpl)
#ADD_SUBDIRECTORY(LocalSrv)
# Remaining subdirectories not yet migrated:
# ADD_SUBDIRECTORY(SymbologyGui)
# ADD_SUBDIRECTORY(SymbologyXML)
# ADD_SUBDIRECTORY(MapObjectsImpl)
# ADD_SUBDIRECTORY(SideBar)
# ADD_SUBDIRECTORY(FunctionDialog)
# ADD_SUBDIRECTORY(GeometryModel)
# ADD_SUBDIRECTORY(Portal)
# ADD_SUBDIRECTORY(GraphicalObjects)
# ADD_SUBDIRECTORY(Map)
# ADD_SUBDIRECTORY(MapImpl)
# ADD_SUBDIRECTORY(MapObjects)
# ADD_SUBDIRECTORY(Rubberbands)
# ADD_SUBDIRECTORY(Utils)
# ADD_SUBDIRECTORY(MathUtils)
# ADD_SUBDIRECTORY(LayerAggregation)
# ADD_SUBDIRECTORY(LocalSrv)
# ADD_SUBDIRECTORY(Tests)
# ADD_SUBDIRECTORY(EvalApps)
# ADD_SUBDIRECTORY(UnitTests)
# ADD_SUBDIRECTORY(UnitTestsGeoModel)
# ADD_SUBDIRECTORY(ModuleTests)
ADD_SUBDIRECTORY(SideBar)
ADD_SUBDIRECTORY(FunctionDialog)
ADD_SUBDIRECTORY(GeometryModel)
ADD_SUBDIRECTORY(Portal)
@@ -4,34 +4,41 @@
# $Author$
#
# The GDAL-based ElevationMap module is not yet migrated to Qt6 (see the
# commented-out entries in ../CMakeLists.txt). LtsElevation still needs an
# ElevationMapManager, so build the compatibility stub that lives in the
# src/ + include/ scaffolding (same API as the Qt5 class, no GDAL).
NGL_ADD_LIBRARY(WS AAR HLA SV situationMapElevationMap SHARED
${CMAKE_SOURCE_DIR}/src/Viewer/SituationMap/ElevationMap/elevation_map_manager.cpp
# The header lives in include/Viewer/SituationMap/ElevationMap, apart from
# the cpp. AUTOMOC only mocs headers that are target sources (or sit next
# to one); MOC_INCLUDES merely feeds moc's own -I flags, not header
# discovery. Listed explicitly, otherwise the vtable/staticMetaObject are
# undefined and the link of libsituationMapElevationMap.so fails.
${CMAKE_SOURCE_DIR}/include/Viewer/SituationMap/ElevationMap/elevation_map_manager.h
# ElevationMap module. The legacy module is GDAL-backed; GDAL is not part of the
# Qt6 / ArcGIS-300 toolchain. Per the established no-GDAL decision, elevation_map.cpp
# is a no-GDAL stand-in (public API preserved; no DEM data loaded) while the rest of
# the module (ElevationMapManager, line_of_sight_calculation) is the real, GDAL-free
# Qt code. This lets the SituationMap layer (MapImpl/SightFanImpl/ElevationMapManager)
# compile and link against the elevation API.
SET(Elevation_SRCS
elevation_map.cpp
elevation_map.h
elevation_map_helper.h
elevation_map_manager.cpp
elevation_map_manager.h
line_of_sight_calculation.cpp
line_of_sight_calculation.h
)
# The stub's ElevationMapManager is a Q_OBJECT class; without AUTOMOC the
# moc symbols (staticMetaObject/vtable) are missing and the link of
# libsituationMapElevationMap.so fails, cascading to every target that
# links it (same pattern as LtsSessionDataDds).
NGL_ADD_LIBRARY2(AAR SV WS HLA situationMapElevationMap SHARED ${Elevation_SRCS})
set_target_properties(situationMapElevationMap PROPERTIES AUTOMOC ON)
NGL_TARGET_INCLUDE_DIRECTORIES(situationMapElevationMap
PUBLIC
# The stub cpp does #include "elevation_map_manager.h" - it lives in
# include/Viewer/SituationMap/ElevationMap/, not next to the source.
${CMAKE_SOURCE_DIR}/include/Viewer/SituationMap/ElevationMap
${CMAKE_SOURCE_DIR}/include
# Consumers include <ElevationMap/elevation_map.h> and the NGL-generated
# <ElevationMap/situationmapelevationmap_export.h>; the parent source/binary
# dirs put the ElevationMap/ subfolder (and the generated export header) on the path.
${CMAKE_CURRENT_SOURCE_DIR}/../
${CMAKE_CURRENT_BINARY_DIR}/../
)
NGL_TARGET_LINK_LIBRARIES(situationMapElevationMap
PRIVATE
situationMapCommon
Qt6::Concurrent
Qt6::Gui
NGLLogger
LtsCoordTrans
PUBLIC
Qt6::Core
LtsUtilsCoreHeaderOnly
)
@@ -0,0 +1,137 @@
/**
* @RDE_HEADER@
* adapting GeISiR source to SituationMap
* $Id$
* $HeadURL$
* $Author$
*/
#include "elevation_map.h"
#include <QFileInfo>
#include <QPolygonF>
#include <QGuiApplication>
#include <limits>
namespace SituationMap
{
// GDAL is not part of the Qt6/ArcGIS-300 build (no GDAL in the toolchain;
// see the no-GDAL ElevationMap stub decision). This translation unit is the
// no-GDAL stand-in for the legacy GDAL-backed reader: the public API is
// preserved (header unchanged) so consumers (MapImpl, ElevationMapManager,
// SightFanImpl) compile and link; elevation data is simply not loaded, so
// queries return defaults / no-coverage. Everything else in the module
// (ElevationMapManager, line_of_sight_calculation) is real, GDAL-free Qt code.
struct ElevationMap::Internal
{
};
ElevationMap::ElevationMap(const QFileInfo &fileInfo)
: m_internal(new Internal())
, m_fileName(fileInfo.absoluteFilePath())
, m_aproximation(false)
, m_valid(false)
, m_logger(getLogger("ElevationMap"))
{
readFromFile();
}
ElevationMap::~ElevationMap()
{
delete m_internal;
}
bool ElevationMap::waitForInitialization()
{
// No asynchronous GDAL read is started, so initialization is already done.
return true;
}
bool ElevationMap::isValid() const
{
return m_valid;
}
QString ElevationMap::filename() const
{
return m_fileName;
}
QRectF ElevationMap::extent() const
{
return QRectF();
}
QPair<double, double> ElevationMap::elexelSize() const
{
return qMakePair(0.0, 0.0);
}
double ElevationMap::elevation(double, double) const
{
return std::numeric_limits<double>::quiet_NaN();
}
double ElevationMap::distance(const QPointF &start, const QPointF &end) const
{
return (end - start).manhattanLength();
}
double ElevationMap::profileDistance(const QPointF &start, const QPointF &end) const
{
return (end - start).manhattanLength();
}
unsigned int ElevationMap::elevationProfile(const QPointF &, const QPointF &, Vec3dVector &) const
{
return 0;
}
bool ElevationMap::contains(const QPointF &) const
{
return false;
}
bool ElevationMap::intersects(const QPolygonF &) const
{
return false;
}
void ElevationMap::LOSProfile(const QPointF &, const QPointF &, LOSVector &)
{
}
int ElevationMap::getElevation(int, int) const
{
return std::numeric_limits<int>::min();
}
double ElevationMap::getElevation(double, double) const
{
return std::numeric_limits<double>::quiet_NaN();
}
double ElevationMap::getOrSubstituteElevation(int, int, double substitute) const
{
return substitute;
}
void ElevationMap::getSamplePoints(const QPointF &, const QPointF &, Vec3dVector &) const
{
}
int ElevationMap::clipp2Map(const QPointF &, const QPointF &, QPointF &, QPointF &) const
{
return 0;
}
bool ElevationMap::readFromFile()
{
// No GDAL: no DEM is read.
m_valid = false;
return false;
}
} // namespace SituationMap
@@ -0,0 +1,168 @@
/**
* @RDE_HEADER@
* adapting GeISiR source to SituationMap
* $Id$
* $HeadURL$
* $Author$
*/
#pragma once
#include "elevation_map_helper.h"
#include <ElevationMap/situationmapelevationmap_export.h>
#include <LtsUtilsCore/qpoint3d.h>
#include <Common/situation_map_logging.h>
#include <QFutureWatcher>
#include <QPointF>
#include <QRectF>
#include <QVector>
class QFileInfo;
namespace SituationMap
{
//------------------------------------------------------------------------------------------------------------
// ElevationMap
//------------------------------------------------------------------------------------------------------------
class SITUATIONMAPELEVATIONMAP_EXPORT ElevationMap final
{
friend class ElevationMapManager;
public:
ElevationMap() = delete;
ElevationMap(const ElevationMap &) = delete;
ElevationMap &operator = (const ElevationMap &) = delete;
explicit ElevationMap(const QFileInfo &fileInfo);
~ElevationMap();
bool waitForInitialization();
bool isValid() const;
QString filename() const;
QRectF extent() const;
QPair<double, double> elexelSize() const;
double elevation(double lon, double lat) const; // rad
double distance(const QPointF &start, const QPointF &end) const;
double profileDistance(const QPointF &start, const QPointF &end) const;
unsigned int elevationProfile(const QPointF &start, const QPointF &end, Vec3dVector &elevProfile) const;
void interpolation(bool on) { m_aproximation = on; }
bool interpolation() const { return m_aproximation; }
bool contains(const QPointF &point) const;
bool intersects(const QPolygonF &polygon) const;
// Line of Sight Profile: berücksichtigt Erdkrümmung und WGS84 Erdellipsoid
void LOSProfile(const QPointF &start, const QPointF &end, LOSVector &losProfile);
protected:
int getElevation(int column, int row) const;
double getElevation(double lon, double lat) const;
double getOrSubstituteElevation(int column, int row, double substitute) const;
// getSamplePoints rastert den Vector( start, end) in Lat/Lon entsprechend dem Höhenraster
void getSamplePoints(const QPointF &start, const QPointF &end, Vec3dVector &sPnts) const;
int clipp2Map(const QPointF &start, const QPointF &end, QPointF &cStart, QPointF &cEnd) const;
bool readFromFile();
struct Internal;
Internal *m_internal;
QString m_fileName;
bool m_aproximation;
bool m_valid;
QFutureWatcher<bool> m_gdalReadWatcher;
LOGGER_T m_logger; ///< Interface of the Logging-Facility
}; // ElevationMap
} // SituationMap
/* -----------------------------------------------------------------------------------------------
** CVS-Id/Release ...: $Header$
** -----------------------------------------------------------------------------------------------
**
** Historie:
**
** $Log: not supported by cvs2svn $
** Revision 1.20 2006/09/26 07:51:12 Jörg
** Syntax Fehler unter Suse Linux 10.1 behoben.
**
** Revision 1.19 2006/03/24 09:05:24 klaus
** Elevationprofile: Begrenzung auf Kartengröße aufgehoben ( Clipping)
**
** Revision 1.18 2005/11/09 11:12:27 klaus
** Anpassung an Linux: Kommentar hinter #endif mit "//" versehen
**
** Revision 1.17 2005/08/22 14:15:02 joerg
** typeId()
**
** Revision 1.16 2005/08/12 09:37:44 joerg
** Koordinaten-Umprojezieren bei Wechsel der Projektion
**
** Revision 1.15 2005/04/15 13:04:35 joerg
** Resource Control
**
** Revision 1.14 2005/03/04 14:29:13 klaus
** Elevationmap mit CachedTileList versehen und automatischem Entladen von Tiles
**
** Revision 1.13 2005/03/03 12:37:14 klaus
** dynamischen Laden und Entladen der ElevationTiles für Reliefmap
**
** Revision 1.12 2005/03/01 12:33:12 klaus
** Reliefmap eingeführt, aus Elevationmap entfernt
**
** Revision 1.11 2005/02/25 15:26:41 klaus
** Ergänzung um Reliefkarte
**
** Revision 1.10 2005/02/10 14:13:21 klaus
** Bias in Basisklasse MapObject überführt
**
** Revision 1.9 2005/02/10 13:51:01 klaus
** Bias für SightFans eingeführt
**
** Revision 1.8 2005/02/09 16:53:06 klaus
** 1. Version der SightFans
**
** Revision 1.7 2005/01/26 12:25:41 klaus
** todos bearbeitet, Fehlerrückmeldnugen
**
** Revision 1.6 2004/12/14 09:43:25 klaus
** 7. Erweiterung für Höhenkarten
**
** Revision 1.5 2004/12/07 11:07:20 klaus
** 5. Erweiterung für Höhenkarten
**
** Revision 1.4 2004/12/03 16:24:12 klaus
** 4. Erweiterung für Höhenkarten
**
** Revision 1.3 2004/11/30 13:15:28 klaus
** 3. Erweiterung für Höhenkarten
**
** Revision 1.2 2004/11/23 14:36:14 klaus
** 2. Erweiterung für Höhenkarten
**
**
** ----------------------------------------------------------------------------------------------- */
@@ -0,0 +1,88 @@
/**
* @RDE_HEADER@
* Some functions and struct for ElevationMap/LineOfSight (LOS)
* $Id$
* $HeadURL$
* $Author$
*/
#pragma once
#include <LtsUtilsCore/qpoint3d.h>
#include <math.h>
#include <MathUtils/math_const.h>
#include <QPointF>
#include <QVector>
namespace SituationMap
{
inline bool isInIntervall(double x, double x1, double x2)
{
return (((x > x1) && (x < x2)) || (((x > x2) && (x < x1))));
} // inline bool isInIntervall(double x, double x1, double x2)
inline double radiusWGS84(double lat)
{
double sinLAT = sin(lat);
return (MathConst::WGS84_Major_a * sqrt(1.0 - MathConst::WGS84_SQR_EXC * sinLAT * sinLAT));
} // inline double radiusWGS84(double lat)
inline QPointF distance_in_meter_WGS84(const QPointF &start, const QPointF &end) // start, end in LonLat
{
// todo: prüfen ob Distanz zu groß, dann verbesserte Berechnung !!
double lat = (end.y() + start.y()) / 2.0;
double faktorLon = MathConst::WGS84_Major_a * cos(lat); // radiusWGS84(lat) * 2.0 * PI;
double faktorLat = MathConst::WGS84_Minor_b;
return QPointF(faktorLon * (end.x() - start.x()), faktorLat * (end.y() - start.y()));
} // QPointF distance_in_meter_WGS84(const QPointF &start, const QPointF &end)
inline double squareLength(const QPointF &v)
{
return v.x() * v.x() + v.y() * v.y();
} // inline double squareLength(const QPoint & v)
inline double length(const QPointF &v)
{
return sqrt(squareLength(v));
} // inline double length(const QPoint & v)
struct LOSentry // Defines 1 Entry for Line of Sight
{
LOSentry() = default;
LOSentry(double dist, double height) : _dist(dist), _height(height) { ; }
double &dist() { return _dist; }
double &height() { return _height; }
double dist() const { return _dist; }
double height() const { return _height; }
bool isUndefined() const { return std::isnan(_height); }
private:
double _dist = 0; // Distance from Start
double _height = -NAN;
}; /* LOSentry */
using Point3D = LtsUtils::QPoint3D; ///< x = lon ; y = lat , z = elevation/altitude in meters
using LOSVector = QVector<LOSentry>;
using Vec2dVector = QVector<QPointF>;
using Vec3dVector = QVector<Point3D>;
} // SituationMap
@@ -0,0 +1,531 @@
/**
* @RDE_HEADER@
* Manage and combine several ElevationMap
* $Id$
* $HeadURL$
* $Author$
*/
#include "elevation_map_manager.h"
#include "elevation_map.h"
// Qt
#include <QPointer>
#include <QFileInfo>
#include <QRectF>
#include <QPolygonF>
// system
#include <vector>
namespace SituationMap
{
static long s_counter{0};
//------------------------------------------------------------------------------------------------------------
// ElevationMapManager::Private
//------------------------------------------------------------------------------------------------------------
class ElevationMapManager::Private
{
public:
// fine to rough
std::vector<ElevationMap *> m_elevationMapCont;
QRectF m_simpleExtent;
};
//------------------------------------------------------------------------------------------------------------
// ElevationMapManager
//------------------------------------------------------------------------------------------------------------
ElevationMapManager::ElevationMapManager()
: BaseClass()
, d(new Private())
, m_logger(getLogger("ElevationMapManager"))
{
++s_counter;
TRACE_LOG(m_logger) << LOGFUNCTION << " START, s_counter=" << s_counter << " this=" << this;
TRACE_LOG(m_logger) << LOGFUNCTION << " END, s_counter=" << s_counter << " this=" << this;
}
ElevationMapManager::~ElevationMapManager()
{
--s_counter;
TRACE_LOG(m_logger) << LOGFUNCTION << " START, s_counter=" << s_counter << " this=" << this;
cleanupCurrentContent();
delete d;
d = nullptr;
TRACE_LOG(m_logger) << LOGFUNCTION << " END, s_counter=" << s_counter << " this=" << this;
}
int ElevationMapManager::init(const QStringList &filePaths_rough_to_fine)
{
NOTICE_LOG(m_logger) << LOGFUNCTION << " START" << " filePaths_rough_to_fine=" << filePaths_rough_to_fine.join(QStringLiteral(" ; "));
cleanupCurrentContent();
d->m_elevationMapCont.reserve(filePaths_rough_to_fine.size());
int cnt = 0;
for (const QString &filePath : filePaths_rough_to_fine)
{
QFileInfo fileInfo(filePath);
const QString &fileName = fileInfo.absoluteFilePath();
if (!fileInfo.exists())
{
ERROR_LOG(m_logger) << LOGFUNCTION << " elevation data file \'" << fileName << "\' doesn't exists.";
continue;
}
if (!fileInfo.isReadable())
{
ERROR_LOG(m_logger) << LOGFUNCTION << " elevation data file \'" << fileName << "\' isn't readable.";
continue;
}
// ctor will spawn thread via QtConcurrent and read file async:
d->m_elevationMapCont.insert(d->m_elevationMapCont.begin(), new ElevationMap(fileInfo));
++cnt;
} // for
NOTICE_LOG(m_logger) << LOGFUNCTION << " END" << " filePaths_rough_to_fine=" << filePaths_rough_to_fine.join(QStringLiteral(" ; "))
<< ", following number of files are going to be loaded: " << cnt;
return cnt;
}
void ElevationMapManager::cleanupCurrentContent()
{
qDeleteAll(d->m_elevationMapCont);
d->m_elevationMapCont.clear();
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
bool ElevationMapManager::waitForInitialization()
{
for (ElevationMap *elevationMap : d->m_elevationMapCont)
elevationMap->waitForInitialization();
return isValid();
}
bool ElevationMapManager::isValid() const
{
bool allAreValid = true;
for (const ElevationMap *elevationMap : d->m_elevationMapCont)
allAreValid = allAreValid && elevationMap->isValid();
// FATAL_LOG(m_logger) << LOGFUNCTION << " allAreValid = " << allAreValid;
return allAreValid;
}
double ElevationMapManager::elevation(double lon_rad, double lat_rad, bool *bIsCovered) const
{
// assume, that all children are ready
for (const ElevationMap *elevationMap : d->m_elevationMapCont)
{
// qCritical() << " EMM::elevation: "
// << " lon_rad=" << lon_rad
// << " lat_rad=" << lat_rad
// << " (try: " << elevationMap->filename() << ")...";
double singleResult = elevationMap->elevation(lon_rad, lat_rad);
if (singleResult > -300) // -300 -> ausserhalb der Höhenkarte !!
{
// qCritical() << " EMM::elevation: elevation= " << singleResult << " (taken from: " << elevationMap->filename() << ")";
if (bIsCovered)
*bIsCovered = true;
return singleResult;
}
}
// DEBUG_LOG(m_logger) << LOGFUNCTION << " invalid= "
// << " lon_rad=" << lon_rad
// << " lat_rad=" << lat_rad;
if (bIsCovered)
*bIsCovered = false;
return std::numeric_limits<double>::min();
}
double ElevationMapManager::elevation(double lon_rad, double lat_rad, double defaultValue, bool *bIsCovered) const
{
bool bIsCoveredLocal = false;
const double elevationValue = elevation(lon_rad, lat_rad, &bIsCoveredLocal);
// in any case: if provided, transfer isCovered back to caller
if (bIsCovered)
*bIsCovered = bIsCoveredLocal;
// which value to be returned?
if (!bIsCoveredLocal)
return defaultValue;
return elevationValue;
}
QRectF ElevationMapManager::simpleUnitedExtent() const
{
if (d->m_simpleExtent.isNull())
{
bool bFirst = true;
for (const ElevationMap *elevationMap : d->m_elevationMapCont)
{
const QRectF &singleExtent = elevationMap->extent();
if (bFirst)
{
bFirst = false;
d->m_simpleExtent = singleExtent;
// qCritical() << " bFirst.left " << singleExtent.left() << " bFirst.right " << singleExtent.right();
// qCritical() << " bFirst.top " << singleExtent.top() << " bFirst.bottom " << singleExtent.bottom();
} else {
// prefer following instead QRectF::united (top vs. bottom):
// qCritical() << " next.left " << singleExtent.left() << " secnextright " << singleExtent.right();
// qCritical() << " next.top " << singleExtent.top() << " next.bottom " << singleExtent.bottom();
d->m_simpleExtent.setLeft (std::min(d->m_simpleExtent.left(), singleExtent.left()));
d->m_simpleExtent.setTop (std::max(d->m_simpleExtent.top(), singleExtent.top())); // top - >use max !!!
d->m_simpleExtent.setBottom(std::min(d->m_simpleExtent.bottom(), singleExtent.bottom())); // bottom -> use min
d->m_simpleExtent.setRight (std::max(d->m_simpleExtent.right(), singleExtent.right()));
}
} // for
}
return d->m_simpleExtent;
}
bool ElevationMapManager::contains(const QPointF &point) const
{
for (const ElevationMap *elevationMap : d->m_elevationMapCont)
{
if (elevationMap->contains(point))
return true;
}
return false;
}
void ElevationMapManager::LOSProfile(const QPointF &start, const QPointF &end, LOSVector &losProfile)
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
if (d->m_elevationMapCont.empty())
{
ERROR_LOG(m_logger) << LOGFUNCTION << " no elevationMap";
return;
}
waitForInitialization();
QRectF simpleExtentLocal = simpleUnitedExtent();
// qCritical() << " simpleExtent.left " << simpleExtentLocal.left() << " simpleExtent.right " << simpleExtentLocal.right();
// qCritical() << " simpleExtent.top " << simpleExtentLocal.top() << " simpleExtent.bottom " << simpleExtentLocal.bottom();
if (!simpleExtentLocal.contains(start))
{
ERROR_LOG(m_logger) << LOGFUNCTION << " start coordinate not within area"
<< ", start: x=" << start.x() << " ; y=" << start.y()
<< ", area: "
<< " left " << simpleExtentLocal.left() << ", right " << simpleExtentLocal.right()
<< " top " << simpleExtentLocal.top() << ", bottom " << simpleExtentLocal.bottom()
;
return; // ausserhalb der Höhenkarte !!
}
bool clipped = false;
double totalLng;
QPointF startG = start;
QPointF endG = end;
if (!simpleExtentLocal.contains(end)) // Clippen
{
clipped = true;
totalLng = length(endG - startG);
if (endG.x() < simpleExtentLocal.left())
{
double m = (endG.y() - startG.y()) / (endG.x() - startG.x());
double x = simpleExtentLocal.left();
endG.setX(x);
endG.setY(startG.y() + m * (x - startG.x()));
}
else if (endG.x() > simpleExtentLocal.right())
{
double m = (endG.y() - startG.y()) / (endG.x() - startG.x());
double x = simpleExtentLocal.right();
endG.setX(x);
endG.setY(startG.y() + m * (x - startG.x()));
}
if (endG.y() < simpleExtentLocal.bottom())
{
double m = (endG.x() - startG.x()) / (endG.y() - startG.y());
double y = simpleExtentLocal.bottom();
endG.setY(y);
endG.setX(startG.x() + m * (y - startG.y()));
}
else if (endG.y() > simpleExtentLocal.top())
{
double m = (endG.x() - startG.x()) / (endG.y() - startG.y());
double y = simpleExtentLocal.top();
endG.setY(y);
endG.setX(startG.x() + m * (y - startG.y()));
}
}
// Korrektursteigung aufgrund WGS84 Erdellipsoid, Lineare Approximation, Fehler bis 200 km: < 1.0m
double startRadius = radiusWGS84(startG.y());
double corrM = (radiusWGS84(endG.y()) - startRadius) / length(endG - startG);
//
// getSamplePoints(start, end, elevProfile);
// find best elevationMap for equested path {startG, endG}
//
// 1st find maps covering the desired pathG:
const QPolygonF pathG( QVector<QPointF>{startG, endG} );
std::vector<ElevationMap *> coveredElevationMaps;
coveredElevationMaps.reserve(d->m_elevationMapCont.size());
for (auto curItem : qAsConst(d->m_elevationMapCont))
{
if (curItem && curItem->intersects(pathG))
coveredElevationMaps.push_back(curItem);
} // for
if (m_logger.isDebugEnabled())
{
DEBUG_LOG(m_logger) << " coveredElevationMap.size() = " << coveredElevationMaps.size();
for (auto curItem : qAsConst(coveredElevationMaps))
DEBUG_LOG(m_logger) << " coveredElevationMap = " << curItem->filename();
}
// if no maps covers the desired path, stay on old approach: use most bottom elevation map:
if (coveredElevationMaps.empty())
coveredElevationMaps = d->m_elevationMapCont;
// 2nd: find elevation map with highest resolution to achieve best results:
using ELE_VEC_IT = std::vector<ElevationMap*>::iterator;
ELE_VEC_IT eleIt = coveredElevationMaps.begin();
for (ELE_VEC_IT curItem = coveredElevationMaps.begin()+1; curItem != coveredElevationMaps.end(); ++curItem)
{
ElevationMap *elePtr = *curItem;
if (!elePtr)
continue;
if (elePtr->elexelSize().first < (*eleIt)->elexelSize().first)
eleIt = curItem;
} // for
Q_ASSERT_X((*eleIt), "ElevationMapManager::LOSProfile", "eleIt failed");
Vec3dVector elevProfile;
(*eleIt)->getSamplePoints(start, end, elevProfile);
INFO_LOG(m_logger) << "Using ElevationMap '" << (*eleIt)->filename() << "'"
<< " (of size = " << d->m_elevationMapCont.size() << ")"
<< " with_elexelSize " << (*eleIt)->elexelSize().first
<< " -> # SamplePoints = " << elevProfile.size();
for (Vec3dVector::iterator itr = elevProfile.begin(); itr != elevProfile.end(); ++itr)
{
double dist = length(distance_in_meter_WGS84(start, itr->toPointF()));
double height = elevation(itr->x(), itr->y()); // use elevation over all seperate elevationMaps
height += corrM * dist; // WGS84 Erdellipsoid Korrektur
height -= (startRadius * (1 - cos(atan(dist / startRadius)))); // Einbeziehen der Erdkruemmung
// alternativ als Naeherung: height -= ( dist * dist) / (startRadius * 2.0);
losProfile.push_back(LOSentry(dist, height));
}
if (clipped)
losProfile.push_back(LOSentry(totalLng, -NAN));
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
}
ElevationMapManager::LineOfSight ElevationMapManager::lineOfSightCalculation(const LOSVector &losProfile,
double centerHat,
double objHat) const
{
// Analog zu SightFanImpl::calculateSightBeam
if (losProfile.size() < 2) // Startpunkt undefiniert oder ausserhalb der Karte
{
return LineOfSight::LOS_ERROR;
}
LOSVector::const_iterator itr = losProfile.begin();
const double centerHeight = itr->height() + centerHat;
double d1 = 0.0;
double height1 = itr->height();
// // überspringen bis _innerRadius erreicht ist !
// while( ++itr != losProfile.end())
// {
// double d2 = itr->dist(); // *EarthRadius;
// double height2 = itr->height();
// if( d2 >= m_internal->m_innerRadius)
// {
// height1 = height1 + (m_internal->m_innerRadius - d1) * ( height2 - height1)/(d2 - d1);
// d1 = m_internal->m_innerRadius;
// --itr;
// break;
// }
// d1 = d2;
// height1 = height2;
// }
// bool visible = true;
// SightMode mode = START;
d1 = itr->dist();
double curM = (height1 - centerHeight ) / d1; // bestimmende Steigung
// sBeam.add( SightEntry( d1, START) );
while (++itr != losProfile.end())
{
double d2 = itr->dist(); // *EarthRadius;
double height2 = itr->height();
if (std::isnan(height2)) // Undefined
{
return LineOfSight::LOS_UNDEFINED;
}
double hObj = (height2 + objHat - centerHeight );
double objM = hObj / d2; // Steigung bezogen auf Objekte( Objekte verdecken nicht !)
LineOfSight newMode = ((objM >= curM)) ? LineOfSight::LOS_VISIBLE : LineOfSight::LOS_INVISIBLE;
if (newMode == LineOfSight::LOS_INVISIBLE)
return LineOfSight::LOS_INVISIBLE;
// if (newMode != mode)
// {
// if ( (mode != LineOfSight::LOS_UNDEFINED) && (d2 != d1) )
// {
// // Korrekturwert für Distanz berechnen, unter Berücksichtigung der Objekthoehe !!
// double localM = (height2 - height1) /(d2 - d1);
// // localM == curM kann nicht auftreten, da newMode != mode
// double dCorr = (hObj - (curM * d2)) / (localM - curM);
// if (dCorr < 0.0)
// dCorr = 0.0;
// dCorr = d2 - dCorr;
// if (dCorr < d1)
// dCorr = d1;
// sBeam.add( SightEntry( dCorr, mode) );
// }
// mode = newMode;
// }
double terrM = (height2 - centerHeight) / d2; // Steigung bezogen auf Gelaende
if (terrM >= curM)
{
curM = terrM; // neue bestimmende Steigung
}
// height1 = height2;
// d1 = d2;
} // while
return LineOfSight::LOS_VISIBLE;
}
ElevationMapManager::LineOfSight ElevationMapManager::lineOfSightCalculation(const LtsUtils::QPoint3D &startPointGeo_absZ,
const LtsUtils::QPoint3D &endPointGeo_absZ)
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START" << ", startPointGeo_absZ = " << startPointGeo_absZ << ", endPointGeo_absZ = " << endPointGeo_absZ;
if (!isValid())
{
ERROR_LOG(m_logger) << LOGFUNCTION << " Error, LtsElevationManager not valid";
return LineOfSight::LOS_ERROR;
}
// 1st: a) centerHat / startHat:
const double startHat = startPointGeo_absZ.z() - this->elevation(startPointGeo_absZ.x(), startPointGeo_absZ.y(), -10000);
if (startHat < 0)
{
ERROR_LOG(m_logger) << LOGFUNCTION << " Error, startHat is negativ";
return LineOfSight::LOS_ERROR;
}
// 1st: b) endHat / objHat:
const double endHat = endPointGeo_absZ.z() - this->elevation(endPointGeo_absZ.x(), endPointGeo_absZ.y(), -10000);
if (endHat < 0)
{
ERROR_LOG(m_logger) << LOGFUNCTION << " Error, objHat is negativ"
<< ", startPointGeo_absZ=" << startPointGeo_absZ
<< ", endPointGeo_absZ=" << endPointGeo_absZ;
return LineOfSight::LOS_ERROR;
}
SituationMap::ElevationMapManager::LineOfSight eleMapMgrResult = lineOfSightCalculation(startPointGeo_absZ.toPointF(), startHat,
endPointGeo_absZ.toPointF(), endHat);
TRACE_LOG(m_logger) << LOGFUNCTION << " END" << ", startPointGeo = " << startPointGeo_absZ << ", endPointGeo = " << endPointGeo_absZ
<< " -> LineOfSight " << static_cast<int>(eleMapMgrResult);
return eleMapMgrResult;
}
ElevationMapManager::LineOfSight ElevationMapManager::lineOfSightCalculation(const QPointF &startPointGeo, double startHat,
const QPointF &endPointGeo, double endHat)
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START"
<< ", startPointGeo = " << startPointGeo << ", startHat = " << startHat
<< ", endPointGeo = " << endPointGeo << ", endHat = " << endHat ;
if (!isValid())
{
ERROR_LOG(m_logger) << LOGFUNCTION << " Error, LtsElevationManager not valid";
return LineOfSight::LOS_ERROR;
}
if (startHat < 0)
{
ERROR_LOG(m_logger) << LOGFUNCTION << " Error, startHat is negativ";
return LineOfSight::LOS_ERROR;
}
if (endHat < 0)
{
ERROR_LOG(m_logger) << LOGFUNCTION << " Error, endHat is negativ";
return LineOfSight::LOS_ERROR;
}
// 1st: create LOSVector:
SituationMap::LOSVector losProfile;
LOSProfile(startPointGeo, endPointGeo, losProfile);
if (losProfile.size() < 2)
{
ERROR_LOG(m_logger) << LOGFUNCTION << " Error, losProfile not valid"
<< ", losProfile.size = " << losProfile.size();
return LineOfSight::LOS_ERROR;
}
// 2nd: lineOfSightCalculation
SituationMap::ElevationMapManager::LineOfSight eleMapMgrResult = this->lineOfSightCalculation(losProfile, startHat, endHat);
TRACE_LOG(m_logger) << LOGFUNCTION << " END"
<< ", startPointGeo = " << startPointGeo << ", startHat = " << startHat
<< ", endPointGeo = " << endPointGeo << ", endPointHat = " << endHat
<< " -> LineOfSight " << static_cast<int>(eleMapMgrResult);
return eleMapMgrResult;
}
} // SituationMap
@@ -0,0 +1,84 @@
/**
* @RDE_HEADER@
* Manage and combine several ElevationMap
* $Id$
* $HeadURL$
* $Author$
*/
#pragma once
#include "elevation_map_helper.h"
#include <ElevationMap/situationmapelevationmap_export.h>
#include <Common/situation_map_logging.h>
#include <QObject>
namespace SituationMap
{
// forward:
class ElevationMap;
//------------------------------------------------------------------------------------------------------------
// ElevationMapManager
//------------------------------------------------------------------------------------------------------------
class SITUATIONMAPELEVATIONMAP_EXPORT ElevationMapManager final : public QObject
{
using BaseClass = QObject;
public:
ElevationMapManager();
ElevationMapManager(const ElevationMapManager &) = delete;
ElevationMapManager &operator = (const ElevationMapManager &) = delete;
~ElevationMapManager();
int init(const QStringList &filePaths_rough_to_fine);
void cleanupCurrentContent();
bool waitForInitialization();
bool isValid() const;
double elevation(double lon_rad, double lat_rad, bool *bIsCovered = nullptr) const;
double elevation(double lon_rad, double lat_rad, double defaultValue, bool *bIsCovered = nullptr) const;
// united extent of seperate files:
QRectF simpleUnitedExtent() const;
bool contains(const QPointF &point) const;
// Line of Sight Profile: berücksichtigt Erdkrümmung und WGS84 Erdellipsoid
void LOSProfile(const QPointF &start, const QPointF &end, LOSVector &losProfile);
/*! \name Line of Sight */
//@{
enum class LineOfSight { LOS_UNDEFINED,
LOS_ERROR,
LOS_VISIBLE,
LOS_INVISIBLE };
LineOfSight lineOfSightCalculation(const LOSVector &losProfile,
double centerHat,
double objHat) const;
LineOfSight lineOfSightCalculation(const LtsUtils::QPoint3D &startPointGeo_absZ,
const LtsUtils::QPoint3D &endPointGeo_absZ);
LineOfSight lineOfSightCalculation(const QPointF &startPointGeo, double startHat,
const QPointF &endPointGeo, double endHat);
//@}
protected:
class Private;
Private *d;
LOGGER_T m_logger; ///< Interface of the Logging-Facility
}; // ElevationMapManager
} // SituationMap
@@ -0,0 +1,229 @@
/**
* @RDE_HEADER@
* LineOfSightCalculation (L400)
* $Id$
* $HeadURL$
* $Author$
* Created by N. Thoden, NLE, 06.04.2020
*/
#include "line_of_sight_calculation.h"
#include "elevation_map.h"
#include <LtsCoordTrans/lts_coord_trans.h>
//
// ESRI / ARCGIS
// if you link libEsriCommonQt, you propably have to add ArcGISQt5Hack AND: # make sure it's loaded *before* libEsriCommonQt.so
// this may effect all executables linking situationMapElevationMap. CHECK!
//
// Qt
#include <QTimer>
#include <QElapsedTimer>
// some helper functions
inline Q_CONSTEXPR double pi() { return M_PI; }
inline Q_CONSTEXPR double deg2rad() { return pi() / 180.; }
inline Q_CONSTEXPR double rad2deg() { return 1. / deg2rad(); }
namespace SituationMap
{
LineOfSightCalculation::LineOfSightCalculation(ElevationMap *elevationMap)
: m_logger(getLogger("LineOfSightCalculation"))
, m_elevationMap(elevationMap)
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
}
LineOfSightCalculation::~LineOfSightCalculation()
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
}
bool LineOfSightCalculation::calculate(ObserverTargetData &observerTarget, unsigned int sampleIntervallMeter)
{
// same checks:
if (!m_elevationMap || !m_elevationMap->isValid())
{
ERROR_LOG(m_logger) << LOGFUNCTION << " no elevationMap configured or not valid";
observerTarget.setLineOfSightVisibility(LineOfSightVisibility::Undefined);
return false;
}
if (!observerTarget.isObserverAndTargetValid())
{
ERROR_LOG(m_logger) << LOGFUNCTION << " observer and/or target not valid";
observerTarget.setLineOfSightVisibility(LineOfSightVisibility::Undefined);
return false;
}
if (observerTarget.observer().toPointF() == observerTarget.target().toPointF())
{
ERROR_LOG(m_logger) << LOGFUNCTION << " observer and target are identical regarding x and y";
observerTarget.setLineOfSightVisibility(LineOfSightVisibility::Undefined);
return false;
}
bool success = true;
QElapsedTimer timer;
if (m_logger.isInfoEnabled())
timer.start();
//
//
// consider using ElevationMap::LOSProfile
//
//
// determine how many iterations we need:
double distanceInMeter = distanceMeter(observerTarget.observer(),
observerTarget.target());
//ERROR_LOG(m_logger) << LOGFUNCTION << " distanceMeter = " << distanceInMeter;
int maxNumberOfIterations = distanceInMeter / sampleIntervallMeter; // check visibility every ~5m
// maxNumberOfIterations = 1000000;
if (maxNumberOfIterations<=0)
maxNumberOfIterations = 5;
double distanceFromObserverToTargetAsFraction = 0;
int i = 0;
while (i<maxNumberOfIterations)
{
++i;
/*
z-axis (Elevation) pCandidate
|---------- /
| ----------
| ----------
| ----------
| ----------
|------------------------------------------------------------ xy-axis
^ ^ ^ ^ ^ ^ ^ ^ samples (every ~5meters)
^ ^
ObserverPosition TargetPosition
On every sample position, check if directLineElevation (maximum) is
obstructed by elevationMapElevation (real value)
if (elevationMapElevation>directLineElevation) -> obstructed/break
*/
distanceFromObserverToTargetAsFraction = (double)i/maxNumberOfIterations;
const Point3D &pCandidate = movePoint(observerTarget.observer(),
observerTarget.target(),
distanceFromObserverToTargetAsFraction);
// {
// static Point3D oldCandidate;
// double distanceInMeter = distanceMeter(pCandidate, oldCandidate);
// ERROR_LOG(m_logger) << LOGFUNCTION << " distanceMeter = " << distanceInMeter;
// oldCandidate = pCandidate;
// }
// z is the elevation of a *direct* line:
const double directLineElevation = pCandidate.z();
const double elevationMapElevation = m_elevationMap->elevation(pCandidate.x(), pCandidate.y());
// Coord covered by elevationMap?
if (elevationMapElevation <= std::numeric_limits<int>::min())
{
ERROR_LOG(m_logger) << LOGFUNCTION << " Error, coordinate not covered be elevationData. Finish this LineOfSightCalculation."
<< " i=" << i
<< ", pCandidate = " << pCandidate;
// write back data
observerTarget.setObstacle(pCandidate);
observerTarget.setLineOfSightVisibility(LineOfSightVisibility::Undefined);
// finish the loop:
success = false;
break;
}
// analyze / check visibility:
if (elevationMapElevation>directLineElevation)
{
DEBUG_LOG(m_logger) << LOGFUNCTION << " i=" << i
<< " break - pCandidate = " << pCandidate
<< " -> directLineElevation = " << directLineElevation
<< " -> elevationMapElevation = " << elevationMapElevation;
// write result
observerTarget.setObstacle(pCandidate);
observerTarget.setLineOfSightVisibility(LineOfSightVisibility::Obstructed);
// finish the loop:
break;
} else {
observerTarget.setLineOfSightVisibility(LineOfSightVisibility::Visible);
}
} // while
if (m_logger.isInfoEnabled())
{
INFO_LOG(m_logger) << LOGFUNCTION << " END"
<< ", success = " << success
<< ", " << i << " of "<< maxNumberOfIterations << " iterations"
<< ", distanceFromObserverToTargetAsFraction = " << distanceFromObserverToTargetAsFraction
<< ", pCandidate=" << observerTarget.obstacle()
<< ", lineOfSightVisibility=" << static_cast<int>(observerTarget.lineOfSightVisibility())
<< ", took [ms] " << timer.elapsed();
}
TRACE_LOG(m_logger) << LOGFUNCTION << " END" << ", success = " << success;
return success;
}
Point3D LineOfSightCalculation::movePoint(const Point3D &oberserver, const Point3D &target, double distanceFromObserverToTargetAsFraction) // 0.0 ... 1.0
{
// positions are lon/lat @ rad.
// for evaluation we do that very simple:
// strange, but: using Point3D seems to be faster then using QPointF
const Point3D &dist = target - oberserver;
const Point3D &point = oberserver + (dist * distanceFromObserverToTargetAsFraction);
return point;
}
double LineOfSightCalculation::distanceMeter(const Point3D &oberserver, const Point3D &target)
{
// Try to avoid the dependency to ESRI (keep ArcGISQt5Hack in mind)
// And good accuracy is not required here
// use LtsCoordTrans::distance
// Esri::ArcGISRuntime::Point geom1(oberserver.x()*rad2deg(), oberserver.y()*rad2deg(), oberserver.z(), Esri::ArcGISRuntime::SpatialReference::wgs84());
// Esri::ArcGISRuntime::Point geom2(target.x() *rad2deg(), target.y() *rad2deg(), target.z() , Esri::ArcGISRuntime::SpatialReference::wgs84());
// Esri::ArcGISRuntime::GeometryEngine *gEngine = Esri::ArcGISRuntime::GeometryEngine::instance();
// Esri::ArcGISRuntime::GeodeticDistanceResult geodeticDistanceResult = gEngine->distanceGeodetic(geom1, geom2,
// Esri::ArcGISRuntime::LinearUnitId::Meters,
// Esri::ArcGISRuntime::AngularUnitId::Degrees,
// Esri::ArcGISRuntime::GeodeticCurveType::Geodesic);
// double distance = geodeticDistanceResult.distance();
double distance = LtsCoordTrans::distance(oberserver.toPointF(), target.toPointF());
return distance;
}
} // namespace SituationMap
@@ -0,0 +1,92 @@
/**
* @RDE_HEADER@
* LineOfSightCalculation (L400)
* $Id$
* $HeadURL$
* $Author$
* Created by N. Thoden, NLE, 06.04.2020
*/
#pragma once
#include <ElevationMap/situationmapelevationmap_export.h>
#include <Common/situation_map_logging.h>
#include <LtsUtilsCore/qpoint3d.h>
using Point3D = LtsUtils::QPoint3D; ///< x = lon ; y = lat , z = elevation/altitude in meters
namespace SituationMap
{
// forward
class ElevationMap;
//----------------------------------------------------------------------------
/*!
\brief Define visibility.
*/
enum class LineOfSightVisibility
{
Undefined, /*!< no data at that location? */
Visible,
Obstructed
};
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------
class SITUATIONMAPELEVATIONMAP_EXPORT ObserverTargetData
{
public:
explicit ObserverTargetData(const Point3D &oberserver = Point3D(), // z-value: incl. observerHeight
const Point3D &target = Point3D()) // z-value: incl. targetHeight
: m_oberserver(oberserver)
, m_target(target)
{}
const Point3D &observer() const { return m_oberserver; }
const Point3D &target() const { return m_target; }
const Point3D &obstacle() const { return m_obstacle; }
void setObstacle(const Point3D &obstacle) { m_obstacle = obstacle; }
LineOfSightVisibility lineOfSightVisibility() const { return m_visible; }
void setLineOfSightVisibility(const LineOfSightVisibility &visible) { m_visible = visible; }
bool isObserverAndTargetValid() const { return (!m_oberserver.isNull()) && (!m_target.isNull()); }
private:
Point3D m_oberserver;
Point3D m_target;
Point3D m_obstacle;
LineOfSightVisibility m_visible = LineOfSightVisibility::Undefined;
};
//----------------------------------------------------------------------------
class SITUATIONMAPELEVATIONMAP_EXPORT LineOfSightCalculation
{
public:
explicit LineOfSightCalculation(ElevationMap *elevationMap);
~LineOfSightCalculation();
bool calculate(ObserverTargetData &observerTarget, unsigned int sampleIntervallMeter = 5);
protected:
static Point3D movePoint(const Point3D &oberserver,
const Point3D &target,
double distanceFromObserverToTargetAsFraction);
static double distanceMeter(const Point3D &oberserver,
const Point3D &target);
private:
LOGGER_T m_logger; ///< Interface of the Logging-Facility
ElevationMap *m_elevationMap = nullptr;
ObserverTargetData m_observerTarget;
};
} // namespace SituationMap
@@ -0,0 +1,49 @@
#
# $Id$
# $HeadURL$
# $Author$
#
# Qt6 + ArcGIS 300 migration: Qt5::->Qt6:: and gated on BUILD_ARCGIS (ArcGIS
# dependent) to match the migrated Symbology convention.
#
# LIBRARY
SET(FunctionDialog_SRCS
function_dialog.cpp
simple_esri_layer.cpp
)
SET(FunctionDialog_HDRS
function_dialog_export.h
function_dialog.h
simple_esri_layer.h
)
SET(FunctionDialog_ICONS
state_icon_b.xpm
state_icon_a.xpm
state_icon_c.xpm
)
SOURCE_GROUP(FunctionDialog FILES ${FunctionDialog_SRCS} ${FunctionDialog_HDRS})
IF(BUILD_ARCGIS)
NGL_ADD_LIBRARY(WS situationMapFunctionDialog SHARED ${FunctionDialog_SRCS} ${FunctionDialog_HDRS})
NGL_TARGET_LINK_LIBRARIES(situationMapFunctionDialog
PRIVATE
NGLLogger
LtsCoordTrans
LtsWidgets
advancedSymbologyGui
Qt6::OpenGL # Qt6: ArcGIS SDK OpenGLGraphicsDevice uses QOpenGLPaintDevice (libQt6OpenGL)
Qt6::OpenGLWidgets # Qt6: ArcGIS SDK uses QOpenGLWidget (separate lib in Qt6)
PUBLIC
ArcGIS::ArcGIS
situationMap
situationMapObjects
situationMapPortal
Qt6::Core
Qt6::Widgets
)
NGL_INSTALL_TARGET(situationMapFunctionDialog)
ENDIF() # BUILD_ARCGIS
File diff suppressed because it is too large. Load diff
@@ -0,0 +1,290 @@
/**
* @RDE_HEADER@
* FunctionDialog
* $Id$
* $HeadURL$
* $Author$
*/
#pragma once
#include "function_dialog_export.h"
#include <Map/map.h>
#include <Map/abstract_map_object.h> // 300 build: RefPointerMapObjectList = QList<RefPointer<AbstractMapObject>> needs the complete type (also for the MOC)
#include <QWidget>
#include <Symbology/symbol_dictionary.h>
// ESRI
#include <Map.h>
#include <MapGraphicsView.h>
#include <GraphicsOverlay.h>
// #define USE_LOCAL_SERVER
class QStandardItemModel;
//----------------------------------------------------------------------------
namespace SituationMap
{
namespace RB
{
class RubberbandBase;
}
class Map;
// TODO: nur fuer Tests exportiert
class FUNCTIONDIALOG_EXPORT FunctionDialog : public QWidget
{
Q_OBJECT
public:
explicit FunctionDialog(Esri::ArcGISRuntime::Map *esriMap,
Esri::ArcGISRuntime::MapGraphicsView *esriView,
QWidget *parent);
explicit FunctionDialog(SituationMap::Map *map);
virtual ~FunctionDialog();
static void addButtonToMap(SituationMap::Map *map, bool isVisible = true);
void init();
void setGraphicsLayer(Esri::ArcGISRuntime::GraphicsOverlay *graphicsLayer);
void setMapPositionString(const QString &mapPosition);
void setPixelSizeString(const QString &text);
void addMapPositionString(const QString &mapPosition);
FunctionDialog(const FunctionDialog &other) = delete; // No copy
FunctionDialog &operator=(const FunctionDialog &other) = delete; // No copy
protected:
void addSimpleLayerTab();
void addLogicalLayerTab();
void addLayerPerformanceTab();
void addGraphicsTab();
void addGraphics3DTab();
void addMessageTab();
void addMapObjectTab();
void addRubberbandTab();
void addRubberband3DTab();
void addToolsTab();
void addViewshedTab();
void addOverlayPlanTab();
void addIconRenderTab();
void addPortalTab();
void addMovePointLuxemburgTab();
void getRotationAndAngle(const QPointF &sectStart, const QPointF &sectEnd, double &rotationDegOut, double &openAngleDegOut);
// void addYourTab();
Esri::ArcGISRuntime::Graphic *createCube(const SituationMap::PositionCont &mapPosCont,
int baseHeight,
double objHeight,
const QString &partyNameValue = QString());
public Q_SLOTS:
void onDestroyed();
void onLayerPerfCreateLayer();
void onGenerateGraphics();
void onGenerateCube();
void onGenerateCubeArray();
void onGenerateStackedCubes();
void onGenerateGraphicsKristenStrandford();
void onGenerateUniqueVaueRendererMountingPoints();
void onGenerate3DGraphicSphereRENDERER();
void onSphereOpacityChangedRENDERER(int opacityValue);
void onGenerate3DGraphicSphere();
void onSphereOpacityChanged(int opacityValue);
void onSphereZValueChanged(int ZValue);
void onGenerate3DGraphicCone();
void onConeOpacityChanged(int opacityValue);
void onConeZValueChanged(int ZValue);
void onConeHeadingChanged(float angle);
void onConeRollChanged(float angle);
void onConePitchChanged(float angle);
void on3dModel();
void on3dModelZValueChanged(int ZValue);
void onGenerate3DGraphicConeUniqueValueRenderer();
void onAddCivilSymbols();
void onMessage();
void onMessageSelect();
void onAddSymbol();
void onSomeParticipants();
void onRubberbandApply(RB::RubberbandBase *);
void onRubberbandAbort(RB::RubberbandBase *);
void onRubberband3DApply(RB::RubberbandBase *);
void onRubberband3DAbort(RB::RubberbandBase *);
void onRubberbandDefineArrow();
void onRubberbandDefineEllipse();
void onRubberbandBoobyTrapSector();
void onRubberbandCheckCoordinates();
void onRubberbandStateSelect();
void onRubberbandTwoInOne();
void onRectCheckCoordinates();
void onPolygonCreate();
void onPolylineCreate();
void onPolylineUpdate();
void onTextCreate();
void onTextUpdate();
void onMapObjectIndicatorCreate();
void onParticipantGetPosition();
void onParticipantGetPositionApplied(RB::RubberbandBase *rubberband = nullptr);
bool createParticipant(const Point3D &origin,
const QString &debugInfo);
void onParticipantCreate();
void onParticipantUpdate();
void onAreaFireCreate();
void onAreaFireUpdate();
void onBuildingCreate();
void onBuildingUpdate();
void onBiologicalAgentCreate();
void onBiologicalAgentUpdate();
void onChemicalAgentCreate();
void onCubeCreate();
void onDangerAreaCreate();
void onDangerAreaUpdate();
void onFunctionalAreaCreate();
void onFunctionalAreaUpdate();
void onGeoImageCreate();
void onMapObjectClicked(const SituationMap::Map::RefPointerMapObjectList &mapObjList,
const QPointF &viewportPosition);
void onSoundAreaCreate();
void onSoundAreaUpdate();
void onHitLineCreate();
void onHitLineUpdate();
void onLineOfSightLineCreate();
void onMineCreate();
void onMineUpdate();
void onMineFieldCreate();
void onMineFieldUpdate();
void onNuclearCreate();
void onNuclearUpdate();
void onChargeEffectCreate();
void onChargeEffectUpdate();
void onBoobyTrapCreate();
void onBoobyTrapUpdate();
void onSingleFireCreate();
void onSingleFireUpdate();
void onShowBasePoint();
void onShowPolizei();
void onObjectIndicator();
void onMeasureLength();
void onStartLocationDisplay();
void onStopLocationDisplay();
void onLoadFile();
void onPortal();
void onMovePoint();
#ifdef USE_LOCAL_SERVER
void onStartLocalService();
void onStopLocalService();
void onStartViewshedSvc();
void onStopViewshedSvc();
void onViewshedInteractive();
void onViewshed();
#endif // USE_LOCAL_SERVER
void onSightFan();
void onViewshedSightFan();
void onLoadPlan();
void onOverlayVisiChanged(bool checked);
void onRemovePlan();
void onRemoveAllPlans();
void onToPdf();
void onDump();
void onOverviewMap();
void onBackupOms();
void onRestoreOms();
void onRemove();
void onRemoveAll();
void onToggleGrid();
void onToggleVisibility();
void onToggleVisibilityTechn();
void onToggleVisibilityTact();
void onToggleSelection();
void onTogglePicking();
void onToggleBoundingBox();
void onToggleBB2();
void onMapRotationChanged();
void onSymbolSizeChanged();
void onSymbolOpacityChanged();
void onDrawOrderChanged();
//void onBuildingPERFORMANCE();
void onMouseWindowPositionChanged(int x, int y);
void onMouseMapPositionChanged(const Point3D &mapPos, bool isValid);
void onMouseGeoPositionChanged(const Point3D &geoPos, bool isValid);
void onExtendChanged();
private:
class Private;
/**
* The private d-pointer to not break BC when changing internals of this class
*/
Private *d = nullptr;
};
} // namespace SituationMap
@@ -0,0 +1,21 @@
/**
* Export definitions
* $Id$
* $HeadURL$
* $Author$
*/
#pragma once
#include <qglobal.h>
#ifndef FUNCTIONDIALOG_EXPORT
# ifdef BUILD_STATIC_LIBRARIES
# define FUNCTIONDIALOG_EXPORT
# else
# if defined(MAKE_SITUATIONMAPFUNCTIONDIALOG_LIB)
# define FUNCTIONDIALOG_EXPORT Q_DECL_EXPORT
# else
# define FUNCTIONDIALOG_EXPORT Q_DECL_IMPORT
# endif
# endif
#endif
@@ -0,0 +1,380 @@
/**
* @RDE_HEADER@
* FunctionDialog
* $Id$
* $HeadURL$
* $Author$
*/
#include "simple_esri_layer.h"
#include <Map.h>
#include <MapImpl/map_impl.h>
#include <Map.h>
#include <MapGraphicsView.h>
#include <LayerListModel.h>
#include <ArcGISTiledLayer.h>
#include <Basemap.h> // 300: basemap() returns Basemap* (fwd-declared only)
#include <GraphicsOverlayListModel.h> // 300: Map::graphicsOverlays() model (fwd-declared only)
// for overview
#include <QDebug>
#include <QDialog>
#include <QLabel>
#include <QCheckBox>
#include <QPushButton>
#include <QSlider>
#include <QGridLayout>
#include <QStandardItemModel>
namespace SituationMap
{
Esri::ArcGISRuntime::Layer *getEsriBasemap_Layer(Esri::ArcGISRuntime::Map *map,
const QString &layername)
{
if (!(map &&
map->basemap() &&
map->basemap()->baseLayers())
)
return nullptr;
Esri::ArcGISRuntime::Layer *layerFound = nullptr;
const Esri::ArcGISRuntime::LayerListModel *model = map->basemap()->baseLayers();
for (int i = 0; i < model->size(); ++i)
{
const Esri::ArcGISRuntime::Layer *curLayer = model->at(i);
const QString &curName = curLayer->name();
if (QString::compare(layername, curName) == 0)
{
layerFound = model->at(i);
break;
}
} // for
return layerFound;
}
Esri::ArcGISRuntime::ArcGISTiledLayer *getEsriBasemap_ArcGISTiledLayer(Esri::ArcGISRuntime::Map *map,
const QString &layername)
{
Esri::ArcGISRuntime::Layer *layerFound = getEsriBasemap_Layer(map, layername);
if (! layerFound)
return nullptr;
if (layerFound->layerType() == Esri::ArcGISRuntime::LayerType::ArcGISTiledLayer)
{
Esri::ArcGISRuntime::ArcGISTiledLayer *layer2 =
static_cast<Esri::ArcGISRuntime::ArcGISTiledLayer *>(layerFound);
return layer2;
}
return nullptr;
}
class SimpleEsriLayer::Private
{
public:
Private()
{
}
~Private()
{
}
// ESRI data:
Esri::ArcGISRuntime::Map *m_map = nullptr;
Esri::ArcGISRuntime::MapGraphicsView *m_mapView = nullptr;
// OWN data:
QGridLayout *m_layout = nullptr;
}; // class SimpleEsriLayer::Private
//-----------------------------------------------------------------------------
SimpleEsriLayer::SimpleEsriLayer(QWidget *parent, Esri::ArcGISRuntime::MapGraphicsView *mapView)
: QWidget(parent)
, d(new Private)
{
d->m_mapView = mapView;
if (d->m_mapView)
d->m_map = d->m_mapView->map();
d->m_layout = new QGridLayout(this);
updatePanel();
}
SimpleEsriLayer::~SimpleEsriLayer()
{
delete d;
}
bool SimpleEsriLayer::updatePanel()
{
for (int row = 0; row < d->m_layout->rowCount(); ++row)
{
for (int col = 0; col < d->m_layout->columnCount(); ++col)
{
QLayoutItem *item = d->m_layout->itemAtPosition(row, col);
if (item)
{
QWidget *w = item->widget();
delete w;
}
}
}
delete d->m_layout;
d->m_layout = new QGridLayout(this);
if (d->m_map)
{
// Header
int row = 0;
int col = 0;
for (const char *name : { "OnOff", "Opac", "Brightness", "Contrast", "Gamma" })
d->m_layout->addWidget(new QLabel(QString::fromLatin1(name)), row, col++);
row = d->m_layout->rowCount();
// GraphicalOverlay
Esri::ArcGISRuntime::GraphicsOverlayListModel *graphicsOverlayListModel = d->m_mapView->graphicsOverlays();
if (graphicsOverlayListModel)
{
int graphicsOverlaySize = graphicsOverlayListModel->size();
// qDebug() << LOGFUNCTION << " graphicsOverlayListModel -> size=" << graphicsOverlaySize;
row += graphicsOverlaySize;
for (int i = 0; i < graphicsOverlaySize; ++i)
{
--row;
col = 0;
// qDebug() << LOGFUNCTION << " graphicsOverlayListModel handle layer i='" << i;
Esri::ArcGISRuntime::GraphicsOverlay *gOverlay = graphicsOverlayListModel->at(i);
if (! gOverlay)
{
qWarning() << LOGFUNCTION << " gOverlay is nil";
return false;
}
const QString &layername = gOverlay->objectName();
QCheckBox *cbOnOff = new QCheckBox(layername);
cbOnOff->setChecked(gOverlay->isVisible());
connect(cbOnOff, &QCheckBox::stateChanged, this, &SimpleEsriLayer::layerOnOff);
d->m_layout->addWidget(cbOnOff, row, col++);
SimpleEsriLayerSlider *sl_opac = new SimpleEsriLayerSlider(layername, 0, 100);
sl_opac->setValue(gOverlay->opacity() * 100);
connect(sl_opac, &SimpleEsriLayerSlider::valueChanged, this, &SimpleEsriLayer::opacity);
d->m_layout->addWidget(sl_opac, row, col++);
} // for
} // if (graphicsOverlayListModel)
// BasemapLayer
row = d->m_layout->rowCount();
Esri::ArcGISRuntime::LayerListModel *baseLayerModel = d->m_map->basemap()->baseLayers();
if (baseLayerModel)
{
int baseLayerModelSize = baseLayerModel->size();
qWarning() << LOGFUNCTION << " baseLayerModel -> size=" << baseLayerModelSize;
row += baseLayerModelSize;
for (int i = 0; i < baseLayerModelSize; ++i)
{
col = 0;
--row;
qWarning() << LOGFUNCTION << " baseLayerModel handle layer i=" << i;
Esri::ArcGISRuntime::Layer *layer = baseLayerModel->at(i);
if (! layer)
{
qWarning() << LOGFUNCTION << " layer is nil";
return false;
}
const QString &layername = layer->name();
QCheckBox *cbOnOff = new QCheckBox(layername);
cbOnOff->setChecked(layer->isVisible());
// QString tooltip = layer->url();
// if (!l->serviceDescription().isEmpty())
// tooltip += QLatin1String(" ; ") % l->serviceDescription();
// if (!tooltip.isEmpty())
// cbOnOff->setToolTip(tooltip);
connect(cbOnOff, &QCheckBox::stateChanged, this, &SimpleEsriLayer::layerOnOff);
d->m_layout->addWidget(cbOnOff, row, col++);
SimpleEsriLayerSlider *sl_opac = new SimpleEsriLayerSlider(layername, 0, 100);
sl_opac->setValue(layer->opacity() * 100);
connect(sl_opac, &SimpleEsriLayerSlider::valueChanged, this, &SimpleEsriLayer::opacity);
d->m_layout->addWidget(sl_opac, row, col++);
if (layer->layerType() == Esri::ArcGISRuntime::LayerType::ArcGISTiledLayer
// || layer->type() == EsriRuntimeQt::LayerType::ArcGISTiledMapService
)
{
Esri::ArcGISRuntime::ArcGISTiledLayer *realLayer =
dynamic_cast<Esri::ArcGISRuntime::ArcGISTiledLayer *>(layer);
if (realLayer)
{
float brightness = realLayer->brightness();
float contrast = realLayer->contrast();
float gamma = realLayer->gamma();
qWarning() << " brightness=" << brightness; // QuartzBeta1 -> not supported
qWarning() << " contrast=" << contrast; // QuartzBeta1 -> not supported
qWarning() << " gamma=" << gamma; // QuartzBeta1 -> not supported
SimpleEsriLayerSlider *sl_brightness = new SimpleEsriLayerSlider(layername, -100, 100);
sl_brightness->setValue(brightness * 100);
connect(sl_brightness, &SimpleEsriLayerSlider::valueChanged, this, &SimpleEsriLayer::brightness);
d->m_layout->addWidget(sl_brightness, row, col++);
SimpleEsriLayerSlider *sl_contrast = new SimpleEsriLayerSlider(layername, -100, 100);
sl_contrast->setValue(contrast * 100);
connect(sl_contrast, &SimpleEsriLayerSlider::valueChanged, this, &SimpleEsriLayer::contrast);
d->m_layout->addWidget(sl_contrast, row, col++);
SimpleEsriLayerSlider *sl_gamma = new SimpleEsriLayerSlider(layername, -100, 100);
sl_gamma->setValue(gamma * 100);
connect(sl_gamma, &SimpleEsriLayerSlider::valueChanged, this, &SimpleEsriLayer::gamma);
d->m_layout->addWidget(sl_gamma, row, col++);
} // ir (realLayer)
} // if (layer->type() == Es
} // for
} // if (baseLayerModel)
QPushButton *pbMaximizeExtent = new QPushButton(QLatin1String("maximize scale of 1st basemap"));
d->m_layout->addWidget(pbMaximizeExtent, 9999, 0);
connect(pbMaximizeExtent, &QPushButton::clicked, this, [this]()
{
if (d->m_map)
{
d->m_map->setMinScale(500000000); // 5e+08
d->m_map->setMaxScale(100);
}
});
}
else
qWarning() << LOGFUNCTION << " no map !!! ";
return true;
}
void SimpleEsriLayer::layerOnOff()
{
QCheckBox *cb = qobject_cast<QCheckBox *>(sender());
if (!cb)
return;
QString layername = cb->text();
qDebug() << LOGFUNCTION << " layername=" << layername;
Esri::ArcGISRuntime::Layer *l = getEsriBasemap_Layer(d->m_map, layername);
if (l)
l->setVisible(cb->isChecked());
else
qDebug() << LOGFUNCTION << " no layer!!!, layername=" << layername;
}
void SimpleEsriLayer::opacity(int)
{
SimpleEsriLayerSlider *sl = qobject_cast<SimpleEsriLayerSlider *>(sender());
if (!sl)
return;
QString layername = sl->m_layername;
double value = sl->value() / 100.0;
Esri::ArcGISRuntime::Layer *l = getEsriBasemap_Layer(d->m_map, layername);
if (l)
{
qDebug() << LOGFUNCTION << " layername=" << layername << " set to val=" << value;
l->setOpacity(value);
}
else
qWarning() << LOGFUNCTION << " no layer!!!, layername=" << layername;
}
void SimpleEsriLayer::brightness(int)
{
SimpleEsriLayerSlider *sl = qobject_cast<SimpleEsriLayerSlider *>(sender());
if (!sl)
return;
QString layername = sl->m_layername;
Esri::ArcGISRuntime::ArcGISTiledLayer *l = getEsriBasemap_ArcGISTiledLayer(d->m_map, layername);
double value = sl->value() / 100.0;
// double value = sl->value();
qDebug() << LOGFUNCTION << " layername=" << layername << " set to val=" << value;
l->setBrightness(value);
}
void SimpleEsriLayer::contrast(int)
{
SimpleEsriLayerSlider *sl = qobject_cast<SimpleEsriLayerSlider *>(sender());
if (!sl)
return;
QString layername = sl->m_layername;
Esri::ArcGISRuntime::ArcGISTiledLayer *l = getEsriBasemap_ArcGISTiledLayer(d->m_map, layername);
double value = sl->value() / 100.0;
// double value = sl->value();
qDebug() << LOGFUNCTION << " layername=" << layername << " set to val=" << value;
l->setContrast(value);
}
void SimpleEsriLayer::gamma(int)
{
SimpleEsriLayerSlider *sl = qobject_cast<SimpleEsriLayerSlider *>(sender());
if (!sl)
return;
QString layername = sl->m_layername;
Esri::ArcGISRuntime::ArcGISTiledLayer *l = getEsriBasemap_ArcGISTiledLayer(d->m_map, layername);
double value = sl->value() / 100.0;
// double value = sl->value();
qDebug() << LOGFUNCTION << " layername=" << layername << " set to val=" << value;
l->setGamma(value);
}
} // namespace SituationMap
@@ -0,0 +1,79 @@
/**
* @RDE_HEADER@
* FunctionDialog
* $Id$
* $HeadURL$
* $Author$
*/
#pragma once
#include <QObject>
#include <QSlider>
// ESRI
#include <Map.h>
#include <MapGraphicsView.h>
#include <GraphicsOverlay.h>
//----------------------------------------------------------------------------
namespace SituationMap
{
class SimpleEsriLayerSlider : public QSlider
{
Q_OBJECT
public:
SimpleEsriLayerSlider(const QString &layername, int min, int max)
: QSlider(), m_layername(layername)
{
this->setOrientation(Qt::Horizontal);
setMinimum(min);
setMaximum(max);
}
public:
QString m_layername;
};
class SimpleEsriLayer : public QWidget
{
Q_OBJECT
public:
SimpleEsriLayer(QWidget *parent, Esri::ArcGISRuntime::MapGraphicsView *mapView);
virtual ~SimpleEsriLayer();
SimpleEsriLayer(const SimpleEsriLayer &other) = delete; // No copy
SimpleEsriLayer &operator=(const SimpleEsriLayer &other) = delete; // No copy
bool updatePanel();
private slots:
void layerOnOff();
void opacity(int);
void brightness(int);
void contrast(int);
void gamma(int);
private :
class Private;
/**
* The private d-pointer to not break BC when changing internals of this class
*/
Private *d = nullptr;
};
} // namespace SituationMap
//----------------------------------------------------------------------------
// Q_DECLARE_METATYPE(SituationMap::GeometryType);
@@ -0,0 +1,156 @@
/* XPM */
static const char * stateIconA_xpm[] = {
"24 24 129 2",
" c None",
". c #4CE146",
"+ c #9E8E3A",
"@ c #4CE045",
"# c #BDAB46",
"$ c #A3912F",
"% c #4BDF44",
"& c #32942E",
"* c #B8C14A",
"= c #CABF35",
"- c #4ADE43",
"; c #F2DA55",
"> c #A7973C",
", c #CDC74E",
"' c #E1D132",
") c #347D25",
"! c #48DD42",
"~ c #E7CF4C",
"{ c #F7D519",
"] c #F8DB3E",
"^ c #9D8E38",
"/ c #E3CC50",
"( c #F6D629",
"_ c #56821F",
": c #37AA32",
"< c #47DB41",
"[ c #DAC54B",
"} c #F6D51F",
"| c #F5D210",
"1 c #F5D211",
"2 c #F5DA3F",
"3 c #819D38",
"4 c #E8D14F",
"5 c #F6D522",
"6 c #A48D0C",
"7 c #46DA40",
"8 c #C3B445",
"9 c #F4D425",
"0 c #F3D00E",
"a c #C9BF13",
"b c #F3D00F",
"c c #F2D840",
"d c #8FAA3D",
"e c #E7D54D",
"f c #F4D31B",
"g c #D4B50C",
"h c #45D93E",
"i c #AC9B3C",
"j c #F3D52C",
"k c #EBCC0D",
"l c #7D9516",
"m c #CCAE0A",
"n c #F1CE0C",
"o c #F1CE0E",
"p c #F4D738",
"q c #F1D015",
"r c #DFC70E",
"s c #43D73D",
"t c #8E7F31",
"u c #F0D434",
"v c #DBC50D",
"w c #588019",
"x c #D6B709",
"y c #EFCC0A",
"z c #EDCB0A",
"A c #5B8F1F",
"B c #42D63B",
"C c #ECD23C",
"D c #C9BA0D",
"E c #3A7F1F",
"F c #DEBD07",
"G c #EDCA08",
"H c #A39309",
"I c #2E972A",
"J c #40D43A",
"K c #E7CF41",
"L c #C2A60A",
"M c #27701E",
"N c #33A92E",
"O c #C1A405",
"P c #38BB32",
"Q c #DCC543",
"R c #9D8709",
"S c #37B931",
"T c #3FD338",
"U c #24711E",
"V c #C2B33F",
"W c #3DD137",
"X c #C8B54A",
"Y c #83A134",
"Z c #3D6517",
"` c #3CD036",
" . c #E4CA37",
".. c #EDD035",
"+. c #29731E",
"@. c #F6D726",
"#. c #F9D821",
"$. c #3ACF34",
"%. c #39CD33",
"&. c #8F8132",
"*. c #F6D414",
"=. c #F6D311",
"-. c #AD9B39",
";. c #38CC32",
">. c #C9B337",
",. c #D9BF33",
"'. c #37CB30",
"). c #E9CB29",
"!. c #F1CD0C",
"~. c #EFD022",
"{. c #36CA2F",
"]. c #EFCD12",
"^. c #EECB09",
"/. c #EECC0C",
"(. c #8C7E2F",
"_. c #35C92E",
":. c #B29F34",
"<. c #EBC806",
"[. c #C4AD31",
"}. c #D7BD29",
"|. c #E8C503",
"1. c #E4C722",
"2. c #E8C714",
"3. c #E7C402",
"4. c #E8C508",
"5. c #97872E",
"6. c #E5C201",
"7. c #E5C200",
"8. c #B8A330",
" ",
" . . . . . . . . + ",
" @ @ @ @ # $ ",
" % & * = ",
" - ; > , ' ) ",
" ! ~ { ] ^ / ( _ : ",
" < [ } | 1 2 3 4 5 6 < ",
" 7 8 9 0 a 0 b c d e f g 7 ",
" h i j k l m n o p q r h ",
" s t u v w x y y z A s ",
" B C D E F G H I B ",
" J K L M N O J ",
" P Q R S T ",
" U V W # X W W ",
" Y Z ` ... ` ` ",
" +. @.#. $. $. ",
" %. &.*.=.-. %. ",
" ;. >.0 0 ,. ;. ",
" '. ).!.!.~. '. ",
" {. ].^.^./.(. {. ",
" _. :.<.<.<.<.[. _. ",
" }.|.|.|.|.1. ",
" 2.3.3.3.3.4. ",
" 5.6.7.7.7.7.7.8. "};
@@ -0,0 +1,216 @@
/* XPM */
static const char * stateIconB_xpm[] = {
"24 24 189 2",
" c None",
". c #4A8448",
"+ c #69BC66",
"@ c #75D272",
"# c #7ADA76",
"$ c #77D673",
"% c #6CC269",
"& c #508E4D",
"* c #61AE5E",
"= c #7EE57A",
"- c #73E76E",
"; c #64E55F",
"> c #5BE355",
", c #57E351",
"' c #59E353",
") c #62E55D",
"! c #71E76C",
"~ c #7EE779",
"{ c #68BB65",
"] c #7BE076",
"^ c #69E563",
"/ c #50E149",
"( c #46CE40",
"_ c #34982E",
": c #44C93E",
"< c #4EE047",
"[ c #65E45F",
"} c #7CE377",
"| c #4A8447",
"1 c #51934E",
"2 c #75E56F",
"3 c #51E04B",
"4 c #48D541",
"5 c #46D140",
"6 c #4FE048",
"7 c #71E56B",
"8 c #59A056",
"9 c #6EE368",
"0 c #4BDE44",
"a c #42C73C",
"b c #40BF3A",
"c c #6AE364",
"d c #4C894A",
"e c #6EDF69",
"f c #49DD43",
"g c #40C63B",
"h c #3FC13A",
"i c #6CE068",
"j c #66BD62",
"k c #4BDC45",
"l c #44D03E",
"m c #5EAB5B",
"n c #75D571",
"o c #42CD3D",
"p c #65C062",
"q c #5CDE57",
"r c #46DA40",
"s c #74D670",
"t c #64E05F",
"u c #52DC4C",
"v c #44CF3E",
"w c #5BDD56",
"x c #5AA956",
"y c #46D93F",
"z c #3EC438",
"A c #6DD168",
"B c #4FDB49",
"C c #3CBC36",
"D c #6DD268",
"E c #58A954",
"F c #57C352",
"G c #43D73D",
"H c #389234",
"I c #569F53",
"J c #50DA4A",
"K c #3ABA35",
"L c #3ABB35",
"M c #4FDA49",
"N c #5BA758",
"O c #58C553",
"P c #50D04B",
"Q c #42D63B",
"R c #5CCA57",
"S c #5BCE56",
"T c #50D049",
"U c #46D240",
"V c #40D43A",
"W c #4CD146",
"X c #3ECE38",
"Y c #3DCB38",
"Z c #4AD545",
"` c #41CF3A",
" . c #3FD338",
".. c #42CF3B",
"+. c #43D03C",
"@. c #45CF3E",
"#. c #40D139",
"$. c #41CE3A",
"%. c #3EC738",
"&. c #3DD137",
"*. c #3ABC35",
"=. c #41D23B",
"-. c #BDAB46",
";. c #C8B54A",
">. c #42D23C",
",. c #3ABF35",
"'. c #3BB136",
"). c #3CD036",
"!. c #53A74F",
"~. c #2F812B",
"{. c #64CF60",
"]. c #E4CA37",
"^. c #EDD035",
"/. c #66CF62",
"(. c #30852C",
"_. c #51A44D",
":. c #3DB637",
"<. c #338530",
"[. c #3ACF34",
"}. c #55CF51",
"|. c #33B72E",
"1. c #42CF3D",
"2. c #F6D726",
"3. c #F9D821",
"4. c #3A6E37",
"5. c #44D13E",
"6. c #35BD2F",
"7. c #55CC51",
"8. c #348930",
"9. c #38CA32",
"0. c #3FCF39",
"a. c #57A654",
"b. c #278723",
"c. c #8F8132",
"d. c #F6D414",
"e. c #F6D311",
"f. c #AD9B39",
"g. c #2EA72A",
"h. c #519A4E",
"i. c #42CF3C",
"j. c #2C9928",
"k. c #38CC32",
"l. c #56D351",
"m. c #C9B337",
"n. c #F3D00E",
"o. c #D9BF33",
"p. c #5AD256",
"q. c #2E9F2A",
"r. c #34C02D",
"s. c #38CB31",
"t. c #62D25D",
"u. c #E9CB29",
"v. c #F1CD0C",
"w. c #EFD022",
"x. c #64CD5F",
"y. c #3ACC33",
"z. c #34BF2D",
"A. c #35C62E",
"B. c #3BCB34",
"C. c #67D261",
"D. c #EFCD12",
"E. c #EECB09",
"F. c #EECC0C",
"G. c #8C7E2F",
"H. c #6ACF65",
"I. c #3FCC39",
"J. c #34C42D",
"K. c #39CA32",
"L. c #5BC656",
"M. c #B29F34",
"N. c #EBC806",
"O. c #C4AD31",
"P. c #63CD5E",
"Q. c #3ECB37",
"R. c #34C52D",
"S. c #30B82A",
"T. c #2B8327",
"U. c #D7BD29",
"V. c #E8C503",
"W. c #E4C722",
"X. c #2D9428",
"Y. c #2FB72A",
"Z. c #E8C714",
"`. c #E7C402",
" + c #E8C508",
".+ c #97872E",
"++ c #E5C201",
"@+ c #E5C200",
"#+ c #B8A330",
" . + @ # # $ % & ",
" * = - ; > , , ' ) ! ~ { ",
" ] ^ / ( _ : < [ } | ",
" 1 2 3 4 5 6 7 8 ",
" 9 0 a b 0 c d ",
" e f g h f i ",
" j k l m n = = n m o k p ",
" q r s t u v v u t s r w ",
"x y z A B C C B D z y E ",
"F G H I J K L M N H G O ",
"P Q R Q Q S Q T ",
"U V W X Y Z V U ",
"` . ..+. @.#. .$.",
"%.&. *.=. -.;. >.,. &.%.",
"'.).!. ~.).{. ].^. /.).(. _.).:.",
"<.[.}. |.1. 2.3. 4.5.6. 7.[.8.",
" 9.0.a. b. c.d.e.f. g. h.i.9. ",
" j.k.l. m.n.n.o. p.k.q. ",
" r.s.t. u.v.v.w. x.y.z. ",
" A.B.C. D.E.E.F.G. H.I.A. ",
" J.K.L. M.N.N.N.N.O. P.Q.R. ",
" S.T. U.V.V.V.V.W. X.Y. ",
" Z.`.`.`.`. + ",
" .+++@+@+@+@+@+#+ "};
@@ -0,0 +1,110 @@
/* XPM */
static const char * stateIconC_xpm[] = {
"24 24 83 1",
" c None",
". c #7FBD7C",
"+ c #8BCF88",
"@ c #84C582",
"# c #588456",
"$ c #63BE5F",
"% c #57B953",
"& c #73BF70",
"* c #56B752",
"= c #499B45",
"- c #699F66",
"; c #59B755",
"> c #54B550",
", c #52B14E",
"' c #6ABC67",
") c #52B34E",
"! c #377334",
"~ c #6FAF6C",
"{ c #50B24C",
"] c #4FB14B",
"^ c #48A144",
"/ c #4C734A",
"( c #5DB559",
"_ c #4DAE49",
": c #4CAD48",
"< c #6BB569",
"[ c #4AAC46",
"} c #377F35",
"| c #5E915C",
"1 c #50AD4C",
"2 c #48A944",
"3 c #44A040",
"4 c #61B05E",
"5 c #45A641",
"6 c #527F50",
"7 c #7BBF78",
"8 c #78BA75",
"9 c #639C60",
"0 c #46A542",
"a c #42A33E",
"b c #368633",
"c c #389035",
"d c #3FA13B",
"e c #43A33F",
"f c #619B5E",
"g c #56AC53",
"h c #3D9D39",
"i c #3B9C37",
"j c #3C9E38",
"k c #54A951",
"l c #64A761",
"m c #3D9E39",
"n c #2A6B26",
"o c #3A9B35",
"p c #3B9B36",
"q c #62A55F",
"r c #4B7749",
"s c #48A243",
"t c #33892F",
"u c #328B2F",
"v c #379833",
"w c #459F41",
"x c #4F7E4D",
"y c #5CA659",
"z c #369632",
"A c #349530",
"B c #349630",
"C c #59A955",
"D c #3A9936",
"E c #276C25",
"F c #256C22",
"G c #32932E",
"H c #2F892B",
"I c #2C8728",
"J c #2F912B",
"K c #2F902B",
"L c #2D8E29",
"M c #2D8F29",
"N c #257322",
"O c #226E1F",
"P c #2B8D27",
"Q c #298826",
"R c #288424",
" ",
" ",
" .+++@ ",
" #$%%% ",
" &***= ",
" -;>>, ",
" ')))! ",
" ~{]]^ ",
" /(__: ",
" <[[[} ",
" |1223 ",
" 4555 ",
" 67778 90aab ",
" cddef gddh ",
" ijjk lmjj ",
" noopq rsoot ",
" uvvwxyvvz ",
" ABBCDBBE ",
" FGGGGGH ",
" IJJJK ",
" LMMN ",
" OPQ ",
" R ",
" "};
@@ -0,0 +1,445 @@
"id";"name";"sym_klassifiz_id";"name";"symbol_id_code";"id";"name";"def_symbol_id"
"611";"ADMINISTRATIVE FINANCE";"331";"FINANCE";"S*G*USAF--*****";"(null)";"(null)";"(null)"
"609";"ADMINISTRATIVE JUDGE ADVOCATE GENERAL (JAG)";"325";"JUDGEADVOCATEGENERAL(JAG)";"S*G*USAJ--*****";"(null)";"(null)";"(null)"
"606";"ADMINISTRATIVE LABOUR";"355";"LABOUR";"S*G*USAL--*****";"(null)";"(null)";"(null)"
"607";"ADMINISTRATIVE MORAL, WELFARE, RECREATION (MWR)";"358";"MORAL,WELFARE,RECREATION(MWR)";"S*G*USAW--*****";"(null)";"(null)";"(null)"
"613";"ADMINISTRATIVE MORTUARY/GRAVE REGISTRY";"337";"MORTUARY/GRAVESREGISTRY";"S*G*USAM--*****";"(null)";"(null)";"(null)"
"612";"ADMINISTRATIVE PERSONNEL SERVICES";"334";"PERSONNELSERVICES";"S*G*USAS--*****";"(null)";"(null)";"(null)"
"610";"ADMINISTRATIVE POSTAL";"328";"POSTAL";"S*G*USAO--*****";"(null)";"(null)";"(null)"
"615";"ADMINISTRATIVE PUPLIC AFFAIRS";"343";"PUBLICAFFAIRS";"S*G*USAP--*****";"(null)";"(null)";"(null)"
"608";"ADMINISTRATIVE QUARTERMASTER (";"361";"QUARTERMASTER(SUPPLY)";"S*G*USAQ--*****";"(null)";"(null)";"(null)"
"614";"ADMINISTRATIVE RELIGIOUS/CHAPLAIN";"340";"RELIGIOUS/CHAPLAIN";"S*G*USAR--*****";"(null)";"(null)";"(null)"
"605";"ADMINISTRATIVE REPLACEMENT HOLDING UNIT (RHV)";"352";"REPLACEMENTHOLDINGUNIT(RHU)";"S*G*USAX--*****";"(null)";"(null)";"(null)"
"364";"AIR DEFENCE";"79";"AIRDEFENCE";"S*G*UCD---*****";"(null)";"(null)";"(null)"
"664";"AIR DEFENCE (AD) MISSILE LAUNC";"471";"AIRDEFENCE(AD)MISSILELAUNCH";"S*G*EWMA--*****";"(null)";"(null)";"(null)"
"379";"AIR DEFENCE COMPOSITE";"90";"COMPOSITE";"S*G*UCDC--*****";"(null)";"(null)";"(null)"
"367";"Air Defence COY";"79";"AIRDEFENCE";"S*G*UCD---*****";"(null)";"(null)";"(null)"
"683";"AIR DEFENCE GUN";"527";"AIRDEFENCEGUN";"S*G*EWA---*****";"(null)";"(null)";"(null)"
"686";"AIR DEFENCE GUN HEAVY";"530";"AIRDEFENCEGUNHEAVY";"S*G*EWAH--*****";"(null)";"(null)";"(null)"
"684";"AIR DEFENCE GUN LIGHT";"528";"AIRDEFENCEGUNLIGHT";"S*G*EWAL--*****";"(null)";"(null)";"(null)"
"685";"AIR DEFENCE GUN MEDIUM";"529";"AIRDEFENCEGUNMEDIUM";"S*G*EWAM--*****";"44";"Soldier Air Defence";"685"
"378";"AIR DEFENCE GUN UNIT";"89";"GUNUNIT";"S*G*UCDG--*****";"(null)";"(null)";"(null)"
"377";"AIR DEFENCE H/MAD";"88";"H/MAD";"S*G*UCDH--*****";"(null)";"(null)";"(null)"
"372";"AIR DEFENCE MISSILE";"83";"AIRDEFENCEMISSILE";"S*G*UCDM--*****";"(null)";"(null)";"(null)"
"376";"AIR DEFENCE MISSILE HEAVY";"87";"AIRDEFENCEMISSILEHEAVY";"S*G*UCDMH-*****";"(null)";"(null)";"(null)"
"373";"AIR DEFENCE MISSILE LIGHT";"84";"AIRDEFENCEMISSILELIGHT";"S*G*UCDML-*****";"229";"Legatus Wiesel";"373"
"375";"AIR DEFENCE MISSILE MEDIUM";"86";"AIRDEFENCEMISSILEMEDIUM";"S*G*UCDMM-*****";"(null)";"(null)";"(null)"
"374";"AIR DEFENCE MISSILE MOTORIZED";"85";"AIRDEFENCEMISSILEMOTORIZED";"S*G*UCDMLA*****";"(null)";"(null)";"(null)"
"369";"AIR DEFENCE SHORT RANGE";"80";"SHORTRANGE";"S*G*UCDS--*****";"(null)";"(null)";"(null)"
"371";"AIR DEFENCE SHORT RANGE GUN";"82";"GUN";"S*G*UCDS--*****";"(null)";"(null)";"(null)"
"370";"AIR DEFENCE SHORT RANGE MISSILE";"81";"MISSILE";"S*G*UCDS--*****";"(null)";"(null)";"(null)"
"380";"AIR DEFENCE TARGETING UNIT";"91";"TARGETINGUNIT";"S*G*UCDT--*****";"(null)";"(null)";"(null)"
"381";"AIR DEFENCE THEATRE MISSILE DEFENCE UNIT";"92";"THEATREMISSILEDEFENCEUNIT";"S*G*UCDO--*****";"(null)";"(null)";"(null)"
"781";"AIRPORT/AIRBASE";"605";"AIRPORT/AIRBASE";"S*G*IBA---H****";"(null)";"(null)";"(null)"
"342";"AIR TRACK";"6";"AIRTRACK";"S*A*------*****";"(null)";"(null)";"(null)"
"777";"AMMUNITION AND EXPLOSIVES PRODUCTION";"595";"AMMUNITIONANDEXPLOSIVESPRODUCTION";"S*G*IME---H****";"(null)";"(null)";"(null)"
"788";"AMPHIBIOUS WARFARE SHIP";"620";"AMPHIBIOUSWARFARESHIP";"S*S*CA----*****";"(null)";"(null)";"(null)"
"414";"ANTI ARMOUR";"110";"ANTIARMOUR";"S*G*UCAA--*****";"(null)";"(null)";"(null)"
"422";"ANTI ARMOUR AIR ASSAULT";"114";"ANTIARMOURAIRASSAULT";"S*G*UCAAS-*****";"(null)";"(null)";"(null)"
"421";"ANTI ARMOUR AIRBORNE";"113";"ANTIARMOURAIRBORNE";"S*G*UCAAM-*****";"(null)";"(null)";"(null)"
"424";"ANTI ARMOUR ARMOURED";"117";"ANTIARMOURARMOURED";"S*G*UCAAA-*****";"(null)";"(null)";"(null)"
"427";"ANTI ARMOUR ARMOURED AIR ASSAU";"120";"ANTIARMOURARMOUREDAIRASSAULT";"S*G*UCAAAS*****";"(null)";"(null)";"(null)"
"425";"ANTI ARMOUR ARMOURED TRACKED";"118";"ANTIARMOURARMOUREDTRACKED";"S*G*UCAAAT*****";"(null)";"(null)";"(null)"
"426";"ANTI ARMOUR ARMOURED WHEELED";"119";"ANTIARMOURARMOUREDWHEELED";"S*G*UCAAAW*****";"(null)";"(null)";"(null)"
"419";"ANTI ARMOUR DISMOUNTED";"111";"ANTIARMOURDISMOUNTED";"S*G*UCAAD-*****";"(null)";"(null)";"(null)"
"420";"ANTI ARMOUR LIGHT";"112";"ANTIARMOURLIGHT";"S*G*UCAAL-*****";"(null)";"(null)";"(null)"
"428";"ANTI ARMOUR MOTORIZED";"121";"ANTIARMOURMOTORIZED";"S*G*UCAAO-*****";"(null)";"(null)";"(null)"
"429";"ANTI ARMOUR MOTORIZED AIR ASSA";"122";"ANTIARMOURMOTORIZEDAIRASSAULT";"S*G*UCAAOS*****";"(null)";"(null)";"(null)"
"423";"ANTI ARMOUR MOUNTAIN";"115";"ANTIARMOURMOUNTAIN";"S*G*UCAAU-*****";"(null)";"(null)";"(null)"
"718";"ANTITANK GUN";"515";"ANTITANKGUN";"S*G*EWG---*****";"130";"Soldier AT (RPG7)";"718"
"722";"ANTITANK GUN HEAVY";"519";"ANTITANKGUNHEAVY";"S*G*EWGH--*****";"(null)";"(null)";"(null)"
"720";"ANTITANK GUN LIGHT";"517";"ANTITANKGUNLIGHT";"S*G*EWGL--*****";"(null)";"(null)";"(null)"
"721";"ANTITANK GUN MEDIUM";"518";"ANTITANKGUNMEDIUM";"S*G*EWGM--*****";"(null)";"(null)";"(null)"
"719";"ANTITANK GUN RECOILLESS";"516";"ANTITANKGUNRECOILLESS";"S*G*EWGR--*****";"(null)";"(null)";"(null)"
"695";"ANTITANK ROCKET LAUNCHER";"492";"ANTITANKROCKETLAUNCHER";"S*G*EWT---*****";"(null)";"(null)";"(null)"
"698";"ANTITANK ROCKET LAUNCHER HEAVY";"495";"ANTITANKROCKETLAUNCHERHEAVY";"S*G*EWTH--*****";"(null)";"(null)";"(null)"
"696";"ANTITANK ROCKET LAUNCHER LIGHT";"493";"ANTITANKROCKETLAUNCHERLIGHT";"S*G*EWTL--*****";"(null)";"(null)";"(null)"
"697";"ANTITANK ROCKET LAUNCHER MEDIU";"494";"ANTITANKROCKETLAUNCHERMEDIUM";"S*G*EWTM--*****";"(null)";"(null)";"(null)"
"392";"ARMOUR";"93";"ARMOUR";"S*G*UCA---*****";"(null)";"(null)";"(null)"
"752";"ARMOURED CARRIER WITH SCATTERA";"561";"ARMOUREDCARRIERWITHSCATTERABLEMINES";"S*G*EVEMSM*****";"(null)";"(null)";"(null)"
"734";"ARMOURED INFANTRY";"542";"ARMOUREDINFANTRY";"S*G*EVAI--*****";"(null)";"(null)";"(null)"
"732";"ARMOURED PERSONNEL CARRIER";"540";"ARMOUREDPERSONNELCARRIER";"S*G*EVAA--*****";"(null)";"(null)";"(null)"
"733";"ARMOURED PERSONNEL CARRIER REC";"541";"ARMOUREDPERSONNELCARRIERRECOVERY";"S*G*EVAAR-*****";"(null)";"(null)";"(null)"
"724";"ARMOURED VEHICLE";"532";"ARMOUREDVEHICLE";"S*G*EVA---*****";"231";"Marder";"724"
"750";"ARMOURED VEHICLE MOUNTED";"558";"ARMOUREDVEHICLEMOUNTED";"S*G*EVEMA-*****";"(null)";"(null)";"(null)"
"397";"ARMOUR TRACK";"94";"ARMOURTRACK";"S*G*UCAT--*****";"(null)";"(null)";"(null)"
"398";"ARMOUR TRACK AIRBORNE";"95";"ARMOURTRACKAIRBORNE";"S*G*UCATA-*****";"(null)";"(null)";"(null)"
"399";"ARMOUR TRACK AMPHIBIOUS";"96";"ARMOURTRACKAMPHIBIOUS";"S*G*UCATW-*****";"(null)";"(null)";"(null)"
"400";"ARMOUR TRACK AMPHIBIOUS RECOVE";"97";"ARMOURTRACKAMPHIBIOUSRECOVERY";"S*G*UCATWR*****";"(null)";"(null)";"(null)"
"403";"ARMOUR TRACK HEAVY";"100";"ARMOURTRACK,HEAVY";"S*G*UCATH-*****";"(null)";"(null)";"(null)"
"401";"ARMOUR TRACK LIGHT";"98";"ARMOURTRACK,LIGHT";"S*G*UCATL-*****";"(null)";"(null)";"(null)"
"402";"ARMOUR TRACK MEDIUM";"99";"ARMOURTRACK,MEDIUM";"S*G*UCATM-*****";"(null)";"(null)";"(null)"
"404";"ARMOUR TRACK RECOVERY";"101";"ARMOURTRACK,RECOVERY";"S*G*UCATR-*****";"(null)";"(null)";"(null)"
"405";"ARMOUR WHEELED";"102";"ARMOUR,WHEELED";"S*G*UCAW--*****";"(null)";"(null)";"(null)"
"406";"ARMOUR WHEELED AIR ASSAULT";"103";"ARMOUR,WHEELEDAIRASSAULT";"S*G*UCAWS-*****";"(null)";"(null)";"(null)"
"407";"ARMOUR WHEELED AIRBORNE";"104";"ARMOUR,WHEELEDAIRBORNE";"S*G*UCAWA-*****";"227";"BMP3 IFV";"407"
"408";"ARMOUR WHEELED AMPHIBIOUS";"105";"ARMOUR,WHEELEDAMPHIBIOUS";"S*G*UCAWA-*****";"(null)";"(null)";"(null)"
"409";"ARMOUR WHEELED AMPHIBIOUS RECO";"1325";"ARMOURWHEELEDAMPHIBIOUSRECOVERY";"S*G*UCAWWR*****";"(null)";"(null)";"(null)"
"412";"ARMOUR WHEELED HEAVY";"108";"ARMOUR,WHEELEDHEAVY";"S*G*UCAWH-*****";"(null)";"(null)";"(null)"
"410";"ARMOUR WHEELED LIGHT";"106";"ARMOUR,WHEELEDLIGHT";"S*G*UCAWL-*****";"(null)";"(null)";"(null)"
"411";"ARMOUR WHEELED MEDIUM";"107";"ARMOUR,WHEELEDMEDIUM";"S*G*UCAWM-*****";"(null)";"(null)";"(null)"
"413";"ARMOUR WHEELED RECOVERY";"109";"ARMOUR,WHEELEDRECOVERY";"S*G*UCAWR-*****";"10";"Armored Recovery Vehicle";"413"
"789";"ASSAULT VESSEL";"621";"ASSAULTVESSEL";"S*S*CALA--*****";"(null)";"(null)";"(null)"
"776";"ATOMIC ENERGY PRODUCTION";"593";"ATOMICENERGYPRODUCTION";"S*G*IMF---H****";"(null)";"(null)";"(null)"
"430";"AVIATION";"123";"AVIATION";"S*G*UCV---*****";"(null)";"(null)";"(null)"
"431";"AVIATION FIXED WING";"124";"FIXEDWING";"S*G*UCVF--*****";"(null)";"(null)";"(null)"
"433";"AVIATION FIXED WING ATTACK";"126";"ATTACKFIXEDWING";"S*G*UCVFA-*****";"(null)";"(null)";"(null)"
"436";"AVIATION FIXED WING RECON";"129";"RECONFIXEDWING";"S*G*UCVFR-*****";"(null)";"(null)";"(null)"
"432";"AVIATION FIXED WING UTILITY";"125";"UTILITYFIXEDWING";"S*G*UCVFU-*****";"(null)";"(null)";"(null)"
"435";"AVIATION FORWARD AIR CONTROLLER (FAC)";"128";"FORWARDAIRCONTROLLER(FAC)";"S*G*UCVUFC*****";"(null)";"(null)";"(null)"
"437";"AVIATION ROTARY WING";"130";"ROTARYWING";"S*G*UCVR--*****";"(null)";"(null)";"(null)"
"440";"AVIATION ROTARY WING C2";"138";"C2ROTARYWING";"S*G*UCVRUC*****";"(null)";"(null)";"(null)"
"441";"AVIATION ROTARY WING MEDEVAC";"139";"MEDEVACROTARYWING";"S*G*UCVRUE*****";"(null)";"(null)";"(null)"
"439";"AVIATION ROTARY WING UTILITY";"134";"UTILITYROTARYWING";"S*G*UCVRU-*****";"(null)";"(null)";"(null)"
"434";"AVIATION TACTICAL AIR CONTROL";"127";"TACTICALAIRCONTROLPARTY(TACP)";"S*G*UCVUTP*****";"(null)";"(null)";"(null)"
"445";"AVIATION UAV CONTROL";"1326";"AVIATIONUAVCONTROL";"S*G*UCVU--*****";"(null)";"(null)";"(null)"
"446";"AVIATION UAV LAUNCHER";"1327";"AVIATIONUAVLAUNCHER";"S*G*UCVU--*****";"(null)";"(null)";"(null)"
"447";"AVIATION UAV RECOVERY";"1337";"AVIATIONUAVRECOVERY";"S*G*UCVU--*****";"(null)";"(null)";"(null)"
"444";"AVIATION UNMANNED AERIAL VEHIC";"145";"UNMANNEDAERIALVEHICLEFIXEDWING";"S*G*UCVUF-*****";"(null)";"(null)";"(null)"
"448";"AVIATION UNMANNED AERIAL VEHICLE ROTARY WING";"146";"UNMANNEDAERIALVEHICLEROTARYWING";"S*G*UCVUR-*****";"(null)";"(null)";"(null)"
"443";"AVIATION UNMANNED AVIATION VEH";"144";"UNMANNEDAERIALVEHICLE";"S*G*UCVU--*****";"(null)";"(null)";"(null)"
"442";"AVIATION VERTICAL/SHORT TAKEOF";"143";"VERTICAL/SHORTTAKEOFFANDLANDING(V/STOL)";"S*G*UCVV--*****";"(null)";"(null)";"(null)"
"769";"BIOLOGICAL";"581";"BIOLOGICAL";"S*G*IRNB--H****";"(null)";"(null)";"(null)"
"745";"BRIDGE";"553";"BRIDGE";"S*G*EVEB--*****";"(null)";"(null)";"(null)"
"778";"BRIDGE";"599";"BRIDGE";"S*G*IMNB--H****";"(null)";"(null)";"(null)"
"739";"BUS";"547";"BUS";"S*G*EVUB--*****";"(null)";"(null)";"(null)"
"735";"C2V/ACV";"543";"C2V/ACV";"S*G*EVAC--*****";"(null)";"(null)";"(null)"
"548";"CBRN";"256";"COMBATSUPPORTCBRN";"S*G*UUA---*****";"(null)";"(null)";"(null)"
"768";"CBRN";"580";"CBRN";"S*G*IRN---H****";"(null)";"(null)";"(null)"
"560";"CBRN BIOLOGICAL";"268";"BIOLOGICAL";"S*G*UUAB--*****";"(null)";"(null)";"(null)"
"561";"CBRN BIOLOGICAL RECON EQUIPPED";"269";"RECONEQUIPPED";"S*G*UUABR-*****";"(null)";"(null)";"(null)"
"549";"CBRN CHEMICAL";"257";"CHEMICAL";"S*G*UUAC--*****";"(null)";"(null)";"(null)"
"556";"CBRN CHEMICAL RECON";"264";"CHEMICALRECON";"S*G*UUACR-*****";"(null)";"(null)";"(null)"
"553";"CBRN CHEMICAL SMOKE";"261";"SMOKE";"S*G*UUACS-*****";"(null)";"(null)";"(null)"
"555";"CBRN CHEMICAL SMOKE ARMOUR";"263";"ARMOURSMOKE";"S*G*UUACSA*****";"(null)";"(null)";"(null)"
"550";"CBRN CHEMICAL SMOKE/DECON";"258";"SMOKE/DECON";"S*G*UUACC-*****";"(null)";"(null)";"(null)"
"551";"CBRN CHEMICAL SMOKE/DECON MECHANIZED";"259";"MECHANIZEDSMOKE/DECON";"S*G*UUACCK*****";"(null)";"(null)";"(null)"
"552";"CBRN CHEMICAL SMOKE/DECON MOTO";"260";"MOTORIZEDSMOKE/DECON";"S*G*UUACCM*****";"(null)";"(null)";"(null)"
"554";"CBRN CHEMICAL SMOKE MOTORIZED";"262";"MOTORIZEDSMOKE";"S*G*UUACSM*****";"(null)";"(null)";"(null)"
"557";"CBRN CHEMICAL WHEELED ARMOURED VEHICLE";"265";"CHEMICALWHEELEDARMOUREDVEHICLE";"S*G*UUACRW*****";"(null)";"(null)";"(null)"
"558";"CBRN CHEMICAL WHEELED ARMOURED VEHICLE RECONNAISAN";"266";"CHEMICALWHEELEDARMOUREDVEHICLERECONNAISSANCESURVEI";"S*G*UUACRS*****";"(null)";"(null)";"(null)"
"562";"CBRN DECON";"270";"DECONTAMINATION";"S*G*UUAD--*****";"(null)";"(null)";"(null)"
"564";"CBRN DECON EQUIPMENT";"1330";"CBRNDECONEQUIPMENT";"S*G*UUADE-*****";"(null)";"(null)";"(null)"
"565";"CBRN DECON EQUIPMENT/TROOP";"1331";"CBRNDECONEQUIPMENT/TROOP";"S*G*UUADET*****";"(null)";"(null)";"(null)"
"563";"CBRN DECON TROOP";"1329";"CBRNDECONTROOP";"S*G*UUADT-*****";"(null)";"(null)";"(null)"
"760";"CBRN EQUIPMENT";"571";"CBRNEQUIPMENT";"S*G*EXN---*****";"(null)";"(null)";"(null)"
"566";"CBRN LABORATORY";"1332";"CBRNLABORATORY";"S*G*UUAL--*****";"(null)";"(null)";"(null)"
"559";"CBRN NUCLEAR";"267";"NUCLEAR";"S*G*UUAN--*****";"(null)";"(null)";"(null)"
"770";"CHEMICAL";"582";"CHEMICAL";"S*G*IRNC--H****";"(null)";"(null)";"(null)"
"356";"CIVIL FIXED WING";"73";"FIXEDWING";"S*A*CF----*****";"(null)";"(null)";"(null)"
"755";"CIVILIAN VEHICLE";"565";"CIVILIANVEHICLE";"S*G*EVC---*****";"(null)";"(null)";"(null)"
"357";"CIVIL ROTARY WING";"74";"ROTARYWING";"S*A*CH----*****";"(null)";"(null)";"(null)"
"604";"COMBAT SERVICE SUPPORT";"321";"COMBATSERVICESUPPORT";"S*G*US----*****";"(null)";"(null)";"(null)"
"736";"COMBAT SERVICE SUPPORT VEHICLE";"544";"COMBATSERVICESUPPORTVEHICLE";"S*G*EVAS--*****";"(null)";"(null)";"(null)"
"547";"COMBAT SUPPORT";"255";"COMBATSUPPORT";"S*G*UU----*****";"(null)";"(null)";"(null)"
"748";"CONSTRUCTION VEHICLE";"556";"CONSTRUCTIONVEHICLE";"S*G*EVEC--*****";"(null)";"(null)";"(null)"
"742";"CROSS-COUNTRY TRUCK";"550";"CROSS-COUNTRYTRUCK";"S*G*EVUX--*****";"212";"TATRA Tanker Fuel";"742"
"742";"CROSS-COUNTRY TRUCK";"550";"CROSS-COUNTRYTRUCK";"S*G*EVUX--*****";"50";"Truck 2t off-road";"742"
"772";"DECON";"585";"DECON";"S*G*IPD---H****";"(null)";"(null)";"(null)"
"676";"DIRECT FIRE GUN";"520";"DIRECTFIREGUN";"S*G*EWD---*****";"(null)";"(null)";"(null)"
"681";"DIRECT FIRE GUN HEAVY";"525";"DIRECTFIREGUNHEAVY";"S*G*EWDH--*****";"(null)";"(null)";"(null)"
"682";"DIRECT FIRE GUN HEAVY SELF-PRO";"526";"DIRECTFIREGUNHEAVYSELF-PROPELLED";"S*G*EWDHS-*****";"(null)";"(null)";"(null)"
"677";"DIRECT FIRE GUN LIGHT";"521";"DIRECTFIREGUNLIGHT";"S*G*EWDL--*****";"(null)";"(null)";"(null)"
"678";"DIRECT FIRE GUN LIGHT SELF PRO";"522";"DIRECTFIREGUNLIGHTSELF-PROPELLED";"S*G*EWDLS-*****";"(null)";"(null)";"(null)"
"679";"DIRECT FIRE GUN MEDIUM";"523";"DIRECTFIREGUNMEDIUM";"S*G*EWDM--*****";"(null)";"(null)";"(null)"
"680";"DIRECT FIRE GUN MEDIUM SELF-PR";"524";"DIRECTFIREGUNMEDIUMSELF-PROPELLED";"S*G*EWDMS-*****";"(null)";"(null)";"(null)"
"753";"DOZER";"562";"DOZER";"S*G*EVED--*****";"215";"CAT Excavator";"753"
"746";"EARTHMOVER";"554";"EARTHMOVER";"S*G*EVEE--*****";"(null)";"(null)";"(null)"
"774";"ELCECTRIC POWER FACILITY";"590";"ELECTRICPOWERFACILITY";"S*G*IUE---H****";"(null)";"(null)";"(null)"
"758";"EMPLACED SENSOR";"568";"EMPLACEDSENSOR";"S*G*ESE---*****";"(null)";"(null)";"(null)"
"467";"ENGINEER";"159";"ENGINEER";"S*G*UCE---*****";"(null)";"(null)";"(null)"
"472";"ENGINEER COMBAT";"160";"ENGINEERCOMBAT";"S*G*UCEC--*****";"(null)";"(null)";"(null)"
"473";"ENGINEER COMBAT AIR ASSAULT";"161";"ENGINEERCOMBATAIRASSAULT";"S*G*UCECS-*****";"(null)";"(null)";"(null)"
"478";"ENGINEER COMBAT AIRBORNE";"162";"ENGINEERCOMBATAIRBORNE";"S*G*UCECA-*****";"(null)";"(null)";"(null)"
"475";"ENGINEER COMBAT BRIDGING";"171";"ENGINEERCOMBATBRIDGING";"S*G*UCEC--*****";"(null)";"(null)";"(null)"
"481";"ENGINEER COMBAT HEAVY";"166";"ENGINEERCOMBATHEAVY";"S*G*UCECH-*****";"(null)";"(null)";"(null)"
"479";"ENGINEER COMBAT LIGHT";"164";"ENGINEERCOMBATLIGHT";"S*G*UCECL-*****";"(null)";"(null)";"(null)"
"482";"ENGINEER COMBAT MECH (TRACK)";"167";"ENGINEERCOMBATMECHANIZED(TRACK)";"S*G*UCECT-*****";"(null)";"(null)";"(null)"
"480";"ENGINEER COMBAT MEDIUM";"165";"ENGINEERCOMBATMEDIUM";"S*G*UCECM-*****";"(null)";"(null)";"(null)"
"476";"ENGINEER COMBAT MINE CLEARING";"172";"ENGINEERCOMBATMINECLEARING";"S*G*UCEC--*****";"(null)";"(null)";"(null)"
"477";"ENGINEER COMBAT MINE LAYING";"173";"ENGINEERCOMBATMINELAYING";"S*G*UCEC--*****";"(null)";"(null)";"(null)"
"483";"ENGINEER COMBAT MOTORIZED";"168";"ENGINEERCOMBATMOTORIZED";"S*G*UCECW-*****";"(null)";"(null)";"(null)"
"484";"ENGINEER COMBAT MOUNTAIN";"169";"ENGINEERCOMBATMOUNTAIN";"S*G*UCECO-*****";"(null)";"(null)";"(null)"
"474";"ENGINEER COMBAT RECON";"170";"ENGINEERCOMBATRECON";"S*G*UCECR-*****";"(null)";"(null)";"(null)"
"485";"ENGINEER CONSTRUCTION";"175";"ENGINEERCONSTRUCTION";"S*G*UCEN--*****";"(null)";"(null)";"(null)"
"744";"ENGINEER VEHICLE";"552";"ENGINEERVEHICLE";"S*G*EVE---*****";"(null)";"(null)";"(null)"
"657";"ENVIRONMENTAL PROTECTION";"463";"ENVIRONMENTALPROTECTION";"S*G*USXEP-*****";"(null)";"(null)";"(null)"
"576";"EW CORPS";"280";"CORPS";"S*G*UUMSEC*****";"(null)";"(null)";"(null)"
"575";"EW THEATRE";"279";"THEATRE";"S*G*UUMSET*****";"(null)";"(null)";"(null)"
"602";"EXPLOSIVE ORDNANCE DISPOSAL";"317";"EXPLOSIVEORDINANCEDISPOSAL";"S*G*UUE---*****";"(null)";"(null)";"(null)"
"490";"FIELD ARTELLERY HOWITZER/GUN AIRBORNE";"181";"AIRBORNE";"S*G*UCFHA-*****";"(null)";"(null)";"(null)"
"495";"FIELD ARTELLERY HOWITZER/GUN AMPHIBIOUS";"187";"AMPHIBIOUS";"S*G*UCFHX-*****";"(null)";"(null)";"(null)"
"494";"FIELD ARTELLERY HOWITZER/GUN HEAVY";"186";"HEAVY";"S*G*UCFHH-*****";"(null)";"(null)";"(null)"
"492";"FIELD ARTELLERY HOWITZER/GUN LIGHT";"184";"LIGHT";"S*G*UCFHL-*****";"(null)";"(null)";"(null)"
"493";"FIELD ARTELLERY HOWITZER/GUN MEDIUM";"185";"MEDIUM";"S*G*UCFHM-*****";"(null)";"(null)";"(null)"
"491";"FIELD ARTELLERY HOWITZER/GUN MOUNTAIN";"183";"MOUNTAIN";"S*G*UCFHO-*****";"(null)";"(null)";"(null)"
"496";"FIELD ARTELLERY ROCKET";"188";"ROCKET";"S*G*UCFR--*****";"(null)";"(null)";"(null)"
"498";"FIELD ARTILEERY ROCKET SINGLE";"190";"SINGLEROCKETSELFPROPELLED";"S*G*UCFRSS*****";"(null)";"(null)";"(null)"
"486";"FIELD ARTILLERY";"177";"FIELDARTILLERY";"S*G*UCF---*****";"(null)";"(null)";"(null)"
"521";"FIELD ARTILLERY ARTILLERY SURV";"214";"ARTILLERYSURVEY";"S*G*UCFS--*****";"(null)";"(null)";"(null)"
"523";"FIELD ARTILLERY FIRE DIRECTION CENTRE";"224";"FIREDIRECTIONCENTRE";"S*G*UCF---*****";"(null)";"(null)";"(null)"
"487";"FIELD ARTILLERY HOWITZER/GUN";"178";"HOWITZER/GUN";"S*G*UCFH--*****";"(null)";"(null)";"(null)"
"489";"FIELD ARTILLERY HOWITZER/GUN AIR ASSAULT";"180";"AIRASSAULT";"S*G*UCFHS-*****";"(null)";"(null)";"(null)"
"488";"FIELD ARTILLERY HOWITZER/GUN SELF-PROPELLED";"179";"SELFPROPELLED";"S*G*UCFHE-*****";"(null)";"(null)";"(null)"
"522";"FIELD ARTILLERY METEOROLOGICAL";"219";"METEOROLOGICAL";"S*G*UCFO--*****";"(null)";"(null)";"(null)"
"513";"FIELD ARTILLERY MORTAR";"205";"MORTAR";"S*G*UCFM--*****";"(null)";"(null)";"(null)"
"514";"FIELD ARTILLERY MORTAR SP TRAC";"206";"SELFPROPELLED(SP)TRACKEDMORTAR";"S*G*UCFMS-*****";"(null)";"(null)";"(null)"
"515";"FIELD ARTILLERY MORTAR SP WHEE";"207";"SPWHEELEDMORTAR";"S*G*UCFMSW*****";"(null)";"(null)";"(null)"
"516";"FIELD ARTILLERY MORTAR TOWED";"208";"TOWEDMORTAR";"S*G*UCFMT-*****";"(null)";"(null)";"(null)"
"518";"FIELD ARTILLERY MORTAR TOWED A";"210";"TOWEDAIRASSAULTMORTAR";"S*G*UCFMTS*****";"(null)";"(null)";"(null)"
"517";"FIELD ARTILLERY MORTAR TOWED A";"209";"TOWEDAIRBORNEMORTAR";"S*G*UCFMTA*****";"(null)";"(null)";"(null)"
"519";"FIELD ARTILLERY MORTAR TOWED M";"212";"TOWEDMOUNTAINMORTAR";"S*G*UCFMTO*****";"(null)";"(null)";"(null)"
"524";"FIELD ARTILLERY OBERSERVER";"225";"OBERSERVER";"S*G*UCF---*****";"(null)";"(null)";"(null)"
"502";"FIELD ARTILLERY ROCKET MULTI R";"194";"MULTIROCKETSELFPROPELLED";"S*G*UCFRMS*****";"(null)";"(null)";"(null)"
"504";"FIELD ARTILLERY ROCKET MULTI ROCKET LAUNCER MULTI";"196";"MULTIROCKETTOWED";"S*G*UCFRMT*****";"(null)";"(null)";"(null)"
"503";"FIELD ARTILLERY ROCKET MULTI ROCKET LAUNCER MULTI";"195";"MULTIROCKETTRUCK";"S*G*UCFRMR*****";"(null)";"(null)";"(null)"
"501";"FIELD ARTILLERY ROCKET MULTI ROCKET LAUNCHER";"193";"MULTIROCKETLAUNCHER";"S*G*UCFRM-*****";"(null)";"(null)";"(null)"
"497";"FIELD ARTILLERY ROCKET SINGLE";"189";"SINGLEROCKETLAUNCHER";"S*G*UCFRS-*****";"(null)";"(null)";"(null)"
"499";"FIELD ARTILLERY ROCKET SINGLE ROCKET LAUNCHER SING";"191";"SINGLEROCKETTRUCK";"S*G*UCFRSR*****";"(null)";"(null)";"(null)"
"500";"FIELD ARTILLERY ROCKET SINGLE ROCKET LAUNCHER SING";"192";"SINGLEROCKETTOWED";"S*G*UCFRST*****";"(null)";"(null)";"(null)"
"506";"FIELD ARTILLERY TARGET ACQUISI";"198";"RADAR";"S*G*UCFTR-*****";"(null)";"(null)";"(null)"
"505";"FIELD ARTILLERY TARGET ACQUISITION";"197";"TARGETACQUISITION";"S*G*UCFT--*****";"(null)";"(null)";"(null)"
"510";"FIELD ARTILLERY TARGET ACQUISITION DISMOUNTED";"202";"TARGETACQUISITIONDISMOUNTED";"S*G*UCFTCD*****";"(null)";"(null)";"(null)"
"508";"FIELD ARTILLERY TARGET ACQUISITION FLASH (OPTICAL)";"200";"FLASH(OPTICAL)";"S*G*UCFTF-*****";"(null)";"(null)";"(null)"
"509";"FIELD ARTILLERY TARGET ACQUISITION MOUNTED";"201";"TARGETACQUISITIONMOUNTED";"S*G*UCFTC-*****";"(null)";"(null)";"(null)"
"512";"FIELD ARTILLERY TARGET ACQUISITION NAVAL GUNFIRE";"204";"TARGETACQUISITIONNAVALGUNFIRE";"S*G*UCFTA-*****";"(null)";"(null)";"(null)"
"507";"FIELD ARTILLERY TARGET ACQUISITION SOUND";"199";"SOUND";"S*G*UCFTS-*****";"(null)";"(null)";"(null)"
"511";"FIELD ARTILLERY TARGET ACQUISITION TRACKED";"203";"TARGETACQUISITIONTRACKED";"S*G*UCFTCM*****";"(null)";"(null)";"(null)"
"345";"FIXED WING DRONE (RPV/UAE)";"36";"DRONE(RPV/UAV)";"S*A*MFQ---*****";"(null)";"(null)";"(null)"
"761";"FLAME THROWER";"572";"FLAMETHROWER";"S*G*EXF---*****";"(null)";"(null)";"(null)"
"660";"GENERAL HEADQUATERS AND SERVICE";"466";"GENERALHEADQUARTERSANDSERVICE";"S*G*UH----*****";"(null)";"(null)";"(null)"
"779";"GOVERNMENT LEADERSHIP";"603";"GOVERNMENTLEADERSHIP";"S*G*IG----H****";"(null)";"(null)";"(null)"
"703";"GRENADE LAUNCHER";"500";"GRENADELAUNCHER";"S*G*EWZ---*****";"(null)";"(null)";"(null)"
"706";"GRENADE LAUNCHER HEAVY";"503";"GRENADELAUNCHERHEAVY";"S*G*EWZH--*****";"(null)";"(null)";"(null)"
"704";"GRENADE LAUNCHER LIGHT";"501";"GRENADELAUNCHERLIGHT";"S*G*EWZL--*****";"(null)";"(null)";"(null)"
"705";"GRENADE LAUNCHER MEDIUM";"502";"GRENADELAUNCHERMEDIUM";"S*G*EWZM--*****";"(null)";"(null)";"(null)"
"662";"GROUND TRACK EQUIPMENT";"468";"GROUNDTRACKEQUIPMENT";"S*G*E-----*****";"(null)";"(null)";"(null)"
"358";"GROUND TRACK UNIT";"77";"UNIT";"S*G*U-----*****";"217";"Soldier (Role Player)";"358"
"358";"GROUND TRACK UNIT";"77";"UNIT";"S*G*U-----*****";"106";"Soldier";"358"
"363";"GROUND TRACK UNIT COMBAT";"78";"COMBAT";"S*G*UC----*****";"(null)";"(null)";"(null)"
"520";"GROUND TRACK UNIT COMBAT FIELD ARTILLERY MORTAR AM";"213";"AMPHIBIOUSMORTAR";"S*G*UCFML-*****";"(null)";"(null)";"(null)"
"659";"GROUND TRACK UNIT GENERAL HEADQUATERS";"465";"UNITGENERALHEADQUARTERS";"S*G*UH----*****";"(null)";"(null)";"(null)"
"723";"GROUND VEHICLE";"531";"GROUNDVEHICLE";"S*G*EV----*****";"(null)";"(null)";"(null)"
"702";"HEAVY MACHINE GUN";"499";"HEAVYMACHINEGUN";"S*G*EWRH--*****";"129";"Soldier HMG";"702"
"785";"HOSPITAL";"609";"HOSPITAL";"S*G*IXH---H****";"(null)";"(null)";"(null)"
"711";"HOWITZER";"508";"HOWITZER";"S*G*EWH---*****";"(null)";"(null)";"(null)"
"716";"HOWITZER HEAVY";"513";"HOWITZERHEAVY";"S*G*EWHH--*****";"(null)";"(null)";"(null)"
"717";"HOWITZER HEAVY SELF-PROPELLED";"514";"HOWITZERHEAVYSELF-PROPELLED";"S*G*EWHHS-*****";"(null)";"(null)";"(null)"
"712";"HOWITZER LIGHT";"509";"HOWITZERLIGHT";"S*G*EWHL--*****";"(null)";"(null)";"(null)"
"713";"HOWITZER LIGHT SELF-PROPELLED";"510";"HOWITZERLIGHTSELF-PROPELLED";"S*G*EWHLS-*****";"(null)";"(null)";"(null)"
"714";"HOWITZER MEDIUM";"511";"HOWITZERMEDIUM";"S*G*EWHM--*****";"(null)";"(null)";"(null)"
"715";"HOWITZER MEDIUM SELF-PROPELLED";"512";"HOWITZERMEDIUMSELF-PROPELLED";"S*G*EWHMS-*****";"(null)";"(null)";"(null)"
"449";"INFANTRY";"149";"INFANTRY";"S*G*UCI---*****";"161";"TM";"449"
"449";"INFANTRY";"149";"INFANTRY";"S*G*UCI---*****";"226";"TEST PLAYER";"449"
"449";"INFANTRY";"149";"INFANTRY";"S*G*UCI---*****";"232";"0Soldier";"449"
"449";"INFANTRY";"149";"INFANTRY";"S*G*UCI---*****";"128";"TM Leader";"449"
"463";"INFANTRY AIR ASSAULT";"154";"INFANTRYAIRASSAULT";"S*G*UCIS--*****";"(null)";"(null)";"(null)"
"462";"INFANTRY AIRBORNE";"153";"INFANTRYAIRBORNE";"S*G*UCIA--*****";"(null)";"(null)";"(null)"
"466";"INFANTRY FIGHTING VEHICLE";"157";"INFANTRYFIGHTINGVEHICLE";"S*G*UCII--*****";"(null)";"(null)";"(null)"
"454";"INFANTRY LIGHT";"150";"INFANTRYLIGHT";"S*G*UCIL--*****";"(null)";"(null)";"(null)"
"464";"INFANTRY MECHANIZED";"155";"INFANTRYMECHANIZED";"S*G*UCIZ--*****";"(null)";"(null)";"(null)"
"456";"INFANTRY MOTORIZED";"151";"INFANTRYMOTORIZED";"S*G*UCIM--*****";"(null)";"(null)";"(null)"
"461";"INFANTRY MOUNTAIN";"152";"INFANTRYMOUNTAIN";"S*G*UCIO--*****";"(null)";"(null)";"(null)"
"465";"INFANTRY NAVAL";"156";"INFANTRYNAVAL";"S*G*UCIN--*****";"(null)";"(null)";"(null)"
"600";"INFORMATION OPERATIONS";"315";"INFORMATIONWARFAREUNIT";"S*G*UUI---*****";"(null)";"(null)";"(null)"
"765";"INSTALLATION";"576";"INSTALLATION";"S*G*I-----H****";"225";"MEU";"765"
"765";"INSTALLATION";"576";"INSTALLATION";"S*G*I-----H****";"224";"Building";"765"
"666";"INTERMEDIATE RANGE AD MISSILE";"473";"INTERMEDIATERANGEADMISSILELAUNCH";"S*G*EWMAI-*****";"(null)";"(null)";"(null)"
"670";"INTERMEDIATE RANGE SS MISSILE";"478";"INTERMEDIATERANGESSMISSILELAUNCH";"S*G*EWMSI-*****";"(null)";"(null)";"(null)"
"382";"INTERNAL SECURITY FORCES";"246";"INTERNALSECURITYFORCES";"S*G*UCS---*****";"(null)";"(null)";"(null)"
"390";"INTERNAL SECURITY FORCES AVIAT";"254";"AVIATION";"S*G*UCSA--*****";"(null)";"(null)";"(null)"
"387";"INTERNAL SECURITY FORCES GROUN";"251";"MECHANIZEDGROUND";"S*G*UCSGA-*****";"(null)";"(null)";"(null)"
"384";"INTERNAL SECURITY FORCES GROUND";"248";"GROUND";"S*G*UCSG--*****";"(null)";"(null)";"(null)"
"385";"INTERNAL SECURITY FORCES GROUND DISMOUNTED";"249";"DISMOUNTEDGROUND";"S*G*UCSGD-*****";"(null)";"(null)";"(null)"
"386";"INTERNAL SECURITY FORCES GROUND MOTORIZED";"250";"MOTORIZEDGROUND";"S*G*UCSGM-*****";"(null)";"(null)";"(null)"
"389";"INTERNAL SECURITY FORCES RAILROAD";"253";"RAILROAD";"S*G*UCSR--*****";"(null)";"(null)";"(null)"
"383";"INTERNAL SECURITY FORCES RIVERINE";"247";"RIVERINE";"S*G*UCSW--*****";"(null)";"(null)";"(null)"
"388";"INTERNAL SECURITY FORCES WHEEL";"252";"WHEELEDMECHANIZED";"S*G*UCSM--*****";"(null)";"(null)";"(null)"
"791";"LANDING CRAFT";"623";"LANDINGCRAFT";"S*S*CALC--*****";"(null)";"(null)";"(null)"
"790";"LANDING SHIP";"622";"LANDINGSHIP";"S*S*CALS--*****";"(null)";"(null)";"(null)"
"601";"LANDING SUPPORT";"316";"LANDINGSUPPORT";"S*G*UUX---*****";"(null)";"(null)";"(null)"
"762";"LAND MINES";"573";"LANDMINES";"S*G*EXM---*****";"(null)";"(null)";"(null)"
"763";"LAND MINES, LETHAL";"574";"LANDMINES,LETHAL";"S*G*EXMC--*****";"(null)";"(null)";"(null)"
"759";"LASER";"570";"LASER";"S*G*EXL---*****";"(null)";"(null)";"(null)"
"584";"LAW ENFORCEMENT UNIT";"292";"LAWENFORCEMENTUNIT";"S*G*UUL---*****";"(null)";"(null)";"(null)"
"587";"LAW ENFORCEMENT UNIT CIVILIAN LAW ENFORCEMENT";"295";"CIVILIANLAWENFORCEMENT";"S*G*UULC--*****";"(null)";"(null)";"(null)"
"588";"LAW ENFORCEMENT UNIT CRIMINAL INVESTIGATION DIVISI";"297";"CENTRALINTELLIGENCEDIVISION(CID)";"S*G*UULD--*****";"(null)";"(null)";"(null)"
"586";"LAW ENFORCEMENT UNIT MILITARY POLICE";"294";"MILITARYPOLICE";"S*G*UULM--*****";"(null)";"(null)";"(null)"
"585";"LAW ENFORCEMENT UNIT SHORE PATROL";"293";"SHOREPATROL";"S*G*UULS--*****";"(null)";"(null)";"(null)"
"794";"LEISURE CRAFT";"665";"LEISURECRAFT";"S*S*XR----*****";"(null)";"(null)";"(null)"
"764";"LESS THAN LETHAL";"575";"LESSTHANLETHAL";"S*G*EXML--*****";"(null)";"(null)";"(null)"
"737";"LIGHT ARMOURED VEHICLE";"545";"LIGHTARMOUREDVEHICLE";"S*G*EVAL--*****";"(null)";"(null)";"(null)"
"701";"LIGHT MACHINE GUN";"498";"LIGHTMACHINEGUN";"S*G*EWRL--*****";"131";"Soldier LMG";"701"
"741";"LIMITED CROSS-COUNTRY TRUCK";"549";"LIMITEDCROSS-COUNTRYTRUCK";"S*G*EVUL--*****";"(null)";"(null)";"(null)"
"667";"LONG RANGE AD MISSILE LAUNCH";"474";"LONGRANGEADMISSILELAUNCH";"S*G*EWMAL-*****";"(null)";"(null)";"(null)"
"671";"LONG RANGE SS MISSILE LAUNCH";"479";"LONGRANGESSMISSILELAUNCH";"S*G*EWMSL-*****";"(null)";"(null)";"(null)"
"648";"MAINTENANCE";"442";"MAINTENANCE";"S*G*USX---*****";"(null)";"(null)";"(null)"
"654";"MAINTENANCE BATTLE DAMAGE REPA";"460";"BATTLEDAMAGEREPAIR";"S*G*USXBDR*****";"(null)";"(null)";"(null)"
"653";"MAINTENANCE ELECTRO-OPTICAL";"457";"ELECTRO-OPTICAL";"S*G*USXE--*****";"(null)";"(null)";"(null)"
"649";"MAINTENANCE HEAVY";"445";"MAINTENANCEHEAVY";"S*G*USXH--*****";"(null)";"(null)";"(null)"
"651";"MAINTENANCE ORDINANCE";"451";"ORDINANCE";"S*G*USXO--*****";"(null)";"(null)";"(null)"
"652";"MAINTENANCE ORDINANCE MISSILE";"454";"ORDINANCEMISSILE";"S*G*USXOM-*****";"(null)";"(null)";"(null)"
"655";"MAINTENANCE PREVENTIVE MAINTEN";"461";"PREVENTIVEMAINTANANCE";"S*G*USXPM-*****";"(null)";"(null)";"(null)"
"650";"MAINTENANCE RECOVERY";"448";"MAINTENANCERECOVERY";"S*G*USXR--*****";"(null)";"(null)";"(null)"
"623";"MEDICAL DENTAL";"373";"MEDICALDENTAL";"S*G*USMD--*****";"(null)";"(null)";"(null)"
"784";"MEDICAL FACILITY";"608";"MEDICALFACILITY";"S*G*IX----H****";"(null)";"(null)";"(null)"
"624";"MEDICAL PSYCHOLOGICAL";"376";"MEDICALPSYCHOLOGICAL";"S*G*USMP--*****";"(null)";"(null)";"(null)"
"621";"MEDICAL TREATMENT FACILITY";"367";"MEDICALTREATMENTFACILITY";"S*G*USMM--*****";"(null)";"(null)";"(null)"
"622";"MEDICAL VETERINARY";"370";"MEDICALVETERINARY";"S*G*USMV--*****";"(null)";"(null)";"(null)"
"343";"MILITARY";"7";"MILITARY";"S*A*M-----*****";"(null)";"(null)";"(null)"
"780";"MILITARY BASE/FACILITY";"604";"MILITARYBASE/FACILITY";"S*G*IB----H****";"(null)";"(null)";"(null)"
"344";"MILITARY FIXED WING";"8";"FIXEDWING";"S*A*MF----*****";"(null)";"(null)";"(null)"
"567";"MILITARY INTELLIGENCE";"271";"MILITARYINTELLIGENCE";"S*G*UUM---*****";"(null)";"(null)";"(null)"
"568";"MILITARY INTELLIGENCE AERIAL EXPLOITATION";"272";"AERIALEXPLOITATION";"S*G*UUMA--*****";"(null)";"(null)";"(null)"
"577";"MILITARY INTELLIGENCE COUNTER INTELLIGENCE";"281";"COUNTERINTELLIGENCE";"S*G*UUMC--*****";"(null)";"(null)";"(null)"
"573";"MILITARY INTELLIGENCE ELECTRON";"277";"INTERCEPT";"S*G*UUMSEI*****";"(null)";"(null)";"(null)"
"572";"MILITARY INTELLIGENCE ELECTRON";"276";"DIRECTIONFINDING";"S*G*UUMSED*****";"(null)";"(null)";"(null)"
"571";"MILITARY INTELLIGENCE ELECTRON";"275";"ARMOUREDWHEELEDVEHICLE";"S*G*UUMSEA*****";"(null)";"(null)";"(null)"
"570";"MILITARY INTELLIGENCE ELECTRONIC WARFARE";"274";"ELECTRONICWARFARE";"S*G*UUMSE-*****";"(null)";"(null)";"(null)"
"574";"MILITARY INTELLIGENCE ELECTRONIC WARFARE JAMMING";"278";"JAMMING";"S*G*UUMSEJ*****";"(null)";"(null)";"(null)"
"582";"MILITARY INTELLIGENCE INTERROGATION";"290";"INTERROGATION";"S*G*UUMQ--*****";"(null)";"(null)";"(null)"
"583";"MILITARY INTELLIGENCE JOINT INTELLIGENCE CENTRE";"291";"JOINTINTELLIGENCECENTRE";"S*G*UUMJ--*****";"(null)";"(null)";"(null)"
"581";"MILITARY INTELLIGENCE OPERATIONS";"288";"OPERATIONS";"S*G*UUMO--*****";"(null)";"(null)";"(null)"
"569";"MILITARY INTELLIGENCE SIGNALS";"273";"SIGNALINTELLIGENCE(SIGINT)";"S*G*UUMS--*****";"(null)";"(null)";"(null)"
"579";"MILITARY INTELLIGENCE SURVEILL";"283";"GROUNDSURVEILLANCERADAR";"S*G*UUMRG-*****";"(null)";"(null)";"(null)"
"578";"MILITARY INTELLIGENCE SURVEILLANCE";"282";"SURVEILLANCE";"S*G*UUMR--*****";"(null)";"(null)";"(null)"
"580";"MILITARY INTELLIGENCE SURVEILLANCE SENSOR";"284";"SENSOR";"S*G*UUMRS-*****";"(null)";"(null)";"(null)"
"346";"MILITARY ROTARY WING";"39";"ROTARYWING";"S*A*MH----*****";"195";"Apache";"346"
"766";"MINE";"578";"MINE";"S*G*IRM---H****";"(null)";"(null)";"(null)"
"749";"MINE LAYING VEHICLE";"557";"MINELAYINGVEHICLE";"S*G*EVEM--*****";"4";"Trailer, Minelaying";"749"
"675";"MISSILE LAUNCHER AT HEAVY";"483";"MISSILELAUNCHERATHEAVY";"S*G*EWMTH-*****";"(null)";"(null)";"(null)"
"674";"MISSILE LAUNCHER AT MEDIUM";"482";"MISSILELAUNCHERATMEDIUM";"S*G*EWMTM-*****";"(null)";"(null)";"(null)"
"663";"MISSILE LAUNCHERS";"470";"MISSILELAUNCHERS";"S*G*EWM---*****";"(null)";"(null)";"(null)"
"672";"MISSILE LAUNCHERS ANTI TANK (A";"480";"MISSILELAUNCHERSANTITANK(AT)";"S*G*EWMT--*****";"(null)";"(null)";"(null)"
"673";"MISSILE LAUNCHERS AT LIGHT";"481";"MISSILELAUNCHERSATLIGHT";"S*G*EWMTL-*****";"(null)";"(null)";"(null)"
"544";"MISSILE (SURF-SURF)";"243";"MISSILE(SURFACE-SURFACE)";"S*G*UCM---*****";"(null)";"(null)";"(null)"
"546";"MISSILE (SURF-SURF) STRATEGIC";"245";"MISSILE(SURFACE-SURFACE)STRATEGIC";"S*G*UCMS--*****";"(null)";"(null)";"(null)"
"545";"MISSILE (SURF-SURF) TACTICAL";"244";"MISSILE(SURFACE-SURFACE)TACTICAL";"S*G*UCMT--*****";"(null)";"(null)";"(null)"
"707";"MORTAR";"504";"MORTAR";"S*G*EWO---*****";"209";"Soldier Mortar";"707"
"710";"MORTAR HEAVY";"507";"MORTARHEAVY";"S*G*EWOH--*****";"(null)";"(null)";"(null)"
"708";"MORTAR LIGHT";"505";"MORTARLIGHT";"S*G*EWOL--*****";"(null)";"(null)";"(null)"
"709";"MORTAR MEDIUM";"506";"MORTARMEDIUM";"S*G*EWOM--*****";"(null)";"(null)";"(null)"
"747";"MULTIFUNCTIONAL EARTHMOVER/DIG";"555";"MULTIFUNCTIONALEARTHMOVER/DIGGER";"S*G*EVEE--*****";"(null)";"(null)";"(null)"
"691";"MULTIPLE ROCKET LAUNCHER";"488";"MULTIPLEROCKETLAUNCHER";"S*G*EWX---*****";"(null)";"(null)";"(null)"
"694";"MULTIPLE ROCKET LAUNCHER HEAVY";"491";"MULTIPLEROCKETLAUNCHERHEAVY";"S*G*EWXH--*****";"(null)";"(null)";"(null)"
"692";"MULTIPLE ROCKET LAUNCHER LIGHT";"489";"MULTIPLEROCKETLAUNCHERLIGHT";"S*G*EWXL--*****";"(null)";"(null)";"(null)"
"693";"MULTIPLE ROCKET LAUNCHER MEDIU";"490";"MULTIPLEROCKETLAUNCHERMEDIUM";"S*G*EWXM--*****";"(null)";"(null)";"(null)"
"771";"NUCLEAR";"583";"NUCLEAR";"S*G*IRNN--H****";"(null)";"(null)";"(null)"
"188";"O/C Force";"5";"SPACESTATION";"S*P*T-----*****";"113";"O/C Staff";"188"
"188";"O/C Force";"5";"SPACESTATION";"S*P*T-----*****";"180";"O/C TM";"188"
"188";"O/C Force";"5";"SPACESTATION";"S*P*T-----*****";"114";"O/C Force";"188"
"807";"O/C Force CE";"5";"SPACESTATION";"S*P*T-----*****";"(null)";"(null)";"(null)"
"793";"OILER/TANKER";"655";"OILER/TANKER";"S*S*XMO---*****";"(null)";"(null)";"(null)"
"792";"PATROL";"630";"PATROL";"S*S*CP----*****";"(null)";"(null)";"(null)"
"767";"PETROLEUM/GAS/OIL";"579";"PETROLEUM/GAS/OIL";"S*G*IRP---H****";"(null)";"(null)";"(null)"
"656";"PIPELINE";"462";"PIPELINE";"S*G*USXP--*****";"(null)";"(null)";"(null)"
"775";"PUBLIC WATER SERVICES";"591";"PUBLICWATERSERVICES";"S*G*IUP---H****";"(null)";"(null)";"(null)"
"757";"RADAR";"567";"RADAR";"S*G*ESR---*****";"(null)";"(null)";"(null)"
"525";"RECONNAISSANCE";"226";"RECONNAISSANCE";"S*G*UCR---*****";"(null)";"(null)";"(null)"
"535";"RECONNAISSANCE AIR ASSAULT";"234";"RECONNAISSANCEAIRASSAULT";"S*G*UCRS--*****";"(null)";"(null)";"(null)"
"536";"RECONNAISSANCE AIRBORNE";"235";"RECONNAISSANCEAIRBORNE";"S*G*UCRA--*****";"(null)";"(null)";"(null)"
"539";"RECONNAISSANCE AMPHIBIOUS";"238";"RECONNAISSANCEMARINE";"S*G*UCRR--*****";"(null)";"(null)";"(null)"
"540";"RECONNAISSANCE AMPHIBIOUS DIVI";"239";"RECONNAISSANCEMARINEDIVISION";"S*G*UCRRD-*****";"(null)";"(null)";"(null)"
"541";"RECONNAISSANCE AMPHIBIOUS FORC";"240";"RECONNAISSANCEMARINEFORCE";"S*G*UCRRF-*****";"(null)";"(null)";"(null)"
"530";"RECONNAISSANCE CAVALRY";"228";"RECONNAISSANCECAVALRY";"S*G*UCRV--*****";"(null)";"(null)";"(null)"
"534";"RECONNAISSANCE CAVALRY AIR";"232";"RECONNAISSANCECAVALRYAIR";"S*G*UCRVO-*****";"(null)";"(null)";"(null)"
"531";"RECONNAISSANCE CAVALRY ARMOURE";"229";"RECONNAISSANCECAVALRYARMOURED";"S*G*UCRVA-*****";"(null)";"(null)";"(null)"
"533";"RECONNAISSANCE CAVALRY GROUND";"231";"RECONNAISSANCECAVALRYGROUND";"S*G*UCRVG-*****";"(null)";"(null)";"(null)"
"532";"RECONNAISSANCE CAVALRY MOTORIZ";"230";"RECONNAISSANCECAVALRYMOTORIZED";"S*G*UCRVM-*****";"(null)";"(null)";"(null)"
"538";"RECONNAISSANCE LIGHT";"237";"RECONNAISSANCELIGHT";"S*G*UCRLL--*****";"(null)";"(null)";"(null)"
"542";"RECONNAISSANCE MARINE LIGHT AR";"241";"RECONNAISSANCEMARINELIGHTARMOUREDRECONNAISSANCE(LA";"S*G*UCRRL-*****";"(null)";"(null)";"(null)"
"537";"RECONNAISSANCE MOUNTAIN";"236";"RECONNAISSANCEMOUNTAIN";"S*G*UCRO--*****";"(null)";"(null)";"(null)"
"543";"RECONNAISSANCE SURVEILLANCE LO";"242";"RECONNAISSANCELONGRANGESURVEILLANCE(LRS)";"S*G*UCRX--*****";"(null)";"(null)";"(null)"
"700";"RIFLE";"497";"RIFLE";"S*G*EWRR--*****";"210";"Soldier Assault Rifle";"700"
"699";"RIFLE/AUTOMATIC WEAPON";"496";"RIFLE/AUTOMATICWEAPON";"S*G*EWR---*****";"205";"Soldier Tgt";"699"
"699";"RIFLE/AUTOMATIC WEAPON";"496";"RIFLE/AUTOMATICWEAPON";"S*G*EWR---*****";"216";"Soldier M203";"699"
"699";"RIFLE/AUTOMATIC WEAPON";"496";"RIFLE/AUTOMATICWEAPON";"S*G*EWR---*****";"153";"Soldier MP";"699"
"438";"ROTARY WING ATTACK";"131";"ATTACKROTARYWING";"S*G*UCVRA-*****";"(null)";"(null)";"(null)"
"347";"ROTARY WING ATTACK";"40";"ATTACK";"S*A*MHA---*****";"(null)";"(null)";"(null)"
"352";"ROTARY WING DRONE (RPV/UAV)";"49";"DRONE(RPV/UAV)";"S*A*MHQ---*****";"(null)";"(null)";"(null)"
"348";"ROTARY WING MEDEVAC";"55";"MEDEVAC";"S*A*MHO---*****";"(null)";"(null)";"(null)"
"351";"ROTARY WING RECCE";"48";"RECONNAISSANCE";"S*A*MHR---*****";"(null)";"(null)";"(null)"
"349";"ROTARY WING SOF";"56";"SPECIALOPERATIONSFORCE(SOF)";"S*A*MHM---*****";"(null)";"(null)";"(null)"
"350";"ROTARY WING UTILITY";"42";"UTILITY";"S*A*MHU---*****";"(null)";"(null)";"(null)"
"782";"SEAPORT/NAVAL BASE";"606";"SEAPORT/NAVALBASE";"S*G*IBN---H****";"(null)";"(null)";"(null)"
"786";"SEA SURFACE INSTALLATION, OIL RIG / PLATFORM";"611";"SEASURFACEINSTALLATION,OILRIG/PLATFORM";"S*G*IRR---H****";"(null)";"(null)";"(null)"
"787";"SEA SURFACE TRACK";"612";"SEASURFACETRACK";"S*S*------*****";"(null)";"(null)";"(null)"
"740";"SEMI";"548";"SEMI";"S*G*EVUS--*****";"(null)";"(null)";"(null)"
"756";"SENSOR";"566";"SENSOR";"S*G*ES----*****";"(null)";"(null)";"(null)"
"616";"SERVICE SUPPORT MEDICAL";"364";"MEDICAL";"S*G*USM---*****";"(null)";"(null)";"(null)"
"641";"SERVICE SUPPORT TRANSPORTATION";"424";"TRANSPORTATION";"S*G*UST---*****";"53";"TATRA Logistics Carrier";"641"
"665";"SHORT RANGE AD MISSILE LAUNCHE";"472";"SHORTRANGEADMISSILELAUNCHERS";"S*G*EWMAS-*****";"(null)";"(null)";"(null)"
"669";"SHORT RANGE SS MISSILE LAUNCH";"477";"SHORTRANGESSMISSILELAUNCH";"S*G*EWMSS-*****";"(null)";"(null)";"(null)"
"593";"SIGNALS UNIT FORWARD COMMUNICATIONS";"303";"FORWARDCOMMUNICATIONS";"S*G*UUSF--*****";"(null)";"(null)";"(null)"
"597";"SIGNALS UNIT SIGNAL SUPPORT";"312";"SIGNALSUPPORT";"S*G*UUSS--*****";"(null)";"(null)";"(null)"
"589";"SIGNAL UNIT";"298";"SIGNALUNIT";"S*G*UUS---*****";"(null)";"(null)";"(null)"
"590";"SIGNAL UNIT AREA";"299";"AREA";"S*G*UUSA--*****";"(null)";"(null)";"(null)"
"592";"SIGNAL UNIT COMMAND OPERATIONS";"302";"COMMANDOPERATIONS";"S*G*UUSO--*****";"(null)";"(null)";"(null)"
"591";"SIGNAL UNIT COMMUNICATION CONF";"300";"COMMUNICATIONCONFIGUREDPACKAGE";"S*G*UUSC--*****";"(null)";"(null)";"(null)"
"599";"SIGNAL UNIT ELECTRONIC RANGING";"314";"ELECTRONICRANGING";"S*G*UUSX--*****";"(null)";"(null)";"(null)"
"594";"SIGNAL UNIT RADIO UNIT";"308";"RADIOUNIT";"S*G*UUSR--*****";"(null)";"(null)";"(null)"
"596";"SIGNAL UNIT RADIO UNIT RELAY";"311";"RELAY";"S*G*UUSRW-*****";"(null)";"(null)";"(null)"
"595";"SIGNAL UNIT RADIO UNIT TACTICA";"309";"TACTICALSATELLITE";"S*G*UUSRS-*****";"(null)";"(null)";"(null)"
"598";"SIGNAL UNIT TELEPHONE SWITCH";"313";"TELEPHONESWITCH";"S*G*UUSW--*****";"(null)";"(null)";"(null)"
"687";"SINGLE ROCKET LAUNCHER";"484";"SINGLEROCKETLAUNCHER";"S*G*EWS---*****";"(null)";"(null)";"(null)"
"690";"SINGLE ROCKET LAUNCHER HEAVY";"487";"SINGLEROCKETLAUNCHERHEAVY";"S*G*EWSH--*****";"(null)";"(null)";"(null)"
"688";"SINGLE ROCKET LAUNCHER LIGHT";"485";"SINGLEROCKETLAUNCHERLIGHT";"S*G*EWSL--*****";"(null)";"(null)";"(null)"
"689";"SINGLE ROCKET LAUNCHER MEDIUM";"486";"SINGLEROCKETLAUNCHERMEDIUM";"S*G*EWSM--*****";"(null)";"(null)";"(null)"
"796";"SOF AVIATION FIXED WING";"707";"SOFUNITFIXEDWING";"S*F*AF----*****";"(null)";"(null)";"(null)"
"797";"SOF AVIATION FIXED WING ATTACK";"708";"SOFUNITATTACK";"S*F*AFA---*****";"(null)";"(null)";"(null)"
"798";"SOF AVIATION FIXED WING UTILIT";"710";"SOFUNITUTILITY";"S*F*AFU---*****";"(null)";"(null)";"(null)"
"799";"SOF AVIATION FIXED WING UTILIT";"711";"SOFUNITUTILITY(LIGHT)";"S*F*AFUL--*****";"(null)";"(null)";"(null)"
"800";"SOF AVIATION ROTARY WING";"715";"SOFUNITROTARYWING";"S*F*AH----*****";"(null)";"(null)";"(null)"
"803";"SOF UNIT GROUND";"727";"SOFUNITGROUND";"S*F*G-----*****";"(null)";"(null)";"(null)"
"805";"SOF UNIT GROUND RANGER";"729";"SOFUNITRANGER";"S*F*GSR---*****";"(null)";"(null)";"(null)"
"804";"SOF UNIT GROUND SPECIAL FORCES";"728";"SOFUNITSPECIALFORCES";"S*F*GS----*****";"(null)";"(null)";"(null)"
"801";"SOF UNIT NAVAL";"722";"SOFUNITSOFUNITNAVAL";"S*F*SN----*****";"(null)";"(null)";"(null)"
"802";"SOF UNIT NAVAL SPECIAL BOAT";"725";"SOFUNITSPECIALBOAT";"S*F*SNB---*****";"(null)";"(null)";"(null)"
"806";"SOF UNIT PSYCHOLOGICAL OPERATI";"730";"SOFUNITPSYCHOLOGICALOPERATIONS(PSYOPS)";"S*F*GSP---*****";"(null)";"(null)";"(null)"
"658";"SPECIAL C2 HEADQUATERS COMPONE";"464";"SPECIALC2HEADQUARTERSCOMPONENT";"S*G*UH----*****";"(null)";"(null)";"(null)"
"795";"SPECIAL OPERATIONS FORCE (SOF)";"705";"SPECIALOPERATIONSFORCE(SOF)UNIT";"S*F*------*****";"(null)";"(null)";"(null)"
"625";"SUPPLY";"379";"SUPPLY";"S*G*USS---*****";"(null)";"(null)";"(null)"
"633";"SUPPLY CLASS I";"382";"SUPPLYCLASSI";"S*G*USS1--*****";"(null)";"(null)";"(null)"
"634";"SUPPLY CLASS II";"385";"SUPPLYCLASSII";"S*G*USS2--*****";"(null)";"(null)";"(null)"
"635";"SUPPLY CLASS III";"388";"SUPPLYCLASSIII";"S*G*USS3--*****";"(null)";"(null)";"(null)"
"636";"SUPPLY CLASS III AVIATION";"391";"SUPPLYCLASSIIIAVIATION";"S*G*USS3A-*****";"(null)";"(null)";"(null)"
"637";"SUPPLY CLASS IV";"394";"SUPPLYCLASSIV";"S*G*USS4--*****";"(null)";"(null)";"(null)"
"627";"SUPPLY CLASS IX";"409";"SUPPLYCLASSIX";"S*G*USS9--*****";"(null)";"(null)";"(null)"
"638";"SUPPLY CLASS V";"397";"SUPPLYCLASSV";"S*G*USS5--*****";"(null)";"(null)";"(null)"
"639";"SUPPLY CLASS VI";"400";"SUPPLYCLASSVI";"S*G*USS6--*****";"(null)";"(null)";"(null)"
"640";"SUPPLY CLASS VII";"403";"SUPPLYCLASSVII";"S*G*USS7--*****";"(null)";"(null)";"(null)"
"626";"SUPPLY CLASS VIII";"406";"SUPPLYCLASSVIII";"S*G*USS8--*****";"(null)";"(null)";"(null)"
"628";"SUPPLY CLASS X";"412";"SUPPLYCLASSX";"S*G*USSX--*****";"(null)";"(null)";"(null)"
"629";"SUPPLY LAUNDRY/BATH";"415";"SUPPLYLAUNDRY/BATH";"S*G*USSL--*****";"(null)";"(null)";"(null)"
"632";"SUPPLY MATERIEL (STOCK)";"1335";"SUPPLYMATERIEL(STOCK)";"S*G*US**--*****";"(null)";"(null)";"(null)"
"630";"SUPPLY WATER";"418";"SUPPLYWATER";"S*G*USSW--*****";"(null)";"(null)";"(null)"
"631";"SUPPLY WATER PURIFICATION";"421";"SUPPLYWATERPURIFICATION";"S*G*USSWP-*****";"(null)";"(null)";"(null)"
"668";"SURFACE- SURFACE (SS) MISSILE";"476";"SURFACE-SURFACE(SS)MISSILELAUNCHER";"S*G*EWMS--*****";"(null)";"(null)";"(null)"
"355";"SURFACE TO AIR MISSILE";"65";"SURFACETOAIRMISSILE(SAM)";"S*A*WMSA--*****";"(null)";"(null)";"(null)"
"354";"SURFACE TO SURFACE MISSILE";"64";"SURFACETOSURFACEMISSILE(SSM)";"S*A*WMSS--*****";"(null)";"(null)";"(null)"
"391";"SURVEILLANCE";"1334";"SURVEILLANCE";"S*G*F-S---*****";"(null)";"(null)";"(null)"
"725";"TANK";"533";"TANK";"S*G*EVAT--*****";"233";"0Vehicle";"725"
"725";"TANK";"533";"TANK";"S*G*EVAT--*****";"43";"MBT";"725"
"725";"TANK";"533";"TANK";"S*G*EVAT--*****";"230";"LEOPARD 2A5";"725"
"730";"TANK HEAVY";"538";"TANKHEAVY";"S*G*EVATH-*****";"(null)";"(null)";"(null)"
"731";"TANK HEAVY RECOVERY";"539";"TANKHEAVYRECOVERY";"S*G*EVATY-*****";"(null)";"(null)";"(null)"
"726";"TANK LIGHT";"534";"TANKLIGHT";"S*G*EVATL-*****";"(null)";"(null)";"(null)"
"727";"TANK LIGHT RECOVERY";"535";"TANKLIGHTRECOVERY";"S*G*EVATW-*****";"110";"BMP3 Recovery";"727"
"728";"TANK MEDIUM";"536";"TANKMEDIUM";"S*G*EVATM-*****";"(null)";"(null)";"(null)"
"729";"TANK MEDIUM RECOVERY";"537";"TANKMEDIUMRECOVERY";"S*G*EVATX-*****";"(null)";"(null)";"(null)"
"773";"TELECOMMUNICATIONS FACILITY";"589";"TELECOMMUNICATIONSFACILITY";"S*G*IUT---H****";"(null)";"(null)";"(null)"
"603";"TOPOGRAPHIC";"318";"TOPOGRAPHIC";"S*G*UUT---*****";"(null)";"(null)";"(null)"
"751";"TRAILER MOUNTED";"559";"TRAILERMOUNTED";"S*G*EVEMT-*****";"(null)";"(null)";"(null)"
"754";"TRAIN LOCOMOTIVE";"564";"TRAINLOCOMOTIVE";"S*G*EVST--*****";"(null)";"(null)";"(null)"
"645";"TRANSPORTATION APOD/APOE";"436";"APOD/APOE";"S*G*USTA--*****";"(null)";"(null)";"(null)"
"647";"TRANSPORTATION INTERMODAL";"1328";"TRANSPORTATIONINTERMODAL";"S*G*UST---*****";"(null)";"(null)";"(null)"
"646";"TRANSPORTATION MISSILE";"439";"MISSILE";"S*G*USTI--*****";"(null)";"(null)";"(null)"
"642";"TRANSPORTATION MOVEMENT CONTRO";"427";"MOVEMENTCONTROLCENTRE(MCC)";"S*G*USTM--*****";"(null)";"(null)";"(null)"
"643";"TRANSPORTATION RAILHEAD";"430";"RAILHEAD";"S*G*USTR--*****";"(null)";"(null)";"(null)"
"644";"TRANSPORTATION SPOD/SPOE";"433";"SPOD/SPOE";"S*G*USTS--*****";"(null)";"(null)";"(null)"
"783";"TRANSPORT FACILITY";"607";"TRANSPORTFACILITY";"S*G*IT----H****";"(null)";"(null)";"(null)"
"661";"UNITS GENERAL LIAISON";"467";"UNITGENERALLIAISON";"S*G*UHGL--*****";"(null)";"(null)";"(null)"
"738";"UTILITY VEHICLE";"546";"UTILITYVEHICLE";"S*G*EVU---*****";"54";"HMMWV Utility";"738"
"738";"UTILITY VEHICLE";"546";"UTILITYVEHICLE";"S*G*EVU---*****";"221";"Vehicle Tgt";"738"
"743";"WATER CRAFT";"551";"WATERCRAFT";"S*G*EVUR--*****";"213";"TATRA Tanker Water";"743"
"353";"WEAPON";"61";"WEAPON";"S*A*W-----*****";"(null)";"(null)";"(null)"
1 id name sym_klassifiz_id name symbol_id_code id name def_symbol_id
2 611 ADMINISTRATIVE FINANCE 331 FINANCE S*G*USAF--***** (null) (null) (null)
3 609 ADMINISTRATIVE JUDGE ADVOCATE GENERAL (JAG) 325 JUDGEADVOCATEGENERAL(JAG) S*G*USAJ--***** (null) (null) (null)
4 606 ADMINISTRATIVE LABOUR 355 LABOUR S*G*USAL--***** (null) (null) (null)
5 607 ADMINISTRATIVE MORAL, WELFARE, RECREATION (MWR) 358 MORAL,WELFARE,RECREATION(MWR) S*G*USAW--***** (null) (null) (null)
6 613 ADMINISTRATIVE MORTUARY/GRAVE REGISTRY 337 MORTUARY/GRAVESREGISTRY S*G*USAM--***** (null) (null) (null)
7 612 ADMINISTRATIVE PERSONNEL SERVICES 334 PERSONNELSERVICES S*G*USAS--***** (null) (null) (null)
8 610 ADMINISTRATIVE POSTAL 328 POSTAL S*G*USAO--***** (null) (null) (null)
9 615 ADMINISTRATIVE PUPLIC AFFAIRS 343 PUBLICAFFAIRS S*G*USAP--***** (null) (null) (null)
10 608 ADMINISTRATIVE QUARTERMASTER ( 361 QUARTERMASTER(SUPPLY) S*G*USAQ--***** (null) (null) (null)
11 614 ADMINISTRATIVE RELIGIOUS/CHAPLAIN 340 RELIGIOUS/CHAPLAIN S*G*USAR--***** (null) (null) (null)
12 605 ADMINISTRATIVE REPLACEMENT HOLDING UNIT (RHV) 352 REPLACEMENTHOLDINGUNIT(RHU) S*G*USAX--***** (null) (null) (null)
13 364 AIR DEFENCE 79 AIRDEFENCE S*G*UCD---***** (null) (null) (null)
14 664 AIR DEFENCE (AD) MISSILE LAUNC 471 AIRDEFENCE(AD)MISSILELAUNCH S*G*EWMA--***** (null) (null) (null)
15 379 AIR DEFENCE COMPOSITE 90 COMPOSITE S*G*UCDC--***** (null) (null) (null)
16 367 Air Defence COY 79 AIRDEFENCE S*G*UCD---***** (null) (null) (null)
17 683 AIR DEFENCE GUN 527 AIRDEFENCEGUN S*G*EWA---***** (null) (null) (null)
18 686 AIR DEFENCE GUN HEAVY 530 AIRDEFENCEGUNHEAVY S*G*EWAH--***** (null) (null) (null)
19 684 AIR DEFENCE GUN LIGHT 528 AIRDEFENCEGUNLIGHT S*G*EWAL--***** (null) (null) (null)
20 685 AIR DEFENCE GUN MEDIUM 529 AIRDEFENCEGUNMEDIUM S*G*EWAM--***** 44 Soldier Air Defence 685
21 378 AIR DEFENCE GUN UNIT 89 GUNUNIT S*G*UCDG--***** (null) (null) (null)
22 377 AIR DEFENCE H/MAD 88 H/MAD S*G*UCDH--***** (null) (null) (null)
23 372 AIR DEFENCE MISSILE 83 AIRDEFENCEMISSILE S*G*UCDM--***** (null) (null) (null)
24 376 AIR DEFENCE MISSILE HEAVY 87 AIRDEFENCEMISSILEHEAVY S*G*UCDMH-***** (null) (null) (null)
25 373 AIR DEFENCE MISSILE LIGHT 84 AIRDEFENCEMISSILELIGHT S*G*UCDML-***** 229 Legatus Wiesel 373
26 375 AIR DEFENCE MISSILE MEDIUM 86 AIRDEFENCEMISSILEMEDIUM S*G*UCDMM-***** (null) (null) (null)
27 374 AIR DEFENCE MISSILE MOTORIZED 85 AIRDEFENCEMISSILEMOTORIZED S*G*UCDMLA***** (null) (null) (null)
28 369 AIR DEFENCE SHORT RANGE 80 SHORTRANGE S*G*UCDS--***** (null) (null) (null)
29 371 AIR DEFENCE SHORT RANGE GUN 82 GUN S*G*UCDS--***** (null) (null) (null)
30 370 AIR DEFENCE SHORT RANGE MISSILE 81 MISSILE S*G*UCDS--***** (null) (null) (null)
31 380 AIR DEFENCE TARGETING UNIT 91 TARGETINGUNIT S*G*UCDT--***** (null) (null) (null)
32 381 AIR DEFENCE THEATRE MISSILE DEFENCE UNIT 92 THEATREMISSILEDEFENCEUNIT S*G*UCDO--***** (null) (null) (null)
33 781 AIRPORT/AIRBASE 605 AIRPORT/AIRBASE S*G*IBA---H**** (null) (null) (null)
34 342 AIR TRACK 6 AIRTRACK S*A*------***** (null) (null) (null)
35 777 AMMUNITION AND EXPLOSIVES PRODUCTION 595 AMMUNITIONANDEXPLOSIVESPRODUCTION S*G*IME---H**** (null) (null) (null)
36 788 AMPHIBIOUS WARFARE SHIP 620 AMPHIBIOUSWARFARESHIP S*S*CA----***** (null) (null) (null)
37 414 ANTI ARMOUR 110 ANTIARMOUR S*G*UCAA--***** (null) (null) (null)
38 422 ANTI ARMOUR AIR ASSAULT 114 ANTIARMOURAIRASSAULT S*G*UCAAS-***** (null) (null) (null)
39 421 ANTI ARMOUR AIRBORNE 113 ANTIARMOURAIRBORNE S*G*UCAAM-***** (null) (null) (null)
40 424 ANTI ARMOUR ARMOURED 117 ANTIARMOURARMOURED S*G*UCAAA-***** (null) (null) (null)
41 427 ANTI ARMOUR ARMOURED AIR ASSAU 120 ANTIARMOURARMOUREDAIRASSAULT S*G*UCAAAS***** (null) (null) (null)
42 425 ANTI ARMOUR ARMOURED TRACKED 118 ANTIARMOURARMOUREDTRACKED S*G*UCAAAT***** (null) (null) (null)
43 426 ANTI ARMOUR ARMOURED WHEELED 119 ANTIARMOURARMOUREDWHEELED S*G*UCAAAW***** (null) (null) (null)
44 419 ANTI ARMOUR DISMOUNTED 111 ANTIARMOURDISMOUNTED S*G*UCAAD-***** (null) (null) (null)
45 420 ANTI ARMOUR LIGHT 112 ANTIARMOURLIGHT S*G*UCAAL-***** (null) (null) (null)
46 428 ANTI ARMOUR MOTORIZED 121 ANTIARMOURMOTORIZED S*G*UCAAO-***** (null) (null) (null)
47 429 ANTI ARMOUR MOTORIZED AIR ASSA 122 ANTIARMOURMOTORIZEDAIRASSAULT S*G*UCAAOS***** (null) (null) (null)
48 423 ANTI ARMOUR MOUNTAIN 115 ANTIARMOURMOUNTAIN S*G*UCAAU-***** (null) (null) (null)
49 718 ANTITANK GUN 515 ANTITANKGUN S*G*EWG---***** 130 Soldier AT (RPG7) 718
50 722 ANTITANK GUN HEAVY 519 ANTITANKGUNHEAVY S*G*EWGH--***** (null) (null) (null)
51 720 ANTITANK GUN LIGHT 517 ANTITANKGUNLIGHT S*G*EWGL--***** (null) (null) (null)
52 721 ANTITANK GUN MEDIUM 518 ANTITANKGUNMEDIUM S*G*EWGM--***** (null) (null) (null)
53 719 ANTITANK GUN RECOILLESS 516 ANTITANKGUNRECOILLESS S*G*EWGR--***** (null) (null) (null)
54 695 ANTITANK ROCKET LAUNCHER 492 ANTITANKROCKETLAUNCHER S*G*EWT---***** (null) (null) (null)
55 698 ANTITANK ROCKET LAUNCHER HEAVY 495 ANTITANKROCKETLAUNCHERHEAVY S*G*EWTH--***** (null) (null) (null)
56 696 ANTITANK ROCKET LAUNCHER LIGHT 493 ANTITANKROCKETLAUNCHERLIGHT S*G*EWTL--***** (null) (null) (null)
57 697 ANTITANK ROCKET LAUNCHER MEDIU 494 ANTITANKROCKETLAUNCHERMEDIUM S*G*EWTM--***** (null) (null) (null)
58 392 ARMOUR 93 ARMOUR S*G*UCA---***** (null) (null) (null)
59 752 ARMOURED CARRIER WITH SCATTERA 561 ARMOUREDCARRIERWITHSCATTERABLEMINES S*G*EVEMSM***** (null) (null) (null)
60 734 ARMOURED INFANTRY 542 ARMOUREDINFANTRY S*G*EVAI--***** (null) (null) (null)
61 732 ARMOURED PERSONNEL CARRIER 540 ARMOUREDPERSONNELCARRIER S*G*EVAA--***** (null) (null) (null)
62 733 ARMOURED PERSONNEL CARRIER REC 541 ARMOUREDPERSONNELCARRIERRECOVERY S*G*EVAAR-***** (null) (null) (null)
63 724 ARMOURED VEHICLE 532 ARMOUREDVEHICLE S*G*EVA---***** 231 Marder 724
64 750 ARMOURED VEHICLE MOUNTED 558 ARMOUREDVEHICLEMOUNTED S*G*EVEMA-***** (null) (null) (null)
65 397 ARMOUR TRACK 94 ARMOURTRACK S*G*UCAT--***** (null) (null) (null)
66 398 ARMOUR TRACK AIRBORNE 95 ARMOURTRACKAIRBORNE S*G*UCATA-***** (null) (null) (null)
67 399 ARMOUR TRACK AMPHIBIOUS 96 ARMOURTRACKAMPHIBIOUS S*G*UCATW-***** (null) (null) (null)
68 400 ARMOUR TRACK AMPHIBIOUS RECOVE 97 ARMOURTRACKAMPHIBIOUSRECOVERY S*G*UCATWR***** (null) (null) (null)
69 403 ARMOUR TRACK HEAVY 100 ARMOURTRACK,HEAVY S*G*UCATH-***** (null) (null) (null)
70 401 ARMOUR TRACK LIGHT 98 ARMOURTRACK,LIGHT S*G*UCATL-***** (null) (null) (null)
71 402 ARMOUR TRACK MEDIUM 99 ARMOURTRACK,MEDIUM S*G*UCATM-***** (null) (null) (null)
72 404 ARMOUR TRACK RECOVERY 101 ARMOURTRACK,RECOVERY S*G*UCATR-***** (null) (null) (null)
73 405 ARMOUR WHEELED 102 ARMOUR,WHEELED S*G*UCAW--***** (null) (null) (null)
74 406 ARMOUR WHEELED AIR ASSAULT 103 ARMOUR,WHEELEDAIRASSAULT S*G*UCAWS-***** (null) (null) (null)
75 407 ARMOUR WHEELED AIRBORNE 104 ARMOUR,WHEELEDAIRBORNE S*G*UCAWA-***** 227 BMP3 IFV 407
76 408 ARMOUR WHEELED AMPHIBIOUS 105 ARMOUR,WHEELEDAMPHIBIOUS S*G*UCAWA-***** (null) (null) (null)
77 409 ARMOUR WHEELED AMPHIBIOUS RECO 1325 ARMOURWHEELEDAMPHIBIOUSRECOVERY S*G*UCAWWR***** (null) (null) (null)
78 412 ARMOUR WHEELED HEAVY 108 ARMOUR,WHEELEDHEAVY S*G*UCAWH-***** (null) (null) (null)
79 410 ARMOUR WHEELED LIGHT 106 ARMOUR,WHEELEDLIGHT S*G*UCAWL-***** (null) (null) (null)
80 411 ARMOUR WHEELED MEDIUM 107 ARMOUR,WHEELEDMEDIUM S*G*UCAWM-***** (null) (null) (null)
81 413 ARMOUR WHEELED RECOVERY 109 ARMOUR,WHEELEDRECOVERY S*G*UCAWR-***** 10 Armored Recovery Vehicle 413
82 789 ASSAULT VESSEL 621 ASSAULTVESSEL S*S*CALA--***** (null) (null) (null)
83 776 ATOMIC ENERGY PRODUCTION 593 ATOMICENERGYPRODUCTION S*G*IMF---H**** (null) (null) (null)
84 430 AVIATION 123 AVIATION S*G*UCV---***** (null) (null) (null)
85 431 AVIATION FIXED WING 124 FIXEDWING S*G*UCVF--***** (null) (null) (null)
86 433 AVIATION FIXED WING ATTACK 126 ATTACKFIXEDWING S*G*UCVFA-***** (null) (null) (null)
87 436 AVIATION FIXED WING RECON 129 RECONFIXEDWING S*G*UCVFR-***** (null) (null) (null)
88 432 AVIATION FIXED WING UTILITY 125 UTILITYFIXEDWING S*G*UCVFU-***** (null) (null) (null)
89 435 AVIATION FORWARD AIR CONTROLLER (FAC) 128 FORWARDAIRCONTROLLER(FAC) S*G*UCVUFC***** (null) (null) (null)
90 437 AVIATION ROTARY WING 130 ROTARYWING S*G*UCVR--***** (null) (null) (null)
91 440 AVIATION ROTARY WING C2 138 C2ROTARYWING S*G*UCVRUC***** (null) (null) (null)
92 441 AVIATION ROTARY WING MEDEVAC 139 MEDEVACROTARYWING S*G*UCVRUE***** (null) (null) (null)
93 439 AVIATION ROTARY WING UTILITY 134 UTILITYROTARYWING S*G*UCVRU-***** (null) (null) (null)
94 434 AVIATION TACTICAL AIR CONTROL 127 TACTICALAIRCONTROLPARTY(TACP) S*G*UCVUTP***** (null) (null) (null)
95 445 AVIATION UAV CONTROL 1326 AVIATIONUAVCONTROL S*G*UCVU--***** (null) (null) (null)
96 446 AVIATION UAV LAUNCHER 1327 AVIATIONUAVLAUNCHER S*G*UCVU--***** (null) (null) (null)
97 447 AVIATION UAV RECOVERY 1337 AVIATIONUAVRECOVERY S*G*UCVU--***** (null) (null) (null)
98 444 AVIATION UNMANNED AERIAL VEHIC 145 UNMANNEDAERIALVEHICLEFIXEDWING S*G*UCVUF-***** (null) (null) (null)
99 448 AVIATION UNMANNED AERIAL VEHICLE ROTARY WING 146 UNMANNEDAERIALVEHICLEROTARYWING S*G*UCVUR-***** (null) (null) (null)
100 443 AVIATION UNMANNED AVIATION VEH 144 UNMANNEDAERIALVEHICLE S*G*UCVU--***** (null) (null) (null)
101 442 AVIATION VERTICAL/SHORT TAKEOF 143 VERTICAL/SHORTTAKEOFFANDLANDING(V/STOL) S*G*UCVV--***** (null) (null) (null)
102 769 BIOLOGICAL 581 BIOLOGICAL S*G*IRNB--H**** (null) (null) (null)
103 745 BRIDGE 553 BRIDGE S*G*EVEB--***** (null) (null) (null)
104 778 BRIDGE 599 BRIDGE S*G*IMNB--H**** (null) (null) (null)
105 739 BUS 547 BUS S*G*EVUB--***** (null) (null) (null)
106 735 C2V/ACV 543 C2V/ACV S*G*EVAC--***** (null) (null) (null)
107 548 CBRN 256 COMBATSUPPORTCBRN S*G*UUA---***** (null) (null) (null)
108 768 CBRN 580 CBRN S*G*IRN---H**** (null) (null) (null)
109 560 CBRN BIOLOGICAL 268 BIOLOGICAL S*G*UUAB--***** (null) (null) (null)
110 561 CBRN BIOLOGICAL RECON EQUIPPED 269 RECONEQUIPPED S*G*UUABR-***** (null) (null) (null)
111 549 CBRN CHEMICAL 257 CHEMICAL S*G*UUAC--***** (null) (null) (null)
112 556 CBRN CHEMICAL RECON 264 CHEMICALRECON S*G*UUACR-***** (null) (null) (null)
113 553 CBRN CHEMICAL SMOKE 261 SMOKE S*G*UUACS-***** (null) (null) (null)
114 555 CBRN CHEMICAL SMOKE ARMOUR 263 ARMOURSMOKE S*G*UUACSA***** (null) (null) (null)
115 550 CBRN CHEMICAL SMOKE/DECON 258 SMOKE/DECON S*G*UUACC-***** (null) (null) (null)
116 551 CBRN CHEMICAL SMOKE/DECON MECHANIZED 259 MECHANIZEDSMOKE/DECON S*G*UUACCK***** (null) (null) (null)
117 552 CBRN CHEMICAL SMOKE/DECON MOTO 260 MOTORIZEDSMOKE/DECON S*G*UUACCM***** (null) (null) (null)
118 554 CBRN CHEMICAL SMOKE MOTORIZED 262 MOTORIZEDSMOKE S*G*UUACSM***** (null) (null) (null)
119 557 CBRN CHEMICAL WHEELED ARMOURED VEHICLE 265 CHEMICALWHEELEDARMOUREDVEHICLE S*G*UUACRW***** (null) (null) (null)
120 558 CBRN CHEMICAL WHEELED ARMOURED VEHICLE RECONNAISAN 266 CHEMICALWHEELEDARMOUREDVEHICLERECONNAISSANCESURVEI S*G*UUACRS***** (null) (null) (null)
121 562 CBRN DECON 270 DECONTAMINATION S*G*UUAD--***** (null) (null) (null)
122 564 CBRN DECON EQUIPMENT 1330 CBRNDECONEQUIPMENT S*G*UUADE-***** (null) (null) (null)
123 565 CBRN DECON EQUIPMENT/TROOP 1331 CBRNDECONEQUIPMENT/TROOP S*G*UUADET***** (null) (null) (null)
124 563 CBRN DECON TROOP 1329 CBRNDECONTROOP S*G*UUADT-***** (null) (null) (null)
125 760 CBRN EQUIPMENT 571 CBRNEQUIPMENT S*G*EXN---***** (null) (null) (null)
126 566 CBRN LABORATORY 1332 CBRNLABORATORY S*G*UUAL--***** (null) (null) (null)
127 559 CBRN NUCLEAR 267 NUCLEAR S*G*UUAN--***** (null) (null) (null)
128 770 CHEMICAL 582 CHEMICAL S*G*IRNC--H**** (null) (null) (null)
129 356 CIVIL FIXED WING 73 FIXEDWING S*A*CF----***** (null) (null) (null)
130 755 CIVILIAN VEHICLE 565 CIVILIANVEHICLE S*G*EVC---***** (null) (null) (null)
131 357 CIVIL ROTARY WING 74 ROTARYWING S*A*CH----***** (null) (null) (null)
132 604 COMBAT SERVICE SUPPORT 321 COMBATSERVICESUPPORT S*G*US----***** (null) (null) (null)
133 736 COMBAT SERVICE SUPPORT VEHICLE 544 COMBATSERVICESUPPORTVEHICLE S*G*EVAS--***** (null) (null) (null)
134 547 COMBAT SUPPORT 255 COMBATSUPPORT S*G*UU----***** (null) (null) (null)
135 748 CONSTRUCTION VEHICLE 556 CONSTRUCTIONVEHICLE S*G*EVEC--***** (null) (null) (null)
136 742 CROSS-COUNTRY TRUCK 550 CROSS-COUNTRYTRUCK S*G*EVUX--***** 212 TATRA Tanker Fuel 742
137 742 CROSS-COUNTRY TRUCK 550 CROSS-COUNTRYTRUCK S*G*EVUX--***** 50 Truck 2t off-road 742
138 772 DECON 585 DECON S*G*IPD---H**** (null) (null) (null)
139 676 DIRECT FIRE GUN 520 DIRECTFIREGUN S*G*EWD---***** (null) (null) (null)
140 681 DIRECT FIRE GUN HEAVY 525 DIRECTFIREGUNHEAVY S*G*EWDH--***** (null) (null) (null)
141 682 DIRECT FIRE GUN HEAVY SELF-PRO 526 DIRECTFIREGUNHEAVYSELF-PROPELLED S*G*EWDHS-***** (null) (null) (null)
142 677 DIRECT FIRE GUN LIGHT 521 DIRECTFIREGUNLIGHT S*G*EWDL--***** (null) (null) (null)
143 678 DIRECT FIRE GUN LIGHT SELF PRO 522 DIRECTFIREGUNLIGHTSELF-PROPELLED S*G*EWDLS-***** (null) (null) (null)
144 679 DIRECT FIRE GUN MEDIUM 523 DIRECTFIREGUNMEDIUM S*G*EWDM--***** (null) (null) (null)
145 680 DIRECT FIRE GUN MEDIUM SELF-PR 524 DIRECTFIREGUNMEDIUMSELF-PROPELLED S*G*EWDMS-***** (null) (null) (null)
146 753 DOZER 562 DOZER S*G*EVED--***** 215 CAT Excavator 753
147 746 EARTHMOVER 554 EARTHMOVER S*G*EVEE--***** (null) (null) (null)
148 774 ELCECTRIC POWER FACILITY 590 ELECTRICPOWERFACILITY S*G*IUE---H**** (null) (null) (null)
149 758 EMPLACED SENSOR 568 EMPLACEDSENSOR S*G*ESE---***** (null) (null) (null)
150 467 ENGINEER 159 ENGINEER S*G*UCE---***** (null) (null) (null)
151 472 ENGINEER COMBAT 160 ENGINEERCOMBAT S*G*UCEC--***** (null) (null) (null)
152 473 ENGINEER COMBAT AIR ASSAULT 161 ENGINEERCOMBATAIRASSAULT S*G*UCECS-***** (null) (null) (null)
153 478 ENGINEER COMBAT AIRBORNE 162 ENGINEERCOMBATAIRBORNE S*G*UCECA-***** (null) (null) (null)
154 475 ENGINEER COMBAT BRIDGING 171 ENGINEERCOMBATBRIDGING S*G*UCEC--***** (null) (null) (null)
155 481 ENGINEER COMBAT HEAVY 166 ENGINEERCOMBATHEAVY S*G*UCECH-***** (null) (null) (null)
156 479 ENGINEER COMBAT LIGHT 164 ENGINEERCOMBATLIGHT S*G*UCECL-***** (null) (null) (null)
157 482 ENGINEER COMBAT MECH (TRACK) 167 ENGINEERCOMBATMECHANIZED(TRACK) S*G*UCECT-***** (null) (null) (null)
158 480 ENGINEER COMBAT MEDIUM 165 ENGINEERCOMBATMEDIUM S*G*UCECM-***** (null) (null) (null)
159 476 ENGINEER COMBAT MINE CLEARING 172 ENGINEERCOMBATMINECLEARING S*G*UCEC--***** (null) (null) (null)
160 477 ENGINEER COMBAT MINE LAYING 173 ENGINEERCOMBATMINELAYING S*G*UCEC--***** (null) (null) (null)
161 483 ENGINEER COMBAT MOTORIZED 168 ENGINEERCOMBATMOTORIZED S*G*UCECW-***** (null) (null) (null)
162 484 ENGINEER COMBAT MOUNTAIN 169 ENGINEERCOMBATMOUNTAIN S*G*UCECO-***** (null) (null) (null)
163 474 ENGINEER COMBAT RECON 170 ENGINEERCOMBATRECON S*G*UCECR-***** (null) (null) (null)
164 485 ENGINEER CONSTRUCTION 175 ENGINEERCONSTRUCTION S*G*UCEN--***** (null) (null) (null)
165 744 ENGINEER VEHICLE 552 ENGINEERVEHICLE S*G*EVE---***** (null) (null) (null)
166 657 ENVIRONMENTAL PROTECTION 463 ENVIRONMENTALPROTECTION S*G*USXEP-***** (null) (null) (null)
167 576 EW CORPS 280 CORPS S*G*UUMSEC***** (null) (null) (null)
168 575 EW THEATRE 279 THEATRE S*G*UUMSET***** (null) (null) (null)
169 602 EXPLOSIVE ORDNANCE DISPOSAL 317 EXPLOSIVEORDINANCEDISPOSAL S*G*UUE---***** (null) (null) (null)
170 490 FIELD ARTELLERY HOWITZER/GUN AIRBORNE 181 AIRBORNE S*G*UCFHA-***** (null) (null) (null)
171 495 FIELD ARTELLERY HOWITZER/GUN AMPHIBIOUS 187 AMPHIBIOUS S*G*UCFHX-***** (null) (null) (null)
172 494 FIELD ARTELLERY HOWITZER/GUN HEAVY 186 HEAVY S*G*UCFHH-***** (null) (null) (null)
173 492 FIELD ARTELLERY HOWITZER/GUN LIGHT 184 LIGHT S*G*UCFHL-***** (null) (null) (null)
174 493 FIELD ARTELLERY HOWITZER/GUN MEDIUM 185 MEDIUM S*G*UCFHM-***** (null) (null) (null)
175 491 FIELD ARTELLERY HOWITZER/GUN MOUNTAIN 183 MOUNTAIN S*G*UCFHO-***** (null) (null) (null)
176 496 FIELD ARTELLERY ROCKET 188 ROCKET S*G*UCFR--***** (null) (null) (null)
177 498 FIELD ARTILEERY ROCKET SINGLE 190 SINGLEROCKETSELFPROPELLED S*G*UCFRSS***** (null) (null) (null)
178 486 FIELD ARTILLERY 177 FIELDARTILLERY S*G*UCF---***** (null) (null) (null)
179 521 FIELD ARTILLERY ARTILLERY SURV 214 ARTILLERYSURVEY S*G*UCFS--***** (null) (null) (null)
180 523 FIELD ARTILLERY FIRE DIRECTION CENTRE 224 FIREDIRECTIONCENTRE S*G*UCF---***** (null) (null) (null)
181 487 FIELD ARTILLERY HOWITZER/GUN 178 HOWITZER/GUN S*G*UCFH--***** (null) (null) (null)
182 489 FIELD ARTILLERY HOWITZER/GUN AIR ASSAULT 180 AIRASSAULT S*G*UCFHS-***** (null) (null) (null)
183 488 FIELD ARTILLERY HOWITZER/GUN SELF-PROPELLED 179 SELFPROPELLED S*G*UCFHE-***** (null) (null) (null)
184 522 FIELD ARTILLERY METEOROLOGICAL 219 METEOROLOGICAL S*G*UCFO--***** (null) (null) (null)
185 513 FIELD ARTILLERY MORTAR 205 MORTAR S*G*UCFM--***** (null) (null) (null)
186 514 FIELD ARTILLERY MORTAR SP TRAC 206 SELFPROPELLED(SP)TRACKEDMORTAR S*G*UCFMS-***** (null) (null) (null)
187 515 FIELD ARTILLERY MORTAR SP WHEE 207 SPWHEELEDMORTAR S*G*UCFMSW***** (null) (null) (null)
188 516 FIELD ARTILLERY MORTAR TOWED 208 TOWEDMORTAR S*G*UCFMT-***** (null) (null) (null)
189 518 FIELD ARTILLERY MORTAR TOWED A 210 TOWEDAIRASSAULTMORTAR S*G*UCFMTS***** (null) (null) (null)
190 517 FIELD ARTILLERY MORTAR TOWED A 209 TOWEDAIRBORNEMORTAR S*G*UCFMTA***** (null) (null) (null)
191 519 FIELD ARTILLERY MORTAR TOWED M 212 TOWEDMOUNTAINMORTAR S*G*UCFMTO***** (null) (null) (null)
192 524 FIELD ARTILLERY OBERSERVER 225 OBERSERVER S*G*UCF---***** (null) (null) (null)
193 502 FIELD ARTILLERY ROCKET MULTI R 194 MULTIROCKETSELFPROPELLED S*G*UCFRMS***** (null) (null) (null)
194 504 FIELD ARTILLERY ROCKET MULTI ROCKET LAUNCER MULTI 196 MULTIROCKETTOWED S*G*UCFRMT***** (null) (null) (null)
195 503 FIELD ARTILLERY ROCKET MULTI ROCKET LAUNCER MULTI 195 MULTIROCKETTRUCK S*G*UCFRMR***** (null) (null) (null)
196 501 FIELD ARTILLERY ROCKET MULTI ROCKET LAUNCHER 193 MULTIROCKETLAUNCHER S*G*UCFRM-***** (null) (null) (null)
197 497 FIELD ARTILLERY ROCKET SINGLE 189 SINGLEROCKETLAUNCHER S*G*UCFRS-***** (null) (null) (null)
198 499 FIELD ARTILLERY ROCKET SINGLE ROCKET LAUNCHER SING 191 SINGLEROCKETTRUCK S*G*UCFRSR***** (null) (null) (null)
199 500 FIELD ARTILLERY ROCKET SINGLE ROCKET LAUNCHER SING 192 SINGLEROCKETTOWED S*G*UCFRST***** (null) (null) (null)
200 506 FIELD ARTILLERY TARGET ACQUISI 198 RADAR S*G*UCFTR-***** (null) (null) (null)
201 505 FIELD ARTILLERY TARGET ACQUISITION 197 TARGETACQUISITION S*G*UCFT--***** (null) (null) (null)
202 510 FIELD ARTILLERY TARGET ACQUISITION DISMOUNTED 202 TARGETACQUISITIONDISMOUNTED S*G*UCFTCD***** (null) (null) (null)
203 508 FIELD ARTILLERY TARGET ACQUISITION FLASH (OPTICAL) 200 FLASH(OPTICAL) S*G*UCFTF-***** (null) (null) (null)
204 509 FIELD ARTILLERY TARGET ACQUISITION MOUNTED 201 TARGETACQUISITIONMOUNTED S*G*UCFTC-***** (null) (null) (null)
205 512 FIELD ARTILLERY TARGET ACQUISITION NAVAL GUNFIRE 204 TARGETACQUISITIONNAVALGUNFIRE S*G*UCFTA-***** (null) (null) (null)
206 507 FIELD ARTILLERY TARGET ACQUISITION SOUND 199 SOUND S*G*UCFTS-***** (null) (null) (null)
207 511 FIELD ARTILLERY TARGET ACQUISITION TRACKED 203 TARGETACQUISITIONTRACKED S*G*UCFTCM***** (null) (null) (null)
208 345 FIXED WING DRONE (RPV/UAE) 36 DRONE(RPV/UAV) S*A*MFQ---***** (null) (null) (null)
209 761 FLAME THROWER 572 FLAMETHROWER S*G*EXF---***** (null) (null) (null)
210 660 GENERAL HEADQUATERS AND SERVICE 466 GENERALHEADQUARTERSANDSERVICE S*G*UH----***** (null) (null) (null)
211 779 GOVERNMENT LEADERSHIP 603 GOVERNMENTLEADERSHIP S*G*IG----H**** (null) (null) (null)
212 703 GRENADE LAUNCHER 500 GRENADELAUNCHER S*G*EWZ---***** (null) (null) (null)
213 706 GRENADE LAUNCHER HEAVY 503 GRENADELAUNCHERHEAVY S*G*EWZH--***** (null) (null) (null)
214 704 GRENADE LAUNCHER LIGHT 501 GRENADELAUNCHERLIGHT S*G*EWZL--***** (null) (null) (null)
215 705 GRENADE LAUNCHER MEDIUM 502 GRENADELAUNCHERMEDIUM S*G*EWZM--***** (null) (null) (null)
216 662 GROUND TRACK EQUIPMENT 468 GROUNDTRACKEQUIPMENT S*G*E-----***** (null) (null) (null)
217 358 GROUND TRACK UNIT 77 UNIT S*G*U-----***** 217 Soldier (Role Player) 358
218 358 GROUND TRACK UNIT 77 UNIT S*G*U-----***** 106 Soldier 358
219 363 GROUND TRACK UNIT COMBAT 78 COMBAT S*G*UC----***** (null) (null) (null)
220 520 GROUND TRACK UNIT COMBAT FIELD ARTILLERY MORTAR AM 213 AMPHIBIOUSMORTAR S*G*UCFML-***** (null) (null) (null)
221 659 GROUND TRACK UNIT GENERAL HEADQUATERS 465 UNITGENERALHEADQUARTERS S*G*UH----***** (null) (null) (null)
222 723 GROUND VEHICLE 531 GROUNDVEHICLE S*G*EV----***** (null) (null) (null)
223 702 HEAVY MACHINE GUN 499 HEAVYMACHINEGUN S*G*EWRH--***** 129 Soldier HMG 702
224 785 HOSPITAL 609 HOSPITAL S*G*IXH---H**** (null) (null) (null)
225 711 HOWITZER 508 HOWITZER S*G*EWH---***** (null) (null) (null)
226 716 HOWITZER HEAVY 513 HOWITZERHEAVY S*G*EWHH--***** (null) (null) (null)
227 717 HOWITZER HEAVY SELF-PROPELLED 514 HOWITZERHEAVYSELF-PROPELLED S*G*EWHHS-***** (null) (null) (null)
228 712 HOWITZER LIGHT 509 HOWITZERLIGHT S*G*EWHL--***** (null) (null) (null)
229 713 HOWITZER LIGHT SELF-PROPELLED 510 HOWITZERLIGHTSELF-PROPELLED S*G*EWHLS-***** (null) (null) (null)
230 714 HOWITZER MEDIUM 511 HOWITZERMEDIUM S*G*EWHM--***** (null) (null) (null)
231 715 HOWITZER MEDIUM SELF-PROPELLED 512 HOWITZERMEDIUMSELF-PROPELLED S*G*EWHMS-***** (null) (null) (null)
232 449 INFANTRY 149 INFANTRY S*G*UCI---***** 161 TM 449
233 449 INFANTRY 149 INFANTRY S*G*UCI---***** 226 TEST PLAYER 449
234 449 INFANTRY 149 INFANTRY S*G*UCI---***** 232 0Soldier 449
235 449 INFANTRY 149 INFANTRY S*G*UCI---***** 128 TM Leader 449
236 463 INFANTRY AIR ASSAULT 154 INFANTRYAIRASSAULT S*G*UCIS--***** (null) (null) (null)
237 462 INFANTRY AIRBORNE 153 INFANTRYAIRBORNE S*G*UCIA--***** (null) (null) (null)
238 466 INFANTRY FIGHTING VEHICLE 157 INFANTRYFIGHTINGVEHICLE S*G*UCII--***** (null) (null) (null)
239 454 INFANTRY LIGHT 150 INFANTRYLIGHT S*G*UCIL--***** (null) (null) (null)
240 464 INFANTRY MECHANIZED 155 INFANTRYMECHANIZED S*G*UCIZ--***** (null) (null) (null)
241 456 INFANTRY MOTORIZED 151 INFANTRYMOTORIZED S*G*UCIM--***** (null) (null) (null)
242 461 INFANTRY MOUNTAIN 152 INFANTRYMOUNTAIN S*G*UCIO--***** (null) (null) (null)
243 465 INFANTRY NAVAL 156 INFANTRYNAVAL S*G*UCIN--***** (null) (null) (null)
244 600 INFORMATION OPERATIONS 315 INFORMATIONWARFAREUNIT S*G*UUI---***** (null) (null) (null)
245 765 INSTALLATION 576 INSTALLATION S*G*I-----H**** 225 MEU 765
246 765 INSTALLATION 576 INSTALLATION S*G*I-----H**** 224 Building 765
247 666 INTERMEDIATE RANGE AD MISSILE 473 INTERMEDIATERANGEADMISSILELAUNCH S*G*EWMAI-***** (null) (null) (null)
248 670 INTERMEDIATE RANGE SS MISSILE 478 INTERMEDIATERANGESSMISSILELAUNCH S*G*EWMSI-***** (null) (null) (null)
249 382 INTERNAL SECURITY FORCES 246 INTERNALSECURITYFORCES S*G*UCS---***** (null) (null) (null)
250 390 INTERNAL SECURITY FORCES AVIAT 254 AVIATION S*G*UCSA--***** (null) (null) (null)
251 387 INTERNAL SECURITY FORCES GROUN 251 MECHANIZEDGROUND S*G*UCSGA-***** (null) (null) (null)
252 384 INTERNAL SECURITY FORCES GROUND 248 GROUND S*G*UCSG--***** (null) (null) (null)
253 385 INTERNAL SECURITY FORCES GROUND DISMOUNTED 249 DISMOUNTEDGROUND S*G*UCSGD-***** (null) (null) (null)
254 386 INTERNAL SECURITY FORCES GROUND MOTORIZED 250 MOTORIZEDGROUND S*G*UCSGM-***** (null) (null) (null)
255 389 INTERNAL SECURITY FORCES RAILROAD 253 RAILROAD S*G*UCSR--***** (null) (null) (null)
256 383 INTERNAL SECURITY FORCES RIVERINE 247 RIVERINE S*G*UCSW--***** (null) (null) (null)
257 388 INTERNAL SECURITY FORCES WHEEL 252 WHEELEDMECHANIZED S*G*UCSM--***** (null) (null) (null)
258 791 LANDING CRAFT 623 LANDINGCRAFT S*S*CALC--***** (null) (null) (null)
259 790 LANDING SHIP 622 LANDINGSHIP S*S*CALS--***** (null) (null) (null)
260 601 LANDING SUPPORT 316 LANDINGSUPPORT S*G*UUX---***** (null) (null) (null)
261 762 LAND MINES 573 LANDMINES S*G*EXM---***** (null) (null) (null)
262 763 LAND MINES, LETHAL 574 LANDMINES,LETHAL S*G*EXMC--***** (null) (null) (null)
263 759 LASER 570 LASER S*G*EXL---***** (null) (null) (null)
264 584 LAW ENFORCEMENT UNIT 292 LAWENFORCEMENTUNIT S*G*UUL---***** (null) (null) (null)
265 587 LAW ENFORCEMENT UNIT CIVILIAN LAW ENFORCEMENT 295 CIVILIANLAWENFORCEMENT S*G*UULC--***** (null) (null) (null)
266 588 LAW ENFORCEMENT UNIT CRIMINAL INVESTIGATION DIVISI 297 CENTRALINTELLIGENCEDIVISION(CID) S*G*UULD--***** (null) (null) (null)
267 586 LAW ENFORCEMENT UNIT MILITARY POLICE 294 MILITARYPOLICE S*G*UULM--***** (null) (null) (null)
268 585 LAW ENFORCEMENT UNIT SHORE PATROL 293 SHOREPATROL S*G*UULS--***** (null) (null) (null)
269 794 LEISURE CRAFT 665 LEISURECRAFT S*S*XR----***** (null) (null) (null)
270 764 LESS THAN LETHAL 575 LESSTHANLETHAL S*G*EXML--***** (null) (null) (null)
271 737 LIGHT ARMOURED VEHICLE 545 LIGHTARMOUREDVEHICLE S*G*EVAL--***** (null) (null) (null)
272 701 LIGHT MACHINE GUN 498 LIGHTMACHINEGUN S*G*EWRL--***** 131 Soldier LMG 701
273 741 LIMITED CROSS-COUNTRY TRUCK 549 LIMITEDCROSS-COUNTRYTRUCK S*G*EVUL--***** (null) (null) (null)
274 667 LONG RANGE AD MISSILE LAUNCH 474 LONGRANGEADMISSILELAUNCH S*G*EWMAL-***** (null) (null) (null)
275 671 LONG RANGE SS MISSILE LAUNCH 479 LONGRANGESSMISSILELAUNCH S*G*EWMSL-***** (null) (null) (null)
276 648 MAINTENANCE 442 MAINTENANCE S*G*USX---***** (null) (null) (null)
277 654 MAINTENANCE BATTLE DAMAGE REPA 460 BATTLEDAMAGEREPAIR S*G*USXBDR***** (null) (null) (null)
278 653 MAINTENANCE ELECTRO-OPTICAL 457 ELECTRO-OPTICAL S*G*USXE--***** (null) (null) (null)
279 649 MAINTENANCE HEAVY 445 MAINTENANCEHEAVY S*G*USXH--***** (null) (null) (null)
280 651 MAINTENANCE ORDINANCE 451 ORDINANCE S*G*USXO--***** (null) (null) (null)
281 652 MAINTENANCE ORDINANCE MISSILE 454 ORDINANCEMISSILE S*G*USXOM-***** (null) (null) (null)
282 655 MAINTENANCE PREVENTIVE MAINTEN 461 PREVENTIVEMAINTANANCE S*G*USXPM-***** (null) (null) (null)
283 650 MAINTENANCE RECOVERY 448 MAINTENANCERECOVERY S*G*USXR--***** (null) (null) (null)
284 623 MEDICAL DENTAL 373 MEDICALDENTAL S*G*USMD--***** (null) (null) (null)
285 784 MEDICAL FACILITY 608 MEDICALFACILITY S*G*IX----H**** (null) (null) (null)
286 624 MEDICAL PSYCHOLOGICAL 376 MEDICALPSYCHOLOGICAL S*G*USMP--***** (null) (null) (null)
287 621 MEDICAL TREATMENT FACILITY 367 MEDICALTREATMENTFACILITY S*G*USMM--***** (null) (null) (null)
288 622 MEDICAL VETERINARY 370 MEDICALVETERINARY S*G*USMV--***** (null) (null) (null)
289 343 MILITARY 7 MILITARY S*A*M-----***** (null) (null) (null)
290 780 MILITARY BASE/FACILITY 604 MILITARYBASE/FACILITY S*G*IB----H**** (null) (null) (null)
291 344 MILITARY FIXED WING 8 FIXEDWING S*A*MF----***** (null) (null) (null)
292 567 MILITARY INTELLIGENCE 271 MILITARYINTELLIGENCE S*G*UUM---***** (null) (null) (null)
293 568 MILITARY INTELLIGENCE AERIAL EXPLOITATION 272 AERIALEXPLOITATION S*G*UUMA--***** (null) (null) (null)
294 577 MILITARY INTELLIGENCE COUNTER INTELLIGENCE 281 COUNTERINTELLIGENCE S*G*UUMC--***** (null) (null) (null)
295 573 MILITARY INTELLIGENCE ELECTRON 277 INTERCEPT S*G*UUMSEI***** (null) (null) (null)
296 572 MILITARY INTELLIGENCE ELECTRON 276 DIRECTIONFINDING S*G*UUMSED***** (null) (null) (null)
297 571 MILITARY INTELLIGENCE ELECTRON 275 ARMOUREDWHEELEDVEHICLE S*G*UUMSEA***** (null) (null) (null)
298 570 MILITARY INTELLIGENCE ELECTRONIC WARFARE 274 ELECTRONICWARFARE S*G*UUMSE-***** (null) (null) (null)
299 574 MILITARY INTELLIGENCE ELECTRONIC WARFARE JAMMING 278 JAMMING S*G*UUMSEJ***** (null) (null) (null)
300 582 MILITARY INTELLIGENCE INTERROGATION 290 INTERROGATION S*G*UUMQ--***** (null) (null) (null)
301 583 MILITARY INTELLIGENCE JOINT INTELLIGENCE CENTRE 291 JOINTINTELLIGENCECENTRE S*G*UUMJ--***** (null) (null) (null)
302 581 MILITARY INTELLIGENCE OPERATIONS 288 OPERATIONS S*G*UUMO--***** (null) (null) (null)
303 569 MILITARY INTELLIGENCE SIGNALS 273 SIGNALINTELLIGENCE(SIGINT) S*G*UUMS--***** (null) (null) (null)
304 579 MILITARY INTELLIGENCE SURVEILL 283 GROUNDSURVEILLANCERADAR S*G*UUMRG-***** (null) (null) (null)
305 578 MILITARY INTELLIGENCE SURVEILLANCE 282 SURVEILLANCE S*G*UUMR--***** (null) (null) (null)
306 580 MILITARY INTELLIGENCE SURVEILLANCE SENSOR 284 SENSOR S*G*UUMRS-***** (null) (null) (null)
307 346 MILITARY ROTARY WING 39 ROTARYWING S*A*MH----***** 195 Apache 346
308 766 MINE 578 MINE S*G*IRM---H**** (null) (null) (null)
309 749 MINE LAYING VEHICLE 557 MINELAYINGVEHICLE S*G*EVEM--***** 4 Trailer, Minelaying 749
310 675 MISSILE LAUNCHER AT HEAVY 483 MISSILELAUNCHERATHEAVY S*G*EWMTH-***** (null) (null) (null)
311 674 MISSILE LAUNCHER AT MEDIUM 482 MISSILELAUNCHERATMEDIUM S*G*EWMTM-***** (null) (null) (null)
312 663 MISSILE LAUNCHERS 470 MISSILELAUNCHERS S*G*EWM---***** (null) (null) (null)
313 672 MISSILE LAUNCHERS ANTI TANK (A 480 MISSILELAUNCHERSANTITANK(AT) S*G*EWMT--***** (null) (null) (null)
314 673 MISSILE LAUNCHERS AT LIGHT 481 MISSILELAUNCHERSATLIGHT S*G*EWMTL-***** (null) (null) (null)
315 544 MISSILE (SURF-SURF) 243 MISSILE(SURFACE-SURFACE) S*G*UCM---***** (null) (null) (null)
316 546 MISSILE (SURF-SURF) STRATEGIC 245 MISSILE(SURFACE-SURFACE)STRATEGIC S*G*UCMS--***** (null) (null) (null)
317 545 MISSILE (SURF-SURF) TACTICAL 244 MISSILE(SURFACE-SURFACE)TACTICAL S*G*UCMT--***** (null) (null) (null)
318 707 MORTAR 504 MORTAR S*G*EWO---***** 209 Soldier Mortar 707
319 710 MORTAR HEAVY 507 MORTARHEAVY S*G*EWOH--***** (null) (null) (null)
320 708 MORTAR LIGHT 505 MORTARLIGHT S*G*EWOL--***** (null) (null) (null)
321 709 MORTAR MEDIUM 506 MORTARMEDIUM S*G*EWOM--***** (null) (null) (null)
322 747 MULTIFUNCTIONAL EARTHMOVER/DIG 555 MULTIFUNCTIONALEARTHMOVER/DIGGER S*G*EVEE--***** (null) (null) (null)
323 691 MULTIPLE ROCKET LAUNCHER 488 MULTIPLEROCKETLAUNCHER S*G*EWX---***** (null) (null) (null)
324 694 MULTIPLE ROCKET LAUNCHER HEAVY 491 MULTIPLEROCKETLAUNCHERHEAVY S*G*EWXH--***** (null) (null) (null)
325 692 MULTIPLE ROCKET LAUNCHER LIGHT 489 MULTIPLEROCKETLAUNCHERLIGHT S*G*EWXL--***** (null) (null) (null)
326 693 MULTIPLE ROCKET LAUNCHER MEDIU 490 MULTIPLEROCKETLAUNCHERMEDIUM S*G*EWXM--***** (null) (null) (null)
327 771 NUCLEAR 583 NUCLEAR S*G*IRNN--H**** (null) (null) (null)
328 188 O/C Force 5 SPACESTATION S*P*T-----***** 113 O/C Staff 188
329 188 O/C Force 5 SPACESTATION S*P*T-----***** 180 O/C TM 188
330 188 O/C Force 5 SPACESTATION S*P*T-----***** 114 O/C Force 188
331 807 O/C Force CE 5 SPACESTATION S*P*T-----***** (null) (null) (null)
332 793 OILER/TANKER 655 OILER/TANKER S*S*XMO---***** (null) (null) (null)
333 792 PATROL 630 PATROL S*S*CP----***** (null) (null) (null)
334 767 PETROLEUM/GAS/OIL 579 PETROLEUM/GAS/OIL S*G*IRP---H**** (null) (null) (null)
335 656 PIPELINE 462 PIPELINE S*G*USXP--***** (null) (null) (null)
336 775 PUBLIC WATER SERVICES 591 PUBLICWATERSERVICES S*G*IUP---H**** (null) (null) (null)
337 757 RADAR 567 RADAR S*G*ESR---***** (null) (null) (null)
338 525 RECONNAISSANCE 226 RECONNAISSANCE S*G*UCR---***** (null) (null) (null)
339 535 RECONNAISSANCE AIR ASSAULT 234 RECONNAISSANCEAIRASSAULT S*G*UCRS--***** (null) (null) (null)
340 536 RECONNAISSANCE AIRBORNE 235 RECONNAISSANCEAIRBORNE S*G*UCRA--***** (null) (null) (null)
341 539 RECONNAISSANCE AMPHIBIOUS 238 RECONNAISSANCEMARINE S*G*UCRR--***** (null) (null) (null)
342 540 RECONNAISSANCE AMPHIBIOUS DIVI 239 RECONNAISSANCEMARINEDIVISION S*G*UCRRD-***** (null) (null) (null)
343 541 RECONNAISSANCE AMPHIBIOUS FORC 240 RECONNAISSANCEMARINEFORCE S*G*UCRRF-***** (null) (null) (null)
344 530 RECONNAISSANCE CAVALRY 228 RECONNAISSANCECAVALRY S*G*UCRV--***** (null) (null) (null)
345 534 RECONNAISSANCE CAVALRY AIR 232 RECONNAISSANCECAVALRYAIR S*G*UCRVO-***** (null) (null) (null)
346 531 RECONNAISSANCE CAVALRY ARMOURE 229 RECONNAISSANCECAVALRYARMOURED S*G*UCRVA-***** (null) (null) (null)
347 533 RECONNAISSANCE CAVALRY GROUND 231 RECONNAISSANCECAVALRYGROUND S*G*UCRVG-***** (null) (null) (null)
348 532 RECONNAISSANCE CAVALRY MOTORIZ 230 RECONNAISSANCECAVALRYMOTORIZED S*G*UCRVM-***** (null) (null) (null)
349 538 RECONNAISSANCE LIGHT 237 RECONNAISSANCELIGHT S*G*UCRLL--***** (null) (null) (null)
350 542 RECONNAISSANCE MARINE LIGHT AR 241 RECONNAISSANCEMARINELIGHTARMOUREDRECONNAISSANCE(LA S*G*UCRRL-***** (null) (null) (null)
351 537 RECONNAISSANCE MOUNTAIN 236 RECONNAISSANCEMOUNTAIN S*G*UCRO--***** (null) (null) (null)
352 543 RECONNAISSANCE SURVEILLANCE LO 242 RECONNAISSANCELONGRANGESURVEILLANCE(LRS) S*G*UCRX--***** (null) (null) (null)
353 700 RIFLE 497 RIFLE S*G*EWRR--***** 210 Soldier Assault Rifle 700
354 699 RIFLE/AUTOMATIC WEAPON 496 RIFLE/AUTOMATICWEAPON S*G*EWR---***** 205 Soldier Tgt 699
355 699 RIFLE/AUTOMATIC WEAPON 496 RIFLE/AUTOMATICWEAPON S*G*EWR---***** 216 Soldier M203 699
356 699 RIFLE/AUTOMATIC WEAPON 496 RIFLE/AUTOMATICWEAPON S*G*EWR---***** 153 Soldier MP 699
357 438 ROTARY WING ATTACK 131 ATTACKROTARYWING S*G*UCVRA-***** (null) (null) (null)
358 347 ROTARY WING ATTACK 40 ATTACK S*A*MHA---***** (null) (null) (null)
359 352 ROTARY WING DRONE (RPV/UAV) 49 DRONE(RPV/UAV) S*A*MHQ---***** (null) (null) (null)
360 348 ROTARY WING MEDEVAC 55 MEDEVAC S*A*MHO---***** (null) (null) (null)
361 351 ROTARY WING RECCE 48 RECONNAISSANCE S*A*MHR---***** (null) (null) (null)
362 349 ROTARY WING SOF 56 SPECIALOPERATIONSFORCE(SOF) S*A*MHM---***** (null) (null) (null)
363 350 ROTARY WING UTILITY 42 UTILITY S*A*MHU---***** (null) (null) (null)
364 782 SEAPORT/NAVAL BASE 606 SEAPORT/NAVALBASE S*G*IBN---H**** (null) (null) (null)
365 786 SEA SURFACE INSTALLATION, OIL RIG / PLATFORM 611 SEASURFACEINSTALLATION,OILRIG/PLATFORM S*G*IRR---H**** (null) (null) (null)
366 787 SEA SURFACE TRACK 612 SEASURFACETRACK S*S*------***** (null) (null) (null)
367 740 SEMI 548 SEMI S*G*EVUS--***** (null) (null) (null)
368 756 SENSOR 566 SENSOR S*G*ES----***** (null) (null) (null)
369 616 SERVICE SUPPORT MEDICAL 364 MEDICAL S*G*USM---***** (null) (null) (null)
370 641 SERVICE SUPPORT TRANSPORTATION 424 TRANSPORTATION S*G*UST---***** 53 TATRA Logistics Carrier 641
371 665 SHORT RANGE AD MISSILE LAUNCHE 472 SHORTRANGEADMISSILELAUNCHERS S*G*EWMAS-***** (null) (null) (null)
372 669 SHORT RANGE SS MISSILE LAUNCH 477 SHORTRANGESSMISSILELAUNCH S*G*EWMSS-***** (null) (null) (null)
373 593 SIGNALS UNIT FORWARD COMMUNICATIONS 303 FORWARDCOMMUNICATIONS S*G*UUSF--***** (null) (null) (null)
374 597 SIGNALS UNIT SIGNAL SUPPORT 312 SIGNALSUPPORT S*G*UUSS--***** (null) (null) (null)
375 589 SIGNAL UNIT 298 SIGNALUNIT S*G*UUS---***** (null) (null) (null)
376 590 SIGNAL UNIT AREA 299 AREA S*G*UUSA--***** (null) (null) (null)
377 592 SIGNAL UNIT COMMAND OPERATIONS 302 COMMANDOPERATIONS S*G*UUSO--***** (null) (null) (null)
378 591 SIGNAL UNIT COMMUNICATION CONF 300 COMMUNICATIONCONFIGUREDPACKAGE S*G*UUSC--***** (null) (null) (null)
379 599 SIGNAL UNIT ELECTRONIC RANGING 314 ELECTRONICRANGING S*G*UUSX--***** (null) (null) (null)
380 594 SIGNAL UNIT RADIO UNIT 308 RADIOUNIT S*G*UUSR--***** (null) (null) (null)
381 596 SIGNAL UNIT RADIO UNIT RELAY 311 RELAY S*G*UUSRW-***** (null) (null) (null)
382 595 SIGNAL UNIT RADIO UNIT TACTICA 309 TACTICALSATELLITE S*G*UUSRS-***** (null) (null) (null)
383 598 SIGNAL UNIT TELEPHONE SWITCH 313 TELEPHONESWITCH S*G*UUSW--***** (null) (null) (null)
384 687 SINGLE ROCKET LAUNCHER 484 SINGLEROCKETLAUNCHER S*G*EWS---***** (null) (null) (null)
385 690 SINGLE ROCKET LAUNCHER HEAVY 487 SINGLEROCKETLAUNCHERHEAVY S*G*EWSH--***** (null) (null) (null)
386 688 SINGLE ROCKET LAUNCHER LIGHT 485 SINGLEROCKETLAUNCHERLIGHT S*G*EWSL--***** (null) (null) (null)
387 689 SINGLE ROCKET LAUNCHER MEDIUM 486 SINGLEROCKETLAUNCHERMEDIUM S*G*EWSM--***** (null) (null) (null)
388 796 SOF AVIATION FIXED WING 707 SOFUNITFIXEDWING S*F*AF----***** (null) (null) (null)
389 797 SOF AVIATION FIXED WING ATTACK 708 SOFUNITATTACK S*F*AFA---***** (null) (null) (null)
390 798 SOF AVIATION FIXED WING UTILIT 710 SOFUNITUTILITY S*F*AFU---***** (null) (null) (null)
391 799 SOF AVIATION FIXED WING UTILIT 711 SOFUNITUTILITY(LIGHT) S*F*AFUL--***** (null) (null) (null)
392 800 SOF AVIATION ROTARY WING 715 SOFUNITROTARYWING S*F*AH----***** (null) (null) (null)
393 803 SOF UNIT GROUND 727 SOFUNITGROUND S*F*G-----***** (null) (null) (null)
394 805 SOF UNIT GROUND RANGER 729 SOFUNITRANGER S*F*GSR---***** (null) (null) (null)
395 804 SOF UNIT GROUND SPECIAL FORCES 728 SOFUNITSPECIALFORCES S*F*GS----***** (null) (null) (null)
396 801 SOF UNIT NAVAL 722 SOFUNITSOFUNITNAVAL S*F*SN----***** (null) (null) (null)
397 802 SOF UNIT NAVAL SPECIAL BOAT 725 SOFUNITSPECIALBOAT S*F*SNB---***** (null) (null) (null)
398 806 SOF UNIT PSYCHOLOGICAL OPERATI 730 SOFUNITPSYCHOLOGICALOPERATIONS(PSYOPS) S*F*GSP---***** (null) (null) (null)
399 658 SPECIAL C2 HEADQUATERS COMPONE 464 SPECIALC2HEADQUARTERSCOMPONENT S*G*UH----***** (null) (null) (null)
400 795 SPECIAL OPERATIONS FORCE (SOF) 705 SPECIALOPERATIONSFORCE(SOF)UNIT S*F*------***** (null) (null) (null)
401 625 SUPPLY 379 SUPPLY S*G*USS---***** (null) (null) (null)
402 633 SUPPLY CLASS I 382 SUPPLYCLASSI S*G*USS1--***** (null) (null) (null)
403 634 SUPPLY CLASS II 385 SUPPLYCLASSII S*G*USS2--***** (null) (null) (null)
404 635 SUPPLY CLASS III 388 SUPPLYCLASSIII S*G*USS3--***** (null) (null) (null)
405 636 SUPPLY CLASS III AVIATION 391 SUPPLYCLASSIIIAVIATION S*G*USS3A-***** (null) (null) (null)
406 637 SUPPLY CLASS IV 394 SUPPLYCLASSIV S*G*USS4--***** (null) (null) (null)
407 627 SUPPLY CLASS IX 409 SUPPLYCLASSIX S*G*USS9--***** (null) (null) (null)
408 638 SUPPLY CLASS V 397 SUPPLYCLASSV S*G*USS5--***** (null) (null) (null)
409 639 SUPPLY CLASS VI 400 SUPPLYCLASSVI S*G*USS6--***** (null) (null) (null)
410 640 SUPPLY CLASS VII 403 SUPPLYCLASSVII S*G*USS7--***** (null) (null) (null)
411 626 SUPPLY CLASS VIII 406 SUPPLYCLASSVIII S*G*USS8--***** (null) (null) (null)
412 628 SUPPLY CLASS X 412 SUPPLYCLASSX S*G*USSX--***** (null) (null) (null)
413 629 SUPPLY LAUNDRY/BATH 415 SUPPLYLAUNDRY/BATH S*G*USSL--***** (null) (null) (null)
414 632 SUPPLY MATERIEL (STOCK) 1335 SUPPLYMATERIEL(STOCK) S*G*US**--***** (null) (null) (null)
415 630 SUPPLY WATER 418 SUPPLYWATER S*G*USSW--***** (null) (null) (null)
416 631 SUPPLY WATER PURIFICATION 421 SUPPLYWATERPURIFICATION S*G*USSWP-***** (null) (null) (null)
417 668 SURFACE- SURFACE (SS) MISSILE 476 SURFACE-SURFACE(SS)MISSILELAUNCHER S*G*EWMS--***** (null) (null) (null)
418 355 SURFACE TO AIR MISSILE 65 SURFACETOAIRMISSILE(SAM) S*A*WMSA--***** (null) (null) (null)
419 354 SURFACE TO SURFACE MISSILE 64 SURFACETOSURFACEMISSILE(SSM) S*A*WMSS--***** (null) (null) (null)
420 391 SURVEILLANCE 1334 SURVEILLANCE S*G*F-S---***** (null) (null) (null)
421 725 TANK 533 TANK S*G*EVAT--***** 233 0Vehicle 725
422 725 TANK 533 TANK S*G*EVAT--***** 43 MBT 725
423 725 TANK 533 TANK S*G*EVAT--***** 230 LEOPARD 2A5 725
424 730 TANK HEAVY 538 TANKHEAVY S*G*EVATH-***** (null) (null) (null)
425 731 TANK HEAVY RECOVERY 539 TANKHEAVYRECOVERY S*G*EVATY-***** (null) (null) (null)
426 726 TANK LIGHT 534 TANKLIGHT S*G*EVATL-***** (null) (null) (null)
427 727 TANK LIGHT RECOVERY 535 TANKLIGHTRECOVERY S*G*EVATW-***** 110 BMP3 Recovery 727
428 728 TANK MEDIUM 536 TANKMEDIUM S*G*EVATM-***** (null) (null) (null)
429 729 TANK MEDIUM RECOVERY 537 TANKMEDIUMRECOVERY S*G*EVATX-***** (null) (null) (null)
430 773 TELECOMMUNICATIONS FACILITY 589 TELECOMMUNICATIONSFACILITY S*G*IUT---H**** (null) (null) (null)
431 603 TOPOGRAPHIC 318 TOPOGRAPHIC S*G*UUT---***** (null) (null) (null)
432 751 TRAILER MOUNTED 559 TRAILERMOUNTED S*G*EVEMT-***** (null) (null) (null)
433 754 TRAIN LOCOMOTIVE 564 TRAINLOCOMOTIVE S*G*EVST--***** (null) (null) (null)
434 645 TRANSPORTATION APOD/APOE 436 APOD/APOE S*G*USTA--***** (null) (null) (null)
435 647 TRANSPORTATION INTERMODAL 1328 TRANSPORTATIONINTERMODAL S*G*UST---***** (null) (null) (null)
436 646 TRANSPORTATION MISSILE 439 MISSILE S*G*USTI--***** (null) (null) (null)
437 642 TRANSPORTATION MOVEMENT CONTRO 427 MOVEMENTCONTROLCENTRE(MCC) S*G*USTM--***** (null) (null) (null)
438 643 TRANSPORTATION RAILHEAD 430 RAILHEAD S*G*USTR--***** (null) (null) (null)
439 644 TRANSPORTATION SPOD/SPOE 433 SPOD/SPOE S*G*USTS--***** (null) (null) (null)
440 783 TRANSPORT FACILITY 607 TRANSPORTFACILITY S*G*IT----H**** (null) (null) (null)
441 661 UNITS GENERAL LIAISON 467 UNITGENERALLIAISON S*G*UHGL--***** (null) (null) (null)
442 738 UTILITY VEHICLE 546 UTILITYVEHICLE S*G*EVU---***** 54 HMMWV Utility 738
443 738 UTILITY VEHICLE 546 UTILITYVEHICLE S*G*EVU---***** 221 Vehicle Tgt 738
444 743 WATER CRAFT 551 WATERCRAFT S*G*EVUR--***** 213 TATRA Tanker Water 743
445 353 WEAPON 61 WEAPON S*A*W-----***** (null) (null) (null)
@@ -0,0 +1,42 @@
#
# $Id$
# $HeadURL$
# $Author$
#
# PlanModel
SET(GeometryModel_SRCS
geometry_model.dtd
geometry_model.cpp
geometry_model.h
geometry_model_export.h
geometry_model_factory.cpp
geometry_model_factory.h
geometry_model_q_dom.cpp
geometry_model_q_dom.h
geometry_node_visitor.cpp
geometry_node_visitor.h
geometry_pixelTextBox.cpp
)
SOURCE_GROUP(GeometryModel FILES ${GeometryModel_SRCS})
NGL_ADD_LIBRARY(WS situationMapGeometryModel SHARED ${GeometryModel_SRCS})
NGL_TARGET_INCLUDE_DIRECTORIES( situationMapGeometryModel
PUBLIC
${CMAKE_CURRENT_SOURCE_DIR}
${CMAKE_CURRENT_SOURCE_DIR}/..
)
NGL_TARGET_LINK_LIBRARIES(situationMapGeometryModel
PRIVATE
NGLLogger
PUBLIC
situationMapCommon
Qt6::Core
Qt6::Gui
Qt6::Xml
)
NGL_INSTALL_TARGET(situationMapGeometryModel)
@@ -0,0 +1,38 @@
/**
**
** @RDE_HEADER@
** GeometryModel to write and read PlanEditor plans.
** $Id$
** $HeadURL$
** $Author$
**
** -----------------------------------------------------------------------------------------------
**
** Hardware-Environment: Intel-PC
** Software-Environment: Windows 7, Qt 5.4. ArcGIS 10.2.5
**
** Language ........: C++ 11
**
** -----------------------------------------------------------------------------------------------
**
** Author ...........: Jörg Turla, SPD G, Tel. 3132
**
** -----------------------------------------------------------------------------------------------
**
** Notes .........:
**
** 11.11.2015, JT : First edition for use with Qt5
**
** -----------------------------------------------------------------------------------------------
*/
#include "geometry_model.h"
namespace SituationMap
{
GeometryModel::GeometryModel(QObject *parent) : QObject(parent) {;}
GeometryModel::GeometryModel(const GeometryModel &) : QObject() {;}
} // namespace SituationMap
@@ -0,0 +1,400 @@
<!--
DTD fuer Plan-Formate
(c)RDE 2009
Stephan Kuhagen
-->
<!--
The Top-Element of the Plan. Defines global variables in the Attributes.
-->
<!ELEMENT GeometryModelDocument (GeometryModel|MapSettings) >
<!ELEMENT GeometryModel (dictionarySymbol|ellipse|line|polyline|rectangle|spline|symbol|text|node)>
<!ELEMENT MapSettings EMPTY>
<!--
utm_zone: UTM-zone and band (two digits, one char)
utm_grid: UTM-grid-Square (two chars)
utm_east: UTM-easting-value (int)
utm_north: UTM-northing-value (int)
pe_show_utm: bool to indicate, if the PE should display the UTM-grid
pe_map_saturation: saturation in % of the map in the PE
pe_map_brightness: brightness in % of the map in the PE
pe_map_zoom: zoom-value of the map in the PE
pe_map_rotation: The rotation of the map (double)
pe_map_type: The type of the map (Raster, Vector, Contour, Elevation, RasterElevation)
pe_map_centerx: center-x of the map in the PE
pe_map_centery: center-y of the map in the PE
-->
<!ATTLIST MapSettings
utm_zone CDATA #REQUIRED
utm_grid CDATA #REQUIRED
utm_east CDATA #REQUIRED
utm_north CDATA #REQUIRED
pe_show_utm CDATA #REQUIRED
pe_map_saturation CDATA #REQUIRED
pe_map_brightness CDATA #REQUIRED
pe_map_zoom CDATA #REQUIRED
pe_map_rotation CDATA #REQUIRED
pe_map_type CDATA #REQUIRED
pe_map_centerx CDATA #REQUIRED
pe_map_centery CDATA #REQUIRED
pe_symbol_transparency CDATA #IMPLIED
pe_symbol_fill_type CDATA #IMPLIED
pe_symbol_scale CDATA #IMPLIED>
<!--
A node is a grouping element, which can hold any number of primitives or
other nodes, thus creating a tree.
-->
<!ELEMENT node (dictionarySymbol|ellipse|line|polyline|rectangle|spline|symbol|text|node)*>
<!--
The symbology library provides a symbol dictionary. Each symbol is defined by a list of coordinates and one non-ambiguous SIDC code. The SIDC
is a string with 15 character. See symbology library for further details.
-->
<!ELEMENT dictionarySymbol (point+)>
<!ATTLIST dictionarySymbol
GuiDisplayName CDATA #IMPLIED
SIDC CDATA #REQUIRED
SIDC_Norm CDATA #REQUIRED >
<!--
Defines ellipsis and circles. Can have start-angle and extent for sections of
circles/ellipsis. The point defines the center of the primitive. The
Attributes width and height define the metric dimensions, resulting in a
centered bounding box. The primitive can be rotated with attribute
rotate. Start-angle and extent are defined for the axis-parallel bounding-box
and are rotated with the box. Rotation is done around the center-point.
The optional text-tag is used for text directly assigned to this primitive.
-->
<!ELEMENT ellipse (point,text?)>
<!--
width: The metric width of the ellipse.
height: The metric height of the ellipse.
rotate: The bounding rectangle, that defines the ellipse is rotated according
to the angle here (360° for full rotation). Double-Value.
start: Sets the start-angle of an open ellipse before (!) rotation. Double-Value.
extent: Sets the extent of the ellipse. For a full ellipse this must be
360. Double-Value.
color: Color in 32-Bit hex RGBA (#RRGGBBAA)
linewidth: Line-width. Double-Value.
linestyle: An enum defining the line-style
fill: A bool, if true, the primitive should be filled with the given color and pattern.
fill_color: Fill-Color in 32-Bit hex RGBA (#RRGGBBAA)
fill_pattern: An enum defining the fill-pattern.
fill_style: An enum defining the style for a filles ellipse:
- "chord": A straight line between the start-point and end-point
defines the inner region to be filled.
- "pieslice": A line from the start-point to the center and from the
center to the end-point define the inner region to be filled.
-->
<!ATTLIST ellipse
GuiDisplayName CDATA #IMPLIED
rotate CDATA #IMPLIED
width CDATA #REQUIRED
height CDATA #REQUIRED
start CDATA #IMPLIED
extent CDATA #IMPLIED
color CDATA #REQUIRED
linewidth CDATA #REQUIRED
linestyle (solid|dashed|dotted|dashed_dotted) #IMPLIED
fill CDATA #IMPLIED
fill_color CDATA #IMPLIED
fill_pattern (none|dots|hor1|hor2|ver1|ver2|diag1|diag2|solid) #IMPLIED
fill_style (chord|pieslice) #IMPLIED>
<!--
Defines a line with start- and endpoint.
The optional text-tag is used for text directly assigned to this primitive.
-->
<!ELEMENT line (point,point,text?)>
<!--
color: Color in 32-Bit hex RGBA (#RRGGBBAA)
arrows: Enum defining, if and where to add arrows to the line.
arrow_height: The height of the arrow from the arrow-head to the outer points,
parallel to the middle axis of the arrow.
arrow_clamp_height: The height from the the arrow-neck to the outer points,
parallel to the middle axis of the arrow.
arrow_width: The distance between the outer points of the arrow.
arrow_line_width: The line width of the line used to draw the arrow.
linewidth: Line-width. Double-Value.
linestyle: An enum defining the line-style
-->
<!ATTLIST line
GuiDisplayName CDATA #IMPLIED
color CDATA #REQUIRED
arrows (none|start|end|both) #IMPLIED
arrow_height CDATA #IMPLIED
arrow_clamp_height CDATA #IMPLIED
arrow_width CDATA #IMPLIED
arrow_line_width CDATA #IMPLIED
linewidth CDATA #REQUIRED
linestyle (solid|dashed|dotted|dashed_dotted) #IMPLIED>
<!--
Defines a polyline with at least three points.
The optional text-tag is used for text directly assigned to this primitive.
-->
<!ELEMENT polyline (point,point,point+,text?)>
<!--
color: Color in 32-Bit hex RGBA (#RRGGBBAA)
linewidth: Line-width. Double-Value.
linestyle: An enum defining the line-style
arrows: Enum defining, if and where to add arrows to the line. If the
primitive is closed, no arrows should be drawn.
arrow_height: The height of the arrow from the arrow-head to the outer points,
parallel to the middle axis of the arrow.
arrow_clamp_height: The height from the the arrow-neck to the outer points,
parallel to the middle axis of the arrow.
arrow_width: The distance between the outer points of the arrow.
arrow_line_width: The line width of the line used to draw the arrow.
close: A bool. If true, connect the start- and end-point.
fill: A bool, if true, the primitive should be filled with the given color and pattern.
fill_color: Fill-Color in 32-Bit hex RGBA (#RRGGBBAA)
fill_pattern: An enum defining the fill-pattern.
-->
<!ATTLIST polyline
GuiDisplayName CDATA #IMPLIED
color CDATA #REQUIRED
linewidth CDATA #REQUIRED
linestyle (solid|dashed|dotted|dashed_dotted) #IMPLIED
arrows (none|start|end|both) #IMPLIED
arrow_height CDATA #IMPLIED
arrow_clamp_height CDATA #IMPLIED
arrow_width CDATA #IMPLIED
arrow_line_width CDATA #IMPLIED
close CDATA #REQUIRED
fill CDATA #IMPLIED
fill_color CDATA #IMPLIED
fill_pattern (none|dots|hor1|hor2|ver1|ver2|diag1|diag2|solid) #IMPLIED>
<!--
Defines a rectangle with a center-point and width/height.
The optional text-tag is used for text directly assigned to this primitive.
-->
<!ELEMENT rectangle (point,text?)>
<!--
color: Color in 32-Bit hex RGBA (#RRGGBBAA)
width: The metric width of the rectangle.
height: The metric height of the rectangle.
rotate: The rectangle is rotated according to the angle here (360° for full
rotation). Double-Value.
linewidth: Line-width. Double-Value.
linestyle: An enum defining the line-style
rounding: A percentage-value (double) for round edges
fill: A bool, if true, the primitive should be filled with the given color and pattern.
fill_color: Fill-Color in 32-Bit hex RGBA (#RRGGBBAA)
fill_pattern: An enum defining the fill-pattern.
-->
<!ATTLIST rectangle
GuiDisplayName CDATA #IMPLIED
color CDATA #REQUIRED
width CDATA #REQUIRED
height CDATA #REQUIRED
rotate CDATA #IMPLIED
linewidth CDATA #REQUIRED
linestyle (solid|dashed|dotted|dashed_dotted) #IMPLIED
rounding CDATA #IMPLIED
fill CDATA #IMPLIED
fill_color CDATA #IMPLIED
fill_pattern (none|dots|hor1|hor2|ver1|ver2|diag1|diag2|solid) #IMPLIED>
<!--
Defines a spline with at least three points. The first and the last point
define the endpoints, all other points define the curve between them.
The optional text-tag is used for text directly assigned to this primitive.
-->
<!ELEMENT spline (point,point,point+,text?)>
<!--
color: Color in 32-Bit hex RGBA (#RRGGBBAA)
linewidth: Line-width. Double-Value.
linestyle: An enum defining the line-style
arrows: Enum defining, if and where to add arrows to the line. If the
primitive is closed, no arrows should be drawn.
arrow_height: The height of the arrow from the arrow-head to the outer points,
parallel to the middle axis of the arrow.
arrow_clamp_height: The height from the the arrow-neck to the outer points,
parallel to the middle axis of the arrow.
arrow_width: The distance between the outer points of the arrow.
arrow_line_width: The line width of the line used to draw the arrow.
close: A bool. If true, connect the start- and end-point.
fill: A bool. If true, the primitive should be filled with the given color and
pattern. This also means, that the start-point is automatically
connected to the end-point to get a closed shape to fill.
fill_color: Fill-Color in 32-Bit hex RGBA (#RRGGBBAA)
fill_pattern: An enum defining the fill-pattern.
-->
<!ATTLIST spline
GuiDisplayName CDATA #IMPLIED
color CDATA #REQUIRED
linewidth CDATA #REQUIRED
linestyle (solid|dashed|dotted|dashed_dotted) #IMPLIED
arrows (none|start|end|both) #IMPLIED
arrow_height CDATA #IMPLIED
arrow_clamp_height CDATA #IMPLIED
arrow_width CDATA #IMPLIED
arrow_line_width CDATA #IMPLIED
close CDATA #REQUIRED
fill CDATA #IMPLIED
fill_color CDATA #IMPLIED
fill_pattern (none|dots|hor1|hor2|ver1|ver2|diag1|diag2|solid) #IMPLIED>
<!--
A symbol to display in the plan.
position, offsetx (in Pixel), offsety (in Pixel), direction of movement
-->
<!ELEMENT symbol (point)>
<!--
text_w: Text for symbols text-field w.
text_xy: Text for symbols text-field xy.
text_v: Text for symbols text-field v.
text_t: Text for symbols text-field t.
text_z: Text for symbols text-field z.
text_ef: Text for symbols text-field ef.
text_g: Text for symbols text-field g.
text_h: Text for symbols text-field h.
text_m: Text for symbols text-field m.
text_jklnp: Text for symbols text-field jklnp.
symbol_id: ID of the symbol (int).
force_id: Force-ID of the symbol (int).
abc_protection: Flag for abc_protection (bool).
affil: Enum for affiliation of the symbol.
mobility: Enum for the mobility of the symbol.
w_vbg_et: Enum for tactical state of the symbol. Corresponds to enum w_vbg_et
in zskssmal_teilnehmer.h.
rotate: The Symbol is rotated according
to the angle here (360° for full rotation). Double-Value.
-->
<!ATTLIST symbol
GuiDisplayName CDATA #IMPLIED
text_w CDATA #IMPLIED
text_xy CDATA #IMPLIED
text_v CDATA #IMPLIED
text_t CDATA #IMPLIED
text_z CDATA #IMPLIED
text_ef CDATA #IMPLIED
text_g CDATA #IMPLIED
text_h CDATA #IMPLIED
text_m CDATA #IMPLIED
text_jklnp CDATA #IMPLIED
symbol_id CDATA #IMPLIED
symbol_offsetX CDATA #IMPLIED
symbol_offsetY CDATA #IMPLIED
symbol_direction CDATA #IMPLIED
force_id CDATA #IMPLIED
symbol_state CDATA #IMPLIED
symbol_uncertainty CDATA #IMPLIED
damage_force_id CDATA #IMPLIED
abc_protection CDATA #IMPLIED
affil (unknown|friend|neutral|enemy) #REQUIRED
mobility (wheel|wheel_all_terrain|chain|chain_all_terrain|trailer|train) #REQUIRED
w_vbg_et (einsatzbereit|treffer_ohne_wirkung|annaehender_treffer|zeitlicher_ausfall|leichter_treffer|mittlerer_treffer|schwerer_treffer|bewegungsunfaehig|bewegungsunfaehig_sichtb|ausfall_waffenanlage|ausfall_waffenanlage_sichtb|totalausfall) #REQUIRED
rotate CDATA #IMPLIED>
<!--
A one-line or multiline-text with optional background and frame.
If used as a child to another primitive, the point position of the text is
ignored. The alignment attributes define the text-position in relation to the
primitive instead.
-->
<!ELEMENT text (point,text_data)>
<!--
anchor_horizontal: Horizontal position of the text on its point
anchor_vertical: Vertical position of the text on its point
margin_horizontal: Horizontal margin in Pixels between the texts bounding box and the surrounding frame
margin_vertical: Vertical margin in Pixels between the texts bounding box and the surrounding frame
color: Color in 32-Bit hex RGBA (#RRGGBBAA)
font: Font-Type
font_size: Font-Size. Int.
font_italic: A bool. If true, the font should be italic.
font_bold: A bool. If true, the font should be bold.
box: A bool, if true, the primitive should be filled with the given color and pattern.
linewidth: Line-width for the box. Double-Value.
linestyle: An enum defining the line-style for the box.
linecolor: Color in 32-Bit hex RGBA (#RRGGBBAA) for the outline of the box.
fill: A bool, if true, the box should be filled with the given color and pattern.
fill_color: Fill-Color for the box in 32-Bit hex RGBA (#RRGGBBAA)
fill_pattern: An enum defining the fill-pattern for the box.
rotate: The bounding rectangle, that defines the ellipse is rotated according
to the angle here (360° for full rotation). Double-Value.
-->
<!ATTLIST text
GuiDisplayName CDATA #IMPLIED
anchor_horizontal (left|center|right) #REQUIRED
anchor_vertical (top|center|bottom) #REQUIRED
margin_horizontal CDATA #IMPLIED
margin_vertical CDATA #IMPLIED
color CDATA #REQUIRED
font (SansSerif|Serif|Fixed|Decorative) #REQUIRED
font_size CDATA #REQUIRED
font_italic CDATA #IMPLIED
font_bold CDATA #IMPLIED
box CDATA #IMPLIED
linewidth CDATA #IMPLIED
linestyle (solid|dashed|dotted|dashed_dotted) #IMPLIED
linecolor CDATA #IMPLIED
fill CDATA #IMPLIED
fill_color CDATA #IMPLIED
fill_pattern (none|dots|hor1|hor2|ver1|ver2|diag1|diag2|solid) #IMPLIED
rotate CDATA #IMPLIED>
<!--
A tag that contains the actual text-data of a text-tag.
-->
<!ELEMENT text_data (#PCDATA)>
<!--
alignment: If this text contains more than one line, this defines the
alignment of the text in the bounding box of all lines.
-->
<!ATTLIST text_data
alignment (left|center|right) #REQUIRED>
<!--
Defines a point with a double precision x and y-value.
-->
<!ELEMENT point EMPTY>
<!--
x: The x-coordinate of the point.
y: The y-coordinate of the point.
-->
<!ATTLIST point
x CDATA #REQUIRED
y CDATA #REQUIRED>
File diff suppressed because it is too large. Load diff
@@ -0,0 +1,21 @@
/**
* Export definitions
* $Id$
* $HeadURL$
* $Author$
*/
#pragma once
#include <qglobal.h>
#ifndef GEOMETRYMODEL_EXPORT
# ifdef BUILD_STATIC_LIBRARIES
# define GEOMETRYMODEL_EXPORT
# else
# if defined(MAKE_SITUATIONMAPGEOMETRYMODEL_LIB)
# define GEOMETRYMODEL_EXPORT Q_DECL_EXPORT
# else
# define GEOMETRYMODEL_EXPORT Q_DECL_IMPORT
# endif
# endif
#endif
@@ -0,0 +1,58 @@
/**
**
** @RDE_HEADER@
** GeometryModelFactory to create geometry model
** $Id$
** $HeadURL$
** $Author$
**
** -----------------------------------------------------------------------------------------------
**
** Hardware-Environment: Intel-PC
** Software-Environment: Windows 7, Qt 5.4. ArcGIS 10.2.5
**
** Language ........: C++ 11
**
** -----------------------------------------------------------------------------------------------
**
** Author ...........: Jörg Turla, SPD G, Tel. 3132
**
** -----------------------------------------------------------------------------------------------
**
** Notes .........:
**
** 20.11.2015, JT : First edition for use with Qt5
**
** -----------------------------------------------------------------------------------------------
*/
#include "geometry_model_factory.h"
#include "geometry_model_q_dom.h"
namespace SituationMap
{
GeometryModelFactory *GeometryModelFactory::singleton()
{
static GeometryModelFactory s_factory;
return &s_factory;
} /* GeometryModelFactory::singleton() */
GeometryModel *GeometryModelFactory::create()
{
return new GeometryModelQDom();
} // GeometryModelFactory::create()
GeometryModel *GeometryModelFactory::clone(GeometryModel *geoModel)
{
GeometryModelQDom * qdomModel = dynamic_cast<GeometryModelQDom*>(geoModel);
if (qdomModel)
return new GeometryModelQDom(*qdomModel);
return nullptr;
} // GeometryModelFactory::clone()
} /* namespace SituationMap */
@@ -0,0 +1,59 @@
/**
**
** @RDE_HEADER@
** GeometryModelFactory to create geometry model
** $Id$
** $HeadURL$
** $Author$
**
** -----------------------------------------------------------------------------------------------
**
** Hardware-Environment: Intel-PC
** Software-Environment: Windows 7, Qt 5.4. ArcGIS 10.2.5
**
** Language ........: C++ 11
**
** -----------------------------------------------------------------------------------------------
**
** Author ...........: Jörg Turla, SPD G, Tel. 3132
**
** -----------------------------------------------------------------------------------------------
**
** Notes .........:
**
** 20.11.2015, JT : First edition for use with Qt5
**
** -----------------------------------------------------------------------------------------------
*/
#pragma once
#include "geometry_model_q_dom.h"
namespace SituationMap
{
/**
@brief Factory class to create GeometryModels
@see GeometryModel GeometryModelQDom
*/
class GEOMETRYMODEL_EXPORT GeometryModelFactory
{
public:
static GeometryModelFactory *singleton();
GeometryModelFactory() = default;
~GeometryModelFactory() = default;
GeometryModelFactory(const GeometryModelFactory &) = delete;
GeometryModelFactory operator =(const GeometryModelFactory &) = delete;
GeometryModel *create();
GeometryModel *clone( GeometryModel * );
}; /* GeometryModelFactory */
} /* namespace SituationMap */
File diff suppressed because it is too large. Load diff
@@ -0,0 +1,374 @@
/**
**
** @RDE_HEADER@
** GeometryModel implementation to write and read PlanEditor plans from/to XML and manipulate DOM-tree.
** $Id$
** $HeadURL$
** $Author$
**
** -----------------------------------------------------------------------------------------------
**
** Hardware-Environment: Intel-PC
** Software-Environment: Windows 7, Qt 5.4. ArcGIS 10.2.5
**
** Language ........: C++ 11
**
** -----------------------------------------------------------------------------------------------
**
** Author ...........: Stephan Kuhagen <kuhagen@rheinmetall-de.com>
** Jörg Turla, SPD G, Tel. 3132
**
** -----------------------------------------------------------------------------------------------
**
** Notes .........:
**
** ??.??.200?, SK : First edition for use with Qt4
** 11.11.2015, JT : Splitting interface and implementation
**
** -----------------------------------------------------------------------------------------------
*/
// clazy:excludeall=const-signal-or-slot
#pragma once
#include <QtGui/QColor>
#include <QtXml/QDomDocument>
#include <QtCore/QMultiMap>
#include <QtCore/QObject>
#include <QtCore/QPair>
#include <QtCore/QPointF>
#include <QtCore/QRectF>
#include <QtCore/QStack>
#include <QtCore/QString>
#include <QtCore/QStringList>
#include <QtCore/QVariant>
#include "geometry_model.h"
class QTransform;
namespace SituationMap
{
// exported for unit test only
class GEOMETRYMODEL_EXPORT GeometryModelQDom : public GeometryModel, public QDomDocument
{
Q_OBJECT
public:
explicit GeometryModelQDom(QObject *parent = nullptr);
//! Copy-Constructor
GeometryModelQDom(const GeometryModelQDom &other);
~GeometryModelQDom();
GeometryModelQDom & operator = (const GeometryModelQDom &other);
QByteArray toByteArray() const override;
QByteArray toByteArrayDebug() const override;
bool fromByteArray(const QByteArray &content) override;
bool fromDevice(QIODevice *device) override;
bool fromByteArrayDebug(const QByteArray &content) override;
bool isEmpty() const override;
Node getRootNode() const override;
Node getMapDefaultSettingsNode() const override;
void setModelAttribute(GeometryModel::Attribute attribute, const QVariant &value) override;
void setModelEditorAttribute(GeometryModel::Attribute attribute, const QVariant &value) override;
void setPrimitiveAttribute(const GeometryModel::Node &node, GeometryModel::Attribute attribute, const QVariant &value) override;
void movePrimitiveIntoGroup(const GeometryModel::Node &primitive, const GeometryModel::Node &target) override;
void releaseGroup(const GeometryModel::Node &group) override;
void deleteGroup(const GeometryModel::Node &group) override;
void removePrimitive(const GeometryModel::Node &primitive) override;
void removePrimitivesByUserData(const QList<int> &userDataList) override;
void removeText(GeometryModel::Node &parent) override;
void setTextData(const GeometryModel::Node &textNode, const QString &data, GeometryModel::HorizontalAlign textAlign) override;
void clearModel() override;
void translateNode(const GeometryModel::Node &node, double x, double y) override;
void moveNode(const GeometryModel::Node &node, double x, double y) override;
void scaleNode(const GeometryModel::Node &node, double scaleX, double scaleY) override;
void rotateNode(const GeometryModel::Node &node, double angle) override;
void reorderPrimitives(const QList<GeometryModel::Node> &nodes, GeometryModel::PrimitivOrder order) override;
void merge(const GeometryModel::Node &other, bool skipUndo = false, bool intoNewGroup = false) override;
void merge(GeometryModel *other, bool skipUndo = false, bool intoNewGroup = false) override;
unsigned int modificationCounter() const override;
void resetModificationCounter() override;
void undo(unsigned int steps = 1) override;
void redo(unsigned int steps = 1) override;
void enableUndo(bool enable) override;
void startUndoBlock() override;
void endUndoBlock(const QString &eventDescription = QString()) override;
void abortUndoBlock() override;
void setMaxUndoSteps(unsigned int max) override;
unsigned int maxUndoSteps() const override;
void cleanModel() override;
GeometryModel::Node addPrimitive(GeometryModel::PrimitiveType type
, const QList<QPointF> &points
, const QList<QPair<GeometryModel::Attribute, QVariant> > &attributes
, int userData = -1
, const QString &textData = QString()
, GeometryModel::HorizontalAlign textAlign = HorizontalAlign::Left) override;
bool setPrimitivePoints(const GeometryModel::Node &node, const QList<QPointF> &points) override;
GeometryModel::Node addText(const GeometryModel::Node &parent
, const QString &textData
, GeometryModel::HorizontalAlign textAlign
, const QList<QPair<GeometryModel::Attribute, QVariant> > &attributes
, int userData) override;
GeometryModel::Node getText(const GeometryModel::Node &parent) const override;
QString getTextData(const GeometryModel::Node &textNode) const override;
QList<QPointF> getPrimitivePoints(const GeometryModel::Node &node) const override;
QRectF getBoundingBox(const GeometryModel::Node &node) const override;
void setNodeDisplayName(const Node &node, const QString &name) override;
QString getNodeDisplayName(const Node &node) const override;
QVariant getModelAttribute(Attribute attribute) const override;
QVariant getAttribute(const GeometryModel::Node &node, GeometryModel::Attribute attribute) const override;
template <class T> T getAttribute(const Node &node, Attribute attribute) const;
bool hasAttribute(const GeometryModel::Node &node, GeometryModel::Attribute attribute) const override;
QVariant::Type attributeType(const GeometryModel::Attribute &attribute) const override;
QList<GeometryModel::Attribute> supportedAttributes(GeometryModel::PrimitiveType type) const override;
GeometryModel::Node createGroup(const QList<GeometryModel::Node> &primitives) override;
GeometryModel::Node isInGroup(const GeometryModel::Node &primitive) const override;
GeometryModel::NodeList getGroupPrimitives(const GeometryModel::Node &node) override;
GeometryModel::Node findPrimitive(int userData) const override;
bool hasUserData(const Node &node) const override;
int getUserData(const GeometryModel::Node &node, bool *ok = nullptr) const override;
void setUserData(const GeometryModel::Node &node, int userData) override;
QMultiMap<int, GeometryModel::Node> userDataMap(const GeometryModel::Node &node = GeometryModel::Node()) override;
GeometryModel::Node copy(const GeometryModel::Node &node, int userData = 0) override;
GeometryModel::PrimitiveType getType(const GeometryModel::Node &node) const override;
unsigned int undoSteps() const override;
unsigned int redoSteps() const override;
QStringList undoHistory() const override { return _undoHistory.toList(); }
QStringList redoHistory() const override { return _redoHistory.toList(); }
void clearUndoStack() override
{
_undoStack.clear();
_undoHistory.clear();
} // clearUndoStack
void clearRedoStack() override
{
_redoStack.clear();
_redoHistory.clear();
} // clearRedoStack
QString attributeToString(const GeometryModel::Attribute &attribute) const override;
bool parseSymbolAttributeString(const QString &sidcAttributes, QMap<QString, QVariant> &attrMap) const override;
QString buildSymbolAttributeString(const QMap<QString, QVariant> &attrMap) const override;
static void cleanupStaticMember();
private:
static void valueFromVariant(const QVariant &v, QPointF &result);
static void valueFromVariant(const QVariant &v, QColor &result);
/**
convert to QString (with non locale-aware conversions)
*/
static QString variant2XmlString(const QVariant &v);
/**
Create a QColor from an attribute-value with alpha-channel (QVariant
ignores Alpha)
\param attColor: The QString-QVariant from an attribute of Type QColor
\return QColor with alpha-channel or invalid QColor, if the value could be parsed.
*/
static QColor colorFromString(const QString &attColor);
/**
Create a QPoint from an attribute-value
\param attPoint: The QString-QVariant from an attribute of Type QPointF
\return QPointF
*/
static QPointF pointFromString(const QString &attPoint);
//! A mapping between all primitives and the attributes they support
static QMultiMap<GeometryModel::PrimitiveType, GeometryModel::Attribute> _primitiveSupportedAttributes;
//! Mappings between all primitive-types and their string/tag-name
static QMap<QString, GeometryModel::PrimitiveType> _primitiveTagsTypes;
static QMap<GeometryModel::PrimitiveType, QString> _primitiveTagsStrings;
//! Default-Values for all supported attributes
static QMap<QPair<GeometryModel::PrimitiveType, GeometryModel::Attribute>, QString> _attributeDefaults;
//! Mapping between Attributes and their QVariant-Type.
static QMap<GeometryModel::Attribute, QVariant::Type> _attributeTypes;
//! Bool to check, if static class variables have been initialized
static bool _staticInitDone;
/**
Init data of the object
*/
void init();
/**
Transform the points of a primitive.
\sa {translateNode(), moveNode(), rotateNode(), scaleNode()}
\param node: The primitive to transform.
\param t: The transformation-matrix.
*/
void transformNode(const QDomNode &node, const QTransform &t);
GeometryModel::PrimitiveType getType(const QDomNode &node) const;
bool hasUserData(const QDomNode &node) const;
int getUserData(const QDomNode &node, bool *okPtr) const;
QRectF getBoundingBox(const QDomNode &node) const;
QList<QPointF> getPrimitivePoints(const QDomNode &node) const;
bool hasAttribute(const QDomNode &node, GeometryModel::Attribute attribute) const;
QVariant getAttribute(const QDomNode &node, GeometryModel::Attribute attribute) const;
void removePrimitive(const QDomNode &primitive);
void translateNode(const QDomNode &node, double x, double y);
void moveNode(const QDomNode &node, double x, double y);
void scaleNode(const QDomNode &node, double scaleX, double scaleY);
void rotateNode(const QDomNode &node, double angle);
void merge(const QDomNode &other, bool skipUndo = false, bool intoNewGroup = false);
QDomNode createGroup(const QList<QDomNode> &primitives);
QMultiMap<int, QDomNode> userDataMap(const QDomNode &node) const;
/**
Wrapper for signal changed(), checks _skipChangedSignal
!!! ATTENTION: Do not use the signal changed directly.
Use emitChangedSignal() instead !!!
\param what: Short description of the change for logging
\param node: the changed node (if this is a Null-Node, the Root-Node of
the plan has changed)
\param att: The attribute, that changed. If att==MaxAttributes, then
multiple attributes are changed
\param coordsChanged: if true, the coordinated of the primitive are changed
*/
void emitChangedSignal(const Node &node, Attribute att, bool coordsChanged);
//! Lock for temporarily blocking changed()-Signals
bool _skipChangedSignal;
//! Undo-Stack
bool _undoEnabled;
unsigned int _maxUndoSteps;
QStack<QDomNode> _undoStack;
QStack<QString> _undoHistory;
QStack<QDomNode> _redoStack;
QStack<QString> _redoHistory;
//! Undo-blocks
QDomNode _undoBlock;
QString _undoHistoryBlock;
bool _insideUndoBlock;
unsigned int _modificationCounter;
//! Push/pop current state to undo-stack, if not locked
void pushUndo(const QString &eventDescription = QString());
GeometryModel::Node popUndo();
}; // GeometryModelQDom
template <class T> T GeometryModelQDom::getAttribute(const Node &node, Attribute attribute) const
{
const QVariant &v = getAttribute(node, attribute);
switch (qMetaTypeId<T>())
{
case QMetaType::QPointF:
case QMetaType::QColor:
{
T result; valueFromVariant(v, result); return result;
} break;
default: break;
}
return v.value<T>();
} // template <class T> T GeometryModelQDom::getAttribute( const Node & node, Attribute attribute ) const
} // namespace SituationMap
@@ -0,0 +1,75 @@
/**
**
** @RDE_HEADER@
** Node visitor for GeometryModel.
** $Id$
** $HeadURL$
** $Author$
**
** -----------------------------------------------------------------------------------------------
**
** Hardware-Environment: Intel-PC
** Software-Environment: Windows 7, Qt 5.4. ArcGIS 10.2.5
**
** Language ........: C++ 11
**
** -----------------------------------------------------------------------------------------------
**
** Author ...........: Jörg Turla, SPD G, Tel. 3132
**
** -----------------------------------------------------------------------------------------------
**
** Notes .........:
**
** 07.07.2016, JT : First edition for use with Qt5
**
** -----------------------------------------------------------------------------------------------
*/
#include "geometry_node_visitor.h"
namespace SituationMap
{
GeometryNodeVisitor::GeometryNodeVisitor(GeometryModel *geoModel) : m_geometryModel(geoModel) {;}
bool GeometryNodeVisitor::traverse()
{
if (!m_geometryModel)
return true;
return traverse(m_geometryModel->getRootNode());
} // bool GeometryNodeVisitor::traverse()
bool GeometryNodeVisitor::traverse(GeometryModel::Node node)
{
if (!m_geometryModel)
return true;
if (node.isValid())
{
const GeometryModel::PrimitiveType primitiveType = m_geometryModel->getType(node);
if ((GeometryModel::PrimitiveType::RootNode == primitiveType) || (GeometryModel::PrimitiveType::Node == primitiveType))
{
if (node.hasChildNodes())
{
node = node.firstChildNode();
while (node.isValid())
{
if (!traverse(node))
return false;
node = node.next();
}
}
}
if (!apply(m_geometryModel, node, primitiveType))
return false;
} // if
return true;
}
} // namespace SituationMap
@@ -0,0 +1,75 @@
/**
**
** @RDE_HEADER@
** Node visitor for GeometryModel.
** $Id$
** $HeadURL$
** $Author$
**
** -----------------------------------------------------------------------------------------------
**
** Hardware-Environment: Intel-PC
** Software-Environment: Windows 7, Qt 5.4. ArcGIS 10.2.5
**
** Language ........: C++ 11
**
** -----------------------------------------------------------------------------------------------
**
** Author ...........: Jörg Turla, SPD G, Tel. 3132
**
** -----------------------------------------------------------------------------------------------
**
** Notes .........:
**
** 07.07.2016, JT : First edition for use with Qt5
**
** -----------------------------------------------------------------------------------------------
*/
#pragma once
#include "geometry_model.h"
namespace SituationMap
{
/**
GeometryNopdeVisitor implements visitor pattern to traverse geoemtry model tree. The apply function will be
called for each node in geometry model.
*/
class GEOMETRYMODEL_EXPORT GeometryNodeVisitor
{
public:
explicit GeometryNodeVisitor(GeometryModel *geoModel);
virtual ~GeometryNodeVisitor() = default;
GeometryNodeVisitor(const GeometryNodeVisitor &) = delete;
/**
Traversing the complete geometry model
*/
bool traverse();
/**
Traversing the sub-tree of node. Coming in deepth first.
*/
bool traverse(GeometryModel::Node node);
protected:
/**
For each node the apply function will be called. If apply returns false the traversal is aborted. In
other case if return value is true the traversel is continued.
@param geoModel Pointer to geometry model
@param node Node of geometry model
@param nodeType Type of node
@return false to abort traversael otherwise true
*/
virtual bool apply(GeometryModel *geoModel, const GeometryModel::Node &node, GeometryModel::PrimitiveType nodeType) = 0;
GeometryModel *m_geometryModel;
}; // GeometryNodeVisitor
} // namespace SituationMap
@@ -0,0 +1,215 @@
/**
* @RDE_HEADER@
* PixelTextBoxData as Addon to GeometryModel
* $Id$
* $HeadURL$
* $Author$
* Created by Norbert Thoden, SLSE, 2023-04-27
*/
#include "geometry_pixelTextBox.h"
#include <QJsonDocument>
#include <QJsonObject>
#include <QJsonValue>
#include <QJsonArray>
#include <QDebug>
namespace SituationMap
{
PixelTextBoxData::PixelTextBoxData(const QString &htmlText, const QColor &backgroundColor)
: m_htmlText(htmlText), m_backgroundColor(backgroundColor)
{
}
void PixelTextBoxData::reset()
{
m_htmlText.clear();
m_backgroundColor = QColor();
m_position = QPoint();
m_size = QSize();
}
bool PixelTextBoxData::isEmpty() const
{
return m_htmlText.isEmpty();
}
QString PixelTextBoxData::toDebugString() const
{
QJsonDocument jDoc(toJson());
return QString::fromStdString(jDoc.toJson(QJsonDocument::JsonFormat::Compact).toStdString());
}
bool PixelTextBoxData::operator==(const PixelTextBoxData &o) const
{
return m_htmlText == o.m_htmlText &&
m_backgroundColor == o.m_backgroundColor &&
m_position == o.m_position &&
m_size == o.m_size;
}
QJsonObject PixelTextBoxData::toJson() const
{
QJsonObject obj;
obj[QStringLiteral("text")] = m_htmlText;
obj[QStringLiteral("backgroundColor")] = m_backgroundColor.name();
obj[QStringLiteral("position")] = QJsonObject({{QStringLiteral("x"), m_position.x()},
{QStringLiteral("y"), m_position.y()},
});
obj[QStringLiteral("size")] = QJsonObject({{QStringLiteral("width"), m_size.width()},
{QStringLiteral("height"), m_size.height()},
});
return obj;
}
bool get(const QJsonObject &obj, const QString &key, int &val)
{
const auto jVal = obj[key];
if (!jVal.isDouble())
{
qCritical() << " isDouble failed";
}
val = jVal.toInt();
return true;
}
PixelTextBoxData PixelTextBoxData::fromJson(const QJsonValue &json)
{
if (json.isUndefined())
return {};
if (!json.isObject())
return {};
PixelTextBoxData ret;
// text
ret.m_htmlText = json[QStringLiteral("text")].toString();
// backgroundColor
QString temp = json[QStringLiteral("backgroundColor")].toString();
ret.m_backgroundColor.setNamedColor(temp);
// position:
{
const auto jVal = json[QStringLiteral("position")];
get(jVal.toObject(), QStringLiteral("x"), ret.m_position.rx());
get(jVal.toObject(), QStringLiteral("y"), ret.m_position.ry());
}
// size:
{
const auto jVal = json[QStringLiteral("size")];
get(jVal.toObject(), QStringLiteral("width"), ret.m_size.rwidth());
get(jVal.toObject(), QStringLiteral("height"), ret.m_size.rheight());
}
return ret;
}
QString PixelTextBoxData::toJsonStr(QJsonDocument::JsonFormat format) const
{
QJsonObject obj = toJson();
QJsonDocument jDoc(obj);
return QString::fromStdString(jDoc.toJson(format).toStdString());
}
PixelTextBoxData PixelTextBoxData::fromJsonStr(const QString &jsonStr)
{
if (jsonStr.isEmpty())
return {};
QJsonParseError parseError;
QJsonDocument jDoc(QJsonDocument::fromJson(jsonStr.toStdString().c_str(), &parseError));
if (parseError.error != QJsonParseError::NoError)
{
qCritical() << " QJsonParseError->errorString: '" << parseError.errorString() << "'"
<< ", offset: " << parseError.offset;
return {};
}
QJsonObject jObj = jDoc.object();
if (jObj.isEmpty())
return {};
return PixelTextBoxData::fromJson(jObj);
}
//
// Container
//
QJsonObject PixelTextBoxData::pixelTextBoxContainerToJson(const QVector<PixelTextBoxData> &ptbdCont)
{
QJsonArray arr;
for (const PixelTextBoxData &item : qAsConst(ptbdCont))
arr.push_back(item.toJson());
QJsonObject jObj;
jObj[QStringLiteral("PixelTextBoxData")] = arr;
return jObj;
}
QVector<PixelTextBoxData> PixelTextBoxData::pixelTextBoxContainerFromJson(const QJsonValue &json)
{
QVector<PixelTextBoxData> ret;
if (!json.isObject())
return ret;
const QJsonObject jObj = json.toObject();
if (!jObj.contains(QStringLiteral("PixelTextBoxData")))
return ret;
const QJsonArray &array = jObj[QStringLiteral("PixelTextBoxData")].toArray();
ret.reserve(array.size());
for(int i = 0; i < array.size(); ++i)
ret.push_back(PixelTextBoxData::fromJson(array.at(i)));
return ret;
}
QString PixelTextBoxData::pixelTextBoxContainerToJsonStr(const QVector<PixelTextBoxData> &ptbdCont, QJsonDocument::JsonFormat format)
{
QJsonObject obj = pixelTextBoxContainerToJson(ptbdCont);
QJsonDocument jDoc(obj);
return QString::fromStdString(jDoc.toJson(format).toStdString());
}
QVector<PixelTextBoxData> PixelTextBoxData::pixelTextBoxContainerFromJsonStr(const QString &jsonStr)
{
if (jsonStr.isEmpty())
return {};
QJsonParseError parseError;
QJsonDocument jDoc(QJsonDocument::fromJson(jsonStr.toStdString().c_str(), &parseError));
if (parseError.error != QJsonParseError::NoError)
{
qCritical() << " QJsonParseError->errorString: '" << parseError.errorString() << "'"
<< ", offset: " << parseError.offset;
return {};
}
QJsonObject jObj = jDoc.object();
if (jObj.isEmpty())
return {};
return PixelTextBoxData::pixelTextBoxContainerFromJson(jObj);
}
//-----------------------------------------------------------------------------
// output operator:
//-----------------------------------------------------------------------------
GEOMETRYMODEL_EXPORT std::ostream &operator<<(std::ostream &stream, const PixelTextBoxData &value)
{
stream << value.toDebugString().toStdString().c_str();
return stream;
}
} // namespace SituationMap
@@ -0,0 +1,70 @@
/**
* @RDE_HEADER@
* PixelTextBoxData as Addon to GeometryModel
* $Id$
* $HeadURL$
* $Author$
* Created by Norbert Thoden, SLSE, 2023-04-27
*/
#pragma once
#include <ostream>
#include <QString>
#include <QColor>
#include <QPoint>
#include <QSize>
#include <QJsonObject>
#include <QJsonDocument>
#include "geometry_model_export.h"
namespace SituationMap
{
class GEOMETRYMODEL_EXPORT PixelTextBoxData
{
public:
PixelTextBoxData() = default;
explicit PixelTextBoxData(const QString &htmlText, const QColor &backgroundColor);
void reset();
bool isEmpty() const;
QString toDebugString() const;
QString m_htmlText;
QColor m_backgroundColor;
QPoint m_position;
QSize m_size;
// operator
bool operator==(const PixelTextBoxData &o) const;
// Json:
QJsonObject toJson() const;
static PixelTextBoxData fromJson(const QJsonValue &json);
QString toJsonStr(QJsonDocument::JsonFormat format = QJsonDocument::JsonFormat::Indented) const;
static PixelTextBoxData fromJsonStr(const QString &jsonStr);
static QJsonObject pixelTextBoxContainerToJson(const QVector<PixelTextBoxData> &ptbdCont);
static QVector<PixelTextBoxData> pixelTextBoxContainerFromJson(const QJsonValue &json);
static QString pixelTextBoxContainerToJsonStr(const QVector<PixelTextBoxData> &ptbdCont, QJsonDocument::JsonFormat format = QJsonDocument::JsonFormat::Indented);
static QVector<PixelTextBoxData> pixelTextBoxContainerFromJsonStr(const QString &jsonStr);
};
//-----------------------------------------------------------------------------
// output operator:
//-----------------------------------------------------------------------------
GEOMETRYMODEL_EXPORT std::ostream &operator<< (std::ostream &stream,
const PixelTextBoxData &value);
} // namespace SituationMap
@@ -0,0 +1,564 @@
/**
* @RDE_HEADER@
* AbstractGraphicalObject
* $Id$
* $HeadURL$
* $Author$
*/
// Own
#include "abstract_graphical_object.h"
#include <Map/situation_map_utils.h> // operator<<
// ESRI
#include <GeoView.h>
#include <Graphic.h>
#include <GraphicsOverlay.h>
#include <Multipart.h>
// Qt
#include <QDebug>
#include <QSharedPointer>
#include <QApplication>
#include <QThread>
#include <QObject>
#include <AttributeListModel.h>
#include <GraphicListModel.h>
#include <ImmutablePartCollection.h>
#include <SpatialReference.h>
#include <ImmutablePart.h>
#include <SymbolTypes.h>
#include <Geometry.h>
namespace SituationMap
{
AbstractGraphicalObject::AbstractGraphicalObject(const Esri::ArcGISRuntime::GeoView *geoView
, Esri::ArcGISRuntime::GraphicsOverlay *graphicsLayer
, const QString &debugInfo
, const UniqueMapId &uniqueMapId)
: m_geoView(geoView)
, m_graphicsLayer(graphicsLayer)
, m_uniqueMapId(uniqueMapId)
, m_debugInfo(debugInfo)
, m_logger(getLogger("AbstractGraphicalObject"))
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START, debugInfo='" << m_debugInfo << "'";
m_pickable = (m_uniqueMapId != INVALID_MAP_ID);
TRACE_LOG(m_logger) << LOGFUNCTION << " END, debugInfo='" << m_debugInfo << "'";
}
AbstractGraphicalObject::~AbstractGraphicalObject()
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START, debugInfo='" << m_debugInfo << "'"
<< ", m_graphicsLayer-overlayId=" << (m_graphicsLayer ? m_graphicsLayer->overlayId() : QString(QStringLiteral("unknown")));
#if ACRGIS_VERSION >= 0x640F00 // 100.15.0
// removeOne ist helpful to let ModuleTest succeed: 'situationMapModuleTest checkOverlayHandler3 none'
if (m_graphic && m_graphicsLayer && m_graphicsLayer->graphics())
m_graphicsLayer->graphics()->removeOne(m_graphic);
delete m_graphic;
m_graphic = nullptr;
#else
/*
// cleanup
// to make sure, the the graphic is removed from internal container BEFORE
// graphic is deleted, follow the documentation: use Layer::removeGraphic
// (instead 'delete m_graphic')
if (m_graphic && m_graphicsLayer && m_graphicsLayer->graphics())
m_graphicsLayer->graphics()->removeOne(m_graphic);
if (m_graphic)
{
delete m_graphic;
m_graphic = nullptr;
}
*/
// Race condition between removeOne() and delete m_graphic :
// BUG-000116867 is for the deadlock
// BUG-000117464 is for the crash
// Use following workaround until ESRI will release the fix (with 100.5!?)
if (m_graphic && m_graphicsLayer && m_graphicsLayer->graphics())
{
const int idx = m_graphicsLayer->graphics()->indexOf(m_graphic);
if (idx < 0)
ERROR_LOG(m_logger) << LOGFUNCTION << " indexOf failed, debugInfo='" << m_debugInfo << "'";
auto graphicCopy = m_graphic;
QObject::connect (m_graphicsLayer->graphics(), &Esri::ArcGISRuntime::GraphicListModel::itemRemoved,
m_graphic, [idx, graphicCopy](int index)
{
if (idx == index)
delete graphicCopy;
});
m_graphicsLayer->graphics()->removeOne(m_graphic);
}
// : Race condition between removeOne() and delete m_graphic
// m_esriSimpleLineSymbol AND m_esriSimpleFillSymbol will be destroyed m_graphic
#endif // ACRGIS_VERSION >= 0x640F00
TRACE_LOG(m_logger) << LOGFUNCTION << " END, debugInfo='" << m_debugInfo << "'";
}
Esri::ArcGISRuntime::Graphic *AbstractGraphicalObject::graphic()
{
return m_graphic;
}
Esri::ArcGISRuntime::GraphicsOverlay *AbstractGraphicalObject::graphicsLayer()
{
return m_graphicsLayer;
}
Esri::ArcGISRuntime::Geometry AbstractGraphicalObject::getGraphicGeometry() const
{
if (! m_graphic)
return Esri::ArcGISRuntime::Geometry();
return m_graphic->geometry();
}
bool AbstractGraphicalObject::updateView()
{
if (!changed())
return true;
bool success = updateViewImpl();
resetChanged();
return success;
}
QString AbstractGraphicalObject::debugInfo() const
{
return m_debugInfo;
}
void AbstractGraphicalObject::setDebugInfo(const QString &debugInfo)
{
m_debugInfo = debugInfo;
}
int AbstractGraphicalObject::drawOrder() const
{
return m_drawOrder.value();
}
void AbstractGraphicalObject::setDrawOrder(int drawOrder)
{
m_drawOrder = drawOrder;
// if (m_graphic)
// m_graphic->setDrawOrder(m_drawOrder.value());
}
QString AbstractGraphicalObject::toString() const
{
QString str;
if (!m_debugInfo.isEmpty())
str.append(QStringLiteral("debugInfo=%1").arg(m_debugInfo));
if (m_graphicsLayer)
str.append(QStringLiteral(" layer='%1'").arg(m_graphicsLayer->objectName()));
str.append(QStringLiteral(" m_drawOrder='%1'").arg(m_drawOrder.value()));
if (m_graphic)
str.append(QStringLiteral(" zIndex='%1'").arg(m_graphic->zIndex()));
str.append(QStringLiteral(" visibility='%1'").arg(m_visibility.value()));
str.append(QStringLiteral(" selected='%1'").arg(m_selected.value()));
str.append(QStringLiteral(" scale='%1'").arg(m_scale.value()));
str.append(QStringLiteral(" positions.count='%1'").arg(m_positions.value().count()));
return str;
}
UniqueMapId AbstractGraphicalObject::uniqueMapId() const
{
return m_uniqueMapId;
}
void AbstractGraphicalObject::setUniqueMapId(UniqueMapId uniqueId)
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START, debugInfo='" << m_debugInfo << "'"
<< " uniqueMapId=" << uniqueId;
m_uniqueMapId = uniqueId;
// use attribute to store application obj id (SimWorld) at graphic
if (m_graphic)
{
// use attributeModel to store application obj id (SimWorld) at graphic
Esri::ArcGISRuntime::AttributeListModel *attListModel = m_graphic->attributes();
if (attListModel)
attListModel->insertAttribute(QLatin1String(SituationMap::UniqueMapIdAttribute), m_uniqueMapId);
else
ERROR_LOG(m_logger) << LOGFUNCTION << " no AttributeListModel, debugInfo='" << m_debugInfo << "'"
<< " uniqueMapId=" << m_uniqueMapId;
}
TRACE_LOG(m_logger) << LOGFUNCTION << " END, debugInfo='" << m_debugInfo << "'"
<< " uniqueMapId=" << uniqueId;
}
Point3D AbstractGraphicalObject::origin() const
{
return m_positions.value().value(0); // value => if index is out of range -> default object
}
void AbstractGraphicalObject::setOrigin(const Point3D &origin)
{
// TRACE_LOG(m_logger) << LOGFUNCTION << " START, debugInfo='" << m_debugInfo << "'"
// << " origin=" << origin;
if (m_positions.value().isEmpty())
m_positions.refValue().append(origin);
else
{
// https://stackoverflow.com/a/1573715/2352507
// Any comparison(except with "!=") with NaN returns false.
// NaN != NaN -> true!!!
if (m_positions.value().value(0) != origin) // NaN != NaN -> true!!!
{
DEBUG_LOG(m_logger) << LOGFUNCTION << " value(0) = " << m_positions.value().value(0) << " origin = " << origin;
m_positions.refValue().clear();
m_positions.refValue().append(origin);
}
}
// TRACE_LOG(m_logger) << LOGFUNCTION << " END, debugInfo='" << m_debugInfo << "'"
// << " origin=" << origin
// << " changed=" << m_positions.changed()
// << " SIZE=" << m_positions.value().size();
}
void AbstractGraphicalObject::setOrigin(const QPointF &origin)
{
setOrigin(Point3D(origin.x(), origin.y(), .0));
}
PositionCont AbstractGraphicalObject::positions() const
{
return m_positions.value();
}
void AbstractGraphicalObject::setPositions(const PositionCont &posCont)
{
m_positions = posCont;
// TRACE_LOG(m_logger) << LOGFUNCTION << " debugInfo='" << m_debugInfo << "'"
// << " changed=" << m_positions.changed();
}
bool AbstractGraphicalObject::isSinglePoint() const
{
return m_positions.value().count() == 1;
}
bool AbstractGraphicalObject::isMultiPoint() const
{
return m_positions.value().count() > 1;
}
bool AbstractGraphicalObject::isArea() const
{
return m_positions.value().count() > 2;
}
LineStyle AbstractGraphicalObject::lineStyle() const
{
return m_lineStyle.value();
}
LineStyle &AbstractGraphicalObject::rLineStyle()
{
return m_lineStyle.refValue();
}
void AbstractGraphicalObject::setLineStyle(const LineStyle &lineStyle)
{
m_lineStyle = lineStyle;
}
FillStyle AbstractGraphicalObject::fillStyle() const
{
return m_fillStyle.value();
}
FillStyle &AbstractGraphicalObject::rFillStyle()
{
return m_fillStyle.refValue();
}
void AbstractGraphicalObject::setFillStyle(const FillStyle &fillStyle)
{
m_fillStyle = fillStyle;
}
bool AbstractGraphicalObject::visibility() const
{
return m_visibility.value();
}
void AbstractGraphicalObject::setVisibility(bool visibility)
{
m_visibility = visibility;
TRACE_LOG(m_logger) << LOGFUNCTION << " debugInfo='" << m_debugInfo << "'"
<< " visibility=" << m_visibility;
}
bool AbstractGraphicalObject::selected() const
{
return m_selected.value();
}
void AbstractGraphicalObject::setSelected(bool selected)
{
m_selected = selected;
}
bool AbstractGraphicalObject::pickable() const
{
return m_pickable.value();
}
void AbstractGraphicalObject::setPickable(bool pickable)
{
// allow pickable only if m_uniqueMapId is valid:
m_pickable = pickable && (m_uniqueMapId != INVALID_MAP_ID);
TRACE_LOG(m_logger) << LOGFUNCTION << " debugInfo='" << m_debugInfo << "'"
<< " pickable=" << m_pickable;
}
float AbstractGraphicalObject::scale() const
{
return m_scale.value();
}
void AbstractGraphicalObject::setScale(float scale)
{
m_scale = scale;
}
bool AbstractGraphicalObject::addUpdateGraphic()
{
TRACE_LOG(m_logger) << LOGFUNCTION << " debugInfo='" << m_debugInfo << "'" << " updateGraphic";
bool successGraphic = true;
if (! m_graphic)
{
DEBUG_LOG(m_logger) << LOGFUNCTION << " debugInfo='" << m_debugInfo << "'"
<< " no m_graphic -> return true";
return true;
}
// append just once :-)
if (! m_graphicsLayer->graphics()->contains(m_graphic))
{
m_graphicsLayer->graphics()->append(m_graphic);
successGraphic = m_graphicsLayer->graphics()->contains(m_graphic);
}
TRACE_LOG(m_logger) << LOGFUNCTION << " debugInfo='" << m_debugInfo << "'"
<< " successGraphic=" << successGraphic;
return successGraphic;
}
bool AbstractGraphicalObject::create()
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START, debugInfo='" << m_debugInfo << "'"
<< " uniqueMapId =" << m_uniqueMapId
<< " origin =" << this->origin()
<< " visibility=" << m_visibility;
bool success = true;
// some checks:
if (!m_graphicsLayer)
{
ERROR_LOG(m_logger) << LOGFUNCTION << " debugInfo='" << m_debugInfo << "'"
<< " no graphicsLayer";
return false;
}
if (!m_graphic)
{
m_graphic = new Esri::ArcGISRuntime::Graphic();
m_graphic->setObjectName(m_debugInfo);
m_graphic->setZIndex(m_drawOrder.value());
// use attributeModel to store application obj id (SimWorld) at graphic
Esri::ArcGISRuntime::AttributeListModel *attLisModel = m_graphic->attributes();
if (attLisModel)
attLisModel->insertAttribute(QLatin1String(SituationMap::UniqueMapIdAttribute), m_uniqueMapId);
else
{
ERROR_LOG(m_logger) << LOGFUNCTION << " no AttributeListModel, debugInfo='" << m_debugInfo << "'"
<< " uniqueMapId=" << m_uniqueMapId;
}
}
TRACE_LOG(m_logger) << LOGFUNCTION << " END, debugInfo='" << m_debugInfo << "'"
<< " success=" << success;
return success;
}
bool AbstractGraphicalObject::updateViewImpl()
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START, debugInfo='" << m_debugInfo << "'"
<< " uniqueMapId=" << m_uniqueMapId
<< " origin=" << this->origin()
<< " visibility=" << m_visibility
<< " selected=" << m_selected
<< " drawOrder=" << m_drawOrder
<< " pickable=" << m_pickable
<< " pickableCHG=" << m_pickable.changed();
if (QApplication::instance()->thread()->currentThreadId() != QThread::currentThreadId())
{
ERROR_LOG(m_logger) << LOGFUNCTION << " wrong Thread, debugInfo='" << m_debugInfo << "'"
<< " uniqueMapId=" << m_uniqueMapId;
abort();
}
if (m_graphic)
{
m_graphic->setZIndex(m_drawOrder.value());
m_graphic->setVisible(m_visibility.value());
m_graphic->setSelected(m_selected.value());
// Picking:
if (m_pickable.changed())
{
// use attributeModel to store m_pickable at graphic
Esri::ArcGISRuntime::AttributeListModel *attLisModel = m_graphic->attributes();
if (attLisModel)
attLisModel->insertAttribute(QLatin1String(SituationMap::IsPickableAttribute), m_pickable.value());
else
{
ERROR_LOG(m_logger) << LOGFUNCTION << " no AttributeListModel, debugInfo='" << m_debugInfo << "'"
<< " uniqueMapId=" << m_uniqueMapId;
}
}
m_pickable.reset();
}
TRACE_LOG(m_logger) << LOGFUNCTION << " END, debugInfo='" << m_debugInfo << "'"
<< " uniqueMapId =" << m_uniqueMapId;
return true;
}
bool AbstractGraphicalObject::assignLineStyleToGraphic()
{
if (!m_graphic)
return false;
const LineStyle &ls = m_lineStyle.value();
if (!m_esriSimpleLineSymbol)
{
m_esriSimpleLineSymbol =
new Esri::ArcGISRuntime::SimpleLineSymbol(convert(ls.linePattern()), ls.lineColor(), ls.lineWidth() * m_scale.value(), m_graphic);
} else {
m_esriSimpleLineSymbol->setStyle(convert(ls.linePattern()));
m_esriSimpleLineSymbol->setColor(ls.lineColor());
m_esriSimpleLineSymbol->setWidth(ls.lineWidth() * m_scale.value());
}
m_graphic->setSymbol(m_esriSimpleLineSymbol.data());
return true;
}
bool AbstractGraphicalObject::assignFillStyleToGraphic()
{
if (!m_graphic)
return false;
const LineStyle &ls = m_lineStyle.value();
const FillStyle &fs = m_fillStyle.value();
// 1. the Line
if (!m_esriSimpleLineSymbol)
{
m_esriSimpleLineSymbol =
new Esri::ArcGISRuntime::SimpleLineSymbol(convert(ls.linePattern()), ls.lineColor(), ls.lineWidth() * m_scale.value(), m_graphic);
} else {
m_esriSimpleLineSymbol->setStyle(convert(ls.linePattern()));
m_esriSimpleLineSymbol->setColor(ls.lineColor());
m_esriSimpleLineSymbol->setWidth(ls.lineWidth() * m_scale.value());
}
// 1. the Fill
if (!m_esriSimpleFillSymbol)
{
m_esriSimpleFillSymbol =
new Esri::ArcGISRuntime::SimpleFillSymbol(convert(fs.fillPattern()), fs.fillColor(), m_esriSimpleLineSymbol, m_graphic);
} else {
m_esriSimpleFillSymbol->setStyle(convert(fs.fillPattern()));
m_esriSimpleFillSymbol->setColor(fs.fillColor());
m_esriSimpleFillSymbol->setOutline(m_esriSimpleLineSymbol);
}
m_graphic->setSymbol(m_esriSimpleFillSymbol.data());
return true;
}
Esri::ArcGISRuntime::SimpleLineSymbolStyle AbstractGraphicalObject::convert(const LinePattern linePattern)
{
switch (linePattern)
{
case LinePattern::Dash: return Esri::ArcGISRuntime::SimpleLineSymbolStyle::Dash;
case LinePattern::DashDot: return Esri::ArcGISRuntime::SimpleLineSymbolStyle::DashDot;
case LinePattern::DashDotDot: return Esri::ArcGISRuntime::SimpleLineSymbolStyle::DashDotDot;
case LinePattern::Dot: return Esri::ArcGISRuntime::SimpleLineSymbolStyle::Dot;
case LinePattern::Null: return Esri::ArcGISRuntime::SimpleLineSymbolStyle::Null;
case LinePattern::Solid: return Esri::ArcGISRuntime::SimpleLineSymbolStyle::Solid;
} // switch
return Esri::ArcGISRuntime::SimpleLineSymbolStyle::Solid;
}
Esri::ArcGISRuntime::SimpleFillSymbolStyle AbstractGraphicalObject::convert(const FillPattern fillPattern)
{
switch (fillPattern)
{
case FillPattern::BackwardDiagonal: return Esri::ArcGISRuntime::SimpleFillSymbolStyle::BackwardDiagonal;
case FillPattern::Cross: return Esri::ArcGISRuntime::SimpleFillSymbolStyle::Cross;
case FillPattern::DiagonalCross: return Esri::ArcGISRuntime::SimpleFillSymbolStyle::DiagonalCross;
case FillPattern::ForwardDiagonal: return Esri::ArcGISRuntime::SimpleFillSymbolStyle::ForwardDiagonal;
case FillPattern::Horizontal: return Esri::ArcGISRuntime::SimpleFillSymbolStyle::Horizontal;
case FillPattern::Null: return Esri::ArcGISRuntime::SimpleFillSymbolStyle::Null;
case FillPattern::Solid: return Esri::ArcGISRuntime::SimpleFillSymbolStyle::Solid;
case FillPattern::Vertical: return Esri::ArcGISRuntime::SimpleFillSymbolStyle::Vertical;
} // switch
return Esri::ArcGISRuntime::SimpleFillSymbolStyle::BackwardDiagonal;
}
int AbstractGraphicalObject::countOfPolygonFirstPart(const Esri::ArcGISRuntime::Geometry &polylinePolygon)
{
const Esri::ArcGISRuntime::Multipart multipart(polylinePolygon);
if (multipart.isEmpty() || multipart.parts().isEmpty())
return -1;
return multipart.parts().part(0).pointCount();
}
const Esri::ArcGISRuntime::SpatialReference AbstractGraphicalObject::spatialReference() const
{
return m_geoView->spatialReference();
}
} // namespace SituationMap
@@ -0,0 +1,214 @@
/**
* @RDE_HEADER@
* AbstractGraphicalObject
* $Id$
* $HeadURL$
* $Author$
*/
#pragma once
// Own
#include <Map/situation_map_types.h>
#include <Map/line_style.h>
#include <Map/fill_style.h>
#include <Common/simple_value.h>
#include <Common/situation_map_logging.h>
// ESRI
#include <SimpleLineSymbol.h>
#include <SimpleFillSymbol.h>
// Qt
#include <QPointer>
#include <Geometry.h>
// forward:
namespace Esri
{
namespace ArcGISRuntime
{
class GeoView;
class Graphic;
class GraphicsOverlay;
class Geometry;
class Multipart;
class SpatialReference;
}
}
//----------------------------------------------------------------------------
namespace SituationMap
{
//forward
class GraphicalObjectText;
class SITUATIONMAP_EXPORT AbstractGraphicalObject
{
public:
AbstractGraphicalObject(const Esri::ArcGISRuntime::GeoView *geoView
, Esri::ArcGISRuntime::GraphicsOverlay *graphicsLayer
, const QString &debugInfo
, const UniqueMapId &uniqueMapId);
virtual ~AbstractGraphicalObject();
AbstractGraphicalObject(const AbstractGraphicalObject &other) = delete;
AbstractGraphicalObject &operator=(AbstractGraphicalObject &other) = delete;
virtual Esri::ArcGISRuntime::Graphic *graphic();
virtual Esri::ArcGISRuntime::GraphicsOverlay *graphicsLayer();
virtual QString toString() const;
virtual UniqueMapId uniqueMapId() const;
virtual void setUniqueMapId(UniqueMapId uniqueId);
virtual QString debugInfo() const;
virtual void setDebugInfo(const QString &debugInfo);
virtual int drawOrder() const;
virtual void setDrawOrder(int drawOrder);
// Data access:
// for SinglePoint:
virtual Point3D origin() const;
virtual void setOrigin(const Point3D &origin);
virtual void setOrigin(const QPointF &origin); // ToDO accept this??
// for MultiPoint:
virtual PositionCont positions() const;
virtual void setPositions(const PositionCont &posCont);
virtual bool isSinglePoint() const;
virtual bool isMultiPoint() const;
virtual bool isArea() const;
virtual LineStyle lineStyle() const;
virtual LineStyle &rLineStyle();
/**
* @brief setLineStyle (Font-)size is limited to 500.
* (High values can lead to coredump with 'SymbolDrawHelper::create_line_image FAILED, SkBitmap is NULL or empty')
* @param lineStyle to set.
*/
virtual void setLineStyle(const LineStyle &lineStyle);
virtual FillStyle fillStyle() const;
virtual FillStyle &rFillStyle();
virtual void setFillStyle(const FillStyle &fillStyle);
// Scale :
virtual float scale() const;
virtual void setScale(float scale);
// : Scale
// Visibility :
virtual bool visibility() const;
virtual void setVisibility(bool visibility);
// : Visibility
// Selection, Picking :
bool selected() const;
void setSelected(bool selected);
bool pickable() const;
/**
* @brief setPickable The method allows pickable=true only if uniqueMapIdis valid.
* @param pickable new value.
*/
void setPickable(bool pickable);
// : Selection, Picking
virtual Esri::ArcGISRuntime::Geometry getGraphicGeometry() const;
bool updateView();
bool addUpdateGraphic();
static Esri::ArcGISRuntime::SimpleLineSymbolStyle convert(const LinePattern linePattern);
static Esri::ArcGISRuntime::SimpleFillSymbolStyle convert(const FillPattern fillPattern);
bool assignLineStyleToGraphic();
bool assignFillStyleToGraphic();
static int countOfPolygonFirstPart(const Esri::ArcGISRuntime::Geometry &polylinePolygon);
protected:
// Internal/Admin
const Esri::ArcGISRuntime::SpatialReference spatialReference() const;
virtual bool changed()
{
return m_drawOrder.changed()
|| m_positions.changed()
|| m_visibility.changed()
|| m_selected.changed()
|| m_pickable.changed()
|| m_scale.changed()
|| m_lineStyle.changed()
|| m_fillStyle.changed();
}
virtual bool updateViewImpl() = 0;
virtual void resetChanged()
{
m_drawOrder.reset();
m_positions.reset();
m_visibility.reset();
m_selected.reset();
m_pickable.reset();
m_scale.reset();
m_lineStyle.reset();
m_fillStyle.reset();
}
virtual bool create() = 0;
const Esri::ArcGISRuntime::GeoView *m_geoView = nullptr;
Esri::ArcGISRuntime::GraphicsOverlay *m_graphicsLayer = nullptr;
Esri::ArcGISRuntime::Graphic *m_graphic = nullptr;
SimpleValue<int> m_drawOrder = 0;
// Data
UniqueMapId m_uniqueMapId;
QString m_debugInfo; ///< for debugging
SimpleValue<PositionCont> m_positions;
SimpleValue<bool> m_visibility = true;
SimpleValue<bool> m_selected = false;
SimpleValue<bool> m_pickable = true;
SimpleValue<float> m_scale = 1.0;
SimpleValue<LineStyle> m_lineStyle;
SimpleValue<FillStyle> m_fillStyle;
QPointer<Esri::ArcGISRuntime::SimpleLineSymbol> m_esriSimpleLineSymbol = nullptr;
QPointer<Esri::ArcGISRuntime::SimpleFillSymbol> m_esriSimpleFillSymbol = nullptr;
private:
LOGGER_T m_logger; ///< Interface of the Logging-Facility
};
} // namespace SituationMap
@@ -0,0 +1,96 @@
/**
* @RDE_HEADER@
* EllipseParameters
* $Id$
* $HeadURL$
* $Author$
*/
// Own
#include "ellipse_parameters.h"
// ESRI
// Qt
#include <QString>
namespace SituationMap
{
float EllipseParameters::lengthX() const
{
return m_lengthX;
}
void EllipseParameters::setLengthX(float lengthX)
{
m_lengthX = lengthX;
}
float EllipseParameters::lengthY() const
{
return m_lengthY;
}
void EllipseParameters::setLengthY(float lengthY)
{
m_lengthY = lengthY;
}
float EllipseParameters::directionDegree() const
{
return m_directionDegree;
}
void EllipseParameters::setDirectionDegree(float directionDegree)
{
m_directionDegree = directionDegree;
}
int EllipseParameters::maxSegmentLength() const
{
return m_maxSegmentLength;
}
void EllipseParameters::setMaxSegmentLength(int value)
{
m_maxSegmentLength = value;
}
int EllipseParameters::maxPointCount() const
{
return m_maxPointCount;
}
void EllipseParameters::setMaxPointCount(int maxPointCount)
{
m_maxPointCount = maxPointCount;
}
bool EllipseParameters::isValid() const
{
return ((m_lengthX > 0) && (m_lengthY > 0)) ;
}
//-----------------------------------------------------------------------------
// output operator:
//-----------------------------------------------------------------------------
std::ostream &operator<< (std::ostream &stream,
const EllipseParameters &value)
{
QString str;
str.append(QStringLiteral(" lengthX=%1").arg(value.lengthX()));
str.append(QStringLiteral(" lengthY=%1").arg(value.lengthY()));
str.append(QStringLiteral(" directionDegree=%1").arg(value.directionDegree()));
str.append(QStringLiteral(" maxSegmentLength=%1").arg(value.maxSegmentLength()));
stream << str.toStdString();
return stream;
}
} // namespace SituationMap
@@ -0,0 +1,95 @@
/**
* @RDE_HEADER@
* EllipseParameters
* $Id$
* $HeadURL$
* $Author$
*/
#pragma once
// Own
#include <situation_map_export.h>
#include <ostream>
// Qt
//----------------------------------------------------------------------------
namespace SituationMap
{
//----------------------------------------------------------------------------
class SITUATIONMAP_EXPORT EllipseParameters
{
public:
static constexpr unsigned int MAX_POINT_COUNT_DEFAULT = 30;
EllipseParameters() = default;
float lengthX() const;
void setLengthX(float lengthX);
float lengthY() const;
void setLengthY(float lengthY);
float directionDegree() const;
void setDirectionDegree(float directionDegree);
int maxSegmentLength() const;
void setMaxSegmentLength(int value);
int maxPointCount() const;
void setMaxPointCount(int maxPointCount);
bool isValid() const;
/**
* @brief operator== Compare two objects
* @param other to be compared with
* @return true if identical, otherwise false.
*/
bool operator==(const EllipseParameters &other) const
{
return ((this->m_lengthX == other.m_lengthX) &&
(this->m_lengthY == other.m_lengthY) &&
(this->m_directionDegree == other.m_directionDegree) &&
(this->m_maxSegmentLength == other.m_maxSegmentLength) &&
(this->m_maxPointCount == other.m_maxPointCount)
);
}
/**
* @brief operator!= Compare two objects
* @param other to be compared with
* @return true if NOT identical, otherwise false.
*/
bool operator!=(const EllipseParameters &other) const
{
return !(*this == other);
}
private:
float m_lengthX = 0;
float m_lengthY = 0;
float m_directionDegree = 0;
int m_maxSegmentLength = 10; // meter
int m_maxPointCount = MAX_POINT_COUNT_DEFAULT;
};
//-----------------------------------------------------------------------------
// output operator:
//-----------------------------------------------------------------------------
SITUATIONMAP_EXPORT std::ostream &operator<< (std::ostream &stream,
const EllipseParameters &value);
} // namespace SituationMap
@@ -0,0 +1,194 @@
/**
* @RDE_HEADER@
* GraphicalObjectAttributes
* $Id$
* $HeadURL$
* $Author$
*/
// Own
#include "graphical_object_attributes.h"
#include <MapImpl/map_impl.h>
#include <Map/situation_map_utils.h> // operator<<
#include <Common/simple_value.h>
// ESRI
#include <Map.h>
#include <GraphicsOverlay.h>
#include <Geometry.h>
#include <Graphic.h>
#include <Point.h>
#include <AttributeListModel.h>
// Qt
namespace SituationMap
{
class GraphicalObjectAttributes::Private
{
public:
Private() = default;
~Private() = default;
// ESRI data:
MapImpl *m_mapImpl = nullptr;
QString m_logicalLayerName;
// OWN data:
SimpleValue<QVariantMap> m_attributes;
}; // class GraphicalObjectAttributes::Private
//-----------------------------------------------------------------------------
GraphicalObjectAttributes::GraphicalObjectAttributes(MapImpl *mapImpl,
Esri::ArcGISRuntime::GraphicsOverlay *graphicsLayer,
const QString &debugInfo,
const UniqueMapId &uniqueMapId)
: BaseClass(mapImpl->getEsriGeoView(), graphicsLayer, debugInfo, uniqueMapId),
m_logger(getLogger("GraphicalObjectAttributes")),
d(new Private)
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START, debugInfo='" << m_debugInfo << "'";
TRACE_LOG(m_logger) << LOGFUNCTION << " END, debugInfo='" << m_debugInfo << "'";
}
GraphicalObjectAttributes::~GraphicalObjectAttributes()
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START, debugInfo='" << m_debugInfo << "'";
delete d;
TRACE_LOG(m_logger) << LOGFUNCTION << " END, debugInfo='" << m_debugInfo << "'";
}
bool GraphicalObjectAttributes::create()
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START, debugInfo='" << m_debugInfo << "'"
<< " m_visibility = " << m_visibility;
bool success = BaseClass::create();
if (!success)
{
ERROR_LOG(m_logger) << LOGFUNCTION << " debugInfo='" << m_debugInfo << "'"
<< " create failed";
return false;
}
bool successGraphic = addUpdateGraphic(); // CHECK
if (!successGraphic)
{
ERROR_LOG(m_logger) << LOGFUNCTION << " addUpdateGraphic failed, debugInfo='" << m_debugInfo << "'" << " uniqueMapId=" << m_uniqueMapId;
return false;
}
// real work:
// empty
TRACE_LOG(m_logger) << LOGFUNCTION << " END, debugInfo='" << m_debugInfo << "'";
return success;
}
QVariantMap GraphicalObjectAttributes::attributes() const
{
return d->m_attributes.value();
}
void GraphicalObjectAttributes::setAttributes(const QVariantMap &attributes)
{
d->m_attributes = attributes;
}
bool GraphicalObjectAttributes::changed()
{
return BaseClass::changed()
|| d->m_attributes.changed();
}
void GraphicalObjectAttributes::resetChanged()
{
BaseClass::resetChanged();
d->m_attributes.reset();
}
Esri::ArcGISRuntime::Geometry GraphicalObjectAttributes::getGraphicGeometry() const
{
if (m_graphic) return m_graphic->geometry();
ERROR_LOG(m_logger) << LOGFUNCTION << "Geometry is undefined";
return Esri::ArcGISRuntime::Geometry();
} // Esri::ArcGISRuntime::Geometry GraphicalObjectAttributes::getGraphicGeometry() const
bool GraphicalObjectAttributes::updateViewImpl()
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START, debugInfo='" << m_debugInfo << "'"
<< " visibility=" << m_visibility
<< " selected=" << m_selected
<< " origin=" << this->origin()
<< " scale=" << m_scale.value();
bool success = create();
if (!success)
{
ERROR_LOG(m_logger) << LOGFUNCTION << " debugInfo='" << m_debugInfo << "'"
<< " create failed";
return false;
}
if (!BaseClass::updateViewImpl())
{
ERROR_LOG(m_logger) << LOGFUNCTION << " debugInfo='" << m_debugInfo << "'"
<< " updateView failed";
return false;
}
// real work:
if (m_positions.changed())
{
const PositionCont &posCont = m_positions.value();
if (posCont.size() == 1)
{
const Point3D &origin = this->origin();
Esri::ArcGISRuntime::Point originGeometry(origin.x(),
origin.y(),
origin.z(),
spatialReference());
m_graphic->setGeometry(originGeometry);
}
}
if (d->m_attributes.changed())
{
QVariantMap rawAttributes = d->m_attributes.value();
// add basics:
rawAttributes[QLatin1String(SituationMap::UniqueMapIdAttribute)] = m_uniqueMapId;
rawAttributes[QLatin1String(SituationMap::IsPickableAttribute)] = m_pickable.value();
m_graphic->attributes()->setAttributesMap(rawAttributes);
if (m_logger.isDebugEnabled())
qCritical() << " XXXXX set rawAttributes " << rawAttributes;
}
if (m_graphic)
{
m_graphic->setZIndex(m_drawOrder.value());
m_graphic->setVisible(m_visibility.value());
m_graphic->setSelected(m_selected.value());
}
if (!success)
ERROR_LOG(m_logger) << LOGFUNCTION << " failure, debugInfo='" << m_debugInfo << "'";
TRACE_LOG(m_logger) << LOGFUNCTION << " END, debugInfo='" << m_debugInfo << "'"
<< " success = " << success
<< " visibility=" << m_visibility;
return success;
}
} // namespace SituationMap
@@ -0,0 +1,88 @@
/**
* @RDE_HEADER@
* GraphicalObjectAttributes
* $Id$
* $HeadURL$
* $Author$
*/
#pragma once
// Own
#include "abstract_graphical_object.h"
// Esri
// Qt
// forward:
//----------------------------------------------------------------------------
namespace SituationMap
{
// forward:
class MapImpl;
/**
* @brief The GraphicalObjectAttributes class
*/
class SITUATIONMAP_EXPORT GraphicalObjectAttributes : public AbstractGraphicalObject
{
using BaseClass = AbstractGraphicalObject;
public:
/**
* @brief GraphicalObjectAttributes
* @param mapImpl map to be used.
* @param logicalLayerName logical layer name to be used.
* @param debugInfo debugInfo to be used
* @param uniqueMapId uniqueMapId to be used. (Optional to fulfill rubberband requirements)
*/
GraphicalObjectAttributes(MapImpl *mapImpl,
Esri::ArcGISRuntime::GraphicsOverlay *graphicsLayer,
const QString &debugInfo,
const UniqueMapId &uniqueMapId = INVALID_MAP_ID);
GraphicalObjectAttributes(const GraphicalObjectAttributes &other) = delete;
GraphicalObjectAttributes &operator=(GraphicalObjectAttributes &other) = delete;
virtual ~GraphicalObjectAttributes();
QVariantMap attributes() const;
void setAttributes(const QVariantMap &attributes);
Esri::ArcGISRuntime::Geometry getGraphicGeometry() const override;
protected:
// Internal/Admin
virtual bool create() override;
bool changed() override;
void resetChanged() override;
bool updateViewImpl() override;
// logical
private:
LOGGER_T m_logger; ///< Interface of the Logging-Facility
class Private;
/**
* The private d-pointer to not break BC when changing internals of this class
*/
Private *d = nullptr;
};
} // namespace SituationMap
@@ -0,0 +1,166 @@
/**
* @RDE_HEADER@
* GraphicalObjectCube
* $Id$
* $HeadURL$
* $Author$
*/
// Own
#include "graphical_object_cube.h"
#include <Map/situation_map_utils.h> // operator<<
// ESRI
#include <GraphicsOverlay.h>
#include <PolygonBuilder.h>
#include <Geometry.h>
#include <Graphic.h>
#include <SpatialReference.h>
#include <AttributeListModel.h>
// Qt
namespace SituationMap
{
GraphicalObjectCube::GraphicalObjectCube(const Esri::ArcGISRuntime::GeoView *geoView
, Esri::ArcGISRuntime::GraphicsOverlay *graphicsLayer
, const QString &debugInfo
, const UniqueMapId &uniqueMapId)
: BaseClass(geoView, graphicsLayer, debugInfo, uniqueMapId)
, m_logger(getLogger("GraphicalObjectCube"))
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START, debugInfo='" << m_debugInfo << "'";
TRACE_LOG(m_logger) << LOGFUNCTION << " END, debugInfo='" << m_debugInfo << "'";
}
GraphicalObjectCube::~GraphicalObjectCube()
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START, debugInfo='" << m_debugInfo << "'";
TRACE_LOG(m_logger) << LOGFUNCTION << " END, debugInfo='" << m_debugInfo << "'";
}
bool GraphicalObjectCube::create()
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START, debugInfo='" << m_debugInfo << "'";
bool success = BaseClass::create();
if (!success)
{
ERROR_LOG(m_logger) << LOGFUNCTION << " debugInfo='" << m_debugInfo << "'"
<< " create failed";
}
// real work:
// empty
TRACE_LOG(m_logger) << LOGFUNCTION << " END, debugInfo='" << m_debugInfo << "'"
// << " drawOrder = " << m_graphic->drawOrder()
<< " success = " << success;
return success;
}
bool GraphicalObjectCube::updateViewImpl()
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START, debugInfo='" << m_debugInfo << "'";
// some checks:
if (!this->isArea())
{
ERROR_LOG(m_logger) << LOGFUNCTION << " incorrect number of positions"
<< " (" << this->positions().count() << ")";
return false;
}
if (!create())
{
ERROR_LOG(m_logger) << LOGFUNCTION << " debugInfo='" << m_debugInfo << "'"
<< " create failed";
return false;
}
if (!BaseClass::updateViewImpl())
{
ERROR_LOG(m_logger) << LOGFUNCTION << " debugInfo='" << m_debugInfo << "'"
<< " updateView failed";
return false;
}
// real work:
DEBUG_LOG(m_logger) << LOGFUNCTION << " debugInfo='" << m_debugInfo << "'";
// Attribute 'height':
QVariantMap attMap = m_graphic->attributes()->attributesMap();
attMap[QStringLiteral("height")] = QVariant(m_height.value());
//
// Attribute 'PartyName' is replaced by Attribute 'Extrusion_Color' to be more flexible
//
// Attribute 'Extrusion_Color':
if (m_extrusionColorName.value().isEmpty())
{
DEBUG_LOG(m_logger) << LOGFUNCTION
<< " debugInfo='" << m_debugInfo << "'"
<< " m_extrusionColorName is empty";
// -> time for the defaultSymbol of the Renderer
attMap[QStringLiteral("Extrusion_Color")] = QStringLiteral("DOES_NOT_EXIST");
}
else
attMap[QStringLiteral("Extrusion_Color")] = QVariant(m_extrusionColorName.value());
m_graphic->attributes()->setAttributesMap(attMap);
DEBUG_LOG(m_logger) << LOGFUNCTION << " debugInfo='" << m_debugInfo << "'" << " attributesMap[height] ='" << attMap[QStringLiteral("height")].toDouble() << "'";
DEBUG_LOG(m_logger) << LOGFUNCTION << " debugInfo='" << m_debugInfo << "'" << " attributesMap[Extrusion_Color] ='" << attMap[QStringLiteral("Extrusion_Color")].toString() << "'";
// geometry:
Esri::ArcGISRuntime::PolygonBuilder builder(spatialReference());
const PositionCont &posCont = m_positions.value();
for (const Point3D &pos : posCont)
{
builder.addPoint(pos.x(), pos.y());
}
if (! builder.isSketchValid())
{
ERROR_LOG(m_logger) << LOGFUNCTION << " debugInfo='" << m_debugInfo << "'"
<< " builder -> sketch invalid";
return false;
}
m_graphic->setGeometry(builder.toGeometry());
// add
bool successGraphic = addUpdateGraphic();
TRACE_LOG(m_logger) << LOGFUNCTION << " END, debugInfo='" << m_debugInfo << "'"
<< " drawOrder = " << m_graphic->zIndex();
return successGraphic;
}
//-----------------------------------------------------------------------------
// output operator:
//-----------------------------------------------------------------------------
std::ostream &operator<<(std::ostream &stream,
const GraphicalObjectCube &value)
{
stream << value.toString();
return stream;
}
} // namespace SituationMap
@@ -0,0 +1,100 @@
/**
* @RDE_HEADER@
* GraphicalObjectCube
* $Id$
* $HeadURL$
* $Author$
*/
#pragma once
// Own
#include "abstract_graphical_object.h"
// Esri
// Qt
// forward:
//----------------------------------------------------------------------------
namespace SituationMap
{
/**
* @brief The GraphicalObjectCube class for 3D
*
*/
class SITUATIONMAP_EXPORT GraphicalObjectCube : public AbstractGraphicalObject
{
using BaseClass = AbstractGraphicalObject;
public:
explicit GraphicalObjectCube(const Esri::ArcGISRuntime::GeoView *geoView
, Esri::ArcGISRuntime::GraphicsOverlay *graphicsLayer
, const QString &debugInfo
, const UniqueMapId &uniqueMapId);
~GraphicalObjectCube();
double height() const
{
return m_height.value();
}
void setHeight(double height)
{
m_height = height;
}
const QString &extrusionColorName() const
{
return m_extrusionColorName.value();
}
void setExtrusionColorName(const QString &extrusionColorName)
{
m_extrusionColorName = extrusionColorName;
}
protected:
// Internal/Admin
bool create() override;
bool changed() override
{
return BaseClass::changed()
|| m_height.changed()
|| m_extrusionColorName.changed();
}
void resetChanged() override
{
BaseClass::resetChanged();
m_height.reset();
m_extrusionColorName.reset();
}
bool updateViewImpl() override;
// Data
SimpleValue<double> m_height;
SimpleValue<QString> m_extrusionColorName;
private:
LOGGER_T m_logger; ///< Interface of the Logging-Facility
};
//-----------------------------------------------------------------------------
// output operator:
//-----------------------------------------------------------------------------
SITUATIONMAP_EXPORT std::ostream &operator<< (std::ostream &stream,
const GraphicalObjectCube &value);
} // namespace SituationMap
@@ -0,0 +1,351 @@
/**
* @RDE_HEADER@
* GraphicalObjectEllipse
* $Id$
* $HeadURL$
* $Author$
*/
// Own
#include "graphical_object_ellipse.h"
#include <Map/situation_map_utils.h> // operator<<
// ESRI
#include <GraphicsOverlay.h>
#include <Polygon.h>
#include <GeometryEngine.h>
#include <SimpleLineSymbol.h>
#include <SimpleFillSymbol.h>
// Qt
#include <QElapsedTimer>
#include <GeodesicEllipseParameters.h>
#include <Graphic.h>
#include <Point.h>
#include <SpatialReference.h>
#include <Multipart.h>
#include <ImmutablePart.h>
#include <ImmutablePartCollection.h>
namespace SituationMap
{
GraphicalObjectEllipse::GraphicalObjectEllipse(const Esri::ArcGISRuntime::GeoView *geoView
, Esri::ArcGISRuntime::GraphicsOverlay *graphicsLayer
, const QString &debugInfo
, const UniqueMapId &uniqueMapId)
: BaseClass(geoView, graphicsLayer, debugInfo, uniqueMapId)
, m_logger(getLogger("GraphicalObjectEllipse"))
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START, debugInfo='" << m_debugInfo << "'";
TRACE_LOG(m_logger) << LOGFUNCTION << " END, debugInfo='" << m_debugInfo << "'";
}
GraphicalObjectEllipse::~GraphicalObjectEllipse()
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START, debugInfo='" << m_debugInfo << "'";
delete m_internalParameters;
TRACE_LOG(m_logger) << LOGFUNCTION << " END, debugInfo='" << m_debugInfo << "'";
}
bool GraphicalObjectEllipse::create()
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START, debugInfo='" << m_debugInfo << "'";
bool success = BaseClass::create();
if (!success)
{
ERROR_LOG(m_logger) << LOGFUNCTION << " debugInfo='" << m_debugInfo << "'"
<< " create failed";
return false;
}
// real work:
// empty
TRACE_LOG(m_logger) << LOGFUNCTION << " END, debugInfo='" << m_debugInfo << "'"
// << " drawOrder = " << m_graphic->drawOrder()
<< " success = " << success;
return success;
}
bool GraphicalObjectEllipse::updateViewImpl()
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START, debugInfo='" << m_debugInfo << "'";
// some checks:
if (!this->isSinglePoint())
{
ERROR_LOG(m_logger) << LOGFUNCTION << " incorrect number of positions"
<< " (" << this->positions().count() << ")";
return false;
}
if (!create())
{
ERROR_LOG(m_logger) << LOGFUNCTION << " debugInfo='" << m_debugInfo << "'"
<< " create failed";
return false;
}
if (!BaseClass::updateViewImpl())
{
ERROR_LOG(m_logger) << LOGFUNCTION << " debugInfo='" << m_debugInfo << "'"
<< " updateView failed";
return false;
}
if (!m_ellipseParameters.value().isValid())
{
ERROR_LOG(m_logger) << LOGFUNCTION << " debugInfo='" << m_debugInfo << "'"
<< " ellipseParameters not valid";
return false;
}
// real work:
DEBUG_LOG(m_logger) << LOGFUNCTION << " debugInfo='" << m_debugInfo << "'"
<< " update geometry";
bool successEllipse = true;
if (m_ellipseParameters.changed() || m_positions.changed())
{
// apply attributes:
parameterToInternal();
Esri::ArcGISRuntime::Polygon ellipse;
successEllipse = createEllipse(ellipse);
if (successEllipse)
m_graphic->setGeometry(ellipse);
else
{
ERROR_LOG(m_logger) << LOGFUNCTION << " debugInfo='" << m_debugInfo << "'"
<< " createEllipse failed";
return false;
}
}
assignFillStyleToGraphic();
DEBUG_LOG(m_logger) << LOGFUNCTION << " debugInfo='" << m_debugInfo << "'";
bool successGraphic = addUpdateGraphic();
TRACE_LOG(m_logger) << LOGFUNCTION << " END, debugInfo='" << m_debugInfo << "'"
<< " drawOrder = " << m_graphic->zIndex()
<< " successEllipse = " << successEllipse
<< " successGraphic = " << successGraphic;
return successEllipse && successGraphic;
}
void GraphicalObjectEllipse::parameterToInternal()
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START, debugInfo='" << m_debugInfo << "'";
if (!m_internalParameters)
{
m_internalParameters = new Esri::ArcGISRuntime::GeodesicEllipseParameters();
m_internalParameters->setGeometryType(Esri::ArcGISRuntime::GeometryType::Polygon);
}
// TODO !!??: set xy correct, calc maxSegLength...
const EllipseParameters &ellipseParameterRef = m_ellipseParameters.value();
// 1a, 1b
m_internalParameters->setMaxSegmentLength(ellipseParameterRef.maxSegmentLength());
m_internalParameters->setMaxPointCount(ellipseParameterRef.maxPointCount());
// 2
const Point3D &origin = this->origin();
Esri::ArcGISRuntime::Point mapPoint(origin.x(), origin.y(), origin.z(), spatialReference()); // center of ellipse
Esri::ArcGISRuntime::Point normalizedPt(
Esri::ArcGISRuntime::GeometryEngine::normalizeCentralMeridian(mapPoint));
m_internalParameters->setCenter(normalizedPt);
// m_internalParameters->setCenter(mapPoint);
// 3, 4
m_internalParameters->setSemiAxis1Length(ellipseParameterRef.lengthX());
m_internalParameters->setSemiAxis2Length(ellipseParameterRef.lengthY());
// 5
m_internalParameters->setAxisDirection(ellipseParameterRef.directionDegree());
TRACE_LOG(m_logger) << LOGFUNCTION << " END, debugInfo='" << m_debugInfo << "'";
}
bool GraphicalObjectEllipse::createEllipse(Esri::ArcGISRuntime::Polygon &ellipse)
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START, debugInfo='" << m_debugInfo << "'";
bool success = createEllipsePolygon(*m_internalParameters, ellipse);
TRACE_LOG(m_logger) << LOGFUNCTION << " END, debugInfo='" << m_debugInfo << "'"
<< " success = " << success
// << " pointCount = " << ellipse.pointCount()
<< " dimension = " << (int)ellipse.dimension();
return success;
}
bool GraphicalObjectEllipse::createEllipsePolygon(const Esri::ArcGISRuntime::GeodesicEllipseParameters &ellipseParameters,
Esri::ArcGISRuntime::Polygon &polygon)
{
LOGGER_T m_logger = getLogger("GraphicalObjectEllipse");
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
QElapsedTimer timer;
if (m_logger.isInfoEnabled())
timer.start();
bool success = false;
Esri::ArcGISRuntime::Geometry ellipseGeometry =
Esri::ArcGISRuntime::GeometryEngine::ellipseGeodesic(ellipseParameters);
if (ellipseGeometry.isEmpty())
{
ERROR_LOG(m_logger) << LOGFUNCTION
<< " There was an error computing the geodesic ellipse. Try a different segment length.";
}
else
{
polygon = Esri::ArcGISRuntime::Polygon(ellipseGeometry);
success = true;
}
int count = AbstractGraphicalObject::countOfPolygonFirstPart(polygon);
DEBUG_LOG(m_logger) << LOGFUNCTION
<< " count=" << count
<< " (semiAxis1Length=" << ellipseParameters.semiAxis1Length()
<< " , semiAxis2Length=" << ellipseParameters.semiAxis2Length()
<< " , maxPointCount=" << ellipseParameters.maxPointCount()
<< " , maxSegmentLength=" << ellipseParameters.maxSegmentLength()
<< " , dimension = " << (int)polygon.dimension()
<< ")";
if (m_logger.isDebugEnabled())
{
DEBUG_LOG(m_logger) << LOGFUNCTION
<< " took " << timer.elapsed() << "ms"
<< " (semiAxis1Length=" << ellipseParameters.semiAxis1Length()
<< " , semiAxis2Length=" << ellipseParameters.semiAxis2Length()
<< " , maxPointCount=" << ellipseParameters.maxPointCount()
<< " , maxSegmentLength=" << ellipseParameters.maxSegmentLength()
<< " , dimension = " << (int)polygon.dimension()
<< ")";
}
TRACE_LOG(m_logger) << LOGFUNCTION << " END"
<< " success = " << success;
return success;
}
bool GraphicalObjectEllipse::createCirclePolygon(const Esri::ArcGISRuntime::Point &originMap,
float radius,
unsigned int maxPointCount,
Esri::ArcGISRuntime::Polygon &polygon)
{
LOGGER_T m_logger = getLogger("GraphicalObjectEllipse");
TRACE_LOG(m_logger) << LOGFUNCTION << " START"
<< " origin=" << originMap.x() << " ; " << originMap.y() << " ; " << originMap.z()
<< " radius=" << radius;
Esri::ArcGISRuntime::GeodesicEllipseParameters ePara;
ePara.setGeometryType(Esri::ArcGISRuntime::GeometryType::Polygon);
// 1
ePara.setMaxSegmentLength(10);
if (maxPointCount == 0)
ePara.setMaxPointCount(EllipseParameters::MAX_POINT_COUNT_DEFAULT);
else
ePara.setMaxPointCount(maxPointCount);
// 2
const Esri::ArcGISRuntime::Point &mapPoint = originMap; // center of ellipse
Esri::ArcGISRuntime::Point normalizedPt(
Esri::ArcGISRuntime::GeometryEngine::normalizeCentralMeridian(mapPoint));
ePara.setCenter(normalizedPt);
// 3, 4
ePara.setSemiAxis1Length(radius);
ePara.setSemiAxis2Length(radius);
// 5
ePara.setAxisDirection(0);
return createEllipsePolygon(ePara, polygon);
}
bool GraphicalObjectEllipse::createCirclePolygon(const Esri::ArcGISRuntime::Point &originMap,
float radius,
unsigned int maxPointCount,
PositionCont &posCont)
{
Esri::ArcGISRuntime::Polygon circle;
bool success = GraphicalObjectEllipse::createCirclePolygon(originMap,
radius,
maxPointCount,
circle);
if (success && !circle.isEmpty())
{
posCont.clear();
const Esri::ArcGISRuntime::ImmutablePart &immutablePart = circle.parts().part(0);
const int size = immutablePart.pointCount();
for (int i = 0; i < size; ++i)
{
const Esri::ArcGISRuntime::Point &p = immutablePart.point(i);
posCont.append(Point3D(p.x(), p.y(), p.z()));
}
}
return success;
}
EllipseParameters GraphicalObjectEllipse::ellipseParameters() const
{
return m_ellipseParameters.value();
}
EllipseParameters &GraphicalObjectEllipse::rEllipseParameters()
{
return m_ellipseParameters.refValue();
}
void GraphicalObjectEllipse::setEllipseParameters(const EllipseParameters &ellipseParameters)
{
m_ellipseParameters = ellipseParameters;
}
//-----------------------------------------------------------------------------
// output operator:
//-----------------------------------------------------------------------------
std::ostream &operator<<(std::ostream &stream,
const GraphicalObjectEllipse &value)
{
stream << value.toString();
return stream;
}
} // namespace SituationMap
@@ -0,0 +1,121 @@
/**
* @RDE_HEADER@
* GraphicalObjectEllipse
* $Id$
* $HeadURL$
* $Author$
*/
#pragma once
// Own
#include "abstract_graphical_object.h"
#include "ellipse_parameters.h"
// Esri
// Qt
// forward:
namespace Esri
{
namespace ArcGISRuntime
{
class Polygon;
class Point;
class GeodesicEllipseParameters;
}
}
//----------------------------------------------------------------------------
namespace SituationMap
{
class SITUATIONMAP_EXPORT GraphicalObjectEllipse : public AbstractGraphicalObject
{
using BaseClass = AbstractGraphicalObject;
public:
GraphicalObjectEllipse(const Esri::ArcGISRuntime::GeoView *geoView
, Esri::ArcGISRuntime::GraphicsOverlay *graphicsLayer
, const QString &debugInfo
, const UniqueMapId &uniqueMapId);
~GraphicalObjectEllipse();
EllipseParameters ellipseParameters() const;
EllipseParameters &rEllipseParameters();
void setEllipseParameters(const EllipseParameters &ellipseParameters);
static bool createEllipsePolygon(const Esri::ArcGISRuntime::GeodesicEllipseParameters &ellipseParameters,
Esri::ArcGISRuntime::Polygon &polygon);
static bool createCirclePolygon(const Esri::ArcGISRuntime::Point &originMap,
float radius,
unsigned int maxPointCount,
Esri::ArcGISRuntime::Polygon &polygon);
static bool createCirclePolygon(const Esri::ArcGISRuntime::Point &originMap,
float radius,
unsigned int maxPointCount,
PositionCont &posCont);
protected:
// Internal/Admin
bool create() override;
bool changed() override
{
return BaseClass::changed()
|| m_ellipseParameters.changed();
}
void resetChanged() override
{
BaseClass::resetChanged();
m_ellipseParameters.reset();
}
bool updateViewImpl() override;
// Data
Esri::ArcGISRuntime::GeodesicEllipseParameters *m_internalParameters = nullptr;
SimpleValue<EllipseParameters> m_ellipseParameters;
void parameterToInternal();
virtual bool createEllipse(Esri::ArcGISRuntime::Polygon &ellipse);
private:
LOGGER_T m_logger; ///< Interface of the Logging-Facility
// Forbid some overloaded methods without effects of this object;
virtual PositionCont positions() const override
{
return PositionCont();
}
virtual void setPositions(const PositionCont &posCont) override
{
Q_UNUSED(posCont);
}
};
//-----------------------------------------------------------------------------
// output operator:
//-----------------------------------------------------------------------------
std::ostream &operator<< (std::ostream &stream,
const GraphicalObjectEllipse &value);
} // namespace SituationMap
@@ -0,0 +1,173 @@
/**
* @RDE_HEADER@
* GraphicalObjectModelSceneMarker
* $Id$
* $HeadURL$
* $Author$
*/
// Own
#include "graphical_object_model_scene_marker.h"
#include <Map/situation_map_utils.h> // operator<<
#include <MathUtils/simple_helper.h>
// ESRI
#include <arcgisversion.h> // This file is created by RME, not ESRI
#include <GraphicsOverlay.h>
#include <ModelSceneSymbol.h>
// Qt
#include <QPainter>
#include <QFile>
#include <Graphic.h>
#include <Point.h>
#include <SpatialReference.h>
namespace SituationMap
{
GraphicalObjectModelSceneMarker::GraphicalObjectModelSceneMarker(const Esri::ArcGISRuntime::GeoView *geoView
, Esri::ArcGISRuntime::GraphicsOverlay *graphicsLayer
, const QString &debugInfo
, const UniqueMapId &uniqueMapId)
: BaseClass(geoView, graphicsLayer, debugInfo, uniqueMapId)
, m_logger(getLogger("GraphicalObjectModelSceneMarker"))
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START, debugInfo='" << m_debugInfo << "'";
TRACE_LOG(m_logger) << LOGFUNCTION << " END, debugInfo='" << m_debugInfo << "'";
}
GraphicalObjectModelSceneMarker::~GraphicalObjectModelSceneMarker()
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START, debugInfo='" << m_debugInfo << "'";
delete m_modelSceneSymbol;
m_modelSceneSymbol = nullptr;
TRACE_LOG(m_logger) << LOGFUNCTION << " END, debugInfo='" << m_debugInfo << "'";
}
void GraphicalObjectModelSceneMarker::setUrl(const QUrl &url)
{
m_url = url;
}
QUrl GraphicalObjectModelSceneMarker::url() const
{
return m_url.value();
}
void GraphicalObjectModelSceneMarker::setHeading(float heading)
{
m_heading = heading;
}
float GraphicalObjectModelSceneMarker::heading() const
{
return m_heading.value();
}
bool GraphicalObjectModelSceneMarker::create()
{
return BaseClass::create();
}
bool GraphicalObjectModelSceneMarker::updateViewImpl()
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START, debugInfo='" << m_debugInfo << "'"
<< " origin =" << this->origin() // .x() << " , " << this->origin().y()
<< " visibility=" << m_visibility
<< " pickable=" << m_pickable
<< " pickable.changed=" << m_pickable.changed()
<< " selected=" << m_selected
<< " m_url = " << m_url.value().toString()
<< " m_drawOrder = " << m_drawOrder
<< " m_scale = " << m_scale.value()
<< " m_heading = " << m_heading.value();
// some checks:
if (!isSinglePoint())
{
ERROR_LOG(m_logger) << LOGFUNCTION
<< " debugInfo='" << m_debugInfo << "'"
<< " incorrect number of positions"
<< " (" << this->positions().count() << ")";
return false;
}
QFile fi(m_url.value().path());
if (!fi.exists())
{
ERROR_LOG(m_logger) << LOGFUNCTION << " debugInfo='" << m_debugInfo << "'"
<< " m_url does not exists: '" << fi.fileName() << "'";
m_url.reset();
}
if (m_url.value().isEmpty())
{
ERROR_LOG(m_logger) << LOGFUNCTION
<< " debugInfo='" << m_debugInfo << "'"
<< " no url provided (or does not exist)";
return false;
}
bool success = create();
if (!success)
{
ERROR_LOG(m_logger) << LOGFUNCTION << " debugInfo='" << m_debugInfo << "'"
<< " create failed";
return false;
}
const Point3D &origin = this->origin();
Esri::ArcGISRuntime::Point originGeometry(origin.x(),
origin.y(),
origin.z(),
spatialReference());
m_graphic->setGeometry(originGeometry);
// url changed?
if ( (m_modelSceneSymbol && (m_modelSceneSymbol->url() != m_url.value())) ||
m_scale.changed())
{
// force re-create ModelSceneSymbol:
delete m_modelSceneSymbol;
m_modelSceneSymbol = nullptr;
}
if (!m_modelSceneSymbol)
{
m_modelSceneSymbol = new Esri::ArcGISRuntime::ModelSceneSymbol(m_url.value(), m_scale.value()); // url, scale
}
m_modelSceneSymbol->setHeading(m_heading.value()); // degree, clockwise, 0 is north/12
// m_modelSceneSymbol->setAnchorPosition(Esri::ArcGISRuntime::SceneSymbolAnchorPosition::Bottom);
m_graphic->setSymbol(m_modelSceneSymbol);
success = BaseClass::updateViewImpl();
if (!success)
{
ERROR_LOG(m_logger) << LOGFUNCTION << " debugInfo='" << m_debugInfo << "'"
<< " updateView failed";
return false;
}
success = addUpdateGraphic();
if (!success)
{
ERROR_LOG(m_logger) << LOGFUNCTION << " debugInfo='" << m_debugInfo << "'"
<< " updateView failed";
return false;
}
TRACE_LOG(m_logger) << LOGFUNCTION << " END, debugInfo='" << m_debugInfo << "'"
<< " success=" << success
<< " m_drawOrder = " << m_drawOrder
<< " m_graphic->drawOrder = " << m_graphic->zIndex();
return success;
}
} // namespace SituationMap
@@ -0,0 +1,111 @@
/**
* @RDE_HEADER@
* GraphicalObjectModelSceneMarker
* $Id$
* $HeadURL$
* $Author$
*/
#pragma once
// Own
#include "abstract_graphical_object.h"
#include <Map/text_style.h>
#include <Common/situation_map_logging.h>
// Esri
#include <SymbolTypes.h>
// Qt
#include <QImage>
#include <QUrl>
// forward:
namespace Esri
{
namespace ArcGISRuntime
{
class Graphic;
class GraphicsOverlay;
class ModelSceneSymbol;
}
}
//----------------------------------------------------------------------------
namespace SituationMap
{
class SITUATIONMAP_EXPORT GraphicalObjectModelSceneMarker : public AbstractGraphicalObject
{
using BaseClass = AbstractGraphicalObject;
public:
GraphicalObjectModelSceneMarker(const Esri::ArcGISRuntime::GeoView *geoView
, Esri::ArcGISRuntime::GraphicsOverlay *graphicsLayer
, const QString &debugInfo
, const UniqueMapId &uniqueMapId);
~GraphicalObjectModelSceneMarker();
// Data access:
// to be cont.
void setUrl(const QUrl &url);
QUrl url() const;
// degree ; 0 is north/12
void setHeading(float heading);
float heading() const;
protected:
// Internal/Admin
bool create() override;
bool changed() override
{
return BaseClass::changed()
|| m_url.changed()
|| m_heading.changed()
;
}
void resetChanged() override
{
BaseClass::resetChanged();
m_url.reset();
m_heading.reset();
}
bool updateViewImpl() override;
// used ModelSceneSymbol:
Esri::ArcGISRuntime::ModelSceneSymbol *m_modelSceneSymbol{nullptr};
SimpleValue<QUrl> m_url; // e.g. /shd/CTC/TOOLS/ArcGIS/Runtime/Data/3D/Bristol/Collada/Bristol.dae
SimpleValue<float> m_heading{0.0}; // degree, clockwise, 0 is north/12
private:
LOGGER_T m_logger; ///< Interface of the Logging-Facility
// Forbid some overloaded methods without effects of this object;
PositionCont positions() const override
{
return PositionCont();
}
void setPositions(const PositionCont &posCont) override
{
Q_UNUSED(posCont);
Q_ASSERT(false);
}
};
} // namespace SituationMap
@@ -0,0 +1,329 @@
/**
* @RDE_HEADER@
* GraphicalObjectPath
* $Id$
* $HeadURL$
* $Author$
*/
// Own
#include "graphical_object_multi_path.h"
#include <Map/situation_map_utils.h> // operator<<
// ESRI
#include <GraphicsOverlay.h>
#include <PolygonBuilder.h>
#include <PolylineBuilder.h>
#include <SimpleLineSymbol.h>
#include <SimpleFillSymbol.h>
#include <GeoView.h>
#include <GeometryEngine.h>
#include <Graphic.h>
#include <PartCollection.h>
#include <Polygon.h>
#include <Polyline.h>
#include <SpatialReference.h>
#include <Part.h>
// Qt
namespace SituationMap
{
GraphicalObjectMultiPath::GraphicalObjectMultiPath(const GraphicalObjectPathType type
, const Esri::ArcGISRuntime::GeoView *geoView
, Esri::ArcGISRuntime::GraphicsOverlay *graphicsLayer
, const QString &debugInfo
, UniqueMapId uniqueMapId)
: BaseClass(geoView, graphicsLayer, debugInfo, uniqueMapId)
, m_pathType(type)
, m_logger(getLogger("GraphicalObjectMultiPath"))
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START, debugInfo='" << m_debugInfo << "'"
<< " m_pathType=" << m_pathType;
TRACE_LOG(m_logger) << LOGFUNCTION << " END, debugInfo='" << m_debugInfo << "'"
<< " m_pathType=" << m_pathType;
}
GraphicalObjectMultiPath::~GraphicalObjectMultiPath()
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START, debugInfo='" << m_debugInfo << "'"
<< " m_pathType=" << m_pathType;
TRACE_LOG(m_logger) << LOGFUNCTION << " END, debugInfo='" << m_debugInfo << "'"
<< " m_pathType=" << m_pathType;
}
PositionCont GraphicalObjectMultiPath::path(int pathIndex) const
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START, debugInfo='" << m_debugInfo << "'"
<< " pathIndex=" << pathIndex;
if (hasPosCont(pathIndex))
return getPosCont(pathIndex).value();
return {};
}
void GraphicalObjectMultiPath::setPath(int pathIndex, const PositionCont &positions)
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START, debugInfo='" << m_debugInfo << "'"
<< " pathIndex=" << pathIndex
<< " positions=" << positions;
m_positionsCont[pathIndex] = positions;
TRACE_LOG(m_logger) << LOGFUNCTION << " END, debugInfo='" << m_debugInfo << "'";
}
void GraphicalObjectMultiPath::clearPath(int pathIndex)
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START, debugInfo='" << m_debugInfo << "'"
<< " pathIndex=" << pathIndex;
if (pathIndex == -1)
{
m_positions.refValue().clear();
m_positionsCont.clear();
}
else
{
if (hasPosCont(pathIndex))
{
// Do not remove the whole entry to let changed() work
m_positionsCont[pathIndex].refValue().clear();
}
}
TRACE_LOG(m_logger) << LOGFUNCTION << " END, debugInfo='" << m_debugInfo << "'";
}
void GraphicalObjectMultiPath::clearAllPaths()
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START, debugInfo='" << m_debugInfo << "'";
m_positions.refValue().clear();
m_positionsCont.clear();
TRACE_LOG(m_logger) << LOGFUNCTION << " END, debugInfo='" << m_debugInfo << "'";
}
void GraphicalObjectMultiPath::reduceTo(const QList<int> &remainingPathIndexes)
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START, debugInfo='" << m_debugInfo << "'"
<< " remainingPathIndexes=" << remainingPathIndexes;
QList<int> keys = m_positionsCont.keys();
for (int key : qAsConst(keys))
{
if (!remainingPathIndexes.contains(key))
{
// Do not remove the whole entry to let chanded() work
m_positionsCont[key].refValue().clear();
}
}
TRACE_LOG(m_logger) << LOGFUNCTION << " END, debugInfo='" << m_debugInfo << "'";
}
QList<int> GraphicalObjectMultiPath::pathIndexInUse()
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START, debugInfo='" << m_debugInfo << "'";
QList<int> ret;
///// ret << 0; // pathIndex=0 -> m_positions
QMapIterator<int, SimpleValue<PositionCont> > mapIt(m_positionsCont);
while (mapIt.hasNext())
{
mapIt.next();
const SimpleValue<PositionCont> &posData = mapIt.value();
const PositionCont &posCont = posData.value();
if (! posCont.isEmpty())
ret += mapIt.key();
} // while
TRACE_LOG(m_logger) << LOGFUNCTION << " END, debugInfo='" << m_debugInfo << "'";
return ret;
}
bool GraphicalObjectMultiPath::create()
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START, debugInfo='" << m_debugInfo << "'";
bool success = BaseClass::create();
if (!success)
{
ERROR_LOG(m_logger) << LOGFUNCTION << " debugInfo='" << m_debugInfo << "'"
<< " create failed";
return false;
}
TRACE_LOG(m_logger) << LOGFUNCTION << " END, debugInfo='" << m_debugInfo << "'";
return success;
}
bool GraphicalObjectMultiPath::updateViewImpl()
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START, debugInfo='" << m_debugInfo << "'";
bool success = create();
if (!success)
{
ERROR_LOG(m_logger) << LOGFUNCTION << " debugInfo='" << m_debugInfo << "'"
<< " create failed";
return false;
}
success = BaseClass::updateViewImpl();
if (!success)
{
ERROR_LOG(m_logger) << LOGFUNCTION << " debugInfo='" << m_debugInfo << "'"
<< " updateView failed";
return false;
}
success = updatePositions();
TRACE_LOG(m_logger) << LOGFUNCTION << " END, debugInfo='" << m_debugInfo << "'"
<< " success = " << success
<< " drawOrder = " << m_graphic->zIndex();
return success;
}
bool GraphicalObjectMultiPath::updatePositions()
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START, debugInfo='" << m_debugInfo << "'";
bool success = true;
int pathIdxToInsert = 0;
const int minPoints = this->pathType() == GraphicalObjectPathType::Polyline ? 2 : 3;
QSharedPointer<Esri::ArcGISRuntime::MultipartBuilder> builder;
// some preparations: ( do no check isMultiPoint / isArea: m_positions should typically be empty!!!
switch (m_pathType)
{
case GraphicalObjectPathType::Polyline:
builder = QSharedPointer<Esri::ArcGISRuntime::PolylineBuilder>(new Esri::ArcGISRuntime::PolylineBuilder(spatialReference()));
break;
case GraphicalObjectPathType::Polygon:
builder = QSharedPointer<Esri::ArcGISRuntime::PolygonBuilder>(new Esri::ArcGISRuntime::PolygonBuilder(spatialReference()));
break;
} // switch
QSharedPointer<Esri::ArcGISRuntime::PartCollection> partCollection =
QSharedPointer<Esri::ArcGISRuntime::PartCollection>(new Esri::ArcGISRuntime::PartCollection(builder->spatialReference()));
TRACE_LOG(m_logger) << LOGFUNCTION << " START, debugInfo='" << m_debugInfo << "'"
<< ", m_positionsCont.size() /#rings=" << m_positionsCont.size();
QMutableMapIterator<int, SimpleValue<PositionCont> > mapIt(m_positionsCont);
//
// LOOP PER SINGLE POLY
//
while (mapIt.hasNext())
{
mapIt.next();
const int key = mapIt.key();
const SimpleValue<PositionCont> &posData = mapIt.value();
const PositionCont &posCont = posData.value();
TRACE_LOG(m_logger) << LOGFUNCTION << " START, debugInfo='" << m_debugInfo << "'"
<< ", key / #ring=" << key
<< ", rings.size()=" << posCont.size();
// maybe some pathIdx are cleared by clearPath() or similar:
if (posCont.isEmpty())
{
DEBUG_LOG(m_logger) << LOGFUNCTION
<< " posCont empty, cleared? -> remove/cleanup"
<< " pathIdxToInsert = " << pathIdxToInsert
<< " mapIt.key() = " << key;
mapIt.remove();
continue;
}
if (posCont.count() < minPoints)
{
ERROR_LOG(m_logger) << LOGFUNCTION
<< " incorrect number of positions"
<< " (" << posCont.count() << ")"
<< ", minPoints=" << minPoints
<< ", pathIdxToInsert = " << pathIdxToInsert
<< ", mapIt.key() = " << key
<< ", m_debugInfo = " << m_debugInfo;
success = false;
}
else
{
Esri::ArcGISRuntime::Part part(builder->spatialReference());
//
// LOOP PER POINT
//
for (auto pos : qAsConst(posCont))
{
part.addPoint(pos.x(), pos.y(), pos.z());
TRACE_LOG(m_logger) << LOGFUNCTION << " START, debugInfo='" << m_debugInfo << "'"
<< ", key / #ring=" << key
<< ", addPoint=" << pos;
}
partCollection->addPart(&part);
} // if (posCont.count() < minPoints)
} // while
builder->setParts(partCollection.get());
//
// builder to geometry;
//
switch (m_pathType)
{
case GraphicalObjectPathType::Polyline:
{
const Esri::ArcGISRuntime::Polyline &multipartPolyline =
static_cast<Esri::ArcGISRuntime::PolylineBuilder *>(builder.data())->toPolyline();
m_graphic->setGeometry(multipartPolyline);
assignLineStyleToGraphic();
}
break;
case GraphicalObjectPathType::Polygon:
{
const Esri::ArcGISRuntime::Polygon &multipartPolygon =
static_cast<Esri::ArcGISRuntime::PolygonBuilder *>(builder.data())->toPolygon();
m_graphic->setGeometry(multipartPolygon);
//assignLineStyleToGraphic();
assignFillStyleToGraphic();
}
break;
} // switch
DEBUG_LOG(m_logger) << LOGFUNCTION << " debugInfo='" << m_debugInfo << "'";
success = addUpdateGraphic();
TRACE_LOG(m_logger) << LOGFUNCTION << " END, debugInfo='" << m_debugInfo << "'"
<< " success = " << success
<< " drawOrder = " << m_graphic->zIndex();
return success;
}
bool GraphicalObjectMultiPath::hasPosCont(int idx) const
{
return m_positionsCont.contains(idx);
}
SimpleValue<PositionCont> &GraphicalObjectMultiPath::getPosCont(int idx)
{
return m_positionsCont[idx];
}
const SimpleValue<PositionCont> GraphicalObjectMultiPath::getPosCont(int idx) const
{
return m_positionsCont[idx];
}
} // namespace SituationMap
@@ -0,0 +1,105 @@
/**
* @RDE_HEADER@
* GraphicalObjectPath
* $Id$
* $HeadURL$
* $Author$
*/
#pragma once
// Own
#include "graphical_object_path.h"
// Esri
// Qt
#include <QMap>
//----------------------------------------------------------------------------
namespace SituationMap
{
class SITUATIONMAP_EXPORT GraphicalObjectMultiPath : public AbstractGraphicalObject
{
using BaseClass = AbstractGraphicalObject;
public:
GraphicalObjectMultiPath(const GraphicalObjectPathType type
, const Esri::ArcGISRuntime::GeoView *geoView
, Esri::ArcGISRuntime::GraphicsOverlay *graphicsLayer
, const QString &debugInfo
, UniqueMapId uniqueMapId);
~GraphicalObjectMultiPath();
GraphicalObjectPathType pathType() const
{
return m_pathType;
}
virtual PositionCont path(int pathIndex) const;
virtual void setPath(int pathIndex, const PositionCont &positions);
/*! \name Subsidiary polyline/polygons */
//@{
virtual void clearPath(int pathIndex);
virtual void clearAllPaths();
virtual QList<int> pathIndexInUse();
virtual void reduceTo(const QList<int> &remainingPathIndexes);
//@}
protected:
// Internal/Admin
bool updatePositions();
bool changed() override
{
bool baseClassChanged = BaseClass::changed();
if (baseClassChanged)
return true;
for (const SimpleValue<PositionCont> &posData : qAsConst(m_positionsCont))
{
if (posData.changed())
return true;
}
return false;
}
void resetChanged() override
{
BaseClass::resetChanged();
for (SimpleValue<PositionCont> &posData : m_positionsCont)
posData.reset();
}
bool create() override;
bool updateViewImpl() override;
// logical
const GraphicalObjectPathType m_pathType;
//bool updatePositions();
private:
// Attention: will contain 'positions' of idx == 1 and higher :
bool hasPosCont(int idx) const;
SimpleValue<PositionCont> &getPosCont(int idx);
const SimpleValue<PositionCont> getPosCont(int idx) const;
QMap<int, SimpleValue<PositionCont> > m_positionsCont;
// : Attention: will contain 'positions' of idx == 1 and higher
LOGGER_T m_logger; ///< Interface of the Logging-Facility
};
} // namespace SituationMap
@@ -0,0 +1,265 @@
/**
* @RDE_HEADER@
* GraphicalObjectPath
* $Id$
* $HeadURL$
* $Author$
*/
// Own
#include "graphical_object_path.h"
#include <Map/situation_map_utils.h> // operator<<
// ESRI
#include <GraphicsOverlay.h>
#include <PolygonBuilder.h>
#include <PolylineBuilder.h>
#include <SimpleLineSymbol.h>
#include <SimpleFillSymbol.h>
#include <GeoView.h>
#include <GeometryEngine.h>
#include <Graphic.h>
#include <Polygon.h>
#include <Polyline.h>
#include <SpatialReference.h>
#include <LinearUnit.h>
// Qt
namespace SituationMap
{
QLatin1String toString(const GraphicalObjectPathType subType)
{
switch (subType)
{
case GraphicalObjectPathType::Polyline:
return QLatin1String("Polyline");
break;
case GraphicalObjectPathType::Polygon:
return QLatin1String("Polygon");
break;
} // switch
return QLatin1String("GraphicalObjectPathTypeERROR");
}
GraphicalObjectPath::GraphicalObjectPath(const GraphicalObjectPathType type
, const Esri::ArcGISRuntime::GeoView *geoView
, Esri::ArcGISRuntime::GraphicsOverlay *graphicsLayer
, const QString &debugInfo
, const UniqueMapId &uniqueMapId)
: BaseClass(geoView, graphicsLayer, debugInfo, uniqueMapId)
, m_pathType(type)
, m_logger(getLogger("GraphicalObjectPath"))
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START, debugInfo='" << m_debugInfo << "'"
<< " m_pathType=" << m_pathType;
TRACE_LOG(m_logger) << LOGFUNCTION << " END, debugInfo='" << m_debugInfo << "'"
<< " m_pathType=" << m_pathType;
}
GraphicalObjectPath::~GraphicalObjectPath()
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START, debugInfo='" << m_debugInfo << "'"
<< " m_pathType=" << m_pathType;
TRACE_LOG(m_logger) << LOGFUNCTION << " END, debugInfo='" << m_debugInfo << "'"
<< " m_pathType=" << m_pathType;
}
bool GraphicalObjectPath::create()
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START, debugInfo='" << m_debugInfo << "'";
bool success = BaseClass::create();
if (!success)
{
ERROR_LOG(m_logger) << LOGFUNCTION << " debugInfo='" << m_debugInfo << "'"
<< " create failed";
return false;
}
TRACE_LOG(m_logger) << LOGFUNCTION << " END, debugInfo='" << m_debugInfo << "'"
<< " success = " << success
// << " drawOrder = " << m_graphic->drawOrder()
;
return success;
}
bool GraphicalObjectPath::updateViewImpl()
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START, debugInfo='" << m_debugInfo << "'"
<< " m_positions= " << m_positions.value()
<< ", m_maxSegmentLength=" << m_maxSegmentLength;
QSharedPointer<Esri::ArcGISRuntime::MultipartBuilder> builder;
// some checks:
switch (m_pathType)
{
case GraphicalObjectPathType::Polyline:
if (!this->isMultiPoint())
{
ERROR_LOG(m_logger) << LOGFUNCTION << " incorrect number of positions"
<< " (" << this->positions().count() << ")";
return false;
}
builder = QSharedPointer<Esri::ArcGISRuntime::PolylineBuilder>(new Esri::ArcGISRuntime::PolylineBuilder(spatialReference()));
break;
case GraphicalObjectPathType::Polygon:
if (!this->isArea())
{
ERROR_LOG(m_logger) << LOGFUNCTION << " incorrect number of positions"
<< " (" << this->positions().count() << ")";
return false;
}
builder = QSharedPointer<Esri::ArcGISRuntime::PolygonBuilder>(new Esri::ArcGISRuntime::PolygonBuilder(spatialReference()));
break;
} // switch
if (! builder)
{
ERROR_LOG(m_logger) << LOGFUNCTION << " debugInfo='" << m_debugInfo << "'"
<< " no builder";
return false;
}
bool success = create();
if (!success)
{
ERROR_LOG(m_logger) << LOGFUNCTION << " debugInfo='" << m_debugInfo << "'"
<< " create failed";
return false;
}
success = BaseClass::updateViewImpl();
if (!success)
{
ERROR_LOG(m_logger) << LOGFUNCTION << " debugInfo='" << m_debugInfo << "'"
<< " updateView failed";
return false;
}
// real work:
DEBUG_LOG(m_logger) << LOGFUNCTION << " debugInfo='" << m_debugInfo << "'"
<< " update geometry";
const PositionCont &posCont = m_positions.value();
for (const Point3D &pos : posCont)
builder->addPoint(pos.x(), pos.y(), pos.z());
if (! builder->isSketchValid())
{
ERROR_LOG(m_logger) << LOGFUNCTION << " debugInfo='" << m_debugInfo << "'"
<< " builder -> sketch invalid";
return false;
}
//
// apply attributes:
//
// N. Thoden, 13.02.2018
// Case #02062713 [BOS] BasicSceneView_lineNotComplete
// If a line has a line of ~10km (Borderline)
// the line may 'move' on the ground (3D, RenderMode::Dynamic, SurfarcePlacement::Draped)
// To avoid these kind of effect, the advice is to densify the geometry
// [similar: Case #02054233 [BOS] LineArtefacts in 3D ->
// BUG-000111565 : Lines created on the GraphicsOverlay with "Dynamic" Rendering mode on 3D doesn't render completely when zooming in]
//
// N. Thoden, 29.03.2018
// Consulting with Luke Smallwood / using the V100.2.1. debug libs:
// densify leads to an assert, so avoid densify
// (until now densify does not lead to an improvement..)
//
// N. Thoden, 19.04.2021
// [GUEZE-495]: 3D Lagedarstellung Trefferlinien
// Linie fehlt teilweise
// jetzt (typeweise) per m_maxSegmentLength aktivierbar
switch (m_pathType)
{
case GraphicalObjectPathType::Polyline:
{
const Esri::ArcGISRuntime::Polyline &polyline =
static_cast<Esri::ArcGISRuntime::PolylineBuilder *>(builder.data())->toPolyline();
if (m_maxSegmentLength > 0)
{
m_graphic->setGeometry(Esri::ArcGISRuntime::GeometryEngine::densifyGeodetic(polyline,
m_maxSegmentLength,
Esri::ArcGISRuntime::LinearUnit::meters(),
Esri::ArcGISRuntime::GeodeticCurveType::Geodesic));
} else {
m_graphic->setGeometry(polyline);
} // if (densify)
assignLineStyleToGraphic();
}
break;
case GraphicalObjectPathType::Polygon:
{
const Esri::ArcGISRuntime::Polygon &polygon =
static_cast<Esri::ArcGISRuntime::PolygonBuilder *>(builder.data())->toPolygon();
if (m_maxSegmentLength > 0)
{
m_graphic->setGeometry(Esri::ArcGISRuntime::GeometryEngine::densifyGeodetic(polygon,
m_maxSegmentLength,
Esri::ArcGISRuntime::LinearUnit::meters(),
Esri::ArcGISRuntime::GeodeticCurveType::Geodesic));
} else {
m_graphic->setGeometry(polygon);
}
assignFillStyleToGraphic();
}
break;
} // switch
const int count = AbstractGraphicalObject::countOfPolygonFirstPart(m_graphic->geometry());
if (count > 1000)
WARNING_LOG(m_logger) << LOGFUNCTION << " debugInfo='" << m_debugInfo << "'"
<< ", huge amount of vertices, countOfPolygonFirstPart = " << count;
else
DEBUG_LOG(m_logger) << LOGFUNCTION << " debugInfo='" << m_debugInfo << "'"
<< ", amount of vertices, countOfPolygonFirstPart = " << count;
success = addUpdateGraphic();
TRACE_LOG(m_logger) << LOGFUNCTION << " END, debugInfo='" << m_debugInfo << "'"
<< " success = " << success
<< " drawOrder = " << m_graphic->zIndex();
return success;
}
double GraphicalObjectPath::maxSegmentLength() const
{
return m_maxSegmentLength;
}
void GraphicalObjectPath::setMaxSegmentLength(double maxSegmentLength)
{
m_maxSegmentLength = maxSegmentLength;
}
//-----------------------------------------------------------------------------
// output operator:
//-----------------------------------------------------------------------------
std::ostream &operator<<(std::ostream &stream,
const GraphicalObjectPathType &value)
{
stream << toString(value).latin1();
return stream;
}
} // namespace SituationMap
@@ -0,0 +1,78 @@
/**
* @RDE_HEADER@
* GraphicalObjectPath
* $Id$
* $HeadURL$
* $Author$
*/
#pragma once
// Own
#include "abstract_graphical_object.h"
// Esri
// Qt
// forward:
//----------------------------------------------------------------------------
namespace SituationMap
{
enum class GraphicalObjectPathType {Polyline, Polygon};
QLatin1String toString(const GraphicalObjectPathType subType);
class SITUATIONMAP_EXPORT GraphicalObjectPath : public AbstractGraphicalObject
{
using BaseClass = AbstractGraphicalObject;
public:
explicit GraphicalObjectPath(const GraphicalObjectPathType type
, const Esri::ArcGISRuntime::GeoView *geoView
, Esri::ArcGISRuntime::GraphicsOverlay *graphicsLayer
, const QString &debugInfo
, const UniqueMapId &uniqueMapId);
~GraphicalObjectPath();
GraphicalObjectPathType pathType() const
{
return m_pathType;
}
double maxSegmentLength() const;
void setMaxSegmentLength(double maxSegmentLength);
protected:
// Internal/Admin
bool create() override;
bool updateViewImpl() override;
// logical
const GraphicalObjectPathType m_pathType;
double m_maxSegmentLength{-1};
private:
LOGGER_T m_logger; ///< Interface of the Logging-Facility
};
//-----------------------------------------------------------------------------
// output operator:
//-----------------------------------------------------------------------------
SITUATIONMAP_EXPORT std::ostream &operator<< (std::ostream &stream,
const GraphicalObjectPathType &value);
} // namespace SituationMap
@@ -0,0 +1,578 @@
/**
* @RDE_HEADER@
* GraphicalObjectPictureMarker
* $Id$
* $HeadURL$
* $Author$
*/
// Own
#include "graphical_object_picture_marker.h"
#include <Map/situation_map_utils.h> // operator<<
#include <SymbologyImpl/symbol_extension_renderer.h>
#include <MathUtils/simple_helper.h>
// ESRI
#include <arcgisversion.h> // This file is created by RME, not ESRI
#include <GraphicsOverlay.h>
#include <PictureMarkerSymbol.h>
#include <SimpleMarkerSymbol.h>
#include <MultipointBuilder.h>
// Qt
#include <QPainter>
#include <QTimer>
#include <Geometry.h>
#include <Graphic.h>
#include <PointCollection.h>
#include <SpatialReference.h>
#include <Point.h>
namespace SituationMap
{
/**
* @brief getSimpleMarkerSymbolStyle
* @param markerSymbolType type to get
* @param filePath filePath of requested marker; if empty -> use return value, if !empty -> use filePath and get file out of qrc
* @param hotSpotPercent -0.5 to 0.5; e.g. x=center, y=bottom -> -0.5
* @return corrosponding Esri::ArcGISRuntime::SimpleMarkerSymbolStyle, see filePath
*/
Esri::ArcGISRuntime::SimpleMarkerSymbolStyle getSimpleMarkerSymbolStyle(MarkerSymbolType markerSymbolType,
QString &filePath,
QPointF *hotSpotPercent = nullptr)
{
if (hotSpotPercent)
*hotSpotPercent = QPointF();
filePath.clear();
Esri::ArcGISRuntime::SimpleMarkerSymbolStyle esriSMSS =
Esri::ArcGISRuntime::SimpleMarkerSymbolStyle::Circle;
switch (markerSymbolType)
{
case SituationMap::MarkerSymbolType::Undefined:
esriSMSS = Esri::ArcGISRuntime::SimpleMarkerSymbolStyle::Circle;
break;
case SituationMap::MarkerSymbolType::Circle:
esriSMSS = Esri::ArcGISRuntime::SimpleMarkerSymbolStyle::Circle;
break;
case SituationMap::MarkerSymbolType::Cross:
esriSMSS = Esri::ArcGISRuntime::SimpleMarkerSymbolStyle::Cross;
break;
case SituationMap::MarkerSymbolType::Diamond:
esriSMSS = Esri::ArcGISRuntime::SimpleMarkerSymbolStyle::Diamond;
break;
case SituationMap::MarkerSymbolType::Square:
esriSMSS = Esri::ArcGISRuntime::SimpleMarkerSymbolStyle::Square;
break;
case SituationMap::MarkerSymbolType::X:
esriSMSS = Esri::ArcGISRuntime::SimpleMarkerSymbolStyle::X;
break;
case SituationMap::MarkerSymbolType::Triangle:
esriSMSS = Esri::ArcGISRuntime::SimpleMarkerSymbolStyle::Triangle;
break;
case SituationMap::MarkerSymbolType::PushPin2D:
esriSMSS = Esri::ArcGISRuntime::SimpleMarkerSymbolStyle::Circle;
filePath = QLatin1String(":/situationMap/pushPinRedClipArt.png");
if (hotSpotPercent)
*hotSpotPercent = QPointF(0, -0.5);
break;
} //switch
return esriSMSS;
}
GraphicalObjectPictureMarker::GraphicalObjectPictureMarker(const Esri::ArcGISRuntime::GeoView *geoView
, Esri::ArcGISRuntime::GraphicsOverlay *graphicsLayer
, const QString &debugInfo
, const UniqueMapId &uniqueMapId)
: BaseClass(geoView, graphicsLayer, debugInfo, uniqueMapId)
, m_logger(getLogger("GraphicalObjectPictureMarker"))
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START, debugInfo='" << m_debugInfo << "'";
TRACE_LOG(m_logger) << LOGFUNCTION << " END, debugInfo='" << m_debugInfo << "'";
}
GraphicalObjectPictureMarker::~GraphicalObjectPictureMarker()
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START, debugInfo='" << m_debugInfo << "'";
resetPictureMarkerSymbol();
resetImage();
resetSimpleMarkerSymbol();
TRACE_LOG(m_logger) << LOGFUNCTION << " END, debugInfo='" << m_debugInfo << "'";
}
void GraphicalObjectPictureMarker::setImage(const QImage &image, const QSize &defaultSize)
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START, debugInfo='" << m_debugInfo << "'"
<< " visibility=" << m_visibility
<< " image.size()=" << image.size()
<< " defaultSize=" << defaultSize
<< " m_imageDefaultSize=" << m_imageDefaultSize
<< " m_imageChanged=" << m_imageChanged
<< " m_imageDefaultSize.changed()=" << m_imageDefaultSize.changed();
resetSimpleMarkerSymbol();
if (m_image != image)
{
m_image = image;
m_imageChanged = true;
}
// store defautlSize (member shouldn´t be modified)
m_imageDefaultSize = defaultSize;
if (m_imageDefaultSize.changed())
m_imageChanged = true;
TRACE_LOG(m_logger) << LOGFUNCTION << " END, debugInfo='" << m_debugInfo << "'"
<< " visibility=" << m_visibility
<< " image.size()=" << image.size()
<< " defaultSize=" << defaultSize
<< " m_imageDefaultSize=" << m_imageDefaultSize
<< " m_imageChanged=" << m_imageChanged
<< " m_imageDefaultSize.changed()=" << m_imageDefaultSize.changed();
}
void GraphicalObjectPictureMarker::setPictureMarkerSymbol(Esri::ArcGISRuntime::PictureMarkerSymbol *pms, QSize defaultSize)
{
resetSimpleMarkerSymbol();
resetImage();
if (m_isOwnPms)
{
delete m_pictureMarkerSymbol;
m_pictureMarkerSymbol = nullptr;
}
if (m_pictureMarkerSymbol == pms &&
m_imageDefaultSize.value() == defaultSize)
return;
m_isOwnPms = false;
m_pictureMarkerSymbol = pms;
m_imageDefaultSize = defaultSize;
m_imageChanged = true;
}
void GraphicalObjectPictureMarker::resetImage()
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START, debugInfo='" << m_debugInfo << "'";
m_image = QImage();
m_imageChanged = true;
TRACE_LOG(m_logger) << LOGFUNCTION << " END, debugInfo='" << m_debugInfo << "'";
}
void GraphicalObjectPictureMarker::resetPictureMarkerSymbol()
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START, debugInfo='" << m_debugInfo << "'";
if (m_isOwnPms)
delete m_pictureMarkerSymbol;
m_pictureMarkerSymbol = nullptr;
if (m_workaorundTimer)
m_workaorundTimer->stop();
TRACE_LOG(m_logger) << LOGFUNCTION << " END, debugInfo='" << m_debugInfo << "'";
}
void GraphicalObjectPictureMarker::resetSimpleMarkerSymbol()
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START, debugInfo='" << m_debugInfo << "'";
delete m_simpleMarkerSymbol;
m_simpleMarkerSymbol = nullptr;
m_markerSymbolType = MarkerSymbolType::Undefined;
TRACE_LOG(m_logger) << LOGFUNCTION << " END, debugInfo='" << m_debugInfo << "'";
}
MarkerSymbolType GraphicalObjectPictureMarker::markerSymbolType()
{
return m_markerSymbolType.value();
}
int GraphicalObjectPictureMarker::markerSymbolSize()
{
return m_markerSize.value();
}
void GraphicalObjectPictureMarker::setMarkerSymbol(MarkerSymbolType markerSymbolType,
int size, const QColor &color)
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START, debugInfo='" << m_debugInfo << "'"
<< " color=" << color;
resetImage();
m_markerSymbolType = markerSymbolType;
m_markerSize = size;
m_markerColor = color;
TRACE_LOG(m_logger) << LOGFUNCTION << " END, debugInfo='" << m_debugInfo << "'";
}
QSize GraphicalObjectPictureMarker::currentSize() const
{
return m_currentSize;
}
bool GraphicalObjectPictureMarker::create()
{
return BaseClass::create();
}
int GraphicalObjectPictureMarker::xOffset() const
{
return m_externalOffset.value().x();
}
void GraphicalObjectPictureMarker::setXOffset(int xOffset)
{
m_externalOffset.refValue().rx() = xOffset;
}
int GraphicalObjectPictureMarker::yOffset() const
{
return m_externalOffset.value().y();
}
void GraphicalObjectPictureMarker::setYOffset(int yOffset)
{
m_externalOffset.refValue().ry() = yOffset;
}
float GraphicalObjectPictureMarker::rotationAngle()
{
return m_angle.value();
}
void GraphicalObjectPictureMarker::setRotationAngle(float angle)
{
m_angle = angle;
}
bool GraphicalObjectPictureMarker::updateViewImpl()
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START, debugInfo='" << m_debugInfo << "'"
<< " origin =" << this->origin() // .x() << " , " << this->origin().y()
<< " visibility=" << m_visibility
<< " pickable=" << m_pickable
<< " pickable.changed=" << m_pickable.changed()
<< " selected=" << m_selected
<< " m_angle = " << m_angle.value()
<< " m_drawOrder = " << m_drawOrder
<< " m_image.size() = " << m_image.size()
<< " m_imageChanged = " << m_imageChanged
<< " m_imageDefaultSize=" << m_imageDefaultSize
<< " m_imageDefaultSize.changed()=" << m_imageDefaultSize.changed()
<< " m_scale = " << m_scale.value();
// some checks:
if (m_positions.value().size() < 1)
{
ERROR_LOG(m_logger) << LOGFUNCTION
<< " debugInfo='" << m_debugInfo << "'"
<< " incorrect number of positions"
<< " (" << this->positions().count() << ")";
return false;
}
//
// Image or Marker ???
//
QString filePath;
QPointF hotSpotPercent;
Esri::ArcGISRuntime::SimpleMarkerSymbolStyle esriSMSS =
getSimpleMarkerSymbolStyle(m_markerSymbolType.value(),
filePath,
&hotSpotPercent);
m_markerHotSpotPercent = hotSpotPercent;
if (m_markerSymbolType.value() != MarkerSymbolType::Undefined)
{
if (m_markerSize.changed() ||
m_markerSymbolType.changed() ||
m_markerColor.changed() ||
m_markerSymbolType.changed() ||
m_angle.changed() ||
m_markerHotSpotPercent.changed())
{
if (!reCreateSymbol(filePath, esriSMSS))
return false;
}
}
else
{
if (m_image.isNull() && (!m_isOwnPms && m_pictureMarkerSymbol == nullptr))
{
// in context of class 'TacticalAppearance' the PictureMarker exist always...
DEBUG_LOG(m_logger) << LOGFUNCTION << " no image and m_markerSymbolType==Undefined -> nothing to do";
// -> nothing to do:
return true; // -> nothing to do:
}
if (m_scale.changed() ||
m_imageChanged ||
m_markerSymbolType.changed() ||
m_markerSize.changed() ||
m_angle.changed() ||
!m_pictureMarkerSymbol)
{
if (!reCreateSymbol(filePath, esriSMSS))
return false;
}
}
const PositionCont &posCont = m_positions.value();
if (posCont.size() == 1)
{
const Point3D &origin = this->origin();
Esri::ArcGISRuntime::Point originGeometry(origin.x(),
origin.y(),
origin.z(),
spatialReference());
m_graphic->setGeometry(originGeometry);
}
else
{
// Eception: Layer with name "AES2" should NOT have no renderer 8 to enable multipoint graphics
// [GUEZE-496] RPL Nr 770: 3D Lagedarstellung Einfrieren der SW Appl.
DEBUG_LOG(m_logger) << LOGFUNCTION << " debugInfo='" << m_debugInfo << "'" << " posCont.size() = " << posCont.size();
Esri::ArcGISRuntime::MultipointBuilder builder(spatialReference());
for (const Point3D &pos : posCont)
builder.points()->addPoint(pos.x(), pos.y(), pos.z());
if (! builder.isSketchValid())
{
ERROR_LOG(m_logger) << LOGFUNCTION << " debugInfo='" << m_debugInfo << "'"
<< " builder -> sketch invalid";
return false;
}
m_graphic->setGeometry(builder.toGeometry());
}
bool success = BaseClass::updateViewImpl();
if (!success)
{
ERROR_LOG(m_logger) << LOGFUNCTION << " debugInfo='" << m_debugInfo << "'"
<< " updateView failed";
return false;
}
success = addUpdateGraphic();
QSize imgSize = m_image.size();
QSizeF pmSize;
if (m_pictureMarkerSymbol)
pmSize = QSizeF(m_pictureMarkerSymbol->width(), m_pictureMarkerSymbol->height());
TRACE_LOG(m_logger) << LOGFUNCTION << " END, debugInfo='" << m_debugInfo << "'"
// << " success=" << success
<< " m_drawOrder = " << m_drawOrder
<< " m_graphic->drawOrder = " << m_graphic->zIndex()
<< " m_image->size() = " << imgSize
<< " pictureMarkerSymbol->size() = " << pmSize;
return success;
}
bool GraphicalObjectPictureMarker::reCreateSymbol(const QString &filePath,
const Esri::ArcGISRuntime::SimpleMarkerSymbolStyle esriSMSS)
{
const bool imageRequired = !m_image.isNull() || !filePath.isEmpty();
TRACE_LOG(m_logger) << LOGFUNCTION << " START, debugInfo='" << m_debugInfo << "'"
<< " filePath = '" << filePath << "'"
<< " m_image->size() = " << m_image.size()
<< " m_imageChanged = " << m_imageChanged
<< " m_angle = " << m_angle.value()
<< " m_currentSize = " << m_currentSize
<< " m_imageDefaultSize = " << m_imageDefaultSize.value()
<< " m_imageDefaultSize.changed() = " << m_imageDefaultSize.changed();
//
// Now we know what to use: Image or Marker
//
if (!create())
{
ERROR_LOG(m_logger) << LOGFUNCTION << " debugInfo='" << m_debugInfo << "'"
<< " create failed";
return false;
}
// what is used currently?
// image or m_simpleMarkerSymbol(esri)?
DEBUG_LOG(m_logger) << LOGFUNCTION << " debugInfo='" << m_debugInfo << "'"
<< " imageRequired=" << imageRequired
<< " m_pictureMarkerSymbol=" << m_pictureMarkerSymbol
<< " m_simpleMarkerSymbol=" << m_simpleMarkerSymbol;
if (!filePath.isEmpty())
{
// e.g. case PushPin2D
QImage img;
if (img.load(filePath))
{
int iSize = qRound(m_markerSize.value() * m_scale.value());
m_currentSize = QSize(iSize, iSize);
img = img.scaledToHeight(iSize, Qt::SmoothTransformation);
QColor localColor = m_markerColor.value();
if (m_markerSymbolType.value() == MarkerSymbolType::PushPin2D && localColor.isValid())
{
QColor colorToBeReplaced(255, 0, 0);
AdvancedSymbology::ExtensionRenderer::replaceColor(img, colorToBeReplaced.rgba(), localColor.rgba());
}
setImage(img);
}
else
{
ERROR_LOG(m_logger) << LOGFUNCTION << " loading image failed, debugInfo='" << m_debugInfo << "'"
<< " path='" << filePath << "'";
return false;
}
}
//
// Transfer data to esriSymbols:
//
// Image:
if (!m_image.isNull() || (!m_isOwnPms && m_pictureMarkerSymbol))
{
resetSimpleMarkerSymbol();
QSize realImageSize;
if (!m_isOwnPms && m_pictureMarkerSymbol)
{
if (m_imageDefaultSize.value().isEmpty())
m_currentSize = m_image.size() * m_scale.value();
else
m_currentSize = m_imageDefaultSize.value() * m_scale.value();
realImageSize = m_currentSize;
}
else
{
// scale localImage by m_scale
QImage localImage;
if (!filePath.isEmpty())
{
// case PushPin2D -> already scaled by m_scale. So don´t scale again:
localImage = m_image;
m_currentSize = localImage.size();
}
else
{
if (m_imageDefaultSize.value().isEmpty())
m_currentSize = m_image.size() * m_scale.value();
else
m_currentSize = m_imageDefaultSize.value() * m_scale.value();
// scaled required?
if (m_image.size() != m_currentSize)
{
DEBUG_LOG(m_logger) << LOGFUNCTION << " SCALE FROM " << m_image.size() << " TO " << m_currentSize;
localImage = m_image.scaled(m_currentSize, Qt::KeepAspectRatio, Qt::SmoothTransformation);
++m_scaleCounter4Moduletest;
} else {
localImage = m_image;
m_currentSize = localImage.size();
}
}
DEBUG_LOG(m_logger) << LOGFUNCTION << " m_scaleCounter4Moduletest = " << m_scaleCounter4Moduletest
<< ", localImage.size() = " << localImage.size();
delete m_pictureMarkerSymbol;
m_pictureMarkerSymbol = new Esri::ArcGISRuntime::PictureMarkerSymbol(localImage);
realImageSize = localImage.size();
// Workaround :
// Norbert Thoden, 11.06.2020:
// do some calls again to fix ESRI-Bug:
// Bug: new Image('localImage#) / pictureMarkerSymbol, but sometimes it will not be shown :-(
// Using try and error, we recognize that an additional call seems to fix that issue:
if (!m_workaorundTimer)
{
m_workaorundTimer = new QTimer(m_graphic);
m_workaorundTimer->setInterval(150);
m_workaorundTimer->setSingleShot(true);
QObject::connect(m_workaorundTimer, &QTimer::timeout, m_graphic, [this]() {
if (!m_graphic)
return;
m_graphic->setZIndex(m_drawOrder.value());
m_graphic->setVisible(m_visibility.value());
m_graphic->setSelected(m_selected.value());
});
}
m_workaorundTimer->start();
// : Workaround
}
m_imageChanged = false;
// set image to pms AND ALSO the Heigth and Width!!!
// // !!! Important !!!
// // Case #01713501 - PictureMarker-offset
// // Esri::PictureMarkerSymbol:: setHeight/setWidth -> typographic points.
// // 36pt -> 48pixel -> factor 0.75
// double pixelToPointFactor = 0.71;
// m_pictureMarkerSymbol->setHeight(m_image->size().height() * pixelToPointFactor);
// m_pictureMarkerSymbol->setWidth (m_image->size().width() * pixelToPointFactor);
// // !!! Important !!!
QPointF markerHotSpot = QPointF(realImageSize.width() / 2.0 * m_markerHotSpotPercent.value().x(),
realImageSize.height() / 2.0 * m_markerHotSpotPercent.value().y());
QPointF finalOffset = (markerHotSpot.toPoint() * -1) * 1.33 // 1.33; // try and error (48pixel / 36pt)
+
(m_externalOffset.value() * 0.75); // 0.75; // try and error (36pt / 48pixel)
m_pictureMarkerSymbol->setOffsetX(finalOffset.x());
m_pictureMarkerSymbol->setOffsetY(finalOffset.y());
m_pictureMarkerSymbol->setAngle(m_angle.value());
m_graphic->setSymbol(m_pictureMarkerSymbol);
}
else
{
resetPictureMarkerSymbol();
resetImage();
if (!m_simpleMarkerSymbol)
m_simpleMarkerSymbol = new Esri::ArcGISRuntime::SimpleMarkerSymbol();
m_simpleMarkerSymbol->setSize(m_markerSize.value() * m_scale.value());
m_simpleMarkerSymbol->setStyle(esriSMSS);
m_simpleMarkerSymbol->setAngle(m_angle.value());
m_simpleMarkerSymbol->setOffsetX(m_externalOffset.value().x());
m_simpleMarkerSymbol->setOffsetY(m_externalOffset.value().y());
m_simpleMarkerSymbol->setColor(m_markerColor.value());
m_graphic->setSymbol(m_simpleMarkerSymbol);
}
TRACE_LOG(m_logger) << LOGFUNCTION << " END, debugInfo='" << m_debugInfo << "'"
<< " filePath = '" << filePath << "'"
<< " m_image->size() = " << m_image.size()
<< " m_imageChanged = " << m_imageChanged
<< " m_currentSize = " << m_currentSize
<< " m_imageDefaultSize = " << m_imageDefaultSize.value()
<< " m_imageDefaultSize.changed() = " << m_imageDefaultSize.changed();
return true;
}
} // namespace SituationMap
@@ -0,0 +1,153 @@
/**
* @RDE_HEADER@
* GraphicalObjectPictureMarker
* $Id$
* $HeadURL$
* $Author$
*/
#pragma once
// Own
#include "abstract_graphical_object.h"
#include <Map/text_style.h>
#include <Common/situation_map_logging.h>
// Esri
#include <SymbolTypes.h>
#include <DistanceCompositeSceneSymbol.h>
// Qt
#include <QImage>
// forward:
namespace Esri
{
namespace ArcGISRuntime
{
class Graphic;
class GraphicsOverlay;
class PictureMarkerSymbol;
class SimpleMarkerSymbol;
}
}
class QTimer;
//----------------------------------------------------------------------------
namespace SituationMap
{
class SITUATIONMAP_EXPORT GraphicalObjectPictureMarker : public AbstractGraphicalObject
{
using BaseClass = AbstractGraphicalObject;
public:
GraphicalObjectPictureMarker(const Esri::ArcGISRuntime::GeoView *geoView
, Esri::ArcGISRuntime::GraphicsOverlay *graphicsLayer
, const QString &debugInfo
, const UniqueMapId &uniqueMapId);
~GraphicalObjectPictureMarker();
// Data access:
const QImage &image() const { return m_image; }
QSize imageDefaultSize() const { return m_imageDefaultSize.value(); }
void setImage(const QImage &image, const QSize &defaultSize = QSize());
void setPictureMarkerSymbol(Esri::ArcGISRuntime::PictureMarkerSymbol *pms, QSize defaultSize);
virtual MarkerSymbolType markerSymbolType();
virtual int markerSymbolSize();
virtual void setMarkerSymbol(MarkerSymbolType markerSymbolType,
int size,
const QColor &color = QColor());
virtual QSize currentSize() const;
// Offset (x: to right ; y: to north)
virtual int xOffset() const;
virtual void setXOffset(int xOffset);
virtual int yOffset() const;
virtual void setYOffset(int yOffset);
// rotation / angle
virtual float rotationAngle();
virtual void setRotationAngle(float angle);
protected:
// Internal/Admin
bool create() override;
bool changed() override
{
return BaseClass::changed()
|| m_markerSymbolType.changed()
|| m_markerSize.changed()
|| m_markerColor.changed()
|| m_angle.changed()
|| m_markerHotSpotPercent.changed()
|| m_externalOffset.changed()
|| m_imageChanged
;
}
void resetChanged() override
{
BaseClass::resetChanged();
m_markerSymbolType.reset();
m_markerSize.reset();
m_markerColor.reset();
m_angle.reset();
m_markerHotSpotPercent.reset();
m_externalOffset.reset();
m_imageChanged = false;
m_imageDefaultSize.reset();
}
bool updateViewImpl() override;
void resetImage();
void resetPictureMarkerSymbol();
void resetSimpleMarkerSymbol();
bool reCreateSymbol(const QString &filePath,
const Esri::ArcGISRuntime::SimpleMarkerSymbolStyle esriSMSS);
// used for image:
QImage m_image;
SimpleValue<QSize> m_imageDefaultSize;
Esri::ArcGISRuntime::PictureMarkerSymbol *m_pictureMarkerSymbol = nullptr;
bool m_imageChanged = true;
bool m_isOwnPms = true;
// used marker:
Esri::ArcGISRuntime::SimpleMarkerSymbol *m_simpleMarkerSymbol = nullptr;
QTimer *m_workaorundTimer = nullptr; // for re-new of Esri::ArcGISRuntime::PictureMarkerSymbol
QSize m_currentSize;
int m_scaleCounter4Moduletest = 0;
SimpleValue<MarkerSymbolType> m_markerSymbolType = MarkerSymbolType::Undefined;
SimpleValue<int> m_markerSize = 10;
SimpleValue<QColor> m_markerColor = QColor(Qt::red);
SimpleValue<float> m_angle = 0; ///
SimpleValue<QPointF> m_markerHotSpotPercent; ///< Store marker-specific offset.
SimpleValue<QPoint> m_externalOffset; ///< Stores external offset.
private:
LOGGER_T m_logger; ///< Interface of the Logging-Facility
};
} // namespace SituationMap
@@ -0,0 +1,170 @@
/**
* @RDE_HEADER@
* GraphicalObjectRange
* $Id$
* $HeadURL$
* $Author$
*/
// Own
#include "graphical_object_range.h"
#include <Map/situation_map_utils.h> // operator<<
// ESRI
#include <GraphicsOverlay.h>
#include <PolygonBuilder.h>
#include <MultipartBuilder.h>
#include <ImmutablePartCollection.h>
#include <Graphic.h>
#include <ImmutablePart.h>
#include <PartCollection.h>
#include <Point.h>
#include <Polygon.h>
#include <Part.h>
#include <SpatialReference.h>
// Qt
namespace SituationMap
{
GraphicalObjectRange::GraphicalObjectRange(const Esri::ArcGISRuntime::GeoView *geoView
, Esri::ArcGISRuntime::GraphicsOverlay *graphicsLayer
, const QString &debugInfo
, const UniqueMapId &uniqueMapId)
: BaseClass(geoView, graphicsLayer, debugInfo, uniqueMapId)
, m_logger(getLogger("GraphicalObjectRange"))
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START, debugInfo='" << m_debugInfo << "'";
TRACE_LOG(m_logger) << LOGFUNCTION << " END, debugInfo='" << m_debugInfo << "'";
}
GraphicalObjectRange::~GraphicalObjectRange()
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START, debugInfo='" << m_debugInfo << "'";
TRACE_LOG(m_logger) << LOGFUNCTION << " END, debugInfo='" << m_debugInfo << "'";
}
int GraphicalObjectRange::range() const
{
return m_range.value();
}
float GraphicalObjectRange::angle() const
{
return m_angleDegree.value();
}
void GraphicalObjectRange::setRange(int range, float angleDegree)
{
m_angleDegree = angleDegree;
m_range = range;
}
bool GraphicalObjectRange::updateViewImpl()
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START, debugInfo='" << m_debugInfo << "'";
EllipseParameters ellipsePara;
ellipsePara.setLengthX(m_range.value());
ellipsePara.setLengthY(m_range.value());
ellipsePara.setDirectionDegree(m_angleDegree.value()) ;
ellipsePara.setDirectionDegree((m_angleDegree.value() * -1) + 90);
ellipsePara.setMaxSegmentLength(10);
ellipsePara.setMaxPointCount(30); // limit to 30 to reduce the number of vertices. If to high, keep performance impact to 3D in mind!!!
this->setEllipseParameters(ellipsePara);
bool success = BaseClass::updateViewImpl();
TRACE_LOG(m_logger) << LOGFUNCTION << " END, debugInfo='" << m_debugInfo << "'"
<< " drawOrder = " << m_graphic->zIndex()
<< " success = " << success;
return success;
}
bool GraphicalObjectRange::createEllipse(Esri::ArcGISRuntime::Polygon &ellipse)
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START, debugInfo='" << m_debugInfo << "'"
<< " range=" << m_range
<< " angle=" << m_angleDegree;
bool success = BaseClass::createEllipse(ellipse);
if (success &&
!ellipse.isEmpty() &&
!ellipse.parts().isEmpty() &&
!ellipse.parts().part(0).isEmpty())
{
const Point3D &center = this->origin();
// 'modify' ellipe (by copying, adding and re-assigning):
// part 0 - ellipse
// we have to copy the point since the ellipse does not contain the z value anymore :-(
Esri::ArcGISRuntime::Part partCircle(ellipse.spatialReference());
const Esri::ArcGISRuntime::ImmutablePart &im = ellipse.parts().part(0);
for (int i = 0; i < im.pointCount(); ++i)
{
const Esri::ArcGISRuntime::Point &p = im.point(i);
partCircle.addPoint(Esri::ArcGISRuntime::Point(p.x(),
p.y(),
center.z() // p.z()
));
}
// part 1 - line to center
Esri::ArcGISRuntime::Part partLine(ellipse.spatialReference());
partLine.addPoint(im.startPoint().x(),
im.startPoint().y(),
center.z());
partLine.addPoint(center.x(),
center.y(),
center.z());
// a polyGON requiree to have at least 3 points:
partLine.addPoint(center.x(),
center.y(),
center.z()+0.01);
// combine them to a PartCollection:
Esri::ArcGISRuntime::PartCollection pc(ellipse.spatialReference());
pc.addPart(&partCircle);
pc.addPart(&partLine);
Esri::ArcGISRuntime::PolygonBuilder builder(ellipse.spatialReference());
builder.setParts(&pc);
ellipse = builder.toPolygon();
success = true;
}
else
ERROR_LOG(m_logger) << LOGFUNCTION << " debugInfo='" << m_debugInfo << "'";
return success;
}
//-----------------------------------------------------------------------------
// output operator:
//-----------------------------------------------------------------------------
std::ostream &operator<<(std::ostream &stream,
const GraphicalObjectRange &value)
{
stream << value.toString();
return stream;
}
} // namespace SituationMap
@@ -0,0 +1,87 @@
/**
* @RDE_HEADER@
* GraphicalObjectRange
* $Id$
* $HeadURL$
* $Author$
*/
#pragma once
// Own
#include "graphical_object_ellipse.h"
// Esri
// Qt
//----------------------------------------------------------------------------
namespace SituationMap
{
class SITUATIONMAP_EXPORT GraphicalObjectRange : public GraphicalObjectEllipse
{
using BaseClass = GraphicalObjectEllipse;
public:
GraphicalObjectRange(const Esri::ArcGISRuntime::GeoView *geoView
, Esri::ArcGISRuntime::GraphicsOverlay *graphicsLayer
, const QString &debugInfo
, const UniqueMapId &uniqueMapId);
~GraphicalObjectRange();
int range() const;
float angle() const;
void setRange(int range, float angleDegree);
protected:
// Internal/Admin
// bool create() override;
bool changed() override
{
return BaseClass::changed()
|| m_angleDegree.changed()
|| m_range.changed();
}
void resetChanged() override
{
BaseClass::resetChanged();
m_angleDegree.reset();
m_range.reset();
}
bool updateViewImpl() override;
bool createEllipse(Esri::ArcGISRuntime::Polygon &ellipse) override;
private:
SimpleValue<float> m_angleDegree = 0;
SimpleValue<int> m_range = 0;
LOGGER_T m_logger; ///< Interface of the Logging-Facility
};
//-----------------------------------------------------------------------------
// output operator:
//-----------------------------------------------------------------------------
std::ostream &operator<< (std::ostream &stream,
const GraphicalObjectRange &value);
} // namespace SituationMap
@@ -0,0 +1,144 @@
/**
* @RDE_HEADER@
* GraphicalObjectRendererAttributes
* $Id$
* $HeadURL$
* $Author$
*/
// Own
#include "graphical_object_renderer_attributes.h"
#include <Map/situation_map_utils.h> // operator<<
#include <MathUtils/simple_helper.h>
// ESRI
#include <arcgisversion.h> // This file is created by RME, not ESRI
#include <GraphicsOverlay.h>
#include <ModelSceneSymbol.h>
// Qt
#include <QPainter>
#include <QFile>
#include <Graphic.h>
#include <SpatialReference.h>
#include <AttributeListModel.h>
#include <Point.h>
namespace SituationMap
{
GraphicalObjectRendererAttributes::GraphicalObjectRendererAttributes(const Esri::ArcGISRuntime::GeoView *geoView
, Esri::ArcGISRuntime::GraphicsOverlay *graphicsLayer
, const QString &debugInfo
, const UniqueMapId &uniqueMapId)
: BaseClass(geoView, graphicsLayer, debugInfo, uniqueMapId)
, m_logger(getLogger("GraphicalObjectRendererAttributes"))
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START, debugInfo='" << m_debugInfo << "'";
TRACE_LOG(m_logger) << LOGFUNCTION << " END, debugInfo='" << m_debugInfo << "'";
}
GraphicalObjectRendererAttributes::~GraphicalObjectRendererAttributes()
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START, debugInfo='" << m_debugInfo << "'";
TRACE_LOG(m_logger) << LOGFUNCTION << " END, debugInfo='" << m_debugInfo << "'";
}
void GraphicalObjectRendererAttributes::setAttributeMap(const QVariantMap &attribMap)
{
m_attributeMap = attribMap;
}
QVariantMap GraphicalObjectRendererAttributes::attributeMap() const
{
return m_attributeMap.value();
}
bool GraphicalObjectRendererAttributes::create()
{
return BaseClass::create();
}
bool GraphicalObjectRendererAttributes::updateViewImpl()
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START, debugInfo='" << m_debugInfo << "'"
<< " origin =" << this->origin() // .x() << " , " << this->origin().y()
<< " visibility=" << m_visibility
<< " pickable=" << m_pickable
<< " pickable.changed=" << m_pickable.changed()
<< " selected=" << m_selected
<< " m_attributeMap = " << m_attributeMap.value().size()
<< " m_drawOrder = " << m_drawOrder;
// some checks:
if (!isSinglePoint())
{
ERROR_LOG(m_logger) << LOGFUNCTION
<< " debugInfo='" << m_debugInfo << "'"
<< " incorrect number of positions"
<< " (" << this->positions().count() << ")";
return false;
}
bool success = create();
if (!success)
{
ERROR_LOG(m_logger) << LOGFUNCTION << " debugInfo='" << m_debugInfo << "'"
<< " create failed";
return false;
}
const Point3D &origin = this->origin();
m_graphic->setGeometry(Esri::ArcGISRuntime::Point(origin.x(),
origin.y(),
origin.z(),
spatialReference()));
if (m_attributeMap.changed())
{
QVariantMap cur = m_graphic->attributes()->attributesMap();
if (m_logger.isDebugEnabled())
qCritical() << " debugInfo='" << m_debugInfo << "'" << ", QVariantMap before unite " << cur;
// Qt6: QMap::unite() removed; insert only the keys not already present (unite semantics).
const QVariantMap otherAttrs = m_attributeMap.value();
for (auto it = otherAttrs.constBegin(); it != otherAttrs.constEnd(); ++it)
if (!cur.contains(it.key()))
cur.insert(it.key(), it.value());
if (m_logger.isDebugEnabled())
qCritical() << " debugInfo='" << m_debugInfo << "'" << ", QVariantMap after unite " << cur;
m_graphic->attributes()->setAttributesMap(cur);
}
// keep anchor like Esri::ArcGISRuntime::SceneSymbolAnchorPosition::Bottom in mind.
// assigned during setup the Renderer (LayerFactory, AdapterDds...)
success = BaseClass::updateViewImpl();
if (!success)
{
ERROR_LOG(m_logger) << LOGFUNCTION << " debugInfo='" << m_debugInfo << "'"
<< " updateView failed";
return false;
}
success = addUpdateGraphic();
if (!success)
{
ERROR_LOG(m_logger) << LOGFUNCTION << " debugInfo='" << m_debugInfo << "'"
<< " updateView failed";
return false;
}
TRACE_LOG(m_logger) << LOGFUNCTION << " END, debugInfo='" << m_debugInfo << "'"
<< " success=" << success
<< " m_drawOrder = " << m_drawOrder
<< " m_graphic->drawOrder = " << m_graphic->zIndex();
return success;
}
} // namespace SituationMap
@@ -0,0 +1,102 @@
/**
* @RDE_HEADER@
* GraphicalObjectRendererAttributes
* $Id$
* $HeadURL$
* $Author$
*/
#pragma once
// Own
#include "abstract_graphical_object.h"
#include <Map/text_style.h>
#include <Common/situation_map_logging.h>
// Esri
#include <SymbolTypes.h>
// Qt
#include <QImage>
#include <QVariantMap>
// forward:
namespace Esri
{
namespace ArcGISRuntime
{
class Graphic;
class GraphicsOverlay;
class ModelSceneSymbol;
}
}
//----------------------------------------------------------------------------
namespace SituationMap
{
class SITUATIONMAP_EXPORT GraphicalObjectRendererAttributes : public AbstractGraphicalObject
{
using BaseClass = AbstractGraphicalObject;
public:
GraphicalObjectRendererAttributes(const Esri::ArcGISRuntime::GeoView *geoView
, Esri::ArcGISRuntime::GraphicsOverlay *graphicsLayer
, const QString &debugInfo
, const UniqueMapId &uniqueMapId);
~GraphicalObjectRendererAttributes();
// Data access:
// to be cont.
void setAttributeMap(const QVariantMap &attribMap);
QVariantMap attributeMap() const;
protected:
// Internal/Admin
bool create() override;
bool changed() override
{
return BaseClass::changed()
|| m_attributeMap.changed()
;
}
void resetChanged() override
{
BaseClass::resetChanged();
m_attributeMap.reset();
}
bool updateViewImpl() override;
// no ModelSceneSymbol since Renderer-based
SimpleValue<QVariantMap> m_attributeMap;
private:
LOGGER_T m_logger; ///< Interface of the Logging-Facility
// Forbid some overloaded methods without effects of this object;
PositionCont positions() const override
{
return PositionCont();
}
void setPositions(const PositionCont &posCont) override
{
Q_UNUSED(posCont);
Q_ASSERT(false);
}
};
} // namespace SituationMap
@@ -0,0 +1,209 @@
/**
* @RDE_HEADER@
* GraphicalObjectSceneMarker
* $Id$
* $HeadURL$
* $Author$
*/
// Own
#include "graphical_object_scene_marker.h"
#include <Map/situation_map_utils.h> // operator<<
#include <MathUtils/simple_helper.h>
#include <LtsCoordTrans/lts_coord_trans.h>
// ESRI
#include <arcgisversion.h> // This file is created by RME, not ESRI
#include <GraphicsOverlay.h>
#include <SimpleMarkerSceneSymbol.h>
// Qt
#include <QPainter>
#include <QTimer>
#include <Graphic.h>
#include <MapTypes.h>
#include <Point.h>
#include <SpatialReference.h>
namespace SituationMap
{
GraphicalObjectSceneMarker::GraphicalObjectSceneMarker(SceneMarkerType type
, const Esri::ArcGISRuntime::GeoView *geoView
, Esri::ArcGISRuntime::GraphicsOverlay *graphicsLayer
, const QString &debugInfo
, const UniqueMapId &uniqueMapId)
: BaseClass(geoView, graphicsLayer, debugInfo, uniqueMapId)
, m_type(type)
, m_logger(getLogger("GraphicalObjectSceneMarker"))
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START, debugInfo='" << m_debugInfo << "'";
TRACE_LOG(m_logger) << LOGFUNCTION << " END, debugInfo='" << m_debugInfo << "'";
}
GraphicalObjectSceneMarker::~GraphicalObjectSceneMarker()
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START, debugInfo='" << m_debugInfo << "'";
delete m_simpleMarkerSceneSymbol;
m_simpleMarkerSceneSymbol = nullptr;
TRACE_LOG(m_logger) << LOGFUNCTION << " END, debugInfo='" << m_debugInfo << "'";
}
void GraphicalObjectSceneMarker::setDiameter(double diameter)
{
m_diameter = diameter;
}
double GraphicalObjectSceneMarker::diameter() const
{
return m_diameter.value();
}
bool GraphicalObjectSceneMarker::create()
{
return BaseClass::create();
}
bool GraphicalObjectSceneMarker::updateViewImpl()
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START, debugInfo='" << m_debugInfo << "'"
<< " origin =" << this->origin() // .x() << " , " << this->origin().y()
<< " visibility=" << m_visibility
<< " pickable=" << m_pickable
<< " pickable.changed=" << m_pickable.changed()
<< " selected=" << m_selected
<< " m_diameter = " << m_diameter.value()
<< " m_heading = " << m_heading.value()
<< " m_pitch = " << m_pitch.value()
<< " m_roll = " << m_roll.value()
<< " m_drawOrder = " << m_drawOrder
<< " m_lineStyle = " << m_lineStyle.value()
<< " m_fillStyle = " << m_fillStyle.value()
<< " fillColor = " << m_fillStyle.value().fillColor()
<< " m_scale = " << m_scale.value();
if (m_graphicsLayer->renderingMode() != Esri::ArcGISRuntime::GraphicsRenderingMode::Dynamic)
for (int i=0; i<10; ++i)
ERROR_LOG(m_logger) << " RenderingMode::Dynamic required!!! , debugInfo='" << m_debugInfo << "'";
// some checks:
if (!isSinglePoint())
{
ERROR_LOG(m_logger) << LOGFUNCTION
<< " debugInfo='" << m_debugInfo << "'"
<< " incorrect number of positions"
<< " (" << this->positions().count() << ")";
return false;
}
bool success = create();
if (!success)
{
ERROR_LOG(m_logger) << LOGFUNCTION << " debugInfo='" << m_debugInfo << "'"
<< " create failed";
return false;
}
const double radiusHeight = m_diameter.value()/2.0;
Point3D origin = this->origin();
// Try to set AnchorPosition::Top, to let the cone rotate around top/tip.
// Using a cone, the anchor point does not work as expected, we have to move
if (m_type == SceneMarkerType::CONE)
{
//
// It´s a SCENE Marker. So we are per definition in 3D and origin is in degree.
//
// heading is in degree:m_heading.value()
// offset as vector:
QPointF offsetMeter(0, radiusHeight/2.0);
const int rotAngleDegree = (static_cast<int>(m_heading.value())-90)%360;
DEBUG_LOG(m_logger) << " offsetMeter = " << offsetMeter << ", m_heading = " << m_heading.value() << ", rotAngleDegree = " << rotAngleDegree;
MathUtils::rotatePoint(offsetMeter, QPointF(), rotAngleDegree);
// new temporary origin...
// -> rad
origin *= LtsCoordTrans::deg2rad();
LtsCoordTrans::UtmCoordinate newOrigin = LtsCoordTrans::UtmCoordinate::fromGeographic(origin.x(), origin.y());
DEBUG_LOG(m_logger) << " newOrigin = " << newOrigin.mgrs();
// add rotated offset to temporary origin:
const QPointF origin2D = newOrigin.geographic(offsetMeter) * LtsCoordTrans::rad2deg();
// -> deg
// write back; z-value stays untouched:
origin.rx() = origin2D.x();
origin.ry() = origin2D.y();
}
const Esri::ArcGISRuntime::Point originGeometry(origin.x(),
origin.y(),
origin.z(),
spatialReference());
m_graphic->setGeometry(originGeometry);
if (!m_simpleMarkerSceneSymbol)
{
switch (m_type)
{
case SceneMarkerType::CONE: // Kegel
m_simpleMarkerSceneSymbol =
Esri::ArcGISRuntime::SimpleMarkerSceneSymbol::cone(
m_fillStyle.value().fillColor(),
radiusHeight, radiusHeight, // V100.8: cone: 'diameter' is interpreted as radius
Esri::ArcGISRuntime::SceneSymbolAnchorPosition::Center); // V100.8: cone: Top does not work as aspected - grrr
break;
case SceneMarkerType::SPHERE: // Kugel
m_simpleMarkerSceneSymbol =
Esri::ArcGISRuntime::SimpleMarkerSceneSymbol::sphere(
m_fillStyle.value().fillColor(),
radiusHeight*2.0,
Esri::ArcGISRuntime::SceneSymbolAnchorPosition::Center);
break;
} // switch
}
m_simpleMarkerSceneSymbol->setColor(m_fillStyle.value().fillColor());
if (m_type == SceneMarkerType::CONE)
{
m_simpleMarkerSceneSymbol->setWidth(radiusHeight);
m_simpleMarkerSceneSymbol->setHeight(radiusHeight);
m_simpleMarkerSceneSymbol->setDepth(radiusHeight);
} else {
m_simpleMarkerSceneSymbol->setWidth(m_diameter.value());
m_simpleMarkerSceneSymbol->setHeight(m_diameter.value());
m_simpleMarkerSceneSymbol->setDepth(m_diameter.value());
}
m_simpleMarkerSceneSymbol->setHeading(m_heading.value());
m_simpleMarkerSceneSymbol->setPitch(m_pitch.value());
m_simpleMarkerSceneSymbol->setRoll(m_roll.value());
m_graphic->setSymbol(m_simpleMarkerSceneSymbol);
success = BaseClass::updateViewImpl();
if (!success)
{
ERROR_LOG(m_logger) << LOGFUNCTION << " debugInfo='" << m_debugInfo << "'"
<< " updateView failed";
return false;
}
success = addUpdateGraphic();
if (!success)
{
ERROR_LOG(m_logger) << LOGFUNCTION << " debugInfo='" << m_debugInfo << "'"
<< " updateView failed";
return false;
}
TRACE_LOG(m_logger) << LOGFUNCTION << " END, debugInfo='" << m_debugInfo << "'"
<< " success=" << success
<< " m_drawOrder = " << m_drawOrder
<< " m_graphic->drawOrder = " << m_graphic->zIndex();
return success;
}
} // namespace SituationMap
@@ -0,0 +1,137 @@
/**
* @RDE_HEADER@
* GraphicalObjectSceneMarker
* $Id$
* $HeadURL$
* $Author$
*/
#pragma once
// Own
#include "abstract_graphical_object.h"
#include <Map/text_style.h>
#include <Common/situation_map_logging.h>
// Esri
#include <SymbolTypes.h>
// Qt
#include <QImage>
// forward:
namespace Esri
{
namespace ArcGISRuntime
{
class Graphic;
class GraphicsOverlay;
class SimpleMarkerSceneSymbol;
}
}
class QTimer;
//----------------------------------------------------------------------------
namespace SituationMap
{
//
//
//
// !!! Layer with RenderingMode::Dynamic required !!!
// !!! Layer with RenderingMode::Dynamic required !!!
// !!! Layer with RenderingMode::Dynamic required !!!
//
//
//
enum class SceneMarkerType {CONE, SPHERE};
class SITUATIONMAP_EXPORT GraphicalObjectSceneMarker : public AbstractGraphicalObject
{
using BaseClass = AbstractGraphicalObject;
public:
GraphicalObjectSceneMarker(SceneMarkerType type
, const Esri::ArcGISRuntime::GeoView *geoView
, Esri::ArcGISRuntime::GraphicsOverlay *graphicsLayer
, const QString &debugInfo
, const UniqueMapId &uniqueMapId);
~GraphicalObjectSceneMarker();
// Data access:
// to be cont. (type is sphere, to support cube, cylinder etc)
void setDiameter(double diameter);
double diameter() const;
double heading() const { return m_heading.value(); }
void setHeading(double headingDegree) { m_heading = headingDegree; }
double pitch() const { return m_pitch.value(); }
void setPitch(double pitchDegree) { m_pitch = pitchDegree; }
double roll() const { return m_roll.value(); }
void setRoll(double rollDegree) { m_roll = rollDegree; }
protected:
// Internal/Admin
bool create() override;
bool changed() override
{
return BaseClass::changed()
|| m_diameter.changed()
|| m_heading.changed()
|| m_pitch.changed()
|| m_roll.changed()
;
}
void resetChanged() override
{
BaseClass::resetChanged();
m_diameter.reset();
m_heading.reset();
m_pitch.reset();
m_roll.reset();
}
bool updateViewImpl() override;
// used marker:
Esri::ArcGISRuntime::SimpleMarkerSceneSymbol *m_simpleMarkerSceneSymbol{nullptr};
SceneMarkerType m_type{SceneMarkerType::SPHERE};
SimpleValue<double> m_diameter{25};
SimpleValue<double> m_heading{0}; // degree
SimpleValue<double> m_pitch{0}; // degree
SimpleValue<double> m_roll{0}; // degree
private:
LOGGER_T m_logger; ///< Interface of the Logging-Facility
// Forbid some overloaded methods without effects of this object;
PositionCont positions() const override
{
return PositionCont();
}
void setPositions(const PositionCont &posCont) override
{
Q_UNUSED(posCont);
Q_ASSERT(false);
}
};
} // namespace SituationMap
@@ -0,0 +1,344 @@
/**
* @RDE_HEADER@
* GraphicalObjectText
* $Id$
* $HeadURL$
* $Author$
*/
// Own
#include "graphical_object_text.h"
#include <Map/situation_map_utils.h> // operator<<
// ESRI
#include <GraphicsOverlay.h>
#include <TextSymbol.h>
#include <PictureMarkerSymbol.h>
// Qt
#include <QString>
#include <iostream>
#include <algorithm>
#include <Graphic.h>
#include <SpatialReference.h>
#include <Point.h>
#include <SymbolTypes.h>
namespace SituationMap
{
GraphicalObjectText::GraphicalObjectText(const Esri::ArcGISRuntime::GeoView *geoView
, Esri::ArcGISRuntime::GraphicsOverlay *graphicsLayer
, const QString &debugInfo
, const UniqueMapId &uniqueMapId)
: BaseClass(geoView, graphicsLayer, debugInfo, uniqueMapId)
, m_textSymbol(nullptr)
, m_logger(getLogger("GraphicalObjectText"))
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START, debugInfo='" << m_debugInfo << "'";
TRACE_LOG(m_logger) << LOGFUNCTION << " END, debugInfo='" << m_debugInfo << "'";
}
GraphicalObjectText::~GraphicalObjectText()
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START, debugInfo='" << m_debugInfo << "'"
<< " text='" << m_text << "'";
delete m_textSymbol;
m_textSymbol = nullptr;
TRACE_LOG(m_logger) << LOGFUNCTION << " END, debugInfo='" << m_debugInfo << "'"
<< " text='" << m_text << "'";
}
QString GraphicalObjectText::toString() const
{
QString str;
// str.append( BaseClass::toString() );
if (!m_debugInfo.isEmpty())
str.append(QStringLiteral("debugInfo=%1").arg(m_debugInfo));
if (m_graphicsLayer)
str.append(QStringLiteral(" layer='%1'").arg(m_graphicsLayer->objectName()));
if (m_graphic)
str.append(QStringLiteral(" zIndex='%1'").arg(m_graphic->zIndex()));
std::ostringstream stream;
stream << this->origin();
str.append(QLatin1String(stream.str().c_str()));
if (!m_text.value().isEmpty())
str.append(QStringLiteral("text=%1").arg(m_text.value()));
return str;
}
QString GraphicalObjectText::text() const
{
return m_text.value();
}
void GraphicalObjectText::setText(const QString &text)
{
m_text = text;
}
TextStyle GraphicalObjectText::textStyle() const
{
return m_textStyle.value();
}
TextStyle &GraphicalObjectText::rTextStyle()
{
return m_textStyle.refValue();
}
void GraphicalObjectText::setTextStyle(const TextStyle &textStyle)
{
m_textStyle = textStyle;
}
float GraphicalObjectText::xOffset() const
{
return m_offset.value().x();
}
void GraphicalObjectText::setXOffset(float xOffset)
{
QPointF temp = m_offset.value();
temp.rx() = xOffset;
m_offset = temp;
}
float GraphicalObjectText::yOffset() const
{
return m_offset.value().y();
}
void GraphicalObjectText::setYOffset(float yOffset)
{
QPointF temp = m_offset.value();
temp.ry() = yOffset;
m_offset = temp;
}
bool GraphicalObjectText::create()
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START, debugInfo='" << m_debugInfo << "'"
<< " text='" << m_text << "'"
<< " origin =" << this->origin() // .x() << " , " << this->origin().y()
<< " visibility=" << m_visibility;
bool success = true;
// some checks:
if (!m_graphicsLayer)
{
ERROR_LOG(m_logger) << LOGFUNCTION << " debugInfo='" << m_debugInfo << "'"
<< " no graphicsLayer";
return false;
}
BaseClass::create();
if (!m_textSymbol)
m_textSymbol = new Esri::ArcGISRuntime::TextSymbol();
TRACE_LOG(m_logger) << LOGFUNCTION << " END, debugInfo='" << m_debugInfo << "'"
<< " text='" << m_text << "'"
<< " success=" << success
<< " drawOrder = " << m_graphic->zIndex();
return success;
}
bool GraphicalObjectText::updateViewImpl()
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START, debugInfo='" << m_debugInfo << "'"
<< " text='" << m_text << "'"
<< " origin =" << this->origin() // .x() << " , " << this->origin().y()
<< " visibility=" << m_visibility
<< " m_textStyle=" << m_textStyle
<< " offset=" << m_offset;
// some checks:
if (!this->isSinglePoint())
{
ERROR_LOG(m_logger) << LOGFUNCTION << " debugInfo='" << m_debugInfo << "'"
<< " incorrect number of positions"
<< " (" << this->positions().count() << ")";
return false;
}
bool success = true;
if (m_visibility.value())
{
success = create(); // create only if visible
if (!success)
{
ERROR_LOG(m_logger) << LOGFUNCTION << " debugInfo='" << m_debugInfo << "'"
<< " create failed";
return false;
}
if (! BaseClass::updateViewImpl())
{
ERROR_LOG(m_logger) << LOGFUNCTION << " debugInfo='" << m_debugInfo << "'"
<< " updateViewImpl failed";
}
// FATAL_LOG(m_logger) << LOGFUNCTION << " debugInfo='" << m_debugInfo << "'"
// << " text='" << m_text << "'"
// << " changed1=" << m_text.changed()
// << " changed2="<< m_textStyle.changed();
bool assignTextSymbol = false;
// || m_visibility.changed()) -> szenario: create invisible object and make it visible
if (m_text.changed() || m_visibility.changed())
{
m_textSymbol->setText(m_text.value());
assignTextSymbol = true;
}
// TextStyle to TextSymbol@ESRI :
if (m_textStyle.changed()
|| m_scale.changed()
|| m_visibility.changed() // -> szenario: create invisible object and make it visible
)
{
const TextStyle &textStyle = m_textStyle.value();
m_textSymbol->setColor(textStyle.textColor());
// High values can lead to coredump with 'SymbolDrawHelper::create_line_image FAILED, SkBitmap is NULL or empty' -> limit
m_textSymbol->setSize(std::min(500.0f, textStyle.size() * m_scale.value()));
m_textSymbol->setAngle(textStyle.angle());
m_textSymbol->setFontFamily(textStyle.fontFamily());
m_textSymbol->setFontWeight(textStyle.bold() ? Esri::ArcGISRuntime::FontWeight::Bold : Esri::ArcGISRuntime::FontWeight::Normal);
m_textSymbol->setFontStyle(textStyle.italic() ? Esri::ArcGISRuntime::FontStyle::Italic : Esri::ArcGISRuntime::FontStyle::Normal);
Esri::ArcGISRuntime::FontDecoration fd = Esri::ArcGISRuntime::FontDecoration::None;
if (textStyle.underline())
fd = Esri::ArcGISRuntime::FontDecoration::Underline;
if (textStyle.strikeThrough())
fd = Esri::ArcGISRuntime::FontDecoration::LineThrough;
m_textSymbol->setFontDecoration(fd);
float outlineWidth = 0;
if (textStyle.textOutlineWidth() > 0)
outlineWidth = textStyle.textOutlineWidth() * m_scale.value();
if (m_textSymbol->size() <= 15) // small size -> outline reduces readability :-(
outlineWidth = 0.0;
m_textSymbol->setHaloWidth(outlineWidth);
if (textStyle.textOutlineColor().isValid())
m_textSymbol->setHaloColor(textStyle.textOutlineColor());
// qWarning() << " haloWidth = " << m_textSymbol->haloWidth();
// m_textSymbol->setHaloColor(Qt::white);
// m_textSymbol->setHaloWidth(outlineWidth);
// qWarning() << " fontSize " << textStyle.size() * m_scale.value()
// <<" (textStyle.size() " << textStyle.size()
// << " m_scale.value() " << m_scale.value() << ")";
// qWarning() << " outlineWidth " << outlineWidth
// <<" (textStyle.textOutlineWidth() " << textStyle.textOutlineWidth()
// << " m_scale.value() " << m_scale.value() << ")";
// if (textStyle.backgroundColor().isValid())
m_textSymbol->setBackgroundColor(textStyle.backgroundColor());
// m_textSymbol->setAntiAliased(textStyle.antiAliased());
m_textSymbol->setHorizontalAlignment(convert(textStyle.horizontalAlignment()));
m_textSymbol->setVerticalAlignment(convert(textStyle.verticalAlignment()));
assignTextSymbol = true;
// : TextStyle to TextSymbol@ESRI
}
// || m_visibility.changed()) -> szenario: create invisible object and make it visible
if (m_offset.changed() || m_visibility.changed())
{
m_textSymbol->setOffsetX(m_offset.value().x());
m_textSymbol->setOffsetY(m_offset.value().y());
assignTextSymbol = true;
}
if (assignTextSymbol)
m_graphic->setSymbol(m_textSymbol);
// check ChangedFlags:
// Object is created and text is invisble due to scale (meterPerPixel)
// map is zoomed in -> text should arise, but on m_visibility is changed:
if (m_visibility.changed() || m_positions.changed())
{
const Point3D &origin = this->origin();
m_graphic->setGeometry(Esri::ArcGISRuntime::Point(origin.x(),
origin.y(),
origin.z(),
spatialReference()));
success = addUpdateGraphic();
} // m_visibility.changed() || m_positions.changed()
}
else // if visible
{
BaseClass::updateViewImpl();
success = addUpdateGraphic();
}
if (m_logger.isTraceEnabled())
{
int drawOrder = -1;
if (m_graphic)
drawOrder = m_graphic->zIndex();
TRACE_LOG(m_logger) << LOGFUNCTION << " END, debugInfo='" << m_debugInfo << "'"
<< " text='" << m_text << "'"
<< " success=" << success
<< " drawOrder = " << drawOrder;
}
TRACE_LOG(m_logger) << LOGFUNCTION << " END, debugInfo='" << m_debugInfo << "'"
// << " fontFamily='" << m_textSymbol->fontFamily() << "'"
;
return success;
}
Esri::ArcGISRuntime::HorizontalAlignment GraphicalObjectText::convert(const HorizontalAlignment horizontalAlignment)
{
Esri::ArcGISRuntime::HorizontalAlignment esriAlignmenmt =
Esri::ArcGISRuntime::HorizontalAlignment::Left;
switch (horizontalAlignment)
{
case HorizontalAlignment::Left: esriAlignmenmt = Esri::ArcGISRuntime::HorizontalAlignment::Left; break;
case HorizontalAlignment::Center: esriAlignmenmt = Esri::ArcGISRuntime::HorizontalAlignment::Center; break;
case HorizontalAlignment::Right: esriAlignmenmt = Esri::ArcGISRuntime::HorizontalAlignment::Right; break;
case HorizontalAlignment::Justify: esriAlignmenmt = Esri::ArcGISRuntime::HorizontalAlignment::Justify; break;
} // switch
return esriAlignmenmt;
}
Esri::ArcGISRuntime::VerticalAlignment GraphicalObjectText::convert(const VerticalAlignment verticalAlignment)
{
Esri::ArcGISRuntime::VerticalAlignment esriAlignmenmt =
Esri::ArcGISRuntime::VerticalAlignment::Bottom;
switch (verticalAlignment)
{
case VerticalAlignment::Bottom: esriAlignmenmt = Esri::ArcGISRuntime::VerticalAlignment::Bottom; break;
case VerticalAlignment::Middle: esriAlignmenmt = Esri::ArcGISRuntime::VerticalAlignment::Middle; break;
case VerticalAlignment::Top: esriAlignmenmt = Esri::ArcGISRuntime::VerticalAlignment::Top; break;
case VerticalAlignment::BaseLine: esriAlignmenmt = Esri::ArcGISRuntime::VerticalAlignment::Baseline; break;
} // switch
return esriAlignmenmt;
}
} // namespace SituationMap
@@ -0,0 +1,125 @@
/**
* @RDE_HEADER@
* GraphicalObjectText
* $Id$
* $HeadURL$
* $Author$
*/
#pragma once
// Own
#include "abstract_graphical_object.h"
#include <Map/text_style.h>
#include <Map/situation_map_utils.h>
#include <Common/simple_value.h>
#include <Common/situation_map_logging.h>
// Esri
// Qt
// forward:
namespace Esri
{
namespace ArcGISRuntime
{
class Graphic;
class GraphicsOverlay;
class PictureMarkerSymbol;
class TextSymbol;
enum class HorizontalAlignment;
enum class VerticalAlignment;
}
}
//----------------------------------------------------------------------------
namespace SituationMap
{
class SITUATIONMAP_EXPORT GraphicalObjectText : public AbstractGraphicalObject
{
using BaseClass = AbstractGraphicalObject;
public:
GraphicalObjectText(const Esri::ArcGISRuntime::GeoView *geoView
, Esri::ArcGISRuntime::GraphicsOverlay *graphicsLayer
, const QString &debugInfo
, const UniqueMapId &uniqueMapId
);
~GraphicalObjectText();
QString toString() const override; // specialized
// Data access:
QString text() const;
void setText(const QString &text);
TextStyle textStyle() const;
TextStyle &rTextStyle();
void setTextStyle(const TextStyle &textStyle);
// Offset
virtual float xOffset() const;
virtual void setXOffset(float xOffset);
virtual float yOffset() const;
virtual void setYOffset(float yOffset);
static Esri::ArcGISRuntime::HorizontalAlignment convert(const HorizontalAlignment horizontalAlignment);
static Esri::ArcGISRuntime::VerticalAlignment convert(const VerticalAlignment verticalAlignment);
protected:
// Internal/Admin
bool create() override;
bool changed() override
{
return BaseClass::changed()
|| m_text.changed()
|| m_textStyle.changed()
|| m_offset.changed();
}
void resetChanged() override
{
BaseClass::resetChanged();
m_text.reset();
m_textStyle.reset();
m_offset.reset();
}
bool updateViewImpl() override;
Esri::ArcGISRuntime::TextSymbol *m_textSymbol = nullptr;
SimpleValue<QString> m_text; ///< to be displayed on map
SimpleValue<TextStyle> m_textStyle;
SimpleValue<QPointF> m_offset; ///< Offset (pixel).
private:
LOGGER_T m_logger; ///< Interface of the Logging-Facility
// Forbid some overloaded methods without effects of this object;
virtual PositionCont positions() const override
{
return PositionCont();
}
virtual void setPositions(const PositionCont &posCont) override
{
Q_UNUSED(posCont);
}
};
} // namespace SituationMap
@@ -0,0 +1,69 @@
/**
* @RDE_HEADER@
* StubGraphicalObject
* $Id$
* $HeadURL$
* $Author$
*/
#pragma once
// Own
#include "abstract_graphical_object.h"
#include <Map/situation_map_types.h>
// Esri
namespace SituationMap
{
/**
@class StubGraphicalObject stub_graphical_object.h
The class \c StubGraphicalObject is used as substitution for a graphical object. It does
nothing and the purpose is only to satisfy the interface of AbstractGraphicalObject.
@see AbstractGraphicalObject
*/
class StubGraphicalObject : public AbstractGraphicalObject
{
public:
explicit StubGraphicalObject()
: AbstractGraphicalObject(nullptr, nullptr, QString(), UniqueMapId())
{
}
~StubGraphicalObject() = default;
StubGraphicalObject(const StubGraphicalObject &other) = delete;
StubGraphicalObject &operator=(StubGraphicalObject &other) = delete;
protected:
bool changed() override
{
return false;
}
bool updateViewImpl() override
{
return true;
}
bool create() override
{
return true;
}
};
} // namespace SituationMap
@@ -0,0 +1,627 @@
/**
* @RDE_HEADER@
* TacticalAppearance
* $Id$
* $HeadURL$
* $Author$
*/
// Own
#include "tactical_appearance.h"
#include <MapImpl/map_impl.h>
#include <Symbology/symbol_dictionary.h>
#include <Symbology/sidc_builder_base.h>
#include <Symbology/sidc_codec.h>
#include <GraphicalObjects/graphical_object_picture_marker.h>
#include <Map/situation_map_utils.h> // operator<<
#include <Common/simple_value.h>
// ESRI
#include <Map.h>
#include <GraphicsOverlay.h>
#include <PolygonBuilder.h>
#include <PolylineBuilder.h>
#include <MultipointBuilder.h>
// Qt
#include <QElapsedTimer>
#include <Geometry.h>
#include <Graphic.h>
#include <GraphicListModel.h>
#include <PointCollection.h>
#include <AttributeListModel.h>
namespace SituationMap
{
class TacticalAppearance::Private
{
public:
Private() = default;
~Private() = default;
// ESRI data:
MapImpl *m_mapImpl = nullptr;
QString m_logicalLayerName;
Esri::ArcGISRuntime::GraphicsOverlay *m_graphicOverlayTactical = nullptr;
AdvancedSymbology::SymbolDictionary *m_dictionary = nullptr;
AdvancedSymbology::SymbolResultWatcher m_symbolResultWatcher;
// OWN data:
SimpleValue<QString> m_uniqueDesignation;
SimpleValue<SymbolData> m_symbol;
AdvancedSymbology::SymbolDataToRender m_symDataToRender;
GraphicalObjectPictureMarker *m_pictureMarker = nullptr;
}; // class TacticalAppearance::Private
//-----------------------------------------------------------------------------
TacticalAppearance::TacticalAppearance(MapImpl *mapImpl,
const QString &logicalLayerName,
const QString &debugInfo,
const UniqueMapId &uniqueMapId)
: BaseClass(mapImpl->getEsriGeoView(), nullptr, debugInfo, uniqueMapId),
m_logger(getLogger("TacticalAppearance")),
d(new Private)
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START, debugInfo='" << m_debugInfo << "'"
<< ", logicalLayerName='" << logicalLayerName << "'";
d->m_symDataToRender.sizeL = 100;
d->m_mapImpl = mapImpl;
d->m_logicalLayerName = logicalLayerName;
if (!m_graphicsLayer && d->m_mapImpl)
m_graphicsLayer = d->m_mapImpl->getGraphicsLayer(d->m_logicalLayerName);
if (!m_graphicsLayer)
{
ERROR_LOG(m_logger) << LOGFUNCTION << " debugInfo='" << m_debugInfo << "'"
<< " getGraphicsLayer failed";
}
if (d->m_mapImpl)
d->m_dictionary = &(d->m_mapImpl->symbolDictionary());
// lambda:
// m_symbolResultWatcher is canceled on destruction.
// So it`s safe that no signal will be fired afterwards.
// To avoid CLang warnings use m_symbolResultWatcher as context (3rd para), although it´s not intended.
// Better idea?
QObject::connect(&d->m_symbolResultWatcher, &AdvancedSymbology::SymbolResultWatcher::resultReady, &d->m_symbolResultWatcher, [this]()
{
DEBUG_LOG(m_logger) << LOGFUNCTION << " debugInfo='" << m_debugInfo << "'"
<< " resultReady...";
QSharedPointer<AdvancedSymbology::SymbolResult> symResult = d->m_symbolResultWatcher.symbolResult();
if (! symResult)
return; // should NEVER happen! (Which object should have triggered the signal???)
if (d->m_pictureMarker)
{
d->m_pictureMarker->setImage(symResult->symbolImage().image());
d->m_pictureMarker->updateView();
}
});
TRACE_LOG(m_logger) << LOGFUNCTION << " END, debugInfo='" << m_debugInfo << "'";
}
TacticalAppearance::~TacticalAppearance()
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START, debugInfo='" << m_debugInfo << "'";
// abort pending call to SymbolDictionary::findSymbol:
d->m_symbolResultWatcher.cancel();
delete d->m_pictureMarker;
d->m_pictureMarker = nullptr;
removeGraphicFromGraphicOverlayTactical();
delete d;
TRACE_LOG(m_logger) << LOGFUNCTION << " END, debugInfo='" << m_debugInfo << "'";
}
void TacticalAppearance::removeGraphicFromGraphicOverlayTactical()
{
if (m_logger.isTraceEnabled())
{
if (m_graphic)
{
Esri::ArcGISRuntime::GraphicsOverlay *gOverlay = m_graphic->graphicsOverlay();
if (gOverlay)
TRACE_LOG(m_logger) << LOGFUNCTION << " START debugInfo='" << m_debugInfo << "'" << " name = '" << gOverlay->overlayId() << "'";
}
}
if (m_graphic && d->m_graphicOverlayTactical && d->m_graphicOverlayTactical->graphics())
d->m_graphicOverlayTactical->graphics()->removeOne(m_graphic);
delete m_graphic;
m_graphic = nullptr;
}
bool TacticalAppearance::useDictionaryRenderMode(const AdvancedSymbology::GeometryType &geomType) const
{
bool usePictureMarker = isSinglePoint() && (AdvancedSymbology::GeometryType::Point == geomType || AdvancedSymbology::GeometryType::Undefined == geomType);
return !usePictureMarker || symbol().useAlwaysDictionaryRenderer;
} // bool TacticalAppearance::useDictionaryRenderMode() const
bool TacticalAppearance::create()
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START, debugInfo='" << m_debugInfo << "'"
<< " m_visibility = " << m_visibility;
bool success = true;
//
// Prepare / create :
//
// a) singlePoint / exactly one coordinate -> use pictureMarker
// or
// b) multiPoint / more than one coordinate -> m_graphic / DictionaryRenderer
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
* This assumption doesn't work any more because some polyline and polygon symbols will have only one
* anchor point and the real geometry is defined by additional attributes like radius, with, length ...
*
* JT 2016/12/20
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
if (m_graphicsLayer && m_visibility.value())
{
const SymbolData &symbolData_ref = d->m_symbol.value();
const QString &baseSymbolCode = AdvancedSymbology::SidcBuilderBase::concreteSidcToBaseSymbolCode(symbolData_ref.sidc);
const AdvancedSymbology::SymbolProperties &symbolProperties = d->m_dictionary->symbolProperties(baseSymbolCode);
AdvancedSymbology::GeometryType geomType = symbolProperties.geometryType();
if (useDictionaryRenderMode(geomType))
{
if (!d->m_graphicOverlayTactical)
d->m_graphicOverlayTactical = d->m_mapImpl->getGraphicsLayerDict(d->m_logicalLayerName);
if (!d->m_graphicOverlayTactical)
{
ERROR_LOG(m_logger) << LOGFUNCTION << " debugInfo='" << m_debugInfo << "'"
<< " getGraphicsLayerDict failed";
return false;
}
if (!m_graphic)
{
m_graphic = new Esri::ArcGISRuntime::Graphic();
m_graphic->setObjectName(m_debugInfo);
m_graphic->setZIndex(m_drawOrder.value());
// use attributeModel to store application obj id (SimWorld) at graphic
Esri::ArcGISRuntime::AttributeListModel *attLisModel = m_graphic->attributes();
if (attLisModel)
attLisModel->insertAttribute(QLatin1String(SituationMap::UniqueMapIdAttribute), m_uniqueMapId);
else
ERROR_LOG(m_logger) << LOGFUNCTION << " no AttributeListModel, debugInfo='" << m_debugInfo << "'" << " uniqueMapId=" << m_uniqueMapId;
// Adding an empty graphic leads to Segmentation fault.
// (in Esri_runtimecore::Map_renderer::Dictionary_renderer::derive_geometry)
bool successGraphic = addUpdateGraphic(); // CHECK
if (!successGraphic)
ERROR_LOG(m_logger) << LOGFUNCTION << " addUpdateGraphic failed, debugInfo='" << m_debugInfo << "'" << " uniqueMapId=" << m_uniqueMapId;
} // if (!m_graphic)
}
else
{
// m_graphic is needless now:
removeGraphicFromGraphicOverlayTactical();
}
}
// : Prepare / create
bool positionsEmpty = m_positions.value().isEmpty();
if (positionsEmpty)
ERROR_LOG(m_logger) << LOGFUNCTION << " debugInfo='" << m_debugInfo << "'" << " positions empty";
success = success && !positionsEmpty;
if (!success)
ERROR_LOG(m_logger) << LOGFUNCTION << " debugInfo='" << m_debugInfo << "'" << " create failed";
TRACE_LOG(m_logger) << LOGFUNCTION << " END, debugInfo='" << m_debugInfo << "'";
return success;
}
void TacticalAppearance::createPictureMarker()
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START, debugInfo='" << m_debugInfo << "'";
if (!d->m_pictureMarker && d->m_mapImpl)
{
d->m_pictureMarker = new GraphicalObjectPictureMarker(d->m_mapImpl->getEsriGeoView()
, m_graphicsLayer
, m_debugInfo + QLatin1String("#PicMarkTacticalAppearance")
, m_uniqueMapId);
}
TRACE_LOG(m_logger) << LOGFUNCTION << " END, debugInfo='" << m_debugInfo << "'";
}
void TacticalAppearance::removePictureMarker()
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START, debugInfo='" << m_debugInfo << "'";
delete d->m_pictureMarker;
d->m_pictureMarker = nullptr;
TRACE_LOG(m_logger) << LOGFUNCTION << " END, debugInfo='" << m_debugInfo << "'";
}
QString TacticalAppearance::uniqueDesignation() const
{
return d->m_uniqueDesignation.value();
}
void TacticalAppearance::setUniqueDesignation(const QString &uniqueDesignation)
{
d->m_uniqueDesignation = uniqueDesignation;
}
SymbolImage TacticalAppearance::symbolImage() const
{
SymbolImage symImage;
if (d->m_pictureMarker)
{
symImage.setImage(d->m_pictureMarker->image());
symImage.setValid(!symImage.image().isNull());
}
return symImage;
}
SymbolData TacticalAppearance::symbol() const
{
return d->m_symbol.value();
}
void TacticalAppearance::setSymbol(const SymbolData &symbol)
{
d->m_symbol = symbol;
}
bool TacticalAppearance::changed()
{
return BaseClass::changed()
|| d->m_uniqueDesignation.changed()
|| d->m_symbol.changed();
}
void TacticalAppearance::resetChanged()
{
BaseClass::resetChanged();
d->m_uniqueDesignation.reset();
d->m_symbol.reset();
}
Esri::ArcGISRuntime::Geometry TacticalAppearance::getGraphicGeometry() const
{
if (d->m_pictureMarker) return d->m_pictureMarker->getGraphicGeometry();
if (m_graphic) return m_graphic->geometry();
ERROR_LOG(m_logger) << LOGFUNCTION << "Geometry is undefined";
return Esri::ArcGISRuntime::Geometry();
} // Esri::ArcGISRuntime::Geometry TacticalAppearance::getGraphicGeometry() const
bool TacticalAppearance::updateViewImpl()
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START, debugInfo='" << m_debugInfo << "'"
<< " symbol='" << d->m_symbol.value().sidc << "'"
<< " visibility=" << m_visibility
<< " selected=" << m_selected
<< " origin=" << this->origin()
<< " scale=" << m_scale.value();
const SymbolData &symbolData_ref = d->m_symbol.value();
const QString &baseSymbolCode = AdvancedSymbology::SidcBuilderBase::concreteSidcToBaseSymbolCode(symbolData_ref.sidc);
const AdvancedSymbology::SymbolProperties &symbolProperties = d->m_dictionary->symbolProperties(baseSymbolCode);
AdvancedSymbology::GeometryType geomType = symbolProperties.geometryType();
if (geomType == AdvancedSymbology::GeometryType::Undefined)
{
ERROR_LOG(m_logger) << LOGFUNCTION << " debugInfo='" << m_debugInfo << "'"
<< " GeometryType::Undefined, symbolProperties failed!?!";
return false;
}
TRACE_LOG(m_logger) << LOGFUNCTION << " START, debugInfo='" << m_debugInfo << "'"
<< ", geomType=" << geomType
<< ", useDictionaryRenderMode(geomType)=" << useDictionaryRenderMode(geomType);
bool success = create();
if (!success)
{
ERROR_LOG(m_logger) << LOGFUNCTION << " debugInfo='" << m_debugInfo << "'"
<< " create failed";
return false;
}
if (useDictionaryRenderMode(geomType))
{
// real work:
if (m_positions.changed() || d->m_symbol.changed() || m_visibility.changed())
{
auto buildPointClusterGeometry = [this]() -> Esri::ArcGISRuntime::Geometry
{
QSharedPointer<Esri::ArcGISRuntime::MultipointBuilder> builder(new Esri::ArcGISRuntime::MultipointBuilder(spatialReference()));
Esri::ArcGISRuntime::PointCollection points(spatialReference());
const auto posCont = positions();
for (const auto &pos : posCont)
{
DEBUG_LOG(m_logger) << LOGFUNCTION << " debugInfo='" << m_debugInfo << "'"
<< " addPoint:" << pos.x() << " - " << pos.y();
points.addPoint(pos.x(), pos.y());
}
builder->setPoints(&points);
return builder->toGeometry();
}; // buildPointClusterGeometry
Esri::ArcGISRuntime::Geometry geom;
switch (geomType)
{
case AdvancedSymbology::GeometryType::Undefined : break;
case AdvancedSymbology::GeometryType::Point :
case AdvancedSymbology::GeometryType::Polyline :
{
DEBUG_LOG(m_logger) << LOGFUNCTION << " debugInfo='" << m_debugInfo << "'" << " m_positions.count()=" << m_positions.value().count();
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*
* If a PolylineBuilder is used here to create symbol geometry the construction appropriate symbol standard (MIL2525C / MIL2525D / App6)
* will not be done and the symbol is always a simple polyline. Using MultipointBuilder to build symbol geometry the result is based on
* underlying symbol standard.
* 2016/12/9 JT
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
geom = buildPointClusterGeometry();
} break;
case AdvancedSymbology::GeometryType::Polygon :
{
DEBUG_LOG(m_logger) << LOGFUNCTION << " debugInfo='" << m_debugInfo << "'" << " m_positions.count()=" << m_positions.value().count();
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*
* Some symbols have polygon geometry and could have only one or two positions. In case of less than 3 positions do the same as for
* polylines and use MultipointBuilder to create the symbol geometry. In other case use PolygonBuilder.
* 2016/12/13 JT
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
if (positions().size() > 2)
{
QSharedPointer<Esri::ArcGISRuntime::PolygonBuilder> builder(new Esri::ArcGISRuntime::PolygonBuilder(spatialReference()));
const auto posCont = positions();
for (const auto &pos : posCont)
{
DEBUG_LOG(m_logger) << LOGFUNCTION << " debugInfo='" << m_debugInfo << "'" << " addPoint:" << pos.x() << " - " << pos.y();
builder->addPoint(pos.x(), pos.y());
}
geom = builder->toGeometry();
}
else
geom = buildPointClusterGeometry();
} break;
} // switch
if (geom.isEmpty())
{
ERROR_LOG(m_logger) << LOGFUNCTION << " Geometry NOT OK -> fallback symbol" << " (geometryType was " << geomType << ")";
createPictureMarker();
d->m_pictureMarker->setDebugInfo(m_debugInfo + QLatin1String("#fallback"));
int size = symbolData_ref.size;
if (size < 10) size = 10;
if (size > 100) size = 100;
d->m_pictureMarker->setMarkerSymbol(MarkerSymbolType::Diamond, size, symbolData_ref.color);
d->m_pictureMarker->setOrigin(this->origin());
d->m_pictureMarker->setDrawOrder(m_drawOrder.value());
d->m_pictureMarker->updateView();
success = false;
}
else // geom is not empty
{
removePictureMarker();
if (m_graphic)
{
success = true;
// move to graphic:
m_graphic->setGeometry(geom);
// prepare rawAttributes for DictionaryRenderer:
QVariantMap rawAttributes = d->m_symbol.value().attributeMap;
// build from scratch to honor removed attributes:
// (Otherwise the will remain wrongly)
rawAttributes[QLatin1String(SituationMap::UniqueMapIdAttribute)] = m_uniqueMapId;
rawAttributes[QLatin1String(SituationMap::IsPickableAttribute)] = m_pickable.value(); // set pickable attribute JT 2016/12/21
rawAttributes[QLatin1String("_type")] = QLatin1String("position_report");
rawAttributes[QLatin1String("_action")] = QLatin1String("update");
rawAttributes[QLatin1String("sidc")] = AdvancedSymbology::SidcCodec::decodeRawSidc(d->m_symbol.value().sidc); // in case of MIL2525
rawAttributes[QLatin1String("sic")] = AdvancedSymbology::SidcCodec::decodeRawSidc(d->m_symbol.value().sidc); // in case of APP6
Esri::ArcGISRuntime::AttributeListModel * attributeModel = m_graphic->attributes();
if (attributeModel)
attributeModel->setAttributesMap(rawAttributes);
else
ERROR_LOG(m_logger) << LOGFUNCTION << " debugInfo='" << m_debugInfo << "'" << " no AttributeListModel";
// // prepare rawAttributes for DictionaryRenderer:
// QVariantMap rawAttributes = d->m_symbol.value().attributeMap;
// rawAttributes[QLatin1String(SituationMap::IsPickableAttribute)] = m_pickable.value(); // set pickable attribute JT 2016/12/21
// rawAttributes[QLatin1String("_type")] = QLatin1String("position_report");
// rawAttributes[QLatin1String("_action")] = QLatin1String("update");
// rawAttributes[QLatin1String("sidc")] = AdvancedSymbology::SidcCodec::decodeRawSidc(d->m_symbol.value().sidc); // in case of MIL2525
// rawAttributes[QLatin1String("sic")] = AdvancedSymbology::SidcCodec::decodeRawSidc(d->m_symbol.value().sidc); // in case of APP6
// // move to graphic:
// m_graphic->setGeometry(geom);
// /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// * Replace:
// * m_graphic->attributes()->setAttributesMap(rawAttributes);
// *
// * because it doesn't work anymore in ArcGISRuntime V100.2
// * JT, 2018/01/24
// * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
// Esri::ArcGISRuntime::AttributeListModel * attributeModel = m_graphic->attributes();
// if (attributeModel)
// {
// if (!attributeModel->isEmpty())
// {
// for (auto it = rawAttributes.cbegin(); it != rawAttributes.cend(); ++it)
// {
// const QString &attrKey = it.key();
// if (attributeModel->containsAttribute(attrKey))
// {
// attributeModel->replaceAttribute(attrKey, rawAttributes[attrKey]);
// continue;
// }
// attributeModel->insertAttribute(attrKey, rawAttributes[attrKey]);
// }
// }
// else attributeModel->setAttributesMap(rawAttributes);
// }
// 2021-08, N. Thoden
// While switching back to the behaviour that one logical layer has
// 1st getGraphicsLayer and 2nd getGraphicsLayerDict [GUEZE-496],
// the tactical appereance of DangerArea and similar disappears.
// Reason: m_graphicsLayer and m_graphicOverlayTactical are different now!
// It seems like that in former versions (< V100.8) the graphic could
// be added to more than one Esri layer.
// Now (V100.8) adding to a second layer fails.
// But we can remove the m_graphic from the default m_graphicsLayer
// before adding the the desired one: m_graphicOverlayTactical
if (m_graphicsLayer->graphics()->contains(m_graphic))
m_graphicsLayer->graphics()->removeOne(m_graphic);
// add to graphicOverlayTactical:
if (! d->m_graphicOverlayTactical->graphics()->contains(m_graphic))
d->m_graphicOverlayTactical->graphics()->append(m_graphic);
bool successGraphic = d->m_graphicOverlayTactical->graphics()->contains(m_graphic);
if (!successGraphic)
ERROR_LOG(m_logger) << LOGFUNCTION << " debugInfo='" << m_debugInfo << "'"
<< " m_graphic not added to m_graphicOverlayTactical";
}
else
{
DEBUG_LOG(m_logger) << LOGFUNCTION << " debugInfo='" << m_debugInfo << "'"
<< " no m_graphic";
// success = false;
success = true; // if the DictionaryRenderer is used, m_graphic is null and that is ok.
}
} // if (geom.isEmpty())
}
}
else // !useDictionaryRenderMode(geomType)
{
createPictureMarker();
d->m_pictureMarker->setOrigin(this->origin());
// real work:
DEBUG_LOG(m_logger) << LOGFUNCTION << " debugInfo='" << m_debugInfo << "'"
<< " update geometry";
if (d->m_symbol.changed() || m_scale.changed())
{
if (d->m_dictionary)
{
int widthPixel = SituationMap::SymbolSizeLdefault;
widthPixel *= symbolData_ref.size * m_scale.value();
d->m_symDataToRender.sidc = symbolData_ref.sidc;
d->m_symDataToRender.fillColor = symbolData_ref.color;
d->m_symDataToRender.fillColorReplace = true;
d->m_symDataToRender.sizeL = widthPixel;
if (d->m_pictureMarker->image().isNull())
d->m_pictureMarker->setImage(d->m_dictionary->temporaryImage(d->m_symDataToRender.sizeL));
d->m_symbolResultWatcher.setSymbolResult(d->m_dictionary->fetchSymbol(d->m_symDataToRender));
success = true;
}
else
{
ERROR_LOG(m_logger) << LOGFUNCTION << " debugInfo='" << m_debugInfo << "'"
<< " visibility=" << m_visibility
<< " no dictionary";
}
}
if (d->m_pictureMarker)
{
d->m_pictureMarker->setDrawOrder(m_drawOrder.value());
d->m_pictureMarker->setVisibility(m_visibility.value());
d->m_pictureMarker->setSelected(m_selected.value());
d->m_pictureMarker->setPickable(m_pickable.value());
success = success && d->m_pictureMarker->updateView();
}
} // else !useDictionaryRenderMode(geomType)
if (d->m_pictureMarker)
{
d->m_pictureMarker->setOrigin(this->origin()); // to avoid incorrect number of positions..
d->m_pictureMarker->setVisibility(m_visibility.value());
d->m_pictureMarker->setSelected(m_selected.value());
success = d->m_pictureMarker->updateView() && success;
}
// in case of no pictureMarker:
if (m_graphic)
{
m_graphic->setZIndex(m_drawOrder.value());
m_graphic->setVisible(m_visibility.value());
m_graphic->setSelected(m_selected.value());
}
// reset flags
d->m_symbol.reset();
if (!success)
ERROR_LOG(m_logger) << LOGFUNCTION << " failure, debugInfo='" << m_debugInfo << "'";
TRACE_LOG(m_logger) << LOGFUNCTION << " END, debugInfo='" << m_debugInfo << "'"
<< " success = " << success
<< " visibility=" << m_visibility;
return success;
}
} // namespace SituationMap
@@ -0,0 +1,117 @@
/**
* @RDE_HEADER@
* TacticalAppearance
* $Id$
* $HeadURL$
* $Author$
*/
#pragma once
// Own
#include "abstract_graphical_object.h"
// Esri
// Qt
// forward:
//----------------------------------------------------------------------------
namespace SituationMap
{
// forward:
class MapImpl;
class GraphicalObjectPictureMarker;
/**
* @brief The TacticalAppearance class displays sidcs.
* To do so, the number of coordinate lead to use
* - the GraphicalObjectPictureMarker (exactly one coordinate)
* or
* - the Message (more than one coordinate)
*
* Use cases:
* - Participant: sidc with #coords == 1, TacticalAppearance should get exactly one coordinate.
* (GraphicalObjectPictureMarker on ESRI::GraphicsLayer is used)
* - Tactical display of a Building: sidc #coords >= 2, TacticalAppearance should get list of positions.
* (Message on ESRI::MessageGroupLayer is used)
* - (Tactical) PreviewIcon of a Building: sidc #coords == 1, TacticalAppearance should get exactly one coordinate.
* (GraphicalObjectPictureMarker on ESRI::GraphicsLayer is used)
* - Tactical symbols of plan editor
*
* In case of GraphicalObjectPictureMarker the image creation is done by AdvancedSymbology::SymbolDictionary::symbolImageBySidcExtended().
*/
class SITUATIONMAP_EXPORT TacticalAppearance : public AbstractGraphicalObject
{
using BaseClass = AbstractGraphicalObject;
public:
/**
* @brief TacticalAppearance
* @param mapImpl map to be used.
* @param logicalLayerName logical layer name to be used.
* @param debugInfo debugInfo to be used
* @param uniqueMapId uniqueMapId to be used. (Optional to fulfill rubberband requirements)
*/
TacticalAppearance(MapImpl *mapImpl,
const QString &logicalLayerName,
const QString &debugInfo,
const UniqueMapId &uniqueMapId = INVALID_MAP_ID);
TacticalAppearance(const TacticalAppearance &other) = delete;
TacticalAppearance &operator=(TacticalAppearance &other) = delete;
virtual ~TacticalAppearance();
SymbolData symbol() const;
void setSymbol(const SymbolData &symbol);
QString uniqueDesignation() const;
void setUniqueDesignation(const QString &uniqueDesignation);
SymbolImage symbolImage() const;
Esri::ArcGISRuntime::Geometry getGraphicGeometry() const override;
protected:
// Internal/Admin
virtual bool create() override;
virtual void createPictureMarker();
virtual void removePictureMarker();
void removeGraphicFromGraphicOverlayTactical();
bool changed() override;
void resetChanged() override;
bool updateViewImpl() override;
bool useDictionaryRenderMode(const AdvancedSymbology::GeometryType &geomType) const;
// logical
private:
LOGGER_T m_logger; ///< Interface of the Logging-Facility
class Private;
/**
* The private d-pointer to not break BC when changing internals of this class
*/
Private *d = nullptr;
};
} // namespace SituationMap
@@ -0,0 +1,603 @@
/**
**
** @RDE_HEADER@
** Handles aggregation of participant layer
** $Id$
** $HeadURL$
** $Author$
**
** -----------------------------------------------------------------------------------------------
**
** Hardware-Environment: Intel-PC
** Software-Environment: Windows 7, Qt 5.4. ArcGIS 10.2.5
**
** Language ........: C++ 11
**
** -----------------------------------------------------------------------------------------------
**
** Author ...........: Jörg Turla, SPD G, Tel. 3132
**
** -----------------------------------------------------------------------------------------------
**
** Notes .........:
**
** 16.08.2017, JT : first edition
**
** -----------------------------------------------------------------------------------------------
*/
#include "layer_aggregation_widget.h"
#include <Map/map.h>
#include <Map/layer_parameter.h>
#include <LtsWidgets/lts_message_dialog.h>
#include <Common/situation_map_logging.h>
#include <QtCore/QMap>
#include <QtCore/QRegularExpression>
#include <QtCore/QString>
#include <QtCore/QVector>
#include <QtWidgets/QCheckBox>
#include <QtWidgets/QLabel>
#include <QtWidgets/QPushButton>
#include <QtWidgets/QGridLayout>
#include <cmath>
using namespace SituationMap;
struct AggregationData
{
QString layerName;
QString displayName;
double minScale = LayerParameter::UNDEFINED_SCALE; // 0
double maxScale = LayerParameter::UNDEFINED_SCALE; // 0
bool minScaleValid = false;
bool maxScaleValid = false;
}; // AggregationData
struct AggregationWidgets
{
QCheckBox *cbMinScaleValid = nullptr;
QPushButton *pbMinScale = nullptr;
QPushButton *pbMinScaleTo = nullptr;
QCheckBox *cbMaxScaleValid = nullptr;
QPushButton *pbMaxScale = nullptr;
QPushButton *pbMaxScaleTo = nullptr;
QPushButton *pbReset = nullptr;
QPushButton *pbApply = nullptr;
};
class LayerAggregationWidget::InternalData
{
public:
Map *m_map = nullptr;
bool m_valid = false;
LayerType m_layerType;
QVector<AggregationData> m_aggregationList;
QMap<QString, AggregationData> m_aggregationReset;
QMap<QString, AggregationWidgets> m_aggregationWidgets;
LOGGER_T m_logger;
explicit InternalData(Map *map,LayerType layerType)
: m_map(map)
, m_layerType(layerType)
, m_logger(getLogger("LayerAggregation"))
{}
}; // LayerAggregationWidget::InternalData
//------------------------------------------------------------------------------
QString LayerAggregationWidget::scaleText(double scale)
{
return (scale >= 1) ? QStringLiteral("1:%1").arg(int(scale)) : tr("undefined");
} // QString LayerAggregationWidget::scaleText(double scale)
void LayerAggregationWidget::setMinScaleLabel(QPushButton *btn, double scale)
{
btn->setText(tr("Min. Scale from Map\n%1").arg(scaleText(scale)));
} // void LayerAggregationWidget::setMinScaleLabel(QPushButton * btn, double scale)
void LayerAggregationWidget::setMaxScaleLabel(QPushButton *btn, double scale)
{
btn->setText(tr("Max. Scale from Map\n%1").arg(scaleText(scale)));
} // void LayerAggregationWidget::setMaxScaleLabel(QPushButton * btn, double scale)
LayerAggregationWidget::LayerAggregationWidget(Map *map, LayerType layerType, const QRegularExpression &nameCondition, QWidget *parent)
: QWidget(parent), m_internal(new InternalData(map,layerType))
{
if (!nameCondition.isValid())
{
ERROR_LOG(m_internal->m_logger) << LOGFUNCTION << " Illegal regular expression in nameCondition.";
return;
}
if (map == nullptr)
{
ERROR_LOG(m_internal->m_logger) << LOGFUNCTION << " Invalid situation map, cannot initialize dialog";
return;
}
QGridLayout *layout = new QGridLayout(this);
layout->setSpacing(10);
const LayerFactory &layerFactory = map->layerFactory();
QIcon scaleToIcon(QStringLiteral("icon:search.svg"));
const auto ln = layerFactory.layernames(layerType);
for (const QString &layerName : ln)
{
if (nameCondition.match(layerName).hasMatch())
{
// get layer
AggregationData data;
AggregationWidgets &widgets = m_internal->m_aggregationWidgets[layerName];
const LayerParameter &layerPara = layerFactory.layerParameter(layerName);
data.layerName = layerName;
data.minScale = layerPara.minScale;
data.maxScale = layerPara.maxScale;
data.minScaleValid = layerPara.minScaleValid();
data.maxScaleValid = layerPara.maxScaleValid();
data.displayName = layerPara.displayName;
int row = m_internal->m_aggregationList.size();
QLabel *laName = new QLabel(layerPara.displayName.isEmpty() ? layerName : layerPara.displayName, this);
widgets.pbReset = new QPushButton(this);
widgets.pbApply = new QPushButton(this);
widgets.pbReset->setSizePolicy(QSizePolicy(QSizePolicy::Minimum, QSizePolicy::Expanding));
widgets.pbApply->setSizePolicy(QSizePolicy(QSizePolicy::Minimum, QSizePolicy::Expanding));
QHBoxLayout *minLayout = new QHBoxLayout();
minLayout->addSpacing(20);
minLayout->addWidget(widgets.cbMinScaleValid = new QCheckBox(QString(), this));
minLayout->addWidget(widgets.pbMinScale = new QPushButton(QString(), this));
minLayout->addWidget(widgets.pbMinScaleTo = new QPushButton(scaleToIcon, QString(), this));
minLayout->addSpacing(20);
setMinScaleLabel(widgets.pbMinScale, layerPara.minScale);
QHBoxLayout *maxLayout = new QHBoxLayout();
maxLayout->addWidget(widgets.cbMaxScaleValid = new QCheckBox(QString(), this));
maxLayout->addWidget(widgets.pbMaxScale = new QPushButton(QString(), this));
maxLayout->addWidget(widgets.pbMaxScaleTo = new QPushButton(scaleToIcon, QString(), this));
maxLayout->addSpacing(20);
setMaxScaleLabel(widgets.pbMaxScale, layerPara.maxScale);
widgets.pbMinScale->setSizePolicy(QSizePolicy(QSizePolicy::Minimum, QSizePolicy::Expanding));
widgets.pbMaxScale->setSizePolicy(QSizePolicy(QSizePolicy::Minimum, QSizePolicy::Expanding));
layout->addWidget(laName, row, 0);
layout->addLayout(minLayout, row, 1);
layout->addLayout(maxLayout, row, 2);
layout->addWidget(widgets.pbReset, row, 3);
layout->addWidget(widgets.pbApply, row, 4);
m_internal->m_aggregationList << data;
m_internal->m_aggregationReset[layerName] = data;
widgets.pbMinScale->setProperty("row", row);
widgets.pbMaxScale->setProperty("row", row);
widgets.cbMinScaleValid->setProperty("row", row);
widgets.cbMaxScaleValid->setProperty("row", row);
widgets.pbMinScaleTo->setProperty("row", row);
widgets.pbMaxScaleTo->setProperty("row", row);
widgets.pbReset->setProperty("row", row);
widgets.pbApply->setProperty("row", row);
connect(widgets.cbMinScaleValid, &QCheckBox::clicked, this, &LayerAggregationWidget::onSetValid);
connect(widgets.cbMaxScaleValid, &QCheckBox::clicked, this, &LayerAggregationWidget::onSetValid);
connect(widgets.pbMinScale, &QPushButton::clicked, this, &LayerAggregationWidget::onGetMinScale);
connect(widgets.pbMaxScale, &QPushButton::clicked, this, &LayerAggregationWidget::onGetMaxScale);
connect(widgets.pbMinScaleTo, &QPushButton::clicked, this, &LayerAggregationWidget::onZoomTo);
connect(widgets.pbMaxScaleTo, &QPushButton::clicked, this, &LayerAggregationWidget::onZoomTo);
connect(widgets.pbReset, &QPushButton::clicked, this, &LayerAggregationWidget::onReset);
connect(widgets.pbApply, &QPushButton::clicked, this, &LayerAggregationWidget::onApply);
widgets.cbMinScaleValid->setChecked(data.minScaleValid);
widgets.cbMinScaleValid->setEnabled(data.minScaleValid);
widgets.cbMaxScaleValid->setChecked(data.maxScaleValid);
widgets.cbMaxScaleValid->setEnabled(data.maxScaleValid);
widgets.pbMinScaleTo->setEnabled(data.minScaleValid);
widgets.pbMaxScaleTo->setEnabled(data.maxScaleValid);
widgets.pbReset->setEnabled(false);
widgets.pbApply->setEnabled(false);
}
}
retranslate();
if (m_internal->m_aggregationList.isEmpty())
{
QLabel *lbEmpty = new QLabel(tr("Can't find any layer"), this);
QPixmap icon(QStringLiteral("icon:overlays.svg"));
lbEmpty->setWindowIcon(icon);
layout->addWidget(lbEmpty, 0, 0, Qt::AlignCenter);
return;
}
} // LayerAggregation::LayerAggregation( Map * map, QObject * parent )
void LayerAggregationWidget::retranslate()
{
if (m_internal->m_map == nullptr)
return;
const LayerFactory &layerFactory = m_internal->m_map->layerFactory();
const auto ln = layerFactory.layernames(m_internal->m_layerType);
for (const QString &layerName : ln)
{
if (!m_internal->m_aggregationWidgets.contains(layerName)) continue;
AggregationWidgets &widgets = m_internal->m_aggregationWidgets[layerName];
widgets.pbReset->setText(tr("Reset"));
widgets.pbApply->setText(tr("Apply to Map"));
widgets.pbReset->setToolTip(tr("Restore initial scales of this level"));
widgets.pbApply->setToolTip(tr("Set scales to corresponding map layer temporarily"));
widgets.cbMinScaleValid->setToolTip(tr("Activate or deactivate this scale value"));
widgets.pbMinScale ->setToolTip(tr("Get current map scale of map view"));
widgets.pbMinScaleTo ->setToolTip(tr("Set this scale value to map view as current scale"));
widgets.cbMaxScaleValid->setToolTip(tr("Activate or deactivate this scale value"));
widgets.pbMaxScale ->setToolTip(tr("Get current map scale of map view"));
widgets.pbMaxScaleTo ->setToolTip(tr("Set this scale value to map view as current scale"));
}
} // void LayerAggregationWidget::retranslate()
LayerAggregationWidget::~LayerAggregationWidget()
{
delete m_internal; m_internal = nullptr;
} // LayerAggregationWidget::~LayerAggregationWidget()
void LayerAggregationWidget::onZoomTo()
{
QPushButton *senderButton = qobject_cast<QPushButton *>(sender());
if (nullptr == senderButton) return;
int row = senderButton->property("row").toInt();
if ((row < 0) || (row >= m_internal->m_aggregationList.size()))
return;
const AggregationData &data = m_internal->m_aggregationList[row];
const AggregationWidgets &widgets = m_internal->m_aggregationWidgets[data.layerName];
double scale = 0.0;
if ((widgets.pbMinScaleTo == senderButton) && (data.minScaleValid))
scale = data.minScale;
if ((widgets.pbMaxScaleTo == senderButton) && (data.maxScaleValid))
scale = data.maxScale;
if (scale < 1)
return;
m_internal->m_map->setScale(scale);
} // void LayerAggregationWidget::onZoomTo()
void LayerAggregationWidget::onGetMinScale()
{
QPushButton *senderButton = qobject_cast<QPushButton *>(sender());
if (nullptr == senderButton) return;
int row = senderButton->property("row").toInt();
if ((row < 0) || (row >= m_internal->m_aggregationList.size()))
return;
double scale = m_internal->m_map->scale();
AggregationData &data = m_internal->m_aggregationList[row];
if (data.maxScaleValid && (data.maxScale >= scale))
{
const QString &msg = tr("Chosen scale is too small");
LtsWidgets::LtsMessageDialog::showMessage(this, msg, tr("Layer Aggregation"));
return;
}
data.minScale = scale;
data.minScaleValid = true;
setMinScaleLabel(senderButton, data.minScale);
const AggregationWidgets &widgets = m_internal->m_aggregationWidgets[data.layerName];
widgets.cbMinScaleValid->setChecked(true);
widgets.cbMinScaleValid->setEnabled(true);
widgets.pbMinScaleTo->setEnabled(true);
widgets.pbReset->setEnabled(true);
widgets.pbApply->setEnabled(true);
emit changesMade();
} // void LayerAggregationWidget::onGetMinScale()
void LayerAggregationWidget::onGetMaxScale()
{
QPushButton *senderButton = qobject_cast<QPushButton *>(sender());
if (nullptr == senderButton) return;
int row = senderButton->property("row").toInt();
if ((row < 0) || (row >= m_internal->m_aggregationList.size()))
return;
double scale = m_internal->m_map->scale();
AggregationData &data = m_internal->m_aggregationList[row];
if (data.minScaleValid && (data.minScale <= scale))
{
const QString &msg = tr("Chosen scale is too large");
LtsWidgets::LtsMessageDialog::showMessage(this, msg, tr("Layer Aggregation"));
return;
}
data.maxScale = scale;
data.maxScaleValid = true;
setMaxScaleLabel(senderButton, data.maxScale);
const AggregationWidgets &widgets = m_internal->m_aggregationWidgets[data.layerName];
widgets.cbMaxScaleValid->setChecked(true);
widgets.cbMaxScaleValid->setEnabled(true);
widgets.pbMaxScaleTo->setEnabled(true);
widgets.pbReset->setEnabled(true);
widgets.pbApply->setEnabled(true);
emit changesMade();
} // void LayerAggregationWidget::onGetMaxScale()
void LayerAggregationWidget::onSetValid(bool value)
{
QCheckBox *senderButton = qobject_cast<QCheckBox *>(sender());
if (nullptr == senderButton) return;
int row = senderButton->property("row").toInt();
if ((row < 0) || (row >= m_internal->m_aggregationList.size()))
return;
AggregationData &data = m_internal->m_aggregationList[row];
const AggregationWidgets &widgets = m_internal->m_aggregationWidgets[data.layerName];
if (senderButton == widgets.cbMinScaleValid)
{
if (data.maxScaleValid && value && (data.maxScale >= data.minScale))
{
senderButton->setChecked(false);
const QString &msg = tr("Minimum scale is too small");
LtsWidgets::LtsMessageDialog::showMessage(this, msg, tr("Layer Aggregation"));
return;
}
data.minScaleValid = value;
}
if (senderButton == widgets.cbMaxScaleValid)
{
if (data.minScaleValid && value && (data.minScale <= data.maxScale))
{
senderButton->setChecked(false);
const QString &msg = tr("Maximum scale is too large");
LtsWidgets::LtsMessageDialog::showMessage(this, msg, tr("Layer Aggregation"));
return;
}
data.maxScaleValid = value;
}
widgets.pbMinScaleTo->setEnabled(data.minScaleValid);
widgets.pbMaxScaleTo->setEnabled(data.maxScaleValid);
widgets.pbReset->setEnabled(true);
widgets.pbApply->setEnabled(true);
emit changesMade();
} // void LayerAggregationWidget::onSetValid(bool value)
void LayerAggregationWidget::doReset(int row)
{
if ((row < 0) || (row >= m_internal->m_aggregationList.size()))
return;
AggregationData &data = m_internal->m_aggregationList[row];
data = m_internal->m_aggregationReset[data.layerName];
const AggregationWidgets &widgets = m_internal->m_aggregationWidgets[data.layerName];
setMinScaleLabel(widgets.pbMinScale, data.minScale);
setMaxScaleLabel(widgets.pbMaxScale, data.maxScale);
widgets.cbMinScaleValid->setChecked(data.minScaleValid);
widgets.cbMinScaleValid->setEnabled(data.minScaleValid);
widgets.cbMaxScaleValid->setChecked(data.maxScaleValid);
widgets.cbMaxScaleValid->setEnabled(data.maxScaleValid);
widgets.pbMinScaleTo->setEnabled(data.minScaleValid);
widgets.pbMaxScaleTo->setEnabled(data.maxScaleValid);
widgets.pbReset->setEnabled(false);
widgets.pbApply->setEnabled(!widgets.pbApply->isEnabled());
} // void doReset(SituationMap::Map * map, const AggregationData & data)
void LayerAggregationWidget::onReset()
{
QObject *senderObj = sender();
if (nullptr == senderObj) return;
int row = senderObj->property("row").toInt();
if ((row < 0) || (row >= m_internal->m_aggregationList.size()))
return;
doReset(row);
} // void LayerAggregationWidget::onReset()
static void doApply(SituationMap::Map *map, const AggregationData &data)
{
LayerFactory &layerFactory = map->layerFactory();
LayerParameter layerParamter = layerFactory.layerParameter(data.layerName);
layerParamter.minScale = data.minScaleValid ? data.minScale : LayerParameter::UNDEFINED_SCALE; // 0;
layerParamter.maxScale = data.maxScaleValid ? data.maxScale : LayerParameter::UNDEFINED_SCALE; // 0;
layerFactory.setLayerParameter(data.layerName, layerParamter);
} // void doApply(SituationMap::Map * map, const AggregationData & data)
void LayerAggregationWidget::onApply()
{
QObject *senderObj = sender();
if (!senderObj)
return;
int row = senderObj->property("row").toInt();
if ((row < 0) || (row >= m_internal->m_aggregationList.size()))
return;
const AggregationData &data = m_internal->m_aggregationList[row];
doApply(m_internal->m_map, data);
const AggregationWidgets &widgets = m_internal->m_aggregationWidgets[data.layerName];
widgets.pbApply->setEnabled(false);
} // void LayerAggregationWidget::onApply()
void LayerAggregationWidget::onApplyAll()
{
for (const AggregationData &data : qAsConst(m_internal->m_aggregationList))
{
const AggregationWidgets &widgets = m_internal->m_aggregationWidgets[data.layerName];
if (widgets.pbApply->isEnabled())
{
doApply(m_internal->m_map, data);
widgets.pbApply->setEnabled(false);
}
}
} // void LayerAggregationWidget::onApplyAll()
void LayerAggregationWidget::onResetAll()
{
for (const auto &aggData : qAsConst(m_internal->m_aggregationList))
{
const AggregationWidgets &widgets = m_internal->m_aggregationWidgets[aggData.layerName];
doReset(widgets.pbApply->property("row").toInt());
doApply(m_internal->m_map, aggData);
widgets.pbApply->setEnabled(false);
}
} // void LayerAggregationWidget::onResetAll()
void LayerAggregationWidget::onSetDefaultScales()
{
if (m_internal->m_aggregationList.isEmpty())
return;
// Calculate scale defaults here ...
double mapMinScaleSQRT = sqrt(m_internal->m_map->minScale());
double mapMaxScaleSQRT = sqrt(m_internal->m_map->maxScale());
const int aggregationListCount = m_internal->m_aggregationList.size();
double stepScaleSQRT = (mapMinScaleSQRT - mapMaxScaleSQRT) / static_cast<double>(aggregationListCount);
unsigned int step = 0;
for (auto &aggData : m_internal->m_aggregationList)
{
double dScaleSQRT = mapMaxScaleSQRT + (step * stepScaleSQRT);
aggData.maxScaleValid = true;
aggData.maxScale = dScaleSQRT * dScaleSQRT;
dScaleSQRT = mapMaxScaleSQRT + ((step + 1) * stepScaleSQRT);
aggData.minScaleValid = true;
aggData.minScale = dScaleSQRT * dScaleSQRT;
} // for
// disable start and end
if (aggregationListCount > 0)
{
// front -> max
m_internal->m_aggregationList.front().maxScale = 0;
m_internal->m_aggregationList.front().maxScaleValid = false;
// back -> min
m_internal->m_aggregationList.back().minScale = 0;
m_internal->m_aggregationList.back().minScaleValid = false;
} // if
// update ui to m_aggregationList:
for (const auto &aggData : qAsConst(m_internal->m_aggregationList))
{
const AggregationWidgets &widgets = m_internal->m_aggregationWidgets[aggData.layerName];
widgets.cbMinScaleValid->setEnabled(aggData.minScaleValid);
widgets.cbMinScaleValid->setChecked(aggData.minScaleValid);
widgets.pbMinScaleTo->setEnabled(aggData.minScaleValid);
widgets.cbMaxScaleValid->setEnabled(aggData.maxScaleValid);
widgets.cbMaxScaleValid->setChecked(aggData.maxScaleValid);
widgets.pbMaxScaleTo->setEnabled(aggData.maxScaleValid);
widgets.pbApply->setEnabled(true);
widgets.pbReset->setEnabled(true);
setMinScaleLabel(widgets.pbMinScale, aggData.minScale);
setMaxScaleLabel(widgets.pbMaxScale, aggData.maxScale);
} // for
emit changesMade();
} // void LayerAggregationWidget::onSetDefaultScales()
@@ -0,0 +1,110 @@
/**
**
** @RDE_HEADER@
** Handles aggregation of participant layer
** $Id$
** $HeadURL$
** $Author$
**
** -----------------------------------------------------------------------------------------------
**
** Hardware-Environment: Intel-PC
** Software-Environment: Windows 7, Qt 5.4. ArcGIS 10.2.5
**
** Language ........: C++ 11
**
** -----------------------------------------------------------------------------------------------
**
** Author ...........: Jörg Turla, SPD G, Tel. 3132
**
** -----------------------------------------------------------------------------------------------
**
** Notes .........:
**
** 16.08.2017, JT : first edition
**
** -----------------------------------------------------------------------------------------------
*/
#pragma once
#include <Map/layer_factory.h>
#include <situation_map_export.h>
#include <QtWidgets/QWidget>
class QPushButton;
class QRegularExpression;
namespace SituationMap
{
class Map;
/**
@class LayerAggregationWidget layer_aggregation_widget.h
@brief Class to handle aggregation of participant layer
*/
class SITUATIONMAP_EXPORT LayerAggregationWidget : public QWidget
{
Q_OBJECT
public:
/**
Constructor to build gui widget for handling aggregation layers.
@param map Map the layer are part of
@param layerType Type of layer in general this will be LayerType::Operational
@param nameCondition If the nameCondition doesn't match with the layername the layer will be skipped and is not handled.
Example of an expression "^Participant.+".
@param parent Parent for Qt object hierarchy
*/
explicit LayerAggregationWidget(Map *map, LayerType layerType, const QRegularExpression &nameCondition, QWidget *parent);
/**
Destructor to clean up memory.
*/
~LayerAggregationWidget();
void retranslate();
public slots:
void onApplyAll();
void onResetAll();
void onSetDefaultScales();
signals:
void changesMade();
protected slots:
void onSetValid(bool value);
void onGetMinScale();
void onGetMaxScale();
void onZoomTo();
void onReset();
void onApply();
private:
void doReset(int row);
static QString scaleText(double scale);
static void setMinScaleLabel(QPushButton *btn, double scale);
static void setMaxScaleLabel(QPushButton *btn, double scale);
class InternalData;
InternalData *m_internal;
}; // LayerAggregationWidget
} /* namespace SituationMap */
@@ -0,0 +1,105 @@
/**
**
** @RDE_HEADER@
** Dialog of aggregation of participant layer
** $Id$
** $HeadURL$
** $Author$
**
** -----------------------------------------------------------------------------------------------
**
** Hardware-Environment: Intel-PC
** Software-Environment: Windows 7, Qt 5.4. ArcGIS 10.2.5
**
** Language ........: C++ 11
**
** -----------------------------------------------------------------------------------------------
**
** Author ...........: Jörg Turla, SPD G, Tel. 3132
**
** -----------------------------------------------------------------------------------------------
**
** Notes .........:
**
** 18.08.2017, JT : first edition
**
** -----------------------------------------------------------------------------------------------
*/
#include "participant_aggregation_dialog.h"
#include "layer_aggregation_widget.h"
#include <Map/map.h>
#include <QtWidgets/QVBoxLayout>
using namespace SituationMap;
ParticipantAggregationDialog::ParticipantAggregationDialog(Map *map, QWidget *parent)
: LtsWidgets::LtsDialog(parent, LtsWidgets::ButtonCombination::OkApplyCancel)
{
m_law = new LayerAggregationWidget(map, LayerType::Operational, QRegularExpression(QStringLiteral("^Participant.+"), QRegularExpression::CaseInsensitiveOption), this);
if (map)
connect(map, &Map::beginDestroy, this, &ParticipantAggregationDialog::onMapDestroyed, Qt::UniqueConnection);
QVBoxLayout *layout = new QVBoxLayout(this);
layout->addWidget(m_law);
layout->addStretch(2);
LtsWidgets::DialogButton btnSetDefault = LtsWidgets::DialogButton::Print;
m_buttonBox->connectButton(btnSetDefault, m_law, &LayerAggregationWidget::onSetDefaultScales);
m_buttonBox->setButtonEnabled(btnSetDefault, true);
m_buttonBox->setButtonVisible(btnSetDefault, true);
connect(this, &ParticipantAggregationDialog::canceled, m_law, &LayerAggregationWidget::onResetAll);
connect(this, &ParticipantAggregationDialog::applied, m_law, &LayerAggregationWidget::onApplyAll);
connect(m_law, &LayerAggregationWidget::changesMade, this, &ParticipantAggregationDialog::slotChangesMade);
retranslate();
setOnlineHelpFilename(QStringLiteral("Situation-Participant_Aggregation"));
} // ParticipantAggregationDialog::ParticipantAggregationDialog( Map * map, QWidget * parent )
void ParticipantAggregationDialog::retranslate()
{
// lupdate doesn't like translate(tr("foo")) ...
const QString txt(tr("Participant Aggregation"));
translate(txt);
LtsWidgets::DialogButton btnSetDefault = LtsWidgets::DialogButton::Print;
m_buttonBox->setText( btnSetDefault, tr("Set Scale Defaults"));
m_buttonBox->setToolTip( btnSetDefault, tr("Calculate scale values for each aggregation from map scale range"));
m_law->retranslate();
} // void ParticipantAggregationDialog::retranslate()
void ParticipantAggregationDialog::dialogCanceled()
{
emit canceled();
} // void ParticipantAggregationDialog::dialogCanceled()
bool ParticipantAggregationDialog::apply()
{
emit applied();
return true;
}
void ParticipantAggregationDialog::onMapDestroyed()
{
// commit suicide
delete this;
} // bool ParticipantAggregationDialog::apply()
@@ -0,0 +1,79 @@
/**
**
** @RDE_HEADER@
** Dialog of aggregation of participant layer
** $Id$
** $HeadURL$
** $Author$
**
** -----------------------------------------------------------------------------------------------
**
** Hardware-Environment: Intel-PC
** Software-Environment: Windows 7, Qt 5.4. ArcGIS 10.2.5
**
** Language ........: C++ 11
**
** -----------------------------------------------------------------------------------------------
**
** Author ...........: Jörg Turla, SPD G, Tel. 3132
**
** -----------------------------------------------------------------------------------------------
**
** Notes .........:
**
** 18.08.2017, JT : first edition
**
** -----------------------------------------------------------------------------------------------
*/
#pragma once
#include <LtsWidgets/lts_dialog.h>
#include <situation_map_export.h>
#include <QtWidgets/QWidget>
namespace SituationMap
{
class Map;
class LayerAggregationWidget;
/**
@class ParticpantAggregation particpant_aggregation.h
@brief Class to handle aggregation of participant layer dialog
*/
class SITUATIONMAP_EXPORT ParticipantAggregationDialog : public LtsWidgets::LtsDialog
{
Q_OBJECT
public:
explicit ParticipantAggregationDialog(SituationMap::Map *map, QWidget *parent);
~ParticipantAggregationDialog() = default;
void retranslate() override;
void dialogCanceled() override;
protected:
bool apply() override;
Q_SIGNALS:
void canceled();
void applied();
protected Q_SLOTS:
void onMapDestroyed();
private:
LayerAggregationWidget *m_law;
}; // ParticipantAggregationDialog
} /* namespace SituationMap */
Binary file not shown.

After

Width:  |  Height:  |  Size: 524 KiB

@@ -0,0 +1,163 @@
# $Id$
# $HeadURL$
# $Author$
[license]
licenseString = "runtimestandard,1000,rud000004959,none,7RC63PJPXJPH003AD234" ;# Bayanat Helpdesk, 21.07.2019
1\extensionString = "Exten1"
size=0
[esriNetworkCache]
enabled = 1 ;# enabled: 1=on ; 0=off, since V100.7.0
[symbology]
type = "MIL2525D" ;# None | MIL2525D | MIL2525C | APP6B
extraSymbols = ":/advancedSymbology/CivilSymbols" ;# ':/advancedSymbology/CivilSymbols'
[mapUrls]
# EXCGEO01 (192.168.133.90) -> CCSAWS01
# 1\url = "URL[#<minScale>:<maxScale>]"
#Example: >>> 1\url = "http://HOSTNAME_FQDN/arcgis/rest/services/Folder/Svcname/MapServer#minScale:maxScale" <<<
#
#if the projection matches, tpk file and/or tile cache folder (win only) are supported:
#1\url = "file:Topographic.tpk#-1:125" ;# -> /usr/share/arcgis/resources/Topographic.tpk
#2\url = "file:///usr/share/arcgis/resources/World_Topo_Map.tpk#-1:125"
# WINDOWS 1\url = "file:///C:/EXTFW/resources/Guez_Topo_32632_guez_topo_32632/Guez Topographic#-1:125"
#
#For factory
1\url = "http://excgeo21.sl.defence-elec.de/arcgis/rest/services/AHTC/AlHamra_Aerial_1m00_32639/MapServer#-1:125" ;# Since 2019-04-05
1\url = "http://excgeo21.sl.defence-elec.de/arcgis/rest/services/AHTC/AlHamra_Aerial_0m21_PreDelivery_32639/MapServer#-1:125" ;# Since 2019-05-08
#For on-site
#1\url = "http://EXCGEO02/arcgis/rest/services/AHTC/2019_06_17_AHTC_CTC_Topo_2016_32639/MapServer#-1:125" ;# Since 2019-06
#2\url = "http://EXCGEO02/arcgis/rest/services/AHTC/2019_06_17_AHTC_CTC_Aerial_2016_32639/MapServer#-1:125" ;# Since 2019-06
#3\url = "http://EXCGEO02/arcgis/rest/services/AHTC/AlHamra_Aerial_0m21_PreDelivery_32639/MapServer#-1:125" ;# Since 2019-06
#TileCacheFolder
1\url = "file:TileCacheFolder/AHTC/AHTC_2019_06_17_AHTC_CTC_Topo_2016_32639/AHTC_CTC_Topogaphic#-1:125"
2\url = "file:TileCacheFolder/AHTC/AHTC_2019_06_17_AHTC_CTC_Aerial_2016_32639/AHTC_CTC_Aerial#-1:125"
3\url = "file:TileCacheFolder/AHTC/AHTC_AlHamra_Aerial_0m21_PreDelivery_32639/Al Hamra Aerial 0m21#-1:125"
#For on-site - windows
# todo
size=3
basemapLayernamePrefix = "" ;# default: "ArcGISTiledLayer_URL_"
# For debugging only:
# an non-empty value will overwrite/skip the mapUrls:
#localMapFile = "Topographic.tpk" ;# empty (if so, try 'Topographic.tpk')
# : For debugging only
[sceneUrls]
#For factory
1\url = "http://excgeo21.sl.defence-elec.de/arcgis/rest/services/AHTC/AlHamra_Aerial_1m00_WebMerc/MapServer#-1:25" ;# Since 2019-04-05
1\url = "http://excgeo21.sl.defence-elec.de/arcgis/rest/services/AHTC/AlHamra_Aerial_0m21_PreDelivery_WebMerc/MapServer#-1:25" ;# Since 2019-05-08
#For on-site
#1\url = "http://EXCGEO02/arcgis/rest/services/AHTC/2019_06_17_AHTC_CTC_Topo_2016_WebMerc/MapServer#-1:125" ;# Since 2019-06
#2\url = "http://EXCGEO02/arcgis/rest/services/AHTC/2019_06_17_AHTC_CTC_Aerial_2016_WebMerc/MapServer#-1:125" ;# Since 2019-06
#3\url = "http://EXCGEO02/arcgis/rest/services/AHTC/AlHamra_Aerial_0m21_PreDelivery_WebMerc/MapServer#-1:125" ;# Since 2019-06
#For on-site - windows
# todo
#TileCacheFolder
1\url = "file:TileCacheFolder/AHTC/AHTC_2019_06_17_AHTC_CTC_Topo_2016_WebMerc/AHTC_CTC_Topogaphic#-1:125"
2\url = "file:TileCacheFolder/AHTC/AHTC_2019_06_17_AHTC_CTC_Aerial_2016_WebMerc/AHTC_CTC_Aerial#-1:125"
3\url = "file:TileCacheFolder/AHTC/AHTC_AlHamra_Aerial_0m21_PreDelivery_WebMerc/Al Hamra Aerial 0m21#-1:125"
4\url = "file:slpk/2022-05-23_AHTC-Bridges_ret_geotifcp-alex.tif#-1:125" ;# according SPD-slpk with bridges
size=4
[sceneObjectUrls]
# 1\url = "URL[#<altitudeOffset>]"
#Example: >>> 1\url = "file:AHTC_LOW.slpk#0.3" <<<
1\url = "file:AHTC_LOW.slpk#0.5"
size=1
[elevationUrls]
# LZW-Compression is ok for Esri-Scene & ElevationMap
#Example: >>> 1\url = "http://elevation3d.arcgis.com/arcgis/rest/services/WorldElevation3D/Terrain3D/ImageServer" <<<
#Example: >>> 1\url = "file:srtm_38_02.tif" <<< -> /usr/share/arcgis/resources/elevation/srtm_38_02.tif
#Example: >>> 1\url = "file:///shd/CTC/TOOLS/Bremen_Elevation/srtm_38_02.tif" <<<
#1\url = "file:alhamra-dtm-PreDelivery.tif" ;# preDelivery - 2019-05-28
1\url = "file:Elevation.tif" ;# BFE, ~30m
2\url = "file:AHTC_utm_dgm_surface_wgs84.tif" ;# Z&M, XY converted to WGS84 (ArcGIS Pro)
size=2
[operationalLayer]
# "<Layername>:<Static|Dynamic>:<Draped|Absolute|Relative>"
1\operationalLayer = "Buildings:Dynamic:Relative"
2\operationalLayer = "TechnicalAreas:Dynamic:Draped" ;# TechnicalArea@AES (MOUTArea), TrainingArea, ShootBackArea
3\operationalLayer = "MountingPoints:Dynamic:Absolute"
4\operationalLayer = "IEDs:Dynamic:Relative"
5\operationalLayer = "BuildingOwnership:Dynamic:Relative" ;# keep ExtrusionMode (AbsoluteHeight) in mind
6\operationalLayer = "AES:Dynamic:Draped"
7\operationalLayer = "Participants:Dynamic:Relative"
8\operationalLayer = "Participants_1:Dynamic:Relative"
9\operationalLayer = "Participants_2:Dynamic:Relative"
10\operationalLayer = "Participants_3:Dynamic:Relative"
11\operationalLayer = "Participants_4:Dynamic:Relative"
12\operationalLayer = "Participants_5:Dynamic:Relative"
size=12
participantLayername = "Participants:Dynamic:Relative" ;# default: "Participants:Dynamic:Relative"
operationalLayerForCubes = "BuildingOwnership" ;# must match with an operationalLayer
[map]
# full mgrs coordinate
# East;North
center = "39RXG4400060000" ;# AHTC
zoomFactorBase = 1.0015 ;# to configure mouse wheel for zooming, only values greater 1 and lower 1.1 will be accepted
initialScale = 30000 ;# 90000 -> Bremen ; 7000000 -> NorthGermany
# scaleMin and scaleMax (of map!) may be overwritten, if a layer is loaded manually -> to rethink
scaleMin = -1 ;# big value (e.g. 10000000) limiting zoomOut 1:10000000 -> 0.0000001
scaleMax = -1 ;# small value (e.g. 1000) limiting zoomIn 1:1000 -> 0.001
scaleHasVisibility = 70000 ;# zoom out -> some objects disappear to not overload the map
gridType = "MGRS" ;# Grid: NoType, MGRS, UTM, USGN, LatLon
animationDuration = 0.5 ;# default -> 0.5 (0< 0 -> off)
rocketDuration = 2.0 ;# default -> 2.0
[widgets]
addMapWidgets = 1
addSideBar = 1
[viewshed]
# // arcgisonline -> only demo (keep proxy in mind!)
viewshedUrl = "http://sampleserver1.arcgisonline.com/ArcGIS/rest/services/Elevation/ESRI_Elevation_World/GPServer/Viewshed" ;# // only demo!!!
[rubberband]
drawColor = "#00406e" ;# Color settings of rubberband
fillColor = "#007eC0"
handleDrawColor = "#00406e" ;# Outline color of handles
handleFillColor = "#00406e" ;# fill color of handles
selectionColor = "red" ;# fill or draw color if handle is selected
frameColor = "#00406e" ;# outline color of frame handle (bounding box)
frameFillColor = "#5043b0e0" ;# fill color of frame handle (bounding box)
frameHandleMargin = 0 ;# Margin of frame handle in pixel
previewOffset = @Point(32 32) ;# Offset of preview icon to mouse position
previewSize = 32 ;# Size of preview icon
pickingRatio = 8 ;# Size of rubberband point handles
lineHandleWidth = 4 ;# Size of rubberband line handles
# to be continued
@@ -0,0 +1,129 @@
# $Id$
# $HeadURL$
# $Author$
[license]
licenseString = "runtimestandard,1000,rud000004959,none,7RC63PJPXJPH003AD234" ;# Bayanat Helpdesk, 21.07.2019
1\extensionString = ""
size=0
[esriNetworkCache]
enabled = 1 ;# enabled: 1=on ; 0=off, since V100.7.0
[symbology]
type = "APP6D" ;# None | MIL2525D | MIL2525C | APP6B | APP6D
extraSymbols = ":/advancedSymbology/CivilSymbols" ;# ':/advancedSymbology/CivilSymbols'
[mapUrls]
#For on-site - windows
1\url = "file:AHTC_2019_06_17_AHTC_CTC_Topo_2016_32639/AHTC_CTC_Topogaphic#-1:125"
1\name = "AHTC Topographic"
2\url ="file:AHTC_2019_06_17_AHTC_CTC_Aerial_2016_32639/AHTC_CTC_Aerial#-1:125"
2\name = "AHTC Aerial"
3\url = "file:AHTC_AlHamra_Aerial_0m21_PreDelivery_32639/Al Hamra Aerial 0m21#-1:125"
3\name = "AlHamra Aerial"
size=3
basemapLayernamePrefix = "" ;# default: "ArcGISTiledLayer_URL_"
# For debugging only:
# an non-empty value will overwrite/skip the mapUrls:
#localMapFile = "Topographic.tpk" ;# empty (if so, try 'Topographic.tpk')
# : For debugging only
[sceneUrls]
#For on-site - windows
1\url = "file:AHTC_2019_06_17_AHTC_CTC_Topo_2016_WebMerc/AHTC_CTC_Topogaphic#-1:125"
1\name = "AHTC Topographic"
2\url = "file:AHTC_2019_06_17_AHTC_CTC_Aerial_2016_WebMerc/AHTC_CTC_Aerial#-1:125"
2\name = "AHTC Aerial"
3\url = "file:AHTC_AlHamra_Aerial_0m21_PreDelivery_WebMerc/Al Hamra Aerial 0m21#-1:125"
3\name = "AlHamra Aerial"
4\url = "file:2022-05-23_AHTC-Bridges_ret_geotifcp-alex.tif#-1:125" ;# according SPD-slpk with bridges
4\name = "AlHamra Aerial NoBridges"
size=4
[sceneObjectUrls]
# 1\url = "URL[#<altitudeOffset>]"
#Example: >>> 1\url = "file:AHTC_LOW.slpk#0.3" <<<
1\url = "file:AHTC_LOW.slpk#0.5"
size=1
[elevationUrls]
1\url = "file:Elevation.tif" ;# BFE, ~30m
2\url = "file:AHTC_utm_dgm_surface_wgs84.tif" ;# Z&M, XY converted to WGS84 (ArcGIS Pro)
size=2
[operationalLayer]
# "<Layername>:<Static|Dynamic>:<Draped|Absolute|Relative>"
1\operationalLayer = "Buildings:Dynamic:Relative" ;# Dynamic to avoid flicker at 3D if selection changes (MapObjectSelectionWidget)
2\operationalLayer = "TechnicalAreas:Dynamic:Draped" ;# TechnicalArea@AES (MOUTArea), TrainingArea, ShootBackArea
3\operationalLayer = "MountingPoints:Dynamic:Absolute"
4\operationalLayer = "IEDs:Dynamic:Relative"
5\operationalLayer = "BuildingOwnership:Dynamic:Relative" ;# keep ExtrusionMode (AbsoluteHeight) in mind
6\operationalLayer = "AES:Dynamic:Draped"
7\operationalLayer = "Participants:Dynamic:Relative"
8\operationalLayer = "Participants_1:Dynamic:Relative"
9\operationalLayer = "Participants_2:Dynamic:Relative"
10\operationalLayer = "Participants_3:Dynamic:Relative"
11\operationalLayer = "Participants_4:Dynamic:Relative"
12\operationalLayer = "Participants_5:Dynamic:Relative"
size=12
participantLayername = "Participants:Dynamic:Relative" ;# default: "Participants:Dynamic:Relative"
operationalLayerForCubes = "BuildingOwnership" ;# must match with an operationalLayer
[map]
# full mgrs coordinate
# East;North
#center = "32UMD9307078331" ;#QPointF(93070, 78331) -> BT56 - Bremen
center = "32UPD7671618433" ;#QPointF(76716, 18433) -> BT39 (Schulgebaeude2b) - Schnoeggersburg
center = "39RXG4344459777"
zoomFactorBase = 1.0015 ;# to configure mouse wheel for zooming, only values greater 1 and lower 1.1 will be accepted
initialScale = 4000 ;# 90000 -> Bremen ; 7000000 -> NorthGermany
# scaleMin and scaleMax (of map!) may be overwritten, if a layer is loaded manually -> to rethink
scaleMin = -1 ;# big value (e.g. 10000000) limiting zoomOut 1:10000000 -> 0.0000001
scaleMax = -1 ;# small value (e.g. 1000) limiting zoomIn 1:1000 -> 0.001
scaleHasVisibility = 70000 ;# zoom out -> some objects disappear to not overload the map
gridType = "MGRS" ;# Grid: NoType, MGRS, UTM, USGN, LatLon
animationDuration = 0.5 ;# default -> 0.5 (0< 0 -> off)
rocketDuration = 2.0 ;# default -> 2.0
[widgets]
addMapWidgets = 1
addSideBar = 1
[viewshed]
# // arcgisonline -> only demo (keep proxy in mind!)
viewshedUrl = "http://sampleserver1.arcgisonline.com/ArcGIS/rest/services/Elevation/ESRI_Elevation_World/GPServer/Viewshed" ;# // only demo!!!
[rubberband]
drawColor = "#00406e" ;# Color settings of rubberband
fillColor = "#007eC0"
handleDrawColor = "#00406e" ;# Outline color of handles
handleFillColor = "#00406e" ;# fill color of handles
selectionColor = "red" ;# fill or draw color if handle is selected
frameColor = "#00406e" ;# outline color of frame handle (bounding box)
frameFillColor = "#5043b0e0" ;# fill color of frame handle (bounding box)
frameHandleMargin = 0 ;# Margin of frame handle in pixel
previewOffset = @Point(32 32) ;# Offset of preview icon to mouse position
previewSize = 32 ;# Size of preview icon
pickingRatio = 8 ;# Size of rubberband point handles
lineHandleWidth = 4 ;# Size of rubberband line handles
# to be continued
@@ -0,0 +1,177 @@
# $Id$
# $HeadURL$
# $Author$
[license]
licenseString = "runtimestandard,1000,rud000189203,none,FAYRMD17J18S6HAZ4078" ;# 14.03.19, Fr. Jonischkeit: Aus 25er Pack für RME, bis Febr; also für Demo etc.
1\extensionString = "Exten1"
size=0
[esriNetworkCache]
enabled = 1 ;# enabled: 1=on ; 0=off, since V100.7.0
[symbology]
type = "APP6D" ;# None MIL2525D MIL2525C APP6B APP6D
extraSymbols = ":/advancedSymbology/CivilSymbols" ;# ':/advancedSymbology/CivilSymbols'
[mapUrls]
# EXCGEO01 (192.168.133.90) -> CCSAWS01
# 1\url = "URL[#<minScale>:<maxScale>]"
#Example: >>> 1\url = "http://HOSTNAME_FQDN/arcgis/rest/services/Folder/Svcname/MapServer#minScale:maxScale" <<<
#
#if the projection matches, tpk file and/or tile cache folder (win only) are supported:
#1\url = "file:Topographic.tpk#-1:125" ;# -> /usr/share/arcgis/resources/Topographic.tpk
#2\url = "file:///usr/share/arcgis/resources/World_Topo_Map.tpk#-1:125"
# WINDOWS 1\url = "file:///C:/EXTFW/resources/Guez_Topo_32632_guez_topo_32632/Guez Topographic#-1:125"
#
1\url = "http://excgeo21.sl.defence-elec.de/arcgis/rest/services/Norddeutschland/Norddeutschland_32632/MapServer#-1:125" ;# Since 2017-08-25
2\url = "http://excgeo21.sl.defence-elec.de/arcgis/rest/services/Bremen/Hemelingen_TIF_32632/MapServer" ;# Since 2017-08-25
2\url = "http://excgeo21.sl.defence-elec.de/arcgis/rest/services/Bremen/BremenHemelingenAerialGeoAmt_32632/MapServer#-1:125" ;# Since 2017-12-12
3\url = "http://excgeo21.sl.defence-elec.de/arcgis/rest/services/Bremen/BremenWerkAerialDrone_32632/MapServer#-1:125" ;# Since 2017-12-12
#1\url = "http://excgeo21.sl.defence-elec.de/arcgis/rest/services/AHTC/AHTC_32639/MapServer"
#1\url = "http://EXCGEO01:9090/geoserver/gwc/service/tms/1.0.0/workspace1:Norddeutschland_UTM@EPSG:32632@png"
#2\url = "http://EXCGEO01:6080/arcgis/rest/services/HemelingenRDE/MapServer"
#3\url = "http://excgeo01:9090/geoserver/gwc/service/tms/1.0.0/Salchau%3ASalchau_overview@EPSG%3A32632@png"
#4\url = "http://excgeo01:9090/geoserver/gwc/service/tms/1.0.0/Salchau%3ASalchau@EPSG%3A32632@png"
#3\url = "http://EXCGEO02/arcgis/rest/services/SampleWorldCities/MapServer" ;# 'SampleWorldCities' = EsriBuiltIn-Service (->ArcGISMapImageLayer)
### arcgisonline
#1\url = "http://server.arcgisonline.com/ArcGIS/rest/services/World_Topo_Map/MapServer" ;# == Basemap::topographic
#2\url = "http://server.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer"
#3\url = "http://server.arcgisonline.com/arcgis/rest/services/Ocean_Basemap/MapServer"
1\url = "file:TilePackage/Bremen/Norddeutschland_osm_32632.tpk#-1:125"
size=1
# Consulting:
# http://192.168.133.88:6080/arcgis/rest/services/Norddeutschland_Osm/MapServer
# ^^
# http://192.168.133.90:6080/arcgis/rest/services/BremenGeoTiffUTM/MapServer
#
# http://192.168.133.90:9090/geoserver/gwc/service/tms/1.0.0/workspace1:Norddeutschland_UTM@EPSG:32632@png
# http://192.168.133.90:9090/geoserver/gwc/service/tms/1.0.0/Bremen:Topo_Bremen@EPSG:32632@png
# http://192.168.133.90:9090/geoserver/gwc/service/tms/1.0.0/Bremen:Aerial_Hemelingen@EPSG:32632@png
basemapLayernamePrefix = "" ;# default: "ArcGISTiledLayer_URL_"
# For debugging only:
# an non-empty value will overwrite/skip the mapUrls:
#localMapFile = "Topographic.tpk" ;# empty (if so, try 'Topographic.tpk', 'Bremen_RME_32632.tpk')
#localMapFile = "World_Topo_Map.tpk"
# : For debugging only
[sceneUrls]
#1\url = "http://excgeo21.sl.defence-elec.de/arcgis/rest/services/Bremen/Hemelingen_TIF_WebMerc/MapServer"
1\url = "http://excgeo21.sl.defence-elec.de/arcgis/rest/services/Norddeutschland/Norddeutschland_WebMerc/MapServer#0:125" ;# Since 2017-08-25
2\url = "http://excgeo21.sl.defence-elec.de/arcgis/rest/services/Bremen/Hemelingen_TIF_WebMerc/MapServer#0:125" ;# Since 2017-08-25
#1\url = "http://excgeo21.sl.defence-elec.de/arcgis/rest/services/AHTC/AHTC_WebMerc_2/MapServer"
#1\url = "http://server.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer"
#1\url = "https://services.arcgisonline.com/ArcGIS/rest/services/World_Topo_Map/MapServer" ;# == Basemap::topographic
1\url = "file:TilePackage/Bremen/Norddeutschland_osm_WebMerc17.tpk#0:125"
size=1
[sceneObjectUrls]
# 1\url = "URL[#<altitudeOffset>]"
#Example: >>> 1\url = "file:AHTC_LOW.slpk#0.3" <<<
#Brest
#1\url = "http://scene.arcgis.com/arcgis/rest/services/Hosted/Buildings_Brest/SceneServer/layers/0" ;# Brest/France
#1\url = "http://scene.arcgis.com/arcgis/rest/services/Hosted/Buildings_Brest/SceneServer/layers" ;# Brest/France
#1\url = "http://tiles.arcgis.com/tiles/P3ePLMYs2RVChkJx/arcgis/rest/services/Buildings_Brest/SceneServer/layers/0" ;# Brest/France from Luke, no textures?
#1\url = "http://excgeo21.sl.defence-elec.de/arcgis/rest/services/Hosted/BT_56_11/SceneServer"
1\url = "http://excgeo21.sl.defence-elec.de/arcgis/rest/services/Hosted/BT56_rev576/SceneServer" ;# Since 2017-08-25
1\url = "file:BT_56_UTM_EPSG_25832.slpk"
1\url = "file:GUEZ_EPSG3857.slpk" ;# Since 2019-03-26
size=1
[elevationUrls]
#Example: >>> 1\url = "http://elevation3d.arcgis.com/arcgis/rest/services/WorldElevation3D/Terrain3D/ImageServer" <<<
#Example: >>> 1\url = "file:srtm_38_02.tif" <<< -> /usr/share/arcgis/resources/elevation/srtm_38_02.tif
#Example: >>> 1\url = "file:///shd/CTC/TOOLS/Bremen_Elevation/srtm_38_02.tif" <<<
#1\url = "http://excgeo21.sl.defence-elec.de/arcgis/rest/services/Bremen/BremenElevation/ImageServer"
1\url = "file:srtm_38_02.tif" ;# srtm_38_02.tif -> Bremen, 50m
size=1
[operationalLayer]
# "<Layername>:<Static|Dynamic>:<Draped|Absolute|Relative>"
1\operationalLayer = "Buildings:Dynamic:Draped" ;# Dynamic to avoid flicker at 3D if selection changes (MapObjectSelectionWidget), draped for fillPattern
2\operationalLayer = "TechnicalAreas:Dynamic:Draped" ;# TechnicalArea@AES (MOUTArea), TrainingArea, ShootBackArea
3\operationalLayer = "MountingPoints:Dynamic:Absolute"
4\operationalLayer = "IEDs:Dynamic:Relative"
5\operationalLayer = "BuildingOwnership:Dynamic:Relative" ;# keep ExtrusionMode (AbsoluteHeight) in mind
6\operationalLayer = "AES:Static:Draped" ;# switch to Static (NLDEVCTRL-692 'Beheben des Speicher(-leck) Problems')
7\operationalLayer = "AESCentral:Dynamic:Draped" ;# 3D-AreaEffectSimulation, draped, SubLayer 'GraphicsLayer_3D_Absolute' is absolute
8\operationalLayer = "Participants:Dynamic:Relative"
9\operationalLayer = "Participants_1:Dynamic:Relative"
10\operationalLayer = "Participants_2:Dynamic:Relative"
11\operationalLayer = "Participants_3:Dynamic:Relative"
12\operationalLayer = "Participants_4:Dynamic:Relative"
13\operationalLayer = "Participants_5:Dynamic:Relative"
size=13
participantLayername = "Participants:Dynamic:Relative" ;# default: "Participants:Dynamic:Relative"
operationalLayerForCubes = "BuildingOwnership" ;# must match with an operationalLayer
[map]
# full mgrs coordinate
# East;North
center = "32UMD9307078331" ;#QPointF(93070, 78331) -> BT56 - Bremen
#center = "32UMD9275080525" ;#QPointF(92750, 80525) -> Rennplatz - Bremen
#center = "39RXG4400060000" ;# AHTC
#center = "30UUU8935659700" ;# 30UUU9100060500 -> Brest, Chateau
zoomFactorBase = 1.0015 ;# to configure mouse wheel for zooming, only values greater 1 and lower 1.1 will be accepted
initialScale = 90000 ;# 90000 -> Bremen ; 7000000 -> NorthGermany
# scaleMin and scaleMax (of map!) may be overwritten, if a layer is loaded manually -> to rethink
scaleMin = -1 ;# big value (e.g. 10000000) limiting zoomOut 1:10000000 -> 0.0000001
scaleMax = -1 ;# small value (e.g. 1000) limiting zoomIn 1:1000 -> 0.001
scaleHasVisibility = 70000 ;# zoom out -> some objects disappear to not overload the map
gridType = "MGRS" ;# Grid: NoType, MGRS, UTM, USGN, LatLon
animationDuration = 0.5 ;# default -> 0.5 (0< 0 -> off)
rocketDuration = 2.0 ;# default -> 2.0
[widgets]
addMapWidgets = 1
addSideBar = 1
[viewshed]
# // arcgisonline -> only demo (keep proxy in mind!)
#viewshedUrl = "http://sampleserver1.arcgisonline.com/ArcGIS/rest/services/Elevation/ESRI_Elevation_World/GPServer/Viewshed" ;# // only demo!!!
viewshedUrl = "" ;# // SightFan -> not necessary
[rubberband]
drawColor = "#00406e" ;# Color settings of rubberband
fillColor = "#007eC0"
handleDrawColor = "#00406e" ;# Outline color of handles
handleFillColor = "#00406e" ;# fill color of handles
selectionColor = "red" ;# fill or draw color if handle is selected
frameColor = "#00406e" ;# outline color of frame handle (bounding box)
frameFillColor = "#5043b0e0" ;# fill color of frame handle (bounding box)
frameHandleMargin = 0 ;# Margin of frame handle in pixel
previewOffset = @Point(32 32) ;# Offset of preview icon to mouse position
previewSize = 32 ;# Size of preview icon
pickingRatio = 8 ;# Size of rubberband point handles
lineHandleWidth = 4 ;# Size of rubberband line handles
# to be continued
@@ -0,0 +1,155 @@
# $Id$
# $HeadURL$
# $Author$
[license]
licenseString = "runtimestandard,1000,rud000189203,none,FAYRMD17J18S6HAZ4078" ;# 14.03.19, Fr. Jonischkeit: Aus 25er Pack für RME, bis Febr; also für Demo etc.
1\extensionString = "Exten1"
size=0
[esriNetworkCache]
enabled = 1 ;# enabled: 1=on ; 0=off, since V100.7.0
[symbology]
type = "APP6D" ;# None MIL2525D MIL2525C APP6B APP6D
extraSymbols = ":/advancedSymbology/CivilSymbols" ;# ':/advancedSymbology/CivilSymbols'
[mapUrls]
# EXCGEO01 (192.168.133.90) -> CCSAWS01
# 1\url = "URL[#<minScale>:<maxScale>]"
#Example: >>> 1\url = "http://HOSTNAME_FQDN/arcgis/rest/services/Folder/Svcname/MapServer#minScale:maxScale" <<<
#
#if the projection matches, tpk file and/or tile cache folder (win only) are supported:
#1\url = "file:Topographic.tpk#-1:125" ;# -> /usr/share/arcgis/resources/Topographic.tpk
#2\url = "file:///usr/share/arcgis/resources/World_Topo_Map.tpk#-1:125"
# WINDOWS 1\url = "file:///C:/EXTFW/resources/Guez_Topo_32632_guez_topo_32632/Guez Topographic#-1:125"
#
1\url = "file:TilePackage/Finland/2025-03-04_Finland_Pohjankagas_Topo_1m_32634.tpk#-1:125"
2\url = "file:TilePackage/Finland/2025-03-04_Finland_Pohjankagas_Aerial_0m5_32634.tpk#-1:125"
size=2
# Consulting:
# http://192.168.133.88:6080/arcgis/rest/services/Norddeutschland_Osm/MapServer
# ^^
# http://192.168.133.90:6080/arcgis/rest/services/BremenGeoTiffUTM/MapServer
#
# http://192.168.133.90:9090/geoserver/gwc/service/tms/1.0.0/workspace1:Norddeutschland_UTM@EPSG:32632@png
# http://192.168.133.90:9090/geoserver/gwc/service/tms/1.0.0/Bremen:Topo_Bremen@EPSG:32632@png
# http://192.168.133.90:9090/geoserver/gwc/service/tms/1.0.0/Bremen:Aerial_Hemelingen@EPSG:32632@png
basemapLayernamePrefix = "" ;# default: "ArcGISTiledLayer_URL_"
# For debugging only:
# an non-empty value will overwrite/skip the mapUrls:
#localMapFile = "Topographic.tpk" ;# empty (if so, try 'Topographic.tpk', 'Bremen_RME_32632.tpk')
#localMapFile = "World_Topo_Map.tpk"
# : For debugging only
[sceneUrls]
#1\url = "http://excgeo21.sl.defence-elec.de/arcgis/rest/services/Bremen/Hemelingen_TIF_WebMerc/MapServer"
1\url = "file:TilePackage/Finland/2025-03-04_Finland_Pohjankagas_Topo_1m_WebMerc.tpk#-1:125"
2\url = "file:TilePackage/Finland/2025-03-04_Finland_Pohjankagas_Aerial_0m5_WebMerc.tpk#-1:125"
size=2
[sceneObjectUrls]
# 1\url = "URL[#<altitudeOffset>]"
#Example: >>> 1\url = "file:AHTC_LOW.slpk#0.3" <<<
#Brest
#1\url = "http://scene.arcgis.com/arcgis/rest/services/Hosted/Buildings_Brest/SceneServer/layers/0" ;# Brest/France
#1\url = "http://scene.arcgis.com/arcgis/rest/services/Hosted/Buildings_Brest/SceneServer/layers" ;# Brest/France
#1\url = "http://tiles.arcgis.com/tiles/P3ePLMYs2RVChkJx/arcgis/rest/services/Buildings_Brest/SceneServer/layers/0" ;# Brest/France from Luke, no textures?
#1\url = "http://excgeo21.sl.defence-elec.de/arcgis/rest/services/Hosted/BT_56_11/SceneServer"
#1\url = "http://excgeo21.sl.defence-elec.de/arcgis/rest/services/Hosted/BT56_rev576/SceneServer" ;# Since 2017-08-25
#1\url = "file:BT_56_UTM_EPSG_25832.slpk"
#1\url = "file:GUEZ_EPSG3857.slpk" ;# Since 2019-03-26
size=0
[elevationUrls]
#Example: >>> 1\url = "http://elevation3d.arcgis.com/arcgis/rest/services/WorldElevation3D/Terrain3D/ImageServer" <<<
#Example: >>> 1\url = "file:srtm_38_02.tif" <<< -> /usr/share/arcgis/resources/elevation/srtm_38_02.tif
#Example: >>> 1\url = "file:///shd/CTC/TOOLS/Bremen_Elevation/srtm_38_02.tif" <<<
#1\url = "http://excgeo21.sl.defence-elec.de/arcgis/rest/services/Bremen/BremenElevation/ImageServer"
1\url = "file:2025-03-06_Finland-Pohjankagas_elevation.tif"
size=1
[operationalLayer]
# "<Layername>:<Static|Dynamic>:<Draped|Absolute|Relative>"
1\operationalLayer = "Buildings:Dynamic:Draped" ;# Dynamic to avoid flicker at 3D if selection changes (MapObjectSelectionWidget), draped for fillPattern
2\operationalLayer = "TechnicalAreas:Dynamic:Draped" ;# TechnicalArea@AES (MOUTArea), TrainingArea, ShootBackArea
3\operationalLayer = "MountingPoints:Dynamic:Absolute"
4\operationalLayer = "IEDs:Dynamic:Relative"
5\operationalLayer = "BuildingOwnership:Dynamic:Relative" ;# keep ExtrusionMode (AbsoluteHeight) in mind
6\operationalLayer = "AES:Static:Draped" ;# switch to Static (NLDEVCTRL-692 'Beheben des Speicher(-leck) Problems')
7\operationalLayer = "AESCentral:Dynamic:Draped" ;# 3D-AreaEffectSimulation, draped, SubLayer 'GraphicsLayer_3D_Absolute' is absolute
8\operationalLayer = "Participants:Dynamic:Relative"
9\operationalLayer = "Participants_1:Dynamic:Relative"
10\operationalLayer = "Participants_2:Dynamic:Relative"
11\operationalLayer = "Participants_3:Dynamic:Relative"
12\operationalLayer = "Participants_4:Dynamic:Relative"
13\operationalLayer = "Participants_5:Dynamic:Relative"
size=13
participantLayername = "Participants:Dynamic:Relative" ;# default: "Participants:Dynamic:Relative"
operationalLayerForCubes = "BuildingOwnership" ;# must match with an operationalLayer
[map]
# full mgrs coordinate
# East;North
center = "32UMD9307078331" ;#QPointF(93070, 78331) -> BT56 - Bremen
center = "34VEP7780067500" ;#34 V EP 68500 55000 -> 2025 Finland Pohjankagas
#center = "32UMD9275080525" ;#QPointF(92750, 80525) -> Rennplatz - Bremen
#center = "39RXG4400060000" ;# AHTC
#center = "30UUU8935659700" ;# 30UUU9100060500 -> Brest, Chateau
zoomFactorBase = 1.0015 ;# to configure mouse wheel for zooming, only values greater 1 and lower 1.1 will be accepted
initialScale = 90000 ;# 90000 -> Bremen ; 7000000 -> NorthGermany
# scaleMin and scaleMax (of map!) may be overwritten, if a layer is loaded manually -> to rethink
scaleMin = -1 ;# big value (e.g. 10000000) limiting zoomOut 1:10000000 -> 0.0000001
scaleMax = -1 ;# small value (e.g. 1000) limiting zoomIn 1:1000 -> 0.001
scaleHasVisibility = 70000 ;# zoom out -> some objects disappear to not overload the map
gridType = "MGRS" ;# Grid: NoType, MGRS, UTM, USGN, LatLon
animationDuration = 0.5 ;# default -> 0.5 (0< 0 -> off)
rocketDuration = 2.0 ;# default -> 2.0
[widgets]
addMapWidgets = 1
addSideBar = 1
[viewshed]
# // arcgisonline -> only demo (keep proxy in mind!)
#viewshedUrl = "http://sampleserver1.arcgisonline.com/ArcGIS/rest/services/Elevation/ESRI_Elevation_World/GPServer/Viewshed" ;# // only demo!!!
viewshedUrl = "" ;# // SightFan -> not necessary
[rubberband]
drawColor = "#00406e" ;# Color settings of rubberband
fillColor = "#007eC0"
handleDrawColor = "#00406e" ;# Outline color of handles
handleFillColor = "#00406e" ;# fill color of handles
selectionColor = "red" ;# fill or draw color if handle is selected
frameColor = "#00406e" ;# outline color of frame handle (bounding box)
frameFillColor = "#5043b0e0" ;# fill color of frame handle (bounding box)
frameHandleMargin = 0 ;# Margin of frame handle in pixel
previewOffset = @Point(32 32) ;# Offset of preview icon to mouse position
previewSize = 32 ;# Size of preview icon
pickingRatio = 8 ;# Size of rubberband point handles
lineHandleWidth = 4 ;# Size of rubberband line handles
# to be continued
@@ -0,0 +1,158 @@
# $Id: situation_map_finland_pohjankagas.ini 64630 2025-03-07 08:12:36Z thoden $
# $HeadURL: svn://slssvn/TDS/branches/product/devel/trunk/Lts/Viewer/SituationMap/Map/situation_map_finland_pohjankagas.ini $
# $Author: thoden $
[license]
licenseString = "runtimestandard,1000,rud000189203,none,FAYRMD17J18S6HAZ4078" ;# 14.03.19, Fr. Jonischkeit: Aus 25er Pack für RME, bis Febr; also für Demo etc.
1\extensionString = "Exten1"
size=0
[esriNetworkCache]
enabled = 1 ;# enabled: 1=on ; 0=off, since V100.7.0
[symbology]
type = "APP6D" ;# None MIL2525D MIL2525C APP6B APP6D
extraSymbols = ":/advancedSymbology/CivilSymbols" ;# ':/advancedSymbology/CivilSymbols'
[mapUrls]
# EXCGEO01 (192.168.133.90) -> CCSAWS01
# 1\url = "URL[#<minScale>:<maxScale>]"
#Example: >>> 1\url = "http://HOSTNAME_FQDN/arcgis/rest/services/Folder/Svcname/MapServer#minScale:maxScale" <<<
#
#if the projection matches, tpk file and/or tile cache folder (win only) are supported:
#1\url = "file:Topographic.tpk#-1:125" ;# -> /usr/share/arcgis/resources/Topographic.tpk
#2\url = "file:///usr/share/arcgis/resources/World_Topo_Map.tpk#-1:125"
# WINDOWS 1\url = "file:///C:/EXTFW/resources/Guez_Topo_32632_guez_topo_32632/Guez Topographic#-1:125"
#
1\url = "file:TilePackage/Finland/2025-04-04_Finland_Pohjankagas_overview_BW_Aerial_2m_32634.tpk#-1:125"
2\url = "file:TilePackage/Finland/2025-04-04_Finland_Pohjankagas_BW_Topo_1m_32634.tpk#-1:125"
3\url = "file:TilePackage/Finland/2025-04-04_Finland_Pohjankagas_BW_Aerial_1m_32634.tpk#-1:125"
size=3
# Consulting:
# http://192.168.133.88:6080/arcgis/rest/services/Norddeutschland_Osm/MapServer
# ^^
# http://192.168.133.90:6080/arcgis/rest/services/BremenGeoTiffUTM/MapServer
#
# http://192.168.133.90:9090/geoserver/gwc/service/tms/1.0.0/workspace1:Norddeutschland_UTM@EPSG:32632@png
# http://192.168.133.90:9090/geoserver/gwc/service/tms/1.0.0/Bremen:Topo_Bremen@EPSG:32632@png
# http://192.168.133.90:9090/geoserver/gwc/service/tms/1.0.0/Bremen:Aerial_Hemelingen@EPSG:32632@png
basemapLayernamePrefix = "" ;# default: "ArcGISTiledLayer_URL_"
# For debugging only:
# an non-empty value will overwrite/skip the mapUrls:
#localMapFile = "Topographic.tpk" ;# empty (if so, try 'Topographic.tpk', 'Bremen_RME_32632.tpk')
#localMapFile = "World_Topo_Map.tpk"
# : For debugging only
[sceneUrls]
#1\url = "http://excgeo21.sl.defence-elec.de/arcgis/rest/services/Bremen/Hemelingen_TIF_WebMerc/MapServer"
1\url = "file:TilePackage/Finland/2025-04-04_Finland_Pohjankagas_overview_BW_Aerial_2m_WebMerc.tpk#-1:125"
2\url = "file:TilePackage/Finland/2025-04-04_Finland_Pohjankagas_BW_Topo_1m_WebMerc.tpk#-1:125"
3\url = "file:TilePackage/Finland/2025-04-04_Finland_Pohjankagas_BW_Aerial_1m_WebMerc.tpk#-1:125"
size=3
[sceneObjectUrls]
# 1\url = "URL[#<altitudeOffset>]"
#Example: >>> 1\url = "file:AHTC_LOW.slpk#0.3" <<<
#Brest
#1\url = "http://scene.arcgis.com/arcgis/rest/services/Hosted/Buildings_Brest/SceneServer/layers/0" ;# Brest/France
#1\url = "http://scene.arcgis.com/arcgis/rest/services/Hosted/Buildings_Brest/SceneServer/layers" ;# Brest/France
#1\url = "http://tiles.arcgis.com/tiles/P3ePLMYs2RVChkJx/arcgis/rest/services/Buildings_Brest/SceneServer/layers/0" ;# Brest/France from Luke, no textures?
#1\url = "http://excgeo21.sl.defence-elec.de/arcgis/rest/services/Hosted/BT_56_11/SceneServer"
#1\url = "http://excgeo21.sl.defence-elec.de/arcgis/rest/services/Hosted/BT56_rev576/SceneServer" ;# Since 2017-08-25
#1\url = "file:BT_56_UTM_EPSG_25832.slpk"
#1\url = "file:GUEZ_EPSG3857.slpk" ;# Since 2019-03-26
size=0
[elevationUrls]
#Example: >>> 1\url = "http://elevation3d.arcgis.com/arcgis/rest/services/WorldElevation3D/Terrain3D/ImageServer" <<<
#Example: >>> 1\url = "file:srtm_38_02.tif" <<< -> /usr/share/arcgis/resources/elevation/srtm_38_02.tif
#Example: >>> 1\url = "file:///shd/CTC/TOOLS/Bremen_Elevation/srtm_38_02.tif" <<<
#1\url = "http://excgeo21.sl.defence-elec.de/arcgis/rest/services/Bremen/BremenElevation/ImageServer"
1\url = "file:2025-03-06_Finland-Pohjankagas_elevation.tif"
size=1
[operationalLayer]
# "<Layername>:<Static|Dynamic>:<Draped|Absolute|Relative>"
1\operationalLayer = "Buildings:Dynamic:Draped" ;# Dynamic to avoid flicker at 3D if selection changes (MapObjectSelectionWidget), draped for fillPattern
2\operationalLayer = "TechnicalAreas:Dynamic:Draped" ;# TechnicalArea@AES (MOUTArea), TrainingArea, ShootBackArea
3\operationalLayer = "MountingPoints:Dynamic:Absolute"
4\operationalLayer = "IEDs:Dynamic:Relative"
5\operationalLayer = "BuildingOwnership:Dynamic:Relative" ;# keep ExtrusionMode (AbsoluteHeight) in mind
6\operationalLayer = "AES:Static:Draped" ;# switch to Static (NLDEVCTRL-692 'Beheben des Speicher(-leck) Problems')
7\operationalLayer = "AESCentral:Dynamic:Draped" ;# 3D-AreaEffectSimulation, draped, SubLayer 'GraphicsLayer_3D_Absolute' is absolute
8\operationalLayer = "Participants:Dynamic:Relative"
9\operationalLayer = "Participants_1:Dynamic:Relative"
10\operationalLayer = "Participants_2:Dynamic:Relative"
11\operationalLayer = "Participants_3:Dynamic:Relative"
12\operationalLayer = "Participants_4:Dynamic:Relative"
13\operationalLayer = "Participants_5:Dynamic:Relative"
size=13
participantLayername = "Participants:Dynamic:Relative" ;# default: "Participants:Dynamic:Relative"
operationalLayerForCubes = "BuildingOwnership" ;# must match with an operationalLayer
[map]
# full mgrs coordinate
# East;North
center = "32UMD9307078331" ;#QPointF(93070, 78331) -> BT56 - Bremen
center = "34VEP7780067500" ;#34 V EP 68500 55000 -> 2025 Finland Pohjankagas
#center = "32UMD9275080525" ;#QPointF(92750, 80525) -> Rennplatz - Bremen
#center = "39RXG4400060000" ;# AHTC
#center = "30UUU8935659700" ;# 30UUU9100060500 -> Brest, Chateau
zoomFactorBase = 1.0015 ;# to configure mouse wheel for zooming, only values greater 1 and lower 1.1 will be accepted
initialScale = 90000 ;# 90000 -> Bremen ; 7000000 -> NorthGermany
# scaleMin and scaleMax (of map!) may be overwritten, if a layer is loaded manually -> to rethink
scaleMin = -1 ;# big value (e.g. 10000000) limiting zoomOut 1:10000000 -> 0.0000001
scaleMax = -1 ;# small value (e.g. 1000) limiting zoomIn 1:1000 -> 0.001
scaleHasVisibility = 70000 ;# zoom out -> some objects disappear to not overload the map
gridType = "MGRS" ;# Grid: NoType, MGRS, UTM, USGN, LatLon
animationDuration = 0.5 ;# default -> 0.5 (0< 0 -> off)
rocketDuration = 2.0 ;# default -> 2.0
[widgets]
addMapWidgets = 1
addSideBar = 1
[viewshed]
# // arcgisonline -> only demo (keep proxy in mind!)
#viewshedUrl = "http://sampleserver1.arcgisonline.com/ArcGIS/rest/services/Elevation/ESRI_Elevation_World/GPServer/Viewshed" ;# // only demo!!!
viewshedUrl = "" ;# // SightFan -> not necessary
[rubberband]
drawColor = "#00406e" ;# Color settings of rubberband
fillColor = "#007eC0"
handleDrawColor = "#00406e" ;# Outline color of handles
handleFillColor = "#00406e" ;# fill color of handles
selectionColor = "red" ;# fill or draw color if handle is selected
frameColor = "#00406e" ;# outline color of frame handle (bounding box)
frameFillColor = "#5043b0e0" ;# fill color of frame handle (bounding box)
frameHandleMargin = 0 ;# Margin of frame handle in pixel
previewOffset = @Point(32 32) ;# Offset of preview icon to mouse position
previewSize = 32 ;# Size of preview icon
pickingRatio = 8 ;# Size of rubberband point handles
lineHandleWidth = 4 ;# Size of rubberband line handles
# to be continued
@@ -0,0 +1,160 @@
# $Id$
# $HeadURL$
# $Author$
[license]
licenseString = "runtimestandard,1000,rud000189203,none,A3C63PJPXMLDLMZ59123" ;# ESRI-BOS-Service, 05.11.2018
1\extensionString = ""
size=0
[esriNetworkCache]
enabled = 1 ;# enabled: 1=on ; 0=off, since V100.7.0
[symbology]
type = "APP6D" ;# None | MIL2525D | MIL2525C | APP6B | APP6D
extraSymbols = ":/advancedSymbology/CivilSymbols" ;# ':/advancedSymbology/CivilSymbols'
[mapUrls]
# 1\url = "URL[#<minScale>:<maxScale>]"
#Example: >>> 1\url = "http://HOSTNAME_FQDN/arcgis/rest/services/Folder/Svcname/MapServer#minScale:maxScale" <<<
#
#if the projection matches, tpk file and/or tile cache folder (win only) are supported:
#1\url = "file:Topographic.tpk#-1:125" ;# -> /usr/share/arcgis/resources/Topographic.tpk
#2\url = "file:///usr/share/arcgis/resources/World_Topo_Map.tpk#-1:125"
# WINDOWS 1\url = "file:///C:/EXTFW/resources/Guez_Topo_32632_guez_topo_32632/Guez Topographic#-1:125"
#
#For factory
#1\url = "http://ecvmgeo02/arcgis/rest/services/Norddeutschland/Norddeutschland_32632/MapServer#-1:125" ;# Since 2017-08-29
#2\url = "http://ecvmgeo02/arcgis/rest/services/Bremen/Hemelingen_TIF_32632/MapServer#-1:125" ;# Since 2017-08-29
#For on-site
1\url = "http://ecvmgeo02/arcgis/rest/services/Altmark/Altmark_Topo_2m5_32632_2018/MapServer#-1:125" ;# Since 2019-09-24
2\url = "http://ecvmgeo02/arcgis/rest/services/Altmark/Altmark_Aerial_32632_2017/MapServer#-1:125" ;# Since 2019-09-24
1\url = "file:TilePackage/Altmark/2020-07-13_Altmark_topographic2015_32632.tpk#-1:125" ;# Since 2020-07-31
2\url = "file:TilePackage/Altmark/2020-07-13_Altmark_aerial2017_32632.tpk#-1:125" ;# Since 2020-07-31
3\url = "file:TilePackage/Altmark/2022-08-23_Altmark_Schnoeggersburg_Drone_32632_Lvl11.tpk#-1:125" ;# Since 2022-08-23
#For on-site - windows
#1\url = "file:///C:/EXTFW/resources/Guez_Topo_32632_guez_topo_32632/Guez Topographic#-1:125"
#2\url = "file:///C:/EXTFW/resources/Guez_Aerial_32632_Guez_Aerial_32632/Guez Aerial#-1:125"
size=3
basemapLayernamePrefix = "" ;# default: "ArcGISTiledLayer_URL_"
# For debugging only:
# an non-empty value will overwrite/skip the mapUrls:
#localMapFile = "Topographic.tpk" ;# empty (if so, try 'Topographic.tpk')
# : For debugging only
[sceneUrls]
#For factory
#1\url = "http://ecvmgeo02/arcgis/rest/services/Norddeutschland/Norddeutschland_WebMerc/MapServer" ;# Since 2017-08-29
#2\url = "http://ecvmgeo02/arcgis/rest/services/Bremen/Hemelingen_TIF_WebMerc/MapServer" ;# Since 2017-08-29
#For on-site
1\url = "http://ecvmgeo02/arcgis/rest/services/Altmark/Altmark_Topo_2m5_WebMerc_2018/MapServer#0:125" ;# Since 2019-09-24
2\url = "http://ecvmgeo02/arcgis/rest/services/Altmark/Altmark_Aerial_WebMerc_2017/MapServer#0:125" ;# Since 2019-09-24
1\url = "file:TilePackage/Altmark/2020-07-13_Altmark_topographic2015_WebMerc.tpk#-1:125" ;# Since 2020-07-31
2\url = "file:TilePackage/Altmark/2020-07-13_Altmark_aerial2017_WebMerc.tpk#-1:125" ;# Since 2020-07-31
3\url = "file:TilePackage/Altmark/2022-08-23_Altmark_Schnoeggersburg_Drone_WebMerc_Lvl21.tpk#-1:125" ;# Since 2022-08-23
#For on-site - windows
#1\url = "file:///C:/EXTFW/resources/Guez_Topo_WebMerc_Guez_Topo_WebMerc/Guez Topographic#-1:125"
#2\url = "file:///C:/EXTFW/resources/Guez_Aerial_WebMerc_Guez_Aerial_WebMerc/Guez Aerial#-1:125"
size=3
[sceneObjectUrls]
#1\url = "http://ecvmgeo02/arcgis/rest/services/Hosted/BT56_rev576/SceneServer" ;# Since 2017-08-29 (not working yet)
1\url = "file:GUEZ_EPSG3857.slpk" ;# Since 2019-03-26
size=1
[elevationUrls]
#Example: >>> 1\url = "http://elevation3d.arcgis.com/arcgis/rest/services/WorldElevation3D/Terrain3D/ImageServer" <<<
#Example: >>> 1\url = "file:srtm_38_02.tif" <<< -> /usr/share/arcgis/resources/elevation/srtm_38_02.tif
#Example: >>> 1\url = "file:///shd/CTC/TOOLS/Bremen_Elevation/srtm_38_02.tif" <<<
#Elevation (rough_to_fine)
#1\url = "http://ecvmgeo02/arcgis/rest/services/Bremen/BremenElevation/ImageServer" ;# Since 2017-08-29
#1\url = "file:srtm_38_02.tif" ;# srtm_38_02.tif -> Bremen, 50m
#1\url = "file:n52_e011_1arc_v3.tif" ;# n52_e011_1arc_v3.tif -> Letzlingen, ??m
1\url = "file:Altmark_dt1.tif" ;# Altmark.dt1 -> Letzlingen, ~15m (0.000138)
2\url = "file:2022-08-02_Schnoeggersburg_3D-18-A317_DGM_EPSG4326_float32.tif" ;# Since 2022-08, aus Drohnebefliegung
size=2
[operationalLayer]
# "<Layername>:<Static|Dynamic>:<Draped|Absolute|Relative>"
1\operationalLayer = "Buildings:Dynamic:Draped" ;# Dynamic to avoid flicker at 3D if selection changes (MapObjectSelectionWidget), draped for fillPattern
2\operationalLayer = "TechnicalAreas:Dynamic:Draped" ;# TechnicalArea@AES (MOUTArea), TrainingArea, ShootBackArea
3\operationalLayer = "MountingPoints:Dynamic:Absolute"
4\operationalLayer = "IEDs:Dynamic:Relative"
5\operationalLayer = "BuildingOwnership:Dynamic:Relative" ;# keep ExtrusionMode (AbsoluteHeight) in mind
#6\operationalLayer = "AES:Static:Draped" ;# switch to Static (NLDEVCTRL-692 'Beheben des Speicher(-leck) Problems')
6\operationalLayer = "AES:Static:Draped" ;# for SubLayer '.._3DExtrusion' SurfacePlaement::Relative is enforced
7\operationalLayer = "AESCentral:Dynamic:Draped" ;# 3D-AreaEffectSimulation, draped, SubLayer 'GraphicsLayer_3D_Absolute' is absolute
8\operationalLayer = "Participants:Dynamic:Relative"
9\operationalLayer = "Participants_1:Dynamic:Relative"
10\operationalLayer = "Participants_2:Dynamic:Relative"
11\operationalLayer = "Participants_3:Dynamic:Relative"
12\operationalLayer = "Participants_4:Dynamic:Relative"
13\operationalLayer = "Participants_5:Dynamic:Relative"
size=13
participantLayername = "Participants:Dynamic:Relative" ;# default: "Participants:Dynamic:Relative"
operationalLayerForCubes = "BuildingOwnership" ;# must match with an operationalLayer
[map]
# full mgrs coordinate
# East;North
#center = "32UMD9307078331" ;#QPointF(93070, 78331) -> BT56 - Bremen
center = "32UPD7671618433" ;#QPointF(76716, 18433) -> BT39 (Schulgebaeude2b) - Schnoeggersburg
zoomFactorBase = 1.0015 ;# to configure mouse wheel for zooming, only values greater 1 and lower 1.1 will be accepted
initialScale = 90000 ;# 90000 -> Bremen ; 7000000 -> NorthGermany
# scaleMin and scaleMax (of map!) may be overwritten, if a layer is loaded manually -> to rethink
scaleMin = -1 ;# big value (e.g. 10000000) limiting zoomOut 1:10000000 -> 0.0000001
scaleMax = -1 ;# small value (e.g. 1000) limiting zoomIn 1:1000 -> 0.001
scaleHasVisibility = 70000 ;# zoom out -> some objects disappear to not overload the map
gridType = "MGRS" ;# Grid: NoType, MGRS, UTM, USGN, LatLon
animationDuration = 0.5 ;# default -> 0.5 (0< 0 -> off)
rocketDuration = 2.0 ;# default -> 2.0
[widgets]
addMapWidgets = 1
addSideBar = 1
[viewshed]
# // arcgisonline -> only demo (keep proxy in mind!)
viewshedUrl = "http://sampleserver1.arcgisonline.com/ArcGIS/rest/services/Elevation/ESRI_Elevation_World/GPServer/Viewshed" ;# // only demo!!!
[rubberband]
drawColor = "#00406e" ;# Color settings of rubberband
fillColor = "#007eC0"
handleDrawColor = "#00406e" ;# Outline color of handles
handleFillColor = "#00406e" ;# fill color of handles
selectionColor = "red" ;# fill or draw color if handle is selected
frameColor = "#00406e" ;# outline color of frame handle (bounding box)
frameFillColor = "#5043b0e0" ;# fill color of frame handle (bounding box)
frameHandleMargin = 0 ;# Margin of frame handle in pixel
previewOffset = @Point(32 32) ;# Offset of preview icon to mouse position
previewSize = 32 ;# Size of preview icon
pickingRatio = 8 ;# Size of rubberband point handles
lineHandleWidth = 4 ;# Size of rubberband line handles
# to be continued
@@ -0,0 +1,136 @@
# $Id$
# $HeadURL$
# $Author$
[license]
licenseString = "runtimestandard,1000,rud000189203,none,FAYRMD17J18S6HAZ4078" ;# V100.2.1, provided by Mr. Steinicke (ESRI), 23.03.2018
1\extensionString = "Exten1"
size=0
[esriNetworkCache]
enabled = 1 ;# enabled: 1=on ; 0=off, since V100.7.0
[symbology]
type = "APP6D" ;# None MIL2525D MIL2525C APP6B APP6D
extraSymbols = ":/advancedSymbology/CivilSymbols" ;# ':/advancedSymbology/CivilSymbols'
[mapUrls]
#For on-site - windows
1\url = "file:Guez_Topo_32632_guez_topo_32632/Guez Topographic#-1:125"
1\name = "Guez Topographic"
2\url = "file:Guez_Aerial_32632_Guez_Aerial_32632/Guez Aerial#-1:125"
2\name = "Guez Aerial"
3\url = "file:Guez_HotSpots_Salchau_Aerial_0m20_2017_32632#-1:125"
3\name = "HotSpots Salchau Aerial"
4\url = "file:Guez_HotSpots_Schnoeggersburg_Aerial_0m20_2017_32632#-1:125"
4\name = "HotSpots Schnoeggersburg Aerial"
size=4
basemapLayernamePrefix = "" ;# default: "ArcGISTiledLayer_URL_"
# For debugging only:
# an non-empty value will overwrite/skip the mapUrls:
#localMapFile = "Topographic.tpk" ;# empty (if so, try 'Topographic.tpk')
# : For debugging only
[sceneUrls]
#For on-site - windows
1\url = "file:Guez_Topo_WebMerc_Guez_Topo_WebMerc/Guez Topographic#-1:125"
1\name = "Guez Topographic"
2\url = "file:Guez_Aerial_WebMerc_Guez_Aerial_WebMerc/Guez Aerial#-1:125"
2\name = "Guez Aerial"
3\url = "file:Guez_HotSpots_Salchau_Aerial_0m20_2017_WebMerc#-1:125"
3\name = "HotSpots Salchau Aerial"
4\url = "file:Guez_HotSpots_Schnoeggersburg_Aerial_0m20_2017_WebMerc#-1:125"
4\name = "HotSpots Schnoeggersburg Aerial"
size=4
[sceneObjectUrls]
1\url = "file:GUEZ_BA1_EPSG3857_20181106.slpk"
size=1
[elevationUrls]
1\url = "file:Altmark_dt1.tif" ;# Altmark.dt1 -> Letzlingen, ??m
size=1
[operationalLayer]
# "<Layername>:<Static|Dynamic>:<Draped|Absolute|Relative>"
1\operationalLayer = "Buildings:Dynamic:Relative" ;# Dynamic to avoid flicker at 3D if selection changes (MapObjectSelectionWidget)
2\operationalLayer = "TechnicalAreas:Dynamic:Draped" ;# TechnicalArea@AES (MOUTArea), TrainingArea, ShootBackArea
3\operationalLayer = "MountingPoints:Dynamic:Absolute"
4\operationalLayer = "IEDs:Dynamic:Relative"
5\operationalLayer = "BuildingOwnership:Dynamic:Relative" ;# keep ExtrusionMode (AbsoluteHeight) in mind
6\operationalLayer = "AES:Dynamic:Draped"
7\operationalLayer = "AESCentral:Dynamic:Draped" ;# 3D-AreaEffectSimulation, draped, SubLayer 'GraphicsLayer_3D_Absolute' is absolute
8\operationalLayer = "Participants:Dynamic:Relative"
9\operationalLayer = "Participants_1:Dynamic:Relative"
10\operationalLayer = "Participants_2:Dynamic:Relative"
11\operationalLayer = "Participants_3:Dynamic:Relative"
12\operationalLayer = "Participants_4:Dynamic:Relative"
13\operationalLayer = "Participants_5:Dynamic:Relative"
size=13
participantLayername = "Participants:Dynamic:Relative" ;# default: "Participants:Dynamic:Relative"
operationalLayerForCubes = "BuildingOwnership" ;# must match with an operationalLayer
[map]
# full mgrs coordinate
# East;North
center = "32UPD7400013000" ;#QPointF(93070, 78331) -> BT56 - Bremen
zoomFactorBase = 1.0015 ;# to configure mouse wheel for zooming, only values greater 1 and lower 1.1 will be accepted
initialScale = 90000 ;# 90000 -> Bremen ; 7000000 -> NorthGermany
# scaleMin and scaleMax (of map!) may be overwritten, if a layer is loaded manually -> to rethink
scaleMin = -1 ;# big value (e.g. 10000000) limiting zoomOut 1:10000000 -> 0.0000001
scaleMax = -1 ;# small value (e.g. 1000) limiting zoomIn 1:1000 -> 0.001
scaleHasVisibility = 70000 ;# zoom out -> some objects disappear to not overload the map
gridType = "MGRS" ;# Grid: NoType, MGRS, UTM, USGN, LatLon
animationDuration = 0.5 ;# default -> 0.5 (0< 0 -> off)
rocketDuration = 2.0 ;# default -> 2.0
[widgets]
addMapWidgets = 1
addSideBar = 1
[viewshed]
# // arcgisonline -> only demo (keep proxy in mind!)
#viewshedUrl = "http://sampleserver1.arcgisonline.com/ArcGIS/rest/services/Elevation/ESRI_Elevation_World/GPServer/Viewshed" ;# // only demo!!!
viewshedUrl = "" ;# // SightFan -> not necessary
[rubberband]
drawColor = "#00406e" ;# Color settings of rubberband
fillColor = "#007eC0"
handleDrawColor = "#00406e" ;# Outline color of handles
handleFillColor = "#00406e" ;# fill color of handles
selectionColor = "red" ;# fill or draw color if handle is selected
frameColor = "#00406e" ;# outline color of frame handle (bounding box)
frameFillColor = "#5043b0e0" ;# fill color of frame handle (bounding box)
frameHandleMargin = 0 ;# Margin of frame handle in pixel
previewOffset = @Point(32 32) ;# Offset of preview icon to mouse position
previewSize = 32 ;# Size of preview icon
pickingRatio = 8 ;# Size of rubberband point handles
lineHandleWidth = 4 ;# Size of rubberband line handles
# to be continued
@@ -0,0 +1,179 @@
# $Id$
# $HeadURL$
# $Author$
[license]
licenseString = "runtimestandard,1000,rud000189203,none,FAYRMD17J18S6HAZ4078" ;# 14.03.19, Fr. Jonischkeit: Aus 25er Pack für RME, bis Febr; also für Demo etc.
1\extensionString = "Exten1"
size=0
[esriNetworkCache]
enabled = 1 ;# enabled: 1=on ; 0=off, since V100.7.0
[symbology]
type = "APP6D" ;# None MIL2525D MIL2525C APP6B APP6D
extraSymbols = ":/advancedSymbology/CivilSymbols" ;# ':/advancedSymbology/CivilSymbols'
[mapUrls]
# EXCGEO01 (192.168.133.90) -> CCSAWS01
# 1\url = "URL[#<minScale>:<maxScale>]"
#Example: >>> 1\url = "http://HOSTNAME_FQDN/arcgis/rest/services/Folder/Svcname/MapServer#minScale:maxScale" <<<
#
#if the projection matches, tpk file and/or tile cache folder (win only) are supported:
#1\url = "file:Topographic.tpk#-1:125" ;# -> /usr/share/arcgis/resources/Topographic.tpk
#2\url = "file:///usr/share/arcgis/resources/World_Topo_Map.tpk#-1:125"
# WINDOWS 1\url = "file:///C:/EXTFW/resources/Guez_Topo_32632_guez_topo_32632/Guez Topographic#-1:125"
#
1\url = "http://excgeo21.sl.defence-elec.de/arcgis/rest/services/Norddeutschland/Norddeutschland_32632/MapServer#-1:125" ;# Since 2017-08-25
2\url = "http://excgeo21.sl.defence-elec.de/arcgis/rest/services/Bremen/Hemelingen_TIF_32632/MapServer" ;# Since 2017-08-25
2\url = "http://excgeo21.sl.defence-elec.de/arcgis/rest/services/Bremen/BremenHemelingenAerialGeoAmt_32632/MapServer#-1:125" ;# Since 2017-12-12
3\url = "http://excgeo21.sl.defence-elec.de/arcgis/rest/services/Bremen/BremenWerkAerialDrone_32632/MapServer#-1:125" ;# Since 2017-12-12
#1\url = "http://excgeo21.sl.defence-elec.de/arcgis/rest/services/AHTC/AHTC_32639/MapServer"
#1\url = "http://EXCGEO01:9090/geoserver/gwc/service/tms/1.0.0/workspace1:Norddeutschland_UTM@EPSG:32632@png"
#2\url = "http://EXCGEO01:6080/arcgis/rest/services/HemelingenRDE/MapServer"
#3\url = "http://excgeo01:9090/geoserver/gwc/service/tms/1.0.0/Salchau%3ASalchau_overview@EPSG%3A32632@png"
#4\url = "http://excgeo01:9090/geoserver/gwc/service/tms/1.0.0/Salchau%3ASalchau@EPSG%3A32632@png"
#3\url = "http://EXCGEO02/arcgis/rest/services/SampleWorldCities/MapServer" ;# 'SampleWorldCities' = EsriBuiltIn-Service (->ArcGISMapImageLayer)
### arcgisonline
#1\url = "http://server.arcgisonline.com/ArcGIS/rest/services/World_Topo_Map/MapServer" ;# == Basemap::topographic
#2\url = "http://server.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer"
#3\url = "http://server.arcgisonline.com/arcgis/rest/services/Ocean_Basemap/MapServer"
1\url = "file:TilePackage/Hungary/2024-07-30_Hungary_Varpalota_topographic_32634.tpk#-1:125"
2\url = "file:TilePackage/Hungary/2024-07-29_Hungary_Varpalota_aerial_32634.tpk#-1:125"
size=2
# Consulting:
# http://192.168.133.88:6080/arcgis/rest/services/Norddeutschland_Osm/MapServer
# ^^
# http://192.168.133.90:6080/arcgis/rest/services/BremenGeoTiffUTM/MapServer
#
# http://192.168.133.90:9090/geoserver/gwc/service/tms/1.0.0/workspace1:Norddeutschland_UTM@EPSG:32632@png
# http://192.168.133.90:9090/geoserver/gwc/service/tms/1.0.0/Bremen:Topo_Bremen@EPSG:32632@png
# http://192.168.133.90:9090/geoserver/gwc/service/tms/1.0.0/Bremen:Aerial_Hemelingen@EPSG:32632@png
basemapLayernamePrefix = "" ;# default: "ArcGISTiledLayer_URL_"
# For debugging only:
# an non-empty value will overwrite/skip the mapUrls:
#localMapFile = "Topographic.tpk" ;# empty (if so, try 'Topographic.tpk', 'Bremen_RME_32632.tpk')
#localMapFile = "World_Topo_Map.tpk"
# : For debugging only
[sceneUrls]
#1\url = "http://excgeo21.sl.defence-elec.de/arcgis/rest/services/Bremen/Hemelingen_TIF_WebMerc/MapServer"
1\url = "http://excgeo21.sl.defence-elec.de/arcgis/rest/services/Norddeutschland/Norddeutschland_WebMerc/MapServer#0:125" ;# Since 2017-08-25
2\url = "http://excgeo21.sl.defence-elec.de/arcgis/rest/services/Bremen/Hemelingen_TIF_WebMerc/MapServer#0:125" ;# Since 2017-08-25
#1\url = "http://excgeo21.sl.defence-elec.de/arcgis/rest/services/AHTC/AHTC_WebMerc_2/MapServer"
#1\url = "http://server.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer"
#1\url = "https://services.arcgisonline.com/ArcGIS/rest/services/World_Topo_Map/MapServer" ;# == Basemap::topographic
1\url = "file:TilePackage/Hungary/2024-07-30_Hungary_Varpalota_topographic_WebMerc.tpk#-1:125"
2\url = "file:TilePackage/Hungary/2024-07-29_Hungary_Varpalota_aerial_WebMerc.tpk#-1:125"
size=2
[sceneObjectUrls]
# 1\url = "URL[#<altitudeOffset>]"
#Example: >>> 1\url = "file:AHTC_LOW.slpk#0.3" <<<
#Brest
#1\url = "http://scene.arcgis.com/arcgis/rest/services/Hosted/Buildings_Brest/SceneServer/layers/0" ;# Brest/France
#1\url = "http://scene.arcgis.com/arcgis/rest/services/Hosted/Buildings_Brest/SceneServer/layers" ;# Brest/France
#1\url = "http://tiles.arcgis.com/tiles/P3ePLMYs2RVChkJx/arcgis/rest/services/Buildings_Brest/SceneServer/layers/0" ;# Brest/France from Luke, no textures?
#1\url = "http://excgeo21.sl.defence-elec.de/arcgis/rest/services/Hosted/BT_56_11/SceneServer"
1\url = "http://excgeo21.sl.defence-elec.de/arcgis/rest/services/Hosted/BT56_rev576/SceneServer" ;# Since 2017-08-25
1\url = "file:BT_56_UTM_EPSG_25832.slpk"
1\url = "file:GUEZ_EPSG3857.slpk" ;# Since 2019-03-26
size=0
[elevationUrls]
#Example: >>> 1\url = "http://elevation3d.arcgis.com/arcgis/rest/services/WorldElevation3D/Terrain3D/ImageServer" <<<
#Example: >>> 1\url = "file:srtm_38_02.tif" <<< -> /usr/share/arcgis/resources/elevation/srtm_38_02.tif
#Example: >>> 1\url = "file:///shd/CTC/TOOLS/Bremen_Elevation/srtm_38_02.tif" <<<
#1\url = "http://excgeo21.sl.defence-elec.de/arcgis/rest/services/Bremen/BremenElevation/ImageServer"
1\url = "file:2024-07-30_Hungary_Varpalota_DDM10_WGS84.tif"
size=1
[operationalLayer]
# "<Layername>:<Static|Dynamic>:<Draped|Absolute|Relative>"
1\operationalLayer = "Buildings:Dynamic:Draped" ;# Dynamic to avoid flicker at 3D if selection changes (MapObjectSelectionWidget), draped for fillPattern
2\operationalLayer = "TechnicalAreas:Dynamic:Draped" ;# TechnicalArea@AES (MOUTArea), TrainingArea, ShootBackArea
3\operationalLayer = "MountingPoints:Dynamic:Absolute"
4\operationalLayer = "IEDs:Dynamic:Relative"
5\operationalLayer = "BuildingOwnership:Dynamic:Relative" ;# keep ExtrusionMode (AbsoluteHeight) in mind
6\operationalLayer = "AES:Static:Draped" ;# switch to Static (NLDEVCTRL-692 'Beheben des Speicher(-leck) Problems')
7\operationalLayer = "AESCentral:Dynamic:Draped" ;# 3D-AreaEffectSimulation, draped, SubLayer 'GraphicsLayer_3D_Absolute' is absolute
8\operationalLayer = "Participants:Dynamic:Relative"
9\operationalLayer = "Participants_1:Dynamic:Relative"
10\operationalLayer = "Participants_2:Dynamic:Relative"
11\operationalLayer = "Participants_3:Dynamic:Relative"
12\operationalLayer = "Participants_4:Dynamic:Relative"
13\operationalLayer = "Participants_5:Dynamic:Relative"
size=13
participantLayername = "Participants:Dynamic:Relative" ;# default: "Participants:Dynamic:Relative"
operationalLayerForCubes = "BuildingOwnership" ;# must match with an operationalLayer
[map]
# full mgrs coordinate
# East;North
center = "34 TBT 74750 25500" ;#QPointF(32000, 04000) -> Hungary, Varpalota
#center = "32UMD9275080525" ;#QPointF(92750, 80525) -> Rennplatz - Bremen
#center = "39RXG4400060000" ;# AHTC
#center = "30UUU8935659700" ;# 30UUU9100060500 -> Brest, Chateau
zoomFactorBase = 1.0015 ;# to configure mouse wheel for zooming, only values greater 1 and lower 1.1 will be accepted
initialScale = 10000 ;# 90000 -> Bremen ; 7000000 -> NorthGermany
# scaleMin and scaleMax (of map!) may be overwritten, if a layer is loaded manually -> to rethink
scaleMin = -1 ;# big value (e.g. 10000000) limiting zoomOut 1:10000000 -> 0.0000001
scaleMax = -1 ;# small value (e.g. 1000) limiting zoomIn 1:1000 -> 0.001
scaleHasVisibility = 70000 ;# zoom out -> some objects disappear to not overload the map
gridType = "MGRS" ;# Grid: NoType, MGRS, UTM, USGN, LatLon
animationDuration = 0.5 ;# default -> 0.5 (0< 0 -> off)
rocketDuration = 2.0 ;# default -> 2.0
[widgets]
addMapWidgets = 1
addSideBar = 1
[viewshed]
# // arcgisonline -> only demo (keep proxy in mind!)
#viewshedUrl = "http://sampleserver1.arcgisonline.com/ArcGIS/rest/services/Elevation/ESRI_Elevation_World/GPServer/Viewshed" ;# // only demo!!!
viewshedUrl = "" ;# // SightFan -> not necessary
[rubberband]
drawColor = "#00406e" ;# Color settings of rubberband
fillColor = "#007eC0"
handleDrawColor = "#00406e" ;# Outline color of handles
handleFillColor = "#00406e" ;# fill color of handles
selectionColor = "red" ;# fill or draw color if handle is selected
frameColor = "#00406e" ;# outline color of frame handle (bounding box)
frameFillColor = "#5043b0e0" ;# fill color of frame handle (bounding box)
frameHandleMargin = 0 ;# Margin of frame handle in pixel
previewOffset = @Point(32 32) ;# Offset of preview icon to mouse position
previewSize = 32 ;# Size of preview icon
pickingRatio = 8 ;# Size of rubberband point handles
lineHandleWidth = 4 ;# Size of rubberband line handles
# to be continued
@@ -0,0 +1,122 @@
# $Id$
# $HeadURL$
# $Author$
[license]
licenseString = "runtimeadvanced,1000,rud000500932,none,5H7LMD17J12GEBZNR016" ;# Mail David Eastman, 20.02.2019
1\extensionString = "runtimeanalysis,1000,rud000500932,none,YYPH5AZAMAG0E3CPR073" ;# Mail David Eastman, 20.02.2019
size=1
[symbology]
type = "APP6D" ;# None MIL2525D MIL2525C APP6B APP6D
#extraSymbols = ":/advancedSymbology/CivilSymbols" ;# ':/advancedSymbology/CivilSymbols'
[mapUrls]
# EXCGEO01 (192.168.133.90) -> CCSAWS01
# 1\url = "URL[#<minScale>:<maxScale>]"
#Example: >>> 1\url = "http://HOSTNAME_FQDN/arcgis/rest/services/Folder/Svcname/MapServer#minScale:maxScale" <<<
#
#if the projection matches, tpk file and/or tile cache folder (win only) are supported:
#1\url = "file:Topographic.tpk#-1:125" ;# -> /usr/share/arcgis/resources/Topographic.tpk
#2\url = "file:///usr/share/arcgis/resources/World_Topo_Map.tpk#-1:125"
# WINDOWS 1\url = "file:///C:/EXTFW/resources/Guez_Topo_32632_guez_topo_32632/Guez Topographic#-1:125"
#
1\url = "file:TilePackage/L400/2020-03-02_Cultana_aerial_0m50_32653.tpk"
size=1
basemapLayernamePrefix = "" ;# default: "ArcGISTiledLayer_URL_"
# For debugging only:
# an non-empty value will overwrite/skip the mapUrls:
#localMapFile = "Topographic.tpk" ;# empty (if so, try 'Topographic.tpk', 'Bremen_RME_32632.tpk')
#localMapFile = "World_Topo_Map.tpk"
# : For debugging only
[sceneUrls]
size=0
[sceneObjectUrls]
size=0
[elevationUrls]
#Example: >>> 1\url = "http://elevation3d.arcgis.com/arcgis/rest/services/WorldElevation3D/Terrain3D/ImageServer" <<<
#Example: >>> 1\url = "file:srtm_38_02.tif" <<< -> /usr/share/arcgis/resources/elevation/srtm_38_02.tif
#Example: >>> 1\url = "file:///shd/CTC/TOOLS/Bremen_Elevation/srtm_38_02.tif" <<<
#1\url = "http://excgeo21.sl.defence-elec.de/arcgis/rest/services/Bremen/BremenElevation/ImageServer"
1\url = "file:L400/Cultana_e137s33_TFRM.dt2" ;# 2020-03-Cultana_e137s33_TFRM.dt2 -> 25m
size=1
[operationalLayer]
# "<Layername>:<Static|Dynamic>:<Draped|Absolute|Relative>"
1\operationalLayer = "Buildings:Dynamic:Relative" ;# Dynamic to avoid flicker at 3D if selection changes (MapObjectSelectionWidget)
2\operationalLayer = "TechnicalAreas:Dynamic:Draped" ;# TechnicalArea@AES (MOUTArea), TrainingArea, ShootBackArea
3\operationalLayer = "MountingPoints:Dynamic:Absolute"
4\operationalLayer = "IEDs:Dynamic:Relative"
5\operationalLayer = "BuildingOwnership:Dynamic:Relative" ;# keep ExtrusionMode (AbsoluteHeight) in mind
6\operationalLayer = "AES:Dynamic:Draped"
7\operationalLayer = "Participants:Dynamic:Relative"
8\operationalLayer = "Participants_1:Dynamic:Relative"
9\operationalLayer = "Participants_2:Dynamic:Relative"
10\operationalLayer = "Participants_3:Dynamic:Relative"
11\operationalLayer = "Participants_4:Dynamic:Relative"
12\operationalLayer = "Participants_5:Dynamic:Relative"
size=12
participantLayername = "Participants:Dynamic:Relative" ;# default: "Participants:Dynamic:Relative"
operationalLayerForCubes = "BuildingOwnership" ;# must match with an operationalLayer
[map]
# full mgrs coordinate
# East;North
center = "53HQD3500071000"
zoomFactorBase = 1.0015 ;# to configure mouse wheel for zooming, only values greater 1 and lower 1.1 will be accepted
initialScale = 200000 ;# 90000 -> Bremen ; 7000000 -> NorthGermany
# scaleMin and scaleMax (of map!) may be overwritten, if a layer is loaded manually -> to rethink
scaleMin = -1 ;# big value (e.g. 10000000) limiting zoomOut 1:10000000 -> 0.0000001
scaleMax = -1 ;# small value (e.g. 1000) limiting zoomIn 1:1000 -> 0.001
scaleHasVisibility = 70000 ;# zoom out -> some objects disappear to not overload the map
gridType = "MGRS" ;# Grid: NoType, MGRS, UTM, USGN, LatLon
animationDuration = 0.5 ;# default -> 0.5 (0< 0 -> off)
rocketDuration = 2.0 ;# default -> 2.0
[widgets]
addMapWidgets = 1
addSideBar = 1
[viewshed]
# // arcgisonline -> only demo (keep proxy in mind!)
#viewshedUrl = "http://sampleserver1.arcgisonline.com/ArcGIS/rest/services/Elevation/ESRI_Elevation_World/GPServer/Viewshed" ;# // only demo!!!
viewshedUrl = "" ;# // SightFan -> not necessary
[rubberband]
drawColor = "#00406e" ;# Color settings of rubberband
fillColor = "#007eC0"
handleDrawColor = "#00406e" ;# Outline color of handles
handleFillColor = "#00406e" ;# fill color of handles
selectionColor = "red" ;# fill or draw color if handle is selected
frameColor = "#00406e" ;# outline color of frame handle (bounding box)
frameFillColor = "#5043b0e0" ;# fill color of frame handle (bounding box)
frameHandleMargin = 0 ;# Margin of frame handle in pixel
previewOffset = @Point(32 32) ;# Offset of preview icon to mouse position
previewSize = 32 ;# Size of preview icon
pickingRatio = 8 ;# Size of rubberband point handles
lineHandleWidth = 4 ;# Size of rubberband line handles
# to be continued
@@ -0,0 +1,122 @@
# $Id$
# $HeadURL$
# $Author$
[license]
licenseString = "runtimeadvanced,1000,rud000500932,none,5H7LMD17J12GEBZNR016" ;# Mail David Eastman, 20.02.2019
1\extensionString = "runtimeanalysis,1000,rud000500932,none,YYPH5AZAMAG0E3CPR073" ;# Mail David Eastman, 20.02.2019
size=1
[symbology]
type = "APP6D" ;# None MIL2525D MIL2525C APP6B APP6D
#extraSymbols = ":/advancedSymbology/CivilSymbols" ;# ':/advancedSymbology/CivilSymbols'
[mapUrls]
# EXCGEO01 (192.168.133.90) -> CCSAWS01
# 1\url = "URL[#<minScale>:<maxScale>]"
#Example: >>> 1\url = "http://HOSTNAME_FQDN/arcgis/rest/services/Folder/Svcname/MapServer#minScale:maxScale" <<<
#
#if the projection matches, tpk file and/or tile cache folder (win only) are supported:
#1\url = "file:Topographic.tpk#-1:125" ;# -> /usr/share/arcgis/resources/Topographic.tpk
#2\url = "file:///usr/share/arcgis/resources/World_Topo_Map.tpk#-1:125"
# WINDOWS 1\url = "file:///C:/EXTFW/resources/Guez_Topo_32632_guez_topo_32632/Guez Topographic#-1:125"
#
1\url = "file:TilePackage/L400/2020-03-02_Puckapunyal_aerial_0m20_32655.tpk"
size=1
basemapLayernamePrefix = "" ;# default: "ArcGISTiledLayer_URL_"
# For debugging only:
# an non-empty value will overwrite/skip the mapUrls:
#localMapFile = "Topographic.tpk" ;# empty (if so, try 'Topographic.tpk', 'Bremen_RME_32632.tpk')
#localMapFile = "World_Topo_Map.tpk"
# : For debugging only
[sceneUrls]
size=0
[sceneObjectUrls]
size=0
[elevationUrls]
#Example: >>> 1\url = "http://elevation3d.arcgis.com/arcgis/rest/services/WorldElevation3D/Terrain3D/ImageServer" <<<
#Example: >>> 1\url = "file:srtm_38_02.tif" <<< -> /usr/share/arcgis/resources/elevation/srtm_38_02.tif
#Example: >>> 1\url = "file:///shd/CTC/TOOLS/Bremen_Elevation/srtm_38_02.tif" <<<
#1\url = "http://excgeo21.sl.defence-elec.de/arcgis/rest/services/Bremen/BremenElevation/ImageServer"
1\url = "file:L400/2020-03-03_Puckapunyal.tif" ;# 2020-03-03_Puckapunyal.tif -> 25m
size=1
[operationalLayer]
# "<Layername>:<Static|Dynamic>:<Draped|Absolute|Relative>"
1\operationalLayer = "Buildings:Dynamic:Relative" ;# Dynamic to avoid flicker at 3D if selection changes (MapObjectSelectionWidget)
2\operationalLayer = "TechnicalAreas:Dynamic:Draped" ;# TechnicalArea@AES (MOUTArea), TrainingArea, ShootBackArea
3\operationalLayer = "MountingPoints:Dynamic:Absolute"
4\operationalLayer = "IEDs:Dynamic:Relative"
5\operationalLayer = "BuildingOwnership:Dynamic:Relative" ;# keep ExtrusionMode (AbsoluteHeight) in mind
6\operationalLayer = "AES:Dynamic:Draped"
7\operationalLayer = "Participants:Dynamic:Relative"
8\operationalLayer = "Participants_1:Dynamic:Relative"
9\operationalLayer = "Participants_2:Dynamic:Relative"
10\operationalLayer = "Participants_3:Dynamic:Relative"
11\operationalLayer = "Participants_4:Dynamic:Relative"
12\operationalLayer = "Participants_5:Dynamic:Relative"
size=12
participantLayername = "Participants:Dynamic:Relative" ;# default: "Participants:Dynamic:Relative"
operationalLayerForCubes = "BuildingOwnership" ;# must match with an operationalLayer
[map]
# full mgrs coordinate
# East;North
center = "55HCV2000012000"
zoomFactorBase = 1.0015 ;# to configure mouse wheel for zooming, only values greater 1 and lower 1.1 will be accepted
initialScale = 200000 ;# 90000 -> Bremen ; 7000000 -> NorthGermany
# scaleMin and scaleMax (of map!) may be overwritten, if a layer is loaded manually -> to rethink
scaleMin = -1 ;# big value (e.g. 10000000) limiting zoomOut 1:10000000 -> 0.0000001
scaleMax = -1 ;# small value (e.g. 1000) limiting zoomIn 1:1000 -> 0.001
scaleHasVisibility = 70000 ;# zoom out -> some objects disappear to not overload the map
gridType = "MGRS" ;# Grid: NoType, MGRS, UTM, USGN, LatLon
animationDuration = 0.5 ;# default -> 0.5 (0< 0 -> off)
rocketDuration = 2.0 ;# default -> 2.0
[widgets]
addMapWidgets = 1
addSideBar = 1
[viewshed]
# // arcgisonline -> only demo (keep proxy in mind!)
#viewshedUrl = "http://sampleserver1.arcgisonline.com/ArcGIS/rest/services/Elevation/ESRI_Elevation_World/GPServer/Viewshed" ;# // only demo!!!
viewshedUrl = "" ;# // SightFan -> not necessary
[rubberband]
drawColor = "#00406e" ;# Color settings of rubberband
fillColor = "#007eC0"
handleDrawColor = "#00406e" ;# Outline color of handles
handleFillColor = "#00406e" ;# fill color of handles
selectionColor = "red" ;# fill or draw color if handle is selected
frameColor = "#00406e" ;# outline color of frame handle (bounding box)
frameFillColor = "#5043b0e0" ;# fill color of frame handle (bounding box)
frameHandleMargin = 0 ;# Margin of frame handle in pixel
previewOffset = @Point(32 32) ;# Offset of preview icon to mouse position
previewSize = 32 ;# Size of preview icon
pickingRatio = 8 ;# Size of rubberband point handles
lineHandleWidth = 4 ;# Size of rubberband line handles
# to be continued
@@ -0,0 +1,123 @@
# $Id$
# $HeadURL$
# $Author$
[license]
licenseString = "runtimeadvanced,1000,rud000500932,none,5H7LMD17J12GEBZNR016" ;# Mail David Eastman, 20.02.2019
1\extensionString = "runtimeanalysis,1000,rud000500932,none,YYPH5AZAMAG0E3CPR073" ;# Mail David Eastman, 20.02.2019
size=1
[symbology]
type = "APP6D" ;# None MIL2525D MIL2525C APP6B APP6D
#extraSymbols = ":/advancedSymbology/CivilSymbols" ;# ':/advancedSymbology/CivilSymbols'
[mapUrls]
# EXCGEO01 (192.168.133.90) -> CCSAWS01
# 1\url = "URL[#<minScale>:<maxScale>]"
#Example: >>> 1\url = "http://HOSTNAME_FQDN/arcgis/rest/services/Folder/Svcname/MapServer#minScale:maxScale" <<<
#
#if the projection matches, tpk file and/or tile cache folder (win only) are supported:
#1\url = "file:Topographic.tpk#-1:125" ;# -> /usr/share/arcgis/resources/Topographic.tpk
#2\url = "file:///usr/share/arcgis/resources/World_Topo_Map.tpk#-1:125"
# WINDOWS 1\url = "file:///C:/EXTFW/resources/Guez_Topo_32632_guez_topo_32632/Guez Topographic#-1:125"
#
1\url = "file:TilePackage/L400/2020-03-02_SWBTA_aerial_0m20_32656.tpk"
size=1
basemapLayernamePrefix = "" ;# default: "ArcGISTiledLayer_URL_"
# For debugging only:
# an non-empty value will overwrite/skip the mapUrls:
#localMapFile = "Topographic.tpk" ;# empty (if so, try 'Topographic.tpk', 'Bremen_RME_32632.tpk')
#localMapFile = "World_Topo_Map.tpk"
# : For debugging only
[sceneUrls]
size=0
[sceneObjectUrls]
size=0
[elevationUrls]
#Example: >>> 1\url = "http://elevation3d.arcgis.com/arcgis/rest/services/WorldElevation3D/Terrain3D/ImageServer" <<<
#Example: >>> 1\url = "file:srtm_38_02.tif" <<< -> /usr/share/arcgis/resources/elevation/srtm_38_02.tif
#Example: >>> 1\url = "file:///shd/CTC/TOOLS/Bremen_Elevation/srtm_38_02.tif" <<<
#1\url = "http://excgeo21.sl.defence-elec.de/arcgis/rest/services/Bremen/BremenElevation/ImageServer"
1\url = "file:L400/SWBTA_e150s23_TFRM.dt2" ;# SWBTA_e150s23_TFRM.dt2 -> 25m
size=1
[operationalLayer]
# "<Layername>:<Static|Dynamic>:<Draped|Absolute|Relative>"
1\operationalLayer = "Buildings:Dynamic:Relative" ;# Dynamic to avoid flicker at 3D if selection changes (MapObjectSelectionWidget)
2\operationalLayer = "TechnicalAreas:Dynamic:Draped" ;# TechnicalArea@AES (MOUTArea), TrainingArea, ShootBackArea
3\operationalLayer = "MountingPoints:Dynamic:Absolute"
4\operationalLayer = "IEDs:Dynamic:Relative"
5\operationalLayer = "BuildingOwnership:Dynamic:Relative" ;# keep ExtrusionMode (AbsoluteHeight) in mind
6\operationalLayer = "AES:Dynamic:Draped"
7\operationalLayer = "Participants:Dynamic:Relative"
8\operationalLayer = "Participants_1:Dynamic:Relative"
9\operationalLayer = "Participants_2:Dynamic:Relative"
10\operationalLayer = "Participants_3:Dynamic:Relative"
11\operationalLayer = "Participants_4:Dynamic:Relative"
12\operationalLayer = "Participants_5:Dynamic:Relative"
size=12
participantLayername = "Participants:Dynamic:Relative" ;# default: "Participants:Dynamic:Relative"
operationalLayerForCubes = "BuildingOwnership" ;# must match with an operationalLayer
[map]
# full mgrs coordinate
# East;North
center = "56KKA2000000001"
zoomFactorBase = 1.0015 ;# to configure mouse wheel for zooming, only values greater 1 and lower 1.1 will be accepted
initialScale = 200000
# scaleMin and scaleMax (of map!) may be overwritten, if a layer is loaded manually -> to rethink
scaleMin = -1 ;# big value (e.g. 10000000) limiting zoomOut 1:10000000 -> 0.0000001
scaleMax = -1 ;# small value (e.g. 1000) limiting zoomIn 1:1000 -> 0.001
scaleHasVisibility = 70000 ;# zoom out -> some objects disappear to not overload the map
gridType = "MGRS" ;# Grid: NoType, MGRS, UTM, USGN, LatLon
animationDuration = 0.5 ;# default -> 0.5 (0< 0 -> off)
rocketDuration = 2.0 ;# default -> 2.0
[widgets]
addMapWidgets = 1
addSideBar = 1
[viewshed]
# // arcgisonline -> only demo (keep proxy in mind!)
#viewshedUrl = "http://sampleserver1.arcgisonline.com/ArcGIS/rest/services/Elevation/ESRI_Elevation_World/GPServer/Viewshed" ;# // only demo!!!
viewshedUrl = "" ;# // SightFan -> not necessary
[rubberband]
drawColor = "#00406e" ;# Color settings of rubberband
fillColor = "#007eC0"
handleDrawColor = "#00406e" ;# Outline color of handles
handleFillColor = "#00406e" ;# fill color of handles
selectionColor = "red" ;# fill or draw color if handle is selected
frameColor = "#00406e" ;# outline color of frame handle (bounding box)
frameFillColor = "#5043b0e0" ;# fill color of frame handle (bounding box)
frameHandleMargin = 0 ;# Margin of frame handle in pixel
previewOffset = @Point(32 32) ;# Offset of preview icon to mouse position
previewSize = 32 ;# Size of preview icon
pickingRatio = 8 ;# Size of rubberband point handles
lineHandleWidth = 4 ;# Size of rubberband line handles
# to be continued
@@ -0,0 +1,122 @@
# $Id$
# $HeadURL$
# $Author$
[license]
licenseString = "runtimeadvanced,1000,rud000500932,none,5H7LMD17J12GEBZNR016" ;# Mail David Eastman, 20.02.2019
1\extensionString = "runtimeanalysis,1000,rud000500932,none,YYPH5AZAMAG0E3CPR073" ;# Mail David Eastman, 20.02.2019
size=1
[symbology]
type = "APP6D" ;# None MIL2525D MIL2525C APP6B APP6D
#extraSymbols = ":/advancedSymbology/CivilSymbols" ;# ':/advancedSymbology/CivilSymbols'
[mapUrls]
# EXCGEO01 (192.168.133.90) -> CCSAWS01
# 1\url = "URL[#<minScale>:<maxScale>]"
#Example: >>> 1\url = "http://HOSTNAME_FQDN/arcgis/rest/services/Folder/Svcname/MapServer#minScale:maxScale" <<<
#
#if the projection matches, tpk file and/or tile cache folder (win only) are supported:
#1\url = "file:Topographic.tpk#-1:125" ;# -> /usr/share/arcgis/resources/Topographic.tpk
#2\url = "file:///usr/share/arcgis/resources/World_Topo_Map.tpk#-1:125"
# WINDOWS 1\url = "file:///C:/EXTFW/resources/Guez_Topo_32632_guez_topo_32632/Guez Topographic#-1:125"
#
1\url = "file:TilePackage/L400/2020-03-02_TFTA_aerial_0m50_32655.tpk"
size=1
basemapLayernamePrefix = "" ;# default: "ArcGISTiledLayer_URL_"
# For debugging only:
# an non-empty value will overwrite/skip the mapUrls:
#localMapFile = "Topographic.tpk" ;# empty (if so, try 'Topographic.tpk', 'Bremen_RME_32632.tpk')
#localMapFile = "World_Topo_Map.tpk"
# : For debugging only
[sceneUrls]
size=0
[sceneObjectUrls]
size=0
[elevationUrls]
#Example: >>> 1\url = "http://elevation3d.arcgis.com/arcgis/rest/services/WorldElevation3D/Terrain3D/ImageServer" <<<
#Example: >>> 1\url = "file:srtm_38_02.tif" <<< -> /usr/share/arcgis/resources/elevation/srtm_38_02.tif
#Example: >>> 1\url = "file:///shd/CTC/TOOLS/Bremen_Elevation/srtm_38_02.tif" <<<
#1\url = "http://excgeo21.sl.defence-elec.de/arcgis/rest/services/Bremen/BremenElevation/ImageServer"
1\url = "file:L400/TFTA_e146s20_TFRM.dt2" ;# 2020-03-TFTA_e146s20_TFRM.dt2 -> 25m
size=1
[operationalLayer]
# "<Layername>:<Static|Dynamic>:<Draped|Absolute|Relative>"
1\operationalLayer = "Buildings:Dynamic:Relative" ;# Dynamic to avoid flicker at 3D if selection changes (MapObjectSelectionWidget)
2\operationalLayer = "TechnicalAreas:Dynamic:Draped" ;# TechnicalArea@AES (MOUTArea), TrainingArea, ShootBackArea
3\operationalLayer = "MountingPoints:Dynamic:Absolute"
4\operationalLayer = "IEDs:Dynamic:Relative"
5\operationalLayer = "BuildingOwnership:Dynamic:Relative" ;# keep ExtrusionMode (AbsoluteHeight) in mind
6\operationalLayer = "AES:Dynamic:Draped"
7\operationalLayer = "Participants:Dynamic:Relative"
8\operationalLayer = "Participants_1:Dynamic:Relative"
9\operationalLayer = "Participants_2:Dynamic:Relative"
10\operationalLayer = "Participants_3:Dynamic:Relative"
11\operationalLayer = "Participants_4:Dynamic:Relative"
12\operationalLayer = "Participants_5:Dynamic:Relative"
size=12
participantLayername = "Participants:Dynamic:Relative" ;# default: "Participants:Dynamic:Relative"
operationalLayerForCubes = "BuildingOwnership" ;# must match with an operationalLayer
[map]
# full mgrs coordinate
# East;North
center = "55KDU3800034000"
zoomFactorBase = 1.0015 ;# to configure mouse wheel for zooming, only values greater 1 and lower 1.1 will be accepted
initialScale = 200000 ;# 90000 -> Bremen ; 7000000 -> NorthGermany
# scaleMin and scaleMax (of map!) may be overwritten, if a layer is loaded manually -> to rethink
scaleMin = -1 ;# big value (e.g. 10000000) limiting zoomOut 1:10000000 -> 0.0000001
scaleMax = -1 ;# small value (e.g. 1000) limiting zoomIn 1:1000 -> 0.001
scaleHasVisibility = 70000 ;# zoom out -> some objects disappear to not overload the map
gridType = "MGRS" ;# Grid: NoType, MGRS, UTM, USGN, LatLon
animationDuration = 0.5 ;# default -> 0.5 (0< 0 -> off)
rocketDuration = 2.0 ;# default -> 2.0
[widgets]
addMapWidgets = 1
addSideBar = 1
[viewshed]
# // arcgisonline -> only demo (keep proxy in mind!)
#viewshedUrl = "http://sampleserver1.arcgisonline.com/ArcGIS/rest/services/Elevation/ESRI_Elevation_World/GPServer/Viewshed" ;# // only demo!!!
viewshedUrl = "" ;# // SightFan -> not necessary
[rubberband]
drawColor = "#00406e" ;# Color settings of rubberband
fillColor = "#007eC0"
handleDrawColor = "#00406e" ;# Outline color of handles
handleFillColor = "#00406e" ;# fill color of handles
selectionColor = "red" ;# fill or draw color if handle is selected
frameColor = "#00406e" ;# outline color of frame handle (bounding box)
frameFillColor = "#5043b0e0" ;# fill color of frame handle (bounding box)
frameHandleMargin = 0 ;# Margin of frame handle in pixel
previewOffset = @Point(32 32) ;# Offset of preview icon to mouse position
previewSize = 32 ;# Size of preview icon
pickingRatio = 8 ;# Size of rubberband point handles
lineHandleWidth = 4 ;# Size of rubberband line handles
# to be continued
@@ -0,0 +1,152 @@
# $Id$
# $HeadURL$
# $Author$
[license]
licenseString = "runtimeadvanced,1000,rud000500932,none,5H7LMD17J12GEBZNR016" ;# Mail David Eastman, 20.02.2019
1\extensionString = "runtimeanalysis,1000,rud000500932,none,YYPH5AZAMAG0E3CPR073" ;# Mail David Eastman, 20.02.2019
size=1
[esriNetworkCache]
enabled = 0 ;# enabled: 1=on ; 0 =off, since V100.7.0
[symbology]
type = "MIL2525D" ;# None | MIL2525D | MIL2525C | APP6B
extraSymbols = ":/advancedSymbology/CivilSymbols" ;# ':/advancedSymbology/CivilSymbols'
[mapUrls]
# EXCGEO01 (192.168.133.90) -> CCSAWS01
# 1\url = "URL[#<minScale>:<maxScale>]"
#Example: >>> 1\url = "http://HOSTNAME_FQDN/arcgis/rest/services/Folder/Svcname/MapServer#minScale:maxScale" <<<
#
#if the projection matches, tpk file and/or tile cache folder (win only) are supported:
#1\url = "file:Topographic.tpk#-1:125" ;# -> /usr/share/arcgis/resources/Topographic.tpk
#2\url = "file:///usr/share/arcgis/resources/World_Topo_Map.tpk#-1:125"
# WINDOWS 1\url = "file:///C:/EXTFW/resources/Guez_Topo_32632_guez_topo_32632/Guez Topographic#-1:125"
#
#For factory
1\url = "http://excgeo21.sl.defence-elec.de/arcgis/rest/services/AHTC/AHTC_32639/MapServer"
#For on-site
#1\url = "http://e-vm-geo-2.ahtc.live/arcgis/rest/services/UAE/UaeTopographic_32639/MapServer" ;# Since 2017-11-30
#2\url = "http://e-vm-geo-2.ahtc.live/arcgis/rest/services/UAE/UaeAerial_32639/MapServer" ;# Since 2017-11-30
#For on-site - windows
# todo
size=1
basemapLayernamePrefix = "" ;# default: "ArcGISTiledLayer_URL_"
# For debugging only:
# an non-empty value will overwrite/skip the mapUrls:
localMapFile = "Topographic.tpk" ;# empty (if so, try 'Topographic.tpk')
# : For debugging only
[sceneUrls]
#For factory
1\url = "http://excgeo21.sl.defence-elec.de/arcgis/rest/services/AHTC/AHTC_WebMerc_2/MapServer"
#For on-site
#1\url = "http://e-vm-geo-2.ahtc.live/arcgis/rest/services/UAE/UaeTopographic_WebMerc/MapServer" ;# Since 2017-11-30
#2\url = "http://e-vm-geo-2.ahtc.live/arcgis/rest/services/UAE/UaeAerial_WebMerc/MapServer" ;# Since 2017-11-30
#For on-site - windows
# todo
size=1
[sceneObjectUrls]
#1\url = "http://e-vm-geo-2.ahtc.live/arcgis/rest/services/Hosted/AHTC_LOW_15_11_2017/SceneServer" ;# Since 2017-11-30
1\url = "file:///tmp/AHTC_2017-12-18_21_0_AHTC_LOW_2017_12_18_v7.slpk"
#1\url = "file:///tmp/AHTC_2018-01-30/AHTC_2018_01_29_featureclass_per_building_gdb.slpk"
#1\url = "file:///tmp/AHTC_2018-01-30/AHTC_2018_01_29_one_featureclass_gdb.slpk"
1\url = "file:AHTC_0_AHTC_LOW_2018_10_17.slpk"
1\url = "file:AHTC_LOW_2018_10_29.slpk"
1\url = "file:AHTC_LOW_2018_10_30.slpk"
1\url = "file:AHTC_LOW_2019_01_17.slpk"
1\url = "file:AHTC_LOW.slpk"
size=1
[elevationUrls]
#Example: >>> 1\url = "http://elevation3d.arcgis.com/arcgis/rest/services/WorldElevation3D/Terrain3D/ImageServer" <<<
#Example: >>> 1\url = "file:srtm_38_02.tif" <<< -> /usr/share/arcgis/resources/elevation/srtm_38_02.tif
#Example: >>> 1\url = "file:///shd/CTC/TOOLS/Bremen_Elevation/srtm_38_02.tif" <<<
#1\url = "http://ecvmgeo02/arcgis/rest/services/Bremen/BremenElevation/ImageServer" ;# Since 2017-08-29
1\url = "http://excgeo21.sl.defence-elec.de/arcgis/rest/services/ZM2/AHTC_UTM_dgm/ImageServer" ;# Z&M Testlauf03 ; 2018-02-14
1\url = "file:AHTC_utm_dgm_surface.tif" ;# Z&M
size=1
[operationalLayer]
# "<Layername>:<Static|Dynamic>:<Draped|Absolute|Relative>"
1\operationalLayer = "Buildings:Dynamic:Relative" ;# Dynamic to avoid flicker at 3D if selection changes (MapObjectSelectionWidget)
2\operationalLayer = "TechnicalAreas:Dynamic:Draped" ;# TechnicalArea@AES (MOUTArea), TrainingArea, ShootBackArea
3\operationalLayer = "MountingPoints:Dynamic:Absolute"
4\operationalLayer = "IEDs:Dynamic:Relative"
5\operationalLayer = "BuildingOwnership:Dynamic:Relative" ;# keep ExtrusionMode (AbsoluteHeight) in mind
6\operationalLayer = "AES:Dynamic:Draped"
7\operationalLayer = "Participants:Dynamic:Relative"
8\operationalLayer = "Participants_1:Dynamic:Relative"
9\operationalLayer = "Participants_2:Dynamic:Relative"
10\operationalLayer = "Participants_3:Dynamic:Relative"
11\operationalLayer = "Participants_4:Dynamic:Relative"
12\operationalLayer = "Participants_5:Dynamic:Relative"
size=12
participantLayername = "Participants:Dynamic:Relative" ;# default: "Participants:Dynamic:Relative"
operationalLayerForCubes = "BuildingOwnership" ;# must match with an operationalLayer
[map]
# full mgrs coordinate
# East;North
center = "39RXG4400060000" ;# AHTC
zoomFactorBase = 1.0015 ;# to configure mouse wheel for zooming, only values greater 1 and lower 1.1 will be accepted
initialScale = 90000 ;# 90000 -> Bremen ; 7000000 -> NorthGermany
# scaleMin and scaleMax (of map!) may be overwritten, if a layer is loaded manually -> to rethink
scaleMin = -1 ;# big value (e.g. 10000000) limiting zoomOut 1:10000000 -> 0.0000001
scaleMax = -1 ;# small value (e.g. 1000) limiting zoomIn 1:1000 -> 0.001
scaleHasVisibility = 70000 ;# zoom out -> some objects disappear to not overload the map
gridType = "MGRS" ;# Grid: NoType, MGRS, UTM, USGN, LatLon
animationDuration = 0.5 ;# default -> 0.5 (0< 0 -> off)
rocketDuration = 2.0 ;# default -> 2.0
[widgets]
addMapWidgets = 1
addSideBar = 1
[viewshed]
# // arcgisonline -> only demo (keep proxy in mind!)
viewshedUrl = "http://sampleserver1.arcgisonline.com/ArcGIS/rest/services/Elevation/ESRI_Elevation_World/GPServer/Viewshed" ;# // only demo!!!
[rubberband]
drawColor = "#00406e" ;# Color settings of rubberband
fillColor = "#007eC0"
handleDrawColor = "#00406e" ;# Outline color of handles
handleFillColor = "#00406e" ;# fill color of handles
selectionColor = "red" ;# fill or draw color if handle is selected
frameColor = "#00406e" ;# outline color of frame handle (bounding box)
frameFillColor = "#5043b0e0" ;# fill color of frame handle (bounding box)
frameHandleMargin = 0 ;# Margin of frame handle in pixel
previewOffset = @Point(32 32) ;# Offset of preview icon to mouse position
previewSize = 32 ;# Size of preview icon
pickingRatio = 8 ;# Size of rubberband point handles
lineHandleWidth = 4 ;# Size of rubberband line handles
# to be continued
@@ -0,0 +1,177 @@
# $Id$
# $HeadURL$
# $Author$
[license]
licenseString = "runtimestandard,1000,rud000189203,none,FAYRMD17J18S6HAZ4078" ;# 14.03.19, Fr. Jonischkeit: Aus 25er Pack für RME, bis Febr; also für Demo etc.
1\extensionString = "Exten1"
size=0
[esriNetworkCache]
enabled = 1 ;# enabled: 1=on ; 0=off, since V100.7.0
[symbology]
type = "APP6D" ;# None MIL2525D MIL2525C APP6B APP6D
extraSymbols = ":/advancedSymbology/CivilSymbols" ;# ':/advancedSymbology/CivilSymbols'
[mapUrls]
# EXCGEO01 (192.168.133.90) -> CCSAWS01
# 1\url = "URL[#<minScale>:<maxScale>]"
#Example: >>> 1\url = "http://HOSTNAME_FQDN/arcgis/rest/services/Folder/Svcname/MapServer#minScale:maxScale" <<<
#
#if the projection matches, tpk file and/or tile cache folder (win only) are supported:
#1\url = "file:Topographic.tpk#-1:125" ;# -> /usr/share/arcgis/resources/Topographic.tpk
#2\url = "file:///usr/share/arcgis/resources/World_Topo_Map.tpk#-1:125"
# WINDOWS 1\url = "file:///C:/EXTFW/resources/Guez_Topo_32632_guez_topo_32632/Guez Topographic#-1:125"
#
1\url = "http://excgeo21.sl.defence-elec.de/arcgis/rest/services/Norddeutschland/Norddeutschland_32632/MapServer#-1:125" ;# Since 2017-08-25
2\url = "http://excgeo21.sl.defence-elec.de/arcgis/rest/services/Bremen/Hemelingen_TIF_32632/MapServer" ;# Since 2017-08-25
2\url = "http://excgeo21.sl.defence-elec.de/arcgis/rest/services/Bremen/BremenHemelingenAerialGeoAmt_32632/MapServer#-1:125" ;# Since 2017-12-12
3\url = "http://excgeo21.sl.defence-elec.de/arcgis/rest/services/Bremen/BremenWerkAerialDrone_32632/MapServer#-1:125" ;# Since 2017-12-12
#1\url = "http://excgeo21.sl.defence-elec.de/arcgis/rest/services/AHTC/AHTC_32639/MapServer"
#1\url = "http://EXCGEO01:9090/geoserver/gwc/service/tms/1.0.0/workspace1:Norddeutschland_UTM@EPSG:32632@png"
#2\url = "http://EXCGEO01:6080/arcgis/rest/services/HemelingenRDE/MapServer"
#3\url = "http://excgeo01:9090/geoserver/gwc/service/tms/1.0.0/Salchau%3ASalchau_overview@EPSG%3A32632@png"
#4\url = "http://excgeo01:9090/geoserver/gwc/service/tms/1.0.0/Salchau%3ASalchau@EPSG%3A32632@png"
#3\url = "http://EXCGEO02/arcgis/rest/services/SampleWorldCities/MapServer" ;# 'SampleWorldCities' = EsriBuiltIn-Service (->ArcGISMapImageLayer)
### arcgisonline
#1\url = "http://server.arcgisonline.com/ArcGIS/rest/services/World_Topo_Map/MapServer" ;# == Basemap::topographic
#2\url = "http://server.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer"
#3\url = "http://server.arcgisonline.com/arcgis/rest/services/Ocean_Basemap/MapServer"
1\url = "file:TilePackage/Lithuania_Rukla/2024-07-03-Lith_Rukla_aerial_0m5_32635.tpk#-1:125"
size=1
# Consulting:
# http://192.168.133.88:6080/arcgis/rest/services/Norddeutschland_Osm/MapServer
# ^^
# http://192.168.133.90:6080/arcgis/rest/services/BremenGeoTiffUTM/MapServer
#
# http://192.168.133.90:9090/geoserver/gwc/service/tms/1.0.0/workspace1:Norddeutschland_UTM@EPSG:32632@png
# http://192.168.133.90:9090/geoserver/gwc/service/tms/1.0.0/Bremen:Topo_Bremen@EPSG:32632@png
# http://192.168.133.90:9090/geoserver/gwc/service/tms/1.0.0/Bremen:Aerial_Hemelingen@EPSG:32632@png
basemapLayernamePrefix = "" ;# default: "ArcGISTiledLayer_URL_"
# For debugging only:
# an non-empty value will overwrite/skip the mapUrls:
#localMapFile = "Topographic.tpk" ;# empty (if so, try 'Topographic.tpk', 'Bremen_RME_32632.tpk')
#localMapFile = "World_Topo_Map.tpk"
# : For debugging only
[sceneUrls]
#1\url = "http://excgeo21.sl.defence-elec.de/arcgis/rest/services/Bremen/Hemelingen_TIF_WebMerc/MapServer"
1\url = "http://excgeo21.sl.defence-elec.de/arcgis/rest/services/Norddeutschland/Norddeutschland_WebMerc/MapServer#0:125" ;# Since 2017-08-25
2\url = "http://excgeo21.sl.defence-elec.de/arcgis/rest/services/Bremen/Hemelingen_TIF_WebMerc/MapServer#0:125" ;# Since 2017-08-25
#1\url = "http://excgeo21.sl.defence-elec.de/arcgis/rest/services/AHTC/AHTC_WebMerc_2/MapServer"
#1\url = "http://server.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer"
#1\url = "https://services.arcgisonline.com/ArcGIS/rest/services/World_Topo_Map/MapServer" ;# == Basemap::topographic
1\url = "file:TilePackage/Lithuania_Rukla/2024-07-03-Lith_Rukla_aerial_0m5_WebMerc.tpk#-1:125"
size=1
[sceneObjectUrls]
# 1\url = "URL[#<altitudeOffset>]"
#Example: >>> 1\url = "file:AHTC_LOW.slpk#0.3" <<<
#Brest
#1\url = "http://scene.arcgis.com/arcgis/rest/services/Hosted/Buildings_Brest/SceneServer/layers/0" ;# Brest/France
#1\url = "http://scene.arcgis.com/arcgis/rest/services/Hosted/Buildings_Brest/SceneServer/layers" ;# Brest/France
#1\url = "http://tiles.arcgis.com/tiles/P3ePLMYs2RVChkJx/arcgis/rest/services/Buildings_Brest/SceneServer/layers/0" ;# Brest/France from Luke, no textures?
#1\url = "http://excgeo21.sl.defence-elec.de/arcgis/rest/services/Hosted/BT_56_11/SceneServer"
1\url = "http://excgeo21.sl.defence-elec.de/arcgis/rest/services/Hosted/BT56_rev576/SceneServer" ;# Since 2017-08-25
1\url = "file:BT_56_UTM_EPSG_25832.slpk"
1\url = "file:GUEZ_EPSG3857.slpk" ;# Since 2019-03-26
size=0
[elevationUrls]
#Example: >>> 1\url = "http://elevation3d.arcgis.com/arcgis/rest/services/WorldElevation3D/Terrain3D/ImageServer" <<<
#Example: >>> 1\url = "file:srtm_38_02.tif" <<< -> /usr/share/arcgis/resources/elevation/srtm_38_02.tif
#Example: >>> 1\url = "file:///shd/CTC/TOOLS/Bremen_Elevation/srtm_38_02.tif" <<<
#1\url = "http://excgeo21.sl.defence-elec.de/arcgis/rest/services/Bremen/BremenElevation/ImageServer"
1\url = "file:2024-07-03_Lith_Rukla_elevation.tif" ;# 2024-07-03_Lith_Rukla_elevation.tif -> Litauen Rukla
size=1
[operationalLayer]
# "<Layername>:<Static|Dynamic>:<Draped|Absolute|Relative>"
1\operationalLayer = "Buildings:Dynamic:Draped" ;# Dynamic to avoid flicker at 3D if selection changes (MapObjectSelectionWidget), draped for fillPattern
2\operationalLayer = "TechnicalAreas:Dynamic:Draped" ;# TechnicalArea@AES (MOUTArea), TrainingArea, ShootBackArea
3\operationalLayer = "MountingPoints:Dynamic:Absolute"
4\operationalLayer = "IEDs:Dynamic:Relative"
5\operationalLayer = "BuildingOwnership:Dynamic:Relative" ;# keep ExtrusionMode (AbsoluteHeight) in mind
6\operationalLayer = "AES:Static:Draped" ;# switch to Static (NLDEVCTRL-692 'Beheben des Speicher(-leck) Problems')
7\operationalLayer = "AESCentral:Dynamic:Draped" ;# 3D-AreaEffectSimulation, draped, SubLayer 'GraphicsLayer_3D_Absolute' is absolute
8\operationalLayer = "Participants:Dynamic:Relative"
9\operationalLayer = "Participants_1:Dynamic:Relative"
10\operationalLayer = "Participants_2:Dynamic:Relative"
11\operationalLayer = "Participants_3:Dynamic:Relative"
12\operationalLayer = "Participants_4:Dynamic:Relative"
13\operationalLayer = "Participants_5:Dynamic:Relative"
size=13
participantLayername = "Participants:Dynamic:Relative" ;# default: "Participants:Dynamic:Relative"
operationalLayerForCubes = "BuildingOwnership" ;# must match with an operationalLayer
[map]
# full mgrs coordinate
# East;North
center = "35 ULB 32000 04000" ;#QPointF(32000, 04000) -> Rukla
#center = "32UMD9275080525" ;#QPointF(92750, 80525) -> Rennplatz - Bremen
#center = "39RXG4400060000" ;# AHTC
#center = "30UUU8935659700" ;# 30UUU9100060500 -> Brest, Chateau
zoomFactorBase = 1.0015 ;# to configure mouse wheel for zooming, only values greater 1 and lower 1.1 will be accepted
initialScale = 28000 ;# 90000 -> Bremen ; 7000000 -> NorthGermany
# scaleMin and scaleMax (of map!) may be overwritten, if a layer is loaded manually -> to rethink
scaleMin = -1 ;# big value (e.g. 10000000) limiting zoomOut 1:10000000 -> 0.0000001
scaleMax = -1 ;# small value (e.g. 1000) limiting zoomIn 1:1000 -> 0.001
scaleHasVisibility = 70000 ;# zoom out -> some objects disappear to not overload the map
gridType = "MGRS" ;# Grid: NoType, MGRS, UTM, USGN, LatLon
animationDuration = 0.5 ;# default -> 0.5 (0< 0 -> off)
rocketDuration = 2.0 ;# default -> 2.0
[widgets]
addMapWidgets = 1
addSideBar = 1
[viewshed]
# // arcgisonline -> only demo (keep proxy in mind!)
#viewshedUrl = "http://sampleserver1.arcgisonline.com/ArcGIS/rest/services/Elevation/ESRI_Elevation_World/GPServer/Viewshed" ;# // only demo!!!
viewshedUrl = "" ;# // SightFan -> not necessary
[rubberband]
drawColor = "#00406e" ;# Color settings of rubberband
fillColor = "#007eC0"
handleDrawColor = "#00406e" ;# Outline color of handles
handleFillColor = "#00406e" ;# fill color of handles
selectionColor = "red" ;# fill or draw color if handle is selected
frameColor = "#00406e" ;# outline color of frame handle (bounding box)
frameFillColor = "#5043b0e0" ;# fill color of frame handle (bounding box)
frameHandleMargin = 0 ;# Margin of frame handle in pixel
previewOffset = @Point(32 32) ;# Offset of preview icon to mouse position
previewSize = 32 ;# Size of preview icon
pickingRatio = 8 ;# Size of rubberband point handles
lineHandleWidth = 4 ;# Size of rubberband line handles
# to be continued
@@ -0,0 +1,130 @@
# $Id$
# $HeadURL$
# $Author$
[license]
licenseString = "runtimestandard,1000,rud000189203,none,FAYRMD17J18S6HAZ4078" ;# 14.03.19, Fr. Jonischkeit: Aus 25er Pack für RME, bis Febr; also für Demo etc.
1\extensionString = "Exten1"
size=0
[esriNetworkCache]
enabled = 1 ;# enabled: 1=on ; 0=off, since V100.7.0
[symbology]
type = "APP6D" ;# None MIL2525D MIL2525C APP6B APP6D
extraSymbols = ":/advancedSymbology/CivilSymbols" ;# ':/advancedSymbology/CivilSymbols'
[mapUrls]
# 1\url = "URL[#<minScale>:<maxScale>]"
#Example: >>> 1\url = "http://HOSTNAME_FQDN/arcgis/rest/services/Folder/Svcname/MapServer#minScale:maxScale" <<<
#
#if the projection matches, tpk file and/or tile cache folder (win only) are supported:
#1\url = "file:Topographic.tpk#-1:125" ;# -> /usr/share/arcgis/resources/Topographic.tpk
#2\url = "file:///usr/share/arcgis/resources/World_Topo_Map.tpk#-1:125"
# WINDOWS 1\url = "file:///C:/EXTFW/resources/Guez_Topo_32632_guez_topo_32632/Guez Topographic#-1:125"
#
1\url = "file:TilePackage/Luxemburg/2023-07-10_Luxemburg_Aerial_0m1_2169_Lvl_10.tpk#-1:125" ;# 16GB
size=1
basemapLayernamePrefix = "" ;# default: "ArcGISTiledLayer_URL_"
# For debugging only:
# an non-empty value will overwrite/skip the mapUrls:
#localMapFile = "Topographic.tpk" ;# empty (if so, try 'Topographic.tpk', 'Bremen_RME_32632.tpk')
#localMapFile = "World_Topo_Map.tpk"
# : For debugging only
[sceneUrls]
1\url = "file:Topographic.tpk#-1:125" ;# 7,8GB
size=1
[sceneObjectUrls]
# 1\url = "URL[#<altitudeOffset>]"
#Example: >>> 1\url = "file:AHTC_LOW.slpk#0.3" <<<
#Brest
1\url = "file:BT_56_UTM_EPSG_25832.slpk"
size=0
[elevationUrls]
#Example: >>> 1\url = "http://elevation3d.arcgis.com/arcgis/rest/services/WorldElevation3D/Terrain3D/ImageServer" <<<
#Example: >>> 1\url = "file:srtm_38_02.tif" <<< -> /usr/share/arcgis/resources/elevation/srtm_38_02.tif
#Example: >>> 1\url = "file:///shd/CTC/TOOLS/Bremen_Elevation/srtm_38_02.tif" <<<
#1\url = "http://excgeo21.sl.defence-elec.de/arcgis/rest/services/Bremen/BremenElevation/ImageServer"
1\url = "file:2023-07-11_elevationLuxemburg.tif"
size=1
[operationalLayer]
# "<Layername>:<Static|Dynamic>:<Draped|Absolute|Relative>"
1\operationalLayer = "Buildings:Dynamic:Relative" ;# Dynamic to avoid flicker at 3D if selection changes (MapObjectSelectionWidget)
2\operationalLayer = "TechnicalAreas:Dynamic:Draped" ;# TechnicalArea@AES (MOUTArea), TrainingArea, ShootBackArea
3\operationalLayer = "MountingPoints:Dynamic:Absolute"
4\operationalLayer = "IEDs:Dynamic:Relative"
5\operationalLayer = "BuildingOwnership:Dynamic:Relative" ;# keep ExtrusionMode (AbsoluteHeight) in mind
6\operationalLayer = "AES:Static:Draped" ;# switch to Static (NLDEVCTRL-692 'Beheben des Speicher(-leck) Problems')
7\operationalLayer = "Participants:Dynamic:Relative"
8\operationalLayer = "Participants_1:Dynamic:Relative"
9\operationalLayer = "Participants_2:Dynamic:Relative"
10\operationalLayer = "Participants_3:Dynamic:Relative"
11\operationalLayer = "Participants_4:Dynamic:Relative"
12\operationalLayer = "Participants_5:Dynamic:Relative"
size=12
participantLayername = "Participants:Dynamic:Relative" ;# default: "Participants:Dynamic:Relative"
operationalLayerForCubes = "BuildingOwnership" ;# must match with an operationalLayer
[map]
# full mgrs coordinate
# East;North
center = "32UKV9284699203" ;#QPointF(92846, 99203) -> Luxemburg
center = "32UKA9000022000" ;# -> complete Luxemburg
zoomFactorBase = 1.0015 ;# to configure mouse wheel for zooming, only values greater 1 and lower 1.1 will be accepted
initialScale = 300000 ;# 90000 -> Bremen ; 300000 -> Luxemburg
# scaleMin and scaleMax (of map!) may be overwritten, if a layer is loaded manually -> to rethink
scaleMin = -1 ;# big value (e.g. 10000000) limiting zoomOut 1:10000000 -> 0.0000001
scaleMax = -1 ;# small value (e.g. 1000) limiting zoomIn 1:1000 -> 0.001
scaleHasVisibility = 70000 ;# zoom out -> some objects disappear to not overload the map
gridType = "MGRS" ;# Grid: NoType, MGRS, UTM, USGN, LatLon
animationDuration = 0.5 ;# default -> 0.5 (0< 0 -> off)
rocketDuration = 2.0 ;# default -> 2.0
[widgets]
addMapWidgets = 1
addSideBar = 1
[viewshed]
# // arcgisonline -> only demo (keep proxy in mind!)
#viewshedUrl = "http://sampleserver1.arcgisonline.com/ArcGIS/rest/services/Elevation/ESRI_Elevation_World/GPServer/Viewshed" ;# // only demo!!!
viewshedUrl = "" ;# // SightFan -> not necessary
[rubberband]
drawColor = "#00406e" ;# Color settings of rubberband
fillColor = "#007eC0"
handleDrawColor = "#00406e" ;# Outline color of handles
handleFillColor = "#00406e" ;# fill color of handles
selectionColor = "red" ;# fill or draw color if handle is selected
frameColor = "#00406e" ;# outline color of frame handle (bounding box)
frameFillColor = "#5043b0e0" ;# fill color of frame handle (bounding box)
frameHandleMargin = 0 ;# Margin of frame handle in pixel
previewOffset = @Point(32 32) ;# Offset of preview icon to mouse position
previewSize = 32 ;# Size of preview icon
pickingRatio = 8 ;# Size of rubberband point handles
lineHandleWidth = 4 ;# Size of rubberband line handles
# to be continued
@@ -0,0 +1,130 @@
# $Id$
# $HeadURL$
# $Author$
[license]
licenseString = "runtimestandard,1000,rud000189203,none,FAYRMD17J18S6HAZ4078" ;# 14.03.19, Fr. Jonischkeit: Aus 25er Pack für RME, bis Febr; also für Demo etc.
1\extensionString = "Exten1"
size=0
[esriNetworkCache]
enabled = 1 ;# enabled: 1=on ; 0=off, since V100.7.0
[symbology]
type = "APP6D" ;# None MIL2525D MIL2525C APP6B APP6D
extraSymbols = ":/advancedSymbology/CivilSymbols" ;# ':/advancedSymbology/CivilSymbols'
[mapUrls]
# 1\url = "URL[#<minScale>:<maxScale>]"
#Example: >>> 1\url = "http://HOSTNAME_FQDN/arcgis/rest/services/Folder/Svcname/MapServer#minScale:maxScale" <<<
#
#if the projection matches, tpk file and/or tile cache folder (win only) are supported:
#1\url = "file:Topographic.tpk#-1:125" ;# -> /usr/share/arcgis/resources/Topographic.tpk
#2\url = "file:///usr/share/arcgis/resources/World_Topo_Map.tpk#-1:125"
# WINDOWS 1\url = "file:///C:/EXTFW/resources/Guez_Topo_32632_guez_topo_32632/Guez Topographic#-1:125"
#
1\url = "file:TilePackage/Luxemburg/2023-07-10_Luxemburg_Aerial_0m1_2169_Lvl_10.tpk#-1:125" ;# 16GB
size=1
basemapLayernamePrefix = "" ;# default: "ArcGISTiledLayer_URL_"
# For debugging only:
# an non-empty value will overwrite/skip the mapUrls:
#localMapFile = "Topographic.tpk" ;# empty (if so, try 'Topographic.tpk', 'Bremen_RME_32632.tpk')
#localMapFile = "World_Topo_Map.tpk"
# : For debugging only
[sceneUrls]
1\url = "file:Topographic.tpk#-1:125" ;# 7,8GB
size=1
[sceneObjectUrls]
# 1\url = "URL[#<altitudeOffset>]"
#Example: >>> 1\url = "file:AHTC_LOW.slpk#0.3" <<<
#Brest
1\url = "file:BT_56_UTM_EPSG_25832.slpk"
size=0
[elevationUrls]
#Example: >>> 1\url = "http://elevation3d.arcgis.com/arcgis/rest/services/WorldElevation3D/Terrain3D/ImageServer" <<<
#Example: >>> 1\url = "file:srtm_38_02.tif" <<< -> /usr/share/arcgis/resources/elevation/srtm_38_02.tif
#Example: >>> 1\url = "file:///shd/CTC/TOOLS/Bremen_Elevation/srtm_38_02.tif" <<<
#1\url = "http://excgeo21.sl.defence-elec.de/arcgis/rest/services/Bremen/BremenElevation/ImageServer"
1\url = "file:2023-07-11_elevationLuxemburg.tif"
size=1
[operationalLayer]
# "<Layername>:<Static|Dynamic>:<Draped|Absolute|Relative>"
1\operationalLayer = "Buildings:Dynamic:Relative" ;# Dynamic to avoid flicker at 3D if selection changes (MapObjectSelectionWidget)
2\operationalLayer = "TechnicalAreas:Dynamic:Draped" ;# TechnicalArea@AES (MOUTArea), TrainingArea, ShootBackArea
3\operationalLayer = "MountingPoints:Dynamic:Absolute"
4\operationalLayer = "IEDs:Dynamic:Relative"
5\operationalLayer = "BuildingOwnership:Dynamic:Relative" ;# keep ExtrusionMode (AbsoluteHeight) in mind
6\operationalLayer = "AES:Static:Draped" ;# switch to Static (NLDEVCTRL-692 'Beheben des Speicher(-leck) Problems')
7\operationalLayer = "Participants:Dynamic:Relative"
8\operationalLayer = "Participants_1:Dynamic:Relative"
9\operationalLayer = "Participants_2:Dynamic:Relative"
10\operationalLayer = "Participants_3:Dynamic:Relative"
11\operationalLayer = "Participants_4:Dynamic:Relative"
12\operationalLayer = "Participants_5:Dynamic:Relative"
size=12
participantLayername = "Participants:Dynamic:Relative" ;# default: "Participants:Dynamic:Relative"
operationalLayerForCubes = "BuildingOwnership" ;# must match with an operationalLayer
[map]
# full mgrs coordinate
# East;North
center = "32UKV9284699203" ;#QPointF(92846, 99203) -> Luxemburg
center = "32UKA9000022000" ;# -> complete Luxemburg
zoomFactorBase = 1.0015 ;# to configure mouse wheel for zooming, only values greater 1 and lower 1.1 will be accepted
initialScale = 300000 ;# 90000 -> Bremen ; 300000 -> Luxemburg
# scaleMin and scaleMax (of map!) may be overwritten, if a layer is loaded manually -> to rethink
scaleMin = -1 ;# big value (e.g. 10000000) limiting zoomOut 1:10000000 -> 0.0000001
scaleMax = -1 ;# small value (e.g. 1000) limiting zoomIn 1:1000 -> 0.001
scaleHasVisibility = 70000 ;# zoom out -> some objects disappear to not overload the map
gridType = "MGRS" ;# Grid: NoType, MGRS, UTM, USGN, LatLon
animationDuration = 0.5 ;# default -> 0.5 (0< 0 -> off)
rocketDuration = 2.0 ;# default -> 2.0
[widgets]
addMapWidgets = 1
addSideBar = 1
[viewshed]
# // arcgisonline -> only demo (keep proxy in mind!)
#viewshedUrl = "http://sampleserver1.arcgisonline.com/ArcGIS/rest/services/Elevation/ESRI_Elevation_World/GPServer/Viewshed" ;# // only demo!!!
viewshedUrl = "" ;# // SightFan -> not necessary
[rubberband]
drawColor = "#00406e" ;# Color settings of rubberband
fillColor = "#007eC0"
handleDrawColor = "#00406e" ;# Outline color of handles
handleFillColor = "#00406e" ;# fill color of handles
selectionColor = "red" ;# fill or draw color if handle is selected
frameColor = "#00406e" ;# outline color of frame handle (bounding box)
frameFillColor = "#5043b0e0" ;# fill color of frame handle (bounding box)
frameHandleMargin = 0 ;# Margin of frame handle in pixel
previewOffset = @Point(32 32) ;# Offset of preview icon to mouse position
previewSize = 32 ;# Size of preview icon
pickingRatio = 8 ;# Size of rubberband point handles
lineHandleWidth = 4 ;# Size of rubberband line handles
# to be continued
@@ -0,0 +1,144 @@
# $Id$
# $HeadURL$
# $Author$
[license]
licenseString = "runtimestandard,1000,rud000189203,none,FAYRMD17J18S6HAZ4078" ;# 14.03.19, Fr. Jonischkeit: Aus 25er Pack für RME, bis Febr; also für Demo etc.
1\extensionString = "Exten1"
size=0
[esriNetworkCache]
enabled = 1 ;# enabled: 1=on ; 0=off, since V100.7.0
[symbology]
type = "APP6D" ;# None MIL2525D MIL2525C APP6B APP6D
extraSymbols = ":/advancedSymbology/CivilSymbols" ;# ':/advancedSymbology/CivilSymbols'
[mapUrls]
# EXCGEO01 (192.168.133.90) -> CCSAWS01
# 1\url = "URL[#<minScale>:<maxScale>]"
#Example: >>> 1\url = "http://HOSTNAME_FQDN/arcgis/rest/services/Folder/Svcname/MapServer#minScale:maxScale" <<<
#
#if the projection matches, tpk file and/or tile cache folder (win only) are supported:
#1\url = "file:Topographic.tpk#-1:125" ;# -> /usr/share/arcgis/resources/Topographic.tpk
#2\url = "file:///usr/share/arcgis/resources/World_Topo_Map.tpk#-1:125"
# WINDOWS 1\url = "file:///C:/EXTFW/resources/Guez_Topo_32632_guez_topo_32632/Guez Topographic#-1:125"
#
1\url = "file:TilePackage/Qatar/2022-06-23_Qatar_OSM_32639.vtpk#-1:125" ;# Since Since 2022
2\url = "file:TilePackage/Qatar/Qatar_Aerial_32639.tpk#-1:125" ;# Since Since 2022
3\url = "file:TilePackage/Qatar/Qatar_Aerial_Islands_32639.tpk#-1:125" ;# Since Since 2022
4\url = "file:TilePackage/Qatar/2021-12-09_Qatar_Doha_Aerial_50cm_32639_Lvl8.tpk#-1:125" ;# Since Since 2022
5\url = "file:TilePackage/Qatar/Qatar_NSA_BarzanCamp_Aerial_32639.tpk#-1:125" ;# Since Since 2022
6\url = "file:TilePackage/Qatar/2021-12-16_Qatar_ABMMC_Aerial_50cm_32639_Lvl8.tpk#-1:125" ;# Since Since 2022
size=6
basemapLayernamePrefix = "" ;# default: "ArcGISTiledLayer_URL_"
# For debugging only:
# an non-empty value will overwrite/skip the mapUrls:
#localMapFile = "Topographic.tpk" ;# empty (if so, try 'Topographic.tpk', 'Bremen_RME_32632.tpk')
#localMapFile = "World_Topo_Map.tpk"
# : For debugging only
[sceneUrls]
# !!! 2022-07: vtpk at 3d scene are support since 100.13!!!
1\url = "file:TilePackage/Qatar/2022-07-12_Qatar_OSM_WebMercator_Raster_Lvl16.tpk#-1:125" ;# Since Since 2022
2\url = "file:TilePackage/Qatar/Qatar_Aerial_WebMerc.tpk#-1:125" ;# Since Since 2022
3\url = "file:TilePackage/Qatar/Qatar_Aerial_Islands_WebMerc.tpk#-1:125" ;# Since Since 2022
4\url = "file:TilePackage/Qatar/2021-12-09_Qatar_Doha_Aerial_50cm_WebMerc_Lvl18.tpk#-1:125" ;# Since Since 2022
5\url = "file:TilePackage/Qatar/Qatar_NSA_BarzanCamp_Aerial_WebMerc.tpk#-1:125" ;# Since Since 2022
6\url = "file:TilePackage/Qatar/2021-12-16_Qatar_ABMMC_Aerial_50cm_WebMerc_Lvl18.tpk#-1:125" ;# Since Since 2022
size=6
[sceneObjectUrls]
1\url = "file:BT_56_UTM_EPSG_25832.slpk"
size=0
[elevationUrls]
#Example: >>> 1\url = "http://elevation3d.arcgis.com/arcgis/rest/services/WorldElevation3D/Terrain3D/ImageServer" <<<
#Example: >>> 1\url = "file:srtm_38_02.tif" <<< -> /usr/share/arcgis/resources/elevation/srtm_38_02.tif
#Example: >>> 1\url = "file:///shd/CTC/TOOLS/Bremen_Elevation/srtm_38_02.tif" <<<
#1\url = "http://excgeo21.sl.defence-elec.de/arcgis/rest/services/Bremen/BremenElevation/ImageServer"
1\url = "file:srtm_38_02.tif" ;# srtm_38_02.tif -> Bremen, 50m
1\url = "file:2022-07-12_Qatar_DEM_float32.tif" ;# 2022-07-12_Qatar_DEM_float32.tif -> ~30m
size=1
[operationalLayer]
# "<Layername>:<Static|Dynamic>:<Draped|Absolute|Relative>"
1\operationalLayer = "Buildings:Dynamic:Relative" ;# Dynamic to avoid flicker at 3D if selection changes (MapObjectSelectionWidget)
2\operationalLayer = "TechnicalAreas:Dynamic:Draped" ;# TechnicalArea@AES (MOUTArea), TrainingArea, ShootBackArea
3\operationalLayer = "MountingPoints:Dynamic:Absolute"
4\operationalLayer = "IEDs:Dynamic:Relative"
5\operationalLayer = "BuildingOwnership:Dynamic:Relative" ;# keep ExtrusionMode (AbsoluteHeight) in mind
6\operationalLayer = "AES:Dynamic:Draped"
7\operationalLayer = "Participants:Dynamic:Relative"
8\operationalLayer = "Participants_1:Dynamic:Relative"
9\operationalLayer = "Participants_2:Dynamic:Relative"
10\operationalLayer = "Participants_3:Dynamic:Relative"
11\operationalLayer = "Participants_4:Dynamic:Relative"
12\operationalLayer = "Participants_5:Dynamic:Relative"
size=12
participantLayername = "Participants:Dynamic:Relative" ;# default: "Participants:Dynamic:Relative"
operationalLayerForCubes = "BuildingOwnership" ;# must match with an operationalLayer
[map]
# full mgrs coordinate
# East;North
center = "39RWJ3650000500" ;#QPointF(36500, 15500) -> Qatar Bldg
zoomFactorBase = 1.0015 ;# to configure mouse wheel for zooming, only values greater 1 and lower 1.1 will be accepted
initialScale = 750000 ;# 90000 -> Bremen ; 7000000 -> NorthGermany
# scaleMin and scaleMax (of map!) may be overwritten, if a layer is loaded manually -> to rethink
scaleMin = -1 ;# big value (e.g. 10000000) limiting zoomOut 1:10000000 -> 0.0000001
scaleMax = -1 ;# small value (e.g. 1000) limiting zoomIn 1:1000 -> 0.001
scaleHasVisibility = 40000 ;# zoom out -> some objects disappear to not overload the map
gridType = "MGRS" ;# Grid: NoType, MGRS, UTM, USGN, LatLon
animationDuration = 0.5 ;# default -> 0.5 (0< 0 -> off)
rocketDuration = 2.0 ;# default -> 2.0
[widgets]
addMapWidgets = 1
addSideBar = 1
[viewshed]
# // arcgisonline -> only demo (keep proxy in mind!)
#viewshedUrl = "http://sampleserver1.arcgisonline.com/ArcGIS/rest/services/Elevation/ESRI_Elevation_World/GPServer/Viewshed" ;# // only demo!!!
viewshedUrl = "" ;# // SightFan -> not necessary
[rubberband]
drawColor = "#00406e" ;# Color settings of rubberband
fillColor = "#007eC0"
handleDrawColor = "#00406e" ;# Outline color of handles
handleFillColor = "#00406e" ;# fill color of handles
selectionColor = "red" ;# fill or draw color if handle is selected
frameColor = "#00406e" ;# outline color of frame handle (bounding box)
frameFillColor = "#5043b0e0" ;# fill color of frame handle (bounding box)
frameHandleMargin = 0 ;# Margin of frame handle in pixel
previewOffset = @Point(32 32) ;# Offset of preview icon to mouse position
previewSize = 32 ;# Size of preview icon
pickingRatio = 8 ;# Size of rubberband point handles
lineHandleWidth = 4 ;# Size of rubberband line handles
# to be continued
@@ -0,0 +1,144 @@
# $Id$
# $HeadURL$
# $Author$
[license]
licenseString = "runtimestandard,1000,rud000189203,none,FAYRMD17J18S6HAZ4078" ;# 14.03.19, Fr. Jonischkeit: Aus 25er Pack für RME, bis Febr; also für Demo etc.
1\extensionString = "Exten1"
size=0
[esriNetworkCache]
enabled = 1 ;# enabled: 1=on ; 0=off, since V100.7.0
[symbology]
type = "APP6D" ;# None MIL2525D MIL2525C APP6B APP6D
extraSymbols = ":/advancedSymbology/CivilSymbols" ;# ':/advancedSymbology/CivilSymbols'
[mapUrls]
# EXCGEO01 (192.168.133.90) -> CCSAWS01
# 1\url = "URL[#<minScale>:<maxScale>]"
#Example: >>> 1\url = "http://HOSTNAME_FQDN/arcgis/rest/services/Folder/Svcname/MapServer#minScale:maxScale" <<<
#
#if the projection matches, tpk file and/or tile cache folder (win only) are supported:
#1\url = "file:Topographic.tpk#-1:125" ;# -> /usr/share/arcgis/resources/Topographic.tpk
#2\url = "file:///usr/share/arcgis/resources/World_Topo_Map.tpk#-1:125"
# WINDOWS 1\url = "file:///C:/EXTFW/resources/Guez_Topo_32632_guez_topo_32632/Guez Topographic#-1:125"
#
1\url = "file:TilePackage/Qatar/2022-06-23_Qatar_OSM_32639.vtpk#-1:125" ;# Since Since 2022
2\url = "file:TilePackage/Qatar/Qatar_Aerial_32639.tpk#-1:125" ;# Since Since 2022
3\url = "file:TilePackage/Qatar/Qatar_Aerial_Islands_32639.tpk#-1:125" ;# Since Since 2022
4\url = "file:TilePackage/Qatar/2021-12-09_Qatar_Doha_Aerial_50cm_32639_Lvl8.tpk#-1:125" ;# Since Since 2022
5\url = "file:TilePackage/Qatar/Qatar_NSA_BarzanCamp_Aerial_32639.tpk#-1:125" ;# Since Since 2022
6\url = "file:TilePackage/Qatar/2021-12-16_Qatar_ABMMC_Aerial_50cm_32639_Lvl8.tpk#-1:125" ;# Since Since 2022
size=6
basemapLayernamePrefix = "" ;# default: "ArcGISTiledLayer_URL_"
# For debugging only:
# an non-empty value will overwrite/skip the mapUrls:
#localMapFile = "Topographic.tpk" ;# empty (if so, try 'Topographic.tpk', 'Bremen_RME_32632.tpk')
#localMapFile = "World_Topo_Map.tpk"
# : For debugging only
[sceneUrls]
# !!! 2022-07: vtpk at 3d scene are support since 100.13!!!
1\url = "file:TilePackage/Qatar/2022-07-12_Qatar_OSM_WebMercator_Raster_Lvl16.tpk#-1:125" ;# Since Since 2022
2\url = "file:TilePackage/Qatar/Qatar_Aerial_WebMerc.tpk#-1:125" ;# Since Since 2022
3\url = "file:TilePackage/Qatar/Qatar_Aerial_Islands_WebMerc.tpk#-1:125" ;# Since Since 2022
4\url = "file:TilePackage/Qatar/2021-12-09_Qatar_Doha_Aerial_50cm_WebMerc_Lvl18.tpk#-1:125" ;# Since Since 2022
5\url = "file:TilePackage/Qatar/Qatar_NSA_BarzanCamp_Aerial_WebMerc.tpk#-1:125" ;# Since Since 2022
6\url = "file:TilePackage/Qatar/2021-12-16_Qatar_ABMMC_Aerial_50cm_WebMerc_Lvl18.tpk#-1:125" ;# Since Since 2022
size=6
[sceneObjectUrls]
1\url = "file:BT_56_UTM_EPSG_25832.slpk"
size=0
[elevationUrls]
#Example: >>> 1\url = "http://elevation3d.arcgis.com/arcgis/rest/services/WorldElevation3D/Terrain3D/ImageServer" <<<
#Example: >>> 1\url = "file:srtm_38_02.tif" <<< -> /usr/share/arcgis/resources/elevation/srtm_38_02.tif
#Example: >>> 1\url = "file:///shd/CTC/TOOLS/Bremen_Elevation/srtm_38_02.tif" <<<
#1\url = "http://excgeo21.sl.defence-elec.de/arcgis/rest/services/Bremen/BremenElevation/ImageServer"
1\url = "file:srtm_38_02.tif" ;# srtm_38_02.tif -> Bremen, 50m
1\url = "file:2022-07-12_Qatar_DEM_float32.tif" ;# 2022-07-12_Qatar_DEM_float32.tif -> ~30m
size=1
[operationalLayer]
# "<Layername>:<Static|Dynamic>:<Draped|Absolute|Relative>"
1\operationalLayer = "Buildings:Dynamic:Relative" ;# Dynamic to avoid flicker at 3D if selection changes (MapObjectSelectionWidget)
2\operationalLayer = "TechnicalAreas:Dynamic:Draped" ;# TechnicalArea@AES (MOUTArea), TrainingArea, ShootBackArea
3\operationalLayer = "MountingPoints:Dynamic:Absolute"
4\operationalLayer = "IEDs:Dynamic:Relative"
5\operationalLayer = "BuildingOwnership:Dynamic:Relative" ;# keep ExtrusionMode (AbsoluteHeight) in mind
6\operationalLayer = "AES:Dynamic:Draped"
7\operationalLayer = "Participants:Dynamic:Relative"
8\operationalLayer = "Participants_1:Dynamic:Relative"
9\operationalLayer = "Participants_2:Dynamic:Relative"
10\operationalLayer = "Participants_3:Dynamic:Relative"
11\operationalLayer = "Participants_4:Dynamic:Relative"
12\operationalLayer = "Participants_5:Dynamic:Relative"
size=12
participantLayername = "Participants:Dynamic:Relative" ;# default: "Participants:Dynamic:Relative"
operationalLayerForCubes = "BuildingOwnership" ;# must match with an operationalLayer
[map]
# full mgrs coordinate
# East;North
center = "39RWJ3650000500" ;#QPointF(36500, 15500) -> Qatar Bldg
zoomFactorBase = 1.0015 ;# to configure mouse wheel for zooming, only values greater 1 and lower 1.1 will be accepted
initialScale = 750000 ;# 90000 -> Bremen ; 7000000 -> NorthGermany
# scaleMin and scaleMax (of map!) may be overwritten, if a layer is loaded manually -> to rethink
scaleMin = -1 ;# big value (e.g. 10000000) limiting zoomOut 1:10000000 -> 0.0000001
scaleMax = -1 ;# small value (e.g. 1000) limiting zoomIn 1:1000 -> 0.001
scaleHasVisibility = 40000 ;# zoom out -> some objects disappear to not overload the map
gridType = "MGRS" ;# Grid: NoType, MGRS, UTM, USGN, LatLon
animationDuration = 0.5 ;# default -> 0.5 (0< 0 -> off)
rocketDuration = 2.0 ;# default -> 2.0
[widgets]
addMapWidgets = 1
addSideBar = 1
[viewshed]
# // arcgisonline -> only demo (keep proxy in mind!)
#viewshedUrl = "http://sampleserver1.arcgisonline.com/ArcGIS/rest/services/Elevation/ESRI_Elevation_World/GPServer/Viewshed" ;# // only demo!!!
viewshedUrl = "" ;# // SightFan -> not necessary
[rubberband]
drawColor = "#00406e" ;# Color settings of rubberband
fillColor = "#007eC0"
handleDrawColor = "#00406e" ;# Outline color of handles
handleFillColor = "#00406e" ;# fill color of handles
selectionColor = "red" ;# fill or draw color if handle is selected
frameColor = "#00406e" ;# outline color of frame handle (bounding box)
frameFillColor = "#5043b0e0" ;# fill color of frame handle (bounding box)
frameHandleMargin = 0 ;# Margin of frame handle in pixel
previewOffset = @Point(32 32) ;# Offset of preview icon to mouse position
previewSize = 32 ;# Size of preview icon
pickingRatio = 8 ;# Size of rubberband point handles
lineHandleWidth = 4 ;# Size of rubberband line handles
# to be continued
@@ -303,15 +303,6 @@ struct SymbolData
*/
using PositionCont = QVector<Point3D>;
inline PositionCont convert2D3D(const QList<QPointF> &lst)
{
PositionCont posCont;
posCont.reserve(lst.size());
for (auto i : std::as_const(lst) )
posCont.append(Point3D::fromQPointF(i));
return posCont;
}
inline PositionCont convert2D3D(const QVector<QPointF> &vec)
{
PositionCont posCont;
@@ -0,0 +1,161 @@
# $Id$
# $HeadURL$
# $Author$
#-- bottom_left: 30 U WB 56700 58000 = lon, lat: -2.190721 , 51.070713 (-0.03823529444, 0.891352093191)
#-- Salisbury England
#INSERT INTO asm.asm_training_area(id, name, bottom_left_x, bottom_left_y, height, width)
# VALUES (XXX, 'Salisbury', -0.03823529444, 0.891352093191, 30000, 30000);
#-- 2D
#INSERT INTO asm.asm_map_description (id, name, description, training_area_id, map_description_type_id, map_type_id, obj_order, url, min_scale, max_scale)
# VALUES (XXX6, 'Salisbury (OSM)', 'Salisbury (OSM)', 30, 1, 1, 0, 'file:TilePackage/Salisbury/2021-09-01_Salisbury_32630.tpk', -1, 125);
[license]
licenseString = "runtimestandard,1000,rud000189203,none,A3C63PJPXMLDLMZ59123" ;# ESRI-BOS-Service, 05.11.2018
1\extensionString = ""
size=0
[esriNetworkCache]
enabled = 1 ;# enabled: 1=on ; 0=off, since V100.7.0
[symbology]
type = "APP6D" ;# None | MIL2525D | MIL2525C | APP6B | APP6D
extraSymbols = ":/advancedSymbology/CivilSymbols" ;# ':/advancedSymbology/CivilSymbols'
[mapUrls]
# 1\url = "URL[#<minScale>:<maxScale>]"
#Example: >>> 1\url = "http://HOSTNAME_FQDN/arcgis/rest/services/Folder/Svcname/MapServer#minScale:maxScale" <<<
#
#if the projection matches, tpk file and/or tile cache folder (win only) are supported:
#1\url = "file:Topographic.tpk#-1:125" ;# -> /usr/share/arcgis/resources/Topographic.tpk
#2\url = "file:///usr/share/arcgis/resources/World_Topo_Map.tpk#-1:125"
# WINDOWS 1\url = "file:///C:/EXTFW/resources/Guez_Topo_32632_guez_topo_32632/Guez Topographic#-1:125"
#
#For factory
#1\url = "http://ecvmgeo02/arcgis/rest/services/Norddeutschland/Norddeutschland_32632/MapServer#-1:125" ;# Since 2017-08-29
#2\url = "http://ecvmgeo02/arcgis/rest/services/Bremen/Hemelingen_TIF_32632/MapServer#-1:125" ;# Since 2017-08-29
#For on-site
1\url = "file:TilePackage/Unterluess/2021-10-14_Unterluess_Aerial_32632.tpk" ;# Since 2021-10-15
#For on-site - windows
#1\url = "file:///C:/EXTFW/resources/Guez_Topo_32632_guez_topo_32632/Guez Topographic#-1:125"
#2\url = "file:///C:/EXTFW/resources/Guez_Aerial_32632_Guez_Aerial_32632/Guez Aerial#-1:125"
size=1
basemapLayernamePrefix = "" ;# default: "ArcGISTiledLayer_URL_"
# For debugging only:
# an non-empty value will overwrite/skip the mapUrls:
#localMapFile = "Topographic.tpk" ;# empty (if so, try 'Topographic.tpk')
# : For debugging only
[sceneUrls]
#For factory
#1\url = "http://ecvmgeo02/arcgis/rest/services/Norddeutschland/Norddeutschland_WebMerc/MapServer" ;# Since 2017-08-29
#2\url = "http://ecvmgeo02/arcgis/rest/services/Bremen/Hemelingen_TIF_WebMerc/MapServer" ;# Since 2017-08-29
#For on-site
#For on-site - windows
#1\url = "file:///C:/EXTFW/resources/Guez_Topo_WebMerc_Guez_Topo_WebMerc/Guez Topographic#-1:125"
#2\url = "file:///C:/EXTFW/resources/Guez_Aerial_WebMerc_Guez_Aerial_WebMerc/Guez Aerial#-1:125"
1\url = "file:Topographic.tpk#-1:125"
size=1
[sceneObjectUrls]
#1\url = "http://ecvmgeo02/arcgis/rest/services/Hosted/BT56_rev576/SceneServer" ;# Since 2017-08-29 (not working yet)
1\url = "file:GUEZ_EPSG3857.slpk" ;# Since 2019-03-26
2\url = "file:GUEZ_EPSG3857.slpk" ;# Since 2019-03-26
size=0
[elevationUrls]
#Example: >>> 1\url = "http://elevation3d.arcgis.com/arcgis/rest/services/WorldElevation3D/Terrain3D/ImageServer" <<<
#Example: >>> 1\url = "file:srtm_38_02.tif" <<< -> /usr/share/arcgis/resources/elevation/srtm_38_02.tif
#Example: >>> 1\url = "file:///shd/CTC/TOOLS/Bremen_Elevation/srtm_38_02.tif" <<<
#1\url = "http://ecvmgeo02/arcgis/rest/services/Bremen/BremenElevation/ImageServer" ;# Since 2017-08-29
#1\url = "file:srtm_38_02.tif" ;# srtm_38_02.tif -> Bremen, 50m
#1\url = "file:n52_e011_1arc_v3.tif" ;# n52_e011_1arc_v3.tif -> Letzlingen, ??m
1\url = "file:e010n52_TFRM.dt2" ;# e010n52_TFRM.dt2.dt1 -> Unterlüß/Unterluess, ??m
size=1
[operationalLayer]
# "<Layername>:<Static|Dynamic>:<Draped|Absolute|Relative>"
1\operationalLayer = "Buildings:Dynamic:Relative" ;# Dynamic to avoid flicker at 3D if selection changes (MapObjectSelectionWidget)
2\operationalLayer = "TechnicalAreas:Dynamic:Draped" ;# TechnicalArea@AES (MOUTArea), TrainingArea, ShootBackArea
3\operationalLayer = "MountingPoints:Dynamic:Absolute"
4\operationalLayer = "IEDs:Dynamic:Relative"
5\operationalLayer = "BuildingOwnership:Dynamic:Relative" ;# keep ExtrusionMode (AbsoluteHeight) in mind
6\operationalLayer = "AES:Static:Draped" ;# switch to Static (NLDEVCTRL-692 'Beheben des Speicher(-leck) Problems')
7\operationalLayer = "Participants:Dynamic:Relative"
8\operationalLayer = "Participants_1:Dynamic:Relative"
9\operationalLayer = "Participants_2:Dynamic:Relative"
10\operationalLayer = "Participants_3:Dynamic:Relative"
11\operationalLayer = "Participants_4:Dynamic:Relative"
12\operationalLayer = "Participants_5:Dynamic:Relative"
size=12
participantLayername = "Participants:Dynamic:Relative" ;# default: "Participants:Dynamic:Relative"
operationalLayerForCubes = "BuildingOwnership" ;# must match with an operationalLayer
[map]
# full mgrs coordinate
# East;North
#center = "32UMD9307078331" ;#QPointF(93070, 78331) -> BT56 - Bremen
center = "32UND 86500 58100" ;#QPointF(86500, 58100) -> Unterlüß/Unterluess
zoomFactorBase = 1.0015 ;# to configure mouse wheel for zooming, only values greater 1 and lower 1.1 will be accepted
initialScale = 40000 ;# 90000 -> Bremen ; 7000000 -> NorthGermany
# scaleMin and scaleMax (of map!) may be overwritten, if a layer is loaded manually -> to rethink
scaleMin = -1 ;# big value (e.g. 10000000) limiting zoomOut 1:10000000 -> 0.0000001
scaleMax = -1 ;# small value (e.g. 1000) limiting zoomIn 1:1000 -> 0.001
scaleHasVisibility = 70000 ;# zoom out -> some objects disappear to not overload the map
gridType = "MGRS" ;# Grid: NoType, MGRS, UTM, USGN, LatLon
animationDuration = 0.5 ;# default -> 0.5 (0< 0 -> off)
rocketDuration = 2.0 ;# default -> 2.0
[widgets]
addMapWidgets = 1
addSideBar = 1
[viewshed]
# // arcgisonline -> only demo (keep proxy in mind!)
viewshedUrl = "http://sampleserver1.arcgisonline.com/ArcGIS/rest/services/Elevation/ESRI_Elevation_World/GPServer/Viewshed" ;# // only demo!!!
[rubberband]
drawColor = "#00406e" ;# Color settings of rubberband
fillColor = "#007eC0"
handleDrawColor = "#00406e" ;# Outline color of handles
handleFillColor = "#00406e" ;# fill color of handles
selectionColor = "red" ;# fill or draw color if handle is selected
frameColor = "#00406e" ;# outline color of frame handle (bounding box)
frameFillColor = "#5043b0e0" ;# fill color of frame handle (bounding box)
frameHandleMargin = 0 ;# Margin of frame handle in pixel
previewOffset = @Point(32 32) ;# Offset of preview icon to mouse position
previewSize = 32 ;# Size of preview icon
pickingRatio = 8 ;# Size of rubberband point handles
lineHandleWidth = 4 ;# Size of rubberband line handles
# to be continued
@@ -31,6 +31,9 @@
#include <QtCore/QRect>
#include <sstream>
#include <Geometry.h>
#include <Point.h>
#include <Error.h>
std::ostream &operator<< (std::ostream &stream,
@@ -378,7 +381,7 @@ QString toString(const Error &value)
{
std::ostringstream stream;
stream << "Esri::ArcGISRuntime::Error: "
<< " code=" << value.code()
<< " code=" << value.arcGISServerErrorCode().value_or(-1)
<< ", domain=" << (int)value.domain()
<< ", extendedErrorType=" << (int)value.extendedErrorType()
<< ", message='" << value.message() << "'"
@@ -496,8 +499,6 @@ QString toString(const Esri::ArcGISRuntime::LayerType value)
return QStringLiteral("FeatureLayer");
case Esri::ArcGISRuntime::LayerType::KMLLayer:
return QStringLiteral("KMLLayer");
case Esri::ArcGISRuntime::LayerType::BingMapLayer:
return QStringLiteral("BingMapLayer");
case Esri::ArcGISRuntime::LayerType::RasterLayer:
return QStringLiteral("RasterLayer");
case Esri::ArcGISRuntime::LayerType::UnsupportedLayer:
@@ -643,8 +644,6 @@ QString toString(const Esri::ArcGISRuntime::ViewpointType value)
{
switch (value)
{
case Esri::ArcGISRuntime::ViewpointType::Unknown:
return QStringLiteral("Unknown");
case Esri::ArcGISRuntime::ViewpointType::CenterAndScale:
return QStringLiteral("CenterAndScale");
case Esri::ArcGISRuntime::ViewpointType::BoundingGeometry:
@@ -696,8 +695,8 @@ QString toString(Esri::ArcGISRuntime::SurfacePlacement value)
{
switch (value)
{
case Esri::ArcGISRuntime::SurfacePlacement::Draped:
return QStringLiteral("Draped");
case Esri::ArcGISRuntime::SurfacePlacement::DrapedBillboarded:
return QStringLiteral("DrapedBillboarded");
case Esri::ArcGISRuntime::SurfacePlacement::Absolute:
return QStringLiteral("Absolute");
case Esri::ArcGISRuntime::SurfacePlacement::Relative:
@@ -13,6 +13,7 @@
// arcgis
#include <arcgisversion.h> // ACRGIS_VERSION (this file is created by RME, not ESRI)
#include <SceneViewTypes.h> // SurfacePlacement
#include <Error.h>
@@ -0,0 +1,59 @@
/**
* @RDE_HEADER@
* Interface-Implementation of AbstractEffectSimulation
* $Id$
* $HeadURL$
* $Author$
*/
// Own
#include "abstract_effect_simulation_impl.h"
#include "map_impl.h"
// ESRI
// Qt
namespace SituationMap
{
//-----------------------------------------------------------------------------
// constants
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// Utils:
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// class AbstractEffectSimulationImpl
//-----------------------------------------------------------------------------
AbstractEffectSimulationImpl::AbstractEffectSimulationImpl()
: BaseClass() // Interface
, m_logger(getLogger("AbstractEffectSimulationImpl"))
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
}
AbstractEffectSimulationImpl::~AbstractEffectSimulationImpl()
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
}
QString AbstractEffectSimulationImpl::toString() const
{
return QString();
}
} // namespace SituationMap
@@ -0,0 +1,52 @@
/**
* @RDE_HEADER@
* Interface-Implementation of AbstractEffectSimulation
* $Id$
* $HeadURL$
* $Author$
*/
#pragma once
// Own
#include "abstract_map_object_impl.h"
#include <Map/abstract_effect_simulation.h> // Interface
// ESRI
// Qt
//----------------------------------------------------------------------------
namespace SituationMap
{
// inherent 'public', to get that implementation
// inherent 'public virtual' to get that interface
class SITUATIONMAP_EXPORT AbstractEffectSimulationImpl : public virtual AbstractEffectSimulation
{
using BaseClass = SituationMap::AbstractEffectSimulation;
public:
AbstractEffectSimulationImpl();
virtual ~AbstractEffectSimulationImpl();
AbstractEffectSimulationImpl(const AbstractEffectSimulationImpl &other) = delete;
AbstractEffectSimulationImpl &operator=(AbstractEffectSimulationImpl &other) = delete;
virtual QString toString() const;
protected:
// logical
private:
LOGGER_T m_logger; ///< Interface of the Logging-Facility
};
} // namespace SituationMap
File diff suppressed because it is too large. Load diff
@@ -0,0 +1,443 @@
/**
* @RDE_HEADER@
* Implementation of AbstractMapObject
* $Id$
* $HeadURL$
* $Author$
*/
#pragma once
// Own
#include <Map/abstract_map_object.h> // Interface
#include <Map/abstract_effect_simulation.h> // for AesEffectState
#include <Map/line_style.h>
#include <Map/fill_style.h>
#include <Common/simple_value.h>
#include <Common/situation_map_logging.h>
#include <Common/ref_pointer.h>
// Qt
#include <QString>
#include <QColor>
#include <limits>
// forward:
namespace Esri
{
namespace ArcGISRuntime
{
class Graphic;
class GraphicsOverlay;
class Geometry;
}
}
//----------------------------------------------------------------------------
namespace SituationMap
{
struct ExtraData;
class MapImpl;
class MapConnector;
class AbstractGraphicalObject;
class GraphicalObjectText;
class GraphicalObjectPath;
class TacticalAppearance;
class GraphicalObjectCube;
//----------------------------------------------------------------------------
class OriginPositionChangedCallback
{
public:
virtual ~OriginPositionChangedCallback() = default;
virtual void onOriginPositionChanged() = 0;
};
//----------------------------------------------------------------------------
/**
* @brief The AbstractMapObjectImpl class is the main base class of all MapObject instances.
* Therefore it supports typical parameters/functionality and avoids redundant code.
* As consequence AbstractMapObjectImpl supports functionality, which is not used in every subclass.
* The typical parameters/functionality is:
* - UniqueMapId
* - debugInfo
* - partyId, partyColor
* - aesState (aes = AreaEffectSimulation)
* - drawOrder
* - (tact.) symbol
* - visibility (major|techn|tact.)
* - pickability
* - selected
* - mainGraphicalObject (displaying the main techn. Appearance)
* - mainGraphicalObjectText (displaying the text/name)
* - tacticalAppearance (displaying the tact. Appearance)
* - m_graphicalObjectExtrusion (displaying the extrusion (3D))
* - mainGraphicalObjectPin (displaying a pin/needle to the ground)
*
* After an parameter changes, the method updateView() hat to be called.
*/
// inherent 'public virtual' to get that interface
class SITUATIONMAP_EXPORT AbstractMapObjectImpl : public virtual AbstractMapObject
{
public:
explicit AbstractMapObjectImpl(const QString &debugInfo = QString());
virtual ~AbstractMapObjectImpl();
void removeMySelf() override;
AbstractMapObjectImpl(const AbstractMapObjectImpl &other) = delete;
AbstractMapObjectImpl &operator=(AbstractMapObjectImpl &other) = delete;
// emulate QObject::property :
bool setProperty(const char *name, const QVariant &value) override;
QVariant property(const char *name) const override;
// : emulate QObject::property
UniqueMapId uniqueMapId() const override;
QString debugInfo() const override;
void setDebugInfo(const QString &debugInfo) override;
QString toString() const override;
// Data access:
void boundingBox(BoundingBox &bbox) const override;
QColor majorColor() const override;
QString identifier() const override;
void setIdentifier(const QString &identifier) override;
bool identifierVisible() const override;
void setIdentifierVisible(bool identifierVisible) override;
int partyId() const override;
bool isPartyIdValid() const override;
void setPartyId(int partyId) override;
bool setPartyIdChanged(int partyId = -1) override;
void forcePartyColor(const QColor &partyColorToForce) override;
bool useLightColor() const override; ///< Only for Participants
void setUseLightColor(bool useLightColor) override; ///< Only for Participants
virtual AesEffectState aesState() const;
virtual void setAesState(AesEffectState aesState);
TextStyle textStyle() const override;
TextStyle &rTextStyle() override;
void setTextStyle(const TextStyle &textStyle) override;
virtual LineStyle lineStyle() const;
virtual LineStyle &rLineStyle();
virtual void setLineStyle(const LineStyle &lineStyle);
virtual FillStyle fillStyle() const;
virtual FillStyle &rFillStyle();
virtual void setFillStyle(const FillStyle &fillStyle);
// Scale :
float scale() const override;
void setScale(float scale) override;
bool isScaleEnabled() const override;
void setScaleEnable(bool enabled) override;
// : Scale
// Layer
QString layer() const override;
int drawOrder() const override;
/**
* @brief Set drawOrder.
* Caused by internal dependencies, the value MUST within -3000...+3000. (INT_MAX=+32767 / 10 = 3276 -> ~3000).
* \n Otherwise the internal graphics will be disordered.
* \internal Background: Due to missing relative drawOrder an absolute drawOrder has to be used.\n
* To create an absolute drawOrder the specified drawOrder is multiplied with 10.
* The components (usually GraphicalObjects) receive that multiplied valued added by s small offset.
* drawOrder() is not influenced by this and will return the value you set before.
* @param drawOrder new value.
*/
void setDrawOrder(int drawOrder) override;
// Visibility :
// Prio 1:
bool visibility() const override;
void setVisibility(bool visibility) override;
// Prio 2
bool visibility(ObjectAppearance appearance) const override;
void setVisibility(ObjectAppearance appearance, bool visibility) override;
bool visibilityOfGeometry() const;
void setVisibilityOfGeometry(bool visiGeometry);
// : Visibility
// Selection, Picking :
bool selected() const override;
void setSelected(bool selected) override;
bool pickable() const override;
void setPickable(bool pickable) override;
// : Selection, Picking
// Symbol :
SymbolData symbol() const override;
void setSymbol(const SymbolData &symbol) override;
void reRenderSymbol() override;
SymbolDataToRender symbolDataToRender() const override;
SymbolImage symbolImage() const override;
QImage previewImage() const override;
QImage previewImageTypical() const override;
QImage previewImageSpecific() const override;
void setForceMajorColor(const QColor &majorColor) override;
// : Symbol
/*! \name Some methods regarding extrusion (renderer approach) */
//@{
double extrusionHeight() const override;
void setExtrusionHeight(double extrusionHeight = std::nan("")) override;
bool extrusionHeightValid() const;
const QString extrusionColorName() const override;
void setExtrusionColorName(const QString &extrusionColorName) override;
//@}
// Geometry :
bool geometryIntersect(const MathUtils::GeometryEngine::Geometry &intersector_polyline) const override;
bool geometryIsInHull(const MathUtils::GeometryEngine::Geometry &hull_polygon) const override;
Esri::ArcGISRuntime::Geometry getEsriGeometry() const;
// : Geometry
// Define default text style for all MapObjects:
static TextStyle defaultTextStyle();
/**
* @brief updateView
* transfer values to view
* @return true on success
*/
bool updateView() override
{
return updateViewImplPre() && updateViewImpl() && updateViewImplPost();
}
virtual MapImpl *mapImpl() { return m_mapImpl; }
int numberOfValuesChanged(); ///< For Unit/Module Test
protected:
virtual bool updateViewImplPre();
virtual bool updateViewImpl() = 0;
virtual bool updateViewImplPost();
friend class ObjectFactory;
// deriving classes MUST overload init and create an GraphicalObject!!!
// (to use whose identifier, textStyle)
virtual bool init(MapImpl *mapImpl, const QString &logicalLayerName = QStringLiteral("GraphicsLayer"));
virtual void setUniqueId(const UniqueMapId &uniqueId);
QString logicalLayerName() const;
bool setLogicalLayerName(const QString &logicalLayerName);
// internal/admin
void createTacticalAppearance();
void resetTacticalAppearanceDrawOrderOffset();
virtual bool updateTacticalAppearance();
// Extrusion
void createGraphicalObjectExtrusion();
void resetGraphicalObjectExtrusion();
bool updateGraphicalObjectExtrusion();
// pin/needle
void createPin();
void resetPin();
bool updatePin();
virtual void updateIdentifierPosition();
friend class MapConnector;
virtual bool onMapExtentChanged();
MapConnector *m_mapConnector = nullptr;
class VisibilityScale
{
public:
VisibilityScale()
{
resetToInitial();
}
void resetToInitial()
{
scale_zoomOutCurrent = scale_zoomOutInitialized;
}
void resetToMax()
{
scale_zoomOutCurrent = std::numeric_limits<double>::max();
}
void setInitial(double newValue)
{
scale_zoomOutInitialized = newValue;
resetToInitial();
}
bool scaleHasVisibility(double curScale) const
{
if (scale_zoomOutCurrent <= 0)
return true;
return (curScale < scale_zoomOutCurrent);
}
private:
double scale_zoomOutCurrent = 0;
double scale_zoomOutInitialized = 70000;
};
VisibilityScale m_visibilityScaleRange; // static value 's_scaleHasVisibilityValue' is located in the interface
UniqueMapId m_uniqueMapId = SituationMap::INVALID_MAP_ID; ///< for identification
QString m_debugInfo; ///< for debugging
MapImpl *m_mapImpl = nullptr;
QString m_logicalLayerName;
Esri::ArcGISRuntime::GraphicsOverlay *m_graphicsLayer = nullptr;
// party :
struct party
{
SimpleValue<int> partyId = -1;
SimpleValue<bool> useLightColor = false; // useful for Participants
mutable QColor partyColor;
SimpleValue<QColor> forcedPartyColor;
bool changed() const { return partyId.changed() || useLightColor.changed() || forcedPartyColor.changed(); }
void reset() { partyId.reset(); useLightColor.reset(); forcedPartyColor.reset(); }
};
party m_party;
bool partyChanged() const { return m_party.changed(); }
void partyReset() { m_party.reset(); }
virtual const QColor &partyColor() const;
virtual QColor partyColor(int partyId, bool useLightColor) const;
virtual AdvancedSymbology::Role partyRole(bool roleIdentityAssumed = false) const;
// : party
// state :
SimpleValue<AesEffectState> m_aesState{AesEffectState::Unknown};
// : state
private:
int m_drawOrder{0}; // logical drawOrder
protected:
int m_internalDrawOrder{0};
// m_mainGraphicalObject will store LineStyle (color/width/pattern), FillStyle (color/pattern):
AbstractGraphicalObject *m_mainGraphicalObject{nullptr};
bool m_enableScale{true};
// m_mainGraphicalText will store TextStyle (color/width/size...)
GraphicalObjectText *m_mainGraphicalObjectText{nullptr};
Point3D m_identifierPositionCandidateTranslated;
SimpleValue<bool> m_identiferVisible{true};
TacticalAppearance *m_tacticalAppearance{nullptr};
int m_tacticalAppearanceDrawOrderOffset{2};
// for 3D Extrusion:
GraphicalObjectCube *m_graphicalObjectExtrusion{nullptr};
double m_extrusionHeight{std::nan("")};
QString m_extrusionColorName;
// For Pin
GraphicalObjectPath *m_graphicalObjectPin{nullptr};
double m_defaultZValue{0};
SimpleValue<SymbolData> m_symbol;
SymbolImage m_symbolImage;
QColor m_forcedMajorColor;
// Update ObjectIndicator :
protected:
bool m_updateObjectIndicator{false};
QVector<OriginPositionChangedCallback *> m_originPositionChangedCb;
public:
void addChangedCallback(OriginPositionChangedCallback *cb);
void removeChangedCallback(OriginPositionChangedCallback *cb);
// : Update ObjectIndicator
protected:
bool m_visibility = true;
bool m_visibilityTechnical = true;
bool m_visibilityTechnicalGeometry = true; // Special case
bool m_visibilityTactical = true;
bool m_selected = false;
bool m_pickable = true;
bool m_editorMode = false;
bool m_lineColorFromParty = true;
int m_fillColorAlpha = 255;
private:
ExtraData *m_extraData = nullptr;
void createGraphicalObjectText();
LOGGER_T m_logger; ///< Interface of the Logging-Facility
};
QString toString(const AesEffectState value);
std::ostream &operator<< (std::ostream &stream,
const AesEffectState &value);
} // namespace SituationMap
@@ -0,0 +1,207 @@
/**
* @RDE_HEADER@
* Interface-Implementation of Map
* $Id$
* $HeadURL$
* $Author$
*/
#pragma once
// Own
#include <Map/coord_translation_functor.h>
#include <Map/situation_map_utils.h>
#include "map_impl.h"
// ESRI
#include <GeometryEngine.h>
//#include <CoordinateConversion.h>
// Qt
#include <QPointF>
#include <QMutex>
#include <QMutexLocker>
#include <cmath>
#include <Point.h>
namespace SituationMap
{
class CoordTranslationFunctorImpl final : public CoordTranslationFunctor
{
public:
explicit CoordTranslationFunctorImpl(const MapImpl *mapImpl)
: m_mapImpl(mapImpl)
, m_logger(getLogger("CoordTranslationFunctorImpl"))
{}
virtual ~CoordTranslationFunctorImpl() = default;
QPointF geographicToMap(const QPointF &coord) const override
{
return geographicToMap(coord.x(), coord.y());
}
QPointF mapToGeographic(const QPointF &coord) const override
{
return mapToGeographic(coord.x(), coord.y());
}
QPointF geographicToMap(const Esri::ArcGISRuntime::Point &coord) const override
{
return geographicToMap(coord.x(), coord.y());
}
QPointF mapToGeographic(const Esri::ArcGISRuntime::Point &coord) const override
{
return mapToGeographic(coord.x(), coord.y());
}
QPointF geographicToMap(const double lon, const double lat) const override
{
return convert(lon, lat, false);
}
QPointF mapToGeographic(const double x, const double y) const override
{
return convert(x, y, true);
}
Point3D geographicToMap(const Point3D &coord) const override
{
const QPointF &p = geographicToMap(coord.x(), coord.y());
return Point3D(p.x(), p.y(), coord.z());
}
Point3D mapToGeographic(const Point3D &coord) const override
{
const QPointF &p = mapToGeographic(coord.x(), coord.y());
return Point3D(p.x(), p.y(), coord.z());
}
bool mapIsGeographic() const override
{
return (m_mapImpl->getEsriSpatialReference().isGeographic());
} // bool mapIsGeographic() const override
void geographicToUtm(const double referenceLon, QList<QPointF> &points) const override
{
int wkid(buildWkid(referenceLon));
const Esri::ArcGISRuntime::SpatialReference utmSR(wkid);
QMutexLocker lock(&m_mutex);
for(QList<QPointF>::iterator it = points.begin(); it != points.end(); ++it)
{
QPointF &pt = *it;
const Esri::ArcGISRuntime::Point utmPoint( Esri::ArcGISRuntime::GeometryEngine::project( Esri::ArcGISRuntime::Point(pt.x(), pt.y(), 0.0, m_wkSR), utmSR ));
pt.setX(utmPoint.x());
pt.setY(utmPoint.y());
}
} // void geographicToUtm(const double referenceLon, QList<QPointF> &points) const override
void utmToGeographic(const double referenceLon, QList<QPointF> &points) const override
{
int wkid(buildWkid(referenceLon));
const Esri::ArcGISRuntime::SpatialReference utmSR(wkid);
QMutexLocker lock(&m_mutex);
for (QList<QPointF>::iterator it = points.begin(); it != points.end(); ++it)
{
QPointF &pt = *it;
const Esri::ArcGISRuntime::Point geoPoint(Esri::ArcGISRuntime::GeometryEngine::project(Esri::ArcGISRuntime::Point(pt.x(), pt.y(), 0.0, utmSR), m_wkSR));
pt.setX(geoPoint.x());
pt.setY(geoPoint.y());
}
} // void utmToGeographic(const double referenceLon, QList<QPointF> &points) const override
int projectionCounter() const override { return m_projectionCounter; }
void resetProjectionCounter() override { m_projectionCounter = 0; }
private:
static int buildWkid(const double referenceLon)
{
int utmZone = referenceLon / 6;
if (utmZone < 0) utmZone = 60 + utmZone;
utmZone += 31;
if (utmZone > 60) utmZone -= 60;
return 32600 + utmZone;
} // static int buildWkid(const double referenceLon)
QPointF convert(const double x, const double y, bool toGeographic) const
{
// if x,y are geographic (x=lon/y=lat), use radian
const char *directionString = toGeographic ? "mapToGeographic" : "geographicToMap";
if (!m_mapImpl)
{
ERROR_LOG(m_logger) << "Error converting " << directionString
<< " - no map!";
return QPointF();
}
const CoordTranslationFunctor *ctF = m_mapImpl->coordTranslationFunctor();
if (!ctF)
{
ERROR_LOG(m_logger) << "Error converting " << directionString
<< " - no coordinate translation function!";
return QPointF();
}
const Esri::ArcGISRuntime::SpatialReference sourceSR = toGeographic ? m_mapImpl->getEsriSpatialReference() : m_wkSR;
const Esri::ArcGISRuntime::SpatialReference destSR = toGeographic ? m_wkSR : m_mapImpl->getEsriSpatialReference();
if (sourceSR.isEmpty() || destSR.isEmpty())
{
ERROR_LOG(m_logger) << LOGFUNCTION
<< " SpatialReference empty"
<< " sourceSR.isEmpty()=" << sourceSR.isEmpty()
<< " destSR.isEmpty()=" << destSR.isEmpty();
return QPointF();
}
// toGeographic: deg -> rad
// !toGeographic: rad -> deg (== from geographic)
const double factorSrc = toGeographic ? 1 : 180 / M_PI;
const double factorDst = toGeographic ? M_PI / 180 : 1;
QMutexLocker lock(&m_mutex);
// const double z = 12.34567;
const Esri::ArcGISRuntime::Point destPoint(Esri::ArcGISRuntime::GeometryEngine::project(Esri::ArcGISRuntime::Point(x * factorSrc,
y * factorSrc,
// z,
sourceSR),
destSR));
// qCritical() << " zOut= " << destPoint.z();
const QPointF ret(destPoint.x() * factorDst, destPoint.y() * factorDst);
++m_projectionCounter;
return ret;
}
const MapImpl *m_mapImpl = nullptr;
const Esri::ArcGISRuntime::SpatialReference m_wkSR = Esri::ArcGISRuntime::SpatialReference(4326); // EPSG:4236 = WGS84
mutable QMutex m_mutex;
mutable int m_projectionCounter = 0; // hmmm - really needed?
LOGGER_T m_logger; ///< Interface of the Logging-Facility
};
} // namespace SituationMap
@@ -0,0 +1,359 @@
/**
* @RDE_HEADER@
* CoordinateTranslation
* $Id$
* $HeadURL$
* $Author$
*/
// Own
#include "coordinate_translation.h"
#include <Map/coord_translation_functor.h>
#include <MapImpl/map_impl.h>
#include <MapImpl/abstract_map_object_impl.h>
#include <MathUtils/simple_helper.h>
// ESRI
#include <Point.h>
#include <GeometryEngine.h>
// Qt
#include <QMutexLocker>
#include <iostream>
//----------------------------------------------------------------------------
namespace SituationMap
{
void TranslatedBase::setCoordTransFunctor(CoordTranslationFunctor *functor)
{
m_coordTransFunctor = functor;
}
void TranslatedBase::setMapObjectImpl(AbstractMapObjectImpl *mapObjectImpl)
{
m_mapObjectImpl = mapObjectImpl;
}
OriginTranslated::OriginTranslated()
#ifdef WITH_LOGGING
: m_logger(getLogger("OriginTranslated"))
#endif
{}
Point3D OriginTranslated::origin() const
{
return m_origin;
}
bool OriginTranslated::setOrigin(const Point3D &origin)
{
bool changed = m_origin != origin;
if (changed)
{
m_origin = origin;
m_translated = false;
}
return changed;
}
const Point3D &OriginTranslated::originTranslated() const
{
#ifdef WITH_LOGGING
TRACE_LOG(m_logger) << LOGFUNCTION << " START"
<< " m_origin=" << m_origin
;
#endif
if (!m_translated)
{
// m_coordTransFunctor has priority, otherwise use functor of mapImpl:
if (!m_coordTransFunctor)
{
if (m_mapObjectImpl && m_mapObjectImpl->mapImpl())
{
// if useful, a MapObjectType specific functor can be prefered here:
// like: if (m_mapObjectImpl->coordTranslationFunctor()) ctFunctor=m_mapObjectImpl->coordTranslationFunctor();
m_coordTransFunctor = m_mapObjectImpl->mapImpl()->coordTranslationFunctor();
}
}
if (m_coordTransFunctor)
m_originTranslated = m_coordTransFunctor->geographicToMap(m_origin);
else
m_originTranslated = Point3D();
m_translated = true;
}
#ifdef WITH_LOGGING
TRACE_LOG(m_logger) << LOGFUNCTION << " END"
<< " m_originTranslated=" << m_originTranslated
;
#endif
return m_originTranslated;
}
PositionsTranslated::PositionsTranslated()
: m_mutex()
#ifdef WITH_LOGGING
, m_logger(getLogger("PositionsTranslated"))
#endif
{}
PositionCont PositionsTranslated::positions() const
{
QMutexLocker lock(&m_mutex);
return m_positions + m_singlePositions;
}
bool PositionsTranslated::setPositions(const PositionCont &posCont)
{
QMutexLocker lock(&m_mutex);
bool changed = m_positions != posCont;
if (changed)
{
m_positions = posCont;
m_translated = false;
}
m_singlePositions.clear();
return changed;
}
void PositionsTranslated::addSinglePosition(const Point3D &singlePositions)
{
QMutexLocker lock(&m_mutex);
m_singlePositions.append(singlePositions);
}
bool PositionsTranslated::setPositionsTranslated(const PositionCont &posCont)
{
QMutexLocker lock(&m_mutex);
if ((m_translated) && (m_positionsTranslated == posCont))
return true;
m_positionsTranslated = posCont;
m_positions.clear();
if (!m_coordTransFunctor)
{
if (m_mapObjectImpl && m_mapObjectImpl->mapImpl())
{
// if useful, a MapObjectType specific functor can be prefered here:
// like: if (m_mapObjectImpl->coordTranslationFunctor()) ctFunctor=m_mapObjectImpl->coordTranslationFunctor();
m_coordTransFunctor = m_mapObjectImpl->mapImpl()->coordTranslationFunctor();
}
}
if (m_coordTransFunctor)
{
m_positions.reserve(m_positionsTranslated.size());
for (int i = 0; i < m_positionsTranslated.count(); ++i)
m_positions.push_back(m_coordTransFunctor->mapToGeographic(m_positionsTranslated.at(i))); // for
}
m_singlePositions.clear();
m_translated = true;
return false;
} // PositionsTranslated::setPositionsTranslated( const PositionCont & posCont )
int PositionsTranslated::size() const
{
QMutexLocker lock(&m_mutex);
return m_positions.size() + m_singlePositions.size();
}
bool PositionsTranslated::isEmpty() const
{
QMutexLocker lock(&m_mutex);
return m_positions.isEmpty() && m_singlePositions.isEmpty();
}
void PositionsTranslated::clear()
{
QMutexLocker lock(&m_mutex);
m_positions.clear();
m_positionsTranslated.clear();
m_singlePositions.clear();
m_translated = false;
}
Point3D PositionsTranslated::first()
{
if (isEmpty())
return Point3D();
if (! m_positions.isEmpty())
return m_positions.first();
return m_singlePositions.first();
}
Point3D PositionsTranslated::last()
{
if (isEmpty())
return Point3D();
if (! m_singlePositions.isEmpty())
return m_singlePositions.last();
return m_positions.last();
}
const PositionCont &PositionsTranslated::positionsTranslated() const
{
#ifdef WITH_LOGGING
TRACE_LOG(m_logger) << LOGFUNCTION << " START"
<< " m_positions=" << m_positions;
#endif
QMutexLocker lock(&m_mutex);
// !!! Important: consolidate !!!
consolidate();
if (!m_translated)
{
// translate:
m_positionsTranslated = geographicToMap(m_positions);
m_translated = true;
}
#ifdef WITH_LOGGING
TRACE_LOG(m_logger) << LOGFUNCTION << " END"
<< " m_positionsTranslated=" << m_positionsTranslated;
#endif
return m_positionsTranslated;
}
PositionCont PositionsTranslated::geographicToMap(const PositionCont &positions) const
{
PositionCont ret;
// m_coordTransFunctor has priority, otherwise use functor of mapImpl:
if (!m_coordTransFunctor)
{
if (m_mapObjectImpl && m_mapObjectImpl->mapImpl())
{
// if useful, a MapObjectType specific functor can be prefered here:
// like: if (m_mapObjectImpl->coordTranslationFunctor()) ctFunctor=m_mapObjectImpl->coordTranslationFunctor();
m_coordTransFunctor = m_mapObjectImpl->mapImpl()->coordTranslationFunctor();
}
}
if (!m_coordTransFunctor)
return ret;
ret.reserve(positions.size());
for (int i = 0; i < positions.count(); ++i)
{
const Point3D &p = positions.at(i);
ret.push_back(m_coordTransFunctor->geographicToMap(p));
} // for
return ret;
}
const Point3D &PositionsTranslated::startPointTranslated() const
{
QMutexLocker lock(&m_mutex);
// make sure that positions are translated:
positionsTranslated();
return m_positionsTranslated.first();
}
const Point3D &PositionsTranslated::endPointTranslated() const
{
QMutexLocker lock(&m_mutex);
// make sure that positions are translated:
positionsTranslated();
return m_positionsTranslated.back();
}
double PositionsTranslated::angleOfStartSegment() const
{
QMutexLocker lock(&m_mutex);
positionsTranslated();
const int size = m_positionsTranslated.size();
if (size < 2)
return 0;
// rechtwinkliges Koordinatensystem benutzen
return MathUtils::getAngleDegreeNorth(m_positionsTranslated.at(0).toPointF(), m_positionsTranslated.at(1).toPointF());
}
double PositionsTranslated::angleOfEndSegment() const
{
QMutexLocker lock(&m_mutex);
positionsTranslated();
const int size = m_positionsTranslated.size();
if (size < 2)
return 0;
// rechtwinkliges Koordinatensystem benutzen
return MathUtils::getAngleDegreeNorth(m_positionsTranslated.at(size - 2).toPointF(), m_positionsTranslated.at(size - 1).toPointF());
}
double PositionsTranslated::angleOfClosingSegment() const
{
QMutexLocker lock(&m_mutex);
positionsTranslated();
const int size = m_positionsTranslated.size();
if (size < 2)
return 0;
// rechtwinkliges Koordinatensystem benutzen
return MathUtils::getAngleDegreeNorth(m_positionsTranslated.last().toPointF(), m_positionsTranslated.first().toPointF());
}
void PositionsTranslated::consolidate() const
{
QMutexLocker lock(&m_mutex);
if (m_translated)
{
// ok, m_positions is already translated to m_positionsTranslated
// translate just the remaining m_singlePositions:
// To do so
// 1. add the m_singlePositions to m_positions
m_positions += m_singlePositions;
// 2. translate just the remaining m_singlePositions
// 3. add the now translated singlePositions to
m_positionsTranslated += geographicToMap(m_singlePositions);
// 4. cleanup m_singlePositions:
m_singlePositions.clear();
}
else
{
// move m_singlePositions to m_positions
m_positions += m_singlePositions;
m_singlePositions.clear();
}
}
} // namespace SituationMap
@@ -0,0 +1,190 @@
/**
* @RDE_HEADER@
* CoordinateTranslation
* $Id$
* $HeadURL$
* $Author$
*/
#pragma once
// Own
#include <Map/situation_map_types.h>
// #define WITH_LOGGING
#ifdef WITH_LOGGING
# include <Common/situation_map_logging.h>
#endif // WITH_LOGGING
// ESRI
// Qt
#include <QRecursiveMutex>
//----------------------------------------------------------------------------
namespace SituationMap
{
//forward:
class CoordTranslationFunctor;
class AbstractMapObjectImpl;
class SITUATIONMAP_EXPORT TranslatedBase
{
public:
explicit TranslatedBase() = default;
virtual ~TranslatedBase() = default;
// use ONE of the following methods to set functor:
void setCoordTransFunctor(CoordTranslationFunctor *functor); // set functor direct
void setMapObjectImpl(AbstractMapObjectImpl *mapObjectImpl); // MapObject->Map->functor
bool isTranslated() const
{
return m_translated;
}
virtual bool isEmpty() const = 0;
protected:
mutable CoordTranslationFunctor *m_coordTransFunctor = nullptr;
AbstractMapObjectImpl *m_mapObjectImpl = nullptr; ///< parent / host
mutable bool m_translated = false;
};
class SITUATIONMAP_EXPORT OriginTranslated final : public TranslatedBase
{
public:
OriginTranslated();
Point3D origin() const;
bool setOrigin(const Point3D &origin);
const Point3D &originTranslated() const;
void clear()
{
m_origin = Point3D();
}
bool isEmpty() const
{
return m_origin.isNull();
}
/**
* @brief operator== Compare two objects
* @param other to be compared with
* @return True if identical, otherwise false.
*/
bool operator==(const OriginTranslated &other) const
{
// m_positionsTranslated must be skipped!
return ((this->m_origin == other.m_origin));
}
/**
* @brief operator!= Compare two objects
* @param other to be compared with
* @return True if NOT identical, otherwise false.
*/
bool operator!=(const OriginTranslated &other) const
{
return !(*this == other);
}
private:
#ifdef WITH_LOGGING
LOGGER_T m_logger; ///< Interface of the Logging-Facility
#endif
Point3D m_origin;
mutable Point3D m_originTranslated;
};
/**
* @brief The PositionsTranslated class to translate positions of simulation world to map coordinate.
* A the translation is done using the CoordTranslationFunctor.
* (A copy of this object is not allowed since inner mutex can´t be copied.)
*/
class SITUATIONMAP_EXPORT PositionsTranslated : public TranslatedBase
{
public:
PositionsTranslated();
// disable copy
PositionsTranslated(const PositionsTranslated &) = delete;
PositionsTranslated &operator=(const PositionsTranslated &) = delete;
PositionCont positions() const;
bool setPositions(const PositionCont &posCont);
void addSinglePosition(const Point3D &singlePositions);
bool setPositionsTranslated(const PositionCont &posCont);
int size() const;
bool isEmpty() const;
void clear();
Point3D first();
Point3D last();
bool isTranslated() const { return m_translated && m_singlePositions.isEmpty(); }
const PositionCont &positionsTranslated() const;
const Point3D &startPointTranslated() const;
const Point3D &endPointTranslated() const;
double angleOfStartSegment() const;
double angleOfEndSegment() const;
double angleOfClosingSegment() const; ///< Angle between end and start
/**
* @brief operator== Compare two objects
* @param other to be compared with
* @return True if identical, otherwise false.
*/
bool operator==(const PositionsTranslated &other) const
{
// m_positionsTranslated must be skipped!
return ((this->m_positions == other.m_positions));
}
/**
* @brief operator!= Compare two objects
* @param other to be compared with
* @return True if NOT identical, otherwise false.
*/
bool operator!=(const PositionsTranslated &other) const
{
return !(*this == other);
}
protected:
void consolidate() const; // method is const
private:
#ifdef WITH_LOGGING
LOGGER_T m_logger; ///< Interface of the Logging-Facility
#endif
PositionCont geographicToMap(const PositionCont &positions) const;
mutable PositionCont m_positions; // mutable to enable consolidate
mutable PositionCont m_singlePositions; // mutable to enable consolidate
mutable PositionCont m_positionsTranslated; // mutable to enable positionsTranslated
mutable QRecursiveMutex m_mutex;
};
} // namespace SituationMap
@@ -0,0 +1,82 @@
/**
* @RDE_HEADER@
* CoordinateTranslation
* $Id$
* $HeadURL$
* $Author$
*/
// Own
#include "coordinate_translation_thread.h"
#include <Map/coord_translation_functor.h>
#include <MapImpl/map_impl.h>
#include <MathUtils/simple_helper.h>
// ESRI
#include <Point.h>
#include <GeometryEngine.h>
// Qt
long SituationMap::CoordTranslationThread::m_counter = 0;
//----------------------------------------------------------------------------
namespace SituationMap
{
CoordTranslationThread::CoordTranslationThread(const QString &debugInfo)
: BaseClass()
, m_logger(getLogger("CoordTranslationThread"))
, m_debugInfo(debugInfo)
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START, debugInfo='" << m_debugInfo << "'"
" counter=" << m_counter;
++m_counter;
TRACE_LOG(m_logger) << LOGFUNCTION << " END, debugInfo='" << m_debugInfo << "'"
<< " counter=" << m_counter;
}
CoordTranslationThread::~CoordTranslationThread()
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START, debugInfo='" << m_debugInfo << "'"
" counter=" << m_counter;
--m_counter;
TRACE_LOG(m_logger) << LOGFUNCTION << " END, debugInfo='" << m_debugInfo << "'"
<< " counter=" << m_counter;
}
void CoordTranslationThread::run()
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START, debugInfo='" << m_debugInfo << "'"
<< " userData=" << m_userData.toInt()
<< " counter=" << m_counter
<< " threadId: " << QThread::currentThreadId() ;
if (m_positions)
m_positions->positionsTranslated();
emit resultReady(m_userData);
TRACE_LOG(m_logger) << LOGFUNCTION << " END, debugInfo='" << m_debugInfo << "'"
<< " userData=" << m_userData.toInt()
<< " counter=" << m_counter
<< " threadId: " << QThread::currentThreadId();
}
QVariant CoordTranslationThread::userData() const
{
return m_userData;
}
void CoordTranslationThread::setUserData(const QVariant &userData)
{
m_userData = userData;
}
} // namespace SituationMap
@@ -0,0 +1,79 @@
/**
* @RDE_HEADER@
* CoordinateTranslation
* $Id$
* $HeadURL$
* $Author$
*/
#pragma once
// Own
#include "coordinate_translation.h"
#include <Common/situation_map_logging.h>
#include <situation_map_export.h>
// Qt
#include <QObject>
#include <QVariant>
#include <QThread>
// ESRI
//----------------------------------------------------------------------------
namespace SituationMap
{
class SITUATIONMAP_EXPORT CoordTranslationThread : public QThread
{
Q_OBJECT
using BaseClass = QThread;
public:
explicit CoordTranslationThread(const QString &debugInfo);
virtual ~CoordTranslationThread();
void setPositions(PositionsTranslated *positions)
{
m_positions = positions;
}
PositionsTranslated *positions() const
{
return m_positions;
}
QVariant userData() const;
void setUserData(const QVariant &userData);
signals:
void resultReady(const QVariant &userData);
protected:
void run() override;
private :
LOGGER_T m_logger; ///< Interface of the Logging-Facility
PositionsTranslated *m_positions = nullptr;
QString m_debugInfo;
QVariant m_userData;
static long m_counter;
};
} // namespace SituationMap
Loaded 100 of 1718 files, more files were not shown because too many files have changed in this diff. Show more