Skip to content

Commit 4d93a55

Browse files
committed
handle null values in stacked bars more carefully
1 parent c61aca7 commit 4d93a55

File tree

2 files changed

+41
-34
lines changed

2 files changed

+41
-34
lines changed

chart-tests/tests/Test20.hs

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,10 @@ import Utils
1111
import Test.QuickCheck (Result(Failure))
1212

1313
dat :: [[Double]]
14-
dat = [ [66.22192174833207, 50.85424119528999]
14+
dat = [ [0.0, 23.81232131645]
15+
, [83.87632543135, 0.0]
16+
, [0.0, 0.0]
17+
, [66.22192174833207, 50.85424119528999]
1518
, [18.507408294149144, 29.94826136042779]
1619
, [271.34564215397256, 482.0060747629345]
1720
, [0.33308595521927825, 0.25399999403605966]
@@ -82,7 +85,7 @@ chart = layoutToRenderable layout
8285
$ plot_bars_label_style . font_slant .~ FontSlantItalic
8386
$ def
8487

85-
dat' = map (\[a,b] -> [ (LogValue (min a b), "")
88+
dat' = map (\[a,b] -> [ (LogValue (min a b), if a == b then "0.0" else "")
8689
, if a < b then
8790
let v = b - a in
8891
(LogValue v, printf "%0.2f" v)
@@ -93,5 +96,7 @@ chart = layoutToRenderable layout
9396
else (LogValue 0, "")
9497
]) dat
9598

96-
alabels = map (\n -> "longDataPointName" ++ show n) $ take (length dat) [1..]
99+
alabels =
100+
["addedDataPointName", "removedDataPointName", "nullDataPointName"] ++
101+
map (\n -> "longDataPointName" ++ show n) (take (length dat - 3) [1..])
97102

chart/Graphics/Rendering/Chart/Plot/Bars.hs

Lines changed: 33 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -192,46 +192,42 @@ instance Default (PlotBars x y) where
192192

193193
plotBars :: (BarsPlotValue y) => PlotBars x y -> Plot x y
194194
plotBars p = Plot {
195-
_plot_render = \pmap -> renderBars (_plot_bars_settings p) vals yref0
196-
(barRect pmap) (mapX pmap),
195+
_plot_render = \pmap -> renderBars s vals yref0
196+
(barRect pmap) (mapX pmap),
197197
_plot_legend = zip (_plot_bars_titles p)
198198
(map renderPlotLegendBars
199-
(_bars_settings_item_styles $ _plot_bars_settings p)),
200-
_plot_all_points = allBarPoints p
199+
(_bars_settings_item_styles s)),
200+
_plot_all_points = allBarPoints s vals
201201
}
202202
where
203+
s = _plot_bars_settings p
203204
vals = _plot_bars_values_with_labels p
205+
yref0 = refVal s vals
204206

205207
barRect pmap xos width x y0 y1 = Rect (Point (x'+xos) y0') (Point (x'+xos+width) y') where
206208
Point x' y' = mapXY pmap (x,y1)
207209
Point _ y0' = mapXY pmap (x,y0)
208210

209-
yref0 = barsReference $ case _bars_settings_style $ _plot_bars_settings p of
210-
BarsClustered -> concatMap (map fst . snd) vals
211-
BarsStacked -> map (fst . head . snd) vals
212-
213211
mapX pmap x = p_x (mapXY pmap (x, yref0))
214212

215213
plotHBars :: (BarsPlotValue x) => PlotBars y x -> Plot x y
216214
plotHBars p = Plot {
217-
_plot_render = \pmap -> renderBars (_plot_bars_settings p) vals xref0
218-
(barRect pmap) (mapY pmap),
215+
_plot_render = \pmap -> renderBars s vals xref0
216+
(barRect pmap) (mapY pmap),
219217
_plot_legend = zip (_plot_bars_titles p)
220218
(map renderPlotLegendBars
221-
(_bars_settings_item_styles $ _plot_bars_settings p)),
222-
_plot_all_points = swap $ allBarPoints p
219+
(_bars_settings_item_styles s)),
220+
_plot_all_points = swap $ allBarPoints s vals
223221
}
224222
where
223+
s = _plot_bars_settings p
225224
vals = _plot_bars_values_with_labels p
225+
xref0 = refVal s vals
226226

227227
barRect pmap yos height y x0 x1 = Rect (Point x0' (y'+yos)) (Point x' (y'+yos+height)) where
228228
Point x' y' = mapXY pmap (x1,y)
229229
Point x0' _ = mapXY pmap (x0,y)
230230

231-
xref0 = barsReference $ case _bars_settings_style $ _plot_bars_settings p of
232-
BarsClustered -> concatMap (map fst . snd) vals
233-
BarsStacked -> map (fst . head . snd) vals
234-
235231
mapY pmap y = p_y (mapXY pmap (xref0, y))
236232

237233
renderBars :: (BarsPlotValue v) =>
@@ -274,30 +270,31 @@ renderBars p vals vref0 r mapk = case _bars_settings_style p of
274270
(pvadd pt $ _bars_settings_label_offset p)
275271
txt
276272

277-
stackedBars (x,ys) = do
278-
let (ys', lbls) = unzip ys
279-
let y2s = zip (vref0:stack ys') (stack ys')
273+
stackedBars (k,vs) = do
274+
let (vs', lbls) = unzip vs
275+
let vs'' = map (\v -> if barsIsNull v then vref0 else v) (stack vs')
276+
let v2s = zip (vref0:vs'') vs''
280277
let ofs = case _bars_settings_alignment p of
281278
BarsLeft -> 0
282279
BarsRight -> -bsize
283280
BarsCentered -> -(bsize/2)
284-
forM_ (zip y2s styles) $ \((y0,y1), (fstyle,_)) ->
285-
unless (y0 == y1) $
281+
forM_ (zip v2s styles) $ \((v0,v1), (fstyle,_)) ->
282+
unless (v0 >= v1) $
286283
withFillStyle fstyle $
287-
alignFillPath (barPath ofs x y0 y1)
284+
alignFillPath (barPath ofs k v0 v1)
288285
>>= fillPath
289-
forM_ (zip y2s styles) $ \((y0,y1), (_,mlstyle)) ->
290-
unless (y0 == y1) $
286+
forM_ (zip v2s styles) $ \((v0,v1), (_,mlstyle)) ->
287+
unless (v0 >= v1) $
291288
whenJust mlstyle $ \lstyle ->
292289
withLineStyle lstyle $
293-
alignStrokePath (barPath ofs x y0 y1)
290+
alignStrokePath (barPath ofs k v0 v1)
294291
>>= strokePath
295292
withFontStyle (_bars_settings_label_style p) $
296-
forM_ (zip y2s lbls) $ \((y0, y1), txt) ->
293+
forM_ (zip v2s lbls) $ \((v0, v1), txt) ->
297294
unless (null txt) $ do
298295
let ha = _bars_settings_label_bar_hanchor p
299296
let va = _bars_settings_label_bar_vanchor p
300-
let pt = rectCorner ha va (r ofs bsize x y0 y1)
297+
let pt = rectCorner ha va (r ofs bsize k v0 v1)
301298
drawTextR
302299
(_bars_settings_label_text_hanchor p)
303300
(_bars_settings_label_text_vanchor p)
@@ -340,14 +337,19 @@ rectCorner h v (Rect (Point x0 y0) (Point x1 y1)) = Point x' y' where
340337
addLabels :: Show y => [(x, [y])] -> [(x, [(y, String)])]
341338
addLabels = map . second $ map (\y -> (y, show y))
342339

343-
allBarPoints :: (BarsPlotValue y) => PlotBars x y -> ([x],[y])
344-
allBarPoints (PlotBars p _ vals) = case _bars_settings_style p of
340+
refVal :: (BarsPlotValue y) => BarsSettings -> [(x, [(y, String)])] -> y
341+
refVal p vals = barsReference $ case _bars_settings_style p of
342+
BarsClustered -> concatMap (map fst . snd) vals
343+
BarsStacked -> concatMap (take 1 . dropWhile barsIsNull . stack . map fst . snd) vals
344+
345+
allBarPoints :: (BarsPlotValue y) => BarsSettings -> [(x, [(y, String)])] -> ([x],[y])
346+
allBarPoints p vals = case _bars_settings_style p of
345347
BarsClustered ->
346348
let ys = concatMap (map fst) yls in
347349
( xs, barsReference ys:ys )
348350
BarsStacked ->
349-
let ys = map (map fst) yls in
350-
( xs, barsReference (map head ys):concatMap stack ys)
351+
let ys = map (stack . map fst) yls in
352+
( xs, barsReference (concatMap (take 1 . dropWhile barsIsNull) ys):concat ys)
351353
where (xs, yls) = unzip vals
352354

353355
stack :: (BarsPlotValue y) => [y] -> [y]

0 commit comments

Comments
 (0)