summaryrefslogtreecommitdiff
path: root/Master/texmf-dist/tex/generic/pgfplots/lua/pgfplots/colormap.lua
blob: 73cbb2c894ec0b133a77e308299372b143ef35c4 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
--
-- This file contains parts of pgfplotscolormap.code.tex
--

local math=math
local pgfplotsmath = pgfplots.pgfplotsmath
local io=io
local type=type
local tostring=tostring
local error=error
local table=table

do
-- all globals will be read from/defined in pgfplots:
local _ENV = pgfplots

local pgftonumber = pgfluamathfunctions.tonumber
-----------------------------------

ColorSpace = newClass()
function ColorSpace:constructor(numComponents)
	self.numComponents=numComponents
end

rgb = ColorSpace.new(3)
cmyk = ColorSpace.new(4)
gray = ColorSpace.new(1)


ColorMap = newClass()

ColorMap.range =1000

-- h: mesh width between adjacent values
-- colorspace: an instance of ColorSpace
-- values: an array (1-based table) with color components. Each color component is supposed to be a table with K entries where K is colorspace:numComponents
-- positions: either an empty array (in which case the colormap is uniform) or one position per value. Positions are in [0,1000]
-- scaleOrderZ the specific scaling factor used for 'colormap access=const' (or negative or the empty string if this is disabled)
function ColorMap:constructor( h, colorspace, values, positions, scaleOrderZ)
	if not h or not colorspace or not positions or not values then error("arguments must not be nil")end

	self.name = name
	self.h = h
	self.invh = 1/h
	self.colorspace = colorspace
	self.values = values
	self.pos = positions
	self:setScaleOrderZ(scaleOrderZ)

	local numComponents = self.colorspace.numComponents
	for i = 1,#self.values do
		local value = self.values[i]
		if #value ~= numComponents then
			error("Some value has an unexpected number of color components, expected " .. self.colorspace.numComponents .. " but was ".. #value);
		end
	end
end

function ColorMap:isUniform()
	if #self.pos == 0 then
		return true
	else
		return false
	end
end

function ColorMap:setScaleOrderZ(scaleOrderZ)
	if type(scaleOrderZ) == "number" then
		self.scaleOrderZ = scaleOrderZ
	elseif #scaleOrderZ == 0 or type(scaleOrderZ) == "string" and scaleOrderZ == "h" then
		-- special case which means "h"
		self.scaleOrderZ = "h"
	else
		self.scaleOrderZ = pgftonumber(scaleOrderZ)
	end
end

function ColorMap:_transform(inMin, inMax, x)
	local transformed
	if inMin == 0 and inMax == ColorMap.range then
		transformed = x
	else
		local scale = ColorMap.range / (inMax - inMin)

		transformed = (x - inMin) * scale
	end
	transformed = math.max(0, transformed)
	transformed = math.min(ColorMap.range, transformed)
	return transformed
end

function ColorMap:findPrecomputed(inMin, inMax, x)
	local transformed = self:_transform(inMin, inMax, x)

	local divh = transformed * self.invh
	local intervalno = math.floor(divh)
	local factor = divh - intervalno
	local factor_two = 1-factor


	-- Step 2: interpolate the desired RGB value using vector valued interpolation on the identified interval
	if intervalno+1 == #self.values then
		-- ah- we are at the right end!
		return self.values[#self.values]
	end

	local left = self.values[intervalno+1]
	local right = self.values[intervalno+2]
	if not left or not right then error("Internal error: the color map does not have enough values for interval no " .. intervalno )end

	local result = {}
	for i = 1,self.colorspace.numComponents do
		local result_i = factor_two * left[i] + factor * right[i]

		result[i] = result_i
	end

	return result
end

function ColorMap:findPiecewiseConst(inMin, inMax, x)
	-- see docs in \pgfplotscolormapfindpiecewiseconst@precomputed@ for details

	local transformed = self:_transform(inMin, inMax, x)
	local intervalno =-1
	if self:isUniform() then
		if self.scaleOrderZ == "h" then
			invh = self.invh + 0.001
		else
			-- disable the extra interval
			invh = self.invh
		end

		local divh = transformed * invh
		intervalno = math.floor(divh)
	else
	 	-- FIXME : IMPLEMENT
	end

	if intervalno+1 == #self.values then
		-- we have artificially increased the "h" (see the comments
		-- above) -- meaning that this 'if' can happen.
		-- ->Map the rightmost point to the rightmost interval:
		return self.values[#self.values]
	end
	return self.values[intervalno+1]
end

-----------------------------------

-- global registry of all colormaps.
-- Key: colormap name
-- Value: an instance of ColorMap
ColorMaps = {}

end