j138 draw-only: yellow triangle (enemy-heading other point, enemy, us) in the geometry overlay
This commit is contained in:
@@ -12,7 +12,15 @@
|
||||
## through a point that is ON the circle meets it twice — the bot itself and
|
||||
## ONE OTHER point — and the OTHER point is drawn visually distinct (that is
|
||||
## the one worth looking at). A tangent line's two points coincide; we draw
|
||||
## what the maths gives.
|
||||
## what the maths gives;
|
||||
## * the TRIANGLE whose corners are the ENEMY heading line's OTHER
|
||||
## intersection, the enemy, and our bot — three vertices the rest of the
|
||||
## overlay already computes. Drawn YELLOW (#FFFF00), stroke width 1.5,
|
||||
## with a small yellow hollow ring (r=6) on each distinct corner, so it is
|
||||
## not confused with the grey circle / cyan / orange heading lines. A
|
||||
## zero-length edge (a tangent enemy heading puts corner 1 on top of
|
||||
## corner 2; or corner 1 on top of corner 3 when the enemy heading points
|
||||
## straight at us) is SKIPPED rather than emitted as a degenerate line.
|
||||
##
|
||||
## Env knobs (read once at boot by ModularBot, registered in env_report.nim):
|
||||
## TR_GEO_DEBUG presence/1 = on. default OFF.
|
||||
@@ -98,11 +106,13 @@ proc lineCircleIntersections*(px, py, headingDeg: float,
|
||||
|
||||
type
|
||||
GeoPrimKind* = enum
|
||||
gpCircle ## the diameter circle outline
|
||||
gpLineSelf ## line along OUR heading
|
||||
gpLineEnemy ## line along the ENEMY heading
|
||||
gpMarkSelf ## intersection that coincides with the bot (hollow ring)
|
||||
gpMarkOther ## the OTHER intersection (filled, distinct)
|
||||
gpCircle ## the diameter circle outline
|
||||
gpLineSelf ## line along OUR heading
|
||||
gpLineEnemy ## line along the ENEMY heading
|
||||
gpMarkSelf ## intersection that coincides with the bot (hollow ring)
|
||||
gpMarkOther ## the OTHER intersection (filled, distinct)
|
||||
gpTriangleEdge ## one edge of the enemy-heading triangle
|
||||
gpTriangleCorner ## a DISTINCT corner of that triangle (hollow ring)
|
||||
|
||||
GeoPrim* = object
|
||||
kind*: GeoPrimKind
|
||||
@@ -117,11 +127,17 @@ const
|
||||
GeoEnemyLineColor* = "#FF8000" # orange— ENEMY heading line
|
||||
GeoSelfMarkColor* = "#FFFFFF" # white — the bot itself (hollow ring)
|
||||
GeoOtherMarkColor* = "#FF00FF" # magenta — the OTHER intersection (filled)
|
||||
GeoTriangleColor* = "#FFFF00" # yellow — the requested triangle (edges+corner rings)
|
||||
GeoCircleWidth* = 1.0
|
||||
GeoLineWidth* = 1.0
|
||||
GeoMarkWidth* = 1.5
|
||||
GeoTriangleWidth* = 1.5
|
||||
GeoSelfMarkRadius* = 4.0
|
||||
GeoOtherMarkRadius* = 4.0
|
||||
GeoTriangleCornerRadius* = 6.0
|
||||
GeoZeroLen* = 1e-6
|
||||
## Below this two triangle corners are the SAME point: the edge between
|
||||
## them is degenerate (skipped) and they share a single corner ring.
|
||||
GeoLineMargin* = 10.0
|
||||
## Extra length (px) the heading segment extends beyond the far
|
||||
## intersection; a segment of half-length 2r + margin always contains both
|
||||
@@ -157,6 +173,36 @@ proc headingSegment(px, py, headingDeg, halfLen: float): tuple[x1, y1, x2, y2: f
|
||||
let dy = sin(h) * halfLen
|
||||
(px - dx, py - dy, px + dx, py + dy)
|
||||
|
||||
proc samePoint(a, b: GeomPoint): bool {.inline.} =
|
||||
hypot(b.x - a.x, b.y - a.y) < GeoZeroLen
|
||||
|
||||
proc trianglePrims*(enemyOther, enemyPos, selfPos: GeomPoint): seq[GeoPrim] =
|
||||
## DRAW-ONLY: the owner-requested triangle whose three corners are, in order,
|
||||
## the ENEMY heading line's OTHER intersection with the diameter circle, the
|
||||
## enemy itself, and our bot. Returns its three edges plus one hollow corner
|
||||
## ring per DISTINCT corner, all in `GeoTriangleColor` (yellow, width 1.5).
|
||||
##
|
||||
## Degenerate handling, no new geometry is derived:
|
||||
## * a zero-length edge is SKIPPED instead of drawn as a degenerate line.
|
||||
## This happens when the enemy heading is TANGENT to the circle (corner 1
|
||||
## coincides with corner 2) or points straight at us (corner 1 coincides
|
||||
## with corner 3);
|
||||
## * coincident corners share a single ring, so no zero-radius garbage.
|
||||
let vs = [enemyOther, enemyPos, selfPos]
|
||||
for i in 0 ..< 3:
|
||||
let a = vs[i]
|
||||
let b = vs[(i + 1) mod 3]
|
||||
if samePoint(a, b): continue
|
||||
result.add GeoPrim(kind: gpTriangleEdge, x1: a.x, y1: a.y, x2: b.x, y2: b.y,
|
||||
color: GeoTriangleColor)
|
||||
for i in 0 ..< 3:
|
||||
var dup = false
|
||||
for j in 0 ..< i:
|
||||
if samePoint(vs[i], vs[j]): dup = true; break
|
||||
if dup: continue
|
||||
result.add GeoPrim(kind: gpTriangleCorner, cx: vs[i].x, cy: vs[i].y,
|
||||
r: GeoTriangleCornerRadius, color: GeoTriangleColor)
|
||||
|
||||
proc collectGeoPrims*(selfX, selfY, selfHeading,
|
||||
enemyX, enemyY, enemyHeading: float): seq[GeoPrim] =
|
||||
## Pure: the primitives the overlay draws. Empty in the degenerate case where
|
||||
@@ -194,6 +240,14 @@ proc collectGeoPrims*(selfX, selfY, selfHeading,
|
||||
cy: soEnemy.other.y, r: GeoOtherMarkRadius,
|
||||
color: GeoOtherMarkColor)
|
||||
|
||||
# The owner-requested TRIANGLE: the enemy heading's OTHER intersection,
|
||||
# the enemy, and our bot. All three corners were already computed just
|
||||
# above — nothing is re-derived here.
|
||||
for p in trianglePrims(soEnemy.other,
|
||||
GeomPoint(x: enemyX, y: enemyY),
|
||||
GeomPoint(x: selfX, y: selfY)):
|
||||
result.add p
|
||||
|
||||
# ── emit to the GUI debug-graphics buffer ────────────────────────────────────
|
||||
|
||||
proc emitGeoPrims*(prims: seq[GeoPrim]): int =
|
||||
@@ -215,6 +269,14 @@ proc emitGeoPrims*(prims: seq[GeoPrim]): int =
|
||||
of gpMarkOther:
|
||||
setFillColor(p.color)
|
||||
fillCircle(p.cx, p.cy, p.r)
|
||||
of gpTriangleEdge:
|
||||
setStrokeColor(p.color)
|
||||
setStrokeWidth(GeoTriangleWidth)
|
||||
drawLine(p.x1, p.y1, p.x2, p.y2)
|
||||
of gpTriangleCorner:
|
||||
setStrokeColor(p.color)
|
||||
setStrokeWidth(GeoTriangleWidth)
|
||||
drawCircle(p.cx, p.cy, p.r)
|
||||
result = prims.len
|
||||
|
||||
proc drawGeoOverlay*(selfX, selfY, selfHeading,
|
||||
|
||||
Reference in New Issue
Block a user