I am working on a simple 2D soccer game, while passing the ball between my players I would like to check if any of the enemy players can intercept the ball, what I would like to do is calculate a list of coordinates between my players a corridor so to speak and then check if any enemy players are in this region,
--------------------------
S S
--------------------------
It is easy to calculate the area between Ss when they lie like this, but how do I calculate the region when they are not aligned,
/S /
/ /
/ /
/ /
/ /
/ /
/ S/
EDIT: When I mean area, I want the list of coordinates in that region so that I can check those coordinates against players coordinates, not the magnitude of the area.
(image) http://img441.imageshack.us/img441/9051/soccer.png
Show enemy is between red lines: Calculate the distance of the enemy to the line formed by the two players (dotted line). If it is <= w/2 (w is the width of your "region"), then either the enemy is within the region, or behind one of the players.
Show enemy is between orange lines: To check that he is not behind one of the players, just check that he is between the two lines which pass through one of the players and are normal (perpendicular) to the first line (the dotted line passing through both players).
This will tell you if the enemy is within the yellow region:
Why don't you rotate your coordinate system, so that both players will be aligned?
Assuming you have a fixed number of players (22 for examples) you multiply each of their (x,y) coordinate in the rotation+translation matrix that makes S1 (or S2, doesn't really matters) aligned with its companion.
And you can calculate the rotation matrix from this simple formula:
http://en.wikipedia.org/wiki/Rotation_matrix#Rotation_matrix_given_an_axis_and_an_angle
Further explanation and a good example:
http://www.quantunet.com/flash8/knowledgebase/actionscript/advanced/matrix/matrix_rotation.html
If it only needs to be approximate, and you need to calculate it quickly, then estimate the "diameter" of your object (even if it's square), and multiply by the distance between their centers (minus 1 radius at each end for a total of 1 diameter). This'll be blazing fast and pretty close.
Update: misread the question, I thought you literally wanted "the area".
You can still approximate it as above, but determine the side points as the points on the imaginary circles, 90 degrees off the line that connects the two. Again, it's approximate, but it keeps you from having to calculate "closest side of the object" and "closest points to a line".
Update 2:
Actually, even better: sort the points of S1 in order of how far they are from the center of S2. Pick the 2nd and 3rd closest. Sort the points of S2 in order of how far they are from the center of S1. Pick the 2nd and 3rd closest. Those are the 4 vertices. The "1st" closest is the one directly pointing at the other object, so the 2nd and 3rd are the "side" ones, in terms of facing the other object.
Related
I've got a 3D solid, represented as the union of a set of polyhedral convex hulls. (Or a single convex, if that makes things easier.) I'd like to approximate that solid as the union of a set of spheres, in a way which minimizes both the number of spheres in the set and the error in the approximation. (The latter objective is deliberately vague: any reasonable error metric will do. Likewise, the way in which the objectives are combined is up in the air; either the number of spheres or the error metric could be constrained, or some function of the two could be minimized. I don't want to specify myself into a corner.)
The approximation does not need to entirely contain or be entirely contained by the original set. Each sphere may have an arbitrary radius.
This feels like the sort of problem that's NP-complete, and in any case unlikely to be practical using exact methods, so I'm assuming the solution lies in the realm of stochastic optimization. It feels like some variant of k-means might fit (assigning uncovered locations to their closest spheres, and refining the spheres to cover some of them), but I'm not sure how to handle multiply-covered locations, or how to find the local, not-necessarily-covering-everything optimum even for a single sphere. Also, for iterative methods efficiency is important, and doing 3D boolean operations is not going to be efficient.
The problem is not simple, but has been studied previously. The central concept
is the medial axis, which can be
viewed as a representation of an object by an infinite union of balls.
A key paper addressing your question is:
"The power crust, unions of balls, and the medial axis transform."
Nina Amenta, Sunghee Choi, Ravi Krishna Kolluri. Computational Geometry.
Volume 19, Issues 2–3, July 2001, Pages 127–153. (Journal link.)
(Images source: From Point Clouds to Power Crusts.)
A second paper is
Cazals, Frédéric, et al. "Greedy Geometric Algorithms for Collection of Balls, with Applications to Geometric Approximation and Molecular Coarse‐Graining." Computer Graphics Forum. Vol. 33. No. 6. 2014. (PDF download.)
whose 1st sentence is "Choosing balls which best approximate a 3D object is a non-trivial problem."!
Their primary application is to molecular models, which might be far
from your interests.
Hm, my best idea so far involves support vector machines. Turn your object into a whole bunch of (probably evenly spaced) points within and on the surface of the object. Train an SVDD model using a linear kernel (see libsvm for an SVDD implementation). The decision function of the model then represents an implicit surface defined by the support vectors of the model (and rho). Turning down the cost will get you more support vectors, turning it up gets you fewer.
Unfortunately, the nature of SVMs is such that the area covered by nearby support vectors will, uh, 'blob' together, sort of like this:
(sorry, my intuition for SVMs is entirely geometric/visual.)
Now, you don't have nice crisp spheres, but (massive hand waving!) hopefully the algorithm chose a useful distribution of centers for spheres.
Finally, you can concoct a function that computes error as a function of radii for spheres centers on all those points. Then just feed that into a nonlinear optimizer and tell it to minimize. Bam.
If you're willing to throw more CPU power at it, you could run another layer of error minimization over top of that one, which reruns the entire above process for different support vector costs, attempting to minimize some combination of error and cost. (Perhaps error/cost.)
This is what I came up with. This approach is more of an iterative 3D boolean operation so it might not be what you're looking for. The surface seems more difficult so I concentrated on that.
Overview
Basically add spheres inside the shape in positions that maximize the coverage of the surface. We convert the sphere into a 3D array of signed byte values. These values are points and will be gobbled up with spheres. We add one spheres at a time inside the object and then grow/shrink it in different directions to "eat" as many points as possible. The goal is to rack up as many points as possible per sphere. Points are earned by summing the points in the area of the sphere. With the addition of each sphere we count then count that area as used and set the Array values to 0.
(A) (B) ZZZZZZ (C) ZZZZZZ (D) ZZZZZZ (E) ZZZZZZ (F) ZZZZZZ
/\ ZX33XZ ZX33XZ ZX33XZ ZX33XZ ZX33XZ
/ \ ZX3223XZ ZX3223XZ ZX##23XZ ZX ##XZ ZX XZ
/ \ ZX321123XZ ZX321123XZ ZX####23XZ ZX ####XZ ZX XZ
| | ZX32111123XZ ZX32111123XZ ZX######23XZ ZX ######XZ ZX XZ
| | ZX32111133XZ ZX32111133XZ ZX######23XZ ZX ######XZ ZX XZ
| | ZX32222223XZ ZX##222223XZ ZX3####223XZ ZX3 ####3XZ ZX3 ##XZ
|------| ZX33333333XZ ZX##333333XZ ZX33##3333XZ ZX33 ##33XZ ZX33 ##XZ
X= -1 ZXXXXXXXXXXZ ZXXXXXXXXXXZ ZXXXXXXXXXXZ ZXXXXXXXXXXZ ZXXXXXXXXXXZ
Y= -2 ZZZZZZZZZZZZ ZZZZZZZZZZZZ ZZZZZZZZZZZZ ZZZZZZZZZZZZ ZZZZZZZZZZZZ
(A) The shape that we want to fill. (2D used here but 3D would be similar)
(B) Convert the shape in a 3D grid of points. Surface gets largest number and as you work to the center the numbers settle on low positive numbers(like 1); Outside the shape gets negative numbers; deep interior gets 1
(C) Add a small sphere. (we will grow it)
(D) Expand the sphere until we gobble up the maximum number of points
(E) Add the Next sphere and grow it.
(F) Add another sphere. This one is small.
Process
5) first break down the shape into a 3D block resolution.
10) Then give the most "points" to the blocks around the surface. High points with the block that actually touches the surface and lower points as you move inward or outward. As you go outward the points should quickly become negative as this will prevent protruding spheres. As you move inward from the surface the points should settle at 1 so that the central area would be all ones. These points can be setup in different ways to produce different results.
15) Find a location on the inside edge of the shape that is outside a sphere. While being near the edge is not required it does minimize the search area. If a location cannot be found goto 80. If a location cannot be found that is near
20) Draw a sphere with a zero radius inside the shape that is not covered
25) Move the sphere up/down until the points are maximized (simulated annealing)
26) Move the sphere in/out until the points are maximized
27) Move the sphere left/right until the points are maximized
28) Move the Top of the sphere up/down until the points are maximized (simulated annealing/hill climbing)
29) Move the Bottom the sphere up/down until the points are maximized
30) Move the Left side of the sphere in/out until the points are maximized
31) Move the Right side of the sphere in/out until the points are maximized
32) Move the Front of the sphere in/out until the points are maximized
50) If any changes in 25-32 then repeat (goto 25)
70) Subtract out the points from the last added sphere. Set all values to zero for internal values(positive numbers) and do not adjust external values(negative numbers). Goto 15.
80) (optional) Fill in an internal gaps. Basically visit each element to make sure it is less then or equal to 0. If positive then goto 20 with that element. Else, if none found then goto 85. Note:all outside values should be negative and all internal values that are in a sphere should be 0.
85) Finished
Notes
Since there would a grid of values, a 1000x1000x1000 workspace would consume up 1GB.
Not an exact solution
Could take lots of compute for higher resolutions.
For efficiency, smaller spheres can have their pixel ranges pre-recorded so that the sphere does not need to be calculated for each iteration.
A lower resolution(i.e. 500x500x500) version could be completed first and then the location and size of the spheres could be applied to a larger 1000x1000x1000. Also for very large shapes sub-sections could be solved.
A good start would be to develop an algorithm to:
1) Find the largest radius of an inscribed sphere.
2) Then consider the subtract volume
3) Approximate the subtract volume by a polyhedral.
4) Subdivide that polyhedral into smaller (finer) polyhedrals.
5) Redo step 1.
There might be some variations, but it seems to answer your question. As you can see, the error function decreases as the number of spheres increases, so you can't minimize both: that is a trade-off. But you can fix one and try to optimize another, e.g. fix the error function to be an acceptable tolerance, and minimize the number of spheres to do it, or vice versa.
Please look at this picture first:
As you can see, blue and red both have a line showing the frontline bases.
Let's assume two players start playing against eachother.
One placing a base at the far left, the other at the far right.
The players continue by expanding and gaining territory.
After a while, the two sides will meet and battle will start.
Question is, in a randomly ordered list of base positions how would one find the two lines that are drawn in the picture?
You could get the distance between enemy bases, where the distance is shorter is the frontline.
Example:
0 1 2 3 4 5 6
0 aa A B bbb
1 aA B bb
2 A B b
3 aA B b
4 aaaA Bb
5 aaaA B
6 aaaA B
If you substract the X positions of the enemy bases in the same row, the ones with the less distance between them are the front lines, B.x - A.x will give you a smaller number that b.x - a.x. Then you can check which ones were the ones that gave you the smaller distance for each row.
Unless I'm getting your question wrong.
area
many games do not draw territory border by polylines
instead they draw a disc with constant radius (or dependent on base strength) at every base position
if the radius is set big enough then these discs/circles will overlap
and create seamless area of single color representing controlled territory
it is easy but inaccurate
perimeter polyline
first cluster all bases and create lists of bases close together
this can be done by grouping bases with distance <= treshold
process each group
find the outer most bases of group
something like perimeter points
this may help with it
also it contains inverse problem of yours which can solve the whole thing more here
now find the perimeter closed loop of area
the algorithm for that is also in the link above
when done then use this list of points as BEZIER cubics poly-curve control points
if borderline too close to the bases then enlarge the points
first compute avg point ap of group
then any point p is computed p=((p-ap)*scale)+ap
it is not exact but for your purposes it is enough
if you want something better then
p=p-ap
l=|p|
p=ap+(p*(l+dl)/l)
where dl is the step at which your border is enlarged
and if you want the accurate thing then you have to compute polygon enlargement
which is not easy task
handle edge cases
for singular base groups draw circle around
this approach has problem in close proximity of bases
one solution is not to count bases too close to any enemy base
per pixel borders
you can process the map image by pixels
something like this: (beware this is not tested)
per each pixel
compute the min distance to any player bases
remember two closest distances of different players
distance0 is closest
distance1 is second closest (but base owns another player)
select territory ownership
the player which has closest base own this
if the distance0 > treshold then this area is uncontrolled
in that case stop processing this pixel
if ((distance0 >= d-w)&&(distance0 <= d+w)&&(distance1>d+w+s)) then set pixel color to border polyline color
d is border line distance from base
w is half-size of borderline thickness
s is min distance between close front lines
edge case
previous step ignore border points that are closer to bases (close enemy bases)
to add them just add
if ((distance0<d)&&(|distance0-distance1|<=s+w)&&(|distance0-distance1|>=s-w)) then set pixel color to player ownership
also this will fail if any two opposing bases are closer then s-w
[Notes]
I think the best way is the per pixel
it is most close to the solution you want
the render can be a bit slower but you need to change it only if any base is conquered
I have a question.
I have N objects and N x N matrix M. Each entry M(i, j) contains (a kind of) relative gravitational force indicating how strongly i pulls j toward it (or inversely pull it away from it).
I want to place these N objects on a two-dimensional R x R plane by assigning a coordinate to each object.
Is there an algorithm/method that does this? There must be some commonly methods used in astrophysics, physics, chemistry, etc.
Thank you for your help.
You are interested in assigning co-ordinates (xi,yi,zi) and mass (mi) to each object such that gravitational force is consistent, right?
Consider 8 points at a time. You have a total of 32 unknowns and 28 equations. You can assume that first point is at origin and second point on x axis. That means, you will have 28 unknown and 28 equations.
So, first device and algorithm to solve for 8 points at a time. Then incrementally add one point at each iteration.
===Walkthrough===
Consider you are given n points in D dimensions. You only have distances between the points, but not the co-ordinates. Goal is to find co-ordinates for each point.
If D=1, you need to consider only two (+1) points at a time. Place first point at origin. Place second point on the positive side of origin. You can place third point in relation to origin, but place it right or left of it depending on the distance to first point and so on...
If D=2, place point 1 at origin, point to on positive side on x axis, third point on positive side of y axis depending on distance. From fourth point onward, you can use any two placed points to place the next and use any other point to refine the options (there will be two options).
Similar with D=3. Place first three points on xy plane (z=0) for all three. Next, place 4th point ofn postive part of z axist. And so on.
Coming back to gravity:
Your problem is complicated because you cannot exactly place mass at the origin. So you would need more than 5 points to place them. As I have shown above, you need at most 8 points though.
In case your mass are all equal, you can calculate distance (~inverse of gravity) and apply the case when D=3.
The problem is, given that we know the n*n distances between n objects, how to obtain their positions?
1. Put the first one, say a, at (0,0)
2. Put the second one b at ( |b-a|, 0 )
3. For the third one c, it is at the one of the two intersections of the two circles:
|p-a|=|c-a| and |p-b|=|c-b|.
Solve this system of quadratic equations using the well-known formula, choose
either of the solutions as the position of c.
4. For any other points p, do the same thing as we're done for c, but choose one of the
two solutions that is consistent with the distance |p-c|. And check the distance
between p and all previous points. If the check fails, return with failure.
my question might be a little strange. I've "developed" an algorithm and don't know if there's a similar algorithm already out there.
The situation: I've got a track defined by track points (2D). The track points represent turns for instance. Between the track points there are only straight lines. Now I'm given a set of coordinates in this 2D space. I calculate the distance from the first track point to the new coordinates and the distance for the interval for the first two track points. If the distance to the measured coordinates is shorter than the distance from the first to the second track point, I'm assuming that this point lies in between this interval. I then do a linear interpolation on that. If it's bigger, I'll check with the next interval.
So it's basically taking interval distances and trying to fit them in there. I'm trying to track an object moving approximately along this track.
Does this sound familiar to somebody? Can somebody come up with a suggestion for a similiar existing algorithm?
EDIT: From what I've stated so far, I want to clarify that a position is not multiply associated to track points. Consider the fine ASCII drawing Jonathan made:
The X position is found to be within Segment 1 and 2 (S12). Now the next position is Y, which is not to be considered close enough to be on S12. I'll move on to S23, and check if it's in.
If it's in, I won't be checking S12 for any other value, because I found one in the next segment already. The algorithm "doesn't look back".
But if it doesn't find the right segment from there on, because it happenend to be to far away from the first segment, but still further away from any other segment anyhow, I will drop the value and the next position will be looked for back in S12, again.
The loop still remains a problem. Consider I get Y for S23 and then skip two or three positions (as they are too far off), I might be losing track. I could determine one position in S34 where it would be already in S56.
Maybe I can come up with some average speed to vage tell in what segment it should be.
It seems the bigger the segments are, the bigger the chance to make a right decision.
What concerns me about the algorithm you've described is that it is 'greedy' and could choose the 'wrong' track segment (or, at least, a track segment that is not the closest to the point).
Time to push ASCII art to the limits. Consider the following path (numbers represent the sequence in the list of track points), and the coordinate X (and, later, Y).
1-------------2
|
| Y
X |
5-----+-----6
| |
| |
4-----3
How are we supposed to interpret your description?
[C]alculate the distance from the first track point to the new coordinates and the distance for the interval for the first two track points. If the distance to the measured coordinates is shorter than the distance from the first to the second track point, [assume] that this point lies in between this interval; [...] [i]f it's bigger, [...] check with the next interval.
I think the first sentence means:
Calculate the distance from TP1 (track point 1) to TP2 - call it D12.
Calculate the distance from TP1 to X (call it D1X) and from TP2 to X (call it D2X).
The tricky part is the interpretation of the conditional sentence.
My impression is that if either D1X or D2X is less than D12, then X will be assumed to be on (or closest too) the track segment TP1 to TP2 (call it segment S12).
Looking at the position of X in the diagram, it is moderately clear that both D1X and D2X are smaller than D12, so my interpretation of your algorithm would interpret X as being associated with S12, yet X is clearly closer to S23 or S56 than it is to S12 (but those are discarded without even being considered).
Have I misunderstood something about your algorithm?
Thinking about it a bit: what I've interpreted your algorithm to mean is that if the point X lies within either the circle of radius D12 centred at TP1 or the circle of radius D12 centred at TP2, then you associate X with S12. However, if we also consider point Y, the algorithm I suggest you are using would also associate it with S12.
If the algorithm is refined to say MAX(D1Y, D2Y) < D12, then it does not consider Y as being related to S12. However, X is probably still considered to be related to S12 rather than S23 or S56.
The first part of this algorithm reminds me of moving through a discretised space. An example of representing such a space is the Z-order space-filling curve. I've used this technique to represent a quadtree, the data structure for an adaptive mesh refinement code I once worked on, and used an algorithm very like the one you describe to traverse the grid and determine distances between particles.
The similarity may not be immediately obvious. Since you are only concerned about interval locations, you are effectively treating all points on the interval as equivalent in this step. This is the same as choosing a space which only has discretised points - you're effectively 'snapping' your points to a grid.
I've asked some questions here and seen this geometric shape mentioned a few times among other geodesic shapes, but I'm curious how exactly would I generate one about a point xyz?
There's a tutorial here.
The essential idea is to start with an icosahedron (which has 20 triangular faces) and to repeatedly subdivide each triangular face into smaller triangles. At each stage, each new point is shifted radially so it is the correct distance from the centre.
The number of stages will determine how many triangles are generated and hence how close the resulting mesh will be to a sphere.
Here is one reference that I've used for subdivided icosahedrons, based on the OpenGL Red Book. The BSD-licensed source code to my iPhone application Molecules contains code for generating simple icosahedrons and loading them into a vertex buffer object for OpenGL ES. I haven't yet incorporated subdivision to improve the quality of the rendering, but it's in my plans.
To tesselate a sphere, most people sub-divide the points linearly, but that does not produce a rounded shape.
For a rounded tesselation, rotate the two points through a series of rotations.
Rotate the second point around z (by the z angle of point 1) to 0
Rotate the second point around y (by the y angle of point 1) to 0 (this logically puts point 1 at the north pole).
Rotate the second point around z to 0 (this logically puts point 1 on the x/y plane, which now becomes a unit circle).
Find the half-angle, compute x and y for the new 3rd point, point 3.
Perform the counter-rotations in the reverse order for steps 3), 2) and 1) to position the 3rd point to its destination.
There are also some mathematical considerations for values near each of the near-0 locations, such as the north and south pole, and the right-most and left-most, and fore-most and aft-most positions, so check those first and perform an additional rotation by pi/4 (45 degrees) if they're at those locations. This prevents floating point math libraries from freaking out and producing wildly out-of-character values for atan2() and other trig functions.
Hope this helps! :-)