Files
qt-migration-legatus/qt5-before/dlbo/Lts/Tools/ArAssets/README.md
T
torstenandCopilot 7173785915 Qt6 Migration: Complete migration with DDS/RTI support and build validation
Major Changes:
- Merged latest Qt5 devel content from dlbo (292 files changed, 7 new dirs)
- Consolidated forward-declarations and include folders
- Removed unneeded modules per Niklas' repo check list

Build System Fixes:
- Fixed CMake VERSION_GREATER syntax in ParticipantManagement/CMakeLists.txt
- Added VLC packages (libvlc-dev, vlc-plugin-base) to docker_build.sh
- Added PostgreSQL dev packages (libpq-dev, postgresql-server-dev-all) to Dockerfile
- Fixed locale warnings (ANSI_X3.4-1968 → C.UTF-8)
- Fixed ArcGIS SDK path warnings when BUILD_ARCGIS=OFF

Code Generation Fixes:
- Fixed IDL enum collisions (PortType→CorePortType/DdsutPortType, PdmEventType)
- Fixed Grantlee template svc_translation.cpp.grantlee:
  - Changed {{ idl_enum.name }}_def:: to {{ idl_enum.name }}::
  - Fixed .underlying() calls for C++11 scoped enums (enum class)
- Removed generated files from repo (moc_*, *_dtc.h, *_ftc.h)

Validation:
- BUILD_RTI=ON: SUCCESS
- BUILD_RTI=OFF: SUCCESS
- C++17 standard maintained for RTI 7.7 compatibility
- Ubuntu 26.04 Docker environment verified

Remaining Warnings (expected):
- BgViewer, KDChart, KDReports, Poppler-Qt6 not found (optional features)

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-09-15 18:20:26 +00:00

274 lines
11 KiB
Markdown

# Leaflet map for displaying mounting points
## Table of contents
1. [Usage](#usage)
2. [Programming](#programming)
1. [Basics](#basics)
1. [TypeScript](#typescript)
2. [AngularJs](#angularjs)
3. [Leaflet](#leaflet)
2. [The code](#the-code)
_Note: view this in a program that supports markdown_
_(e.g. VS Code or a browser with plugin) and it will look much better_
---
## Usage
### Connection
When opening index.html you will first see the connection menu.
Here you can choose if you want to connect to localhost:2080, enter
a custom ip or load data from the browser cache.
### Main page
The main page consists of two parts: the map on the left side and the selection
menu on the right side.
The map will display the buildings and mouting points received from the previously
entered websocket. Buildings are currently light blue while mounting points are
highlighted with a typical map marker in black. These markers will open a popup
that displays additional info when clicked.
The selection menu on the right side has three sections, namely "Layers", "Asset
types" and finally "Selected mounting points".
- The layer selection is handled via checkboxes where checked means displayed
- The asset type selection happens with a dropdown menu
- Selected mounting points are displayed in a table with tag/designation and id
The table displaying selected mounting points also features a button for each
point that centers the map on it and opens its popup. It can also be searched
using the text input above it (case sensitive, checks if name or id contain given
text).
---
## Programming
### Basics
This program is a kind of messy combination of several libraries/frameworks that
weren't really made to work with each other soI have to explain some things first:
#### TypeScript
TypeScript (TS) is a superset of JavaScript (JS) which means every JS command is also valid TS.
The big difference is that TS is typed (who would have guessed?) andfeatures object
oriented programming. Concepts such as classes and inheritance are
supported. TS is transpiled into JS. This secures compatibility with most browsers.
A little syntax example of TS:
```typescript
var name: type = value;
function name(parameter: type): returnType {
// ...
}
class name extends inheritedClass {
PropertyOne: type;
PropertyTwo: type = value;
constructor(parameter: type) {
this.PropertyOne = parameter;
}
}
```
The command `tsc --build <file.ts>` can be used to transpile "file.ts",
`tsc --watch <file.ts>` however will stay running and always retranspile when
it detects changes in "file.ts".
#### AngularJs
AngularJs is a kind of library for JS/htm which allows you to build dynamic pages
with really little actual code. There has to be some backing code but most of it
will actually happen wihtin the html file. It's kinda hard to explain but here's
an example:
```html
<li>
<ul ng-repeat="x in [1, 2, 3, 4, 5]">
{{x}}
</ul>
</li>
```
This example doesn't really show anything too useful but you can see two of the most
important concepts of AngularJs: directives and templates.
- The directive `ng-repeat` for example will repeat the tag it is in dynamically
depending on its content, in this case 5 times
- The template `{{x}}` will be dynamically replaced by the value of x, in this
case 1 thorugh 5
When viewed in a browser the example will render as this:
> - 1
> - 2
> - 3
> - 4
> - 5
We can make JS variables visible to AngularJs by attaching them to its `$scope`
object.
This was really short but I can't really teach a whole framework within a
readme. There is a nice (German) [tutorial](https://angular.de/artikel/angularjs-tutorial-deutsch/)
though.
There actually is a newer version of Angular explicitly for TS but it's way more
complicated so I stuck with the old JS version. It was a headache to get that to
work but now it does. Don't touch it.
#### Leaflet
Leaflet is a JS library for creating maps. It's rather simple to understand
and has nice [documentation](https://leafletjs.com/reference-1.4.0.html).
Basically you create a div with a special id and then put stuff like markers
into it via JS. Not much I could explain here. Except maybe I can say a sentence
about function chaining. Leaflet smartly uses return types in its functions that
allow you to chain them like crazy. For example:
```typescript
var marker: L.Marker = L.marker(coordinates)
.bindPopup(popupContent)
.addTo(map);
```
`.bindPopup()` and `.addTo()` both still return the marker. This way you can get
a lot of stuff done with a single statement.
In this example you can also see that Leaflet likes to use factory methods instead
of instance contructors (`new`). Feels weird in the beginning but makes sense when
you keep in mind that this is a TS port of a JS library.
### The code
Let me first tell you how to actually run the code:
1. Transpile: Ctrl+Shift+B in VS Code, choose "build"
2. Browserify: `browserify main.js -o scripts/main.js`
3. Open index.html
The browserify step is needed since this program is basically a nodejs app.
Browserify combines all node modules into a single .js file
so we can actually use the file in a html website.
To clear things up:
- ./main.ts is the source file - _develop here_
- ./main.js is the transpiled file - _don't touch it_
- ./scripts/main.js is the final browerified file - _don't even look at it_
When developing it is way easier to have those commands in watch mode so
you can simply refresh the browser to see the changes you made:
- Ctrl+Shift+B in VS Code, choose watch
- `watchify main.js -o scripts/main.js`
These commands will automatically retranspile and rebrowserify main.ts when you
hit save in an editor of your choice (use VS Code though - it's the best).
tsc, browserify and watchify can be installed via npm.
**Also, don't update utm-latlng!**
utm-latlng is a dependency which features conversion of coordinates from
latitude/longtitude to UTM and vice-versa. There's a bug in it that prevents
the correct conversion from UTM back to lat/lon in the current version. There's
a pull request with a one line fix on GitHub but that was half a year ago and
has never been merged so I copied the line and pasted it in the local installation
of the library. Updating it will probably break it. So don't.
_Actually, it's probably best to not update anything, just to be sure._
---
Now let's get to the actual code. I wont explain every little detail since there
are additional comments in the code but I will highlight _some_ things. For writing
I recommend VS Code.
- The only files needed to display the final page in the end are:
- index.html
- style.css
- The scripts folder and its content
- the img forler and its content
- index.html is rather simple. Contains additional comments as well but here's
some more things:
- leaflet.css has to be before leaflet.min.js apparently
- Everything withing `{{}}` is an AngularJs template and will be filled
dynamically with the code inside
- `ng-click` is basically `onclick`
- I wont even talk about style.css
- main.ts. This is the evil one
- Don't question the angular module and controllers. They are basically magic.
- `module Calc` is a little collection of some math stuff:
- `RadToDeg()` and `DegToRad()` are really just one-liner functions to
convert between degrees and radians
- `RotatePoint()` rotates a point around an angle using fancy trigonometry
I snatched of the internet
- class UTM` is just there so a have a uniform way of representing UTM
coords
- `LatLonToUtm()` and `UtmToLatLon()` are just wrappers to simplify the
respective utm-latlng functions
- `class MountingPoint` is a leaflet marker which stores additional info
about the mounting point it represents
- `class Layer` stores the markers and is basically a representation of
floors but floors with the same name are stored in the same layer
- `IsStringEmpty()` returns `true` when the given string is either empty,
`null` or `undefined`
- Any property of `$scope` within the angular controller is visible to
angular templates within index.html
- `$scope.loadData()` gets the data from the entered websocket and calls
the event `webSocketResponse`
- `$scope.$on("webSocketResponse", /* ... */)`:
This handles the `webSocketResponse`-event. Almost the whole program is
contained wihtin its callback. This is so that nothing tries to access
any data that has not been received yet. It is divided into sections
that handle the different types of objects we want to display, namely
buildings, levels, mounting points and assets. It also sets up the leaflet
map.
- Nested `for (let x of y)`-"loops" are godsent. I mostly use them to get two
objects with matching properties and then do stuff with them. For example:
```typescript
for (let m of mountingPoints) {
for (let b of buildings) {
if (m.objectId == b.id) {
// ...
```
- `(layer.LLayer.getLayers() as unknown[]) as MountingPoint[])`
This thing... Let me break it down.
`layer` is an instance of my `Layer`-class. `LLayer` is the leaflet map
layer it encapsulates.
`.getLayers()` returns the array of markers on that layer. The problem
I faced here was that they lost the properties I added in my
`MountingPoint`-class because it returns `L.Marker`s.
More precisely, the values is still there but not accessible since
`L.Marker` doesn't have the properties.
But I can't directly cast from `L.Marker` to `MountingPoint`.
Therefore I do a cheaty cast via `unknown`.
It's confusing as heck but the only way I can easily get access to the
`MountingPoint`-properties.
- The mean conditional statement at `foundBySearch` within
`$scope.MountingPointFilter()` is a short way of saying
`true` if either
- `$scope.mpSearch` (search text input in index.html) is empty
- currently tested mounting point tag/designation or id contain
`$scope.mpSearch`
- `$scope.SelectionChanged()` is called in the end so that I don't have
to manually fix all the default selections
- `$scope.$apply()` will update the `$scope`-object so that it's values
are actually available in the angular templates within index.html.
It would happen automatically eventually but I want to be on the safe side.
Sometimes it is nessecary to call it, sometimes it thorws an error. Just try
it out. The error doesn't seem to matter.
---
I hope this and the comments in the code are enough to understand it.
If not, you can send me a [mail](mailto:justus.hertel@rheinmetall.com).
If you are lucky I might remember how it works :p