custom charts: Add formatter for the charts
[deliverable/tracecompass.git] / tmf / org.eclipse.tracecompass.tmf.chart.ui / src / org / eclipse / tracecompass / internal / tmf / chart / ui / data / ChartRangeMap.java
1 /*******************************************************************************
2 * Copyright (c) 2016 École Polytechnique de Montréal
3 *
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 *******************************************************************************/
9
10 package org.eclipse.tracecompass.internal.tmf.chart.ui.data;
11
12 import static org.eclipse.tracecompass.common.core.NonNullUtils.checkNotNull;
13
14 import java.math.BigDecimal;
15
16 /**
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.
21 * <p>
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.
24 *
25 * @author Gabriel-Andrew Pollo-Guilbert
26 */
27 public class ChartRangeMap {
28
29 // ------------------------------------------------------------------------
30 // Constants
31 // ------------------------------------------------------------------------
32
33 private static final int BIG_DECIMAL_DIVISION_SCALE = 22;
34
35 // ------------------------------------------------------------------------
36 // Members
37 // ------------------------------------------------------------------------
38
39 private ChartRange fPlottedRange;
40 private ChartRange fInputDataRange;
41
42 // ------------------------------------------------------------------------
43 // Constructors
44 // ------------------------------------------------------------------------
45
46 /**
47 * Constructor.
48 */
49 public ChartRangeMap() {
50 fPlottedRange = new ChartRange();
51 fInputDataRange = new ChartRange();
52 }
53
54 /**
55 * Surcharged constructor with the input data range.
56 *
57 * @param input
58 * The range of the input data
59 */
60 public ChartRangeMap(ChartRange input) {
61 fPlottedRange = new ChartRange();
62 fInputDataRange = input;
63 }
64
65 /**
66 * Surcharged constructor with the plotted and input data ranges.
67 *
68 * @param plotted
69 * The plotted range
70 * @param input
71 * The range of the input data
72 */
73 public ChartRangeMap(ChartRange plotted, ChartRange input) {
74 fPlottedRange = plotted;
75 fInputDataRange = input;
76 }
77
78 // ------------------------------------------------------------------------
79 // Accessors
80 // ------------------------------------------------------------------------
81
82 /**
83 * Accessor that returns the plotted range of the map.
84 *
85 * @return The plotted range
86 */
87 public ChartRange getPlottedRange() {
88 return fPlottedRange;
89 }
90
91 /**
92 * Accessor that returns the input data range of the map.
93 *
94 * @return The input data range
95 */
96 public ChartRange getInputDataRange() {
97 return fInputDataRange;
98 }
99
100 // ------------------------------------------------------------------------
101 // Mutators
102 // ------------------------------------------------------------------------
103
104 /**
105 * Mutator that sets the plotted range of the map.
106 *
107 * @param plotted
108 * The new plotted range
109 */
110 public void setPlottedRange(ChartRange plotted) {
111 fPlottedRange = plotted;
112 }
113
114 /**
115 * Mutator that sets the input data range of the map.
116 *
117 * @param input
118 * The new input data range
119 */
120 public void setInputDataRange(ChartRange input) {
121 fInputDataRange = input;
122 }
123
124 // ------------------------------------------------------------------------
125 // Operations
126 // ------------------------------------------------------------------------
127
128 /**
129 * This method transforms a number from the input data range into a number
130 * that fits in the plotted range.
131 * <p>
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.
137 * <p>
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:
142 * <p>
143 * i_val=(e_val-e_min)*(i_Δ/e_Δ)+i_min
144 *
145 * @param number
146 * A number to transform
147 * @return The transformed value
148 */
149 public Number getInternalValue(Number number) {
150 BigDecimal value = new BigDecimal(number.toString());
151 ChartRange internal = getPlottedRange();
152 ChartRange external = getInputDataRange();
153
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());
160
161 return checkNotNull(internalValue);
162 }
163
164 /**
165 * Util method that transforms an plotted value back into its original
166 * range.
167 * <p>
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.
171 *
172 * @param number
173 * A number to transform
174 * @return A BigDecimal representation of the external value
175 */
176 public BigDecimal getExternalValue(Number number) {
177 ChartRange internal = getPlottedRange();
178 ChartRange external = getInputDataRange();
179
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());
186
187 return checkNotNull(externalValue);
188 }
189
190 }
This page took 0.035091 seconds and 5 git commands to generate.