Attribute based rotation and offset with OpenLayers WebGL Points Layer - rotation

Using normal vector layers, I already draw directed antenna symbolizers like this:
Basically this is a point with a direction (and a horizontal beam width, but let's forget about that for now). This is what I try to recreate in OL 6.8.1 using WebGLPoints layer, but have issues with creating the correct style. I way able to rotate simple triangle symbols but they are overlapping, and they should touch by the corners:
I guess the key to the problem is setting some offset, but this is where I failed to find a working solution. This is the style I currently use:
symbol: {
symbolType: 'triangle',
size: ['interpolate', ['exponential', 2.5], ['zoom'], 6, 10, 20, 100],
color: ['case',["==", ['get','band'],2100], '#aa0000',["==", ['get','band'],3500], '#00aa00', '#0000aa' ],
rotateWithView: true,
offset: [ 0,0 ],
opacity: 0.4,
rotation: ['-', ['*', ['get','azy'] , 0.01745329251 ], 3.1415926],
}
(notes: as you can see the symbol size is zoom dependent, I use 2 different colors based on the 'band' attribute and rotate it using the 'azy' attribute (which is the desired direction in degrees, counted from N as 0, clockwise))
The rotation works okay, but for the offset, I need some help. I'm not even sure of it's affected by the rotation or not... Thanks in advance! If you have any other solution for the problem using WebGL, I'd appreciate that too!

So, here's the solution, thanks to #Mike! The trick is to multiply the offset with -1, so the corners of the triangles touch.
symbol: {
symbolType: 'triangle',
size: ['interpolate', ['exponential', 2.5], ['zoom'], 6, 10, 20, 100],
color: ['case',["==", ['get','band'],2100], '#aa0000',["==", ['get','band'],3500], '#00aa00', '#0000aa' ],
rotateWithView: false,
offset: ['array', 0, ['*', ['interpolate', ['exponential', 2.5], ['zoom'], 6, 3, 20, 48], -1] ],
opacity: 0.75,
rotation: ['-', ['*', ['get','azy'] , 0.01745329251 ], 3.1415926],
}
Note: the offset is smaller with 2 pixels that half the size. With half size, the triangles did not touch, had a few pixels gap. It looks like this:
Another solution is that I created a png with the desired symbol:
Note that the center of picture is the center of circle of which the sector was cut out, so when rotated, it will stay over the point of the rotation. The style is:
symbol: {
symbolType: 'image',
src: 'tools/testbench/olmap2/cell_symbol.png',
size: ['interpolate', ['exponential', 2.5], ['zoom'], 6, 10, 20, 100],
color: ['case',["==", ['get','band'],2100], '#aa0000',["==", ['get','band'],3500], '#00aa00', '#0000aa' ],
rotateWithView: false,
opacity: 0.75,
rotation: ['*', ['get','azy'] , 0.01745329251 ]
},
The result is:
This is somewhat slower, but I guess the 800x800px png is an overkill for this, so maybe downsizing it would solve the performance issue :) The pro side of this solution that I can create circle segments in different opening angles, so the antenna's (horizontal) beamwidth could be shown too. With the triangle symbolizer I cannot do this. (If later I could draw custom polygons in OL, that would be the perfect solution for this.)

Related

Mapping an image to a quadrilateral in p5.js without using WEBGL

I'm trying to map a custom image to a 4-sided quad with a non-rectangular shape in p5.js. I know this is possible(and quite easy) using a WEBGL canvas and the texture() command, but I'm trying not to use WEBGL in my code simply because I don't like the WEBGL coding environment; and it seems kind of overkill to swap to a 3D canvas just for this(I don't need any other 3D objects in my program).
I'm looking for an in-built solution, or a custom library with something of this matter in it. I've tried both to some degree and have turned up empty-handed; which is odd because this seems like a relatively simple thing to ask for.
I'm also kind of stupid and I don't understand HTML in general. I use p5.js because of this, but I'm not against any kind of help: all is appreciated.
I've tried using a mixture of shearX() and shearY() but those would only work for an orthographic view; I'm going for perspective.
I have looked into brute-forcing it by literally going through each pixel in the quad and calculating the pixel color it should have based on the image, but haven't had this work yet. It also seems hecka laggy; and I'm looking for this quad to render in real-time.
If you don't want to use WebGL (or p5.js) there are other js libraries that can apply perspective warp via canvas, such as perspective.js.
Here's their example:
// ctx (CanvasRenderingContext2D): The 2D context of a HTML5 canvas element.
// image (Image): The image to transform.
var p = new Perspective(ctx, image);
p.draw([
[30, 30], // Top-left [x, y]
[image.width - 50, 50], // Top-right [x, y]
[image.width - 70, image.height - 30], // bottom-right [x, y]
[10, image.height] // bottom-left [x, y]
]);
This may be bit overkill, but warpPerspective() in opencv.js also support a similar transform.
Here's their example:
let src = cv.imread('canvasInput');
let dst = new cv.Mat();
let dsize = new cv.Size(src.rows, src.cols);
// (data32F[0], data32F[1]) is the first point
// (data32F[2], data32F[3]) is the sescond point
// (data32F[4], data32F[5]) is the third point
// (data32F[6], data32F[7]) is the fourth point
let srcTri = cv.matFromArray(4, 1, cv.CV_32FC2, [56, 65, 368, 52, 28, 387, 389, 390]);
let dstTri = cv.matFromArray(4, 1, cv.CV_32FC2, [0, 0, 300, 0, 0, 300, 300, 300]);
let M = cv.getPerspectiveTransform(srcTri, dstTri);
// You can try more different parameters
cv.warpPerspective(src, dst, M, dsize, cv.INTER_LINEAR, cv.BORDER_CONSTANT, new cv.Scalar());
cv.imshow('canvasOutput', dst);
src.delete(); dst.delete(); M.delete(); srcTri.delete(); dstTri.delete();

ThreeJS world unit to pixel conversion

Is there a way compute the ratio between world unit and pixels in ThreeJS ? I need to determine how many units apart my objects need to be in order to be rendered 1 pixel apart on the screen.
The camera is looking at the (x,y) plane from a (0, 0, 10) coordinate, and objects are drawn in 2D on the (x,y) plane at z=0.
<Canvas gl={{ alpha: true, antialias: true }} camera={{ position: [0, 0, 10] }}>
I cannot seem to figure out what the maths are or if there is any function that does it already...
I'm thinking I might have to compare the size of the canvas in pixels and world units, but I dont know how to get that either. There's also this raycasting solution, but surely there has to be a way to just compute it, no ?

d3 force directed graphs have grouped items overlap each other

I have this plunker (https://next.plnkr.co/edit/17t5ujwC71IK3PCi) which shows d3 graph of nodes grouped together based on group ID. Graph appears fine but I need to make sure that the groups never overlap each other (as shown below where orange, blue and lightblue are different groups but they are appearing on top of each other).
Dragging them causes the graph to endlessly move (which is another issue) and doesn't always fix the overlapping issue. I saw another example (http://bl.ocks.org/GerHobbelt/3071239) which is a bit better but its made with d3.v2. It has quite some good space between each group which makes it easier to analyze.
I thought setting charge to a negative value will do the magic but setting it like .force('charge', d3.forceManyBody().strength(-30)) didn't help at all.
Problem:
Now, trying to make the groups distant apart by coding something like following from the d3.v2 example I mentioned above but having hard time cooking something similar for my d3.v4. Any good suggestions on how to dynamically keep all groups away from each other?
I ended up following https://bl.ocks.org/emeeks/302096884d5fbc1817062492605b50dd to use forceX and forceY for positioning same group nodes together - away from other groups. Problem with it is that group positions are hardcoded as following:
this.grpPositions = {
'1': {x: 100, y: 100},
'2': {x: 900, y: 200},
'3': {x: 700, y: 400},
'4': {x: 200, y: 400},
'5': {x: 500, y: 400},
'6': {x: 600, y: 500}
};
I will have to come up with some good algorithm to dynamically generate far apart group x, y co-ordinates based on total number of groups and available width and height of given SVG.
If you have a better way of doing it via d3, please feel free to post your answer and I will accept it.

Three.js colors rgb not correct

Working on a project in Three.js, and the RGB values I get back don't seem to correlate with the on screen graphics as they should.
I set a material like this:
var planeMaterial = new THREE.MeshBasicMaterial({ color: 0x00ff00, vertexColors: THREE.FaceColors });
Apply it to a plane geometry, and then later change it with this:
face.color.setHSL(0, 0, 0.0)
Then repeatedly later change it with
face.color.offsetHSL(0, 0, 0.1)
The colors do in fact go from black to green, but then will not continue on and tend towards white.
Looking at the RBG values, they then tell me that the color values are equal to:
ColorĀ {b: 1, g: 1, r: 1}
and using getHSL it says:
{h: 0, s: 0, l: 1}
Yet the plane is very clearly green, and not white.
I'm obviously missing something big about how colors work here, but I cant for the life of me make heads or tails of this. Can anyone see what I'm doing wrong? Thanks inadvance.

How to display the axis to the right?

I have 3 axes (velue-axis)
Can one axis be displayed on the left
Other two axes to display on the right?
http://demos.telerik.com/kendo-ui/line-charts/multiple-axes
(In this example, the axis is located on the right, but I do not know how to configure it)
Thanks.
Granted this isn't entirely clear when you first look at the demo. The important thing to look at is this section:
categoryAxis: {
categories: [],
axisCrossingValues:[]//This is the fella you are looking for.
}
I have tweaked the demo slightly to show you one of the axis in the middle of the chart. http://dojo.telerik.com/ASidu
The number is simply the position column on the chart that the axis should be rendered. By default if this in't set then all axis should be on the left hand side as normal. but if we start applying a number greater than 0 then the axis will shift. So in the example we have 3 value axis set up:
valueAxes: [{
name: "rain",
color: "#007eff",
min: 0,
max: 60
}, {
name: "wind",
color: "#73c100",
min: 0,
max: 60
}, {
name: "temp",
min: -30,
max: 30
}],
so if we look at them from crossing the y-axis (i.e. the bottom axis) we have 31 columns available to us 1- 31 so in my tweak I have applied this to the crossingAxis:
axisCrossingValues: [32, 15, 0]
This is effectively telling each of the value axes where they should be positioned:
so:
"rain" should be at position 32
"wind" should be at position 15
"temp" should be at position 0
So the order in which you add your value axes will determine which setting they take based on the order you include them.
Hopefully that helps clear things up for you. If you need any more info let me know and I will update accordingly

Resources