procedure TForm1.Button3Click(Sender: TObject); var i: integer; begin SysDataset.CommandText:='SELECT * FROM GOOGLEMAPCORRECT'; SysDataset.Active:=true; progress.Max:=RecordCount; progress.Position:=0; for i := 0 to RecordCount-1 do begin SysDataset.Append; SysDataset.FieldValues['Long']:=Records[i].Long; SysDataset.FieldValues['Lat']:=Records[i].Lat; SysDataset.FieldValues['LongError']:=Records[i].LongOffset; SysDataset.FieldValues['LatError']:=Records[i].LatOffset; SysDataset.Post; Progress.Position:=i+1; end; SysDataset.Active:=false; memo1.Lines.Add('数据已经保存到数据库!'); end;
procedure TForm1.Button4Click(Sender: TObject); var i: integer; Long,Lat: word; LongError,LatError: smallint; Stream: TMemoryStream; begin SysDataset.CommandText:='SELECT * FROM GOOGLEMAPCORRECT ORDER BY LONG,LAT'; SysDataset.Active:=true; progress.Max:=SysDataset.RecordCount; progress.Position:=0; Stream:=TMemoryStream.Create; while not sysdataset.Eof do begin Long:=word(SysDataset.FieldByName('Long').AsInteger); Lat:=word(SysDataset.FieldByName('Lat').AsInteger); Longerror:=smallint(SysDataset.FieldByName('LongError').AsInteger); Laterror:=smallint(SysDataset.FieldByName('LatError').AsInteger); Stream.Write(long,2); Stream.Write(lat,2); Stream.Write(longerror,2); Stream.Write(laterror,2); SysDataset.Next; Progress.Position:=Progress.Position+1; end; SysDataset.Active:=false; Stream.Position:=0; Stream.SaveToFile('f:\gmapcorrect.dat'); FreeANdNil(Stream); memo1.Lines.Add('规格化排序后数据已经导出到文件!'); end;
3、插值计算算法 GIS里常用的是反距离加权算法。于是写一个,主要计算函数: // // 插值计算... function TIDWInterpolation.Interpolating(const x: double; const y: double): double; var a,b: double; i: integer; begin a:=0; b:=0; try for i := 0 to PointCount-1 do begin if (points[i].x=x) and (points[i].y=y) then begin result:=points[i].z; exit; end; a:=a+(1/((x-Points[i].x)*(x-Points[i].x)+(y-points[i].y)*(y-points[i].y)))*points[i].z; b:=b+1/((x-Points[i].x)*(x-Points[i].x)+(y-points[i].y)*(y-points[i].y)); end; if b=0 then result:=0 else result:=a/b; except result:=0; end; end;
先来测试一下此算法的正确性: procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction); begin FreeAndNil(IDW); end;
procedure TForm1.FormCreate(Sender: TObject); begin idw:=TIDWInterpolation.Create; idw.AddPoint(0,0,20); idw.AddPoint(400,0,5); idw.AddPoint(0,300,15); idw.AddPoint(400,300,-2); end;
procedure TForm1.Shape1MouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer); var z: double; begin z:=idw.Interpolating(x,y); edit5.Text:=inttostr(x)+','+inttostr(y)+','+floattostr(z); end;
主要代码: // // 查找某经度起始记录... function TGMapCorrect.FindBeginIndex(aLong: word): integer; var l,h,m: integer; begin result:=-1; l:=0; h:=PointCount-1; while l<=h do begin m:=(l+h) div 2; // // 找到... if aLon_g=Points[m].Long then begin // // 确定起始记录... result:=m; l:=m-1; while points[l].lon_g=aLong do begin dec(result); dec(l); end; break; end; // // 修正查找范围... if Points[m].Long>aLong then h:=m-1 else l:=m+1; end; end;
// // 纠偏... function TGMapCorrect.Correct(const Long: double; const Lat: double; var NewLong: double; var NewLat: double): boolean; var MinLong,MaxLong: word; MinLat,MaxLat: word; i,j: integer; begin result:=true; // // 假如经度超出,返回原值... if (Long<=75) or (Long>=131.9) then begin NewLong:=Long; NewLat:=Lat; exit; end; // // 假如纬度超出,返回原值... if (Lat<=21) or (Lat>=51.9) then begin NewLong:=Long; NewLat:=Lat; exit; end; // // 根据经纬度确定所属小矩形区域四顶点经纬度... MinLong:=word(trunc(Long*10)); MaxLong:=MinLong+1; MinLat:=word(trunc(Lat*10)); MaxLat:=MinLat+1; // // 检索得到四顶点偏差值... j:=FindBeginIndex(MinLong); if j=-1 then begin NewLong:=Long; NewLat:=Lat; result:=false; exit; end; // // 使用插值算法计算经纬度偏差... IDWI1.initialize; IDWI2.initialize; for i:= j to PointCount-1 do begin // // 找到第一点... if (Points[i].Lon_g=MinLong) and (Points[i].Lat=MinLat) then begin IDWI1.AddPoint(MinLong,MinLat,Points[i].LongError); IDWI2.AddPoint(MinLong,MinLat,Points[i].LatError); end; // // 找到第二点... if (Points[i].Lon_g=MinLong) and (Points[i].Lat=MaxLat) then begin IDWI1.AddPoint(MinLong,MaxLat,Points[i].LongError); IDWI2.AddPoint(MinLong,MaxLat,Points[i].LatError); end; // // 找到第三点... if (Points[i].Lon_g=MaxLong) and (Points[i].Lat=MinLat) then begin IDWI1.AddPoint(MaxLong,MinLat,Points[i].LongError); IDWI2.AddPoint(MaxLong,MinLat,Points[i].LatError); end; // // 找到第四点... if (Points[i].Lon_g=MaxLong) and (Points[i].Lat=MaxLat) then begin IDWI1.AddPoint(MaxLong,MaxLat,Points[i].LongError); IDWI2.AddPoint(MaxLong,MaxLat,Points[i].LatError); break; end; end; // // 原经纬度+偏差,得到纠偏结果... NewLong:=Long+IDWI1.Interpolating(Long*10,Lat*10)/10000; NewLat:=Lat+IDWI2.Interpolating(Long*10,Lat*10)/10000; end;