@esengine/pathfinding
Version:
寻路系统 | Pathfinding System - A*, Grid, NavMesh
444 lines (438 loc) • 13.9 kB
TypeScript
import { IVector2 } from '@esengine/ecs-framework-math';
/**
* @zh ORCA 局部避让接口定义
* @en ORCA Local Avoidance Interface Definitions
*/
/**
* @zh ORCA 约束线(半平面)
* @en ORCA constraint line (half-plane)
*
* @zh 约束线定义了一个半平面,代理的速度必须在允许的一侧
* @en A constraint line defines a half-plane, agent's velocity must be on the allowed side
*/
interface IORCALine {
/**
* @zh 线上的一点
* @en A point on the line
*/
point: IVector2;
/**
* @zh 线的方向向量(单位向量,允许区域在左侧)
* @en Direction vector of the line (unit vector, allowed region is on the left)
*/
direction: IVector2;
}
/**
* @zh 避让代理数据
* @en Avoidance agent data
*
* @zh 包含计算 ORCA 所需的所有代理信息
* @en Contains all agent information needed for ORCA computation
*/
interface IAvoidanceAgent {
/**
* @zh 代理唯一标识
* @en Unique identifier for the agent
*/
id: number;
/**
* @zh 当前位置
* @en Current position
*/
position: IVector2;
/**
* @zh 当前速度
* @en Current velocity
*/
velocity: IVector2;
/**
* @zh 首选速度(通常指向目标方向)
* @en Preferred velocity (usually towards target)
*/
preferredVelocity: IVector2;
/**
* @zh 代理半径
* @en Agent radius
*/
radius: number;
/**
* @zh 最大速度
* @en Maximum speed
*/
maxSpeed: number;
/**
* @zh 邻居检测距离
* @en Neighbor detection distance
*/
neighborDist: number;
/**
* @zh 最大邻居数量
* @en Maximum number of neighbors to consider
*/
maxNeighbors: number;
/**
* @zh 代理避让时间视野(秒)
* @en Time horizon for agent avoidance (seconds)
*
* @zh 更大的值会让代理更早开始避让
* @en Larger values make agents start avoiding earlier
*/
timeHorizon: number;
/**
* @zh 障碍物避让时间视野(秒)
* @en Time horizon for obstacle avoidance (seconds)
*/
timeHorizonObst: number;
}
/**
* @zh 静态障碍物顶点(链表节点)
* @en Static obstacle vertex (linked list node)
*/
interface IObstacleVertex {
/**
* @zh 顶点位置
* @en Vertex position
*/
point: IVector2;
/**
* @zh 下一个顶点(构成障碍物边,循环链表)
* @en Next vertex (forms obstacle edge, circular linked list)
*/
next: IObstacleVertex;
/**
* @zh 前一个顶点(循环链表)
* @en Previous vertex (circular linked list)
*/
previous: IObstacleVertex;
/**
* @zh 边的单位方向向量(从此顶点指向 next 顶点)
* @en Unit direction vector of edge (from this vertex towards next vertex)
*/
direction: IVector2;
/**
* @zh 是否为凸顶点
* @en Whether this is a convex vertex
*/
isConvex: boolean;
/**
* @zh 顶点 ID(用于调试)
* @en Vertex ID (for debugging)
*/
id: number;
}
/**
* @zh 静态障碍物(多边形)
* @en Static obstacle (polygon)
*
* @zh 重要:顶点必须按逆时针(CCW)顺序排列(在 Y 轴向上的坐标系中)
* @en Important: Vertices must be in counter-clockwise (CCW) order (in Y-axis up coordinate system)
*
* @zh 可以使用 math 库中的 Polygon.ensureCCW() 确保正确顺序
* @en Use Polygon.ensureCCW() from math library to ensure correct order
*
* @zh 在 Y 轴向下的坐标系(如 Canvas)中,视觉上的 CCW 需要传入 yAxisDown=true
* @en In Y-axis down coordinate system (like Canvas), use yAxisDown=true for visual CCW
*
* @example
* ```typescript
* import { Polygon } from '@esengine/ecs-framework-math';
*
* // 标准 Y 轴向上坐标系
* const obstacle: IObstacle = {
* vertices: Polygon.ensureCCW(myVertices)
* };
*
* // Canvas/屏幕坐标系(Y 轴向下)
* const obstacle: IObstacle = {
* vertices: Polygon.ensureCCW(myVertices, true)
* };
* ```
*/
interface IObstacle {
/**
* @zh 顶点列表(逆时针顺序,Y 轴向上坐标系)
* @en Vertex list (counter-clockwise order in Y-axis up coordinate system)
*/
vertices: IVector2[];
}
/**
* @zh ORCA 求解器配置
* @en ORCA solver configuration
*/
interface IORCASolverConfig {
/**
* @zh 默认时间视野(代理)
* @en Default time horizon for agents
*/
defaultTimeHorizon?: number;
/**
* @zh 默认时间视野(障碍物)
* @en Default time horizon for obstacles
*/
defaultTimeHorizonObst?: number;
/**
* @zh 时间步长(用于碰撞响应)
* @en Time step (for collision response)
*/
timeStep?: number;
/**
* @zh 数值精度阈值
* @en Numerical precision threshold
*/
epsilon?: number;
/**
* @zh 是否使用 Y 轴向下的坐标系(如 Canvas/屏幕坐标)
* @en Whether using Y-axis down coordinate system (like Canvas/screen coords)
*
* @zh 这会影响障碍物顶点顺序的判断(CCW 检测)
* @en This affects obstacle vertex order detection (CCW check)
*
* @default false
*/
yAxisDown?: boolean;
}
/**
* @zh ORCA 求解结果
* @en ORCA solve result
*/
interface IORCAResult {
/**
* @zh 计算得到的新速度
* @en Computed new velocity
*/
velocity: IVector2;
/**
* @zh 是否找到可行解(满足所有约束)
* @en Whether a feasible solution was found (satisfies all constraints)
*/
feasible: boolean;
/**
* @zh 生成的 ORCA 约束线数量
* @en Number of ORCA lines generated
*/
numLines: number;
/**
* @zh 违反的约束数量
* @en Number of violated constraints
*/
violatedConstraints: number;
}
/**
* @zh ORCA 求解器接口
* @en ORCA solver interface
*/
interface IORCASolver {
/**
* @zh 计算代理的新速度
* @en Compute new velocity for agent
*
* @param agent - @zh 当前代理 @en Current agent
* @param neighbors - @zh 邻近代理列表 @en List of neighbor agents
* @param obstacles - @zh 静态障碍物列表 @en List of static obstacles
* @param deltaTime - @zh 时间步长 @en Time step
* @returns @zh 新速度 @en New velocity
*/
computeNewVelocity(agent: IAvoidanceAgent, neighbors: readonly IAvoidanceAgent[], obstacles: readonly IObstacle[], deltaTime: number): IVector2;
}
/**
* @zh 邻居查询结果
* @en Neighbor query result
*/
interface INeighborResult {
/**
* @zh 代理数据
* @en Agent data
*/
agent: IAvoidanceAgent;
/**
* @zh 距离的平方
* @en Squared distance
*/
distanceSq: number;
}
/**
* @zh 空间索引接口(用于快速邻居查询)
* @en Spatial index interface (for fast neighbor queries)
*/
interface ISpatialIndex {
/**
* @zh 构建空间索引
* @en Build spatial index
*
* @param agents - @zh 代理列表 @en List of agents
*/
build(agents: readonly IAvoidanceAgent[]): void;
/**
* @zh 查询指定范围内的邻居
* @en Query neighbors within specified range
*
* @param position - @zh 查询位置 @en Query position
* @param radius - @zh 查询半径 @en Query radius
* @param maxResults - @zh 最大返回数量 @en Maximum number of results
* @param excludeId - @zh 排除的代理 ID @en Agent ID to exclude
* @returns @zh 邻居列表(按距离排序)@en List of neighbors (sorted by distance)
*/
queryNeighbors(position: IVector2, radius: number, maxResults: number, excludeId?: number): INeighborResult[];
/**
* @zh 清空索引
* @en Clear the index
*/
clear(): void;
}
/**
* @zh 默认 ORCA 求解器配置
* @en Default ORCA solver configuration
*/
declare const DEFAULT_ORCA_CONFIG: Required<IORCASolverConfig>;
/**
* @zh 默认代理参数
* @en Default agent parameters
*/
declare const DEFAULT_AGENT_PARAMS: {
radius: number;
maxSpeed: number;
neighborDist: number;
maxNeighbors: number;
timeHorizon: number;
timeHorizonObst: number;
};
/**
* @zh 碰撞解决器
* @en Collision Resolver
*
* @zh 提供位置级别的硬碰撞检测和解决,作为 ORCA 的补充保护层
* @en Provides position-level hard collision detection and resolution as a supplementary protection layer for ORCA
*/
/**
* @zh 碰撞检测结果
* @en Collision detection result
*/
interface ICollisionResult {
/**
* @zh 是否发生碰撞
* @en Whether collision occurred
*/
collided: boolean;
/**
* @zh 穿透深度
* @en Penetration depth
*/
penetration: number;
/**
* @zh 碰撞法线(从障碍物指向代理)
* @en Collision normal (pointing from obstacle to agent)
*/
normal: IVector2;
/**
* @zh 最近点
* @en Closest point on obstacle
*/
closestPoint: IVector2;
}
/**
* @zh 空碰撞结果
* @en Empty collision result
*/
declare const EMPTY_COLLISION: ICollisionResult;
/**
* @zh 碰撞解决器配置
* @en Collision resolver configuration
*/
interface ICollisionResolverConfig {
/**
* @zh 碰撞响应系数(0-1,1 表示完全推出)
* @en Collision response factor (0-1, 1 means fully push out)
*/
responseFactor?: number;
/**
* @zh 安全边距(额外距离)
* @en Safety margin (extra distance)
*/
safetyMargin?: number;
}
/**
* @zh 默认配置
* @en Default configuration
*/
declare const DEFAULT_COLLISION_CONFIG: Required<ICollisionResolverConfig>;
/**
* @zh 碰撞解决器
* @en Collision Resolver
*
* @zh 提供位置级别的硬碰撞检测和解决
* @en Provides position-level hard collision detection and resolution
*/
declare class CollisionResolver {
private readonly config;
constructor(config?: ICollisionResolverConfig);
/**
* @zh 检测圆与单个障碍物的碰撞
* @en Detect collision between circle and single obstacle
*
* @param position - @zh 圆心位置 @en Circle center position
* @param radius - @zh 圆半径 @en Circle radius
* @param obstacle - @zh 障碍物 @en Obstacle
* @returns @zh 碰撞结果 @en Collision result
*/
detectCollision(position: IVector2, radius: number, obstacle: IObstacle): ICollisionResult;
/**
* @zh 检测圆与所有障碍物的碰撞
* @en Detect collision between circle and all obstacles
*
* @param position - @zh 圆心位置 @en Circle center position
* @param radius - @zh 圆半径 @en Circle radius
* @param obstacles - @zh 障碍物列表 @en List of obstacles
* @returns @zh 最严重的碰撞结果 @en Most severe collision result
*/
detectCollisions(position: IVector2, radius: number, obstacles: readonly IObstacle[]): ICollisionResult;
/**
* @zh 解决碰撞,返回修正后的位置
* @en Resolve collision, return corrected position
*
* @param position - @zh 当前位置 @en Current position
* @param radius - @zh 半径 @en Radius
* @param obstacles - @zh 障碍物列表 @en List of obstacles
* @returns @zh 修正后的位置 @en Corrected position
*/
resolveCollision(position: IVector2, radius: number, obstacles: readonly IObstacle[]): IVector2;
/**
* @zh 验证速度是否会导致碰撞,返回安全速度
* @en Validate velocity won't cause collision, return safe velocity
*
* @param position - @zh 当前位置 @en Current position
* @param velocity - @zh 目标速度 @en Target velocity
* @param radius - @zh 半径 @en Radius
* @param obstacles - @zh 障碍物列表 @en List of obstacles
* @param deltaTime - @zh 时间步长 @en Time step
* @returns @zh 安全速度 @en Safe velocity
*/
validateVelocity(position: IVector2, velocity: IVector2, radius: number, obstacles: readonly IObstacle[], deltaTime: number): IVector2;
/**
* @zh 检测两个代理之间的碰撞
* @en Detect collision between two agents
*
* @param posA - @zh 代理 A 位置 @en Agent A position
* @param radiusA - @zh 代理 A 半径 @en Agent A radius
* @param posB - @zh 代理 B 位置 @en Agent B position
* @param radiusB - @zh 代理 B 半径 @en Agent B radius
* @returns @zh 碰撞结果 @en Collision result
*/
detectAgentCollision(posA: IVector2, radiusA: number, posB: IVector2, radiusB: number): ICollisionResult;
/**
* @zh 解决代理之间的碰撞
* @en Resolve collision between agents
*
* @param posA - @zh 代理 A 位置 @en Agent A position
* @param radiusA - @zh 代理 A 半径 @en Agent A radius
* @param posB - @zh 代理 B 位置 @en Agent B position
* @param radiusB - @zh 代理 B 半径 @en Agent B radius
* @returns @zh 修正后的位置 [A, B] @en Corrected positions [A, B]
*/
resolveAgentCollision(posA: IVector2, radiusA: number, posB: IVector2, radiusB: number): [IVector2, IVector2];
}
/**
* @zh 创建碰撞解决器
* @en Create collision resolver
*/
declare function createCollisionResolver(config?: ICollisionResolverConfig): CollisionResolver;
export { CollisionResolver as C, DEFAULT_ORCA_CONFIG as D, EMPTY_COLLISION as E, type IORCALine as I, type IAvoidanceAgent as a, type IObstacle as b, type IORCASolverConfig as c, type IORCAResult as d, type IORCASolver as e, type INeighborResult as f, type ISpatialIndex as g, type ICollisionResult as h, type ICollisionResolverConfig as i, DEFAULT_AGENT_PARAMS as j, DEFAULT_COLLISION_CONFIG as k, createCollisionResolver as l, type IObstacleVertex as m };