3D effect to distort paper - image

This may be a little hard to describe since I don't have a sample. I'm trying to find a math function or full 3d function in php or a similar language that can help me with the following effect:
imagine if you were to take a flat sheet or paper and glue it on a glass of water. It wouldn't be flat any more. It would have a curve, and one of its sides might end up being slightly hidden.
Anyone can refer me to a good library or resource on the web where such functions can be found?

Lets say the center of your paper is x=0, and your cylinder is vertical along the y-axis. Your x-coordinate on the paper could be equated to an arc length on the surface of the cylinder. Arc length (s) is equal to the angle (in radians) times the radius. Your radius is given, so you can compute the angle from the arc length and radius. Angle = Arc Length / Radius. Since you now have the angle and the radius, you can compute the new x-offset, which would be (radius * cos(angle)). So your mapping functions would be:
new_x = radius * cos(old_x/radius)
new_y = old_y; //y-coordinate doesn't change
new_z = radius * sin(old_x/radius);
You'll have to enforce boundaries (keep x on the paper, and make sure it's not more than half the circumference (x must be less than or equal to PI*r). Also, watch the signs... especially the z-coordinate, which will depend on whether your coordinate system is right-handed or left-handed, or where you imagine the paper starting on the cylindar (back or front). Finally, you can use standard matrix transforms to move and position the paper/cylinder in 3D space once you have the warped coordinates.

Related

How to calculate Arc length dependently of start angle?

I am building a road editor where one can drag predefined road segments together and combine them to a connected road. One of those segments is a right curve.
The curve is drawn as SVG (using D3 arc path function) and has two handles to change the radius and the length directly within the SVG (small black circle changes length and small black square changes the radius). I use a d3 drag handler on the handles.
To calculate the new central angle I do as follows:
get YOffset from center point of the arc
flip YOffset (to match screen y and math)
get corresponding x value with Pythagoras (x = Math.sqrt(r^2 - YOffset^2))
get the respective central angle (Math.PI / 2 - Math.atan2(YOffset, x);
This will only work if the arc starts at PI/2 like in the figure. If I add further arcs with arbitrary start angles (see next figure, red arc), my solution wont work.
I'm looking for a general solution so it will work for any arc regardless of its start angle.
To me it seems this is not much of a programming problem, but of math. What I understand is: given a start point (x₁, y₁), an end pont(x₂, y₂) and a radius r, what is the angle α?
You can compute the distance d between the two points. Half its length is the far leg of a right triangle with r as its hypothenuse. d/2r is the sinus of the near angle; double that and you have the angle between the end points.
(And, having α expressed in radians, the path length is simply α * r.)

Point in circle segment

I have a circle I want to divide up in to a number of segments all defined by X and Y coordinates. How to I test to see if a point (X, Y) is in a particular segment?
A code example would be preferable.
You don't need to use trigonometry for this (and in general, trigonometry should be avoided whenever possible... it leads to too many precision, domain, and around-the-corner problems).
To determine whether a point P is counter-clockwise of another point A (in the sense of being in the half-plane defined by the left side of a directed line going through the origin and then through A), you can examine the sign of the result of Ax*Py - Ay*Px. This is generally known as the "perpendicular dot product", and is the same as the Z coordinate of the 3D cross product.
If there are two points A and B (with B defining the CCW-most extent) defining a sector, and the sector is less than half the circle, any point which is CCW of A and CW of B can be classified as in that sector.
That leaves only a sector which is more than half of the circle. Obviously, a given set of points can only define at most one such sector. There's clever things you can do with angle bisection, but the easiest approach is probably just to classify points as in that sector if you can't classify them as being in any other sector.
Oh, forgot to mention -- determining the order of the points for the purposes of pairing them up for sectors. Not to go against my previous advice, but the most straightforward thing here is just to sort them by their atan2 (not atan... never ever use atan).
Use the polar coordinate system centred at the centre of the circle, and examine the angular coordinate (φ in the Wikipedia article).
What exactly you do with φ depends on how your segments are defined. For example, if you have n equal segments that start at 0 radians, floor(φ * n / (2 * π)) will give you the segment number.
Your segment is defined by two intersections between the circle and a line. You just have to know if:
The angle between the center of your circle and your point is between
the angles formed by the two previous points and the center.
the point is in the circle (the length from this point to the center is smaller than the radius)
from what side is the point compared to the line (it must be beyond the line).
Remark
In geometry, a circular segment (symbol: ⌓) is a region of a circle
which is "cut off" from the rest of the circle by a secant or a chord.
Here is a segment:
If x & y are not already relative to the center of the circle, subtract the coordinates of the center of the circle:
x -= circle.x
y -= circle.y
Use atan2 to get the angle of the point about the origin of the circle:
angle = atan2(y, x)
This angle is negative for points below the x-axis, so adjust to always be positive:
if (angle < 0) angle += 2 * pi
Assuming your segments are equally spaced, use this formula to get the index of the segment:
segment = floor((angle * numSegments) / (2 * pi))
If you find the result is referring to a segment on the opposite side of the circle to what you want, you might have to do y = -y in the beginning or a segment = (numSegments - 1) - segment at the end to flip it round the right way, but it should basically work.

Calculating radius of smallest circle encompassing a North-East/Sout-West based bounding rectangle on Earth

I have a webpage that I am using a Google Map on. When the user drags the map and lets go, I need to query a server for all data points that fall within the bounds of the visible region of the map. I can quite easily get the North-East and South-West coordinate of the visible region of the map through the javascript API, essentially providing a bounding rectangle. However on the server, I am relying on a database whose geographic query API only supports queries in the form of a center point and a radius. So basically what I would like to do is figure out the minimum radius circle I would need to at least encompass the North-East and South-West points.
The simplest algorithm I thought of involved finding the center point between the NE and SW coordinate and then measuring the radius as the distance from the center point to either the NE or SW coordinate. In a simple euclidean space I'd be comfortable doing this, but I think I'd probably get something wrong with the Earth's non-flat coordinate system. I haven't even been able to convince myself that if I knew that centerpoint that the distance would be the same between the center and NE and the center and SW.
I've come across algorithms for smallest circles on a flat 2D surface and also algorithms describing the opposite i.e. bounding box from circle center and radius. I haven't come across a concise algorithm for this particular problem though.
I assume what you call the east-west and north-south coordinates are the longitude and latitude. You can convert them to Cartesian points and find the midpoint between the edge points of your region. This will yield a point C' below Earth's surface with the same latitude and longitude as your centre point C. (This will only work if the difference of your longitudes is smaller than 180°, however; otherwise you'll get a point on the opposite side of the earth, but with the same latitude.) If you need Cartesian coordinates for your centre point, you can project C' onto the surface by adjusting the radius to find your new centre point.
The distance bewteen the two points on the surface of Earth can be calculated with the great-circle disnatce formula.
Transformation is easy if you assume that Earth is a perfect sphere with radius R = 6373 km:
x = R * cos(lat) * cos(lon)
y = R * cos(lat) * sin(lon)
z = R * sin(lat)
and back:
lon = atan2(y, x)
lat = atan2(z, r) with r = sqrt(x*x + y*y)
(But Earth does not have a constant radius, so you might want to use a better coordinate system, maybe ECEF as explained in this answer if you need more precision.)
My first thought was to find your midpoint in terms of longitude and latitude, which should be okay if you take care of wrapping for the latitude. Then you calculate your distance accpording to the great-circle formula. But averaging the longitudes and latitudes does not seem to be sensible if your map region includes a pole.

How to find collision center of two rectangles? Rects can be rotated

I've just implemented collision detection using SAT and this article as reference to my implementation. The detection is working as expected but I need to know where both rectangles are colliding.
I need to find the center of the intersection, the black point on the image above (but I don't have the intersection area neither). I've found some articles about this but they all involve avoiding the overlap or some kind of velocity, I don't need this.
The information I've about the rectangles are the four points that represents them, the upper right, upper left, lower right and lower left coordinates. I'm trying to find an algorithm that can give me the intersection of these points.
I just need to put a image on top of it. Like two cars crashed so I put an image on top of the collision center. Any ideas?
There is another way of doing this: finding the center of mass of the collision area by sampling points.
Create the following function:
bool IsPointInsideRectangle(Rectangle r, Point p);
Define a search rectangle as:
TopLeft = (MIN(x), MAX(y))
TopRight = (MAX(x), MAX(y))
LowerLeft = (MIN(x), MIN(y))
LowerRight = (MAX(x), MIN(y))
Where x and y are the coordinates of both rectangles.
You will now define a step for dividing the search area like a mesh. I suggest you use AVG(W,H)/2 where W and H are the width and height of the search area.
Then, you iterate on the mesh points finding for each one if it is inside the collition area:
IsPointInsideRectangle(rectangle1, point) AND IsPointInsideRectangle(rectangle2, point)
Define:
Xi : the ith partition of the mesh in X axis.
CXi: the count of mesh points that are inside the collision area for Xi.
Then:
And you can do the same thing with Y off course. Here is an ilustrative example of this approach:
You need to do the intersection of the boundaries of the boxes using the line to line intersection equation/algorithm.
http://en.wikipedia.org/wiki/Line-line_intersection
Once you have the points that cross you might be ok with the average of those points or the center given a particular direction possibly. The middle is a little vague in the question.
Edit: also in addition to this you need to work out if any of the corners of either of the two rectangles are inside the other (this should be easy enough to work out, even from the intersections). This should be added in with the intersections when calculating the "average" center point.
This one's tricky because irregular polygons have no defined center. Since your polygons are (in the case of rectangles) guaranteed to be convex, you can probably find the corners of the polygon that comprises the collision (which can include corners of the original shapes or intersections of the edges) and average them to get ... something. It will probably be vaguely close to where you would expect the "center" to be, and for regular polygons it would probably match exactly, but whether it would mean anything mathematically is a bit of a different story.
I've been fiddling mathematically and come up with the following, which solves the smoothness problem when points appear and disappear (as can happen when the movement of a hitbox causes a rectangle to become a triangle or vice versa). Without this bit of extra, adding and removing corners will cause the centroid to jump.
Here, take this fooplot.
The plot illustrates 2 rectangles, R and B (for Red and Blue). The intersection sweeps out an area G (for Green). The Unweighted and Weighted Centers (both Purple) are calculated via the following methods:
(0.225, -0.45): Average of corners of G
(0.2077, -0.473): Average of weighted corners of G
A weighted corner of a polygon is defined as the coordinates of the corner, weighted by the sin of the angle of the corner.
This polygon has two 90 degree angles, one 59.03 degree angle, and one 120.96 degree angle. (Both of the non-right angles have the same sine, sin(Ɵ) = 0.8574929...
The coordinates of the weighted center are thus:
( (sin(Ɵ) * (0.3 + 0.6) + 1 - 1) / (2 + 2 * sin(Ɵ)), // x
(sin(Ɵ) * (1.3 - 1.6) + 0 - 1.5) / (2 + 2 * sin(Ɵ)) ) // y
= (0.2077, -0.473)
With the provided example, the difference isn't very noticeable, but if the 4gon were much closer to a 3gon, there would be a significant deviation.
If you don't need to know the actual coordinates of the region, you could make two CALayers whose frames are the rectangles, and use one to mask the other. Then, if you set an image in the one being masked, it will only show up in the area where they overlap.

How do you map a point(x,y) on a 2D image to 3D space? (illustration provided)

I have a stack of images (about 180 of them) and there are 2 stars (just basic annotations) on every single image. Hence, the position (x,y) of the two stars are provided initially. The dimensions of all these images are fixed and constant.
The 'distance' between the image is about 1o with the origin to be the center (width/2, height/2) of every single 2D image. Note that, if this is plotted out and interpolated nicely, the stars would actually form a ring of an irregular shape.
The dotted red circle and dotted purple circle are there to give a stronger scent of a 3D space and the arrangement of the 2D images (like a fan). It also indicates that each slice is about 1o apart.
With the provided (x,y) that appeared in the 2D image, how do you get the corresponding (x,y,z) in the 3d space knowing that each image is about 1o apart?
I know that MATLAB had 3D plotting capabilities, how should I go about implementing the solution to the above scenario? (Unfortunately, I have very little experience plotting 3D with MATLAB)
SOLUTION
Based on the accepted answer, I looked up a bit further: spherical coordinate system. Based on the computation of phi, rho and theta, I could reconstruct the ring without problems. Hopefully this helps anyone with similar problems.
I have also documented the solution here. I hope it helps someone out there, too:
http://gray-suit.blogspot.com/2011/07/spherical-coordinate-system.html
I believe the y coordinate stays as is for 3D, so we can treat this as converting 2D x and image angle to an x and z when viewed top down.
The 2D x coordinate is the distance from the origin in 3D space (viewed top down). The image angle is the angle the point makes with respect to the x axis in 3D space (viewed top down). So the x coordinate (distance from orign) and the image angle (angle viewed top down) makes up the x and z coordinates in 3D space (or x and y if viewed top down).
That is a polar coordinate.
Read how to convert from polar to cartesian coordinates to get your 3D x and z coordinates.
I'm not great at maths either, here's my go:
3D coords = (2Dx * cos(imageangle), 2Dy, 2Dx * sin(imageangle))
Given the 2D coordinates (x,y) just add the angle A as a third coordinate: (x,y,A). Then you have 3D.
If you want to have the Anotations move on a circle of radius r in 3D you can just calculate:
you can use (r*cos(phi),r*sin(phi),0) which draws a circle in the XY-plane and rotate it with a 3x3 rotation matrix into the orientation you need.
It is not clear from you question around which axis your rotation is taking place. However, my answer holds for a general rotation axis.
First, put your points in a 3D space, lying on the X-Y plane. This means the points have a 0 z-coordinate. Then, apply a 3D rotation of the desired angle around the desired axis - in your example, it is a one degree rotation. You could calculate the transformation matrix yourself (should not be too hard, google "3D rotation matrix" or similar keywords). However, MATLAB makes it easier, using the viewmtx function, which gives you a 4x4 rotational matrix. The extra (fourth) dimension is dependent on the projection you specify (it acts like a scaling coefficient), but in order to make things simple, I will let MATLAB use its default projection - you can read about it in MATLAB documentation.
So, to make the plot clearer, I assume four points which are the vertices of a square lying on the x-y plane (A(1,1), B(1,-1), C(-1,-1), D(1,-1)).
az = 0; % Angle (degrees) of rotation around the z axis, measured from -y axis.
el = 90; % Angle (degrees) of rotation around the y' axis (the ' indicates axes after the first rotation).
x = [1,-1, -1, 1,1]; y = [1, 1, -1, -1,1]; z = [0,0, 0, 0,0]; % A square lying on the X-Y plane.
[m,n] = size(x);
x4d = [x(:),y(:),z(:),ones(m*n,1)]'; % The 4D version of the points.
figure
for el = 90 : -1 :0 % Start from 90 for viewing directly above the X-Y plane.
T = viewmtx(az, el);
x2d = T * x4d; % Rotated version of points.
plot3 (x2d(1,:), x2d(2,:),x2d(3,:),'-*'); % Plot the rotated points in 3D space.
grid
xlim ([-2,2]);
ylim ([-2,2]);
zlim([-2,2]);
pause(0.1)
end
If you can describe your observation of a real physical system (like a binary star system) with a model, you can use particle filters.
Those filters were developed to locate a ship on the sea, when only one observation direction was available. One tracks the ship and estimates where it is and how fast it moves, the longer one follows, the better the estimates become.

Resources