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; //得到象素点的数目��??/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; //得到象素点的数目��??/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); } } }