Mmptlist.pas
上传用户:hylc_2004
上传日期:2014-01-23
资源大小:46800k
文件大小:14k
源码类别:

Delphi控件源码

开发平台:

Delphi

  1. {========================================================================}
  2. {=                (c) 1995-98 SwiftSoft Ronald Dittrich                 =}
  3. {========================================================================}
  4. {=                          All Rights Reserved                         =}
  5. {========================================================================}
  6. {=  D 01099 Dresden             = Tel.: +0351-8012255                   =}
  7. {=  Loewenstr.7a                = info@swiftsoft.de                     =}
  8. {========================================================================}
  9. {=  Actual versions on http://www.swiftsoft.de/mmtools.html             =}
  10. {========================================================================}
  11. {=  This code is for reference purposes only and may not be copied or   =}
  12. {=  distributed in any format electronic or otherwise except one copy   =}
  13. {=  for backup purposes.                                                =}
  14. {=                                                                      =}
  15. {=  No Delphi Component Kit or Component individually or in a collection=}
  16. {=  subclassed or otherwise from the code in this unit, or associated   =}
  17. {=  .pas, .dfm, .dcu, .asm or .obj files may be sold or distributed     =}
  18. {=  without express permission from SwiftSoft.                          =}
  19. {=                                                                      =}
  20. {=  For more licence informations please refer to the associated        =}
  21. {=  HelpFile.                                                           =}
  22. {========================================================================}
  23. {=  $Date: 20.01.1998 - 18:00:00 $                                      =}
  24. {========================================================================}
  25. unit MMPtList;
  26. {$I COMPILER.INC}
  27. interface
  28. uses          
  29. {$IFDEF WIN32}
  30.   Windows,
  31. {$ELSE}
  32.   WinProcs,
  33.   WinTypes,
  34. {$ENDIF}
  35.   SysUtils,
  36.   Classes,
  37.   MMObj,
  38.   MMMuldiv,
  39.   MMUtils;
  40. type
  41.   PMMPoint = ^TMMPoint;
  42.   TMMPoint = record
  43.     X: Longint;
  44.     Y: Longint;
  45.   end;
  46. const
  47.   { Maximum List size }
  48.   MaxListSize   = Maxint div (sizeOf(TMMPoint)*sizeOf(TMMPoint));
  49. type
  50.   PMMPointArray = ^TMMPointArray;
  51.   TMMPointArray = array[0..MaxListSize-1] of TMMPoint;
  52.   TMMPointList = class(TMMObject)
  53.   private
  54.     FList     : PMMPointArray;
  55.     FCount    : Integer;
  56.     FCapacity : Integer;
  57.   protected
  58.     procedure Error; virtual;
  59.     procedure Grow; virtual;
  60.     function  Get(Index: Integer): PMMPoint;
  61.     procedure Put(Index: Integer; Point: PMMPoint);
  62.     procedure SetCapacity(NewCapacity: Integer);
  63.     procedure SetCount(NewCount: Integer);
  64.   public
  65.     constructor Create; virtual;
  66.     destructor Destroy; override;
  67.     procedure  Clear; virtual;
  68.     procedure  Assign(Source: TPersistent);
  69.     function   Add(Point: TMMPoint): Integer;
  70.     procedure  Insert(Index: Integer; Point: TMMPoint);
  71.     procedure  Exchange(Index1, Index2: Integer);
  72.     procedure  Move(CurIndex, NewIndex: Integer);
  73.     function   Remove(Point: PMMPoint): Integer;
  74.     procedure  Delete(Index: Integer);
  75.     function   IndexOf(Point: PMMPoint): Integer;
  76.     function   LocatePointX(X: Longint): integer;
  77.     function   LocatePointY(Y: Longint): integer;
  78.     function   CalcX(Y: Longint): Longint;
  79.     function   CalcY(X: Longint): Longint;
  80.     procedure  SortByX;
  81.     procedure  SortByY;
  82.     function   First: PMMPoint;
  83.     function   Last: PMMPoint;
  84.     function   Expand: TMMPointList;
  85.     property   Capacity: Integer read FCapacity write SetCapacity;
  86.     property   Count: Integer read FCount write SetCount;
  87.     property   Points[Index: Integer]: PMMPoint read Get write Put; default;
  88.     property   List: PMMPointArray read FList;
  89.   end;
  90. function  ComparePoints(Point1,Point2: PMMPoint): Boolean;
  91. function  LocateX(Points: PMMPointArray; NumPoints: integer; X: Longint): integer;
  92. function  LocateY(Points: PMMPointArray; NumPoints: integer; Y: Longint): integer;
  93. procedure SortX(Points: PMMPointArray; NumPoints: integer);
  94. procedure SortY(Points: PMMPointArray; NumPoints: integer);
  95. implementation
  96. uses consts;
  97. {------------------------------------------------------------------------}
  98. procedure ListError(Ident: Integer);
  99. begin
  100.    raise EListError.CreateRes(Ident);
  101. end;
  102. {------------------------------------------------------------------------}
  103. procedure ListIndexError;
  104. begin
  105.    ListError(SListIndexError);
  106. end;
  107. {------------------------------------------------------------------------}
  108. function ComparePoints(Point1,Point2: PMMPoint): Boolean;
  109. begin
  110.    Result := (Point1^.X = Point2^.X) and (Point1^.Y = Point2^.Y);
  111. end;
  112. {------------------------------------------------------------------------}
  113. function LocateX(Points: PMMPointArray; NumPoints: integer; X: Longint): integer;
  114. var
  115.    L, H : integer;
  116. begin
  117.    if (NumPoints = 0) then
  118.    begin
  119.       Result := -1;
  120.    end
  121.    else
  122.    begin
  123.       if Points^[NumPoints-1].X <= X then
  124.       begin
  125.          Result := NumPoints;
  126.       end
  127.       else
  128.       begin
  129.          L := 0;
  130.          H := NumPoints-1;
  131.          Result := H shr 1;
  132.          while L < H do
  133.          begin
  134.             if Points^[Result].X <= X then
  135.                L := Result+1
  136.             else
  137.                H := Result;
  138.             Result := (L + H) shr 1;
  139.          end;
  140.       end;
  141.    end;
  142. end;
  143. {------------------------------------------------------------------------}
  144. function LocateY(Points: PMMPointArray; NumPoints: integer; Y: Longint): integer;
  145. var
  146.    L, H : integer;
  147. begin
  148.    if (NumPoints = 0) then
  149.    begin
  150.       Result := -1;
  151.    end
  152.    else
  153.    begin
  154.       if Points^[NumPoints-1].Y <= Y then
  155.       begin
  156.          Result := NumPoints;
  157.       end
  158.       else
  159.       begin
  160.          L := 0;
  161.          H := NumPoints-1;
  162.          Result := H shr 1;
  163.          while L < H do
  164.          begin
  165.             if Points^[Result].Y <= Y then
  166.                L := Result+1
  167.             else
  168.                H := Result;
  169.             Result := (L + H) shr 1;
  170.          end;
  171.       end;
  172.    end;
  173. end;
  174. {------------------------------------------------------------------------}
  175. procedure SortX(Points: PMMPointArray; NumPoints: integer);
  176. var
  177.    i,j,h: integer;
  178.    p: TMMPoint;
  179. begin          // Start Shell-Sort
  180.    h := 1;
  181.    while h <= NumPoints div 9 do h := h*3 + 1;
  182.    while h > 0 do
  183.    begin
  184.       for i := h to NumPoints-1 do
  185.       begin
  186.          p := Points^[i];
  187.          j := i;
  188.          while ( j >= h ) and (Points^[j-h].X > p.X) do
  189.          begin
  190.             Points^[j] := Points^[j-h];
  191.             dec(j, h);
  192.          end;
  193.          Points^[j] := p;
  194.       end;
  195.       h := h div 3;
  196.    end;
  197. end;
  198. {------------------------------------------------------------------------}
  199. procedure SortY(Points: PMMPointArray; NumPoints: integer);
  200. var
  201.    i,j,h: integer;
  202.    p: TMMPoint;
  203. begin          // Start Shell-Sort
  204.    h := 1;
  205.    while h <= NumPoints div 9 do h := h*3 + 1;
  206.    while h > 0 do
  207.    begin
  208.       for i := h to NumPoints-1 do
  209.       begin
  210.          p := Points^[i];
  211.          j := i;
  212.          while ( j >= h ) and (Points^[j-h].Y > p.Y) do
  213.          begin
  214.             Points^[j] := Points^[j-h];
  215.             dec(j, h);
  216.          end;
  217.          Points^[j] := p;
  218.       end;
  219.       h := h div 3;
  220.    end;
  221. end;
  222. {== TMMPointList ========================================================}
  223. constructor TMMPointList.Create;
  224. begin
  225.    inherited Create;
  226. end;
  227. {-- TMMPointList --------------------------------------------------------}
  228. destructor TMMPointList.Destroy;
  229. begin
  230.    Clear;
  231.    inherited Destroy;
  232. end;
  233. {-- TMMPointList --------------------------------------------------------}
  234. procedure TMMPointList.Error;
  235. begin
  236.    ListIndexError;
  237. end;
  238. {-- TMMPointList --------------------------------------------------------}
  239. function TMMPointList.Add(Point: TMMPoint): Integer;
  240. begin
  241.    Result := FCount;
  242.    if Result = FCapacity then Grow;
  243.    FList^[Result] := Point;
  244.    Inc(FCount);
  245. end;
  246. {-- TMMPointList --------------------------------------------------------}
  247. procedure TMMPointList.Clear;
  248. begin
  249.    SetCount(0);
  250.    SetCapacity(0);
  251. end;
  252. {-- TMMPointList --------------------------------------------------------}
  253. procedure TMMPointList.Delete(Index: Integer);
  254. begin
  255.    if (Index < 0) or (Index >= FCount) then Error;
  256.    Dec(FCount);
  257.    if Index < FCount then
  258.      System.Move(FList^[Index + 1], FList^[Index],
  259.                  (FCount - Index) * SizeOf(TMMPoint));
  260. end;
  261. {-- TMMPointList --------------------------------------------------------}
  262. procedure TMMPointList.Exchange(Index1, Index2: Integer);
  263. var
  264.   Point: TMMPoint;
  265. begin
  266.    if (Index1 < 0) or (Index1 >= FCount) or
  267.       (Index2 < 0) or (Index2 >= FCount) then Error;
  268.    Point := FList^[Index1];
  269.    FList^[Index1] := FList^[Index2];
  270.    FList^[Index2] := Point;
  271. end;
  272. {-- TMMPointList --------------------------------------------------------}
  273. function TMMPointList.Expand: TMMPointList;
  274. begin
  275.    if FCount = FCapacity then Grow;
  276.    Result := Self;
  277. end;
  278. {-- TMMPointList --------------------------------------------------------}
  279. function TMMPointList.First: PMMPoint;
  280. begin
  281.    Result := Get(0);
  282. end;
  283. {-- TMMPointList --------------------------------------------------------}
  284. function TMMPointList.Get(Index: Integer): PMMPoint;
  285. begin
  286.    if (Index < 0) or (Index >= FCount) then Error;
  287.    Result := @FList^[Index];
  288. end;
  289. {-- TMMPointList --------------------------------------------------------}
  290. procedure TMMPointList.Grow;
  291. var
  292.   Delta: Integer;
  293. begin
  294.    if FCapacity > 8 then
  295.       Delta := 16
  296.    else if FCapacity > 4 then
  297.       Delta := 8
  298.    else
  299.       Delta := 4;
  300.   SetCapacity(FCapacity + Delta);
  301. end;
  302. {-- TMMPointList --------------------------------------------------------}
  303. function TMMPointList.IndexOf(Point: PMMPoint): Integer;
  304. begin
  305.    Result := 0;
  306.    while (Result < FCount) and not ComparePoints(@FList^[Result],Point) do Inc(Result);
  307.    if Result = FCount then Result := -1;
  308. end;
  309. {-- TMMPointList --------------------------------------------------------}
  310. procedure TMMPointList.Insert(Index: Integer; Point: TMMPoint);
  311. begin
  312.    if (Index < 0) or (Index > FCount) then Error;
  313.    if FCount = FCapacity then Grow;
  314.    if Index < FCount then
  315.       System.Move(FList^[Index], FList^[Index + 1],
  316.                  (FCount - Index) * SizeOf(TMMPoint));
  317.    FList^[Index] := Point;
  318.    Inc(FCount);
  319. end;
  320. {-- TMMPointList --------------------------------------------------------}
  321. function TMMPointList.Last: PMMPoint;
  322. begin
  323.    Result := Get(FCount-1);
  324. end;
  325. {-- TMMPointList --------------------------------------------------------}
  326. procedure TMMPointList.Move(CurIndex, NewIndex: Integer);
  327. var
  328.   Point: TMMPoint;
  329. begin
  330.    if CurIndex <> NewIndex then
  331.    begin
  332.       if (NewIndex < 0) or (NewIndex >= FCount) then Error;
  333.       Point := Get(CurIndex)^;
  334.       Delete(CurIndex);
  335.       Insert(NewIndex, Point);
  336.    end;
  337. end;
  338. {-- TMMPointList --------------------------------------------------------}
  339. procedure TMMPointList.Put(Index: Integer; Point: PMMPoint);
  340. begin
  341.    if (Index < 0) or (Index >= FCount) then Error;
  342.    FList^[Index] := Point^;
  343. end;
  344. {-- TMMPointList --------------------------------------------------------}
  345. function TMMPointList.Remove(Point: PMMPoint): Integer;
  346. begin
  347.    Result := IndexOf(Point);
  348.    if Result <> -1 then Delete(Result);
  349. end;
  350. {-- TMMPointList --------------------------------------------------------}
  351. procedure TMMPointList.SetCapacity(NewCapacity: Integer);
  352. begin
  353.    if (NewCapacity < FCount) or (NewCapacity > MaxListSize) then Error;
  354.    if NewCapacity <> FCapacity then
  355.    begin
  356.      ReallocMem(FList, NewCapacity * SizeOf(TMMPoint));
  357.      FCapacity := NewCapacity;
  358.    end;
  359. end;
  360. {-- TMMPointList --------------------------------------------------------}
  361. procedure TMMPointList.SetCount(NewCount: Integer);
  362. begin
  363.    if (NewCount < 0) or (NewCount > MaxListSize) then Error;
  364.    if NewCount > FCapacity then SetCapacity(NewCount);
  365.    if NewCount > FCount then
  366.       FillChar(FList^[FCount], (NewCount - FCount) * SizeOf(TMMPoint), 0);
  367.    FCount := NewCount;
  368. end;
  369. {-- TMMPointList --------------------------------------------------------}
  370. procedure TMMPointList.Assign(Source: TPersistent);
  371. var
  372.    i: integer;
  373.    p: TMMPoint;
  374. begin
  375.    if (Source is TMMPointList) or (Source = nil) then
  376.    begin
  377.       Clear;
  378.       if (Source <> nil) then
  379.       begin
  380.          for i := 0 to TMMPointList(Source).Count-1 do
  381.          begin
  382.             p := TMMPointList(Source).Points[i]^;
  383.             Add(p);
  384.          end;
  385.          SortByX;
  386.       end;
  387.    end
  388.    else inherited assign(Source);
  389. end;
  390. {-- TMMPointList --------------------------------------------------------}
  391. function TMMPointList.CalcX(Y: Longint): Longint;
  392. var
  393.    i: integer;
  394. begin
  395.    // TODO : exception
  396.    { liste must be sorted }
  397.    i := LocatePointY(Y);
  398.    if (i > 0) then
  399.    begin
  400.       i := Min(i,Count-1);
  401.       Result := RangeScale(Y,Points[i-1].Y,Points[i].Y,Points[i-1].X,Points[i].X);
  402.    end
  403.    else Result := 0;
  404. end;
  405. {-- TMMPointList --------------------------------------------------------}
  406. function TMMPointList.CalcY(X: Longint): Longint;
  407. var
  408.    i: integer;
  409. begin
  410.    // TODO : exception
  411.    { liste must be sorted }
  412.    i := LocatePointX(X);
  413.    if (i > 0) then
  414.    begin
  415.       i := Min(i,Count-1);
  416.       Result := RangeScale(X,Points[i-1].X,Points[i].X,Points[i-1].Y,Points[i].Y);
  417.    end
  418.    else Result := 0;
  419. end;
  420. {-- TMMPointList --------------------------------------------------------}
  421. function TMMPointList.LocatePointX(X: Longint): integer;
  422. { LocatePoint returns the Index of the first point, which lies right   }
  423. { from X. Is the list empty -1, is there no other element Count(!)     }
  424. begin
  425.    // TODO : exception
  426.    { liste must be sorted }
  427.    Result := LocateX(List,Count,X);
  428. end;
  429. {-- TMMPointList --------------------------------------------------------}
  430. function TMMPointList.LocatePointY(Y: Longint): integer;
  431. { LocatePoint returns the Index of the first point, which lies above   }
  432. { from Y. Is the list empty -1, is there no other element Count(!)     }
  433. begin
  434.    Result := LocateY(List,Count,Y);
  435. end;
  436. {-- TMMPointList --------------------------------------------------------}
  437. procedure TMMPointList.SortByX;
  438. begin
  439.    SortX(List,Count);
  440. end;
  441. {-- TMMPointList --------------------------------------------------------}
  442. procedure TMMPointList.SortByY;
  443. begin
  444.    SortY(List,Count);
  445. end;
  446. end.