I know how to rotate an entire 2d array by 90 degrees around the center(My 2d array lengths are always odd numbers), but I need to find an algorithm that rotates specific indices of a 2d array of known length. For example I know that the 2d array is a 17 by 17 grid and I want the method to rotate the indices [4][5] around the center by 90 degrees and return the new indices as two separate ints(y,x); Please point me in the right direction or if your feeling charitable I would very much appreciate some bits of code - preferably in java. Thanks!
Assuming cartesian coordinates (i.e. x points right, and y points up) and that your coordinates are in the form array[y][x] the center [cx, cy] of your 17x17 grid is [8, 8].
Calculate the offset [dx, dy] of your point [px, py] being [4, 5] from there, i.e. [-4, -3]
For a clockwise rotation, the new location will be [cx - dy, cy + dx]
If your array uses the Y axis pointing "downwards" then you will need to reverse some of the signs in the formulae.
For a non-geometric solution, consider that the element [0][16] needs to get mapped to [16][16], and [0][0] mapped to [0][16]. i.e. the first row maps to the last column, the second row maps to the second last column, etc.
If n is one less than the size of the grid (i.e. 16) that just means that point [y][x] will map to [x][n - y]
In theory, the geometric solution should provide the same answer - here's the equivalence:
n = 17 - 1;
c = n / 2;
dx = x - c;
dy = y - c;
nx = c - dy = c - (y - c) = 2 * c - y = n - y
ny = c + dx = c + (x - c) = x
If you have a square array with N elements in each row/column a 90deg turn anti-/counter-clockwise sends (x,y) to (N+1-y,x) doesn't it ?
That is, if like me, you think that the top-left element in a square array is (1,1) and row numbers increase down and column numbers to the right. I guess someone who counts from 0 will have to adjust the formula somewhat.
The point in Cartesian space x,y rotated 90 degrees counterclockwise maps to -y,x.
An array with N columns and M rows would map to an array of M columns and N rows. The new "x" index will be non-positive, and will be made zero-based by adding M:
a[x][y] maps to a[M-y][x]
Related
I have inputs height if first coordinate, height of last coordinate, and n where n is a number of points I need to create on the edge including first and last.
I created points that are at equal distance but they form a straight line. I want to have a sinusoidal wave-like curve instead of a straight line. That means points closer to the first coordinate and last coordinates and the rest of the points are gradually increasing.
final double heightOfFirstCoordinate = 0;
final double heightOfLastCoordinate = 6;
final int n = 4;
final double step = (heightOfLastCoordinate - heightOfFirstCoordinate) / (n - 1);
final List<Double> collect = IntStream.range(0, n)
.mapToObj(i -> heightOfFirstCoordinate + step * I)
.collect(Collectors.toList());
As you can see on the screenshot what I produced is the black line but I need to produce the brown line.
I can't think of any simple algorithm to do this thing without making it much complicated.
assumed the derivative of the start and end points are exactly 0, you can use a cubic function running from 0 to 1 and returning values from 0 to 1:
double cubic(double x)
{
return 3*x*x-2*x*x*x;
}
To transform from the actual coordinates, use
y = y0+dy*cubic((x-x0)/dx);
where x0,y0 is the starting point the dy,dx are the deltas between start and end points.
I have segments of lines and ellipses (NOT planes and ellipsoids) transformed into 3d space and need to calculate whether two given segments intersect and where.
I'm using Java but haven't yet found a library which solves my problem, nor came across some algorithms that I could use for my own implementation.
For line-line intersection test there are several ways to solve. The classic way is using linear algebra (i.e., solving a linear matrix system) but from software development point of view I like more the Geometric-Algebra way, in the form of Plucker Coordinates, which only requires to implement vector algebra operations (i.e., cross-product and dot-product) which are simpler to code than matrix operations for solving linear systems.
I will show both for the sake of comparison then you decide:
Linear Algebra Way
Given line segment P limited by points P1 and P2 and line segment Q limited by points Q1 and Q2.
The parametric form of the lines is given by:
P(t) = P1 + t (P2 - P1)
Q(t) = Q1 + t (Q2 - Q1)
Where t is a real number in the interval [0 1].
If two lines intersect then the following equation holds:
P(t0) = Q(t1)
Provided that the two unknown numbers t0 and t1 exist. Expanding the above equation we get:
t0 (P2 - P1) - t1 (Q2 - Q1) = Q1 - P1
We can solve for t0 and t1 by expressing the above equation in matrix algebra:
A x = B
Where A is a 3x2 matrix with coordinates of vector (P2 - P1) in the first column and coordinates of the vector (Q2 - Q1) in the second column; x is a 2x1 column vector of unknowns t0 and t1 and B is a 3x1column vector with coordinates of vector (Q1 - P1).
Classically the system can be solved calculating the pseudo-inverse of matrix A, denoted by A^+:
A^+ = (A^T A)^-1 A^T
See:
https://en.m.wikipedia.org/wiki/Generalized_inverse
Fortunately any matrix package in Java should be able to compute the above calculations very easily and perhaps very efficiently too.
If multiplying A with its pseudo-inverse A^+ is equal to the identity matrix I, i.e., (A A^+) == I, then there IS a unique answer (intersection) and you can get it computing the following product:
x = A^+ B
Of course if you cannot compute the pseudo-inverse in the first place, e.g., because (A^T A) is singular (i.e. determinant is zero), then no intersection exists.
Since we are dealing with segments, the intersection point is at point P(x0) or Q(x1) iff x0 and x1 are both in the interval [0 1].
OTHER METHOD OF SOLUTION
To avoid dealing with matrix algebra we can try to solve the system using vector algebra and substitution method:
t0 (P2 - P1) - t1 (Q2 - Q1) = Q1 - P1
t0 = a + t1 b
t1 = C • (Q1 - (1 - a) P1 - a P2) / |C|^2
Where:
a = (P2 - P1) • (Q1 - P1) / |P2 - P1|^2
b = (P2 - P1) • (Q2 - Q1) / |P2 - P1|^2
C = b (P2 - P1) - (Q2 - Q1)
I cannot provide a geometric intuition of the above results yet.
Plucker Coordinates way
Given line segment P limited by points P1 and P2 and line segment Q limited by points Q1 and Q2.
The Plucker Coordinates of line P is given by a pair of 3d vectors (Pd, Pm):
Pd = P2 - P1
Pm = P1 x P2
Where Pm is the cross-product of P1 and P2. The Plucker Coordinates (Qd, Qm) of line Q can be calculated in exactly the same way.
The lines P and Q only can intersect if they are coplanar. Thr lines P and Q are coplnanar iif:
Pd • Qm + Qd • Pm = 0
Where (•) is the dot-product. Since machines have finite precision a robust test should check not for zero but for a small number. If Pd x Qd = 0 then lines are parallel (here 0 is the zero vector). Again a robust test should be for instamce that the squared length of (Pd x Qd) is small.
If the lines are not parallel then they are coplanar and their intersection (called "meet" in Plucker's jargon) will be the point:
x = ((Pm • N) Qd - (Qm • N) Pd - (Pm • Qd) N) / (Pd x Qd) • N
Where N is any coordinate axis vector (i.e., (1,0,0) or (0,1,0) or (0,0,1)), such that (Pd x Qd) • N is non-zero.
If the neither P nor Q pass through the origin, then their Plucker coordinate Pm and Qm respectively will be non-zero and the following sinpler formula will work
x = Pm x Qm / Pd • Qm
For an introduction to Plucker Coordinates see:
https://en.m.wikipedia.org/wiki/Plücker_coordinates
http://www.realtimerendering.com/resources/RTNews/html/rtnv11n1.html#art3
For a general intersection formula see "Corollary 6" of:
http://web.cs.iastate.edu/~cs577/handouts/plucker-coordinates.pdf
Transforming Ellipses to Circles Forth and Back
We can always transform an ellipse into a circle. An ellipse has two "radius", called semi-axes, which you can visualize in your mind as two orthogonal vectors, one big called major semi-axes and one small called minor semi-axes. You can apply a non-uniform scaling transformation to both semi-axes vectors for making them of equal size, so you get a circle.
We define an ellipse "E" by its center O, which is a 3d point and its two semi-axes A1 and A2, which are also 3d vectors. A normal vector N to the ellipse's plane can be computed by the cross product of its semi-axes N = A1 x A2 and then normalizing it to have unit length.
For now suppose there is a linear function M that you can use to transform (scale) your ellipse E into a circle C, with radius equal to the minor semi-axes, by applying it to your ellipse's semi-axes A1 and A2 and to the ellipse's center O.
Notice that the eliipse's center O and ellipse's normal vector N are not changed by M. So M(N) = N and M(O) = O. That means that the circle is in the same plane and has the same position C than the ellipse. The linear function M has a corresponding inverse function M^-1 so we can transform back the vectors of the circle to get the original ellipse E.
Of course we can transform the endpoints of lines P and Q also using function M for sending them to the "circle space" and we can send them back to "ellipse space" using M^-1.
Using M we can compute the intersection of the lines P and Q with the ellipse E in the circle space. So now we can focus on the line-circle intersection.
Line-Plane Intersection
Given a plane with normal vector N and distance D such that:
N • x + D = 0
For every point x in the plane. Then the intersection with line P with Plucker Coordinates (Pd, Pm) is given by:
x = (N x Pm - D Pd) / N • Pd
This works only if the line P is not in the plane i.e.,:
(N • P1 + D) != 0 and (N • P2 + D) != 0
And for our ellipse E we have:
N = (A1 x A2)/|A1 x A2|
D = -N • O
Line-Circle and Point-Circle Intersection
Now having x, the point-in-circle check is easy:
|O - x| <= |A2|
Equality holds only when x is in circle boundary.
If line P is in circle's plane then the following sinple check will give you the answer:
https://stackoverflow.com/a/1079478/9147444
How to Compute the Linear Function M
A simple way to compute M is the following. Use the Ellipse's normal vector N and semi-axes A1 and A2 to create a 3x3 matrix U. Such that U has the vectors A1, A2 and N as columns.
Then scale the major semi-axes A1 to have the same length to the minor semi-axes A2. Then create the matrix V auch that V has the new vector A1 and A2 and N as columns.
Then we define the linear matrix system:
R U = V
Where R is a 3x3 (non-uniform-)scaling-rotation matrix.
We can solve for R by multiplying both sides of the equation by the inverse of U which is denoted by U^-1
R U U^-1 = V U^-1
Since U U^-1 is the identity matrix we get:
R = V U^+
Using R we define the affine transformation
M(x) = R (x - O) + O
We can use M to transform points to circle space, such as O, P1, P2, Q1 and Q2. But if we need to transform vectors such as A1, A2, N, Pd and Qd. We need to use the simpler M:
M(x) = R x
Since A1, A2 and N are eigenvectors of R then R is not singular and has an inverse. We define the inverse M as:
M^-1(x) = R^-1 (x - O) + O
And for vectors:
M^-1(x) = R^-1 x
Update: Ellipse-Ellipse intersection
Two intersecting non-coplanar 3d-ellipses have their intersection points on the line formed by the intersection between their planes. So you first find the line formed by the intersection of the planes containig the ellipses (if planes do not intersect i.e., they are parallel, then neither the ellipses intersect).
The line of intersection belong to both planes, so it is perpendicular to both normals. The direction vector V is the cross product of the plane normals:
V = N1 × N2
To fully determine the line we also need to find a point on the line. We can do that solving the linear equations of the planes. Given the 2x3 matrix N = [N1^T N2^T] with the normals N1 and N2 as rows, and the 2x1 column vector b = [N1 • C1, N2 • C2], where C1 and C2 are the centers of the ellipses, we can form the linear matrix system:
N X = b
Where X is some point satifying both plane equations. The system is underdetermined since there are infinite number of points in the line satifying the system. We can still find a particular solution closer to the origin by using the pseudo-inverse of matrix N, denoted by N^+.
X = N^+ b
The line equation is
L(t) = X + t V
For some scalar t.
Then you can apply the method described earlier to test the line-ellipse intersection i.e., scaling the ellipse to a circle and intersect with the coplanar line. If both ellipses intersect the line in the same points then they intersect.
Now, the case in which the ellipses actually lie on the same plane is more complex. You can ceck the approach taken by Dr Eberly in his excellent book "Geometric Tools" (also available online):
https://www.geometrictools.com/Documentation/IntersectionOfEllipses.pdf
And also you can check the C++ source code which is open source:
https://www.geometrictools.com/GTEngine/Include/Mathematics/GteIntrEllipse2Ellipse2.h
I've been trying to make a code that goes through all array elements that are between two specified points, but I am stuck.
Let's suppose it's an array like that:
int[][] new_array = new int[100][100];
And how do I get all elements that are in straight line between let's say
new_array[17][2];
and
new_array[5][90];
This is what I want to achieve:
Let's imagine that your array is a first quadrant of a cartesian coordinates system. With a first column lying on axis Y and last row lying on axis X.
Having that assumption you could find a function that describes a straight line between any of two points in your array.
You need to solve the function:
y = ax + b
It's a standard linear function. You have two points, solving that you'll find your equation (values of a and b).
When you know equation you need to evaluate points in the array for each x value. Doing that you'll find all y values that are below/on/above the line.
Following #Marcin Pietraszek's answer the function can be obtained this way:
Given the two points (a,b) and (c,d) the straight line that passes through both points is given by
a + K * (x - a) = c AND b + K (y - b) = d
where K is a scalar number.
And this resolves to:
y = ( (d - b) * x - (d - b) * a + (c - a) * b ) / (c - a)
So any point (x, y) that meets this condition will be on the straight line.
You will need go through the matrix, checking one by one to see which points meet the condition.
If you want only the point inside the segment, then aditionally you need to check the boundaries.
I'm attempting to write a method that determines the area of a polygon (complex or simple) on a sphere. I have a paper that was written by a few guys at the JPL that more or less give you the equations for these calculations.
The pdf file can be found here:
http://trs-new.jpl.nasa.gov/dspace/handle/2014/40409
The equation can be found on page 7, under "The Spherical Case - Approximation":
I also typed the equation in Word:
Spherical_Case_Equation
I need assistance with converting this equation into the standard form (I think that's the right terminology). I've already done something similar for the Planer Case:
private double calcArea(Point2D[] shape) {
int n = shape.length;
double sum = 0.0;
if (n < 3) return 0.0;
for (int i = 0; i < n-1 ; i++) {
sum += (shape[i].getX() * shape[i+1].getY()) - (shape[i+1].getX() * shape[i].getY());
}
System.out.println(0.5 * Math.abs(sum));
return 0.5 * Math.abs(sum);
}
I just need help with doing something similar for the spherical case. Any assistance will be greatly appreciated.
I haven't read the paper you referenced. The area of a spherical polygon is proportional to the angle excess.
Area = r²(Σ Aᵢ - (n - 2)π)
To compute the corner angles, you may start with the 3D coordinates of your points. So at corner i you have vertex p[i] = (x[i],y[i],z[i]) and adjacent vertices p[i-1] and p[i+1] (resp p[(i+n-1)%n] and p[(i+1)%n] to get this cyclically correct). Then the cross products
v₁ = p[i] × p[i-1]
v₂ = p[i] × p[i+1]
will be orthogonal to the planes spanned by the incident edges and the origin which is the center of the sphere. Noe the angle between two vectors in space is given by
Aᵢ = arccos(⟨v₁,v₂⟩ / (‖v₁‖ * ‖v₂‖))
where ⟨v₁,v₂⟩ denotes the dot product between these two vectors which is proportional to the cosine of the angle, and ‖v₁‖ denotes the length of the first vector, likewise ‖v₂‖ for the second.
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Pack squares into a rectangle
i need to calculate the most efficient size of squares will fill the the screen,
if you look at the below images, there are different screen sizes and square count.
I need a algorithm to calculate x axis square count and y axis square count which will fill the screen most efficiently (minimum empty area will be left after filling with squares).
i looked at the below post but it is not the answer that solves my question
Pack squares into a rectangle
1 - Square count can be changed (3-5-10 so on ...)
2 - Screen size can be different
For examples ,
on 1280 x 800 with 15 square ?
on 800 x 480 with 12 square ?
on 600x1024 with 9 square ?
on 720x1280 with 45 square ?
** I need a algorith which calculate the squares width (height is same with width) **
If you look at differencies beetween image 3 and Image 3-1 you will see that Image 3-1 uses the screen more efective because there are less unused area.
Image 3
Or maybe this is a better way to fill:
Image 3-1
If you look at differencies beetween image 4 and Image 4-1 you will see that Image 4-1 uses the screen more efective because there are less unused area.
Image 4
** 4. Image must be like below , because there are less unused area on the screen **
Image 4-1
I believe what you suggest by "efficient" is the larger the area covered by the squares the better.
let :
a : x axis square count
b : y axis square count
s : size of a square (length of one side)
w : width of screen
h : height of screen
c : number of squares to put
then we have
a * s <= w
b * s <= h
a * b >= c
With these inequalities it is possible to find an upper bound for s.
Examining the forth example given where c = 20, w = 1280 and h = 800
a * s <= 1280
b * s <= 800
a * b >= 20
a * b = (1280 / s) * (800 / s) >= 20 ---> s^2 <= (1280*800) / 20 ---> s <= 226,27..
With an upper bound for s, we can estimate a and b as;
a * s <= 1280 ---> a ~= 5,6568
b * s <= 800 ---> b ~= 3,53
with these values the inequality a * b >= 20 does not hold.
But both a and b must be whole numbers. Then we try the 4 possibilities that a and b can get :
a = 5, b = 3 // round down both
a = 5, b = 4 // one down, one up
a = 6, b = 3 // one down, one up
a = 6, b = 4 // round up both
since a * b >= 20 the first and third cases are eliminated to be a valid answer.
Choosing the answer where a = 5, b = 4 follows as the next step since their product is more close to the desired number of squares.
What you're looking for is the greatest common factor between the width and the height of the display.
Since most displays have a ratio of 4:3 or 16:9, the greatest common factor will give you the biggest square that you can use to fill the display area.
In your 400 x 400 pixel display, the greatest common factor is 400, and one square will fill the display.
In your 1280 X 800 pixel display, the greatest common factor is 160. You'll need 40 squares (8 x 5) to fill the display.
if you want to calculate one greatest common factor for all display sizes, the answer is 1. Every pixel is a square. You should calculate a separate greatest common factor for each display size you want to support.