GARANTIR DESCONTO

Fórum TList.Sort #207583

19/01/2004

0

estou com problemas com esse Sort

ao código:

tenho um registro:
  
type

  TLayerLevel = ( yllLowest, yllLow, yllNormal, yllHigh, yllHighest );

  PBufferData = ^TBufferData;
  TBufferData = record
    ...........
    Layer: TLayerLevel;
    Z: Single;
    case Integer of
     .........
  end;

  PBufferList = ^TBufferList;
  TBufferList = array[0..MaxInt div SizeOf( TBufferData ) - 1] of TBufferData;


e tenho um Buffer:
[color=green:d1c8fc429c]Buffer: PBufferList;[/color:d1c8fc429c]
e tambem isto:
[color=green:d1c8fc429c]DrawList: TList;[/color:d1c8fc429c]

que eu altero o tamanho assim:
ReallocMem( Buffer, NewCapacity * SizeOf( TBufferData ) );

por compatibilidade com o Delphi3

tem uma hora, que preciso ordenar o Buffer pelo [i:d1c8fc429c]Layer[/i:d1c8fc429c] e pelo [i:d1c8fc429c]Z[/i:d1c8fc429c]

estou fazendo assim:

procedure TyBuffer.SortBuffer;
var
  I: Integer;
begin
  DrawList.Count := BufferSize;
  for I := 0 to BufferSize - 1 do
    DrawList.List[I] := @Buffer[I];
  DrawList.Sort( Compare );
end;


e a função de comparação:

unction Compare( _Item1, _Item2: Pointer ): Integer;
var
  Item1: PBufferData;
  Item2: PBufferData;
begin
  Item1 := _Item1;
  Item2 := _Item2;
  if Item1.Layer > Item2.Layer then
    Result := 1
  else if Item1.Layer < Item2.Layer then
    Result := -1
  else
    if Item1.Z > Item2.Z then
      Result := 1
    else if Item1.Z < Item2.Z then
      Result := -1
    else
      Result := 0;
end;


[b:d1c8fc429c]mas o problema é que, eu não sei usar essa função compare direito[/b:d1c8fc429c]

pelo que vi, ela tem que retornar um valor maios que zero, ou menor [u:d1c8fc429c]ou zero?[/u:d1c8fc429c]

a função acima funciona em partes, ordena a lista pelo [i:d1c8fc429c]layer[/i:d1c8fc429c], seguido pelo [i:d1c8fc429c]Z[/i:d1c8fc429c], mas quando a dois ou mais itens na lista que estão no mesmo layer e possuem o mesmo valor para Z, queria preservar a ordem com que os itens foram inseridos,é é isso que não está acontecendo. ´Bagunça´ a posição dos Itens

Será que alguém poderia me ajudar, caso não tenha sido claro na explicação, eu deescrevo o problema com mais detalhes.

Obrigado pela atenção :P


Marcelo Saviski

Marcelo Saviski

Responder

Post mais votado

19/01/2004

Valew Fabio.HC, vou testar quando chegar em casa.

Brigadão pelas dica :mrgreen:

só complementado, isso é para ser usado em conjunto com um ´canvas´ próprio, com DirectX, como o ZBuffer do DirectX não funciona na minha máquina, nem na de um camarada, tivemos que implementar isso no braço, para agrupar as imagens por layer e ordenalas pela profundidade

a parte principal do código:

  PBufferData = ^TBufferData;
  TBufferData = record
    pTexture: ^IDirect3DTexture8
    BufferType: TBufferType;
    Layer: TLayerLevel;
    Z: Single;
  end;
  PBufferList = ^TBufferList;
  TBufferList = array[0..MaxInt div SizeOf( TBufferData ) - 1] of TBufferData;


tenho uma classe para controlar o Buffer de Imagens

  TyBuffer = class
  protected
    procedure GrowBuffer;  //Isso aqui aumenta o tamanho do array
    procedure SortBuffer;  //Isso ordena
  public
    BufferSize, BufferCapacity: Cardinal;  {quantidade de imagens que foram adicionadas }
    Buffer: PBufferList; {Aqui as imagens vão sendo colocadas desordenadamente }
    DrawList: TList; //Usado para Ordenar
    procedure ClearBuffer;
  end;


tentei fazer várias funções para ordenar o array, mas de todas, a melhor foi a Sort do TList (performance)


A parte principal está aqui:
function Compare( _Item1, _Item2: Pointer ): Integer;
var
  Item1: PBufferData;
  Item2: PBufferData;
begin
  Item1 := _Item1;
  Item2 := _Item2;
  if Item1.Layer > Item2.Layer then
    Result := 1
  else if Item1.Layer < Item2.Layer then
    Result := -1
  else
    if Item1.Z > Item2.Z then
      Result := 1
    else if Item1.Z < Item2.Z then
      Result := -1
    else
      Result := 0;
end;

procedure TyBuffer.SortBuffer;
var
  I: Integer;
begin
  DrawList.Count := BufferSize; 
  for I := 0 to BufferSize - 1 do
    DrawList.List[I] := @Buffer[I]; {Isso só para copiar os itens do array pra Lista}
  DrawList.Sort( Compare );
end;

procedure TyBuffer.ClearBuffer;
begin
  BufferSize := 0;
end;


Depois usaria DrawList para desenhar as Imagens na Tela obedecendo as Camadas e Zs.

pensei em colocar um Index: nº; no TBufferData, toda vez que incluisse algo no array, configuraria o Index com um contador, co caso BufferSize, assim oderia preservar a ordem em que os Itens foram incluidos, colocando mas uma comparaçaõ, no lugar aonde está o [color=green:9b10ff3279]Result := 0;[/color:9b10ff3279] na procedure Compare, um [color=green:9b10ff3279]if Item1.Index > Item2.Index then Result := 1 else Result := 0[/color:9b10ff3279], dispensaria mais um else, porque eles nunca seriam iguais
seria uma solução, mas não acredito ser a mais correta

agradeço a preferência, ooops, digo, a atenção :)


Marcelo Saviski

Marcelo Saviski
Responder

Gostei + 1

Mais Posts

19/01/2004

Fabio.hc

[quote:e8e55cb28c=´Marcelo Saviski´]a função acima funciona em partes, ordena a lista pelo layer, seguido pelo Z, mas quando a dois ou mais itens na lista que estão no mesmo layer e possuem o mesmo valor para Z, queria preservar a ordem com que os itens foram inseridos,é é isso que não está acontecendo. ´Bagunça´ a posição dos Itens [/quote:e8e55cb28c]

Tente assim:

function Compare( _Item1, _Item2: Pointer ): Integer;
var
  Item1: PBufferData;
  Item2: PBufferData;
begin
   Item1 := _Item1;
   Item2 := _Item2;
   if (Item1.Layer = Item2.Layer) and (Item1.Z = Item2.Z) then
      Result := 0
   else if (Item1.Layer > Item2.Layer) and (Item1.Z > Item2.Z) then
      Result := 1
   else if (Item1.Layer < Item2.Layer) and (Item1.Z < Item2.Z) then
      Result := -1
   else
      if (Item1.Layer = Item2.Layer) then
         begin
         if Item1.Z > Item2.Z then
            Result := 1
         else if Item1.Z < Item2.Z then
            Result := -1
         else
            Result := 0;
         end;
end;



Responder

Gostei + 0

19/01/2004

Beppe

O algoritmo usado no TList.Sort é um quicksort. Ele é muito bom, só que não é estável, isto é, não preserva a ordem dos items iguais. Se a lista é pequena um insertionsort dá conta do recado. Se a lista é maior, um heap ou merge é preciso. Me dá mais informações que faço pra ti mais tarde.


Responder

Gostei + 0

Utilizamos cookies para fornecer uma melhor experiência para nossos usuários, consulte nossa política de privacidade.

Aceitar