Calculate Width and Height from 4 points of a polygon - c#

I have four points which form a rectangle, and I am allowing the user to move any point and to rotate the rectangle by an angle (which rotates each point around the center point). It stays in near-perfect Rectangle shape (as far as PointF precision allows). Here's an example of my "rectangle" drawn from four points:
However, I need to be able to get the width and height between the points. This is easy when the rectangle is not rotated, but once I rotate it my math returns the width and height shown by the red outline here:
Assuming I know the order of the points (clockwise from top-left for example), how do I retrieve the width and the height of the rectangle they represent?

If by "width" and "height", you just mean the edge lengths, and you have your 4 PointF structures in a list or array, you can do:
double width = Math.Sqrt( Math.Pow(point[1].X - point[0].X, 2) + Math.Pow(point[1].Y - point[0].Y, 2));
double height = Math.Sqrt( Math.Pow(point[2].X - point[1].X, 2) + Math.Pow(point[2].Y - point[1].Y, 2));

Just use the algorithm for the distance between two points.
If you have points A, B, C, D, you will get two distances.
sqrt((Bx-Ax)^2 + (By-Ay)^2) will be equal to sqrt((Dx-Cx)^2 + (Dy-Cy)^2)
sqrt((Cx-Bx)^2 + (Cy-By)^2) will be equal to sqrt((Ax-Dx)^2 + (Ay-Dy)^2)
Pick one to be your width and one to be your height.

Let's say top-most corner is A. Then name other edges anti-clockwise as ABCD
width of rectangle = distance between A and B
height of rectangle = distance between B and C
Formula to find distance between two points say A(x1,y1) and B(x2,y2) is:
d = sqrt( (x2 - x1)^2 + ( y2 - y1)^2 )
where d is distance.

Related

Calculating area of intersection between two rectangles

//C# Console Application Home assignment
I have 8 coordinates like this:
(x1, y1) (x2, y2) ... (x8, y8)
//The first 4 coordinates are for 1st rectangle
//The rest for 2nd rectangle
I store the values like this:
int[,] array2D = new int[8,2];
array2d[0,0] = x1;
array2d[0,1] = y1;
array2d[1,0] = x2;
array2d[1,1] = y2;
//...
array[7,0] = x8;
array[7,1] = y8;
I want to calculate area of intersection between those coordinates.
I already have this code to check when the rectangles aren't overlapping (it works):
if (!(array2D[2, 1] <= array2D[4, 1] && array2D[0, 1] >= array2D[6, 1]
&& array2D[2, 0] >= array2D[4, 0] && array2D[0, 0] <= array2D[6, 0]))
{
//not overlapping
}
{
//overlapping
}
I need help with algorithm to get the area of intersection.
NOTE: Coordinates can have negative values.
I would use the Rectangle.Intersect method from System.Drawing. There's no point in reinventing the wheel... ;-)
Returns a third Rectangle structure that represents the intersection
of two other Rectangle structures. If there is no intersection, an
empty Rectangle is returned.
The simplest solution is to first note that intersection of rectangles (or indeed anything) is commutative. That is, if I want to intersect A, B and C, I can intersect A and B and then intersect that with C OR intersect B and C and then intersect the result with A.
Therefore, store a rectangle and intersect it with successive rectangles. So you start with the first rectangle, intersect that with the second. Then you intersect the result with the third and so on.
This will give you the intersection rectangle, so you can simply compute the area.
Update
Your problem seems to mainly be your format for your rectangles. Namely, the 4 vertices defining the rectangle. This can easily be turned in to an X/Y for the top left and a width and height by taking the top left to be your first vertex (obviously), the width and height are the difference between this vertex and the bottom right

find the center point of coordinate 2d array c#

Is there a formula to average all the x, y coordinates and find the location in the dead center of them.
I have 100x100 squares and inside them are large clumps of 1x1 red and black points, I want to determine out of the red points which one is in the middle.
I looked into line of best fit formulas but I am not sure if this is what I need.
Sometimes all the red will be on one side, or the other side. I want to essentially draw a line then find the center point of that line, or just find the center point of the red squares only. based on the 100x100 grid.
List<Point> dots = new List<Point>();
int totalX = 0, totalY = 0;
foreach (Point p in dots)
{
totalX += p.X;
totalY += p.Y;
}
int centerX = totalX / dots.Count;
int centerY = totalY / dots.Count;
Simply average separately the x coordinates and the y coordinates, the result will be the coordinates of the "center".
What if there are two or more subsets of red points ? Do you want the black point inside them?
Otherwis, if I understood your question, just give a weight of 1 to red points and 0 to blacks. Then do the weighted mean on X and Y coordinate

Calculate the coordinates in a circle

I am drawing an imaginary circle around the middle of a button.
The radius of the circle is the Height/2 if Height>Width or Width/2 if Width>Height.
Now i have to calculate which coordinates (in pixels) are in this circle.
The idea is that if e.g. the mouse cursor hovers over that circle, something happens.
Calculating each co-ordinate is overkill; just compare the distance to the center. For example:
int radius = 5; // whatever
int deltaX = originX - mouseX, deltaY = originY - mouseY;
// compare the square distance, to avoid an unnecessary square-root
if((deltaX * deltaX) + (deltaY * deltaY) <= (radius * radius)) {
// inside the circle, or on the edge
}
To avoid a little math, you could also do a quick bounding-box check, i.e. checking the rectangular region (just addition/subtraction). This can be used in combination, i.e.
check the bounding box
if it isn't in the bounding box it certainly isn't in the circle
if it is in the bounding box, do the math to compare the square-distance
You are inside the circle when this equation is satisfied:
Math.pow(mouse_pos_x-center_circle_x,2)+Math.pow(mouse_pos_y-center_circle_y,2)<Math.pow(radius,2)
The area of a a circle by definition is a group of points whose distance is equal to or less than the center.
All you must do to test if a point is within a circle is to calculate the distance between it and the center point. If this distance is smaller than the radius of the circle, the point is within the circle.
double Distance(Point p1, Point p2)
{
int x = p1.X - p2.X;
int y = p1.Y - p2.Y;
return Math.Sqrt(x * x + y * y);
}
You can use next condition:
x^2+y^2<R^2
Where R - radius,
All this points are in circle.

Need some math - Projecting Slope

I have a rectangle.
Its height (RH) is 400.
Its width (RW) is 500.
I have circle.
Its height (CH) is 10.
Its width (CW) is 10.
Its starting location (CX1, CY1) is 20, 20.
The circle has moved.
Its new location (CX2, CY2) is 30, 35.
Assuming my circle continues to move in a straight line.
What is the circle's location when its edge reaches the boundary?
Hopefully you can provide a reusable formula.
Perhaps some C# method with a signature like this?
point GetDest(size itemSize, point itemPos1, point itemPos2, size boundarySize)
I need to calculate what that location WILL be once it arrives - knowing that it is not there yet.
Thank you.
PS: I need this because my application is watching the accelerometer on my Windows Phone. I am calculating the target necessary to animate the motion of the circle inside the rectangle as the user is tilting their device.
It is 1 radius away from the boundar(y/ies).
The answer is X=270 Y=395
first define the slope V as dy/dx =(y2-y1)/(x2-x1). In your example: (35-20)/(30-20)=1.5
the line equation is
y = V * (x-x1) + y1. You are interested in the horizontal locations x at:
y= CH/2 OR y= H-CH/2
so (not code, just math)
if (y2-y1)<0:
x=(CH/2 -y1)/V +x1 10 for your example. OR
if (y2-y1)>0:
x=(H-CH/2 -y1)/V +x1 270 for your example
else (that is: y2==y1)
the upper or lower lines were not hit.
if CH/2 <= x <= W-CH/2 the circle did hit the that upper or lower side: since V>0, we use x=270 and that is within CH/2 and W-CH/2.
So the answer to your question is y=H-CH/2 = 395 , X=270
For the side lines it's similar:
(if (x2-x1)<0)
y=(CH/2 -x1)*V +y1
(if (x2-x1)>0)
y=(W-CH/2 -x1)*V +y1
else (that is: x2==x1)
the side lines were not hit.
if CH/2 <= y <= H-CH/2 the circle did hit that side at that y.
be careful with the trivial cases of completely horizontal or vertical movement so that you don't divide by zero. when calculating V or 1/V. Also deal with the case where the circle did not move at all.
Since you now asked, here's metacode which you should easily be able to convert to a real method. It deals with the special cases too. The input is all the variables you listed in your example. I here use just one symbol for the circle size, since it's a circle not an ellipse.
method returning a pair of doubles getzy(x1,y1,W,H,CH){
if (y2!=y1){ // test for hitting upper or lower edges
Vinverse=(x2-x1)/(y2-y1)
if ((y2-y1)<0){
xout=(CH/2 -y1)*Vinverse +x1
if (CH/2 <= y <= H-CH/2) {
yout=CH/2
return xout,yout
}
}
if ((y2-y1)>0){
xout=(H-CH/2 -y1)*Vinverse +x1
if (CH/2 <= y <= H-CH/2) {
yout=H-CH/2
return xout,yout
}
}
}
// reaching here means upper or lower lines were not hit.
if (x2!=x1){ // test for hitting upper or lower edges
V=(y2-y1)/(x2-x1)
if ((x2-x1)<0){
yout=(CH/2 -x1)*V +y1
if (CH/2 <= x <= W-CH/2) {
xout=CH/2
return xout,yout
}
}
if ((x2-x1)>0){
yout=(H-CH/2 -x1)*V +y1
if (CH/2 <= x <= W-CH/2) {
xout=H-CH/2
return xout,yout
}
}
}
// if you reach here that means the circle does not move...
deal with using exceptions or some other way.
}
It's easy; no calculus required.
Your circle has radius R = CW/2 = CH/2, since the diameter of the circle D = CW = CH.
In order to have the circle touch the vertical edge of the rectangle at a tangent point, you have to move the circle to the right by a distance (W - (CX1 + CW/2))
Likewise, the circle will touch the bottom edge of the rectangle at a tangent point when you move it down by a distance (H - (CY1 + CH/2)).
If you do this in two separate translations (e.g., first to the right by the amount given, then down by the amount given or visa versa), you'll see that the circle will touch both the right hand vertical and the bottom horizontal edges at tangent points.
When the moving circle arrives at a wall (boundary) then it will be tangent at one of four points on the circle, call them N, S, E, and W. You know their initial coordinates.
The points travel in a line with a slope known to you: m=(y2-y1)/(x2-x1); where in your example (x1, y1) - (20,20) and (x2, y2)= (30, 35).
Your problem is to find the trajectory of the first point N, S, E, or W which reaches any wall. The trajectory will be a line with slope m.
You can do this by adding (or subtracting) the direction vector for the line to the point N, S, E, or W, scaled by some t.
For example, N is (20, 15). The direction vector is (x2-x1,y2-y1) = (10, 15). Then (20, 15) + t * (10, 15) will hit the boundary lines at different t's. You can solve for these; for example 20 + t*10 = 0, and 20 + t*10 = 400, etc.
The t that is smallest in magnitude, over all four trajectories, gives you your tangent point.
Not sure its calculus..wouldn't it just be the following:
if y >= 390 then it reached the top edge of the rectangle
if x >= 490 then it reached the right edge of the rectangle
if y <= 0 then it reached the bottom edge of the rectangle
if x <= 0 then it reached the left edge of the rectangle

Drawing Images to fit circle

I'm making an inventory screen for a game I'm working on, and I'd like to be able to draw a series of panels representing each item in the inventory. I want to be able to fit those panels on a circular path.
Here's a mock up I made of what I mean
http://fc02.deviantart.net/fs70/f/2010/280/7/2/khmp_magic_menu_concept_by_magna_alphamon-d30a7em.png
basically I'd like to be able to, give a radius, a center point, and the y co-ordinate to start drawing at, draw this series of panels so they align with the path of the circle like in the image.
Computing the y dimension is easy, its just the startposition y + panel height * panel index, but I'm unsure how to compute the x for a variable radius/center point circle.
Any help would be appreciated.
This is in C#, but something similar in C/C++ will be fine as long as I can convert it
Thanks in advance
EDIT: To calirify, y's position is relative to the top or bottom of the screen and is independent of the circle. If a given y does not map to a point on the circle, then I'll discard that point and not draw the panel.
While ideally I'd like to be able to use any elliptical shape (given two radii), a circle would be good too
Let cx, cy be the coordinates of the center point. Let r be the radius of the circle. Let y be the drawing y-coordinate and x, the x-coordinate. You observe that y = cy + panel height * panel index. By the magic of right triangles, this means that x^2 + y^2 = r^2. Solving for x, we get x = cx + sqrt(r^2 - (y-cy)^2).
EDIT: Converting to code:
#include <math>
float ordinate(float cx, float cy, float r, float y) {
// assumes cx and cy are in the same coordinate system as x and y
// assumes the coordinate origin is in the lower left corner.
return cx + sqrtf(powf(r,2) - powf(y-cy,2));
}
I'm dumb. After seeing Eric's answer, I remembered I can just rearrange and solve the equations of a circle or elipse as necessary.
Thanks
You can use a rotational matrix for this. Here is a simple algorithm that finds the next point {x, y} such that it is rotated theta radians around a circle. You can start with the first item at x=radius and y=radius (wherever really, just a point that you know will contain an item), and then just continue to increment theta as you loop through your items.
Point Rotate(int x, int y, float theta)
int x_p = (x * Math.Cos(theta)) - (y * Math.Sin(theta));
int y_p = (y * Math.Cos(theta)) + (x * Math.Sin(theta));
return new Point(x_p, y_p);
end
On a side note; I always preferred "Bolt1, Bolt2, Bolt3" to "Thunder, Thundara, Thundaga" =P

Categories