I try to arrange multiple square pictures on a canvas so that they form a circle which is completely covered with these elements like on this picture:
See original here (slide three)
How can I compute the x and y coordinates and the size of each element given n elements and a fix radius?
thanks in advance!
P.S.: probably I'll use pixi.js for this
My suggestion:
The question is related to the "Gauss circle problem", that has no simple solution.
So I would choose a too large radius, to be sure to cover at least n squares (such as the smallest integer such that π(r-1)² ≥ n). Then generate all (x, y) pairs within that radius (x²+y² ≤ r²), keeping the value of x²+y² for each.
Next, sort by increasing x²+y², and keep the n smallest. This will fill a regular circle, with extra pixels on the outer layer until the count is n.
Related
Situation:
The following components exist for this problem:
Two-dimensional, rectangular grid ("r" rows by "c" columns)
One or more shapes: here a shape is defined as a straight line that is one segment by "L" adjacent segments in length. Each segment is equivalent in size to one cell of the grid.
Objective:
Algebraically calculate the total number of unique ways (permutations) that all shapes may be arranged on the grid simultaneously.
Ultimately, I will be using this function in either R or JavaScript; however, this is primarily a math/algebra question. I am comfortable converting any solutions provided into the appropriate language, as long as I understand how the solution works. All thoughts/languages are welcome and appreciated.
Criteria:
All shapes must fit on the grid at once (and entirely).
Shapes may not over lap. Only one segment may occupy a grid cell at a time.
Shapes may be positioned vertically.
Shapes may be positioned horizontally.
Shapes may NOT be positioned diagonally.
Shapes must remain intact (i.e., a 2-segment shape may not be split into two, one-segment shapes)
Background:
If each shape has a single segment (i.e., occupies only one cell of the grid) then factorials may be used:
Let x = r * c (the number of cells in the grid)
Let n = the number of single-segment shapes to fit on the grid
P(x,n) = x! / (x-n)!
Therefore, the permutations for two, single-segment shapes on a grid of three rows and three columns may be calculated as:
P((3*3),2) = 9!/(9-2)! = 72
Relatively simple and elegant.
Calculating permutations for a single shape having a length of L >=1 (requiring L <= r and L <= c) the process is somewhat less elegant but still relatively simple:
P(r,c,L) = r*(c-(L-1)) + c*(r-(L-1))
[I realize this can likely be simplified algebraically but it is clearer for me to illustrate the process this way]
Therefore, the permutations for a single, two-segment shape on a grid of three rows and three columns may be calculated as:
P(3,3,2) = 3*(3-(2-1)) + 3*(3-(2-1)) = 12
The next step is to introduce additional shapes of varying lengths into the equation.
For example, how many permutations exist for positioning a two-segment shape and a three-segment shape simultaneously on a grid of four rows and four columns? This is where I am stuck and feel I may be searching for an algebraic solution that does not exist or that is not possible.
(Incidentally, for testing purposes, I physically tested the example above and found 251 possible unique positions)
Graphic illustration of the problem:
Question:
Can this problem be solved algebraically, or does the problem require iterative functions to actually find all possible positions before providing a count of the number of permutations?
If the problem is solvable algebraically, can anyone provide direction on how this would be accomplished, or recommend a publicly accessible resource that I could use to learn how to solve this problem.
Background:
I am working on a tile-based game in Javascript where a character freely moves around the map (no diagonal - Left/Right/Up/Down) and fills in tiles as he moves around the map. There are three tile types -- tiles you've filled (blue), your current path (red), and empty ones (black). There are also enemies (stars) that move around the map as well, but only in empty areas. The objective is to fill as much of the map as possible.
Map is sized as roughly 40x40 tiles. There is a 1 tile thick border around the entire outside of the map that is already "filled" (blue).
I have established that a flood-fill algorithm will work for filling up areas of tiles when needed. However, my problem is as follows:
PROBLEM STATEMENT:
I want to only fill a sectioned-off part of the map if there are no enemies in it.
My Question:
I could run flood-fill algorithm and stop it if it reaches a tile occupied by an enemy -- however, is this the most efficient approach (for a real time game)?
IF YES, how do I determine where to start the algorithm from in a systematic way since there are multiple areas to check and the character doesn't have to move in a perfectly straight line (can zig-zag up/down/right/left, but can't move diagonally).
Picture Example 1 (pics explain better):
Note: red areas turn blue (filled) once you reach another filled area. In example below, there are no enemies in the contained area, so the area is filled.
Picture Example 2:
In this second example, there is an enemy within the contained area (and on the outside area - not shown) so nothing but the line is filled.
Summary: What is the best approach for doing this type of filling? Is flood fill the best choice for determining whether to fill or not -- 40x40 makes for a pretty large calculation. If yes, how do I determine what tile do I start with?
Let me suggest a different way of looking at your problem.
Going by the description of your game, it seems like the user's main, perhaps only, "verb" (in game design terms) is to draw a line that divides the open area of the field into two sections. If either of these two sections is free of enemies, that section gets filled in; if neither section is free of enemies, the line remains but both sections remain open. There are no other conditions determining whether a section gets filled or not, right?
So the most efficient way to solve this problem, I would think, is simply to draw a continuous line, which may make corners but only moves in horizontal or vertical directions, from one of your enemies to every other enemy in turn. We'll call this line the "probe line". From here on, we're using the approach of Derek's suggested "Ray casting algorithm": We look at the number of times the "probe line" crosses the "border line", and if the number of crossings is ever odd, it means you have at least one enemy on each side of the line, and there's no filling.
Note, though, that there's a difference between the two lines coinciding and the two lines crossing. Picture a probe line that goes from the coordinates (0,10) to (39,10) , and a border line that goes down from (5,0) to (5,10) and then goes right to (13,10). If it goes down from there towards (13,39), the two lines are crossing; if instead it goes upwards toward (13,0), they're not.
After a lot of thought, I strongly suggest that you store the "border line", and construct the "probe line", in terms of line segments - rather than trying to determine from which cells are filled which line segments created them. That will make it much harder than it has to be.
Finally, one odd game design note to be aware of: unless you constrict the user's control so that he cannot bring the border line back to within one cell of itself, then a single border line drawn by a user might end up sectioning off the field into more than two sections - there could be sections created by the border line looping right back on itself. If you allow that, it could very drastically complicate the calculation of where to fill. Check the following diagram I made via Derek's fiddle (thank you, Derek!):
As you can see, one border line has actually created three sections: one on the upper side of the line, one below the line, and one formed by the line itself. I'm still thinking about how that would affect things algorithmically, for that to be possible.
EDIT: With a) time to think about the above creation-of-multiple-sections-by-loops, and b) the Simulation of Simplicity resource brought up by Derek, I think I can outline the simplest and most efficient algorithm that you're likely to get.
There's one subproblem to it which I'll leave to you, and that is determining what your new sections are after the player's actions have drawn a new line. I leave that to you because it's one that would have had to be solved before a solution to your original problem (how to tell if there are enemies within those sections) could have been called.
The solution, presented here as pseudocode, assumes you have the border of each section stored as line segments between coordinates.
Create a list of the sections.
Create a list of the enemies.
Continue as long as neither list is empty:
For each enemy in the enemy list:
Designate "Point A" as the coordinates of the enemy, PLUS 0.5 to both x and y.
For each section in the section list:
Designate "Point B" as the upper-left-most coordinate, PLUS 0.5 to both x and y.
Count how many of the section border segments cross a line between A and B.
If the answer is even:
remove this section from the section list
skip forward to the next enemy
If any sections remain in the list, they are free of enemies. Fill them in.
The addition of the 0.5 to the coordinates of the "probe line" are thanks to Derek's SoS resource; they eliminate the difficult case where the lines coincide rather than simply crossing or not crossing.
If you have the points of the border of your shape that lies on the same y as the enemy, then you can simply count the number of borders, starting from either left or right to the enemy. If it's odd then it's inside. If it's even then it's outside.
Since you are using a grid system this should be easy to implement (and very fast). This algorithm is called the Ray casting algorithm.
Here's a simple example I created: http://jsfiddle.net/DerekL/8QBz6/ (can't deal with degenerate cases)
function testInside(){
var passedBorder = 0,
passingBorder = false;
for(var x = 0; x <= enemy[0]; x++){
if(board[x][enemy[1]] === 1) passingBorder = true;
else if(board[x][enemy[1]] === 0 && passingBorder){
passingBorder = false;
passedBorder++;
}
}
return !!(passedBorder%2);
}
For example, you have this shape which you have determined:
removed
Guess what I found, (slightly modified)
//simple enough, it only needs the x,y of your testing point and the wall.
//no direction or anything else
function testInside3() {
var i, j, c = 0;
for (i = 0, j = wallList.length-1; i < wallList.length; j = i++) {
if ( ((wallList[i][1]>enemy[1]) ^ (wallList[j][1]>enemy[1])) &&
(enemy[0] < (wallList[j][0]-wallList[i][0]) * (enemy[1]-wallList[i][1]) / (wallList[j][1]-wallList[i][1]) + wallList[i][0]) )
c = !c;
}
return !!c;
}
http://jsfiddle.net/DerekL/NvLcK/
This is using the same ray casting algorithm I mentioned, but this time the "ray" is now mathematical using the following inequality for x and a condition for y:
(X2 - X1)(Py - Y1)
Px < ────────────────── + X1
Y2 - Y1
which is derived by combining these two:
Ray:
x(t) = Px + t, y(t) = Py, where t > 0 (the ray goes to the right)
Edge:
x(u) = (X2 - X1)u + X1, y(u) = (Y2 - Y1)u + Y1, where 0 <= u <= 1
And the condition for y:
(Y1 > Py) ⊕ (Y2 > Py)
which is equivalent to:
(Y1 ≥ Py > Y2) ∨ (Y2 ≥ Py > Y1)
and yadi yadi yada some other interesting technical stuff.
Seems like this is the default algorithm in many native libraries. The method used to dealing with degenerate cases is called Simulation of Simplicity, described in this paper (section 5.1).
Nevertheless, here's the result generated with the algorithm testing every coordinate:
If it's easy to determine where the borders of a region to possibly fill are, you can use the following approach:
Assign each edge a clockwise directionality. That is, construct a vector for each edge that starts on its corners and has a direction such that a clockwise path around the region is described by these vectors.
For each enemy:
Construct a vector starting from the enemy and ending on the closest edge. We'll call this an enemy_vector.
Calculate the cross product of the enemy_vector and the vector corresponding to the closest edge. The sign of the cross product will tell you whether the enemy is inside the region: if it's positive, the enemy is outside of it, and if it's negative it isn't!
EXAMPLE:
Suppose we have the following region and enemy to evaluate the inside-ness of.
We can encode the region as a series of vectors that give it a clockwise orientation, like so:
So how do we use that to determine the side of the region inhabited by the enemy? We draw a vector from it (which I've colored red) to the nearest edge (which I've colored green)...
...and take the cross product of the red vector and the green vector. Application of the right-hand rule tells us that (red) x (green) > 0, so the enemy must be outside the region!
I am implementing a map-like interface for a personal project, in Javascript with HTML5 canvas, and I am mostly looking for ideas on how I could properly tessellate all 2D polygon sides with equal-length rectangles per side. Before explaining further, here are two actual screenshots of the existing interface:
(source: mavrosxristoforos.com)
As you can see, there are "n" rectangles on each of the polygon sides, with length equal to "side's length" divided by "n", and width their length divided by 2. The number of rectangles is user-set.
The actual data I have is: the polygon corner coordinates and the number of rectangles.
The sides are always populated clockwise.
At the moment, the pseudocode for how they are drawn, looks like this:
RECT_LENGTH = polygon_side_length / count_of_rectangles;
i = first_corner_of_the_polygon_side;
for ( j = 0; j < count_of_rectangles; j++) {
move pen to i;
point1 = i + RECT_LENGTH * right_angle_on_polygon_side_slope;
line to point1;
point2 = point1 - RECT_LENGTH * polygon_side_slope;
line to point2;
i += RECT_LENGTH * polygon_side_slope;
line to i;
}
It is pretty obvious from the code, that it doesn't take into consideration anything other than the polygon side slope, which is the angle from the horizontal axis, measured in -π (pi) to +π, calculated from the two corner coordinates.
There are mainly three appearance problems in these screenshots:
In the upper screenshot, on the left, the big rectangle goes out of the polygon side.
In the upper screenshot, on the bottom right, the rectangles overlap (also on other corners, but that particular one looks completely unnatural).
In the lower screenshot, on the top corner, both sides' rectangles get out of the original polygon.
As a solution, I thought that I could search for a line segment intersection between the current line being drawn and the polygon sides, as well as the previous rectangle, but that doesn't feel right, and it would perform quite slow.
As already mentioned, any idea is welcome. I am not a native English speaker, so please feel free to correct me on my English.
Thank you for your time!
EDIT: I wouldn't mind it if the last rectangle became a trapezoid, just to completely cover the polygon side.
Since you're using rectangles you just can cover right-angled areas. So you have to leave some area of polygons uncovered. You have to reduce the actual length of edges like this:
In this solution you can reduce length of edges just form heads which meet an acute angle. With Alpha as the inner angle of corner, the reduction amount would be Rectangle.Width / Tan(Alpha). It keeps rectangles inside polygon but wont solve the overlap problem.
To prevent rectangles from overlapping you have to leave more area uncovered:
To do this you have to reduce the length of edge form both heads by Rectangle.Width / Tan(Alpha / 2) (Alpha may differ at each corner).
But all of these wont help since width of rectangle is unknown. In fact width of rectangle is calculated by length of edge itself, and we are using it to calculate the length of edge!!
So we have a mathematical problem here:
Known:
L1: actual length of edge
N: number of divisions
Alpha & Beta: half of inner angle of head corners
Unknown:
L2: reduced length of edge
W: width of rectangles
We can form two equations:
(1): L2 = 2 * N * W
(2): L2 = L1 - (W / Tan(Alpha) - (W / Tan(Beta)
By solving them we can find W:
W = L1 / (2 * N + Cot(Alpha) + Cot(Beta))
All these are true in convex polygons. If either head corners of edge are concave you can replace their inner angle with Pi / 2 to prevent reduction from those corners.
Please recheck everything! Considering your lovely UI, I suppose you can handle trigonometric calculations for finding start and end point of rectangles.
I'm currently trying to build a kind of pie chart / voronoi diagram hybrid (in canvas/javascript) .I don't know if it's even possible. I'm very new to this, and I haven't tried any approaches yet.
Assume I have a circle, and a set of numbers 2, 3, 5, 7, 11.
I want to subdivide the circle into sections equivalent to the numbers (much like a pie chart) but forming a lattice / honeycomb like shape.
Is this even possible? Is it ridiculously difficult, especially for someone who's only done some basic pie chart rendering?
This is my view on this after a quick look.
A general solution, assuming there are to be n polygons with k vertices/edges, will depend on the solution to n equations, where each equation has no more than 2nk, (but exactly 2k non-zero) variables. The variables in each polygon's equation are the same x_1, x_2, x_3... x_nk and y_1, y_2, y_3... y_nk variables. Exactly four of x_1, x_2, x_3... x_nk have non-zero coefficients and exactly four of y_1, y_2, y_3... y_nk have non-zero coefficients for each polygon's equation. x_i and y_i are bounded differently depending on the parent shape.. For the sake of simplicity, we'll assume the shape is a circle. The boundary condition is: (x_i)^2 + (y_i)^2 <= r^2
Note: I say no more than 2nk, because I am unsure of the lowerbound, but know that it can not be more than 2nk. This is a result of polygons, as a requirement, sharing vertices.
The equations are the collection of definite, but variable-bounded, integrals representing the area of each polygon, with the area equal for the ith polygon:
A_i = pi*r^2/S_i
where r is the radius of the parent circle and S_i is the number assigned to the polygon, as in your diagram.
The four separate pairs of (x_j,y_j), both with non-zero coefficients in a polygon's equation will yield the vertices for the polygon.
This may prove to be considerably difficult.
Is the boundary fixed from the beginning, or can you deform it a bit?
If I had to solve this, I would sort the areas from large to small. Then, starting with the largest area, I would first generate a random convex polygon (vertices along a circle) with the required size. The next area would share an edge with the first area, but would be otherwise also random and convex. Each polygon after that would choose an existing edge from already-present polygons, and would also share any 'convex' edges that start from there (where 'convex edge' is one that, if used for the new polygon, would result in the new polygon still being convex).
By evaluating different prospective polygon positions for 'total boundary approaches desired boundary', you can probably generate a cheap approximation to your initial goal. This is quite similar to what word-clouds do: place things incrementally from largest to smallest while trying to fill in a more-or-less enclosed space.
Given a set of voronio centres (i.e. a list of the coordinates of the centre for each one), we can calculate the area closest to each centre:
area[i] = areaClosestTo(i,positions)
Assume these are a bit wrong, because we haven't got the centres in the right place. So we can calculate the error in our current set by comparing the areas to the ideal areas:
var areaIndexSq = 0;
var desiredAreasMagSq = 0;
for(var i = 0; i < areas.length; ++i) {
var contrib = (areas[i] - desiredAreas[i]);
areaIndexSq += contrib*contrib;
desiredAreasMagSq += desiredAreas[i]*desiredAreas[i];
}
var areaIndex = Math.sqrt(areaIndexSq/desiredAreasMagSq);
This is the vector norm of the difference vector between the areas and the desiredAreas. Think of it like a measure of how good a least squares fit line is.
We also want some kind of honeycomb pattern, so we can call that honeycombness(positions), and get an overall measure of the quality of the thing (this is just a starter, the weighting or form of this can be whatever floats your boat):
var overallMeasure = areaIndex + honeycombnessIndex;
Then we have a mechanism to know how bad a guess is, and we can combine this with a mechanism for modifying the positions; the simplest is just to add a random amount to the x and y coords of each centre. Alternatively you can try moving each point towards neighbour areas which have an area too high, and away from those with an area too low.
This is not a straight solve, but it requires minimal maths apart from calculating the area closest to each point, and it's approachable. The difficult part may be recognising local minima and dealing with them.
Incidentally, it should be fairly easy to get the start points for the process; the centroids of the pie slices shouldn't be too far from the truth.
A definite plus is that you could use the intermediate calculations to animate a transition from pie to voronoi.
I'm trying to develop a component that should look somewhat like this
I'm using RaphaelJS to draw this and that works just fine. I have an array of angles which I use to calculate the paths of the individual segments. I store these paths in a simple array so the inner circle is at segments[0] and so on spiralling outwards.
My problem is that I need each segment to be aware of it's adjacent segments both clockwise, anti-clockwise, inwards and outwards and I'm having difficulty figuring out how to calculate the position of these is my segment array. So for instance, in the case of the above diagram, the red segment at level 2 (where 0 is the inner-most circle) has red, bright green, kaki, light purple and dark purple neighbours.
Perhaps I need a different coordinate system. If each level had the same number and angle distribution of segments it would be a simple case of using modulus's like indexing a circular array but this isn't the case.
Any help would be much appreciated.
Many Thanks,
Anthony
I'd change how you're storing the segments from one sorted array into one sorted array per level.
Finding the neighbours of a given segment (S) is then fairly easy: the left and right neighbours are the previous and next elements of that level's array.
The neighbours in the adjacent levels are found with a couple of binary searches in those arrays: find the segments that coincide with the start and end angles of S, the neighbours are the sequence of segments between those two.