Danielkaas94 / ProjectZomboid_WestJutland

My repository for any kinds of PZ modding
Creative Commons Zero v1.0 Universal
1 stars 0 forks source link

πŸŒπŸ—Ί Proper Scaling from Real Life ➑ Project Zomboid World Editor πŸ—ΊπŸŒ #1

Open Danielkaas94 opened 1 year ago

Danielkaas94 commented 1 year ago

MapResolution = 156543.04 meters/pixel * cos(latitude) / (2 ^ zoomlevel)

MapScale = 1 : (ScreenRes pixels/inch * 39.37 inches/meter * 156543.04 meters/pixel * cos(latitude) / (2 ^ zoomlevel))

Hand drawing the whole municipality would take ages, what if a program could take a snapshot and generate a rough .png for the Project Zomboid World Editor

1 pixel = 1 meter Chunk Size = 300 pixels

Understanding Scale and Resolution πŸ€”

Directly accessing the Bing Maps tiles πŸ—Ί

Danielkaas94 commented 1 year ago

Colour Code for the Map Editor πŸ–πŸŽ¨

Grass & Nature πŸ’šπŸ’™πŸŒ±πŸŒŠ

Dark Grass #5A6423 Medium Grass #75752F Light Grass #91873C

Sand #D2C8A0

Tall Grass #00FF00

Dirt #784614 Water #008AFF

Trees #FF0000 Trees + Dark Grass #7F0000 Trees + More Dark Grass #400000

Lots of grass & tress #008000 Bushes, Trees and dark grass #FF00FF

Roads πŸš—πŸ’¨

Dark Asphalt #646464 Medium Asphalt #787878 Light Asphalt #A5A08C

Dark Pothole #6E6464 Light Pothole #827878

Danielkaas94 commented 1 year ago

Generating a simple PNG based on map terrain and vegetation data in C# involves a multi-step process. Here's a general outline of the steps you can follow to accomplish this task:

  1. Obtain Terrain and Vegetation Data: You'll need to obtain the map terrain and vegetation data from reliable sources. This data could be in the form of heightmaps or raster images representing terrain elevation and vegetation coverage, respectively.

  2. Set Up C# Project and Required Libraries: Create a new C# project or use an existing one. You'll need to use libraries that support image processing and manipulation. One popular library for working with images in C# is "System.Drawing."

  3. Load and Process Data: Load the terrain and vegetation data into your C# application. Depending on the format of the data, you may need to use appropriate libraries to read and interpret the data. For instance, you might use a library like "GDAL" to handle geospatial raster data.

  4. Generate the Image: Create a blank PNG image or a canvas using the "System.Drawing" library. Then, based on the terrain and vegetation data, apply colors or textures to represent different terrain types and vegetation coverage. You can use various drawing functions like rectangles, polygons, or pixel-by-pixel manipulation to achieve this.

  5. Save the Image: Once the image is generated, save it as a PNG file using the "System.Drawing" library.

Here's a simplified example of how you might generate a basic PNG image with random terrain and vegetation:

using System;
using System.Drawing;

class MapGenerator
{
    static void Main()
    {
        int width = 800;
        int height = 600;

        Bitmap mapImage = new Bitmap(width, height);
        Random random = new Random();

        // Generate terrain and vegetation data (for demonstration, let's use random values)
        int[,] terrainData = new int[width, height];
        int[,] vegetationData = new int[width, height];

        for (int x = 0; x < width; x++)
        {
            for (int y = 0; y < height; y++)
            {
                terrainData[x, y] = random.Next(0, 256); // Terrain elevation (0 to 255)
                vegetationData[x, y] = random.Next(0, 256); // Vegetation coverage (0 to 255)

                Color color = Color.FromArgb(terrainData[x, y], vegetationData[x, y], 0);
                mapImage.SetPixel(x, y, color);
            }
        }

        // Save the image as a PNG file
        mapImage.Save("map.png", System.Drawing.Imaging.ImageFormat.Png);

        // Dispose the image object after use
        mapImage.Dispose();
    }
}

This example generates a simple PNG image with random terrain elevation and vegetation coverage. In a real-world scenario, you would replace the random data with your actual terrain and vegetation data obtained from reliable sources. Also, for larger and more complex maps, more advanced algorithms and techniques may be required.

Danielkaas94 commented 1 year ago

If 1 pixel represents 1 square meter in your map, you'll need to adjust the image size and data accordingly to ensure the correct scale. Here's an updated version of the previous example with the appropriate changes:

using System;
using System.Drawing;

class MapGenerator
{
    static void Main()
    {
        int widthInMeters = 800;
        int heightInMeters = 600;

        int imageWidth = widthInMeters;   // Each pixel represents 1 square meter
        int imageHeight = heightInMeters; // Each pixel represents 1 square meter

        Bitmap mapImage = new Bitmap(imageWidth, imageHeight);
        Random random = new Random();

        // Generate terrain and vegetation data (for demonstration, let's use random values)
        int[,] terrainData = new int[imageWidth, imageHeight];
        int[,] vegetationData = new int[imageWidth, imageHeight];

        for (int x = 0; x < imageWidth; x++)
        {
            for (int y = 0; y < imageHeight; y++)
            {
                terrainData[x, y] = random.Next(0, 256); // Terrain elevation (0 to 255)
                vegetationData[x, y] = random.Next(0, 256); // Vegetation coverage (0 to 255)

                Color color = Color.FromArgb(terrainData[x, y], vegetationData[x, y], 0);
                mapImage.SetPixel(x, y, color);
            }
        }

        // Save the image as a PNG file
        mapImage.Save("map.png", System.Drawing.Imaging.ImageFormat.Png);

        // Dispose the image object after use
        mapImage.Dispose();
    }
}

In this updated example, the widthInMeters and heightInMeters variables represent the dimensions of your map in meters. The imageWidth and imageHeight variables are set to the same values as the map's dimensions, ensuring that each pixel in the image represents 1 square meter.

Remember to replace the random data generation with your actual terrain and vegetation data to create a meaningful map. Also, consider using more sophisticated algorithms and real-world data sources for a more accurate representation of terrain and vegetation patterns.

Danielkaas94 commented 1 year ago

GDAL (Geospatial Data Abstraction Library) is a powerful open-source library for reading and writing geospatial raster and vector data. In C#, you can use the GDAL C# bindings to work with geospatial data formats like GeoTIFF, DEM, Shapefiles, and more. To use GDAL in your C# project, you'll need to add a reference to the GDAL C# bindings and include the necessary GDAL native libraries.

Here's a simple example of how to use GDAL in C# to read raster data from a GeoTIFF file and access its metadata:

  1. Set up your project:

    • Download the GDAL C# bindings (e.g., gdal_csharp.dll) appropriate for your platform (x86 or x64).
    • Add a reference to the GDAL C# bindings in your C# project.
    • Make sure the GDAL native libraries (e.g., gdal_wrap.dll, gdal.dll) are accessible to your application. You can place them in the project's output directory or set the appropriate environment variables.
  2. Install GDAL in your system:

  3. Use the GDAL C# bindings in your code:

    
    using System;
    using OSGeo.GDAL;

class Program { static void Main() { // Initialize GDAL Gdal.AllRegister();

    // Replace the file path with the path to your GeoTIFF file
    string filePath = "path_to_your_geotiff.tif";

    // Open the dataset (GeoTIFF file)
    Dataset dataset = Gdal.Open(filePath, Access.GA_ReadOnly);

    if (dataset != null)
    {
        // Get the number of raster bands in the dataset
        int numBands = dataset.RasterCount;

        Console.WriteLine($"Number of raster bands: {numBands}");

        // Get the geotransform parameters (georeferencing information)
        double[] geotransform = new double[6];
        dataset.GetGeoTransform(geotransform);

        double originX = geotransform[0];
        double originY = geotransform[3];
        double pixelWidth = geotransform[1];
        double pixelHeight = geotransform[5];

        Console.WriteLine($"Origin (X, Y): ({originX}, {originY})");
        Console.WriteLine($"Pixel Size (Width, Height): ({pixelWidth}, {pixelHeight})");

        // Access raster data (for demonstration, we'll read the first band)
        Band band = dataset.GetRasterBand(1);

        int width = band.XSize;
        int height = band.YSize;
        int[] rasterData = new int[width * height];

        band.ReadRaster(0, 0, width, height, rasterData, width, height, 0, 0);

        // You can now work with the raster data in the 'rasterData' array
        // For example, you can manipulate the pixel values or perform analysis on the data

        // Close the dataset when done
        dataset.Dispose();
    }
    else
    {
        Console.WriteLine("Failed to open the dataset.");
    }
}

}



Make sure to replace `"path_to_your_geotiff.tif"` with the actual path to your GeoTIFF file. This example demonstrates how to open a GeoTIFF file, access its metadata (number of bands, geotransform), and read raster data from the first band into an array.

Remember that GDAL supports a wide range of geospatial formats and functionalities. Depending on your requirements, you can perform various operations such as writing data, working with vector data, and applying raster operations. Check the GDAL documentation for more details and advanced usage.
Danielkaas94 commented 1 year ago

To color the PNG based on road data, you'll need to obtain road data in a suitable format, overlay it on the existing map, and then apply appropriate colors to the road segments. Here's a general outline of the steps to achieve this:

  1. Obtain Road Data: Obtain the road data for your map area. Road data is usually available in vector formats like Shapefiles or GeoJSON, which contain information about the road geometry and attributes.

  2. Read the Existing PNG Map: Read the existing PNG map (generated from terrain and vegetation data) using the System.Drawing library or any other suitable library.

  3. Overlay Road Data on the Map: Use GDAL or another library capable of reading vector data to read the road data (Shapefile or GeoJSON). Overlay the road data on top of the existing map by converting the vector data to pixel coordinates.

  4. Color the Roads: Iterate through the road segments and apply the desired colors to them on the PNG map. You can use different colors to represent different types of roads (e.g., highways, streets) or use a single color for all roads.

  5. Save the Modified PNG: Save the modified PNG map, now with colored roads, as the final output.

Here's a simplified example of how you can perform these steps using C# with GDAL and the System.Drawing library:

using System;
using System.Drawing;
using OSGeo.OGR;
using OSGeo.GDAL;

class MapGenerator
{
    static void Main()
    {
        // Initialize GDAL and OGR
        Gdal.AllRegister();
        Ogr.RegisterAll();

        // Paths to your input files
        string terrainVegetationMapPath = "path_to_terrain_vegetation_map.png";
        string roadDataPath = "path_to_road_data.shp";

        // Read the existing PNG map (terrain and vegetation data)
        Bitmap mapImage = new Bitmap(terrainVegetationMapPath);

        // Open the road data
        DataSource roadDataSource = Ogr.Open(roadDataPath, 0);
        Layer roadLayer = roadDataSource.GetLayerByIndex(0);

        // Color the roads on the map
        Color roadColor = Color.Red; // You can choose any color you prefer

        Feature roadFeature;
        while ((roadFeature = roadLayer.GetNextFeature()) != null)
        {
            // Get road geometry (for demonstration, assuming a simple LineString geometry)
            Geometry roadGeometry = roadFeature.GetGeometryRef();
            int numPoints = roadGeometry.GetPointCount();

            // Convert road geometry to pixel coordinates
            for (int i = 0; i < numPoints - 1; i++)
            {
                double x1 = roadGeometry.GetX(i);
                double y1 = roadGeometry.GetY(i);
                double x2 = roadGeometry.GetX(i + 1);
                double y2 = roadGeometry.GetY(i + 1);

                // Assuming each pixel represents 1 square meter
                int pixelX1 = (int)Math.Round(x1);
                int pixelY1 = mapImage.Height - (int)Math.Round(y1); // Flip Y-axis for image coordinates
                int pixelX2 = (int)Math.Round(x2);
                int pixelY2 = mapImage.Height - (int)Math.Round(y2);

                // Draw the road segment on the map using the chosen color
                using (Graphics graphics = Graphics.FromImage(mapImage))
                {
                    graphics.DrawLine(new Pen(roadColor, 2), pixelX1, pixelY1, pixelX2, pixelY2);
                }
            }

            roadFeature.Dispose();
        }

        // Save the modified image with colored roads
        mapImage.Save("map_with_roads.png", System.Drawing.Imaging.ImageFormat.Png);

        // Dispose the image and data sources after use
        mapImage.Dispose();
        roadDataSource.Dispose();
    }
}

Please note that this is a simplified example, and in real-world scenarios, road data might contain more complex geometries or attributes that require additional processing. You might need to handle different types of road geometries, add legends, and customize colors based on road classifications. Additionally, this example assumes that the road data is in the form of simple LineString geometries; in practice, road data can be more diverse, such as multi-line geometries or polygon representations for road areas. Make sure to adapt the code accordingly to handle your specific road data format and requirements.