How to program a fractal? - theory

I do not have any experience with programming fractals. Of course I've seen the famous Mandelbrot images and such.
Can you provide me with simple algorithms for fractals.
Programming language doesn't matter really, but I'm most familiar with actionscript, C#, Java.
I know that if I google fractals, I get a lot of (complicated) information but I would like to start with a simple algorithm and play with it.
Suggestions to improve on the basic algorithm are also welcome, like how to make them in those lovely colors and such.

Programming the Mandelbrot is easy.
My quick-n-dirty code is below (not guaranteed to be bug-free, but a good outline).
Here's the outline:
The Mandelbrot-set lies in the Complex-grid completely within a circle with radius 2.
So, start by scanning every point in that rectangular area.
Each point represents a Complex number (x + yi).
Iterate that complex number:
[new value] = [old-value]^2 + [original-value] while keeping track of two things:
1.) the number of iterations
2.) the distance of [new-value] from the origin.
If you reach the Maximum number of iterations, you're done.
If the distance from the origin is greater than 2, you're done.
When done, color the original pixel depending on the number of iterations you've done.
Then move on to the next pixel.
public void MBrot()
{
float epsilon = 0.0001; // The step size across the X and Y axis
float x;
float y;
int maxIterations = 10; // increasing this will give you a more detailed fractal
int maxColors = 256; // Change as appropriate for your display.
Complex Z;
Complex C;
int iterations;
for(x=-2; x<=2; x+= epsilon)
{
for(y=-2; y<=2; y+= epsilon)
{
iterations = 0;
C = new Complex(x, y);
Z = new Complex(0,0);
while(Complex.Abs(Z) < 2 && iterations < maxIterations)
{
Z = Z*Z + C;
iterations++;
}
Screen.Plot(x,y, iterations % maxColors); //depending on the number of iterations, color a pixel.
}
}
}
Some details left out are:
1.) Learn exactly what the Square of a Complex number is and how to calculate it.
2.) Figure out how to translate the (-2,2) rectangular region to screen coordinates.

You should indeed start with the Mandelbrot set, and understand what it really is.
The idea behind it is relatively simple. You start with a function of complex variable
f(z) = z2 + C
where z is a complex variable and C is a complex constant. Now you iterate it starting from z = 0, i.e. you compute z1 = f(0), z2 = f(z1), z3 = f(z2) and so on. The set of those constants C for which the sequence z1, z2, z3, ... is bounded, i.e. it does not go to infinity, is the Mandelbrot set (the black set in the figure on the Wikipedia page).
In practice, to draw the Mandelbrot set you should:
Choose a rectangle in the complex plane (say, from point -2-2i to point 2+2i).
Cover the rectangle with a suitable rectangular grid of points (say, 400x400 points), which will be mapped to pixels on your monitor.
For each point/pixel, let C be that point, compute, say, 20 terms of the corresponding iterated sequence z1, z2, z3, ... and check whether it "goes to infinity". In practice you can check, while iterating, if the absolute value of one of the 20 terms is greater than 2 (if one of the terms does, the subsequent terms are guaranteed to be unbounded). If some z_k does, the sequence "goes to infinity"; otherwise, you can consider it as bounded.
If the sequence corresponding to a certain point C is bounded, draw the corresponding pixel on the picture in black (for it belongs to the Mandelbrot set). Otherwise, draw it in another color. If you want to have fun and produce pretty plots, draw it in different colors depending on the magnitude of abs(20th term).
The astounding fact about fractals is how we can obtain a tremendously complex set (in particular, the frontier of the Mandelbrot set) from easy and apparently innocuous requirements.
Enjoy!

If complex numbers give you a headache, there is a broad range of fractals that can be formulated using an L-system. This requires a couple of layers interacting, but each is interesting in it own right.
First you need a turtle. Forward, Back, Left, Right, Pen-up, Pen-down. There are lots of fun shapes to be made with turtle graphics using turtle geometry even without an L-system driving it. Search for "LOGO graphics" or "Turtle graphics". A full LOGO system is in fact a Lisp programming environment using an unparenthesized Cambridge Polish syntax. But you don't have to go nearly that far to get some pretty pictures using the turtle concept.
Then you need a layer to execute an L-system. L-systems are related to Post-systems and Semi-Thue systems, and like virii, they straddle the border of Turing Completeness. The concept is string-rewriting. It can be implemented as a macro-expansion or a procedure set with extra controls to bound the recursion. If using macro-expansion (as in the example below), you will still need a procedure set to map symbols to turtle commands and a procedure to iterate through the string or array to run the encoded turtle program. For a bounded-recursion procedure set (eg.), you embed the turtle commands in the procedures and either add recursion-level checks to each procedure or factor it out to a handler function.
Here's an example of a Pythagoras' Tree in postscript using macro-expansion and a very abbreviated set of turtle commands. For some examples in python and mathematica, see my code golf challenge.

There is a great book called Chaos and Fractals that has simple example code at the end of each chapter that implements some fractal or other example. A long time ago when I read that book, I converted each sample program (in some Basic dialect) into a Java applet that runs on a web page. The applets are here: http://hewgill.com/chaos-and-fractals/
One of the samples is a simple Mandelbrot implementation.

Another excellent fractal to learn is the Sierpinski Triangle Fractal.
Basically, draw three corners of a triangle (an equilateral is preferred, but any triangle will work), then start a point P at one of those corners. Move P halfway to any of the 3 corners at random, and draw a point there. Again move P halfway towards any random corner, draw, and repeat.
You'd think the random motion would create a random result, but it really doesn't.
Reference: http://en.wikipedia.org/wiki/Sierpinski_triangle

The Sierpinski triangle and the Koch curve are special types of flame fractals. Flame fractals are a very generalized type of Iterated function system, since it uses non-linear functions.
An algorithm for IFS:es are as follows:
Start with a random point.
Repeat the following many times (a million at least, depending on final image size):
Apply one of N predefined transformations (matrix transformations or similar) to the point. An example would be that multiply each coordinate with 0.5.
Plot the new point on the screen.
If the point is outside the screen, choose randomly a new one inside the screen instead.
If you want nice colors, let the color depend on the last used transformation.

I would start with something simple, like a Koch Snowflake. It's a simple process of taking a line and transforming it, then repeating the process recursively until it looks neat-o.
Something super simple like taking 2 points (a line) and adding a 3rd point (making a corner), then repeating on each new section that's created.
fractal(p0, p1){
Pmid = midpoint(p0,p1) + moved some distance perpendicular to p0 or p1;
fractal(p0,Pmid);
fractal(Pmid, p1);
}

I think you might not see fractals as an algorithm or something to program. Fractals is a concept! It is a mathematical concept of detailed pattern repeating itself.
Therefore you can create a fractal in many ways, using different approaches, as shown in the image below.
Choose an approach and then investigate how to implement it. These four examples were implemented using Marvin Framework. The source codes are available here

Here is a codepen that I wrote for the Mandelbrot fractal using plain javascript and HTML.
Hopefully it is easy to understand the code.
The most complicated part is scale and translate the coordinate systems. Also complicated is making the rainbow palette.
function mandel(x,y) {
var a=0; var b=0;
for (i = 0; i<250; ++i) {
// Complex z = z^2 + c
var t = a*a - b*b;
b = 2*a*b;
a = t;
a = a + x;
b = b + y;
var m = a*a + b*b;
if (m > 10) return i;
}
return 250;
}

The mandelbrot set is generated by repeatedly evaluating a function until it overflows (some defined limit), then checking how long it took you to overflow.
Pseudocode:
MAX_COUNT = 64 // if we haven't escaped to infinity after 64 iterations,
// then we're inside the mandelbrot set!!!
foreach (x-pixel)
foreach (y-pixel)
calculate x,y as mathematical coordinates from your pixel coordinates
value = (x, y)
count = 0
while value.absolutevalue < 1 billion and count < MAX_COUNT
value = value * value + (x, y)
count = count + 1
// the following should really be one statement, but I split it for clarity
if count == MAX_COUNT
pixel_at (x-pixel, y-pixel) = BLACK
else
pixel_at (x-pixel, y-pixel) = colors[count] // some color map.
Notes:
value is a complex number. a complex number (a+bi) is squared to give (aa-b*b+2*abi). You'll have to use a complex type, or include that calculation in your loop.

Sometimes I program fractals for fun and as a challenge. You can find them here. The code is written in Javascript using the P5.js library and can be read directly from the HTML source code.
For those I have seen the algorithms are quite simple, just find the core element and then repeat it over and over. I do it with recursive functions, but can be done differently.

People above are using finding midpoints for sierpinski and Koch, I'd much more recommend copying shapes, scaling them, and then translating them to achieve the "fractal" effect.
Pseudo-code in Java for sierpinski would look something like this:
public ShapeObject transform(ShapeObject originalCurve)
{
Make a copy of the original curve
Scale x and y to half of the original
make a copy of the copied shape, and translate it to the right so it touches the first copied shape
make a third shape that is a copy of the first copy, and translate it halfway between the first and second shape,and translate it up
Group the 3 new shapes into one
return the new shape
}

Related

Uniform random sampling of CIELUV for RGB colors

Selecting a random color on a computer is a touch harder than I thought it would be.
The naive way of uniform random sampling of 0..255 for R,G,B will tend to draw lots of similar greens. It would make sense to sample from a perceptually uniform space like CIELUV.
A simple way to do this is to sample L,u,v on a regular mesh and ensure the color solid is contained in the bounds (I've seen different bounds for this). If the sample falls outside embedded RGB solid (tested by mapping it XYZ then RGB), reject it and sample again. You can settle for a kludgy-but-guaranteed-to-terminate "bailout" selection (like the naive procedure) if you reject more then some arbitrary threshold number of times.
Testing if the sample lies within RGB needs to be sure to test for the special case of black (some implementations end up being silent on the divide by zero), I believe. If L=0 and either u!=0 or v!=0, then the sample needs to be rejected or else you would end up oversampling the L=0 plane in Luv space.
Does this procedure have an obvious flaw? It seems to work but I did notice that I was rolling black more often than I thought made sense until I thought about what was happening in that case. Can anyone point me to the right bounds on the CIELUV grid to ensure that I am enclosing the RGB solid?
A useful reference for those who don't know it:
https://www.easyrgb.com/en/math.php
The key problem with this is that you need bounds to reject samples that fall outside of RGB. I was able to find it worked out here (nice demo on page, API provides convenient functions):
https://www.hsluv.org/
A few things I noticed with uniform sampling of CIELUV in RGB:
most colors are green and purple (this is true independent of RGB bounds)
you have a hard time sampling what we think of as yellow (very small volume of high lightness, high chroma space)
I implemented various strategies that focus on sampling hues (which is really what we want when we think of "sampling colors") by weighting according to the maximum chromas at that lightness. This makes colors like chromatic light yellows easier to catch and avoids oversampling greens and purples. You can see these methods in actions here (select "randomize colors"):
https://www.mysticsymbolic.art/
Source for color randomizers here:
https://github.com/mittimithai/mystic-symbolic/blob/chromacorners/lib/random-colors.ts
Okay, while you don't show the code you are using to generate the random numbers and then apply them to the CIELUV color space, I'm going to guess that you are creating a random number 0.0-100.0 from a random number generator, and then just assigning it to L*.
That will most likely give you a lot of black or very dark results.
Let Me Explain
L* of L * u * v* is not linear as to light. Y of CIEXYZ is linear as to light. L* is perceptual lightness, so an exponential curve is applied to Y to make it linear to perception but then non-linear as to light.
TRY THIS
To get L* with a random value 0—100:
Generate a random number between 0.0 and 1.0
Then apply an exponent of 0.42
Then multiply by 100 to get L*
Lstar = Math.pow(Math.random(), 0.42) * 100;
This takes your random number that represents light, and applies a powercurve that emulates human lightness perception.
UV Color
As for the u and v values, you can probably just leave them as linear random numbers. Constrain u to about -84 and +176, and v to about -132.5 and +107.5
Urnd = (Math.random() - 0.5521) * 240;
Vrnd = (Math.random() - 0.3231) * 260;
Polar Color
It might be interesting converting uv to LChLUV or LshLUV
For hue, it's probably as simple as H = Math.random() * 360
For chroma contrained 0—178: C = Math.random() * 178
The next question is, should you find chroma? Or saturation? CIELUV can provide either Hue or Sat — but for directly generating random colors, it seems that chroma is a bit better.
And of course these simple examples are not preventing over-runs, so they color values to be tested to see if they are legal sRGB or not. There's a few things that can be done to constrain the generated values to legal colors, but the object here was to get you to a better distribution without excess black/dark results.
Please let me know of any questions.

C create a txt.ppm file from a safed textfile

PPM1
Textfile
I tried create a C code, that can create a ppm, like on the picture 1 from a textfile like on picture 3. When somemone can help, it where great. I am a new Programmer, i tried do do that Code for 6h. I tried to scan in the data from the textfile and put it in a array and try to make withe that a ppm, but my code is unusable:/.
The path forward is to split the task into smaller sub-tasks, solve and test each one of them separately, and only after they all work, combine them into a single program.
Because the OP has not posted any code, I will not post any directly useful code either. If OP is truly blocked due to not getting any forward progress even after trying, this should actually be of practical use. If OP is just looking for someone to do their homework, this should annoy them immensely. Both work for me. :)
First sub-task is to read the input in an array. There are several examples on the web, and related questions here. You'll want to put this in a separate function, so merging into the complete project later on is easier. Since you are a beginner programmer, you could go for a function like
int read_numbers(double data[], int max);
so that the caller declares the maximum number of data points, and the function returns the number of data points read; or negative if an error occurs. Your main() for testing that function should be trivial, say
#define MAX_NUMBERS 500
int main(void)
{
double x[MAX_NUMBERS];
int i, n;
n = read_numbers(x, MAX_NUMBERS, stdin);
if (n <= 0) {
fprintf(stderr, "Error reading numbers from standard input.\n");
return EXIT_FAILURE;
}
printf("Read %d numbers:\n", n);
for (i = 0; i < n; i++)
printf("%.6f\n", x[i]);
return EXIT_SUCCESS;
}
The second sub-task is to generate a PPM image. PPM is actually a group of closely related image formats, also called Netpbm formats. The example image is a bitmap image -- black and white only; no colors, no shades of gray --, so the PBM format (or variant of PPM) is suitable for this.
I suspect it is easiest to attack this sub-task by using a two-dimensional array, sized for the largest image you can generate (i.e. unsigned char bitmap[HEIGHT_MAX][WIDTH_MAX];), but note that you can also just use a part of it. (You could also generate the image on the fly, without any array, but that is much more error prone, and not as universally applicable as using an array to store the image is.)
You'll probably need to decide the width of the bitmap based on the maximum data value, and the height of the bitmap based on the number of data points.
For testing, just fill the array with some simple patterns, or maybe just a diagonal line from top left corner to bottom right corner.
Then, consider writing a function that sets a rectangular area to a given value (0 or 1). Based on the image, you'll also need a function that draws vertical dotted lines, changing (exclusive-OR'ing) the state of each bit. For example,
#define WIDTH_MAX 1024
#define HEIGHT_MAX 768
unsigned char bitmap[HEIGHT_MAX][WIDTH_MAX];
int width = 0;
int height = 0;
void write_pbm(FILE *out); /* Or perhaps (const char *filename)? */
void fill_rect(int x, int y, int w, int h, unsigned char v);
void vline_xor(int x, int y, int h);
At this point, you should have realized that the write_pbm() function, the one that saves the PBM image, should be written and tested first. Then, you can use the fill_rect() function to not just draw filled rectangles, but also to initialize the image -- the portion of the array you are going to use -- to a background color (0 or 1). All of the three functions above you can, and should, do in separate sub-steps, so that at any point you can rely on that the code you've written earlier is correct and tested. That way, you only need to look at bugs in the code you have written since the last successful testing! It might sound like a slow way to progress, but it actually turns out to be the fastest way to get code working. You very quickly start to love the confidence the testing gives you, and the fact that you only need to focus and worry about one thing at a time.
The third sub-task is to find out a way to draw the rectangles and vertical dotted lines, for various inputs.
(I cheated a bit, above, and included the fill_rect() and vline_xor() functions in the previous sub-task, because I could tell those are needed to draw the example picture.)
The vertical dotted lines are easiest to draw afterwards, using a function that draws a vertical line, leaving every other pixel untouched, but exclusive-ors every other pixel. (Hint: for (y = y0; y < y0 + height; y += 2) bitmap[y][x] ^= 1;)
That leaves the filled rectangles. Their height is obviously constant, and they have a bit of vertical space in between, and they start at the left edge; so, the only thing, is to calculate how wide each rectangle needs to be. (And, how wide the entire bitmap should be, and how tall, as previously mentioned; the largest data value, and the number of data values, dictates those.)
Rather than writing one C source file, and adding to it every step, I recommend you write a separate program for each of the sub-steps. That is, after every time you get a sub-part working, you save that as a separate file, and keep it for reference -- a back-up, if you will. If you lose your way completely, or decide on another path for solving some problem, you only need to revert back to your last reference version, rather than start from scratch.
That kind of work-flow is known to be reliable, efficient, and scalable: it does not matter how large the project is, the above approach works. Of course, there are tools to help us do this in an easy, structured manner (with comments on each commit -- completed unit of code, if you will); and git is a popular, free, but very powerful one. Just do a web search for git for beginners if you are interested in it.
If you bothered to read all through the above wall of text, and grasped the work flow it describes, you won't have much trouble learning how to use tools like git to help you with the workflow. You'll also love how much typing tools like make (and the Makefiles containing the make recipes) help, and how easy it is to make and maintain projects that not only work, but also look professional. Yet, don't try to grasp all of it at once: take it one small step at a time, and verify you have a solid footing, before going onwards. That way, when you stumble, you won't hurt yourself; just learn.
Have fun!

Following 3D Spiral Path

I would like to produce a realistic 3D demonstration of a ball rolling down a Conical Helix path. The reference that has helped me get close to a solution can be found here. [I am creating my solution in Actionscript 3, using Stage3D, but would be happy to have any suggested coding solutions in other languages, using other 3D frameworks, with which you may be more familiar.]
As I entered the title for my posting, the system pointed me to a wealth of "Questions that may already have your answer", and that was helpful, and I did check each of them out. Without wanting to hijack an existing thread, I should say that this oneincludes a good deal of very helpful commentary about the general subject, but does not get to the specific challenges I have been unable to resolve.
Using the cited reference, I am happy with this code snippet that traces the path I would like the ball to follow. [N.B. My reference, and most other math-based references, treat Z as being up-down; my usage, however, is the more usual 3D graphics of Y for up-down.]
This code is executed for each frame.
ft += 0.01; // Where ft is a global Number.
var n:Number = Math.pow (0.5, (0.15 * ft));
// Where s is a constant used to scale the overall path.
obj.moveTo (
(s * n * Math.cos (2.0 * ft)),
(s * n),
(s * n * Math.sin (2.0 * ft))
);
The ball follows a nice path, and owing to the lighting and other shader code, a very decent effect is viewed in the scene.
What is not good about my current implementation is that the ball does not appear to be rolling along that path as it moves from point to point. I am not using any physics engine, and am not seeking any solution dealing with collisions, but I would like the ball to correctly demonstrate what would be happening if the movement were due to the ball rolling down a track.
So, to make a little more clear the challenge, let's say that the ball is a billiard ball with the stripe and label for #15. In that case, the visual result should be that the number 15 should be turning head over heals, but, as you can probably surmise from the name of my obj.moveTo() function, that only results in changes in position of the 3D object, not its orientation.
That, finally, brings me to the specific question/request. I have been unable to discover what rotation changes must be synchronized with each positional change in order to correctly demonstrate the way the billiard ball would appear if it rolled from point 1 from point 2 along the path.
Part of the solution appears to be:
obj.setRotation ((Math.atan2 (Math.sin (ft), Math.cos (ft))), Vector3D.Y_AXIS);
but that is still not correct. I hope there is some well-known formula that I can add to my render code.

Source engine styled rope rendering

I am creating a 3D graphics engine and one of the requirements is ropes that behave like in Valve's source engine.
So in the source engine, a section of rope is a quad that rotates along it's direction axis to face the camera, so if the section of rope is in the +Z direction, it will rotate along the Z axis so it's face is facing the camera's centre position.
At the moment, I have the sections of ropes defined, so I can have a nice curved rope, but now I'm trying to construct the matrix that will rotate it along it's direction vector.
I already have a matrix for rendering billboard sprites based on this billboarding technique:
Constructing a Billboard Matrix
And at the moment I've been trying to retool it so that Right, Up, Forward vector match the rope segment's direction vector.
My rope is made up of multiple sections, each section is a rectangle made up of two triangles, as I said above, I can get the position and sections perfect, it's the rotating to face the camera that's causing me a lot of problems.
This is in OpenGL ES2 and written in C.
I have studied Doom 3's beam rendering code in Model_beam.cpp, the method used there is to calculate the offset based on normals rather than using matrices, so I have created a similar technique in my C code and it sort of works, at least it, works as much as I need it to right now.
So for those who are also trying to figure this one out, use the cross-product of the mid-point of the rope against the camera position, normalise that and then multiply it to how wide you want the rope to be, then when constructing the vertices, offset each vertex in either + or - direction of the resulting vector.
Further help would be great though as this is not perfect!
Thank you
Check out this related stackoverflow post on billboards in OpenGL It cites a lighthouse3d tutorial that is a pretty good read. Here are the salient points of the technique:
void billboardCylindricalBegin(
float camX, float camY, float camZ,
float objPosX, float objPosY, float objPosZ) {
float lookAt[3],objToCamProj[3],upAux[3];
float modelview[16],angleCosine;
glPushMatrix();
// objToCamProj is the vector in world coordinates from the
// local origin to the camera projected in the XZ plane
objToCamProj[0] = camX - objPosX ;
objToCamProj[1] = 0;
objToCamProj[2] = camZ - objPosZ ;
// This is the original lookAt vector for the object
// in world coordinates
lookAt[0] = 0;
lookAt[1] = 0;
lookAt[2] = 1;
// normalize both vectors to get the cosine directly afterwards
mathsNormalize(objToCamProj);
// easy fix to determine wether the angle is negative or positive
// for positive angles upAux will be a vector pointing in the
// positive y direction, otherwise upAux will point downwards
// effectively reversing the rotation.
mathsCrossProduct(upAux,lookAt,objToCamProj);
// compute the angle
angleCosine = mathsInnerProduct(lookAt,objToCamProj);
// perform the rotation. The if statement is used for stability reasons
// if the lookAt and objToCamProj vectors are too close together then
// |angleCosine| could be bigger than 1 due to lack of precision
if ((angleCosine < 0.99990) && (angleCosine > -0.9999))
glRotatef(acos(angleCosine)*180/3.14,upAux[0], upAux[1], upAux[2]);
}

Understanding this C function

I'm trying to understand how this function works, I have studied several algorithms to generate sudoku puzzles and found out this one.
Tested the function and it does generates a valid 9x9 Latin Square (Sudoku) Grid.
My problem is that I can't understand how the function works, i do know the struct is formed by to ints, p and b , p will hold the number for the cell in the table, But after that I don't understand why it creates more arrays (tab 1 and tab2) and how it checks for a latin square =/ etc , summarizing , I'm completely lost.
I'm not asking for a line by line explanation, the general concept behind this function.
would help me a lot !
Thanks again <3
int sudoku(struct sudoku tabla[9][9],int x,int y)
{
int tab[9] = {1,1,1,1,1,1,1,1,1};
int i,j;
for(i=0;i<y;++i)
{
tab[tabla[x][i].p-1]=0;
for(i=0;i<x;++i)
{
tab[tabla[i][y].p-1]=0;
}
for(i=(3*(x/3));i<(3*(x/3)+3);++i)
{
for(j=(3*(y/3));j<y;++j)
{
tab[tabla[i][j].p-1]=0;
}
}
int n=0;
for(i=0;i<9;++i)
{
n=n+tab[i];
}
int *tab2;
tab2=(int*)malloc(sizeof(int)*n);
j=0;
for(i=0;i<9;++i)
{ if(tab[i]==1)
{
tab2[j]=i+1;
j++;
}
}
int ny, nx;
if(x==8)
{
ny=y+1;
nx=0;
}
else
{
ny=y;
nx=x+1;
}
while(n>0)
{
int los=rand()%n;
tabla[x][y].p=tab2[los];
tab2[los]=tab2[n-1];
n--;
if(x==8 && y==8)
{
return 1;
}
if (sudoku(tabla,nx,ny)==1)
{
return 1;
}
}
return 0;
}
EDIT
Great, I now understand the structure, thanks lijie's answer. What I still don't understand is the part that tries out the values in random order). I don't understand how it checks if the random value placement is valid without calling the part of the code that checks if the movement is legal, also, after placing the random numbers is it necessary to check if the grid is valid again? –
Basically, the an invocation of the function fills in the positions at and "after" (x, y) in the table tabla, and the function assumes that the positions "prior" to (x, y) are filled, and returns whether a legal "filling in" of the values is possible.
The board is linearized via increasing x, then y.
The first part of the function finds out the values that are legal at (x, y), and the second part tries out the values in a random order, and attempts fills out the rest of the board via a recursive call.
There isn't actually a point in having tab2 because tab can be reused for that purpose, and the function leaks memory (since it is never freed, but aside from these, it works).
Does this make sense to you?
EDIT
The only tricky area in the part that checks for legal number is the third loop (checking the 3x3 box). The condition for j is j < y because those values where j == y are already checked by the second loop.
EDIT2
I nitpick, but the part that counts n and fills tab2 with the legal values should really be
int n = 0;
for (i = 0; i < 9; ++i) if (tab[i]) tab[n++] = i+1;
hence omitting the need for tab2 (the later code can just use tab and n instead of tab2). The memory leak is thusly eliminated.
EDIT
Note that the randomness is only applied to valid values (the order of trying the values is randomized, not the values themselves).
The code follows a standard exhaustive search pattern: try each possible candidate value, immediately returning if the search succeeds, and backtracking with failure if all the candidate values fail.
Try to solve sudoku yourself, and you'll see that there is inherent recursion in finding a solution to it. So, you have function that calls itself until whole board is solved.
As for code, it can be significantly simplified, but it will be for the best if you try to write one yourself.
EDIT:
Here is one from java, maybe it will be similar to what you are trying to do.
A quick description of the principles - ignoring the example you posted. Hopefully with the idea, you can tie it to the example yourself.
The basic approach is something that was the basis of a lot of "Artificial Intelligence", at least as it was seen until about the end of the 80s. The most general solution to many puzzles is basically to try all possible solutions.
So, first you try all possible solutions with a 1 in the top-left corner, then all possible solutions with a 2 in the top-left corner and so on. You recurse to try the options for the second position, third position and so on. This is called exhaustive search - or "brute force".
Trouble is it takes pretty much forever - but you can short-cut a lot of pointless searching.
For example, having placed a 1 in the top-left corner, you recurse. You place a 1 in the next position and recurse again - but now you detect that you've violated two rules (two ones in a row, two ones in a 3x3 block) even without filling in the rest of the board. So you "backtrack" - ie exit the recursion to the previous level and advance to putting a 2 in that second position.
This avoids a lot of searching, and makes things practical. There are further optimisations, as well, if you keep track of the digits still unused in each row, column and block - think about the intersection of those sets.
What I described is actually a solution algorithm (if you allow for some cells already being filled in). Generating a random solved sudoku is the same thing but, for each digit position, you have to try the digits in random order. This also leaves the problem of deciding which cells to leave blank while ensuring the puzzle can still be solved and (much harder) designing puzzles with a level-of-difficulty setting. But in a way, the basic approach to those problems is already here - you can test whether a particular set of left-blank spaces is valid by running the solution algorithm and finding if (and how many) solutions you get, for example, so you can design a search for a valid set of cells left blank.
The level-of-difficulty thing is difficult because it depends on a human perception of difficulty. Hmmm - can I fit "difficult" in there again somewhere...
One approach - design a more sophisticated search algorithm which uses typical human rules-of-thumb in preference to recursive searching, and which judges difficulty as the deepest level of recursion needed. Some rules of thumb might also be judged more advanced than others, so that using them more counts towards difficulty. Obviously difficulty is subjective, so there's no one right answer to how precisely the scoring should be done.
That gives you a measure of difficulty for a particular puzzle. Designing a puzzle directly for a level of difficulty will be hard - but when trying different selections of cells to leave blank, you can try multiple options, keep track of all the difficulty scores, and at the end select the one that was nearest to your target difficulty level.

Resources