how to convert polyline to bitmap in matlab - image

I have a polyline, given as 2 vectors X, Y, of coordinates, both vectors of the same length, and X(i) corresponds to Y(i).
I need an easy way to create a boolean matrix, that has 1 where a polyline passes, and 0 where it doesn't.
is there a nice way of doing this?
I thought about poly2mask, but doc says it closes the polygon, which is not what i am looking for
Thanks

you can extend the line to the left and right edge of the graph. just copy the row numbers and change column to first and last. then add top-left and top-right corners into the coordinate array. use poly2mask to draw that huge polygon. then remove everything except the last line of the polygon. finally trim the left and right ends.
you can also use line to draw lines.

Related

Algorithm to find raycast to "special" capsule

I have two circles joined together like this:
And I have a point inside the shape, and I would like to cast a ray in a direction from that point onto the shape. In order to retrieve the casted position on the edge of the shape.
My first thought will be to raycast with the 2 segments joining the 2 circles. And if there is no success hit, I'll raycast with the 2 circles and take the farthest hit position. Is there a better solution? More efficient computation-wise?
Thank you for your answers
Is suppose that you have direction vector of ray D=(dx, dy) and source point is inside of capsule
If you have central axis, use it's direction vector A, otherwise get direction vector S, S of any segment.
At first decide what segment might be intersected: get cross product A x D or S x Dand look at it's sign. Positive sign denotes that you have to check only intersection with the "left" segment, negative one - intersection with the "right" segment.

What is the fastest way to determine all cells in a regular 2d grid that are touched by a line segment

I want to find all grid tiles that touch or contain parts of a given finite line segment. The grid is a 2d regular grid, thus I can deduce any tile's center from a tile position (row,colum) and vice versa I can calculate a tile position from a given floating point coordinate with two fast integer divisions. The tiles are quadratic e.g. 0.25x0.25 with 0.25 defined as the tile width.
Now I need to determine all tiles that are touched by a given line segment
(two 2d points given in floats define a line segment).
My current approach is to split the segment into equidistant points with a distance half the tile-width (greetings to shannon). Than I collect all tiles that contain the given points and remove duplicate tiles.
Since this operation is the most performance critical part of my program I was wondering whether there is a faster approach to calculate the respective tiles.
Edit: As Patricia noted my current approach does not result in a complete tile set since a tile that is only touched to a very small fraction by the line would not be included. This is acceptable for me since in my case speed is more important than accuracy, but should be noted none the less.
To make it clearer: I want all red tiles in the image but I can spare e.g. the rose ones if I gain speed for that.
Your problem basically comes down to drawing a line segment on a raster image.
If you can spare the pink tiles, use the Bresenham's algorithm. Otherwise, use a similar technique as is used to draw antialiased lines:
You start at the tile which contains one end of the segment and put it to the queue. Then follow with a regular BFS algorithm, putting only tiles which intersect with the segment to the queue:
In one iteration take one tile from one end of the queue, this is your next found intersecting tile. Then find all its neighbors, and put those which intersect with the segment (it's enough to test intersection with a line in this case) to the other end of the queue. The neighbors must be chosen according to the direction of the line. If it goes down-right, use the down, right and down-right tiles as neighbors, if it goes up, use only up neighbors, and so on.
You end when you reach the tile which contains the other end of the segment.
Test the gradient of the line, against the tile diagonal with the same gradient sign. If it is steeper than a tile diagonal, exchange x and y coordinates in what follows.
If the gradient is shallower than the tile diagonal, the line touches or crosses a given tile, and the tile does not contain an end point, at least one of its intersections with the edges of the tile must be on an x boundary of the tile.
For each line end, collect the tile containing or tiles touching the end point.
For each x coordinate that is a tile edge between the two end point x coordinates, calculate the line's y coordinate. Collect the tiles touching that point.
I think this can all be done with at most a couple of divisions to do the gradient check. The main process is all multiplication, addition, and comparisons.
Given the line segment's end points, you can easily compute the equation of the line, y = mx + b. And given the length of the segment, you can compute the parametric form:
x = x0 + ft
y = y0 + gt
Given either of those equations, you can calculate the y coordinate for any given x coordinate on the line. So ...
Starting at the first end point of the line, you know that the cell containing that point is in the set. You know the x coordinates for each cell, so you can quickly determine the y coordinate at which your line segment crosses the cell boundary. If that y coordinate is above the cell's top y coordinate, then the line segment intersects the cell above the starting cell. (Substitute "below" if the line's slope is "down.)
If you repeat that test for each cell boundary along the x axis, you will get the list of all cells that the segment crosses.

How to erase an area delimited by a line segment and a block of colors?

Given the picture below:
The position of A and B is known, the rest of the picture is just raw pixel data (only red and white pixels). What algorithm can I use to erase the part to the right of AB?
Having two points define a line. The equation of line separates pixels that have to be removed. If you want to delete points in a way that new border is smoothly following the curve of the shape you need some way to interpolate the shape border (based on the information of other points from the border). This interpolation have to pass trough two black points. Now, if you have interpolation you can calculate the interpolation curve between two black points and set to white all points right from the curve. I can suggest to use at least one more point from the curve and use some cubic spline interpolation.
EDIT:
Based on you comment.
Then the algorithm is simple: Keep a pointer that starts from lower point (A) and moves along the border (A') until it reaches the other point. This can be done by checking the neighbors of current pointer location and comparing colors. Now, when you pointer moves remove the line of red points from pointer (A') to line (blue) defined between to points A-B (in green). There is a pointer position when the row is the same as the other black point (e.g A' and B are on the same row). Then start a new pointer from B point in the same way tracing the border and remove the red pixels between two pointers A' and B'.
You need to draw the line from A to B and then start a flood fill on one of the red pixels to the right of the line.

Method for combining tiled squares defined as points into vectors

If I tile squares, and the squares can be defined by their coordinates, how can I simplify shapes made of multiple squares into vectors that define each edge of the entire shape? Pseudo-code or general terms are fine.
The first thing I can think of is (probably not the most efficient way) :
1) Get the bounding box of your entire tiling - which is min(x), min(y) to max(x), max(y) for all x and y of your tiles
2) For every row, start with STATE==EMPTY, iterate over each column : STATE changes to FULL when you hit a square, and EMPTY when you find a hole. Every time STATE goes from EMPTY to FULL, save the left hand line segment of that square and every time STATE goes from FULL to EMPTY, save the right hand line segment of that square.
3) Repeat above in the Y axis
Now you have a set containing only the outermost line segments, you can combine those that are co-linear etc and get the overall shape.
This will work for non-convex shapes and also if you have holes in your tiling.

Visiting the points in a triangle in a random order

For a right triangle specified by an equation aX + bY <= c on integers
I want to plot each pixel(*) in the triangle once and only once, in a pseudo-random order, and without storing a list of previously hit points.
I know how to do this with a line segment between 0 and x
pick a random point'o' along the line,
pick 'p' that is relatively prime to x
repeat for up to x times: Onext = (Ocur + P) MOD x
To do this for a triangle, I would
1. Need to count the number of pixels in the triangle sans lists
2. Map an integer 0..points into a x,y pair that is a valid pixel inside the triangle
I hope any solution could be generalized to pyramids and higher dimensional shapes.
(*) I use the CG term pixel for the pair of integer points X,Y such that the equation is satisfied.
Since you want to guarantee visiting each pixel once and only once, it's probably better to think in terms of pixels rather than the real triangles.
You can slice the triangles horizontally and get bunch of horizontal scan lines. Connect the scan lines together and you have converted your "triangle" into a long line. Apply your point visiting algorithm to your long chain of scan lines.
By the way, this mapping only needs to happen on paper, all you need is a function that can return (x, y) given (t) along the virtual scan line.
Edit:
To convert two points to a line segment, you can look for Bresenham's scan conversion. Once you get the 3 line segments converted into series of points, you can put all points into a bucket and group all points by y. Within the same y-value, sort points by x. The smallest x within a y-value is the begin point of the scan line and the largest x within the y-value is the end point of the scan line. This is called "scan converting triangle". You can find more info if you Google.
Here's a solution for Triangle Point Picking.
What you have to do is choose two vectors (sides) of your triangle, multiply each with a random number in [0,1] and add them up. This will provide a uniform distribution in the quadrilateral defined by the vectors. You'll have to check whether the result lies inside the original triangle; if it doesn't either transform it back in or simply discard it and try again.
One method is to put all of the pixels into an array and then shuffle the array (this is O(n)), then visit the pixels in the order in the shuffled array. This could require quite a lot of memory though.
Here's a method which wastes some CPU time but probably doesn't waste as much as a more complicated method would do.
Compute a rectangle that circumscribes the triangle. It will be easy to "linearize" that rectangle, each scan line followed by the next. Use the algorithm that you already know in order to traverse the pixels of the rectangle. When you hit each pixel, check if the pixel is in the triangle, and if not then skip it.
I would consider the lines of the triangle as single line, which is cut into segments. The segments would be stored in an array where the length of the segment also stored as well as the offset in the total length of the lines. Then depending on the value of O, you can select which array element contains the pixel you want to draw at that moment based on this information and paint the pixel based on the values in the element.

Resources