Indexing in equilateral triangle grid given simple 2D Cartesian coordinates - grid

I have an equilateral triangle grid constructed like this:
Now, given that 2D coordinate origin point is red dot at very bottom left of image, i need to find index into this triangle grid.
Given Input: X and Y coordinates of point (floating point) of interest, triangle side length and height
Need Output: X and Y index of triangle. (sample indexes seen in image)
Getting Y (row) coordinate of triangle is simple as it is just integer part of (GivenY / TRIANGLE_HEIGHT), but i cant get around to calculate Needed X coordinate without doing to much of operations.

Here is a more explicit answer, for people having issues (or too lazy) to figure out the geometry.
First scale your coordinates to a convenient basis
vec2 pos=(input-origin)/vec2(edge/2,median);
Split your coordinates in integer and fractional part
int x=pos.x, y=pos.y; float u=pos.x-x, v=pos.y-y;
Test for the diagonal (x,y of different parity) or anti-diagonal edge (x,y of same parity)
if(x%2 ^ y%2) { if(v+u<1) x--; } else { if(v-u>0) x--; }
That's it (x,y) is now your face index.
Finding vertex index for each face is a bit more involved.
You have four cases, Here is a list of CCW vertex indices for each face:
face vertices
xy xy xy xy
00 -> 00 10 01
10 -> 11 01 10
01 -> 01 12 02
11 -> 12 01 11
It's easier to see the pattern if you don't add 1 to the y vertex indices, So your final table is:
00 -> 00 10 01
10 -> 11 01 10
01 -> 00 11 01
11 -> 11 00 10
Each column is respectively: x, x, !x, x^y, x, !x. Alternatively, you can simply use a lookup table.
It works with arbitrary face indices, you just need to add (x/2, y) and do your lookup on (x%2, y%2).
In the end, the triangle vertex indices are:
x/2 + x%2, y + x%2; x/2 + !(x%2), y + (x%2^y%2); x/2 + (x%2), y + !(x%2)
with vertex coordinates in your original cartesian space:
origin+vec2(2*x+y%2),y)*vec2(edge/2,median)

More triangles
If you draw a line from the bottom left of 0,0, to the top right of 1,0, the shaded are of the two triangles is now made up of four right angled triangles. Drop a line down from the top right of 1,0 you end up with another right angled triangle and a triangle composed of three right angled triangles height is your original triangle height, width is 1.5 * triangle length, hypotenuse I leave for an exercise for the class.
So then whether it's in the left or right triangle is where your point intercepts that line.
You can precaclc most of this based on triangle length.
Another option is to work out the parallelogram, calc it's centre, move that to the origin, rotatee 30 degrees clockwise, move back, Precalc the transform, you have a diamond with a width of the above hypotenuse, Which side of the middle is which triangle, height of the diamond is triangle length, you'll still need to work or the parallegram as 1.0 and 2,0 will overlap.

Related

How do I triangulate a 3d coordinate from two 2d points?

I'm working on a project with two infrared positioning cameras which output the (X,Y) coordinate of any IR source. I'm placing them next to each other and my goal is to measure the 3D coordinate (X,Y,Z) of the IR source, using the same technique our eyes use to measure depth.
I have drawn a (lousy) sketch here
which illustrates what I'm trying to calculate. The red dot is my IR source, which can also be seen on the 'views' of the camera to the right. I am trying to measure the length of the blue line.
I have a few known variables:
The cameras have a resolution of 1024x768 (which also means that this is the maximum of the (X,Y) coordinate mentioned earlier)
Horizontally the field of view is 41deg, vertically 31deg.
I have yet to decide on the distance between cameras (AB), but this will be a known variable. Let's make it 30 cm for now.
Sadly I cannot seem to find the focal length of the camera.
Ultimately I'm hoping for an (X,Y,Z) coordinate relative to the middle point of AB. How would I go about measuring (Z)?
I am not sure how well aligned your cameras are, but from your pictures I am beginning to assume that the camera A and camera B are so well aligned that the rectangle representing the camera B's screen is simply horizontal translation of the rectangle representing the camera A's screen. What I mean by that is that the corresponding edges of the screens' rectangles are parallel to each other and the two rectangular screens lie in a common vertical plane perpendicular to the ground. Now, consider the plane parallel to the vertical plane that contains the two camera screens and passing through the focal points A and B of the two cameras. Call this latter plane the screen_plane. Also, the focal points A and B are at an equal height from the ground. If that is the case, and if I assume that c = |AB| is the distance between the focal points of the two cameras, and if I put a coordinate system at A, so that the x axis is horizontal to the ground, the y axis is perpendicular to the ground, and the z axis is parallel to the ground but perpendicular to the screen, then the focal point of camera B would have coordinates ( c, 0, 0 ). As an example, you have given c = 30 cm. Also the screen_plane is spanned by the x and y axes described above and the z axis is perpendicular to the screen_plane.
If that is the setting you want to work with, then the red point P will appear on both screens with the same coordinate Y_A = Y_B but different coordinates X_A and X_B.
Then let us denote by theta the horizontal field of view angle, which you have determined as theta = 41 deg. Just to be clear, I am assuming the angle between the leftmost side to the rightmost side of view is 2 * theta = 82 deg.
If I understand correctly, you are trying to calculate the distance Z between the vertical plane screen_plane that contains both camera focal points and the plane parallel to screen_plane and passing through the red point P, i.e. you are trying to calculate the distance from P to the vertical plane screen_plane.
Then, here is how you calculate Z:
Step 1: From the image of point P on screen A calculate the distances (e.g. the number of pixels) from P to the vertical edges of the screen. Say they are dist_P_to_left_edge and dist_P_to_right_edge. Set
a_A = dist_P_to_left_edge / (dist_P_to_left_edge + dist_P_to_right_edge) (this one is not really necessary)
b_A = dist_P_to_right_edge / (dist_P_to_left_edge + dist_P_to_right_edge)
Step 2: Do the same with the image of point P on screen B:
a_B = dist_P_to_left_edge / (dist_P_to_left_edge + dist_P_to_right_edge)
b_B = dist_P_to_right_edge / (dist_P_to_left_edge + dist_P_to_right_edge) (this one is not really necessary)
Step 3: Apply the formula:
Z = c * cot(theta) / (2 * (1 - b_A - a_B) )
So for example, from the pictures of the screens of camera A and B you have provided, I measured with a ruler, that
b_A = 4/38
a_B = 12.5/38
and from the data you have included
theta = 41 deg
c = 30 cm
so I have calculated that the length of the blue segment on your picture is
Z = 30 * cos(41*pi/180) / (sin(41*pi/180) * (1 - 4/38 - 12.5/38))
= 60.99628 cm

Vector Projection through a point and onto a plane

I need to calculate the location of the yellow star on the plane, in flat plane Tangent Space.
So first I need to project a vector from the eye, through the pink square, and find the resulting location on the plane (find the yellow star).
Everything is in tangent space already. So I know the location and direction of the eye, and the location of the pink square, in relation to the center of the plane (tangent space).
The resulting yellow star must be on the plane. So its position with respect to the direction of the blue arrow must be always zero. In the above image, it would have a positive value for its position with respect to the green and red arrows.
I've been trying to figure out how to do this using math such as Vector Projection, but I can't seem to wrap my head around it.
So the camera has 3d location vector r and direction vector e. The plane is defined by z=0 which you use on the equation of the line
z = r_z + t * e_z = 0 } t = -r_z/e_z
the coordinate are then
x = r_x + t * e_x
y = r_y + t * e_y
I assume that everything is already expressed in the desired coordinate system with blue along the z-axis.

Sorting a List of 3d coplanar points to be clockwise or counterclockwise

I have a list of 3D points. I know they are all coplanar. I have the center that I want to sort them around and the normal to the plane on which the points and the center lie. How can I test if one point is right (or left) of another point?
I understand how to do it in 2D. Sort points in clockwise order? explains how to compare 2d points. So I think I need to somehow covert all the points and the center to local 2d plane coordinates. How can I do that? Is it the most efficient way to solve this problem?
//from link:
// a and b are points
//center is the center around which to determine order
//int num = (a.x-center.x) * (b.y-center.y) - (b.x - center.x) * (a.y - center.y);
//if num=0 then they're on the same line
//if num <0 or num>0 then a is to the left or right of b
How would I adapt this to handle 3d coplanar points?
There's no need to convert everything to 2D.
You have the center C and the normal n. To determine whether point B is clockwise or counterclockwise from point A, calculate dot(n, cross(A-C, B-C)). If the result is positive, B is counterclockwise from A; if it's negative, B is clockwise from A.

Rectangle Coordinate Rotation

I want to rotate rectangles on a centre point rectangle.
For example I have grid of rectangles size 41 x 21
So my centre rectangle is 20 x 10
Now I wanna rotate 22 x 14 to 90 degree along centre rectangle.
What will be formula to rotate 22 x 14.
any help will be great.
Generally, project the cells onto a plane, then use a rotation matrix, then project them cells back into the grid. For this example, its overkill, but works nonetheless.
You need to set your origin to be (21,11) not (0,0) so first translate your points
[x'] := [x - 21]
[y'] [y - 11]
Then apply the rotation matrix transform (note that I'm assuming traditional direction of axes)
[x''] := [ cos(-Pi/2) -sin(-Pi/2) ][x'] = [ y']
[y''] [ sin(-Pi/2) cos(-Pi/2) ][y'] [-x']
Then un-translate the origin. Because your plane wasn't square, the resultant rotated plane is a different shape (it measures 21x41 with origin 11,21). I've assumed this is what you wanted, and you didn't want points to be able to "fall off" the plane.
[x'''] := [x'' + 11]
[y'''] [y'' + 21]
Simplifying the algebra, this boils down to the map
[x] -> [ y ]
[y] [42-x]
Answer
(22,14) rotates to (14,20)
Note: Counting from 1, I make the centre of 41x21 as 21x11, not 20x10?

Finding Whether A Point is Within a Right-Angle Triangle

I've always wondered the easiest way to figure out whether or not a point lies within a triangle, or in this instance, a rectangle cut into half diagonally.
Let's say I have a rectangle that is 64x64 pixels. With this rectangle, I want to return a TRUE value if a passed point is within the upper-left corner of the rectangle, and FALSE if it isn't.
-----
| /|
| / |
|<__|
Horray for bad ASCII art.
Anyway, the hypothetical points for this triangle that would return TRUE would be (0,0) and (63,0) and (0, 63). If a point lands on a line (e.g., 50,0) it would return TRUE as well.
Assuming 0,0 is in the upper-left corner and increases downwards...
I've had a possible solution in my head, but it seems more complicated than it should be - taking the passed Y value, determining where it would be in the rectangle, and figuring out manually where the line would cut at that Y value. E.g, a passed Y value of 16 would be quarter height of the rectangle. And thus, depending on what side you were checking (left or right), the line would either be at 16px or 48px, depending on the direction of the line. In the example above, since we're testing the upper-left corner, at 16px height, the line would be at 48px width
There has to be a better way.
EDIT:
The rectangle could also look like this as well
-----
|\ |
| \ |
|__>|
But I'm figuring in most cases the current answers already provided should still hold up...
Top-left/bottom-right triangles: For all points in the top-left triangle, x+y<=64. Points in the bottom-right triangle have x+y>64.
(for a rectangle of size (w,h) use w*y+h*x-w*h<0)
Top-right/bottom-left triangles: For all points in the bottom-left triangle, x<=y. Points in the top-right triangle have x>y.
(for a rectangle of size (w,h) use h*x-w*y<0)
How did we get there?
For a rectangle of dimensions (w,h) and TL/BR triangles, the equation of the diagonal is (try it out! assign x=0 and check that you get y==h, and assign y=0 and check that x==w)
h*x + w*y - w*h = 0
Points on one side of that line will have
h*x + w*y - w*h > 0
While points on the other will have
h*x + w*y - w*h < 0
Inserting 64 for both w and h, we get:
64x + 64y - 64*64 < 0
Dividing by 64 gets us:
x+y < 64
For TR/BL triangles, the line equation and the resulting inequalities are:
h*x - w*y = 0
h*x - w*y < 0
h*x - w*y > 0
Inserting 64 for w and h, we get
64x-64y < 0
=> x<y
you can represent the triangle with three affine functions
take the unit triangle with corners at (0, 0), (1, 0) and (1, 1). the sides are represented by the three lines
y = 0
x = 1
y = x
So the interior and boundry of the triangle are given as the intersection of the sets
x >= 1
y >= 0
y <= x
so given a point, (x, y), you just need to verify that it satisfies those three inequalities.
You can of course generalize this to any triangle using the fact that any affine function (representing a line) can be written in the form y = mx + b.
The equation for the line looks like this :
y = mx + b
So, if you insert your x and y-Values into that equation, it will probably not hold anymore. Let's reformulate it:
mx + b - y = 0
Same thing, different look. Again, the result is probably not zero. But, the result will now tell you whether it's on the one side of the line or the other.
Now you just have to find out whether the point is inside your rectangle.
Lets assume your right angled triangle has one corner at 0,0 and the diagonal corner at a,b.
So y=mx+c c=0 as we start at the origin.
m=b/a
So y=bx/a
To know which half of the triangle your point (c,d) falls in
if (d<=(bc/a)) {//point is in bottom half}
if (d>(bc/a)) {//point is in top half}
I think...
A simple option is to use a ray casting algorithm. Whilst perhaps a little overkill for what you need, it does have the advantage that it will work with more complex triangles and polygons.
Loosely, the algorithm takes an imaginary point in a direction (infinitely off to the left, for example) and casts a ray to your test point; you then calculate whether each line of your triangle crosses that infinitely long line. If you get an odd number of crossings, your point is inside your triangle; even and you're out of your triangle

Resources