Koch's Snowflake

Anything R'n'D unrelated.

Moderators: Zomis, Flumminator

Post Reply
User avatar
Francesco
Posts: 577
Joined: Thu Dec 29, 2005 2:22 pm
Location: Sardinia (Italy)
Contact:

Koch's Snowflake

Post by Francesco » Sun May 20, 2007 7:07 pm

Here I am with my toy program 8)

http://www.zomis.net/rnd/download.php?id=656

It is the first thing I've made (with C++) that I can (almost) safely show to the public :P

It is not very fast, but considering that it shows a Koch's snowflake at the 7th level of depth (i.e. a polygon with 49152 sides), I am very proud of its performances.

The filling routine is just a silly flood fill that starts 5 pixels below of the snowflake's top, so it is a bit broken...

You can move along the shape by clicking and moving the mouse and you can zoom it with the mousewheel.

Finally, the program uses the SDL runtime library.

Well, for what is worth, enjoy!
Anyway, by the way, have fun!
Francesco

Zomis
Posts: 1501
Joined: Mon Jun 21, 2004 1:27 pm
Location: Sweden
Contact:

Post by Zomis » Sun May 20, 2007 9:00 pm

Wow, good to see that you've learned C++, Francesco :)

I gotta say that I have absolutely no idea about how to make such snowflakes. But I do know the structure (A whole bunch of triangels splitted in half a couple of times, or however you could describe it...).

And for those who don't know: SDL is the libraries included with the RnD release. Just place Francesco's program in your RnD dir and it will work.

Btw: I'm not sure if this topic actually belongs in "Programmer's Corner" or not, so until later - I leave it here.

User avatar
Francesco
Posts: 577
Joined: Thu Dec 29, 2005 2:22 pm
Location: Sardinia (Italy)
Contact:

Post by Francesco » Sun May 20, 2007 11:37 pm

"learned C++"... I wish this sentence to come true one day...

I didn't release the source code for a reason :?

Calculating the snowflake is the easy part, you just have to divide the side lenght by 3 and build the next triangle on that size... it is quite straightforward done with polar coordinates.

The hard part was to make a decent "draw line" function, but it also came not-so-hard once I've found the Bresenham's algorithm.

Now, really, this is all childplay... when I'll get straight a bigger amount of correlated classes (compared to the half dozen I am managing now in some toy program), only then I could begin thinking that I am learning C++.

Until then, it is all pretty fun... if I'll ever work for a couple of years on some "real life" C++ project, then maybe I wouldn't find it so fun :P
Anyway, by the way, have fun!
Francesco

HerzAusGold
Posts: 326
Joined: Sun Sep 25, 2005 4:41 pm
Location: Germany

Post by HerzAusGold » Tue May 22, 2007 6:49 pm

Hi ,
I'm back from Finnland - and alive. But full reincarnation takes some more weeks...
Nice to see your first toy program, Francesco.
Hm. The Bresenham's algo is for curved lines, I think.
So if you can send me the source code, i can take a look inn the near future.

Greetings to all..
And the answer is ... 42 !

User avatar
Francesco
Posts: 577
Joined: Thu Dec 29, 2005 2:22 pm
Location: Sardinia (Italy)
Contact:

Post by Francesco » Wed May 23, 2007 2:48 pm

Hi HerzAusGold,
welcome back among mortals ;)

Here is the function that scans the lines and stores each point in a map, which then gets printed on the screen by another function.

There is some room for a little optimization (in effect this is not exactly the function used in my program).

You'll see the complete code in your mailbox quite soon, just the time to delete a bunch of C-style pointer casts scattered here and there ;)

Code: Select all

void ScanPoly(const std::vector<PointXY>& points,
						std::map<Sint16, std::set<Sint16> >* scan,
						Surface* dest) {
	Sint16 maxx = dest->w-1;
	Sint16 maxy = dest->h-1;
	for (size_t i = 1; i < points.size(); ++i) {
		PointXY p1 = points[i-1];
		PointXY p2 = points[i];
		if (!(
					( (p1.x < 0)    && (p2.x < 0)    ) ||
					( (p1.x > maxx) && (p2.x > maxx) ) ||
					( (p1.y < 0)    && (p2.y < 0)    ) ||
					( (p1.y > maxy) && (p2.y > maxy) )
				) )
		{
			Sint16 Yd = p2.y - p1.y;
			Sint16 Xd = p2.x - p1.x;
			Sint16 change = (Sign(Xd)==Sign(Yd)) ? 1 : -1;
			double m = double(Yd) / Xd;
			if (fabs(m) <= 1) {
				if (p1.x > p2.x) std::swap(p1, p2);
				Sint16 dx = abs(p2.x - p1.x);
				Sint16 dy = abs(p2.y - p1.y);
				Sint16 d = dy * 2 - dx;
				Sint16 difneg = 2 * dy;
				Sint16 difpos = 2 * (dy - dx);
				(*scan)[p1.y].insert(p1.x);
				while (p1.x < p2.x) {
					if (d <= 0) {
						d += difneg;
						++p1.x;
					}
					else {
						d += difpos;
						++p1.x;
						p1.y += change;
					}
					(*scan)[p1.y].insert(p1.x);
				}
			}
			else {
				if (p1.y > p2.y) std::swap(p1, p2);
				Sint16 dx = abs(p2.x - p1.x);
				Sint16 dy = abs(p2.y - p1.y);
				Sint16 d = dx * 2 - dy;
				Sint16 difneg = 2 * dx;
				Sint16 difpos = 2 * (dx - dy);
				(*scan)[p1.y].insert(p1.x);
				while (p1.y < p2.y) {
					if (d <= 0) {
						d += difneg;
						++p1.y;
					}
					else {
						d += difpos;
						++p1.y;
						p1.x+=change;
					}
					(*scan)[p1.y].insert(p1.x);
				}
			}
		}
	}
}
(a variant of) The Bresenham's algo can be used to draw circles, but the original version was designed specifically for straight lines.
Anyway, by the way, have fun!
Francesco

Post Reply