在上次的二维码生成镂空模型的例子中,发现逐像素读取生成立柱这不仅使程序运行缓慢,而且让一个280*280的二维码生成的stl有65M之大。所以想着简化这个模型,让它的大小变小一些。
我先是直接改变了for循环中的加量使3*3的像素区视作一个像素(值为像素区左上像素的值)。这使运行速度大大提升,且大小从单扫的64M左右变为了7M左右。修改部分的代码如下:
再后修改了生成立柱的函数使之能生成长宽高自定的长方体。
仅仅修改writein函数即可,代码如下:
接下来尝试扫行时看是否检查是否可以将原本是多个立柱拼起来的几何体换成一个长乘倍的长方体。我在遍历像素点之前先是声明了几个变量来控制这个过程:judge用于判断当前是否还在构造一个长方体,还是说已经构造完上一个立方体了。counter用来记数,看当前构造的长方体的顶面宽应该是几倍的原普通立柱。x,y用来记录当前构造的长方体的起点坐标,此处容易想当然地在长方体结束的时候的坐标处生成长方体,易造成bug。
此外,要想到的是,遍历完一行之后,如果最后一个像素为白且下一行的第一个像素也为白,会使长方体违背我们意愿地跨行构造,我在第一层for循环后加了一条判断语句来解决这个问题。遍历部分修改代码如下:
我先是直接改变了for循环中的加量使3*3的像素区视作一个像素(值为像素区左上像素的值)。这使运行速度大大提升,且大小从单扫的64M左右变为了7M左右。修改部分的代码如下:
for (int k = 0;k<image.rows;k+=3)
{
uchar* data = image.ptr<uchar>(k);
for (int i = 0;i < image.cols;i += 3)
{
if(data[i]!=0) writein(p(x, y, 0), 10, 3, output);
}
}
再后修改了生成立柱的函数使之能生成长宽高自定的长方体。
仅仅修改writein函数即可,代码如下:
void writein(const p &a, int c, int k, int kk, ostream& output)
{
inat(a, c, k, 2, output);
inat(a, k, kk, 3, output);
inat(a, c, kk, 1, output);
inat(p(a.x, a.y, a.z - c), k, kk, -3, output);
inat(p(a.x + k, a.y, a.z), c, kk, -1, output);
inat(p(a.x, a.y + kk, a.z), c, k, -2, output);
}
接下来尝试扫行时看是否检查是否可以将原本是多个立柱拼起来的几何体换成一个长乘倍的长方体。我在遍历像素点之前先是声明了几个变量来控制这个过程:judge用于判断当前是否还在构造一个长方体,还是说已经构造完上一个立方体了。counter用来记数,看当前构造的长方体的顶面宽应该是几倍的原普通立柱。x,y用来记录当前构造的长方体的起点坐标,此处容易想当然地在长方体结束的时候的坐标处生成长方体,易造成bug。
此外,要想到的是,遍历完一行之后,如果最后一个像素为白且下一行的第一个像素也为白,会使长方体违背我们意愿地跨行构造,我在第一层for循环后加了一条判断语句来解决这个问题。遍历部分修改代码如下:
int counter = 0;
int x = 0, y = 0;
int judge = 0;
for (int k = 0;k<image.rows;k+=3)
{
uchar* data = image.ptr<uchar>(k);
for (int i = 0;i<image.cols;i+=3)
{
if (judge == 1)
{
if (data[i] != 0)
{
counter++;
}
else if (data[i] == 0)
{
writein(p(x, y, 0), 10, 3 * counter, 3, output);
judge = 0;
counter = 0;
x = 0, y = 0;
}
}
else if((judge == 0) && (data[i] != 0))
{
x = i;
y = k;
judge = 1;
}
}
if (judge == 1)
{
writein(p(x, y, 0), 10, 3 * counter, 3, output);
judge = 0;
counter = 0;
x = 0, y = 0;
judge = 0;
}
}
在简化后,我的模型变为了700k左右,且程序地运行时间从十秒左右变成了秒运行完成。