I have tried two algorithms that were answers in other StackOverflow questions:
Check point within polygon
Point in Polygon Algorithm
Both were showing some points in as out or out as in while other points were correct. This test cast assumes that there are always only 4 vertices (rectangle)
bool PointInPolygon(Coordinate point, vector<Coordinate> points) {
cout << "x,y" << point.getX() << "," << point.getY() << endl;
cout << "TEST COOR ARRAY" << endl;
for (int i=0; i<4; i++) {
cout << points[i].getX() << "," << points[i].getY() << endl;
}
int i, j, nvert = points.size();
bool c = false;
for(i = 0, j = nvert - 1; i < nvert; j = i++) {
if( ( (points[i].getY() > point.getY() ) != (points[j].getY() > point.getY()) ) &&
(point.getX() < (points[j].getX() - points[i].getX()) * (point.getY() - points[i].getY()) / (points[j].getY() - points[i].getY()) + points[i].getX())
)
c = !c;
}
cout << c << "======================" << endl;
return c;
}
And the output was wrong where (2,3) and (1,1) shouldn't be in.
Lines on the perimeter are not considered to be in.
But even so, then 2,3 should always be in.
x,y1,1
TEST COOR ARRAY
1,1
1,3
4,3
4,1
1======================
IN
x,y2,2
TEST COOR ARRAY
1,1
1,3
4,3
4,1
1======================
IN
x,y2,3
TEST COOR ARRAY
1,1
1,3
4,3
4,1
0======================
OUT
x,y3,2
TEST COOR ARRAY
1,1
1,3
4,3
4,1
1======================
IN
x,y3,3
TEST COOR ARRAY
1,1
1,3
4,3
4,1
0======================
OUT
I have similar issues in using the other algorithms I found as well. If anyone could point me in the right direction, I'd appreciate it a lot thanks!
The Algorithm is based on the concept:
For any closed polygon, any straight line should intersect it's edges Even number of times (not taking line on line situation into account)...
think of it as (Enter, Exit, Enter, Exit, ...).
so, If you draw a Line from your Test-Point to basically infinity, depending on where it started, it should intersect Even times if the point was outside, and Odd if it was in!
As i see, by the test cases, and the "4 vertices" note: you are seeking
PointInRectangle(Coord c, Rect r) which is much simpler, faster and seems fit.
For your test case where (2,3) in (1,1)-(1,3)-(3,4)-(4,1) = TRUE
it is parallel on your bottom line, and probobally is "Disregarded",
but most likely, the intersections with your verticals are there because of Floating Point Inaccuracy.
you should split the Expression in parts, or Debug it as is to see what actual values are calculated There.
Related
I need an Algorithm that I will use to scan pixels out from the center. Problem is with different lengths and sizes, it sometimes can't get to the position (See Image below blue part).
To illustrate the problem more I will show the example output:
If you compare the pictures you will notice that it goes in a spiral and the outputs match with a regular for loop and obviously the problem that it doesn't print the blue part correctly
Here is the code:
#include<iostream>
#include<string>
#include<math.h>
int arr[] = { 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15 };
int arrSize = sizeof(arr) / sizeof(arr[0]);
int width = 5;
int height = 3;
void normal2DArray() {
int index = 0;
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++) {
std::cout << std::to_string(x) << "," << std::to_string(y) << " = " << std::to_string(arr[index]) << "\n";
index++;
}
}
}
int convertToInex(int x, int y) {
int left = x * y; // elements to the left
int right = (width - x) * y; // elements to the right
return left + right + x;
}
void spiralArray() {
// calculate middle point, which is also the start point
int x = round((float)width / 2) - 1;
int y = round((float)height / 2) - 1;
int direction = 0; // 0=right, 1=up, 2=left, 3=down
int turnCounter = 1;
int numSteps = 1;
int step = 1;
int index;
while (true) {
index = convertToInex(x, y); // defines the index position in arr
std::cout << std::to_string(x) << "," << std::to_string(y) << " = " << std::to_string(arr[index]) << "\n";
switch (direction) {
case 0: x++; break;
case 1: y--; break;
case 2: x--; break;
case 3: y++; break;
}
index = convertToInex(x, y);
if (step % numSteps == 0) {
direction = (direction + 1) % 4;
turnCounter++;
if (turnCounter % 2 == 0) numSteps++;
}
step++;
if (step > arrSize) break;
}
}
void main() {
std::cout << "Output of Normal 2D Array:\n";
normal2DArray();
std::cout << "\n"; // better spacing
std::cout << "Output of Spiral Array:\n";
spiralArray();
}
I tried to keep the code as simple and small as possible. It should be ready to import and use.
And yes I already searched for my answer online but I didn't find anything that covered up the problem here nor had a similar setup like I have(1D arr and combined 2D array WIDTH/HEIGHT) and for sure not in c++.
❗ Also I need a Solution that works with all widths and heights and arr sizes and also works for any side ❗
I hope you can provide me with helpful answers and would be grateful with good and fast algorithm implementations/optimizations
EDIT:
Thanks to the replies in this Thread. I decided to go with the solution from #ldog for now even though I'm not completely satisfied with it.
Here are the edited code parts:
int failcounter = 0;
while (true) {
index = convertToInex(x, y); // defines the index position in arr
if (index < 0 || index > arrSize) failcounter++;
else std::cout << std::to_string(x) << "," << std::to_string(y) << " = " << std::to_string(arr[index]) << "\n";
// unchanged code inbetween
if (step > arrSize + failcounter) break;
Based on your comment:
#Beta they don't need to connect. It just has to detect that it's outside the array size (in that case -1) and don't scan them and find the next continue point. So it would continue like this: 5, 1, 6, 11
it seems you don't care that the spiral goes "out-of-bounds". In this case, the trivial answer is, embed the shapes that have no spiral in one that is always guaranteed to have one.
Thus if your input rectangle is N x M, then embed it in a rectangle of size max(M,N) x max(M,N), solve the problem in the latter, and when printing just ignore non-existent numbers in the original problem. Your printed sequence then will always be unique up to how the embedding occurs. The most reasonable embedding would try to center the smaller rectangle as much as possible in the larger rectangle, but this is up to you.
In this case you don't need an algorithm as you can compute everything analytically if you care to do the book-keeping and figure out the formulas involved.
You can hit a dead end (meaning exit the grid) in four spots. In each case, jump to the next live pixel you would have reached, if any live cells remain.
You can do this fairly easily by keeping track of the four corners you've visited furthest from the starting pixel. Using compass coords and N for up, these are the NE, NW, SW, and SE extremes visited.
If you hit a dead end going N from the NE pixel, jump to the pixel one to the left of the NW pixel and set the movement direction to down. If that is also a dead end, jump to one below the SW pixel and set the movement direction to right. Etc... When all four corners and dead ends then you're done.
I'm playing around with C++ and decided to try printing geometric shapes to the console. After printing an equilateral triangle, I decided I should try printing a triangle with varying side lengths, so that one is longer / shorter than the other.
I've tried searching the internet for this, but couldn't find any good explanations for it. After failing to do it on my own, I'd appreciate some help. Below is my code for an equilateral triangle:
unsigned size{ 5 };
for (int x{ 0 }; x < size; x++) {
for (int y{ 0 }; y <= x; y++) {
std::cout << "*";
}
std::cout << std::endl;
}
Which works and prints:
*
**
***
****
*****
Issue is, it can't handle the lower side being longer than the left one, for example. How do I go about doing that, so that I can end up with something like...
*
***
****
******
********
...where the left side and the lower side are not equal?
This could be a start:
void paint_triangle(size_t x, size_t y) {
size_t Y=1;
while(Y<=y) std::cout << std::string(x*Y++/y, '*') << "\n";
}
I am trying to determine whether a point within a shape.
I found a algorithm that does the job
https://wrf.ecse.rpi.edu/Research/Short_Notes/pnpoly.html
I tested the algorithm out with a square shape.
total corners of a square = 4
but however it returns me a wrong result.(see my output results below) after my codes
Shape.h
#ifndef __Shape__Shape__
#define __Shape__Shape__
class Shape {
private:
int xArray[4];
int yArray[4];
int x;
int y;
public:
bool inPoly(int x,int y);
void pointInShape();
};
#endif
Shape.cpp
#include "Shape.h"
#include <iostream>
bool Shape::inPoly(int x,int y) {
xArray[0] = 1;
xArray[1] = 1;
xArray[2] = 3;
xArray[3] = 3;
yArray[0] = 1;
yArray[1] = 3;
yArray[2] = 3;
yArray[3] = 1;
int i, j, nvert = 4, c = 0;
for (i = 0, j = nvert - 1; i < nvert; j = i++) {
if ( ((yArray[i]>y) != (yArray[j]>y)) &&
(x < (xArray[j]-xArray[i]) * (y-yArray[i]) / (yArray[j]-yArray[i]) + xArray[i]) )
c = !c;
}
return c;
}
void Shape::pointInShape() {
std::cout << "results" << std::endl;
std::cout << inPoly(1,1) << std::endl;
std::cout << inPoly(1,2) << std::endl;
std::cout << inPoly(1,3) << std::endl;
std::cout << inPoly(2,1) << std::endl;
std::cout << inPoly(2,2) << std::endl;
std::cout << inPoly(2,3) << std::endl;
std::cout << inPoly(3,1) << std::endl;
std::cout << inPoly(3,2) << std::endl;
std::cout << inPoly(3,3) << std::endl;
}
main.cpp
#include "Shape.h"
#include <iostream>
int main() {
Shape shape;
shape.pointInShape();
}
it returns me this output
results
1 <-- (means that 1,1 is is within polygon)
1 <-- (means that 1,2 is is within polygon)
0 <-- (means that 1,3 is is not within polygon)
1 <-- (means that 2,1 is is within polygon)
1 <-- (means that 2,2 is is within polygon)
0 <-- (means that 2,3 is is not within polygon)
0 <-- (means that 3,1 is is not within polygon)
0 <-- (means that 3,2 is is not within polygon)
0 <-- (means that 3,3 is is not within polygon)
by right the correct output should only return 2,2 as true
correct output
results
0 <-- (means that 1,1 is not within polygon)
0 <-- (means that 1,2 is not within polygon)
0 <-- (means that 1,3 is not within polygon)
0 <-- (means that 2,1 is not within polygon)
1 <-- (2,2 is is within polygon)
0 <-- (means that 2,3 is is not within polygon)
0 <-- (means that 3,1 is is not within polygon)
0 <-- (means that 3,2 is is not within polygon)
0 <-- (means that 3,3 is is not within polygon)
Any advice/suggestions?
the PNPOLY code as written is really meant for floats not ints. If you defined your arrays and vertices as floats it would give you the expected results.
1.0f and 2.0f are not adjacent in float math, but 1 and 2 are in int math.
what should tip you off is the function prototype
int pnpoly(int nvert, float *vertx, float *verty, float testx, float testy)
furthermore the line:
(testx < (vertx[j]-vertx[i]) * (testy-verty[i]) / (verty[j]-verty[i]) + vertx[i]) )
is going to truncate your ints to the nearest int after those divides.
If you really want to use ints you would have to define your shapes with a more room, say 100x100 instead of 2x2.
According to your link and this one: http://www.faqs.org/faqs/graphics/algorithms-faq/ (see section 2.03) the algorithm you've used will only work for points in the inside/outside of the polygon. Points on the border may return a 1 or a 0
If you want to know when a point is exactly on the boundary, you need another program. This is only one of many functions that PNPOLY lacks; it also doesn't predict tomorrow's weather. You are free to extend PNPOLY's source code.
I've got an fstream input file that has [N] lines or items. I've written code to decide which items are triangles and which are rectangles and which are circles. I've got to isolate just the triangle items and then compare them to see if they are equal to +/- 0.1 the area of all the other triangle items. Then I have to cout the equal pairs of items as uppercase char letters.
Here's my code so far but it's not working correctly. It's giving me the last item in the array plus one that doesn't exist. How do I fix this?
// ........................................................
// 4. List any triangular blocks that are the same size.
// ........................................................
float TAE = 0.0;
float ItmM = 0.0;
for (int i=0; i<M; i++)
{
if (btype[i] == Triangles)
{
TA[i] = (0.5 * (D[i] * E[i]));
TAE = TA[i+1];
if ((TA[i] - 0.1) <= TAE <= (TA[i] + 0.1))
{
TAE = TA[i];
ItmN = i;
ItmM = i+1;
}
}
}
cout << "4. Triangular blocks that are the same size = "
<< (char)('A' + ItmN) << "&" << (char)('A' + ItmM)
<< endl;
First, when you don comparison, you don't write a<b<c. The correct one should be a<b && b<c. The compiler should give a warning here.
And when you do TAE=TA[i+1], I guess from your code that TA[i+1] is not assigned yet, which can contain an arbitrary value.
And why use float for ItmM? From your program, you can use an int.
Given a n*n matrix and a value k, how do we find all the neighbors for each element?
for example: in a 4*4 matrix, with k=2
say matrix is :
[ 1 2 3 4
5 6 7 8
9 10 11 12
13 14 15 16]
where these values are the indexes of the location, the neighbors for 1 are 1,2,3,5,6,9 . The values 3,6 and 9 come only because k =2 and wouldnt be there if k was = 1.
similarly the neighbors of 6 will be 1 2 3 5 6 7 8 9 10 11 and 14
Can you please help me to write a c code to implement this in c++.
It is the problem of von Neumann neighborhood, please can some one implement it in c++. Thanks
Your neighbors will form a diamond pattern around your target element. The points of the diamond will be k hops away from the target element. So the top will be k rows up, the left will be k columns over, etc. The diamond expands uniformly as you go from level to level. If you start at the top point and go one row down (closer to the target node) then you go out 1 to each side. It's symmetric in the other directions. In other words, the difference in x coordinates between a neighbor and the target node plus the difference in y will be <= k.
So just make two nested for loops that iterate over this diamond. Outer loop iterates over the rows, inner loop over the columns. Start at the top then expand the diamond by 1 at each outer loop iteration until you reach the same row as the target element, then contract until you reach the bottom point.
Obviously you'll need to test boundary conditions for going outside the matrix.
This should do the trick for k=1. Make minor changes to make it work for all k
int width = 4;
int height = 4;
int k = 1;
int value = 2;
bool hasRight = (value % width != 0);
bool hasLeft = (value % width != 1);
bool hasTop = (value > 4);
bool hasBottom = (value < (height * width - width));
cout << value; // Always itself
if(hasRight == true) {
cout << value+1 << " "; // Right
if(hasTop == true) {
cout << value-width << " " << value-width+1 << " "; // Top and Top-right
}
if(hasBottom == true) {
cout << value+width << " " << value+width+1; // Bottom and Bottom-right
}
}
if(hasLeft == true) {
cout << value-1 << " "; // Left
if(hasTop == true) {
cout << value-width-1 << " "; // Top-left
}
if(hasBottom == true) {
cout << value+width-1 << " "; // Bottom-left
}
}