Tree Gen 1.40.0: Obstbaum-Krone schliesst sich oben (Trichter behoben)
Der Baum erfuellte Kronenradius, Deckung, Kronenansatz und Tri-Budget - und sah trotzdem falsch aus. Sichtbar wurde es erst am BREITENPROFIL der Krone in Dritteln (unten/mitte/oben, Messung der Spielseite nachgestellt): Eiche 3.0 / 2.8 / 2.6 oben/mitte 0.90 (liest sich als Baum) Obstbaum 3.3 / 4.5 / 4.7 oben/mitte 1.07 (Trichter) Kein einzelner Regler hat das geloest: Crown Taper (-0.10 bis +0.50), Branch Droop (0.6-1.2), Crown Bulge (1.0-1.8) und Attraction Up einzeln durchgefahren liessen oben/mitte bei rund 1.0 stehen. Der Grund ist strukturell: die Kronenform folgt nicht der Astlaenge je Hoehe, sondern dem WEG DER ASTSPITZEN. Solange die Aeste aufwaerts schwingen, landet das aeusserste Laub oben. Loesung ist eine andere Bauform, kein Feintuning - kurze Aeste an einem hohen Stamm statt langer Aeste an einem kurzen: Height 3.8 -> 4.9, Branch Length 2.55 -> 1.25, Branch Start 0.52 -> 0.40, Attraction Up +0.40 -> -0.05, Crown Taper -0.30 -> +0.15, Crown Bulge 0.60 -> 1.10, Branch Droop 0.35 -> 0.40. Ueber alle neun Produktions-Seeds: oben/mitte 0.63-0.84, Kronenradius 1.88-2.01 m, Deckung 100-134 % der Eiche, 3752-4166 Tris, Ansatz 39 %. Beim Einregeln kippte die Form zwischendurch in eine PILZform (unten am breitesten) - deshalb steht das Profil jetzt als Test da. test_obstbaum prueft oben/mitte <= 0.85. Gegenprobe mit den 1.39er Werten: neun Fehler bei 0.98-1.11. B/H liegt jetzt bei 0.77-0.82 (Band der Spielseite 0.55-0.75). Bleibt bewusst ungeprueft, wie beim Kronenradius entschieden: die Vorgaben Kronenradius >= 1.80 und B/H <= 0.75 sind bei 4-5 m Hoehe nur im Mittel gleichzeitig erfuellbar. 26 Tests bestehen. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
+38
-6
@@ -127,12 +127,13 @@ print("")
|
||||
# Birne 3/17/24. Ein Preset, das nur bei einem Seed passt, ist keines.
|
||||
SEEDS = (1, 15, 22, 2, 16, 23, 3, 17, 24)
|
||||
|
||||
print("%-6s %7s %6s %9s %9s %9s %7s %9s"
|
||||
% ("Seed", "Hoehe", "B/H", "KronR", "Card-Max", "KronR/Card", "Ansatz",
|
||||
"m2/m3"))
|
||||
print("%-6s %7s %6s %9s %9s %7s %8s %-15s %s"
|
||||
% ("Seed", "Hoehe", "B/H", "KronR", "KronR/Cd", "Ansatz", "m2/m3",
|
||||
"Profil u/m/o", "o/m"))
|
||||
|
||||
verh = []
|
||||
deckungen = []
|
||||
obenmitte = []
|
||||
for seed in SEEDS:
|
||||
for o in list(bpy.context.scene.objects):
|
||||
if o is not card:
|
||||
@@ -172,6 +173,7 @@ for seed in SEEDS:
|
||||
ev = bl.evaluated_get(dg)
|
||||
m2 = ev.to_mesh()
|
||||
blatt_flaeche = sum(p.area for p in m2.polygons)
|
||||
blatt_pts = [v.co.copy() for v in m2.vertices]
|
||||
mitten = []
|
||||
for grp in inseln(m2):
|
||||
pts = [m2.vertices[i].co for i in grp]
|
||||
@@ -186,13 +188,33 @@ for seed in SEEDS:
|
||||
lz = [z for _x, _y, z in mitten]
|
||||
kron_zyl = math.pi * lr ** 2 * (max(lz) - min(lz))
|
||||
|
||||
# BREITENPROFIL der Krone in Dritteln.
|
||||
#
|
||||
# Ohne diesen Check kann die Krone alle bisherigen Zahlen erfuellen und
|
||||
# trotzdem falsch aussehen: der erste Obstbaum war ein TRICHTER - nach oben
|
||||
# breiter, unten hohl (gemessen oben/mitte 1.07 gegen 0.90 der Eiche). Die
|
||||
# Laubmasse sass an den top-aussen endenden Astspitzen. Kronenradius,
|
||||
# Deckung und Tri-Zahl waren dabei alle in Ordnung.
|
||||
profil = [0.0, 0.0, 0.0]
|
||||
if blatt_pts:
|
||||
pz = [p.z for p in blatt_pts]
|
||||
pz0, pz1 = min(pz), max(pz)
|
||||
drittel = (pz1 - pz0) / 3.0
|
||||
for kk in range(3):
|
||||
teil = [p for p in blatt_pts
|
||||
if pz0 + kk * drittel <= p.z <= pz0 + (kk + 1) * drittel]
|
||||
profil[kk] = 2 * max((math.hypot(p.x, p.y) for p in teil),
|
||||
default=0.0)
|
||||
om = profil[2] / profil[1] if profil[1] else 0.0
|
||||
obenmitte.append(om)
|
||||
|
||||
v = kron_r / card_max if card_max else 0.0
|
||||
verh.append(v)
|
||||
deckung = blatt_flaeche / kron_zyl if kron_zyl else 0.0
|
||||
deckungen.append(deckung)
|
||||
print("%-6d %7.2f %6.2f %9.2f %9.2f %9.2f %6.0f%% %9.1f"
|
||||
% (seed, hoehe, 2 * kron_r / hoehe, kron_r, card_max, v, ansatz,
|
||||
deckung))
|
||||
print("%-6d %7.2f %6.2f %9.2f %9.2f %6.0f%% %8.1f %.1f/%.1f/%.1f %.2f"
|
||||
% (seed, hoehe, 2 * kron_r / hoehe, kron_r, v, ansatz, deckung,
|
||||
profil[0], profil[1], profil[2], om))
|
||||
|
||||
# Kronen-DECKUNG: Blattflaeche je m3 Kronenvolumen.
|
||||
#
|
||||
@@ -218,6 +240,14 @@ for seed in SEEDS:
|
||||
"Ast-Schlaeuche" % (seed, deckung, EICHE,
|
||||
100 * deckung / EICHE))
|
||||
|
||||
# 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
|
||||
# laesst Spielraum nach oben, schliesst den Trichter aber sicher aus.
|
||||
if om > 0.85:
|
||||
fails.append("Seed %d: Krone oben %.1f m breit, in der Mitte %.1f "
|
||||
"(%.2f) - sie wird nach oben breiter statt sich zu "
|
||||
"schliessen" % (seed, profil[2], profil[1], om))
|
||||
|
||||
# DIE funktionale Bedingung.
|
||||
if v < 1.3:
|
||||
fails.append("Seed %d: Kronenradius %.2f m bei %.2f m Card - die Krone "
|
||||
@@ -241,6 +271,8 @@ for seed in SEEDS:
|
||||
# funktionale (Kronenradius), weil an ihr die Frucht-Streuung haengt.
|
||||
print("")
|
||||
print("Kronenradius/Card ueber alle Seeds: %.2f - %.2f" % (min(verh), max(verh)))
|
||||
print("Krone oben/mitte ueber alle Seeds: %.2f - %.2f (Eiche 0.90, "
|
||||
"Trichter war 1.07)" % (min(obenmitte), max(obenmitte)))
|
||||
print("Kronen-Deckung ueber alle Seeds: %.1f - %.1f m2/m3, Eiche %.1f "
|
||||
"(%.0f-%.0f %%)"
|
||||
% (min(deckungen), max(deckungen), EICHE,
|
||||
|
||||
Reference in New Issue
Block a user