@@ -44,79 +44,50 @@ object GraphUtil {
4444
4545 // 6-connectivity (Axis-aligned moves only)
4646 fun createGridGraph6Conn (blockedNodes : MutableSet <FastVector > = mutableSetOf()): LazyGraph {
47- val cost = 1.0
4847 return LazyGraph { node ->
49- if (node in blockedNodes) return @LazyGraph emptyMap()
50- val neighbors = mutableMapOf<FastVector , Double >()
51- val x = node.x
52- val y = node.y
53- val z = node.z
54- // Add neighbors differing by 1 in exactly one dimension
55- neighbors[fastVectorOf(x + 1 , y, z)] = cost
56- neighbors[fastVectorOf(x - 1 , y, z)] = cost
57- neighbors[fastVectorOf(x, y + 1 , z)] = cost
58- neighbors[fastVectorOf(x, y - 1 , z)] = cost
59- neighbors[fastVectorOf(x, y, z + 1 )] = cost
60- neighbors[fastVectorOf(x, y, z - 1 )] = cost
61- neighbors.minus(blockedNodes)
48+ if (node in blockedNodes) emptyMap()
49+ else n6(node).filterKeys { it !in blockedNodes }
6250 }
6351 }
6452
6553 // 18-connectivity (Axis-aligned + Face diagonal moves)
6654 fun createGridGraph18Conn (blockedNodes : MutableSet <FastVector > = mutableSetOf()): LazyGraph {
67- val cost1 = 1.0 // Axis-aligned
68- val cost2 = sqrt(2.0 ) // Face diagonal
6955 return LazyGraph { node ->
70- if (node in blockedNodes) return @LazyGraph emptyMap()
71- val neighbors = mutableMapOf<FastVector , Double >()
72- val x = node.x
73- val y = node.y
74- val z = node.z
75- for (dx in - 1 .. 1 ) {
76- for (dy in - 1 .. 1 ) {
77- for (dz in - 1 .. 1 ) {
78- if (dx == 0 && dy == 0 && dz == 0 ) continue // Skip self
79- val distSq = dx* dx + dy* dy + dz* dz
80- if (distSq > 2 ) continue // Exclude cube diagonals (distSq = 3)
81-
82- val cost = if (distSq == 1 ) cost1 else cost2
83- neighbors[fastVectorOf(x + dx, y + dy, z + dz)] = cost
84- }
85- }
86- }
87- neighbors.minus(blockedNodes)
56+ if (node in blockedNodes) emptyMap()
57+ else n18(node).filterKeys { it !in blockedNodes }
8858 }
8959 }
9060
9161 // 26-connectivity (Axis-aligned + Face diagonal + Cube diagonal moves)
9262 fun createGridGraph26Conn (blockedNodes : MutableSet <FastVector > = mutableSetOf()): LazyGraph {
93- val cost1 = 1.0 // Axis-aligned
94- val cost2 = sqrt(2.0 ) // Face diagonal
95- val cost3 = sqrt(3.0 ) // Cube diagonal
9663 return LazyGraph { node ->
97- if (node in blockedNodes) return @LazyGraph emptyMap()
98- val neighbors = mutableMapOf<FastVector , Double >()
99- val x = node.x
100- val y = node.y
101- val z = node.z
102- for (dx in - 1 .. 1 ) {
103- for (dy in - 1 .. 1 ) {
104- for (dz in - 1 .. 1 ) {
105- if (dx == 0 && dy == 0 && dz == 0 ) continue // Skip self
64+ if (node in blockedNodes) emptyMap()
65+ else n26(node).filterKeys { it !in blockedNodes }
66+ }
67+ }
68+
69+ fun n6 (o : FastVector ) = neighborhood(o, minDistSq = 1 , maxDistSq = 1 )
70+ fun n18 (o : FastVector ) = neighborhood(o, minDistSq = 1 , maxDistSq = 2 )
71+ fun n26 (o : FastVector ) = neighborhood(o, minDistSq = 1 , maxDistSq = 3 )
10672
107- val cost = when (dx* dx + dy* dy + dz* dz) {
108- 1 -> cost1
109- 2 -> cost2
110- 3 -> cost3
111- else -> continue // Should not happen with dx/dy/dz in -1..1
73+ fun neighborhood (origin : FastVector , minDistSq : Int = 1, maxDistSq : Int = 1): Map <FastVector , Double > =
74+ (- 1 .. 1 ).flatMap { dx ->
75+ (- 1 .. 1 ).flatMap { dy ->
76+ (- 1 .. 1 ).mapNotNull { dz ->
77+ val distSq = dx* dx + dy* dy + dz* dz
78+ if (distSq in minDistSq.. maxDistSq) {
79+ val neighbor = fastVectorOf(origin.x + dx, origin.y + dy, origin.z + dz)
80+ val cost = when (distSq) {
81+ 1 -> 1.0
82+ 2 -> sqrt(2.0 )
83+ 3 -> sqrt(3.0 )
84+ else -> error(" Unexpected squared distance: $distSq " )
11285 }
113- neighbors[fastVectorOf(x + dx, y + dy, z + dz)] = cost
114- }
86+ neighbor to cost
87+ } else null
11588 }
11689 }
117- neighbors.minus(blockedNodes)
118- }
119- }
90+ }.toMap()
12091
12192 fun List<FastVector>.string () = joinToString(" -> " ) { it.string }
12293 fun List<FastVector>.length () = zipWithNext { a, b -> a dist b }.sum()
0 commit comments