Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bar plots can't be drawn with a negative y-axis #87

Open
kxygk opened this issue Jul 18, 2021 · 0 comments
Open

Bar plots can't be drawn with a negative y-axis #87

kxygk opened this issue Jul 18, 2021 · 0 comments

Comments

@kxygk
Copy link

kxygk commented Jul 18, 2021

There is bit of a weird limitation with the bar plots. The bars are at the moment drawn with respect to the first value in the domain - but this causes some usability issues

If you have bar plots that have mostly negative values - for instance:

    (let [left-margin 50
	  width 720
	  height 180]
      (->> {:x-axis (linear-axis
		     {:domain [0 5]
		      :range  [left-margin width]
		      :pos    (/ height 2)})
	    :y-axis (linear-axis
		     {:domain  [0 10] ;; the first values in effect sets the bar's `zero`
		      :range   [(/  height
				    2.0)
				0]
		      :major  1
		      :pos    (+ left-margin 0)})
	    :data [{:values  [[1 4] [2 -6] [3 -3] [4 2]]
		    :attribs {:fill "none" :stroke "#0af" :stroke-width (/ width 6)}
		    :layout  svg-bar-plot}]}
	   (svg-plot2d-cartesian)
	   (svg {:width width :height height })
	   (serialize)
	   (spit "normal-bar-plot.svg")))

normal-bar-plot

Adding a Y axis that spans the full range is impossible b/c the domain range must start with a zero (otherwise the zero point of the bar will be some negative value)

.An alternative that almost works - that will give you just a negative Y axis - is to give it a decreasing :domain and a modified :range

    (let [left-margin 50
	  width 720
	  height 180]
      (->> {:x-axis (linear-axis
		     {:domain [0 5]
		      :range  [left-margin width]
		      :label-style {:fill "none"}
		      :pos    (/ height 2)})
	    :y-axis (linear-axis
		     {:domain  [0 -10] ;; the first values in effect sets the bar's `zero`
		      :range   [(/  height
				    2.0)
				height ]
		      :major  1
		      :pos    (+ left-margin 0)})
	    :data [{:values  [[1 4] [2 -6] [3 -3] [4 2] ]
		    :attribs {:fill "none" :stroke "#0af" :stroke-width (/ width 6)}
		    :layout  svg-bar-plot}]}
	   (svg-plot2d-cartesian)
	   (svg {:width width :height height })
	   (serialize)
	   (spit "negative-bar-plot.svg")))

negative-bar-plot

This however clobbers the axis labels.

It looks like an issue in thi.ng.geom.viz.core/lin-tick-marks

I tried changing the code to look like

(defn lin-tick-marks
  [[d1 d2] delta]
  (if (m/delta= delta 0.0 m/*eps*)
    '()
    (let [dr (- d2 d1)
          d1' (m/roundto d1 delta)]
      (filter #(m/in-range? d1 d2 %) (range d1' (+ d2 delta) (if (< d1 d2) delta (- delta)))))))

(b/c if the first argument to range is smaller than the second, then the incrementor need to be negative)

However this didn't seem to fix the issue. My guess is that thi.ng.math.core/in-range? isn't meant to handle d2 > d1. I didn't want to go deeper and change things in math.core b/c it might break something else in the larger project

In any case, maybe decreasing domain ranges shouldn't be supported :)

Ideally some alternate solution would allow the axis to go from negative to positive in whatever domain the user wants (by setting some sort of :zero-point for the bar plots maybe?).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant