How to detect if a whole point cloud is under or on top of a given line? - precision

This question is related to this topic.
tl;dr: in a given plane lies a cloud of point. I'm moving a line in this plane and I want to know if every points of my point cloud is on the same side of the line.
This is how I do it (pseudo code):
bool same_side(PointCloud pc, Point a, Point b, Plane plane):
L := Vector(a,b) // the line
n := L.cross_product(plane.normal)
bottom, top, zero := 0
for each p in pc:
current_result := Vector(a, p).dot_product(n)
if(current_result < -EPSILLON)
bottom++
else if(current_result >= -EPSILLON && current_result <= EPSILLON)
zero++
else
top++
return top == 0 OR bottom == 0
Where EPSILLON positive value such as 0.000000001.
You can see that I'm not using zero in this code, just as an illustration.
The problem is that when the line gets closer to the point cloud, some lines aren't detected to be crossing the point cloud.
I think this as to do with accuracy and whether or not a point is triggering a top or bottom increment.
I already tried with different values of EPSILLON from 0 to 0.01 without any satisfying results.
My question is how to handle this ?

Related

Point crossing path

I have a problem in which i need to alert when a point (obviously in movement) had crossed a line-path,
a line path is complex collection of lines (y=ax+b).
Postulation -
I do not know from which side the "Point" will cross the line.
The line-path can be very complex and contain many lines.
For example -
What is the best approach to this problem?
Does anyone know if there is algorithm for that?
Finding line / path intercept
There is no simple solution if you consider that the line can come from any direction and that the line segments in the path can be any configuration. You will need to check each path segment against the line
The image below shows three lines AD, BD, and CD. Lines AD and CD intercept the path at 3 locations and BD at one.
For each line segment the point closest to the start of the line segment is the point you are looking for.
To find these points we must first define a point and line segment.
// point
p.x = ?
p.y = ?
// line segment contains start and end points p1, p2
l.p1 = {x, y}
l.p2 = {x, y}
Finding smallest unit dist on line segment
Compute the unit distance on the line segment that each path segment intercepts if any. The path segment that intercepts the line segment at the smallest unit distance >= 0 will be the first point of intercept. The one you are looking for.
Pseudo-code
The following shows the steps required. Checking each path segment against the line segment. First check if the path is not parallel to the line segment. If so check if the intercept is on the path segment. If so check if the intercept is on the line segment and is the closest intercept to the line start so far found.
// l is line segment
interceptFound = false // Semaphore to indicate point found
minUnitDist = 1 // unit dist of intercept
ix = 0 // intercept point
iy = 0
pathSeg // if needed the path segment that intercepted
vx1 = l.p2.x - l.p1.x // vector of line segment
vy1 = l.p2.y - l.p1.y
for each pathSegment // p path segment
vx2 = p.p2.x - p.p1.x // vector of path segment
vy2 = p.p2.y - p.p1.y
crossProd = vx1 * vy2 - vy1 * vx2
if crossProd != 0 // Check lines are not parallel
vx3 = l.p1.x - p.p1.x // Vector from start of l to start of p
vy3 = l.p1.y - p.p1.y
unit = (vx1 * vy3 - vy1 * vx3) / crossProd // unit dist on path segment
if unit >= 0 && unit <= 1 // Code Point A.
unit = (vx2 * vy3 - vy2 * vx3) / crossProd // unit dist on line segment
if unit >= 0 && unit <= minUnitDist // Is the intercept closest to start
interceptFound = true
minUnitDist = unit
pathSeg = p // store intercepting path segment
if interceptFound // Was a intercept found
ix = l.p1.x + vx1 * minUnitDist // Calculate intercept point
iy = l.p1.y + vy1 * minUnitDist
You can pre-compute the vector for each path segment vx2, vy2 in the above example to save a little time (if the path does not change over time)
You could also exit the loop early if the minUnitDist is zero
This is relatively quick and does not need complex data structures. Most path segments will be culled at // Code Point A
AABB check
Axis Aligned Bounding Box check
If the number of path segments are very high you can perform an AABB to avoid some of the math in the above example. This will only be a benefit if the path points do not change over time and that you calculate the bounding box once at the start for each path segment
Pseudo-code AABB check
// l is a line segment
l.left = min(l.p1.x, l.p2.x)
l.right = max(l.p1.x, l.p2.x)
l.top = min(l.p1.y, l.p2.y)
l.bottom = max(l.p1.y, l.p2.y)
Then to check if two segments may intercept
// l and p are line segs with bounding boxes calculated
if l.left > p.right || l.right < p.left || l.top > p.bottom || l.bottom < p.top
// line segments do not intercept
else
// Line segments may intercept
More bounding boxes and Quad trees
If you still find that the solution is too slow you can divide the path segments into related (close together connected) groups and do the AABB test against each group before checking the path segments in the group.
Further you could consider using a quad tree to store path segments to further reduce the number of path segments you need to test the line against.
To quickly check for a possible intersection, you can plug the two endpoints of every "line" in the equation of the point trajectory (presumably itself a line segment), of the form px+qy+r=0. There is a possible intersection if the signs of px+qy+r differ. This pre-screening will be fast.
To make it even faster, you can think of enclosing the lines in a hierarchy of bounding boxes. A quite simple way would be to group every bounding boxes of the lines two by two (in the traversal order), then group the groups to by to, and so on. Then by recursively comparing the bounding box of the trajectory to the bounding boxes in the hierarchy, you can obtain fast rejection of numerous lines.

How to get vertexes of polyline from a list of its points?

I have a list of points (pixels) QList<QPoint> that represent a curve looking like a orthogonal polyline.
My task is to split this one to small straight lines (an instance of QList<QLineF>). In order to know the end of a previous subline and beginning of a next subline, I got to know which points are vertexes of polyline, that is, the points where sublines are intersected.
What would be the best way to figure out that some point is a vertex?
I've found the answer by myself. It doesn't seem to be convenient and clear, nevertheless it works out.
QList<QPoint> vertexes;
for (int i = 2; i < points.size(); i++)
{
bool xChanged = points[i-2].x() != points[i].x();
bool yChanged = points[i-2].y() != points[i].y();
if (xChanged && yChanged)
vertexes.append(points[i-1]);
}
vertexes.prepend(points.first());
vertexes.append(points.last());
We check two points every loop iteration - the current point and the point two points ago. If their X and Y aren't equal, it means that curve change its direction and the point between them is a vertex.

Elegant verification of a piece being at the edge of a maze

Let's consider a game where the player has n number of pieces on a x*y grid. Also the player can move his pieces in any direction (north, south, north-east etc...). Let's assume that the only rule is that the player (when he decides to move) must move a piece for as much as he can.
ooooo
.....
.....
.....
.....
Player moves the first piece
.oooo
.....
.....
.....
o....
To make such a function (ignoring for a moment about the other directions that the player can move his piece) we have:
while(!AtEdge()){
move()
}
However this AtEdge must be configured to check if the piece is at edge depending on the direction of travel. For example:
o.....
......
......
The first piece is at edge if the direction is north, west or north-west but it's good to go in any other direction.
My thinking at the moment is that I need a switch statement to check if the piece is AtEdge() based on the direction of travel. But then I also need a switch statement for the move function.
switch(direction){
case NORTH_EAST: //code to move north-east
}
This results in 16 Switch statements however if the game was 3D and then the number would multiply. Is there a more elegant solution to achieve what I described? Is there a better way to check if the piece can move any further based on direction of travel?
The position in a x*y grid can be represented by coordinates 0 <= px < x and 0 <= py < y. (You can also choose 1 <= px <= x and 1 <= py <= y, but starting with index/coordinate 0 is more common.)
A single move to a neighbouring field can be represented by a vector (mx my) with mx, my having each one of the values -1,0,1; the combination (0 0) is excluded.
Moving now just means adding the move vector to the position giving
px_new = px + mx
py_new = py + my
Checking if the new position is inside the board can simple be done by:
inside = (0 <= px_new) and (px_new < x) and (0 <= py_new) and (py_new < y)

Algorithm for minimizing the amount of lines to draw?

I am currently working on optimizing a project of mine that is a few years old now. The purpose is to draw an image after hitting a certain combination of keys. The original version that I made a few years ago manually moved to each square section, but I've recently optimized it to draw rectangles for consecutive squares which makes it a lot faster.
The next step I want to take is optimizing the way the program draws a given layout, but I don't know where to start looking. I'm hoping someone can point me in the right direction since I can't even think of a search term for this.
Currently the program has a function called Draw which takes an input like this:
Invader =
(
00100000100
00010001000
00111111100
01101110110
11111111111
10111111101
10100000101
00011011000
)
Draw(Invader, 10) ; Where 10 is the size in pixels of each square
The layout above is for this image:
Draw will take that layout and draw it top to bottom, left to right in the following way:
In total, it takes 18 separate sections to finish the picture. What I'm looking for is some algorithm that can minimize this number. For instance, the following is one of the few ways of having only 16 sections:
Likewise, the difference between the current way and something I just made up on the spot for this image is 19 (65 compared to 46).
Where should I start with this?
Also for reference, here is the current Draw function:
Draw(Layout, BlockSize)
{
Len := StrLen(Layout) ; Total amount of characters
RowSize := StrLen(StrSplit(Layout, "`n")[1]) ; Size of a single row
Index := 0
While (Index < Len)
{
Length := 1
Char := GetChar(Layout, Index) ; Get next character in string
if (Char == "1")
{
; Get the number of consecutive 1s
While (GetChar(Layout, Index + Length) == "1")
{
Length := Length + 1
}
; Draw the rectangle
FillRectangle(Length, BlockSize)
}
else if (Char == "0")
{
; Get the number of consecutive 0s
While (GetChar(Layout, Index + Length) == "0")
{
Length := Length + 1
}
; Skip the entire length
MouseMove, BlockSize * Length, 0, 0, R
}
else
{
; End of line, reset position
MouseMove, -(RowSize * BlockSize), BlockSize, 0, R
}
Index := Index + Length
}
}
FillRectangle(Width, BlockSize)
{
MouseGetPos, mX, mY
mY2 := mY ; Same Y for straight line
mX2 := mX + Width * BlockSize ; Add Width of rectangle times the block size to get final X position
Loop %BlockSize%
{
; Draw line
MouseClickDrag, L, mX, mY, mX2, mY2
; Move to next line
mY -= 1
mY2 -= 1
}
; Move mouse to next position
MouseMove, 0, BlockSize - 1, 0, R
}
GetChar(String, Index)
{
return SubStr(String, Index, 1)
}
You should do some sort of analysis first either way. Afterwards I would propose to pass "image" both way and keep the longer line ( mark each cell of longer line as passed or "black" so you do not repeat checking).
void analyze(){
var horSize = 0, verSize = 0;
// run horizontally & vertically for each white cell
while(!reached_boundary){
++horSize ;
}
while(!reached_boundary){
++verSize ;
}
someContainer.Add( (horSize > verSize) ? horSize:verSize);
}
This is expanded from EpiGen's answer, but I felt it needed its own post to explain the differences.
This is the current status of what I have, but it's still not 100% optimal in all cases (as shown below). If there are any improvements feel free to add them.
So, the basic flow of the algorithm is as follows:
Get horizontal length from current point
Get vertical length from current point
Pick bigger length and use that direction
However, it doesn't just give the length it sees. Instead it picks the max length that doesn't intersect a line that has a greater length. Here are the steps:
Check if next pixel is a 1 (Going right for horizontal, down for vertical)
If it is, then check the length in the opposite direction starting from that index.
If that length is longer than the current length, then save the current length and the opposite length value.
Once a character that isn't a 1 is seen, if the max length in the direction being checked is lower than the max length in the opposite direction, then return the length in our direction before that point.
Here is an example of this logic in action. The grey lines represent lines that have already been drawn, the green line represents the line being checked, and the red line indicates a boundary.
Since the red line's horizontal length is greater than the current vertical length at this point, the values are saved in their current form (vertical 1, horizontal 7). After the vertical line check completes and finds a length of 2, it then sees that it crossed a line of length 7. Since it's less efficient to split this line for a smaller one, it instead changes its length back to 1 which is what it had before it crossed that line. That makes the final output look like this with a total of 16 segments, which is optimal as far as I know.
However, it fails under certain conditions; specifically the bottom left corner of this image.
The green line has a length of 10, and the row it stops at has a length of 9. Since that row isn't greater or equal to its size, it splits the line which leaves a single block to the side. If this problem were fixed, then this image would be optimal as far as I'm aware. (Lowest I've gotten is 44, current logic gets 45).
Regardless, this seems to be working as good as I need it to. If there are any other answers with better solutions in the next day or so I'll take a look at them.
As an extra, here's a gif of it running for one of the larger ones:

Calculating which tiles are lit in a tile-based game ("raytracing")

I'm writing a little tile-based game, for which I'd like to support light sources. But my algorithm-fu is too weak, hence I come to you for help.
The situation is like this: There is a tile-based map (held as a 2D array), containing a single light source and several items standing around. I want to calculate which tiles are lit up by the light source, and which are in shadow.
A visual aid of what it would look like, approximately. The L is the light source, the Xs are items blocking the light, the 0s are lit tiles, and the -s are tiles in shadow.
0 0 0 0 0 0 - - 0
0 0 0 0 0 0 - 0 0
0 0 0 0 0 X 0 0 0
0 0 0 0 0 0 0 0 0
0 0 0 0 L 0 0 0 0
0 0 0 0 0 0 0 0 0
0 0 0 X X X X 0 0
0 0 0 - - - - - 0
0 0 - - - - - - -
A fractional system would be even better, of course, where a tile can be in half-shadow due to being partially obscured. The algorithm wouldn't have to be perfect - just not obviously wrong and reasonably fast.
(Of course, there would be multiple light sources, but that's just a loop.)
Any takers?
The roguelike development community has a bit of an obsession with line-of-sight, field-of-view algorithms.
Here's a link to a roguelike wiki article on the subject:
http://roguebasin.roguelikedevelopment.org/index.php?title=Field_of_Vision
For my roguelike game, I implemented a shadow casting algorithm (http://roguebasin.roguelikedevelopment.org/index.php?title=Shadow_casting) in Python. It was a bit complicated to put together, but ran reasonably efficiently (even in pure Python) and generated nice results.
The "Permissive Field of View" seems to be gaining popularity as well:
http://roguebasin.roguelikedevelopment.org/index.php?title=Permissive_Field_of_View
You can get into all sorts of complexities with calculating occlusion etc, or you can go for the simple brute force method: For every cell, use a line drawing algorithm such as the Bresenham Line Algorithm to examine every cell between the current one and the light source. If any are filled cells or (if you have only one light source) cells that have already been tested and found to be in shadow, your cell is in shadow. If you encounter a cell known to be lit, your cell will likewise be lit. An easy optimisation to this is to set the state of any cells you encounter along the line to whatever the final outcome is.
This is more or less what I used in my 2004 IOCCC winning entry. Obviously that doesn't make good example code, though. ;)
Edit: As loren points out, with these optimisations, you only need to pick the pixels along the edge of the map to trace from.
The algorithms being presented here seem to me to be doing more calculations than I think are needed. I have not tested this but I think it would work:
Initially, mark all pixels as lit.
For every pixel on the edge of the map: As Arachnid suggested, use Bresenham to trace a line from the pixel to the light. If that line strikes an obstruction then mark all pixels from the edge to just beyond the obstruction as being in shadow.
Quick and dirty:
(Depending on how big the array is)
Loop through each tile
draw a line to the Light
If any pary of the line hits an X, then it is in shadow
(Optional): calculate the amount of X the line passes through and do fancy maths to determint the proportion of the tile in shadow. NB: This could be done by anti-aliasing the line between the tile and the Light (therefore looking at other tiles along the route back to the light source) during the thresholding procedure these will appear as small anomolies. Depending on the logic used you could potentially determine how much (if at all) the tile is in shadow.
You could also keep a track of which pixels have been tested, therefore optimize the solution a little and not re-test pixels twice.
This could be dome pretty well by using image manipulation and drawing straight lines between pixles (tiles) If the lines are semi transparent and the X blocks are semi-transparent again. You can threshold the image to determine if the line has intersected an 'X'
If you have an option to use a 3rd party tool, then Id probably take it. In the long run it might turn out to be quicker, but you'd understand less about your game.
This is just for fun:
You can replicate the Doom 3 approach in 2D if you first do a step to convert your tiles into lines. For instance,
- - - - -
- X X X -
- X X - -
- X - - -
- - - - L
...would be reduced into three lines connecting the corners of the solid object in a triangle.
Then, do what the Doom 3 engine does: From the perspective of the light source, consider each "wall" that faces the light. (In this scene, only the diagonal line would be considered.) For each such line, project it into a trapezoid whose front edge is the original line, whose sides lie on lines from the light source through each end point, and whose back is far away, past the whole scene. So, it's a trapezoid that "points at" the light. It contains all the space that the wall casts its shadow on. Fill every tile in this trapezoid with darkness.
Proceed through all such lines and you will end up with a "stencil" that includes all the tiles visible from the light source. Fill these tiles with the light color. You may wish to light the tile a little less as you get away from the source ("attenuation") or do other fancy stuff.
Repeat for every light source in your scene.
To check if a tile is in shadow you need to draw a straight line back to the light source. If the line intersects another tile that's occupied, then the tile you were testing is in shadow. Raytracing algorithms do this for every object (in your case tile) in the view.
The Raytracing article on Wikipedia has pseudocode.
Here is a very simple but fairly effective approach that uses linear time in the number of tiles on screen. Each tile is either opaque or transparent (that's given to us), and each can be visible or shaded (that's what we're trying to compute).
We start by marking the avatar itself as "visible".
We then apply this recursive rule to determine the visibility of the remaining tiles.
If the tile is on the same row or column as the avatar, then it is only visible if the adjacent tile nearer to the avatar is visible and transparent.
If the tile is on a 45 degree diagonal from the avatar, then it is only visible if the neighboring diagonal tile (towards the avatar) is visible and transparent.
In all other cases, consider the three neighboring tiles that are closer to the avatar than the tile in question. For example, if this tile is at (x,y) and is above and to the right of the avatar, then the three tiles to consider are (x-1, y), (x, y-1) and (x-1, y-1). The tile in question is visible if any of those three tiles are visible and transparent.
In order to make this work, the tiles must be inspected in a specific order to ensure that the recursive cases are already computed. Here is an example of a working ordering, starting from 0 (which is the avatar itself) and counting up:
9876789
8543458
7421247
6310136
7421247
8543458
9876789
Tiles with the same number can be inspected in any order amongst themselves.
The result is not beautiful shadow-casting, but computes believable tile visibility.
I know this is years old question, but for anyone searching for this style of stuff I'd like to offer a solution I used once for a roguelike of my own; manually "precalculated" FOV. If you field of view of light source has a maximum outer distance it's really not very much effort to hand draw the shadows created by blocking objects. You only need to draw 1/8 th of the circle (plus the straight and diagonal directions); you can use symmerty for the other eigths. You'll have as many shadowmaps as you have squares in that 1/8th of a circle. Then just OR them together according to objects.
The three major pros for this are:
1. It's very quick if implemented right
2. You get to decide how the shadow should be cast, no comparing which algorith handles which situation the best
3. No weird algorith induced edge cases which you have to somehow fix
The con is you don't really get to implement a fun algorithm.
TK's solution is the one that you would generally use for this sort of thing.
For the partial lighting scenario, you could have it so that if a tile results in being in shadow, that tile is then split up into 4 tiles and each one of those is tested. You could then split that up as much as you wanted?
Edit:
You can also optimise it out a bit by not testing any of the tiles adjacent to a light - this would be more important to do when you have multiple light sources, I guess...
I've actually just recently wrote this functionality into one of my projects.
void Battle::CheckSensorRange(Unit* unit,bool fog){
int sensorRange = 0;
for(int i=0; i < unit->GetSensorSlots(); i++){
if(unit->GetSensorSlot(i)->GetSlotEmpty() == false){
sensorRange += unit->GetSensorSlot(i)->GetSensor()->GetRange()+1;
}
}
int originX = unit->GetUnitX();
int originY = unit->GetUnitY();
float lineLength;
vector <Place> maxCircle;
//get a circle around the unit
for(int i = originX - sensorRange; i < originX + sensorRange; i++){
if(i < 0){
continue;
}
for(int j = originY - sensorRange; j < originY + sensorRange; j++){
if(j < 0){
continue;
}
lineLength = sqrt( (float)((originX - i)*(originX - i)) + (float)((originY - j)*(originY - j)));
if(lineLength < (float)sensorRange){
Place tmp;
tmp.x = i;
tmp.y = j;
maxCircle.push_back(tmp);
}
}
}
//if we're supposed to fog everything we don't have to do any fancy calculations
if(fog){
for(int circleI = 0; circleI < (int) maxCircle.size(); circleI++){
Map->GetGrid(maxCircle[circleI].x,maxCircle[circleI].y)->SetFog(fog);
}
}else{
bool LOSCheck = true;
vector <bool> placeCheck;
//have to check all of the tiles to begin with
for(int circleI = 0; circleI < (int) maxCircle.size(); circleI++){
placeCheck.push_back(true);
}
//for all tiles in the circle, check LOS
for(int circleI = 0; circleI < (int) maxCircle.size(); circleI++){
vector<Place> lineTiles;
lineTiles = line(originX, originY, maxCircle[circleI].x, maxCircle[circleI].y);
//check each tile in the line for LOS
for(int lineI = 0; lineI < (int) lineTiles.size(); lineI++){
if(false == CheckPlaceLOS(lineTiles[lineI], unit)){
LOSCheck = false;
//mark this tile not to be checked again
placeCheck[circleI] = false;
}
if(false == LOSCheck){
break;
}
}
if(LOSCheck){
Map->GetGrid(maxCircle[circleI].x,maxCircle[circleI].y)->SetFog(fog);
}else{
LOSCheck = true;
}
}
}
}
There's some extra stuff in there that you wouldn't need if you're adapting it for your own use. The type Place is just defined as an x and y position for conveniences sake.
The line function is taken from Wikipedia with very small modifications. Instead of printing out x y coordinates I changed it to return a place vector with all the points in the line. The CheckPlaceLOS function just returns true or false based on if the tile has an object on it. There's some more optimizations that could be done with this but this is fine for my needs.
i have implemented tilebased field of view in a single C function. here it is:
https://gist.github.com/zloedi/9551625
If you don't want to spend the time to reinvent/re-implement this, there are plenty of game engines out there. Ogre3D is an open source game engine that fully supports lighting, as well as sound and game controls.

Resources