diff --git a/internal/geom/geom.go b/internal/geom/geom.go index 034bb23..db77cf3 100644 --- a/internal/geom/geom.go +++ b/internal/geom/geom.go @@ -1,3 +1,20 @@ package geom -//init +import "math" + +const EPS = 1e-6 + +type Vec struct { + X, Y float64 +} + +type Seg struct { + A, B Vec +} + +func V(x, y float64) Vec { return Vec{x, y} } +func Sub(a, b Vec) Vec { return Vec{a.X - b.X, a.Y - b.Y} } +func Dot(a, b Vec) float64 { return a.X*b.X + a.Y*b.Y } +func Cross(a, b Vec) float64 { return a.X*b.Y - a.Y*b.X } +func Len(a Vec) float64 { return math.Hypot(a.X, a.Y) } +func NearlyZero(x float64) bool { return math.Abs(x) < EPS } diff --git a/main.go b/main.go index 370e405..b7e7d6d 100644 --- a/main.go +++ b/main.go @@ -1,6 +1,7 @@ package main import ( + "bspviz/internal/geom" "bspviz/internal/mapfmt" "bspviz/internal/wad" "flag" @@ -19,6 +20,7 @@ func main() { info := flag.Bool("info", false, "Roh-Infos zur Map (Counts von VERTEXES/LINEDEFS)") extract := flag.String("extract", "", "Kommagetrennte Lump-Namen aus der Map extrahieren (z.B. VERTEXES,LINEDEFS)") outdir := flag.String("out", ".", "Zielordner für -extract") + geomtest := flag.Bool("geomtest", false, "Geometrie-Check: Segmente/AABB/Probe-Split ausgeben") flag.Parse() if *wadPath == "" { @@ -100,4 +102,58 @@ func main() { fmt.Printf("wrote %s (%d bytes)\n", dst, len(data)) } } + + // Zum debug test der geo functions + if *geomtest { + raw, err := w.LoadMapLumps(*mapMarker, "VERTEXES", "LINEDEFS") + if err != nil { + log.Fatalf("load map lumps: %v", err) + } + m, err := mapfmt.LoadMap(raw) + if err != nil { + log.Fatalf("parse map: %v", err) + } + + segs := mapfmt.LinedefsToSegs(m.Vertices, m.Linedefs) + fmt.Printf("GEOM: vertices=%d linedefs=%d segs=%d\n", len(m.Vertices), len(m.Linedefs), len(segs)) + if len(segs) == 0 { + fmt.Println("GEOM: keine Segmente gefunden – prüfe LINEDEFS/VERTEXES") + return + } + + pts := make([]geom.Vec, 0, len(m.Vertices)) + for _, v := range m.Vertices { + pts = append(pts, geom.V(float64(v.X), float64(v.Y))) + } + bb := geom.Bounds(pts) + w := bb.Max.X - bb.Min.X + h := bb.Max.Y - bb.Min.Y + fmt.Printf("AABB: min=(%.1f,%.1f) max=(%.1f,%.1f) size=(%.1f×%.1f)\n", + bb.Min.X, bb.Min.Y, bb.Max.X, bb.Max.Y, w, h) + + O := segs[0].A + D := geom.Sub(segs[0].B, segs[0].A) + if geom.Len(D) < 1e-9 && len(segs) > 1 { + O = segs[1].A + D = geom.Sub(segs[1].B, segs[1].A) + } + var left, right, splits, degens int + for _, s := range segs { + f, b := geom.SplitSeg(s, O, D) + if len(f) == 0 && len(b) == 0 { + degens++ + continue + } + left += len(f) + right += len(b) + if len(f) > 0 && len(b) > 0 { + splits++ + } + } + fmt.Printf("PROBE-SPLIT: O=(%.1f,%.1f) D=(%.1f,%.1f)\n", O.X, O.Y, D.X, D.Y) + fmt.Printf("PROBE-SPLIT: left=%d right=%d splits=%d degens=%d (EPS=%.1e)\n", + left, right, splits, degens, geom.EPS) + + return + } }