Rotate line with two points - vector

I have line with two points
(x1, y1) (x2, y2)
and I am working on x+, y+ plane only
and say this line is vertical say
(320, 320) (320, 160)
How do I rotate it by 90 degrees to get
(320, 320) (480, 320) [90 deg rotated by bottom point (320, 320)]
(320, 160) (480, 160) [90 deg rotated by top point (320, 160)]
Remember I would need in same form—i.e,
(x1, y1) (x2, y2)
By the way, these lines can only be vertical or horizontal, so the slope is either undefined or zero.

To rotate B 90 degrees around A:
diff = B-A
B_new = A + array([-diff[1],diff[0]])
To be more general, you do this:
def rot_origin(p, ang):
return array([p[0]*cos(ang)-p[1]*sin(ang),p[0]*sin(ang)+p[1]*cos(ang)])
def rot_around(p, p0, ang):
return p0 + rot_origin(p-p0, ang)
Then, your case would be B_new = rot_around(A, B, pi/2), since 90 degrees is pi/2 radians.
Edit: Just to make it completely explicit for your example. To rotate by 90 degrees around point 1, you would get:
(x1,y1) (x1-(y2-y1),y1+(x2-x1))
To rotate around point 2, you would get:
(x2-(y1-y2),y2+(x1-x2)) (x2,y2)

To get what you put as example:
Get the distance between top and bottom points. In your example, d = sqrt((x2 - x1)^2 + (y2-y1)^2).
For a 90 degrees rotation by bottom point, simply use (x2,y2) and (x2+d, y2) as end points.
For a 90 degrees rotation by top point, simply use (x1,y1) and (x1+d, y1) as end points.
This can be easily generalized to any line, not only a vertical one, and any rotation angle.

Related

Parabola in Processing

I was transferring tasks from my maths textbook to Processing. One of the problems required the use of a parabola. I decided to write it as a Bézier curve, wrote the code, but something didn't work.
Could anyone please explain to me what I did wrong here?
The code:
def setup():
background(255,255,255)
size(800,800)
rectMode(CENTER)
line(400,0,400,800)
line(0,400,800,400)
#B 0 to know the start and the end points
a=1
x=3
b=0
c=10
translate(width/2, height/2)
noFill()
beginShape()
#Parabola formula
y=-(a*x*x+b*x+c)
#X of the point of the symetry
Sx=(-b)/(2*a)
#Y of the point of the symetry
Sy=-(a*Sx*Sx+b*Sx+c)
#Derivative
Ny=-(800+b)
#Y of the starting point
By=-(a*400*400-b*400+c)
#Y of the end point
Ey=-(a*400*400+b*400+c)
#Y3 Y4
Ty=Ny*(x+400)-By
bezier(-400,By,Sx,Ty,400,Ey,Sx,Ty)
endShape()
noFill()
beginShape()
for i in range (-400,400):
x=i
y=-i
vertex(x,y)
endShape()
(It had to be an 800x800 coordinate plane, a parabola and a straight line.)
Your resulting y coordinates are way too high for the bezier curve.
If you want to draw the curve with line segments, you need to calculate the y coordinates inside the loop:
def setup():
size(400, 400)
background(255,255,255)
rectMode(CENTER)
line(width/2, 0, width/2, height)
line(0, height/2, width, height/2)
translate(width/2, height/2)
a, b, c = 1, 10, -100
scaleX = 0.1;
noFill()
strokeWeight(4)
beginShape(LINES)
for i in range (-400, 400):
x = i * scaleX
y = -(a*x*x +b*x + c)
vertex(i, y)
endShape()

projections of 3d vector on respective planes

I have a 3d vector defined by start and end coordinates (x0,y0,z0 and x1,y1,z1). Also I know the angles made by this vector to the x,y,z axes. Does some one know how do I get to know the angles induced by the vector in xy, yz and zx planes?
Projection of given segment to OXY plane is segment with coordinates (x1, y1) - (x2, y2).
It forms angle relative to OX-axis:
Axy = atan2(y2-y1, x2-x1)
Angle between segment and its projection on OXY plane is
Pxy = arcsin((z2 - z1) / Sqrt((x2-x1)^2 + (y2-y1)^2 + (z2-z1)^2)

Calculate ball rotation angle based on marker position

I am using camera to trace one black marker on blue ball as shown in image below.
I can detect marker position on top of ball image reliably but would need to know
how to calculate ball rotation angles based on marker location.
When marker is in the middle as shown both angles should be 0 degrees. When marker is only half visible at left edge as shown horizontal angle should be -90 degrees. I understand calculating angles from 2D-image is non-linear, near the edge similar movement in pixels means bigger change in rotation than in the middle but I just can't come up with the formula.
Rotation about vertical axis:
Phi = ArcSin((Marker.X - Center.X) / Radius)
In general, if you grab initial point with 2D coordinates (x0, y0) at the front surface of ball manipulator with radius 1 and drag it ti end point (x1,y1), then you rotate direction vector
d0 = (x0, y0, Sqrt(1 - x0^2 - y0^2))
to
d1 = (x1, y1, Sqrt(1 - x1^2 - y1^2))
What to do with these vectors? I depends on what approach are you going to use for rotation

finding a dot on a circle by degree?

Let's say we have a 100x100 coordinate system, like the one below. 0,0 is its left-top corner, 50,50 is its center point, 100,100 is its bottom right corner, etc.
Now we need to draw a line from the center outwards. We know the angle of the line, but need to calculate the coordinates of its end point. What do you think would be the best way to do it?
For example, if the angle of the line is 45 degrees, its end point coordinates would be roughly 75,15.
You need to use the trigonometric functions sin and cos.
Something like this:
theta = 45
// theta = pi * theta / 180 // convert to radians.
radius = 50
centerX = 50
centerY = 50
p.x = centerX + radius * cos(theta)
p.y = centerY - radius * sin(theta)
Keep in mind that most implementations assume that you're working with radians and have positive y pointing upwards.
Use the unit circle to calculate X and Y, but because your radius is 50, multiply by 50
http://en.wikipedia.org/wiki/Unit_circle
Add the offset (50,50) and bob's your uncle
X = 50 + (cos(45) * 50) ~ 85,36
Y = 50 - (sin(45) * 50) ~ 14,65
The above happens to be 45 degrees.
EDIT: just saw the Y axis is inverted
First you would want to calculate the X and Y coordinates as if the circle were the unit circle (radius 1). The X coordinate of a given angle is given by cos(angle), and the Y coordinate is given by sin(angle). Most implementations of sin and cos take their inputs in radians, so a conversion is necessary (1 degree = 0.0174532925 radians). Now, since your coordinate system is not in fact the unit circle, you need to multiply the resultant values by the radius of your circle. In this given instance, you would multiply by 50, since your circle extends 50 units in each direction. Finally, using a unit circle coorindate system assumes your circle is centered at the origin (0,0). To account for this, add (or subtract) the offset of your center from your calculated X and Y coordinates. In your scenario, the offset from (0,0) is 50 in the positive X direction, and 50 in the negative Y direction.
For example:
cos(45) = x ~= .707
sin(45) = y ~= .707
.707*50 = 35.35
35.35+50 = 85.35
abs(35.35-50) = 14.65
Thus the coordinates of the ending segment would be (85.35, 14.65).
Note, there is probably a built-in degrees-to-radians function in your language of choice, I provided the unit conversion for reference.
edit: oops, used degrees at first

Knowing two points of a rectangle, how can I figure out the other two?

Hey there guys, I'm learning processing.js, and I've come across a mathematical problem, which I can't seem to solve with my limited geometry and trigonometry knowledge or by help of Wikipedia.
I need to draw a rectangle. To draw this rectangle, I need to know the coordinate points of each corner. All I know is x and y for the midpoints of the top and bottom of the box, and the length of all four sides.
There is no guarantee on the orientation of the box.
Any help? This seems like it should be easy, but it is really stumping me.
If this quadrilateral is a rectangle (all four angles are 90 degrees), then it can be solved. (if it could be any quadrilateral, then it is not solvable)
if the points are (x1,y1), and (x2, y2), and if the two points are not perfectly vertical (x1 = x2) or horizontal (y1 = y2), then the slope of one edge of the rectangle is
m1 = (y2-y1) / (x2-x1)
and the slope of the other edge is:
m2 = - 1 / m1
If you know the lengths of the sides, and the midpoints of two opposite sides, then the corrner points are easily determined by adding dx, dy to the midpoints: (if L is length of the sides that the midpoints are on)
dx = Sqrt( L^2 / (1 + m2^2) ) / 2
and
dy = m2 * dx
NOTE: if the points are vertically or horizontally aligned, this technique will not work, although the obvious solution for those degenerative cases is much simpler.
If you know your quadrilateral is a rectangle, then you can use some simple vector maths to find the coordinates of the corners. The knowns are:
(x1,y1) - the coordinate of the midpoint on the top line
(x2,y2) - the coordinate of the midpoint on the bottom line
l1 - the length of the top and bottom lines
l2 - the length of the other two lines
First, we find the vector between the two known points. This vector is parallel to the side lines:
(vx, vy) = (x2 - x1, y2 - y1)
We need to normalize this vector (i.e. make it length 1) so we can use it later as a basis to find our coordinates.
vlen = sqrt(vx*vx + vy*vy)
(v1x, v1y) = (vx / vlen, vy / vlen)
Next, we rotate this vector anticlockwise by 90 degrees. The rotated vector will be parallel to the top and bottom lines. 90 degree rotation turns out to just be swapping the coordinates and negating one of them. You can see this just by trying it out on paper. Or take at look at the equations for 2D rotations and substitute in 90 degrees.
(u1x, u1y) = (-v1y, v1x)
Now we have enough information to find the 'top-left' corner. We simply start at our point (x1, y1) and move back along that side by half the side length:
(p1x, p1y) = (x1 - u1x * l1 / 2, y1 - u1y * l1 / 2)
From here we can find the remaining points just by adding the appropriate multiples of our basis vectors. When implementing this you can obviously speed it up by only calculating each unique multiplication a single time:
(p2x, p2y) = (p1x + u1x * l1, p1y + u1y * l1)
(p3x, p3y) = (p1x + v1x * l2, p1y + v1y * l2)
(p4x, p4y) = (p3x + u1x * l1, p3y + u1y * l1)
function getFirstPoint(x1,y1,x2,y2,l1,l2)
distanceV = {x2 - x1, y2 - y1}
vlen = math.sqrt(distanceV[1]^2 + distanceV[2]^2)
normalized = {distanceV[1] / vlen, distanceV[2] / vlen}
rotated = {-normalized[2], normalized[1]}
p1 = {x1 - rotated[1] * l1 / 2, y1 - rotated[2] * l1 / 2}
p2 = {p1[1] + rotated[1] * l1, p1[2] + rotated[2] * l1}
p3 = {p1[1] + normalized[1] * l2, p1[2] + normalized[2] * l2}
p4 = {p3[1] + rotated[1] * l1, p3[2] + rotated[2] * l1}
points = { p1 , p2 , p3 , p4}
return p1
end
It's definitely a rectangle? Then you know the orientation of the short sides (they're parallel to the line between your points), and hence the orientation of the long sides.
You know the orientation and length of the long sides, and you know their midpoints, so it's straightforward to find the corners from there.
Implementation is left as an exercise to the reader.
This means that there will be two lines parallel to the line between the two points you have. Get the corners by translating the line you have 1/2 the length of the top side in each direction perpendicular to the line you have.
If you know the midpoint for the top, and the length of the top, then you know that the y will stay the same for both top corners, and the x will be the midpoint plus/minus the width of the rectangle. This will also be true for the bottom.
Once you have the four corners, there is no need to worry about the side lengths, as their points are the same as those used for the top and bottom.
midpoint
x,10 10,10 x,10
*--------------------------------------------*
width = 30
mx = midpoint x.
top left corner = (w/2) - mx or 15 - 10
top left corner coords = -5,10
mx = midpoint x.
top right corner = (w/2) + mx or 15 + 10
top left corner coords = 25,10
There's a difference between a "quadrilateral" and a "rectangle".
If you have the midpoint of the top and bottom, and the sides lengths, the rest is simple.
Given:
(x1, y1) -- (top_middle_x, top_middle_y) -- (x2, y1)
(x1, y2) -- (btm_middle_x, btm_middle_y) -- (x2, y2)
and top/bottom length along with right/left length.
x1 = top_middle_x - top/bottom_length / 2;
x2 = x1 + top/bottom_length;
y1 = top_middle_y
y2 = bottom_middle_y
Obviously, that's the simplest case and assuming that the line of (tmx, tmy) (bmx, bmy) is solely along the Y axis.
We'll call that line the "mid line".
The next trick is to take the mid line, and calculate it's rotational offset off the Y axis.
Now, my trig is super rusty.
dx = tmx - bmx, dy = tmy - bmy.
So, the tangent of the angle is dy / dx. The arctangent(dy / dx) is the angle of the line.
From that you can get your orientation.
(mind, there's some games with quadrants, and signs, and stuff to get this right -- but this is the gist of it.)
Once you have the orientation, you can "rotate" the line back to the Y axis. Look up 2D graphics for the math, it's straight forward.
That gets you your normal orientation. Then calculate the rectangles points, in this new normal form, and finally, rotate them back.
Viola. Rectangle.
Other things you can do is "rotate" a line that's half the length of the "top" line to where it's 90 deg of the mid line. So, say you have a mid line that's 45 degrees. You would start this line at tmx, tmy, and rotate this line 135 degrees (90 + 45). That point would be your "top left" corner. Rotate it -45 (45 - 90) to get the "top right" point. Then do something similar with the lower points.
Calculate the angle of the line joining the two midpoints using an arc-tangent function applied to the vector you get between them.
Subtract 90 degrees from that angle to get the direction of the top edge
Starting from the top-center point, move relative (1/2 top width x sin(angle), 1/2 top width x cos(angle)) - that gets the top right corner point.
Continue around the rectangle using the sin and cos of the angles and widths as appropriate
As a test: Check you made it back to the starting point
/* rcx = center x rectangle, rcy = center y rectangle, rw = width rectangle, rh = height rectangle, rr = rotation in radian from the rectangle (around it's center point) */
function toRectObjectFromCenter(rcx, rcy, rw, rh, rr){
var a = {
x: rcx+(Math.sin((rr-degToRad(90))+Math.asin(rh/(Math.sqrt(rh*rh+rw*rw)))) * (Math.sqrt(rh*rh+rw*rw)/2)),
y: rcy-(Math.cos((rr-degToRad(90))+Math.asin(rh/(Math.sqrt(rh*rh+rw*rw)))) * (Math.sqrt(rh*rh+rw*rw)/2))
};
var b = {
x: a.x+Math.cos(rr)*rw,
y: a.y+Math.sin(rr)*rw
};
var c = {
x: b.x+Math.cos(degToRad(radToDeg(rr)+90))*rh,
y: b.y+Math.sin(degToRad(radToDeg(rr)+90))*rh
};
var d = {
x: a.x+Math.cos(degToRad(radToDeg(rr)+90))*rh,
y: a.y+Math.sin(degToRad(radToDeg(rr)+90))*rh
};
return {a:a,b:b,c:c,d:d};
}

Resources