Identify outer border of bordering polygons C++ - c++

I'm looking for advice on an algorithm I've been struggling with. I have something represented in code (shown later) that looks like the following diagram (initial state on left, desired output on right):
I have this represented in C++ as the following:
#include <vector>
using namespace std;
class Shape {
public:
Shape(vector<vector<float> > c) {
coordinates = c;
}
vector<vector<float> > coordinates; // in format {{x1,y1},{x2,y2}}
};
class Shape_Group {
public:
Shape_Group(vector<Shape> s) {
shapes = s;
}
vector<Shape> shapes;
Shape generate_border();
};
Shape Shape_Group::generate_border() {
/*
define algorithm here
*/
}
int main() {
// define rectangle shapes
Shape s1({{0,0}, {0,1}, {1,1}, {1,0}});
Shape s2({{0,0}, {0,1}, {1,-1}, {-1,0}});
Shape_Group group({s1, s2});
Shape border = group.generate_border(); // should return a shape with the exterior border
// border should be filed with {{1,0}, {1,1}, {1,-1}, {-1,0}};
}
My initial idea for generating this exterior shape was to do something like the following:
loop through each line segment for each shape in the Shape_Group object
loop through every other segment in the Shape_Group object
if both line segments are colinear and overlap, remove them
whatever's left over should be the exterior border
However, with large inputs this is a very slow algorithm. What else can I do?

Geometry O(n^2) approach:
make list of all edges
remove all interrior edges
use hit test to detect interior/exterior edges.
reconnect all remaining edges into new polygon
simply connect edges sharing the same end point.
If you want something simpler then O(n) graphics approach:
render your shape
fill background with specific color
remove all edges not neighboring background color
this is somewhat related:
Render filled complex polygons with large number of vertices with OpenGL
it also combines vector graphics and pixel access ...
There are also different approaches to this problem for example like this one:
Finding holes in 2d point sets?

Related

How to scale down QGraphicsItem in Qt?

I have a QGraphicsItem made up of QGraphicsPathItem (polyline) and QGraphicsEllipseItem (an Arc )
Through co-ordinates of Line and an Arc I have drawn QGraphicsItem ( XNOR gate ) But the problem is, it is quite bigger.
I want that it should get fit in a rectangle. But I do not want to resize it manually.
struct mySymbols
{
vector<LINES> lines;
vector<ARCS> arcs;
};
struct LINES
{
tuple<int,int,int,int> lines_
};
struct ARCS
{
tuple<int,int,int,int,int,int> arc_;
};
std::map<std::string, mySymbols> allSymbols ;
The above figure is showing the current scenario. I want to scale down XNOR gate such that it's input line should match to the a0 and a1 rectangle and it's output should get match to the o rectangle. Currently I have hidden whole rectnagle and showing only input , output (small) rectangle.
I am reading co-ordinates of XNOR gate and storing them in a object. And when I am drawing those on a scene I want to resize them.
How to do that ? Can anyone help me ?

how to alternate colors in a circle, so that circle looks like rotating?

The expected output should be like this with the colors changing their position as well:
Expected output-:
the colors should change their positions in a circle so that it looks like they are moving without changing the position of circle.
though my code is written in codeblocks in c/c++, i will be happy to get answers in any other programming languages.
my present code
#include<graphics.h>
#include<stdlib.h>
#include<stdio.h>
#include<conio.h>
#include<math.h>
#include<string.h>
#include<iostream>
using namespace std;
void vvcircle(float xk,float yk,float radius);
int i=0;
int main()
{
float xk,yk,radius;
int gdriver=DETECT,gmode,errorcode;
initgraph(&gdriver,&gmode,"C:\\TURBOC3\\BGI");
// cout<<"enter the value of x, y and radius of circle"<<endl;
//cin>>xk>>yk>>radius;
vvcircle(200,200,100);
getch();
closegraph();
return 0;
}
void vvcircle(float xk,float yk,float radius)
{
int color[60]={0,1,2,3,4,5,6,7,8,9};
while(radius>0)
{
float xo,yo;
float P;
xo=0.0;
yo=radius;
P=1-radius;
/// vvcircle(200,200,100);
for(;xo<=yo;)
{
putpixel(xo+xk,yo+yk,1);
putpixel(yo+xk,xo+yk,1);
putpixel(-yo+xk,xo+yk,2);
putpixel(xo+xk,-yo+yk,2);
putpixel(-yo+xk,-xo+yk,4);
putpixel(-xo+xk,-yo+yk,4);
putpixel(yo+xk,-xo+yk,4);
putpixel(-xo+xk,+yo+yk,4);
if(P<0)
{
xo=xo+1;
yo=yo;
P=P+2*xo+1;
}
else
{
xo=xo+1;
yo=yo-1;
P=P+(2*xo)-(2*yo)+1;
// putpixel(xo,yo,WHITE);
}
}
radius=radius-1;
}
}
Present output-:
i get many concentric circles with colors. but i want to move the colors so that it looks like the circle is moving and it is not achieved.
How about something like this:
#include <math.h>
void my_circle(int xc,int yc,int r,float a) // center(x,y), radius, animation angle [rad]
{
const int n=4; // segments count
int x,sx,xx,x0,x1,rr=r*r,
y,sy,yy,y0,y1,i,
dx[n+1],dy[n+1], // segments edges direction vectors
c[n]={5,1,2,3}; // segments colors
float da=2.0*M_PI/float(n);
// BBOX
x0=xc-r; x1=xc+r;
y0=yc-r; y1=yc+r;
// compute segments
for (i=0;i<=n;i++,a+=da)
{
dx[i]=100.0*cos(a);
dy[i]=100.0*sin(a);
}
// all pixels in BBOX
for (sx=x0,x=sx-xc;sx<=x1;sx++,x++){ xx=x*x;
for (sy=y0,y=sy-yc;sy<=y1;sy++,y++){ yy=y*y;
// outside circle?
if (xx+yy>rr) continue;
// compute segment
for (i=0;i<n;i++)
if ((x*dy[i ])-(y*dx[i ])>=0)
if ((x*dy[i+1])-(y*dx[i+1])<=0)
break;
// render
putpixel(sx,sy,c[i]);
}}
}
It simply loop through all pixels of outscribed square to your circle, determines if pixel is inside and then detect which segment it is in and color it with segments color.
The segments are described by direction vectors from circle center towards the segments edges. So if pixel is inside it mean its CW to one edge and CCW to the other so in 2D inspecting z coordinate of the cross product between vector to pixel and vectors to edges will tell if the pixel is in or not ...
As you can see I did not use floating point math in the rendering it self, its needed only to compute the segments edge vectors prior rendering...
I used standard 256 color VGA palette (not sure what BGI uses I expect 16 col) so the colors might be different on your platform here preview:
The noise is caused by my GIF capturing tool dithering the render itself is clean ...
Do not forget to call the my_circle repeatedly with changing angle ...
PS. I encoded this in BDS2006 without BGI so in different compiler there might be some minor syntax problem related to used language quirks...
I faked the putpixel with this:
void putpixel(int x,int y,BYTE c)
{
static const DWORD pal[256]=
{
0x00000000,0x000000A8,0x0000A800,0x0000A8A8,0x00A80000,0x00A800A8,0x00A85400,0x00A8A8A8,
0x00545454,0x005454FC,0x0054FC54,0x0054FCFC,0x00FC5454,0x00FC54FC,0x00FCFC54,0x00FCFCFC,
0x00000000,0x00101010,0x00202020,0x00343434,0x00444444,0x00545454,0x00646464,0x00747474,
0x00888888,0x00989898,0x00A8A8A8,0x00B8B8B8,0x00C8C8C8,0x00DCDCDC,0x00ECECEC,0x00FCFCFC,
0x000000FC,0x004000FC,0x008000FC,0x00BC00FC,0x00FC00FC,0x00FC00BC,0x00FC0080,0x00FC0040,
0x00FC0000,0x00FC4000,0x00FC8000,0x00FCBC00,0x00FCFC00,0x00BCFC00,0x0080FC00,0x0040FC00,
0x0000FC00,0x0000FC40,0x0000FC80,0x0000FCBC,0x0000FCFC,0x0000BCFC,0x000080FC,0x000040FC,
0x008080FC,0x009C80FC,0x00BC80FC,0x00DC80FC,0x00FC80FC,0x00FC80DC,0x00FC80BC,0x00FC809C,
0x00FC8080,0x00FC9C80,0x00FCBC80,0x00FCDC80,0x00FCFC80,0x00DCFC80,0x00BCFC80,0x009CFC80,
0x0080FC80,0x0080FC9C,0x0080FCBC,0x0080FCDC,0x0080FCFC,0x0080DCFC,0x0080BCFC,0x00809CFC,
0x00B8B8FC,0x00C8B8FC,0x00DCB8FC,0x00ECB8FC,0x00FCB8FC,0x00FCB8EC,0x00FCB8DC,0x00FCB8C8,
0x00FCB8B8,0x00FCC8B8,0x00FCDCB8,0x00FCECB8,0x00FCFCB8,0x00ECFCB8,0x00DCFCB8,0x00C8FCB8,
0x00B8FCB8,0x00B8FCC8,0x00B8FCDC,0x00B8FCEC,0x00B8FCFC,0x00B8ECFC,0x00B8DCFC,0x00B8C8FC,
0x00000070,0x001C0070,0x00380070,0x00540070,0x00700070,0x00700054,0x00700038,0x0070001C,
0x00700000,0x00701C00,0x00703800,0x00705400,0x00707000,0x00547000,0x00387000,0x001C7000,
0x00007000,0x0000701C,0x00007038,0x00007054,0x00007070,0x00005470,0x00003870,0x00001C70,
0x00383870,0x00443870,0x00543870,0x00603870,0x00703870,0x00703860,0x00703854,0x00703844,
0x00703838,0x00704438,0x00705438,0x00706038,0x00707038,0x00607038,0x00547038,0x00447038,
0x00387038,0x00387044,0x00387054,0x00387060,0x00387070,0x00386070,0x00385470,0x00384470,
0x00505070,0x00585070,0x00605070,0x00685070,0x00705070,0x00705068,0x00705060,0x00705058,
0x00705050,0x00705850,0x00706050,0x00706850,0x00707050,0x00687050,0x00607050,0x00587050,
0x00507050,0x00507058,0x00507060,0x00507068,0x00507070,0x00506870,0x00506070,0x00505870,
0x00000040,0x00100040,0x00200040,0x00300040,0x00400040,0x00400030,0x00400020,0x00400010,
0x00400000,0x00401000,0x00402000,0x00403000,0x00404000,0x00304000,0x00204000,0x00104000,
0x00004000,0x00004010,0x00004020,0x00004030,0x00004040,0x00003040,0x00002040,0x00001040,
0x00202040,0x00282040,0x00302040,0x00382040,0x00402040,0x00402038,0x00402030,0x00402028,
0x00402020,0x00402820,0x00403020,0x00403820,0x00404020,0x00384020,0x00304020,0x00284020,
0x00204020,0x00204028,0x00204030,0x00204038,0x00204040,0x00203840,0x00203040,0x00202840,
0x002C2C40,0x00302C40,0x00342C40,0x003C2C40,0x00402C40,0x00402C3C,0x00402C34,0x00402C30,
0x00402C2C,0x0040302C,0x0040342C,0x00403C2C,0x0040402C,0x003C402C,0x0034402C,0x0030402C,
0x002C402C,0x002C4030,0x002C4034,0x002C403C,0x002C4040,0x002C3C40,0x002C3440,0x002C3040,
0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,
};
if ((x<0)||(x>=Main->xs)) return;
if ((y<0)||(y>=Main->ys)) return;
Main->pyx[y][x]=pal[c];
}
Where Main->xs, Main->ys is my window resolution and Main->pyx is direct pixel acces to its canvas for more info see:
Graphics rendering: (#4 GDI Bitmap)

Draw (2D) Polygon with given 3D-Vertices and Transformation with VTK

I have some 3d models and I want to display each face of the model seperately. For each face, I have a list of the vertices (as pcl::PointCloud), the Translation vector (as Eigen::Vector3f) and the Rotation Matrix (as Eigen::Quaternionf). The faces can have different shapes. It will be rectangular, round (n-verts polygon) and trapezial.
For the rectangular faces, I used vtkCubeSource so far and it works good. For the round faces, I could maybe use vtkCylinderSource. For trapezial faces, I didn't found a solution so far.
The best would be a class like vtkPolyLineSource, where I just need a list of vertices for any polygons. But as far as I see, vtkPolyLineSource would just draw the the line and don't fill the polynom with a color.
Is there a way to draw a polygon into 3d-space with vtk? Since it is possible to directly draw a 3d-model from a file, I think there should be a method for drawing a model (or just one face), but I couldn't find it so far. That's my first contact with VTK, so I think I just overlooked the right classes.
One reason why I don't just load a model-file is, that I need the faces in different colors and opacitys (defiend at runtime).
Use vtkPolygon
vtkSmartPointer<vtkPoints> points = vtkSmartPointer<vtkPoints>::New();
// ... fill in your points with n points
// Create the polygon
vtkSmartPointer<vtkPolygon> polygon = vtkSmartPointer<vtkPolygon>::New();
polygon->GetPointIds()->SetNumberOfIds(n);
for (int j = 0; j < n; j++)
{
polygon->GetPointIds()->SetId(j, j);
}
// Add the polygon to a list of polygons
vtkSmartPointer<vtkCellArray> polygons = vtkSmartPointer<vtkCellArray>::New();
polygons->InsertNextCell(polygon);
// Create a PolyData
vtkPolyData* polygonPolyData = vtkPolyData::New();
polygonPolyData->SetPoints(points);
polygonPolyData->SetPolys(polygons);
// create mapper and actor using this polydata - the usual stuff

Arrange particles in the shape of a rectangle

I have a particle simulation program I'm currently working on that generate random particle positions in a rectangular shape. This works for now but it's not the best solution, often particles overlap and there are small holes in the rectangle. How would I initialize the particles in the shape of a rectangle?
My current loop:
for(auto i=0; i<MAXPARTICLES; i++){
int particleIndex = FindUnusedParticle(); //grab the index to give a particle life
ParticlesContainer[particleIndex].life = 100.0f; //Long particle life
//generate random positions for particles in the shape of a box with random patterns
ParticlesContainer[particleIndex].pos = glm::vec3((rand()%50)/5.0,(rand()%50)/5.0,-50.0);
// Very bad way to generate a random color
ParticlesContainer[particleIndex].r = 255;
ParticlesContainer[particleIndex].g = 0;
ParticlesContainer[particleIndex].b = 0;
ParticlesContainer[particleIndex].a = 255;
ParticlesContainer[particleIndex].size = .2f;
}
It's a more complicated problem than just using uniform distribution over two dimensions separately. If your "evenliness" is the distance between two closest particles, then there are exactly two ways to achieve that: equilateral triangles and squares (well, three if you count hexagons). The only random thing there is the position of one seed and the "direction" in which that will go.
Refer to the image:
That will give you a very regular, grid-like look, though. You could try applying random, minuscule changes to particles distributed that way, and see how that would work.

C++ Algorithm to Filter Irrelevant Coordinate Data

I'm currently working on a hobby project in which I have several thousand stars in a 2D fictional universe. I need to render these stars to the screen, but clearly I don't want to have to operate on all of them -- only the ones that are visible at any given time.
For proof of concept, I wrote a brute force algorithm that would look at every star and test its coordinates against the bounds of the player's screen:
for (const std::shared_ptr<Star>& star : stars_) {
if (moved_)
star->MoveStar(starfield_offset_, level_);
position = star->position();
if (position.x >= bounds_[0] &&
position.x <= bounds_[1] &&
position.y >= bounds_[2] &&
position.y <= bounds_[3])
target.draw(*star);
}
While this clunky method does, indeed, draw only the visible stars to the screen, it clearly operates in linear time. Since stars are only part of the background and, frankly, aren't the most important thing for the processor to be spending time filtering through, I'd like to devise a faster algorithm to reduce some of the load.
So, my current train of thought is along the lines of using binary search to find the relevant stars. For this, I would clearly need to sort my data. However, I wasn't really sure how I could go about sorting my coordinate data -- I couldn't think of any absolute ordering that would allow me to properly sort my data in ascending order (with regards to both x and y coordinates).
So, I implemented two new containers -- one for the data sorted by x coordinate, and the other by y coordinate. My original thought was to take the intersection of these two sorted sets and draw the resulting stars to screen (stars whose x and y coordinates lie within the screen bounds):
struct SortedStars {
std::vector<std::shared_ptr<Star>>::iterator begin, end;
std::vector<std::shared_ptr<Star>> stars;
} stars_x_, stars_y_;
I then sorted these containers:
// comparison objects
static struct SortX {
bool operator() (const std::shared_ptr<Star>& first, const std::shared_ptr<Star>& second)
{ return (first->position().x < second->position().x); }
bool operator() (const std::shared_ptr<Star>& first, const float val)
{ return (first->position().x < val); }
bool operator() (const float val, const std::shared_ptr<Star>& second)
{ return (val < second->position().x); }
} sort_x;
static struct SortY {
bool operator() (const std::shared_ptr<Star>& first, const std::shared_ptr<Star>& second)
{ return (first->position().y < second->position().y); }
bool operator() (const std::shared_ptr<Star>& first, const float val)
{ return (first->position().y < val); }
bool operator() (const float val, const std::shared_ptr<Star>& second)
{ return (val < second->position().y); }
} sort_y;
void Starfield::Sort() {
// clone original data (shared pointers)
stars_x_.stars = stars_;
stars_y_.stars = stars_;
// sort as needed
std::sort(stars_x_.stars.begin(), stars_x_.stars.end(), sort_x);
std::sort(stars_y_.stars.begin(), stars_y_.stars.end(), sort_y);
// set iterators to the outermost visible stars (defined by screen bounds)
// these are updated every time the screen is moved
stars_x_.begin = std::lower_bound(stars_x_.stars.begin(), stars_x_.stars.end(), bounds_[0], sort_x);
stars_x_.end = std::upper_bound(stars_x_.stars.begin(), stars_x_.stars.end(), bounds_[1], sort_x);
stars_y_.begin = std::lower_bound(stars_y_.stars.begin(), stars_y_.stars.end(), bounds_[2], sort_y);
stars_y_.end = std::upper_bound(stars_y_.stars.begin(), stars_y_.stars.end(), bounds_[3], sort_y);
return;
}
Unfortunately, I cannot seem to either come up with an appropriate comparison function for std::set_intersection or a method through which I could manually compare coordinates using my iterators.
Could you guys point me in the right direction? Feedback on my methodology or implementation is very welcome.
Thanks for your time!
There are a variety of spatial acceleration data structures that help to answer questions of 'what points are in this region'. Quadtrees are a popular solution for 2D but may be overkill for your problem. Probably the simplest approach is to have a 2D grid with points (stars) bucketed by the grid square they fall into. You then check to see which grid squares your view window overlaps and only need to look at the stars in the buckets for those squares. If you make your grid squares a bit larger than your view window size you'll only ever have to check a maximum of four buckets.
If you can zoom in and out a more complicated structure like a Quadtree might be appropriate.
I use real star data for rendering (psychosomatic style) for years and have no speed problems without any visibility ordering/selecting under OpenGL (VBO)
I usually used BSC star catalog in the past
stars up to +6.5mag
9110 stars
few years back I convert my engines to hipparcos catalog
118322 stars
3D coordinates
So unless you use too much stars it should be faster to just render them all
- How many stars are you rendering?
- How are you stars rendered? (I use blended Quad per star)
What platform/setup ...
- this worked well even on my old setup GeForce 4000 Ti, 1.3GHz single core AMD
- also in stereo 3D
what is your desired FPS ? ... I am fine with 30fps for my simulations
If you have similar values and low speed may be there is something wrong with your rendering code (not with the amount of data)...
PS.
if you have a big space to cover you can select bright stars to viewer only
after each hyperspace jump or what ever
based on relative magnitude and distance
also you use too much ifs for star selection
they are sometimes slower then the rendering
try just dot product of viewing direction and star direction vectors instead
and test the sign only (do not see what is behind)
of course if you use quads then CULL_FACE make it for you
Also i see you are calling draw for each star
that is heap trashing
try to avoid calling functions when you can
it will boost the speed a lot !!!
for example you can add a flag to each star if it should be rendered or not
and then render them with single for and no sub-calls to render function
You can try spatial R-tree which is now part of Boost Geometry library.
The application could work as follows:
You add your star's coordinate to the tree in some "absolute" coordinate system. If your stars have different sizes you probably want to add not a point but a bounding box of each star.
#include <boost/geometry/index/rtree.hpp>
#include <boost/geometry/geometries/box.hpp>
namespace bg = boost::geometry;
namespace bgi = boost::geometry::index;
typedef bg::model::point<float, 2, bg::cs::cartesian> point;
typedef bg::model::box<point> box;
typedef std::pair<box, Star*> value; //here "second" can optionally give the star index in star's storage
bgi::rtree<value> rtree;
As you build your universe, you populate the rtree:
for (auto star: stars)
{
box b(star->position(), star->position()));
bg::expand(b, point(star->radius(), star->radius());
// insert new value
rtree.insert(std::make_pair(b, star));
}
When you need to render them, you compute your screen window into "absolute" coord system and query the tree about stars which overlap your window:
box query_box(point(0, 0), point(5, 5));
std::vector<value> result_s;
rtree.query(bgi::intersects(query_box), std::back_inserter(result_s));
Here result_s will list the relevant stars and their bounding boxes.
Good luck!