How to fill a closed poly-line with equidistant horizontal lines? - c++

I need to write and algorithm that fills closed poly-line with horizontal equidistant lines.
I've done similar things with rectangles and circles, here is a code snippet for the latter:
// circle parameters: center(point(0).x, point(0).y), radius
int offsetX = point(0).x + radius;
int offsetY = point(0).y + radius;
for(int i = -radius; i < radius; i += spacing){
int ry = i;
int rx = sqrt(double(radius*radius - ry*ry));
// the parameters are pair of coordinates of the horizontal line
fl_line(offsetX - rx, offsetY + i,
offsetX + rx, offsetY + i);
}
In the case of closed poly-line the additional degree of difficulty (for me) is that the coordinates of the horizontal lines would not be extracted from a single equation (circle, height of rectangle, etc), but rather from the equations of the lines with the same "y" coordinates, which will not match continuously.
Question:
Could you provide me with some insight on how to proceed with creating an algorithm that fills closed poly-lines with horizontal lines?

This is just a special case of the scan line algorithm (designed for filling polygons): http://www.tutorialspoint.com/computer_graphics/polygon_filling_algorithm.htm
Iterate y from yMin (top of your polygon) to yMax with the desired step (spacing).
For each y, find intersections with the polygon line segments, order them by their x-coordinate, connect every other pair with a line

Create a list of all edges with their lowest endpoint first. Sort the list by increasing ordinate (of the lowest endpoint).
Create an "active list" that will contain all edges that are intersected by the current horizontal.
Initialize the current horizontal position just below the lowest edge and make sure the active list is empty.
Move the horizontal upward in desired increments until the active list empties again.
Upon a move, discard from the active list the edges that will no more intersect it. Also add to it the edges that will start intersecting it (as the edges are sorted, you will search no more than needed).
Beware that an edge can be completely skipped (it can enter the active list and immediately leave it).
When the active list is up-to-date, compute all intersections and join them by an horizontal segment, left-to-right.
Note that it is possible to avoid horizontal sorting before joining the intersections in pairs, by carefully inserting the new edges where necessary. Given that the active list is usually very short, I prefer to systematically apply insertion sort.
Assuming that all active list operations take linear time in the size of the list, the total time is like O(Ne.Lg(Ne) + Ny.L), where Ne is the number of edges, Ny the number of horizontals and L the average number of intersections per horizontal (usually between 2 and 4). This is to be compared to O(Ne.Ny) for the naïve algorithm.

Related

How to determine if a point is within an polygon consist of horizontal and vertical lines only?

I want to find a best way because all coordinates are integer values and polygons consist of horizontal and vertical lines only. I think there may be a simple and fast method to do this.
From an asymptotic complexity point of view, a rectilinear polygon is not really simpler to process than a general one: O(N) without preprocessing, and O(Log N) after O(N Log N) preprocessing (but using a complicated procedure).
For the case of no preprocessing, the procedure is simple: consider every vertical side in turn and count those that cross the horizontal half-line from the given point (+1 upward, -1 downward). The point is inside if the final count is nonzero.
The status of points on the outline is application-dependent.
For rectilinear poygons with not too large integer coordinates, you can anyway do a little better, by "compressing" them. By two independent sorts on X and Y, you can obtain a mapping from X (or Y) to integer indexes in range [0,N). This gives the shrunk polygon below, of size NxN.
Now you can embed the polygon in an image and preprocess to label the pixels as inside/outside (by seed-filling). After filling two lookup-tables for coordinate conversion, you can obtain the status of any point in constant time O(1).
This will take O(N²+M) preprocessing time and storage, where M is the range of X and Y values.
Consider any polygon, not necessary convex, formed only with horizontal and vetical lines:
Take a point (I've drawn A,B,C,D) and draw horizontal and vertical lines passing through the point.
Let's take point A. You see the horizontal line through it crosses four (vertical) segments. Note one segment is at left and the others are at right.
For point B its horizontal line crosses also four segments, but two at left and two at right.
The conditions that a point must fulfill to be inside a polygon are:
At least one segment is horizontaly crossed at left of the point.
At least one segment is horizontaly crossed at right of the point.
Both numbers of crosses left, right must be odd.
Same three conditions for vertical lines.
So, in pseudocode it goes like this:
let nL = 0, nR = 0 //left/right counters
let nA = 0, nU = 0 //above/under counters
for each segment s(sx1,sy1, sx2, sy2) in polygon
if point is on segment
return true //or false, your choice
else if segment is vertical and pointY is inside of (sy1,sy2)
if pointX > min(sx1,sx2)
nL = nL + 1
else
nR = nR + 1
else if segment is horizontal and pointX is inside of (sx1,sx2)
if pointY > min(sy1,sy2)
nU = nU + 1
else
nA = nA + 1
//Check conditions
if nL > 0 and nR > 0 and nL is odd and nR is odd
return true
if nA > 0 and nU > 0 and nA is odd and nU is odd
return true
return false

Create continuous matrix of rectangles from set of rectangles

I have a set of objects(each object contains a rectangle and a value assigned to it) which is kept in a vector container.
See picture below:
I need to create a matrix by drawing horizontal and vertical lines at each y/x lower left (LL) / upper right(UR) coordinate like below:
And I need to assign value = 0 to each new empty rectangle, and to other rectangles which are inside of initial rectangles, I need to assign their old values.
I've implemented this with some naive algorithm but it works too slow when I have huge number of rectangles. My algorithm basically does the following:
- Stores all rectangles in a map container. Each element of the map contains set of rectangles with the same LL Y coordinate and they are sorted by LL X coordinate, i.e. key is LL Y coordinate.
- Stores all X/Y coordinates in set containers.
- Iterates over Y/X coordinate containers, and for each new rectangle finds out if it exists in map or not, if exists-assigns existing value to it, otherwise-assigns 0 value. I.e, for each new rectangle it looks for its LL Y coordinate in map, if such Y exists, then searches through the corresponding value(set of rectangles), otherwise-it searches in a whole map.
Is there an effective algorithm to get needed results?
For n rectangles this can be solved easily in O(n^3) time (or just O(n^2) time if at most a bounded number of rectangles intersect) by looking at the problem a different way. This should be adequate for handling up to thousands of rectangles in a few seconds.
Also, unless some other constraints are added to the problem, the latter time bound is optimal: that is, there exist inputs consisting of n non-intersecting rectangles for which O(n^2) smaller grid rectangles will need to be output (which of course requires O(n^2) time). An example such input is n width-1 rectangles, all having equal bottommost y co-ord and having heights 1, 2, ..., n.
Grid size bounds
First of all, notice that there can be at most 2n vertical lines, and at most 2n horizontal lines, since each input rectangle introduces at most 2 of each kind (it may introduce less if one or both vertical lines are also the edge(s) for some already-considered rectangle, and likewise for horizontal lines). So there can be at most (2*n - 1)^2 = O(n^2) cells in the grid defined by these lines.
The grid cell co-ordinate system
We can invent a co-ordinate system for grid cells in which each cell is identified by its lower-left corner, and the co-ordinates of an intersection of two grid lines is given simply by the number of horizontal grid lines below it and the number of vertical grid lines to its left (so that the bottommost, leftmost grid cell has co-ords (0, 0), the cell to its right has co-ords (1, 0), the cell two cells above that cell has co-ords (1, 2), etc.)
The algorithm
For each input rectangle having LL co-ords (x1, y1) and UR co-ords (x2, y2), we determine the horizontal and vertical intervals that it occupies within the new grid co-ordinate system, and then simply iterate through every cell (i, j) belonging to this rectangular region (i.e., every grid cell (i, j) such that toGridX(x1) <= i < toGridX(x2) and toGridY(y1) <= j < toGridY(y2)) with a nested for loop, recording in a hashtable that the ID (colour?) for the cell at (i, j) should be the colour of the current input rectangle. Input rectangles should be processed in decreasing z-order (implicitly at least there seems to be such an order, from your example) so that for any cell covered by more than one input rectangle, the hashtable will wind up recording whatever the "nearest" rectangle's colour is. Finally, iterate through the hash table, converting each grid co-ord pair (i, j) back to the LL and UR co-ords of the input-space rectangle that corresponds to this grid cell, and output this rectangle with the ID given by the value for this hash key.
Preprocessing
In order to accomplish the above, we need two things: a way to map input-space co-ordinates to grid co-ordinates (to determine the horizontal and vertical grid intervals for a given input rectangle), and a way to map grid co-ordinates back to input-space co-ordinates (to generate the output rectangles in the final step). Both operations are easy to do via that old workhorse, sorting.
Given any corner (x, y) of some input rectangle, the grid x co-ordinate corresponding to x, toGridX(x), is simply the rank position of x within the sorted list of all distinct x positions of vertical edges that are present among the input rectangles. Similarly, toGridY(y) is just the rank position of y within the sorted list of all distinct y positions of horizontal edges that are present among the input rectangles. In the other direction, for any grid co-ordinate (i, j), the corresponding input-space x co-ordinate, fromGridX(i), is simply the i-th smallest x co-ord (ignoring duplicates) of any vertical edge among the input rectangles, and similarly for fromGridY(j). These can all be computed as follows (all array indices start at 0, and I show only how to do it for x co-ords; y co-ords are similar):
For each rectangle i in the input having LL co-ords (x1, y1) and (x2, y2):
Append the two-element array [x1, i] to the list-of-arrays VERT.
Append the two-element array [x2, i] to the list-of-arrays VERT.
Sort the list VERT in increasing order by its first item.
Combine elements in VERT having identical x co-ords. Specifically:
Set j = 0.
For i from 1 to n-1:
If VERT[i][0] == VERT[j][0] then append VERT[i][1] to VERT[j] (thereby forming an array of length 3 or more at position j), otherwise set j = j + 1 and overwrite VERT[j] with the two-element array VERT[i].
Delete VERT[j+1] and all later elements from VERT.
By this time, for any i, VERT[i] is an array that contains (in its second and subsequent positions) the IDs of every input rectangle that uses, as either its left or right edge, the ith-leftmost distinct vertical line used by any input rectangle -- or in other words, the rank-i vertical line. We now "invert" this:
For i from 0 to n-1:
For j from 1 to length(VERT[i])-1:
Set toGridX[VERT[i][j]] = i.
For i from 0 to length(VERT)-1:
Set fromGridX[i] = VERT[i][0].
Running time
As previously established, there are at most O(n^2) grid cells. Each of the n input rectangles can occupy at most all of these cells, each of which is visited once per input rectangle, for a time bound of O(n^3). Note that this is an extremely pessimistic time bound, and for example if none (or none but a bounded number) of your rectangles overlap, then it drops to O(n^2) since no grid cell will ever be visited more than once.
I suspect the lookups and iterations are not fast enough. Things like 'otherwise it searches the whole map' point out that you do very heavy computations.
What I think you need is to use a 2d datastructure. A k-d tree or a BSP would work but the easiest to understand and implement would be a quad tree.
In a quad tree each node represents a rectangle in your space. Each node can be split into 4 children by selecting the mid point along the 2 dimensions and having the children represent the 4 resulting rectangles. Each node also holds the value that you want to assign to the area and an extra flag if the value is uniform.
To mark a rectangle with some value, you start from the root and recursively:
If the input rectangle covers the node rectangle you set the value to that node, mark it as uniform and return.
If the input rectangle and the node rectangle don't touch just return.
If the node is marked as uniform, copy the value to it's children and mark the node not uniform.
Recursively call for the 4 children (you might have to create them).
On the way back, check if the 4 children have the same value and are all marked as uniform and if so mark the node as uniform and set the same value as the children.
The main advantage of this approach is that you get to mark large areas of your map quickly. You can also prove that marking a area is O(logN) where N is the size of your map (with a larger constant than the usual tree).
You can find a more detailed explanation and some helpful images on wikipedia.
Assuming you know the top- and bottom-most y and the left- and right-most x, extend the four vectors belonging to each rectangle to the respective max and min x and y points. Keep a set of extended vertical vectors and a set of extended horizontal ones. Whenever an extended vector is added, it will necessarily intersect with each vector in the perpendicular list - the intersections are the cell coordinates of the matrix.
Once the list of cell coordinates is made, iterate over them and assign values appropriately, looking up if they are in or out of an original rectangle. I'm not too versed in data structures for rectangles, but it seems to me that two interval trees, one for horizontal, the other for vertical could find that answer in O(log n) time per query, where n is the number of intervals in the tree.
All together, this method seems to be O(n * log m) time, where n is the number of cell coordinates in the resultant matrix and m is the number of original rectangles.

Distance between two cells in a 2D matrix

I have a 2D matrix represented as a vector of values, an index representing the first cell and a pair of coordinate representing the second cell.
vector<double> matrix;
auto index = 10;
auto x1 = index % width;
auto y1 = index / width;
auto x2 = ...
auto y2 = ...
I need to find the distance between these two cells, where the distance is equals to 1 for the first "ring" of the 8 neighbor cells, 2 for the second ring, and so on.
Is there a way faster than the euclidean distance?
What you need is something like a modified Manhattan Distance. I think there may be a specific name for your use case, but I don't know it. Anyway, this is how I'd do it.
Suppose the two points are x rows away and y columns away. Then x+y is the Manhattan Distance. But in your case, diagonal movements are also allowed. So, if you moved diagonally towards the point initially, you'd cover the smaller of x and y, with some amount remaining in the other. You can then move horizontally/vertically to cover the remaining distance. Hence, the distance by your metric would be max(x,y).
Given points (x1,y1) and (x2,y2), the answer would be max(|x1-x2|,|y1-y2|)

C++ recognize shape from points

I'am trying to find out an algorithm to recognize circle in array of points.
Lets say that I've got points array where circle could or could not be stored (that also means array doesn't have to store only circle's points, there could be some "extra" points before or after circle's data).
I've already tried some algorithms but none of them work properly with those "extra" points. Have you got any ideas how to deal with this problem?
EDIT// I didn't mention that before. I want this algorithm to be used on circle gesture recognition. I've thought I would have data in array (for last few seconds) and by analysing this data in every tracking frame I would be able to say if there was or was not a circle gesture.
First I calculate the geometric mean (not the aritmetic mean) for each X and Y component.
I choose geometric mean because one feature is that small values ​​(with respect to the arithmetic mean ) of the values ​​are much more influential than the large values.
This lead me to the theoretical center of all points: circ_center
Then I calculate the standard deviation of distance of each point to center: stddev. This gives me the "indicator" to quantify the amount of variation. One property of circle is that all circumference point is at the same distance of it's center. With standard dev I try to test if your points are (with max variance threshold: max_dispersion) equally distance.
Last I calculates the average distance of points inside max_dispersion threshold from center, this give me the radius of the circle: avg_dist.
Parameters:
max_dispersion represents the "cicle precision". Smaller means more precise.
min_points_needed is the minimun number of points valid to be considered as circumference.
This is just an attempt, I have not tried. Let me know.
I will try this (in pseudo language)
points_size = 100; //number_of_user_points
all_poins[points_size]; //coordinates of points
//thresholds to be defined by user
max_dispersion = 20; //value of max stddev accepted, expressed in geometric units
min_points_needed = 5; //minimum number of points near the circumference
stddev = 0; //standard deviation of points from center
circ_center; //estimated circumference center, using Geometric mean
num_ok_points = 0; //points with distance under standard eviation
avg_dist = 0; //distance from center of "ok points"
all_x = 1; all_y = 1;
for(i = 0 ; i < points_size ; i++)
{
all_x = all_x * all_poins[i].x;
all_y = all_y * all_poins[i].y;
}
//pow(x, 1/y) = nth root
all_x = pow(all_x, 1 / points_size); //Geometric mean
all_y = pow(all_y, 1 / points_size); //Geometric mean
circ_center = make_point(all_x, all_y);
for(i = 0 ; i < points_size ; i++)
{
dist = distance(all_poins[i], circ_center);
stddev = stddev + (dist * dist);
}
stddev = square_root(stddev / points_size);
for(i = 0 ; i < points_size ; i++)
{
if( distance(all_poins[i], circ_center) < max_dispersion )
{
num_ok_points++;
avg_dist = avg_dist + distance(all_poins[i], circ_center);
}
}
avg_dist = avg_dist / num_ok_points;
if(stddev <= max_dispersion && num_ok_points >= min_points_needed)
{
circle recognized; it's center is circ_center; it's radius is avg_dist;
}
Can we assume the array of points are mostly on or near to the circumference of the circle?
A circle has a center and radius. If you can determine the circle's center coordinates, via the intersection of perpendiculars of two chords, then all the true circle points should be equidistant(r), from the center point.
The false points can be eliminated by not being equidistant (+-)tolerance from the center point.
The weakness of this approach is how well can you determine the center and radius? You may want to try a least squares approach to computing the center coordinates.
To answer the initially stated question, my approach would be to iterate through the points and derive the center of a circle from each consecutive set of three points. Then, take the longest contiguous subset of points that create circles with centers that fall within some absolute range. Then determine if the points wind consistently around the average of the circles. You can always perform some basic heuristics on any discarded data to determine if a circle is actually what the user wanted to make though.
Now, since you say that you want to perform gesture recognition, I would suggest you think of a completely different method. Personally, I would first create a basic sort of language that can be used to describe gestures. It should be very simple; the only words I would consider having are:
Start - Denotes the start of a stroke
Angle - The starting angle of the stroke. This should be one of the eight major cardinal directions (N, NW, W, SW, S, SE, E, NE) or Any for unaligned gestures. You could also add combining mechanisms, or perhaps "Axis Aligned" or other such things.
End - Denotes the end of a stroke
Travel - Denotes a straight path in the stroke
Distance - The percentage of the total length of the path that this particular operation will consume.
Turn - Denotes a turn in the stroke
Direction - The direction to turn in. Choices would be Left, Right, Any, Previous, or Opposite.
Angle - The angle of the turn. I would suggest you use just three directions (90 deg, 180 deg, 270 deg)
Tolerance - The maximum tolerance for deviation from the specified angle. This should have a default of somewhere around 45 degrees in either direction for a high chance of matching the angle in a signature.
Type - Hard or Radial. Radial angles would be a stroke along a radius. Hard angles would be a turn about a point.
Radius - If the turn is radial, this is the radius of the turn (units are in percentage of total path length, with appropriate conversions of course)
Obviously you can make the angles much more fine, but the coarser the ranges are, the more tolerant of input error it can be. Being too tolerant can lead to misinterpretation though.
If you apply some fuzzy logic, it wouldn't be hard to break just about any gesture down into a language like this. You could then create a bunch of gesture "signatures" that describe various gestures that can be performed. For instance:
//Circle
Start Angle=Any
Turn Type=Radial Direction=Any Angle=180deg Radius=50%
Turn Type=Radial Direction=Previous Angle=180deg Radius=50%
End
//Box
Start Angle=AxisAligned
Travel Distance=25%
Turn Type=Hard Direction=Any Angle=90deg Tolerance=10deg
Travel Distance=25%
Turn Type=Hard Direction=Previous Angle=90deg Tolerance=10deg
Travel Distance=25%
Turn Type=Hard Direction=Previous Angle=90deg Tolerance=10deg
Travel Distance=25%
End
If you want, I could work on an algorithm that could take a point cloud and degenerate it into a series of commands like this so you can compare them with pre-generated signatures.

Traverse a 2.5D grid

I'm trying to figure out how to traverse a 2.5D grid in an efficient manner. The grid itself is 2D, but each cell in the grid has a float min/max height. The line to traverse is defined by two 3D floating point coordinates. I want to stop traversing the line if the range of z values between entering/exiting a grid cell doesn't overlap with the min/max height for that cell.
I'm currently using the 2D DDA algorithm to traverse through the grid cells in order(see picture), but I'm not sure how to calculate the z value when each grid cell is reached. If I could do that, I could test the z value when entering/leaving the cell against the min/max height for the cell.
Is there a way to modify this algorithm that allows z to be calculated when each grid cell is entered? Or is there a better traversal algorithm that would allow me to do that?
Here's the current code I'm using:
void Grid::TraceGrid(Point3<float>& const start, Point3<float>& const end, GridCallback callback )
{
// calculate and normalize the 2D direction vector
Point2<float> direction=end-start;
float length=direction.getLength( );
direction/=length;
// calculate delta using the grid resolution
Point2<float> delta(m_gridresolution/fabs(direction.x), m_gridresolution/fabs(direction.y));
// calculate the starting/ending points in the grid
Point2<int> startGrid((int)(start.x/m_gridresolution), (int)(start.y/m_gridresolution));
Point2<int> endGrid((int)(end.x/m_gridresolution), (int)(end.y/m_gridresolution));
Point2<int> currentGrid=startGrid;
// calculate the direction step in the grid based on the direction vector
Point2<int> step(direction.x>=0?1:-1, direction.y>=0?1:-1);
// calculate the distance to the next grid cell from the start
Point2<float> currentDistance(((step.x>0?start.x:start.x+1)*m_gridresolution-start.x)/direction.x, ((step.y>0?start.y:start.y+1)*m_gridresolution-start.y)/direction.y);
while(true)
{
// pass currentGrid to the callback
float z = 0.0f; // need to calculate z value somehow
bool bstop=callback(currentGrid, z);
// check if the callback wants to stop or the end grid cell was reached
if(bstop||currentGrid==endGrid) break;
// traverse to the next grid cell
if(currentDistance.x<currentDistance.y) {
currentDistance.x+=delta.x;
currentGrid.x+=step.x;
} else {
currentDistance.y+=delta.y;
currentGrid.y+=step.y;
}
}
}
It seems like a 3D extension of the Bresenham Line Algorithm would work. You would iterate over X and independently track the error for the Y and Z components of your line segment to determine the Y and Z values for each corresponding X value. You just stop when the accumulated error in Z reaches some critical level which would indicate it is outside of your min/max.
For each cell, you know from which cell you came from. This means you know from which side you came from. Calculating z at the intersection of the green line and a given grid line seems trivial.
I figured out a good way to do it. Add to the start of the function:
float fzoffset=end.z-start.z;
Point2<float> deltaZ(fzoffset/fabs(end.x-start.x), fzoffset/fabs(end.y-start.y));
Point2<float> currentOffset((step.x>0?start.x:start.x+1)*m_gridresolution-start.x, (step.y>0?start.y:start.y+1)*m_gridresolution-start.y);
Inside the loop where currentDistance.x/.y are incremented, add:
currentOffset.x+=m_gridresolution; //When stepping in the x axis
currentOffset.y+=m_gridresolution; //When stepping in the y axis
Then to calculate z at each step:
z=currentOffset.x*deltaZ.x+start.z; //When stepping in the x axis
z=currentOffset.y*deltaZ.y+start.z; //When stepping in the y axis