ASTAR/PATHLINE

This commit is contained in:
Frank 2023-09-12 23:57:50 +02:00
parent abb7f860ae
commit aa1e12163d
2 changed files with 95 additions and 73 deletions

View File

@ -281,16 +281,23 @@ function ASTAR:AddNodeFromPathlineName(Pathline)
for i,_point in pairs(Pathline.points) do
local point=_point --Core.Pathline#PATHLINE.Point
local coord=COORDINATE:NewFromVec3(point.vec3)
local node=self:AddNodeFromCoordinate(coord)
-- Create node from point coordinate.
local node=self:AddNodeFromCoordinate(COORDINATE:NewFromVec3(point.vec3))
-- Add pathline parameters.
node.pathline=Pathline
node.pathpoint=point
-- Debug.
local name=node.pathline and node.pathline.name or "N/A"
local idx=node.pathline and node.pathline:_GetPointIndex(node.pathpoint) or "N/A"
-- Debug message.
self:T(self.lid..string.format("Adding node UID=%d pathline=%s [%s]", node.id, name, tostring(idx)))
node.coordinate:MarkToAll(string.format("Node ID=%d\npathline=%s [%s]", node.id, name, tostring(idx)))
-- Debug mark
--node.coordinate:MarkToAll(string.format("Node ID=%d\npathline=%s [%s]", node.id, name, tostring(idx)))
end
@ -604,7 +611,7 @@ function ASTAR.Pathline(nodeA, nodeB, distmax)
distmax=distmax or 10
if nodeA.pathpoint.name==nodeB.pathpoint.name then
if nodeA.pathline.name==nodeB.pathline.name then
-- Nodes are on the same pathline. We use the index to check if they are neighbours.
@ -618,28 +625,22 @@ function ASTAR.Pathline(nodeA, nodeB, distmax)
end
else
-- local dist=nodeA.coordinate:Get2DDistance(nodeB.coordinate)
-- if dist<distmax then
-- return true
-- end
local idxA=nodeA.pathline:_GetPointIndex(nodeA.pathpoint)
local idxB=nodeB.pathline:_GetPointIndex(nodeB.pathpoint)
-- Check if nodeB is close to pathline of nodeA.
local c, dist, segA=nodeA.pathline:GetClosestPoint3D(nodeB.coordinate)
local seg=segA --Core.Pathline#PATHLINE.Segment
--TODO: Check that
if dist<distmax and (nodeA.pathpoint.uid==seg.p1.uid or nodeA.pathpoint.uid==seg.p2.uid) then
env.info(string.format("FF NodeB=%d [pathline=%s] is close to NodeA=%d [pathline=%s] ==> valid neighbour", nodeB.id, nodeB.pathline.name, nodeA.id, nodeA.pathline.name))
return true
end
-- Check if nodeA is close to pathline of nodeB.
local c, dist=nodeB.pathline:GetClosestPoint3D(nodeA.coordinate)
if dist<distmax then
local c, dist, segB=nodeB.pathline:GetClosestPoint3D(nodeA.coordinate)
local seg=segB --Core.Pathline#PATHLINE.Segment
if dist<distmax and (nodeB.pathpoint.uid==seg.p1.uid or nodeB.pathpoint.uid==seg.p2.uid) then
env.info(string.format("FF NodeA=%d [pathline=%s] is close to NodeB=%d [pathline=%s] ==> valid neighbour", nodeA.id, nodeA.pathline.name, nodeB.id, nodeB.pathline.name))
return true
end
@ -674,6 +675,8 @@ end
-- @return #number Distance between the two nodes.
function ASTAR.Dist2D(nodeA, nodeB)
local dist=nodeA.coordinate:Get2DDistance(nodeB.coordinate)
local text=string.format("FF Cost Dist2D NodeA=%d-->NodeB=%d = %.1f", nodeA.id, nodeB.id, dist)
env.info(text)
return dist
end
@ -797,23 +800,24 @@ function ASTAR:FindStartNode()
-- Find the closest pathline to the
local pathline, dist, vec3, s=self:FindClosestPathline(self.startCoord)
if pathline and vec3 then
local Coordinate=COORDINATE:NewFromVec3(vec3)
local node=self:AddNodeFromCoordinate(Coordinate)
node.pathline=pathline
if pathline and vec3 and dist and dist>10 then
-- Create a node on the closest pathline so we first go straight there and then along the pathline.
local node=self:AddNodeFromCoordinate(COORDINATE:NewFromVec3(vec3))
-- We also need the pathline point.
local point=pathline:AddPointFromVec3(vec3, nil, s.p1)
node.pathline=pathline
node.pathpoint=point
self.startNode=node
else
-- Find the closest node to the given start coordinate.
self.startNode, dist=self:FindClosestNode(self.startCoord)
self:T2(self.lid..string.format("Added new node=%d, which is closest to start coord. dist=%.1f m", node.id, dist))
end
-- Find the closest node to the given start coordinate.
self.startNode, dist=self:FindClosestNode(self.startCoord)
--self.startNode.coordinate:MarkToAll("Start Node")
-- Debug info.
self:T(self.lid..string.format("START node ID=%d", self.startNode.id))
@ -834,23 +838,26 @@ function ASTAR:FindEndNode()
local pathline, dist, vec3, s=self:FindClosestPathline(self.endCoord)
if pathline and vec3 then
local Coordinate=COORDINATE:NewFromVec3(vec3)
local node=self:AddNodeFromCoordinate(Coordinate)
node.pathline=pathline
if pathline and vec3 and dist and dist>10 then
-- Create a node on the closest pathline so we first go straight there and then along the pathline.
local node=self:AddNodeFromCoordinate(COORDINATE:NewFromVec3(vec3))
-- We also need the point.
local point=pathline:AddPointFromVec3(vec3, nil, s.p1)
-- Add pathline parameters to node.
node.pathline=pathline
node.pathpoint=point
self.endNode=node
else
self.endNode, dist=self:FindClosestNode(self.endCoord, {self.startNode})
self:T2(self.lid..string.format("Added new node=%d, which is closest to END coord: dist=%.1f m", node.id, dist))
end
-- Find closest node to the end coordinate (exclude the start coordinate.
self.endNode, dist=self:FindClosestNode(self.endCoord, {self.startNode})
--self.endNode.coordinate:MarkToAll("End Node")
-- Debug info.
self:T(self.lid..string.format("END node ID=%d", self.endNode.id))
@ -913,22 +920,21 @@ function ASTAR:GetPath(ExcludeStartNode, ExcludeEndNode)
-- Get current node.
local current=self:_LowestFscore(openset, f_score)
env.info("FF current node="..current.id)
env.info("FF came_from")
for _neighbour,_current in pairs(came_from) do
local neighbour=_neighbour --#ASTAR.Node
local current=_current --#ASTAR.Node
env.info(string.format("neighbour=%d --> %d=current", neighbour.id, current.id))
end
--self:I(came_from)
local text="Path:"
local path=self:_UnwindPath({}, came_from, current)
for i,_node in pairs(path) do
local node=_node --#ASTAR.Node
text=text..string.format("\n[%d] Node=%d", i, node.id)
end
env.info(text)
-- Debug
-- self:I("FF current node="..current.id)
-- self:I("FF came_from")
-- for _neighbour,_current in pairs(came_from) do
-- local neighbour=_neighbour --#ASTAR.Node
-- local current=_current --#ASTAR.Node
-- self:I(string.format("neighbour=%d --> %d=current", neighbour.id, current.id))
-- end
-- local text="Path:"
-- local path=self:_UnwindPath({}, came_from, current)
-- for i,_node in pairs(path) do
-- local node=_node --#ASTAR.Node
-- text=text..string.format("\n[%d] Node=%d", i, node.id)
-- end
-- self:I(text)
-- Check if we are at the end node.
if current.id==goal.id then
@ -975,12 +981,12 @@ function ASTAR:GetPath(ExcludeStartNode, ExcludeEndNode)
-- Get neighbour nodes.
local neighbors=self:_NeighbourNodes(current, nodes)
local text=string.format("Current node UID=%d pathline=%s", current.id, current.pathline and current.pathline.name or "N/A")
for _,_node in pairs(neighbors) do
local node=_node --#ASTAR.Node
text=text..string.format("\nNeighbour node UID=%d pathline=%s", node.id, node.pathline and node.pathline.name or "N/A")
end
self:T(self.lid..text)
-- local text=string.format("Current node UID=%d pathline=%s", current.id, current.pathline and current.pathline.name or "N/A")
-- for _,_node in pairs(neighbors) do
-- local node=_node --#ASTAR.Node
-- text=text..string.format("\nNeighbour node UID=%d pathline=%s", node.id, node.pathline and node.pathline.name or "N/A")
-- end
-- self:T(self.lid..text)
-- Loop over neighbours.
for _,neighbor in pairs(neighbors) do
@ -1034,10 +1040,11 @@ function ASTAR:GetPathline(ExcludeStartNode, ExcludeEndNode)
pathline=PATHLINE:New("Astar")
for _,_note in pairs(nodes) do
local note=_note --#ASTAR.Node
for _,_node in pairs(nodes) do
local node=_node --#ASTAR.Node
local point=pathline:AddPointFromVec3(note.coordinate)
local point=pathline:AddPointFromVec3(node.coordinate)
point.name=node.pathline.name
end
@ -1074,11 +1081,7 @@ function ASTAR:GetPathlinesFromNodes(Nodes)
end
end
-- Add pathline to table (if it is not already in).
--if not UTILS.IsAnyInTable(pathlines, {pathline}, "name") then
--env.info(string.format("Adding pathline %s", pathline.name, tostring(UTILS.IsAnyInTable(pathlines, pathline))))
-- We do not want to add the same pathline two times in a row.
if #pathlines==0 or (#pathlines>0 and pathlines[#pathlines].name~=pathline.name) then
table.insert(pathlines, pathline)
@ -1110,7 +1113,6 @@ function ASTAR:_HeuristicCost(nodeA, nodeB)
return cost
end
local cost=nil
if self.CostFunc then
cost=self.CostFunc(nodeA, nodeB, unpack(self.CostArg))
else

View File

@ -68,7 +68,8 @@ PATHLINE = {
--- Point of line.
-- @type PATHLINE.Point
-- @field #number uid Unique ID of this point.
-- @field #string name Name of the pathline this point belongs to.
-- @field #string mother Name of the pathline this point belongs to.
-- @field #string name Name of this point.
-- @field DCS#Vec3 vec3 3D position.
-- @field DCS#Vec2 vec2 2D position.
-- @field #number surfaceType Surface type.
@ -240,11 +241,28 @@ end
--- Get points of pathline. Not that points are tables, that contain more information as just the 2D or 3D position but also the surface type etc.
-- @param #PATHLINE self
-- @return <#PATHLINE.Point> List of points.
-- @return <Core.Pathline#PATHLINE.Point> List of points.
function PATHLINE:GetPoints()
return self.points
end
--- Get segments of pathline.
-- @param #PATHLINE self
-- @return <Core.Pathline#PATHLINE.Segment> List of points.
function PATHLINE:GetSetments()
local segments={}
for i=1,#self.points-1 do
local segment={} --#PATHLINE.Segment
segment.p1=self.points[i]
segment.p2=self.points[i+1]
table.insert(segments, segment)
end
return segments
end
--- Get 3D points of pathline.
-- @param #PATHLINE self
-- @return <DCS#Vec3> List of DCS#Vec3 points.
@ -557,7 +575,9 @@ function PATHLINE:_CreatePoint(Vec)
self.counter=self.counter+1
point.uid=self.counter
point.name=self.name
point.mother=self.name
point.name=string.format("%s #%d", self.name, point.uid)
if Vec.z then
-- Given vec is 3D