1 //=========================================================
2 //  MusE
3 //  Linux Music Editor
4 //    $Id: dimap.cpp,v 1.1.1.1 2003/10/27 18:55:11 wschweer Exp $
5 
6 //    Copyright (C) 1997  Josef Wilgen
7 //    (C) Copyright 2000 Werner Schweer (ws@seh.de)
8 //
9 //  This program is free software; you can redistribute it and/or
10 //  modify it under the terms of the GNU General Public License
11 //  as published by the Free Software Foundation; version 2 of
12 //  the License, or (at your option) any later version.
13 //
14 //  This program is distributed in the hope that it will be useful,
15 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
16 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17 //  GNU General Public License for more details.
18 //
19 //  You should have received a copy of the GNU General Public License
20 //  along with this program; if not, write to the Free Software
21 //  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
22 //
23 //=========================================================
24 
25 #include "muse_math.h"
26 #include "dimap.h"
27 #include "mmath.h"
28 
29 namespace MusEGui {
30 
31 const double DiMap::LogMin = 1.0e-150;
32 const double DiMap::LogMax = 1.0e150;
33 
34 //	DiMap - Map a double interval into an integer interval
35 //
36 //	The DiMap class maps an interval of type double into an interval of
37 //	type integer. It consists
38 //	of two intervals D = [d1, d2] (double) and I = [i1, i2] (int), which are
39 //	specified with the @DiMap::setDblRange@ and @DiMap::setIntRange@
40 //	members. The point d1 is mapped to the point i1, and d2 is mapped to i2.
41 //	Any point inside or outside D can be mapped to a point inside or outside
42 //	I using @DiMap::transform@ or @DiMap::limTransform@ or vice versa
43 //	using @QwtPlot::invTransform@. D can be scaled linearly or
44 //	logarithmically, as specified with @DiMap::setDblRange@.
45 
46 //------------------------------------------------------------
47 //.F	DiMap::DiMap (1)
48 //	Construct a DiMap instance.
49 //
50 //.u	Syntax
51 //.f	 DiMap::DiMap()
52 //
53 //.u	Description
54 //	The double and integer intervals are both set to [0,1].
55 //------------------------------------------------------------
56 
DiMap()57 DiMap::DiMap()
58       {
59       d_x1 = 0.0;
60       d_x2 = 1.0;
61       d_y1 = 0;
62       d_y2 = 1;
63       d_cnv = 1.0;
64       }
65 
66 //------------------------------------------------------------
67 //.F	DiMap::DiMap (2)
68 //	Construct a DiMap instance with initial integer
69 //	and double intervals
70 //
71 //.u	Syntax
72 //.f	 DiMap::DiMap(int i1, int i2, double d1, double d2, bool logarithmic)
73 //
74 //.u	Parameters
75 //.p	int i1		--	first border of integer interval
76 //	int i2		--	second border of integer interval
77 //	double d1	--	first border of double interval
78 //	double d2	--	second border of double interval
79 //	bool logarithmic  -- logarithmic mapping, TRUE or FALSE. Defaults
80 //					to FALSE.
81 //------------------------------------------------------------
82 
DiMap(int i1,int i2,double d1,double d2,bool logarithmic)83 DiMap::DiMap(int i1, int i2, double d1, double d2, bool logarithmic)
84       {
85       d_log = logarithmic;
86       setIntRange(i1,i2);
87       setDblRange(d1, d2);
88       }
89 
90 //------------------------------------------------------------
91 //.F	DiMap::~DiMap
92 //	Destroy a DiMap instance.
93 //
94 //.u	Syntax
95 //.f	 DiMap::~DiMap()
96 //------------------------------------------------------------
97 
~DiMap()98 DiMap::~DiMap()
99       {
100       }
101 
102 //------------------------------------------------------------
103 //.F	DiMap::contains (1)
104 //	Returns TRUE if a value x lies inside or at the border of the
105 //	map's double range.
106 //
107 //.u	Syntax
108 //.f	bool DiMap::contains(double x)
109 //
110 //.u	Parameters
111 //.p	double x -- value
112 //------------------------------------------------------------
113 
contains(double x) const114 bool DiMap::contains(double x) const
115       {
116       return ( (x >= MusECore::qwtMin(d_x1, d_x1)) && (x <= MusECore::qwtMax(d_x1, d_x2)));
117       }
118 
119 //------------------------------------------------------------
120 //.F	DiMap::contains (2)
121 //	Returns TRUE if a value x lies inside or at the border of the
122 //	map's integer range
123 //
124 //.u	Syntax
125 //.f	bool DiMap::contains(int x)
126 //
127 //.u	Parameters
128 //.p	int x -- value
129 //------------------------------------------------------------
130 
contains(int x) const131 bool DiMap::contains(int x) const
132       {
133       return ( (x >= MusECore::qwtMin(d_y1, d_y1)) && (x <= MusECore::qwtMax(d_y1, d_y2)));
134       }
135 
136 //------------------------------------------------------------
137 //.F	DiMap::setDblRange
138 //	Specify the borders of the double interval
139 //
140 //.u	Syntax
141 //.f	void DiMap::setDblRange(double d1, double d2, bool lg = FALSE)
142 //
143 //.u	Parameters
144 //.p	double d1	--	first border
145 //	double d2	--	second border
146 //	bool lg		--	logarithmic (TRUE) or linear (FALSE)
147 //				scaling. Defaults to FALSE.
148 //------------------------------------------------------------
149 
setDblRange(double d1,double d2,bool lg)150 void DiMap::setDblRange(double d1, double d2, bool lg)
151       {
152       if (lg) {
153             d_log = true;
154             if (d1 < LogMin)
155                   d1 = LogMin;
156             else if (d1 > LogMax)
157                   d1 = LogMax;
158 
159             if (d2 < LogMin)
160                   d2 = LogMin;
161             else if (d2 > LogMax)
162                   d2 = LogMax;
163 
164             d_x1 = log(d1);
165             d_x2 = log(d2);
166             }
167       else {
168             d_log = false;
169             d_x1 = d1;
170             d_x2 = d2;
171             }
172       newFactor();
173       }
174 
175 //------------------------------------------------------------
176 //.F	DiMap::setIntRange
177 //	Specify the borders of the integer interval
178 //
179 //.u	Syntax
180 //.f	void DiMap::setIntRange(int i1, int i2)
181 //
182 //.u	Parameters
183 //.p	int i1	--	first border
184 //	int i2  --	second border
185 //------------------------------------------------------------
186 
setIntRange(int i1,int i2)187 void DiMap::setIntRange(int i1, int i2)
188       {
189       d_y1 = i1;
190       d_y2 = i2;
191       newFactor();
192       }
193 
194 //------------------------------------------------------------
195 //.F	DiMap::transform
196 //	Transform a point in double interval into an point in the
197 //	integer interval
198 //
199 //.u	Syntax
200 //.f	int DiMap::transform(double x)
201 //
202 //.u	Parameters
203 //.p	double x
204 //
205 //.u	Return Value
206 //.t
207 //	linear mapping:	-- rint(i1 + (i2 - i1) / (d2 - d1) * (x - d1))
208 //	logarithmic mapping: -- rint(i1 + (i2 - i1) / log(d2 / d1) * log(x / d1))
209 //
210 //.u    Note
211 //	The specified point is allowed to lie outside the intervals. If you
212 //	want to limit the returned value, use @DiMap::limTransform@.
213 //------------------------------------------------------------
214 
transform(double x) const215 int DiMap::transform(double x) const
216       {
217       if (d_log)
218             return (d_y1 + int(rint( (log(x) - d_x1) * d_cnv )));
219       else
220             return (d_y1 + int(rint( (x - d_x1) * d_cnv )));
221       }
222 
223 //------------------------------------------------------------
224 //.F	DiMap::invTransform
225 //	Transform an integer value into a double value
226 //
227 //.u	Syntax
228 //.f	double DiMap::invTransform(int y)
229 //
230 //.u	Parameters
231 //.p	int y	--	integer value to be transformed
232 //
233 //.u	Return Value
234 //.t
235 //	linear mapping:	-- d1 + (d2 - d1) / (i2 - i1) * (y - i1)
236 //	logarithmic mapping: -- d1 + (d2 - d1) / log(i2 / i1) * log(y / i1)
237 //------------------------------------------------------------
238 
invTransform(int y) const239 double DiMap::invTransform(int y) const
240       {
241       if (d_cnv == 0.0)
242             return 0.0;
243       else {
244             if (d_log)
245                   return exp(d_x1 + double(y - d_y1) / d_cnv );
246             else
247                   return ( d_x1 + double(y - d_y1) / d_cnv );
248             }
249       }
250 
251 //------------------------------------------------------------
252 //.F	DiMap::limTransform
253 //	Transform and limit
254 //
255 //.u	Syntax
256 //.f	int DiMap::limTransform(double x)
257 //
258 //.u	Parameters
259 //.p	double x
260 //
261 //.u	Return Value
262 //		transformed value
263 //
264 //.u	Description
265 //	The function is similar to @DiMap::transform@, but limits the input value
266 //	to the nearest border of the map's double interval if it lies outside
267 //	that interval.
268 //------------------------------------------------------------
269 
limTransform(double x) const270 int DiMap::limTransform(double x) const
271       {
272       if ( x > MusECore::qwtMax(d_x1, d_x2) )
273             x = MusECore::qwtMax(d_x1, d_x2);
274       else if ( x < MusECore::qwtMin(d_x1, d_x2))
275             x = MusECore::qwtMin(d_x1, d_x2);
276       return transform(x);
277       }
278 
279 //------------------------------------------------------------
280 //.F	DiMap::xTransform
281 //	Exact transformation
282 //
283 //.u	Syntax
284 //.f	double DiMap::dTransform(double x)
285 //
286 //.u	Parameters
287 //.p		double x	-- value to be transformed
288 //
289 //.u	Return Value
290 //.t
291 //	linear mapping:	-- i1 + (i2 - i1) / (d2 - d1) * (x - d1)
292 //	logarithmic mapping: -- i1 + (i2 - i1) / log(d2 / d1) * log(x / d1)
293 //
294 //.u	Description
295 //	This function is similar to @DiMap::transform@, but
296 //	makes the integer interval appear to be double.
297 //------------------------------------------------------------
298 
xTransform(double x) const299 double DiMap::xTransform(double x) const
300       {
301       double rv;
302 
303       if (d_log)
304             rv = double(d_y1) + (log(x) - d_x1) * d_cnv;
305       else
306             rv = double(d_y1) + (x - d_x1) * d_cnv;
307       return rv;
308       }
309 
310 //------------------------------------------------------------
311 //.F	DiMap::newFactor
312 //	Re-calculate the conversion factor.
313 //------------------------------------------------------------
314 
newFactor()315 void DiMap::newFactor()
316       {
317       if (d_x2 != d_x1)
318             d_cnv = double(d_y2 - d_y1) / (d_x2 - d_x1);
319       else
320             d_cnv = 0.0;
321       }
322 
323 } // namespace MusEGui
324