1 /*******************************************************************************
2 * Copyright (c) 2016 École Polytechnique de Montréal
4 * All rights reserved. This program and the accompanying materials are
5 * made available under the terms of the Eclipse Public License v1.0 which
6 * accompanies this distribution, and is available at
7 * http://www.eclipse.org/legal/epl-v10.html
8 *******************************************************************************/
10 package org
.eclipse
.tracecompass
.internal
.tmf
.chart
.ui
.data
;
12 import static org
.eclipse
.tracecompass
.common
.core
.NonNullUtils
.checkNotNull
;
14 import java
.math
.BigDecimal
;
17 * Simple class that maps two {@link ChartRange} together. The first one is the
18 * plotted range: it represents the range of the chart in which the data will be
19 * plotted. The second one is the input data range: it represents the range of
20 * the incoming data that will be plotted.
22 * This map is used for mapping values that might be too big for a chart. Values
23 * that are in the external range are mapped to fit the internal range.
25 * @author Gabriel-Andrew Pollo-Guilbert
27 public class ChartRangeMap
{
29 // ------------------------------------------------------------------------
31 // ------------------------------------------------------------------------
33 private static final int BIG_DECIMAL_DIVISION_SCALE
= 22;
35 // ------------------------------------------------------------------------
37 // ------------------------------------------------------------------------
39 private ChartRange fPlottedRange
;
40 private ChartRange fInputDataRange
;
42 // ------------------------------------------------------------------------
44 // ------------------------------------------------------------------------
49 public ChartRangeMap() {
50 fPlottedRange
= new ChartRange();
51 fInputDataRange
= new ChartRange();
55 * Surcharged constructor with the input data range.
58 * The range of the input data
60 public ChartRangeMap(ChartRange input
) {
61 fPlottedRange
= new ChartRange();
62 fInputDataRange
= input
;
66 * Surcharged constructor with the plotted and input data ranges.
71 * The range of the input data
73 public ChartRangeMap(ChartRange plotted
, ChartRange input
) {
74 fPlottedRange
= plotted
;
75 fInputDataRange
= input
;
78 // ------------------------------------------------------------------------
80 // ------------------------------------------------------------------------
83 * Accessor that returns the plotted range of the map.
85 * @return The plotted range
87 public ChartRange
getPlottedRange() {
92 * Accessor that returns the input data range of the map.
94 * @return The input data range
96 public ChartRange
getInputDataRange() {
97 return fInputDataRange
;
100 // ------------------------------------------------------------------------
102 // ------------------------------------------------------------------------
105 * Mutator that sets the plotted range of the map.
108 * The new plotted range
110 public void setPlottedRange(ChartRange plotted
) {
111 fPlottedRange
= plotted
;
115 * Mutator that sets the input data range of the map.
118 * The new input data range
120 public void setInputDataRange(ChartRange input
) {
121 fInputDataRange
= input
;
124 // ------------------------------------------------------------------------
126 // ------------------------------------------------------------------------
129 * This method transforms a number from the input data range into a number
130 * that fits in the plotted range.
132 * Incoming numbers from the data might be bigger than the numbers that the
133 * chart library supports (e.g. SWT supports Double and we can pass Long).
134 * While processing the numbers, a loss of precision might occur. In order
135 * to minimize this, we transform the raw values to an internal
136 * representation based on a linear transformation.
138 * Let <i>e_val</i>, <i>e_min</i>, <i>e_Δ</i> be the external value,
139 * external minimum and external delta respectively and <i>i_min</i>,
140 * <i>i_Δ</i> be the internal minimum and the internal delta. The internal
141 * value <i>i_val</i> is given by the formula:
143 * i_val=(e_val-e_min)*(i_Δ/e_Δ)+i_min
146 * A number to transform
147 * @return The transformed value
149 public Number
getInternalValue(Number number
) {
150 BigDecimal value
= new BigDecimal(number
.toString());
151 ChartRange internal
= getPlottedRange();
152 ChartRange external
= getInputDataRange();
154 /* Apply the formula */
155 BigDecimal internalValue
= value
156 .subtract(external
.getMinimum())
157 .multiply(internal
.getDelta())
158 .divide(external
.getDelta(), BIG_DECIMAL_DIVISION_SCALE
, BigDecimal
.ROUND_DOWN
)
159 .add(internal
.getMinimum());
161 return checkNotNull(internalValue
);
165 * Util method that transforms an plotted value back into its original
168 * It is very similar to {@link #getInternalValue(Number)}, except that is
169 * apply the formula in reverse in order to obtain the original value while
170 * minimizing lost in precision.
173 * A number to transform
174 * @return A BigDecimal representation of the external value
176 public BigDecimal
getExternalValue(Number number
) {
177 ChartRange internal
= getPlottedRange();
178 ChartRange external
= getInputDataRange();
180 /* Apply the formula in reverse */
181 BigDecimal externalValue
= (new BigDecimal(number
.toString()))
182 .subtract(internal
.getMinimum())
183 .multiply(external
.getDelta())
184 .divide(internal
.getDelta(), BIG_DECIMAL_DIVISION_SCALE
, BigDecimal
.ROUND_DOWN
)
185 .add(external
.getMinimum());
187 return checkNotNull(externalValue
);