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

Polar area: align start angle with angleLines #5919

Closed
wants to merge 3 commits into from

Conversation

kurkle
Copy link
Member

@kurkle kurkle commented Dec 16, 2018

Polar area treats startAngle as radians and 0 at right. However radar chart and radialLinear scale expects startAngle to be degrees and 0 to be at top.

https://codepen.io/kurkle/pen/RERWEz

polar-angle-lines
Note: I did not botrher changing values displayed to radians for this gif. They were just converted to radians for config.

Fixes #5907

@simonbrunel
Copy link
Member

I think that's a breaking change, right?

@kurkle
Copy link
Member Author

kurkle commented Dec 17, 2018

@simonbrunel Yes, its breaking change. Also a bug fix 🙈

@simonbrunel
Copy link
Member

I don't think we can/should change the unit of startAngle (radians -> degrees), neither where the angle 0 is positioned (right -> top), because all projects that explicitly set this option will be impacted by major visual changes.

@kurkle
Copy link
Member Author

kurkle commented Dec 17, 2018

Should not have it both ways either 2.7.3
2.7.3 projects would probably have ticks hidden always.
Both default to start at top, only 2.7.3 does it by setting startAngle to - 0.5PI (so by default ticks are -1.57° off)

@simonbrunel
Copy link
Member

I updated the PR description with a before / after screenshots.

The problem is when there is no angle lines, the current (2.7.3) behavior is not bugged but startAngle is expected to be in radian. I agree that startAngle in not consistent between radar and polar charts, but should we break existing project that don't use angle lines (display: false by default in polar)?

Another question: why startAngle doesn't apply when angleLines.display: false?

@kurkle
Copy link
Member Author

kurkle commented Dec 17, 2018

Another question: why startAngle doesn't apply when angleLines.display: false?

getValueCount returns 0

	function getValueCount(scale) {
		var opts = scale.options;
		return opts.angleLines.display || opts.pointLabels.display ? scale.chart.data.labels.length : 0;
	}

getIndexAngle divides by that 0

		getIndexAngle: function(index) {
			var angleMultiplier = (Math.PI * 2) / getValueCount(this);

@kurkle
Copy link
Member Author

kurkle commented Dec 17, 2018

The problem is when there is no angle lines, the current (2.7.3) behavior is not bugged but startAngle is expected to be in radian. I agree that startAngle in not consistent between radar and polar charts, but should we break existing project that don't use angle lines (display: false by default in polar)?

I think not. Something should still be done. Couple of options come in mind;

  • Apply this fix only if angleLines (or pointLabels) are shown.
  • Apply this fix only if abs(startAngle)>2PI. If its > 0 and <= 2PI warn about deprecation
  • Introduce new option to work around this issue
  • Postpone this change to 3.0

@nagix
Copy link
Contributor

nagix commented Dec 18, 2018

I would suggest to

  • not change startAngle (-0.5 * Math.PI by default) for polarArea
  • add startAngle (-0.5 * Math.PI by default) for radar
  • keep startAngle in radians
  • make getIndexAngle return radians staring from the right and staying between -PI and PI
  • modify the related code (min and max arguments for determineLimits, getTextAlignForAngle and adjustPointPositionForLabelHeight)
  • add Math.PI / 2 to
    ctx.rotate(startAngle);

This won't break existing projects.

@nagix
Copy link
Contributor

nagix commented Dec 18, 2018

Maybe getIndexAngle can return radians from the top and leave other parts in radialLinear.js as is.

@kurkle
Copy link
Member Author

kurkle commented Dec 18, 2018

I would suggest to

  • keep startAngle in radians

This was my initial approach.
However that test broke and made me think it was supposed to be degrees.
IMO configuration should be degrees and immediately converted to radians when parsing (so code is all radians)
--snip--

This won't break existing projects.

What about radar charts with startAngle defined in degrees? Custom chart types using radialLinear axis?

@nagix
Copy link
Contributor

nagix commented Dec 18, 2018

I notice that startAngle was first introduced to polarArea charts in a452094 representing radians while offsetAngle was first introduced to radar charts in #2984 representing degrees, then renamed to startAngle in #2947. Unfortunately, the description of startAngle for radar charts was removed from the document when v2.6 was released.

@benmccann
Copy link
Contributor

It seems to me like the fundamental problem here is that all the radialLinear scale methods like getIndexAngle (used by the aforementioned test) utilize degrees while the polarArea chart uses radians. This is a big problem since the polarArea chart uses the radialLinear scale.

Here's from the radialLinear scale:

	getIndexAngle: function(index) {
		var angleMultiplier = (Math.PI * 2) / getValueCount(this);
		var startAngle = this.chart.options && this.chart.options.startAngle ?
			this.chart.options.startAngle :
			0;

		var startAngleRadians = startAngle * Math.PI * 2 / 360;

		// Start from the top instead of right, so remove a quarter of the circle
		return index * angleMultiplier + startAngleRadians;
	},

The problem here is that the scale doesn't know whether this.chart.options.startAngle is defined as radians or degrees since the radar chart and polarArea chart have defined them differently.

I'm not really sure how to fix this while maintaining backwards compatibility. I think I agree with @kurkle when he calls it a bug in the polarArea chart. It may be a bit painful to change it, but it's also a bit painful to leave this bug in place. I would vote for fixing the bug which I think means we need to change to degrees

@simonbrunel @nagix thoughts?

@nagix
Copy link
Contributor

nagix commented Jan 2, 2019

This problem appears only when scale.angleLines.display is explicitly set to true in a polarArea chart, so I guess not many projects are suffering from this. As discussed in #5279, changing to degrees in v3.0 seems to be way to go. Until then, why don't we use the following workaround?

var startAngleRadians = (this.chart.config.type === 'polarArea') ?
    startAngle + Math.PI * 0.5 :
    startAngle * Math.PI * 2 / 360;

@kurkle
Copy link
Member Author

kurkle commented Jan 2, 2019

How about this? (it does not work with decimal angles between -6.28 and 6.28 degrees (about), excluding 0. But who needs those in a chart?):

	helpers.autoRadians = function(angle) {
		var TAU = 2 * Math.PI;
		if (angle >= -TAU && angle <= TAU && Math.floor(angle) !== angle) {
			console.warn('angles defined in radians are deprecated and will not be supported in 3.0.');
			return angle;
		}
		return helpers.toRadians(angle);
	};
  • and rotate canvas 90 degrees when angleLines are displayed (to match with scale)

Demonstrated in this pen: https://codepen.io/kurkle/pen/ZVvrqg

Added "&& Math.floor(angle) !== angle" to allow whole degrees of 1..6 (this leaves tiny holes in radian support)
Holes in radians approximated in degrees:

1/180*PI = 57.29577951308232
2/180*PI = 114.59155902616465
3/180*PI = 171.88733853924697
4/180*PI = 229.1831180523293
5/180*PI = 286.4788975654116
6/180*PI = 343.77467707849394

@benmccann
Copy link
Contributor

Another idea: we could introduce an option for degrees vs radians. Then the scale doesn't need to know which chart is being used and users can specify which ever they prefer

docs/charts/polar.md Outdated Show resolved Hide resolved
@kurkle kurkle force-pushed the #5907 branch 2 times, most recently from 492b0a6 to fb5c00b Compare March 2, 2019 07:30
@kurkle kurkle changed the title Polar area: startAngle in degrees, 0 at top. Polar area: align start angle with agnleLines Mar 2, 2019
@kurkle kurkle changed the title Polar area: align start angle with agnleLines Polar area: align start angle with angleLines Mar 2, 2019
? me.chart.options.startAngle
: 0;

var startAngleRadians = (me.chart.config.type === 'polarArea')
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This works, but it'd be nicer if the scale didn't have to know about the chart type. What if we instead introduce an option for degrees vs radians? Then the scale doesn't need to know which chart is being used and users can specify which ever they prefer

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Trying to fix a bug here, I'd rather not introduce a new option to work around it.
If this was fixed using a new option, then would have to specify conflicting defaults to chart types. IMO that would be a new confusing public API to keep backward compatible.

@benmccann
Copy link
Contributor

I just remembered this PR. It might be a good idea to standardize on degrees vs radians now that we're working on 3.0, so I'll reopen this one. @kurkle you can close it again if it's not something you want to eventually pursue

@kurkle
Copy link
Member Author

kurkle commented Dec 22, 2019

Rebased

etimberg
etimberg previously approved these changes Dec 22, 2019
@benmccann
Copy link
Contributor

The polar area behavior is changed? It's now in degrees with 0 at the top, which wasn't the case before? If that's right, then it'd be good to add something to migration guide about that

var angle = (index * angleMultiplier + startAngle) % 360;

return (angle < 0 ? angle + 360 : angle) * Math.PI * 2 / 360;
return _normalizeAngle(index * angleMultiplier + toRadians(startAngle));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's a bit surprising to me that this is returning radians now that all the options are specified in degrees. Should we just standardize on degrees everywhere?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

CanvasRenderingContext2d is going to need radians as input, so need to convert at some point.
IMO its clear that options are degrees, while everything internal (API included) should be radians.

There are only couple of things that contribute to that opinion:

  • developers are usually familiar with radians
  • people in general (users) are more likely familiar with degrees.
  • most functions require radians as input

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok. That makes sense. Should we convert determineLimits to use radians and remove the toDegrees function in that case?

@benmccann
Copy link
Contributor

@kurkle this one will need to be rebased

@kurkle
Copy link
Member Author

kurkle commented Jan 8, 2020

Ok, this is going nowhere.

@kurkle kurkle closed this Jan 8, 2020
@benmccann
Copy link
Contributor

I'd rather merge as is than let perfect be the enemy of good

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

Successfully merging this pull request may close these issues.

[BUG] polarArea angleLines don't align with data borders
6 participants