Tree Gen 1.41.0: Obstbaum-Kugelkrone (Lollipop) ueber den Kronenansatz
Zielbild der Spielseite ist der Lollipop der stilisierten Vektor-Illustration. Der Weg dorthin fuehrt NICHT ueber mehr Baumhoehe (4.9 m sind die Ernte-Reichweite), sondern ueber einen tieferen Kronenansatz: 39 % -> 29 %, Stamm 1.9 -> 1.5 m. Die Krone wird dadurch von selbst hoeher (3.8 -> 4.3 m). Dazu Crown Taper 0.15 -> 0.35, Crown Bulge 1.1 -> 1.5, Branch Droop 0.4 -> 0.25. Gemessen ueber alle neun Produktions-Seeds: Kronenansatz 29 %, unten/mitte 0.86-1.01, oben/mitte 0.63-0.74, Kugel 1.35-1.47, Kronenradius 2.00-2.15 m, Deckung 81-103 % der Eiche, Hoehe 4.90 m. Das Messen war schwieriger als das Einstellen; zwei eigene Fehler, beide vor der Abnahme gefunden: 1) Die Kronenbreite je Drittel als MAXIMUM ueber die Card-Punkte zu messen haengt an EINER Card. Unten/mitte sprang je Seed zwischen 0.89 und 1.00 bei stabilem Mittelwert 0.94 - Rauschen, keine Form. Mit dem 90. PERZENTIL wurde es stabil und zeigte sofort etwas anderes: die Krone war unten tatsaechlich am breitesten (1.04), was das Maximum verdeckt hatte. 2) Der Kugel-Kennwert bekam erst die Schranke 0.88 - eine Zahl aus einem Messskript mit anderer Breitendefinition. Mit der Test-Formel liegen die Werte um 1.4, die Schranke haette alles durchgelassen. Zum zweiten Mal dieselbe Falle nach der Deckungs-Schwelle. Deshalb sind jetzt ALLE Referenzformen mit demselben Mass gemessen und stehen als Tabelle im Test (Eiche, Trichter, Haube, Pilz, Kugel). Die Tabelle zeigt auch, was NICHT trennt: der Kugel-Kennwert unterscheidet Kugel und Haube nicht (1.35-1.47 gegen 1.26-1.44) - das tut der Kronenansatz, und der wird geprueft. Die Kugel-Schranke bleibt als zweites Netz gegen Trichter und Pilz drin, mit genau diesem Vermerk. Das Wunschband der Spielseite (u/m 0.85-0.95) ist schmaler als die Streuung von Seed zu Seed (0.86-1.01). Die Schranken kommen deshalb aus der Messung aller Formen, nicht aus dem Band. Gegenproben: Haube 9 Fehler (Kronenansatz), Trichter 37 (alle vier Kriterien). 26 Tests bestehen. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
+63
-13
@@ -10,8 +10,8 @@ Deshalb ist das hier KEIN Silhouetten-Test mit Geschmacksurteil, sondern eine
|
||||
funktionale Bedingung: Kronenradius > Card-Groesse.
|
||||
|
||||
Vorgaben der Spielseite, die mitgeprueft werden:
|
||||
Kronenansatz 35-40 %, Kronenradius S4 >= 1.8 m, Hoehe 4-5 m,
|
||||
Breitenprofil (die Krone muss sich nach oben schliessen),
|
||||
Kronenansatz ~30 %, Kronenradius S4 >= 1.8 m, Hoehe 4-5 m,
|
||||
Breitenprofil + Kugel-Kennwert (Lollipop: Kronenhoehe ~ Kronenbreite),
|
||||
Deckung gegen die Eiche.
|
||||
B/H gilt fuer dieses Preset NICHT - siehe Kommentar unten.
|
||||
|
||||
@@ -136,6 +136,8 @@ print("%-6s %7s %6s %9s %9s %7s %8s %-15s %s"
|
||||
verh = []
|
||||
deckungen = []
|
||||
obenmitte = []
|
||||
untenmitte = []
|
||||
kugeln = []
|
||||
for seed in SEEDS:
|
||||
for o in list(bpy.context.scene.objects):
|
||||
if o is not card:
|
||||
@@ -203,12 +205,36 @@ for seed in SEEDS:
|
||||
pz0, pz1 = min(pz), max(pz)
|
||||
drittel = (pz1 - pz0) / 3.0
|
||||
for kk in range(3):
|
||||
teil = [p for p in blatt_pts
|
||||
teil = [math.hypot(p.x, p.y) 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)
|
||||
# 90. PERZENTIL statt Maximum. Das Maximum haengt an EINER Card:
|
||||
# bei ~400 Cards von 1.25 m Diagonale reicht eine einzige weit
|
||||
# aussen haengende, um die Breite eines Drittels zu setzen.
|
||||
# Gemessen sprang unten/mitte dadurch je Seed zwischen 0.89 und
|
||||
# 1.00, waehrend der Mittelwert stabil bei 0.94 lag - das war
|
||||
# Rauschen, keine Formabweichung. Das Perzentil misst, wo die
|
||||
# Laubmasse endet, nicht wo die letzte Card haengt.
|
||||
teil.sort()
|
||||
profil[kk] = 2 * (teil[int(0.9 * (len(teil) - 1))] if teil else 0.0)
|
||||
om = profil[2] / profil[1] if profil[1] else 0.0
|
||||
um = profil[0] / profil[1] if profil[1] else 0.0
|
||||
# KUGEL-Kennwert: Kronenhoehe geteilt durch die groesste Kronenbreite.
|
||||
#
|
||||
# Er steht hier als zweites Netz gegen Trichter (0.98-1.12) und Pilz
|
||||
# (1.05-1.17) - und weil die Spielseite "Hoehe ~ Breite" als Zielbild
|
||||
# genannt hat, gehoert die Zahl sichtbar ins Protokoll.
|
||||
# Er trennt die Kugel (1.35-1.47) aber NICHT von der Haube (1.26-1.44):
|
||||
# beide Formen unterscheiden sich vor allem im KRONENANSATZ (29 % gegen
|
||||
# 39 %), und den prueft der Check weiter unten. Ein erster Anlauf setzte
|
||||
# die Grenze auf 0.88 - eine Zahl aus einer anderen Messung, die hier bei
|
||||
# Werten um 1.4 alles durchgelassen haette.
|
||||
kugel = 0.0
|
||||
if blatt_pts and max(profil) > 0:
|
||||
pz = [p.z for p in blatt_pts]
|
||||
kugel = (max(pz) - min(pz)) / max(profil)
|
||||
kugeln.append(kugel)
|
||||
obenmitte.append(om)
|
||||
untenmitte.append(um)
|
||||
|
||||
v = kron_r / card_max if card_max else 0.0
|
||||
verh.append(v)
|
||||
@@ -245,10 +271,30 @@ for seed in SEEDS:
|
||||
# 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:
|
||||
# Die Grenzen kommen aus einer Messung ALLER Formen mit DIESEM Mass, nicht
|
||||
# aus dem Wunschband - die Streuung von Seed zu Seed ist breiter als das
|
||||
# Band, das die Spielseite genannt hat (u/m 0.85-0.95). Gemessen ueber neun
|
||||
# Seeds:
|
||||
# Eiche u/m 1.04-1.15 o/m 0.77-0.88
|
||||
# Trichter u/m 0.66-0.72 o/m 1.18-1.31
|
||||
# Haube u/m 0.99-1.13 o/m 0.69-0.80
|
||||
# Pilz u/m 0.75-0.90 o/m 0.78-0.94
|
||||
# Kugel u/m 0.86-1.01 o/m 0.63-0.74
|
||||
# Die Schranken trennen die Kugel von Trichter und Pilz; von der Haube
|
||||
# trennt sie der Kugel-Kennwert weiter unten.
|
||||
if om > 0.80:
|
||||
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))
|
||||
"(%.2f) - sie schliesst sich oben nicht (Trichter lag bei "
|
||||
"1.18-1.31)" % (seed, profil[2], profil[1], om))
|
||||
if um < 0.82:
|
||||
fails.append("Seed %d: Krone unten %.1f m breit, in der Mitte %.1f "
|
||||
"(%.2f) - unten zu schmal, das wird ein Pilz bzw. ein "
|
||||
"Trichter (0.66-0.90)"
|
||||
% (seed, profil[0], profil[1], um))
|
||||
if kugel < 1.20:
|
||||
fails.append("Seed %d: Kronenhoehe/-breite %.2f - flacher als Trichter "
|
||||
"(0.98-1.12) und Pilz (1.05-1.17) zulassen"
|
||||
% (seed, kugel))
|
||||
|
||||
# DIE funktionale Bedingung.
|
||||
if v < 1.3:
|
||||
@@ -260,9 +306,9 @@ for seed in SEEDS:
|
||||
if not (4.0 <= hoehe <= 5.2):
|
||||
fails.append("Seed %d: Hoehe %.2f m, Vorgabe 4-5 m (5.2 als Toleranz)"
|
||||
% (seed, hoehe))
|
||||
if not (33.0 <= ansatz <= 45.0):
|
||||
fails.append("Seed %d: Kronenansatz %.0f %%, Vorgabe 35-40 %% "
|
||||
"(33-45 als Toleranz)" % (seed, ansatz))
|
||||
if not (25.0 <= ansatz <= 35.0):
|
||||
fails.append("Seed %d: Kronenansatz %.0f %%, Vorgabe ~30 %% "
|
||||
"(25-35 als Toleranz)" % (seed, ansatz))
|
||||
|
||||
# B/H gilt fuer dieses Preset NICHT MEHR - Entscheidung der Spielseite,
|
||||
# 2026-08-06. Es wird nur noch mitgedruckt.
|
||||
@@ -282,8 +328,12 @@ for seed in SEEDS:
|
||||
# Pilzform (unten/mitte 1.17) durchgelassen.
|
||||
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("Krone unten/mitte ueber alle Seeds: %.2f - %.2f (Pilz 0.75-0.90, "
|
||||
"Trichter 0.66-0.72)" % (min(untenmitte), max(untenmitte)))
|
||||
print("Kugel (KronH/KronB) ueber alle Seeds: %.2f - %.2f (Trichter 0.98-1.12, "
|
||||
"Pilz 1.05-1.17, Haube 1.26-1.44)" % (min(kugeln), max(kugeln)))
|
||||
print("Krone oben/mitte ueber alle Seeds: %.2f - %.2f (Trichter 1.18-1.31)"
|
||||
% (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