From 7d10f1d2a9610ffacb09c0a530e88b011fe56867 Mon Sep 17 00:00:00 2001 From: Boki Date: Mon, 16 Feb 2026 14:41:15 -0500 Subject: [PATCH] work no minimap --- src/Poe2Trade.Navigation/MinimapCapture.cs | 7 +++-- src/Poe2Trade.Navigation/NavigationTypes.cs | 6 +++- src/Poe2Trade.Navigation/PathFinder.cs | 29 +++++++++++++++++- src/Poe2Trade.Navigation/WorldMap.cs | 33 +++++++++++++++++++++ 4 files changed, 70 insertions(+), 5 deletions(-) diff --git a/src/Poe2Trade.Navigation/MinimapCapture.cs b/src/Poe2Trade.Navigation/MinimapCapture.cs index 9f7d444..764e3b7 100644 --- a/src/Poe2Trade.Navigation/MinimapCapture.cs +++ b/src/Poe2Trade.Navigation/MinimapCapture.cs @@ -205,8 +205,9 @@ public class MinimapCapture : IFrameConsumer, IDisposable private Mat BuildWallMask(Mat hsv, Mat playerMask, bool sample = false) { - var lo = _colorTracker.AdaptedLo ?? _config.WallLoHSV; - var hi = _colorTracker.AdaptedHi ?? _config.WallHiHSV; + var isCorner = _detectedMode == MinimapMode.Corner; + var lo = isCorner ? _config.CornerWallLoHSV : (_colorTracker.AdaptedLo ?? _config.WallLoHSV); + var hi = isCorner ? _config.CornerWallHiHSV : (_colorTracker.AdaptedHi ?? _config.WallHiHSV); var wallMask = new Mat(); Cv2.InRange(hsv, lo, hi, wallMask); @@ -215,7 +216,7 @@ public class MinimapCapture : IFrameConsumer, IDisposable Cv2.BitwiseNot(playerMask, notPlayer); Cv2.BitwiseAnd(wallMask, notPlayer, wallMask); - if (sample) + if (sample && !isCorner) _colorTracker.SampleFrame(hsv, wallMask); using var kernel = Cv2.GetStructuringElement(MorphShapes.Ellipse, new Size(3, 3)); diff --git a/src/Poe2Trade.Navigation/NavigationTypes.cs b/src/Poe2Trade.Navigation/NavigationTypes.cs index 610ebb5..02ca91e 100644 --- a/src/Poe2Trade.Navigation/NavigationTypes.cs +++ b/src/Poe2Trade.Navigation/NavigationTypes.cs @@ -98,11 +98,15 @@ public class MinimapConfig public Scalar PlayerLoHSV { get; set; } = new(5, 80, 80); public Scalar PlayerHiHSV { get; set; } = new(25, 255, 255); - // Wall detection: target #A2AEE5 (blue-lavender structure lines) + // Wall detection (overlay): target #A2AEE5 (blue-lavender structure lines) // HSV(115, 75, 229) — blue hue, low-medium saturation, bright public Scalar WallLoHSV { get; set; } = new(110, 25, 190); public Scalar WallHiHSV { get; set; } = new(136, 120, 255); + // Wall detection (corner): wider V range for faded walls + public Scalar CornerWallLoHSV { get; set; } = new(110, 25, 100); + public Scalar CornerWallHiHSV { get; set; } = new(136, 120, 255); + // Connected components: minimum area to keep (kills speckle) public int WallMinArea { get; set; } = 30; diff --git a/src/Poe2Trade.Navigation/PathFinder.cs b/src/Poe2Trade.Navigation/PathFinder.cs index 5a77691..77b623f 100644 --- a/src/Poe2Trade.Navigation/PathFinder.cs +++ b/src/Poe2Trade.Navigation/PathFinder.cs @@ -3,11 +3,24 @@ using Serilog; namespace Poe2Trade.Navigation; +/// +/// Last BFS result for visualization. +/// +internal record BfsResult( + List BestFrontier, // frontier cells in the chosen direction (canvas coords) + List OtherFrontier, // frontier cells in other directions (canvas coords) + double DirX, double DirY, // chosen direction (unit vector) + int PlayerCx, int PlayerCy // player position on canvas +); + /// /// BFS pathfinding through the world map canvas. Pure function — reads canvas, never modifies it. /// internal class PathFinder { + /// Last BFS result for viewport overlay. + public BfsResult? LastResult { get; private set; } + /// /// BFS through walkable (Explored) cells to find the best frontier direction. /// Instead of stopping at the nearest frontier, runs the full BFS and counts @@ -40,9 +53,10 @@ internal class PathFinder ReadOnlySpan dxs = [-1, 0, 1, -1, 1, -1, 0, 1]; ReadOnlySpan dys = [-1, -1, -1, 0, 0, 1, 1, 1]; - // Count frontier cells per first-step direction + // Count frontier cells per first-step direction, and collect positions var frontierCounts = new Dictionary(); var firstStepCoords = new Dictionary(); + var frontierByKey = new Dictionary>(); while (queue.Count > 0) { @@ -71,7 +85,9 @@ internal class PathFinder { frontierCounts[fsKey] = 1; firstStepCoords[fsKey] = (firstStepX[cellIdx], firstStepY[cellIdx]); + frontierByKey[fsKey] = []; } + frontierByKey[fsKey].Add(new Point(wx, wy)); break; // don't double-count this cell } } @@ -114,6 +130,7 @@ internal class PathFinder if (frontierCounts.Count == 0) { Log.Information("BFS: no reachable frontier within {Radius}px", searchRadius); + LastResult = null; return null; } @@ -138,6 +155,16 @@ internal class PathFinder dirX /= len; dirY /= len; + // Store result for visualization + var bestFrontier = frontierByKey[bestKey]; + var otherFrontier = new List(); + foreach (var (key, pts) in frontierByKey) + { + if (key != bestKey) + otherFrontier.AddRange(pts); + } + LastResult = new BfsResult(bestFrontier, otherFrontier, dirX, dirY, cx, cy); + Log.Debug("BFS: {DirCount} directions, best={Best} frontier cells, dir=({Dx:F2},{Dy:F2})", frontierCounts.Count, bestCount, dirX, dirY); return (dirX, dirY); diff --git a/src/Poe2Trade.Navigation/WorldMap.cs b/src/Poe2Trade.Navigation/WorldMap.cs index 1fe21ec..3d545c5 100644 --- a/src/Poe2Trade.Navigation/WorldMap.cs +++ b/src/Poe2Trade.Navigation/WorldMap.cs @@ -459,6 +459,39 @@ public class WorldMap : IDisposable colored.Set(r, c, new Vec3b(55, 40, 28)); } + // BFS overlay: frontier cells + direction line + var bfs = _pathFinder.LastResult; + if (bfs != null) + { + // Other frontier directions (dim cyan) + foreach (var pt in bfs.OtherFrontier) + { + var vx = pt.X - x0; + var vy = pt.Y - y0; + if (vx >= 0 && vx < viewSize && vy >= 0 && vy < viewSize) + colored.Set(vy, vx, new Vec3b(100, 80, 0)); + } + + // Best frontier direction (bright green) + foreach (var pt in bfs.BestFrontier) + { + var vx = pt.X - x0; + var vy = pt.Y - y0; + if (vx >= 0 && vx < viewSize && vy >= 0 && vy < viewSize) + colored.Set(vy, vx, new Vec3b(0, 220, 0)); + } + + // Direction line from player + var px2 = bfs.PlayerCx - x0; + var py2 = bfs.PlayerCy - y0; + var lineLen = 60; + var ex = (int)(px2 + bfs.DirX * lineLen); + var ey = (int)(py2 + bfs.DirY * lineLen); + Cv2.ArrowedLine(colored, new Point(px2, py2), new Point(ex, ey), + new Scalar(0, 220, 0), 2, tipLength: 0.3); + } + + // Player dot (orange, on top) var px = cx - x0; var py = cy - y0; if (px >= 0 && px < viewSize && py >= 0 && py < viewSize)