Algorithm 快速块布局算法,需要建议吗?
我需要模拟窗口管理器的窗口放置策略 作为一个粗略的指导,想象一下随机大小的窗口一次填满一个屏幕,其中每个窗口的粗略大小导致屏幕上平均有80个窗口,没有任何窗口重叠 如果您的系统上安装了Fluxbox和Xterm,您可以尝试使用BASH脚本来查看我希望发生的事情的大致原型。请看我写的关于它的注释,解释它的作用和应该如何使用 需要注意的是,窗口将关闭,以前关闭的窗口占用的空间将再次用于放置新窗口。 该算法需要“以串行方式逐块”处理数据,即按照输入输入到算法的顺序,而不必从一开始就提供整个输入 Fluxbox窗口放置策略有三个二进制选项,我想模仿它们:Algorithm 快速块布局算法,需要建议吗?,algorithm,packing,bisection,Algorithm,Packing,Bisection,我需要模拟窗口管理器的窗口放置策略 作为一个粗略的指导,想象一下随机大小的窗口一次填满一个屏幕,其中每个窗口的粗略大小导致屏幕上平均有80个窗口,没有任何窗口重叠 如果您的系统上安装了Fluxbox和Xterm,您可以尝试使用BASH脚本来查看我希望发生的事情的大致原型。请看我写的关于它的注释,解释它的作用和应该如何使用 需要注意的是,窗口将关闭,以前关闭的窗口占用的空间将再次用于放置新窗口。 该算法需要“以串行方式逐块”处理数据,即按照输入输入到算法的顺序,而不必从一开始就提供整个输入 Flu
- Windows构建水平行或垂直列(可能)
- 窗口从左到右放置或从右到左放置
- 窗口从上到下放置或从下到上放置
make
来构建它。有点不友好,请使用--help
(或任何其他无效选项)查看命令行选项列表。必须使用选项指定文本文件
2)我的替代方法。
此方法仅部分实现,对矩形空闲未使用的空间的每个区域使用数据结构(窗口列表可以完全分开,并且不需要测试此算法)。数据结构充当双链接列表(带有排序插入)中的节点,并包含左上角的坐标以及宽度和高度
此外,每个块数据结构还包含四个链接,这些链接连接到四面上的每个紧邻(接触)块
重要规则:每个区块每侧只能接触一个区块。这是一条特定于算法存储空闲未使用空间的方法的规则,不考虑实际窗口相互接触的数量
这种方法的问题是,它非常复杂。我已经实施了一些简单的案例,其中1)从块的一个角移除空间,2)分割相邻块,以便遵守重要规则
不太简单的情况是,要删除的空间只能在一列或一行框中找到,仅部分实现-如果要删除的块之一与宽度(即列)或高度(即行)完全匹配,则会出现问题。甚至不要提及这样一个事实:它只检查一个框宽的列和一个框高的行
我已经用C语言实现了这个算法(我用了这个项目的语言(我用C++几年了,在把所有注意力都放在C开发上之后,我不喜欢它,这是一个爱好)。实现是700多行代码(包括大量的空行、大括号行、注释等)。该实现仅适用于水平行+左右+上下放置策略
因此,我要么要添加一些方法,使这+700行代码适用于其他7个布局策略选项,要么我要为其他7个选项复制+700行代码。这两种方法都没有吸引力,第一种是因为现有代码足够复杂,第二种是因为代码膨胀
由于缺少功能,该算法甚至还没有达到我可以在实时最坏情况下使用它的阶段,因此我仍然不知道它的实际性能是否比第一种方法更好或更差
该算法的C实现的当前状态为。我使用gcc-O0-ggdb freespace.c
构建,并在大小至少为124 x 60个字符的xterm中运行它
还有什么?
我略过并打折:
- 装箱算法 强调最佳配合并不重要 符合本标准的要求 算法
- 递归二分法
struct block{ int free_x[4]; // 0 = top left, 1 = top right, int free_y[4]; // 2 = bottom left, 3 = bottom right int n_windows; // number of windows that occupy this block int window_id[4]; // IDs of windows that occupy this block }; block blocks[NX][NY]; struct window{ int id; int used_block_x[2]; // 0 = first index of used block, int used_block_y[2]; // 1 = last index of used block };
_Bool freespace_remove( freespace* fs, int width, int height, int* resultx, int* resulty) { int x = 0; int y = 0; const int rx = FSWIDTH - width; const int by = FSHEIGHT - height; *resultx = -1; *resulty = -1; char* buf[height]; for (y = 0; y < by; ++y) { x = 0; char* scanx = fs->buf[y]; while (x < rx) { while(x < rx && *(scanx + x)) ++x; int w, h; for (h = 0; h < height; ++h) buf[h] = fs->buf[y + h] + x; _Bool usable = true; w = 0; while (usable && w < width) { h = 0; while (usable && h < height) if (*(buf[h++] + w)) usable = false; ++w; } if (usable) { for (w = 0; w < width; ++w) for (h = 0; h < height; ++h) *(buf[h] + w) = 1; *resultx = x; *resulty = y; return true; } x += w; } } return false; }
#include <limits.h> #include <stdbool.h> #include <stddef.h> #include <stdlib.h> #include <stdint.h> #include <stdio.h> #include <string.h> #define FSWIDTH 128 #define FSHEIGHT 128 #ifdef USE_64BIT_ARRAY #define FSBUFBITS 64 #define FSBUFWIDTH 2 typedef uint64_t fsbuf_type; #define TRAILING_ZEROS( v ) __builtin_ctzl(( v )) #define LEADING_ONES( v ) __builtin_clzl(~( v )) #else #ifdef USE_32BIT_ARRAY #define FSBUFBITS 32 #define FSBUFWIDTH 4 typedef uint32_t fsbuf_type; #define TRAILING_ZEROS( v ) __builtin_ctz(( v )) #define LEADING_ONES( v ) __builtin_clz(~( v )) #else #ifdef USE_16BIT_ARRAY #define FSBUFBITS 16 #define FSBUFWIDTH 8 typedef uint16_t fsbuf_type; #define TRAILING_ZEROS( v ) __builtin_ctz( 0xffff0000 | ( v )) #define LEADING_ONES( v ) __builtin_clz(~( v ) << 16) #else #ifdef USE_8BIT_ARRAY #define FSBUFBITS 8 #define FSBUFWIDTH 16 typedef uint8_t fsbuf_type; #define TRAILING_ZEROS( v ) __builtin_ctz( 0xffffff00 | ( v )) #define LEADING_ONES( v ) __builtin_clz(~( v ) << 24) #else #define FSBUFBITS 1 #define FSBUFWIDTH 128 typedef unsigned char fsbuf_type; #define TRAILING_ZEROS( v ) (( v ) ? 0 : 1) #define LEADING_ONES( v ) (( v ) ? 1 : 0) #endif #endif #endif #endif static const fsbuf_type fsbuf_max = ~(fsbuf_type)0; static const fsbuf_type fsbuf_high = (fsbuf_type)1 << (FSBUFBITS - 1); typedef struct freespacegrid { fsbuf_type buf[FSHEIGHT][FSBUFWIDTH]; _Bool left_to_right; _Bool top_to_bottom; } freespace; void freespace_dump(freespace* fs) { int x, y; for (y = 0; y < FSHEIGHT; ++y) { for (x = 0; x < FSBUFWIDTH; ++x) { fsbuf_type i = FSBUFBITS; fsbuf_type b = fs->buf[y][x]; for(; i != 0; --i, b <<= 1) putchar(b & fsbuf_high ? '#' : '/'); /* if (x + 1 < FSBUFWIDTH) putchar('|'); */ } putchar('\n'); } } freespace* freespace_new(void) { freespace* fs = malloc(sizeof(*fs)); if (!fs) return 0; int y; for (y = 0; y < FSHEIGHT; ++y) { memset(&fs->buf[y][0], 0, sizeof(fsbuf_type) * FSBUFWIDTH); } fs->left_to_right = true; fs->top_to_bottom = true; return fs; } void freespace_delete(freespace* fs) { if (!fs) return; free(fs); } /* would be private function: */ void fs_set_buffer( fsbuf_type buf[FSHEIGHT][FSBUFWIDTH], unsigned x, unsigned y1, unsigned xoffset, unsigned width, unsigned height) { fsbuf_type v; unsigned y; for (; width > 0 && x < FSBUFWIDTH; ++x) { if (width < xoffset) v = (((fsbuf_type)1 << width) - 1) << (xoffset - width); else if (xoffset < FSBUFBITS) v = ((fsbuf_type)1 << xoffset) - 1; else v = fsbuf_max; for (y = y1; y < y1 + height; ++y) { #ifdef FREESPACE_DEBUG if (buf[y][x] & v) printf("**** over-writing area ****\n"); #endif buf[y][x] |= v; } if (width < xoffset) return; width -= xoffset; xoffset = FSBUFBITS; } } _Bool freespace_remove( freespace* fs, unsigned width, unsigned height, int* resultx, int* resulty) { unsigned x, x1, y; unsigned w, h; unsigned xoffset, x1offset; unsigned tz; /* trailing zeros */ fsbuf_type* xptr; fsbuf_type mask = 0; fsbuf_type v; _Bool scanning = false; _Bool offset = false; *resultx = -1; *resulty = -1; for (y = 0; y < (unsigned) FSHEIGHT - height; ++y) { scanning = false; xptr = &fs->buf[y][0]; for (x = 0; x < FSBUFWIDTH; ++x, ++xptr) { if(*xptr == fsbuf_max) { scanning = false; continue; } if (!scanning) { scanning = true; x1 = x; x1offset = xoffset = FSBUFBITS; w = width; } retry: if (w < xoffset) mask = (((fsbuf_type)1 << w) - 1) << (xoffset - w); else if (xoffset < FSBUFBITS) mask = ((fsbuf_type)1 << xoffset) - 1; else mask = fsbuf_max; offset = false; for (h = 0; h < height; ++h) { v = fs->buf[y + h][x] & mask; if (v) { tz = TRAILING_ZEROS(v); offset = true; break; } } if (offset) { if (tz) { x1 = x; w = width; x1offset = xoffset = tz; goto retry; } scanning = false; } else { if (w <= xoffset) /***** RESULT! *****/ { fs_set_buffer(fs->buf, x1, y, x1offset, width, height); *resultx = x1 * FSBUFBITS + (FSBUFBITS - x1offset); *resulty = y; return true; } w -= xoffset; xoffset = FSBUFBITS; } } } return false; } int main(int argc, char** argv) { int x[1999]; int y[1999]; int w[1999]; int h[1999]; int i; freespace* fs = freespace_new(); for (i = 0; i < 1999; ++i, ++u) { w[i] = rand() % 18 + 4; h[i] = rand() % 18 + 4; freespace_remove(fs, w[i], h[i], &x[i], &y[i]); /* freespace_dump(fs); printf("w:%d h:%d x:%d y:%d\n", w[i], h[i], x[i], y[i]); if (x[i] == -1) printf("not removed space %d\n", i); getchar(); */ } freespace_dump(fs); freespace_delete(fs); return 0; }