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);
|
|||
|
}
|
|||
|
}
|
|||
|
}
|