Handdrawn Lines for Highcharts - charts

How would you extend Highcharts to accomplish a "hand-drawn" effect (example: https://www.amcharts.com/demos/column-and-line-mix/?theme=chalk ).
Or can it be done using a library?

Implementing that in Highcharts requires some core code analyzing and wrapping/overwriting SVGRenderer methods.
Example
Column points are SVG rect's shapes:
https://github.com/highcharts/highcharts/blob/master/js/parts/ColumnSeries.js
translate function:
// Register shape type and arguments to be used in drawPoints
point.shapeType = 'rect';
drawPoints function:
point.graphic = graphic =
renderer[point.shapeType](shapeArgs)
.add(point.group || series.group);
SVGRenderer (https://github.com/highcharts/highcharts/blob/master/js/parts/SvgRenderer.js) contains rect method that can be wrapperd/overwritten so that it returns the complex path (handwritten effect) instead of simple rect tag.
Docs about wrapping/overwriting: https://www.highcharts.com/docs/extending-highcharts/extending-highcharts

Related

AnyLogic: is it possible to embed code to define a color?

In the Java source code of my class, I saw that color is integrated as a method call with the input color as a word. So it seems that you can't implement any code, because color is defined with shape.setFillColor().
Is there a way around this? Otherwise a more complicated coloring would not be possible.
I have attached an example here in this screenshot how I could imagine it, however I get some errors because semicolons are missing and I have not declared the variables. So my problem is that i don't know how and if i can query if-else as well as embed switch case. So how can I write various functions for a color setting?
Can someone help me?
Example code for a color change of a rectangle
You could define a function that returns Color type, e.g. chooseColor(<your parameters>) and you could call shape.setFillColor(chooseColor(<your parameters>)). The body of the chooseColor() function can be based on the example code you posted.
Or you could call the chooseColor() function directly at the Fill color property of your shape if it is not too computation heavy, otherwise it could slow down the simulation.
Not quite sure what you need, tbh. You can make coloring as complex as you like. But once you decide on a color, you must call shape.setFillColor(theColorYouChose) to actually do it...
You can, however, create any possible color using Color myNewColor = new Color(x,y,z,a) where x, y and z are RGB values (0-255) and the last is the transparency you want (also 0-255)
To use this with switch/if statements, you can create a local Color variable and use it at the end for the shape:
Color myColor = new Color(0,0,0,0);
switch(someThing) {
case myCase:
myColor = yellowGreen;
break;
case myOtherCase:
if (someCondition) {
myColor = new Color(12, 222,45,122);
} else {
myColor = blue;
}
break;
}
shape.setFillColor(myColor);

How to figure out resolution array from user inputted ArcGIS projection data

I have a Leaflet based mapping solution that uses ArcGIS map configuration supplied by a user (I have no idea what it will be, they will customize it with their own ArcGIS services). The issue is that the projection can be pretty much anything, and I will need to use Proj4Leaflet to configure the CRS of the map accordingly. The problem I'm running into is I'm not sure how to calculate the scale/resolution array. The user is inputting these values: projection key, Proj4 string, origin, bounds, zoom levels.
So, for example (yes I know EPSG:3857 is standard and I could just use L.CRS.EPSG3857 but it serves as a good example of how to set the same thing up using Proj4Leaflet):
Projection key = EPSG:3857
Proj4 string = +proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 +lon_0=0.0 +x_0=0.0 +y_0=0 +k=1.0 +units=m +nadgrids=#null +wktext +no_defs
Origin = [0,0]
Bounds = [[-20026376.39, -20048966.10], [20026376.39, 20048966.10]]
Zoom levels = 18
With that I think I have enough to set up a L.Proj.CRS for it:
var crs = new L.Proj.CRS("EPSG:3857", "+proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 +lon_0=0.0 +x_0=0.0 +y_0=0 +k=1.0 +units=m +nadgrids=#null +wktext +no_defs",
{
resolutions : [?????],
origin : [0,0],
bounds : [[-20026376.39, -20048966.10], [20026376.39, 20048966.10]]
});
I have everything I need apart from the resolutions array, I am not sure exactly how to go about setting that up based on the data given and having a hard time finding answers to get me pointed in the right direction.
So bottom line, the only way I found to calculate resolutions is if it is a mercator projection and we know the longitude extents of it and the tile size. Otherwise the resolutions will need to be looked up at the ArcGIS Server tile server REST endpoint. Thus for my project I will need the user to supply the array themselves and cannot calculate it for them.
In the case of the mercator projection, I came up with this function that does the trick:
function parseResolutionsFromZoomLevels(zoomLevels, tileSize, mapWGS84Extent)
{
var metersPerExtent = 40075008/360;
var mapWGS84Meters = mapWGS84Extent*metersPerExtent;
var resolutionArray = [];
for (var i=0; i<zoomLevels; i++)
{
var tilesAtZoom = Math.pow(2,i);
var pixelsAtZoom = tilesAtZoom*tileSize;
resolutionArray.push(mapWGS84Meters/pixelsAtZoom);
}
return resolutionArray;
}
Hope this helps anyone else that happens to encounter this same situation.

Error when using Circle getBounds() and contains()

I'm getting the error below when trying to run getBounds() and contains() with a Circle shape.
leaflet.js:7 Uncaught TypeError: Cannot read property 'layerPointToLatLng' of undefined
I'm able to use it with the other shapes, but the circle is being stubborn. I tried this solution from another question, but no success.
Here's the code I have for the polygon and rectangle shapes:
drawnLayers.eachLayer(function(l) {
if (type == 'circle') {
// console.log(l.getBounds().contains(layer.getBounds()));
} else {
if (l.getBounds().contains(layer.getBounds())) {
isDonut = true;
l._latlngs.push(layer.getLatLngs());
l.redraw();
$('#map-info').append("<br>New Polygon: <pre>" +
JSON.stringify(l.getLatLngs(), null, 2) + '</pre>');
}
}
});
l.getBounds().contains(layer.getBounds())
getBounds() is a method specific only to polyline/polygon/rectangle in leaflet 0.7.x
It was added to circle shapes as of version 1.0.0 - see leaflet reference versions
To solve the problem you have 2 options
use some other methods for circles like getRadius() and compute by yourself if the shape contains your other shape
upgrade your leaflet library
Personally I would upgrade the leaflet library to 1.0.3 (which I did very easy and without any compatibility issues on my project)

Optimal way of drawing hexagonal map with GWT

I'm looking for best solution - I'm drawing a hexagonal map (Civilization like :) ) for my browser based game in GWT. Currently I'm drawing it on canvas which basically works.
However - I'm also able to slide map left,right,down and up to see another fragment of the map. In such situation I'm forced to redraw the whole map - which doesn't look too good, and will probaly cause preformance issues when the map gets more complex.
Is there a better approach for that? Some library? Or maybe I should make every hex a button like widget. so I could be able to move it instead creating from the scratch... but what about different resolutions then... I'm affraid the map could tear apart sometimes...
You could try doing it will simple DIVs (FlowPanel, HTMLPanel, etc) and style the hexagons using CSS. See this tutorial: http://jtauber.github.com/articles/css-hexagon.html
There are some neat suggestions here as well: html/css hexagon with image inside and hexagonal shaped cells in html
You could draw the entire map (usually just the relatively static background, not the animations!) in a hidden canvas, and then copy the parts you need to your visible canvas:
final Canvas hiddenCanvas = buildCanvas(1000, 1000);
drawHexPattern(hiddenCanvas);
// don't add the hiddenCanvas to your DOM
final Canvas visibleCanvas = buildCanvas(320, 200);
RootPanel.get().add(visibleCanvas); // add the visibleCanvas to the DOM
showArea(hiddenCanvas, visibleCanvas, 0, 0);
...
showArea(hiddenCanvas, visibleCanvas, 20, 10);
...
With a showArea() method like
private void showArea(final Canvas hiddenCanvas, final Canvas visibleCanvas,
final double x, final double y) {
final Context2d hiddenCtx = hiddenCanvas.getContext2d();
final Context2d visibleCtx = visibleCanvas.getContext2d();
final ImageData imageData = hiddenCtx.getImageData(x, y,
visibleCanvas.getCoordinateSpaceWidth(),
visibleCanvas.getCoordinateSpaceHeight());
visibleCtx.putImageData(imageData, 0, 0);
}
I created a pastebin with a working example: http://pastebin.com/tPN2093a

Get size of repeated pattern from UIColor?

I can query if a UIColor is a pattern by inspecting the CGColor instance it wraps, the CGColorGetPattern() function returns the pattern if it exist, or null if it is not a pattern color.
CGPatternCreate() method requires a bounds when creating a pattern, this value defines the size of the pattern tile (Known as cell in Quartz parlance).
How would I go about to retrieve this pattern size from a UIColor, or the backing CGPattern once it has been created?
If your application is intended for internal distribution only, then you can use a private API. If you look at the functions defined in the CoreGraphics framework, you will see that there is a bunch of functions and among them one called CGPatternGetBounds:
otool -tV /Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS4.3.sdk/System/Library/Frameworks/CoreGraphics.framework/CoreGraphics | egrep "^_CGPattern"
You just have to make some function lookup on the framework and use it through a function pointer.
The header to include:
#include <dlfcn.h>
The function pointer:
typedef CGRect (*CGPatternGetBounds)(CGPatternRef pattern);
The code to retrieve the function:
void *handle = dlopen("/System/Library/Frameworks/CoreGraphics.framework/CoreGraphics", RTLD_NOW);
CGPatternGetBounds getBounds = (CGPatternGetBounds) dlsym(handle, "CGPatternGetBounds");
The code to retrieve the bounds:
UIColor *uicolor = [UIColor groupTableViewBackgroundColor]; // Select a pattern color
CGColorRef color = [uicolor CGColor];
CGPatternRef pattern = CGColorGetPattern(color);
CGRect bounds = getBounds (pattern); // This result is a CGRect(0, 0, 84, 1)
I dont think its possible to get the bounds from the CGPatternRef, if thats what you're asking
There does not appear to be any way to directly retrieve any information from the CGPatternRef.
If you must do this, probably the only way (besides poking at the private contents of the CGPattern struct, which probably counts as "using private APIs") is to render the pattern to a sufficiently large image buffer and then detect the repeating subunit. Finding repeating patterns/images in images may be a good starting point for that.
Making your own color class that stores the bounds and let you access them through a property might be a viable solution.
Extracting the pattern bounds from UIColor doesn't seem to be possible.