I got a problem to solve. Look at the picture:
Image.
Red filled Ellipse is an obstacle.
Black dots are beginning and end of "road".
Blue line, is shortest way from one point to another.
I draw obstacles using mouse (mouse click creates ellipse), then i put in cords of start and the end, and then i use DrawLine to draw line from point to point. The question here is, how can i check or count, how many pixels of line, goes trough obstacle?
I thought of putting every pixel color in a 2D array before drawing the line, and then check it somehow on the numbers, counting shortest way from point to point, and checking how many 255's (obstacle number) would it meet in that array? As you see, i can create obstacle that way, so line will go trough the middle, just some part of it, or even next to it. I am simply lacking any idea how to do that. I need it, so i could rate every "road". More it goes trough obstacle, the less rate it gets.
Any ideas? Any algorithm?
Using the equations of the ellipse and the line, find the intersection points of the line with the outline of the ellipse (there may be 2, 1 or no intersections). You can find a worked example of this here.
If there are indeed 2 intersection points, use the distance formula to calculate the distance between them.
Related
I'm still making the game about tower building using Unity and now I have problem that have haunted me for about week now.
Game mechanic for losing is that there is line which goes up at a certain speed and when it goes above the tower, game should end. I'm wondering is there any way of checking highest objects highest point(because of rotated objects and irregularly stacked objects)?
There's a few ways to achieve this:
1) You can shoot a bunch of rays down from high up in the sky. Find all the hit.point positions and then loop through the points and store which building is the highest.
2) Another would be for each block of your building that is added - keep it as a child of an Empty Building gameObject. Then all you need to do is see which Building gameObject has the most children and you know it's the tallest. This assumes all blocks are the same size in Y and then you can easily calculate the height with highestChildCount * blockSizeY
3) Another way to do it would be to use the point in the line that is traveling up. Shoot a ray out of that point to the left and right. If it is hitting a building then the game continues. If it doesn't hit anything the game is over. This is the simpliest as it doesn't require calculation of any heights and your buildings can be made any way you like as long as they have colliders on it for the ray to hit. <--- This is likely the best method for what I'm hearing you asking.
(Note. I might have some spelling mistakes in the naming of methods so proofread before copy-pasting)
Since your are using a line, you might want to find the bounding box of an object. I have never tried the bounding box method so it might not work. The second method uses a little bit of math. If your line is vertical, then finding the highest point is easy. All you need to do is find the y position of the object and add half the y-scale to find the highest point. Note it will only work if the transform origin of the object is at the center. If the origin is at the bottom of the line you will have to add the full y-scale value. If its one third the way up, then only 2 thirds the y-scale value. I think you get the idea. This rule apples for the next condition too. If your line is at an angle, this is where it gets a little bit more complicated. We need to find the absolute value of the rotation in which the line is rotated at. Make sure the line is rotated at less than a 90 degree angle from being vertical. After this, we need to know the length of the line. Imagine a right triangle that the line itself is the hypotenuse, the base is the distance between the farthest left point of the line to the farthest right on the line(or other way around), and the distance from the lowest point of the line to the highest point of the line being the actual height of the triangle. Since we know the angle the line is rotated at and the length of the line, we need to figure out the ratio between the side opposite to the angle that represents the rotation the the hypotenuse(aka the length of the line) and the hypotenuse. This always stays the same if the rotation is the same for all right triangles. Because of this why use mathf.sin(), the rotation of the line. Remember to convert the rotation value(which is stored in degrees) to radians. This can be done by multiplying the rotation value by mathf.deg2rad. Once we know the sin, we multiply the length by the sin value that is outputted. Now we know how long the distance from the bottom to the top of the line is. Again, if the origin is the middle we add the y-position to half the value we get from the previous calculations. If it is in the bottom then the y-position plus the whole value we get from the previous calculations. Same rule as before. I am also quite new to Unity, only a little over a year of experience so there may be fallacies in my answer. Hope it helps. :)
I'm trying to write some image detection code for a pick and place machine. I'm new to OpenCV and have been going through a lot of examples - but still ahve two outstanding questions. The first one I think I have a solution for but I'm lost on the second.
I'm trying to detect the offset and angle of the bottom of a part. Essentially, how far is the object from the cross (just an indicator of the center of the frame), and what the angle of rotation the part has about the part's center. I've used filters to show the pads of the components.
I'm pretty sure that I want to implement something like this http://felix.abecassis.me/2011/10/opencv-bounding-box-skew-angle/ - but I'm not sure how to translate the code into C# (http://www.emgu.com/wiki/index.php/Main_Page). Any pointers would be helpful.
One issue is if the part is smaller than the needle that's holding it and you can see both the part and the needle.
The square bit is the part I want to detect. The round part is part of the needle that is still exposed. I've got no clue how to approach this - I'm thinking something along the lines of detecting the straight lines and discarding the curved ones to generate a shape. Again, I'm interested in the offset from the center and the angle of rotation.
First you should detect every Object with findContours. Then you can use the minimum area rectangle function on every found contour. I assume you know the size and coordiantes of your cross so you can use the Center Coordinates of the MCvBox2D to get the Offset to it. Furthermore you can read the angle property of the box so it should fit your purpose.
For the second part i would try to fit a least square reactangle. The round part seems to be very small compared to the square one so maybe it will work.
Maybe the Detection of Quadrilaterlas in the AForge Library could help you too.
Edit:
To merge your the contours i would try something like this:
Rectangle merged = New Rectangle(New Point(img.Width, img.Height), New Size(0, 0)); //img is your binarized image
Contour<Point> Pad_contours= img.FindContours(CvEnum.CHAIN_APPROX_METHOD.CV_CHAIN_APPROX_SIMPLE,CvEnum.RETR_TYPE.CV_RETR_LIST);
while(Pad_contours !=null)
{
if(Pad_contours.Area <Pad_Area_max &&Pad_contours>Pad_Area_min)//Filter Pads to avoid false positive Contours
{
//Merge Pad contours into a single rectangle
if(merged.Height >0)
merged.Bottom=Math.Max(merged.Bottom,Pad_Contours.BoundingRectangle.Bottom);
else
merged.Height = contours.BoundingRectangle.Height;
merged.Top=Math.Min(merged.Top,Pad_Contours.BoundingRectangle.Top);
merged.Left=math.Min(merged.Left,Pad_Contours.BoundingRectangle.Left);
if(merged.Width>0)
merged.Right=Max(merged.Right,pad_Contours.BoundingRectangle.Right);
else
merged.Width=Pad_Contours.BoundingRectangle.Width;
}
//get next Pad
If(Pad_contours.VNext==null)
Pad_contours=Pad_contours.HNext;
else
Pad_contours = Pad_contours.VNext;
}
The rectangle "merged" should enclose all your Pads now. The problem is you wont get an angle this way because the rectangle is always vertically 90°. To solve this I would iterate through the contours like shown above and store every point of every contour in an extra datacontainer. Then I would use the minimum area rectangle function mentioned above and apply it on all gathered points. This should give you a bounding rectangle with an angle property.
I have 2 sets of parallel and when their angles differ, I end up with a intersection on one end, and an open gap on the other. I have taken care of the interesection, by setting the endPoint of line1 to the same as the starting point for line2. Like so...
This is the code I have so far for adding the lines....
for (int i: 0; i < myLines.size() ; i++) {
Line myLine = checkforInterection( myLines, i);
myCanvas.Children.Add(myLine);
myCanvas.Children.Add(createParallel(myLine));
}
I would like to close the gap on the rightHand side by having a curved line that can span the distance. What is the best way of going about this?
Use a BezierSegment to obtain a smooth curve. The start and end points should be the start and end points of the straight line. The control point may require some experimentation to get looking like you want it to, since that's more of a preference, but setting the control point to the projected intersection of the two lines the curve is attached to would make a good starting point. If you do want to tweak it after that, you should move it along the line from the projected intersection to the actual intersection of the two lines on the left.
For clarity:
Start off with the start and end points at the green dots. Start off with the control point at the intersection of the red line, and, if you want to adjust it, move it along the blue line to keep a symmetric curve.
Note: using the intersection of the red lines will give you a perfectly smooth transition; other points won't.
Is there anyway that allows me to find all the intersection points between a line and a grid? ( The intersection circles are not drawn to scale with each other, I know)
A brute force way is to compute very intersection for the x-y grid with the line, but this algorithm is awfully inefficient (O(m*n), where m is the number of x grid and n is the number of y grid).
I'm looking for a better algorithm on this.
Sounds like you need a Digital Differential Analyzer or Bresenham's line algorithm. Bresenham is the same algorithm used to draw lines on a bitmap; in this case, coloring a pixel is equivalent to checking for collisions in that square.
I'm not sure I really understand the question. Is this what you're looking for by any chance?
If the grid is axis aligned:
find out the line equation
calculate the intersection points
directly using either the grid
line's x or y as a fixed variable
If the grid is regular, the distance between the intersections with each horizontal line will be the same. The same also goes for the vertical lines. You could just do a simple iterative algorithm with dx and dy in that case.
Algorithm:
The grid consists out of walls.
A wall is of/in a certain dimension: (Vertical, Horizontal, Depth)
The wall dimensions intersect forming cells (in final dimension)
The line intersects the walls primarly in their own dimension.
The solution is to view the problem as: How to intersect a line with a wall in it's own dimension.
The solution is to slide across the line from wall to wall, switch dimensions as necessary.
The sliding across the line happens such that the nearest wall is always chosen as the next destination.
The sliding from wall to wall in it's own dimension is constant/always the same.
The intersection of the line and the walls is different per dimension.
This ultimately decides the order of the wall intersections.
The solution is therefore to:
Phase 1: Initialization
Compute Dimension.IntersectT
Compute Dimension.SlideT
Phase 2: Start sliding from origin towards destination selecting nearest wall:
Dimension.T := Dimension.IntersectT
while ? end condition ?
Select smallest Dimension.T
Update selected Dimension.T += Dimension.SlideT
end
The difficulty lies in computing the Ts.
Bye,
Skybuck.
I have some problems getting an algorithm for my game to work and hope someone here can help me. Google didn't seem to be a good help as most solutions just work for full tiles.
In the game units can occupy different positions inside a tile, i.e. they can be in the upper left corner, center, bottom right, ... position of tile (2/3), i.e. (2.2/3.1), (2.5/3.5), (2.8/3.9).
If they move from position (2.2/3.1) to (5.7/4.1) i require a check to see if there is an obstacle in the path.
My current algorithm is:
Starting from (2.2/3.1)
Calculate the angle of the movement (i.e. 70 degree)
Move 0.1 steps in that direction
Check which tile i'm on (floor(p.X)/floor(p.Y))
Repeat from 2
This algorithm works but to me it doesn't look very efficient as an obstacle can be only a full tile, not a part of a tile (units don't collide). If i increase the step size i begin to miss tiles that are only crossed slightly (i.e. you only cross the lowest left corner). Even with a step size of 0.1 it's still possible to miss an obstacle.
I tried to find a solution to take the sub map (all tiles with the corners (floor(start.X)/floor(start.Y)) and (ceil(start.X)/ceil(start.Y)), move through every tile and check mathmatically if it gets crossed. Sadly i seem to lack the required math knowledge for this check.
My last idea was to take all 4 borders of a tile as a line and do line-intersection but that seems to be slower than my original approach.
Any hints?
Thanks.
Instead of tracing the path by stepping along the line - you want to jump right to the next possible tile (the border). This can be calculated fairly simply. I will use your sample numbers above.
Calculate the line eqn (y= .286x + 2.471)
You are starting on tile 2,3 and moving towards tile 5,4. So calculate the y value when x goes to 3 (the border to the tile immediately to the right). It is 3.329.
Then calculate the x value when y goes to 4 (the border to the tile immediately above). It is 5.346.
Starting at 2,3 and moving right gets to 3,3.329. Moving up gets to 5.346,4. You intersect on the right(moving 2 -> 3 on x doesn't move a tile on y). You don't intersect above until you are on tile 5 in the x.
The tile calculated in 4 becomes your new comparison (3,3). Repeat from step 2.
This process only incurs one calculation per tile moved (regardless of your precision or how big the tiles are) and is exact. Note that the values calculated can be stored and reused instead of blindly calculating both intersections over and over. In the above we know (step 4) that we don't move up a tile until x=5. So the entire path can be inferred without another calculation (2,3 -> 3,3 -> 4,3 -> 5,3 -> 5,4).
It is also possible to precalculate all the transistions instead of doing them stepwise although this would only be beneficial if you always need the entire path (you don't since you want to stop processing once you find an obstacle).
Two caveats. Be careful about signs and which way the line is going - many a bug happen by not paying close attention to negative slopes. Also, using reals you almost never will cross diagonally (two borders at once) but you should be aware of it (handle it in the code) just in case.
There is a name for this method but I can't remember it off the top of my head. I believe it might be from Game Programming Gems series but maybe someone else can provide a better reference.