Skip to content

Commit 65b377c

Browse files
committed
Filled out the JPS finder and updated the heuristic functions.
1 parent 6ac0c63 commit 65b377c

File tree

7 files changed

+168
-11
lines changed

7 files changed

+168
-11
lines changed

src/main/java/io/github/coderodde/pathfinding/finders/JumpPointSearchFinder.java

Lines changed: 110 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,26 @@
11
package io.github.coderodde.pathfinding.finders;
22

3+
import io.github.coderodde.pathfinding.finders.jps.DiagonalCrossingJumper;
34
import io.github.coderodde.pathfinding.finders.jps.DiagonalCrossingNeighbourFinder;
45
import io.github.coderodde.pathfinding.finders.jps.DiagonalNoCrossingNeighbourFinder;
6+
import io.github.coderodde.pathfinding.finders.jps.DiagonalNonCrossingJumper;
7+
import io.github.coderodde.pathfinding.finders.jps.NoDiagonalJumper;
58
import io.github.coderodde.pathfinding.finders.jps.NoDiagonalNeighbourFinder;
9+
import io.github.coderodde.pathfinding.heuristics.HeuristicFunction;
610
import io.github.coderodde.pathfinding.logic.GridCellNeighbourIterable;
7-
import io.github.coderodde.pathfinding.logic.GridNodeExpander;
811
import io.github.coderodde.pathfinding.logic.PathfindingSettings;
912
import io.github.coderodde.pathfinding.logic.SearchState;
1013
import io.github.coderodde.pathfinding.logic.SearchStatistics;
1114
import io.github.coderodde.pathfinding.model.GridModel;
1215
import io.github.coderodde.pathfinding.utils.Cell;
1316
import io.github.coderodde.pathfinding.utils.CellType;
14-
import java.util.ArrayList;
1517
import java.util.HashMap;
18+
import java.util.HashSet;
1619
import java.util.List;
1720
import java.util.Map;
1821
import java.util.PriorityQueue;
1922
import java.util.Queue;
23+
import java.util.Set;
2024

2125
/**
2226
* This class implements the Jump Point Search.
@@ -82,12 +86,21 @@ public List<Cell> findPath(GridModel model,
8286
NeighbourFinder neighbourFinder =
8387
getNeighbourFinder(pathfindingSettings);
8488

89+
Jumper jumper = getJumper(pathfindingSettings);
90+
8591
Cell source = model.getSourceGridCell();
8692
Cell target = model.getTargetGridCell();
87-
HeapNode startHeapNode = new HeapNode(source, 0.0);
8893

89-
Queue<HeapNode> open = new PriorityQueue<>();
90-
Map<Cell, Cell> parentsMap = new HashMap<>();
94+
Queue<HeapNode> open = new PriorityQueue<>();
95+
Set<Cell> openSet = new HashSet<>();
96+
Set<Cell> closed = new HashSet<>();
97+
Map<Cell, Double> distanceMap = new HashMap<>();
98+
Map<Cell, Cell> parentsMap = new HashMap<>();
99+
100+
open.add(new HeapNode(source, 0.0));
101+
openSet.add(source);
102+
parentsMap.put(source, null);
103+
distanceMap.put(source, 0.0);
91104

92105
while (!open.isEmpty()) {
93106
Cell current = open.remove().cell;
@@ -97,21 +110,36 @@ public List<Cell> findPath(GridModel model,
97110
model.setCellType(current, CellType.VISITED);
98111
}
99112

113+
closed.add(current);
114+
100115
if (current.equals(target)) {
101116
return tracebackPath(target,
102117
parentsMap);
103118
}
104119

105120
identifySuccessors(current,
121+
open,
122+
closed,
123+
openSet,
124+
distanceMap,
106125
parentsMap,
107126
model,
108127
pathfindingSettings,
109-
neighbourFinder);
128+
neighbourFinder,
129+
jumper);
110130
}
111131

112132
return List.of();
113133
}
114134

135+
/**
136+
* Returns the required neighbour finder.
137+
*
138+
* @param pathfindingSettings the pathfinding settings object.
139+
*
140+
* @return an instance of the suitable
141+
* {@link io.github.coderodde.pathfinding.finders.JumpPointSearchFinder.NeighbourFinder}.
142+
*/
115143
private static NeighbourFinder
116144
getNeighbourFinder(PathfindingSettings pathfindingSettings) {
117145

@@ -125,17 +153,92 @@ public List<Cell> findPath(GridModel model,
125153
return new NoDiagonalNeighbourFinder();
126154
}
127155
}
156+
157+
/**
158+
* Returns the required jumper.
159+
*
160+
* @param pathfindingSettings the pathfinding settings object.
161+
*
162+
* @return an instance of the suitable
163+
* {@link io.github.coderodde.pathfinding.finders.JumpPointSearchFinder.Jumper}.
164+
*/
165+
private static Jumper getJumper(PathfindingSettings pathfindingSettings) {
166+
167+
if (pathfindingSettings.allowDiagonals()) {
168+
if (pathfindingSettings.dontCrossCorners()) {
169+
return new DiagonalNonCrossingJumper();
170+
} else {
171+
return new DiagonalCrossingJumper();
172+
}
173+
} else {
174+
return new NoDiagonalJumper();
175+
}
176+
}
128177

129178
private static void identifySuccessors(Cell current,
179+
Queue<HeapNode> open,
180+
Set<Cell> closed,
181+
Set<Cell> openSet,
182+
Map<Cell, Double> distanceMap,
130183
Map<Cell, Cell> parentsMap,
131184
GridModel model,
132185
PathfindingSettings ps,
133-
NeighbourFinder neighbourFinder) {
186+
NeighbourFinder neighbourFinder,
187+
Jumper jumper) {
134188

135189
List<Cell> neighbors =
136190
neighbourFinder.findNeighbours(current,
137191
parentsMap,
138192
model,
139193
ps);
194+
195+
int x = current.getx();
196+
int y = current.gety();
197+
HeuristicFunction hf = ps.getHeuristicFunction();
198+
199+
for (Cell child : neighbors) {
200+
Cell jumpCell = jumper.jump(child.getx(),
201+
child.gety(),
202+
x,
203+
y,
204+
model);
205+
206+
if (jumpCell == null) {
207+
continue;
208+
}
209+
210+
int jx = jumpCell.getx();
211+
int jy = jumpCell.gety();
212+
jumpCell = model.getCell(jx, jy);
213+
214+
if (closed.contains(jumpCell)) {
215+
continue;
216+
}
217+
218+
double distance = hf.estimate(jx - x,
219+
jy - y);
220+
221+
double nextg = distanceMap.get(current) + distance;
222+
223+
if (!openSet.contains(jumpCell) ||
224+
nextg < distanceMap.get(jumpCell)) {
225+
226+
distanceMap.put(jumpCell, nextg);
227+
228+
double f =
229+
nextg +
230+
hf.estimate(jx - model.getTargetGridCell().getx(),
231+
jy - model.getTargetGridCell().gety());
232+
233+
parentsMap.put(jumpCell, current);
234+
235+
236+
if (!openSet.contains(jumpCell)) {
237+
openSet.add(jumpCell);
238+
}
239+
240+
open.add(new HeapNode(jumpCell, f));
241+
}
242+
}
140243
}
141244
}

src/main/java/io/github/coderodde/pathfinding/heuristics/ChebyshevHeuristicFunction.java

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
* Implements the Chebyshev heuristic function.
77
*
88
* @author Rodion "rodde" Efremov
9-
* @version 1.0.0
9+
* @version 1.1.0 (Oct 21, 2025)
1010
* @since 1.0.0
1111
*/
1212
public final class ChebyshevHeuristicFunction implements HeuristicFunction {
@@ -20,4 +20,12 @@ public double estimate(Cell cell1, Cell cell2) {
2020
int dy = Math.abs(cell1.gety() - cell2.gety());
2121
return Math.max(dx, dy);
2222
}
23+
24+
/**
25+
* {@inheritDoc }.
26+
*/
27+
@Override
28+
public double estimate(double dx, double dy) {
29+
return Math.max(Math.abs(dx), Math.abs(dy));
30+
}
2331
}

src/main/java/io/github/coderodde/pathfinding/heuristics/EuclideanHeuristicFunction.java

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,15 +6,26 @@
66
* Implements the Euclidean-heuristic function.
77
*
88
* @author Rodion "rodde" Efremov
9-
* @version 1.0.0
9+
* @version 1.1.0 (Oct 21, 2025)
1010
* @since 1.0.0
1111
*/
1212
public final class EuclideanHeuristicFunction implements HeuristicFunction {
1313

14+
/**
15+
* {@inheritDoc }
16+
*/
1417
@Override
1518
public double estimate(Cell cell1, Cell cell2) {
1619
int dx = cell1.getx() - cell2.getx();
1720
int dy = cell1.gety() - cell2.gety();
1821
return Math.sqrt(dx * dx + dy * dy);
1922
}
23+
24+
/**
25+
* {@inheritDoc }
26+
*/
27+
@Override
28+
public double estimate(double dx, double dy) {
29+
return Math.sqrt(dx * dx + dy * dy);
30+
}
2031
}

src/main/java/io/github/coderodde/pathfinding/heuristics/HeuristicFunction.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,4 +20,13 @@ public interface HeuristicFunction {
2020
* @return the distance estimate.
2121
*/
2222
public double estimate(Cell cell1, Cell cell2);
23+
24+
/**
25+
* Computes the heuristic estimate using the coordinate differences.
26+
*
27+
* @param dx the difference in {@code X}-coordinate.
28+
* @param dy the difference in {@code Y}-coordinate.
29+
* @return the distance estimate.
30+
*/
31+
public double estimate(double dx, double dy);
2332
}

src/main/java/io/github/coderodde/pathfinding/heuristics/ManhattanHeuristicFunction.java

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
* Implements the Manhattan-heuristic function.
77
*
88
* @author Rodion "rodde" Efremov
9-
* @version 1.0.0
9+
* @version 1.1.0 (Oct 21, 2025)
1010
* @since 1.0.0
1111
*/
1212
public class ManhattanHeuristicFunction implements HeuristicFunction {
@@ -20,4 +20,12 @@ public double estimate(Cell cell1, Cell cell2) {
2020
int dy = Math.abs(cell1.gety() - cell2.gety());
2121
return dx + dy;
2222
}
23+
24+
/**
25+
* {@inheritDoc }
26+
*/
27+
@Override
28+
public double estimate(double dx, double dy) {
29+
return Math.abs(dx) + Math.abs(dy);
30+
}
2331
}

src/main/java/io/github/coderodde/pathfinding/heuristics/OctileHeuristicFunction.java

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
* Implements the octile heuristic function.
77
*
88
* @author Rodion "rodde" Efremov
9-
* @version 1.0.0
9+
* @version 1.1.0 (Oct 21, 2025)
1010
* @since 1.0.0
1111
*/
1212
public final class OctileHeuristicFunction implements HeuristicFunction {
@@ -23,4 +23,17 @@ public double estimate(Cell cell1, Cell cell2) {
2323
int dy = Math.abs(cell1.gety() - cell2.gety());
2424
return Math.max(dx, dy) + FACTOR * Math.min(dx, dy);
2525
}
26+
27+
/**
28+
* {@inheritDoc }
29+
*/
30+
@Override
31+
public double estimate(double dx, double dy) {
32+
dx = Math.abs(dx);
33+
dy = Math.abs(dy);
34+
35+
return (dx < dy)
36+
? FACTOR * dx + dy
37+
: FACTOR * dy + dx;
38+
}
2639
}

src/main/java/io/github/coderodde/pathfinding/heuristics/ZeroHeuristicFunction.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,4 +15,9 @@ public final class ZeroHeuristicFunction implements HeuristicFunction {
1515
public double estimate(Cell cell1, Cell cell2) {
1616
return 0.0;
1717
}
18+
19+
@Override
20+
public double estimate(double dx, double dy) {
21+
return 0.0;
22+
}
1823
}

0 commit comments

Comments
 (0)