15 throw std::invalid_argument(
"Attempted to form ROI2D with cutoff of: " + std::to_string(cutoff) +
16 ". cutoff must be an integer of value 0 or greater.");
24 Array2D<bool> mask_buf(this->mask_ptr->height(), this->mask_ptr->width());
25 for (
const auto &nlinfo : nlinfos_pair.first) {
26 auto boundary = nlinfo.to_boundary(mask_buf);
27 this->regions_ptr->emplace_back(std::move(nlinfo), std::move(boundary));
30 if (nlinfos_pair.second) {
43 auto boundary = nlinfo.to_boundary(*this->mask_ptr);
44 this->regions_ptr->emplace_back(std::move(nlinfo), std::move(boundary));
57 auto nlinfo = boundary.to_nlinfo(*this->mask_ptr);
58 this->regions_ptr->emplace_back(std::move(nlinfo), std::move(boundary));
71 for (
const auto &nlinfo : nlinfos) {
72 auto boundary = nlinfo.to_boundary(*this->mask_ptr);
73 this->regions_ptr->emplace_back(std::move(nlinfo), std::move(boundary));
87 for (
const auto &boundary : boundaries) {
88 auto nlinfo = boundary.to_nlinfo(*this->mask_ptr);
89 this->regions_ptr->emplace_back(std::move(nlinfo), std::move(boundary));
108 double r_squared = std::pow(r,2);
112 double h_squared = std::pow(p2-r,2);
113 difference_type np_top = std::ceil(-std::sqrt(r_squared - h_squared)) + r;
114 difference_type np_bottom = std::floor(std::sqrt(r_squared - h_squared)) + r;
120 return ROI2D(std::move(mask));
126 return ROI2D(std::move(mask));
138 is.read(
reinterpret_cast<char*
>(&num_regions), std::streamsize(
sizeof(
difference_type)));
139 roi.regions_ptr = std::make_shared<std::vector<ROI2D::region>>(num_regions);
140 for (
auto ® : *roi.regions_ptr) {
145 is.read(
reinterpret_cast<char*
>(&roi.points), std::streamsize(
sizeof(
difference_type)));
152 os <<
"Mask :" <<
'\n';
155 for (
const auto &
region : *roi.regions_ptr) {
159 os <<
"Total points: " << roi.points;
167 if (roi1.points == roi2.points &&
isequal(*roi1.mask_ptr, *roi2.mask_ptr) && roi1.regions_ptr->size() == roi2.regions_ptr->size()) {
169 if (!
isequal((*roi1.regions_ptr)[region_idx], (*roi2.regions_ptr)[region_idx])) {
186 save(*roi.mask_ptr, os);
189 os.write(
reinterpret_cast<const char*
>(&num_regions), std::streamsize(
sizeof(
difference_type)));
190 for (
const auto ® : *roi.regions_ptr) {
194 os.write(
reinterpret_cast<const char*
>(&roi.points), std::streamsize(
sizeof(
difference_type)));
199 chk_region_idx_in_bounds(region_idx,
"get_nlinfo()");
201 return (*regions_ptr)[region_idx].nlinfo;
205 chk_region_idx_in_bounds(region_idx,
"get_boundary()");
207 return (*regions_ptr)[region_idx].boundary;
213 if (!mask_ptr->in_bounds(p1,p2)) {
218 const auto &nlinfo = (*regions_ptr)[region_idx].nlinfo;
220 if (nlinfo.noderange.in_bounds(nl_idx)) {
221 for (
difference_type np_idx = 0; np_idx < nlinfo.noderange(nl_idx); np_idx += 2) {
227 if (p1 <= np_bottom) {
228 return {region_idx, np_idx};
239 if (scalefactor < 1) {
240 throw std::invalid_argument(
"Attempted to reduce ROI2D with scalefactor of: " + std::to_string(scalefactor) +
241 ". scalefactor must be an integer of value 1 or greater.");
249 std::vector<region_nlinfo> nlinfos_reduced;
252 nlinfos_reduced.push_back((*regions_ptr)[region_idx].nlinfo.reduce(scalefactor, mask_buf));
255 return ROI2D(std::move(nlinfos_reduced), std::ceil(
double(
height())/scalefactor), std::ceil(
double(
width())/scalefactor));
260 throw std::invalid_argument(
"Attempted to form union of ROI2D of size: " +
size_2D_string() +
261 " with mask of size : " + mask.
size_2D_string() +
". Mask and ROI2D must have the same size.");
269 std::vector<region_nlinfo> nlinfos_unioned;
272 nlinfos_unioned.push_back((*regions_ptr)[region_idx].nlinfo.form_union(mask,mask_buf));
280 return (regions_ptr->empty() ?
incrementor(*
this, 0, { }) :
incrementor(*
this, 0, regions_ptr->front().nlinfo.begin_inc()));
284 return (regions_ptr->empty() ?
incrementor(*
this, 0, { }) :
incrementor(*
this, regions_ptr->size(), regions_ptr->back().nlinfo.end_inc()));
293void ROI2D::set_points() {
295 for (
const auto ®ion : *regions_ptr) {
296 points += region.nlinfo.points;
300void ROI2D::draw_mask() {
301 (*this->mask_ptr)() =
false;
302 for (
const auto ®ion : *regions_ptr) {
303 fill(*this->mask_ptr, region.nlinfo,
true);
308void ROI2D::chk_region_idx_in_bounds(difference_type idx,
const std::string &op)
const {
310 throw std::invalid_argument(
"Attempted to access region " + std::to_string(idx) +
" for " + op +
" operation, but there are only " + std::to_string(regions_ptr->size()) +
" regions.");
320 is.read(
reinterpret_cast<char*
>(&nlinfo.
top), std::streamsize(
sizeof(
difference_type)));
339 os <<
"nlinfo: " <<
'\n';
340 os <<
"Top bound of nlinfo: " << std::to_string(nlinfo.
top) <<
"." <<
'\n';
341 os <<
"Bottom bound of nlinfo: " << std::to_string(nlinfo.
bottom) <<
"." <<
'\n';
342 os <<
"Left bound of nlinfo: " << std::to_string(nlinfo.
left) <<
"." <<
'\n';
343 os <<
"Right bound of nlinfo: " << std::to_string(nlinfo.
right) <<
"." <<
'\n';
344 os <<
"Left position of nodelist: " << std::to_string(nlinfo.
left_nl) <<
"." <<
'\n';
345 os <<
"Right position of nodelist: " << std::to_string(nlinfo.
right_nl) <<
"." <<
'\n';
347 os <<
'\n' <<
"nodelist: " <<
'\n';
349 os <<
"noderange: " <<
'\n';
352 os <<
'\n' <<
"nlinfo points: " << std::to_string(nlinfo.
points) <<
"." <<
'\n';
358 return nlinfo1.
top == nlinfo2.
top &&
373 os.write(
reinterpret_cast<const char*
>(&nlinfo.
top), std::streamsize(
sizeof(
difference_type)));
375 os.write(
reinterpret_cast<const char*
>(&nlinfo.
left), std::streamsize(
sizeof(
difference_type)));
376 os.write(
reinterpret_cast<const char*
>(&nlinfo.
right), std::streamsize(
sizeof(
difference_type)));
389 if (noderange.in_bounds(nl_idx)) {
390 for (
difference_type np_idx = 0; np_idx < noderange(nl_idx); np_idx += 2) {
396 if (p1 <= np_bottom) {
414 right_nl += p2_shift;
417 for (
difference_type nl_idx = 0; nl_idx < nodelist.width(); ++nl_idx) {
418 for (
difference_type np_idx = 0; np_idx < noderange(nl_idx); ++np_idx) {
419 nodelist(np_idx,nl_idx) += p1_shift;
432 return (
empty() ?
incrementor(*
this, 0, 0, 0) :
incrementor(*
this, nodelist.width(), noderange(last_pos_idx()), last_pos_p1() + 1));
440 Array2D<std::vector<ROI2D::difference_type>> &overall_nodelist,
441 Array2D<std::vector<bool>> &overall_active_nodepairs,
442 std::stack<ROI2D::difference_type> &queue_np_idx) {
446 if (overall_nodelist.in_bounds(np_adj_p2)) {
448 for (difference_type np_adj_idx = 0; np_adj_idx < difference_type(overall_nodelist(np_adj_p2).size()); np_adj_idx += 2) {
449 difference_type np_adj_top = overall_nodelist(np_adj_p2)[np_adj_idx];
450 difference_type np_adj_bottom = overall_nodelist(np_adj_p2)[np_adj_idx + 1];
451 if (np_loaded_bottom < np_adj_top) {
454 if (overall_active_nodepairs(np_adj_p2)[np_adj_idx/2] && np_loaded_top <= np_adj_bottom) {
456 overall_active_nodepairs(np_adj_p2)[np_adj_idx/2] =
false;
457 queue_np_idx.push(np_adj_top);
458 queue_np_idx.push(np_adj_bottom);
459 queue_np_idx.push(np_adj_p2);
468 throw std::invalid_argument(
"Attempted to form nlinfos with cutoff of: " + std::to_string(cutoff) +
469 ". cutoff must be an integer of value 0 or greater.");
476 bool in_nodepair =
false;
478 if (!in_nodepair && mask(p1,p2)) {
480 overall_nodelist(p2).push_back(p1);
482 if (in_nodepair && (!mask(p1,p2) || p1 == mask.
height()-1)) {
484 overall_nodelist(p2).push_back((p1 == mask.
height()-1 && mask(p1,p2)) ? p1 : p1-1);
491 overall_active_nodepairs(p2).resize(overall_nodelist(p2).size()/2,
true);
497 std::vector<ROI2D::region_nlinfo> nlinfos;
498 bool removed =
false;
503 if (overall_active_nodepairs(p2_sweep)[np_idx/2]) {
504 overall_active_nodepairs(p2_sweep)[np_idx/2] =
false;
505 np_init_idx = np_idx;
511 if (np_init_idx == -1) {
530 std::stack<difference_type> queue_np_idx;
531 queue_np_idx.push(overall_nodelist(p2_sweep)[np_init_idx]);
532 queue_np_idx.push(overall_nodelist(p2_sweep)[np_init_idx + 1]);
533 queue_np_idx.push(p2_sweep);
534 while (!queue_np_idx.empty()) {
538 difference_type np_loaded_bottom = queue_np_idx.top(); queue_np_idx.pop();
539 difference_type np_loaded_top = queue_np_idx.top(); queue_np_idx.pop();
546 overall_active_nodepairs,
554 overall_active_nodepairs,
558 nlinfo_buf.
points += np_loaded_bottom - np_loaded_top + 1;
561 if (np_loaded_top < nlinfo_buf.
top) { nlinfo_buf.
top = np_loaded_top; }
562 if (np_loaded_bottom > nlinfo_buf.
bottom) { nlinfo_buf.
bottom = np_loaded_bottom; }
563 if (np_loaded_p2 > nlinfo_buf.
right) { nlinfo_buf.
right_nl = nlinfo_buf.
right = np_loaded_p2; }
567 separate_nodelist(np_loaded_p2).push_back(np_loaded_top);
568 separate_nodelist(np_loaded_p2).push_back(np_loaded_bottom);
569 std::sort(separate_nodelist(np_loaded_p2).begin(), separate_nodelist(np_loaded_p2).end());
576 for (
const auto &nodes : separate_nodelist) {
578 max_nodes = nodes.size();
591 nlinfo_buf.
nodelist(np_idx,nl_idx) = separate_nodelist(p2)[np_idx];
601 if (nlinfo_buf.
points >= cutoff) {
602 nlinfos.push_back(nlinfo_buf);
608 return {std::move(nlinfos), removed};
613 if (scalefactor < 1) {
614 throw std::invalid_argument(
"Attempted to reduce nlinfo with scalefactor of: " + std::to_string(scalefactor) +
615 ". scalefactor must be an integer of value 1 or greater.");
623 return region_nlinfo();
630 difference_type bottom_reduced = std::floor(
double(bottom)/scalefactor);
631 difference_type left_reduced_nl = std::ceil(
double(left_nl)/scalefactor);
632 difference_type right_reduced_nl = std::floor(
double(right_nl)/scalefactor);
633 region_nlinfo nlinfo_reduced(bottom_reduced,
640 right_reduced_nl - left_reduced_nl + 1,
643 for (
difference_type nl_idx_reduced = 0; nl_idx_reduced < nlinfo_reduced.nodelist.width(); ++nl_idx_reduced) {
644 difference_type nl_idx = (nl_idx_reduced + nlinfo_reduced.left_nl) * scalefactor - left_nl;
645 for (
difference_type np_idx = 0; np_idx < noderange(nl_idx); np_idx += 2) {
646 difference_type np_top_reduced = std::ceil(
double(nodelist(np_idx, nl_idx))/scalefactor);
647 difference_type np_bottom_reduced = std::floor(
double(nodelist(np_idx + 1, nl_idx))/scalefactor);
648 if (np_bottom_reduced >= np_top_reduced) {
650 nlinfo_reduced.points += np_bottom_reduced - np_top_reduced + 1;
653 if (np_top_reduced < nlinfo_reduced.top) { nlinfo_reduced.top = np_top_reduced; }
654 if (np_bottom_reduced > nlinfo_reduced.bottom) { nlinfo_reduced.bottom = np_bottom_reduced; }
655 if (nl_idx_reduced + nlinfo_reduced.left_nl < nlinfo_reduced.left) { nlinfo_reduced.left = nl_idx_reduced + nlinfo_reduced.left_nl; }
656 if (nl_idx_reduced + nlinfo_reduced.left_nl > nlinfo_reduced.right) { nlinfo_reduced.right = nl_idx_reduced + nlinfo_reduced.left_nl; }
659 nlinfo_reduced.nodelist(nlinfo_reduced.noderange(nl_idx_reduced), nl_idx_reduced) = np_top_reduced;
660 nlinfo_reduced.nodelist(nlinfo_reduced.noderange(nl_idx_reduced)+1, nl_idx_reduced) = np_bottom_reduced;
663 nlinfo_reduced.noderange(nl_idx_reduced) += 2;
669 return nlinfo_reduced.largest_contig_nlinfo(mask_buf);
672ROI2D::region_nlinfo ROI2D::region_nlinfo::form_union(
const Array2D<bool> &mask, Array2D<bool> &mask_buf)
const {
673 if (!mask.same_size(mask_buf)) {
674 throw std::invalid_argument(
"Attempted to form union with mask of size: " + mask.size_2D_string() +
675 " with mask_buf of size : " + mask_buf.size_2D_string() +
". Mask and mask_buf must have the same size.");
682 return region_nlinfo();
687 region_nlinfo nlinfo_union(bottom,
699 Array2D<std::vector<difference_type>> nodelist_buf_vec(nodelist.width(),1);
703 for (
difference_type nl_idx = 0; nl_idx < nodelist.width(); ++nl_idx) {
705 for (
difference_type np_idx = 0; np_idx < noderange(nl_idx); np_idx += 2) {
708 bool in_nodepair =
false;
711 if (!in_nodepair && mask(p1,p2)) {
714 nodelist_buf_vec(nl_idx).push_back(np_top_new);
716 if (in_nodepair && (!mask(p1,p2) || p1 == np_bottom)) {
718 np_bottom_new = ((p1 == np_bottom && mask(p1,p2)) ? p1 : p1-1);
721 nlinfo_union.points += np_bottom_new - np_top_new + 1;
724 if (np_top_new < nlinfo_union.top) { nlinfo_union.top = np_top_new; }
725 if (np_bottom_new > nlinfo_union.bottom) { nlinfo_union.bottom = np_bottom_new; }
726 if (nl_idx + nlinfo_union.left_nl < nlinfo_union.left) { nlinfo_union.left = nl_idx + nlinfo_union.left_nl; }
727 if (nl_idx + nlinfo_union.left_nl > nlinfo_union.right) { nlinfo_union.right = nl_idx + nlinfo_union.left_nl; }
730 nodelist_buf_vec(nl_idx).push_back(np_bottom_new);
733 nlinfo_union.noderange(nl_idx) += 2;
736 if (nlinfo_union.noderange(nl_idx) > max_height) { max_height = nlinfo_union.noderange(nl_idx); }
743 nlinfo_union.nodelist = Array2D<difference_type>(max_height, nlinfo_union.nodelist.width());
744 for (
difference_type nl_idx = 0; nl_idx < nodelist.width(); ++nl_idx) {
746 nlinfo_union.nodelist(np_idx,nl_idx) = nodelist_buf_vec(nl_idx)[np_idx];
751 return nlinfo_union.largest_contig_nlinfo(mask_buf);
758 if (init_direc < 0 || init_direc > 3) {
759 throw std::invalid_argument(
"Initial direction of: " + std::to_string(init_direc) +
" was provided to calc_boundary function. Initial direction must be between (inclusive) 0 and 3.");
786 difference_type direc = init_direc;
789 std::vector<double> boundary_vec = {p1,p2};
790 bool initpoint_encountered =
false;
791 while (!initpoint_encountered) {
793 direc = (direc + 3) % 4;
796 for (difference_type it = 0; it < 4; ++it) {
798 double p1_inc, p2_inc;
799 difference_type p1_inc_mask, p2_inc_mask;
801 case 0: p1_inc = p1; p2_inc = p2 + 1;
802 p1_inc_mask = std::round(p1_inc - 0.5); p2_inc_mask = std::round(p2_inc - 0.5);
804 case 1: p1_inc = p1 - 1; p2_inc = p2;
805 p1_inc_mask = std::round(p1_inc + 0.5); p2_inc_mask = std::round(p2_inc - 0.5);
807 case 2: p1_inc = p1; p2_inc = p2 - 1;
808 p1_inc_mask = std::round(p1_inc + 0.5); p2_inc_mask = std::round(p2_inc + 0.5);
810 case 3: p1_inc = p1 + 1; p2_inc = p2;
811 p1_inc_mask = std::round(p1_inc - 0.5); p2_inc_mask = std::round(p2_inc + 0.5);
815 if (mask.
in_bounds(p1_inc_mask,p2_inc_mask) && mask(p1_inc_mask,p2_inc_mask)) {
817 if (boundary_vec[0] != p1_inc || boundary_vec[1] != p2_inc) {
819 boundary_vec.push_back(p1_inc); boundary_vec.push_back(p2_inc);
820 p1 = p1_inc; p2 = p2_inc;
822 initpoint_encountered =
true;
828 direc = (direc + 1) % 4;
834 throw std::invalid_argument(
"Invalid initial point or empty mask was provided to calc_boundary() function.");
841 for (difference_type idx = 0; idx < difference_type(boundary_vec.size()); idx += 2) {
842 boundary(idx/2,0) = boundary_vec[idx];
843 boundary(idx/2,1) = boundary_vec[idx+1];
850ROI2D::region_nlinfo ROI2D::region_nlinfo::largest_contig_nlinfo(Array2D<bool> &mask_buf)
const {
853 return ROI2D::region_nlinfo();
858 fill(mask_buf, *
this,
true);
863 return *std::max_element(nlinfos_pair.first.begin(), nlinfos_pair.first.end(), [](
const ROI2D::region_nlinfo &a,
const ROI2D::region_nlinfo &b) { return a.points < b.points; });
866ROI2D::region_boundary ROI2D::region_nlinfo::to_boundary(Array2D<bool> &mask_buf)
const {
873 return ROI2D::region_boundary();
879 fill(mask_buf, *
this,
true);
888 Array2D<bool> mask_inv_buf(mask_buf.height(), mask_buf.width());
889 fill(mask_inv_buf, add_boundary,
true);
890 mask_inv_buf = mask_inv_buf & ~mask_buf;
893 std::vector<Array2D<double>> sub_boundaries;
894 for (
difference_type nl_idx = 0; nl_idx < nodelist.width(); ++nl_idx) {
895 if (noderange(nl_idx) > 2) {
899 for (
difference_type np_idx = 0; np_idx < noderange(nl_idx) - 2; np_idx += 2) {
901 if (mask_inv_buf(np_bottom + 1,p2)) {
909 fill(mask_inv_buf, sub_boundaries.back(),
false);
915 return ROI2D::region_boundary(std::move(add_boundary), std::move(sub_boundaries));
919void ROI2D::region_nlinfo::chk_nonempty_op(
const std::string &op)
const {
921 throw std::invalid_argument(
"Attempted to use " + op +
" operator on empty nlinfo" +
922 ". nlinfo must be nonempty.");
936 is.read(
reinterpret_cast<char*
>(&num_sub_boundaries), std::streamsize(
sizeof(
difference_type)));
937 boundary.
sub.resize(num_sub_boundaries);
938 for (
auto &sub_boundary : boundary.
sub) {
949 os <<
"Add Boundary: " <<
'\n' << boundary.
add;
951 os <<
'\n' <<
"Sub Boundary(" << boundary_idx <<
") :" <<
'\n' << boundary.
sub[boundary_idx];
960 if (
isequal(boundary1.
add,boundary2.
add) && boundary1.
sub.size() == boundary2.
sub.size()) {
962 if (!
isequal(boundary1.
sub[boundary_idx], boundary2.
sub[boundary_idx])) {
981 os.write(
reinterpret_cast<const char*
>(&num_sub_boundaries), std::streamsize(
sizeof(
difference_type)));
983 for (
const auto &sub_boundary : boundary.
sub) {
984 save(sub_boundary, os);
996 for (
const auto &sub_boundary : sub) {
997 fill(mask_buf, sub_boundary,
false);
1003 if (nlinfos_pair.first.empty()) {
1011 return *std::max_element(nlinfos_pair.first.begin(), nlinfos_pair.first.end(), [](
const ROI2D::region_nlinfo &a,
const ROI2D::region_nlinfo &b) { return a.points < b.points; });
1045 if (p1 == nlinfo_ptr->nodelist(np_idx+1,nl_idx)) {
1047 if (np_idx == nlinfo_ptr->noderange(nl_idx)-2) {
1050 for (++nl_idx; nl_idx < nlinfo_ptr->nodelist.width() && nlinfo_ptr->noderange(nl_idx) == 0; ++nl_idx) { }
1051 if (nl_idx == nlinfo_ptr->nodelist.width()) {
1058 p1 = nlinfo_ptr->nodelist(np_idx,nl_idx);
1062 p1 = nlinfo_ptr->nodelist(np_idx,nl_idx);
1076 if (this->roi.
size_regions() > 0 && this->nlinfo_inc == this->roi.get_nlinfo(0).begin_inc() && this->roi.get_nlinfo(0).empty()) {
1078 for (++this->region_idx; this->region_idx < this->roi.
size_regions() && this->roi.
get_nlinfo(this->region_idx).
empty(); ++this->region_idx) { }
1124 this->active_nodepairs =
Array2D<bool>(max_height/2, 2*this->r + 1);
1128 switch (subregion_type) {
1142 const ROI2D::ROI2D::region_nlinfo &nlinfo_roi,
1143 const ROI2D::ROI2D::region_nlinfo &nlinfo_simple,
1145 std::stack<ROI2D::difference_type> &queue_np_idx) {
1149 difference_type nl_adj_idx = np_adj_p2 - nlinfo_roi.left_nl;
1150 difference_type nl_simple_idx = np_adj_p2 - nlinfo_simple.left_nl;
1151 if (nlinfo_roi.noderange.in_bounds(nl_adj_idx) && nlinfo_simple.noderange.in_bounds(nl_simple_idx)) {
1153 difference_type np_simple_top = nlinfo_simple.nodelist(0, nl_simple_idx);
1154 difference_type np_simple_bottom = nlinfo_simple.nodelist(1, nl_simple_idx);
1156 for (difference_type np_adj_idx = 0; np_adj_idx < nlinfo_roi.noderange(nl_adj_idx); np_adj_idx += 2) {
1157 difference_type np_adj_top = nlinfo_roi.nodelist(np_adj_idx, nl_adj_idx);
1158 difference_type np_adj_bottom = nlinfo_roi.nodelist(np_adj_idx + 1, nl_adj_idx);
1159 if (np_loaded_bottom < np_adj_top || np_loaded_bottom < np_simple_top) {
1162 if (active_nodepairs(np_adj_idx/2, nl_simple_idx) && np_loaded_top <= np_adj_bottom && np_loaded_top <= np_simple_bottom) {
1168 difference_type np_top = std::max(np_adj_top, np_simple_top);
1169 difference_type np_bottom = std::min(np_adj_bottom, np_simple_bottom);
1170 if (np_top <= np_bottom) {
1175 active_nodepairs(np_adj_idx/2, nl_simple_idx) =
false;
1176 queue_np_idx.push(np_top);
1177 queue_np_idx.push(np_bottom);
1178 queue_np_idx.push(np_adj_p2);
1190 nlinfo_subregion.
bottom = 0;
1192 nlinfo_subregion.
right = 0;
1193 nlinfo_subregion.
left_nl = p2 - r;
1194 nlinfo_subregion.
right_nl = p2 + r;
1196 nlinfo_subregion.
points = 0;
1200 if (region_idx_pair.first == -1) {
1202 return nlinfo_subregion;
1206 active_nodepairs() =
true;
1209 auto &nlinfo_roi = roi.
get_nlinfo(region_idx_pair.first);
1212 nlinfo_simple.
shift(p1 - r, p2 - r);
1216 active_nodepairs(region_idx_pair.second/2, r) =
false;
1217 std::stack<difference_type> queue_np_idx;
1218 queue_np_idx.push(std::max(nlinfo_simple.
nodelist(0, r), nlinfo_roi.nodelist(region_idx_pair.second, p2 - nlinfo_roi.left_nl)));
1219 queue_np_idx.push(std::min(nlinfo_simple.
nodelist(1, r), nlinfo_roi.nodelist(region_idx_pair.second + 1, p2 - nlinfo_roi.left_nl)));
1220 queue_np_idx.push(p2);
1221 while (!queue_np_idx.empty()) {
1224 difference_type np_loaded_p2 = queue_np_idx.top(); queue_np_idx.pop();
1225 difference_type np_loaded_bottom = queue_np_idx.top(); queue_np_idx.pop();
1226 difference_type np_loaded_top = queue_np_idx.top(); queue_np_idx.pop();
1247 nlinfo_subregion.
points += np_loaded_bottom - np_loaded_top + 1;
1250 if (np_loaded_top < nlinfo_subregion.
top) { nlinfo_subregion.
top = np_loaded_top; }
1251 if (np_loaded_bottom > nlinfo_subregion.
bottom) { nlinfo_subregion.
bottom = np_loaded_bottom; }
1252 if (np_loaded_p2 < nlinfo_subregion.
left) { nlinfo_subregion.
left = np_loaded_p2; }
1253 if (np_loaded_p2 > nlinfo_subregion.
right) { nlinfo_subregion.
right = np_loaded_p2; }
1257 nlinfo_subregion.
nodelist(nlinfo_subregion.
noderange(nl_output_idx), nl_output_idx) = np_loaded_top;
1258 nlinfo_subregion.
nodelist(nlinfo_subregion.
noderange(nl_output_idx) + 1, nl_output_idx) = np_loaded_bottom;
1259 std::sort(&nlinfo_subregion.
nodelist(0, nl_output_idx), &nlinfo_subregion.
nodelist(0, nl_output_idx) + nlinfo_subregion.
noderange(nl_output_idx) + 2);
1262 nlinfo_subregion.
noderange(nl_output_idx) += 2;
1266 nlinfo_simple.
shift(r - p1, r - p2);
1268 return nlinfo_subregion;
difference_type width() const
std::string size_2D_string() const
static std::enable_if< std::is_arithmetic< T >::value, T_output >::type load(const std::string &)
difference_type height() const
difference_type size() const
bool in_bounds(difference_type p) const
friend void save(const ROI2D &, std::ofstream &)
contig_subregion_generator get_contig_subregion_generator(SUBREGION, difference_type) const
std::ptrdiff_t difference_type
ROI2D reduce(difference_type) const
difference_type size_regions() const
difference_type width() const
friend std::ostream & operator<<(std::ostream &, const ROI2D &)
details::ROI2D_incrementor incrementor
incrementor end_inc() const
static ROI2D simple_square(difference_type)
incrementor begin_inc() const
const region_nlinfo & get_nlinfo(difference_type) const
friend bool isequal(const ROI2D &, const ROI2D &)
static ROI2D load(std::ifstream &)
static ROI2D simple_circle(difference_type)
ROI2D form_union(const Array2D< bool > &) const
details::ROI2D_contig_subregion_generator contig_subregion_generator
difference_type height() const
std::pair< difference_type, difference_type > get_region_idx(difference_type, difference_type) const
std::string size_2D_string() const
const region_boundary & get_boundary(difference_type) const
const ROI2D::region_nlinfo & operator()(difference_type, difference_type) const
ROI2D::difference_type difference_type
ROI2D_contig_subregion_generator() noexcept
ROI2D::difference_type difference_type
ROI2D_incrementor & operator++()
void add_interacting_nodes(ROI2D::difference_type np_adj_p2, ROI2D::difference_type np_loaded_top, ROI2D::difference_type np_loaded_bottom, Array2D< std::vector< ROI2D::difference_type > > &overall_nodelist, Array2D< std::vector< bool > > &overall_active_nodepairs, std::stack< ROI2D::difference_type > &queue_np_idx)
void simple_contig_subregion_add_interacting_nodes(ROI2D::difference_type np_adj_p2, ROI2D::difference_type np_loaded_top, ROI2D::difference_type np_loaded_bottom, const ROI2D::ROI2D::region_nlinfo &nlinfo_roi, const ROI2D::ROI2D::region_nlinfo &nlinfo_simple, Array2D< bool > &active_nodepairs, std::stack< ROI2D::difference_type > &queue_np_idx)
Array2D< double > calc_boundary(const Array2D< bool > &mask, double init_p1, double init_p2, ROI2D::difference_type init_direc=0)
bool isequal(const Data2D &data1, const Data2D &data2)
T_container & fill(T_container &A, const ROI2D::region_nlinfo &nlinfo, const T &val)
Disp2D add(const std::vector< Disp2D > &, INTERP)
void save(const Data2D &data, std::ofstream &os)
std::ostream & operator<<(std::ostream &os, const Data2D &data)
static region_boundary load(std::ifstream &)
std::vector< Array2D< double > > sub
difference_type last_pos_p2() const
incrementor begin_inc() const
Array2D< difference_type > noderange
bool in_nlinfo(difference_type, difference_type) const
difference_type last_pos_p1() const
static region_nlinfo load(std::ifstream &)
Array2D< difference_type > nodelist
incrementor end_inc() const
region_nlinfo & shift(difference_type, difference_type)
static std::pair< std::vector< ROI2D::region_nlinfo >, bool > form_nlinfos(const Array2D< bool > &, ROI2D::difference_type=0)
static region load(std::ifstream &)