445 lines
15 KiB
C#
445 lines
15 KiB
C#
using System;
|
||
using System.Collections.Generic;
|
||
using System.IO;
|
||
using System.Linq;
|
||
using System.Text;
|
||
using System.Threading.Tasks;
|
||
|
||
namespace Plane.Maps.ChinaOffset
|
||
{
|
||
internal class ChinaOffsetMap
|
||
{
|
||
private byte[] gbuffer;
|
||
//private byte[] gbuffer1;
|
||
//FileInputStream file;
|
||
SOffsetMapFileHeader header;
|
||
String filename;
|
||
Stream pFileIn;
|
||
private int ixFromX;
|
||
private int iyFromY;
|
||
|
||
internal ChinaOffsetMap(Stream FileIn)
|
||
{
|
||
//RandomAccessFile a=new Ra;
|
||
|
||
//FileIn.reset();
|
||
pFileIn = FileIn;
|
||
byte[] bb = new byte[1];
|
||
ixFromX = -1;
|
||
iyFromY = -1;
|
||
|
||
//FileInputStream file = new FileInputStream();
|
||
//bs = new BufferedInputStream(FileIn);
|
||
//ds = new DataInputStream(bs);
|
||
|
||
header = new SOffsetMapFileHeader();
|
||
int a, b, c, d;
|
||
|
||
a = pFileIn.ReadByte();
|
||
b = pFileIn.ReadByte();
|
||
c = pFileIn.ReadByte();
|
||
d = pFileIn.ReadByte();
|
||
header.ixFromLng = (((d & 0xff) << 24) | ((c & 0xff) << 16) | ((b & 0xff) << 8) | (a & 0xff));
|
||
//header.ixFromLng = pFileIn.read();
|
||
|
||
//a = ds.readByte();
|
||
//b = ds.readByte();
|
||
//c = ds.readByte();
|
||
//d = ds.readByte();
|
||
|
||
|
||
a = pFileIn.ReadByte();
|
||
b = pFileIn.ReadByte();
|
||
c = pFileIn.ReadByte();
|
||
d = pFileIn.ReadByte();
|
||
header.ixToLng = (((d & 0xff) << 24) | ((c & 0xff) << 16) | ((b & 0xff) << 8) | (a & 0xff));
|
||
//header.ixToLng = pFileIn.read();
|
||
|
||
// a = ds.readByte();
|
||
// b = ds.readByte();
|
||
// c = ds.readByte();
|
||
// d = ds.readByte();
|
||
|
||
a = pFileIn.ReadByte();
|
||
b = pFileIn.ReadByte();
|
||
c = pFileIn.ReadByte();
|
||
d = pFileIn.ReadByte();
|
||
header.iyFromLat = (((d & 0xff) << 24) | ((c & 0xff) << 16) | ((b & 0xff) << 8) | (a & 0xff));
|
||
//header.iyFromLat = pFileIn.read();
|
||
|
||
// a = ds.readByte();
|
||
// b = ds.readByte();
|
||
// c = ds.readByte();
|
||
// d = ds.readByte();
|
||
|
||
a = pFileIn.ReadByte();
|
||
b = pFileIn.ReadByte();
|
||
c = pFileIn.ReadByte();
|
||
d = pFileIn.ReadByte();
|
||
header.iyToLat = (((d & 0xff) << 24) | ((c & 0xff) << 16) | ((b & 0xff) << 8) | (a & 0xff));
|
||
//header.iyToLat = pFileIn.read();
|
||
|
||
gbuffer = new byte[101 * 101 * 4];
|
||
}
|
||
|
||
private class SOffsetMapFileHeader
|
||
{
|
||
public int ixFromLng;
|
||
public int ixToLng;
|
||
public int iyFromLat;
|
||
public int iyToLat;
|
||
};
|
||
|
||
private class SOffsetXY
|
||
{
|
||
public short sXOffset;
|
||
public short sYOffset;
|
||
};
|
||
|
||
private class SRealOffsetXY
|
||
{
|
||
public double dXOffset;
|
||
public double dYOffset;
|
||
};
|
||
|
||
public void LonLat2GMAbsPt(int iLevel, double dxLon, double dyLat, int[] ixy)
|
||
{
|
||
int ulPixCnt = 1;
|
||
for (int i = 0; i < iLevel; i++)
|
||
ulPixCnt *= 2;
|
||
ulPixCnt *= 256; //得到象素点的数目<E695B0><E79BAE>??/2
|
||
|
||
dxLon += (double)180;
|
||
|
||
ixy[0] = (int)((double)ulPixCnt * dxLon / 360.0);
|
||
|
||
if (dyLat > 0)//北纬
|
||
{
|
||
double dtmp = Math.Tan((dyLat + 90.0) * Math.PI / 360.0);
|
||
double dy = Math.Log(dtmp) / Math.PI;
|
||
ixy[1] = (int)((1 - dy) * ulPixCnt / 2);
|
||
}
|
||
else//南纬
|
||
{
|
||
double dtmp = Math.Tan((dyLat + 90) * Math.PI / 360.0);
|
||
double dy = Math.Log(dtmp) / Math.PI;
|
||
ixy[1] = (int)((1 - dy) * ulPixCnt / 2);
|
||
}
|
||
}
|
||
|
||
public void GMAbsPt2LonLat(int iLevel, int ix, int iy, double[] dxyLonLat)
|
||
{
|
||
double dTemp;
|
||
int ulPixCnt = 1;
|
||
for (int i = 0; i < iLevel; i++)
|
||
ulPixCnt *= 2;
|
||
ulPixCnt *= 128; //得到象素点的数目<E695B0><E79BAE>??/2
|
||
|
||
dTemp = ix + 0.5;
|
||
// dTemp = ix;
|
||
dxyLonLat[0] = 180.0 * dTemp / ((double)ulPixCnt) - 180.0; //计算经度
|
||
if (dxyLonLat[0] > 180.0)
|
||
dxyLonLat[0] = dxyLonLat[0] - 360.0;
|
||
|
||
dxyLonLat[1] = 0.0;
|
||
if (iy < ulPixCnt) //计算纬度(unsigned long)
|
||
{
|
||
//北纬,大于零
|
||
dTemp = 1.0 - ((double)(iy + 0.5)) / (double)ulPixCnt;
|
||
dTemp = Math.Exp(Math.PI * dTemp);
|
||
dxyLonLat[1] = 360 * Math.Atan(dTemp) / Math.PI - 90.0;
|
||
}
|
||
else
|
||
{
|
||
//南纬,小于零
|
||
dTemp = ((double)(iy + 0.5)) / (double)ulPixCnt - 1;
|
||
dTemp = Math.Exp(Math.PI * dTemp);
|
||
dxyLonLat[1] = 360.0 * Math.Atan(dTemp) / Math.PI - 90.0;
|
||
dxyLonLat[1] = -dxyLonLat[1];
|
||
}
|
||
}
|
||
|
||
public void LoadOffsetFromFile(String FilePath)
|
||
{
|
||
filename = FilePath;
|
||
|
||
using (var fs = File.OpenRead(FilePath))
|
||
{
|
||
|
||
header = new SOffsetMapFileHeader();
|
||
int a, b, c, d;
|
||
|
||
a = fs.ReadByte();
|
||
b = fs.ReadByte();
|
||
c = fs.ReadByte();
|
||
d = fs.ReadByte();
|
||
header.ixFromLng = (((d & 0xff) << 24) | ((c & 0xff) << 16) | ((b & 0xff) << 8) | (a & 0xff));
|
||
|
||
a = fs.ReadByte();
|
||
b = fs.ReadByte();
|
||
c = fs.ReadByte();
|
||
d = fs.ReadByte();
|
||
header.ixToLng = (((d & 0xff) << 24) | ((c & 0xff) << 16) | ((b & 0xff) << 8) | (a & 0xff));
|
||
|
||
a = fs.ReadByte();
|
||
b = fs.ReadByte();
|
||
c = fs.ReadByte();
|
||
d = fs.ReadByte();
|
||
header.iyFromLat = (((d & 0xff) << 24) | ((c & 0xff) << 16) | ((b & 0xff) << 8) | (a & 0xff));
|
||
|
||
a = fs.ReadByte();
|
||
b = fs.ReadByte();
|
||
c = fs.ReadByte();
|
||
d = fs.ReadByte();
|
||
header.iyToLat = (((d & 0xff) << 24) | ((c & 0xff) << 16) | ((b & 0xff) << 8) | (a & 0xff));
|
||
}
|
||
}
|
||
|
||
public interface LoadProgress
|
||
{
|
||
void LoadPrs(int progress, int total);
|
||
}
|
||
|
||
LoadProgress loadProgress;
|
||
public void SetOnLoadProgress(LoadProgress loadPrs)
|
||
{
|
||
loadProgress = loadPrs;
|
||
}
|
||
|
||
private bool GetOffset(int ixPos, int iyPos, SOffsetXY rXY)
|
||
{
|
||
rXY.sXOffset = rXY.sYOffset = 0;
|
||
|
||
int MapWidth = header.ixToLng - header.ixFromLng;
|
||
int MapHeight = header.iyToLat - header.iyFromLat;
|
||
|
||
if (ixPos < 0 || ixPos >= MapWidth || iyPos < 0 || iyPos >= MapHeight)
|
||
return false;
|
||
|
||
if ((ixFromX < 0) || (iyFromY < 0) || (ixFromX != (ixPos / 100) * 100) || (iyFromY != (iyPos / 100) * 100))
|
||
{
|
||
ixFromX = (ixPos / 100) * 100;
|
||
iyFromY = (iyPos / 100) * 100;
|
||
|
||
pFileIn.Position = 0;
|
||
int lastFilePos = 0;
|
||
int filePos;
|
||
int readsize = 0;
|
||
byte[] lnbuffer = new byte[101 * 4];
|
||
for (int j = 0; j < 101; j++)
|
||
{
|
||
filePos = (iyFromY + j) * MapWidth * 4 + ixFromX * 4 + 16;
|
||
pFileIn.Seek(filePos - lastFilePos - readsize, SeekOrigin.Current);
|
||
lastFilePos = filePos;
|
||
if (pFileIn.Length - pFileIn.Position - 1 >= lnbuffer.Length)
|
||
{
|
||
pFileIn.Read(lnbuffer, 0, lnbuffer.Length);
|
||
readsize = 404;
|
||
}
|
||
else
|
||
{
|
||
readsize = (int)(pFileIn.Length - pFileIn.Position - 1);
|
||
pFileIn.Read(lnbuffer, 0, readsize);
|
||
}
|
||
Array.Copy(lnbuffer, 0, gbuffer, j * 101 * 4, 101 * 4);
|
||
//loadProgress.LoadPrs(j, 100);
|
||
}
|
||
}
|
||
|
||
int iPixInx = (iyPos % 100) * 101 + (ixPos % 100);
|
||
int iFilePos = iPixInx * 4;
|
||
|
||
short a, b;
|
||
|
||
a = gbuffer[iFilePos];
|
||
b = gbuffer[iFilePos + 1];
|
||
rXY.sXOffset = (short)(((b & 0xff) << 8) | (a & 0xff));
|
||
|
||
a = gbuffer[iFilePos + 2];
|
||
b = gbuffer[iFilePos + 3];
|
||
rXY.sYOffset = (short)(((b & 0xff) << 8) | (a & 0xff));
|
||
return true;
|
||
|
||
/*rXY.sXOffset = rXY.sYOffset = 0;
|
||
int MapWidth = header.ixToLng - header.ixFromLng;
|
||
int MapHeight = header.iyToLat - header.iyFromLat;
|
||
|
||
if (ixPos < 0 || ixPos >= MapWidth || iyPos < 0 || iyPos >= MapHeight)
|
||
return false;
|
||
|
||
int iPixInx = iyPos * MapWidth + ixPos;
|
||
int iFilePos = iPixInx*4;
|
||
try {
|
||
if (iFilePos >= MinID && iFilePos <= MaxID) {
|
||
|
||
}else{
|
||
pFileIn.reset();
|
||
// ds.mark(0);
|
||
// ds.reset();
|
||
|
||
if (iFilePos - 50000 >= 0){
|
||
MinID = iFilePos - 50000;
|
||
}else{
|
||
MinID = 0;
|
||
}
|
||
if (iFilePos + 50000 <= pFileIn.available()){
|
||
MaxID = iFilePos + 50000;
|
||
}else{
|
||
MaxID = pFileIn.available();
|
||
}
|
||
|
||
pFileIn.skip(MinID+16);
|
||
pFileIn.read(gbuffer,0,(MaxID - MinID));
|
||
}
|
||
} catch (IOException e) {
|
||
e.printStackTrace();
|
||
}
|
||
//ds.read(gbuffer1,0,ds.available());
|
||
//ds.close();
|
||
//bs.close();
|
||
//file.skip(iFilePos);
|
||
//RandomAccessFile randomFile = new RandomAccessFile(filename, "r");
|
||
//randomFile.seek(iFilePos);
|
||
// DataInputStream ds = new DataInputStream(pFileIn);
|
||
// pFileIn.reset();
|
||
// pFileIn.skip(iFilePos);
|
||
//BufferedInputStream bs = new BufferedInputStream(randomFile);
|
||
//DataInputStream ds = new DataInputStream(bs);
|
||
|
||
short a,b;
|
||
|
||
a = gbuffer[iFilePos-MinID];
|
||
b = gbuffer[iFilePos-MinID+1];
|
||
rXY.sXOffset = (short) (((b & 0xff) << 8) | (a & 0xff));
|
||
|
||
a = gbuffer[iFilePos-MinID+2];
|
||
b = gbuffer[iFilePos-MinID+3];
|
||
rXY.sYOffset = (short) (((b & 0xff) << 8) | (a & 0xff));
|
||
|
||
return true;*/
|
||
}
|
||
|
||
private bool GetRealOffset(double dxRefLng, double dyRefLat, SRealOffsetXY rXY)
|
||
{
|
||
double dyPos = (dyRefLat - header.iyFromLat / 100.0) * 100.0;
|
||
double dxPos = (dxRefLng - header.ixFromLng / 100.0) * 100.0;
|
||
|
||
int ixPos = (int)dxPos;
|
||
int iyPos = (int)dyPos;
|
||
SOffsetXY[] ofsXY = new SOffsetXY[4];
|
||
|
||
ofsXY[0] = new SOffsetXY();
|
||
ofsXY[1] = new SOffsetXY();
|
||
ofsXY[2] = new SOffsetXY();
|
||
ofsXY[3] = new SOffsetXY();
|
||
|
||
bool[] bRet = new bool[4];
|
||
int iTmpCnt = 0;
|
||
|
||
for (int k = 0; k < 4; k++)
|
||
{
|
||
bRet[k] = GetOffset(ixPos + k % 2, iyPos + k / 2, ofsXY[k]);
|
||
if (bRet[k])
|
||
iTmpCnt++;
|
||
}
|
||
|
||
if (iTmpCnt == 0)
|
||
return false;
|
||
|
||
SRealOffsetXY rfsXY_Up = new SRealOffsetXY();
|
||
SRealOffsetXY rfsXY_Down = new SRealOffsetXY();
|
||
bool bUpValid = false, bDownValid = false;
|
||
if (bRet[0] || bRet[1])
|
||
{
|
||
if (bRet[0] == false)
|
||
{
|
||
rfsXY_Up.dXOffset = (double)ofsXY[1].sXOffset;
|
||
rfsXY_Up.dYOffset = (double)ofsXY[1].sYOffset;
|
||
}
|
||
else if (bRet[1] == false)
|
||
{
|
||
rfsXY_Up.dXOffset = (double)ofsXY[0].sXOffset;
|
||
rfsXY_Up.dYOffset = (double)ofsXY[0].sYOffset;
|
||
}
|
||
else
|
||
{
|
||
rfsXY_Up.dXOffset = (double)ofsXY[0].sXOffset * ((double)(ixPos) + 1.0 - dxPos) +
|
||
(double)ofsXY[1].sXOffset * (dxPos - (double)(ixPos));
|
||
rfsXY_Up.dYOffset = (double)ofsXY[0].sYOffset * ((double)(ixPos) + 1.0 - dxPos) +
|
||
(double)ofsXY[1].sYOffset * (dxPos - (double)(ixPos));
|
||
}
|
||
bUpValid = true;
|
||
}
|
||
|
||
if (bRet[2] || bRet[3])
|
||
{
|
||
if (bRet[2] == false)
|
||
{
|
||
rfsXY_Down.dXOffset = (double)ofsXY[3].sXOffset;
|
||
rfsXY_Down.dYOffset = (double)ofsXY[3].sYOffset;
|
||
}
|
||
else if (bRet[3] == false)
|
||
{
|
||
rfsXY_Down.dXOffset = (double)ofsXY[2].sXOffset;
|
||
rfsXY_Down.dYOffset = (double)ofsXY[2].sYOffset;
|
||
}
|
||
else
|
||
{
|
||
rfsXY_Down.dXOffset = (double)ofsXY[2].sXOffset * ((double)(ixPos) + 1.0 - dxPos) +
|
||
(double)ofsXY[3].sXOffset * (dxPos - (double)(ixPos));
|
||
rfsXY_Down.dYOffset = (double)ofsXY[2].sYOffset * ((double)(ixPos) + 1.0 - dxPos) +
|
||
(double)ofsXY[3].sYOffset * (dxPos - (double)(ixPos));
|
||
}
|
||
bDownValid = true;
|
||
}
|
||
|
||
if (!bUpValid)
|
||
{
|
||
rXY.dXOffset = rfsXY_Down.dXOffset;
|
||
rXY.dYOffset = rfsXY_Down.dYOffset;
|
||
}
|
||
else if (!bDownValid)
|
||
{
|
||
rXY.dXOffset = rfsXY_Up.dXOffset;
|
||
rXY.dYOffset = rfsXY_Up.dYOffset;
|
||
}
|
||
else
|
||
{
|
||
rXY.dXOffset = rfsXY_Up.dXOffset * ((double)(iyPos) + 1.0 - dyPos) +
|
||
rfsXY_Down.dXOffset * (dyPos - (double)(iyPos));
|
||
rXY.dYOffset = rfsXY_Up.dYOffset * ((double)(iyPos) + 1.0 - dyPos) +
|
||
rfsXY_Down.dYOffset * (dyPos - (double)(iyPos));
|
||
}
|
||
|
||
return true;
|
||
}
|
||
|
||
public void GetLonLatAfterOffset(double dxRefLng, double dyRefLat, double[] dxyRetLngLat)
|
||
{
|
||
int[] ixyAbs = new int[2];
|
||
|
||
if ((dxRefLng < header.ixFromLng / 100.0) || (dxRefLng > header.ixToLng / 100.0) ||
|
||
(dyRefLat < header.iyFromLat / 100.0) || (dyRefLat > header.iyToLat / 100.0))
|
||
{
|
||
dxyRetLngLat[0] = dxRefLng;
|
||
dxyRetLngLat[1] = dyRefLat;
|
||
return;
|
||
}
|
||
|
||
SRealOffsetXY rXY = new SRealOffsetXY();
|
||
if (GetRealOffset(dxRefLng, dyRefLat, rXY) == false)
|
||
{
|
||
dxyRetLngLat[0] = dxRefLng;
|
||
dxyRetLngLat[1] = dyRefLat;
|
||
return;
|
||
}
|
||
|
||
LonLat2GMAbsPt(18, dxRefLng, dyRefLat, ixyAbs);
|
||
ixyAbs[0] += (int)rXY.dXOffset;
|
||
ixyAbs[1] += (int)rXY.dYOffset;
|
||
|
||
GMAbsPt2LonLat(18, ixyAbs[0], ixyAbs[1], dxyRetLngLat);
|
||
}
|
||
}
|
||
}
|