(EGE)Circle Packing—— 随机画或基于图片

#这是以前利用这段代码生成的,原理是导入一张图片,然后基于这张图片进行绘制,为了便于理解,下面的代码会分成两段

(请通过截图保存图片(以后会更新保存图片的功能(届时应该是可以之支持到任意大小的图片)

/* 
** filename:   circlePacking.cpp
** createtime: 2020-03-08
** author:     TheBadZhang
** balabalabala
*/
 
#include <graphics.h>
#include <ctime>
#include <cstdlib>
#include <cmath>
// #include <conio.h>
 
 
int main (int argc, char *argv []) {
	
 
	const unsigned int minRadius = 1;
	const unsigned int maxRadius = 50;
	// 最小与最大半径
	const unsigned int WW = 800, WH = 600, times = 3000;
	// 窗口宽度,窗口高度,圈数
	// 在这个程序里,窗口的大小决定了生成图片的大小
	// 图片过大或者过小都会被缩小或者放大到窗口大小
	int *circleList = new int[3 * times];
	// 0 为 x, 1 为 y, 2 为 r, 以此类推 
	// 存储圈圈数据 
	unsigned int count = 0;
	// 圆圈计数器
 
	srand (time (0));
	initgraph (WW, WH, 0);
	setfillcolor (WHITE);
	
	int x, y, r, l;
	int i;
	do {
redo:
		x = rand () % WW;
		y = rand () % WH;
		r = rand () % (maxRadius - minRadius) + 1;
		// 取模 防止圆 get 不到 pixel,限定园大小为 1 - 50 px
		for (i = 0; i < count; i += 1) {
			
			l = sqrt (pow (x - circleList [3*i + 0], 2) +
			          pow (y - circleList [3*i + 1], 2))
			          - circleList [3*i + 2];
			// 当前坐标点下的最大半径
			 // 需遍历每一个圆(照理这里应该有优化,但是我没有做,导致到了后面速度就非常慢了
			r = r > l ? l : r;
			// 选择半径较小的那一个
		}
		if (r <= 0) goto redo;
		
		// 如果不合法重新生成 
		// 也就是圆要是出现在了别的圆里就跳过这个数据
		fillellipse (x, y, r, r);
		// 画出图形
		circleList [count * 3 + 0] = x;
		circleList [count * 3 + 1] = y;
		circleList [count * 3 + 2] = r;
		// 计数值加一
		count ++;
		// getch ();
	} while (count < times);
	getch ();
	closegraph ();
	
	return 0;
}

升级一下,让他可以根据图片画圈圈

/* 
** filename:   circlePacking.cpp
** createtime: 2020-03-08
** author:     TheBadZhang
** balabalabala
*/
 
#include <graphics.h>
#include <ctime>
#include <cstdlib>
#include <cmath>
// #include <conio.h>
 
 
int main (int argc, char *argv []) {
	
 
	const unsigned int minRadius = 1;
	const unsigned int maxRadius = 35;
	// 最小与最大半径
	const unsigned int WW = 1600, WH = 1000, times = 60000;
	// 窗口宽度,窗口高度,圈数
	// 在这个程序里,窗口的大小决定了生成图片的大小
	// 图片过大或者过小都会被缩小或者放大到窗口大小
	int *circleList = new int[3 * times];
	// 0 为 x, 1 为 y, 2 为 r, 以此类推 
	// 存储圈圈数据 
	unsigned int count = 0;
	// 圆圈计数器
	srand (time (0));
	
	initgraph (WW, WH, 0);
	setfillcolor (WHITE);
	// ege_enable_aa (true);
	
	
	PIMAGE PIC = newimage ();	
	// 用于生成彩色的 circlepacking
	PIMAGE CHECK = newimage (WW, WH);
	setfillcolor (WHITE, CHECK);
	// getimage (PIC, argv [1], WW, WH);
	getimage (PIC, "pic.jpg", WW, WH);
	putimage (0, 0, PIC);
	// 打印图片,否则背景默认纯黑色,圆圈的空隙处会显得有些难看
	// 纯几何图形建议不要输出图片 
	// 可以使用 blur 函数说不定效果好一点
	// blur 函数看来要自己写一个了 
 
 
	int x, y, r, l;
	int i;
	do {
redo:
		x = rand () % WW;
		y = rand () % WH;
		r = rand () % (maxRadius - minRadius) + 1;
		// 取模 防止圆 get 不到 pixel,限定园大小为 1 - 50 px
		if (getpixel (x, y, CHECK) == WHITE) goto redo;
		for (i = 0; i < count; i += 1) {
			
			l = sqrt (pow (abs (x - circleList [3*i + 0]), 2) +
			          pow (abs (y - circleList [3*i + 1]), 2))
			          - circleList [3*i + 2];
			// 当前坐标点下的最大半径
			 // 需遍历每一个圆(照理这里应该有优化,但是我没有做,导致到了后面速度就非常慢了
			r = r > l ? l : r;
			// 选择半径较小的那一个
		}
		// if (r <= 0 || pic [x + WW * y] == bgcolor) goto redo;
		if (r <= 0) goto redo;
		// 如果不合法重新生成 
		// 也就是圆要是出现在了别的圆里就跳过这个数据
		
		
		setcolor (getpixel (x, y, PIC));
		setfillcolor (getpixel (x, y, PIC));
		// circle (x, y, r);
		// 手动选择实心还是空心
		fillellipse (x, y, r, r);
		// 画出图形
		
		
		
		circleList [count * 3 + 0] = x;
		circleList [count * 3 + 1] = y;
		circleList [count * 3 + 2] = r;
		// 存入数据 
		fillellipse (x, y, r, r, CHECK);
		// 快速判断圆心是否合规 
		count += 1;
		// 计数值加一
		
	} while (count < times);
	// imagefilter_blurring (NULL, 0xFF, 0xFF);
	getch ();
	closegraph ();
	
	return 0;
}