mixster

mixster

Mar 22nd, 2010
207
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 4.31 KB | None | 0 0
  1. type
  2. TPointArray = array of TPoint;
  3. TIntegerArray = array of Integer;
  4.  
  5. PNode = ^TNode;
  6. PNodeArray = array of PNode;
  7.  
  8. TNode = record
  9. pos: TPoint;
  10. parent: PNode;
  11. open, closed: Boolean;
  12. distance: Extended;
  13. index: Integer;
  14. end;
  15.  
  16. TBox = record
  17. x1, y1: Integer;
  18. x2, y2: Integer;
  19. end;
  20.  
  21. TBoxArray = array of TBox;
  22.  
  23. function FindNeighbours(var neigh: PNodeArray; start: Integer; maxdist: Extended): Boolean;
  24. var
  25. i, maxY, minY, maxX, minX: Integer;
  26. h: Integer;
  27.  
  28. begin
  29. Result := False;
  30.  
  31. h := -1;
  32. SetLength(neigh, 10);
  33.  
  34. maxY := nodes[start].pos.y + Round(maxdist);
  35. minY := nodes[start].pos.y - Round(maxdist);
  36. maxX := nodes[start].pos.x + Round(maxdist);
  37. minX := nodes[start].pos.x - Round(maxdist);
  38.  
  39. for i := start - 1 downto 0 do
  40. begin
  41. if (minY > nodes[i].pos.y) then
  42. Break;
  43. if (minX > nodes[i].pos.x) or (maxX < nodes[i].pos.x) then
  44. Continue;
  45.  
  46. if sqrt(Sqr(nodes[i].pos.x - nodes[start].pos.x) + Sqr(nodes[i].pos.y - nodes[start].pos.y)) <= maxdist then
  47. begin
  48. Inc(h);
  49. neigh[h] := @nodes[i];
  50. if h mod 10 = 9 then
  51. SetLength(neigh, h + 11);
  52. end;
  53. end;
  54.  
  55. for i := start + 1 to High(nodes) do
  56. begin
  57. if (maxY < nodes[i].pos.y) then
  58. Break;
  59. if (minX > nodes[i].pos.x) or (maxX < nodes[i].pos.x) then
  60. Continue;
  61.  
  62. if sqrt(Sqr(nodes[i].pos.x - nodes[start].pos.x) + Sqr(nodes[i].pos.y - nodes[start].pos.y)) <= maxdist then
  63. begin
  64. Inc(h);
  65. neigh[h] := @nodes[i];
  66. if h mod 10 = 9 then
  67. SetLength(neigh, h + 11);
  68. end;
  69. end;
  70.  
  71. SetLength(neigh, h + 1);
  72.  
  73. Result := h <> -1;
  74. end;
  75.  
  76. function Dijkstra(start: Integer; ending: TPointArray; maxdist: Integer): Boolean;
  77. var
  78. len: Integer;
  79. open, closed, neigh: PNodeArray;
  80. openH, closeH: Integer;
  81. endBoxes: TBoxArray;
  82. st: TNode;
  83. cl: PNode;
  84. clI, i, counter: Integer;
  85. clD, tmpD: Extended;
  86. begin
  87. Result := False;
  88.  
  89. len := High(ending);
  90. SetLength(endBoxes, len + 1);
  91.  
  92. for i := len downto 0 do
  93. begin
  94. clI := Ceil(maxdist);
  95. endBoxes[i].x1 := ending[i].x - clI;
  96. endBoxes[i].x2 := ending[i].x + clI;
  97. endBoxes[i].y1 := ending[i].y - clI;
  98. endBoxes[i].y2 := ending[i].y + clI;
  99. end;
  100.  
  101. len := Length(nodes);
  102. SetLength(open, len);
  103. SetLength(closed, len);
  104. openH := 0;
  105. closeH := -1;
  106.  
  107. nodes[start].open := True;
  108.  
  109. open[0] := @nodes[start];
  110.  
  111. repeat
  112. if openH = -1 then
  113. Break;
  114.  
  115. clI := 0;
  116. clD := open[0]^.distance;
  117. for i := 1 to openH do
  118. begin
  119. if open[i]^.distance < clD then
  120. begin
  121. clD := open[i]^.distance;
  122. clI := i;
  123. end;
  124. end;
  125.  
  126. cl := open[clI];
  127.  
  128. Inc(closeH);
  129. closed[closeH] := cl;
  130. open[clI] := open[openH];
  131. Dec(openH);
  132. cl^.closed := True;
  133.  
  134. for i := High(endBoxes) downto 0 do
  135. begin
  136. if (cl^.pos.x >= endBoxes[i].x1) and (cl^.pos.x <= endBoxes[i].x2) then
  137. if (cl^.pos.y >= endBoxes[i].y1) and (cl^.pos.y <= endBoxes[i].y2) then
  138. begin
  139. if sqrt(sqr(cl^.pos.x - ending[i].x) + sqr(cl^.pos.y - ending[i].y)) <= maxdist then
  140. begin
  141. Result := True;
  142. Break;
  143. end;
  144. end;
  145. end;
  146.  
  147. if Result then
  148. Break;
  149.  
  150. if not FindNeighbours(neigh, cl^.index, maxdist) then
  151. Continue;
  152.  
  153. for i := High(neigh) downto 0 do
  154. begin
  155. tmpD := cl^.distance + sqrt(sqr(cl^.pos.x - neigh[i]^.pos.x) + sqr(cl^.pos.y - neigh[i]^.pos.y));
  156.  
  157. if neigh[i]^.open then
  158. begin
  159. if tmpD < neigh[i]^.distance then
  160. begin
  161. neigh[i]^.distance := tmpD;
  162. neigh[i]^.parent := cl;
  163. end;
  164. end
  165. else
  166. begin
  167. neigh[i]^.distance := tmpD;
  168. neigh[i]^.parent := cl;
  169. neigh[i]^.open := True;
  170. Inc(openH);
  171. open[openH] := neigh[i];
  172. end;
  173. end;
  174. until False;
  175.  
  176. if Result then
  177. frmMain.Canvas.MoveTo(ending[i])
  178. else
  179. begin
  180. frmMain.Canvas.MoveTo(cl^.pos.x, cl^.pos.y);
  181. cl := cl^.parent;
  182. frmMain.Canvas.Pen.Color := clRed;
  183. end;
  184.  
  185. while cl <> nil do
  186. begin
  187. frmMain.Canvas.LineTo(cl^.pos.x, cl^.pos.y);
  188. cl := cl^.parent;
  189. end;
  190.  
  191. if not Result then
  192. frmMain.Canvas.Pen.Color := clBlack;
  193. end;
Add Comment
Please, Sign In to add comment