I have got a four 2d vertices A B C D of rotated rectangle,
I need to rasterize/draw it (efficiently) in pixelbufer
with setpixel(x,y,color)
how to do it?
i was trying with some code like
// convertilg a b c d do up down left right,
// calculating some dx_left dx_right on y--
// etc (frustrating on special cases when there are 2 up_y vertices in same line etc)
for(;;)
{
drawhorizontalline(y, xstart, xend, color);
if(y==downy) break;
y--;
xstart+=dxstart;
xend+=dxend;
if(y==lefty) dxstart = dxright;
if(y==righty) dxend = dxleft;
}
but it is most frustrating (terribly bug prone and most frustrating)
i am really tired of debuging this all day yesterday and i need to find
maybe some working code rather than to try to debug this
To fill your rectangle handle it as closed convex polygon (almost the same as triangle filling)
order your points to match winding rule
so there are lines AB BC CD DA or reverse
create left and right buffer
address is y-coordinate, its an array of x-positions and if needed also array of color,texture coordinates,.... for starters:
int buf_x0[ys],buf_x1[ys];
where ys is screen y-resolution
implement any draw line algorithm
but instead of draw to screen just store x coordinate of pixel to buffer.
instead of: setpixel(x,y,color); do: buf_x?[y]=x;.
Which buffer is the destination depends on the line Y direction
if dy<0 then fill buff_x0
if dy>0 then fill buff_x1
if dy==0 then buf_x0[y]=min(x) and buf_x1[y]=max(x)
Beware you have to sort the line endpoints by x coordinate before rasterizing to avoid seams/holes in meshes caused by different pixels produced for reversed endpoints lines.
apply this line algorithm to all border lines of polygon (AB,BC,CD,DA)
after this the buffers contains start and end x-positions of your horizontal lines
fill the rectangle on screen
for (y=min(Ay,By,Cy,Dy);y<=max(Ay,By,Cy,Dy);y++)
draw_horizontal_line(y,buf_x0[y],buf_x1[y],color);
Image for clarity (taken from my lectures on low level computer graphics)
image description:
vertical rectangles represents the border buffers buf_x0[],buf_x1[]
clockwise winding rule ensures the destination buffer. If its coded properly than buf_x0[y] <= buf_x1[y] so draw of horizontal line colapses to single for loop
Also se these:
simple 2D raster C++ example of mine
simple 3D voxel grid C++ example of mine
Related
I'm trying to play around with image manipulation in C and I want to be able to read and write pixels on an SDL Surface. (I'm loading a bmp to a surface to get the pixel data) I'm having some trouble figuring out how to properly use the following functions.
SDL_CreateRGBSurfaceFrom();
SDL_GetRGB();
SDL_MapRGB();
I have only found examples of these in c++ and I'm having a hard time implementing it in C because I don't fully understand how they work.
so my questions are:
how do you properly retrieve pixel data using GetRGB? + How is the pixel addressed with x, y cordinates?
What kind of array would I use to store the pixel data?
How do you use SDL_CreateRGBSurfaceFrom() to draw the new pixel data back to a surface?
Also I want to access the pixels individually in a nested for loop for y and x like so.
for(int y = 0; y < h; y++)
{
for (int x = 0; x < w; x++)
{
// get/put the pixel data
}
}
First have a look at SDL_Surface.
The parts you're interested in:
SDL_PixelFormat*format
int w, h
int pitch
void *pixels
What else you should know:
On position x, y (which must be greater or equal to 0 and less than w, h) the surface contains a pixel.
The pixel is described by the format field, which tells us, how the pixel is organized in memory.
The Remarks section of SDL_PixelFormat gives more information on the used datatype.
The pitch field is basically the width of the surface multiplied by the size of the pixel (BytesPerPixel).
With the function SDL_GetRGB, one can easily convert a pixel of any format to a RGB(A) triple/quadruple.
SDL_MapRGB is the reverse of SDL_GetRGB, where one can specify a pixel as RGB(A) triple/quadruple to map it to the closest color specified by the format parameter.
The SDL wiki provides many examples of the specific functions, i think you will find the proper examples to solve your problem.
I'm working on a program in which I need to find all lines which are in a circles located at some cartesian point of some radius.
At the moment, for every circle, I am iterating over all the lines and checking if the line enters/contacts the circle at any point.
The code essentially looks like this.
for (int i = 0; i < num_circles; i++)
{
for (int j = 0; j < num_lines; j++)
{
if(lineIntersectWithCircle(circle[i], lines[j]))
{
//Append line[j] to a list of lines intersecting with circle[i];
//some code
}
}
}
I've been thinking of many way to optimize this, but I'm having trouble.
I have sorted the circles by minimum Cartesian distance and sorted lines by maximum distance away. This way you can somewhat optimize, but it's quite minimal because once you reach the point where line[j].max > circle[i].min, you still have to iterate through all the rest of the lines.
I am fine with my intersection checking method, I just would like to minimize the amount of times I need to call it.
Is there a good way of doing this?
Cheapest way is just check the bounding extents/rectangles of the two shapes (line and circle) prior to the more expensive intersection test. Chances are that you can even compute the extents on the fly of the line/circle, not precompute, and still get a decent performance boost unless your line/circle intersection is already dirt cheap.
A really effective approach but one that requires a bit more work is to just create a grid. You can use the bounding rectangles computed above to cheaply see which grid cells your shapes intersect.
struct GridNode
{
// Points to the index of the next node in the grid cell
// or -1 if we're at the end of the singly-linked list.
int next_node;
// Points to the index of the shape being stored.
int shape;
};
struct GridCell
{
// Points to the first node or -1 if the cell is empty.
int first_node;
};
struct Grid
{
// Stores the cells in the grid. This is just illustrative
// code. You should dynamically allocate this with adjustable
// grid widths and heights based on your needs.
struct GridCell cells[grid_width * grid_height];
// Stores the nodes in the grid (one or more nodes per shape
// inserted depending on how many it intersects). This is
// a variable-sized array you can realloc needed (ex: double
// the size when you're out of room).
struct GridNode* nodes;
// The maximum number of nodes we can store before realloc.
int node_cap;
// The number of nodes inserted so far. realloc when this
// exceeds node_cap.
int node_num;
};
... something to this effect. This way, most of the time you can insert elements to the grid doing nothing more than just some integer (emulating pointers) operations and adding some grid node entries to this variable-sized nodes array. Heap allocations occur very infrequently.
I find in practice this outperforms quad-trees if you have many dynamic elements moving from one cell to the next like in a 2D video game where everything is moving around all the time while we need rapid collision detection, and can even rival quad-trees for searching if you are careful with the memory layout of the nodes to minimize cache misses when iterating through grid cells that intersect the shape you are testing against. You can even do a post-pass after the grid is constructed to rearrange the memory of each node for cache-friendly list iteration based on how efficient you need the intersection searches to be. If you want to get fancy, you can use Bresenham to figure out exactly what grid cells a line intersects, e.g., but given the quadratic complexity of what you're doing, you stand to improve exponentially without bothering with that and just doing it in a very simple way with bounding rectangles.
Basically to find an intersection, first grab the bounding rect of the shape. Then see which cells it intersects in the grid. Now check for intersection with the shapes contained in the grid cells the original shape intersects. This way you can work towards constant-time complexity except for gigantic shapes (worst-case with O(n)) which are hopefully a rare case.
I even find use for these in 3 dimensions when things are moving around a lot. They're often cheaper than the octree, BVH, and kd-tree variants which provide extensive search acceleration but at the cost of more expensive builds and updates, and if you use this strategy of a singly-linked list for each grid cell which doesn't have to individually allocate nodes, you can store it in a very reasonable amount of memory even with the 3rd dimension. I wouldn't use a 3-dimensional version of this for raytracing, but it can be very useful for 3D collision detection, like detecting collision between particles moving every single frame.
As with anything it depends on your use case. If you have a fixed number of lines or infrequently added, you may want to precompute some of the calculations needed to find out if any part of the line is within radius distance of the center of the circle
Starting with the equation for the shortest distance between a line and a point and comparing that distance is less than the radius of the circle:
//abs(Cx*(y1-y0)-Cy*(x1-x0)+x1*y0-y1*x0)/sqrt((y1-y0)*(y1-y0)+(x1-x0)*(x1-x0))<R
//pull out some constants and cache these as they are initialized
//int y10 = y1-y0, //add to the line struct
// x10 = x1 -x0,
// delta = x1*y0-y1*x0,
// sides = (y10)*(y10)+(x10)*(x10);
// R2 = R*R; //add to the circle struct
//now the equation factors down to
//abs(Cx*(y10)-Cy*(x10)+delta)/sqrt(sides)< R //replace constants
//abs(Cx*(y10)-Cy*(x10)+delta) < sqrt(sides) * R //remove division
//pow(Cx*(y10)-Cy*(x10)+delta , 2.0) < sides * R * R //remove sqrt()
//int tmp = Cx*(y10)-Cy*(x10)+delta //factor out pow data
//tmp * tmp < sides * R2 //remove pow() and use cache R squared
//now it is just a few cheap instructions
Now the check should be just 4 integer multiplies, 2 add/subtract and a compare.
lineIntersectWithCircle(size_t circle, size_t line){
struct circle C = circle_cache[circle]; //these may be separate arrays
struct line L = line_cache[line]; //from your point data
long tmp = C.x * L.y10 - C.y * L.x10 + L.delta;
return (tmp*tmp < L.sides * C.R2);
}
... but you may want to check my math - its been a while. Also I assumed the points would be integers - change to float as needed - it should still be relatively fast.
If that isn't fast enough you can add additional data for the bounding boxes of the circle and line
bool lineIntersectWithCircle(size_t circle, size_t line){
struct circle C = circle_cache[circle]; //these may be separate arrays
struct line L = line_cache[line]; //from your point data
//if the bounding boxes don't intersect neither does the line
//this may not be _that_ helpful and you would need to:
// figure out the bounding boxes for each line/circle
// and cache additional data
if (C.leftx > L.rightx || L.leftx > C.rightx) //a box is to the side
return 0;
if (C.topy < L.boty || L.topy < C.boty) //a box is below/above
return 0;
//the bounding boxes intersected so check exact calculation
long tmp = C.x * L.y10 - C.y * L.x10 + L.delta;
return (tmp*tmp < L.sides * C.R2);
}
I am a beginner programmer that is working on elementary tests for myself to grasp core values of working with C. I have a test case and don't really know where to begin in structuring it for compiling with GCC. I have a basic theory and pseudocode summary but mainly needing a little help stepping forward.
I have googled the related questions and permutations to this question and have been unable to make heads or tails of the logic for C.
Given the following logic:
Using the C language, have the function OverlappingRectangles(strArr)
read the strArr parameter being passed which will represent two
rectangles on a Cartesian coordinate plane and will contain 8
coordinates with the first 4 making up rectangle 1 and the last 4
making up rectange 2. It will be in the following format:
"(0,0),(2,2),(2,0),(0,2),(1,0),(1,2),(6,0),(6,2)." Your program should
determine the area of the space where the two rectangles overlap, and
then output the number of times this overlapping region can fit into
the first rectangle. For the above example, the overlapping region
makes up a rectangle of area 2, and the first rectangle (the first 4
coordinates) makes up a rectangle of area 4, so your program should
output 2. The coordinates will all be integers. If there's no overlap
between the two rectangles return 0.
I'm lost.
Should have added this at first:
Given a string(n1,n2,n3,n4,m1,m2,m3,m4)
Split string into string1(n1,n2,n3,n4) string2(m1,m2,m3,m4)
If n1+n4 < m1 or n2+n3 < m2 or m1+m4 < n1 or m2+m3 < m1
Calculate area of intersecting rectangle and divide into area of first rectangle.
Else
Print 0
You have a string of the form:
(x1,y1)(x2,y2)(x2,y1)(x1,y2)(x3,y3)(x4,y4)(x4,y3)(x3,y4)
defining 2 rectangles:
r1 = (x1,y1) to (x2,y2)
r2 = (x3,y3) to (x4,y4)
You need to first:
define a representation (structure) for the rectangles
parse (read) the string to extract the numbers for x1-x4 and y1-y4 -- look at e.g. sscanf and its return value for doing this
You can create a helper function, e.g.:
const char *parse_rectangle(const char *str, rectangle *r);
That will read a rectangle r from str in the form (x1,y1)(x2,y2)(x2,y1)(x1,y2)(x3,y3) (including any validation) and return a pointer to the next character.
Now, you will have two rectangles.
You can then compute the intersection of these rectangles as a third rectangle, e.g.:
int intersection(const rectangle *r1, const rectangle *r2, rectangle *result);
which will return 1 if the rectangles intersect, or 0 if they don't and fill result with the intersection. If you are using C99, you can use _Bool instead.
Now, you need a function to compute the area, e.g.:
int area(const rectangle *r);
You can pass this through the intersected rectangle and the first rectangle to get the areas of both.
Now, you simply divide the first rectangle area by the intersected rectangle area and print the result.
In the book learning opencv there's a question in chapter 3 :
Create a two dimensional matrix with three channels of type byte with data size 100-by-100 and initialize all the values to 0.
Use the pointer element to access cvptr2D to point to the middle 'green' channel.Draw the rectangle between 20,5 and 40,20.
I've managed to do the first part, but I can't get my head around second part. Here's what I've done so far :
/*
Create a two dimensional matrix with three channels of type byte with data size 100- by-100 and initialize all the values to 0.
Use the pointer element to access cvptr2D to point to the middle 'green' channel.Draw `enter code here`the rectangle between 20,5 and 40,20.
*/
void ex10_question3(){
CvMat* m = cvCreateMat(100,100,CV_8UC3);
CvSetZero(m); // initialize to 0.
uchar* ptr = cvPtr2D(m,0,1); // if RGB, then start from first RGB pair, Green.
cvAdd(m,r);
cvRect r(20,5,20,15);
//cvptr2d returns a pointer to a particular row element.
}
I was considering adding both the rect and matrix, but obviously that won't work because a rect is just co-ordinates, and width/height. I'm unfamiliar with cvPtr2D(). How can I visualise what the exercise wants me to do and can anyone give me a hint in the right direction? The solution must be in C.
From my understanding with interleaved RGB channels the 2nd channel will always be the channel of interest. (array index : 1,4,6..)
So that's the direction where the winds blow from...
First of all, the problem is the C API. This API is still present for legacy reasons, but will soon become obsolete. If you are serious about OpenCV please refer to C++ API. The official tutorials are great source of information.
To further target your question, this would be implementation of your question in C++.
cv::Mat canvas = cv::Mat::zero(100,100, CV_8UC3); // create matrix of bytes, filled with 0
std::vector<cv::Mat> channels(3); // prepare storage for splitting
split(canvas, channels); // split matrix to single channels
rectangle(channels[1], ...); // draw rectangle [I don't remember exact params]
merge(channels, canvas); // merge the channels together
If you only need to draw green rectangle, it's actually much easier:
cv::Mat canvas = cv::Mat::zero(100,100, CV_8UC3); // create matrix of bytes, filled with 0
rectangle(canvas, ..., Scalar(0,255,0)); // draw green rectangle
Edit:
To find out how to access single pixels in image using C++ API please refer to this answer:
https://stackoverflow.com/a/8139210/892914
Try this code:
cout<<"Chapter 3. Task 3."<<'\n';
CvMat *Mat=cvCreateMat(100, 100, CV_8UC3);
cvZero(Mat);
for(int J=5; J<=20; J++)
for(int I=20; I<40; I++)
(*(cvPtr2D(Mat, J, I)+1))=(uchar)(255);
cvNamedWindow("Chapter 3. Task 3", CV_WINDOW_FREERATIO);
cvShowImage("Chapter 3. Task 3", Mat);
cvWaitKey(0);
cvReleaseMat(&Mat);
cvDestroyAllWindows;
A frequent question that props up during array manipulation exercises is to rotate a two dimensional array by 90 degrees. There are a few SO posts that answer how to do it in a variety of programming languages. My question is to clarify one of the answers that is out there and explore what sort of thought-process is required in order to get to the answer in an organic manner.
The solution to this problem that I found goes as follows:
public static void rotate(int[][] matrix,int n)
{
for( layer = 0;layer < n/2;++layer){
int first = layer;
int last = n -1 - layer;
for(int i = first;i<last;++i){
int offset = i - first;
int top = matrix[first][i];
matrix[first][i] = matrix[last-offset][first];
matrix[last-offset][first] = matrix[last][last-offset];
matrix[last][last-offset] = matrix[i][last];
matrix[i][last] = top;
}
}
}
I have somewhat of an idea what the code above is trying to do, it is swapping out the extremities/corners by doing a four-way swap and doing the same for the other cells separated by some offset.
Stepping through this code I know it works, what I do not get is the mathematical basis for the above given algorithm. What is the rationale behind the 'layer','first','last' and the offset?
How did 'last' turn out to be n-1-layer? Why is the offset i-first? What is the offset in the first place?
If somebody could explain the genesis of this algorithm and step me through the thought process to come up with the solution, that will be great.
Thanks
The idea is to break down the big task (rotating a square matrix) into smaller tasks.
First, a square matrix can be broken into concentric square rings. The rotation of a ring is independent from the rotation of other rings, so to rotate the matrix just rotate each of the rings, one by one. In this case, we start at the outermost ring and work inward. We count the rings using layer (or first, same thing), and stop when we get to the middle, which is why it goes up to n/2. (It is worth checking to make sure this will work for odd and even n.) It is useful to keep track of the "far edge" of the ring, using last = n - 1 - layer. For instance, in a 5x5 matrix, the first ring starts at first=0 and ends at last=4, the second ring starts at first=1 and ends at last=3 and so on.
How to rotate a ring? Walk right along the top edge, up along the left edge, left along the bottom edge and down along the right edge, all at the same time. At each step swap the four values around. The coordinate that changes is i, and the number of steps is offset. For example, when walking around the second ring, i goes {1,2,3} and offset goes {0,1,2}.