Rev 2097 |
Blame |
Compare with Previous |
Last modification |
View Log
| RSS feed
/*
* rect.cc
* DIN Is Noise is copyright (c) 2006-2025 Jagannathan Sampath
* DIN Is Noise is released under GNU Public License 2.0
* For more information, please visit https://dinisnoise.org/
*/
#include "mondrian.h"
#include "container.h"
#include "console.h"
#include "utils.h"
#include <utility>
using namespace std;
rect::rect () {
parent = child1 = child2 = 0;
total_slits = 0;
for (int i = 0; i < 4; ++i) nslits[i] = 0;
split = split::NONE;
make_random_color ();
++ref;
}
void rect::erase (ball* b) {::erase (balls, b);}
void rect::calc_intervals () {
hint.first = extents.bottom;
hint.second = extents.top;
vint.first = extents.left;
vint.second = extents.right;
}
void rect::get_vertical_interval (pair<float, float>& invl, rect* _root) {
invl.first = 1.0f + (vint.first - _root->extents.left) * _root->extents.width_1;
invl.second = 1.0f + (vint.second - _root->extents.left) * _root->extents.width_1;
}
void rect::get_horizontal_interval (pair<float, float>& invl, rect* _root) {
invl.first = 1.0f + (hint.first - _root->extents.bottom) * _root->extents.height_1;
invl.second = 1.0f + (hint.second - _root->extents.bottom) * _root->extents.height_1;
}
int rect::add_slit (slit* s, int e) {
int result = 1;
int& nse = nslits [e]; // number of slits on this edge
// for all edges
float lows [rect::nedges] = {extents.left, extents.bottom, extents.left, extents.bottom};
float highs [rect::nedges] = {extents.right, extents.top, extents.right, extents.top};
float low = lows[e];
if (nse) { // slits already on this edge
list<slit*>& ls = slits [e]; // slits of this edge
for (slit_iterator i = ls.begin (), j = ls.end (); i != j; ++i) {
slit* si = *i;
if (s->mid < si->start) {
s->start = max (s->start, low);
s->end = min (s->end, si->start);
i = ls.insert (i, s); // inserts sorted
slit_iterator ip (i); --ip; // slit b4 inserted slit
slit_iterator in (i); ++in; // slit after inserted slit
// handle animation of previous and next slits
slit *ips = *ip, *ins = *in;
if (ip != j && ips->fdr) ips->anim_end = min (ips->anim_end, s->start);
if (in != j && ins->fdr) ins->anim_start = max (ins->anim_start, s->end);
// handle edited slit
if (mondrian0.editing_slit) {
int hl = 0;
slit* eds = mondrian0.slit_lip.slitt; // the edited slit
if ((ip != j) && (*ip == eds)) { // edited slit is b4 inserted slit
// slits editable high is inserted slits low
mondrian0.slit_lip.set_high (s->start);
hl = 1;
} else if ((in != j) && (*in == eds)) { // slit after inserted slit is edited slit
// slit's editable low is inserted slits high
mondrian0.slit_lip.set_low (s->end);
hl = 1;
}
if (hl && mondrian0.slit_lip.slitt->is_too_small()) mondrian0.remove_slit (mondrian0.slit_lip.slitt);
}
goto adder;
}
low = si->end;
}
// append slit
// if last slit is currently edited slit, adjusts its high
//
slit* sl = ls.back ();
if (sl == mondrian0.slit_lip.slitt) mondrian0.slit_lip.set_high (s->start);
} /*else cons << console::cyan << "No slits on edge, adding first slit" << eol;*/
// append slit
s->start = max (s->start, low);
s->end = min (s->end, highs[e]);
slits[e].push_back (s);
adder:
s->anim_start = s->start;
s->anim_end = s->end;
++nse;
++total_slits;
/*cons << console::yellow << "Slit size = " << (s->end - s->start) << eol;
cons << console::yellow << "Slits on edge = " << nse << eol;*/
if (s->is_too_small()) result = 0; else s->calc_mid ();
return result;
}
void rect::update_slits (int e, float minn, float maxx) {
list<slit*>& ls = slits [e];
for (slit_iterator i = ls.begin (), j = ls.end (); i != j;) {
slit* si = *i;
clamp (minn, si->start, maxx);
clamp (minn, si->end, maxx);
if (si->is_too_small()) {
mondrian0.remove_slit (si);
i = ls.begin ();
j = ls.end ();
} else {
++i;
si->calc_mid ();
}
}
}