Help in combining two functions in c++ - c++

I am just trying something with somebody else's code.
I have two functions:
int Triangle(Render *render, int numParts, Token *nameList, Pointer *valueList)
int i;
for (i=0; i<numParts; i++)
{
switch (nameList[i])
{
case GZ_NULL_TOKEN:
break;
case GZ_POSITION:
return putTrianglePosition(render, (Coord *)valueList[i]);
break;
}
}
return SUCCESS;
}
int putTrianglePosition(Render *render, Coord vertexList[3]) /*vertexList[3][3:xyz]*/
{
Coord *pv[3];
int i,j;
// sort verts by inc. y and inc. x
pv[0] = &vertexList[0];
pv[1] = &vertexList[1];
pv[2] = &vertexList[2];
for (i=0; i<2; i++)
for (j=i+1; j<3; j++)
{
if ((*pv[i])[1]>(*pv[j])[1] ||
(*pv[i])[1]==(*pv[j])[1] && (*pv[i])[0]>(*pv[j])[0]) {
Coord *tmp;
tmp = pv[i];
pv[i] = pv[j];
pv[j] = tmp;
}
}
;
// all y the same?
if ((*pv[0])[1] == (*pv[2])[1]) {
drawHorizonLine(render, *pv[0], *pv[2]);
return SUCCESS;
}
// assign middle point
Coord mid;
mid[1] = (*pv[1])[1]; // y
float ratio = ((*pv[1])[1] - (*pv[0])[1]) / ((*pv[2])[1] - (*pv[0])[1]);
mid[0] = (*pv[0])[0] + ratio * ((*pv[2])[0] - (*pv[0])[0]); // x
mid[2] = (*pv[0])[2] + ratio * ((*pv[2])[2] - (*pv[0])[2]); // z
if (mid[0]<=(*pv[1])[0]) { // compare X
drawTrapzoid(render, *pv[0], mid, *pv[0], *pv[1]); // upper tri
drawTrapzoid(render, mid, *pv[2], *pv[1], *pv[2]); // lower tri
}else{
drawTrapzoid(render, *pv[0], *pv[1], *pv[0], mid); // upper tri
drawTrapzoid(render, *pv[1], *pv[2], mid, *pv[2]); // lower tri
}
return SUCCESS;
}
I don't want two functions here. I want to copy the putTrianglePosition() function into the Triangle() function.
I tried doing that, but I got a lot of errors.
Can somebody else show me how to do this?

You shouldn't put functions together, you should split them apart. Put a new function wherever you can name them -- try to make them as small as you can. If you want a function that does all of that stuff, have a function that calls the other functions.
int foobar() {
int a;
int b;
/* do a whole bunch of stuff with a */
/* do a whole bunch of stuff with b */
return a + b;
}
this is sort of what you're trying to do. Instead, do this:
int foo(){
int a;
/* do a bunch of stuff with a */
return a;
}
int bar() {
int b;
/* do a bunch of stuff with b */
return b;
}
int foobar() {
return foo() + bar();
}
The result will be cleaner, easier to maintain and re-usable.

If you just change the line
return putTrianglePosition(render, (Coord *)valueList[i]);
into:
Coord* vertexList = (Coord*) valueList[i];
followed by the whole body of what's now putTrianglePosition from the opening { to the closing } included, I believe it should just work. If not, please edit your question to add the exact, complete, code as obtained by this edit and the exact, complete error messages you get.

I strongly recommend you to go with Functions because it allows better separation of logic and allows you to reuse the logic. But still in case if you want to use it that way please check the function below :
int Triangle(Render *render, int numParts, Token *nameList, Pointer *valueList)
{
int iOuter;
for (iOuter=0; iOuter<numParts; iOuter++)
{
switch (nameList[iOuter])
{
case GZ_NULL_TOKEN:
break;
case GZ_POSITION:
{
Coord* vertexList = (Coord*) valueList[i];
Coord *pv[3];
int i,j;
// sort verts by inc. y and inc. x
pv[0] = &vertexList[0];
pv[1] = &vertexList[1];
pv[2] = &vertexList[2];
for (i=0; i<2; i++)
for (j=i+1; j<3; j++)
{
if ((*pv[i])[1]>(*pv[j])[1] ||
(*pv[i])[1]==(*pv[j])[1] && (*pv[i])[0]>(*pv[j])[0]) {
Coord *tmp;
tmp = pv[i];
pv[i] = pv[j];
pv[j] = tmp;
}
}
;
// all y the same?
if ((*pv[0])[1] == (*pv[2])[1]) {
drawHorizonLine(render, *pv[0], *pv[2]);
return SUCCESS;
}
// assign middle point
Coord mid;
mid[1] = (*pv[1])[1]; // y
float ratio = ((*pv[1])[1] - (*pv[0])[1]) / ((*pv[2])[1] - (*pv[0])[1]);
mid[0] = (*pv[0])[0] + ratio * ((*pv[2])[0] - (*pv[0])[0]); // x
mid[2] = (*pv[0])[2] + ratio * ((*pv[2])[2] - (*pv[0])[2]); // z
if (mid[0]<=(*pv[1])[0]) { // compare X
drawTrapzoid(render, *pv[0], mid, *pv[0], *pv[1]); // upper tri
drawTrapzoid(render, mid, *pv[2], *pv[1], *pv[2]); // lower tri
}else{
drawTrapzoid(render, *pv[0], *pv[1], *pv[0], mid); // upper tri
drawTrapzoid(render, *pv[1], *pv[2], mid, *pv[2]); // lower tri
}
return SUCCESS;
}
break;
}
}
return SUCCESS;
}

Well, since the tag says C++ (even though the code seems to be pure C), the solution would be to put an inline modifier before the function:
inline int putTrianglePosition(Render *render, Coord vertexList[3])
{
...
}
However, even after thinking about this for ten minutes, I still fail a valid reason for wanting this.

Related

Using the minimax algorithm, how do I access the node that returned the best value so it can be utilised?

I am currently completing an assignment for a uni paper. I am making an AI for a checkers game. I understand the principles of the minimax algorithm, however, when it came to implementing it I am struggling to see how I can access the node with the best move so it can be implemented. It may be that I have implemented the code incorrectly which, has put me in this situation. However, as far as I can see it is only returning the best score that was evaluated. How do I then get the node that returned it to the Root?
This is the code for the GameTree that has the minimax function in it. I want to be able to use the node that sent the best score in the GetNextMove()
#include "gametree.h"
//Constructor
GameTree::GameTree()
{
}
/* This function is part of the evalutaion of which move is best by looking for the best
* score in the tree. which is set up by the nodes calling themselves via the Move::PosMove
* function. This function was used because it was taught in class and it enables pruning.
* this function goes down the left side to the bottom of the tree first. Because the
* children of each node are stored in a set the highest score is the first to be seen.
* this will enable maximum pruning, so will speed up the search for the best move.
* Called by Move::AiMove() */
int GameTree::minimax(Node *node, int depth, int alpha, int beta, bool isMaxNode)
{
int Alpha = alpha;
int Beta = beta;
if (depth == 0|| endGame ==1)
{
nScore= node->score;
return nScore;
}
if (isMaxNode)
{
int HighScore = -1000;
for (int i =0; i< (int)node->children.size(); i++)
{
nScore= minimax(node, depth-1, Alpha, Beta, false);
HighScore= max(HighScore,nScore);
Alpha= max(Alpha, HighScore);
if (beta<=alpha)
{
break;
}
}
return Alpha;
}
else
{
int LowScore = 1000;
for (int i =0; i< (int)node->children.size(); i++)
{
nScore= minimax(node,depth-1, Alpha, Beta, true);
LowScore= min(LowScore,nScore);
Beta= min(Beta, LowScore);
if (beta<=alpha)
{
break;
}
}
return Beta;
}
}
/* This function serches for the best move based on teh minimax evaluation by looking at
* the children of the root node.
* Called By Move::AiMove() */
void GameTree::GetNextMove()
{
nodeNext = *nodeRoot->children.begin();
for (Node *n : nodeRoot->children)
{
if (n->score > nodeNext->score)
{
nodeNext = n;
}
}
nodeNext->UpdateDisplay(4);
return;
}
Thank you, in advance for your help I have received a lot of help from this website, without ever having to ask a question. Hopefully, you can help me again. Thanks.
Since you do not show AiMove() it is difficult to answer correctly. However one basic way is to write a minimax algorithm in AiMove that catches when the best score has been beaten.
void AiMove(){
//Make all the moves for the ROOT
//Compute the alpha-beta value of all moves :
int alpha = -INF, beta = INF;
Node* nodeNext;
for(Node* n : nodeRoot->children){
int cur = minimax(n, depth-1, alpha, beta, false);
n->score = cur; //Warning, not necessarily the real score for this node
if(cur > alpha){ //Wow ! new high score
alpha = cur;
nodeNext = n; // here you go
}
}
//GetNextMove(); //useless now
}
Some corrections of your minimax functions :
int GameTree::minimax(Node *node, int depth, int alpha, int beta, bool isMaxNode)
{
//int Alpha = alpha; No need of Alpha and Beta, alpha and beta are the very one used
//int Beta = beta;
if (depth == 0|| endGame ==1)
{
nScore= node->score;
return nScore;
}
//Warning : you need to generate all children of node here only
if (isMaxNode)
{
int HighScore = -1000;
for (int i =0; i< (int)node->children.size(); i++)
{
nScore= minimax(node->children[i], depth-1, Alpha, Beta, false); //mistake here
HighScore= max(HighScore,nScore);
Alpha= max(Alpha, HighScore);
if (beta<=alpha) //mistake here : Alpha or alpha? use the varying variable in the function
{
break;
}
}
return Alpha;
}
else
{
int LowScore = 1000;
for (int i =0; i< (int)node->children.size(); i++)
{
nScore= minimax(node,depth-1, Alpha, Beta, true); //mistake here too
LowScore= min(LowScore,nScore);
Beta= min(Beta, LowScore);
if (beta<=alpha) //Same here
{
break;
}
}
return Beta;
}
}
Finally, for efficiency you don't want to use a Node structure, because then every Node is saved in the memory and it takes some time. One faster way is to work on the board directly. This looks something like that in the minimax function. There will be nothing saved.
for each possible move:
apply(move);
minimax(depth-1, alpha, beta); //Recursively compute the minimax value
//Do stuffs on alpha and beta
undo(move);

OpenGL/Glut: glutTimerFunc seems not to start

I would like to use glutTimerFunc to move the camera around the scene which is composed of some mesh models. The camera path is build with a Bezier curve like the following:
if(sel == MODE_CAMERA_MOTION) {
mode = MODE_CAMERA_MOTION;
stepsCounter = 0;
// Building camera track
int i, j, k;
for(j=0; j<MAX_CV; j++) {
tmpCV[j][0] = CV[j][0];
tmpCV[j][1] = CV[j][1];
tmpCV[j][2] = CV[j][2];
}
for(i=0; i<STEPS; i++) {
for(j=1; j<MAX_CV; j++) {
for(k=0; k<MAX_CV-j; k++) {
lerp(i/(float)(STEPS*10), tmpCV[k], tmpCV[k+1], tmpCV[k]);
}
}
cameraPosition[i][0] = tmpCV[0][0];
cameraPosition[i][1] = tmpCV[0][1];
cameraPosition[i][2] = tmpCV[0][2];
}
glutTimerFunc(250, moveCamera, STEPS);
}
where the moveCamera function is:
void moveCamera() {
if (mode == MODE_CAMERA_MOTION) {
camE[0] = cameraPosition[stepsCounter][0];
camE[1] = cameraPosition[stepsCounter][1];
camE[2] = cameraPosition[stepsCounter][2];
if(stepsCounter < STEPS) {
stepsCounter++;
}
else {
/* come back to the first point */
camE[0] = 8.8;
camE[1] = 4.9;
camE[2] = 9.0;
stepsCounter = 0;
}
glutPostRedisplay();
}
}
But nothing moves. Maybe I have misunderstood the behaviour of that function.
Where am I wrong?
The prototype to the function passed to glutTimerFunc should be
void (*func)(int value)
Where the last parameter of glutTimerFunc is the passed value. So your moveCamera should be:
void moveCamera( int STEPS )
Also, even so, the moveCamera function will be called once. You need to reregister at end of execution. This might be a possible solution:
// instead of global STEPS and stepsCounter, we decrement at reexecution
void moveCamera( int STEPS ) {
... do stuff
glutTimerFunc(250, moveCamera, STEPS-1 );
}

convert from recursive to iterative function cuda c++

I'm working on a genetic program in which I am porting some of the heavy lifting into CUDA. (Previously just OpenMP).
It's not running very fast, and I'm getting an error related to the recursion:
Stack size for entry function '_Z9KScoreOnePdPiS_S_P9CPPGPNode' cannot be statically determined
I've added a lump of the logic which runs on CUDA. I believe its enough to show how its working. I'd be happy to hear about other optimizations I could add, but I would really like to take the recursion if it will speed things up.
Examples on how this could be achieved are very welcome.
__device__ double Fadd(double a, double b) {
return a + b;
};
__device__ double Fsubtract(double a, double b) {
return a - b;
};
__device__ double action (int fNo, double aa , double bb, double cc, double dd) {
switch (fNo) {
case 0 :
return Fadd(aa,bb);
case 1 :
return Fsubtract(aa,bb);
case 2 :
return Fmultiply(aa,bb);
case 3 :
return Fdivide(aa,bb);
default:
return 0.0;
}
}
__device__ double solve(int node,CPPGPNode * dev_m_Items,double * var_set) {
if (dev_m_Items[node].is_terminal) {
return var_set[dev_m_Items[node].tNo];
} else {
double values[4];
for (unsigned int x = 0; x < 4; x++ ) {
if (x < dev_m_Items[node].fInputs) {
values[x] = solve(dev_m_Items[node].children[x],dev_m_Items,var_set);
} else {
values[x] = 0.0;
}
}
return action(dev_m_Items[node].fNo,values[0],values[1],values[2],values[3]);
}
}
__global__ void KScoreOne(double *scores,int * root_nodes,double * targets,double * cases,CPPGPNode * dev_m_Items) {
int pid = blockIdx.x;
// We only work if this node needs to be calculated
if (root_nodes[pid] != -1) {
for (unsigned int case_no = 0; case_no < FITNESS_CASES; case_no ++) {
double result = solve(root_nodes[pid],dev_m_Items,&cases[case_no]);
double target = targets[case_no];
scores[pid] += abs(result - target);
}
}
}
I'm having trouble making any stack examples work for a large tree structure, which is what this solves.
I've solved this issue now. It was not quite a case of placing the recursive arguments into a stack but it was a very similar system.
As part of the creation of the node tree, I append each node each to into a vector. I now solve the problem in reverse using http://en.wikipedia.org/wiki/Reverse_Polish_notation, which fits very nicely as each node contains either a value or a function to perform.
It's also ~20% faster than the recursive version, so I'm pleased!

Can't return anything other than 1 or 0 from int function

I wish my first post wasn't so newbie. I've been working with openframeworks, so far so good, but as I'm new to programming I'm having a real headache returning the right value from an int function. I would like the int to increment up until the Boolean condition is met and then decrement to zero. The int is used to move through an array from beginning to end and then back. When I put the guts of the function into the method that I'm using the int in, everything works perfectly, but very messy and I wonder how computationally expensive it is to put there, it just seems that my syntactic abilities are lacking to do otherwise. Advice appreciated, and thanks in advance.
int testApp::updown(int j){
if(j==0){
arp =true;
}
else if (j==7){
arp = false;
}
if(arp == true){
j++;
}
else if(arp == false){
j--;
}
return (j);
}
and then its called like this in an audioRequest block of the library I'm working with:
for (int i = 0; i < bufferSize; i++){
if ((int)timer.phasor(sorSpeed)) {
z = updown(_j);
noteOut = notes [z];
cout<<arp;
cout<<z;
}
EDIT: For addition of some information. Removed the last condition of the second if statement, it was there because I was experiencing strange happenings where j would start walking off the end of the array.
Excerpt of testApp.h
int z, _j=0;
Boolean arp;
EDIT 2: I've revised this now, it works, apologies for asking something so rudimentary and with such terrible code to go with. I do appreciate the time that people have taken to comment here. Here are my revised .cpp and my .h files for your perusal. Thanks again.
#include "testApp.h"
#include <iostream>
using namespace std;
testApp::~testApp() {
}
void testApp::setup(){
sampleRate = 44100;
initialBufferSize = 1024;
//MidiIn.openPort();
//ofAddListener(MidiIn.newMessageEvent, this, &testApp::newMessage);
j = 0;
z= 0;
state = 1;
tuning = 440;
inputNote = 127;
octave = 4;
sorSpeed = 2;
freqOut = (tuning/32) * pow(2,(inputNote-69)/12);
finalOut = freqOut * octave;
notes[7] = finalOut+640;
notes[6] = finalOut+320;
notes[5] = finalOut+160;
notes[4] = finalOut+840;
notes[3] = finalOut+160;
notes[2] = finalOut+500;
notes[1] = finalOut+240;
notes[0] = finalOut;
ofSoundStreamSetup(2,0,this, sampleRate, initialBufferSize, 4);/* Call this last ! */
}
void testApp::update(){
}
void testApp::draw(){
}
int testApp::updown(int &_j){
int tmp;
if(_j==0){
arp = true;
}
else if(_j==7) {
arp = false;
}
if(arp == true){
_j++;
}
else if(arp == false){
_j--;
}
tmp = _j;
return (tmp);
}
void testApp::audioRequested (float * output, int bufferSize, int nChannels){
for (int i = 0; i < bufferSize; i++){
if ((int)timer.phasor(sorSpeed)) {
noteOut = notes [updown(z)];
}
mymix.stereo(mySine.sinewave(noteOut),outputs,0.5);
output[i*nChannels ] = outputs[0];
output[i*nChannels + 1] = outputs[1];
}
}
testApp.h
class testApp : public ofBaseApp{
public:
~testApp();/* destructor is very useful */
void setup();
void update();
void draw();
void keyPressed (int key);
void keyReleased(int key);
void mouseMoved(int x, int y );
void mouseDragged(int x, int y, int button);
void mousePressed(int x, int y, int button);
void mouseReleased(int x, int y, int button);
void windowResized(int w, int h);
void dragEvent(ofDragInfo dragInfo);
void gotMessage(ofMessage msg);
void newMessage(ofxMidiEventArgs &args);
ofxMidiIn MidiIn;
void audioRequested (float * input, int bufferSize, int nChannels); /* output method */
void audioReceived (float * input, int bufferSize, int nChannels); /* input method */
Boolean arp;
int initialBufferSize; /* buffer size */
int sampleRate;
int updown(int &intVar);
/* stick you maximilian stuff below */
double filtered,sample,outputs[2];
maxiFilter filter1;
ofxMaxiMix mymix;
ofxMaxiOsc sine1;
ofxMaxiSample beats,beat;
ofxMaxiOsc mySine,myOtherSine,timer;
int currentCount,lastCount,i,j,z,octave,sorSpeed,state;
double notes[8];
double noteOut,freqOut,tuning,finalOut,inputNote;
};
It's pretty hard to piece this all together. I do think you need to go back to basics a bit, but all the same I think I can explain what is going on.
You initialise _j to 0 and then never modify the value of _j.
You therefore call updown passing 0 as the parameter every time.
updown returns a value of 1 when the input is 0.
Perhaps you meant to pass z to updown when you call it, but I cannot be sure.
Are you really declaring global variables in your header file? That's not good. Try to use local variables and/or parameters as much as possible. Global variables are pretty evil, especially declared in the header file like that!

c++ Floodfill algorithm final errors

My floodfilling algorithm is nearly finished, but there is a small error somewhere, I've spent about 3 hours debugging, but i can't seem to find it!
note:
When reading in I use numbers from 0 to 15 to define the walls
1 = top
2 = right
4 = bottom
8 = left
(so 13 would mean that the top/bottom/left walls are there)
My Program:
It reads in number of fields to calculate the biggest room from (so everything below here is a cycle that gets repeated for the number of fields).
Then it gets the room's dimensions
Now in the class field, it creates an array of objects (Cell) which store the walls around (left right down up), and a value below 16
Now here is where I think the problem comes, reading in values through std::cin
and then when everything is read in, it scans for empty (0), and then creates a room, and checks for availeble spaces around it (using the wall-check)
and at the end it returns the max value, and we are done.
The input I use:
1
2 2
13 3
15 14
so what happens is is that somewhere, in or the wall-check, or the creation of a object Cell something goes wrong (I think)
Here is my script, and sorry to have to ask something silly like this!
Thanks in advance
// een simpele floodfill
#include <stdlib.h>
#include <iostream>
#include <bitset>
class Cell {
private:
int kamer, value;
bool left, right, up, down;
public:
// constructor
Cell::Cell() {};
// functions
bool CanLeft() { return left ; }
bool CanRight() { return right; }
bool CanDown() { return down ; }
bool CanUp() { return up ; }
int GetRoom() { return kamer; }
void SetRoom(int x) { kamer = x ; }
void SetValue(int x, int room=0) { value = x;
kamer = room;
std::bitset<sizeof(int)> bits(value);
if (bits[3]) left = true;
else left = false;
if (bits[2]) down = true;
else down = false;
if (bits[1]) right = true;
else right = false;
if (bits[0]) up = true;
else up = false;
}
};
class Field {
private:
int Biggest_Chamber;
int Y;
int X;
int temp;
Cell playfield[][1];
public:
// constructor
Field::Field(int SizeY, int SizeX) {
Y = SizeY;
X = SizeX;
Cell playfield[SizeY-1][SizeX-1];
}
// Create a 2d array and fill it
void Get_input() {
for (int Yas = 0; Yas < Y; Yas++){
for (int Xas = 0; Xas < X; Xas++){
std::cin >> temp;
playfield[Yas][Xas].SetValue(temp);
}
}
};
void Start() { Mark(0,0,1); }
void Mark(int y, int x, int nr) {
std::cout << nr;
temp = nr;
playfield[y][x].SetRoom(nr);
if (playfield[y][x].CanLeft()) {
if (playfield[y][x-1].GetRoom() != 0) {
Mark(y, x-1, nr);
std::cout << nr;
system("pause");}}
if (playfield[y][x].CanDown()) {
if (playfield[y+1][x].GetRoom() != 0) {
Mark(y+1, x, nr);
std::cout << nr;
system("pause");}}
if (playfield[y][x].CanRight()) {
if (playfield[y][x+1].GetRoom() != 0) {
Mark(y, x+1, nr);
std::cout << nr;
system("pause");}}
if (playfield[y][x].CanUp()) {
if (playfield[y-1][x].GetRoom() != 0) {
Mark(y-1, x, nr);
std::cout << nr;
system("pause");}}
for (int vertical = 0; vertical < Y; vertical++) {
for (int horizontal = 0; horizontal < X; horizontal++) {
if (playfield[vertical][horizontal].GetRoom() == 0) Mark(vertical, horizontal, nr+1);
}
}
}
int MaxValue() {
int counter[temp];
int max = 0;
for (int y = 0; y < Y; y++) {
for (int x = 0; x < X; x++) {
counter[playfield[y][x].GetRoom()]++;
}
}
for (int i = 0; i < temp; i++)
{
if (counter[i] > max)
max = counter[i];
}
return max;
}
};
int main() {
using namespace std;
int NrKamers;
int sizeY;
int sizeX;
std::cin >> NrKamers;
for (int i = 0; i < NrKamers; i++){
std::cin >> sizeY >> sizeX;
Field floodfield(sizeY, sizeX);
floodfield.Get_input();
floodfield.Start();
std::cout << floodfield.MaxValue() << std::endl;
}
return 0;
}
I have not had much time to deal with the code, but my first impression is that you are not marking (or rather not using the mark) each visited position in the array, so that you move in one direction, and while processing that other position you return back to the original square. Consider that the sequence of tests where: left, right, up, down; and that you start in the top-left corner:
You cannot move left, but you can move right. At that second recursion level you can move left and go back to square one. Then you cannot move left, but you can move right, so you go back to square two, from which you move to square one... infinitedly.
Before you move to the next square you have to mark your square as visited, and also check that the square you intend to move to has not been visited in the current run.
The segmentation fault is the result of infinite recursion, after you exhaust the stack.
1-11-2017: NEW-VERSION; SUCCESFULLY TESTED WITH TWO BITMAPS.
I propose my C version of the Flood-Fill algorithm, which doesn't uses recursive calls, but only a queue of the offsets of the new points, it works on the window: WinnOffs-(WinDimX,WinDimY) of the double-buffer: *VBuffer (copy of the screen or image) and, optionally, it write a mask of the flood-fill's result (*ExtraVBuff).
ExtraVBuff must be filled it with 0 before the call (if you don't need a mask you may set ExtraVBuff= NULL); using it after call you can do gradient floodfill or other painting effects. NewFloodFill works with 32 Bit per Pixel and it is a C function. I've reinvented this algorithm in 1991 (I wrote his in Pascal), but now it works in C with 32 Bit per Pixel; also not uses any functions calls, does only a division after each "pop" from queue, and never overflows the queue, that, if it is sized in the right way (about 1/4 of the pixels of the image), it allows always to fill correctly any area; I show before the c-function (FFILL.C), after the test program (TEST.C):
#define IMAGE_WIDTH 1024
#define IMAGE_HEIGHT 768
#define IMAGE_SIZE IMAGE_WIDTH*IMAGE_HEIGHT
#define QUEUE_MAX IMAGE_SIZE/4
typedef int T_Queue[QUEUE_MAX];
typedef int T_Image[IMAGE_SIZE];
void NewFloodFill(int X,
int Y,
int Color,
int BuffDimX,
int WinOffS,
int WinDimX,
int WinDimY,
T_Image VBuffer,
T_Image ExtraVBuff,
T_Queue MyQueue)
/* Replaces all pixels adjacent to the first pixel and equal to this; */
/* if ExtraVBuff == NULL writes to *VBuffer (eg BUFFER of 786432 Pixel),*/
/* otherwise prepare a mask by writing on *ExtraVBuff (such BUFFER must */
/* always have the same size as *VBuffer (it must be initialized to 0)).*/
/* X,Y: Point coordinates' of origin of the flood-fill. */
/* WinOffS: Writing start offset on *VBuffer and *ExtraVBuff. */
/* BuffDimX: Width, in number of Pixel (int), of each buffer. */
/* WinDimX: Width, in number of Pixel (int), of the window. */
/* Color: New color that replace all_Pixel == origin's_point. */
/* WinDimY: Height, in number of Pixel (int), of the window. */
/* VBuffer: Pointer to the primary buffer. */
/* ExtraVBuff: Pointer to the mask buffer (can be = NULL). */
/* MyQueue: Pointer to the queue, containing the new-points' offsets*/
{
int VBuffCurrOffs=WinOffS+X+Y*BuffDimX;
int PixelIn=VBuffer[VBuffCurrOffs];
int QueuePnt=0;
int *TempAddr=((ExtraVBuff) ? ExtraVBuff : VBuffer);
int TempOffs1;
int TempX1;
int TempX2;
char FLAG;
if (0<=X && X<WinDimX && 0<=Y && Y<WinDimY) do
{
/* Fill to left the current line */
TempX2=X;
while (X>=0 && PixelIn==VBuffer[VBuffCurrOffs])
{
TempAddr[VBuffCurrOffs--]=Color;
--X;
}
TempOffs1=VBuffCurrOffs+1;
TempX1=X+1;
/* Fill to right the current line */
VBuffCurrOffs+=TempX2-X;
X=TempX2;
while (X+1<WinDimX && PixelIn==VBuffer[VBuffCurrOffs+1])
{
++X;
TempAddr[++VBuffCurrOffs]=Color;
}
TempX2=X;
/* Backward scan of the previous line; puts new points offset in Queue[] */
if (Y>0)
{
FLAG=1;
VBuffCurrOffs-=BuffDimX;
while (X-->=TempX1)
{
if (PixelIn!=VBuffer[VBuffCurrOffs] ||
ExtraVBuff && Color==ExtraVBuff[VBuffCurrOffs])
FLAG=1;
else
if (FLAG)
{
FLAG=0;
if (QueuePnt<QUEUE_MAX)
MyQueue[QueuePnt++]=VBuffCurrOffs;
}
--VBuffCurrOffs;
}
}
/* Forward scan of the next line; puts new points offset in Queue[] */
if (Y<WinDimY-1)
{
FLAG=1;
VBuffCurrOffs=TempOffs1+BuffDimX;
X=TempX1;
while (X++<=TempX2)
{
if (PixelIn!=VBuffer[VBuffCurrOffs] ||
ExtraVBuff && Color==ExtraVBuff[VBuffCurrOffs])
FLAG=1;
else
if (FLAG)
{
FLAG=0;
if (QueuePnt<QUEUE_MAX)
MyQueue[QueuePnt++]=VBuffCurrOffs;
}
++VBuffCurrOffs;
}
}
/* Gets a new point offset from Queue[] */
if (--QueuePnt>=0)
{
VBuffCurrOffs=MyQueue[QueuePnt];
TempOffs1=VBuffCurrOffs-WinOffS;
X=TempOffs1%BuffDimX;
Y=TempOffs1/BuffDimX;
}
/* Repeat the main cycle until the Queue[] is not empty */
} while (QueuePnt>=0);
}
Here there is the test program:
#include <stdio.h>
#include <malloc.h>
#include "ffill.c"
#define RED_COL 0xFFFF0000
#define WIN_LEFT 52
#define WIN_TOP 48
#define WIN_WIDTH 920
#define WIN_HEIGHT 672
#define START_LEFT 0
#define START_TOP 671
#define BMP_HEADER_SIZE 54
typedef char T_Image_Header[BMP_HEADER_SIZE];
void main(void)
{
T_Image_Header bmpheader;
T_Image *image;
T_Image *mask;
T_Queue *MyQueue;
FILE *stream;
char *filename1="ffill1.bmp";
char *filename2="ffill2.bmp";
char *filename3="ffill3.bmp";
int bwritten;
int bread;
image=malloc(sizeof(*image));
mask=malloc(sizeof(*mask));
MyQueue=malloc(sizeof(*MyQueue));
stream=fopen(filename1,"rb");
bread=fread(&bmpheader, 1, BMP_HEADER_SIZE, stream);
bread=fread((char *)image, 1, IMAGE_SIZE<<2, stream);
fclose(stream);
memset(mask,0,IMAGE_SIZE<<2);
NewFloodFill(START_LEFT,
START_TOP,
RED_COL,
IMAGE_WIDTH,
IMAGE_WIDTH*WIN_TOP+WIN_LEFT,
WIN_WIDTH,
WIN_HEIGHT,
*image,
NULL,
*MyQueue);
stream=fopen(filename2,"wb+");
bwritten=fwrite(&bmpheader, 1, BMP_HEADER_SIZE, stream);
bwritten=fwrite((char *)image, 1, IMAGE_SIZE<<2, stream);
fclose(stream);
stream=fopen(filename3,"wb+");
bwritten=fwrite(&bmpheader, 1, BMP_HEADER_SIZE, stream);
bwritten=fwrite((char *)mask, 1, IMAGE_SIZE<<2, stream);
fclose(stream);
free(MyQueue);
free(mask);
free(image);
}
I've used, for the input of the test program shown, the follow Windows uncompressed .BMP image (ffill1.bmp):
Filled, by the test program shown, as follows (ffill2.bmp):
Using "mask" instead of NULL, the output bitmap is (ffill3.bmp):