Timeline: work out a scheme of Invariants and Normalisation for the ZoomWindow
Getting all those requirements translated into code turns out to be a challenging task; and the usual ascent to handle such a situation is to define **Invariants** in conjunction with a normalisation scheme; each manipulation will then be translated into invocation of one of the three fundamental mutators, and these in turn always lead into the common normalisation sequence. __Invariants__ - oriented and non-empty windows - never alter given pxWidth - zoom metric factor < max zoom - visibleWindow ⊂ Canvas
This commit is contained in:
parent
f2ef893adb
commit
5ed5905d7f
3 changed files with 763 additions and 109 deletions
|
|
@ -82,9 +82,11 @@
|
|||
#include "lib/rational.hpp"
|
||||
#include "lib/time/timevalue.hpp"
|
||||
#include "lib/nocopy.hpp"
|
||||
#include "lib/util.hpp"
|
||||
//#include "lib/idi/entry-id.hpp"
|
||||
//#include "lib/symbol.hpp"
|
||||
|
||||
#include <limits>
|
||||
//#include <utility>
|
||||
//#include <string>
|
||||
|
||||
|
|
@ -105,11 +107,39 @@ namespace model {
|
|||
using util::Rat;
|
||||
using util::rational_cast;
|
||||
|
||||
namespace {
|
||||
/** the deepest zoom is to use 2px per micro-tick */
|
||||
const uint ZOOM_MAX_RESOLUTION = 2 * TimeValue::SCALE;
|
||||
using util::min;
|
||||
using util::max;
|
||||
|
||||
namespace { ///////////////////////////////////////////////////////////////////////////////////////////////TICKET #1259 : reorganise raw time base datatypes : need conversion path into FSecs
|
||||
/**
|
||||
* @todo preliminary helper to enter into fractional integer calculations
|
||||
* - FSecs (maybe better called `RSec`) should be a light-weight wrapper
|
||||
* on top of util::Rat = `boost::rational<int64_t>`
|
||||
* - a conversion function like in TimeVar should be in the base type
|
||||
* - however, cross conversion from raw int64_t should be prohibited
|
||||
* to avoid ill-guided automatic conversions from µ-tick to seconds
|
||||
*/
|
||||
inline FSecs
|
||||
_FSecs (TimeValue const& timeVal)
|
||||
{
|
||||
return FSecs{_raw(timeVal), TimeValue::SCALE};
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/** the deepest zoom is to use 2px per micro-tick */
|
||||
const uint ZOOM_MAX_RESOLUTION = 2 * TimeValue::SCALE;
|
||||
|
||||
namespace {// initial values (rather arbitrary)
|
||||
const FSecs DEFAULT_CANVAS{23};
|
||||
const Rat DEFAULT_METRIC{25};
|
||||
const uint MAX_PX_WIDTH{1000000};
|
||||
const FSecs MAX_TIMESPAN{_FSecs(Time::MAX-Time::MIN)};
|
||||
const FSecs MICRO_TICK{1_r/Time::SCALE};
|
||||
const Rat FRACT_ULP{1_r/std::numeric_limits<int64_t>::max()};
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* A component to ensure uniform handling of zoom scale
|
||||
* and visible interval on the timeline. Changes through
|
||||
|
|
@ -129,23 +159,21 @@ namespace model {
|
|||
{
|
||||
TimeVar startAll_, afterAll_,
|
||||
startWin_, afterWin_;
|
||||
uint px_per_sec_; ///////////////////TODO use rational
|
||||
Rat px_per_sec_;
|
||||
|
||||
public:
|
||||
ZoomWindow (TimeSpan timeline =TimeSpan{Time::ZERO, FSecs(23)})
|
||||
ZoomWindow (uint pxWidth, TimeSpan timeline =TimeSpan{Time::ZERO, DEFAULT_CANVAS})
|
||||
: startAll_{timeline.start()}
|
||||
, afterAll_{nonEmpty(timeline.end())}
|
||||
, afterAll_{ensureNonEmpty(startAll_, timeline.end())}
|
||||
, startWin_{startAll_}
|
||||
, afterWin_{afterAll_}
|
||||
, px_per_sec_{25}
|
||||
{ }
|
||||
, px_per_sec_{establishMetric (pxWidth, startWin_, afterWin_)}
|
||||
{
|
||||
ensureInvariants();
|
||||
}
|
||||
|
||||
ZoomWindow (uint pxWidth, TimeSpan timeline =TimeSpan{Time::ZERO, FSecs(23)})
|
||||
: startAll_{timeline.start()}
|
||||
, afterAll_{nonEmpty(timeline.end())}
|
||||
, startWin_{startAll_}
|
||||
, afterWin_{afterAll_}
|
||||
, px_per_sec_{25}
|
||||
ZoomWindow (TimeSpan timeline =TimeSpan{Time::ZERO, DEFAULT_CANVAS})
|
||||
: ZoomWindow{0, timeline} //see ensureConsistent()
|
||||
{ }
|
||||
|
||||
TimeSpan
|
||||
|
|
@ -169,11 +197,12 @@ namespace model {
|
|||
uint
|
||||
pxWidth() const
|
||||
{
|
||||
REQUIRE (0 < _raw(afterWin_ - startWin_));
|
||||
return rational_cast<uint> (px_per_sec() / FSecs(afterWin_-startWin_));
|
||||
REQUIRE (startWin_ < afterWin_);
|
||||
return rational_cast<uint> (px_per_sec() * FSecs(afterWin_-startWin_));
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* === Mutators === */
|
||||
|
||||
void
|
||||
|
|
@ -185,7 +214,7 @@ namespace model {
|
|||
void
|
||||
setMetric (Rat px_per_sec)
|
||||
{
|
||||
UNIMPLEMENTED ("setMetric");
|
||||
mutateScale (px_per_sec);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -201,12 +230,11 @@ namespace model {
|
|||
void
|
||||
nudgeMetric (int steps)
|
||||
{
|
||||
uint changedScale =
|
||||
steps > 0 ? px_per_sec_ << steps
|
||||
: px_per_sec_ >> -steps;
|
||||
if (0 < changedScale
|
||||
and changedScale <= ZOOM_MAX_RESOLUTION)
|
||||
mutateScale (changedScale);
|
||||
mutateScale(
|
||||
steps > 0 ? Rat{px_per_sec_.numerator() << steps
|
||||
,px_per_sec_.denominator()}
|
||||
: Rat{px_per_sec_.numerator()
|
||||
,px_per_sec_.denominator() << -steps});
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -283,104 +311,203 @@ namespace model {
|
|||
UNIMPLEMENTED ("navigate Zoom History");
|
||||
}
|
||||
|
||||
private:
|
||||
/* === adjust and coordinate === */
|
||||
|
||||
TimeValue
|
||||
nonEmpty (TimeValue endPoint)
|
||||
private:
|
||||
/* === establish and maintain invariants === */
|
||||
/*
|
||||
* - oriented and non-empty windows
|
||||
* - never alter given pxWidth
|
||||
* - zoom metric factor < max zoom
|
||||
* - visibleWindow ⊂ Canvas
|
||||
*/
|
||||
|
||||
static TimeValue
|
||||
ensureNonEmpty (TimeVar& startRef, TimeValue endPoint)
|
||||
{
|
||||
if (startAll_ < endPoint)
|
||||
if (startRef < endPoint)
|
||||
return endPoint;
|
||||
if (startAll_ < Time::MAX)
|
||||
return TimeValue{startAll_ + 1};
|
||||
startAll_ = Time::MAX - TimeValue(1);
|
||||
if (startRef <= Time::MAX - Time{DEFAULT_CANVAS})
|
||||
return startRef + Time{DEFAULT_CANVAS};
|
||||
startRef = Time::MAX - Time{DEFAULT_CANVAS};
|
||||
return Time::MAX;
|
||||
}
|
||||
|
||||
static Rat
|
||||
establishMetric (uint pxWidth, Time startWin, Time afterWin)
|
||||
{
|
||||
REQUIRE (startWin < afterWin);
|
||||
FSecs dur = _FSecs(afterWin-startWin);
|
||||
if (pxWidth == 0 or pxWidth > MAX_PX_WIDTH) // default to sane pixel width
|
||||
pxWidth = max<uint> (1, rational_cast<uint> (DEFAULT_METRIC * dur));
|
||||
Rat metric = Rat(pxWidth) / dur;
|
||||
// rational arithmetic ensures we can always reproduce the pxWidth
|
||||
ENSURE (pxWidth == rational_cast<uint> (metric*dur));
|
||||
ENSURE (0 < metric);
|
||||
return metric;
|
||||
}
|
||||
|
||||
Rat
|
||||
conformMetricToWindow (uint pxWidth)
|
||||
{
|
||||
REQUIRE (pxWidth > 0);
|
||||
REQUIRE (afterWin_> startWin_);
|
||||
FSecs dur{afterWin_-startWin_};
|
||||
Rat adjMetric = Rat(pxWidth) / dur;
|
||||
ENSURE (pxWidth == rational_cast<uint> (adjMetric*dur));
|
||||
return adjMetric;
|
||||
}
|
||||
|
||||
void
|
||||
conformWindowToMetric (Rat changedMetric)
|
||||
{
|
||||
REQUIRE (changedMetric > 0);
|
||||
REQUIRE (afterWin_> startWin_);
|
||||
FSecs dur{afterWin_-startWin_};
|
||||
uint pxWidth = rational_cast<uint> (px_per_sec_*dur);
|
||||
dur = Rat(pxWidth) / changedMetric;
|
||||
dur += MICRO_TICK - FRACT_ULP; // prefer bias towards increased window instead of increased metric
|
||||
dur = min (dur, MAX_TIMESPAN);
|
||||
dur = max (dur, MICRO_TICK); // prevent window going void
|
||||
if (startWin_<= Time::MAX - Time{dur})
|
||||
afterWin_ = startWin_ + Time{dur};
|
||||
else
|
||||
{
|
||||
startWin_ = Time::MAX - Time{dur};
|
||||
afterWin_ = Time::MAX;
|
||||
}
|
||||
// re-check metric to maintain precise pxWidth
|
||||
px_per_sec_ = conformMetricToWindow (pxWidth);
|
||||
ENSURE (_FSecs(afterWin_-startWin_) < MAX_TIMESPAN);
|
||||
ENSURE (px_per_sec_<= changedMetric); // bias towards increased window
|
||||
}
|
||||
|
||||
void
|
||||
conformWindowToCanvas()
|
||||
{
|
||||
FSecs dur{afterWin_-startWin_};
|
||||
REQUIRE (dur < MAX_TIMESPAN);
|
||||
REQUIRE (Time::MIN <= startWin_);
|
||||
REQUIRE (afterWin_ <= Time::MAX);
|
||||
if (dur <= _FSecs(afterAll_-startAll_))
|
||||
{//possibly shift into current canvas
|
||||
if (afterWin_ > afterAll_)
|
||||
{
|
||||
Offset shift{afterWin_ - afterAll_};
|
||||
startWin_ -= shift;
|
||||
afterWin_ -= shift;
|
||||
}
|
||||
else
|
||||
if (startWin_ < startAll_)
|
||||
{
|
||||
Offset shift{startAll_ - startWin_};
|
||||
startWin_ += shift;
|
||||
afterWin_ += shift;
|
||||
}
|
||||
}
|
||||
else
|
||||
{//need to cap window to fit into canvas
|
||||
startWin_ = startAll_;
|
||||
afterWin_ = afterAll_;
|
||||
}
|
||||
ENSURE (startAll_ <= startWin_);
|
||||
ENSURE (afterWin_ <= afterAll_);
|
||||
}
|
||||
|
||||
void
|
||||
conformToBounds (Rat changedMetric)
|
||||
{
|
||||
if (changedMetric > ZOOM_MAX_RESOLUTION)
|
||||
{
|
||||
changedMetric = ZOOM_MAX_RESOLUTION;
|
||||
conformWindowToMetric (changedMetric);
|
||||
}
|
||||
startAll_ = min (startAll_, startWin_);
|
||||
afterAll_ = max (afterAll_, afterWin_);
|
||||
ENSURE (Time::MIN <= startWin_);
|
||||
ENSURE (afterWin_ <= Time::MAX);
|
||||
ENSURE (startAll_ <= startWin_);
|
||||
ENSURE (afterWin_ <= afterAll_);
|
||||
ENSURE (px_per_sec_ <= ZOOM_MAX_RESOLUTION);
|
||||
ENSURE (px_per_sec_ <= changedMetric); // bias
|
||||
}
|
||||
|
||||
/**
|
||||
* Procedure to (re)establish the invariants.
|
||||
* Adjustments should be done first to windows,
|
||||
* then to the metric, using #conformWindowToMetric().
|
||||
* Then this function shall be called and will first
|
||||
* shift and possibly cap the window, then reestablish
|
||||
* the metric and possibly increase the canvas to keep
|
||||
* ensure the ZOOM_MAX_RESOLUTION is not exceeded.
|
||||
* These steps ensure overall pixel size remains stable.
|
||||
*/
|
||||
void
|
||||
ensureInvariants(uint px =0)
|
||||
{
|
||||
if (px==0) px = pxWidth();
|
||||
conformWindowToCanvas();
|
||||
px_per_sec_ = conformMetricToWindow (px);
|
||||
conformToBounds (px_per_sec_);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* === adjust and coordinate window parameters === */
|
||||
|
||||
/** @internal change Window TimeSpan, validate and adjust all params */
|
||||
void
|
||||
mutateWindow (TimeVar start, TimeVar after)
|
||||
{
|
||||
if (not (start < after))
|
||||
{
|
||||
if (after == Time::MAX)
|
||||
start = Time::MAX - TimeValue(1);
|
||||
else
|
||||
after = start + TimeValue(1);
|
||||
}
|
||||
|
||||
FSecs dur{after - start};
|
||||
if (dur > FSecs{afterAll_ - startAll_})
|
||||
{
|
||||
start = startAll_;
|
||||
after = afterAll_;
|
||||
}
|
||||
else
|
||||
if (start < startAll_)
|
||||
{
|
||||
start = startAll_;
|
||||
after = start + dur;
|
||||
}
|
||||
else
|
||||
if (after > afterAll_)
|
||||
{
|
||||
after = afterAll_;
|
||||
start = after - dur;
|
||||
}
|
||||
ASSERT (after-start <= afterAll_-startAll_);
|
||||
|
||||
px_per_sec_ = adjustedScale (start,after, startWin_,afterWin_);
|
||||
uint px{pxWidth()};
|
||||
startWin_ = start;
|
||||
afterWin_ = after;
|
||||
afterWin_ = ensureNonEmpty (startWin_, after);
|
||||
px_per_sec_ = conformMetricToWindow (px);
|
||||
ensureInvariants (px);
|
||||
fireChangeNotification();
|
||||
}
|
||||
|
||||
/**
|
||||
/**
|
||||
* @internal adjust Window to match given scale,
|
||||
* validate and adjust all params */
|
||||
void
|
||||
mutateScale (uint px_per_sec)
|
||||
mutateScale (Rat changedMetric)
|
||||
{
|
||||
if (px_per_sec == 0) px_per_sec = 1;
|
||||
if (px_per_sec == px_per_sec_) return;
|
||||
changedMetric = min (changedMetric, ZOOM_MAX_RESOLUTION);
|
||||
if (changedMetric == px_per_sec_) return;
|
||||
|
||||
FSecs changeFactor{px_per_sec, px_per_sec_};
|
||||
Rat changeFactor{changedMetric / px_per_sec_};
|
||||
FSecs dur{afterWin_ - startWin_};
|
||||
dur /= changeFactor;
|
||||
if (dur > FSecs{afterAll_ - startAll_})
|
||||
{// limit to the overall timespan...
|
||||
px_per_sec_ = adjustedScale (startAll_,afterAll_, startWin_,afterWin_);
|
||||
uint px{pxWidth()};
|
||||
startWin_ = startAll_;
|
||||
afterWin_ = afterAll_;
|
||||
px_per_sec_ = conformMetricToWindow(px);
|
||||
ensureInvariants (px);
|
||||
fireChangeNotification();
|
||||
}
|
||||
else
|
||||
{
|
||||
TimeVar start{anchorPoint() - dur*relativeAnchor()};
|
||||
if (start < startAll_)
|
||||
start = startAll_;
|
||||
TimeVar after{start + dur};
|
||||
if (after > afterAll_)
|
||||
{
|
||||
after = afterAll_;
|
||||
start = afterAll_ - dur;
|
||||
}
|
||||
ASSERT (after-start <= afterAll_-startAll_);
|
||||
|
||||
if (start == startWin_ and after == afterWin_)
|
||||
return; // nothing changed effectively
|
||||
|
||||
px_per_sec_ = adjustedScale (start,after, startWin_,afterWin_);
|
||||
startWin_ = start;
|
||||
afterWin_ = after;
|
||||
}
|
||||
fireChangeNotification();
|
||||
mutateDuration (dur);
|
||||
}
|
||||
|
||||
/** @internal change visible duration centred around anchor point,
|
||||
* validate and adjust all params */
|
||||
void
|
||||
mutateDuration (Duration duration)
|
||||
mutateDuration (FSecs duration)
|
||||
{
|
||||
UNIMPLEMENTED ("change visible duration, validate and adjust all params");
|
||||
if (duration <= 0)
|
||||
duration = DEFAULT_CANVAS;
|
||||
uint px{pxWidth()};
|
||||
TimeVar start{anchorPoint() - duration*relativeAnchor()};
|
||||
TimeVar after{start + duration};
|
||||
if (start == startWin_ and after == afterWin_)
|
||||
return; // nothing changed effectively
|
||||
|
||||
Rat changedMetric = adjustedScale (start,after, startWin_,afterWin_);
|
||||
conformWindowToMetric (changedMetric);
|
||||
ensureInvariants(px);
|
||||
fireChangeNotification();
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -392,12 +519,12 @@ namespace model {
|
|||
* @param afterOld previous end point
|
||||
* @return adapted scale factor in pixel per second, rounded half up to the next pixel.
|
||||
*/
|
||||
uint
|
||||
Rat
|
||||
adjustedScale (TimeVar startNew, TimeVar afterNew, TimeVar startOld, TimeVar afterOld)
|
||||
{
|
||||
REQUIRE (startOld < afterOld);
|
||||
FSecs factor = FSecs{afterNew - startNew} / FSecs{afterOld - startOld};
|
||||
return boost::rational_cast<uint>(px_per_sec_ / factor + 1/2); // rounding half pixels
|
||||
REQUIRE (startNew < afterNew and startOld < afterOld);
|
||||
Rat change{_raw(afterNew - startNew), _raw(afterOld - startOld)};
|
||||
return px_per_sec_ / change;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -413,7 +540,7 @@ namespace model {
|
|||
FSecs
|
||||
anchorPoint() const
|
||||
{
|
||||
return startWin_ + FSecs{afterWin_-startWin_} * relativeAnchor();
|
||||
return startWin_ + FSecs{afterWin_-startWin_} * relativeAnchor();
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -423,13 +550,13 @@ namespace model {
|
|||
* to the current visible window's position within the overall timeline; if it's
|
||||
* close to the beginning, the anchor point is also rather to the beginning...
|
||||
*/
|
||||
FSecs
|
||||
Rat
|
||||
relativeAnchor() const
|
||||
{
|
||||
// the visible window itself has to fit in, which reduces the action range
|
||||
FSecs possibleRange = (afterAll_-startAll_) - (afterWin_-startWin_);
|
||||
if (possibleRange == 0) // if there is no room for scrolling...
|
||||
return FSecs{1,2}; // then anchor zooming in the middle
|
||||
if (possibleRange <= 0) // if there is no room for scrolling...
|
||||
return 1_r/2; // then anchor zooming in the middle
|
||||
|
||||
// use a 3rd degree parabola to favour positions in the middle
|
||||
FSecs posFactor = FSecs{startWin_-startAll_} / possibleRange;
|
||||
|
|
|
|||
|
|
@ -66,9 +66,9 @@ namespace test {
|
|||
CHECK (_t(10,3) == Time{FSecs(10,3)}); // Time point at t = 10/3sec (fractional number)
|
||||
CHECK (FSecs(10,3) == FSecs(10)/3); // fractional number arithmetics
|
||||
CHECK (FSecs(10)/3 == 10_r/3); // _r is a user defined literal to denote 64-bit fractional
|
||||
CHECK (10_r/3 == Rat(10,3));
|
||||
CHECK (Rat(10/3) == boost::rational<int64_t>(10,3)); // using Rat = boost::rational<int64_t>
|
||||
CHECK (rational_cast<float> (10_r/3) == 3.33333f); // rational_cast performs the division with indicated type
|
||||
CHECK (Rat(10,3) == 10_r/3);
|
||||
CHECK (Rat(10,3) == boost::rational<int64_t>(10,3)); // using Rat = boost::rational<int64_t>
|
||||
CHECK (rational_cast<float> (10_r/3) == 3.33333f); // rational_cast calculates division after type conversion
|
||||
|
||||
verify_simpleUsage();
|
||||
verify_setup();
|
||||
|
|
@ -101,10 +101,11 @@ namespace test {
|
|||
|
||||
|
||||
/** @test verify the possible variations for initial setup of the zoom window
|
||||
* - can be defined either the canvas duration, or an explicit extension
|
||||
* given in pixels, or both
|
||||
* - window extension, when given, defines the visible span
|
||||
* - otherwise the whole canvas is visible, thereby defining the metric
|
||||
* - can be defined either the canvas duration,
|
||||
* or an explicit extension given in pixels, or both
|
||||
* - after construction, visible window always covers whole canvas
|
||||
* - window extension, when given, defines the initial metric
|
||||
* - otherwise pixel extension is derived from default metric
|
||||
*/
|
||||
void
|
||||
verify_setup()
|
||||
|
|
@ -112,26 +113,26 @@ namespace test {
|
|||
ZoomWindow win1;
|
||||
CHECK (win1.overallSpan() == TimeSpan(_t(0), FSecs(23)));
|
||||
CHECK (win1.visible() == win1.overallSpan());
|
||||
CHECK (win1.pxWidth() == 25*23);
|
||||
CHECK (win1.px_per_sec() == 25);
|
||||
CHECK (win1.pxWidth() == 23*25);
|
||||
|
||||
ZoomWindow win2{TimeSpan{_t(-1), _t(+1)}};
|
||||
CHECK (win2.overallSpan() == TimeSpan(_t(-1), FSecs(2)));
|
||||
CHECK (win2.visible() == win2.overallSpan());
|
||||
CHECK (win2.pxWidth() == 25*2);
|
||||
CHECK (win2.px_per_sec() == 25);
|
||||
CHECK (win2.pxWidth() == 2*25);
|
||||
|
||||
ZoomWindow win3{555};
|
||||
CHECK (win3.overallSpan() == TimeSpan(_t(0), FSecs(23)));
|
||||
CHECK (win3.visible() == win3.overallSpan());
|
||||
CHECK (win3.pxWidth() == 555);
|
||||
CHECK (win3.px_per_sec() == 555_r/23);
|
||||
CHECK (win3.visible() == win3.overallSpan());
|
||||
|
||||
ZoomWindow win4{555, TimeSpan{_t(-10), _t(-5)}};
|
||||
CHECK (win4.overallSpan() == TimeSpan(_t(10), FSecs(5)));
|
||||
CHECK (win4.visible() == win4.overallSpan());
|
||||
CHECK (win4.pxWidth() == 555);
|
||||
CHECK (win4.px_per_sec() == 111);
|
||||
CHECK (win4.visible() == win4.overallSpan());
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -38638,9 +38638,24 @@
|
|||
<icon BUILTIN="idea"/>
|
||||
</node>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1667592413859" ID="ID_745987096" MODIFIED="1667592507648" TEXT="brauche dazu einen offiziellen Zugang zu einer fraktionalen Repräsentation">
|
||||
<icon BUILTIN="yes"/>
|
||||
<node CREATED="1667592510702" ID="ID_669892678" MODIFIED="1667592532079" TEXT="Duration ⟶ FSec"/>
|
||||
<node CREATED="1667592539018" ID="ID_1283310585" MODIFIED="1667592544568" TEXT="Offset ⟶ FSec"/>
|
||||
<node CREATED="1667592532973" ID="ID_31952265" MODIFIED="1667592538214" TEXT="Time ⟶ FSec"/>
|
||||
</node>
|
||||
<node COLOR="#338800" CREATED="1667593654463" ID="ID_1694088540" MODIFIED="1667593677324" TEXT="vorläufige Zwischenlösung: _FSecs() direkt in ZoomWindow-Header">
|
||||
<icon BUILTIN="button_ok"/>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#ccb59b" COLOR="#6e2a38" CREATED="1667488158059" ID="ID_898168096" MODIFIED="1667491200716" TEXT="neue Zielvorgabe: Pixel-Angaben sind stets präzise">
|
||||
<font ITALIC="true" NAME="SansSerif" SIZE="14"/>
|
||||
<icon BUILTIN="yes"/>
|
||||
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1667593710047" ID="ID_920638973" MODIFIED="1667593745244" TEXT="kein Runden mehr, sondern nur noch truncate">
|
||||
<icon BUILTIN="flag-yellow"/>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1667593719313" ID="ID_317494909" MODIFIED="1667593745245" TEXT="dafür die Toleranz senken auf der Metrik">
|
||||
<icon BUILTIN="flag-yellow"/>
|
||||
</node>
|
||||
</node>
|
||||
</node>
|
||||
</node>
|
||||
|
|
@ -38660,6 +38675,378 @@
|
|||
</html></richcontent>
|
||||
</node>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#fdfdcf" COLOR="#ff0000" CREATED="1667603662334" ID="ID_162164091" MODIFIED="1667603891148" TEXT="drehe mich mit den geforderten Randbedingungen im Kreis">
|
||||
<arrowlink COLOR="#ec1941" DESTINATION="ID_1507636517" ENDARROW="Default" ENDINCLINATION="27;-47;" ID="Arrow_ID_49426086" STARTARROW="None" STARTINCLINATION="-122;6;"/>
|
||||
<icon BUILTIN="stop-sign"/>
|
||||
<node BACKGROUND_COLOR="#e0ceaa" COLOR="#690f14" CREATED="1667603756089" ID="ID_1802881683" MODIFIED="1667603844726" TEXT="möchte einen maximal-Zoom-Faktor vorgeben">
|
||||
<icon BUILTIN="yes"/>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#e0ceaa" COLOR="#690f14" CREATED="1667603784445" ID="ID_1006588421" MODIFIED="1667603844726" TEXT="Fenster soll immer im Canvas bleiben">
|
||||
<icon BUILTIN="yes"/>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#e0ceaa" COLOR="#690f14" CREATED="1667603813378" ID="ID_1979403390" MODIFIED="1667603844727" TEXT="Pixel-Vorgaben stets einzuhalten">
|
||||
<icon BUILTIN="yes"/>
|
||||
</node>
|
||||
</node>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1667603646312" ID="ID_1507636517" MODIFIED="1667603891148" TEXT="muß Invarianten sicherstellen">
|
||||
<linktarget COLOR="#ec1941" DESTINATION="ID_1507636517" ENDARROW="Default" ENDINCLINATION="27;-47;" ID="Arrow_ID_49426086" SOURCE="ID_162164091" STARTARROW="None" STARTINCLINATION="-122;6;"/>
|
||||
<icon BUILTIN="flag-yellow"/>
|
||||
<node BACKGROUND_COLOR="#fdfdcf" COLOR="#ff0000" CREATED="1667603900358" ID="ID_353785530" MODIFIED="1667603950298" TEXT="das gewählte Implementierungs-Schema ist nicht beherrschbar">
|
||||
<icon BUILTIN="broken-line"/>
|
||||
<node CREATED="1667603974758" ID="ID_1895105732" MODIFIED="1667603997149" TEXT="Konstuktor legt sichere Startwerte fest"/>
|
||||
<node CREATED="1667603997785" ID="ID_1559828104" MODIFIED="1667604014827" TEXT="von dort weiter, mit Einzelfall-bezogenen Regeln"/>
|
||||
</node>
|
||||
<node CREATED="1667604115641" ID="ID_340228791" MODIFIED="1667604155428">
|
||||
<richcontent TYPE="NODE"><html>
|
||||
<head>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<p>
|
||||
mein Anspruch ist, hier eine <b>absolut fehlerfrei</b> arbeitende Komponente zu schreiben
|
||||
</p>
|
||||
</body>
|
||||
</html></richcontent>
|
||||
<icon BUILTIN="messagebox_warning"/>
|
||||
</node>
|
||||
<node CREATED="1667604025125" ID="ID_573471794" MODIFIED="1667604225117" TEXT="die Korrektur-Regeln zum Einhalten der Constraints sind komplex (im Allgemeinen)">
|
||||
<richcontent TYPE="NOTE"><html>
|
||||
<head>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<p>
|
||||
...und zwar, wenn man <i>wirklich alle</i> Eingangswerte zuläßt, und sich eben nicht nur auf <i>vernünftige </i>Eingaben <i>verläßt.</i>
|
||||
</p>
|
||||
</body>
|
||||
</html></richcontent>
|
||||
</node>
|
||||
<node CREATED="1667604082603" ID="ID_1966401065" MODIFIED="1667604109981" TEXT="ich muß letztlich Vergößerung des Canvas zulassen (oder beliebig starken Zoom)">
|
||||
<node CREATED="1667604258315" ID="ID_539837281" MODIFIED="1667604273064" TEXT="Canvas-Vergrößerung erscheint mir pragmatischer"/>
|
||||
<node CREATED="1667604319406" ID="ID_169844915" MODIFIED="1667604346784" TEXT="ich möchte den Zoom-Faktor auf eine technisch realisierbare Spanne beschränken"/>
|
||||
<node CREATED="1667604407474" ID="ID_1964908869" MODIFIED="1667609918926" TEXT="diese Spanne kann in der logarithmischen Skala vergleichsweise rasch durchschritten werden.">
|
||||
<richcontent TYPE="NOTE"><html>
|
||||
<head>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<p>
|
||||
so ±15 2er-Potenz-Schritte genügen, um von der maximalen Auflösung in den Minuten-Bereich zu kommen
|
||||
</p>
|
||||
</body>
|
||||
</html></richcontent>
|
||||
</node>
|
||||
<node CREATED="1667610042409" ID="ID_1645790878" MODIFIED="1667610212422" TEXT="es kann nicht die Aufgabe des ZoomWindow sein, sinnvolle Speicher-Limits einzuhalten">
|
||||
<richcontent TYPE="NOTE"><html>
|
||||
<head>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<p>
|
||||
insofern muß es dann aber auch mit maximal großen Integer-Zahlen noch sauber funktionieren
|
||||
</p>
|
||||
</body>
|
||||
</html></richcontent>
|
||||
</node>
|
||||
<node CREATED="1667610216018" ID="ID_399148751" MODIFIED="1667610253025" TEXT="insofern ist das hier auch eine sportliche Herausforderung">
|
||||
<richcontent TYPE="NOTE"><html>
|
||||
<head>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<p>
|
||||
...einmal wirklich sicheren Code schreiben...
|
||||
</p>
|
||||
</body>
|
||||
</html></richcontent>
|
||||
<icon BUILTIN="ksmiletris"/>
|
||||
</node>
|
||||
</node>
|
||||
<node CREATED="1667610259517" ID="ID_738196107" MODIFIED="1667610281605" TEXT="andere Code-Struktur als Lösung?">
|
||||
<node CREATED="1667610283233" ID="ID_1965026515" MODIFIED="1667610294374" TEXT="Konstruktur initialisiert nur"/>
|
||||
<node CREATED="1667610295059" ID="ID_15303386" MODIFIED="1667610302622" TEXT="es gibt eine Invarianten-Funktion"/>
|
||||
<node CREATED="1667610303406" ID="ID_268951847" MODIFIED="1667610331180" TEXT="diese führt eine feste Folge von Prüf- und Korrekturschritten aus"/>
|
||||
<node CREATED="1667610416991" ID="ID_1022295277" MODIFIED="1667610430339" TEXT="und die gleiche Funktion wird nach jeder Änderung gleichermaßen angewendet"/>
|
||||
</node>
|
||||
<node CREATED="1667610443917" ID="ID_156996069" MODIFIED="1667610464053" TEXT="Invariante(n)">
|
||||
<node CREATED="1667610465437" ID="ID_1890704401" MODIFIED="1667660026181" TEXT="pxWidth konstant erhalten">
|
||||
<icon BUILTIN="full-1"/>
|
||||
</node>
|
||||
<node CREATED="1667610496460" ID="ID_1598935964" MODIFIED="1667660029149" TEXT="Metrik < Maximal-Faktor">
|
||||
<icon BUILTIN="full-2"/>
|
||||
</node>
|
||||
<node CREATED="1667610522737" ID="ID_870501024" MODIFIED="1667660034107" TEXT="visibleWindow ⊂ Canvas">
|
||||
<icon BUILTIN="full-3"/>
|
||||
</node>
|
||||
</node>
|
||||
<node CREATED="1667610617421" ID="ID_1255567216" MODIFIED="1667659859838" TEXT="Ausgleichs-Regeln">
|
||||
<icon BUILTIN="idea"/>
|
||||
<node COLOR="#338800" CREATED="1667610965654" ID="ID_1822123568" MODIFIED="1667667095016" TEXT="Canvas und Fenster orientieren">
|
||||
<icon BUILTIN="button_ok"/>
|
||||
<node CREATED="1667667099807" ID="ID_313293093" MODIFIED="1667667110754" TEXT="kann relativ brachial erfolgen">
|
||||
<icon BUILTIN="yes"/>
|
||||
</node>
|
||||
<node CREATED="1667667111845" ID="ID_240814651" MODIFIED="1667667131096" TEXT="Input kann nur leer sein, nicht negativ"/>
|
||||
<node CREATED="1667667143969" ID="ID_971076298" MODIFIED="1667667564598" TEXT="falls leer, weite aus auf DEFAULT_CANVAS (≙ 23sec)">
|
||||
<richcontent TYPE="NOTE"><html>
|
||||
<head>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<p>
|
||||
...zunächst habe ich hier immer nur das Minimale getan, nämlich 1 µTick aufgeweitet; dies würde zwar funktionieren, aber in der Regel nicht zu einem praktikablen Verhalten führen — wohingegen der <i>DEFAULT_CANVAS</i>  so gewählt ist, daß er klein und handlich ist
|
||||
</p>
|
||||
</body>
|
||||
</html></richcontent>
|
||||
</node>
|
||||
<node CREATED="1667667185251" ID="ID_396603353" MODIFIED="1667667316295" TEXT="extrem große Canvas oder Fenster sind nicht gefährlich">
|
||||
<richcontent TYPE="NOTE"><html>
|
||||
<head>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<p>
|
||||
sofern wir den Speicher haben...
|
||||
</p>
|
||||
<p>
|
||||
Will sagen, sie sind nicht gefährlich für den Invarianten-Mechanismus, denn für diesen wird es ehr bei sehr kleinen Zeitspannen kniffelig; wohingegen beliebig starkes zoom-out stets repräsentierbar ist als fraktionaler Integer
|
||||
</p>
|
||||
</body>
|
||||
</html></richcontent>
|
||||
</node>
|
||||
</node>
|
||||
<node COLOR="#338800" CREATED="1667611339595" ID="ID_1035209313" MODIFIED="1667668297039" TEXT="pxWidth errechnen / festsetzen">
|
||||
<icon BUILTIN="button_ok"/>
|
||||
<node CREATED="1667667900172" ID="ID_638983817" MODIFIED="1667667999509" TEXT="hier nun doch eine Maximal-Pixelzahl eingeführt">
|
||||
<richcontent TYPE="NOTE"><html>
|
||||
<head>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<p>
|
||||
...auch das basiert auf einer pragmatischen Überlegung; theoretisch könnten wir beliebig große Pixelanzahl unterstützen, dies würde aber auf allen Ebenen zu unerwartetem Verhalten führen, dessen Konsequenzen ich nicht überblicke ⟹ dann besser eine willkürliche und hinreichend große Grenze
|
||||
</p>
|
||||
</body>
|
||||
</html></richcontent>
|
||||
</node>
|
||||
<node CREATED="1667668184215" ID="ID_364715169" MODIFIED="1667668292358" TEXT="und fall-back auf das visibleWin in default-Metrik">
|
||||
<richcontent TYPE="NOTE"><html>
|
||||
<head>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<p>
|
||||
dies ist ein reiner Platzhalter für Tests, denn in der Praxis erwarte ich stets daß sofort zu Beginn eine Breite in Pixeln gesetzt wird — kann ja gar nicht anders sein...
|
||||
</p>
|
||||
</body>
|
||||
</html></richcontent>
|
||||
<icon BUILTIN="idea"/>
|
||||
</node>
|
||||
</node>
|
||||
<node CREATED="1667610653277" ID="ID_1224205751" MODIFIED="1667611359311" TEXT="neue Metrik ⟶ visibleWin">
|
||||
<node CREATED="1667659377837" ID="ID_634768326" MODIFIED="1667659613008" TEXT="»conformWindowToMetric«"/>
|
||||
</node>
|
||||
<node CREATED="1667610682228" ID="ID_154285310" MODIFIED="1667610688031" TEXT="Fenster in Canvas schieben">
|
||||
<node CREATED="1667659486321" ID="ID_897577157" MODIFIED="1667659616368" TEXT="»conformWindowToCanvas«"/>
|
||||
</node>
|
||||
<node CREATED="1667610688715" ID="ID_11883276" MODIFIED="1667610699053" TEXT="Fenster auf Canvas beschneiden"/>
|
||||
<node CREATED="1667610653277" ID="ID_831514693" MODIFIED="1667611449269" TEXT="neue Metrik ⟵ visibleWin">
|
||||
<node CREATED="1667659622859" ID="ID_828891167" MODIFIED="1667659633949" TEXT="»conformMetricToWindow«"/>
|
||||
</node>
|
||||
<node CREATED="1667611135215" ID="ID_1783825207" MODIFIED="1667611444146" TEXT="neue Metrik beschneiden">
|
||||
<node CREATED="1667659689795" ID="ID_1515577475" MODIFIED="1667659703886" TEXT="»conformBounds«"/>
|
||||
<node CREATED="1667672310513" ID="ID_1440027403" MODIFIED="1667672328162" TEXT="Metric < MAX_ZOOM"/>
|
||||
<node CREATED="1667610653277" ID="ID_761246682" MODIFIED="1667682138815" TEXT="Metrik ⟶ visibleWin">
|
||||
<linktarget COLOR="#9e7367" DESTINATION="ID_761246682" ENDARROW="Default" ENDINCLINATION="145;-11;" ID="Arrow_ID_702546557" SOURCE="ID_1067254564" STARTARROW="None" STARTINCLINATION="-54;-36;"/>
|
||||
</node>
|
||||
<node CREATED="1667611247456" ID="ID_1658100193" MODIFIED="1667611265274" TEXT="visibleWin ⟶ Canvas"/>
|
||||
<node BACKGROUND_COLOR="#f0d5c5" COLOR="#990033" CREATED="1667673574471" ID="ID_1973274504" MODIFIED="1667673591693" TEXT="neue Metrik < MAX_ZOOM">
|
||||
<icon BUILTIN="help"/>
|
||||
<node CREATED="1667673606578" ID="ID_1067254564" MODIFIED="1667682151865" TEXT="potentiell gefährlich: Metrik ⟶ visibleWin">
|
||||
<richcontent TYPE="NOTE"><html>
|
||||
<head>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<p>
|
||||
denn dabei wird gerundet, um die exakte Pixel-Zahl zu erhalten
|
||||
</p>
|
||||
</body>
|
||||
</html></richcontent>
|
||||
<arrowlink COLOR="#9e7367" DESTINATION="ID_761246682" ENDARROW="Default" ENDINCLINATION="145;-11;" ID="Arrow_ID_702546557" STARTARROW="None" STARTINCLINATION="-54;-36;"/>
|
||||
</node>
|
||||
<node CREATED="1667682713949" ID="ID_425310807" MODIFIED="1667682719231" TEXT="Grenzfall-Analyse">
|
||||
<node CREATED="1667682721338" ID="ID_842333816" MODIFIED="1667682794317" TEXT="Fenster kann verkürzt werden durch Rundung">
|
||||
<richcontent TYPE="NOTE"><html>
|
||||
<head>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<p>
|
||||
<font face="Monospaced">afterWin_ = startWin_ + Time{dur};</font>
|
||||
</p>
|
||||
<p>
|
||||
wobei dur einen fraktionalen Anteil < 1 µTick enthalten könnte
|
||||
</p>
|
||||
</body>
|
||||
</html></richcontent>
|
||||
</node>
|
||||
<node COLOR="#338800" CREATED="1667683782783" ID="ID_1842670966" MODIFIED="1667683907910" TEXT="MAX_TIMESPAN: Begrenzung hier nicht relevant">
|
||||
<richcontent TYPE="NOTE"><html>
|
||||
<head>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<p>
|
||||
Der Grenzfall ist ja changedMetric = MAX_ZOOM
|
||||
</p>
|
||||
<p>
|
||||
Wenn ich das durch eine irgendwie geartete pxWidth teile, wird es niemals größer, und zudem ist MAX_ZOOM < MAX_TIMESPAN
|
||||
</p>
|
||||
</body>
|
||||
</html></richcontent>
|
||||
<icon BUILTIN="idea"/>
|
||||
</node>
|
||||
<node CREATED="1667683116532" ID="ID_895916326" MODIFIED="1667683126786" TEXT="ruft auf: conformMetricToWindow">
|
||||
<node COLOR="#435e98" CREATED="1667683149810" ID="ID_872183002" MODIFIED="1667683633595" TEXT="Bug: errechnet pxWidth neu mit schon geänderter Länge">
|
||||
<richcontent TYPE="NOTE"><html>
|
||||
<head>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<p>
|
||||
das bedeutet: genau durch diese Abrundung auf den nächst kleineren µTick könnten wir u.U einen Pixel verlieren
|
||||
</p>
|
||||
<p>
|
||||
⟹ Abhilfe: originale pxWidth als Paremeter mitgeben
|
||||
</p>
|
||||
</body>
|
||||
</html></richcontent>
|
||||
<icon BUILTIN="broken-line"/>
|
||||
</node>
|
||||
<node CREATED="1667683634701" ID="ID_1449451873" MODIFIED="1667685735423" TEXT="Metrik kann minimal größer geworden sein (durch Rundung)">
|
||||
<richcontent TYPE="NOTE"><html>
|
||||
<head>
|
||||
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<p>
|
||||
<u>Konkretes Rechenbeispiel:</u>
|
||||
</p>
|
||||
<p>
|
||||
pxWidth = 99999&#160;&#160;(ein Pixel weniger als maximal m&#246;glich)
|
||||
</p>
|
||||
<p>
|
||||
changedMetric = MAX_ZOOM = 2000000
|
||||
</p>
|
||||
<p>
|
||||
&#10233; conformWindowToMetric() errechnet
|
||||
</p>
|
||||
<p>
|
||||
dur = 49999+1/2 &#181;Tick
|
||||
</p>
|
||||
<p style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; text-indent: 0px">
|
||||
&#55358;&#56370; das wird abgerundet auf 49999 &#181;Tick
|
||||
</p>
|
||||
<p>
|
||||
&#10233; conformMetricToWindow() errechnet
|
||||
</p>
|
||||
<p>
|
||||
adjMetric = 99999 / (49999/1000000) = 2000020,0004000080001600032
|
||||
</p>
|
||||
<p style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; text-indent: 0px">
|
||||
&#10233; das ist <b>definitiv gr&#246;&#223;er</b>&#160;als MAX_ZOOM
|
||||
</p>
|
||||
<p>
|
||||
|
||||
</p>
|
||||
<p>
|
||||
|
||||
</p>
|
||||
<p>
|
||||
|
||||
</p>
|
||||
</body>
|
||||
</html>
|
||||
</richcontent>
|
||||
<icon BUILTIN="messagebox_warning"/>
|
||||
</node>
|
||||
</node>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#e0ceaa" COLOR="#690f14" CREATED="1667688476525" ID="ID_226096711" MODIFIED="1667688576067" TEXT="⟹ Konsequenz: Bias in Richtung vergrößerter Zoom / verkleinertes Fenster">
|
||||
<icon BUILTIN="messagebox_warning"/>
|
||||
<node CREATED="1667688579306" ID="ID_486622183" MODIFIED="1667688586268" TEXT="allerdings ein sehr kleiner Effekt"/>
|
||||
<node CREATED="1667688595090" ID="ID_1458378798" MODIFIED="1667688601683" TEXT="äquivalent +1 µTick"/>
|
||||
<node CREATED="1667688946763" ID="ID_376119418" MODIFIED="1667689144112" TEXT="trotzdem unerwünscht ⟹ man kommt nicht zum Anfrang zurück">
|
||||
<richcontent TYPE="NOTE"><html>
|
||||
<head>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<p>
|
||||
einmal stark reinzoomen, und dann wieder zurück ⟹ Bereich ist beschnitten und kleiner geworden; das ist lästig, weil die nächst größere Stufe deutlich größer ist; meiner Einschätzung nach wäre es weniger lästig, wenn man ein kleines bischen zu viel sieht, zumal sich das auf der nächsten Zweierpotenz einpendeln dürfte
|
||||
</p>
|
||||
</body>
|
||||
</html></richcontent>
|
||||
</node>
|
||||
</node>
|
||||
<node CREATED="1667687800139" ID="ID_1785911993" MODIFIED="1667687809137" TEXT="Abhilfe">
|
||||
<node CREATED="1667687810116" ID="ID_1519072103" MODIFIED="1667689196961" TEXT="Lösung-1">
|
||||
<icon BUILTIN="smily_bad"/>
|
||||
<node CREATED="1667688228377" ID="ID_1083352192" MODIFIED="1667688446311" TEXT="den Fall MAX_ZOOM + Rundungsfehler explizit abtesten"/>
|
||||
<node CREATED="1667688234896" ID="ID_1025502092" MODIFIED="1667688423306" TEXT="und dann das visibleWin um 1 µTick vergrößern">
|
||||
<richcontent TYPE="NOTE"><html>
|
||||
<head>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<p>
|
||||
...vergrößern, weil damit die Metrik kleiner wird und unter der Schwelle MAX_ZOOM gehalten wird
|
||||
</p>
|
||||
</body>
|
||||
</html></richcontent>
|
||||
</node>
|
||||
</node>
|
||||
<node CREATED="1667688257381" ID="ID_1551466069" MODIFIED="1667689187817" TEXT="Lösung-2">
|
||||
<icon BUILTIN="button_cancel"/>
|
||||
<node CREATED="1667688279379" ID="ID_873793356" MODIFIED="1667688288165" TEXT="stets pauschal 1µTick aufschlagen"/>
|
||||
<node CREATED="1667688305031" ID="ID_950638301" MODIFIED="1667688330439" TEXT="keine gute Idee: behandelt exakte Verhältnisse falsch"/>
|
||||
</node>
|
||||
<node CREATED="1667688337402" ID="ID_124934014" MODIFIED="1667689201165" TEXT="Lösung-3">
|
||||
<icon BUILTIN="forward"/>
|
||||
<node CREATED="1667688343137" ID="ID_1666323585" MODIFIED="1667688353420" TEXT="explizit auf Rundungsfehler testen"/>
|
||||
<node CREATED="1667688354104" ID="ID_1203966035" MODIFIED="1667688377833" TEXT="und in diesem Fall visibleWin um 1 µTick vergrößern"/>
|
||||
<node CREATED="1667689836161" ID="ID_1356615492" MODIFIED="1667690176127" TEXT="besser: Aufrundungs-Konstante addieren">
|
||||
<richcontent TYPE="NOTE"><html>
|
||||
<head>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<p>
|
||||
...nach grober Abschätzung sind das weniger Operationen, als die Konvertierung auszuführen und zurück zu konvertieren und dann zu testen; zwar könnte der Optimiser den Test per common subexpression noch vereinfachen — aber letztlich empfinde ich das Addieren einer ULP-Konstante als deklarativer
|
||||
</p>
|
||||
</body>
|
||||
</html></richcontent>
|
||||
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1667690184889" ID="ID_1410341897" MODIFIED="1667690193752" TEXT="Vorsicht: experimentell prüfen">
|
||||
<icon BUILTIN="flag-yellow"/>
|
||||
</node>
|
||||
</node>
|
||||
</node>
|
||||
</node>
|
||||
</node>
|
||||
</node>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#eef0c5" COLOR="#990000" CREATED="1667659852956" ID="ID_1802836695" MODIFIED="1667659962798" TEXT="Implementierung">
|
||||
<icon BUILTIN="pencil"/>
|
||||
<node CREATED="1667659867147" ID="ID_1797487380" MODIFIED="1667659882100" TEXT="jeweils den beweglichen Teil als Argument"/>
|
||||
<node CREATED="1667659890055" ID="ID_1728452596" MODIFIED="1667659897292" TEXT="immer nur einen Aspekt justieren"/>
|
||||
<node CREATED="1667659931146" ID="ID_1567516385" MODIFIED="1667659944676" TEXT="die jeweilige Ziel-Invariante per Assertion dokumentieren"/>
|
||||
<node BACKGROUND_COLOR="#eef0c5" COLOR="#990000" CREATED="1667698387387" ID="ID_1173911153" MODIFIED="1667698425495" TEXT="Normalisierungs-Sequenz auf Basis der einzel-Normalisierungen definieren">
|
||||
<icon BUILTIN="pencil"/>
|
||||
</node>
|
||||
</node>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#eef0c5" COLOR="#990000" CREATED="1667260366701" ID="ID_1895903283" MODIFIED="1667528268261" TEXT="nächste Fälle">
|
||||
<icon BUILTIN="pencil"/>
|
||||
|
|
@ -55560,7 +55947,7 @@
|
|||
<node CREATED="1667336818154" ID="ID_228764070" MODIFIED="1667336839107" TEXT="TimeValue + symbolische Grid-Referenz"/>
|
||||
<node CREATED="1667336841967" ID="ID_1852849270" MODIFIED="1667336856426" TEXT="Grid über das Advice-System publiziert"/>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#d2beaf" COLOR="#5c4d6e" CREATED="1667476797049" FOLDED="true" ID="ID_767502481" MODIFIED="1667487664229" TEXT="Diskussion: interne Zeitbasis">
|
||||
<node BACKGROUND_COLOR="#d2beaf" COLOR="#5c4d6e" CREATED="1667476797049" FOLDED="true" ID="ID_767502481" MODIFIED="1667593632385" TEXT="Diskussion: interne Zeitbasis">
|
||||
<linktarget COLOR="#af1a4c" DESTINATION="ID_767502481" ENDARROW="Default" ENDINCLINATION="96;-430;" ID="Arrow_ID_1672039685" SOURCE="ID_1838246834" STARTARROW="None" STARTINCLINATION="-670;38;"/>
|
||||
<icon BUILTIN="hourglass"/>
|
||||
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1667486621881" ID="ID_566152244" MODIFIED="1667486629636" TEXT="#1258 clarify internal time base">
|
||||
|
|
@ -55572,6 +55959,7 @@
|
|||
<node CREATED="1667486681289" ID="ID_1245609548" MODIFIED="1667486715504" TEXT="egal ob man nun floating-point nimmt, oder eine feste integrale Basis (µ-Ticks)"/>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#d2beaf" COLOR="#5c4d6e" CREATED="1667486847011" ID="ID_1394182591" MODIFIED="1667486860346" TEXT="sehe folgende Lösungen">
|
||||
<linktarget COLOR="#b3a5d6" DESTINATION="ID_1394182591" ENDARROW="Default" ENDINCLINATION="-42;135;" ID="Arrow_ID_1017363931" SOURCE="ID_945218071" STARTARROW="None" STARTINCLINATION="-118;6;"/>
|
||||
<icon BUILTIN="hourglass"/>
|
||||
<node CREATED="1667486862210" ID="ID_860525476" MODIFIED="1667487583167" TEXT="Umstellen auf Bruch-Darstellung">
|
||||
<icon BUILTIN="full-1"/>
|
||||
|
|
@ -55638,6 +56026,144 @@
|
|||
</node>
|
||||
</node>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1667592184752" ID="ID_1933332619" MODIFIED="1667592189752" TEXT="Aufräum-Arbeiten">
|
||||
<icon BUILTIN="flag-yellow"/>
|
||||
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1667592193783" ID="ID_1808934689" MODIFIED="1667592204255" TEXT="#1259 organise raw time base implementation">
|
||||
<icon BUILTIN="flag-yellow"/>
|
||||
</node>
|
||||
<node CREATED="1667592218952" ID="ID_1463501252" MODIFIED="1667592230199" TEXT="Einsichten">
|
||||
<icon BUILTIN="idea"/>
|
||||
<node CREATED="1667592232354" ID="ID_1809679126" MODIFIED="1667592268849" TEXT="die unterliegende Roh-Implementierung wird stets „durchscheinen“"/>
|
||||
<node CREATED="1667592285128" ID="ID_945218071" MODIFIED="1667592349554">
|
||||
<richcontent TYPE="NODE"><html>
|
||||
<head>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<p>
|
||||
im Besonderen bei den <i>pragmatischen Lösungen</i>
|
||||
</p>
|
||||
</body>
|
||||
</html></richcontent>
|
||||
<arrowlink COLOR="#b3a5d6" DESTINATION="ID_1394182591" ENDARROW="Default" ENDINCLINATION="-42;135;" ID="Arrow_ID_1017363931" STARTARROW="None" STARTINCLINATION="-118;6;"/>
|
||||
<icon BUILTIN="full-2"/>
|
||||
<icon BUILTIN="full-3"/>
|
||||
</node>
|
||||
<node CREATED="1667592366001" ID="ID_170684768" LINK="#ID_745987096" MODIFIED="1667592483713" TEXT="Zeit-Berechnungen brauchen einen validen Zugang">
|
||||
<icon BUILTIN="messagebox_warning"/>
|
||||
</node>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#fdfdcf" COLOR="#ff0000" CREATED="1667592593027" ID="ID_1398816169" MODIFIED="1667592611842" TEXT="Aufgaben">
|
||||
<icon BUILTIN="yes"/>
|
||||
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1667592613824" ID="ID_1877249067" MODIFIED="1667593560997" TEXT="keine externen Library-Typen mehr im normalen Implementierungs code">
|
||||
<icon BUILTIN="yes"/>
|
||||
<node CREATED="1667592632302" ID="ID_1344505411" MODIFIED="1667592635745" TEXT="boost::rational"/>
|
||||
<node CREATED="1667592636666" ID="ID_392219650" MODIFIED="1667592641529" TEXT="gavl_time_t"/>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1667592643724" ID="ID_504422240" MODIFIED="1667592665218" TEXT="LibGavl-Dependency hier entfernen">
|
||||
<icon BUILTIN="flag-yellow"/>
|
||||
<node CREATED="1667592666825" ID="ID_1632149108" MODIFIED="1667592677380" TEXT="so sehr ich Gavl im allgemeinen gut finde"/>
|
||||
<node CREATED="1667592677944" ID="ID_130946855" MODIFIED="1667592698682" TEXT="wir brauchen keine Lib um einen int64_t zu deklarieren">
|
||||
<icon BUILTIN="yes"/>
|
||||
</node>
|
||||
<node CREATED="1667592700101" ID="ID_942374659" MODIFIED="1667592737240" TEXT="ansonsten wird Gavl nicht / noch nicht verwendet">
|
||||
<richcontent TYPE="NOTE"><html>
|
||||
<head>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<p>
|
||||
und ganz im Besonderen: wir stützen uns für die Zeitbehandlung nicht auf libGavl ab
|
||||
</p>
|
||||
</body>
|
||||
</html></richcontent>
|
||||
<icon BUILTIN="idea"/>
|
||||
</node>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1667593471839" ID="ID_1651396499" MODIFIED="1667593549109" TEXT="gavl_time_t ersetzen durch einen Typedef RawTicks">
|
||||
<icon BUILTIN="flag-yellow"/>
|
||||
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1667593606149" ID="ID_1259605001" MODIFIED="1667593625459" TEXT="_raw() ⟶ _rawTicks()">
|
||||
<icon BUILTIN="flag-yellow"/>
|
||||
</node>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1667592743130" ID="ID_675688540" MODIFIED="1667593547383">
|
||||
<richcontent TYPE="NODE"><html>
|
||||
<head>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<p>
|
||||
FSecs durch einen neuen Wrapper <font face="Monospaced" color="#1e178c"><b>RSec</b></font> ersetzen
|
||||
</p>
|
||||
</body>
|
||||
</html></richcontent>
|
||||
<icon BUILTIN="flag-yellow"/>
|
||||
<node CREATED="1667592790281" ID="ID_1680785799" MODIFIED="1667592800092" TEXT="außerdem den neuen lib/rational.hpp hier einbinden"/>
|
||||
<node CREATED="1667592805748" ID="ID_290360900" MODIFIED="1667592820329" TEXT="explizit als Typ RSec verwenden für alle Konvertierungen"/>
|
||||
<node CREATED="1667592821013" ID="ID_289952678" MODIFIED="1667592916791" TEXT="RSec">
|
||||
<icon BUILTIN="info"/>
|
||||
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1667592825916" ID="ID_66335543" MODIFIED="1667592941549" TEXT="implizit konstruierbar aus Rat">
|
||||
<icon BUILTIN="flag-yellow"/>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1667592930415" ID="ID_569654636" MODIFIED="1667592944318" TEXT="implizit konstruierbar aus TimeVal">
|
||||
<icon BUILTIN="flag-yellow"/>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1667592835795" ID="ID_1955597942" MODIFIED="1667592942626">
|
||||
<richcontent TYPE="NODE"><html>
|
||||
<head>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<p>
|
||||
<b>nicht</b> implizit konstruierbar aus int64_t
|
||||
</p>
|
||||
</body>
|
||||
</html></richcontent>
|
||||
<icon BUILTIN="messagebox_warning"/>
|
||||
<icon BUILTIN="flag-yellow"/>
|
||||
<node CREATED="1667592866911" ID="ID_416309268" MODIFIED="1667592869523" TEXT="ganz wichtig"/>
|
||||
<node CREATED="1667592870151" ID="ID_1316405427" MODIFIED="1667592884425" TEXT="denn int64_t impliziert µ-Ticks"/>
|
||||
<node CREATED="1667592895059" ID="ID_556517411" MODIFIED="1667592912143" TEXT="sollte explizit konstruierbar sein, mit Skalen-Transformation"/>
|
||||
</node>
|
||||
<node CREATED="1667592989079" ID="ID_531764150" MODIFIED="1667593020006" TEXT="minimale Arithmetik-Integration mit Time und Duration"/>
|
||||
<node CREATED="1667593029266" ID="ID_1518807557" MODIFIED="1667593045317" TEXT="aber Zeit-Größen nur explizit konstruierbar (= Status quo)"/>
|
||||
</node>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1667593084541" ID="ID_737389227" MODIFIED="1667593105376" TEXT="C-Library effektiv entfernen">
|
||||
<icon BUILTIN="flag-yellow"/>
|
||||
<node CREATED="1667593106935" ID="ID_1453484901" MODIFIED="1667593139782" TEXT="ich will keine C-Implementierungen mehr">
|
||||
<icon BUILTIN="yes"/>
|
||||
</node>
|
||||
<node CREATED="1667593146938" ID="ID_572582896" MODIFIED="1667593420308" TEXT="die C-Library verführt dazu, das Time-Framework zu umgehen">
|
||||
<richcontent TYPE="NOTE"><html>
|
||||
<head>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<p>
|
||||
...seinerzeit fand ich diese Art »Offenheit« noch gut; auch weil ich mir erhoffte, damit mehr Contributors zu bekommen. Die Erfahrungen sprechen dagegen; klar, die Leute mögen erst einmal gerne „move fast and break things“ — aber wenn dann Aufräumen oder anstrengende Konzeptions-Arbeit notwendig würde, bleibt alles liegen und man verschwindet aus dem Projekt.
|
||||
</p>
|
||||
</body>
|
||||
</html></richcontent>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1667593164461" ID="ID_1585303440" MODIFIED="1667593241126" TEXT="Umbau">
|
||||
<icon BUILTIN="flag-yellow"/>
|
||||
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1667593169047" ID="ID_377190169" MODIFIED="1667593239462" TEXT="Header umbenennen">
|
||||
<icon BUILTIN="flag-yellow"/>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1667593179870" ID="ID_1823116307" MODIFIED="1667593239462" TEXT="Header und Implementierung in C++">
|
||||
<icon BUILTIN="flag-yellow"/>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1667593196675" ID="ID_530670970" MODIFIED="1667593239463" TEXT="plain-C-Tests in C++-Tests umziehen">
|
||||
<icon BUILTIN="flag-yellow"/>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1667593209815" ID="ID_1675418151" MODIFIED="1667593239463" TEXT="Hinweise aus Dokumentation entfernen">
|
||||
<icon BUILTIN="flag-yellow"/>
|
||||
</node>
|
||||
</node>
|
||||
</node>
|
||||
</node>
|
||||
</node>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#d2beaf" COLOR="#5c4d6e" CREATED="1667336859796" ID="ID_1810244902" MODIFIED="1667337099718" TEXT="Timecode">
|
||||
<icon BUILTIN="hourglass"/>
|
||||
|
|
|
|||
Loading…
Reference in a new issue