---
# System prepended metadata

title: Positionseingabe und Anzeige

---

# Positionseingabe und Anzeige
Diese Seite befasst sich mit dem Modul AP2a "Positionseingabe und Anzeige" bearbeitet durch Gruppe 1 (@hfi419inma, @hfi419inkr und @hfi419intr).

[Hauptseite](https://fhdwdev.ha.bib.de/gitea/INT2021Q4/resect/wiki)

## Inhaltsverzeichnis
1. [User-Storys](#user-storys)
2. [3D-Modell](#3d-modell)
3. [Umwandelung zwischen Koordinatensystemen](#umwandelung-zwischen-koordinatensystemen)
4. [Mockup](#mockup)
5. [Zukünftige Erweiterungen](#zukünftige-erweiterungen)

## User-Storys
* Als Arzt möchte ich einen Tumor in ein Modell Einzeichnen, sodass ein vollständiger Text generiert wird, der den Tumor in Position und Größe beschreibt.
* Als Arzt möchte ich eine intuitive Anwendung, mit der ich einfach umgehen kann.
* Als Arzt möchte ich, dass das Zeichnen im Blasen-Modell so intuitiv ist wie das Zeichnen auf Papier.

## 3D-Modell
### Importieren von 3D-Modellen
Um 3D-Modelle in die Anwendung zu importieren und anzuzeigen, wird die Funktion [`useGLTF()`](https://docs.pmnd.rs/drei/loaders/use-gltf) aus der Bibliothek [@react-three/drei](https://docs.pmnd.rs/drei/introduction). Diese Funktion ermöglicht das Einlesen von Dateien des "Graphics Language Transmission Format" (.glTF bzw. .glb). Diese Dateiformate sind die gängigen Formate für dreidimensionale Szenen und Modelle. Der wesentliche Unterschied zwischen .glTF und .glb ist die Kodierung. Dabei verwenden .glTFs den ASCII-Zeichensatz und JSON-Struktur. Dateien des .glb-Formats hingegen sind in Binär kodiert.

Ein Beispiel für den Import einer .glTF-Datei ist [hier](https://docs.pmnd.rs/react-three-fiber/tutorials/loading-models) zu finden.  Anhand dieses Beispiels ist zu erkennen, dass beim Import einer .glTF für jedes verwendete Material des 3D-Modells ein [`Mesh`](https://threejs.org/docs/?q=Mesh#api/en/objects/Mesh) zu erstellen ist. Um das manuelle Auslesen und Erstellen der einzelnen Meshes abzukürzen, wird hierfür dieses [Tool](https://gltf.pmnd.rs/) verwendet. In diesem kann eine .gltf oder .glb hochgeladen werden. Der für die Anzeige benötigte React-Code wird anschließend automatisch generiert.

### Darstellung der Blase
Ein Ziel der Anwendung ist es, möglichst intuitiv und schnell Tumore an der passenden Stelle einzeichnen zu können. Bisher wurden diese auf einer 2D-Darstellung per Hand eingezeichnet. Die Darstellung der Blase ist dabei in der Mitte aufgeklappt, um beide Seiten der Blase abbilden zu können. Folgende Abbildung zeigt eine solche Darstellung. Der rote Punkt in der Abbildung zeigt den eingezeichneten Tumor.

![2D-Bladder](https://fhdwdev.ha.bib.de/gitea/attachments/95bcd4f5-3830-467f-89de-e870cdf15136)
*2D-Darstellung einer Blase*

Diese Darstellung ist insofern unschön, da es nicht immer direkt ersichtlich ist, welche eingezeichneten Tumore zusammengehören und welche nicht. Denn erst sobald die beiden auseinandergeklappten Flächen gedanklich zusammengeklappt werden, bildet sich die vollständige Blase ab. Die einzige Alternative, um eine Blase räumlich besser Darstellen zu können, ist eine Darstellung der Blase in 3D. Hierbei wird kein erhöhtes räumliches Denken mehr gefordert, da alle Verbindungen der Flächen auf einen Blick direkt erkennbar sind. Der einzige Vorteil vom Einzeichnen von Tumoren auf dieser 2D-Darstellung einer Blase ist der zeitliche Aspekt. Hat der Arzt dieses 2D-Modell einmal verinnerlicht, ist es in nur wenigen Augenblicken möglich, die resezierten Flächen einzeichnen zu können. Diesen Zeitfaktor können wir daher beim Einzeichen der resezierten Flächen in einem 3D-Modell nicht vernachlässigen. Es sollte kein erhöhter Mehraufwand und auch nicht viel zeitintensiver werden, da sonst die Anwendung voraussichtlich nicht genutzt werden würde.

### 3D-Darstellung der Blase
Die Modellierung der 3D-Blase findet mit Hilfe der Software [Blender](https://www.blender.org/) statt. Sie eignet sich zur Modellierung von 3D-Objekten, Animieren und Gestalten von 3D-Objekten.

Als Basis für die Modellierung der Blase nutzen wir eine UV-Kugel. UV steht hierbei dafür, dass die Blase im Nachhinein auf eine 2D-Karte ausgelegt werden kann. Näheres dazu bei dem Kapitel der [UV-Map](#uv-Map) Sie besteht aus Ringen und Segmenten, die größtenteils in viereckigen Flächen resultieren. Eine Ausnahme bildet das obere und untere Ende der Kugel. Dort werden Dreiecke verwendet, um eine bündige Kugel zu erreichen. Da wir die Berechnung der Positionierung mit 180° für die Länge und 360° für die Länge verwenden, wurde bei der Erstellung der Kugel mit 180 Ringen und 360 Segmenten gearbeitet. Dies ermöglicht es, die [definierten Bereiche](https://fhdwdev.ha.bib.de/gitea/INT2021Q4/resect/issues/17#issuecomment-995) genau passend einzeichnen zu können.

Mit einer solch kleinen Darstellung der Flächen ist es zwar sehr einfach möglich die benötigten Bereiche einzuzeichnen, jedoch erhalten wir hierdurch 64800 einzelne Flächen für die Blase allein. Es ist auch möglich, bei der Erstellung der Blase weniger Ringe und Segmente zu verwenden und diese im Nachhinein zu glätten. Sollte sich im späteren Verlauf herausstellen, dass dieses 3D-Modell zu viel Rechenleistung benötigt, wäre dies eine Möglichkeit, die Anwendung performanter zu bekommen.

Folgende Abbildung zeigt die Ringe, Segmente und Dreiecke bei einer UV-Kugel:

![rings_segments](https://fhdwdev.ha.bib.de/gitea/attachments/061d6668-6767-4130-b7cb-2b01fa177bd7)
*Ringe, Segmente und Dreiecke einer UV-Kugel*


Zusätzlich zu der UV-Kugel für die Blase verwenden wir einen Zylinder, der die Harnröhre darstellt. Da dieser direkt bündig mit der Kugel verbunden werden soll, erhält auch der Zylinder 360 Seiten. Dadurch ist es möglich, eine 1:1 Verbindung zwischen Zylinder und Kugel zu erreichen und einen flüssigen Übergang von Blase zu Harnröhre zu erhalten. Die folgende Abbildung zeigt die unverbundene Basis für die Blase und die Harnröhre mit weniger Ringen und Segmenten als oben beschrieben:

![abstract_bladder](https://fhdwdev.ha.bib.de/gitea/attachments/a60b2eca-f3ee-4538-a055-013e1007c821)
*Abstrakte Bauteile für ein 3D-Modell einer Blase*

Durch das Zusammenfügen des Zylinders und der UV-Kugel erhalten wir ein zusammengefügtes Objekt, bei dem ein flüssiger Übergang von UV-Kugel zu Zylinder vorhanden ist. Anschließend werden die definierten Bereiche in dem Modell eingepflegt, was zu dem folgenden Modell führt:

![Bladder-outside](https://fhdwdev.ha.bib.de/gitea/attachments/afaa8452-44fe-4dc2-9ec8-579ef0fbba91)
*Außenbereich der modellierten Blase*

Dies zeigt jedoch nur die äußere Ansicht, welche für den Anwender letztlich nicht sichtbar sein soll. Der Anwender soll nach aktuellem Stand sich nur in der Blase aufhalten und mit festen Kamerapositionen umherspringen und den Standpunkt ändern können. Um sich in der Kamera orientieren zu können, sind zudem in dem 3D-Modell die definierten Flächen beschriftet.

![Posterior_wall](https://fhdwdev.ha.bib.de/gitea/attachments/b39e9390-e019-45bb-a548-60ee5baa4c0d)
*Sicht auf die Posterior wall*

Aktuelle Ansicht eines Anwenders auf die Posterior wall:

![Posterior_wall_inside](https://fhdwdev.ha.bib.de/gitea/attachments/9f83ba41-8cee-4591-8e96-f93fa7d5b6e3)
*Sicht eines Anwenders*



### UV-Map
Unter UV-Mapping ist der geometrische Modellierungsprozess zur Herstellung eines 2D-Bilds zur Repräsentation eines 3D-Modells zu verstehen. Eine UV-Map gleicht der mathematischen Darstellung von Körpern als Netze. Die UV-Map eines Würfels wird in der nachstehenden Grafik dargestellt.

![UV-Map eines Würfels](https://fhdwdev.ha.bib.de/gitea/attachments/a4e0bd8a-ffa4-4a35-91ce-11c26758e1fc)
*Darstellung des UV-Mappings eines Würfels - Wikipedia*

In der UV-Map eines 3D-Modells sind alle für die Darstellung benötigten Polygone enthalten. Die UV-Map einer Kugel besteht z.B. aus Drei- und Vierecken. Die folgende Abbildung zeigt die UV-Map einer Kugel bestehend aus Drei- und Vierecken.

![UV-Map einer Kugel](https://fhdwdev.ha.bib.de/gitea/attachments/29cd81e6-cb4b-4bc3-9acc-0adb83da4709)
*UV-Map einer Kugel*

### Positionseingabe
Ein Ziel für die Positionseingabe war, diese möglichst intuitiv zu gestalten. Zum aktuellen Zeitpunkt der Abgabe (21.11.2021) ist die Eingabe über einen Doppelklick auf die gewünschte Stelle im 3D-Modell durchzuführen.  Das Ausrichten des Blickwinkels auf das 3D-Modell ist nur durch Rotieren der Kamera mittels Drücken und Halten der linken Maustaste möglich.

Die Technik, welche für die Präzision der Positionseingabe verantwortlich ist, wird als [RayCasting](https://sbcode.net/threejs/raycaster/) bezeichnet. Dabei handelt es sich um eine Technik, mit der ein Strahl (`ray`) von einem Punkt ausgehend in eine spezifizierte Richtung ausgestrahlt wird. Mithilfe des `ray` ist es möglich, alle durch diesen getroffen Objekte zu bestimmen. Darüber hinaus lassen sich die Schnittpunkte zwischen dem `ray` und der Objekte bestimmen. [ThreeJS](https://threejs.org/) enthält einen nativen [RayCaster](https://threejs.org/docs/index.html?q=raycaster#api/en/core/Raycaster), welcher die [Schnittpunkte](https://threejs.org/docs/index.html?q=raycaster#api/en/core/Raycaster.intersectObject) sowohl als kartesischen Punkt im Raum (x, y, z) als auch als einen Punkt auf der [UV-Map](#uv-map) (u, v) zurückliefert. Beide Darstellungsarten der Schnittpunkte sind dabei für diese Anwendung wichtig. Die kartesischen Punkte werden dafür benötigt, diese gemäß der [Bereichsdefinition](https://fhdwdev.ha.bib.de/gitea/INT2021Q4/resect/wiki/Texterzeugung#bereichsdefinition) des Aufgabenpaktes [AP2b](https://fhdwdev.ha.bib.de/gitea/INT2021Q4/resect/wiki/Texterzeugung) in geografische Koordinaten (Latitude, Longitude) zu konvertieren. Die geografischen Koordinaten werden für die [Texterzeugung](https://fhdwdev.ha.bib.de/gitea/INT2021Q4/resect/wiki/Texterzeugung#texterzeugung) und [Generierung des Serialisierungsschlüssel](https://fhdwdev.ha.bib.de/gitea/INT2021Q4/resect/wiki/Serialisierungsschl%C3%BCssel) benötigt. Die Punkte der UV-Map bilden die Grundlage der [Positionsanzeige](#positionsanzeige).

Die nachfolgende Grafik zeigt das Konzept von RayCasting.
![RayCasting](https://fhdwdev.ha.bib.de/gitea/attachments/17984184-8afa-4dda-89d2-7ddaaca78dc5)*Ljung, Patric. (2006). Efficient Methods for Direct Volume Rendering of Large Data Sets.*


### Positionsanzeige
Das Zeichnen auf dem 3D-Modell findet mithilfe der UV-Map statt. Allerdings müssen einige Vorkehrungen getroffen werden, um auf dem 3D-Modell zu zeichnen. Hierfür ist es notwendig, dem Material des 3D-Modells ein bemalbares HTML-Canvas zuzuweisen. Zunächst muss dafür ein [`canvas`](https://developer.mozilla.org/en-US/docs/Web/API/Canvas_API) erzeugt und auf dessen zweidimensionalen [`context`](https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D) über [`canvas.getContext('2d')`](https://developer.mozilla.org/en-US/docs/Web/API/HTMLCanvasElement/getContext) zugegriffen werden. Das erzeugte Canvas wird anschließend einer [`THREE.Texture`](https://threejs.org/docs/index.html?q=texture#api/en/textures/Texture) hinzugefügt, welche dann dem Material zugewiesen wird.

``` javascript
// Create in memory canvas with size of 2000px x 2000px
const canvas = document.createElement('canvas');
canvas.width = 2000;
canvas.height = 2000;

// Get context of canvas as 2D
const context = canvas.getContext('2d');

// Create texture from canvas
const texture = new THREE.Texture(canvas);

// Add texture to material
material.map = texture;
```

Um nun auf dem 3D-Modell zu zeichnen, findet ein Zusammenspiel aus dem RayCasting, der UV-Map und des soeben erstellten Canvas statt. Dabei wird der erste Schnittpunkt des RayCastings und die dazu in Korrelation stehenden Koordinaten der UV-Map ermittelt. Danach wird der `Context` des `Canvas` eingesetzt, um auf diesem zu zeichnen. Das Zeichnen erfolgt durch das nacheinander verbinden der vom Anwender bestimmten Punkte über einer Geraden. Die Punkte werden dabei mit über die UV-Werte und der Größen des Canvas ermittelt.

```javascript
const draw = (intersection) => {
    // Determine material 
    const { object } = intersection;
    const { material } = object;
    
    // Get context
    const canvas = material.map.image;
    const context = canvas.getContext('2d');
    
    // Get UV-Coordinates
    const { uv } = intersection;
    
    // Calculate equivalent point in canvas
    const x = uv.x * canvas.width;
    const y = canvas.height - uv.y * canvas.height;
    
    // Draw on context
    context.lineTo(x, y):
    context.stroke();
    
    // Update material
    material.map.needsUpdate = true;
}
```

### UV-Map Problematiken
Das Zeichnen auf der UV-Map vereinfacht einiges, jedoch muss dafür die UV-Map sorgfältig ausgearbeitet und einiges betrachtet werden. Nachfolgend werden zwei Probleme näher betrachtet und deren Lösung bzw. Lösungsansätze erläutert.

#### Rechteckige UV-Map
Um auf dem 3D-Modell zeichnen zu können, nutzen wir nicht das 3D-Modell selbst, sondern die [UV-Map](#uv-map) des 3D-Modells. Um zwei Punkte auf dem 3D-Modell mit einer Linie zu verbinden, wird jeder dieser beiden Punkte auf der UV-Map gesetzt und eine direkte Linie zwischen diesen beiden Punkten gezogen. 

![UV-Map1](https://fhdwdev.ha.bib.de/gitea/attachments/bef54476-d078-47e4-9721-68a7f554b969)
*Ausgeklappte UV-Map einer UV-Kugel*

Damit dieses Vorgehen funktioniert, benötigen wir jedoch eine rechteckige UV-Map, bei der zusammengehörige Flächen direkt miteinander verbunden sind. Blender kann aus jedem standardmäßig vorhandenen Objekt (Würfel, UV-Sphere, Zylinder, ...) eine Rechteckige UV-Map ohne große Aufwände erzeugen. Sobald eine einzige UV-MAP aus mehreren Objekte erstellt werden soll, überlappen die UV-Maps beider Objekte übereinander. Dies geschieht auch, wenn beide Objekte zu einem Objekt zusammengefügt werden und nur noch als ein Objekt gehandhabt werden.

![UV-Map4](https://fhdwdev.ha.bib.de/gitea/attachments/754baaa1-5856-4954-9f1d-0cbcb8b5a5d0)
*Überlappende UV-Map*

Eine solche UV-Map würde darin resultieren, dass, sobald ein Strich gezogen wird, dieser immer an zwei Positionen gleichzeitig gezeichnet wird, da diese überlappen und "durchdrücken".
Blender hat außerdem die Möglichkeit eines [Smart UV-Unwrap](https://docs.blender.org/manual/en/2.79/editors/uv_image/uv/editing/unwrapping/mapping_types.html). Dabei werden die Objekte klein gestückelt und an einer passenden Stelle auf der UV-Map platziert. Dabei wird jedoch nicht mehr drauf geachtet, dass zusammengehörige Flächen auch nebeneinander platziert sind. Wird auf einer solchen UV-Map ein gerader Strich zwischen zwei Punkten gezogen, so wird der Strich an unterschiedlichen Stellen auf dem 3D-Modell gezeichnet, jedoch nicht da, wo er eigentlich gezeichnet werden sollte. 

![UV-Map2](https://fhdwdev.ha.bib.de/gitea/attachments/5f9f80b4-5545-4001-ac17-eeb8090f8ecc)
*Zerstückelte UV-Map zweier Objekte*

![UV-Map3](https://fhdwdev.ha.bib.de/gitea/attachments/5ed3711a-fc3b-4f93-996e-946a122925e5)
*Striche auf zerstückelter UV-Map im 3D-Modell*

#### Lösung Rechteckige UV-Map Problematik
Um eine rechteckige UV-Map aus mehreren zusammengefügten Objekten in Blender zu erhalten, muss eine [Seam-Kante](https://docs.blender.org/manual/en/2.79/editors/uv_image/uv/editing/unwrapping/seams.html) definiert werden. Diese Kante definiert die Kante, an der das Objekt in der UV-Map aufgeklappt werden soll. Mit Hilfe dieser Kante können diese zusammengefügte Objekte als zusammengehörige UV-Map exportiert werden.

![Bladder_unwrap](https://fhdwdev.ha.bib.de/gitea/attachments/df9df811-e5d3-4544-88ef-8371605a8e81)
*Ausgeklappte Blase anhand einer Seam-Kante*

Die dadurch generierte UV-Map füllt jedoch nur einen kleinen Teil der ganzen Fläche aus. Um dem Problem [Malen über Rand](#zeichnen-über-rand) vorzubeugen und den Lösungsansatz dafür weiterhin nutzen zu können, wird jedoch eine vollständig rechteckige UV-Map benötigt.
Bei der aus dem Seam generierten UV-Map können wir erkennen, dass die Punkte, an denen das Modell nicht weiter ausgeklappt werden kann, der oberste Punkt der UV-Kugel und der unterste Punkt des Zylinders ist. Dies ist dem geschuldet, dass an dieser Stelle Dreiecke zu einem einzigen Punkt zusammenlaufen. Das wird noch einmal näher bei den [Ringen und Segmenten](#3d-darstellung-der-blase) gezeigt. Diese Fokussierung auf diesen einen Punkt ist nicht gewünscht, da sich dadurch die UV-Map nicht weiter entfalten kann. Um diese Fokussierung zu entfernen, müssen aus den eben genannten Dreiecken Vierecke gemacht werden. Dadurch, dass an diesen Stellen dann Vierecke sind, gibt es keinen Punkt, an dem sich zentral alles bündelt. 

Hierzu müssen zuerst die dreieckigen Flächen entfernt werden. Anschließend wird der nächste anschließende Ring an die gelöschten Flächen dupliziert und so klein gemacht, dass so gut wie keine Lücke ersichtlich ist. Hierdurch wird erreicht, dass eine direkte Verbindung zwischen den bereits vorhanden Flächen existiert und diese auf einen sehr kleinen Ring am oberen Ende der UV-Kugel schließen.

![delete_triangles](https://fhdwdev.ha.bib.de/gitea/attachments/0366ed49-6fa4-4329-8c56-56937f361591)
*Schrittfolge um aus Dreiecken Vierecke zu generieren*

Das anschließende Generieren der UV-Map liefert genau das gewünschte Ergebnis, mit dem wir vernünftig die Striche auf UV-Map zeichnen können. Bei dieser UV-Map sind alle Rechtecke, welche in dem 3D-Modell miteinander verbunden sind, auch auf der UV-Map verbunden. Einzig und allein die Seam-Kante ist räumlich voneinander getrennt. Diese Problematik wird in [Malen über Rand](#Zeichnen-über-Rand) behandelt.

![UV-Map5](https://fhdwdev.ha.bib.de/gitea/attachments/ccb3d900-da71-420a-bd72-5a4e0ca57ff3)
*Fertige UV-Map*


#### Zeichnen über den Rand
Beim Verbinden von zwei Punkten auf der UV-Map wird die kürzeste direkte Strecke genutzt. Dabei wird jedoch nicht standardmäßig betrachtet, dass eine Verbindung über den Rand hinaus teilweise kürzer sein kann als eine Verbindung über die komplette UV-Map. Dies resultiert darin, dass Punkte, die in der Nähe der Seam-Kante gesetzt werden, fast eine komplette Umrundung der Blase vornehmen, um an ihren Zielort zu gelangen. Folgendes Bild zeigt genau diese Problematik. Der Start und Endpunkt der schwarzen Linie sind die beiden ausgewählten Punkte. Hierbei wurde nicht die direkte Verbindung in Richtung Left upper wall genutzt, sondern der längere Weg in die genau entgegengesetzte Richtung. Die Seam-Kante wird umgangen, da diese Strecke für das Zeichnen nicht automatisch für die Betrachtung des kürzesten Weges berücksichtigt wird.

![drawing_edge_problem](https://fhdwdev.ha.bib.de/gitea/attachments/5c5c0115-e8fb-49de-acaa-bddcb7b6893c)
*Zeichnen über den Rand Problematik im 3D-Modell*

Gewünschtes Ergebnis:

![drawing_edge_problem2](https://fhdwdev.ha.bib.de/gitea/attachments/792a53ed-fc03-4033-9f8d-c870ea9a8ac9)
*Gewünschtes Ergebnis bei der Zeichnen über den Rand Problematik*


#### Lösungskonzept für das Zeichnen über den Rand
Das Ziel ist es, horizontal über den Rand der UV-Map zu zeichnen, insofern es sich dabei um den kürzeren Weg handelt. Um zu ermitteln, was die kürzere Strecke zwischen den Punkten ist, müssen diese Strecken berechnet werden. 

Die Streckenberechnung zwischen zwei Punkten innerhalb der UV-Map ist wie folgt möglich:

$$
|\overline{P_0P_1}| = P_1 - P_0 = \sqrt{(x_1 - x_0)^2 + (y_1 - y_0)^2}
$$

Um den Abstand der Punkte über den horizontalen Rand hinaus zu ermitteln, kann folgende Berechnung durchgeführt werden:

$$
x_{nR} : \text{Abstand von Punkt n zum nächsten (horizontalen) Rand} \\
|\overline{P_1P_0}| = \sqrt{(x_{0R} + x_{1R})^2 + (y_1 - y_0)^2}
$$

Soll nun eine Strecke von $P_0$ nach $P_1$ über den Rand hinaus gezeichnet werden, muss dies so geschehen, dass $P_0$ zunächst über eine Linie mit dem nächsten Rand verbunden wird. Anschließend wird $P_1$ mit dessen nächsten Rand verbunden. Bei diesem Verfahren muss allerdings beachtet werden, dass der Anstieg der Strecke korrekt übernommen wird. Siehe die folgende Grafik.

![UV-MapP0P1](https://fhdwdev.ha.bib.de/gitea/attachments/0fa8d6a3-d10d-4c24-8b3b-0b289c41e332)
*Zeichnen über den Rand Problematik mit Anstieg*

Um den Anstieg beizubehalten, muss dieser mit der anschließenden Formell berechnet werden.

$$
m = \frac{\Delta y}{\Delta x} = \frac{y_1 - y_0}{x_{0R} + x_{1R}}
$$

Mithilfe des Anstiegs der Breite der UV-Map und der Geradengleichung kann die anschließende formell zur Ermittlung des Punktes am Rand ermittelt werden.

$$
y_R, x_R : \text{Koordinatenwert am (rechten) Rand der UV-Map} \\
y_R = m \cdot x_R
$$

Der Punkt am rechten Rand der UV-Map ist dann $P_{RR}(x_R | y_R)$. Dieser Punkt muss nun über eine Linie vom entsprechend mit $P_0$ oder $P_1$ verbunden werden, je nachdem welcher sich am rechten Rand befindet. Bezogen auf das obenstehende Beispiel würde es sich dabei um $P_1$ handeln. Der Punkt am linken Rand ist $P_{RL}(0|y_R)$. Dieser muss dann mit dem zum linken Rand nächsten Punkt verbunden werden. Im oberen Beispiel ist dies also $P_0$.

### Harnröhren Problematik
Da in der Anwendung die Tumore sowohl in der Blase als auch im Harnröhreneingang eingezeichnet werden sollen können, wird eine Kamerasicht benötigt, bei der das Einzeichnen von Tumoren im Harnröhreneingang möglich ist.
Die Harnröhre ist proportional passend zur Blase modelliert, was sie sehr schmal macht. Genau dies ist das Problem der Kamerasicht. Durch diese schmale Harnröhre ist es schwierig, eine vernünftige Kameraposition zu erhalten, bei der das Drehen und Schwenken der Sicht mit anschließendem Einzeichnen der Tumore vernünftig funktioniert.

## Umwandelung zwischen Koordinatensystemen
Die Punkte innerhalb des 3D-Modells werden von ThreeJS als kartesische Koordinaten dargestellt. Für die Anwendung ist es allerdings notwendig, diese in geografische Koordinaten und zurück zu konvertieren.

Bei der Umwandlung wurden die geografischen Koordinaten wie Kugelkoordinaten ohne einen angegebenen Radius $r$ behandelt. Dabei entspricht der Polarwinkel $\theta$ den Breitengraden und der Azimutwinkel $\phi$ den Längengraden. Der Radius kann lediglich für die Berechnung von kartesischen Koordinaten in geografische Koordinaten verwendet werden. Dieser kann folgendermaßen berechnet werden.

$$
r = \sqrt{x^2 + y^2 + z^2}
$$

**Breitengrade / Polarwinkel:**
Aus der [Bereichsdefinion](https://fhdwdev.ha.bib.de/gitea/INT2021Q4/resect/wiki/Texterzeugung#bereichsdefinition) des Aufgabenpaket AP2b lässt sich die nachstehende Tabelle erstellen.
| $\theta$ | $\frac{y}{r}$ |
| -------- | -------- |
| 0°       | -1     | 
| 45°      | -0.5   | 
| 90°      | 0    | 
| 135°     | 0.5  | 
| 180°     | 1     |


**Längengrad / Azimutwinkel**
| $\phi$ | $\frac{x}{r}$ | $\frac{z}{r}$ |
| ------ | ------------- | ------------- |
| 0°     | 1             | 0             |
| 45°    | 0.5           | -0.5          |
| 90°    | 0             | -1            |
| 135°   | -0.5          | -0.5          |
| 180°   | -1            | 0             |
| 225°   | -0.5          | 0.5           |
| 270°   | 0             | 1             |
| 315°   | 0.5           | 0.5           |
| 360°   | 1             | 0             |

### Kartesische Koordinaten -> Geografische Koordinaten
Mithilfe der Tabellen für die Beziehung zwischen den Koordinaten und den Winkeln lässt sich für die Berechnung des Breitengrades folgende formell aufstellen.
$$
\theta = 90° + 90°\frac{y}{r}
$$

Zur Berechnung des Längengrades kann diese Funktion aufgestellt werden.
$$
\
    \phi = 
\begin{cases}
    -90°\frac{x}{r} + 90°,& \text{wenn } z\leq 0\\
    90°\frac{z}{r} + 180°,& \text{wenn } z>0 \wedge x\leq 0 \\
    90°\frac{x}{r} + 270°,& \text{wenn } z>0 \wedge x>0
\end{cases}
\
$$

### Geografische Koordinaten -> Kartesische Koordinaten
Aus den geografischen Koordinaten lässt sich der Radius nicht bestimmen. Somit ist auch kein konkreter Punkt auf dem 3D-Modell bestimmbar. Stattdessen wird dabei ein dreidimensionaler Vektor ([`THREE.Vector3`](https://threejs.org/docs/index.html?q=vector#api/en/math/Vector3)) erstellt. Für diesen gilt: 
$$
x,y,z \in [-1,1]
$$

Die Berechnung der Werte für x, y und z findet folgendermaßen über die Längen- und Breitengrade statt.

$$
x = \cos(\phi) \\
y = \sin(\theta - 90°) \\
z = -\sin(\phi)
$$

Um nun die Punkte auf dem 3D-Modell bestimmen zu können, wird der Vektor in Kombination mit RayCasting verwendet. Dabei wird der hat der Strahl seinen Ursprung im Mittelpunkt des 3D-Modells von verläuft dann in Richtung des Vektors. Alle vom Strahl geschnittenen Punkte werden dann wie im Abschnitt [Positionsanzeige](#positionsanzeige) beschrieben, eingezeichnet und zu einem Pfad verbunden.

## Anbindung an den Anwendungskern
Die Anbindung an den Anwendungskern ist bisher noch nicht erfolgt. Allerdings wurde durch die Umwandlung von Koordinatensystem bereits eine Grundlage für diese geschaffen, sodass der Import und Export von Koordinaten zukünftig ohne großen Zeitaufwand geschehen kann.


## Mockup

### Gesamtansicht Operation erstellen

Auf der Seite "Operation erstellen" wurde das 3D-Modell optisch der Informationsbox angepasst. Das wurde erzielt, in dem der Hintergrund des Modell-Fensters schattiert wurde und das Modell-Fenster auf die selbe Höhe wie die Informationsbox gebracht wurde.
![Gesamtansicht Operation erstellen](https://fhdwdev.ha.bib.de/gitea/attachments/ce1ef8f5-3083-45e9-8de8-d3143351b214)
*Gesamtansicht Operation erstellen*

### Informationsbox
In der ersten Version der Oberfläche konnte die gesamte Seite inklusive Footer in Tabs aufgeteilt werden. Das 3D-Modell soll pro Operation gleich bleiben, die Informationen unterscheiden sich jedoch pro Tumor. Aus diesem Grund sollte die Funktion der [Tabs](https://fhdwdev.ha.bib.de/gitea/INT2021Q4/resect/issues/20) bestehen bleiben, aber nicht für die gesamte Seite, sondern pro Tumor in der Informationsbox. 
Um die Tumore im Modell unterscheiden zu können, sollen diese farblich gekennzeichnet werden. Damit die Konfiguration des Tumors in der Informationsbox einfach dem gezeichneten Tumor zugeordnet werden kann, wird der [Tab in der jeweils selben Farbe](https://fhdwdev.ha.bib.de/gitea/INT2021Q4/resect/issues/25)  gekennzeichnet. 

Die [Auswahlmöglichkeiten](https://fhdwdev.ha.bib.de/gitea/INT2021Q4/resect/issues/51) in der Informationsbox wurden um die Optionen "Sonstige" für alle Unterpunkte und "Koagulation" für Technik ergänzt. Des Weiteren wurden für alle Unterpunkte ["defaultValues"](https://fhdwdev.ha.bib.de/gitea/INT2021Q4/resect/issues/34) eingerichtet. Diese sind immer zu Beginn ausgewählt. 
![Informationsbox](https://fhdwdev.ha.bib.de/gitea/attachments/28ecf893-41f1-4738-8c2d-8c1211c83914)
*Informationbox*


## Zukünftige Erweiterungen:
### Positionseingabe
* Kamera zwischen verschiedenen Blickwinkeln wechseln lassen
* Kamera auf Ausgangsposition zurücksetzen
* Zoom reaktivieren, aber verhindern Blase verlassen zu können

### Positionsanzeige
* Schrift des 3D Modells vernünftig in Anwendung anzeigen lassen
* Lösungkonzept für das Zeichnen über den Rand implementieren und testen

### Werkzeuge der Positionseingabe
Derzeit erfolgt die Positionseingabe über eine direkte Verbindung von zwei oder mehr Punkten. Unter dem Punkt [Positionsanzeige](#positionsanzeige) wird diese Darstellung näher erläutert. 

Zukünftig wollen wir die Positionseingabe über einen Point, eine Line, eine Polyline oder eine Polyarea realisieren. Das bedeutet jedoch nicht gleichzeitig, dass der Anwender zwischen diesen Tools entscheiden muss. Mindestens Point, Line und Polyline können über ein und dasselbe Werkzeug zum Einzeichnen verwendet werden. Diese Unterscheidung dient hauptsächlich den internen Verarbeitungszwecken. 

![shapes](https://fhdwdev.ha.bib.de/gitea/attachments/d2601443-2979-45d6-abef-110ab04bef7f)
*Werkzeuge der Positionseingabe*

#### Point
Ein Point ist ein einzelner eingezeichneter Point mit einem definierten Radius.

#### Line
Eine Line sind zwei eingezeichnete Punkte, zwischen denen eine Verbindung mit einem festgelegten Radius gezogen wird.

#### Polyline
Eine Polyline ist eine Verbindung von mindestens 3 eingezeichneten Punkten. Die Polyline besitzt zudem einen fest definierten Radius, anhand derer die Strichstärke festgemacht wird.

#### Polyarea
Eine Polyarea definiert ein Polygon aus eingezeichneten Punkten. Die Besonderheit hierbei ist es, dass der Startpunkt auch gleichzeitig der Endpunkt ist. 


### Mockup
#### [Button](https://fhdwdev.ha.bib.de/gitea/INT2021Q4/resect/issues/24)

Es soll ein Druckenbutton eingefügt werden. Wird dieser gedrückt, soll damit die Generierung des Ausgabetextes und des Serialisierungsschlüssels angestoßen werden. 

#### [Konfiguration der Tabs zwischenspeichern](https://fhdwdev.ha.bib.de/gitea/INT2021Q4/resect/issues/21)

Derzeit gehen die Änderung in einem Tab verloren, wenn man zwischen diesen wechselt. Im nächsten Schritt sollen eine Möglichkeit gefunden werden, diese zwischen zu speichern. Dadurch würden Änderungen nicht bei einem Tabwechsel nicht mehr verloren gehen.

#### [Felder für Text- und Schlüsselausgabe](https://fhdwdev.ha.bib.de/gitea/INT2021Q4/resect/issues/55)

Derzeit existieren in der Oberfläche weder ein Feld für die Text- noch die Serialisierungsschlüsselausgabe. Diese sollen unterhalb der Informationsbox eingefügt werden.
 
#### [Positionierung Informationsbox und 3D-Modell](https://fhdwdev.ha.bib.de/gitea/INT2021Q4/resect/issues/56)

Die Informationsbox und das 3D-Modell befinden sich bereits an der ungefähren Position, jedoch ist ein sehr breiter Rand rechts vorhanden. Dieser soll beseitigt werden und für den Nutzer eine optisch bessere Ansicht geschaffen werden.