ASE Home Page Products Download Purchase Support About ASE
ChartDirector Support
Forum HomeForum Home   SearchSearch

Message ListMessage List     Post MessagePost Message

  Error in barLayer xAxis-layout
Posted by Michael on Oct-20-2012 17:54
Attachments:
Hi,

I am currently evaluating ChartDirector 5.1.

It seems that the barLayer xAxis layout is not working correctly whereas the same works
perfectly when using an area layer.

Attached you will find the gapBar.cs sample slightly modified to show the problem, here
are some extracted lines:

   XYChart c = new XYChart(1280, 150);
   c.setPlotArea(0, 20, 1280, 100);
   var axis = c.xAxis();

   // BUG reproducable in case of timeranges < 10 s
   axis.setDateScale(DateTime.Now, DateTime.Now.AddSeconds(5));

   axis.setMultiFormat2(Chart.AllPassFilter(), "X"); //, Chart.AllPassFilter(), "{value}");
   c.layout();
///   c.addAreaLayer(data);                              // !!!! WORKS
   c.addBarLayer(data);                               // !!!! BUG

   // Output the chart
   viewer.Chart = c;

As you can see, the layout is correct if you use AreaLayers. Once you add the bar layer,
the layout is corrupt. However, I need to use the stack layer.

Is there a way to workaround the issue?

Thanks,
Michael
gapbar.cs
using System;
using ChartDirector;

namespace CSharpChartExplorer
{
    public class gapbar : DemoModule
    {
        //Name of demo module
        public string getName() { return "Bar Gap"; }

        //Number of charts produced in this demo module
        public int getNoOfCharts() { return 6; }

        //Main code for creating charts
        public void createChart(WinChartViewer viewer, string img)
        {
            double bargap = int.Parse(img) * 0.25 - 0.25;

            // The data for the bar chart
            double[] data = {100, 125, 245, 147, 67};

            // The labels for the bar chart
            string[] labels = new string[100];

            for (int i = 0; i < 100; i++)
            {
                labels[i] = i.ToString();
            }

            // Create a XYChart object of size 150 x 150 pixels
            XYChart c = new XYChart(1280, 150);

            // Set the plotarea at (27, 20) and of size 120 x 100 pixels
            c.setPlotArea(0, 20, 1280, 100);

            // Set the labels on the x axis
//            setupXAxis1(c);

            var axis = c.xAxis();
            axis.setDateScale(DateTime.Now, DateTime.Now.AddSeconds(5));            // BUG in case of timeranges < 10 s
            axis.setMultiFormat2(Chart.AllPassFilter(), "X"); //, Chart.AllPassFilter(), "{value}");
            c.layout();

            ////the ticks on the axis
            //Double[] ticks = axis.getTicks();
            //double lastValue = 0;
            //for (int i = 0; i < ticks.Length; ++i)
            //{
            //    string label = axis.getLabel(ticks[i]);
            //    if ((!string.IsNullOrEmpty(label)) && (label == "X"))   //require custom formatting?
            //    {
            //        double floorValue = Math.Floor(ticks[i]);
            //        double roundedValue = Math.Round(ticks[i], 3);
            //        double decimalPlace = roundedValue - floorValue;

            //        string hhnnss = c.formatValue(roundedValue - decimalPlace, "<*font=bold*>{value|hh:nn:ss}");

            //        string buffer;
            //        if (floorValue != lastValue)
            //        {
            //            if (decimalPlace > 0)
            //            {
            //                buffer = string.Format("{0}.<*font=normal*>{1:000}", hhnnss, decimalPlace * 1000);
            //            }
            //            else
            //            {
            //                buffer = string.Format("{0}", hhnnss);
            //            }
            //            lastValue = floorValue;
            //        }
            //        else
            //        {
            //            buffer = string.Format(".{1:000}", hhnnss, decimalPlace * 1000);
            //        }

            //        axis.addLabel(ticks[i], buffer);
            //    }
            //}




            if (bargap >= 0) {
                // Add a title to display to bar gap using 8 pts Arial font
                c.addTitle("      Bar Gap = " + bargap, "Arial", 8);
            } else {
                // Use negative value to mean TouchBar
                c.addTitle("      Bar Gap = TouchBar", "Arial", 8);
                bargap = Chart.TouchBar;
            }

            // Add a bar chart layer using the given data and set the bar gap
      //      c.addAreaLayer(data);                        // !!!! WORKS
            c.addBarLayer(data);                         // !!!! BUG

            // Output the chart
            viewer.Chart = c;

            //include tool tip for the chart
            viewer.ImageMap = c.getHTMLImageMap("clickable", "",
                "title='Production on {xLabel}: {value} kg'");
        }

        private void setupXAxis1(XYChart c)
        {
            var axis = c.xAxis();

            axis.setDateScale(DateTime.Now, DateTime.Now.AddSeconds(1));
            // In the current demo, the x-axis range can be from a few years to a few days. We can 
            // let ChartDirector auto-determine the date/time format. However, for more beautiful 
            // formatting, we set up several label formats to be applied at different conditions. 
            //

            // If all ticks are yearly aligned, then we use "yyyy" as the label format.
            axis.setFormatCondition("align", 360 * 86400);
            axis.setLabelFormat("{value|yyyy}");

            // If all ticks are monthly aligned, then we use "mmm yyyy" in bold font as the first 
            // label of a year, and "mmm" for other labels.
            axis.setFormatCondition("align", 30 * 86400);
            axis.setMultiFormat(Chart.StartOfYearFilter(), "<*font=bold*>{value|mmm yyyy}",
                Chart.AllPassFilter(), "{value|mmm}");

            // If all ticks are daily algined, then we use "mmm dd<*br*>yyyy" in bold font as the 
            // first label of a year, and "mmm dd" in bold font as the first label of a month, and
            // "dd" for other labels.
            axis.setFormatCondition("align", 86400);
            axis.setMultiFormat(
                Chart.StartOfYearFilter(), "<*block,halign=left*><*font=bold*>{value|mmm dd<*br*>yyyy}",
                Chart.StartOfMonthFilter(), "<*font=bold*>{value|mmm dd}");
            axis.setMultiFormat2(Chart.AllPassFilter(), "{value|dd}");

            // For all other cases (sub-daily ticks), use "hh:nn<*br*>mmm dd" for the first label of
            // a day, and "hh:nn" for other labels.
            axis.setFormatCondition("else");
            //      axis.setMultiFormat(Chart.StartOfDayFilter(), "<*font=bold*>{value|hh:nn:ss<*br*>mmm dd}",
            //          Chart.AllPassFilter(), "{value|hh:nn:ss}");

            axis.setMultiFormat2(Chart.AllPassFilter(), "X"); //, Chart.AllPassFilter(), "{value}");
            c.layout();

            //the ticks on the axis
            Double[] ticks = axis.getTicks();
            double lastValue = 0;
            for (int i = 0; i < ticks.Length; ++i)
            {
                string label = axis.getLabel(ticks[i]);
                if ((!string.IsNullOrEmpty(label)) && (label == "X"))   //require custom formatting?
                {
                    double floorValue = Math.Floor(ticks[i]);
                    double roundedValue = Math.Round(ticks[i], 3);
                    double decimalPlace = roundedValue - floorValue;

                    string hhnnss = c.formatValue(roundedValue - decimalPlace, "<*font=bold*>{value|hh:nn:ss}");

                    string buffer;
                    if (floorValue != lastValue)
                    {
                        if (decimalPlace > 0)
                        {
                            buffer = string.Format("{0}.<*font=normal*>{1:000}", hhnnss, decimalPlace * 1000);
                        }
                        else
                        {
                            buffer = string.Format("{0}", hhnnss);
                        }
                        lastValue = floorValue;
                    }
                    else
                    {
                        buffer = string.Format(".{1:000}", hhnnss, decimalPlace * 1000);
                    }

                    axis.addLabel(ticks[i], buffer);
                }
            }
        }
    }
}


  Re: Error in barLayer xAxis-layout
Posted by Peter Kwan on Oct-23-2012 02:23
Attachments:
Hi Michael,

For the x-axis layout, are you referring to the "axis indentation" (that the first and last labels are not at the end points of the x-axis)? This is normal for a bar chart.

I see that in your code, you do not actually have a visible bar layer. I have just added a visible bar layer in the chart so demonstrate why ChartDirector will automatically "indent" the axis (see the attached chart). If ChartDirector does not indent the axis and the first label is at the left edge of the plot area, then half of the first bar will overflow outside the plot area. It is because a bar has a bar width. So if you plot a bar at x = aaa, you need to reserve some additional space to the left and right of aaa for the bar width. In ChartDirector, the space reserved is 0.5 x-unit, which is suitable for a label based x-axis.

See also:

http://www.chartdir.com/forum/download_thread.php?bn=chartdir_support&thread=1215399849#N1215450996

If you do not want the axis indentation, you may disable it using Axis.setIndent. Note that in this case, there is a bar at the first or last x-position, half of the bar may overflow outside the plotarea. To avoid this, you may extend your x-axis scale a little bit to reserve for some space, or use Axis.setMargin to reserve for some space.

Hope this can help.

Regards
Peter Kwan
test.png

  Re: Error in barLayer xAxis-layout
Posted by Michael on Oct-23-2012 02:38
Excellent support, Peter!  setIndent(false) is exactly what I needed.
Thank you!