有一个100*100的网格,每个点有一个值(这个值在50-100之间),现在要根据这个画等值线,该怎么做呢?

解决方案 »

  1.   

    这个好像和AI中的A*算法有些相似,楼主不妨搜索参考一下
      

  2.   

    to postren(小虫):
    A*算法?搜了一下没找到:(
    to h2yang(小青) :
    每个点的值在画线前是已知的
      

  3.   

    呵呵。我编写了一个控件。你可测试用下  //等值线数组
      TValueArray=array of array of integer;
      PValueArray=^TValueArray;
      //标记数组
      TTagArray=array of array [0..1] of integer;
      PTagArray=^TTagArray;
      //等值线控件
      TValueGraphic=class(TCustomControl)
      private
        fBmp:TBitmap;
        fValueArray: TValueArray;
        fTagArray:TTagArray;
        fValueWidth: Integer;
        fValueHeight: Integer;
        fMaxValue: integer;
        procedure setValueArray(const Value: TValueArray);
        procedure setValueHeight(const Value: Integer);
        procedure setValueWidth(const Value: Integer);
        procedure setMaxValue(const Value: integer);
      protected
        procedure PerformChanged;
        procedure Paint;override;
      public
        constructor Create(AOwner:TComponent);override;
        destructor Destroy;override;    procedure ClearValueArray;
        procedure RadonValueArray;
        procedure GetTagArray;    property ValueArray:TValueArray read fValueArray write setValueArray;
        property ValueWidth:Integer read fValueWidth write setValueWidth;
        property ValueHeight:Integer read fValueHeight write setValueHeight;
        property MaxValue:integer read fMaxValue write setMaxValue;
      end;{ TValueGraphic }procedure TValueGraphic.ClearValueArray;
    var
      ArraySize:integer;
    begin
      ArraySize := max(0,fValueHeight)*max(0,fValueWidth);
      if assigned(fValueArray) then
        ZeroMemory(@fValueArray[low(fValueArray)],ArraySize*sizeof(integer));
    end;constructor TValueGraphic.Create(AOwner: TComponent);
    begin
      inherited Create(AOwner);
      ControlStyle := ControlStyle + [csOpaque];
      fBmp := TBitmap.Create;
      fValueWidth := 100;
      fValueHeight:= 100;
      fBmp.Width  := fValueWidth;
      fBmp.Height := fValueHeight;
      fMaxValue  := 100;
      setLength(fValueArray,fValueHeight,fValueWidth);
      Randomize;
      RadonValueArray;
      PerformChanged;
    end;destructor TValueGraphic.Destroy;
    begin
      fBmp.Free;
      inherited;
    end;procedure TValueGraphic.GetTagArray;
    var
      i:integer;
      ArraySize:integer;
    begin
      setLength(fTagArray,fMaxValue);
      ArraySize := fMaxValue*2*sizeof(integer);
      ZeroMemory(@fTagArray[low(fTagArray)],ArraySize);
    end;procedure TValueGraphic.Paint;
    begin
      inherited;
      Canvas.StretchDraw(rect(0,0,width,height),fBmp);
    end;procedure TValueGraphic.PerformChanged;
    var
      i,j:integer;
    begin
      GetTagArray;
      with fBmp.Canvas do
      begin
        brush.Color := clWhite;
        pen.Color := clBlack;
        Rectangle(rect(0,0,fBmp.Width,fBmp.Height));
     
        if (fValueHeight<>0) or (fValueWidth<>0) then
        begin
          for i := 0 to fValueHeight-1 do
          begin
            for j := 0 to fValueWidth-1 do
            begin
              if fValueArray[i,j]<>0 then
              begin
                if (fTagArray[fValueArray[i,j],0]<>0) or (fTagArray[fValueArray[i,j],1]<>0) then
                begin
                  MoveTo(fTagArray[fValueArray[i,j],0],fTagArray[fValueArray[i,j],1]);
                  LineTo(i,j);
                end
                else
                begin
                  Pixels[i,j] := clRed;
                end;
                fTagArray[fValueArray[i,j],0] := i;
                fTagArray[fValueArray[i,j],1] := j;
              end;
            end;
          end;
        end;  end;
    end;procedure TValueGraphic.RadonValueArray;
    var
      i,j:integer;
    begin
      {
      if Assigned(fValueArray) then
      begin
        for i := 0 to fValueHeight-1 do
          for j := 0 to fValueWidth-1 do
            fValueArray[i,j] := random(fMaxValue);
      end;
      }  if Assigned(fValueArray) then
      begin
        fValueArray[10,10] := 10;
        fValueArray[30,30] := 10;
        fValueArray[35,40] := 10;    fValueArray[20,20] := 20;
        fValueArray[40,30] := 20;
        fValueArray[60,40] := 20;
        fValueArray[61,30] := 20;    fValueArray[50,10] := 30;
        fValueArray[20,30] := 30;
        fValueArray[60,80] := 30;
        fValueArray[70,40] := 30;    fValueArray[4,5]   := 40;
        fValueArray[20,14] := 40;
        fValueArray[36,50] := 40;
        fValueArray[89,90] := 40;
      end;
     
    end;procedure TValueGraphic.setMaxValue(const Value: integer);
    begin
      fMaxValue := max(Value,0);
    end;procedure TValueGraphic.setValueArray(const Value: TValueArray);
    begin
      fValueArray := Value;
    end;procedure TValueGraphic.setValueHeight(const Value: Integer);
    begin
      fValueHeight := Value;
      fBmp.Height  := Value;
      ClearValueArray;
      setLength(fValueArray,fValueHeight,fValueWidth);
      PerformChanged;
    end;procedure TValueGraphic.setValueWidth(const Value: Integer);
    begin
      fValueWidth := Value;
      fBmp.Width  := Value;
      ClearValueArray;
      setLength(fValueArray,fValueHeight,fValueWidth);
      PerformChanged;
    end;procedure TForm1.BitBtn4Click(Sender: TObject);
    var
      ValueGraphic:TValueGraphic;
    begin
      ValueGraphic := TValueGraphic.Create(self);
      ValueGraphic.Parent  := self;
      ValueGraphic.Visible := true;
      ValueGraphic.Left := 200;
      ValueGraphic.Top  := 200;
      ValueGraphic.Width  := 100;
      ValueGraphic.Height := 100;  //noneed:
      //ValueGraphic.free;
    end;
      

  4.   

    为了美观。修改了PerformChanged.就是封闭矩形边框黑色。等值线蓝色。孤立点红色procedure TValueGraphic.PerformChanged;
    var
      i,j:integer;
    begin
      GetTagArray;
      with fBmp.Canvas do
      begin
        brush.Color := clWhite;
        pen.Color := clBlack;
        Rectangle(rect(0,0,fBmp.Width,fBmp.Height));
        pen.Color := clBlue;
        if (fValueHeight<>0) or (fValueWidth<>0) then
        begin
          for i := 0 to fValueHeight-1 do
          begin
            for j := 0 to fValueWidth-1 do
            begin
              if fValueArray[i,j]<>0 then
              begin
                if (fTagArray[fValueArray[i,j],0]<>0) or (fTagArray[fValueArray[i,j],1]<>0) then
                begin
                  MoveTo(fTagArray[fValueArray[i,j],0],fTagArray[fValueArray[i,j],1]);
                  LineTo(i,j);
                end
                else
                begin
                  Pixels[i,j] := clRed;
                end;
                fTagArray[fValueArray[i,j],0] := i;
                fTagArray[fValueArray[i,j],1] := j;
              end;
            end;
          end;
        end;  end;
    end;为了测试孤立点,可在上面procedure TValueGraphic.RadonValueArray;中加入  if Assigned(fValueArray) then
      begin
        .
        .
        fValueArray[90,95] := 45;    fValueArray[95,98] := 50;
      end;
      

  5.   

    A*算法
    http://dev.gameres.com/Program/Abstract/Arithmetic/A%20Pathfinding%20for%20Beginners.htm
      

  6.   

    to risingsoft(一苇渡江) ;
    感谢您提供代码,您能说说这段代码该怎么用呢?to postren(小虫) :
    非常感谢您提供的网址!
      

  7.   

    我的思路是。建立一个100*100的位图
        一个100*100的2维等值线数组,每个数组元素的值最大是MaxValue
        一个长度是MaxValue,宽度是2的标记数组算法:
        初始化100*100的等值线数组ValueArray
        1、循环处理1..100 -> x
             循环处理1..100 -> y
               对于等值线数组元素ValueArray[x,y],其数值为Index  
               {
                 如果标记数组FlagArray[Index,0],FlagArray[Index,1]都非0
                 { 
                    移动到FlagArray[Index,0],FlagArray[Index,1]
                    移动到当前点X,Y
                 } 
                 否则
                 {
                   将X,Y点处的颜色设置为红色
                 }
                 将当前X,Y记录到标记数组FlagArray[Index,0],FlagArray[Index,1] 
               }
      

  8.   

    to risingsoft(一苇渡江) ;
    直接用您的代码画出的等值线是相交的啊