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>
274 lines
11 KiB
Markdown
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
|