private LatLonZoom PixelToLatLong(Point64 p, int zoomLevel) { double num = this.MetersPerPixel(zoomLevel); double num2 = (double)p.X * num - 20037508.342789244; double num3 = 20037508.342789244 - (double)p.Y * num; return new LatLonZoom(CoordinateSystemUtilities.RadiansToDegrees(1.5707963267948966 - 2.0 * Math.Atan(Math.Exp(-num3 / 6378137.0))), CoordinateSystemUtilities.RadiansToDegrees(num2 / 6378137.0), zoomLevel); }
public TileDisplayDescriptorArray GetTileArrayDescriptor(LatLonZoom center, Size windowSize) { TileDisplayDescriptorArray tileDisplayDescriptorArray = new TileDisplayDescriptorArray(); MapRectangle unclippedMapWindow = this.GetUnclippedMapWindow(center, windowSize); tileDisplayDescriptorArray.topLeftTile = this.GetTileContainingLatLonZoom(new LatLonZoom(unclippedMapWindow.GetNW(), center.zoom)); TileAddress tileContainingLatLonZoom = this.GetTileContainingLatLonZoom(new LatLonZoom(unclippedMapWindow.GetSE(), center.zoom)); tileDisplayDescriptorArray.tileCountX = tileContainingLatLonZoom.TileX - tileDisplayDescriptorArray.topLeftTile.TileX + 1; tileDisplayDescriptorArray.tileCountY = -(tileContainingLatLonZoom.TileY - tileDisplayDescriptorArray.topLeftTile.TileY) + 1; Point64 point = new Point64(this.degreesToPixels(unclippedMapWindow.GetNW().lon, center.zoom), this.degreesToPixels(unclippedMapWindow.GetNW().lat, center.zoom)); tileDisplayDescriptorArray.topLeftTileOffset = new Point((int)((long)(tileDisplayDescriptorArray.topLeftTile.TileX * 512) - point.X), (int)(point.Y - (long)((tileDisplayDescriptorArray.topLeftTile.TileY + 1) * 512))); tileDisplayDescriptorArray.layout = this.addressLayout; tileDisplayDescriptorArray.tileSize = this.GetTileSize(); return tileDisplayDescriptorArray; }
private TileAddress GetTileContainingLatLonZoom(LatLonZoom llz) { Point64 point = new Point64(this.degreesToPixels(llz.lon, llz.zoom), this.degreesToPixels(llz.lat, llz.zoom)); return new TileAddress((int)Math.Floor((double)point.X / 512.0), (int)Math.Floor((double)point.Y / 512.0), llz.zoom); }
public LatLon GetLatLonOfTileNW(TileAddress ta) { Point64 p = new Point64((long)ta.TileX * 256L, (long)ta.TileY * 256L); return this.PixelToLatLong(p, ta.ZoomLevel).latlon; }
public PathNode(Path p, JoinType jt, EndType et) { joinType = jt; endType = et; int lenP = p.Count; if (et == EndType.Polygon || et == EndType.OpenJoined) { while (lenP > 1 && p[lenP - 1] == p[0]) { lenP--; } } else if (lenP == 2 && p[1] == p[0]) { lenP = 1; } if (lenP == 0) { return; } if (lenP < 3 && (et == EndType.Polygon || et == EndType.OpenJoined)) { if (jt == JoinType.Round) { endType = EndType.OpenRound; } else { endType = EndType.OpenSquare; } } path = new Path(lenP); path.Add(p[0]); Point64 lastIp = p[0]; lowestIdx = 0; for (int i = 1; i < lenP; i++) { if (lastIp == p[i]) { continue; } path.Add(p[i]); lastIp = p[i]; if (et != EndType.Polygon) { continue; } if (p[i].Y >= path[lowestIdx].Y && (p[i].Y > path[lowestIdx].Y || p[i].X < path[lowestIdx].X)) { lowestIdx = i; } } if (endType == EndType.Polygon && path.Count < 3) { path = null; } }
//------------------------------------------------------------------------------ private void DoOffset(double d) { solution = null; delta = d; double absDelta = Math.Abs(d); //if a Zero offset, then just copy CLOSED polygons to FSolution and return ... if (absDelta < Tolerance) { solution = new Paths(nodes.Count); foreach (PathNode node in nodes) { if (node.endType == EndType.Polygon) { solution.Add(node.path); } } return; } //MiterLimit: see offset_triginometry3.svg in the documentation folder ... if (MiterLimit > 2) { miterLim = 2 / (MiterLimit * MiterLimit); } else { miterLim = 0.5; } double arcTol; if (ArcTolerance < DefaultArcFrac) { arcTol = absDelta * DefaultArcFrac; } else { arcTol = ArcTolerance; } //see offset_triginometry2.svg in the documentation folder ... double steps = Math.PI / Math.Acos(1 - arcTol / absDelta); //steps per 360 degrees if (steps > absDelta * Math.PI) { steps = absDelta * Math.PI; //ie excessive precision check } sin = Math.Sin(TwoPi / steps); cos = Math.Cos(TwoPi / steps); if (d < 0) { sin = -sin; } stepsPerRad = steps / TwoPi; solution = new Paths(nodes.Count * 2); foreach (PathNode node in nodes) { pathIn = node.path; pathOut = new Path(); int pathInCnt = pathIn.Count; //if a single vertex then build circle or a square ... if (pathInCnt == 1) { if (node.joinType == JoinType.Round) { double X = 1.0, Y = 0.0; for (int j = 1; j <= steps; j++) { pathOut.Add(new Point64( Round(pathIn[0].X + X * delta), Round(pathIn[0].Y + Y * delta))); double X2 = X; X = X * cos - sin * Y; Y = X2 * sin + Y * cos; } } else { double X = -1.0, Y = -1.0; for (int j = 0; j < 4; ++j) { pathOut.Add(new Point64( Round(pathIn[0].X + X * delta), Round(pathIn[0].Y + Y * delta))); if (X < 0) { X = 1; } else if (Y < 0) { Y = 1; } else { X = -1; } } } solution.Add(pathOut); continue; } //end of single vertex offsetting //build norms ... norms.Clear(); norms.Capacity = pathInCnt; for (int j = 0; j < pathInCnt - 1; j++) { norms.Add(GetUnitNormal(pathIn[j], pathIn[j + 1])); } if (node.endType == EndType.OpenJoined || node.endType == EndType.Polygon) { norms.Add(GetUnitNormal(pathIn[pathInCnt - 1], pathIn[0])); } else { norms.Add(new PointD(norms[pathInCnt - 2])); } if (node.endType == EndType.Polygon) { int k = pathInCnt - 1; for (int j = 0; j < pathInCnt; j++) { OffsetPoint(j, ref k, node.joinType); } solution.Add(pathOut); } else if (node.endType == EndType.OpenJoined) { int k = pathInCnt - 1; for (int j = 0; j < pathInCnt; j++) { OffsetPoint(j, ref k, node.joinType); } solution.Add(pathOut); pathOut = new Path(); //re-build norms ... PointD n = norms[pathInCnt - 1]; for (int j = pathInCnt - 1; j > 0; j--) { norms[j] = new PointD(-norms[j - 1].X, -norms[j - 1].Y); } norms[0] = new PointD(-n.X, -n.Y); k = 0; for (int j = pathInCnt - 1; j >= 0; j--) { OffsetPoint(j, ref k, node.joinType); } solution.Add(pathOut); } else { int k = 0; for (int j = 1; j < pathInCnt - 1; j++) { OffsetPoint(j, ref k, node.joinType); } Point64 pt1; if (node.endType == EndType.OpenButt) { int j = pathInCnt - 1; pt1 = new Point64((Int64)Round(pathIn[j].X + norms[j].X * delta), (Int64)Round(pathIn[j].Y + norms[j].Y * delta)); pathOut.Add(pt1); pt1 = new Point64((Int64)Round(pathIn[j].X - norms[j].X * delta), (Int64)Round(pathIn[j].Y - norms[j].Y * delta)); pathOut.Add(pt1); } else { int j = pathInCnt - 1; k = pathInCnt - 2; sinA = 0; norms[j] = new PointD(-norms[j].X, -norms[j].Y); if (node.endType == EndType.OpenSquare) { DoSquare(j, k); } else { DoRound(j, k); } } //reverse norms ... for (int j = pathInCnt - 1; j > 0; j--) { norms[j] = new PointD(-norms[j - 1].X, -norms[j - 1].Y); } norms[0] = new PointD(-norms[1].X, -norms[1].Y); k = pathInCnt - 1; for (int j = k - 1; j > 0; --j) { OffsetPoint(j, ref k, node.joinType); } if (node.endType == EndType.OpenButt) { pt1 = new Point64((Int64)Round(pathIn[0].X - norms[0].X * delta), (Int64)Round(pathIn[0].Y - norms[0].Y * delta)); pathOut.Add(pt1); pt1 = new Point64((Int64)Round(pathIn[0].X + norms[0].X * delta), (Int64)Round(pathIn[0].Y + norms[0].Y * delta)); pathOut.Add(pt1); } else { k = 1; sinA = 0; if (node.endType == EndType.OpenSquare) { DoSquare(0, 1); } else { DoRound(0, 1); } } solution.Add(pathOut); } } }
public PointD(Point64 ip) { this.X = ip.X; this.Y = ip.Y; }