SciChart® the market leader in Fast WPF Charts, WPF 3D Charts, iOS Chart, Android Chart and JavaScript Chart Components

Answered
0
0

This is what I want it to look like: (see 1.jpg)

This is what (see 2.jpg) it does look like if I leave setIsLabelCullingEnabled enabled (all labels are culled except if I zoom WAY in)
This is what (see 3.jpg) it does look like if I turn off setIsLabelCullingEnabled

I would expect #2 to look like #3 without either one of the 20/15% and either 1% or 1.25% culled, when culling is enabled.

First things the specific values/locations are precise, I need those lines and labels exactly where they are. So I had to create my own LogarithmicNumericTickProvider and feed it all the numbers; this worked great and the numbers are where they need to be — but apparently using our own LogarithmicNumericTickProvider totally breaks culling. Any ideas on how we can get culling to work with our own LogarithmicNumericTickProvider. Is their another way to do this without using our own LogarithmicNumericTickProvider.

Version
3
Images
  • You must to post comments
Best Answer
1
0

The more proper way to generate tick priorities would be place labels with highest priority on opposite ends of axis, find the closest tick to the middle of axis, set slightly lower priority for it, then divide axis into two halves. Then for each half of axis do the same ( find middle tick, set for it lower priority, than on edges of axis segment, divide again ) until you run of labels to set priority for. Please take a look on attached screenshot – I tried to explain algorithm on your screenshot.

Best regards,
Yura

Images
  • Nathanael Anderson
    Thanks, with this information I was able to make a custom provider that eliminated only the rows that needed to be eliminated based on importance and known location. And using the code to track zoom in out ranges; I was about to clip the ranging code to have it cull the labels outside the viewport that should have been auto-culled. So I am very happy with the solution based on these answers. Thank you for your time. I would recommend that a new feature be added where it culls just the labels outside of view port; because honestly printing all labels except those outside of viewport would be a very acceptable solution for a lot of people, and in my case my client might have preferred that solution over having some of the labels culled despite them having room to print w/o them overlapping. (I assume the internal calculation for detecting collisions, must have some padding, because all labels looks good, except for those that overwrite each other that are out of view port…
  • Andrew Burnett-Thompson
    > Thanks, with this information I was able to make a custom provider that eliminated only the rows that needed to be eliminated based on importance and known location < Nice!!
  • You must to post comments
0
0

Hi Nathanael,

Well if you created custom TickProvider then it’s possible that culling won’t work as it should, because by default it designed for ticks which are evenly spaced ( with same distance on screen between ticks ). In your case you need to update calculation for culling priorities by overriding updateCullingPriorities(), where for each major tick you should set a number with priority of tick. The higher the value you set – the more chances that tick won’t be hidden, but you should be aware that ticks with same priority are combined into groups, so if two tick labels will overlap ( for example with priority 1 and 3), then axis will hide all ticks with lower priority value ( in our case all labels with priority 1 ).

In your case I don’t see a pattern which would allow to combine ticks into groups and sort them by priorities so maybe you should set priorities to -1 which disables culling priorities for those labels. This will provide next behavior – if there will be overlap with already placed label, new label won’t be placed ( just this one label ):

 protected void updateCullingPriorities(IntegerValues cullingPriorities, DoubleValues majorTicks) {
    final int size = majorTicks.size();

    cullingPriorities.setSize(size);
    final int[] itemsArray = cullingPriorities.getItemsArray();
    Arrays.fill(itemsArray, 0, size, -1); // default behavior - no culling priorities,
}

Hope this will help you!

Best regards,
Yura

  • Nathanael Anderson
    Ok, now that I have this code working under API 21; is their a way (or a magic priority) to force a label to print — I attempted to set everything to -1 and I get the default behavior (as you specified) then I attempted to set everything except the two overlapping labels to 2000, and then it randomly decides which 2 or so labels will be seen.
  • You must to post comments
0
0

Hi Yura,

This seems like a good direction to proceed. However, it appears with the latest 3.x version of SCICharts on Android that the updateCullingPriorities is not called. I have overridden it; but no logs are output from my log statement inside it…

Unless that wasn’t the proper prototype: protected void updateCullingPriorities(IntegerValues cullingPriorities, DoubleValues majorTicks)

Thanks,

Nathanael A.

  • Yura Khariton
    Can you provide a code sample which allows to reproduce this issue ( code of custom TickProvider and how you use it with axis )? I just tried to extend LogarithmicNumericTickProvider and override this method and overload was called as expected.
  • You must to post comments
0
0

Ok, that is really strange — this code is in JavaScript ( NativeScript app). đŸ™‚

However, the statements should be easily readable as to what Java it is calling.
1. .extend basically creates a java inherited override of the class
2. this.builder is an already created builder object.

const CustomNumericTickProvider = com.scichart.charting.numerics.tickProviders.LogarithmicNumericTickProvider.extend( {
_ticks: [0.01, 0.02, 0.05, 0.10, 0.15, 0.50, 1.00, 1.25, 2.00, 5.00, 7.00, 10.00, 15.00, 20.00],
updateTicks: function(minorTicks, majorTicks) {
console.log("Update Ticks");
majorTicks.clear();
for (let i=0;i<this._ticks.length;i++) {
majorTicks.add(this._ticks[i]);
}
},
updateCullingPriorities: function(cullingPriorities, majorTicks) {
console.log("Update Culling");
const size = majorTicks.size();
// Additional culling code...
}
});

And the init code for the yAxis
const yAxis = this.builder.newLogarithmicNumericAxis()
.withVisibleRange(0.01, 20.0)
.withGrowBy(0.01, 0.10)
.withTextFormatting("0.00'%'")
.withScientificNotation(com.scichart.charting.visuals.axes.ScientificNotation.None)
.withDrawMajorBands(false)
.withLogarithmicBase(10)
.build();
yAxis.setDrawMinorGridLines(false);
yAxis.setTickProvider(new CustomNumericTickProvider());
yAxis.setAutoFitMarginalLabels(true);
yAxis.setDrawLabels(true);

I’m going to try eliminating some of the yAxis init code and see if it makes a difference, maybe one of those setting is messing up culling… But right now the updateCullingPriorities is not being called. I’ll do some more tests… But you are sure on your end it is being called, correct?

  • Nathanael Anderson
    Appears this might be an API versioning issue; when I switched the Minimum API to 21; updateCulling is now being called. API 19; seems to be throwing a error exactly like this issue –https://stackoverflow.com/questions/53161063/viewcompatonunhandledkeyeventlistener-on-setcontentview … I’m going to be playing with it now… Is their a minimum API level that SciCharts supports on AndroidX support?
  • Nathanael Anderson
    Nope, this appears to be an issue completely on my side — something was causing the binding generator to not run; so it never created the bindings — when I switched the API versions, I also nuked all the temporary files; which caused the binding generator to run and create the proper binding.. So it not running was 100% on my side…
  • Yura Khariton
    I’m glad that you managed to find cause of this issue and fix it. Regarding min API level for Android – currently it’s 19
  • You must to post comments
0
0

Ok, so now that I have this code working; is their a way (or a magic priority) to force a label to print — I attempted to set everything to -1 and I get the default behavior (as you specified) then I attempted to set everything except the two overlapping labels to 2000, and then it randomly decides which 1 or 2 labels will be seen.

Any way to make the culling not cull labels; or is the internal code just not setup to allow this…

  • Yura Khariton
    This is how it works for now – we have IsLabelCullingEnabled property which completely disables culling of labels if you set it to false. If it’s set to true then axis uses culling priorities provided by TickProvider to determine how labels should be rendered in case of overlap. At first it tries to render label/labels with the highest priority. If there are several labels with same priority and they overlap with each other then all labels with this priority and lower won’t be rendered by axis. If you want to specify which of two labels should be hidden first, then just set for this label slightly lower priority then for other. For example labels on screenshot which you provided you can set priorities [2, 4, 3, 1, 5, 1, 3, 4, 2, 1, 3, 2, 4] for labels from top to bottom. In this case label with 5 will always remain on screen, because it has the highest priority and there is only one label, so it can’t overlap with other labels with same priority. Then axis will try to place labels with priority = 4, so we need to spread those labels to prevent overlapping with each other and with label which already placed and has priority = 5, because if there will be overlap, then these labels and other remaining labels with lower priority ( 3, 2, 1 ) won’t be rendered by axis. Then axis will try to render labels with priority 3 with checks if they overlap with each other or with labels which already rendered ( with priority 4 and 5 ) and after that it will repeat the process for priority 2 and 1. Hope this will help you!
  • You must to post comments
0
0

Well, I attempted to do 20,19,18.17,16,15…1 (and 1,2,3…20) and it still only rendered two of them when in landscape mode. The weird thing is it only rendered the two at the top of the screen. The entire rest of the labels are hidden. So obviously it seems to be pretty broken in this situation… See image1.png — the code was simple; basically: for (i=1;i less than length) array.push(i);


Since culling seems to not work properly; is their any way that we can turn off culling BUT have the labels off screen not show. If I disable culling; then when I zoom in; the labels on top and bottom just stack on each other and look horrible; I would much rather have them disappear (like in culling mode) so that only the labels on screen are with any lines on screen. (see image2)

Images
  • Yura Khariton
    Well this is expected behavior. As I already said in previous reply where I explained how culling works – if there are intersection of labels, then we take priorities of both labels and pick up the one with lower priority. Then we hide all labels with this priority and lower. We hide labels with lower priority, because we assume that if there is no free space to place label with high priority, then there is no need to check other labels with lower priority and we don’t check the rest of labels. In your case when you set priorities one by one from top to bottom you will see labels till first intersection. On your screenshot there is only 2 labels, which means that 3rd label intersected with 2nd labels with “10.00 %” value. According to your logic for setting priorities ( 20 for 1st label, 19 for 2nd and so on ) when there was intersection with 3rd label which has priority 18 this triggered hiding of the rest of the labels with priority 18 and below. That’s why you get such output.
  • Yura Khariton
    Regarding question about turning off culling – well we have only IsLabelCullingEnabled property for this. If approach with culling priorities isn’t suitable for your needs, then you can disable it and try to generate major ticks in a such way that they won’t intersect. To replace using of culling priorities on something else would require rewriting axis renderer which uses these priorities to render labels.
  • Nathanael Anderson
    I think I understand what is going on; thanks for the clear answers. I’ll play with the code to see if I can come up with a better culling numbers to eliminate the issue of vanished labels in landscape. :) Your last comment I’m not sure we are communicating properly. Basically I was wondering if their was a “label culling = offscreen” function with labels off screen are culled, but the rest of the labels always printed. Because zooming in causes all the labels to overprint each other even though they shouldn’t be even on the screen as they are no longer in the view area. (See image #2 above)
  • You must to post comments
Showing 6 results
Your Answer

Please first to submit.