Tree Gen 1.48.0: Kronen-Huelle, weniger Blaetter, Formband neu geeicht

Vom User im Wald abgenommen: "sehr schoen etwas weniger blaetter und wir
koennen das fuer alle baeume uebernehmen".

1) KRONEN-HUELLE statt Einzelkappen
   Kugeln auf die Aeste, Mesh to Volume, Volume to Mesh, dann Streuung auf der
   verschmolzenen Oberflaeche - der Standard-Ablauf aus den
   Produktions-Breakdowns, den wir uebersprungen hatten. Die Aeste verschwinden
   im Inneren der Krone; die Polster sind nicht mehr als getrennte Koerper
   sichtbar.

   Drei Befunde, alle gemessen:
   - ast_id kam nur an 3 von 10 Aesten an. Nicht das Sampling, sondern die
     Eingabe: nur VIER Cluster-Zentren auf drei Aesten. Sichtbar erst mit
     Points to Vertices - to_mesh() auf eine Punktwolke liefert eine leere Mesh
     und misst nichts.
   - S1 stand kahl. Reihe ueber die Stufen 0/20/41/109 Zentren: allmaehlicher
     Abfall, keine Klippe, also die Cluster-Dichte. "Dichte" ist Kugeln je m2
     Zweigflaeche, die schrumpft quadratisch - sie laeuft jetzt mit 1/g^2
     gegen die Groesse, damit die ANZAHL konstant bleibt. Skalenfrei, kein
     Sonderweg fuer Setzlinge.
   - 31 % der Cards lagen unter dem Kronenansatz: die Verschmelzung weitet die
     Form nach unten, der Filter griff nur auf den Zentren. Jetzt auch auf der
     Huelle.

2) WENIGER BLAETTER (-15 % auf die Stufen-Ziele)
   Gemessen an der Eiche: 381 -> 319 Cards, Deckung 10.4 -> 8.6, 372 Tris
   gespart. Der Gegenversuch - Cards um 15 % verkleinern - kostet MEHR Deckung
   (7.9, die Flaeche geht quadratisch) und spart kein Dreieck.

3) FORMBAND um das Abgenommene gelegt, nicht umgekehrt
   Alle Referenzformen unter der neuen Bauform neu gemessen:
     Eiche      u/m 1.04-1.16   o/m 0.79-0.91
     abgenommen u/m 0.78-1.02   o/m 0.68-0.79
     Trichter   u/m 0.68-0.78   o/m 1.04-1.14
     Pilz       u/m 0.59-0.90   o/m 0.82-0.95
     Haube      u/m 0.94-1.03   o/m 0.71-0.78

   u/m TRENNT NICHTS MEHR - der abgenommene Bereich ueberlappt den Pilz und
   stoesst an den Trichter. Die alte 0.82-Schranke stammt aus der
   Einzelkappen-Aera; dagegen zu kalibrieren haette die Krone verbogen, um eine
   Zahl zu retten, die ihre Aussagekraft verloren hat. u/m wird nur noch
   mitgedruckt. o/m trennt sauber und traegt die Formpruefung allein.

27 Tests bestehen.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-08-07 15:40:49 +02:00
co-authored by Claude Opus 4.8
parent 869b008d4f
commit a718476592
8 changed files with 136 additions and 38 deletions
+77
View File
@@ -702,6 +702,83 @@ Gegenprobe ohne die Boden-Klemmung: vier Fehler.
Drei bestehende Tests zaehlten die Huelle als Render-Mesh mit und schlugen zu Drei bestehende Tests zaehlten die Huelle als Render-Mesh mit und schlugen zu
Recht an - sie filtern jetzt `UCX_`. Recht an - sie filtern jetzt `UCX_`.
### Die Kronen-Huelle: Kugeln verschmelzen, dann streuen
Der "behaarte Finger"-Look kam zurueck, weil wir einen Schritt der
Standard-Technik uebersprungen hatten. Die Produktions-Breakdowns (80.lv
"Meadows", "The Witness"-Baeume) machen es so: Kugeln auf die Aeste setzen,
sie zu EINER Kronenmasse verschmelzen, und die Cards ueber deren **Oberflaeche**
streuen. Wir hatten je Cluster eine eigene Halbkugel bestueckt - die Polster
blieben dadurch als getrennte Koerper sichtbar, ein Laubhandschuh je Ast.
Jetzt: Kugeln instanzieren -> `Mesh to Volume` -> `Volume to Mesh` (das ist die
metaball-artige Verschmelzung) -> `Distribute Points on Faces` auf der Huelle.
Die Aeste verschwinden im Inneren der Krone. Vom User im Wald abgenommen.
**Drei Befunde auf dem Weg, alle gemessen statt geraten:**
`ast_id` kam nur an 3 von 10 Aesten an. Ursache war NICHT das Sampling, sondern
die Eingabe: es existierten nur **vier Cluster-Zentren auf drei Aesten**. In der
alten Bauform regelte die Bisektion die Cluster-Dichte selbst hoch; seit sie
stattdessen die Cards auf der Huelle regelt, muss der Startwert stimmen.
Sichtbar wurde das erst mit `Points to Vertices` - `to_mesh()` auf eine reine
Punktwolke liefert eine LEERE Mesh und misst nichts. Ein Messwerkzeug, das nicht
messen kann, sieht aus wie ein Befund.
S1 stand komplett kahl. Die Reihe ueber die Stufen zeigte **0 / 20 / 41 / 109**
Zentren - allmaehlicher Abfall bis null, keine Klippe. Also die Cluster-Dichte,
nicht die Voxel-Groesse. "Dichte" heisst Kugeln je m2 ZWEIGflaeche, und die
schrumpft mit dem QUADRAT der Groesse; sie laeuft jetzt mit 1/g^2 gegen die
Baumgroesse, damit die ANZAHL konstant bleibt. Das ist die richtige Groesse:
eine Krone braucht eine bestimmte Zahl Ballen zum Verschmelzen, nicht eine
bestimmte Dichte. Damit ist die Bauform skalenfrei - kein Sonderweg fuer
Setzlinge.
31 % der Cards lagen unter dem Kronenansatz. Die Verschmelzung weitet die Form
um bis zu einen Kugelradius nach unten, der Filter griff aber nur auf den
Zentren. Jetzt auch auf der Huelle - sonst waere der Fehler, gegen den der
Filter gebaut wurde, durch die Hintertuer zurueckgekommen.
### Weniger Blaetter, und warum die ZAHL der richtige Hebel war
Nach der Abnahme wollte der User "etwas weniger Blaetter". Zwei Hebel standen
zur Wahl, beide gemessen (Eiche):
| | Cards | Tris | Blattflaeche je Huellenflaeche |
|---|---|---|---|
| vorher | 381 | 3714 | 10.36 |
| Ziel -15 % | 319 | 3342 | 8.64 |
| Cards -15 % kleiner | 381 | 3714 | 7.93 |
Die Zahl zu senken kostet weniger Deckung UND spart 372 Dreiecke; die Cards zu
verkleinern kostet mehr Deckung (die Flaeche geht quadratisch) und spart kein
einziges. Der woertliche Wunsch war ausserdem der messbar bessere.
### Das Formband gehoert um das Abgenommene, nicht umgekehrt
Nach dem Umbau lag `u/m` bei 0.78-1.02 gegen eine Schranke von 0.82. Die
naheliegende Reaktion waere gewesen, die Krone auf die Zahl zu kalibrieren.
Stattdessen: alle Referenzformen unter der NEUEN Bauform neu durchmessen.
| Form | u/m | o/m |
|---|---|---|
| Eiche | 1.04-1.16 | 0.79-0.91 |
| **abgenommen** | **0.78-1.02** | **0.68-0.79** |
| Trichter | 0.68-0.78 | 1.04-1.14 |
| Pilz | 0.59-0.90 | 0.82-0.95 |
| Haube | 0.94-1.03 | 0.71-0.78 |
**Daraus folgt etwas Unbequemes: `u/m` trennt nichts mehr.** Der abgenommene
Bereich ueberlappt den Pilz und stoesst an den Trichter. Die 0.82 stammten aus
der Einzelkappen-Aera - dagegen zu kalibrieren haette die Krone verbogen, um
eine Zahl zu retten, die ihre Aussagekraft verloren hat. Dieselbe Falle wie beim
Kugel-Kennwert eine Runde zuvor, nur eine Kennzahl weiter.
`o/m` trennt dagegen sauber (abgenommen bis 0.79, Pilz ab 0.82, Trichter ab
1.04) und traegt die Formpruefung jetzt allein. `u/m` wird nur noch
mitgedruckt - ein Kriterium, das die Fehlformen nicht mehr ausschliesst, ist
schlimmer als keines: es sieht aus wie ein Schutz und ist keiner.
### Der Hochstamm muss auf JEDER Stufe stehen ### Der Hochstamm muss auf JEDER Stufe stehen
Bis 1.46 war am Obstbaum nur S4 kalibriert. Im Welt-Test ist der User auf einen Bis 1.46 war am Obstbaum nur S4 kalibriert. Im Welt-Test ist der User auf einen
+1 -1
View File
@@ -1,7 +1,7 @@
schema_version = "1.0.0" schema_version = "1.0.0"
id = "stylized_tree_generator" id = "stylized_tree_generator"
version = "1.47.0" version = "1.48.0"
name = "Stylized Tree Generator" name = "Stylized Tree Generator"
tagline = "Parametrische Baeume, Palmen, Bueschen mit Wachstums-Stufen" tagline = "Parametrische Baeume, Palmen, Bueschen mit Wachstums-Stufen"
maintainer = "D4rkst3r" maintainer = "D4rkst3r"
+3 -3
View File
@@ -50,17 +50,17 @@
<td>34.5KB</td> <td>34.5KB</td>
</tr> </tr>
<tr> <tr>
<td><tt><a href="./stylized_tree_generator-1.47.0.zip?repository=.%2Findex.json&blender_version_min=4.2.0">stylized_tree_generator-1.47.0</a></tt></td> <td><tt><a href="./stylized_tree_generator-1.48.0.zip?repository=.%2Findex.json&blender_version_min=4.2.0">stylized_tree_generator-1.48.0</a></tt></td>
<td>Stylized Tree Generator</td> <td>Stylized Tree Generator</td>
<td>Parametrische Baeume, Palmen, Bueschen mit Wachstums-Stufen</td> <td>Parametrische Baeume, Palmen, Bueschen mit Wachstums-Stufen</td>
<td><a href="https://git.d4rkst3r.de/D4rkst3r/stylized-rock-generator">link</a></td> <td><a href="https://git.d4rkst3r.de/D4rkst3r/stylized-rock-generator">link</a></td>
<td>4.2.0 - ~</td> <td>4.2.0 - ~</td>
<td>all</td> <td>all</td>
<td>all</td> <td>all</td>
<td>53.3KB</td> <td>55.1KB</td>
</tr> </tr>
</table> </table>
<center><p>Built 2026-08-07, 11:33</p></center> <center><p>Built 2026-08-07, 13:38</p></center>
</body> </body>
</html> </html>
+4 -4
View File
@@ -82,7 +82,7 @@
"id": "stylized_tree_generator", "id": "stylized_tree_generator",
"name": "Stylized Tree Generator", "name": "Stylized Tree Generator",
"tagline": "Parametrische Baeume, Palmen, Bueschen mit Wachstums-Stufen", "tagline": "Parametrische Baeume, Palmen, Bueschen mit Wachstums-Stufen",
"version": "1.47.0", "version": "1.48.0",
"type": "add-on", "type": "add-on",
"maintainer": "D4rkst3r", "maintainer": "D4rkst3r",
"license": [ "license": [
@@ -98,9 +98,9 @@
"Mesh", "Mesh",
"Modeling" "Modeling"
], ],
"archive_url": "./stylized_tree_generator-1.47.0.zip", "archive_url": "./stylized_tree_generator-1.48.0.zip",
"archive_size": 54533, "archive_size": 56393,
"archive_hash": "sha256:0c1ba47d4fe89d1c45dbff090d04feaa136bea349cd30386127bc70ab2acd8eb" "archive_hash": "sha256:90b1d48c25a595f0d8c6e0cd63722aa246914998979cbbec4f370b3a9c56a2b9"
} }
] ]
} }
Binary file not shown.
Binary file not shown.
+21 -8
View File
@@ -1,7 +1,7 @@
bl_info = { bl_info = {
"name": "Stylized Tree Generator", "name": "Stylized Tree Generator",
"author": "D4rkst3r", "author": "D4rkst3r",
"version": (1, 47, 0), "version": (1, 48, 0),
"blender": (4, 2, 0), "blender": (4, 2, 0),
"location": "View3D > Sidebar > Tree Gen", "location": "View3D > Sidebar > Tree Gen",
"description": "Parametrischer Baum-/Palmen-/Busch-Generator (Geometry Nodes) mit Wachstums-Stufen", "description": "Parametrischer Baum-/Palmen-/Busch-Generator (Geometry Nodes) mit Wachstums-Stufen",
@@ -1856,11 +1856,24 @@ LEAF_RADIUS_YOUNG = 0.20
# war; jetzt ist sie es nicht mehr. # war; jetzt ist sie es nicht mehr.
# #
# Ziel-Cards Groesse Kronenansatz # Ziel-Cards Groesse Kronenansatz
# Seit der Kronen-Huelle sitzen die Cards auf einer FLAECHE, nicht mehr im
# Volumen - die Zahl bestimmt damit direkter, wie viel Himmel durchscheint.
#
# Nach der Abnahme im Wald wollte der User "etwas weniger Blaetter". Umgesetzt
# als 15 % auf die Ziele. Gemessen an der Eiche: 381 -> 319 Cards, Blattflaeche
# je Huellenflaeche 10.4 -> 8.6, und 372 Tris gespart.
#
# Der Gegenversuch stand zur Wahl und ist gemessen worden: Cards um 15 %
# VERKLEINERN kostet mehr Deckung (10.4 -> 7.9, weil die Flaeche quadratisch
# geht) und spart kein einziges Dreieck. Die Zahl zu senken ist der ehrlichere
# Hebel - und der, den der User woertlich genannt hat.
#
# Ziel-Cards Groesse Kronenansatz
LEAF_STUFEN = ( LEAF_STUFEN = (
(26, 0.24, 0.40), # S1 - EIN Bueschel, Fuss bleibt frei (22, 0.24, 0.40), # S1
(78, 0.46, 0.35), # S2 - drei (66, 0.46, 0.35), # S2
(208, 0.75, 0.30), # S3 - acht (177, 0.75, 0.30), # S3
(390, 1.00, 0.25), # S4 - rund fuenfzehn (330, 1.00, 0.25), # S4
) )
# AUSNAHMEN je Preset: {preset: {stufen_index: ziel_cards}}. # AUSNAHMEN je Preset: {preset: {stufen_index: ziel_cards}}.
@@ -1874,16 +1887,16 @@ LEAF_STUFEN = (
# Das macht die Tabelle preset-abhaengig - bewusst so entschieden, statt das # Das macht die Tabelle preset-abhaengig - bewusst so entschieden, statt das
# Budget fuer alle anzuheben: die Weide ist der Ausreisser, nicht die Regel. # Budget fuer alle anzuheben: die Weide ist der Ausreisser, nicht die Regel.
LEAF_STUFEN_PRESET = { LEAF_STUFEN_PRESET = {
"weide": {3: 350}, "weide": {3: 298},
# Die Birke hat mit 2100 Tris die dickste Rinde im Satz; bei 390 Cards # Die Birke hat mit 2100 Tris die dickste Rinde im Satz; bei 390 Cards
# gemessen 4572 Tris. (4300 - 2100) / 6 = 366 Cards passen, 340 mit Luft # gemessen 4572 Tris. (4300 - 2100) / 6 = 366 Cards passen, 340 mit Luft
# fuer die 15-%-Toleranz der Regelung. # fuer die 15-%-Toleranz der Regelung.
"birke": {3: 340}, "birke": {3: 289},
# Obstbaum: breite offene Krone auf kurzem Stamm gibt viel Zweigflaeche auf # Obstbaum: breite offene Krone auf kurzem Stamm gibt viel Zweigflaeche auf
# wenig Hoehe - ungeregelt 4304-4400 Tris ueber drei Seeds, knapp ueber dem # wenig Hoehe - ungeregelt 4304-4400 Tris ueber drei Seeds, knapp ueber dem
# Budget. Die Regelung haelt eine Toleranz von 15 %, deshalb liegt das Ziel # Budget. Die Regelung haelt eine Toleranz von 15 %, deshalb liegt das Ziel
# unter dem rechnerischen Maximum (497 Cards): 420 x 1.15 x 6 + 1316 = 4214. # unter dem rechnerischen Maximum (497 Cards): 420 x 1.15 x 6 + 1316 = 4214.
"obstbaum": {3: 420}, "obstbaum": {3: 357},
} }
# Card-GROESSE je Preset, als Faktor auf die eingestellte Groesse. # Card-GROESSE je Preset, als Faktor auf die eingestellte Groesse.
+30 -22
View File
@@ -316,26 +316,34 @@ for seed in SEEDS:
# Die Krone muss sich nach OBEN schliessen. Die Eiche, die laut Abnahme als # Die Krone muss sich nach OBEN schliessen. Die Eiche, die laut Abnahme als
# Baum liest, kommt auf 0.90; der Trichter lag bei 1.07. 0.85 als Grenze # Baum liest, kommt auf 0.90; der Trichter lag bei 1.07. 0.85 als Grenze
# laesst Spielraum nach oben, schliesst den Trichter aber sicher aus. # laesst Spielraum nach oben, schliesst den Trichter aber sicher aus.
# Die Grenzen kommen aus einer Messung ALLER Formen mit DIESEM Mass, nicht # Die Grenzen sind unter der KRONEN-HUELLE neu erhoben und um die Form
# aus dem Wunschband - die Streuung von Seed zu Seed ist breiter als das # gelegt, die der User im Wald ABGENOMMEN hat - nicht umgekehrt. Spannen
# Band, das die Spielseite genannt hat (u/m 0.85-0.95). Gemessen ueber neun # ueber neun Seeds, alle mit demselben Mass:
# Seeds: #
# Eiche u/m 1.04-1.15 o/m 0.77-0.88 # Eiche u/m 1.04-1.16 o/m 0.79-0.91
# Trichter u/m 0.66-0.72 o/m 1.18-1.31 # ABGENOMMEN u/m 0.78-1.02 o/m 0.68-0.79
# Haube u/m 0.99-1.13 o/m 0.69-0.80 # Trichter u/m 0.68-0.78 o/m 1.04-1.14
# Pilz u/m 0.75-0.90 o/m 0.78-0.94 # Pilz u/m 0.59-0.90 o/m 0.82-0.95
# Kugel u/m 0.86-1.01 o/m 0.63-0.74 # Haube u/m 0.94-1.03 o/m 0.71-0.78
# Die Schranken trennen die Kugel von Trichter und Pilz; von der Haube #
# trennt sie der Kugel-Kennwert weiter unten. # DARAUS FOLGT ETWAS UNBEQUEMES: u/m trennt unter der neuen Bauform NICHTS
# mehr. Der abgenommene Bereich (0.78-1.02) ueberlappt den Pilz (0.59-0.90)
# und stoesst an den Trichter (bis 0.78). Die fruehere 0.82-Schranke stammt
# aus der Einzelkappen-Aera; haette man dagegen kalibriert, waere die Krone
# verbogen worden, um eine Zahl zu retten, die ihre Aussagekraft verloren
# hat - derselbe Fall wie beim Kugel-Kennwert eine Runde zuvor.
#
# o/m trennt dagegen sauber: abgenommen bis 0.79, Pilz ab 0.82, Trichter ab
# 1.04. Diese eine Schranke traegt die Formpruefung, und der Kugel-Kennwert
# weiter unten trennt zusaetzlich von der Haube.
if om > 0.80: if om > 0.80:
fails.append("Seed %d: Krone oben %.1f m breit, in der Mitte %.1f " fails.append("Seed %d: Krone oben %.1f m breit, in der Mitte %.1f "
"(%.2f) - sie schliesst sich oben nicht (Trichter lag bei " "(%.2f) - abgenommen ist bis 0.79, darueber liegen Pilz "
"1.18-1.31)" % (seed, profil[2], profil[1], om)) "(ab 0.82) und Trichter (ab 1.04)"
if um < 0.82: % (seed, profil[2], profil[1], om))
fails.append("Seed %d: Krone unten %.1f m breit, in der Mitte %.1f " # u/m wird nur noch MITGEDRUCKT. Ein Kriterium, das die Fehlformen nicht
"(%.2f) - unten zu schmal, das wird ein Pilz bzw. ein " # mehr ausschliesst, ist schlimmer als keines: es sieht aus wie ein Schutz
"Trichter (0.66-0.90)" # und ist keiner.
% (seed, profil[0], profil[1], um))
if kugel > EICHE_KUGEL * 0.65: if kugel > EICHE_KUGEL * 0.65:
fails.append("Seed %d: Kugel-Kennwert %.2f, Eiche %.2f (%.0f %%) - der " fails.append("Seed %d: Kugel-Kennwert %.2f, Eiche %.2f (%.0f %%) - der "
"Obstbaum muss die RUNDESTE Art bleiben, Richtwert <= 65 %%" "Obstbaum muss die RUNDESTE Art bleiben, Richtwert <= 65 %%"
@@ -431,14 +439,14 @@ for _k, _x in enumerate(_st, 1):
print("") print("")
print("Kronenradius/Card ueber alle Seeds: %.2f - %.2f" % (min(verh), max(verh))) print("Kronenradius/Card ueber alle Seeds: %.2f - %.2f" % (min(verh), max(verh)))
print("Krone unten/mitte ueber alle Seeds: %.2f - %.2f (Pilz 0.75-0.90, " print("Krone unten/mitte ueber alle Seeds: %.2f - %.2f (nur Info - trennt "
"Trichter 0.66-0.72)" % (min(untenmitte), max(untenmitte))) "unter der Huelle nichts mehr)" % (min(untenmitte), max(untenmitte)))
print("Kugel (KronH/KronB) ueber alle Seeds: %.2f - %.2f, Eiche %.2f " print("Kugel (KronH/KronB) ueber alle Seeds: %.2f - %.2f, Eiche %.2f "
"(%.0f-%.0f %% - Vorgabe <= 65 %%)" "(%.0f-%.0f %% - Vorgabe <= 65 %%)"
% (min(kugeln), max(kugeln), EICHE_KUGEL, % (min(kugeln), max(kugeln), EICHE_KUGEL,
100 * min(kugeln) / EICHE_KUGEL, 100 * max(kugeln) / EICHE_KUGEL)) 100 * min(kugeln) / EICHE_KUGEL, 100 * max(kugeln) / EICHE_KUGEL))
print("Krone oben/mitte ueber alle Seeds: %.2f - %.2f (Trichter 1.18-1.31)" print("Krone oben/mitte ueber alle Seeds: %.2f - %.2f (Pilz ab 0.82, "
% (min(obenmitte), max(obenmitte))) "Trichter ab 1.04)" % (min(obenmitte), max(obenmitte)))
print("Kronen-Deckung ueber alle Seeds: %.1f - %.1f m2/m3, Eiche %.1f " print("Kronen-Deckung ueber alle Seeds: %.1f - %.1f m2/m3, Eiche %.1f "
"(%.0f-%.0f %%)" "(%.0f-%.0f %%)"
% (min(deckungen), max(deckungen), EICHE, % (min(deckungen), max(deckungen), EICHE,