OpenLayers3 Custom Scale Select Options: Calculation needed - openlayers-3

I'm a newbie using OpenLayers 3 and having the following problem:
I've created a custom control (select box; see image) where I would like to add 3 predefined scale options (see code after image).
let option2 = new Option('1 : 150.000', '2183910.7260319907', false, false);
option2.id = 'opt2';
select.appendChild(option2);
let option3 = new Option('1 : 30.000', '2183910.7260319907', false, false);
option3.id = 'opt3';
select.appendChild(option3);
let option4 = new Option('1 : 15.000', '2183910.7260319907', false, false);
option4.id = 'opt4';
select.appendChild(option4);
From other sources I've found that I "simply" need to pass the correct value (above it would be 2183910.7260319907 for the 1:2M scale) to the respective scale option and then I've already implemented the set resolution function in order to update the map.
Question: How can I now calculate that particular value (I don't even know what it represents...) for the scales of 1:150.000, 1:30.000 and 1:15.000?
Thank you so much in advance & if something is not clear, I'm happy to clarify and provide more code/screenshots if necessary.
Cheers :)

In web cartography, we work with resolutions, not scales. Resolution simply means map units per screen pixel.
If you want to apply the concept of paper map scales, you'll need to make assumptions about the resolution of the user's screen, which is usually expressed in dots per inch (dpi). Then you can calculate the scale like this:
var inchesPerMeter = 39.3700787;
var dpi = 96;
function getResolutionForScale(scaleDenominator) {
return scaleDenominator / inchesPerMeter / dpi;
}
To use this, simply use the scale denominator as value in your options. So e.g. 2000000 for the "1 : 2.000.000" scale. Then it is easy to apply the scale to the map:
map.getView().setResolution(getResolutionForScale(scaleDenominator));
Side note if you want to get super accurate: projections like Web Mercator have different resolutions for different latitudes. To accommodate for that, you could use ol.proj.getPointResolution() to get the true resolution for a specific location on the map, and adjust the result from getResolutionForScale() accordingly:
var view = map.getView();
view.setResolution(ol.proj.getPointResolution(
view.getProjection(),
getResolutionForScale(scaleDenominator),
view.getCenter());

Related

highcharts change smoothing setting on polar areaspline chart

is there any way to change the smoothing setting via config ?
https://github.com/highcharts/highcharts/blob/master/ts/parts-more/Polar.ts
line 190.
Or do I have to override some functions ? for info - I'm trying to change the interpolation and have got this far. If there is a better way to change the interpolation that would be an acceptable solution.
The problem I am trying to solve is where the interpolated area chart curves actually plot outside of the radar chart because the curvature is too large (ie when every value is at its maximum)
Many thanks
It is impossible to change this value via the config. You can report this idea here: https://github.com/highcharts/highcharts/issues - if core developers will see that this feature is needed they will implement it in the future.
For now, as a workaround, you can overwrite the whole function as a function with changed value.
Demo: https://jsfiddle.net/BlackLabel/j362zfpq/
Highcharts.Series.prototype.getConnectors = function(segment, index, calculateNeighbours, connectEnds) {
var i, prevPointInd, nextPointInd, previousPoint, nextPoint, previousX, previousY, nextX, nextY, plotX, plotY, ret,
// 1 means control points midway between points, 2 means 1/3 from
// the point, 3 is 1/4 etc;
smoothing = 1,
denom = smoothing + 1,
leftContX, leftContY, rightContX, rightContY, dLControlPoint, // distance left control point
dRControlPoint, leftContAngle, rightContAngle, jointAngle, addedNumber = connectEnds ? 1 : 0;
....
}

custom image filter

1.Introduction:
So I want to develop a special filter method for uiimages - my idea is to change from one picture all the colors to black except a certain color, which should keep their appearance.
Images are always nice, so look at this image to get what I'd like to achieve:
2.Explanation:
I'd like to apply a filter (algorithm) that is able to find specific colors in an image. The algorithm must be able to replace all colors that are not matching to the reference colors with e.g "black".
I've developed a simple code that is able to replace specific colors (color ranges with threshold) in any image.
But tbh this solution doesn't seems to be a fast & efficient way at all!
func colorFilter(image: UIImage, findcolor: String, threshold: Int) -> UIImage {
let img: CGImage = image.cgImage!
let context = CGContext(data: nil, width: img.width, height: img.height, bitsPerComponent: 8, bytesPerRow: 4 * img.width, space: CGColorSpaceCreateDeviceRGB(), bitmapInfo: CGImageAlphaInfo.premultipliedLast.rawValue)!
context.draw(img, in: CGRect(x: 0, y: 0, width: img.width, height: img.height))
let binaryData = context.data!.assumingMemoryBound(to: UInt8.self),
referenceColor = HEXtoHSL(findcolor) // [h, s, l] integer array
for i in 0..<img.height {
for j in 0..<img.width {
let pixel = 4 * (i * img.width + j)
let pixelColor = RGBtoHSL([Int(binaryData[pixel]), Int(binaryData[pixel+1]), Int(binaryData[pixel+2])]) // [h, s, l] integer array
let distance = calculateHSLDistance(pixelColor, referenceColor) // value between 0 and 100
if (distance > threshold) {
let setValue: UInt8 = 255
binaryData[pixel] = setValue; binaryData[pixel+1] = setValue; binaryData[pixel+2] = setValue; binaryData[pixel+3] = 255
}
}
}
let outputImg = context.makeImage()!
return UIImage(cgImage: outputImg, scale: image.scale, orientation: image.imageOrientation)
}
3.Code Information The code above is working quite fine but is absolutely ineffective. Because of all the calculation (especially color conversion, etc.) this code is taking a LONG (too long) time, so have a look at this screenshot:
My question I'm pretty sure there is a WAY simpler solution of filtering a specific color (with a given threshold #c6456f is similar to #C6476f, ...) instead of looping trough EVERY single pixel to compare it's color.
So what I was thinking about was something like a filter (CIFilter-method) as alternative way to the code on top.
Some Notes
So I do not ask you to post any replies that contain suggestions to use the openCV libary. I would like to develop this "algorithm" exclusively with Swift.
The size of the image from which the screenshot was taken over time had a resolution of 500 * 800px
Thats all
Did you really read this far? - congratulation, however - any help how to speed up my code would be very appreciated! (Maybe theres a better way to get the pixel color instead of looping trough every pixel) Thanks a million in advance :)
First thing to do - profile (measure time consumption of different parts of your function). It often shows that time is spent in some unexpected place, and always suggests where to direct your optimization effort. It doesn't mean that you have to focus on that most time consuming thing though, but it will show you where the time is spent. Unfortunately I'm not familiar with Swift so cannot recommend any specific tool.
Regarding iterating through all pixels - depends on the image structure and your assumptions about input data. I see two cases when you can avoid this:
When there is some optimized data structure built over your image (e.g. some statistics in its areas). That usually makes sense when you process the same image with same (or similar) algorithm with different parameters. If you process every image only once, likely it will not help you.
When you know that the green pixels always exist in a group, so there cannot be an isolated single pixel. In that case you can skip one or more pixels and when you find a green pixel, analyze its neighbourhood.
I do not code on your platform but...
Well I assume your masked areas (with the specific color) are continuous and large enough ... that means you got groups of pixels together with big enough areas (not just few pixels thick stuff). With this assumption you can create a density map for your color. What I mean if min detail size of your specific color stuff is 10 pixels then you can inspect every 8th pixel in each axis speeding up the initial scan ~64 times. And then use the full scan only for regions containing your color. Here is what you have to do:
determine properties
You need to set the step for each axis (how many pixels you can skip without missing your colored zone). Let call this dx,dy.
create density map
simply create 2D array that will hold info if center pixel of region is set with your specific color. so if your image has xs,ys resolution than your map will be:
int mx=xs/dx;
int my=ys/dy;
int map[mx][my],x,y,xx,yy;
for (yy=0,y=dy>>1;y<ys;y+=dy,yy++)
for (xx=0,x=dx>>1;x<xs;x+=dx,xx++)
map[xx][yy]=compare(pixel(x,y) , specific_color)<threshold;
enlarge map set areas
now you should enlarge the set areas in map[][] to neighboring cells because #2 could miss edge of your color region.
process all set regions
for (yy=0;yy<my;yy++)
for (xx=0;xx<mx;xx++)
if (map[xx][yy])
for (y=yy*dy,y<(yy+1)*dy;y++)
for (x=xx*dx,x<(xx+1)*dx;x++)
if (compare(pixel(x,y) , specific_color)>=threshold) pixel(x,y)=0x00000000;
If you want to speed up this even more than you need to detect set map[][] cells that are on edge (have at least one zero neighbor) you can distinquish the cells like:
0 - no specific color is present
1 - inside of color area
2 - edge of color area
That can be done by simply in O(mx*my). After that you need to check for color only the edge regions so:
for (yy=0;yy<my;yy++)
for (xx=0;xx<mx;xx++)
if (map[xx][yy]==2)
{
for (y=yy*dy,y<(yy+1)*dy;y++)
for (x=xx*dx,x<(xx+1)*dx;x++)
if (compare(pixel(x,y) , specific_color)>=threshold) pixel(x,y)=0x00000000;
} else if (map[xx][yy]==0)
{
for (y=yy*dy,y<(yy+1)*dy;y++)
for (x=xx*dx,x<(xx+1)*dx;x++)
pixel(x,y)=0x00000000;
}
This should be even faster. In case your image resolution xs,ys is not a multiple of region size mx,my you should handle the outer edge of image either by zero padding or by special loops for that missing part of image...
btw how long it takes to read and set your whole image?
for (y=0;y<ys;y++)
for (x=0;x<xs;x++)
pixel(x,y)=pixel(x,y)^0x00FFFFFF;
if this alone is slow than it means your pixel access is too slow and you should use different api for this. That is very common mistake on Windows GDI platform as people usually use Pixels[][] which is slower than crawling snail. there are other ways like bitlocking/blitting,ScanLine etc so in such case you need to look for something fast on your platform. If you are not able to speed even this stuff than you can not do anything else ... btw what HW is this run on?

SceneKit - Textures not properly displayed

I have a cube (rounded) and want to display a texture on one of it's side. I can access the material on that side with:
var tex1: SCNMaterial! = cube.geometry?.materialWithName("_1")!
I then set it's image contents:
tex1.diffuse.contents = "cube1"
This then looks like this:
This shows me that it does work, but the white part is not in the center as
it should be. (The image I am using has the white part in the center.)
I tried to use offset to move the image around on the surface, I would like scale it as well. I tried it like this:
tex1.diffuse.contents.offset = SCNVector3Make(20, 0, 0)
That gives me errors: it says it cannot assign the result of that expression. (I also tried contentMode, same error, I think because these are for UI, not SCN)
Questions
Does anyone know what I can do?
Maybe offset is not the way to go?
How can I scale the image?
The type of a material property's contents is AnyObject, which means the compiler will allow you to call any method (defined on any object type) on it. That doesn't mean all methods or property accessors are actually really implemented by the actual class that's in your particular contents.
Material properties do have a contentsTransform option, though. Have you looked at that?
Here is my solution :
create offset:
let offsetVal = SCNMatrix4MakeTranslation(0, -0.05, 0)
create scale:
let scaleVal = SCNMatrix4MakeScale(1.5, 1.5, 1.5)
if you want to set Offset Property only:
material.diffuse.contentsTransform = offsetVal
if you want to set Scale Property only:
material.diffuse.contentsTransform = scaleVal
if you want to mix them:
material.diffuse.contentsTransform = SCNMatrix4Mult(scaleVal, offsetVal)
hope this helpful!!!

Draw only part of data in Highcharts

I looking for a way to only draw part of the data set in area chart. There is a slider above the chart that can limit the range of one series in the chart while other stile rendered in whole. I wonder whats the best way to do this. The only idea at the moment is to redraw the chart every time the slider moves but I'm afraid this could result in worse performance. Maybe this could be done with something like mask on the SVG element.
I came up with a simple solution by just clipping the svg graph with an clip path:
//var chart is the actual HighChartsInstance;
var renderer = chart.renderer;
var group = renderer.g().add();
var clipPath = renderer.createElement("clipPath");
clipPath.element.id = 'clip';
var rect = renderer.rect(0, 0, 200, 400).add(clipPath);
this.clippingMask = rect.element; //reference to the clipping rect which width is changed by the slider
clipPath.add(group);
chart.series[1].group.element.setAttribute('clip-path', "url(#clip)");
chart.series[1].group.element.childNodes[0].setAttribute('clip-path', "url(#clip)");
You have a few ways
use highstock which contains "slider" http://www.highcharts.com/stock/demo/
use highstock.js and highcharts chart with scroller http://jsfiddle.net/UCmUx/
scrollbar:{
enabled:true
},
use highcharts chart without scroller http://jsfiddle.net/UCmUx/1/ and in case when you move your own scroller, then use setExtremes() http://api.highcharts.com/highcharts#Axis.setExtremes()
I think one option is to modify the series data which you want to restrict, and then call:
chart.series[n].setData(newData);
where 'n' is the number of the series you are truncating. newData is a copy of the series data with the unwanted points taken out. You will need to specify x and y values in the series in order for it to be plotted in the correct position.

Repeating 2d world

How to make a 2d world with fixed size, which would repeat itself when reached any side of the map?
When you reach a side of a map you see the opposite side of the map which merged togeather with this one. The idea is that if you didn't have a minimap you would not even notice the transition of map repeating itself.
I have a few ideas how to make it:
1) Keeping total of 3x3 world like these all the time which are exactly the same and updated the same way, just the players exists in only one of them.
2) Another way would be to seperate the map into smaller peaces and add them to required place when asked.
Either way it can be complicated to complete it. I remember that more thatn 10 years ago i played some game like that with soldiers following each other in a repeating wold shooting other AI soldiers.
Mostly waned to hear your thoughts about the idea and how it could be achieved. I'm coding in XNA(C#).
Another alternative is to generate noise using libnoise libraries. The beauty of this is that you can generate noise over a theoretical infinite amount of space.
Take a look at the following:
http://libnoise.sourceforge.net/tutorials/tutorial3.html#tile
There is also an XNA port of the above at: http://bigblackblock.com/tools/libnoisexna
If you end up using the XNA port, you can do something like this:
Perlin perlin = new Perlin();
perlin.Frequency = 0.5f; //height
perlin.Lacunarity = 2f; //frequency increase between octaves
perlin.OctaveCount = 5; //Number of passes
perlin.Persistence = 0.45f; //
perlin.Quality = QualityMode.High;
perlin.Seed = 8;
//Create our 2d map
Noise2D _map = new Noise2D(CHUNKSIZE_WIDTH, CHUNKSIZE_HEIGHT, perlin);
//Get a section
_map.GeneratePlanar(left, right, top, down);
GeneratePlanar is the function to call to get the sections in each direction that will connect seamlessly with the rest of your world.
If the game is tile based I think what you should do is:
Keep only one array for the game area.
Determine the visible area using modulo arithmetics over the size of the game area mod w and h where these are the width and height of the table.
E.g. if the table is 80x100 (0,0) top left coordinates with a width of 80 and height of 100 and the rect of the viewport is at (70,90) with a width of 40 and height of 20 you index with [70-79][0-29] for the x coordinate and [90-99][0-9] for the y. This can be achieved by calculating the index with the following formula:
idx = (n+i)%80 (or%100) where n is the top coordinate(x or y) for the rect and i is in the range for the width/height of the viewport.
This assumes that one step of movement moves the camera with non fractional coordinates.
So this is your second alternative in a little bit more detailed way. If you only want to repeat the terrain, you should separate the contents of the tile. In this case the contents will most likely be generated on the fly since you don't store them.
Hope this helped.

Resources