abstract-chart 3.1.10 → 3.2.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/src/axis.ts CHANGED
@@ -1,234 +1,234 @@
1
- import * as R from "ramda";
2
- import * as AbstractImage from "abstract-image";
3
-
4
- export type Axis = LinearAxis | LogarithmicAxis;
5
-
6
- export interface LinearAxis {
7
- readonly type: "linear";
8
- readonly min: number;
9
- readonly max: number;
10
- readonly label: string;
11
- }
12
-
13
- export function createLinearAxis(
14
- min: number,
15
- max: number,
16
- label: string
17
- ): LinearAxis {
18
- return {
19
- type: "linear",
20
- min: min,
21
- max: max,
22
- label: label
23
- };
24
- }
25
-
26
- export interface LogarithmicAxis {
27
- readonly type: "logarithmic";
28
- readonly min: number;
29
- readonly max: number;
30
- readonly label: string;
31
- }
32
-
33
- export function createLogarithmicAxis(
34
- min: number,
35
- max: number,
36
- label: string
37
- ): LogarithmicAxis {
38
- return {
39
- type: "logarithmic",
40
- min: min,
41
- max: max,
42
- label: label
43
- };
44
- }
45
-
46
- const linearMultiples = [1, 2, 5];
47
- const linearPowers = [-2, -1, 0, 1, 2, 3, 4, 5, 6];
48
-
49
- export function getTicks(desiredTicks: number, axis: Axis): Array<number> {
50
- switch (axis.type) {
51
- case "linear":
52
- return getLinearTicks(desiredTicks, axis.min, axis.max);
53
- case "logarithmic":
54
- return getLogarithmicTicks(desiredTicks, axis.min, axis.max);
55
- default:
56
- return [];
57
- }
58
- }
59
-
60
- interface Alternative {
61
- readonly min: number;
62
- readonly step: number;
63
- readonly ticks: number;
64
- }
65
-
66
- export function getLinearTicks(
67
- desiredTicks: number,
68
- min: number,
69
- max: number
70
- ): Array<number> {
71
- let best: Alternative | undefined;
72
- for (const power of linearPowers) {
73
- const base = Math.pow(10, power);
74
- for (const multiple of linearMultiples) {
75
- const step = base * multiple;
76
- const cMin = Math.ceil(min / step);
77
- const cMax = Math.floor(max / step);
78
- const ticks = cMax - cMin + 1;
79
-
80
- if (
81
- !best ||
82
- Math.abs(best.ticks - desiredTicks) > Math.abs(ticks - desiredTicks)
83
- ) {
84
- best = {
85
- min: cMin * step,
86
- step: step,
87
- ticks: ticks
88
- };
89
- }
90
- }
91
- }
92
-
93
- if (!best) {
94
- return [];
95
- }
96
- const b = best;
97
- return R.range(0, b.ticks).map(l => b.min + b.step * l);
98
- }
99
-
100
- const logarithmicAlternatives = [
101
- [0],
102
- [0, 5],
103
- [0, 1, 2, 5],
104
- [0, 1, 2, 3, 5],
105
- [0, 1, 2, 3, 5, 8],
106
- [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
107
- ];
108
-
109
- export function getLogarithmicTicks(
110
- desiredTicks: number,
111
- min: number,
112
- max: number
113
- ): Array<number> {
114
- const minPow = Math.floor(Math.log10(min)) - 1;
115
- const maxPow = Math.ceil(Math.log10(max)) + 1;
116
- const powers = R.range(0, maxPow - minPow + 1).map(p => minPow + p);
117
- const alternatives = logarithmicAlternatives.map(stepAlt => {
118
- const altLines = powers.reduce((lines: Array<number>, power: number) => {
119
- const base = Math.pow(10, power);
120
- const powerLines = stepAlt.map(i => i * base);
121
- return lines.concat(powerLines);
122
- }, []);
123
- return altLines.filter(l => l >= min && l <= max);
124
- });
125
- const bestLines = alternatives.reduce(
126
- (prev, alt) =>
127
- Math.abs(alt.length - desiredTicks) < Math.abs(prev.length - desiredTicks)
128
- ? alt
129
- : prev
130
- );
131
- return bestLines;
132
- }
133
-
134
- export function transformPoint(
135
- point: AbstractImage.Point,
136
- xMin: number,
137
- xMax: number,
138
- yMin: number,
139
- yMax: number,
140
- xAxis: Axis | undefined,
141
- yAxis: Axis | undefined
142
- ): AbstractImage.Point {
143
- const x = transformValue(point.x, xMin, xMax, xAxis);
144
- const y = transformValue(point.y, yMin, yMax, yAxis);
145
- return AbstractImage.createPoint(x, y);
146
- }
147
-
148
- export function transformValue(
149
- value: number,
150
- min: number,
151
- max: number,
152
- axis: Axis | undefined
153
- ): number {
154
- if (!axis) {
155
- return value;
156
- }
157
- const range = max - min;
158
- switch (axis.type) {
159
- case "linear":
160
- return min + range * linearTransform(value, axis.min, axis.max);
161
- case "logarithmic":
162
- return min + range * logarithmicTransform(value, axis.min, axis.max);
163
- default:
164
- return 0;
165
- }
166
- }
167
-
168
- export function inverseTransformValue(
169
- value: number,
170
- min: number,
171
- max: number,
172
- axis: Axis | undefined
173
- ): number {
174
- if (!axis) {
175
- return value;
176
- }
177
- const range = max - min;
178
- switch (axis.type) {
179
- case "linear":
180
- return inverseLinearTransform((value - min) / range, axis.min, axis.max);
181
- case "logarithmic":
182
- return inverseLogarithmicTransform(
183
- (value - min) / range,
184
- axis.min,
185
- axis.max
186
- );
187
- default:
188
- return 0;
189
- }
190
- }
191
-
192
- export function linearTransform(
193
- value: number,
194
- min: number,
195
- max: number
196
- ): number {
197
- return (value - min) / (max - min);
198
- }
199
-
200
- export function logarithmicTransform(
201
- value: number,
202
- min: number,
203
- max: number
204
- ): number {
205
- if (value > 0) {
206
- return (
207
- (Math.log10(value) - Math.log10(min)) /
208
- (Math.log10(max) - Math.log10(min))
209
- );
210
- } else if (value < 0) {
211
- return 0.0;
212
- } else {
213
- return 0.0;
214
- }
215
- }
216
-
217
- export function inverseLinearTransform(
218
- value: number,
219
- min: number,
220
- max: number
221
- ): number {
222
- return min + value * (max - min);
223
- }
224
-
225
- export function inverseLogarithmicTransform(
226
- value: number,
227
- min: number,
228
- max: number
229
- ): number {
230
- return Math.pow(
231
- 10,
232
- value * (Math.log10(max) - Math.log10(min)) + Math.log10(min)
233
- );
234
- }
1
+ import * as R from "ramda";
2
+ import * as AbstractImage from "abstract-image";
3
+
4
+ export type Axis = LinearAxis | LogarithmicAxis;
5
+
6
+ export interface LinearAxis {
7
+ readonly type: "linear";
8
+ readonly min: number;
9
+ readonly max: number;
10
+ readonly label: string;
11
+ }
12
+
13
+ export function createLinearAxis(
14
+ min: number,
15
+ max: number,
16
+ label: string
17
+ ): LinearAxis {
18
+ return {
19
+ type: "linear",
20
+ min: min,
21
+ max: max,
22
+ label: label
23
+ };
24
+ }
25
+
26
+ export interface LogarithmicAxis {
27
+ readonly type: "logarithmic";
28
+ readonly min: number;
29
+ readonly max: number;
30
+ readonly label: string;
31
+ }
32
+
33
+ export function createLogarithmicAxis(
34
+ min: number,
35
+ max: number,
36
+ label: string
37
+ ): LogarithmicAxis {
38
+ return {
39
+ type: "logarithmic",
40
+ min: min,
41
+ max: max,
42
+ label: label
43
+ };
44
+ }
45
+
46
+ const linearMultiples = [1, 2, 5];
47
+ const linearPowers = [-2, -1, 0, 1, 2, 3, 4, 5, 6];
48
+
49
+ export function getTicks(desiredTicks: number, axis: Axis): Array<number> {
50
+ switch (axis.type) {
51
+ case "linear":
52
+ return getLinearTicks(desiredTicks, axis.min, axis.max);
53
+ case "logarithmic":
54
+ return getLogarithmicTicks(desiredTicks, axis.min, axis.max);
55
+ default:
56
+ return [];
57
+ }
58
+ }
59
+
60
+ interface Alternative {
61
+ readonly min: number;
62
+ readonly step: number;
63
+ readonly ticks: number;
64
+ }
65
+
66
+ export function getLinearTicks(
67
+ desiredTicks: number,
68
+ min: number,
69
+ max: number
70
+ ): Array<number> {
71
+ let best: Alternative | undefined;
72
+ for (const power of linearPowers) {
73
+ const base = Math.pow(10, power);
74
+ for (const multiple of linearMultiples) {
75
+ const step = base * multiple;
76
+ const cMin = Math.ceil(min / step);
77
+ const cMax = Math.floor(max / step);
78
+ const ticks = cMax - cMin + 1;
79
+
80
+ if (
81
+ !best ||
82
+ Math.abs(best.ticks - desiredTicks) > Math.abs(ticks - desiredTicks)
83
+ ) {
84
+ best = {
85
+ min: cMin * step,
86
+ step: step,
87
+ ticks: ticks
88
+ };
89
+ }
90
+ }
91
+ }
92
+
93
+ if (!best) {
94
+ return [];
95
+ }
96
+ const b = best;
97
+ return R.range(0, b.ticks).map(l => b.min + b.step * l);
98
+ }
99
+
100
+ const logarithmicAlternatives = [
101
+ [0],
102
+ [0, 5],
103
+ [0, 1, 2, 5],
104
+ [0, 1, 2, 3, 5],
105
+ [0, 1, 2, 3, 5, 8],
106
+ [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
107
+ ];
108
+
109
+ export function getLogarithmicTicks(
110
+ desiredTicks: number,
111
+ min: number,
112
+ max: number
113
+ ): Array<number> {
114
+ const minPow = Math.floor(Math.log10(min)) - 1;
115
+ const maxPow = Math.ceil(Math.log10(max)) + 1;
116
+ const powers = R.range(0, maxPow - minPow + 1).map(p => minPow + p);
117
+ const alternatives = logarithmicAlternatives.map(stepAlt => {
118
+ const altLines = powers.reduce((lines: Array<number>, power: number) => {
119
+ const base = Math.pow(10, power);
120
+ const powerLines = stepAlt.map(i => i * base);
121
+ return lines.concat(powerLines);
122
+ }, []);
123
+ return altLines.filter(l => l >= min && l <= max);
124
+ });
125
+ const bestLines = alternatives.reduce(
126
+ (prev, alt) =>
127
+ Math.abs(alt.length - desiredTicks) < Math.abs(prev.length - desiredTicks)
128
+ ? alt
129
+ : prev
130
+ );
131
+ return bestLines;
132
+ }
133
+
134
+ export function transformPoint(
135
+ point: AbstractImage.Point,
136
+ xMin: number,
137
+ xMax: number,
138
+ yMin: number,
139
+ yMax: number,
140
+ xAxis: Axis | undefined,
141
+ yAxis: Axis | undefined
142
+ ): AbstractImage.Point {
143
+ const x = transformValue(point.x, xMin, xMax, xAxis);
144
+ const y = transformValue(point.y, yMin, yMax, yAxis);
145
+ return AbstractImage.createPoint(x, y);
146
+ }
147
+
148
+ export function transformValue(
149
+ value: number,
150
+ min: number,
151
+ max: number,
152
+ axis: Axis | undefined
153
+ ): number {
154
+ if (!axis) {
155
+ return value;
156
+ }
157
+ const range = max - min;
158
+ switch (axis.type) {
159
+ case "linear":
160
+ return min + range * linearTransform(value, axis.min, axis.max);
161
+ case "logarithmic":
162
+ return min + range * logarithmicTransform(value, axis.min, axis.max);
163
+ default:
164
+ return 0;
165
+ }
166
+ }
167
+
168
+ export function inverseTransformValue(
169
+ value: number,
170
+ min: number,
171
+ max: number,
172
+ axis: Axis | undefined
173
+ ): number {
174
+ if (!axis) {
175
+ return value;
176
+ }
177
+ const range = max - min;
178
+ switch (axis.type) {
179
+ case "linear":
180
+ return inverseLinearTransform((value - min) / range, axis.min, axis.max);
181
+ case "logarithmic":
182
+ return inverseLogarithmicTransform(
183
+ (value - min) / range,
184
+ axis.min,
185
+ axis.max
186
+ );
187
+ default:
188
+ return 0;
189
+ }
190
+ }
191
+
192
+ export function linearTransform(
193
+ value: number,
194
+ min: number,
195
+ max: number
196
+ ): number {
197
+ return (value - min) / (max - min);
198
+ }
199
+
200
+ export function logarithmicTransform(
201
+ value: number,
202
+ min: number,
203
+ max: number
204
+ ): number {
205
+ if (value > 0) {
206
+ return (
207
+ (Math.log10(value) - Math.log10(min)) /
208
+ (Math.log10(max) - Math.log10(min))
209
+ );
210
+ } else if (value < 0) {
211
+ return 0.0;
212
+ } else {
213
+ return 0.0;
214
+ }
215
+ }
216
+
217
+ export function inverseLinearTransform(
218
+ value: number,
219
+ min: number,
220
+ max: number
221
+ ): number {
222
+ return min + value * (max - min);
223
+ }
224
+
225
+ export function inverseLogarithmicTransform(
226
+ value: number,
227
+ min: number,
228
+ max: number
229
+ ): number {
230
+ return Math.pow(
231
+ 10,
232
+ value * (Math.log10(max) - Math.log10(min)) + Math.log10(min)
233
+ );
234
+ }