Home | History | Annotate | Download | only in source
      1 /*****************************************************************************/
      2 // Copyright 2006-2007 Adobe Systems Incorporated
      3 // All Rights Reserved.
      4 //
      5 // NOTICE:  Adobe permits you to use, modify, and distribute this file in
      6 // accordance with the terms of the Adobe license agreement accompanying it.
      7 /*****************************************************************************/
      8 
      9 /* $Id: //mondo/dng_sdk_1_4/dng_sdk/source/dng_spline.cpp#1 $ */
     10 /* $DateTime: 2012/05/30 13:28:51 $ */
     11 /* $Change: 832332 $ */
     12 /* $Author: tknoll $ */
     13 
     14 /*****************************************************************************/
     15 
     16 #include "dng_spline.h"
     17 
     18 #include "dng_assertions.h"
     19 #include "dng_exceptions.h"
     20 
     21 /******************************************************************************/
     22 
     23 dng_spline_solver::dng_spline_solver ()
     24 
     25 	:	X ()
     26 	,	Y ()
     27 	,	S ()
     28 
     29 	{
     30 
     31 	}
     32 
     33 /******************************************************************************/
     34 
     35 dng_spline_solver::~dng_spline_solver ()
     36 	{
     37 
     38 	}
     39 
     40 /******************************************************************************/
     41 
     42 void dng_spline_solver::Reset ()
     43 	{
     44 
     45 	X.clear ();
     46 	Y.clear ();
     47 
     48 	S.clear ();
     49 
     50 	}
     51 
     52 /******************************************************************************/
     53 
     54 void dng_spline_solver::Add (real64 x, real64 y)
     55 	{
     56 
     57 	X.push_back (x);
     58 	Y.push_back (y);
     59 
     60 	}
     61 
     62 /******************************************************************************/
     63 
     64 void dng_spline_solver::Solve ()
     65 	{
     66 
     67 	// This code computes the unique curve such that:
     68 	//		It is C0, C1, and C2 continuous
     69 	//		The second derivative is zero at the end points
     70 
     71 	int32 count = (int32) X.size ();
     72 
     73 	DNG_ASSERT (count >= 2, "Too few points");
     74 
     75 	int32 start = 0;
     76 	int32 end   = count;
     77 
     78 	real64 A =  X [start+1] - X [start];
     79 	real64 B = (Y [start+1] - Y [start]) / A;
     80 
     81 	S.resize (count);
     82 
     83 	S [start] = B;
     84 
     85 	int32 j;
     86 
     87 	// Slopes here are a weighted average of the slopes
     88 	// to each of the adjcent control points.
     89 
     90 	for (j = start + 2; j < end; ++j)
     91 		{
     92 
     93 		real64 C = X [j] - X [j-1];
     94 		real64 D = (Y [j] - Y [j-1]) / C;
     95 
     96 		S [j-1] = (B * C + D * A) / (A + C);
     97 
     98 		A = C;
     99 		B = D;
    100 
    101 		}
    102 
    103 	S [end-1] = 2.0 * B - S [end-2];
    104 	S [start] = 2.0 * S [start] - S [start+1];
    105 
    106 	if ((end - start) > 2)
    107 		{
    108 
    109 		dng_std_vector<real64> E;
    110 		dng_std_vector<real64> F;
    111 		dng_std_vector<real64> G;
    112 
    113 		E.resize (count);
    114 		F.resize (count);
    115 		G.resize (count);
    116 
    117 		F [start] = 0.5;
    118 		E [end-1] = 0.5;
    119 		G [start] = 0.75 * (S [start] + S [start+1]);
    120 		G [end-1] = 0.75 * (S [end-2] + S [end-1]);
    121 
    122 		for (j = start+1; j < end - 1; ++j)
    123 			{
    124 
    125 			A = (X [j+1] - X [j-1]) * 2.0;
    126 
    127 			E [j] = (X [j+1] - X [j]) / A;
    128 			F [j] = (X [j] - X [j-1]) / A;
    129 			G [j] = 1.5 * S [j];
    130 
    131 			}
    132 
    133 		for (j = start+1; j < end; ++j)
    134 			{
    135 
    136 			A = 1.0 - F [j-1] * E [j];
    137 
    138 			if (j != end-1) F [j] /= A;
    139 
    140 			G [j] = (G [j] - G [j-1] * E [j]) / A;
    141 
    142 			}
    143 
    144 		for (j = end - 2; j >= start; --j)
    145 			G [j] = G [j] - F [j] * G [j+1];
    146 
    147 		for (j = start; j < end; ++j)
    148 			S [j] = G [j];
    149 
    150 		}
    151 
    152 	}
    153 
    154 /******************************************************************************/
    155 
    156 bool dng_spline_solver::IsIdentity () const
    157 	{
    158 
    159 	int32 count = (int32) X.size ();
    160 
    161 	if (count != 2)
    162 		return false;
    163 
    164 	if (X [0] != 0.0 || X [1] != 1.0 ||
    165 		Y [0] != 0.0 || Y [1] != 1.0)
    166 		return false;
    167 
    168 	return true;
    169 
    170 	}
    171 
    172 /******************************************************************************/
    173 
    174 real64 dng_spline_solver::Evaluate (real64 x) const
    175 	{
    176 
    177 	int32 count = (int32) X.size ();
    178 
    179 	// Check for off each end of point list.
    180 
    181 	if (x <= X [0])
    182 		return Y [0];
    183 
    184 	if (x >= X [count-1])
    185 		return Y [count-1];
    186 
    187 	// Binary search for the index.
    188 
    189 	int32 lower = 1;
    190 	int32 upper = count - 1;
    191 
    192 	while (upper > lower)
    193 		{
    194 
    195 		int32 mid = (lower + upper) >> 1;
    196 
    197 		if (x == X [mid])
    198 			{
    199 			return Y [mid];
    200 			}
    201 
    202 		if (x > X [mid])
    203 			lower = mid + 1;
    204 		else
    205 			upper = mid;
    206 
    207 		}
    208 
    209 	DNG_ASSERT (upper == lower, "Binary search error in point list");
    210 
    211 	int32 j = lower;
    212 
    213 	// X [j - 1] < x <= X [j]
    214 	// A is the distance between the X [j] and X [j - 1]
    215 	// B and C describe the fractional distance to either side. B + C = 1.
    216 
    217 	// We compute a cubic spline between the two points with slopes
    218 	// S[j-1] and S[j] at either end. Specifically, we compute the 1-D Bezier
    219 	// with control values:
    220 	//
    221 	//		Y[j-1], Y[j-1] + S[j-1]*A, Y[j]-S[j]*A, Y[j]
    222 
    223 	return EvaluateSplineSegment (x,
    224 								  X [j - 1],
    225 								  Y [j - 1],
    226 								  S [j - 1],
    227 								  X [j    ],
    228 								  Y [j    ],
    229 								  S [j    ]);
    230 
    231 	}
    232 
    233 /*****************************************************************************/
    234