Plane.Libraries/Plane.Maps.ChinaOffset/ChinaOffsetMap.cs
2017-02-27 02:04:13 +08:00

445 lines
15 KiB
C#
Raw Blame History

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