Drawn line - picking up random point on it - javascript

I am using JavaScript to draw on HTML Canvas.
I have a polygon represented as array of [x,y] coordinates. In my situation (game focused on expanding player's area) I want periodically expand the area represented by the polygon. I have two random possibilities - expand one of existing vertexes, or split one of the line.
My method works kinda good, but I have problem with splitting the lines. I can pick random line (or to be more precise two random neighboring polygons) and I can insert new polygon into my array of polygons. That works fine.
To find where the new polygon shall be, I tried to use midpoint formula. In my code it goes like this:
var x_mid = Math.round((globalMap[v1][0] + globalMap[v2][0]) / 2);
var y_mid = Math.round((globalMap[v1][1] + globalMap[v2][1]) / 2);
But I found it is not always picking up the correct spot on the line. Sometimes it ends up inside my polygon, which is a problem, because for expansion, my script is looking for free (not colored) pixels around and it finds none here.
I blame the round() function, but can't figure out how to make sure, I end up on the line that is actually drawn on canvas?
It doesn't have to be exact middle of the line, if someone knows other technique, it just needs to be somewhere on the edge, so it can expand later without flaws. Thanks a lot!

Related

Find all free rectangular regions in a 2-D box with random positioned obstacles inside

I have a pre-defined-size rectangular area with some other rectangles inside, which represents filled regions, or, let say, obstacles.
All the rectangles are axis-aligned.
Origin of the axis (i.e. 0,0) is top-left.
The X and Y coordinates of all the rectangles, as well as the horizontal and vertical size is known.
Information about the rectangles inside the main area is contained in an already-sorted array, where i[0],i[1] are the X,Y coordinates of the upper-left corner and i[2],i[3] are respectively the x and y size:
[
[10,1,14,7],
[34,1,14,15],
[16,22,27,44]
]
How can i get all the rectangles covering the free remaining space, like in the image below?
(credits: Jukka Jylänki, A Thousand Ways to Pack the Bin - A Practical Approach to Two-Dimensional Rectangle Bin Packing http://clb.demon.fi/)
I don't need an algorithm for optimal bin-packing, as the rectangles are already placed, nor to find the biggest rectangle, but i'm aware that these can be related arguments.
I have also read some papers about the line-sweep algorithm, but i'm not able to get a working implementation, and so i cannot imagine if this would be the right solution for my problem.
My first attempt (clearly wrong) was to gather all the cuts generated by all the sides (inverse intersection):
[
[24,8,37,8],
[1,16,60,6],
[1,22,15,44],
[43,22,18,44],
[1,66,60,5],
[1,1,9,70],
[10,16,6,55],
[24,1,10,21],
[34,8,9,14],
[43,8,5,63],
[48,1,13,70]
]
...but this would require an additional step to to join adjacent rectangles and then filter out those inside a bigger one. See for example, the red-marked rectangles in this picture:
Could be this a way to go, though not optimized?

move rotated ol.style.text relative to a given point in openlayers 3

I will try to explain what I'm trying to accomplish.
I have a point feature to which I set an array of 2 styles: 1 style represents a rotated image at the given point, the second one should be a rotated text at a fixed distance of the given point.
To clarify things I've created an image. I want to achieve the situation on the right. (the x,y,z lines and labels are for explanation purposes). I want to move the text over a fixed distance z. The rotation angle is also variable.
So what I did was give a rotation to the ol.style.text object and then give the text an offset for Y but then the text gets pulled straight below the point.
What I am looking for is a method to offset the text for a given distance, taking the rotation in account, without having to manually set the ofssetX and offsetY.
One solution here is indeed to use geometry.. calculate x and y offset based on the angles and the given z , using the sin formulas and the Pythagorean theorem, but I would like to avoid those calculations and find a more simple resolution.
I am using the latest version of openlayers3, currently v3.16.0
Thanks in advance.

d3 arc diagram - add top semi circles

http://jsfiddle.net/pRkpL/ and http://fiddle.jshell.net/pRkpL/show/
I am making an arc diagram which is based heavily on this demo: http://bl.ocks.org/sjengle/5431779. It's taken me a while to get to this stage, and the graph now adapts to the data in all the ways I need it to.
However, I have 2 questions:
1) I need to create 2 arc diagrams - one above the black rectangles (named buckets in the code) and one below. As a temporary fix, I have used css3 3D transforms to flip one of the arc diagrams over on the x-axis, but the browser support is flaky at best. It does work, only in Chrome, and sometimes you have to refresh, open dev tools, or resize the fiddle frame for it to kick in. I'd like to do it properly with d3.
I think the code which creates the red arcs (the lower half of a circle) is this:
var radians = d3.scale.linear()
.range([Math.PI / 2, 3 * Math.PI / 2]);
I found if I remove the last / 2 it displays a full circle, however I can't get it to display only the top half in my drawTop function.
2) I currently duplicate 2 large functions for the 2 arc diagrams, drawTop and drawBtm. The only differences between the two are the data arrays (good_jumps and bad_jumps), the container id, and the radians logic above, if that can get solved. Is there a way I can combine these into one so I'm not duplicating the logic?
I'm fairly new to JS so please let me know if there are any obvious blunders in the code :) Also, there's no possibility to alter the json as it comes from an external api.
To make the arcs appear on top of the boxes, you just need to change the output range of your radians scale to cover the top half:
radians.range([-Math.PI / 2, Math.PI / 2]);
Regarding the second question, one way of doing this is to add another attribute to your data that allows to distinguish between the two types of arcs, e.g. .good. Once you've done that, you can switch on the value of that attribute to decide the class of the added path and the range of radians, which are the only differences between the arcs.
Complete jsfiddle here.

Dividing a rectangle into four clickable (or hover-able) triangles

Before reading on, my issue is to know what are the optimal methods to find an objects height/width/position as there seems to be some conflict about this.
After that I'll need help with how to use the previously obtained data to do number 4 in the following list. And after that I'll need help with number 5. I was hoping to do this gradually so please bear with me.
I found code for how to divide a square into two equal triangular clickable areas (Two triangular clickable area within a square). I didn't really understand much of what the code was doing to be honest. My question was about subdividing the rectangle that represents the visible screen area into four clickable areas, imagine its diagonals are drawn.
I did find this very useful (pseudo)-pseudocode :
Create a div and style it to be a square. Use a background image to illustrate the triangles
Create a variable, square, in javascript to hold the square element
Get the position, height, and width of square in your js
Do some math to determine the coordinates of each triangle's vertices
Write a function, getQuadrant(), that determines which triangle any given point within the square is in
Add an event listener to click events on the square. The event listener should call the getQuadrant function
Use a switch/case to execute whatever code you need to call conditional upon which quadrant the click lands in
I'm not going to ask for the full code right away, I'd like to learn in the process. Could someone please help in just pointing me towards which methods to use for numbers 3 and 4? And I'll most probably need help with number 5 as well.
Thanks a for the help! =)
K
If you translate everything so that the center of the square is the origin, then the borders of the triangle are defined by the lines x == y and x == -y. You can base your quadrant classification on that relationship:
If x > Math.abs(y), then you are in the right triangle
If y > Math.abs(x), then you are in the top triangle
If -x > Math.abs(y), then you are in the left triangle
If -y > Math.abs(x), then you are in the bottom triangle
Ties can be resolved arbitrarily between the two (or four, if x == y == 0) closest triangles.

Isometric Screen to Map

I'm trying to figure out how I can get the correct "active" tile under the mouse when I have "ramp" and +1 height tiles (see picture below).
When my world is flat, everything works no problem. Once I add a tile with a height of say +1, along with a ramp going back to +0, my screen -> map routine is still looking as if everything is "flat".
In the picture above, the green "ramp" is the real tile I want to render and calculate mouse -> map, however the blue tile you see "below" it is the area which gets calculated. So if you move your mouse into any of the dark green areas, it thinks you're on another tile.
Here is my map render (very simple)
canvas.width = canvas.width; // cheap clear in firefox 3.6, does not work in other browsers
for(i=0;i<map_y;i++){
for(j=0;j<map_x;j++){
var xpos = (i-j)*tile_h + current_x;
var ypos = (i+j)*tile_h/2+ current_y;
context.beginPath();
context.moveTo(xpos, ypos+(tile_h/2));
context.lineTo(xpos+(tile_w/2), ypos);
context.lineTo(xpos+(tile_w), ypos+(tile_h/2));
context.lineTo(xpos+(tile_w/2), ypos+(tile_h));
context.fill();
}
}
And here is my mouse -> map routine:
ymouse=( (2*(ev.pageY-canvas.offsetTop-current_y)-ev.pageX+canvas.offsetLeft+current_x)/2 );
xmouse=( ev.pageX+ymouse-current_x-(tile_w/2)-canvas.offsetLeft );
ymouse=Math.round(ymouse/tile_h);
xmouse=Math.round(xmouse/(tile_w/2));
current_tile=[xmouse,ymouse];
I have a feeling I'll have to start over and implement a world based map system rather than a simple screen -> map routine.
Thanks.
Your assumption is correct. In order to "pick" against world geometry, your routine needs to be aware of the world (and not just the base-level tile configuration). That is, without any concept of the height of the tiles near the one that is currently picked (by your current algorithm), there's no way to determine whether a neighboring tile (or one even further away, depending on the permitted height) should be intercepted by picking ray.
You've got the final possible point of your picking ray, already. What remains is to define the remainder of the ray, in world-space, and to check that ray for intersections with world geometry.
If, like the picture, your view angle is always 45 degrees and always from the same direction, your mouse -> map routine could use an algorithm something like:
calculate i,j of tile as you're doing currently (your final value of xmouse, ymouse)
look up height and angle of tile at i,j
given the height and angle, does this tile intersect the picking ray? If so, set lasti, lastj = i, j
increment/decrement i,j one step diagonally toward viewer
have we fallen off the edge of the map? If so, return lasti, lastj. Otherwise go back to 2.
Depending on the maximum height of a tile, you might have to check only 2 tiles, rather than going all the way to the edge of the map.
3 is the tricky part, and depends on your world geometry. Draw some triangles and you should be able to figure it out. Or you might try looking at the function intersect_quadrilateral_ray() here.

Categories

Resources