reformat Qt/qt_clust.cpp

This commit is contained in:
PatR
2020-12-27 17:01:33 -08:00
parent 7e20be61df
commit 953f0652c4
+121 -119
View File
@@ -5,163 +5,165 @@
static void include(QRect& r, const QRect& rect) static void include(QRect& r, const QRect& rect)
{ {
if (rect.left()<r.left()) { if (rect.left() < r.left()) {
r.setLeft(rect.left()); r.setLeft(rect.left());
} }
if (rect.right()>r.right()) { if (rect.right() > r.right()) {
r.setRight(rect.right()); r.setRight(rect.right());
} }
if (rect.top()<r.top()) { if (rect.top() < r.top()) {
r.setTop(rect.top()); r.setTop(rect.top());
} }
if (rect.bottom()>r.bottom()) { if (rect.bottom() > r.bottom()) {
r.setBottom(rect.bottom()); r.setBottom(rect.bottom());
} }
} }
/* /*
A Clusterizer groups rectangles (QRects) into non-overlapping rectangles * A Clusterizer groups rectangles (QRects) into non-overlapping
by a merging heuristic. * rectangles by a merging heuristic.
*/ */
Clusterizer::Clusterizer(int maxclusters) : Clusterizer::Clusterizer(int maxclusters) :
cluster(new QRect[maxclusters]), cluster(new QRect[maxclusters]),
count(0), count(0),
max(maxclusters) max(maxclusters)
{ } {
}
Clusterizer::~Clusterizer() Clusterizer::~Clusterizer()
{ {
delete [] cluster; delete [] cluster;
} }
void Clusterizer::clear() void Clusterizer::clear()
{ {
count=0; count = 0;
} }
void Clusterizer::add(int x, int y) void Clusterizer::add(int x, int y)
{ {
add(QRect(x,y,1,1)); add(QRect(x, y, 1, 1));
} }
void Clusterizer::add(int x, int y, int w, int h) void Clusterizer::add(int x, int y, int w, int h)
{ {
add(QRect(x,y,w,h)); add(QRect(x, y, w, h));
} }
void Clusterizer::add(const QRect& rect) void Clusterizer::add(const QRect& rect)
{ {
QRect biggerrect(rect.x()-1,rect.y()-1,rect.width()+2,rect.height()+2); QRect biggerrect(rect.x() - 1, rect.y() - 1,
rect.width() + 2, rect.height() + 2);
//assert(rect.width()>0 && rect.height()>0); //assert(rect.width() > 0 && rect.height() > 0);
int cursor; int cursor;
for (cursor=0; cursor<count; cursor++) { for (cursor=0; cursor < count; cursor++) {
if (cluster[cursor].contains(rect)) { if (cluster[cursor].contains(rect)) {
// Wholly contained already. // Wholly contained already.
return; return;
} }
} }
int lowestcost=9999999; int lowestcost = 9999999;
int cheapest=-1; int cheapest = -1;
for (cursor=0; cursor<count; cursor++) { for (cursor = 0; cursor < count; cursor++) {
if (cluster[cursor].intersects(biggerrect)) { if (cluster[cursor].intersects(biggerrect)) {
QRect larger=cluster[cursor]; QRect larger=cluster[cursor];
include(larger,rect); include(larger,rect);
int cost=larger.width()*larger.height() int cost = larger.width() * larger.height()
- cluster[cursor].width()*cluster[cursor].height(); - cluster[cursor].width() * cluster[cursor].height();
if (cost < lowestcost) { if (cost < lowestcost) {
bool bad=false; bool bad = false;
for (int c=0; c<count && !bad; c++) { for (int c = 0; c < count && !bad; c++) {
bad=cluster[c].intersects(larger) && c!=cursor; bad = cluster[c].intersects(larger) && c != cursor;
} }
if (!bad) { if (!bad) {
cheapest=cursor; cheapest = cursor;
lowestcost=cost; lowestcost = cost;
} }
} }
} }
} }
if (cheapest>=0) { if (cheapest >= 0) {
include(cluster[cheapest],rect); include(cluster[cheapest], rect);
return; return;
} }
if (count < max) { if (count < max) {
cluster[count++]=rect; cluster[count++] = rect;
return; return;
} }
// Do cheapest of: // Do cheapest of:
// add to closest cluster // add to closest cluster
// do cheapest cluster merge, add to new cluster // do cheapest cluster merge, add to new cluster
lowestcost=9999999; lowestcost = 9999999;
cheapest=-1; cheapest = -1;
for (cursor=0; cursor<count; cursor++) { for (cursor = 0; cursor < count; cursor++) {
QRect larger=cluster[cursor]; QRect larger = cluster[cursor];
include(larger,rect); include(larger, rect);
int cost=larger.width()*larger.height() int cost = larger.width() * larger.height()
- cluster[cursor].width()*cluster[cursor].height(); - cluster[cursor].width() * cluster[cursor].height();
if (cost < lowestcost) { if (cost < lowestcost) {
bool bad=false; bool bad = false;
for (int c=0; c<count && !bad; c++) { for (int c = 0; c < count && !bad; c++) {
bad=cluster[c].intersects(larger) && c!=cursor; bad = cluster[c].intersects(larger) && c != cursor;
} }
if (!bad) { if (!bad) {
cheapest=cursor; cheapest = cursor;
lowestcost=cost; lowestcost = cost;
} }
} }
} }
// XXX could make an heuristic guess as to whether we // XXX could make an heuristic guess as to whether we
// XXX need to bother looking for a cheap merge. // XXX need to bother looking for a cheap merge.
int cheapestmerge1=-1; int cheapestmerge1 = -1;
int cheapestmerge2=-1; int cheapestmerge2 = -1;
for (int merge1=0; merge1<count; merge1++) { for (int merge1 = 0; merge1 < count; merge1++) {
for (int merge2=0; merge2<count; merge2++) { for (int merge2 = 0; merge2 < count; merge2++) {
if (merge1!=merge2) { if (merge1 != merge2) {
QRect larger=cluster[merge1]; QRect larger = cluster[merge1];
include(larger,cluster[merge2]); include(larger, cluster[merge2]);
int cost=larger.width()*larger.height() int cost = larger.width() * larger.height()
- cluster[merge1].width()*cluster[merge1].height() - cluster[merge1].width() * cluster[merge1].height()
- cluster[merge2].width()*cluster[merge2].height(); - cluster[merge2].width() * cluster[merge2].height();
if (cost < lowestcost) { if (cost < lowestcost) {
bool bad=false; bool bad = false;
for (int c=0; c<count && !bad; c++) { for (int c = 0; c < count && !bad; c++) {
bad=cluster[c].intersects(larger) && c!=cursor; bad = cluster[c].intersects(larger) && c != cursor;
} }
if (!bad) { if (!bad) {
cheapestmerge1=merge1; cheapestmerge1 = merge1;
cheapestmerge2=merge2; cheapestmerge2 = merge2;
lowestcost=cost; lowestcost = cost;
} }
} }
} }
} }
} }
if (cheapestmerge1>=0) { if (cheapestmerge1 >= 0) {
include(cluster[cheapestmerge1],cluster[cheapestmerge2]); include(cluster[cheapestmerge1], cluster[cheapestmerge2]);
cluster[cheapestmerge2]=cluster[count--]; cluster[cheapestmerge2] = cluster[count--];
} else { } else {
// if (!cheapest) debugRectangles(rect); // if (!cheapest) debugRectangles(rect);
include(cluster[cheapest],rect); include(cluster[cheapest],rect);
} }
// NB: clusters do not intersect (or intersection will // NB: clusters do not intersect (or intersection will
// overwrite). This is a result of the above algorithm, // overwrite). This is a result of the above algorithm,
// given the assumption that (x,y) are ordered topleft // given the assumption that (x,y) are ordered topleft
// to bottomright. // to bottomright.
} }
const QRect& Clusterizer::operator[](int i) const QRect& Clusterizer::operator[](int i)
{ {
return cluster[i]; return cluster[i];
} }