/// <summary> /// Draw square boxes around each area to approximate how they would behave in an offline app /// </summary> /// <param name="info">the image information for drawing</param> /// <param name="items">the elements to draw.</param> /// <returns>byte array of the generated .png tile image</returns> public byte[] DrawOfflineEstimatedAreas(ImageStats info, List <DbTables.Place> items) { SKBitmap bitmap = new SKBitmap(info.imageSizeX, info.imageSizeY, SKColorType.Rgba8888, SKAlphaType.Premul); SKCanvas canvas = new SKCanvas(bitmap); var bgColor = SKColors.Transparent; canvas.Clear(bgColor); canvas.Scale(1, -1, info.imageSizeX / 2, info.imageSizeY / 2); SKPaint fillpaint = new SKPaint(); fillpaint.IsAntialias = true; fillpaint.Style = SKPaintStyle.Fill; var strokePaint = new SKPaint(); strokePaint.Color = SKColors.Black; strokePaint.TextSize = 32; strokePaint.StrokeWidth = 3; strokePaint.Style = SKPaintStyle.Stroke; strokePaint.TextAlign = SKTextAlign.Center; //TagParser.ApplyTags(items); var placeInfo = PraxisCore.Standalone.Standalone.GetPlaceInfo(items.Where(i => i.IsGameElement ).ToList()); //this is for rectangles. foreach (var pi in placeInfo) { var rect = PlaceInfoToRect(pi, info); fillpaint.Color = SKColor.Parse(TagParser.PickStaticColorForArea(pi.Name)); canvas.DrawRect(rect, fillpaint); canvas.DrawRect(rect, strokePaint); } canvas.Scale(1, -1, info.imageSizeX / 2, info.imageSizeY / 2); //inverts the inverted image again! foreach (var pi in placeInfo) { var rect = PlaceInfoToRect(pi, info); canvas.DrawText(pi.Name, rect.MidX, info.imageSizeY - rect.MidY, strokePaint); } var ms = new MemoryStream(); var skms = new SKManagedWStream(ms); bitmap.Encode(skms, SKEncodedImageFormat.Png, 100); var results = ms.ToArray(); skms.Dispose(); ms.Close(); ms.Dispose(); return(results); }
/// <summary> /// Take a path provided by a user, draw it as a maptile. Potentially useful for exercise trackers. Resulting file must not be saved to the server as that would be user tracking. /// </summary> /// <param name="pointListAsString">a string of points separate by , and | </param> /// <returns>the png file with the path drawn over the mapdata in the area.</returns> public byte[] DrawUserPath(string pointListAsString) { //String is formatted as Lat,Lon~Lat,Lon~ repeating. Characters chosen to not be percent-encoded if submitted as part of the URL. //first, convert this to a list of latlon points string[] pointToConvert = pointListAsString.Split("|"); List <Coordinate> coords = pointToConvert.Select(p => new Coordinate(double.Parse(p.Split(',')[0]), double.Parse(p.Split(',')[1]))).ToList(); var mapBuffer = resolutionCell8 / 2; //Leave some area around the edges of where they went. GeoArea mapToDraw = new GeoArea(coords.Min(c => c.Y) - mapBuffer, coords.Min(c => c.X) - mapBuffer, coords.Max(c => c.Y) + mapBuffer, coords.Max(c => c.X) + mapBuffer); ImageStats info = new ImageStats(mapToDraw, 1024, 1024); LineString line = new LineString(coords.ToArray()); var drawableLine = PolygonToSKPoints(line, mapToDraw, info.degreesPerPixelX, info.degreesPerPixelY); //Now, draw that path on the map. var places = GetPlaces(mapToDraw); //, null, false, false, degreesPerPixelX * 4 ///TODO: restore item filtering var baseImage = DrawAreaAtSize(info, places); SKBitmap sKBitmap = SKBitmap.Decode(baseImage); SKCanvas canvas = new SKCanvas(sKBitmap); SKPaint paint = new SKPaint(); paint.Style = SKPaintStyle.Stroke; paint.StrokeWidth = 4; //Larger than normal lines at any zoom level. paint.Color = new SKColor(0, 0, 0); //Pure black, for maximum visibility. for (var x = 0; x < drawableLine.Length - 1; x++) { canvas.DrawLine(drawableLine[x], drawableLine[x + 1], paint); } var ms = new MemoryStream(); var skms = new SKManagedWStream(ms); sKBitmap.Encode(skms, SKEncodedImageFormat.Png, 100); var results = ms.ToArray(); skms.Dispose(); ms.Close(); ms.Dispose(); return(results); }
public byte[] DrawAreaAtSize(ImageStats stats, List <CompletePaintOp> paintOps) { //This is the new core drawing function. Once the paint operations have been created, I just draw them here. //baseline image data stuff SKBitmap bitmap = new SKBitmap(stats.imageSizeX, stats.imageSizeY, SKColorType.Rgba8888, SKAlphaType.Premul); SKCanvas canvas = new SKCanvas(bitmap); canvas.Clear(eraser.Color); canvas.Scale(1, -1, stats.imageSizeX / 2, stats.imageSizeY / 2); SKPaint paint = new SKPaint(); foreach (var w in paintOps.OrderByDescending(p => p.paintOp.LayerId).ThenByDescending(p => p.areaSize)) { paint = cachedPaints[w.paintOp.Id]; //SetPaintForTPP(w.paintOp); // w.paintOp.paint; if (w.paintOp.FromTag) //FromTag is for when you are saving color data directly to each element, instead of tying it to a styleset. { paint.Color = SKColor.Parse(w.tagValue); } if (w.paintOp.Randomize) //To randomize the color on every Draw call. { paint.Color = new SKColor((byte)r.Next(0, 255), (byte)r.Next(0, 255), (byte)r.Next(0, 255), 99); } paint.StrokeWidth = (float)w.lineWidthPixels; var path = new SKPath(); switch (w.elementGeometry.GeometryType) { case "Polygon": var p = w.elementGeometry as Polygon; //if (p.Envelope.Length < (stats.degreesPerPixelX * 4)) //This poly's perimeter is too small to draw //continue; path.AddPoly(PolygonToSKPoints(p.ExteriorRing, stats.area, stats.degreesPerPixelX, stats.degreesPerPixelY)); foreach (var ir in p.Holes) { //if (ir.Envelope.Length < (w.lineWidth * 4)) //This poly's perimeter is less than 2x2 pixels in size. //continue; path.AddPoly(PolygonToSKPoints(ir, stats.area, stats.degreesPerPixelX, stats.degreesPerPixelY)); } canvas.DrawPath(path, paint); break; case "MultiPolygon": foreach (var p2 in ((MultiPolygon)w.elementGeometry).Geometries) { //if (p2.Envelope.Length < (stats.degreesPerPixelX * 4)) //This poly's perimeter is too small to draw //continue; var p2p = p2 as Polygon; path.AddPoly(PolygonToSKPoints(p2p.ExteriorRing, stats.area, stats.degreesPerPixelX, stats.degreesPerPixelY)); foreach (var ir in p2p.Holes) { //if (ir.Envelope.Length < (stats.degreesPerPixelX * 4)) //This poly's perimeter is too small to draw // continue; path.AddPoly(PolygonToSKPoints(ir, stats.area, stats.degreesPerPixelX, stats.degreesPerPixelY)); } canvas.DrawPath(path, paint); } break; case "LineString": var firstPoint = w.elementGeometry.Coordinates.First(); var lastPoint = w.elementGeometry.Coordinates.Last(); var points = PolygonToSKPoints(w.elementGeometry, stats.area, stats.degreesPerPixelX, stats.degreesPerPixelY); if (firstPoint.Equals(lastPoint)) { //This is a closed shape. Check to see if it's supposed to be filled in. if (paint.Style == SKPaintStyle.Fill) { path.AddPoly(points); canvas.DrawPath(path, paint); continue; } } //if (w.lineWidth < 1) //Don't draw lines we can't see. //continue; for (var line = 0; line < points.Length - 1; line++) { canvas.DrawLine(points[line], points[line + 1], paint); } break; case "MultiLineString": //if (w.lineWidth < 1) //Don't draw lines we can't see. //continue; foreach (var p3 in ((MultiLineString)w.elementGeometry).Geometries) { var points2 = PolygonToSKPoints(p3, stats.area, stats.degreesPerPixelX, stats.degreesPerPixelY); for (var line = 0; line < points2.Length - 1; line++) { canvas.DrawLine(points2[line], points2[line + 1], paint); } } break; case "Point": var convertedPoint = PolygonToSKPoints(w.elementGeometry, stats.area, stats.degreesPerPixelX, stats.degreesPerPixelY); //If this type has an icon, use it. Otherwise draw a circle in that type's color. if (!string.IsNullOrEmpty(w.paintOp.FileName)) { SKBitmap icon = SKBitmap.Decode(TagParser.cachedBitmaps[w.paintOp.FileName]); //TODO optimize by making icons in Initialize. canvas.DrawBitmap(icon, convertedPoint[0]); } else { var circleRadius = (float)(ConstantValues.resolutionCell10 / stats.degreesPerPixelX / 2); //I want points to be drawn as 1 Cell10 in diameter. canvas.DrawCircle(convertedPoint[0], circleRadius, paint); //TODO re-add outline paint to this DLL not TagParser. //canvas.DrawCircle(convertedPoint[0], circleRadius, TagParser.outlinePaint); } break; default: Log.WriteLog("Unknown geometry type found, not drawn."); break; } } //} var ms = new MemoryStream(); var skms = new SKManagedWStream(ms); bitmap.Encode(skms, SKEncodedImageFormat.Png, 100); var results = ms.ToArray(); skms.Dispose(); ms.Close(); ms.Dispose(); return(results); }