Clipper.RectClip.pas 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656
  1. unit Clipper.RectClip;
  2. (*******************************************************************************
  3. * Author : Angus Johnson *
  4. * Date : 21 October 2022 *
  5. * Website : http://www.angusj.com *
  6. * Copyright : Angus Johnson 2010-2022 *
  7. * Purpose : FAST rectangular clipping *
  8. * License : http://www.boost.org/LICENSE_1_0.txt *
  9. *******************************************************************************)
  10. interface
  11. {$I Clipper.inc}
  12. uses
  13. Classes, Math, SysUtils, Clipper.Core;
  14. type
  15. TLocation = (locLeft, locTop, locRight, locBottom, locInside);
  16. TRectClip = class
  17. protected
  18. fResultCnt : integer;
  19. fCapacity : integer;
  20. fRect : TRect64;
  21. fRectPath : TPath64;
  22. fRectMidPt : TPoint64;
  23. fFirstCrossLoc : TLocation;
  24. fResult : TPath64;
  25. fStartLocs : TList;
  26. procedure Reset;
  27. procedure Add(const pt: TPoint64);
  28. {$IFDEF INLINING} inline; {$ENDIF}
  29. procedure AddCorner(prev, curr: TLocation); overload;
  30. {$IFDEF INLINING} inline; {$ENDIF}
  31. procedure AddCorner(var loc: TLocation; isClockwise: Boolean); overload;
  32. {$IFDEF INLINING} inline; {$ENDIF}
  33. procedure GetNextLocation(const path: TPath64;
  34. var loc: TLocation; var i: integer; highI: integer);
  35. public
  36. constructor Create(const rect: TRect64);
  37. destructor Destroy; override;
  38. function Execute(const path: TPath64): TPath64;
  39. end;
  40. TRectClipLines = class(TRectClip)
  41. private
  42. function GetCurrentPath: TPath64;
  43. public
  44. function Execute(const path: TPath64): TPaths64;
  45. end;
  46. implementation
  47. //------------------------------------------------------------------------------
  48. // Miscellaneous functions
  49. //------------------------------------------------------------------------------
  50. function GetLocation(const rec: TRect64; const pt: TPoint64;
  51. out loc: TLocation): Boolean; {$IFDEF INLINING} inline; {$ENDIF}
  52. begin
  53. Result := false; // only returns false when pt on rect
  54. if (pt.X = rec.Left) and
  55. (pt.Y >= rec.Top) and (pt.Y <= rec.Bottom) then
  56. begin
  57. loc := locLeft;
  58. Exit; //false
  59. end
  60. else if (pt.X = rec.Right) and
  61. (pt.Y >= rec.Top) and (pt.Y <= rec.Bottom) then
  62. begin
  63. loc := locRight;
  64. Exit; //false
  65. end
  66. else if (pt.Y = rec.Top) and
  67. (pt.X >= rec.Left) and (pt.X <= rec.Right) then
  68. begin
  69. loc := locTop;
  70. Exit; //false
  71. end
  72. else if (pt.Y = rec.Bottom) and
  73. (pt.X >= rec.Left) and (pt.X <= rec.Right) then
  74. begin
  75. loc := locBottom;
  76. Exit; //false
  77. end
  78. else if (pt.X < rec.Left) then loc := locLeft
  79. else if (pt.X > rec.Right) then loc := locRight
  80. else if (pt.Y < rec.Top) then loc := locTop
  81. else if (pt.Y > rec.Bottom) then loc := locBottom
  82. else loc := locInside;
  83. Result := true;
  84. end;
  85. //------------------------------------------------------------------------------
  86. function GetIntersection(const rectPath: TPath64;
  87. const p, p2: TPoint64; var loc: TLocation; out ip: TPoint64): Boolean;
  88. begin
  89. // gets the intersection closest to 'p'
  90. // when Result = false, loc will remain unchanged
  91. Result := false;
  92. case loc of
  93. locLeft:
  94. if SegmentsIntersect(p, p2, rectPath[0], rectPath[3], true) then
  95. ip := GetIntersectPoint64(p, p2, rectPath[0], rectPath[3])
  96. else if (p.Y < rectPath[0].Y) and
  97. SegmentsIntersect(p, p2, rectPath[0], rectPath[1], true) then
  98. begin
  99. ip := GetIntersectPoint64(p, p2, rectPath[0], rectPath[1]);
  100. loc := locTop;
  101. end
  102. else if SegmentsIntersect(p, p2, rectPath[2], rectPath[3], true) then
  103. begin
  104. ip := GetIntersectPoint64(p, p2, rectPath[2], rectPath[3]);
  105. loc := locBottom;
  106. end
  107. else Exit;
  108. locRight:
  109. if SegmentsIntersect(p, p2, rectPath[1], rectPath[2], true) then
  110. ip := GetIntersectPoint64(p, p2, rectPath[1], rectPath[2])
  111. else if (p.Y < rectPath[0].Y) and
  112. SegmentsIntersect(p, p2, rectPath[0], rectPath[1], true) then
  113. begin
  114. ip := GetIntersectPoint64(p, p2, rectPath[0], rectPath[1]);
  115. loc := locTop;
  116. end
  117. else if SegmentsIntersect(p, p2, rectPath[2], rectPath[3], true) then
  118. begin
  119. ip := GetIntersectPoint64(p, p2, rectPath[2], rectPath[3]);
  120. loc := locBottom;
  121. end
  122. else Exit;
  123. locTop:
  124. if SegmentsIntersect(p, p2, rectPath[0], rectPath[1], true) then
  125. ip := GetIntersectPoint64(p, p2, rectPath[0], rectPath[1])
  126. else if (p.X < rectPath[0].X) and
  127. SegmentsIntersect(p, p2, rectPath[0], rectPath[3], true) then
  128. begin
  129. ip := GetIntersectPoint64(p, p2, rectPath[0], rectPath[3]);
  130. loc := locLeft;
  131. end
  132. else if (p.X > rectPath[1].X) and
  133. SegmentsIntersect(p, p2, rectPath[1], rectPath[2], true) then
  134. begin
  135. ip := GetIntersectPoint64(p, p2, rectPath[1], rectPath[2]);
  136. loc := locRight;
  137. end
  138. else Exit;
  139. locBottom:
  140. if SegmentsIntersect(p, p2, rectPath[2], rectPath[3], true) then
  141. ip := GetIntersectPoint64(p, p2, rectPath[2], rectPath[3])
  142. else if (p.X < rectPath[3].X) and
  143. SegmentsIntersect(p, p2, rectPath[0], rectPath[3], true) then
  144. begin
  145. ip := GetIntersectPoint64(p, p2, rectPath[0], rectPath[3]);
  146. loc := locLeft;
  147. end
  148. else if (p.X > rectPath[2].X) and
  149. SegmentsIntersect(p, p2, rectPath[1], rectPath[2], true) then
  150. begin
  151. ip := GetIntersectPoint64(p, p2, rectPath[1], rectPath[2]);
  152. loc := locRight;
  153. end
  154. else Exit;
  155. else // loc = rInside
  156. begin
  157. if SegmentsIntersect(p, p2, rectPath[0], rectPath[3], true) then
  158. begin
  159. ip := GetIntersectPoint64(p, p2, rectPath[0], rectPath[3]);
  160. loc := locLeft;
  161. end else if SegmentsIntersect(p, p2, rectPath[0], rectPath[1], true) then
  162. begin
  163. ip := GetIntersectPoint64(p, p2, rectPath[0], rectPath[1]);
  164. loc := locTop;
  165. end
  166. else if SegmentsIntersect(p, p2, rectPath[1], rectPath[2], true) then
  167. begin
  168. ip := GetIntersectPoint64(p, p2, rectPath[1], rectPath[2]);
  169. loc := locRight;
  170. end
  171. else if SegmentsIntersect(p, p2, rectPath[2], rectPath[3], true) then
  172. begin
  173. ip := GetIntersectPoint64(p, p2, rectPath[2], rectPath[3]);
  174. loc := locBottom;
  175. end
  176. else Exit;
  177. end;
  178. end;
  179. Result := true;
  180. end;
  181. //------------------------------------------------------------------------------
  182. function AreOpposites(prev, curr: TLocation): Boolean;
  183. {$IFDEF INLINING} inline; {$ENDIF}
  184. begin
  185. Result := Abs(Ord(prev) - Ord(curr)) = 2;
  186. end;
  187. //------------------------------------------------------------------------------
  188. function HeadingClockwise(prev, curr: TLocation): Boolean;
  189. {$IFDEF INLINING} inline; {$ENDIF}
  190. begin
  191. Result := (Ord(prev) + 1) mod 4 = Ord(curr);
  192. end;
  193. //------------------------------------------------------------------------------
  194. function GetAdjacentLocation(loc: TLocation; isClockwise: Boolean): TLocation;
  195. {$IFDEF INLINING} inline; {$ENDIF}
  196. var
  197. delta: integer;
  198. begin
  199. if isClockwise then delta := 1 else delta := 3;
  200. Result := TLocation((Ord(loc) + delta) mod 4);
  201. end;
  202. //------------------------------------------------------------------------------
  203. function IsClockwise(prev, curr: TLocation;
  204. const prevPt, currPt, rectMidPt: TPoint64): Boolean;
  205. {$IFDEF INLINING} inline; {$ENDIF}
  206. begin
  207. if AreOpposites(prev, curr) then
  208. Result := CrossProduct(prevPt, rectMidPt, currPt) < 0 else
  209. Result := HeadingClockwise(prev, curr);
  210. end;
  211. //------------------------------------------------------------------------------
  212. // TRectClip class
  213. //------------------------------------------------------------------------------
  214. constructor TRectClip.Create(const rect: TRect64);
  215. begin
  216. fRect := rect;
  217. fRectPath := fRect.AsPath;
  218. fRectMidPt := rect.MidPoint;
  219. fStartLocs := TList.Create;
  220. end;
  221. //------------------------------------------------------------------------------
  222. destructor TRectClip.Destroy;
  223. begin
  224. fStartLocs.Free;
  225. end;
  226. //------------------------------------------------------------------------------
  227. procedure TRectClip.Reset;
  228. begin
  229. fResultCnt := 0;
  230. fCapacity := 0;
  231. fResult := nil;
  232. end;
  233. //------------------------------------------------------------------------------
  234. procedure TRectClip.Add(const pt: TPoint64);
  235. begin
  236. if fResultCnt = fCapacity then
  237. begin
  238. inc(fCapacity, 32);
  239. SetLength(fResult, fCapacity);
  240. end;
  241. fResult[fResultCnt] := pt;
  242. inc(fResultCnt);
  243. end;
  244. //------------------------------------------------------------------------------
  245. procedure TRectClip.AddCorner(prev, curr: TLocation);
  246. begin
  247. if (HeadingClockwise(prev, curr)) then
  248. Add(fRectPath[Ord(prev)]) else
  249. Add(fRectPath[Ord(curr)]);
  250. end;
  251. //------------------------------------------------------------------------------
  252. procedure TRectClip.AddCorner(var loc: TLocation; isClockwise: Boolean);
  253. begin
  254. if (isClockwise) then
  255. begin
  256. Add(fRectPath[Ord(loc)]);
  257. loc := GetAdjacentLocation(loc, true);
  258. end else
  259. begin
  260. loc := GetAdjacentLocation(loc, false);
  261. Add(fRectPath[Ord(loc)]);
  262. end;
  263. end;
  264. //------------------------------------------------------------------------------
  265. procedure TRectClip.GetNextLocation(const path: TPath64;
  266. var loc: TLocation; var i: integer; highI: integer);
  267. begin
  268. case loc of
  269. locLeft:
  270. begin
  271. while (i <= highI) and (path[i].X <= fRect.Left) do inc(i);
  272. if (i > highI) then Exit;
  273. if path[i].X >= fRect.Right then loc := locRight
  274. else if path[i].Y <= fRect.Top then loc := locTop
  275. else if path[i].Y >= fRect.Bottom then loc := locBottom
  276. else loc := locInside;
  277. end;
  278. locTop:
  279. begin
  280. while (i <= highI) and (path[i].Y <= fRect.Top) do inc(i);
  281. if (i > highI) then Exit;
  282. if path[i].Y >= fRect.Bottom then loc := locBottom
  283. else if path[i].X <= fRect.Left then loc := locLeft
  284. else if path[i].X >= fRect.Right then loc := locRight
  285. else loc := locInside;
  286. end;
  287. locRight:
  288. begin
  289. while (i <= highI) and (path[i].X >= fRect.Right) do inc(i);
  290. if (i > highI) then Exit;
  291. if path[i].X <= fRect.Left then loc := locLeft
  292. else if path[i].Y <= fRect.Top then loc := locTop
  293. else if path[i].Y >= fRect.Bottom then loc := locBottom
  294. else loc := locInside;
  295. end;
  296. locBottom:
  297. begin
  298. while (i <= highI) and (path[i].Y >= fRect.Bottom) do inc(i);
  299. if (i > highI) then Exit;
  300. if path[i].Y <= fRect.Top then loc := locTop
  301. else if path[i].X <= fRect.Left then loc := locLeft
  302. else if path[i].X >= fRect.Right then loc := locRight
  303. else loc := locInside;
  304. end;
  305. locInside:
  306. begin
  307. while (i <= highI) do
  308. begin
  309. if path[i].X < fRect.Left then loc := locLeft
  310. else if path[i].X > fRect.Right then loc := locRight
  311. else if path[i].Y > fRect.Bottom then loc := locBottom
  312. else if path[i].Y < fRect.Top then loc := locTop
  313. else begin Add(path[i]); inc(i); continue; end;
  314. break; //inner loop
  315. end;
  316. end;
  317. end;
  318. end;
  319. //------------------------------------------------------------------------------
  320. function Path1ContainsPath2(const path1, path2: TPath64): TPointInPolygonResult;
  321. var
  322. i: integer;
  323. begin
  324. Result := pipOutside;
  325. for i := 0 to High(path2) do
  326. begin
  327. Result := PointInPolygon(path2[i], path1);
  328. if Result <> pipOn then break;
  329. end;
  330. end;
  331. //------------------------------------------------------------------------------
  332. function TRectClip.Execute(const path: TPath64): TPath64;
  333. var
  334. i,k, highI : integer;
  335. prevPt,ip,ip2 : TPoint64;
  336. loc, prev : TLocation;
  337. loc2 : TLocation;
  338. startingLoc : TLocation;
  339. crossingLoc : TLocation;
  340. prevCrossLoc : TLocation;
  341. tmpRect : TRect64;
  342. isClockw : Boolean;
  343. begin
  344. Result := nil;
  345. if (Length(path) < 3) or fRect.IsEmpty then Exit;
  346. Reset;
  347. i := 0;
  348. fStartLocs.Clear;
  349. highI := Length(path) -1;
  350. crossingLoc := locInside;
  351. fFirstCrossLoc := locInside;
  352. if not GetLocation(fRect, path[highI], loc) then
  353. begin
  354. i := highI - 1;
  355. while (i >= 0) and
  356. not GetLocation(fRect, path[i], prev) do
  357. dec(i);
  358. if (i < 0) then
  359. begin
  360. Result := path;
  361. Exit;
  362. end;
  363. if (prev = locInside) then
  364. loc := locInside;
  365. i := 0;
  366. end;
  367. startingLoc := loc;
  368. ///////////////////////////////////////////////////
  369. while i <= highI do
  370. begin
  371. prev := loc;
  372. prevCrossLoc := crossingLoc;
  373. GetNextLocation(path, loc, i, highI);
  374. if i > highI then Break;
  375. if i = 0 then
  376. prevPt := path[highI] else
  377. prevPt := path[i-1];
  378. crossingLoc := loc;
  379. if not GetIntersection(fRectPath, path[i], prevPt, crossingLoc, ip) then
  380. begin
  381. // ie remains outside (and crossingLoc still == loc)
  382. if (prevCrossLoc = locInside) then //ie rect still uncrossed
  383. begin
  384. isClockw := IsClockwise(prev, loc, prevPt, path[i], fRectMidPt);
  385. repeat
  386. fStartLocs.Add(Pointer(prev));
  387. prev := GetAdjacentLocation(prev, isClockw);
  388. until prev = loc;
  389. crossingLoc := prevCrossLoc; // because still not crossed
  390. end
  391. else if (prev <> locInside) and (prev <> loc) then
  392. begin
  393. isClockw := IsClockwise(prev, loc, prevPt, path[i], fRectMidPt);
  394. repeat
  395. AddCorner(prev, isClockw);
  396. until prev = loc;
  397. end;
  398. inc(i);
  399. Continue;
  400. end;
  401. ////////////////////////////////////////////////////
  402. // we must be crossing the rect boundary to get here
  403. ////////////////////////////////////////////////////
  404. if (loc = locInside) then // path must be entering rect
  405. begin
  406. if (fFirstCrossLoc = locInside) then
  407. begin
  408. fFirstCrossLoc := crossingLoc;
  409. fStartLocs.Add(Pointer(prev));
  410. end
  411. else if (prev <> crossingLoc) then
  412. begin
  413. isClockw := IsClockwise(prev, crossingLoc, prevPt, path[i], fRectMidPt);
  414. repeat
  415. AddCorner(prev, isClockw);
  416. until prev = crossingLoc;
  417. end;
  418. end
  419. else if (prev <> locInside) then
  420. begin
  421. // passing right through rect. 'ip' here will be the second
  422. // intersect pt but we'll also need the first intersect pt (ip2)
  423. loc := prev;
  424. GetIntersection(fRectPath, prevPt, path[i], loc, ip2);
  425. if (prevCrossLoc <> locInside) then
  426. AddCorner(prevCrossLoc, loc);
  427. if (fFirstCrossLoc = locInside) then
  428. begin
  429. fFirstCrossLoc := loc;
  430. fStartLocs.Add(Pointer(prev));
  431. end;
  432. loc := crossingLoc;
  433. Add(ip2);
  434. if PointsEqual(ip, ip2) then
  435. begin
  436. // it's very likely that path[i] is on rect
  437. GetLocation(fRect, path[i], loc);
  438. AddCorner(crossingLoc, loc);
  439. crossingLoc := loc;
  440. Continue;
  441. end;
  442. end else // path must be exiting rect
  443. begin
  444. loc := crossingLoc;
  445. if (fFirstCrossLoc = locInside) then
  446. fFirstCrossLoc := crossingLoc;
  447. end;
  448. Add(ip);
  449. end; //while i <= highI
  450. ///////////////////////////////////////////////////
  451. if (fFirstCrossLoc = locInside) then
  452. begin
  453. // path never intersects with rect
  454. if startingLoc <> locInside then
  455. begin
  456. // path is outside rect but may or may not contain rect
  457. tmpRect := GetBounds(path);
  458. if tmpRect.Contains(fRect) and
  459. (Path1ContainsPath2(path, fRectPath) <> pipOutside) then
  460. Result := fRectPath
  461. else
  462. result := nil;
  463. end
  464. else Result := path;
  465. Exit;
  466. end;
  467. if (loc <> locInside) and
  468. ((loc <> fFirstCrossLoc) or (fStartLocs.Count > 2)) then
  469. begin
  470. if (fStartLocs.Count > 0) then
  471. begin
  472. prev := loc;
  473. for i := 0 to fStartLocs.Count -1 do
  474. begin
  475. loc2 := TLocation(fStartLocs[i]);
  476. if (prev = loc2) then Continue;
  477. AddCorner(prev, HeadingClockwise(prev, loc2));
  478. prev := loc2;
  479. end;
  480. loc := prev;
  481. end;
  482. if (loc <> fFirstCrossLoc) then
  483. AddCorner(loc, HeadingClockwise(loc, fFirstCrossLoc));
  484. end;
  485. if fResultCnt < 3 then Exit;
  486. // tidy up duplicates and collinear segments
  487. SetLength(Result, fResultCnt);
  488. k := 0;
  489. prevPt := fResult[fResultCnt -1];
  490. Result[0] := fResult[0];
  491. for i := 1 to fResultCnt -1 do
  492. if CrossProduct(prevPt, Result[k], fResult[i]) = 0 then
  493. begin
  494. Result[k] := fResult[i];
  495. end else
  496. begin
  497. prevPt := Result[k];
  498. inc(k);
  499. Result[k] := fResult[i];
  500. end;
  501. if k < 2 then
  502. Result := nil
  503. // and a final check for collinearity
  504. else if CrossProduct(Result[0], Result[k-1], Result[k]) = 0 then
  505. SetLength(Result, k)
  506. else
  507. SetLength(Result, k +1);
  508. end;
  509. //------------------------------------------------------------------------------
  510. // TRectClipLines
  511. //------------------------------------------------------------------------------
  512. function TRectClipLines.GetCurrentPath: TPath64;
  513. begin
  514. SetLength(fResult, fResultCnt);
  515. Result := fResult;
  516. Reset;
  517. end;
  518. //------------------------------------------------------------------------------
  519. function TRectClipLines.Execute(const path: TPath64): TPaths64;
  520. var
  521. i, highI : integer;
  522. resCnt : integer;
  523. prevPt,ip,ip2 : TPoint64;
  524. loc, prev : TLocation;
  525. crossingLoc : TLocation;
  526. begin
  527. resCnt := 0;
  528. Result := nil;
  529. if (Length(path) < 2) or fRect.IsEmpty then Exit;
  530. Reset;
  531. i := 1;
  532. highI := Length(path) -1;
  533. if not GetLocation(fRect, path[0], loc) then
  534. begin
  535. while (i <= highI) and
  536. not GetLocation(fRect, path[i], prev) do
  537. inc(i);
  538. if (i > highI) then
  539. begin
  540. SetLength(Result, 1);
  541. Result[0] := path;
  542. Exit;
  543. end;
  544. if (prev = locInside) then
  545. loc := locInside;
  546. i := 1;
  547. end;
  548. if loc = locInside then Add(path[0]);
  549. ///////////////////////////////////////////////////
  550. while i <= highI do
  551. begin
  552. prev := loc;
  553. GetNextLocation(path, loc, i, highI);
  554. if i > highI then Break;
  555. prevPt := path[i-1];
  556. crossingLoc := loc;
  557. if not GetIntersection(fRectPath, path[i], prevPt, crossingLoc, ip) then
  558. begin
  559. // must be remaining outside
  560. inc(i);
  561. Continue;
  562. end;
  563. ////////////////////////////////////////////////////
  564. // we must be crossing the rect boundary to get here
  565. ////////////////////////////////////////////////////
  566. if (loc = locInside) then // path must be entering rect
  567. begin
  568. Add(ip);
  569. end
  570. else if (prev <> locInside) then
  571. begin
  572. // passing right through rect. 'ip' here will be the second
  573. // intersect pt but we'll also need the first intersect pt (ip2)
  574. crossingLoc := prev;
  575. GetIntersection(fRectPath, prevPt, path[i], crossingLoc, ip2);
  576. Add(ip2);
  577. Add(ip);
  578. inc(resCnt);
  579. SetLength(Result, resCnt);
  580. Result[resCnt -1] := GetCurrentPath;
  581. end else // path must be exiting rect
  582. begin
  583. Add(ip);
  584. inc(resCnt);
  585. SetLength(Result, resCnt);
  586. Result[resCnt -1] := GetCurrentPath;
  587. end;
  588. end; //while i <= highI
  589. ///////////////////////////////////////////////////
  590. if fResultCnt > 1 then
  591. begin
  592. inc(resCnt);
  593. SetLength(Result, resCnt);
  594. Result[resCnt -1] := GetCurrentPath;
  595. end;
  596. SetLength(Result, resCnt);
  597. end;
  598. //------------------------------------------------------------------------------
  599. //------------------------------------------------------------------------------
  600. end.