Fantasy-Map-Generator/QGIS Style Conversion from Fantasy Map.md
barrulus 83573c8936 Enhance population counting accuracy and add comprehensive geoJSON exports
Population System Fixes:
- Fix province, culture, and religion population calculations to exclude rural population from cells without burgs
- Burgs now represent ALL population for their cells (both urban and rural components)
- Eliminate double-counting where cell populations were incorrectly added to burg populations

Export Enhancements:
- Add complete geoJSON export for burgs with all settlement properties
- Enhance routes geoJSON export to include type and feature metadata
- Add missing length and width properties to rivers geoJSON export
- Fix burg coordinate system to match CSV export format with xWorld/yWorld fields

UI Improvements:
- Add burgs export button to geoJSON export interface
- Fix vite module loading issue by adding type="module" to notes-editor.js script tag

Documentation:
- Create comprehensive QGIS Style Conversion guide with route types, burg features, and relief rendering methods
- Add WKT coordinate reference system definition for Fantasy Map Cartesian CRS
- Include rule-based styling examples and data processing workflows
2025-08-15 19:00:03 +01:00

17 KiB

QGIS Style Conversion from Fantasy Map JSON

Overview

This document converts the fantasy map styling JSON to QGIS-compatible styles. The original JSON contains SVG/CSS-style properties that need to be translated to QGIS symbology.

Layer Style Conversions

Water Bodies

Rivers (#rivers)

<!-- QML Style for Rivers -->
<symbol alpha="1" type="line" name="rivers">
  <layer class="SimpleLine" enabled="1">
    <prop k="color" v="0,137,202,255"/>
    <prop k="width" v="0.8"/>
    <prop k="capstyle" v="round"/>
  </layer>
</symbol>

Freshwater Lakes (#freshwater)

<!-- QML Style for Freshwater -->
<symbol alpha="1" type="fill" name="freshwater">
  <layer class="SimpleFill" enabled="1">
    <prop k="color" v="202,227,247,255"/>
    <prop k="outline_color" v="0,137,202,255"/>
    <prop k="outline_width" v="1.01"/>
  </layer>
</symbol>

Ocean Base (#oceanBase)

<!-- QML Style for Ocean -->
<symbol alpha="1" type="fill" name="ocean">
  <layer class="SimpleFill" enabled="1">
    <prop k="color" v="180,210,243,255"/>
    <prop k="outline_style" v="no"/>
  </layer>
</symbol>

Landmass and Terrain

Landmass (#landmass)

<!-- QML Style for Landmass -->
<symbol alpha="1" type="fill" name="landmass">
  <layer class="SimpleFill" enabled="1">
    <prop k="color" v="238,246,251,255"/>
    <prop k="outline_style" v="no"/>
  </layer>
</symbol>

Ice (#ice)

<!-- QML Style for Ice -->
<symbol alpha="0.9" type="fill" name="ice">
  <layer class="SimpleFill" enabled="1">
    <prop k="color" v="232,240,246,255"/>
    <prop k="outline_color" v="232,240,246,255"/>
    <prop k="outline_width" v="1"/>
  </layer>
</symbol>

Relief and Terrain

The Fantasy Map Generator uses SVG icons placed based on elevation to create relief effects. QGIS can replicate this using several approaches:

Method 1: Hillshade from Elevation Data

Create a Digital Elevation Model (DEM) from the cells GeoJSON data:

  1. Import cells GeoJSON with elevation data in the height property
  2. Convert to raster: Vector → Conversion Tools → Rasterize
    • Use height field for raster values
    • Set appropriate resolution (e.g., 100m)
  3. Generate hillshade: Raster → Analysis → Hillshade
    • Z factor: 1.0
    • Azimuth: 315° (northwest)
    • Altitude: 45°
<!-- Hillshade Layer Style -->
<rasterrenderer opacity="0.6" type="hillshade">
  <rasterproperties>
    <mDrawingStyle>SingleBandGray</mDrawingStyle>
    <mColorShadingAlgorithm>0</mColorShadingAlgorithm>
    <mInvertColor>false</mInvertColor>
    <mGrayBand>1</mGrayBand>
  </rasterproperties>
</rasterrenderer>

Method 2: Icon-Based Relief (Fantasy Map Style)

Replicate the original icon-based relief using rule-based point symbols:

Step 1: Create point layer from cell centroids

  • Vector → Geometry Tools → Centroids
  • Filter: "height" >= 50 (land areas only)

Step 2: Configure rule-based symbology

<!-- Mountain Icons (height > 70) -->
<symbol alpha="1" type="marker" name="mountains">
  <layer class="SvgMarker" enabled="1">
    <prop k="size" v="8"/>
    <prop k="name" v="mountain.svg"/>
    <prop k="color" v="139,69,19,255"/>
    <prop k="angle" v="0"/>
  </layer>
</symbol>

<!-- Hill Icons (height 50-70) -->
<symbol alpha="1" type="marker" name="hills">
  <layer class="SvgMarker" enabled="1">
    <prop k="size" v="5"/>
    <prop k="name" v="hill.svg"/>
    <prop k="color" v="101,67,33,255"/>
    <prop k="angle" v="0"/>
  </layer>
</symbol>

Step 3: Rule expressions

  • Mountains: "height" > 70
  • Hills: "height" >= 50 AND "height" <= 70

Method 3: Density-Controlled Relief Points

For scattered relief icons (matching FMG's Poisson distribution):

Step 1: Use Geometry Generator with point symbols

  • Symbol type: Point
  • Geometry type: Point
  • Expression for scattered points:
-- Generate multiple points per cell based on elevation
CASE 
  WHEN "height" > 70 THEN 
    -- Mountains: 2-4 points per cell
    array_to_string(
      array_foreach(
        generate_series(1, floor("height"/30)),
        point_on_surface(
          translate($geometry, 
            rand(-50,50), 
            rand(-50,50)
          )
        )
      ), ','
    )
  WHEN "height" >= 50 THEN
    -- Hills: 1-2 points per cell  
    point_on_surface($geometry)
  ELSE
    NULL
END

Combine multiple techniques for best results:

  1. Base layer: Hillshade raster (opacity 30%)
  2. Mid layer: Graduated cell polygons by elevation
  3. Top layer: Scattered point symbols for major peaks

Graduated Elevation Symbology:

<!-- Low elevation -->
<symbol alpha="0.3" type="fill" name="low">
  <layer class="SimpleFill" enabled="1">
    <prop k="color" v="144,238,144,76"/>
  </layer>
</symbol>

<!-- High elevation -->
<symbol alpha="0.5" type="fill" name="high">
  <layer class="SimpleFill" enabled="1">
    <prop k="color" v="139,69,19,127"/>
  </layer>
</symbol>

Relief Color Ramps

For elevation-based coloring:

Height Classes:

  • 0-20: Ocean (blue tones)
  • 20-40: Lowlands (green tones)
  • 40-60: Hills (yellow-brown tones)
  • 60-80: Mountains (brown tones)
  • 80+: High peaks (gray-white tones)
<!-- Elevation Color Ramp -->
<colorrampshader colorRampType="INTERPOLATED">
  <item alpha="255" value="0" color="#4A90E2" label="Ocean"/>
  <item alpha="255" value="20" color="#90EE90" label="Coast"/>
  <item alpha="255" value="40" color="#F4A460" label="Hills"/>
  <item alpha="255" value="60" color="#8B4513" label="Mountains"/>
  <item alpha="255" value="80" color="#696969" label="High Peaks"/>
</colorrampshader>

Political Boundaries

State Borders (#stateBorders)

<!-- QML Style for State Borders -->
<symbol alpha="1" type="line" name="state_borders">
  <layer class="SimpleLine" enabled="1">
    <prop k="color" v="0,0,0,255"/>
    <prop k="width" v="1.01"/>
    <prop k="capstyle" v="flat"/>
  </layer>
</symbol>

Province Borders (#provinceBorders)

<!-- QML Style for Province Borders -->
<symbol alpha="0.8" type="line" name="province_borders">
  <layer class="SimpleLine" enabled="1">
    <prop k="color" v="0,0,0,255"/>
    <prop k="width" v="0.69"/>
    <prop k="capstyle" v="round"/>
  </layer>
</symbol>

Transportation

Routes can be styled based on their type property using QGIS rule-based styling. The available route types are:

  • royal: Major roads connecting capitals and important cities
  • market: Trade routes connecting market towns
  • local: Secondary roads for regional connectivity
  • footpath: Walking trails and paths
  • majorSea: Major shipping routes between ports

Royal Roads (type = 'royal')

<!-- QML Style for Royal Roads -->
<symbol alpha="1" type="line" name="royal_roads">
  <layer class="SimpleLine" enabled="1">
    <prop k="color" v="255,44,44,255"/>
    <prop k="width" v="1.2"/>
    <prop k="capstyle" v="flat"/>
  </layer>
</symbol>

Market Roads (type = 'market')

<!-- QML Style for Market Roads -->
<symbol alpha="1" type="line" name="market_roads">
  <layer class="SimpleLine" enabled="1">
    <prop k="color" v="255,100,44,255"/>
    <prop k="width" v="0.9"/>
    <prop k="capstyle" v="flat"/>
  </layer>
</symbol>

Local Roads (type = 'local')

<!-- QML Style for Local Roads -->
<symbol alpha="1" type="line" name="local_roads">
  <layer class="SimpleLine" enabled="1">
    <prop k="color" v="200,100,50,255"/>
    <prop k="width" v="0.6"/>
    <prop k="capstyle" v="flat"/>
  </layer>
</symbol>

Footpaths (type = 'footpath')

<!-- QML Style for Footpaths -->
<symbol alpha="1" type="line" name="footpaths">
  <layer class="SimpleLine" enabled="1">
    <prop k="color" v="159,81,34,255"/>
    <prop k="width" v="0.43"/>
    <prop k="capstyle" v="flat"/>
    <prop k="customdash" v="2;1"/>
    <prop k="use_custom_dash" v="1"/>
  </layer>
</symbol>

Major Sea Routes (type = 'majorSea')

<!-- QML Style for Major Sea Routes -->
<symbol alpha="1" type="line" name="major_searoutes">
  <layer class="SimpleLine" enabled="1">
    <prop k="color" v="0,137,202,255"/>
    <prop k="width" v="0.6"/>
    <prop k="capstyle" v="round"/>
    <prop k="customdash" v="1;2"/>
    <prop k="use_custom_dash" v="1"/>
  </layer>
</symbol>

Legacy Route Groups

For backward compatibility, routes can also be styled by group property:

  • roads: All land-based routes (royal, market, local)
  • trails: Walking paths (footpath)
  • searoutes: All sea-based routes (majorSea)

Settlements

Burgs can be styled based on their boolean properties using QGIS rule-based styling. The available burg feature types are:

  • capital: State capitals (administrative centers)
  • port: Coastal settlements with harbors
  • citadel: Fortified settlements with citadels
  • walls: Settlements with defensive walls
  • plaza: Settlements with central plazas
  • temple: Settlements with religious temples
  • shanty: Settlements with shanty town districts

Capital Cities (capital = true)

<!-- QML Style for Capital Cities -->
<symbol alpha="1" type="marker" name="capitals">
  <layer class="SimpleMarker" enabled="1">
    <prop k="color" v="255,215,0,255"/>
    <prop k="outline_color" v="0,0,0,255"/>
    <prop k="outline_width" v="0.4"/>
    <prop k="size" v="5"/>
    <prop k="name" v="star"/>
  </layer>
</symbol>

Port Cities (port = true)

<!-- QML Style for Port Cities -->
<symbol alpha="1" type="marker" name="ports">
  <layer class="SimpleMarker" enabled="1">
    <prop k="color" v="0,137,202,255"/>
    <prop k="outline_color" v="0,0,0,255"/>
    <prop k="outline_width" v="0.3"/>
    <prop k="size" v="4"/>
    <prop k="name" v="diamond"/>
  </layer>
</symbol>

Fortified Cities (citadel = true OR walls = true)

<!-- QML Style for Fortified Cities -->
<symbol alpha="1" type="marker" name="fortified">
  <layer class="SimpleMarker" enabled="1">
    <prop k="color" v="139,69,19,255"/>
    <prop k="outline_color" v="0,0,0,255"/>
    <prop k="outline_width" v="0.3"/>
    <prop k="size" v="4"/>
    <prop k="name" v="square"/>
  </layer>
</symbol>

Religious Centers (temple = true)

<!-- QML Style for Religious Centers -->
<symbol alpha="1" type="marker" name="religious">
  <layer class="SimpleMarker" enabled="1">
    <prop k="color" v="128,0,128,255"/>
    <prop k="outline_color" v="0,0,0,255"/>
    <prop k="outline_width" v="0.3"/>
    <prop k="size" v="4"/>
    <prop k="name" v="cross"/>
  </layer>
</symbol>

Trading Centers (plaza = true)

<!-- QML Style for Trading Centers -->
<symbol alpha="1" type="marker" name="trading">
  <layer class="SimpleMarker" enabled="1">
    <prop k="color" v="255,165,0,255"/>
    <prop k="outline_color" v="0,0,0,255"/>
    <prop k="outline_width" v="0.3"/>
    <prop k="size" v="3.5"/>
    <prop k="name" v="pentagon"/>
  </layer>
</symbol>

Shanty Towns (shanty = true)

<!-- QML Style for Shanty Towns -->
<symbol alpha="0.8" type="marker" name="shanty">
  <layer class="SimpleMarker" enabled="1">
    <prop k="color" v="139,131,120,255"/>
    <prop k="outline_color" v="0,0,0,255"/>
    <prop k="outline_width" v="0.2"/>
    <prop k="size" v="2.5"/>
    <prop k="name" v="triangle"/>
  </layer>
</symbol>

Regular Settlements (default)

<!-- QML Style for Regular Settlements -->
<symbol alpha="0.7" type="marker" name="settlements">
  <layer class="SimpleMarker" enabled="1">
    <prop k="color" v="0,0,0,179"/>
    <prop k="outline_color" v="0,0,0,255"/>
    <prop k="outline_width" v="0.24"/>
    <prop k="size" v="3"/>
    <prop k="name" v="circle"/>
  </layer>
</symbol>

Settlement Labels

<!-- QML Style for Settlement Labels -->
<text-style fontFamily="Arial" fontSize="5" fontSizeUnit="Point">
  <text-color alpha="255" r="0" g="0" b="0"/>
  <text-buffer bufferDraw="1" bufferSize="1" bufferSizeUnits="Point">
    <buffer-color alpha="255" r="255" g="255" b="255"/>
  </text-buffer>
</text-style>

Implementation Steps

1. Create Layer Structure

Project Root/
├── Water Bodies/
│   ├── Rivers
│   ├── Lakes
│   └── Ocean
├── Landmass/
│   ├── Base Land
│   └── Ice
├── Relief & Terrain/
│   ├── Elevation DEM (raster)
│   ├── Hillshade (raster)
│   ├── Relief Icons (points)
│   └── Elevation Polygons
├── Political/
│   ├── State Borders
│   └── Province Borders
├── Transportation/
│   ├── Routes (by type)
│   └── Routes (by group)
└── Settlements/
    ├── Burgs (by feature type)
    └── Settlement Labels

2. Apply Styles in QGIS

  1. Load your vector layers into QGIS
  2. Right-click layer → Properties → Symbology
  3. Copy the XML from above into a text editor
  4. Save as .qml file (e.g., rivers.qml)
  5. Load style in layer properties → Style → Load Style

3. Color Reference Table

Original Color RGB Values QGIS Color Code
#000000 0,0,0 0,0,0,255
#0089ca 0,137,202 0,137,202,255
#cae3f7 202,227,247 202,227,247,255
#eef6fb 238,246,251 238,246,251,255
#ff2c2c 255,44,44 255,44,44,255
#9f5122 159,81,34 159,81,34,255
#b4d2f3 180,210,243 180,210,243,255

4. Layer Ordering (Bottom to Top)

  1. Ocean Base
  2. Landmass
  3. Elevation DEM (raster)
  4. Hillshade (30% opacity)
  5. Elevation Polygons (graduated colors)
  6. Freshwater Bodies
  7. Ice
  8. Province Borders
  9. State Borders
  10. Transportation Routes (by type or group)
  11. Relief Icons (mountains/hills)
  12. Settlement Icons (by feature type)
  13. Settlement Labels

Notes

  • Opacity values from the JSON (like 0.8, 0.9) translate to QGIS alpha values
  • Stroke-dasharray properties become custom dash patterns in QGIS
  • Filter effects like blur and drop shadows need to be recreated using QGIS effects
  • Font families may need substitution if not available in your system
  • Coordinate system should be set to the Fantasy Map Cartesian CRS (WKT format below)

Coordinate Reference System (CRS)

The Fantasy Map Generator uses a custom Cartesian coordinate system. Use this WKT definition in QGIS:

ENGCRS["Fantasy Map Cartesian (meters)",
    EDATUM["Fantasy Map Datum"],
    CS[Cartesian,2],
        AXIS["easting (X)",east,
            ORDER[1],
            LENGTHUNIT["metre",1]],
        AXIS["northing (Y)",north,
            ORDER[2],
            LENGTHUNIT["metre",1]]]

Setting up the CRS in QGIS:

  1. Go to SettingsCustom Projections
  2. Click + to add a new CRS
  3. Set Name: Fantasy Map Cartesian
  4. Set Format: WKT (Recommended)
  5. Paste the WKT definition above
  6. Click OK and Apply

Data Requirements for Relief

Essential GeoJSON Exports

To implement relief rendering, you need these exports from Fantasy Map Generator:

  1. Cells GeoJSON (cells.geojson)

    • Contains elevation data in height property
    • Provides cell polygons for DEM generation
    • Includes biome information for terrain variation
  2. Burgs GeoJSON (burgs.geojson)

    • Settlement locations for reference
    • Population data for symbol sizing

Processing Workflow

  1. Import cells.geojson into QGIS
  2. Create DEM raster: Vector → Conversion Tools → Rasterize
    • Field: height
    • Resolution: 50-200m (depending on map detail)
    • Output extent: Use layer extent
  3. Generate hillshade: Raster → Analysis → Hillshade
  4. Create relief points: Vector → Geometry Tools → Centroids
  5. Apply symbology using the styles below

Rule-Based Styling

Route Styling by Type

To style routes by their type property:

  1. Right-click route layer → Properties → Symbology
  2. Change from "Single Symbol" to "Rule-based"
  3. Add rules with expressions like: "type" = 'royal'
  4. Apply the corresponding symbol for each type

Burg Styling by Features

To style burgs by their feature properties:

  1. Right-click burg layer → Properties → Symbology
  2. Change to "Rule-based" styling
  3. Create rules with expressions like:
    • "capital" = 1 for capitals
    • "port" = 1 for ports
    • "citadel" = 1 OR "walls" = 1 for fortified cities
  4. Set priority order (capitals first, then ports, etc.)

Graduated Symbols by Population

To size burg symbols by population:

  1. Right-click burg layer → Properties → Symbology
  2. Change to "Graduated"
  3. Set Value: population
  4. Choose appropriate Method and Classes
  5. Adjust symbol sizes in the range

Advanced Features

For complex effects like the texture overlay (#texture) and fogging (#fogging), consider:

  • Using Raster layers with blend modes
  • Layer effects in symbology
  • Custom SVG symbols for complex markers
  • Expression-based styling for dynamic effects