From 330755591bc0c78fb6625aa9979bffe6ab82d26a Mon Sep 17 00:00:00 2001 From: Emile Clark-Boman Date: Mon, 15 Sep 2025 19:26:04 +1000 Subject: [PATCH] got nonbinary partitioning working yippie --- cursetree/dims.c | 13 ++-- cursetree/node.c | 163 ++++++++++++++++++++++++++++++------------- cursetree/node.h | 2 +- cursetree/nsparted.c | 11 +++ cursetree/nsparted.h | 26 +++++++ cursetree/util.h | 12 ++++ 6 files changed, 170 insertions(+), 57 deletions(-) create mode 100644 cursetree/nsparted.c create mode 100644 cursetree/nsparted.h create mode 100644 cursetree/util.h diff --git a/cursetree/dims.c b/cursetree/dims.c index 4fa4895..7d7401e 100644 --- a/cursetree/dims.c +++ b/cursetree/dims.c @@ -4,6 +4,7 @@ #include #include "dims.h" +#include "util.h" struct ct_dims *new_dims(int x, int y, int width, int height) { struct ct_dims *dims; @@ -42,19 +43,17 @@ static struct ct_bounds *__bounds(const enum ct_boundtype type, const int wmin, return bounds; } -static inline void clamp(int *const val, const int min, const int max, +static inline void __clamp(int *const val, const int min, const int max, const int do_ceiling) { if (*val == __BOUND_UNLIMITED) *val = do_ceiling ? max : min; - else if (*val > max) - *val = max; - else if (*val < min) - *val = min; + else + *val = clampi(*val, min, max); } #define CLAMP_ABS(val, is_max) \ - (clamp(&val, __BOUND_ABS_MIN, __BOUND_ABS_MAX, is_max)) + (__clamp(&val, __BOUND_ABS_MIN, __BOUND_ABS_MAX, is_max)) #define CLAMP_REL(val, is_max) \ - (clamp(&val, __BOUND_REL_MIN, __BOUND_REL_MAX, is_max)) + (__clamp(&val, __BOUND_REL_MIN, __BOUND_REL_MAX, is_max)) struct ct_bounds *bounds_none(void) { return __bounds(BOUND_NONE, __BOUND_ABS_MIN, __BOUND_ABS_MAX, __BOUND_ABS_MIN, diff --git a/cursetree/node.c b/cursetree/node.c index bc198f9..cd43598 100644 --- a/cursetree/node.c +++ b/cursetree/node.c @@ -7,6 +7,7 @@ #include "dims.h" #include "node.h" #include "surface.h" +#include "util.h" /* Internal allocator method for ct_node structures. */ @@ -74,9 +75,12 @@ void satisfy_node(struct ct_node *const node, struct ct_dims *const dims) { } } -struct ct_whdims { +/* Surface Partition Dimensions */ +/* TODO: can I use unsigned short instead of int? */ +struct ct_spdims { // Main Axis & Orthogonal Axis Sizes - int axm_size, axo_size; + int axm_size; + // int axo_size; bool fixed; int min, max; }; @@ -98,75 +102,136 @@ int resize_node(struct ct_node *const node, struct ct_dims *const dims) { return 1; } - struct ct_whdims cwhdims[node->cindex]; - struct ct_whdims *const parts[node->cindex]; - int cunfixedn = node->cindex; // number of non-fixed children - memset(cwhdims, 0, sizeof(struct ct_whdims) * node->cindex); - - int axm_size, axm_free, axo_size; - size_t axm_min_offset, axm_max_offset; + int axm_size, axm_free; + // int axo_size; + size_t bounds_axm_min_offset, bounds_axm_max_offset; + size_t dims_axm_pos_offset, dims_axm_size_offset; + // size_t dims_axo_pos_offset, dims_axo_size_offset; + if (node->axis == AXIS_X) { axm_free = dims->width; axm_size = dims->width; - axo_size = dims->height; + // axo_size = dims->height; - axm_min_offset = offsetof(struct ct_bounds, wmin); - axm_max_offset = offsetof(struct ct_bounds, wmax); + bounds_axm_min_offset = offsetof(struct ct_bounds, wmin); + bounds_axm_max_offset = offsetof(struct ct_bounds, wmax); + + dims_axm_pos_offset = offsetof(struct ct_dims, x); + // dims_axo_pos_offset = offsetof(struct ct_dims, y); + dims_axm_size_offset = offsetof(struct ct_dims, width); + // dims_axo_size_offset = offsetof(struct ct_dims, height); } else { assert(node->axis == AXIS_Y); axm_free = dims->height; axm_size = dims->height; - axo_size = dims->width; + // axo_size = dims->width; - axm_min_offset = offsetof(struct ct_bounds, hmin); - axm_max_offset = offsetof(struct ct_bounds, hmax); + bounds_axm_min_offset = offsetof(struct ct_bounds, hmin); + bounds_axm_max_offset = offsetof(struct ct_bounds, hmax); + + dims_axm_pos_offset = offsetof(struct ct_dims, y); + // dims_axo_pos_offset = offsetof(struct ct_dims, x); + dims_axm_size_offset = offsetof(struct ct_dims, height); + // dims_axo_size_offset = offsetof(struct ct_dims, width); } - int split = axm_free / node->cindex; - for (int j = 0; j < node->cindex; j++) { - cwhdims[j].min = *(int*)(node->child[j]->surface->bounds + axm_min_offset); - cwhdims[j].max = *(int*)(node->child[j]->surface->bounds + axm_max_offset); - if (node->child[j]->surface->bounds->type == BOUND_RELATIVE) { - cwhdims[j].min *= axm_size; - cwhdims[j].max *= axm_size; + struct ct_spdims cspdims[node->cindex]; + // struct ct_spdims *parts[node->cindex]; + cindex parts_n = node->cindex; + memset(cspdims, 0, sizeof(struct ct_spdims) * node->cindex); + for (int i = 0; i < node->cindex; i++) { + cspdims[i].min = *(int *)(node->child[i]->surface->bounds + bounds_axm_min_offset); + cspdims[i].max = *(int *)(node->child[i]->surface->bounds + bounds_axm_max_offset); + if (node->child[i]->surface->bounds->type == BOUND_RELATIVE) { + cspdims[i].min *= axm_size; + cspdims[i].max *= axm_size; } - cwhdims[j].axm_size = fmax(fmin(split, cwhdims[j].max), cwhdims[j].min); - cwhdims[j].axo_size = axo_size; - - axm_free -= cwhdims[j].axm_size; + cspdims[i].axm_size = 0; + // cspdims[i].axo_size = axo_size; + + // parts[i] = &cspdims[i]; } - int delta; - while (axm_free) { - if (axm_free < cunfixedn) { - int progress = 0; - for (int j = 0; j < node->cindex; j++) { - if (cwhdims[j].fixed) - continue; - cwhdims[j].axm_size--; - axm_free--; - } - } - - // split is guaranteed to be >0 - split = axm_free / node->cindex; - for (int j = 0; j < node->cindex; j++) { - if (cwhdims[j].fixed) + int split, new_size; + while (parts_n) { + split = axm_free / parts_n; + for (int i = 0; i < node->cindex; i++) { + if (cspdims[i].fixed) continue; - - delta = cwhdims[j].axm_size - fmax(cwhdims[j].axm_size - split, bounds->wmin); - if (delta == 0) { - cwhdims[j].fixed = true; - cunfixedn++; + + new_size = + clampi(cspdims[i].axm_size + split, cspdims[i].min, cspdims[i].max); + if (new_size == cspdims[i].axm_size) { + cspdims[i].fixed = true; + parts_n--; continue; } - cwhdims[j].axm_size -= delta; - axm_free -= delta; + axm_free -= (new_size - cspdims[i].axm_size); + cspdims[i].axm_size = new_size; } } + /* TODO: using axo_size this way means cspdims doesn't need an axo field!! */ + struct ct_dims * cdims = dup_dims(dims); + /* NOTE: the statements below are done implicitly by dup_dims */ + // *(int*)(cdims + dims_axm_pos_offset) = *(int*)(dims + dims_axm_pos_offset); + // *(int*)(cdims + dims_axo_pos_offset) = *(int*)(dims + dims_axo_pos_offset); + // *(int*)(cdims + dims_axo_size_offset) = axo_size; + for (int i = 0; i < node->cindex; i++) { + *(int*)(cdims + dims_axm_size_offset) = cspdims[i].axm_size; + resize_node(node->child[i], dup_dims(cdims)); + *(int*)(cdims + dims_axm_pos_offset) += cspdims[i].axm_size; + } + free(cdims); + + // int split = axm_free / node->cindex; + // for (int j = 0; j < node->cindex; j++) { + // cwhdims[j].min = *(int*)(node->child[j]->surface->bounds + + // axm_min_offset); cwhdims[j].max = *(int*)(node->child[j]->surface->bounds + // + axm_max_offset); if (node->child[j]->surface->bounds->type == + // BOUND_RELATIVE) { + // cwhdims[j].min *= axm_size; + // cwhdims[j].max *= axm_size; + // } + + // cwhdims[j].axm_size = fmax(fmin(split, cwhdims[j].max), cwhdims[j].min); + // cwhdims[j].axo_size = axo_size; + + // axm_free -= cwhdims[j].axm_size; + // } + + // int delta; + // while (axm_free) { + // if (axm_free < cunfixedn) { + // int progress = 0; + // for (int j = 0; j < node->cindex; j++) { + // if (cwhdims[j].fixed) + // continue; + // cwhdims[j].axm_size--; + // axm_free--; + // } + // } + + // // split is guaranteed to be >0 + // split = axm_free / node->cindex; + // for (int j = 0; j < node->cindex; j++) { + // if (cwhdims[j].fixed) + // continue; + + // delta = cwhdims[j].axm_size - fmax(cwhdims[j].axm_size - split, + // bounds->wmin); if (delta == 0) { + // cwhdims[j].fixed = true; + // cunfixedn++; + // continue; + // } + + // cwhdims[j].axm_size -= delta; + // axm_free -= delta; + // } + // } + // bifurcate_dims(dims, node->axis, node->ratio, &dims0, &dims1); // resize_node(node->child[0], dims0); diff --git a/cursetree/node.h b/cursetree/node.h index 650f98f..9906af0 100644 --- a/cursetree/node.h +++ b/cursetree/node.h @@ -44,7 +44,7 @@ struct ct_node *new_node(struct ct_dims *const dims, struct ct_bounds *const bounds, struct ct_node *const parent); void destroy_node(struct ct_node *const node); -void resize_node(struct ct_node *const node, struct ct_dims *const new_dims); +int resize_node(struct ct_node *const node, struct ct_dims *const new_dims); void collapse_node(struct ct_node **const node, const int i, const bool preserve_bounds); diff --git a/cursetree/nsparted.c b/cursetree/nsparted.c new file mode 100644 index 0000000..67231c3 --- /dev/null +++ b/cursetree/nsparted.c @@ -0,0 +1,11 @@ +#include "nsparted.h" + +struct ct_nsparted init_nsparted(struct ct_node *const node, + struct ct_dims *const dims) { + struct ct_nsparted nsparted = (struct ct_nsparted) { + .node = node, + .dims = dims, + . + } +} + diff --git a/cursetree/nsparted.h b/cursetree/nsparted.h new file mode 100644 index 0000000..c4fda2d --- /dev/null +++ b/cursetree/nsparted.h @@ -0,0 +1,26 @@ +#ifndef CURSETREE_NSPARTED_H +#define CURSETREE_NSPARTED_H + +#include "node.h" + +/* Surface Partition Dimensions */ +struct ct_spdims { + // Main Axis & Orthogonal Axis Sizes + int axm_size, axo_size; + bool fixed; + int min, max; +}; + +/* Node Surface Partitioner */ +struct ct_nsparted { + struct ct_node *const node; + struct ct_dims *const dims; + + /* Child Surface Partition Dimensions */ + struct ct_spdims *const cspdims; +}; + +struct ct_nsparted *init_nsparted(struct ct_node *const node, + struct ct_dims *const dims); + +#endif /* CURSETREE_NSPARTED_H */ diff --git a/cursetree/util.h b/cursetree/util.h new file mode 100644 index 0000000..6b97a12 --- /dev/null +++ b/cursetree/util.h @@ -0,0 +1,12 @@ +#ifndef CURSETREE_UTIL_H +#define CURSETREE_UTIL_H + +static inline int clampi(int val, int min, int max) { + if (val > max) + return max; + else if (val < min) + return min; + return val; +} + +#endif /* CURSETREE_UTIL_H */