From 031e5f49a5cc8711019ded195fe7ffea883e06c6 Mon Sep 17 00:00:00 2001 From: Mike van Riel Date: Mon, 21 Oct 2024 13:40:02 +0200 Subject: [PATCH] Append Coding Standard with more Directory related information, and add the Architectural Decision for symbology --- .../contributing/coding-standards.md | 58 +++++ .../decisions/20241009-styling-of-layers.md | 229 ++++++++++++++++++ docs/docs/developers/decisions/index.md | 41 ++++ 3 files changed, 328 insertions(+) create mode 100644 docs/docs/developers/decisions/20241009-styling-of-layers.md create mode 100644 docs/docs/developers/decisions/index.md diff --git a/docs/docs/developers/contributing/coding-standards.md b/docs/docs/developers/contributing/coding-standards.md index b86b081..3539438 100644 --- a/docs/docs/developers/contributing/coding-standards.md +++ b/docs/docs/developers/contributing/coding-standards.md @@ -21,6 +21,64 @@ intent effectively. It is important to read the full guide at [https://unity.com/how-to/naming-and-code-style-tips-c-scripting-unity](https://unity.com/how-to/naming-and-code-style-tips-c-scripting-unity) for a more complete picture of the coding guidelines followed in this project. +### General Principles + +* Call a thing what it is. A bird should be called Bird. +* Choose names that can be pronounced and remembered. +* Be consistent. When you choose a name, stick to it. +* Use Pascal case, like this: ComplicatedVerySpecificObject. Do not use spaces, underscores, or hyphens. +* Do not use version numbers, or words to indicate their progress (WIP, final). +* Do not use abbreviations: DVamp@W should be DarkVampire@Walk. +* Keep the most specific descriptor on the left: PauseButton, not ButtonPaused. It is, for instance, easier to find + the pause button in the inspector if not all buttons start with the word Button. +* Some names form a sequence. Use numbers in these names, for example, PathNode0, PathNode1. Always start with 0, not 1. +* Do not use numbers for things that don’t form a sequence. For example, Bird0, Bird1, Bird2 should be Flamingo, Eagle, Swallow. + +## Structure + +The organisation of your project folder should follow a similar pattern. + +!!! warning + + We are in the process of moving project files to the structure below, until that process is complete you can expect + to find asset folders directly in the root of the Assets folder. + + For new components it is recommended to follow this structure. + +We differentiate between architectural folders and asset folders. Architectural folders are meant to organize the +project in such a way that we have a modular -or composable- architecture with independent layers; asset folders can be +found inside each architectural folder and is similar to the regular folder structure that is normal with Unity. + +### Architectural folders + +In the `Assets` folder there are four special folders: + +1. _Application - assets needed for the application itself, such as + - Rendering pipelines, + - Inputsystem, + - Overall ui, + - Bootstrapping + - etc. +2. _BuildingBlocks - contains a series of folders for each building block that can be consumed by a functionality +3. _Functionalities +4. _UIKit + +### Unity Folder Structure + +- Animations +- Editor +- Fonts +- Materials +- Models +- Resources +- Prefabs +- Scenes +- ScriptableObjects +- Scripts +- Shaders +- Sprites +- Textures + ## 2. Bracing Style We use the **Allman** style for braces, which is standard in most C# coding conventions. This style places opening diff --git a/docs/docs/developers/decisions/20241009-styling-of-layers.md b/docs/docs/developers/decisions/20241009-styling-of-layers.md new file mode 100644 index 0000000..831e4df --- /dev/null +++ b/docs/docs/developers/decisions/20241009-styling-of-layers.md @@ -0,0 +1,229 @@ +# 2024-10-09 - Laagstijlen / Symbologie + +| | | +|------------|--------------| +| **Datum** | 09-10-2024 | +| **Status** | Geaccepteerd | + +## Context + +Als uitkomst van dit voorstel willen we dat Netherlands3D gebruik maakt van visualisaties waarbij lagen worden +gestileerd met behulp van symbologie, gebaseerd op de **OGC Cartographic Symbology - Part 1: Core Model & Encodings** +(https://docs.ogc.org/DRAFTS/18-067r4.html). De implementatie is een **systeem vergelijkbaar met CSS**, waarbij een +**Symbolizer** styling-eigenschappen bevat, en **Selectors** (beschreven als **Expressions**) bepalen wanneer en hoe +deze eigenschappen worden toegepast. + +Hoewel de term "symbologie" gebruikelijk is in GIS, noemen we dit systeem "styling" om het toegankelijker te maken voor +een breder publiek en de parallel met CSS te benadrukken. + +!!! warning "Scheiding tussen Styling en Visualisatie" + + Het styling-systeem zelf doet **niets** met de daadwerkelijke visualisatie. Het systeem beschrijft alleen hoe de + styling moet zijn, maar het is aan de visualisatiecode die hoort bij een laag om te bepalen of en hoe de + styling-eigenschappen worden toegepast. Dit betekent dat het mogelijk is dat bepaalde styling-eigenschappen **niet** + worden toegepast als de visualisatiecode daarvoor geen ondersteuning biedt. + +## Besluit + +We implementeren een flexibel styling-systeem waarin **Symbolizers** styling-eigenschappen bevatten, en **Selectors** en +**Expressions** bepalen wanneer deze eigenschappen van toepassing zijn. Dit systeem wordt toegepast op lagen, en de +mogelijke waarden binnen een Symbolizer worden bepaald door de aanwezige **Symbolizer-extensies**. + +Externe partijen kunnen hun eigen extensies en **styling-eigenschap prefixes** toevoegen, volgens het patroon uit +hoofdstuk 8.1.7 van de OGC-specificatie: `vendor..`. Voor Netherlands3D betekent dit dat +we de prefix `vendor.netherlands3d.` zullen hanteren. + +## Rationale + +Het gebruik van een systeem, vergelijkbaar met CSS, biedt de flexibiliteit en uitbreidbaarheid die nodig is voor het +werken met dynamische geodata. Door selectors en expressies te gebruiken, kunnen we styling-eigenschappen toepassen op +basis van attribuutwaarden of andere condities. Symbolizer-extensies zorgen ervoor dat nieuwe styling-eigenschappen +kunnen worden toegevoegd zonder de kernstructuur te verstoren. Door gebruik te maken van extension methods met +default-waarden, waarborgen we een voorspelbare werking van het systeem, zelfs wanneer geen expliciete waarde aanwezig +is. + +## Codeorganisatie + +De implementatie van het systeem wordt ondergebracht in een aparte **OpenUPM-package**. De code voor de verschillende +**Symbolizer-extensies** wordt georganiseerd in mappen, waarbij iedere extensie een **Requirement Class** uit de +OGC-specificatie volgt. Dit maakt het beheer van verschillende extensies overzichtelijk en zorgt voor een heldere +scheiding tussen kernfunctionaliteit en uitbreidingen. + +Wij passen zelf de **styling-eigenschap prefix** `vendor.netherlands3d.` toe voor onze eigen +uitbreidingen. Derde partijen kunnen hun eigen extensies via hun eigen packages toevoegen en daarbij hun eigen +**styling-eigenschap prefixes** introduceren volgens hetzelfde patroon uit hoofdstuk 8.1.7 van de OGC-specificatie. + +## Implementatiestrategie + +We voeren de implementatie **stapsgewijs** uit. Dit houdt in dat we niet alle eigenschappen van de Symbolizer in één +keer toevoegen, maar in kleine iteraties werken. Elke iteratie implementeert één of meer specifieke **eigenschappen** +van de Symbolizer, afhankelijk van de eisen van een user story. Bijvoorbeeld: wanneer een user story vraagt om een laag +een enkele vulkleur te geven, wordt alleen de **fill**-eigenschap van de Symbolizer-extensie voor vectorfeatures +geïmplementeerd. + +Hoewel hoofdstuk 17 van de OGC-specificatie extra opties beschrijft zoals het gebruik van het "alter" veld, variabelen +en het includen van stylesheets, zullen we deze opties expliciet **niet** implementeren. Ons doel is niet om de +volledige specificatie te implementeren, maar om de organisatiestructuur van symbolizers, expressies en styling te +adopteren. Dit voorkomt dat we het wiel opnieuw uitvinden, maar zorgt ervoor dat we ons beperken tot een basisstructuur +die ons flexibiliteit biedt zonder de complexiteit van volledige implementatie. + +## Implementatie + +```mermaid +classDiagram + namespace Netherlands3D { + class Layers + } + namespace Layers { + class LayerData { + +LayerStyle styles + } + class Styles + } + + namespace Styles { + class LayerStyle { + +StylingRule stylingRules + +Metadata metadata + } + + class Metadata { + + string name + } + + class StylingRule { + +string name + +Symbolizer symbolizer + +Expression selector + } + + class Expression { + } + + class Symbolizer { + - Dictionary properties + ~ void GetProperty(string name) + ~ object SetProperty(string name, object value) + } + + class CoreSymbolizerExtension { + +GetVisibility() bool + +SetVisibility(bool visible) + +GetOpacity() float + +SetOpacity(float opacity) + } + + class VectorSymbolizerExtension { + +GetFill() Color + +SetFill(Color fillColor) + } + } + + LayerData --> "0..*" LayerStyle + LayerStyle --> "0..*" StylingRule + LayerStyle --> "0..1" Metadata + StylingRule --> "0..1" Symbolizer + StylingRule --> "0..1" Expression + CoreSymbolizerExtension .. Symbolizer : extension of + VectorSymbolizerExtension .. Symbolizer : extension of + +``` + +!!! note "Let op" + + We wijken in de naamgeving af van de beschrijving in de OGC standaard bij de LayerStyle klasse, in de OGC standaard + heeft deze enkel `Style`, maar om consistent te zijn in de applicatie en ter verduidelijking voegen wij het + voorzetsel `Layer` toe om te benadrukken dat dit een style is behorende bij layers; vergelijkbaar + met `LayerPropertyData` + +### Opslag van Stijlen in het Projectbestand + +Elke **layer** in het projectbestand krijgt een nieuw veld genaamd **"styles"** waarin de stylinginformatie wordt +opgeslagen. Dit veld verwijst naar een JSON-structuur die hetzelfde formaat is zoals gedefinieerd in hoofdstuk 17 van de +**OGC Cartographic Symbology - Part 1: Core Model & Encodings** OGC-standaard. Hierdoor kunnen we stijlen opnieuw laden +en heen en weer converteren tussen het interne representatiemodel en het JSON-bestand. Dit zorgt ervoor dat stijlen +behouden blijven wanneer ze eenmaal gedefinieerd zijn. + +!!!warning "Technische Vereisten voor Serialization" + + Omdat het hele projectbestand wordt geserialized met **Newtonsoft's JSON.net**, moet de klassestructuur van de + symbolizers ook in dit format worden geserialized. Dit waarborgt strict typing en maakt het consistent met de rest + van het project. + + Voor de Symbolizer zal een aparte JsonConverter geschreven moeten worden die ervoor zorgt dat de waarden in + de `properties` dictionary als losse velden direct in de JSON voor het symbolizer object verschijnen en niet dat een + extra veld `properties` in de JSON terecht komt. + +### Expressions, en Selectors + +Bij het implementeren van **expressions** en **selectors** volgen we de structuur zoals beschreven in hoofdstuk 8.1.5 +van de **OGC Cartographic Symbology - Part 1: Core Model & Encodings**. Net als bij de styling-eigenschappen, zullen we +de expressie-taal niet in één keer volledig implementeren, maar stap voor stap, afhankelijk van de vereisten van user +stories. + +!!!example "Voorbeeld" + + Een voorbeeld hiervan is een user story waarin we een groep features kleuren op basis van een attribuutwaarde. Voor deze + implementatie hebben we alleen de volgende onderdelen nodig: + + - Een **vergelijkingsoperator** (alleen gelijkheid), + - Een **attribuut-identiteits-expressie** (om het attribuut aan te duiden), + - Een **TextLiteral-expressie** (om de letterlijke waarde te beschrijven). + +Dit iteratieve proces maakt het mogelijk om gericht de functionaliteiten toe te voegen die direct noodzakelijk zijn voor +de behoeften van de gebruikers. + +## Risico's + +De OGC Cartographic Symbology-standaard bevindt zich in een draft-stadium, wat betekent dat de specificaties nog kunnen +veranderen. We accepteren dat onze implementatie niet volledig overeenkomt met de definitieve specificatie, en houden +hier rekening mee in toekomstige aanpassingen. + +## Appendix A: Woordenlijst + +- **OGC Cartographic Symbology-standaard**: De standaard waarop het styling-systeem is gebaseerd. +- **Layer**: Een verzameling van geografische objecten die in een bepaalde stijl worden weergegeven. +- **Styling**: Het toekennen van visuele eigenschappen aan geografische objecten. +- **Style**: Een verzameling van stylingregels die wordt toegepast op een layer. +- **Styling-eigenschap**: Een specifieke visuele eigenschap, zoals kleur of lijnstijl, die wordt toegepast op een + object. +- **Symbolizer**: Een object dat styling-eigenschappen bevat voor lagen. +- **Symbologie**: Een GIS-term voor het beschrijven van hoe geografische objecten visueel worden weergegeven. +- **Selector**: Een conditie die bepaalt wanneer een symbolizer moet worden toegepast. +- **Expression**: Een voorwaarde of waarde die bepaalt hoe en wanneer een bepaalde styling-eigenschap wordt toegepast. +- **Symbolizer-extensie**: Uitbreidingen die nieuwe styling-eigenschappen toevoegen aan de Symbolizer. +- **Styling-eigenschap prefix**: Een voorvoegsel toegevoegd aan eigen styling-eigenschappen om conflicten met + OGC-gedefinieerde eigenschappen te voorkomen, zoals beschreven in hoofdstuk 8.1.7 van de OGC-specificatie. + +## Appendix B: Voorbeeld flow voor het wijzigen van kleur + +Wanneer een gebruiker de kleur van een laag aanpast in de UI, doorloopt de applicatie de volgende stappen: + +```mermaid +graph TD + A[Gebruiker past kleur aan in UI] --> B[UI haalt huidige laag op] + B --> C[UI zoekt standaard stylingregel op en haalt Symbology object op] + C --> D[UI roept SetFillColor aan op Symbology-object] + D --> E[Symbology slaat nieuwe kleur op in private dictionary] + subgraph Update van visualisatie + E --> F[Laag triggert update naar visualisatieklasse] + F --> G[Visualisatieklasse haalt Symbology op] + G --> H[Visualisatieklasse leest FillColor uit] + H --> I[Visualisatieklasse past nieuwe kleur toe] + end + I --> J[Visualisatie wordt bijgewerkt] +``` + +1. **Gebruiker past kleur aan in UI**: De gebruiker kiest een nieuwe kleur voor een laag. +2. **UI haalt huidige laag en standaard stylingregel op**: De UI haalt de geselecteerde laag en de standaard + stylingregel op, inclusief het bijbehorende Symbology-object. +3. **Symbology-object bijwerken**: De UI roept de `SetFillColor` method aan op het Symbology-object, dat de nieuwe kleur + opslaat in een private dictionary. +4. **Update van visualisatie**: De laag triggert een update naar de visualisatieklasse, die vervolgens het + Symbology-object ophaalt, de nieuwe kleur uitleest, en deze toepast op de visualisatie. +5. **Visualisatie wordt bijgewerkt**: De visualisatie wordt automatisch bijgewerkt om de nieuwe stijl van de laag te + reflecteren. + +Het updaten van de visualisatie is een herbruikbaar blok dat niet alleen in deze flow kan worden ingezet, maar ook bij +het openen van een project. Door de scheiding tussen de symbologie data en de visualisatie kan, vergelijkbaar met de +scheiding tussen LayerData en visualisatie, styling in het project uniform worden opgeslagen. diff --git a/docs/docs/developers/decisions/index.md b/docs/docs/developers/decisions/index.md new file mode 100644 index 0000000..d16b09e --- /dev/null +++ b/docs/docs/developers/decisions/index.md @@ -0,0 +1,41 @@ +# Architectural Decisions + +In the Netherlands3D project, we recognize the importance of documenting key architectural decisions to ensure that the +rationale behind our choices is clear, traceable, and accessible to all contributors and stakeholders. This section +serves as a living document where we track these decisions, both accepted and rejected, to provide a transparent record +of our technical direction. + +## Why Track Architectural Decisions? + +Architectural decisions often shape the foundation of a project and influence how future features are built. By +documenting these decisions: + +* **We ensure clarity and alignment**: Everyone working on the project understands why certain paths were chosen over + others. +* **We maintain consistency**: Having a record of decisions helps to maintain a coherent and stable architectural vision + as the project evolves. +* **We enable future-proofing**: Teams and future developers can reference past decisions to avoid re-evaluating or + re-implementing resolved issues. +* **We encourage informed collaboration**: It creates an open dialogue for discussing technical options and ensures + everyone has access to the decision-making process. + +## What to Expect + +In this section, you will find a record of: + +* **Accepted proposals**: Decisions that have been approved and are guiding the current development. +* **Rejected proposals**: Ideas that were considered but ultimately not adopted, along with the reasons why. +* **Ongoing discussions**: Some entries may reflect decisions that are still under consideration, providing insight into + our ongoing thought process. + +Each architectural decision is written in a lightweight, actionable format that includes a summary of the problem, the +considered options, the decision taken, and the rationale behind it. We strive to keep these entries concise while +capturing the essential technical and business context. + +## Language Considerations + +Since the core Netherlands3D team operates primarily in Dutch, many architectural proposals and discussions will +initially be documented in Dutch. This allows us to facilitate faster and more in-depth discussions within the team. +However, we strive to provide English translations for most of these decisions to ensure that non-Dutch speakers can +follow and contribute to the project. Whenever possible, both Dutch and English versions of each decision will be +available.