Giardini Rurali

Land Art in Barbarano Vicentino

Das Projekt „Giardini Rurali“ in Barbarano Vicentino stellt eine harmonische Verbindung zwischen Natur, Landwirtschaft und architektonischen Interventionen her. Ziel war es, ein weitläufiges Wein- und Olivenanbauareal sowohl ästhetisch als auch funktional aufzuwerten. Zentrale Elemente des Projekts sind die 21 Folies, die in drei Hauptkategorien unterteilt sind: Treppen, Terrassen und Sitzmöglichkeiten. Jeder Kategorie wurde eine Farbe zugewiesen. Außerdem greift jedes dieser Folies greift Formen auf, die in der umgebenden Natur – von den Olivenhainen bis hin zu den Weinreben – vorherrschen, und fügt sich auf natürliche Weise in das Gelände ein.

Die Folies sind nicht nur visuelle Akzente, sondern erfüllen auch vielseitige Funktionen: Sie ermöglichen das Sitzen, überwinden topografische Barrieren und eröffnen atemberaubende Ausblicke auf die umliegende Landschaft. Als zusammenhängende Elemente bilden sie ein Wegenetz, das das gesamte Areal erlebbar macht. Die Verwendung von pulverbeschichtetem Eisen als Material sorgt für eine lange Haltbarkeit und minimale Wartung, während die Handarbeit lokaler Betriebe die Verbindung zur Region stärkt und die kulturelle Identität des Projekts unterstreicht.

Die Integration von parametrischem Design in der Entwurfsphase, insbesondere bei Folie Nr. 10, ermöglichte es, kreative und funktionale Lösungen zu entwickeln, die flexibel an die spezifischen Gegebenheiten vor Ort angepasst werden konnten. Durch diese Technologie konnten verschiedene Designvariationen effizient erstellt und optimiert werden, was den gestalterischen Prozess erheblich erleichterte.

Folie Nr. 10: Camera nel Bosco – Zimmer im Wald

Ein herausragendes Beispiel für die Anwendung des parametrischen Designs ist Folie Nr. 10 – „Camera nel Bosco“. Diese Folie bildet einen kreisförmigen Raum, der von einer Reihe von Metallrohren begrenzt wird, die dynamisch in ihrer Höhe, ihrem Abstand und ihrem Durchmesser variieren. Diese Variation wurde mithilfe von parametrischem Design in Grasshopper und Rhino realisiert. Durch die Anpassung der Parameter konnte die Form des Raumes gezielt modifiziert werden, sodass die Rohre eine Wellenstruktur entlang des Umfangs bilden, deren Enden über den Rand des Kreises hinauswachsen und dem Raum eine organische, fließende Form verleihen.

Das Design

Im Inneren des Raumes ist auf etwa zwei Dritteln des inneren Umfangs eine Sitzbank aus Holz angebracht. Diese Sitzfläche besteht aus Holzlatten mit einer Breite von 5 cm, die zusammengefügt wurden, um eine stabile und dennoch ästhetische Oberfläche zu bilden. Das Holz, Iroko, wurde aufgrund seiner Beständigkeit und der natürlichen Patina, die es im Laufe der Zeit entwickelt, ausgewählt. Die minimale Oberflächenbehandlung fördert die Entstehung einer natürlichen Patina, die im Einklang mit der Umgebung und der Jahreszeit steht.Die parametrische Gestaltung ermöglichte es, nicht nur die funktionalen Anforderungen des Entwurfs zu erfüllen, sondern auch eine visuell ansprechende und organische Formensprache zu entwickeln. Diese Flexibilität in der Planung brachte eine effiziente und präzise Umsetzung des Designs, das sich sowohl in ästhetischer als auch in funktionaler Hinsicht perfekt in die umgebende Natur einfügt.

Die parametrische Gestaltung spielte eine zentral Rolle im Entwicklungsprozess. Grasshopper wurde verwendet, um folgende Variablen dynamisch anzupassen:

  • Höhenvariationen der Metallrohre, um eine abschließende Wellenform zu erzeugen.
  • Abstände zwischen den Rohren, die zufällig in Intervallen von 15, 20 und 25 cm verteilt wurden.
  • Drei verschiedene Rohrdurchmesser von 6, 8 und 10 cm, die prozentual gesteuert wurden.

Diese parametrische Steuerung ermöglichte eine schnelle Anpassung und Optimierung des Entwurfs, sodass verschiedene Varianten getestet werden konnten, ohne den gesamten Modellierungsprozess neu zu starten.

Die Umsetzung

Ex Sirmiocar

Das Projekt „Ex Sirmiocar“ bietet eine spannende Möglichkeit, den östlichen Ortseingang von Sirmione neu zu gestalten und dabei sowohl touristische als auch urbane Anforderungen zu erfüllen. Das Projektgebiet ist die Grundstücksfläche eines ehemaligen Fahrzeughändlers. Die gründliche Analyse der bestehenden Strukturen, Topografie, Infrastruktur und Naturmerkmale bildet die Grundlage für eine Planung, die respektvoll mit der Umgebung umgeht und gleichzeitig zukunftsorientiert ist.

Projektziel

Sensible Integration eines Neubaus mit gemischter touristischer, gewerblicher und sozialer Nutzung in die bestehenden Strukturen und Landschaftsmerkmale der Umgebung. Der Fokus liegt auf der harmonischen Verbindung zwischen den neuen Architekturideen und den landschaftlichen, kulturellen sowie infrastrukturellen Gegebenheiten.

Fotografische Ortserfassung


Landschaftliche und geografische Analyse

Die Abbildung in Form eines „Landschaftsecholotes“ veranschaulicht den touristischen Charakter der Küstenregion des Gardasees unter besonderer Berücksichtigung von Sirmione, einem der wichtigsten Reiseziele. Das Gebiet zeichnet sich durch zahlreiche touristische Einrichtungen aus, darunter Campingplätze entlang der Küste sowie kulturelle und historische Stätten wie Museen und archäologische Ausgrabungen. Die Halbinsel Sirmione und ihr Stadtzentrum sind sowohl touristisch als auch historisch bedeutsam. Nördlich von Peschiera del Garda, entlang der Ostküste, befinden sich Freizeitparks, während im Westen das Projektgebiet in der Nähe von Desenzano del Garda liegt, was das touristische Angebot bereichert. Die Abbildung zeigt auch die infrastrukturelle Anbindung über die Autobahn A4 und die Mautstellen Peschiera und Sirmione sowie den nationalen Radweg AIDA, der die Mobilitätsinfrastruktur vervollständigt.

Die Abbildung zeigt die Topographie des Projektgebietes und des angrenzenden Gebietes von Sirmione. Die Küstenregion des Gardasees ist sowohl entlang des Seeufers als auch im angrenzenden Hinterland auf den ersten Kilometern durch ein nahezu ebenes Gelände gekennzeichnet. Die Höhe des Gardaseeufers beträgt ca. 70 m über dem Meeresspiegel, was den flachen Charakter der Landschaft unterstreicht. 5 km südlich des Projektgebietes ändert sich die Topographie und das Gelände steigt leicht an und wird hügelig. In diesem Bereich erreichen die Höhen 140 m über dem Meeresspiegel und markieren die Grenze zu den sanften Hügeln, die die Landschaft im südlichen Teil des Gebiets prägen. Die Abbildung zeigt einen 7 km langen Geländeausschnitt, der diesen Übergang vom Flach- zum Hügelland veranschaulicht und so einen visuellen Eindruck von der Landschaftsentwicklung in der Region vermittelt.

Paesaggio Liquido

Gardasee

Peasaggio di Transizione

Touristischer Küstenbereich

Paesaggio di Pianura

Landwirtschaftszone

Paesaggio Collinare

Hügelige Zone

Der Küstenstreifen des Gardasees ist die Nahtstelle zwischen Wasser und Land. Das Gebiet zeichnet sich durch eine flache Topographie und eine stark touristisch geprägte Landnutzung mit Stränden, Häfen und Freizeiteinrichtungen aus. Das Wasser prägt die Landschaft und schafft ein dynamisches und lebendiges Gebiet.

Dieses Gebiet erstreckt sich von der Küste bis ins Landesinnere und zeichnet sich durch eine noch überwiegend flache Topographie aus. Die Landnutzung wird von touristischen Aktivitäten wie Hotels, Campingplätzen und Erholungsgebieten dominiert, die in städtische und Wohngebiete integriert sind. Die Übergangszone fungiert als Bindeglied zwischen dem Küstenstreifen und den landwirtschaftlich genutzten Flächen im Landesinneren.

Hier geht die Landschaft in ein leicht hügeliges, landwirtschaftlich geprägtes Gebiet über. Hier herrschen Weinberge vor, deren traditionelle Anordnung das Landschaftsbild prägt. Kleine Dörfer, Bauernhöfe und Landstraßen prägen den Charakter dieses Gebietes, das sich eine starke Identität bewahrt hat, die mit der landwirtschaftlichen Produktion, insbesondere dem Weinbau, verbunden ist.

Die Hügel, die bei bis zu 140 m üNN liegen, bilden den letzten Übergang in der Landschaft. Hier ist die Topographie stärker ausgeprägt und Weinberge, Wälder und Naturflächen wechseln sich ab. Die Weinhügel bieten nicht nur eine hochwertige landwirtschaftliche Produktion, sondern auch beeindruckende Ausblicke auf den See und die darunter liegende Ebene.

Tourismus, Mobilität und Infrastruktur

Verteilung von Hotels und touristischen Unterkünften

Verteilung von Freizeit- und Sportangeboten

Die Fußgänger-Isochronen stellen die Gehzeiten vom zentralen Projektgebiet dar. Im Umkreis von 5 Minuten befinden sich die Bushaltestellen der Linie LN026 (grüne Markierungen), die eine gute Anbindung an die umliegenden Ziele bieten und auch weiter entfernte Orte erreichbar machen. In einem Umkreis von 10-15 Minuten sind lokale Sehenswürdigkeiten und kleine Geschäfte zu erreichen. Nach einem 30-minütigen Spaziergang kann ein großer Teil der Umgebung erkundet werden und in ca. 60 Minuten erreicht man die Spitze der Halbinsel Sirmione. Dies unterstreicht die gute fußläufige Erreichbarkeit der Region, die sie sowohl für Einheimische als auch für Touristen besonders attraktiv macht.

Die Fahrrad-Isochronen zeigen die Entfernungen, die vom zentralen Projektgebiet aus mit dem Fahrrad zurückgelegt werden können. Die Spitze der Halbinsel von Sirmione ist aufgrund der flachen Topographie leicht mit dem Fahrrad zu erreichen. Innerhalb von 15 Minuten können große Teile der Halbinsel erkundet werden. Darüber hinaus sind die Nachbarorte Peschiera del Garda und Desenzano del Garda in nur 30 Minuten bequem zu erreichen. Diese Isochronen verdeutlichen die hohe Mobilität und Flexibilität, die das Fahrrad in der Region bietet und unterstreichen das Potenzial für nachhaltige Mobilität in diesem Gebiet.

Die Auto-Isochronen zeigen die Entfernungen, die vom Projektgebiet aus zurückgelegt werden können. Innerhalb von 10 Minuten erreicht man die Spitze von Sirmione, die Nachbarstädte Peschiera del Garda und Desenzano del Garda sowie die Hauptverkehrsachsen wie die A4 nach Verona und Mailand. Diese Isochronen verdeutlichen die infrastrukturelle Entwicklung der Region. Sie zeigen aber auch, dass die Unterschiede zwischen Fahrrad- und Autoverkehr nicht überwältigend sind.

Essay „Playgrounds – A Living Landscape“

What makes a playground? Is it defined by its boundaries, its equipment, or the laughter of children that fills its air? The concept of a playground is far more complex than the slides and swings that often come to mind. Playgrounds are cultural artifacts – spaces that mirror the societies that create them, embodying their values, anxieties, and hopes for the future. They are living landscapes, dynamic and ever-changing, shaped by the needs of the communities which use them. Yet this simple idea of a playground – a place for play – has profound implications for our view of children, society and even ourselves.


The history of the playground is a story of human connection, creativity and adaptability to ever- changing environments. From pristine sandbanks, forest glades and village squares of yesteryear, playgrounds have evolved into inclusive, multi-functional environments and play worlds that meet the diverse needs of children and adults alike. In the industrial age, it became an instrument of control, a fenced-in space where children could safely exercise their bodies while developing their morals under watchful eyes. But today, playgrounds are experiencing a renaissance – a return to their roots as open spaces for exploration and imagination,
no longer confined by rigid structures or narrow definitions.

If we look closely, we can see that playgrounds don’t have to be just for children. They can be, and perhaps are already becoming, vibrant social ecosystems, spaces where people of all ages and backgrounds come together. We can create spaces not just for running, climbing or swinging – but also for sitting, talking, dancing and socializing. It thrives on movement and creativity, offering unexpected moments of joy and shared experience.
It is as much about what happens outside the design as inside it.

Perhaps this evolution challenges us to rethink the very definition of a playground. Could a playground be anywhere that movement, spontaneity, and connection exist? Could it be a busy square, a quiet park, or even a parade winding through the streets? The playground might not need slides or swings to fulfill its purpose. It might not even need children. But it most certainly needs people. It might simply be a living, breathing landscape shaped by the people who dwell in it –
a canvas for community, a stage for creativity, and a space for the unexpected.

As playgrounds continue to evolve, maybe it’s time to ask a deeper question: Are they truly spaces for children, or are they a reflection of the societies we want to build? Perhaps the playground of the future is not a place but a concept – a dynamic ecosystem where movement, diversity, and imagination come together to create a new part of landscape. Could it be that the playground’s greatest potential lies not in its boundaries, but in its openness to possibility? This openness reminds us that play is not just an activity – it is a way of being and living, and the playground is its ultimate expression.

Python-Projekt zur automatischen Baumrastererstellung

Dieser Python-Code ist ein Werkzeug zur automatisierten Generierung von Baumdarstellungen innerhalb von definierten Flächen, die aus verschiedenen Vektordatenformaten (DXF, SVG, Shapefile) importiert werden können. Die generierten Baumpositionen können dann in verschiedene Ausgabeformate (DXF, SVG, Shapefile) exportiert werden.

Was dieser Code macht:

  1. Importieren von Vektordaten:
    • Er kann Geometrien aus DXF-, SVG- und Shapefile-Dateien einlesen.
    • Für DXF-Dateien werden LWPOLYLINE, POLYLINE und LINE-Entitäten verarbeitet.
    • Für SVG-Dateien werden Pfade extrahiert.
    • Für Shapefiles werden Polygone und Linien extrahiert.
  2. Benutzereingabe:
    • Über ein tkinter-basiertes GUI werden Parameter wie die Auflösung der Baumkronen (als Polygone), die Anzahl unterschiedlicher Baumdurchmesser, deren Durchmesser, prozentualer Anteil und Farbe abgefragt.
    • Es gibt eine Option, Bäume in Clustern anzuordnen, und der Benutzer kann den Prozentsatz der Bäume festlegen, die geclustert werden sollen.
    • Der Benutzer kann die gewünschten Ausgabeformate (Shapefile, SVG, DXF) auswählen.
    • Der Benutzer kann wählen, ob nur zufällige, nur Cluster-basierte oder beide Varianten der Baumverteilung generiert werden sollen.
  3. Baumplatzierung:
    • Die Funktion generate_tree_positions platziert Bäume innerhalb der importierten Geometrien.
    • Sie berücksichtigt die angegebenen Durchmesser und deren prozentualen Anteil an der Gesamtbaumbepflanzung.
    • Es wird überprüft, ob neu platzierte Bäume mit bestehenden Bäumen überlappen, um realistische Abstände zu gewährleisten.
    • Für die Platzierung wird die shape_path.contains_point-Methode verwendet, um sicherzustellen, dass Bäume innerhalb der definierten Form platziert werden.
    • Es gibt eine Logik zur Erstellung eines Rasterpunktrasters für den Fall, dass nur ein Baumdurchmesser verwendet wird, was eine gleichmäßigere Verteilung ermöglicht.
  4. Interaktive Vorschau:
    • Es wird ein separates tkinter-Fenster mit einer matplotlib-Visualisierung der importierten Geometrie und der generierten Bäume angezeigt.
    • Ein Slider ermöglicht die interaktive Anpassung der „Füllungsintensität“, was die Dichte der platzierten Bäume beeinflusst.
    • Dies erlaubt dem Benutzer, die Baumplatzierung vor dem endgültigen Export zu überprüfen und anzupassen.
  5. Export in verschiedene Formate:
    • Die generierten Baumpositionen werden zusammen mit den importierten Geometrien in die ausgewählten Ausgabeformate exportiert.
    • DXF: Bäume werden als Kreise auf separaten Layern nach ihrem Durchmesser gezeichnet. Die Farben werden als True-Color-Werte gespeichert.
    • SVG: Die Visualisierung (inklusive der Bäume) wird als SVG-Datei gespeichert.
    • Shapefile: Bäume werden als Polygone (approximierte Kreise) mit Attributen wie ID, Radius, Durchmesser und Farbe gespeichert. Der Benutzer wird nach dem Koordinatensystem (EPSG-Code) gefragt, falls es nicht aus der Eingabedatei übernommen werden kann.
  6. Batch-Verarbeitung:
    • Der Code ermöglicht die Auswahl mehrerer Eingabedateien für die Verarbeitung, wodurch eine Batch-Verarbeitung möglich ist.
  7. Skalierung für SVG:
    • Für SVG-Dateien fragt der Code nach einer maximalen Länge und skaliert die importierte Geometrie entsprechend. Dies ist nützlich, um SVG-Zeichnungen auf eine bestimmte Größe zu bringen.
  8. Eindeutige Dateinamen:
    • Die Funktion get_unique_filename stellt sicher, dass beim Export keine Dateien überschrieben werden, indem eindeutige Dateinamen generiert werden (z.B. durch Hinzufügen von Versionsnummern).

Was diesen Code besonders macht:

  • Integration verschiedener Formate: Die Fähigkeit, sowohl CAD-Formate (DXF, DWG) als auch GIS-Formate (Shapefile) und Grafikformate (SVG) zu lesen und zu schreiben, macht ihn sehr flexibel und vielseitig einsetzbar.
  • Interaktive Baumplatzierung: Die Vorschaufunktion mit dem Füllintensitäts-Slider ermöglicht eine intuitive Anpassung der Baumdichte und -verteilung. Dies ist ein großer Vorteil gegenüber rein algorithmischen Ansätzen.
  • Berücksichtigung von Baumdurchmessern und Proportionen: Die Möglichkeit, verschiedene Baumdurchmesser mit unterschiedlichen Anteilen und Farben zu definieren, ermöglicht realistischere und differenziertere Pflanzpläne.
  • Optionale Clusterbildung: Die Möglichkeit, Bäume in Clustern anzuordnen, kann die Natürlichkeit der Pflanzung erhöhen.
  • Benutzerfreundliche GUI: Die tkinter-Oberfläche erleichtert die Bedienung, auch für Benutzer ohne tiefe Programmierkenntnisse.
  • Umfassende Parametrisierung: Viele Aspekte der Baumplatzierung und des Exports sind konfigurierbar.
  • Behandlung von Koordinatensystemen: Die Berücksichtigung von Koordinatensystemen beim Export von Shapefiles ist wichtig für die Integration in GIS-Systeme.

Anwendungsbeispiele in einem landschaftsarchitektonischen Projekt:

  1. Erstellung von Pflanzplänen:
    • Der Code kann verwendet werden, um automatisch Baumstandorte innerhalb von Projektgrenzen zu generieren, die durch DXF-Pläne (z.B. Gebäudegrundrisse, Wegeführungen), SVG-Zeichnungen oder Shapefiles (z.B. Grundstücksgrenzen) definiert sind.
    • Landschaftsarchitekten können verschiedene Baumarten und -größen mit entsprechenden Proportionen festlegen und die Software die Platzierung übernehmen lassen.
    • Die interaktive Vorschau ermöglicht es, die Dichte und Verteilung der Bäume zu visualisieren und anzupassen, um ästhetische und funktionale Anforderungen zu erfüllen (z.B. Sichtachsen, Schattenspenden).
  2. Visualisierung von Baumpflanzungen:
    • Die SVG-Exportfunktion ermöglicht die Erstellung von Vektorgrafiken, die für Präsentationen und Pläne verwendet werden können. Die farbliche Unterscheidung der Baumkronen nach Durchmesser erhöht die Verständlichkeit.
  3. Erstellung von technischen Zeichnungen:
    • Der DXF-Export ermöglicht die Integration der Baumstandorte in CAD-Pläne für die Bauausführung. Die Layer-basierte Organisation nach Baumdurchmesser kann die Organisation und Bearbeitung im CAD erleichtern.
  4. Datenerfassung für GIS:
    • Der Shapefile-Export ermöglicht die Übergabe der Baumstandorte und ihrer Attribute (Durchmesser, Farbe) an GIS-Systeme für weitere Analysen (z.B. Berechnung der Baumkronenfläche, räumliche Beziehungen zu anderen Elementen).
  5. Entwurfsiterationen und Variantenstudien:
    • Durch die einfache Parametrisierung können schnell verschiedene Pflanzvarianten mit unterschiedlichen Baumgrößen, Dichten und Anordnungen generiert und verglichen werden. Die Möglichkeit, zufällige und Cluster-basierte Anordnungen zu generieren, bietet Flexibilität bei der Gestaltung.
  6. Bestandsaufnahme und Analyse:
    • Wenn vorhandene Baumstandorte in einem der unterstützten Formate vorliegen, könnte der Code angepasst werden, um diese zu visualisieren oder Analysen auf Basis der Baumdurchmesser durchzuführen.

Zusammenfassend lässt sich sagen, dass dieser Code ein wertvolles Werkzeug für Landschaftsarchitekten ist, um den Prozess der Baumplatzierung in Entwürfen zu automatisieren und zu visualisieren, die Effizienz zu steigern und kreative Möglichkeiten zu eröffnen. Die Kombination aus der Unterstützung verschiedener Dateiformate, der interaktiven Vorschau und der flexiblen Parametrisierung macht ihn zu einem mächtigen Instrument für die Planung und Dokumentation von Baumpflanzungen.

import os
import ezdxf
import numpy as np
import matplotlib
matplotlib.use('TkAgg')
import matplotlib.pyplot as plt
import random
import tkinter as tk
from tkinter import filedialog, messagebox, simpledialog, colorchooser
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
from matplotlib.figure import Figure
from matplotlib.path import Path
from shapely.geometry import shape, mapping, Polygon, Point, MultiPolygon, LineString, MultiLineString
import fiona
from pyproj import CRS

# Korrekte Importierung von rgb2int
from ezdxf.colors import rgb2int

# Funktion zur Überprüfung, ob sich zwei Kreise überschneiden
def check_overlap(x1, y1, r1, x2, y2, r2, min_distance=0):
    distance = np.sqrt((x2 - x1) ** 2 + (y2 - y1) ** 2)
    return distance < r1 + r2 + min_distance

# Funktion zur Berechnung der Fläche der Form mittels Shoelace-Formel
def compute_shape_area(polylines):
    total_area = 0.0
    for polyline in polylines:
        if len(polyline) < 3:
            continue  # Keine gültige Polygonfläche
        x, y = zip(*polyline)
        # Sicherstellen, dass das Polygon geschlossen ist
        if (x[0], y[0]) != (x[-1], y[-1]):
            x = list(x) + [x[0]]
            y = list(y) + [y[0]]
        total_area += 0.5 * np.abs(np.dot(x, np.roll(y, 1)) - np.dot(y, np.roll(x, 1)))
    return total_area

# Funktion zum Lesen der Eingabedatei basierend auf dem Dateiformat
def read_input_file(file_path):
    extension = file_path.split('.')[-1].lower()
    if extension == 'dxf':
        return process_dxf(file_path)
    elif extension == 'dwg':
        messagebox.showinfo("Hinweis", "Bitte konvertiere die DWG-Datei zuerst in eine DXF-Datei.")
        return []
    elif extension == 'svg':
        return process_svg(file_path)
    elif extension == 'shp':
        return process_shapefile(file_path)
    else:
        messagebox.showerror("Fehler", "Nicht unterstütztes Dateiformat.")
        return []

# Funktion zum Schreiben der Ausgabedatei basierend auf dem gewünschten Format
def write_output_file(file_path, polylines, tree_positions, crs, fig=None):
    extension = file_path.split('.')[-1].lower()
    if extension == 'dxf':
        write_dxf(file_path, polylines, tree_positions)
    elif extension == 'svg':
        if fig is not None:
            write_svg_matplotlib(fig, file_path)
    elif extension == 'shp':
        # Wenn crs None ist, den Benutzer nach dem EPSG-Code fragen
        if crs is None:
            crs_input = simpledialog.askstring(
                "Koordinatensystem für Export",
                "Bitte gib den EPSG-Code des Koordinatensystems für das Shapefile ein (z.B. 32632 für UTM Zone 32N):"
            )
            if crs_input is None:
                messagebox.showerror("Fehler", "Kein Koordinatensystem eingegeben.")
                return
            try:
                crs_epsg = int(crs_input)
                crs = CRS.from_epsg(crs_epsg)
            except ValueError:
                messagebox.showerror("Fehler", "Ungültiger EPSG-Code.")
                return
        write_shapefile(file_path[:-4], polylines, tree_positions, crs)
    else:
        messagebox.showerror("Fehler", "Nicht unterstütztes Exportformat.")

# Funktion zum Schreiben einer DXF-Datei einschließlich der Bäume
def write_dxf(file_path, polylines, tree_positions):
    doc = ezdxf.new(dxfversion='R2000')
    msp = doc.modelspace()

    # Setze Einheiten auf Meter
    doc.header['$INSUNITS'] = 6  # 6 entspricht Metern in DXF

    # Layer für Geometrie erstellen
    doc.layers.new(name='Geometrie', dxfattribs={'color': 7})

    # Hinzufügen der Polylinien auf Layer 'Geometrie'
    for polyline in polylines:
        if len(polyline) < 2:
            continue
        msp.add_lwpolyline(polyline, format='xy', dxfattribs={'layer': 'Geometrie'})

    # Gruppierung der Bäume nach Durchmesser und Erstellung von Layern
    diameter_layers = {}
    for tree in tree_positions:
        x, y, radius, color = tree
        diameter = radius * 2
        layer_name = f"Bäume_{diameter}m"

        if layer_name not in diameter_layers:
            # Erstelle einen neuen Layer für diesen Durchmesser
            doc.layers.new(name=layer_name)
            diameter_layers[layer_name] = color  # Speichere die Farbe für den Layer

        # Füge den Baum auf dem entsprechenden Layer hinzu
        circle = msp.add_circle(center=(x, y), radius=radius, dxfattribs={'layer': layer_name})

        # Setze die Farbe des Kreises entsprechend der RGB-Werte
        r, g, b = [int(c * 255) for c in color]
        circle.dxf.true_color = rgb2int((r, g, b))

    # Speichern der DXF-Datei
    doc.saveas(file_path)

# Funktion zum Schreiben einer SVG-Datei mit Matplotlib
def write_svg_matplotlib(fig, file_path):
    fig.savefig(file_path, format='svg', bbox_inches='tight')

# Funktion zum Schreiben eines Shapefiles
def write_shapefile(file_path, polylines, tree_positions, crs):
    """
    Schreibt die Bäume in ein Shapefile mit dem angegebenen Koordinatensystem.
    Die Bäume werden als Polygone (approximierte Kreise) gespeichert.
    :param file_path: Pfad zum Shapefile (ohne Erweiterung)
    :param polylines: Liste von Polylinien
    :param tree_positions: Liste der Baumpositionen (x, y, radius, color)
    :param crs: Koordinatensystem (CRS) für das Shapefile
    """
    if crs is None:
        messagebox.showerror("Fehler", "Kein Koordinatensystem für das Shapefile angegeben.")
        return

    # Schreiben der Bäume als Polygone (approximierte Kreise)
    schema_trees = {
        'geometry': 'Polygon',
        'properties': {
            'id': 'int',
            'radius': 'float',
            'diameter': 'float',
            'color': 'str',
        },
    }

    # Generiere einen eindeutigen Basisnamen für die Bäume
    tree_base_name = get_unique_filename(file_path + "_baeume", "shp")

    with fiona.open(tree_base_name, 'w', driver='ESRI Shapefile', crs=crs.to_wkt(), schema=schema_trees) as shp:
        for idx, tree in enumerate(tree_positions):
            x, y, radius, color = tree
            # Erzeuge einen Kreis (Polygon) um den Punkt
            point = Point(x, y)
            circle_polygon = point.buffer(radius, resolution=circle_resolution)
            shp.write({
                'geometry': mapping(circle_polygon),
                'properties': {
                    'id': idx,
                    'radius': radius,
                    'diameter': radius * 2,
                    'color': '#%02x%02x%02x' % (
                        int(color[0]*255), int(color[1]*255), int(color[2]*255)
                    ),
                },
            })

# Funktion zur Generierung eines eindeutigen Dateinamens
def get_unique_filename(base_name, extension):
    counter = 1
    unique_name = f"{base_name}.{extension}"
    while os.path.exists(unique_name):
        unique_name = f"{base_name}_version_{counter}.{extension}"
        counter += 1
    return unique_name

# Funktion zur Auswahl der Ausgabeformate
def select_output_formats():
    formats = []

    def confirm():
        if var_shp.get():
            formats.append('shp')
        if var_svg.get():
            formats.append('svg')
        if var_dxf.get():
            formats.append('dxf')
        format_window.destroy()

    format_window = tk.Toplevel()
    format_window.title("Ausgabeformate auswählen")

    # Fenstergröße automatisch anpassen
    format_window.update_idletasks()
    width = format_window.winfo_reqwidth()
    height = format_window.winfo_reqheight()
    format_window.geometry(f"{width}x{height}")

    var_shp = tk.IntVar()
    var_svg = tk.IntVar()
    var_dxf = tk.IntVar()

    tk.Label(format_window, text="Bitte die gewünschten Ausgabeformate auswählen:").pack(anchor='w')
    tk.Checkbutton(format_window, text="Shapefile (.shp)", variable=var_shp).pack(anchor='w')
    tk.Checkbutton(format_window, text="SVG Datei (.svg)", variable=var_svg).pack(anchor='w')
    tk.Checkbutton(format_window, text="DXF Datei (.dxf)", variable=var_dxf).pack(anchor='w')

    tk.Button(format_window, text="OK", command=confirm).pack()

    format_window.wait_window()

    return formats

# Funktion zur Umwandlung eines Hex-Farbcodes in ein RGB-Tupel
def hex_to_rgb(hex_string):
    hex_string = hex_string.lstrip('#')
    return tuple(int(hex_string[i:i+2], 16) / 255 for i in (0, 2, 4))

# Funktion zum Verarbeiten von DXF-Dateien
def process_dxf(file_path):
    try:
        doc = ezdxf.readfile(file_path)
    except IOError:
        print(f"Die Datei konnte nicht gelesen werden: {file_path}")
        return []
    except ezdxf.DXFStructureError:
        print(f"Die DXF-Datei ist ungültig oder beschädigt: {file_path}")
        return []

    msp = doc.modelspace()
    polylines = []

    for entity in msp:
        if entity.dxftype() == 'LWPOLYLINE':
            polyline_points = [tuple((point[0], point[1])) for point in entity]
            polylines.append(polyline_points)
        elif entity.dxftype() == 'POLYLINE':
            polyline_points = []
            for vertex in entity.vertices:
                x = vertex.dxf.location[0]
                y = vertex.dxf.location[1]
                polyline_points.append((x, y))
            polylines.append(polyline_points)
        elif entity.dxftype() == 'LINE':
            start_point = entity.dxf.start
            end_point = entity.dxf.end
            polyline_points = [start_point[:2], end_point[:2]]
            polylines.append(polyline_points)
        # Weitere Entitätstypen können hier hinzugefügt werden

    return polylines

# Funktion zum Verarbeiten von SVG-Dateien
def process_svg(file_path):
    from svgpathtools import svg2paths2
    try:
        paths, attributes, svg_attributes = svg2paths2(file_path)
    except Exception as e:
        print(f"Fehler beim Lesen der SVG-Datei: {e}")
        return []

    polylines = []
    for path in paths:
        polyline = []
        for segment in path:
            points = [segment.start, segment.end]
            for point in points:
                polyline.append((point.real, point.imag))
        if polyline:
            polylines.append(polyline)

    return polylines

# Funktion zum Verarbeiten von Shapefiles
def process_shapefile(file_path):
    """
    Verarbeitet das Shapefile und extrahiert Polygone oder Linien als Listen von Punkten.
    :param file_path: Pfad zum Shapefile
    :return: Liste von Polylinien (jeweils eine Liste von (x, y) Punkten)
    """
    polylines = []
    with fiona.open(file_path, 'r') as shp:
        for feature in shp:
            geom = shape(feature['geometry'])
            if geom.is_empty:
                continue
            if isinstance(geom, (Polygon, MultiPolygon)):
                # Extrahiere die äußeren Ringe
                if isinstance(geom, Polygon):
                    polygons = [geom]
                else:
                    polygons = list(geom.geoms)
                for polygon in polygons:
                    exterior_coords = list(polygon.exterior.coords)
                    polylines.append(exterior_coords)
            elif isinstance(geom, (LineString, MultiLineString)):
                if isinstance(geom, LineString):
                    lines = [geom]
                else:
                    lines = list(geom.geoms)
                for line in lines:
                    coords = list(line.coords)
                    polylines.append(coords)
            else:
                # Andere Geometrietypen können hier behandelt werden
                continue
    return polylines

# Funktion zur interaktiven Eingabe aller Parameter in einem einzigen Fenster
def get_user_inputs():
    user_inputs = {}

    input_window = tk.Toplevel()
    input_window.title("Eingabeparameter")

    # Fenstergröße automatisch anpassen
    input_window.update_idletasks()
    width = input_window.winfo_reqwidth()
    height = input_window.winfo_reqheight()
    input_window.geometry(f"{width}x{height}")

    # Funktion zum Schließen des Fensters
    def submit():
        try:
            user_inputs['circle_resolution'] = int(entry_circle_resolution.get())
            user_inputs['num_diameters'] = int(entry_num_diameters.get())
            if user_inputs['num_diameters'] <= 0:
                raise ValueError

            # Baumdurchmesser, Proportionen und Farben sammeln
            diameters = []
            proportions = []
            colors = []
            for i in range(user_inputs['num_diameters']):
                diameter = float(entries_diameters[i].get())
                proportion = float(entries_proportions[i].get())
                color_hex = entries_colors[i].get()
                color_tuple = hex_to_rgb(color_hex)
                if diameter <= 0 or not (0 <= proportion <= 100):
                    raise ValueError
                diameters.append(diameter)
                proportions.append(proportion)
                colors.append(color_tuple)
            user_inputs['diameters'] = diameters
            user_inputs['proportions'] = proportions
            user_inputs['colors'] = colors

            # Clusteroption
            user_inputs['use_clustering'] = var_use_clustering.get()
            if user_inputs['use_clustering']:
                user_inputs['cluster_percentage'] = float(entry_cluster_percentage.get())
                if not (0 <= user_inputs['cluster_percentage'] <= 100):
                    raise ValueError
            else:
                user_inputs['cluster_percentage'] = 0

            # Auswahl der Ausgabeformate
            user_inputs['output_formats'] = select_output_formats()
            if not user_inputs['output_formats']:
                messagebox.showerror("Fehler", "Keine Ausgabeformate ausgewählt.")
                return

            # Auswahl der Varianten (Cluster, Zufällig, Beide)
            variant = variant_var.get()
            user_inputs['variant'] = variant

            input_window.destroy()
        except ValueError:
            messagebox.showerror("Fehler", "Bitte gültige Eingaben machen.")

    # Kreisauflösung
    tk.Label(input_window, text="Kreisauflösung (z.B. 36):").grid(row=0, column=0, sticky='w')
    entry_circle_resolution = tk.Entry(input_window)
    entry_circle_resolution.insert(0, "36")
    entry_circle_resolution.grid(row=0, column=1)

    # Anzahl der Baumdurchmesser
    tk.Label(input_window, text="Anzahl der unterschiedlichen Kronendurchmesser:").grid(row=1, column=0, sticky='w')
    entry_num_diameters = tk.Entry(input_window)
    entry_num_diameters.insert(0, "1")
    entry_num_diameters.grid(row=1, column=1)

    # Platz für dynamische Eingabefelder
    frame_diameters = tk.Frame(input_window)
    frame_diameters.grid(row=2, column=0, columnspan=2)

    entries_diameters = []
    entries_proportions = []
    entries_colors = []

    def update_diameter_entries(*args):
        # Lösche vorhandene Einträge
        for widget in frame_diameters.winfo_children():
            widget.destroy()
        entries_diameters.clear()
        entries_proportions.clear()
        entries_colors.clear()
        try:
            num_diameters = int(entry_num_diameters.get())
        except ValueError:
            return
        for i in range(num_diameters):
            tk.Label(frame_diameters, text=f"Kronendurchmesser {i+1} (in Metern):").grid(row=i*3, column=0, sticky='w')
            entry_diameter = tk.Entry(frame_diameters)
            entry_diameter.grid(row=i*3, column=1)
            entries_diameters.append(entry_diameter)

            tk.Label(frame_diameters, text=f"Prozentualer Anteil für Durchmesser {i+1} (%):").grid(row=i*3+1, column=0, sticky='w')
            entry_proportion = tk.Entry(frame_diameters)
            entry_proportion.grid(row=i*3+1, column=1)
            entries_proportions.append(entry_proportion)

            tk.Label(frame_diameters, text=f"Farbe für Durchmesser {i+1} (Hex-Code):").grid(row=i*3+2, column=0, sticky='w')
            entry_color = tk.Entry(frame_diameters)
            entry_color.insert(0, "#00ff00")
            entry_color.grid(row=i*3+2, column=1)
            entries_colors.append(entry_color)

            def choose_color(index=i):
                color_code = colorchooser.askcolor(title=f"Farbe für Durchmesser {index+1} auswählen")
                if color_code[1]:
                    entries_colors[index].delete(0, tk.END)
                    entries_colors[index].insert(0, color_code[1])

            btn_color = tk.Button(frame_diameters, text="Farbe auswählen", command=lambda idx=i: choose_color(idx))
            btn_color.grid(row=i*3+2, column=2)

        # Fenstergröße anpassen
        input_window.update_idletasks()
        width = input_window.winfo_reqwidth()
        height = input_window.winfo_reqheight()
        input_window.geometry(f"{width}x{height}")

    entry_num_diameters.bind('<KeyRelease>', update_diameter_entries)
    update_diameter_entries()

    # Clusteroption
    var_use_clustering = tk.BooleanVar()
    tk.Checkbutton(input_window, text="Bäume in Clustern anordnen", variable=var_use_clustering).grid(row=3, column=0, sticky='w')

    tk.Label(input_window, text="Cluster-Prozentsatz (0-100%):").grid(row=4, column=0, sticky='w')
    entry_cluster_percentage = tk.Entry(input_window)
    entry_cluster_percentage.insert(0, "50")
    entry_cluster_percentage.grid(row=4, column=1)

    # Auswahl der Varianten
    tk.Label(input_window, text="Varianten für die Baumverteilung:").grid(row=5, column=0, sticky='w')
    variant_var = tk.StringVar(value="both")
    tk.Radiobutton(input_window, text="Nur zufällig", variable=variant_var, value="random").grid(row=6, column=0, sticky='w')
    tk.Radiobutton(input_window, text="Nur Cluster", variable=variant_var, value="cluster").grid(row=7, column=0, sticky='w')
    tk.Radiobutton(input_window, text="Beide Varianten", variable=variant_var, value="both").grid(row=8, column=0, sticky='w')

    # Bestätigungsbutton
    tk.Button(input_window, text="Weiter", command=submit).grid(row=9, column=0, columnspan=3)

    input_window.wait_window()

    return user_inputs

# Hauptfunktion zum Plotten der Bäume innerhalb der Form
def plot_trees_within_shape():
    global circle_resolution  # Damit die Variable in write_shapefile verwendet werden kann

    # Haupt-Tkinter-Fenster erstellen
    root = tk.Tk()
    root.title("Baumraster-Erstellung")

    # Benutzerinputs sammeln
    user_inputs = get_user_inputs()
    if not user_inputs:
        root.destroy()
        return

    circle_resolution = user_inputs['circle_resolution']
    num_diameters = user_inputs['num_diameters']
    diameters = user_inputs['diameters']
    proportions = user_inputs['proportions']
    colors = user_inputs['colors']
    use_clustering = user_inputs['use_clustering']
    cluster_percentage = user_inputs['cluster_percentage']
    output_formats = user_inputs['output_formats']
    variant_selection = user_inputs['variant']

    # Auswahl der Eingabedateien (Batch-Verarbeitung)
    input_files = filedialog.askopenfilenames(
        title="Bitte die Eingabedateien auswählen",
        filetypes=[
            ("Unterstützte Dateien", "*.shp *.dxf *.svg"),
            ("Shapefile", "*.shp"),
            ("DXF Dateien", "*.dxf"),
            ("SVG Dateien", "*.svg")
        ]
    )

    if not input_files:
        messagebox.showerror("Fehler", "Keine Eingabedateien ausgewählt.")
        root.destroy()
        return

    # Auswahl des Ausgabeverzeichnisses
    output_directory = filedialog.askdirectory(
        title="Bitte das Ausgabeverzeichnis auswählen"
    )

    if not output_directory:
        messagebox.showerror("Fehler", "Kein Ausgabeverzeichnis ausgewählt.")
        root.destroy()
        return

    # Verarbeitung jeder Eingabedatei
    for input_file in input_files:
        filename = os.path.basename(input_file)
        name_without_ext = os.path.splitext(filename)[0]
        extension = input_file.split('.')[-1].lower()

        polylines = read_input_file(input_file)

        if len(polylines) == 0:
            messagebox.showerror("Fehler", f"Keine gültigen Formen gefunden oder das Dateiformat wird nicht unterstützt: {filename}")
            continue

        # Wenn es sich um eine SVG-Datei handelt, nach maximaler Länge fragen und skalieren
        if extension == 'svg':
            # Kombinieren aller Punkte, um die Begrenzungsbox zu finden
            all_points = np.concatenate(polylines)
            min_x, min_y = np.min(all_points, axis=0)
            max_x, max_y = np.max(all_points, axis=0)
            shape_width = max_x - min_x
            shape_height = max_y - min_y
            shape_max_length = max(shape_width, shape_height)

            # Eingabe der maximalen Länge für die Skalierung
            try:
                max_length_input = simpledialog.askstring("Skalierung", f"Bitte die maximale Länge für die Skalierung von {filename} (in Metern) angeben:")
                if max_length_input is None:
                    messagebox.showerror("Fehler", "Keine Eingabe für die maximale Länge.")
                    continue
                max_length = float(max_length_input)
            except ValueError:
                messagebox.showerror("Fehler", "Ungültige Eingabe für die maximale Länge.")
                continue

            if max_length <= 0:
                messagebox.showerror("Fehler", "Die maximale Länge muss positiv sein.")
                continue

            scale = max_length / shape_max_length

            # Skalieren aller Polylinien
            scaled_polylines = []
            for polyline in polylines:
                scaled_polyline = [(scale * (x - min_x), scale * (y - min_y)) for x, y in polyline]
                scaled_polylines.append(scaled_polyline)

            # CRS ist nicht relevant für SVG
            crs = None

        else:
            # Für andere Formate, CRS verarbeiten
            if extension == 'shp':
                with fiona.open(input_file, 'r') as shp:
                    crs = CRS(shp.crs)
            else:
                # CRS vom Benutzer abfragen
                crs_input = simpledialog.askstring(
                    "Koordinatensystem",
                    f"Bitte gib den EPSG-Code des Koordinatensystems für {filename} ein (z.B. 32632 für UTM Zone 32N):"
                )
                if crs_input is None:
                    messagebox.showerror("Fehler", "Kein Koordinatensystem eingegeben.")
                    continue
                try:
                    crs_epsg = int(crs_input)
                    crs = CRS.from_epsg(crs_epsg)
                except ValueError:
                    messagebox.showerror("Fehler", "Ungültiger EPSG-Code.")
                    continue

            # Verwende die Originalpolylinien ohne Skalierung
            scaled_polylines = polylines

            # Kombinieren aller Punkte, um die Begrenzungsbox zu finden
            all_points = np.concatenate(polylines)
            min_x, min_y = np.min(all_points, axis=0)
            max_x, max_y = np.max(all_points, axis=0)

        # Aktualisiere die Begrenzungsbox
        scaled_all_points = np.concatenate(scaled_polylines)
        min_x_scaled, min_y_scaled = np.min(scaled_all_points, axis=0)
        max_x_scaled, max_y_scaled = np.max(scaled_all_points, axis=0)

        # Erstellen von Path-Objekten für jede Polyline
        paths = []
        for polyline in scaled_polylines:
            if len(polyline) < 2:
                continue  # Nicht genügend Punkte für einen Pfad
            verts = list(polyline)
            if verts[0] != verts[-1]:
                verts.append(verts[0])  # Polygon schließen
            codes = [Path.MOVETO] + [Path.LINETO] * (len(verts) - 2) + [Path.CLOSEPOLY]
            path = Path(verts, codes)
            paths.append(path)

        if not paths:
            messagebox.showerror("Fehler", f"Keine gültigen geschlossenen Polylinien gefunden in {filename}.")
            continue

        # Erstellen eines zusammengesetzten Path-Objekts
        shape_path = Path.make_compound_path(*paths)

        # Neues Fenster für die interaktive Vorschau erstellen
        preview_window = tk.Toplevel(root)
        preview_window.title(f"Vorschau und Anpassung - {filename}")

        # Vorschaufenster bildschirmfüllend anzeigen
        preview_window.attributes('-fullscreen', True)

        # Frame für Plot und Steuerungselemente
        frame = tk.Frame(preview_window)
        frame.pack(fill=tk.BOTH, expand=True)

        # Matplotlib-Figur erstellen
        fig = Figure(figsize=(8, 6))
        ax = fig.add_subplot(111)

        canvas = FigureCanvasTkAgg(fig, master=frame)
        canvas.draw()
        canvas.get_tk_widget().pack(side=tk.LEFT, fill=tk.BOTH, expand=1)

        # Steuerungsframe für Slider und Button
        control_frame = tk.Frame(frame)
        control_frame.pack(side=tk.RIGHT, fill=tk.Y)

        # Füllungsintensität Slider
        fill_intensity = tk.DoubleVar(value=1.0)

        def update_fill_intensity(val):
            nonlocal tree_positions
            tree_positions, _ = generate_tree_positions(current_variant)
            update_trees()

        slider = tk.Scale(control_frame, from_=0.1, to=2.0, resolution=0.1, orient=tk.VERTICAL, variable=fill_intensity, label="Füllungsintensität", command=update_fill_intensity)
        slider.pack(fill=tk.Y, padx=10, pady=10)

        # Button zum Schließen und Fortfahren
        def on_close():
            preview_window.destroy()

        close_button = tk.Button(control_frame, text="Bearbeitung abschließen", command=on_close)
        close_button.pack(pady=10)

        # Funktion zur Erstellung der Baumpositionen
        def generate_tree_positions(variant):
            tree_positions = []
            diameter_tree_counts = {}
            max_trees_per_diameter = 100000  # Erhöht, um mehr Bäume zuzulassen
            intensity = fill_intensity.get()

            tree_data = sorted(zip(diameters, proportions, colors), key=lambda x: -x[0])

            # Berechnung der Gesamtfläche der Form
            total_area = compute_shape_area(scaled_polylines)

            # Berechnung der Gesamtanzahl der Bäume pro Durchmesser
            total_trees = {}
            for diameter, proportion, _ in tree_data:
                radius = diameter / 2
                total_trees[diameter] = int((proportion / 100) * total_area / (np.pi * (radius ** 2)) * intensity)

            if num_diameters == 1:
                diameter_tree_counts = {}
                diameter, proportion, color = tree_data[0]
                radius = diameter / 2

                # Mindestabstand berechnen
                if diameter >= 3:
                    min_distance = diameter * 1.3  # Zentrum-zu-Zentrum-Abstand
                else:
                    min_distance = diameter  # Kein zusätzlicher Abstand

                # Rasterpunkte erstellen
                x_min = min_x_scaled + radius
                x_max = max_x_scaled - radius
                y_min = min_y_scaled + radius
                y_max = max_y_scaled - radius

                x_coords = np.arange(x_min, x_max + min_distance, min_distance)
                y_coords = np.arange(y_min, y_max + min_distance, min_distance)

                # Maximal zulässige Anzahl von Bäumen berechnen
                max_trees = min(total_trees[diameter], max_trees_per_diameter)

                for x in x_coords:
                    for y in y_coords:
                        if shape_path.contains_point((x, y)):
                            tree_positions.append((x, y, radius, color))
                            if len(tree_positions) >= max_trees:
                                break
                    if len(tree_positions) >= max_trees:
                        break

                diameter_tree_counts[diameter] = len(tree_positions)

            else:
                diameter_tree_counts = {diameter: 0 for diameter in diameters}

                # Platzierung der Bäume für jeden Durchmesser
                for diameter, proportion, color in tree_data:
                    radius = diameter / 2
                    trees_to_place = min(total_trees[diameter], max_trees_per_diameter)
                    attempts = 0

                    while diameter_tree_counts[diameter] < trees_to_place and attempts < 100000:
                        x_pos = random.uniform(min_x_scaled + radius, max_x_scaled - radius)
                        y_pos = random.uniform(min_y_scaled + radius, max_y_scaled - radius)

                        if not shape_path.contains_point((x_pos, y_pos)):
                            attempts += 1
                            continue

                        overlaps = False
                        for (existing_x, existing_y, existing_radius, _) in tree_positions:
                            if check_overlap(x_pos, y_pos, radius, existing_x, existing_y, existing_radius, min_distance=radius * 0.3):
                                overlaps = True
                                break

                        if not overlaps:
                            tree_positions.append((x_pos, y_pos, radius, color))
                            diameter_tree_counts[diameter] += 1
                        attempts += 1

            return tree_positions, diameter_tree_counts

        # Funktion zur Aktualisierung der Bäume
        def update_trees():
            nonlocal tree_positions, tree_circles, total_area

            # Berechne neue Gesamtfläche
            total_area = compute_shape_area(scaled_polylines)

            # Bäume neu generieren
            tree_positions, diameter_tree_counts = generate_tree_positions(current_variant)

            # Lösche vorhandene Baumkronen
            for circle in tree_circles:
                circle.remove()
            tree_circles.clear()

            # Begrenze die Anzahl der Bäume in der Vorschau für bessere Leistung
            max_preview_trees = 1000
            preview_tree_positions = tree_positions[:max_preview_trees]

            # Neue Bäume plotten
            for x_pos, y_pos, radius, color in preview_tree_positions:
                circle = plt.Circle((x_pos, y_pos), radius, edgecolor=color, facecolor='none', linewidth=0.8)
                ax.add_artist(circle)
                tree_circles.append(circle)

            canvas.draw()

        # Baumdaten sortieren
        tree_data = sorted(zip(diameters, proportions, colors), key=lambda x: -x[0])

        # Berechnung der Gesamtfläche der Form
        total_area = compute_shape_area(scaled_polylines)
        print(f"Gesamtfläche der Form in {filename}: {total_area:.2f} Quadratmeter")

        # Initiale Bäume generieren
        current_variant = variant_selection
        tree_positions, diameter_tree_counts = generate_tree_positions(current_variant)

        # Plotten der initialen Form und Bäume
        ax.clear()
        ax.set_title(f"Interaktive Vorschau - {filename}")
        ax.set_xlabel('Entfernung Ost (m)')
        ax.set_ylabel('Entfernung Nord (m)')

        # Plotten der Form
        for path in paths:
            patch = plt.Polygon(path.vertices, closed=True, fill=False, edgecolor='black')
            ax.add_patch(patch)

        # Plotten der initialen Bäume
        tree_circles = []

        # Begrenze die Anzahl der Bäume in der Vorschau
        max_preview_trees = 1000
        preview_tree_positions = tree_positions[:max_preview_trees]

        for x_pos, y_pos, radius, color in preview_tree_positions:
            circle = plt.Circle((x_pos, y_pos), radius, edgecolor=color, facecolor='none', linewidth=0.8)
            ax.add_artist(circle)
            tree_circles.append(circle)

        # Achsenlimits setzen
        ax.set_xlim(min_x_scaled - 10, max_x_scaled + 10)
        ax.set_ylim(min_y_scaled - 10, max_y_scaled + 10)
        ax.set_aspect('equal', adjustable='box')

        canvas.draw()

        # Warten, bis das Vorschaufenster geschlossen wird
        root.wait_window(preview_window)

        # Nach der Bearbeitung: Bäume generieren und Dateien exportieren
        variants = []
        if variant_selection == 'both':
            variants_to_generate = [('random', 'random'), ('cluster', 'cluster')]
        elif variant_selection == 'random':
            variants_to_generate = [('random', 'random')]
        elif variant_selection == 'cluster':
            variants_to_generate = [('cluster', 'cluster')]
        else:
            variants_to_generate = [('selected', current_variant)]

        # Verwende die aktuelle Füllungsintensität
        final_fill_intensity = fill_intensity.get()

        for variant_name, use_clustering_variant in variants_to_generate:
            # Generiere die Bäume für die Ausgabe mit voller Anzahl
            tree_positions, diameter_tree_counts = generate_tree_positions(use_clustering_variant)

            tree_count = len(tree_positions)

            # Dateinamen für die Ausgabe erstellen
            output_filename_base = os.path.join(output_directory, f"{name_without_ext}_{variant_name}_output")

            # Für jedes ausgewählte Ausgabeformat, die Datei schreiben
            for export_extension in output_formats:
                # Verwende die Funktion, um einen eindeutigen Dateinamen zu erhalten
                current_export_file = get_unique_filename(output_filename_base, export_extension)

                # Schreiben der Ausgabedatei basierend auf dem gewählten Format
                write_output_file(current_export_file, scaled_polylines, tree_positions, crs, fig=fig if export_extension == 'svg' else None)

                # Erfolgreiche Speicherung
                print(f"Das Schema wurde erfolgreich unter {current_export_file} gespeichert.\nAnzahl der gezeichneten Bäume in {filename}: {tree_count}")

    messagebox.showinfo("Fertig", "Die Verarbeitung aller Dateien ist abgeschlossen.")
    root.destroy()

if __name__ == "__main__":
    plot_trees_within_shape()

RETHINKING COUNTRYSIDE


Das Projekt „Rethinking Countryside“ hatte das Ziel, mögliche Szenarien für die Umnutzung einer ehemaligen landwirtschaftlichen Hühnerzucht am Stadtrand von Vicenza zu entwickeln. Dafür wurde eine kreative Analyse durchgeführt, die als Grundlage für Planungsansätze diente. Auf dieser Basis wurden Planungspersektiven definiert, die schließlich in drei Szenarien mündeten, die unterschiedliche ökologische, soziale und ökonomische Schwerpunkte setzen. Ziel ist es, den stillgelegten Ort in einen Raum zu transformieren, der nachhaltige Nutzungen, kulturelle Aktivitäten und ökologische Funktionen vereint. Durch innovative Ansätze und eine sensible Gestaltung soll der Ort ein Bindeglied zwischen Stadt und Land werden, das sowohl die lokale Gemeinschaft als auch Besucher inspiriert.

Ausgangslage


Die ehemalige Hühnerzucht war zum Zeitpunkt der Projektausarbeitung noch in Betrieb, befand sich jedoch im letzten Jahr ihrer landwirtschaftlichen Nutzung. Das Areal umfasst acht Gebäude, die teilweise mit dem problematischen Baustoff Eternit errichtet wurden, und erstreckt sich über eine potenzielle Eingriffsfläche von 6,1 Hektar. Die Lage am Übergang zwischen städtischen und ländlichen Strukturen bietet großes Potenzial für eine neue Nutzung, bringt jedoch auch Herausforderungen mit sich – darunter der Umgang mit den bestehenden Bauten und die Integration ökologischer sowie sozialer Funktionen in die Planung.

Stadt-Landschaftlicher Kontext


Das Projektgebiet liegt am nordöstlichen Stadtrand von Vicenza und befindet sich innerhalb des bebauten Stadtgebiets in einem letzten unbebauten Bereich, der noch von landwirtschaftlicher Nutzung geprägt ist. Dieser unbebaute Bereich stellt eine Besonderheit dar, da er sich in seinen Dimensionen mit nahe gelegenen Kasernen- und Parkanlagen vergleichen lässt. Er nimmt etwa 6 % der gesamten bebauten Fläche der Stadt ein und bietet damit nicht nur räumliches, sondern auch funktionales Potenzial für zukünftige Entwicklungen. Die Lage des Areals macht es zu einem entscheidenden Verbindungspunkt zwischen urbanen Strukturen und den angrenzenden ländlichen Gebieten, was seine Bedeutung für die Stadtplanung zusätzlich unterstreicht.

Landschafts-Layer

Kreative Landschaftslektüre

Das Projektgebiet befindet sich am nordöstlichen Rand der Stadt Vicenza, östlich einer süd-nördlich verlaufenden Bahnschiene. Diese Bahnschiene markiert eine deutliche Grenze zwischen urbanen und ländlichen Nutzungen. Westlich der Bahnschiene ist das Gebiet dicht bebaut und weist eine städtische Struktur mit Wohn- und Gewerbeflächen auf. Östlich davon beginnt abrupt die landwirtschaftliche Nutzung, die durch eine andere Flächenstruktur geprägt ist: große, offene Felder wechseln sich mit pflasterförmig angeordneten landwirtschaftlichen Anlagen und Höfen ab.

Das Projektgebiet liegt zentral in dieser Übergangszone, eingebettet zwischen der Bahnschiene im Westen und einer Straße im Osten. Diese einzigartige Lage unterstreicht das Potenzial des Areals, als Bindeglied zwischen Stadt und Land zu fungieren und Synergien zwischen urbanen und ländlichen Funktionen zu schaffen.

Luftbild Layer

Bebauungsstruktur

Offene Flächen

Landwirtschaft

Schwingungen der Landschaft im Übergangsbereich

Masterplan

Planungsobjektiven

sozialer Fokus


Das Projekt „Rethinking Countryside“ möchte soziale Interaktion und Bildung fördern, indem es vielfältige Nutzungsmöglichkeiten für die Gemeinschaft schafft. Geplant sind Bildungsangebote mit einem Schwerpunkt auf Umweltbildung, die sowohl praktische als auch theoretische Inhalte vermitteln. Darüber hinaus bieten Ausstellungsräume und Veranstaltungsflächen Raum für kulturelle und kreative Veranstaltungen, während Sportangebote die körperliche Aktivität und den sozialen Austausch fördern. Durch diese vielfältigen Angebote soll das Projekt zu einem lebendigen Ort der Begegnung und des Austauschs werden.

ökonomischer Fokus


Die wirtschaftliche Perspektive des Projekts konzentriert sich auf die Schaffung eines nachhaltigen und regional verankerten Wirtschaftskonzepts. Eine Möglichkeit besteht in der Integration von Agri-PV (Photovoltaik in der Landwirtschaft), die eine doppelte Nutzung der Flächen für Energieproduktion und landwirtschaftliche Zwecke erlaubt. Dies könnte die wirtschaftliche Basis des Projekts stärken und gleichzeitig zur Energiewende beitragen. Weitere wirtschaftliche Impulse könnten durch lokale Produkte, landwirtschaftliche Schulungen und innovative Geschäftsmodelle, wie Direktvermarktung oder Hofläden, gesetzt werden.

ökologischer Fokus


Das ökologische Ziel des Projekts liegt in der Wiederherstellung und langfristigen Förderung natürlicher Systeme. Geplante Maßnahmen umfassen die Renaturierung von Flächen und die Aufforstung, um die Biodiversität zu steigern und das Mikroklima zu verbessern. Zudem wird die Zulassung von Ruderal- und Spontanvegetation ein integraler Bestandteil des Konzepts sein, da diese Vegetationstypen wichtige Lebensräume für Insekten und andere Tierarten schaffen. Diese Maßnahmen tragen zur ökologischen Resilienz des Gebiets bei und stellen eine nachhaltige Nutzung sicher.

Entwicklung von drei Scenarien


Im Rahmen des Projekts „Rethinking Countryside“ wurden drei unterschiedliche Szenarien entwickelt, die jeweils eine spezifische Gewichtung der drei Planungsobjektive – sozial, ökonomisch und ökologisch – in den Mittelpunkt stellen. Jedes Szenario reflektiert eine andere Herangehensweise an die Umnutzung der ehemaligen Hühnerzucht und bietet individuelle Antworten auf die Herausforderungen und Potenziale des Projektgebiets. Diese Ansätze verdeutlichen, wie verschiedene Prioritäten die Gestaltung und Nutzung des Areals prägen können, und bieten gleichzeitig eine Grundlage für flexible und zukunftsorientierte Planung.

Scenario „Green Lung“

Dieses erste entwickelte Szenario legt den Fokus auf die ökologischen Perspektiven, indem durch umfassende Entsiegelungsmaßnahmen, gezielte Aufforstung und Renaturierung auf der ehemaligen landwirtschaftlichen Anlage und den umliegenden stadtnahen landwirtschaftlichen Feldern ein urbaner Wald geschaffen wird. Ziel ist es, eine grüne Lunge am Stadtrand zu etablieren, die nicht nur einen ökologischen Mehrwert bietet, sondern auch soziale und ökonomische Funktionen integriert.

Der geplante urbane Wald umfasst verschiedene Bereiche, die die ökologische Vielfalt fördern und die Anpassungsfähigkeit an klimatische Herausforderungen stärken. Ein Teil des Gebiets wird für nachhaltige Holzproduktion genutzt, die eine Ressource für die regionale Bau- und Energiewirtschaft darstellt. Andere Bereiche werden bewusst der ruderalen Vegetation überlassen, die durch ihre natürliche Dynamik wertvolle Lebensräume für Tiere und Pflanzen schafft. Zusätzlich sollen Wasserflächen und Feuchtvegetationszonen angelegt werden, um die Biodiversität weiter zu steigern und gleichzeitig wichtige ökologische Dienstleistungen wie Wasserspeicherung und Klimaregulation zu erfüllen.

Ein weiteres zukunftsweisendes Element ist der Agro-Forstanbau, bei dem landwirtschaftliche und forstwirtschaftliche Nutzungen kombiniert werden. Dieser Ansatz ermöglicht es, auf derselben Fläche sowohl Nahrungsmittel als auch Holzprodukte zu gewinnen, was die ökonomische Tragfähigkeit des Projekts erhöht. Gleichzeitig trägt er zur Erhaltung traditioneller landwirtschaftlicher Praktiken bei, die in moderner Weise weiterentwickelt werden.

Das Szenario berührt nicht nur die ökologischen, sondern auch die sozialen und ökonomischen Planungsobjektive. Der urbane Wald soll nicht nur ein Produktionsraum sein, sondern auch ein frei zugänglicher Erholungsraum für die Bevölkerung. Spazierwege, Ruhezonen und naturnahe Erlebnisbereiche bieten den Bewohnern und Besuchern von Vicenza Möglichkeiten zur Erholung und Naturerfahrung. Damit wird der urbane Wald zu einem Ort der Begegnung und zum Bindeglied zwischen der Stadt und ihrer ländlichen Umgebung.

Mit seiner multifunktionalen Ausrichtung schlägt dieses Szenario eine Brücke zwischen ökologischer Nachhaltigkeit, sozialem Mehrwert und wirtschaftlichem Potenzial. Es zeigt, wie eine gezielte Umgestaltung ländlicher und periurbaner Flächen nicht nur Umweltprobleme lösen, sondern auch die Lebensqualität der Menschen nachhaltig verbessern kann.

Erste Visualisation

Masterplan „Green Lung“

Layer des Masterplans

Scenario „Corte Rigoni“

Das zweite entwickelte Szenario, „Corte Rigoni“, legt den Schwerpunkt auf die Transformation und Neugestaltung der bestehenden Gebäudestrukturen. Die Planung sieht vor, die bestehenden Bauvolumen gemäß den Vorgaben des Piano di Intervento (PI) in einen neuen Baukörper zu überführen, der sich harmonisch in die ländliche Umgebung einfügt. Dabei orientiert sich der Entwurf bewusst am Gebäudetyp des Hofs – einer für die Region typischen und identitätsstiftenden Bauform.

Wesentliche Gestaltungselemente dieses Szenarios sind die gezielte Ausrichtung des neuen Baukörpers entlang bedeutender Achsen: einerseits zur historischen Villa Guiotto, andererseits zum bestehenden landwirtschaftlichen Hof. Diese Achsen betonen die visuelle und funktionale Verknüpfung zwischen Tradition und Innovation und schaffen ein räumliches Konzept, das lokale Werte und moderne Nutzungsanforderungen verbindet.

Die Gebäude im neuen Hofensemble sollen vielfältigen Nutzungen dienen. Geplant sind Veranstaltungsflächen für kulturelle und gesellschaftliche Events, ein Restaurant mit regionalem Fokus sowie Ferienunterkünfte, die den Tourismus in der Region fördern. Ergänzend wird das Freiraumkonzept durch Spielplätze, eine Streuobstwiese und ökologische Ausgleichsflächen bereichert. Diese Maßnahmen bieten nicht nur Erholungsräume für die lokale Bevölkerung, sondern tragen auch zur ökologischen Aufwertung des Gebiets bei. „Corte Rigoni“ verbindet somit eine innovative Nutzung mit der Bewahrung und Weiterentwicklung ländlicher Bau- und Landschaftstraditionen.

Masterplan 1:5000

Lageplan ‚Corte Rigoni‘ 1:1250

Il Corte – Der Hof

Scenario „AgriLab“

Das Szenario “AgriLab” kombiniert nachhaltige Landwirtschaft, Forschung und Bildung und legt dabei einen Schwerpunkt auf die ökonomischen Perspektiven. Die ehemalige landwirtschaftliche Hühnerzucht wird zu einem multifunktionalen Areal transformiert, das innovative Ansätze wie Agri-PV mit traditionellen Praktiken vereint. Um die Nutzungen klar zu strukturieren, gliedert sich das Szenario in drei Zonen: die ökologische Zone, die Markzone und die landwirtschaftliche Versuchs- und Bildungsfläche.

In der ökologischen Zone steht der Schutz und die Förderung der Biodiversität im Vordergrund. Blühstreifen, Feuchtbiotope und natürliche Vegetationsflächen schaffen Lebensräume für bestäubende Insekten und andere Tierarten. Diese Zone trägt nicht nur zur ökologischen Resilienz des Gebiets bei, sondern verbessert auch die Umweltqualität und bietet Raum für Erholung und Naturerfahrung.

Die Markzone zeichnet sich dadurch aus, dass bis auf ein Gebäude alle bestehenden Strukturen in diesem Szenario abgerissen werden. Das verbleibende Gebäude wird bewusst erhalten, um seinen industriellen Charakter zu nutzen und eine besondere Atmosphäre zu schaffen. Es wird als zentraler Ort für den Verkauf von regionalen Produkten, Veranstaltungen und temporäre Nutzungen gestaltet. Diese einzigartige Mischung aus Funktionalität und architektonischer Ästhetik macht die Markzone zu einem lebendigen Treffpunkt. Ergänzt wird die Markzone durch Hofläden, Wochenmärkte und gastronomische Angebote, die die regionale Wirtschaft fördern und die Beziehung zwischen Produzenten und Konsumenten stärken.

Die landwirtschaftliche Versuchs- und Bildungsfläche ist das Herzstück des “AgriLab”. Auf diesen Flächen werden moderne und nachhaltige Anbaumethoden wie regenerative Landwirtschaft, Permakultur und Agroforstwirtschaft erforscht und demonstriert. Agri-PV (Photovoltaik in der Landwirtschaft) spielt hier eine zentrale Rolle, da sie eine doppelte Nutzung der Flächen für Energieproduktion und landwirtschaftliche Zwecke ermöglicht. Diese Technologie zeigt, wie erneuerbare Energien in die Landwirtschaft integriert werden können, um ökologische und wirtschaftliche Ziele gleichzeitig zu erreichen. Ergänzt wird diese Zone durch Bildungs- und Schulungsangebote, die praktische und theoretische Kenntnisse über nachhaltige Landwirtschaft vermitteln.

Das Szenario “AgriLab” verbindet soziale, ökologische und ökonomische Perspektiven in einem ganzheitlichen Ansatz. Es schafft nicht nur eine Plattform für Forschung und Innovation, sondern auch einen Ort, an dem Menschen zusammenkommen, um voneinander zu lernen und gemeinsam eine nachhaltige Zukunft zu gestalten. Die Kombination aus ökologischen Maßnahmen, wirtschaftlichen Impulsen und sozialen Angeboten macht “AgriLab” zu einem zukunftsweisenden Modell für nachhaltige Entwicklung im ländlich-städtischen Übergangsraum.

Masterplan ‚AgriLab‘ 1:5000

Lageplan 1:1250

Detailzonen

ökologische Zone – 1:300
landwirtschaftliche Zone – 1:500
Markt Zone – 1:200