[vspline] 24/72: pv now uses image pyramid To further reduce stutter with large panoramas, I added code to use a pyramid of slightly smoothed, scaled down spline objects which are put to use depending on the scale of the display. I commit this status quo because it seems to be a nice milestone without any immediately obvious bugs.

Kay F. Jahnke kfj-guest at moszumanska.debian.org
Sun Jul 2 09:02:39 UTC 2017


This is an automated email from the git hooks/post-receive script.

kfj-guest pushed a commit to branch master
in repository vspline.

commit 7fd27c7ae5beb37c7ad0e403e34b219f18385252
Author: Kay F. Jahnke <kfjahnke at gmail.com>
Date:   Mon Jan 2 17:53:42 2017 +0100

    pv now uses image pyramid
    To further reduce stutter with large panoramas, I added code to use a pyramid
    of slightly smoothed, scaled down spline objects which are put to use depending
    on the scale of the display. I commit this status quo because it seems to be a nice
    milestone without any immediately obvious bugs.
---
 brace.h   | 11 ++++++++++-
 bspline.h | 65 +++++++++++++++++++++++++++++++++++++++++++++------------------
 2 files changed, 57 insertions(+), 19 deletions(-)

diff --git a/brace.h b/brace.h
index fdf106e..7cc8093 100644
--- a/brace.h
+++ b/brace.h
@@ -169,7 +169,7 @@ struct bracer
 
   static int left_brace_size ( int spline_degree , bc_code bc )
   {
-    if ( bc == REFLECT || bc == SPHERICAL )
+    if ( bc == REFLECT || bc == SPHERICAL || bc == RTAG )
       return ( spline_degree + 1 ) / 2 ;
     else
       return spline_degree / 2 ;
@@ -365,6 +365,8 @@ struct bracer
       }
       case NATURAL :
       case MIRROR :
+      case TAG :
+      case TAGP :
       {
         ls = l0 + 2 ;
         rs = r0 - 2 ;
@@ -373,6 +375,7 @@ struct bracer
       case CONSTANT :
       case SPHERICAL :
       case REFLECT :
+      case RTAG :
       {
         ls = l0 + 1 ;
         rs = r0 - 1 ;
@@ -404,6 +407,9 @@ struct bracer
           case PERIODIC :
           case MIRROR :
           case REFLECT :
+          case TAG :
+          case RTAG :
+          case TAGP :
           {
             // with these three bracing modes, we simply copy from source to target
             a.bindAt ( axis , lt ) = a.bindAt ( axis , ls ) ;
@@ -453,6 +459,9 @@ struct bracer
           case PERIODIC :
           case MIRROR :
           case REFLECT :
+          case TAG :
+          case RTAG :
+          case TAGP :
           {
             // with these three bracing modes, we simply copy from source to target
             a.bindAt ( axis , rt ) = a.bindAt ( axis , rs ) ;
diff --git a/bspline.h b/bspline.h
index 3d55b93..bf6d574 100644
--- a/bspline.h
+++ b/bspline.h
@@ -216,7 +216,7 @@ public:
   /// setup_metrics determines the sizes of the three views and any braces/frames
   /// needed with the given parameters
 
-  void setup_metrics()
+  void setup_metrics ( int headroom = 0 )
   {
     switch ( strategy )
     {
@@ -231,13 +231,14 @@ public:
         // again an implicit prefiltering scheme will be used, but here we add
         // a 'brace' to the core data, which makes the resulting bspline object
         // suitable to work with vspline's evaluation code. The container array's
-        // size is the same as the braced core's size.
+        // size is the same as the braced core's size, unless additional headroom
+        // was requested.
         braced_shape = bracer<view_type>::target_shape ( core_shape , bcv , spline_degree ) ;
         left_brace = bracer<view_type>::left_corner ( bcv , spline_degree ) ;
         right_brace = bracer<view_type>::right_corner ( bcv , spline_degree ) ;
-        left_frame = left_brace ;
-        right_frame = right_brace ;
-        container_shape = braced_shape ;
+        left_frame = left_brace + headroom ;
+        right_frame = right_brace + headroom ;
+        container_shape = core_shape + left_frame + right_frame ;
         braced = true ;
         break ;
       case EXPLICIT:
@@ -245,12 +246,13 @@ public:
         // space, namely the 'frame', around the core data, into which the extrapolated
         // data are put before prefiltering the lot. This frame is applied in excess of
         // the bracing, to make sure all coefficients inside the brace meet the precision
-        // requirements expressed by the choice of 'horizon'.
+        // requirements expressed by the choice of 'horizon'. If additional headroom
+        // is requested, this comes yet on top.
         braced_shape = bracer<view_type>::target_shape ( core_shape , bcv , spline_degree ) ;
         left_brace = bracer<view_type>::left_corner ( bcv , spline_degree ) ;
         right_brace = bracer<view_type>::right_corner ( bcv , spline_degree ) ;
-        left_frame = left_brace + horizon ;
-        right_frame = right_brace + horizon ;
+        left_frame = left_brace + horizon + headroom ;
+        right_frame = right_brace + horizon + headroom ;
         container_shape = core_shape + left_frame + right_frame ;
         braced = true ;
         break ;
@@ -302,6 +304,10 @@ public:
   /// deemed to be 'sufficiently large' to keep the error 'low enough'. the expression
   /// used here produces a frame which is roughly the size needed to make any margin
   /// effects vanish by the time the prefilter hits the core, but it's a bit 'rule of thumb'.
+  ///
+  /// The additional parameter 'headroom' is used to make the 'frame' even wider. This is
+  /// needed if the spline is to be 'shifted' up (evaluated as if it had been prefiltered
+  /// with a higher-degree prefilter) - see shift().
   
   // TODO: when bracing/framing is applied, we might widen the array size to a
   // multiple of the Vc:Vector's Size for the given data type to have better-aligned
@@ -313,6 +319,8 @@ public:
   // widen class bspline's scope to accept input of other types and/or use a different
   // math_type.
 
+  // TODO: write copy constructor, operator=
+  
   bspline ( shape_type _core_shape ,  ///< shape of knot point data
             int _spline_degree = 3 , ///< spline degree with reasonable default
             bcv_type _bcv = bcv_type ( MIRROR ) ,   ///< boundary conditions and common default
@@ -320,7 +328,8 @@ public:
             int _horizon = -1 ,                     ///< width of frame for explicit scheme
             view_type _space = view_type() ,        ///< coefficient storage to 'adopt'
             double _tolerance = -1.0 ,              ///< acceptable error (relative to unit pulse)
-            double _smoothing = 0.0                 ///< apply smoothing to data before prefiltering
+            double _smoothing = 0.0 ,               ///< apply smoothing to data before prefiltering
+            int headroom = 0                        ///< additional headroom, for 'shifting'
           )
   : core_shape ( _core_shape ) ,
     spline_degree ( _spline_degree ) ,
@@ -355,7 +364,7 @@ public:
       horizon = _horizon ; // whatever the user specifies
 
     // first, calculate all the various shapes and sizes used internally
-    setup_metrics() ;
+    setup_metrics ( headroom ) ;
 
     // now either adopt external memory or allocate memory for the coefficients
     if ( _space.hasData() )
@@ -392,7 +401,10 @@ public:
 
   /// prefilter converts the knot point data in the 'core' area into b-spline
   /// coefficients. Depending on the strategy chosen in the b-spline object's
-  /// constructor, bracing/framing may be applied.
+  /// constructor, bracing/framing may be applied. Even if the degree of the
+  /// spline is zero or one, prefilter() should be called because it also
+  /// performs the bracing, if any, which may still be needed if the spline
+  /// is 'shifted' - unless the stratgey is UNBRACED, of course.
   ///
   /// If data are passed in, they have to have precisely the shape
   /// we have set up in core (_core_shape passed into the constructor).
@@ -416,7 +428,8 @@ public:
       // spline but constitutes a view to data kept elsewhere (by passing _space to the
       // constructor).
       if ( data.shape() != core_shape )
-        throw shape_mismatch ( "when passing data to prefilter, they have to have precisely the core's shape" ) ;
+        throw shape_mismatch
+         ( "when passing data to prefilter, they have to have precisely the core's shape" ) ;
       if ( strategy == EXPLICIT )
       {
         // the explicit scheme requires the data and frame to be together in the
@@ -475,11 +488,17 @@ public:
                 use_vc ,
                 nthreads
               ) ;
+        // using the more general code here now, since the frame may be larger
+        // than strictly necessary for the given spline degree due to a request
+        // for additional headroom
         for ( int d = 0 ; d < dimension ; d++ )
-          br ( coeffs , bcv[d] , spline_degree , d ) ;
+          br.apply ( container , bcv[d] , left_frame[d] , right_frame[d] , d ) ;
+// was:
+//         for ( int d = 0 ; d < dimension ; d++ )
+//           br ( coeffs , bcv[d] , spline_degree , d ) ;
         break ;
       case EXPLICIT:
-        // apply bracing with BC codes passed in, then solve with BC code IGNORE
+        // apply bracing with BC codes passed in, then solve with BC code GUESS
         // this automatically fills the brace, as well, since it's part of the frame.
         // TODO: the values in the frame will not come out precisely the same as they
         // would by filling the brace after the coefficients have been calculated.
@@ -502,7 +521,7 @@ public:
         break ;
       case MANUAL:
         // like EXPLICIT, but don't apply a frame, assume a frame was applied
-        // by external code. process whole container with IGNORE BC. For cases
+        // by external code. process whole container with GUESS BC. For cases
         // where the frame can't be constructed by applying any of the stock bracing
         // modes. Note that if any data were passed into this routine, in this case
         // they will be silently ignored (makes no sense overwriting the core after
@@ -531,7 +550,9 @@ public:
             prefilter_strategy _strategy = BRACED , ///< default strategy is the 'implicit' scheme
             int _horizon = -1 ,                     ///< width of frame for explicit scheme
             view_type _space = view_type() ,        ///< coefficient storage to 'adopt'
-            double _tolerance = -1.0                ///< acceptable error (relative to unit pulse)
+            double _tolerance = -1.0 ,              ///< acceptable error (relative to unit pulse)
+            double _smoothing = 0.0 ,               ///< apply smoothing to data before prefiltering
+            int headroom = 0                        ///< additional headroom, for 'shifting'
           )
   :bspline ( TinyVector < long , 1 > ( _core_shape ) ,
              _spline_degree ,
@@ -539,7 +560,10 @@ public:
              _strategy ,
              _horizon ,
              _space ,
-             _tolerance )
+             _tolerance ,
+             _smoothing ,
+             headroom
+           )
   {
     static_assert ( _dimension == 1 , "bspline: 1D constructor only usable for 1D splines" ) ;
   } ;
@@ -552,7 +576,11 @@ public:
   /// interpolated signal, shifting with negative d will sharpen it.
   /// For shifting to work, the spline has to have enough 'headroom', meaning that
   /// spline_degree + d, the new spline degree, has to be greater or equal to 0
-  /// and smaller than the largest supported spline degree (lower twenties)
+  /// and smaller than the largest supported spline degree (lower twenties) -
+  /// and, additionally, there has to bee a wide-enough brace to allow evaluation
+  /// with the wider kernel of the higher-degree spline's reconstruction filter.
+  /// So if a spline is set up with degree 0 and shifted to degree 5, it has to be
+  /// constructed with an additional headroom of 3 (see the constructor).
   /// This is a quick-shot solution to the problem of scaled-down interpolated
   /// results; it may be better in some situations to shift the spline up and
   /// evaluate than to apply smoothing to the source data.
@@ -624,6 +652,7 @@ public:
     osr << "left frame:.................. " << bsp.left_frame << endl ;
     osr << "right frame:................. " << bsp.right_frame << endl ;
     osr << ( bsp._coeffs.hasData() ? "bspline object owns data" : "data are owned externally" ) << endl ;
+    osr << "container base adress:....... " << bsp.container.data() << endl ;
     return osr ;
   }
 

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/debian-science/packages/vspline.git



More information about the debian-science-commits mailing list