mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-09-11 06:18:09 +00:00
ifcviewer: fix progress bar capping at ~1/n during streaming
The streamer carved [0,100] evenly across N prioritised contexts (and again across the net/gross passes). In practice nearly every element yields from the first (Body) context, so smooth progress only ever filled range/n of the bar — typically ~20% — before snapping forward. Drive progress directly from yielded element count over total instead. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -482,12 +482,15 @@ void GeometryStreamer::run(const std::string& path, int num_threads) {
|
|||||||
QElapsedTimer stream_timer;
|
QElapsedTimer stream_timer;
|
||||||
stream_timer.start();
|
stream_timer.start();
|
||||||
|
|
||||||
// Split the 0–100 progress range proportionally to element counts so
|
// Drive the bar from yields across all passes/contexts. Earlier the
|
||||||
// the bar advances roughly with wall time across both passes.
|
// [0,100] range was carved evenly across N prioritised contexts, but
|
||||||
|
// in practice nearly every element yields from the first (Body)
|
||||||
|
// context, so smooth progress only ever filled 1/n of the bar before
|
||||||
|
// jumping to the next allocation — visually, a typical 5-context
|
||||||
|
// file looked like it capped at ~20%.
|
||||||
const size_t total_count = net_ids.size() + gross_ids.size();
|
const size_t total_count = net_ids.size() + gross_ids.size();
|
||||||
const int net_progress_end = total_count == 0
|
size_t yielded_count = 0;
|
||||||
? 100
|
int last_emitted_progress = 0;
|
||||||
: static_cast<int>(100.0 * net_ids.size() / total_count + 0.5);
|
|
||||||
|
|
||||||
// High-priority context first, so each element gets its preferred
|
// High-priority context first, so each element gets its preferred
|
||||||
// representation; lower-priority contexts only pick up elements the
|
// representation; lower-priority contexts only pick up elements the
|
||||||
@@ -497,9 +500,7 @@ void GeometryStreamer::run(const std::string& path, int num_threads) {
|
|||||||
prioritisedContextIds(ifc_file_.get());
|
prioritisedContextIds(ifc_file_.get());
|
||||||
|
|
||||||
auto run_pass = [&](const std::set<int>& include_ids,
|
auto run_pass = [&](const std::set<int>& include_ids,
|
||||||
bool is_gross,
|
bool is_gross) -> bool {
|
||||||
int progress_lo,
|
|
||||||
int progress_hi) -> bool {
|
|
||||||
if (include_ids.empty()) return true;
|
if (include_ids.empty()) return true;
|
||||||
|
|
||||||
ifcopenshell::geometry::Settings base_settings = settings;
|
ifcopenshell::geometry::Settings base_settings = settings;
|
||||||
@@ -510,8 +511,7 @@ void GeometryStreamer::run(const std::string& path, int num_threads) {
|
|||||||
// Elements that haven't yet produced geometry from any context.
|
// Elements that haven't yet produced geometry from any context.
|
||||||
std::set<int> remaining = include_ids;
|
std::set<int> remaining = include_ids;
|
||||||
|
|
||||||
auto run_iterator = [&](ifcopenshell::geometry::Settings& iter_settings,
|
auto run_iterator = [&](ifcopenshell::geometry::Settings& iter_settings) -> bool {
|
||||||
int sub_lo, int sub_hi) -> bool {
|
|
||||||
if (remaining.empty()) return true;
|
if (remaining.empty()) return true;
|
||||||
|
|
||||||
std::vector<ifcopenshell::geometry::filter_t> filters;
|
std::vector<ifcopenshell::geometry::filter_t> filters;
|
||||||
@@ -535,14 +535,10 @@ void GeometryStreamer::run(const std::string& path, int num_threads) {
|
|||||||
|
|
||||||
if (!iterator->initialize()) {
|
if (!iterator->initialize()) {
|
||||||
// No geometry survived this context for the remaining ids.
|
// No geometry survived this context for the remaining ids.
|
||||||
// Still advance progress so the bar doesn't stall.
|
// Subsequent contexts will pick them up; nothing to emit.
|
||||||
progress_ = sub_hi;
|
|
||||||
emit progressChanged(sub_hi);
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
int last_progress = sub_lo;
|
|
||||||
|
|
||||||
do {
|
do {
|
||||||
if (cancel_requested_.load()) break;
|
if (cancel_requested_.load()) break;
|
||||||
|
|
||||||
@@ -656,11 +652,13 @@ void GeometryStreamer::run(const std::string& path, int num_threads) {
|
|||||||
|
|
||||||
emit instanceReady(std::move(inst));
|
emit instanceReady(std::move(inst));
|
||||||
total_shapes++;
|
total_shapes++;
|
||||||
|
yielded_count++;
|
||||||
|
|
||||||
const int p = sub_lo +
|
const int p = total_count > 0
|
||||||
(iterator->progress() * (sub_hi - sub_lo)) / 100;
|
? static_cast<int>((100 * yielded_count) / total_count)
|
||||||
if (p != last_progress) {
|
: 100;
|
||||||
last_progress = p;
|
if (p != last_emitted_progress) {
|
||||||
|
last_emitted_progress = p;
|
||||||
progress_ = p;
|
progress_ = p;
|
||||||
emit progressChanged(p);
|
emit progressChanged(p);
|
||||||
}
|
}
|
||||||
@@ -672,12 +670,10 @@ void GeometryStreamer::run(const std::string& path, int num_threads) {
|
|||||||
if (prioritised_contexts.empty()) {
|
if (prioritised_contexts.empty()) {
|
||||||
// No IfcGeometricRepresentationContext entities — fall back to
|
// No IfcGeometricRepresentationContext entities — fall back to
|
||||||
// a single iterator pass without context-id filtering.
|
// a single iterator pass without context-id filtering.
|
||||||
return run_iterator(base_settings, progress_lo, progress_hi);
|
return run_iterator(base_settings);
|
||||||
}
|
}
|
||||||
|
|
||||||
const int range = progress_hi - progress_lo;
|
for (size_t i = 0; i < prioritised_contexts.size(); ++i) {
|
||||||
const int n = static_cast<int>(prioritised_contexts.size());
|
|
||||||
for (int i = 0; i < n; ++i) {
|
|
||||||
if (cancel_requested_.load()) break;
|
if (cancel_requested_.load()) break;
|
||||||
if (remaining.empty()) break;
|
if (remaining.empty()) break;
|
||||||
|
|
||||||
@@ -685,22 +681,15 @@ void GeometryStreamer::run(const std::string& path, int num_threads) {
|
|||||||
iter_settings.set("context-ids",
|
iter_settings.set("context-ids",
|
||||||
std::set<int>{ prioritised_contexts[i] });
|
std::set<int>{ prioritised_contexts[i] });
|
||||||
|
|
||||||
const int sub_lo = progress_lo + (range * i) / n;
|
if (!run_iterator(iter_settings)) return false;
|
||||||
const int sub_hi = (i + 1 == n)
|
|
||||||
? progress_hi
|
|
||||||
: progress_lo + (range * (i + 1)) / n;
|
|
||||||
|
|
||||||
if (!run_iterator(iter_settings, sub_lo, sub_hi)) return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
progress_ = progress_hi;
|
|
||||||
emit progressChanged(progress_hi);
|
|
||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
|
|
||||||
if (!run_pass(net_ids, /*is_gross=*/false, 0, net_progress_end)) return;
|
if (!run_pass(net_ids, /*is_gross=*/false)) return;
|
||||||
if (!cancel_requested_.load()) {
|
if (!cancel_requested_.load()) {
|
||||||
run_pass(gross_ids, /*is_gross=*/true, net_progress_end, 100);
|
run_pass(gross_ids, /*is_gross=*/true);
|
||||||
}
|
}
|
||||||
|
|
||||||
progress_ = 100;
|
progress_ = 100;
|
||||||
|
|||||||
Reference in New Issue
Block a user