//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
Related
Well, I'm continuing this question without answer (Smoothing random noises with different amplitudes) and I have another question.
I have opted to use the contour/shadow of a shape (Translating/transforming? list of points from its center with an offset/distance).
This contour/shadow is bigger than the current path. I used this repository (https://github.com/n-yoda/unity-vertex-effects) to recreate the shadow. And this works pretty well, except for one fact.
To know the height of all points (obtained by this shadow algorithm (Line 13 of ModifiedShadow.cs & Line 69 of CircleOutline.cs)) I get the distance of the current point to the center and I divide between the maximum distance to the center:
float dist = orig.Max(v => (v - Center).magnitude);
foreach Point in poly --> float d = 1f - (Center - p).magnitude / dist;
Where orig is the entire list of points obtained by the shadow algorithm.
D is the height of the shadow.
But the problem is obvious I get a perfect circle:
In red and black to see the contrast:
And this is not what I want:
As you can see this not a perfect gradient. Let's explain what's happening.
I use this library to generate noises: https://github.com/Auburns/FastNoise_CSharp
Note: If you want to know what I use to get noises with different amplitude: Smoothing random noises with different amplitudes (see first block of code), to see this in action, see this repo
Green background color represent noises with a mean height of -0.25 and an amplitude of 0.3
White background color represent noises with a mean height of 0 and an amplitude of 0.1
Red means 1 (total interpolation for noises corresponding to white pixels)
Black means 0 (total interpolation for noises corresponding to green pixels)
That's why we have this output:
Actually, I have tried comparing distances of each individual point to the center, but this output a weird and unexpected result.
Actually, I don't know what to try...
The problem is that the lerp percentage (e.g., from high/low or "red" to "black" in your visualization) is only a function of the point's distance from the center, which is divided by a constant (which happens to be the maximum distance of any point from the center). That's why it appears circular.
For instance, the centermost point on the left side of the polygon might be 300 pixels away from the center, while the centermost point on the right might be 5 pixels. Both need to be red, but basing it off of 0 distance from center = red won't have either be red, and basing it off the min distance from center = red will only have red on the right side.
The relevant minimum and maximum distances will change depending on where the point is
One alternative method is for each point: find the closest white pixel, and find the closest green pixel, (or, the closest shadow pixel that is adjacent to green/white, such as here). Then, choose your redness depending on how the distances compare between those two points and the current point.
Therefore, you could do this (pseudo-C#):
foreach pixel p in shadow_region {
// technically, closest shadow pixel which is adjacent to x Pixel:
float closestGreen_distance = +inf;
float closestWhite_distance = +inf;
// Possibly: find all shadow-adjacent pixels prior to the outer loop
// and cache them. Then, you only have to loop through those pixels.
foreach pixel p2 in shadow {
float p2Dist = (p-p2).magnitude;
if (p2 is adjacent to green) {
if (p2Dist < closestGreen_distance) {
closestGreen_distance = p2Dist;
}
}
if (p2 is adjacent to white) {
if (p2Dist < closestWhite_distance) {
closestWhite_distance = p2Dist;
}
}
}
float d = 1f - closestWhite_distance / (closestWhite_distance + closestGreen_distance)
}
Using the code you've posted in the comments, this might look like:
foreach (Point p in value)
{
float minOuterDistance = outerPoints.Min(p2 => (p - p2).magnitude);
float minInnerDistance = innerPoints.Min(p2 => (p - p2).magnitude);
float d = 1f - minInnerDistance / (minInnerDistance + minOuterDistance);
Color32? colorValue = func?.Invoke(p.x, p.y, d);
if (colorValue.HasValue)
target[F.P(p.x, p.y, width, height)] = colorValue.Value;
}
The above part was chosen for the solution. The below part, mentioned as another option, turned out to be unnecessary.
If you can't determine if a shadow pixel is adjacent to white/green, here's an alternative that only requires the calculation of the normals of each vertex in your pink (original) outline.
Create outer "yellow" vertices by going to each pink vertex and following its normal outward. Create inner "blue" vertices by going to each pink vertex and following its normal inward.
Then, when looping through each pixel in the shadow, loop through the yellow vertices to get your "closest to green" and through the blue to get "closest to white".
The problem is that since your shapes aren't fully convex, these projected blue and yellow outlines might be inside-out in some places, so you would need to deal with that somehow. I'm having trouble determining an exact method of dealing with that but here's what I have so far:
One step is to ignore any blues/yellows that have outward-normals that point towards the current shadow pixel.
However, if the current pixel is inside of a point where the yellow/blue shape is inside out, I'm not sure how to proceed. There might be something to ignoring blue/yellow vertexes that are closer to the closest pink vertex than they should be.
extremely rough pseudocode:
list yellow_vertex_list = new list
list blue_vertex_list = new list
foreach pink vertex p:
given float dist;
vertex yellowvertex = new vertex(p+normal*dist)
vertex bluevertex = new vertex(p-normal*dist)
yellow_vertex_list.add(yellowvertex)
blue_vertex_list.add(bluevertex)
create shadow
for each pixel p in shadow:
foreach vertex v in blue_vertex_list
if v.normal points towards v: break;
if v is the wrong side of inside-out region: break;
if v is closest so far:
closest_blue = v
closest_blue_dist = (v-p).magnitude
foreach vertex v in yellow_vertex_list
if v.normal points towards v break;
if v is the wrong side of inside-out region: break;
if v is closest so far:
closest_yellow = v
closest_yellow_dist = (v-p).magnitude
float d = 1f - closest_blue_dist / (closest_blue_dist + closest_yellow_dist)
Here is point collection of polygons
<Polygon Points="24,188,24,183,25,176,26,172,29,166,33,160,38,155,44,151,50,148,54,147,61,146,67,146,74,147,78,148,84,151,90,155,95,160,99,166,102,172,103,176,104,183,104,188" Stroke="Black" StrokeThickness="1" />
<Polygon Points="568,263,520,263,520,256,521,253,523,249,526,245,531,241,536,239,540,238,548,238,552,239,557,241,562,245,565,249,567,253,568,256,568,263" Stroke="Black" StrokeThickness="1" />
that gives me below shapes.
I need to check the shape is a semicircle or not?
Please anyone can guide me to determine. Is it semicircle?
I will only get collection before drawing only I should determine the shapes. It can be any(Rectangle, Line, Semicircle, curve etc.)I am able to find a rectangle, triangle and lines shape from point collection.
like for a rectangle, I am checking its opposite faces should be equal and inside angle should be 90 degrees.
public bool IsRectangle()
{
var pointColl = polygon.PointCollection;
bool isRightAngle = false;
if (polygon == null || pointColl == null)
{
return false;
}
if (pointColl.Count == 5)
{
double length1 = (pointColl[0] - pointColl[1]).LengthSquared;
double width1 = (pointColl[1] - pointColl[2]).LengthSquared;
double length2 = (pointColl[2] - pointColl[3]).LengthSquared;
double width2 = (pointColl[3] - pointColl[0]).LengthSquared;
if ((length1 == length2 && length1 != 0) && (width1 == width2 && width1 != 0))
isRightAngle = CalculateAngle(polygon);
}
else
{
isRightAngle = false;
}
Can I write something like this for a semicircle or circular shape detection?
Thanks in advance.
What defines a shape as being a semicircle?
In the true sense of the word, neither of your shapes are semi-circles as they are both composed of straight line segments.
How many points does a shape need to be considered as a semi-circle (is triangle sufficiently round enough). What is the margin of error of each point on the circumference (some percentage of the radius) before a shape is no longer considered to be semi-circular.
Some pseudo code for you ...
Given a collection of n points P1, P2 .. Pn
For each pair of points, calculate the distance between them.
The two points with the maximum distance between them (Pa & Pb) are considered to be the diameter (flat side) of the semi circle.
The centre point of the semi-circle is the mid point between Pa and Pb.
The distance from Pa & Pb to the centre point is radius R.
For each remaining point in the collection, calculate the distance to the centre point.
If this distance lies within (1 +/- e) * R for all points, then the shape is a semi-circle. The value of e is left for you to define.
Note that this method will work whatever the orientation of the semi-circle. If you need something more specific then also check the slope of the line from Pa to Pb.
Algorithm:
1) Take 3 points from polygon.
2) Estimate circle from them using this method (or any other).
3) Check if other points from given poligon are placed on the estimated circle.
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
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
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.