这是以前利用这段代码生成的,原理是导入一张图片,然后基于这张图片进行绘制,为了便于理解,下面的代码会分成两段
(请通过截图保存图片(以后会更新保存图片的功能(届时应该是可以之支持到任意大小的图片)
/* ** 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; }