I'm currently working on a private project which depends on some operations on polygons using the Boost C++ Libraries.
I'm currently trying to work with the inner polygon/negative polygon concept.
What I need to do now is to join three polygons where two of them have a positive (counterclockwise) outer polygon and an negative (clockwise) inner polygon.
The third one is a negative polygon a new polygon object with a negative area - points in clockwise direction. And this is the point where I'm not fully sure how to handle the situation.
Here's a picture of those three polygons. The middle one which connects the left upper polygon with the right lower one is the negative one.
Now what I would like to do is to join all three polygons through the union function.
What I expect union to do is to cut away the positive parts of the polygons 1 and 3 (the positive polygons) and return the remaining two polygons of 1 and 3.
What I actually get are my polygons 1 and 3 untouched as there would be no negative polygon 2.
Any help will be appreciated.
Edit:
What I need to get is a vector not a bitmap or a picture or whatever.
These Picture are just used to better visualize what I have and what I need.
Those three Polygons are actually not more than an vector of x and y points.
Here's a picture of what I would expect to be the correct result of union of all three polygons:
Edit2: Corrected the result
How do you want unions to work? Usually a union of polygons 1 and 2 would result in polygon 3, but I suspect for your use case you want it to result in polygon 4. If that's the case, you can simply do a union of all the clockwise paths, then do a union of the counterclockwise paths, then take the difference of the former from the latter. If you want the union to result in polygon 3, then I don't think there's a consistent way to do what you want.
Good plan is to consider your polygons as a bitmap (of booleans):
Every polygon will be blit to a bitmap of type (R,R)->bool. Once it's in bitmap format, negative polygons are just andnot-operations on the booleans:
class Bitmap { virtual bool Map(float x, float y) const=0; };
class AndNot : public Bitmap {
public:
AndNot(Bitmap &bm1, Bitmap &bm2) : bm1(bm1), bm2(bm2) { }
bool Map(float x, float y) const {
return b1.Map(x,y) && !b2.Map(x,y);
}
private:
Bitmap &bm1, &bm2;
};
Related
I got a vector with n rows with xy coordinates of points. These points form a conture of an given CAD model. Now I want to restore the conture of the model. So I tried to sort the point with the atan2 function.
This is the code I use to sort the points.
std::sort(matrix.begin(), matrix.end(), sort1);
matrix.erase(std::unique(matrix.begin(), matrix.end(), compare2),matrix.end());
matrix.push_back(std::vector<double>(3, 0));
So first I sort the points in the vector matrix. As compare function i use this code
bool sort1(vector<double> const& s1, vector<double> const& s2)
{
return atan2(s1[1],s1[0])<atan2(s2[1],s2[0]);
}
After the vector has been sorted, I just delete duplicates to reduce the size of the vector. The last step is to push back the first point to the end of the vector to close the conture.
For standard models like a cube, or a ball this works fine, but for more complicate models the atan2 function is note working fine.
So this image show the unsorted points.
When I sort the vector I get this conture as result
My first approach was to check the atan2 function but it's working fine. The problem seem to be the result of the atan2 function. So this list shows the actual coordinates and the result of the atan2 function
x y z atan2
-5.44283 -1.94995 0 -2.79758
-5.36969 -1.93228 0 -2.79617
-5.33637 -1.92454 0 -2.79547
-13.15 -4.76500 0 -2.79395
-5.26308 -1.90750 0 -2.79389
-5.22970 -1.90005 0 -2.7931
-5.15626 -1.88364 0 -2.79134
As you can see while the x and y coordinate change the atan2 stays in the same range as the other values. For me that's the problem, why my conture isn't correct. Do I have to add something to my sort function to get the correct results?
One idea i had was to sort the coordinates not just by the atan2, but also by the length of the vector between the point, with the lowest atan2, and all other points. But here's my problem. I would first sort by atan2, and then sort again by the length. But the second sort process would destroy the hole result of the first sort function.
atan2 obviously won't help in generic case. It is mostly good for convex figures. Consider a narrow rectangle with (0,0) inside and an adjacent rectangle and try to sort their points by their atan2.
Have you tried painting a point in the set and then looking for the closest not yet painted point as an iteration step?
If you're dealing with curves only then I'd suggest to use following algorithm:
Define angle range R
Take initial point A, mark it as visited
Find closest to A point B, mark it as visited
Calculate the direction formed by vector [A, B]
Find closest to B unvisited point C in angle range R and mark it visited
Go to step 4 with B as A and C as B
This is not an ultimate solution but it should be able to find basic curves and some polygons. With wider angle range R you can approximate more curved lines.
I have a working class that generates regular polygons given: polygon center and polygon radius and number of sides. Implementation details of the two private member functions here.
The class interface looks like this:
class RegularPolygon: public Closed_polyline{
public:
RegularPolygon(Point c, int r, int n)
: center(c), radius(r), sidesNumber(n)
{ generatePoly(); }
private:
Point center;
int radius;
int sidesNumber;
void generatePoly();
void rotateCoordinate(Point& axisOfRotation, Point& initial,
double angRads, int numberOfRotations);
};
Problem:
I am asked to implement a second way of generating regular polygons by using
a set of coordinates1. The constructor needs firstly to perform a validity check of the passed coordinates:
RegularPolygon(vector<Point>& vertices)
:center(), radius(), sideNumber()
{
// validity check of the elements of vertices
}
My initial thought is to:
Check if each pair of coordinates produces the same side length.
Check for each lines'(generated by a pair of coordinates) relative orientation. (they should be at an angle 360/polygon sides, from each other)
Question:
How could I check if all lines are properly oriented, i.e. their relative orientation? solved
Is there any standard algorithm that can determine if a set of coordinates are vertices of a regular polygon?
Note:
After checking [1] and all the question and answers regarding generating coordinates. I didn't found what I'm searching for.
1 In clockwise sequence, passed with the vector: vertices
All the additional files for compilation could be found: here. The FLTK could be found here.
Your task would be a lot simpler if you could find the center of your polygon. Then you would be able to check the distance from that center to each vertex to verify the placement of the vertices on the circle, and also to check the angles from the center to each individual vertex.
Fortunately, there is an easy formula for finding the center of a polygon: all you need to do is averaging the coordinates in both dimensions. With the center coordinates in hand, verify that
The distance from the center to each vertex is the same, and
The angle between consecutive vertices is the same, and that angle is equal to 2π/N radians
These two checks are sufficient to ensure that you have a regular polygon. You do not need to check the distances between consecutive vertices.
I am coding Tetris in Qt C++ at the moment. The game is almost completed and the only thing I need to add is the rotation. Now what I am struggling with, is the theory behind the rotation. Tetris has 7 different kind of stones ( I, S, Z, L, J, T, O ). Is there any algorithm or anything similar with the rotations from the different shapes ?
What I prefer not to do is having a switch case for 7 different shapes to handle the rotations. Also if a shape like L is rotated it has 4 different positions, which have to be handled different.
So the only thing I have thought of yet is to ask for the shape and then for the position. This would grant me some switches or else if's in a switch... Means a lot to type and a lot to check for the compiler.
P.S. My Stone structure looks like this:( Steine = german for stone, Art = shape )
struct position
{
int X;
int Y;
};
struct Steine
{
struct position* Position;
int Art;
};
You could use a 2D array of bool representation for each shape. Then when you rotate some specific array, you rotate that shape (maybe have the code at the initialization generate all the rotations) and check if any pixel is outside the Tetris borders or if the rotated shape should not be rotated because some of it's pixel would be on the same position as some already existing pixel from previous shapes.
Edit: Yeah, like you said yourself, best is to try on paper/paint to check it out (about the middle point for the rotation). For every shape you then end up with a 3x3 or 4x4. for 3x3 you rotate around it's middle point, for 4x4 around 1x1 for example (where index goes from 0 to 3). That is somewhat how I went for my Tetris 9 years ago or so.
I'm experimenting with OpenGL 3.2+ and have starting loading Obj files/models in 3D and trying to interact with them.
(following tutorials from sources like this site)
I was wondering what the easiest way (if it's possible) to set up collision detection between two existing(loaded) Obj objects/Models without using third party physics engines etc?
The easiest possible algorithm that can meet your criteria detects collision between spheres, that concludes your meshes. Here you can see the implementation example.
Simplest collision model is to use bounding boxes for collision. The principle is simple: You surround your object by a box defined by two points, minimum and maximum. You then use these points to determine whether two boxes intersect.
In my engine the structure of bounding box and collision-detection method are set as this:
typedef struct BoundingBox
{
Vector3 min; //Contains lowest corner of the box
Vector3 max; //Contains highest corner of the box
} AABB;
//True if collision is detected, false otherwise
bool detectCollision( BoundingBox a, BoundingBox b )
{
return (a.min <= b.max && b.min <= a.max);
}
Other simple method is to use spheres. This method is useful for objects that are of similar size in all dimensions but it creates lots of false collisions if they are not. In this method, you surround your object by sphere with radius radius and center position position and when it comes to the collision, you simply check whether the distance between centers is smaller than sum of the radii and that case two spheres intersect.
Again, code snippet from my engine:
struct Sphere
{
Vector3 position; //Center of the sphere
float radius; //Radius of the sphere
};
bool inf::physics::detectCollision( Sphere a, Sphere b )
{
Vector3 tmp = a.position - b.position; //Distance between centers
return (Dot(tmp, tmp) <= pow((a.radius + b.radius), 2));
}
In code above Dot() computes the dot product of two vectors, if you dot vector with itself it gives you (by definition) the magnitude of the vector squared. Notice how I am actually not square-rooting to get the actual distances and I am comparing the squares instead to avoid extra computations.
You should also be aware that neither of these methods are perfect and will give you false collision detection (unless the objects are perfect boxes or spheres) from time to time but that is the trade-off of the simple implementation and computation complexity. Nevertheless it is good way to start detecting collisions.
EDIT: I reformulate the question simply:
How do I generate in C++ or Python, random points (x,y) following: a circular distribution, a square distribution, and a triangular distribution.
This is a simple code for square for example:
def generateSquare(min, max, size):
data = []
for i in range(size):
x = randint(min, max)
y = randint(min, max)
data += [[x, y]]
return data
First of all, instead of storing your coordinates in a vector, you would be better off using std::pair or a custom class:
struct Point
{
int x;
int y;
};
Then you just need to have a way of generating random points, such as
Point randomPoint(Point const & min, Point const & max)
{
static std::mt19937 gen;
std::uniform_int_distribution<> distribX(min.x, max.x);
std::uniform_int_distribution<> distribY(min.y, max.y);
return Point{distribX(gen), distribY(gen)};
}
You can then use this generation function to fill your vector, for instance with generate_n:
unsigned int const nbPoints = 100;
std::vector<Point> points;
std::generate_n(back_inserter(points), nbPoints,
std::bind(randomPoint, Point{0, 0}, Point{1000, 1000}));
Note that this will generate random points, so you are not guaranteed to end up with a square, a triangle, etc. If you want to generate a could, you could either use a non-uniform distribution (if you know what distribution your coordinates follow) to generate your numbers, or use rejection sampling to discard points that are not in the area you want them to be.
Generating a triangle boils down to drawing three random points.
To generate a square, you can draw two points, corresponding to two opposite corners of the square.
And so on... I don't think there is a "universal" solution that would work for any shapes.
As supplement to Luc Touraille's post.
For a square find two random points and let these two points be the two furhest apart corners of the square.
For a triangle find three random points and let the triangle be triangle these three points make.
For a circle find a random point as a center for the circle and another random point, and let the distance between the two be the radius of the circle.
A more general approach could be to find the center point of the figures and let the parameters (scale, rotation, etc.) be found by further randomly generated numbers. (I guess a bit like Rook suggests).
Your problem is underspecified.
There is no such thing as a "circular distribution" or "triangular distribution".
You probably meant: a uniform distribution in the shape of a circle, rectangle, triangle.
There even is no uniquely specified triangle...
The key point is uniform.
E.g. a standard normal distribution in 2D may appear to be somewhat circular, but it is not exactly the shape of a circle.
There is no random generator that directly produces a circle with uniform density; at least not that I know of. The most common way is just to generate a square, and reject those points that you do not want to have.
E.g. generate (x,y) pairs on [0:1]x[0:1] and reject those with distance from .5,.5 larger than .5 - then you get the circle.
If you - as other users suggested - generate a radius and a distance, then the generated points will not be uniformly distributed on the circle.