public bool FindTileInMask(Mask m, bool pngTileOnly, ref TileXY txy) { foreach (KeyValuePair <TileXY, TileMeta> pair in tiles) { if (!m.ContainsTile(pair.Key)) { continue; } if (!pngTileOnly || pair.Value.hasAlpha) { txy = pair.Key; while (true) { bool hasParent = false; TileXY[] parents = txy.GetParent().GetSiblings(); for (int i = 0; i < 4; i++) { if (m.ContainsTile(parents[i]) && tiles.ContainsKey(parents[i]) && (!pngTileOnly || tiles[parents[i]].hasAlpha)) { txy = parents[i]; hasParent = true; break; } } if (!hasParent || txy.level == 0) { break; } } return(true); } } return(false); }
/// <summary> /// check if this mask contains a tile /// </summary> /// <param name="tilexy"></param> /// <returns></returns> public bool ContainsTile(TileXY tilexy) { double lat, lon; BingProjection.PixelXYToLatLong((int)tilexy.x * 256, (int)tilexy.y * 256, (int)tilexy.level, out lat, out lon); if (!ContainsLatLon(lat, lon)) { return(false); } BingProjection.PixelXYToLatLong((int)tilexy.x * 256 + 256, (int)tilexy.y * 256, (int)tilexy.level, out lat, out lon); if (!ContainsLatLon(lat, lon)) { return(false); } BingProjection.PixelXYToLatLong((int)tilexy.x * 256, (int)tilexy.y * 256 + 256, (int)tilexy.level, out lat, out lon); if (!ContainsLatLon(lat, lon)) { return(false); } BingProjection.PixelXYToLatLong((int)tilexy.x * 256 + 256, (int)tilexy.y * 256 + 256, (int)tilexy.level, out lat, out lon); if (!ContainsLatLon(lat, lon)) { return(false); } return(true); }
public void MoveTo(int offsetx, int offsety, bool isZoomOut, bool isZoomIn) { // get target location TileXY targetXY = centerTilexy; if (isZoomOut) { targetXY = centerTilexy.GetParent(); } else if (isZoomIn) { TileXY[] sons = centerTilexy.GetSon().GetSiblings(); foreach (TileXY txy in sons) { targetXY = txy; if (tiles.ContainsKey(targetXY)) { break; } } } else { targetXY = centerTilexy.GetNeighbor(offsetx, offsety); } // move the center and paint centerTilexy = targetXY; Paint(); }
private PointD GetLonLat(Point pixelOffset, TileXY tilexy) { double lat, lon; BingProjection.PixelXYToLatLong(tilexy.x * 256 + pixelOffset.X, tilexy.y * 256 + pixelOffset.Y, (int)tilexy.level, out lat, out lon); return(new PointD(lon, lat)); }
public bool ContainsTilePixel(TileXY tilexy, Point pixelOffset) { double lat, lon; BingProjection.PixelXYToLatLong((int)tilexy.x * 256 + pixelOffset.X, (int)tilexy.y * 256 + pixelOffset.Y, (int)tilexy.level, out lat, out lon); return(ContainsLatLon(lat, lon) ? true : false); }
public Point[] GetUtmCorrectedRelativePolygon(TileXY tilexy, int zone) { double[] input = new double[4]; double[] result = new double[8]; input[0] = box.top; input[1] = box.right; input[2] = box.bottom; input[3] = box.left; for (int i = 0; i < 4; i++) { input[i] = input[i] * Math.PI / 180; } MUtilities.LatLonRectangleExpandByUtm(zone, input, result); for (int i = 0; i < 8; i++) { result[i] = result[i] * 180 / Math.PI; } Point[] points = new Point[4]; points[0] = BingProjection.LatLongToPixelXY(result[0], result[1], tilexy.level); points[1] = BingProjection.LatLongToPixelXY(result[2], result[3], tilexy.level); points[2] = BingProjection.LatLongToPixelXY(result[4], result[5], tilexy.level); points[3] = BingProjection.LatLongToPixelXY(result[6], result[7], tilexy.level); for (int i = 0; i < 4; i++) { points[i].X -= tilexy.x * 256; points[i].Y -= tilexy.y * 256; } return(points); }
public static string TileXYToLatLong(TileXY tilexy) { double lat, lon; PixelXYToLatLong((int)tilexy.x * 256, (int)tilexy.y * 256, (int)tilexy.level, out lat, out lon); return(lat.ToString("F6") + "," + lon.ToString("F6")); }
public TileXY GetNeighbor(int offsetx, int offsety) { TileXY txy = this; txy.x += offsetx; txy.y += offsety; return(txy); }
public TileXY GetSon() { TileXY txy = this; txy.level++; txy.x *= 2; txy.y *= 2; return(txy); }
public Mask(Point start, Point end, TileXY tilexy) { if (end.X < start.X || end.Y < start.Y) { throw new Exception("Invalid rectangle!"); } PointD a = GetLonLat(start, tilexy); PointD b = GetLonLat(end, tilexy); box = new RectangleD(a.lat, b.lon, b.lat, a.lon); }
public TileXY GetParent() { TileXY txy = this; if (txy.level == 0) { return(txy); } txy.level--; txy.x /= 2; txy.y /= 2; return(txy); }
public Point[] GetRelativePolygon(TileXY tilexy) { Point[] points = new Point[4]; points[0] = BingProjection.LatLongToPixelXY(box.top, box.left, tilexy.level); points[1] = BingProjection.LatLongToPixelXY(box.top, box.right, tilexy.level); points[2] = BingProjection.LatLongToPixelXY(box.bottom, box.right, tilexy.level); points[3] = BingProjection.LatLongToPixelXY(box.bottom, box.left, tilexy.level); for (int i = 0; i < 4; i++) { points[i].X -= tilexy.x * 256; points[i].Y -= tilexy.y * 256; } return(points); }
public static string GetQuadKey(TileXY tilexy) { StringBuilder quadKey = new StringBuilder(); for (int i = tilexy.level; i > 0; i--) { char digit = '0'; int mask = 1 << (i - 1); if ((tilexy.x & mask) != 0) { digit++; } if ((tilexy.y & mask) != 0) { digit++; digit++; } quadKey.Append(digit); } return(quadKey.ToString()); }
public void OnMouseUp(Point mousePositionEnd, int actionType) { isMouseDown = false; Bitmap bm = (Bitmap)pbox.Image; if (mousePositionEnd != mousePositionStart) // it's a drag { // get real start and end Point start = new Point(Math.Min(mousePositionStart.X, mousePositionEnd.X), Math.Min(mousePositionStart.Y, mousePositionEnd.Y)); Point end = new Point(Math.Max(mousePositionStart.X, mousePositionEnd.X), Math.Max(mousePositionStart.Y, mousePositionEnd.Y)); Mask mask = new Mask(start, end, centerTilexy.GetNeighbor(-centerX, -centerY)); switch (actionType) { case 0: // get statistics Paint(); // Very important! Paint first to get rid of red line drawn by drag of mouse byte minr = byte.MaxValue, ming = byte.MaxValue, minb = byte.MaxValue; byte maxr = 0, maxg = 0, maxb = 0; for (int w = start.X; w <= end.X; w++) { for (int h = start.Y; h <= end.Y; h++) { Color c = bm.GetPixel(w, h); if (c.A == 0) { continue; } maxr = Math.Max(maxr, c.R); maxg = Math.Max(maxg, c.G); maxb = Math.Max(maxb, c.B); minr = Math.Min(minr, c.R); ming = Math.Min(ming, c.G); minb = Math.Min(minb, c.B); } } FormNav.ShowMessage("Min RGB: " + minr + "/" + ming + "/" + minb); FormNav.ShowMessage("Max RGB: " + maxr + "/" + maxg + "/" + maxb); break; case 1: // zoom in TileXY txy = centerTilexy; if (FindTileInMask(mask, false, ref txy)) { centerTilexy = txy; } break; case 2: // add to mask masks.Add(mask); FormNav.ShowMessage("new mask added"); break; case 3: // find PNG TileXY txy2 = centerTilexy; if (FindTileInMask(mask, true, ref txy2)) { centerTilexy = txy2; } break; case 4: // guess valid pixel range // important, paint to original images before doing the calculation Paint(true); // first, get pixel cnt array int[,] pixelCnt = new int[3, 256]; for (int i = 0; i < 3; i++) { for (int j = 0; j < 256; j++) { pixelCnt[i, j] = 0; } } for (int w = start.X; w <= end.X; w++) { for (int h = start.Y; h <= end.Y; h++) { Color c = bm.GetPixel(w, h); if (c.A == 0) { continue; } pixelCnt[0, c.R]++; pixelCnt[1, c.G]++; pixelCnt[2, c.B]++; } } // then, convert to pixel sum for (int i = 0; i < 3; i++) { for (int j = 1; j < 256; j++) { pixelCnt[i, j] += pixelCnt[i, j - 1]; } } double[] ratios = new double[] { 0.6, 0.7, 0.8, 0.9, 0.95, 0.96, 0.965, 0.97, 0.975, 0.98, 0.985, 0.99, 0.995, 0.998 }; int[,] guessedRanges = new int[3, ratios.Length]; for (int i = 0; i < 3; i++) { int j = 0; for (int k = 0; k < ratios.Length; k++) { for (; j < 50; j++) { if (((double)pixelCnt[i, j]) / pixelCnt[i, 50] > ratios[k]) { break; } } guessedRanges[i, k] = j; } } cbGuessedPixelValidRanges.Items.Clear(); for (int i = 0; i < ratios.Length; i++) { cbGuessedPixelValidRanges.Items.Add((guessedRanges[0, i] + 1) + "," + (guessedRanges[1, i] + 1) + "," + (guessedRanges[2, i] + 1) + ",255,255,255"); } FormNav.ShowMessage("Pixel Valid Ranges are guessed"); break; default: break; } // paint anyway Paint(); } else // it's a single click { FormNav.ShowMessage("Color: " + bm.GetPixel(mousePositionEnd.X, mousePositionEnd.Y)); // get top left tile TileXY tileTopLeft = centerTilexy.GetNeighbor(-centerX, -centerY); for (int i = 0; i < masks.Count; i++) { if (masks[i].ContainsTilePixel(tileTopLeft, mousePositionEnd)) { FormNav.ShowMessage("Mask " + i + ": " + masks[i].ToString()); } } } }
public void Paint(bool originalOnly = false, bool centerOnly = false) { // clear image Graphics g = Graphics.FromImage(pbox.Image); if (!originalOnly) { g.Clear(bgColor); } else { g.Clear(Color.FromArgb(0, 0, 0, 0)); } // draw tiles for (int j = 0; j < rowCount; j++) { for (int i = 0; i < columnCount; i++) { int offsetx = i - centerX; int offsety = j - centerY; if (centerOnly && (offsetx != 0 || offsety != 0)) { continue; } TileXY xy = centerTilexy.GetNeighbor(offsetx, offsety); if (tiles.ContainsKey(xy)) { TileMeta tmeta = tiles[xy]; byte[] imgBuff = MDataFile.Read(tdataPaths[tmeta.tdataPathId], tmeta.imgOffset, tmeta.imgLength); Rectangle rect = new Rectangle(i * imageSize, j * imageSize, imageSize, imageSize); g.DrawImage(Image.FromStream(new MemoryStream(imgBuff)), rect); if (!originalOnly && !_isShowValidGraph && distinguishPng && tmeta.hasAlpha) { g.FillRectangle(brushCoverPNG, rect); } } } } if (!originalOnly) { // get current utm correction zone int zone = Int32.Parse(tbUtmCorrectionZone.Text); // get top left tile xy TileXY topLeftTileXY = centerTilexy.GetNeighbor(-centerX, -centerY); // draw masks if (!_isShowValidGraph) { foreach (Mask m in masks) { // draw utm corrected masks g.FillPolygon(m.type == 0 ? brushMaskSkip : (m.type == 1 ? brushMaskNewRange : brushMaskRemove), m.GetUtmCorrectedRelativePolygon(topLeftTileXY, zone)); } } // show valid graph if (_isShowValidGraph && pixelValidRange != null) { pixelValidRange.DrawValidGraph((Bitmap)pbox.Image); } // draw mouse line if (isMouseDown) { g.DrawRectangle(penMouseDragLine, Math.Min(mousePositionNow.X, mousePositionStart.X), Math.Min(mousePositionNow.Y, mousePositionStart.Y), Math.Abs(mousePositionNow.X - mousePositionStart.X), Math.Abs(mousePositionNow.Y - mousePositionStart.Y)); // draw utm corrected line Point start = new Point(Math.Min(mousePositionStart.X, mousePositionNow.X), Math.Min(mousePositionStart.Y, mousePositionNow.Y)); Point end = new Point(Math.Max(mousePositionStart.X, mousePositionNow.X), Math.Max(mousePositionStart.Y, mousePositionNow.Y)); Mask mTmp = new Mask(start, end, topLeftTileXY); g.DrawPolygon(penMouseDragLineUtmCorrected, mTmp.GetUtmCorrectedRelativePolygon(topLeftTileXY, zone)); } } pbox.Refresh(); ShowCenterTileInfo(); }
/// <summary> /// initialize map from a dir which contains *.tdata and *.tmeta files /// </summary> /// <param name="dataDir"></param> public TDataNavigator(string[] tmetaPaths, PictureBox pbox, TextBox tbTileInfo, ComboBox cbGuessedPixelValidRanges, TextBox tbUtmCorrectionZone) { this.pbox = pbox; this.tbTileInfo = tbTileInfo; this.cbGuessedPixelValidRanges = cbGuessedPixelValidRanges; this.tbUtmCorrectionZone = tbUtmCorrectionZone; // create dataPath array tdataPaths = new string[tmetaPaths.Length]; for (int i = 0; i < tmetaPaths.Length; i++) { tdataPaths[i] = tmetaPaths[i].ToLower().Replace(".tmeta", ".tdata"); } // load all meta info levelMin = Int32.MaxValue; levelMax = 0; for (int i = 0; i < tmetaPaths.Length; i++) { using (MMetaFile metaFile = new MMetaFile(tmetaPaths[i])) { int recordCnt = metaFile.GetRecordCnt(); for (int j = 0; j < recordCnt; j++) { MSTileMetaInfo meta = metaFile.Read(j); if ((int)meta.tilexy.level < levelMin) { levelMin = (int)meta.tilexy.level; centerTilexy = new TileXY(meta.tilexy); } levelMax = Math.Max(levelMax, (int)meta.tilexy.level); tiles.Add(new TileXY(meta.tilexy), new TileMeta(meta, i)); } } } // zoom in center tile to a reasonable level while (true) { int validSonCount = 0; TileXY validSonXY = centerTilexy; foreach (TileXY txy in centerTilexy.GetSon().GetSiblings()) { if (tiles.ContainsKey(txy)) { validSonCount++; validSonXY = txy; } } if (validSonCount == 1) { centerTilexy = validSonXY; } else { break; } } // guess an initial utm correction zone double lat, lon; BingProjection.PixelXYToLatLong(centerTilexy.x * 256 + 128, centerTilexy.y * 256 + 128, (int)centerTilexy.level, out lat, out lon); tbUtmCorrectionZone.Text = Helper.LongitudeToUtmZone(lon).ToString(); Paint(); }