Uniform random sampling of CIELUV for RGB colors - rgb

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.

Related

OpenGL -- GL_LINE_LOOP --

I am using GL_LINE_LOOP to draw a circle in C and openGL! Is it possible for me to fill the circle with colors?
If needed, this is the code I'm using:
const int circle_points=100;
const float cx=50+i, cy=50+x, r=50;
const float pi = 3.14159f;
int i = 50;
glColor3f(1, 1, 1);
glBegin(GL_LINE_LOOP);
for(i=0;i<circle_points;i++)
{
const float theta=(2*pi*i)/circle_points;
glVertex2f(cx+r*cos(theta),cy+r*sin(theta));
}
glEnd();
Lookup polygon triangulation!
I hope something here is somehow useful to someone, even though this question was asked in February. There are many answers, even though a lot of people would give none. I could witter forever, but I'll try to finish before then.
Some would even say, "You never would," or, "That's not appropriate for OpenGL," I'd like to say more than them about why. Converting polygons into the triangles that OpenGL likes so much is outside of OpenGL's job-spec, and is probably better done on the processor side anyway. Calculate that stage in advance, as few times as possible, rather than repeatedly sending such a chunky problem on every draw call.
Perhaps the original questioner drifted away from OpenGL since February, or perhaps they've become an expert. Perhaps I'll re-inspire them to look at it again, to hack away at some original 'imposters'. Or maybe they'll say it's not the tool for them after all, but that would be disappointing. Whatever graphics code you're writing, you know that OpenGL can speed it up!
Triangles for convex polygons are easy
Do you just want a circle? Make a triangle fan with the shared point at the circle's origin. GL_POLYGON was, for better or worse, deprecated then killed off entirely; it will not work with current or future implementations of OpenGL.
Triangles for concave polygons are hard
You'll want more general polygons later? Well, there are some tricks you could play with, for all manner of convex polygons, but concave ones will soon get difficult. It would be easy to start five different solutions without finishing a single one. Then it would be difficult, on finishing one, to make it quick, and nearly impossible to be sure that it's the quickest.
To achieve it in a future-proofed way you really want to stick with triangles -- so "polygon triangulation" is the subject you want to search for. OpenGL will always be great for drawing triangles. Triangle strips are popular because they reuse many vertices, and a whole mesh can be covered with only triangle strips, (perhaps including the odd lone triangle or pair of triangles). Drawing with only one primitive usually means the entire mesh can be rendered with a single draw call, which could improve performance. (Number of draw calls is one performance consideration, but not always the most important.)
Polygon triangulation gets more complex when you allow convex polygons or polygons with holes. (Finding algorithms for triangulating a general polygon, robustly yet quickly, is actually an area of ongoing research. Nonetheless, you can find some pretty good solutions out there that are probably fit for purpose.)
But is this what you want?
Is a filled polygon crucial to your final goals in OpenGL? Or did you simply choose what felt like it would be a simple early lesson?
Frustratingly, although drawing a filled polygon seems like a simple thing to do -- and indeed is one of the simplest things to do in many languages -- the solution in OpenGL is likely to be quite complicated. Of course, it can be done if we're clever enough -- but that could be a lot of effort, without being the best route to take towards your later goals.
Even in languages that implement filled polygons in a way that is simple to program with, you don't always know how much strain it puts on the CPU or GPU. If you send a sequence of vertices, to be linked and filled, once every animation frame, will it be slow? If a polygon doesn't change shape, perhaps you should do the difficult part of the calculation just once? You will be doing just that, if you triangulate a polygon once using the CPU, then repeatedly send those triangles to OpenGL for rendering.
OpenGL is very, very good at doing certain things, very quickly, taking advantage of hardware acceleration. It is worth appreciating what it is and is not optimal for, to decide your best route towards your final goals with OpenGL.
If you're looking for a simple early lesson, rotating brightly coloured tetrahedrons is ideal, and happens early in most tutorials.
If on the other hand, you're planning a project that you currently envision using filled polygons a great deal -- say, a stylized cartoon rendering engine for instance -- I still advise going to the tutorials, and even more so! Find a good one; stick with it to the end; you can then think better about OpenGL functions that are and aren't available to you. What can you take advantage of? What do you need or want to redo in software? And is it worth writing your own code for apparently simple things -- like drawing filled polygons -- that are 'missing from' (or at least inappropriate to) OpenGL?
Is there a higher level graphics library, free to use -- perhaps relying on OpenGL for rasterisation -- that can already do want you want? If so, how much freedom does it give you, to mess with the nuts and bolts of OpenGL itself?
OpenGL is very good at drawing points, lines, and triangles, and hardware accelerating certain common operations such as clipping, face culling, perspective divides, perspective texture accesses (very useful for lighting) and so on. It offers you a chance to write special programs called shaders, which operate at various stages of the rendering pipeline, maximising your chance to insert your own unique cleverness while still taking advantage of hardware acceleration.
A good tutorial is one that explains the rendering pipeline and puts you in a much better position to assess what the tool of OpenGL is best used for.
Here is one such tutorial that I found recently: Learning Modern 3D Graphics Programming
by Jason L. McKesson. It doesn't appear to be complete, but if you get far enough for that to annoy you, you'll be well placed to search for the rest.
Using imposters to fill polygons
Everything in computer graphics is an imposter, but the term often has a specialised meaning. Imposters display very different geometry from what they actually have -- only more so than usual! Of course, a 3D world is very different from the pixels representing it, but with imposters, the deception goes deeper than usual.
For instance, a rectangle that OpenGL actually constructs out of two triangles can appear to be a sphere if, in its fragment shader, you write a customised depth value to the depth coordinate, calculate your own normals for lighting and so on, and discard those fragments of the square that would fall outside the outline of the sphere. (Calculating the depth on those fragments would involve a square root of a negative number, which can be used to discard the fragment.) Imposters like that are sometimes called flat cards or billboards.
(The tutorial above includes a chapter on imposters, and examples doing just what I've described here. In fact, the rectangle itself is constructed only part way through the pipeline, from a single point. I warn that the scaling of their rectangle, to account for the way that perspective distorts a sphere into an ellipse in a wide FOV, is a non-robust fudge . The correct and robust answer is tricky to work out, using mathematics that would be slightly beyond the scope of the book. I'd say it is beyond the author's algebra skills to work it out but I could be wrong; he'd certainly understand a worked example. However, when you have the correct solution, it is computationally inexpensive; it involves only linear operations plus two square roots, to find the four limits of a horizontally- or vertically-translated sphere. To generalise that technique for other displacements requires one more square root, for a vector normalisation to find the correct rotation, and one application of that rotation matrix when you render the rectangle.)
So just to suggest an original solution that others aren't likely to provide, you could use an inequality (like x * x + y * y <= 1 for a circle or x * x - y * y <= 1 for a hyperbola) or a system of inequalities (like three straight line forms to bound a triangle) to decide how to discard a fragment. Note that if inequalities have more than linear order, they can encode perfect curves, and render them just as smoothly as your pixelated screen will allow -- with no limitation on the 'geometric detail' of the curve. You can also combine straight and curved edges in a single polygon, in this way.
For instance, a fragment shader (which would be written in GLSL) for a semi-circle might have something like this:
if (y < 0) discard;
float rSq = x * x + y * y;
if (1 < rSq) discard;
// We're inside the semi-circle; put further shader computations here
However, the polygons that are easy to draw, in this way, are very different from the ones that you're used to being easy. Converting a sequence of connected nodes into inequalities means yet more code to write, and deciding on the Boolean logic, to deal with combining those inequalities, could then get quite complex -- especially for concave polygons. Performing inequalities in a sensible order, so that some can be culled based on the results of others, is another ill-posed headache of a problem, if it needs to be general, even though it is easy to hard-code an optimal solution for a single case like a square.
I suggest using imposters mainly for its contrast with the triangulation method. Something like either one could be a route to pursue, depending on what you're hoping to achieve in the end, and the nature of your polygons.
Have fun...
P.S. have a related topic... Polygon triangulation into triangle strips for OpenGL ES
As long as the link lasts, it's a more detailed explanation of 'polygon triangulation' than mine. Those are the two words to search for if the link ever dies.
A line loop is just an outline.
To fill the middle as well, you want to use GL_POLYGON.

How to identify optimal parameters for cvCanny for polygon approximation

This is my source image (ignore the points, they were added manually later):
My goal is to get a rough polygon approximation of the two hands. Something like this:
I have a general idea on how to do this; I want to use cvCanny to find edges, cvFindContours to find contours, and then cvApproxPoly.
The problem I'm facing is that I have no idea on how to properly use cvCanny, particularly, what should I use for the last 3 parameters (threshold1&2, apertureSize)? I tried doing:
cvCanny(source, cannyProcessedImage, 20, 40, 3);
but the result is not ideal. The left hand looks relatively fine but for the right hand it detected very little:
In general it's not as reliable as I'd like. Is there a way to guess the "best" parameters for Canny, or at least a detailed explanation (understandable by a beginner) of what they do so I can make educated guesses? Or perhaps there's a better way to do this altogether?
It seems you have to lower your thresholds.
The Canny algorithm work on the hysteresis threshold: it selects a contour if at least a pixel is as bright as the max threshold, and takes all the connected contour pixels if they are above the lower threshold.
Papers recommend to take the two thresholds in a scale of 2:1 oe 3:1 (by example 10 and 30, or 20 and 60, etc). For some applications, a threshold determined manually and hardcoded is enough. It may your case, too. I suspect that if you lower your thresholds, you will have good results, because the images are not that complicated.
A number of methods to automatically determine the best canny thresholds have been proposed. Most of them rely on gradient magnitudes to estimate the best thresholds.
Steps:
Extract the gradients (Sobel is a good option)
You can convert it to uchar. Gradients teoretically can have greater numerical values than 255, but that's ok. opencv's sobel returns uchars.
make a histogram of the resulting image.
take the max threshold at the 95th percentile of your histogram, and the lower as high/3.
You should probably adjust the percentile value depending on your app, but the results will be much more robust than a hardcoded hig and low values
Note: An excellent threshold detection algorithm is implemented in Matlab. It is based on the idea above, but a bit more sophisticated.
Note 2: This methods will work if the contours and illumination do not varies a lot between image areas. If the contours are crisper on one part of the image, then you need locally adaptive thresholds, and that's another story. But looking at you pics, it should not be the case.
Maybe one of the easiest solution is make Otsu thresholding on grayscale image, find contours on the binary image and than approximate them. Here's code:
Mat img = imread("test.png"), gray;
vector<Vec4i> hierarchy;
vector<vector<Point2i> > contours;
cvtColor(img, gray, CV_BGR2GRAY);
threshold(gray, gray, 0, 255, THRESH_OTSU);
findContours(gray, contours, hierarchy, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_SIMPLE);
for(size_t i=0; i<contours.size(); i++)
{
approxPolyDP(contours[i], contours[i], 5, false);
drawContours(img, contours, i, Scalar(0,0,255));
}
imshow("result", img);
waitKey();
And this is result:

Chart optimization: More than million points

I have custom control - chart with size, for example, 300x300 pixels and more than one million points (maybe less) in it. And its clear that now he works very slowly. I am searching for algoritm which will show only few points with minimal visual difference.
I have a link to the component which have functionallity exactly what i need
(2 million points demo):
I will be grateful for any matherials, links or thoughts how to realize such functionallity.
If I understand your question correctly, then you are looking to plot a graph of a dataset where you have ~1M points, but the chart's horizontal resolution is much smaller? If so, you can down-sample your dataset to get about the number of available x values. If your data is sorted in equal intervals, you can extract every N'th point and plot it. Choose N such that the number of points is, say, double the resolution (in this case, N=2000 will give you 500 points to display).
If the intervals are very different from eachother (not regularly spaced), you can approximate your graph with a polynomial, or spline or any other method that fits, and then interpolate 300-600 points from that approximation.
EDIT:
Depending on the nature of the data, you may end up with aliasing artifacts when you simply sample every N't point. There are probably better methods for coping with this problem, but again - it depends on what exactly you want to plot.
You could always buy the control - it is for sale!
John-Daniel Trask (Co-founder of Mindscape ;-)

Unprecise rendering of huge WPF visuals - any solutions?

When rendering huge visuals in WPF, the visual gets distorted and more distorted with increasing coordinates. I assume that it has something to do with the floating point data types used in the render pipeline, but I'm not completely sure. Either way, I'm searching for a practical solution to solve the problem.
To demonstrate what I'm talking about, I created a sample application which just contains a custom control embedded in a ScrollViewer that draws a sine curve.
You can see here that the drawing is alright for double values <= 2^24 (in this case the horizontal coordinate value), but from that point on it gets distorted.
The distortion gets worse at 2^25 and so the distortion continues to increase with every additional bit until it just draws some vertical lines.
For performance reasons I'm just drawing the visible part of the graph, but for layouting reasons I cannot "virtualize" the control which would make this problem obsolete. The only solution I could come up with is to draw the visible part of the graph to a bitmap, and then render the bitmap at the appropriate point - but there I have again the precision problem with big values, as I cannot accurately place the bitmap at the position where I need it.
Does anybody have an idea how to solve this?
It is not WPF's fault.
Floating point numbers get less and less precise the farther from zero they are - it is a cost of stuffing enormous data range (-Inf, +Inf) into 32 (float) / 64 (double) bits of data space. Floats actually become less precise than integer at around 2^30.
64bit integers have constant spacing (1), but have limited range of −9,223,372,036,854,775,808 to +9,223,372,036,854,775,807.
You may also consider using Decimal type (which however has also limited value range).
(update: oh didnt see how old this post was... i guess i clicked the wrong filter button in stack overflow...)
The relative precision is relevant here. So just saying "look 2^24 is fine and 2^25 is not" is not enough information. You said it is a sin, thus I guess y-axis max and min never changes between those pictures. So y-axis doesnt matter. Furthermore the x-step size stays the same, i guess? But you did not tell us the sin period length or the x-step size, you chose. That is relevant here. The relative precision of the x-size steps becomes worse when you go to higher x-values, because the x-step-size becomes too small relativly to the x-value itself.
precision of c# floating point types:
https://learn.microsoft.com/de-de/dotnet/csharp/language-reference/builtin-types/floating-point-numeric-types
example:
x-step size = 1.
x = 1 (no problem)
x = 1000 (no problem)
x = >2^23 (32 bit starts to get problems with step size = 1; 64 bit no problems yet)
x = >2^52 (64 bit starts to get problems with step size = 1)

How to program a fractal?

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
}

Resources