mirror of
https://git.dev.opencascade.org/repos/occt.git
synced 2025-04-26 10:19:45 +03:00
Update empty method guards to new style with regex (see PR). Used clang-format 18.1.8. New actions to validate code formatting is added. Update .clang-format with disabling of include sorting. It is temporary changes, then include will be sorted. Apply formatting for /src and /tools folder. The files with .hxx,.cxx,.lxx,.h,.pxx,.hpp,*.cpp extensions.
618 lines
23 KiB
C++
618 lines
23 KiB
C++
// Created on: 2002-02-22
|
|
// Created by: Andrey BETENEV
|
|
// Copyright (c) 2002-2014 OPEN CASCADE SAS
|
|
//
|
|
// This file is part of Open CASCADE Technology software library.
|
|
//
|
|
// This library is free software; you can redistribute it and/or modify it under
|
|
// the terms of the GNU Lesser General Public License version 2.1 as published
|
|
// by the Free Software Foundation, with special exception defined in the file
|
|
// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
|
|
// distribution for complete text of the license and disclaimer of any warranty.
|
|
//
|
|
// Alternatively, this file may be used under the terms of Open CASCADE
|
|
// commercial license or contractual agreement.
|
|
|
|
#ifndef _Message_ProgressScope_HeaderFile
|
|
#define _Message_ProgressScope_HeaderFile
|
|
|
|
#include <Standard_Assert.hxx>
|
|
#include <Standard_TypeDef.hxx>
|
|
#include <Standard_DefineAlloc.hxx>
|
|
#include <Standard_Handle.hxx>
|
|
#include <Precision.hxx>
|
|
#include <TCollection_AsciiString.hxx>
|
|
|
|
class Message_ProgressRange;
|
|
class Message_ProgressIndicator;
|
|
|
|
//! Message_ProgressScope class provides convenient way to advance progress
|
|
//! indicator in context of complex program organized in hierarchical way,
|
|
//! where usually it is difficult (or even not possible) to consider process
|
|
//! as linear with fixed step.
|
|
//!
|
|
//! On every level (sub-operation) in hierarchy of operations
|
|
//! the local instance of the Message_ProgressScope class is created.
|
|
//! It takes a part of the upper-level scope (via Message_ProgressRange) and provides
|
|
//! a way to consider this part as independent scale with locally defined range.
|
|
//!
|
|
//! The position on the local scale may be advanced using the method Next(),
|
|
//! which allows iteration-like advancement. This method can take argument to
|
|
//! advance by the specified value (with default step equal to 1).
|
|
//! This method returns Message_ProgressRange object that takes responsibility
|
|
//! of making the specified step, either directly at its destruction or by
|
|
//! delegating this task to another sub-scope created from that range object.
|
|
//!
|
|
//! It is important that sub-scope must have life time less than
|
|
//! the life time of its parent scope that provided the range.
|
|
//! The usage pattern is to create scope objects as local variables in the
|
|
//! functions that do the job, and pass range objects returned by Next() to
|
|
//! the functions of the lower level, to allow them creating their own scopes.
|
|
//!
|
|
//! The scope has a name that can be used in visualization of the progress.
|
|
//! It can be null. Note that when C string literal is used as a name, then its
|
|
//! value is not copied, just pointer is stored. In other variants (char pointer
|
|
//! or a string class) the string is copied, which is additional overhead.
|
|
//!
|
|
//! The same instance of the progress scope! must not be used concurrently from different threads.
|
|
//! For the algorithm running its tasks in parallel threads, a common scope is
|
|
//! created before the parallel execution, and the range objects produced by method
|
|
//! Next() are used to initialise the data pertinent to each task.
|
|
//! Then the progress is advanced within each task using its own range object.
|
|
//! See example below.
|
|
//!
|
|
//! Note that while a range of the scope is specified using Standard_Real
|
|
//! (double) parameter, it is expected to be a positive integer value.
|
|
//! If the range is not an integer, method Next() shall be called with
|
|
//! explicit step argument, and the rounded value returned by method Value()
|
|
//! may be not coherent with the step and range.
|
|
//!
|
|
//! A scope can be created with option "infinite". This is useful when
|
|
//! the number of steps is not known by the time of the scope creation.
|
|
//! In this case the progress will be advanced logarithmically, approaching
|
|
//! the end of the scope at infinite number of steps. The parameter Max
|
|
//! for infinite scope indicates number of steps corresponding to mid-range.
|
|
//!
|
|
//! A progress scope created with empty constructor is not connected to any
|
|
//! progress indicator, and passing the range created on it to any algorithm
|
|
//! allows it executing safely without actual progress indication.
|
|
//!
|
|
//! Example of preparation of progress indicator:
|
|
//!
|
|
//! @code{.cpp}
|
|
//! Handle(Message_ProgressIndicator) aProgress = ...; // assume it can be null
|
|
//! func (Message_ProgressIndicator::Start (aProgress));
|
|
//! @endcode
|
|
//!
|
|
//! Example of usage in sequential process:
|
|
//!
|
|
//! @code{.cpp}
|
|
//! Message_ProgressScope aWholePS(aRange, "Whole process", 100);
|
|
//!
|
|
//! // do one step taking 20%
|
|
//! func1 (aWholePS.Next (20)); // func1 will take 20% of the whole scope
|
|
//! if (aWholePS.UserBreak()) // exit prematurely if the user requested break
|
|
//! return;
|
|
//!
|
|
//! // ... do next step taking 50%
|
|
//! func2 (aWholePS.Next (50));
|
|
//! if (aWholePS.UserBreak())
|
|
//! return;
|
|
//! @endcode
|
|
//!
|
|
//! Example of usage in nested cycle:
|
|
//!
|
|
//! @code{.cpp}
|
|
//! // Outer cycle
|
|
//! Message_ProgressScope anOuter (theProgress, "Outer", nbOuter);
|
|
//! for (Standard_Integer i = 0; i < nbOuter && anOuter.More(); i++)
|
|
//! {
|
|
//! // Inner cycle
|
|
//! Message_ProgressScope anInner (anOuter.Next(), "Inner", nbInner);
|
|
//! for (Standard_Integer j = 0; j < nbInner && anInner.More(); j++)
|
|
//! {
|
|
//! // Cycle body
|
|
//! func (anInner.Next());
|
|
//! }
|
|
//! }
|
|
//! @endcode
|
|
//!
|
|
//! Example of use in function:
|
|
//!
|
|
//! @code{.cpp}
|
|
//! //! Implementation of iterative algorithm showing its progress
|
|
//! func (const Message_ProgressRange& theProgress)
|
|
//! {
|
|
//! // Create local scope covering the given progress range.
|
|
//! // Set this scope to count aNbSteps steps.
|
|
//! Message_ProgressScope aScope (theProgress, "", aNbSteps);
|
|
//! for (Standard_Integer i = 0; i < aNbSteps && aScope.More(); i++)
|
|
//! {
|
|
//! // Optional: pass range returned by method Next() to the nested algorithm
|
|
//! // to allow it to show its progress too (by creating its own scope object).
|
|
//! // In any case the progress will advance to the next step by the end of the func2 call.
|
|
//! func2 (aScope.Next());
|
|
//! }
|
|
//! }
|
|
//! @endcode
|
|
//!
|
|
//! Example of usage in parallel process:
|
|
//!
|
|
//! @code{.cpp}
|
|
//! struct Task
|
|
//! {
|
|
//! Data& Data;
|
|
//! Message_ProgressRange Range;
|
|
//!
|
|
//! Task (const Data& theData, const Message_ProgressRange& theRange)
|
|
//! : Data (theData), Range (theRange) {}
|
|
//! };
|
|
//! struct Functor
|
|
//! {
|
|
//! void operator() (Task& theTask) const
|
|
//! {
|
|
//! // Note: it is essential that this method is executed only once for the same Task object
|
|
//! Message_ProgressScope aPS (theTask.Range, NULL, theTask.Data.NbItems);
|
|
//! for (Standard_Integer i = 0; i < theTask.Data.NbSteps && aPS.More(); i++)
|
|
//! {
|
|
//! do_job (theTask.Data.Item[i], aPS.Next());
|
|
//! }
|
|
//! }
|
|
//! };
|
|
//! ...
|
|
//! {
|
|
//! std::vector<Data> aData = ...;
|
|
//! std::vector<Task> aTasks;
|
|
//!
|
|
//! Message_ProgressScope aPS (aRootRange, "Data processing", aData.size());
|
|
//! for (Standard_Integer i = 0; i < aData.size(); ++i)
|
|
//! aTasks.push_back (Task (aData[i], aPS.Next()));
|
|
//!
|
|
//! OSD_Parallel::ForEach (aTasks.begin(), aTasks.end(), Functor());
|
|
//! }
|
|
//! @endcode
|
|
//!
|
|
//! For lightweight algorithms that do not need advancing the progress
|
|
//! within individual tasks the code can be simplified to avoid inner scopes:
|
|
//!
|
|
//! @code
|
|
//! struct Functor
|
|
//! {
|
|
//! void operator() (Task& theTask) const
|
|
//! {
|
|
//! if (theTask.Range.More())
|
|
//! {
|
|
//! do_job (theTask.Data);
|
|
//! // advance the progress
|
|
//! theTask.Range.Close();
|
|
//! }
|
|
//! }
|
|
//! };
|
|
//! @endcode
|
|
class Message_ProgressScope
|
|
{
|
|
public:
|
|
class NullString; //!< auxiliary type for passing NULL name to Message_ProgressScope constructor
|
|
public: //! @name Preparation methods
|
|
//! Creates dummy scope.
|
|
//! It can be safely passed to algorithms; no progress indication will be done.
|
|
Message_ProgressScope()
|
|
: myProgress(0),
|
|
myParent(0),
|
|
myName(0),
|
|
myStart(0.),
|
|
myPortion(1.),
|
|
myMax(1.),
|
|
myValue(0.),
|
|
myIsActive(false),
|
|
myIsOwnName(false),
|
|
myIsInfinite(false)
|
|
{
|
|
}
|
|
|
|
//! Creates a new scope taking responsibility of the part of the progress
|
|
//! scale described by theRange. The new scope has own range from 0 to
|
|
//! theMax, which is mapped to the given range.
|
|
//!
|
|
//! The topmost scope is created and owned by Message_ProgressIndicator
|
|
//! and its pointer is contained in the Message_ProgressRange returned by the Start() method of
|
|
//! progress indicator.
|
|
//!
|
|
//! @param[in][out] theRange range to fill (will be disarmed)
|
|
//! @param[in] theName new scope name
|
|
//! @param[in] theMax number of steps in scope
|
|
//! @param[in] isInfinite infinite flag
|
|
Message_ProgressScope(const Message_ProgressRange& theRange,
|
|
const TCollection_AsciiString& theName,
|
|
Standard_Real theMax,
|
|
Standard_Boolean isInfinite = false);
|
|
|
|
//! Creates a new scope taking responsibility of the part of the progress
|
|
//! scale described by theRange. The new scope has own range from 0 to
|
|
//! theMax, which is mapped to the given range.
|
|
//!
|
|
//! The topmost scope is created and owned by Message_ProgressIndicator
|
|
//! and its pointer is contained in the Message_ProgressRange returned by the Start() method of
|
|
//! progress indicator.
|
|
//!
|
|
//! @param[in][out] theRange range to fill (will be disarmed)
|
|
//! @param[in] theName new scope name constant (will be stored by pointer with no deep
|
|
//! copy)
|
|
//! @param[in] theMax number of steps in scope
|
|
//! @param[in] isInfinite infinite flag
|
|
template <size_t N>
|
|
Message_ProgressScope(const Message_ProgressRange& theRange,
|
|
const char (&theName)[N],
|
|
Standard_Real theMax,
|
|
Standard_Boolean isInfinite = false);
|
|
|
|
//! Creates a new scope taking responsibility of the part of the progress
|
|
//! scale described by theRange. The new scope has own range from 0 to
|
|
//! theMax, which is mapped to the given range.
|
|
//!
|
|
//! The topmost scope is created and owned by Message_ProgressIndicator
|
|
//! and its pointer is contained in the Message_ProgressRange returned by the Start() method of
|
|
//! progress indicator.
|
|
//!
|
|
//! @param[in][out] theRange range to fill (will be disarmed)
|
|
//! @param[in] theName empty scope name (only NULL is accepted as argument)
|
|
//! @param[in] theMax number of steps in scope
|
|
//! @param[in] isInfinite infinite flag
|
|
Message_ProgressScope(const Message_ProgressRange& theRange,
|
|
const NullString* theName,
|
|
Standard_Real theMax,
|
|
Standard_Boolean isInfinite = false);
|
|
|
|
//! Sets the name of the scope.
|
|
void SetName(const TCollection_AsciiString& theName)
|
|
{
|
|
if (myIsOwnName)
|
|
{
|
|
Standard::Free(myName);
|
|
myIsOwnName = false;
|
|
}
|
|
myName = NULL;
|
|
if (!theName.IsEmpty())
|
|
{
|
|
myIsOwnName = true;
|
|
myName = (char*)Standard::AllocateOptimal(Standard_Size(theName.Length()) + Standard_Size(1));
|
|
char* aName = (char*)myName;
|
|
memcpy(aName, theName.ToCString(), theName.Length());
|
|
aName[theName.Length()] = '\0';
|
|
}
|
|
}
|
|
|
|
//! Sets the name of the scope; can be null.
|
|
//! Note! Just pointer to the given string is copied,
|
|
//! so do not pass string from a temporary variable whose
|
|
//! lifetime is less than that of this object.
|
|
template <size_t N>
|
|
void SetName(const char (&theName)[N])
|
|
{
|
|
if (myIsOwnName)
|
|
{
|
|
Standard::Free(myName);
|
|
myIsOwnName = false;
|
|
}
|
|
myName = theName;
|
|
}
|
|
|
|
public: //! @name Advance by iterations
|
|
//! Returns true if ProgressIndicator signals UserBreak
|
|
Standard_Boolean UserBreak() const;
|
|
|
|
//! Returns false if ProgressIndicator signals UserBreak
|
|
Standard_Boolean More() const { return !UserBreak(); }
|
|
|
|
//! Advances position by specified step and returns the range
|
|
//! covering this step
|
|
Message_ProgressRange Next(Standard_Real theStep = 1.);
|
|
|
|
public: //! @name Auxiliary methods to use in ProgressIndicator
|
|
//! Force update of presentation of the progress indicator.
|
|
//! Should not be called concurrently.
|
|
void Show();
|
|
|
|
//! Returns true if this progress scope is attached to some indicator.
|
|
Standard_Boolean IsActive() const { return myIsActive; }
|
|
|
|
//! Returns the name of the scope (may be null).
|
|
//! Scopes with null name (e.g. root scope) should
|
|
//! be bypassed when reporting progress to the user.
|
|
Standard_CString Name() const { return myName; }
|
|
|
|
//! Returns parent scope (null for top-level scope)
|
|
const Message_ProgressScope* Parent() const { return myParent; }
|
|
|
|
//! Returns the maximal value of progress in this scope
|
|
Standard_Real MaxValue() const { return myMax; }
|
|
|
|
//! Returns the current value of progress in this scope.
|
|
//!
|
|
//! The value is computed by mapping current global progress into
|
|
//! this scope range; the result is rounded up to integer.
|
|
//! Note that if MaxValue() is not an integer, Value() can be
|
|
//! greater than MaxValue() due to that rounding.
|
|
//!
|
|
//! This method should not be called concurrently while the progress
|
|
//! is advancing, except from implementation of method Show() in
|
|
//! descendant of Message_ProgressIndicator.
|
|
Standard_Real Value() const;
|
|
|
|
//! Returns the infinite flag
|
|
Standard_Boolean IsInfinite() const { return myIsInfinite; }
|
|
|
|
//! Get the portion of the indicator covered by this scope (from 0 to 1)
|
|
Standard_Real GetPortion() const { return myPortion; }
|
|
|
|
public: //! @name Destruction, allocation
|
|
//! Destructor - closes the scope and adds its scale to the total progress
|
|
~Message_ProgressScope()
|
|
{
|
|
Close();
|
|
if (myIsOwnName)
|
|
{
|
|
Standard::Free(myName);
|
|
myIsOwnName = false;
|
|
myName = NULL;
|
|
}
|
|
}
|
|
|
|
//! Closes the scope and advances the progress to its end.
|
|
//! Closed scope should not be used.
|
|
void Close();
|
|
|
|
DEFINE_STANDARD_ALLOC
|
|
|
|
private: //! @name Internal methods
|
|
//! Creates a top-level scope with default range [0,1] and step 1.
|
|
//! Called only by Message_ProgressIndicator constructor.
|
|
Message_ProgressScope(Message_ProgressIndicator* theProgress);
|
|
|
|
//! Convert value from this scope to global scale, but disregarding
|
|
//! start position of the scope, in the range [0, myPortion]
|
|
Standard_Real localToGlobal(const Standard_Real theVal) const;
|
|
|
|
private:
|
|
//! Copy constructor is prohibited
|
|
Message_ProgressScope(const Message_ProgressScope& theOther);
|
|
|
|
//! Copy assignment is prohibited
|
|
Message_ProgressScope& operator=(const Message_ProgressScope& theOther);
|
|
|
|
private:
|
|
Message_ProgressIndicator* myProgress; //!< Pointer to progress indicator instance
|
|
const Message_ProgressScope* myParent; //!< Pointer to parent scope
|
|
Standard_CString myName; //!< Name of the operation being done in this scope, or null
|
|
|
|
Standard_Real myStart; //!< Start position on the global scale [0, 1]
|
|
// clang-format off
|
|
Standard_Real myPortion; //!< The portion of the global scale covered by this scope [0, 1]
|
|
// clang-format on
|
|
|
|
Standard_Real myMax; //!< Maximal value of progress in this scope
|
|
Standard_Real myValue; //!< Current position advanced within this scope [0, Max]
|
|
|
|
Standard_Boolean myIsActive; //!< flag indicating armed/disarmed state
|
|
Standard_Boolean myIsOwnName; //!< flag indicating if name was allocated or not
|
|
Standard_Boolean myIsInfinite; //!< Option to advance by hyperbolic law
|
|
|
|
private:
|
|
friend class Message_ProgressIndicator;
|
|
friend class Message_ProgressRange;
|
|
};
|
|
|
|
#include <Message_ProgressRange.hxx>
|
|
|
|
//=======================================================================
|
|
// function : Message_ProgressScope
|
|
// purpose :
|
|
//=======================================================================
|
|
inline Message_ProgressScope::Message_ProgressScope(Message_ProgressIndicator* theProgress)
|
|
: myProgress(theProgress),
|
|
myParent(0),
|
|
myName(0),
|
|
myStart(0.),
|
|
myPortion(1.),
|
|
myMax(1.),
|
|
myValue(0.),
|
|
myIsActive(theProgress != NULL),
|
|
myIsOwnName(false),
|
|
myIsInfinite(false)
|
|
{
|
|
}
|
|
|
|
//=======================================================================
|
|
// function : Message_ProgressScope
|
|
// purpose :
|
|
//=======================================================================
|
|
inline Message_ProgressScope::Message_ProgressScope(const Message_ProgressRange& theRange,
|
|
const TCollection_AsciiString& theName,
|
|
Standard_Real theMax,
|
|
Standard_Boolean isInfinite)
|
|
: myProgress(theRange.myParentScope != NULL ? theRange.myParentScope->myProgress : NULL),
|
|
myParent(theRange.myParentScope),
|
|
myName(NULL),
|
|
myStart(theRange.myStart),
|
|
myPortion(theRange.myDelta),
|
|
myMax(Max(1.e-6, theMax)), // protection against zero range
|
|
myValue(0.),
|
|
myIsActive(myProgress != NULL && !theRange.myWasUsed),
|
|
myIsOwnName(false),
|
|
myIsInfinite(isInfinite)
|
|
{
|
|
SetName(theName);
|
|
Standard_ASSERT_VOID(!theRange.myWasUsed,
|
|
"Message_ProgressRange is used to initialize more than one scope");
|
|
theRange.myWasUsed = true; // Disarm the range
|
|
}
|
|
|
|
//=======================================================================
|
|
// function : Message_ProgressScope
|
|
// purpose :
|
|
//=======================================================================
|
|
template <size_t N>
|
|
Message_ProgressScope::Message_ProgressScope(const Message_ProgressRange& theRange,
|
|
const char (&theName)[N],
|
|
Standard_Real theMax,
|
|
Standard_Boolean isInfinite)
|
|
: myProgress(theRange.myParentScope != NULL ? theRange.myParentScope->myProgress : NULL),
|
|
myParent(theRange.myParentScope),
|
|
myName(theName),
|
|
myStart(theRange.myStart),
|
|
myPortion(theRange.myDelta),
|
|
myMax(Max(1.e-6, theMax)), // protection against zero range
|
|
myValue(0.),
|
|
myIsActive(myProgress != NULL && !theRange.myWasUsed),
|
|
myIsOwnName(false),
|
|
myIsInfinite(isInfinite)
|
|
{
|
|
Standard_ASSERT_VOID(!theRange.myWasUsed,
|
|
"Message_ProgressRange is used to initialize more than one scope");
|
|
theRange.myWasUsed = true; // Disarm the range
|
|
}
|
|
|
|
//=======================================================================
|
|
// function : Message_ProgressScope
|
|
// purpose :
|
|
//=======================================================================
|
|
inline Message_ProgressScope::Message_ProgressScope(const Message_ProgressRange& theRange,
|
|
const NullString*,
|
|
Standard_Real theMax,
|
|
Standard_Boolean isInfinite)
|
|
: myProgress(theRange.myParentScope != NULL ? theRange.myParentScope->myProgress : NULL),
|
|
myParent(theRange.myParentScope),
|
|
myName(NULL),
|
|
myStart(theRange.myStart),
|
|
myPortion(theRange.myDelta),
|
|
myMax(Max(1.e-6, theMax)), // protection against zero range
|
|
myValue(0.),
|
|
myIsActive(myProgress != NULL && !theRange.myWasUsed),
|
|
myIsOwnName(false),
|
|
myIsInfinite(isInfinite)
|
|
{
|
|
Standard_ASSERT_VOID(!theRange.myWasUsed,
|
|
"Message_ProgressRange is used to initialize more than one scope");
|
|
theRange.myWasUsed = true; // Disarm the range
|
|
}
|
|
|
|
//=======================================================================
|
|
// function : Close
|
|
// purpose :
|
|
//=======================================================================
|
|
inline void Message_ProgressScope::Close()
|
|
{
|
|
if (!myIsActive)
|
|
{
|
|
return;
|
|
}
|
|
|
|
// Advance indicator to the end of the scope
|
|
Standard_Real aCurr = localToGlobal(myValue);
|
|
myValue = (myIsInfinite ? Precision::Infinite() : myMax);
|
|
Standard_Real aDelta = myPortion - aCurr;
|
|
if (aDelta > 0.)
|
|
{
|
|
myProgress->Increment(aDelta, *this);
|
|
}
|
|
Standard_ASSERT_VOID(myParent == 0 || myParent->myIsActive,
|
|
"Parent progress scope has been closed before child");
|
|
|
|
myIsActive = false;
|
|
}
|
|
|
|
//=======================================================================
|
|
// function : UserBreak
|
|
// purpose :
|
|
//=======================================================================
|
|
inline Standard_Boolean Message_ProgressScope::UserBreak() const
|
|
{
|
|
return myProgress && myProgress->UserBreak();
|
|
}
|
|
|
|
//=======================================================================
|
|
// function : Next
|
|
// purpose :
|
|
//=======================================================================
|
|
inline Message_ProgressRange Message_ProgressScope::Next(Standard_Real theStep)
|
|
{
|
|
if (myIsActive && theStep > 0.)
|
|
{
|
|
Standard_Real aCurr = localToGlobal(myValue);
|
|
Standard_Real aNext = localToGlobal(myValue += theStep);
|
|
Standard_Real aDelta = aNext - aCurr;
|
|
if (aDelta > 0.)
|
|
{
|
|
return Message_ProgressRange(*this, myStart + aCurr, aDelta);
|
|
}
|
|
}
|
|
return Message_ProgressRange();
|
|
}
|
|
|
|
//=======================================================================
|
|
// function : Show
|
|
// purpose :
|
|
//=======================================================================
|
|
|
|
inline void Message_ProgressScope::Show()
|
|
{
|
|
if (myIsActive)
|
|
{
|
|
myProgress->Show(*this, Standard_True);
|
|
}
|
|
}
|
|
|
|
//=======================================================================
|
|
// function : localToGlobal
|
|
// purpose :
|
|
//=======================================================================
|
|
inline Standard_Real Message_ProgressScope::localToGlobal(const Standard_Real theVal) const
|
|
{
|
|
if (theVal <= 0.)
|
|
return 0.;
|
|
|
|
if (!myIsInfinite)
|
|
{
|
|
if (myMax - theVal < RealSmall())
|
|
return myPortion;
|
|
return myPortion * theVal / myMax;
|
|
}
|
|
|
|
double x = theVal / myMax;
|
|
// return myPortion * ( 1. - std::exp ( -x ) ); // exponent
|
|
return myPortion * x / (1. + x); // hyperbola
|
|
}
|
|
|
|
//=======================================================================
|
|
// function : Value
|
|
// purpose :
|
|
//=======================================================================
|
|
|
|
inline Standard_Real Message_ProgressScope::Value() const
|
|
{
|
|
if (!myIsActive)
|
|
{
|
|
return myIsInfinite ? Precision::Infinite() : myMax;
|
|
}
|
|
|
|
// get current progress on the global scale counted
|
|
// from the start of this scope
|
|
Standard_Real aVal = myProgress->GetPosition() - myStart;
|
|
|
|
// if progress has not reached yet the start of this scope, return 0
|
|
if (aVal <= 0.)
|
|
return 0.;
|
|
|
|
// if at end of the scope (or behind), report the maximum
|
|
Standard_Real aDist = myPortion - aVal;
|
|
if (aDist <= Precision::Confusion())
|
|
return myIsInfinite ? Precision::Infinite() : myMax;
|
|
|
|
// map the value to the range of this scope [0, Max],
|
|
// rounding up to integer, with small correction applied
|
|
// to avoid rounding errors
|
|
return std::ceil(myMax * aVal / (myIsInfinite ? aDist : myPortion) - Precision::Confusion());
|
|
}
|
|
|
|
#endif // _Message_ProgressScope_HeaderFile
|