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

Message ListMessage List     Post MessagePost Message

  Blocks in gantt diagram
Posted by Thomas on Dec-04-2014 15:11
Attachments:
Hi together,

I use a gantt Chart in an application and so far so good everything works fine when all the blocks are on different steps (see Picture 1).
If I have more than one block in the same Level (Picture 2), the block become smaller and smaller. Has anyone an idea whats the reason for that behavior?

Thanks Thomas
Pic1.jpg
Pic2.jpg

  Re: Blocks in gantt diagram
Posted by Peter Kwan on Dec-04-2014 23:08
Hi Thomas,

By default, ChartDirector will flow the bars from top to bottom (or bottom to top). It
calculates the full width of the bar as (centerOfBottomBar - centerOfTopBar) / (barCount
- 1)  (of course there would be additional code to avoid division by zero error, which is
omitted here). This would result in the width in your Picture 1.

However, ChartDirector actually allows the bars to be at arbitrary positions, even non-
integral positions (which would be somewhere in between two labels) by specifying the
positions with setXData. Suppose the bars are at x = 0, 2, 4.7836, 4.455, 8.123. In this
case, the bar would be ambiguous. Nevertheless, ChartDirector would still use the same
formula (centerOfBottomBar - centerOfTopBar) / (barCount - 1) to estimate a width.
According to this estimation, the bar width can be narrow if there are many bars crowded
in a narrow strip. On the other hand, if there are a few bars over a wide range (such as
three bars at x = 0, 4, 8), the bars may be wide.

For gantt charts, the intention is usually to configure the bar width based on the number
of events (labels on the vertical axis), regardless of the number of bars and how they are
distributed. That's why in the "Multi-Color Gantt Chart" sample code (which also has
multiple bars in the same block), there is a line of code that uses setDataWidth to tell
ChartDirector to proper bar width to use. In PHP, it is:

$layer->setDataWidth((int)(200 * 4 / 5 / count($labels)));

In Java, it is:

layer.setDataWidth((int)(200 * 4 / 5 / (labels.length)));

The above code configures the bar width to be 80% of the block width, leaving 20% as
the spacing among bars. You can use other ratio as well.

Hope this can help.

Regards
Peter Kwan

  Re: Blocks in gantt diagram
Posted by Thomas on Dec-05-2014 01:04
Thanks Peter it works perfect, Thomas

  Re: Blocks in gantt diagram
Posted by Babak on Sep-21-2016 16:48
Attachments:
hI I WOULD LIKE DRAW ARROWS LIKE YOU COULD YOU PLEASE SEND ME your codes ?
gantt.png

  Re: Blocks in gantt diagram
Posted by Thomas on Sep-21-2016 17:09
Attachments:
I can send you my code but the problem is, we integrate the ChartDirector into SAP.
This software has his own programming language called ABAP. We build VB code and send this code to the chart engine, so the code looks a bit strange, sorry

Here is an example of this code to bild the chart in the attachment:

Set cd = CreateObject("ChartDirector.API")
labels = Array("(1) Request","(2) Sales Input","(3) Finance Input","(4) Portfolio Manager Decision","(5) Create Specification","(6) Approval AWT","(7) Approval Production","(8) Issue Specification and first SKU","(9) Calculation Plant Finance","(10) Check Tarif Code","(11) Check and close")
stepNo = Array(0,1,2,0,1,2,3,4,5)
maxNo = 00009
arr0 = Array("25.03.2015 14:14","25.03.2015 14:22","25.03.2015 14:23","25.03.2015 14:24","25.03.2015 14:26","25.03.2015 14:26","25.03.2015 14:27","25.03.2015 14:28","25.03.2015 14:28")
arr1 = Array("25.03.2015 14:22","25.03.2015 14:23","25.03.2015 14:24","25.03.2015 14:26","25.03.2015 14:26 (Skipped)","25.03.2015 14:27","25.03.2015 14:28","25.03.2015 14:28 (Skipped)","25.03.2015 14:29")
startNo = Array(0,1,2,3,4,5,6,7,8)
endNo = Array(1,2,3,4,5,6,7,8,9)
colors = Array( _
&H00cc00, _
&H00cc00, _
&H00cc00, _
&H00cc00, _
&Hffff00, _
&H00cc00, _
&H00cc00, _
&Hffff00, _
&H888888)
Set c = cd.XYChart(1566, 220, &Hf4f3ee, &H000000, 1)
Call c.setPlotArea(160, 1, 1566-160, 220-2, &Hffffff, -1, _
cd.LineColor, &Hc0c0c0, &Hc0c0c0).setGridWidth(1, 1, 1, 1)
Call c.swapXY()
Call c.setYAxisOnRight()
Set xaxis = c.xAxis()
Call xaxis.setLabelStyle("tahoma.ttf", 8)
Call xaxis.setLabels(labels)
Call xaxis.setReverse()
Call xaxis.setTickOffset(0.5)
Call xaxis.addZone(00000.5, 00000.5 + 1, &Heeeeee)
Call xaxis.addZone(00002.5, 00002.5 + 1, &Heeeeee)
Call xaxis.addZone(00004.5, 00004.5 + 1, &Heeeeee)
Call xaxis.addZone(00006.5, 00006.5 + 1, &Heeeeee)
Call xaxis.addZone(00008.5, 00008.5 + 1, &Heeeeee)
Call xaxis.addZone(00010.5, 00010.5 + 1, &Heeeeee)
Set yaxis = c.yAxis()
Call yaxis.setMinTickInc(1)
Call yaxis.setLinearScale(0, maxNo)
Set layer = c.addBoxWhiskerLayer(startNo, endNo, Empty, Empty, Empty, &H00cc00, cd.SameAsMainColor, &H000000)
Call layer.setXData(stepNo)
Call c.addExtraField(arr0)
Call c.addExtraField(arr1)
Call layer.setDataGap(0)
Call layer.setBorderColor(cd.Transparent, cd.glassEffect(cd.ReducedGlare, cd.Center))
Call layer.setBoxColors(colors)
Call layer.setDataWidth((220 - 2) /00011)
Call c.layout()
For i=0 To UBound(startNo) - 1
For j=i+1 To UBound(startNo)
If colors(j) <> &Hffff00 Then
x1 = c.GetYCoor(startNo(i))+(c.GetYCoor(startNo(i+1))-c.GetYCoor(startNo(i))) / 2
offset = Abs(c.GetXCoor(stepNo(i+1))-c.GetXCoor(stepNo(i))) / 2.5
y1 = c.GetXCoor(stepNo(i))
y2 = c.GetXCoor(stepNo(j))
Call c.addLine(x1, y1, x1, y2, &H0000ff, 2)
x2 = c.GetYCoor(startNo(j))
Call c.addLine(x1, y2, x2, y2, &H0000ff, 2)
Call c.addLine(x2-1, y2-2, x2-8, y2-5, &H0000ff, 2)
Call c.addLine(x2-1, y2, x2-8, y2+3, &H0000ff, 2)
i = j - 1
Exit For
End If
Next
Next
Set cd = Nothing
Set Viewer.Picture = c.makePicture()
viewer.ImageMap = layer.getHTMLImageMap("clickable?ID={dataItem}", "", "title='{xLabel} {field0} - {field1}'")
Chart.jpg
Chart.jpg

42.93 Kb

  Re: Blocks in gantt diagram
Posted by Babak on Sep-21-2016 17:14
thank of your answer i need it in c++ could you help me in it

  Re: Blocks in gantt diagram
Posted by Babak on Sep-21-2016 17:46
if you saw i can draw and make connection between blocks but problem is the green line starting y coordinate is wrong and is not from related data could you please help me  how can i start from true position .

int main(int argc, char *argv[])
{
    // data for the gantt chart, representing the start date, end date and names for various
    // activities
    double startDate[] = {Chart::chartTime2(16), Chart::chartTime2(30),
        Chart::chartTime2(13), Chart::chartTime2(20), Chart::chartTime2(27),
        Chart::chartTime2(4), Chart::chartTime2(25), Chart::chartTime2(1
        ), Chart::chartTime2(15), Chart::chartTime2(18), Chart::chartTime2(12), Chart::chartTime2(28)};
    double endDate[] ={Chart::chartTime2(19), Chart::chartTime2(35),
        Chart::chartTime2(23), Chart::chartTime2(25), Chart::chartTime2(32),
        Chart::chartTime2(9), Chart::chartTime2(33), Chart::chartTime2(6
        ), Chart::chartTime2(22), Chart::chartTime2(23), Chart::chartTime2(16), Chart::chartTime2(34)};
    const char *labels[] = {"Job1", "Job2", "m1",
        "M2", "Job3", "m3", "Job4", "M4",
        "Job5","M5","Job6","M6"};

  // Relation tasks for connection line draw

double startDate1[] = {Chart::chartTime2(16), Chart::chartTime2(30),
        Chart::chartTime2(13), Chart::chartTime2(20), Chart::chartTime2(27),
        Chart::chartTime2(4), Chart::chartTime2(25), Chart::chartTime2(1
        )};
    double endDate1[] ={Chart::chartTime2(19), Chart::chartTime2(35),
        Chart::chartTime2(23), Chart::chartTime2(25), Chart::chartTime2(32),
        Chart::chartTime2(9), Chart::chartTime2(33), Chart::chartTime2(6
        ), Chart::chartTime2(22)};

double startDate2[] = {Chart::chartTime2(15), Chart::chartTime2(18), Chart::chartTime2(12), Chart::chartTime2(28)};
double endDate2[] ={Chart::chartTime2(22), Chart::chartTime2(23), Chart::chartTime2(16), Chart::chartTime2(34)};



// Create a XYChart object of size 620 x 280 pixels. Set background color to light blue
    // (ccccff), with 1 pixel 3D border effect.
    XYChart *c = new XYChart(1100, 800, 0xccccff, 0x000000, 1);
    c->setRoundedFrame();

    // Add a title to the chart using 15 points Times Bold Itatic font, with white (ffffff) text on
    // a deep blue (000080) background
    c->addTitle("Scheduling Time System", "timesbi.ttf", 15, 0xffffff)->setBackground(0x000080);

    // Set the plotarea at (140, 55) and of size 460 x 200 pixels. Use alternative white/grey
    // background. Enable both horizontal and vertical grids by setting their colors to grey
    // (c0c0c0). Set vertical major grid (represents month boundaries) 2 pixels in width
    c->setPlotArea(40, 55, 1000, 600, 0xffffff, 0xeeeeee, Chart::Transparent, 0xc0c0c0, 0xc0c0c0
        )->setGridWidth(2, 1, 1, 1);

    // swap the x and y axes to create a horziontal box-whisker chart
    c->swapXY();

    // Set the y-axis scale to be date scale from minimum to maxmim
    // days (1 week)
    c->yAxis()->setDateScale(Chart::chartTime2(1), Chart::chartTime2(40),0);

    // Set multi-style axis label formatting. Month labels are in Arial Bold font in "mmm d" format.
    // Weekly labels just show the day of month and use minor tick (by using '-' as first character
    // of format string).
    c->yAxis()->setMultiFormat(Chart::StartOfSecondFilter(), "<*font=arialbd.ttf*>{value|s}",
        Chart::StartOfSecondFilter(),"{value|s}");

    // Set the y-axis to shown on the top (right + swapXY = top)
    c->setYAxisOnRight();

    // Set the labels on the x axis
    c->xAxis()->setLabels(StringArray(labels, (int)(sizeof(labels) / sizeof(labels[0]))));

    // Reverse the x-axis scale so that it points downwards.
    c->xAxis()->setReverse();

    // Set the horizontal ticks and grid lines to be between the bars
    c->xAxis()->setTickOffset(0.5);

    // Add a green (33ff33) box-whisker layer showing the box only.
    c->addBoxWhiskerLayer(DoubleArray(startDate, (int)(sizeof(startDate) / sizeof(startDate[0]))),
        DoubleArray(endDate, (int)(sizeof(endDate) / sizeof(endDate[0]))), DoubleArray(),
        DoubleArray(), DoubleArray(), 0x00cc00, Chart::SameAsMainColor, Chart::SameAsMainColor);

///*******************************

// Add a line layer to the chart
    LineLayer *layer = c->addLineLayer();

    // Set the line width to 3 pixels
    layer->setLineWidth(3);

    //Add the three data sets to the line layer, using circles, diamands and X shapes as symbols
    layer->addDataSet(DoubleArray( startDate1, (int)(sizeof( startDate1) / sizeof( startDate1[0]))), 0xff0000,
        "Set1")->setDataSymbol(Chart::CircleSymbol, 6);

/*** this have to start from true Y cordination *///
LineLayer *layer1 = c->addLineLayer();
layer1->addDataSet(DoubleArray( startDate2, (int)(sizeof( startDate2) / sizeof( startDate2[0]))), 0x33ff33,
    "Set2")->setDataSymbol(Chart::DiamondSymbol, 18);








//******************************
    // Output the chart
    c->makeChart("gantt.jpg");

    //free up resources
    delete c;
    return 0;
}

  Re: Blocks in gantt diagram
Posted by Peter Kwan on Sep-21-2016 19:14
Hi Babak,

I have tried your exact code, and the "green line" coordinates are correct. According to your code, the "y-coordinates" of the green line should be the startDate2, which is {15, 18, 12, 28}, and in the chart I created, the "y-coordinates" are in fact at {15, 18, 12, 28}.

Actually, I am not too sure what you mean by y-coordinates. For the gantt chart, the "swapXY" is in effect, which means the y-data values are using the horizontal axis. The vertical coordinates are the x-coordinate and is controlled using Layer.setXData. The x-data coordinates of the bars are just 0, 1, 2, 3, ..... counting from top to bottom.

For the arrows, Babak's code is to draw the arrows using 4 lines. Translated to C++, the essential code is like:

// Draw a L shape right pointing error from (x1, y1) to (x2, y2)
void drawArrow(XYChart *c, double x1, double y1, double x2, double y2)
{
        // dual to swapXY, the x-pixel coordinates refers to the y-data coordinates,
        // and the y-pixel coordinates refers to the x-data coordinates,
int pX1 = c->getYCoor(y1);
int pX2 = c->getYCoor(y2);
int pY1 = c->getXCoor(x1);
int pY2 = c->getXCoor(x2);

c->addLine(pX1, pY1, pX1, pY2, 0x0000ff, 2);
c->addLine(pX1, pY2, pX2, pY2, 0x0000ff, 2);
c->addLine(pX2 - 1, pY2 - 2, pX2 - 8, pY2 - 5, 0x0000ff, 2);
c->addLine(pX2 - 1, pY2, pX2 - 8, pY2 + 3, 0x0000ff, 2);
}

To use the above code, you have to call XYChart.layoutAxes first. So the code is like:

.... draw gantt chart as usual .....

// layoutAxes so we can use getXCoor and getYCoor
c->layoutAxes();

// Draw right pointing arrows joining the middle point of the previous bar to
// the starting point of the current bar
for (int i = 1; i < barCount; ++i)
   drawArrow(c, i - 1, (startDate[i - 1] + endDate[i - 1]) / 2, i, startDate[i]);


Note that the above code may not be what you expect for your data, because it is drawing a right pointing arrow. (Dependencies usually is left to right in a gantt chart, because the future depends on the past, not the reverse.) For your data, the ordering is rather random, so it is not sure exactly how you would like to join the bars.

Regards
Peter Kwan

  Re: Blocks in gantt diagram
Posted by Babak on Sep-21-2016 19:35
Dear Peter
Thank of your answer .
Satartdate2 and enddate2 are a group that related to each other , it means that the green line  Y position have to start from Job 5 Position not Job 1 .
It means that i need to force  this code that start Y position of Job 5
layer1->addDataSet(DoubleArray( startDate2, (int)(sizeof( startDate2) / sizeof( startDate2[0]))), 0x33ff33,
    "Set2")->setDataSymbol(Chart::DiamondSymbol, 18);

Regardss

  Re: Blocks in gantt diagram
Posted by Peter Kwan on Sep-22-2016 00:48
Hi Babak,

As explained in my last email, the vertical position is the x-data coordinate, and is set using setData. If you need the data point to be at "Job 5", which is the 9th bar, please use the x-coordinate x = 8. So for your 4 points, it should be:

double xCoor[] = {8, 9, 10, 11}
layer1->setXData(DoubleArray(xCoor, 4));

Regards
Peter Kwan

  Re: Blocks in gantt diagram
Posted by Babak on Sep-21-2016 19:49
Attachments:
I used your code but when i what to draw 2 group you can see results

   for (int i = 1; i < 8; ++i)
   drawArrow(c, i - 1, (startDate[i - 1] + endDate[i - 1]) / 2, i, startDate[i]);

   for (int i = 1; i < 8; ++i)
   drawArrow2(c, i - 1, (startDate2[i - 1] + endDate2[i - 1]) / 2, i, startDate2[i]);
gantt.png

  Re: Blocks in gantt diagram
Posted by Peter Kwan on Sep-22-2016 00:54
Hi Babak,

The code is based on the original code used in this forum. You cannot just copy the code and use it on arbitrary data and expect it to work. You would need to modify it to fit your own needs.

As explained in my last message, the code is for drawing a right pointing arrow from the mid-point of a bar to the starting date of the next bar. Is this what you need? If this is not what you what, please modify the code to achieve what you need.

For example, if you want some arrows to point to the left, please modify the code so that the arrows can point to the left. If you want some arrows to point to the end date of the next bar (rather than the start date), please modify the code so that those arrows point to the end date.

According to your attached chart, the original code in fact works normally. The arrows point to the right and is from the mid-point of one bar to the starting data of the next bar. It is just may be this is not what you want, in which case please modify the code to achieve what you want.

Also, the code assumes the x-coordinate is the array index i. If you want using another array xCoor as the x-coordinates, please use those x-coordinates instead of the array index.

In summary, please make sure you understand the code and adapt it for your own needs.

Regards
Peter Kwan

  Re: Blocks in gantt diagram
Posted by Babak on Sep-22-2016 17:01
Attachments:
Dear Peter
Thank for your guides .
the results now attached .
But now my question is :
1- for each line we need a new layer ? .
2-how is your solution that id we want connecting end of each box to start next box for example green line start from end job5 to start m5 and end of m5 to start job6 and etc .
3-


int main(int argc, char *argv[])
{
    // data for the gantt chart, representing the start date, end date and names for various
    // activities
    double startDate[] = {Chart::chartTime2(1), Chart::chartTime2(7),
        Chart::chartTime2(13), Chart::chartTime2(20), Chart::chartTime2(27),
        Chart::chartTime2(4), Chart::chartTime2(25), Chart::chartTime2(1
        ), Chart::chartTime2(15), Chart::chartTime2(18), Chart::chartTime2(12), Chart::chartTime2(28)};
    double endDate[] ={Chart::chartTime2(8), Chart::chartTime2(13),
        Chart::chartTime2(23), Chart::chartTime2(25), Chart::chartTime2(32),
        Chart::chartTime2(9), Chart::chartTime2(33), Chart::chartTime2(6
        ), Chart::chartTime2(22), Chart::chartTime2(23), Chart::chartTime2(16), Chart::chartTime2(34)};
    const char *labels[] = {"Job1", "Job2", "m1",
        "M2", "Job3", "m3", "Job4", "M4",
        "Job5","M5","Job6","M6"};

    // Related tasks

double startDate1[] = {Chart::chartTime2(1), Chart::chartTime2(7),
        Chart::chartTime2(13), Chart::chartTime2(20), Chart::chartTime2(27),
        Chart::chartTime2(4), Chart::chartTime2(25), Chart::chartTime2(1
        )};
double endDate1[] ={Chart::chartTime2(8), Chart::chartTime2(13),
        Chart::chartTime2(23), Chart::chartTime2(25), Chart::chartTime2(32),
        Chart::chartTime2(9), Chart::chartTime2(33), Chart::chartTime2(6
        ), Chart::chartTime2(22)};

double startDate2[] = {Chart::chartTime2(15), Chart::chartTime2(18), Chart::chartTime2(12), Chart::chartTime2(28)};
double endDate2[] ={Chart::chartTime2(22), Chart::chartTime2(23), Chart::chartTime2(16), Chart::chartTime2(34)};
double startDate3[] = {Chart::chartTime2(1), Chart::chartTime2(13), Chart::chartTime2(25), Chart::chartTime2(15)};


// Create a XYChart object of size 620 x 280 pixels. Set background color to light blue
    // (ccccff), with 1 pixel 3D border effect.
    XYChart *c = new XYChart(1100, 800, 0xccccff, 0x000000, 1);

    c->setRoundedFrame();


    // Add a title to the chart using 15 points Times Bold Itatic font, with white (ffffff) text on
    // a deep blue (000080) background
    c->addTitle("Scheduling Time System", "timesbi.ttf", 15, 0xffffff)->setBackground(0x000080);

    // Set the plotarea at (140, 55) and of size 460 x 200 pixels. Use alternative white/grey
    // background. Enable both horizontal and vertical grids by setting their colors to grey
    // (c0c0c0). Set vertical major grid (represents month boundaries) 2 pixels in width
    c->setPlotArea(40, 55, 1000, 600, 0xffffff, 0xeeeeee, Chart::Transparent, 0xc0c0c0, 0xc0c0c0
        )->setGridWidth(2, 1, 1, 1);


    // swap the x and y axes to create a horziontal box-whisker chart
    c->swapXY();

    // Set the y-axis scale to be date scale from minimum to maxmim
    // days (1 week)
    c->yAxis()->setDateScale(Chart::chartTime2(1), Chart::chartTime2(40),0);

    // Set multi-style axis label formatting. Month labels are in Arial Bold font in "mmm d" format.
    // Weekly labels just show the day of month and use minor tick (by using '-' as first character
    // of format string).
    c->yAxis()->setMultiFormat(Chart::StartOfSecondFilter(), "<*font=arialbd.ttf*>{value|s}",
        Chart::StartOfSecondFilter(),"{value|s}");

    // Set the y-axis to shown on the top (right + swapXY = top)
    c->setYAxisOnRight();

    // Set the labels on the x axis
    c->xAxis()->setLabels(StringArray(labels, (int)(sizeof(labels) / sizeof(labels[0]))));

    // Reverse the x-axis scale so that it points downwards.
    c->xAxis()->setReverse();

    // Set the horizontal ticks and grid lines to be between the bars
    c->xAxis()->setTickOffset(0.5);

    // Add a green (33ff33) box-whisker layer showing the box only.
    c->addBoxWhiskerLayer(DoubleArray(startDate, (int)(sizeof(startDate) / sizeof(startDate[0]))),
        DoubleArray(endDate, (int)(sizeof(endDate) / sizeof(endDate[0]))), DoubleArray(),
        DoubleArray(), DoubleArray(), 0x00cc00, Chart::SameAsMainColor, Chart::SameAsMainColor);


//*******************************

// Add a line layer to the chart
    LineLayer *layer0 = c->addLineLayer();
    LineLayer *layer1 = c->addLineLayer();
    LineLayer *layer2 = c->addLineLayer();

    // Set the line width to 3 pixels
    layer0->setLineWidth(3);
    layer1->setLineWidth(3);
    layer2->setLineWidth(3);

//Add the 2 data sets to the line layer, using circles, diamands and X shapes as symbols
   layer0->addDataSet(DoubleArray( startDate1, (int)(sizeof( startDate1) / sizeof( startDate1[0]))), 0xff0000,
     "Set1")->setDataSymbol(Chart::CircleSymbol, 18);

double xCoor[] = {8,9,10,11};//related tasks
layer1->setXData(DoubleArray(xCoor, 4));//Number of tasks fore new layer connection

layer1->addDataSet(DoubleArray(startDate2, (int)(sizeof( startDate2) / sizeof( startDate2[0]))), 0x33ff33,
    "Set2")->setDataSymbol(Chart::DiamondSymbol, 18);

double xCoor2[] = {0,2,6,8};//related tasks
layer2->setXData(DoubleArray(xCoor2, 4));//Number of tasks fore new layer connection

layer2->addDataSet(DoubleArray(startDate3, (int)(sizeof( startDate3) / sizeof( startDate3[0]))), 0xf3ff33,
    "Set2")->setDataSymbol(Chart::DiamondSymbol, 18);

//   c->layoutAxes();
  // c->layout();




//******************************
    // Output the chart
    c->makeChart("gantt.png");

    //free up resources
    delete c;
    return 0;
}
gantt.png

  Re: Blocks in gantt diagram
Posted by Peter Kwan on Sep-23-2016 02:45
Hi Babak,

1. In many cases, it is possible to put multiple lines in the same layer. It is also possible in your case, but with your current data structure, it is easy to put it in multiple layers. The overhead of a layer is very low in ChartDirector. You do not need to worry even if your chart has hundreds of layers.

2. In the code I mentioned in one of my messages, it is already connect from the mid-point of one bar to the starting point of the next bar. Please feel free to modify it to connect from the ending point instead of mid-point, and use your x-coordinates. For example:

// layoutAxes so we can use getXCoor and getYCoor
c->layoutAxes();

// Draw a line joining the end date of the previous bar to the
// start date of the current bar
for (int i = 1; i < barCount; ++i)
   c->addLine(xCoor[i - 1], endDate2[i - 1], xCoor[i], startDate2[i], 0x0000cc, 2);

If you need a more complex line, please modify the above code (eg. add more line segments) to create the line you want.

Regards
Peter Kwan

  Re: Blocks in gantt diagram
Posted by Peter Kwan on Sep-23-2016 02:48
Hi Babak,

The code should be:

// layoutAxes so we can use getXCoor and getYCoor
c->layoutAxes();

// Draw a line joining the end date of the previous bar to the
// start date of the current bar
for (int i = 1; i < barCount; ++i)
{
    c->addLine(c->getYCoor(endDate2[i - 1]), c->getXCoor(xCoor[i - 1]),
           c->getYCoor(startDate2[i]), c->getXCoor(xCoor[i]), 0x0000cc, 2);
}

Regards
Peter Kwan

  Re: Blocks in gantt diagram
Posted by Babak on Sep-22-2016 17:44
Hi How can i add Y axis labels  to each data box.
Regards

  Re: Blocks in gantt diagram
Posted by Peter Kwan on Sep-23-2016 02:55
Hi Babak,

For the "Y-Axis Labels", are you referring to the "Job 5", "Job 6" labels, which are the labels you put on the x-axis with the code:

    c->xAxis()->setLabels(StringArray(labels, (int)(sizeof(labels) / sizeof(labels[0]))));

If you are referring to the above labels, you can use "{xLabel}" with Layer.setDataLabelFormat to put them on the boxes, and use Layer.setDataLabelStyle to configure the display style. For example:

// Your existing addBoxWhiskerLayer line
BoxWhiskerLayer *bLayer = c->addBoxWhiskerLayer(....);

// Add the x-axis label to the box and configure its style
bLayer->setDataLabelFormat("{xLabel}");
bLayer->setDataLabelStyle("arialbd.ttf", 10)->setAlignment(Chart::Center);

Regards
Peter Kwan

  Re: Blocks in gantt diagram
Posted by Babak on Sep-23-2016 16:17
Attachments:
Dear Peter
Thank you for your kindly helps .
1- How can i have different "{xLabel}" .
2- how can i use multi  constant labels in Y Axis , if you see i have ESlabels and SWlabels , some times i need 4 es and 6 sw but i dont want define  as 1 constant label and would like mix mix them with limited choice .

Best Regards

int main(int argc, char *argv[])
{

/************************************ Label Define  **************************************************/
/************************************ Y Axis Lables Define  **************************************************/
    char const *ESlabels[] = {"ES0","ES1", "ES2", "ES3",
        "ES4", "ES5", "ES6", "ES7", "ES8",
        "ES12","ES11","ES10","ES9"};
    char const *SWlabels[] = {"SW0","SW1", "SW2", "SW3",
        "SW4", "SW5", "SW6", "SW7", "SW8",
        "SW9","SW10","SW11","SW12"};
/************************************ Task Lables Define  **************************************************/
    char const *Jlabels[] = {"JOB0","JOB1", "JOB2", "JOB3",
        "JOB4", "JOB5", "JOB6", "JOB7", "JOB8",
        "JOB9","JOB10","JOB11","JOB12"};

    char const *Mlabels[] = {"MSG0","MSG1", "MSG2", "MSG3",
        "MSG4", "MSG5", "MSG6", "MSG7", "MSG8",
        "MSG9","MSG10","MSG11","MSG12"};

/************************************ Task relation Define  **************************************************/
/************************************ JOB TO JOB relation   **************************************************/

double startDate1[] = {Chart::chartTime2(1), Chart::chartTime2(7),
        Chart::chartTime2(13), Chart::chartTime2(20), Chart::chartTime2(27),
        Chart::chartTime2(4), Chart::chartTime2(25), Chart::chartTime2(1
        )};
double endDate1[] ={Chart::chartTime2(8), Chart::chartTime2(13),
        Chart::chartTime2(23), Chart::chartTime2(25), Chart::chartTime2(32),
        Chart::chartTime2(9), Chart::chartTime2(33), Chart::chartTime2(6
        ), Chart::chartTime2(22)};

/************************************ MESSAGE TO MESSAGE relation   **************************************************/

double startDate2[] = {Chart::chartTime2(15), Chart::chartTime2(18), Chart::chartTime2(12), Chart::chartTime2(28)};
double endDate2[] ={Chart::chartTime2(22), Chart::chartTime2(23), Chart::chartTime2(16), Chart::chartTime2(28)};
double startDate3[] = {Chart::chartTime2(1), Chart::chartTime2(13), Chart::chartTime2(25), Chart::chartTime2(15)};

/************************************ VARIABLES  Define  **************************************************/

double MCoor[] = {8,9,10,11};//Message cordination
int HT =2 ;//hope to hope time

/************************************ Chart Define  **************************************************/

// Create a XYChart object of size 620 x 280 pixels. Set background color to light blue
    // (ccccff), with 1 pixel 3D border effect.
    XYChart *c = new XYChart(1100, 800, 0xccccff, 0x000000, 1);

    c->setRoundedFrame();


    // Add a title to the chart using 15 points Times Bold Itatic font, with white (ffffff) text on
    // a deep blue (000080) background
    c->addTitle("MetaScheduling Time System", "timesbi.ttf", 15, 0xffffff)->setBackground(0x000080);

    // Set the plotarea at (140, 55) and of size 460 x 200 pixels. Use alternative white/grey
    // background. Enable both horizontal and vertical grids by setting their colors to grey
    // (c0c0c0). Set vertical major grid (represents month boundaries) 2 pixels in width
    c->setPlotArea(40, 55, 1000, 600, 0xffffff, 0xeeeeee, Chart::Transparent, 0xc0c0c0, 0xc0c0c0
        )->setGridWidth(2, 1, 1, 1);


    // swap the x and y axes to create a horziontal box-whisker chart
    c->swapXY();

    // Set the y-axis scale to be date scale from minimum to maxmim
    // days (1 week)
    c->yAxis()->setDateScale(Chart::chartTime2(1), Chart::chartTime2(40),0);

    // Set multi-style axis label formatting. Month labels are in Arial Bold font in "mmm d" format.
    // Weekly labels just show the day of month and use minor tick (by using '-' as first character
    // of format string).
    c->yAxis()->setMultiFormat(Chart::StartOfSecondFilter(), "<*font=arialbd.ttf*>{value|s}",
        Chart::StartOfSecondFilter(),"{value|s}");

    // Set the y-axis to shown on the top (right + swapXY = top)
    c->setYAxisOnRight();

    // Set the labels on the x axis
c->xAxis()->setLabels(StringArray(ESlabels, (int)(sizeof(ESlabels) / sizeof(ESlabels[0]))));
// c->xAxis()->setLabels(StringArray(labels, (int)(sizeof(labels) / sizeof(labels[0]))));

    // Reverse the x-axis scale so that it points downwards.
    c->xAxis()->setReverse();

    // Set the horizontal ticks and grid lines to be between the bars
    c->xAxis()->setTickOffset(0.5);

/*************************************** Job **************************************************/
/************************************Draw  BOX Job **************************************************/

    // Add a green (33ff33) box-whisker layer showing the box only.
BoxWhiskerLayer *JLayer =c->addBoxWhiskerLayer(DoubleArray(startDate1, (int)(sizeof(startDate1) / sizeof(startDate1[0]))),
        DoubleArray(endDate1, (int)(sizeof(endDate1) / sizeof(endDate1[0]))), DoubleArray(),
        DoubleArray(), DoubleArray(), 0x00cc00, Chart::SameAsMainColor, Chart::SameAsMainColor);

/************************************ BOX labels Job  **************************************************/
c->xAxis()->setLabels(StringArray(Jlabels, (int)(sizeof(Jlabels)/ sizeof(Jlabels[0]))));
JLayer->setDataLabelFormat(*Jlabels);
JLayer->setDataLabelStyle("arialbd.ttf", 10)->setAlignment(Chart::Center);

/*************************************** Message **************************************************/
/************************************Draw  BOX Message **************************************************/

    // Add a green (33ff33) box-whisker layer showing the box only.
BoxWhiskerLayer *MLayer =c->addBoxWhiskerLayer(DoubleArray(startDate2, (int)(sizeof(startDate2) / sizeof(startDate2[0]))),
        DoubleArray(endDate2, (int)(sizeof(endDate2) / sizeof(endDate2[0]))), DoubleArray(),
        DoubleArray(), DoubleArray(), 0xFFcc00, Chart::SameAsMainColor, Chart::SameAsMainColor);
MLayer->setXData(DoubleArray(MCoor, 4));//Number of tasks fore new layer connection

/************************************ BOX labels Message  **************************************************/
c->xAxis()->setLabels(StringArray(Mlabels, (int)(sizeof(Mlabels)/ sizeof(Mlabels[0]))));
MLayer->setDataLabelFormat("{xLabel}");
MLayer->setDataLabelStyle("arialbd.ttf", 10)->setAlignment(Chart::Center);






/************************************ Layer Define  **************************************************/
// Add a line layer to the chart
    LineLayer *layer0 = c->addLineLayer();
    LineLayer *layer1 = c->addLineLayer();
    LineLayer *layer2 = c->addLineLayer();

    // Set the line width to 3 pixels
    layer0->setLineWidth(3);
    layer1->setLineWidth(3);
    layer2->setLineWidth(3);



/************************************ Line connectio Start **************************************************/


//Add the 2 data sets to the line layer, using circles, diamands and X shapes as symbols
   layer0->addDataSet(DoubleArray( startDate1, (int)(sizeof( startDate1) / sizeof( startDate1[0]))), 0xff0000,
     "Set1")->setDataSymbol(Chart::CircleSymbol, 18);

layer1->setXData(DoubleArray(MCoor, 4));//Number of tasks fore new layer connection


//std::cout << "coorx " <<  c->getXCoor(startDate[0]) << "n";
//std::cout << "coory " <<  c->getYCoor(startDate[0]) << "n";


layer1->addDataSet(DoubleArray(startDate2, (int)(sizeof( startDate2) / sizeof( startDate2[0]))), 0x33ff33,
    "Set2")->setDataSymbol(Chart::DiamondSymbol, 18);

double xCoor2[] = {0,2,6,8};//related tasks
layer2->setXData(DoubleArray(xCoor2, 4));//Number of tasks fore new layer connection

layer2->addDataSet(DoubleArray(startDate3, (int)(sizeof( startDate3) / sizeof( startDate3[0]))), 0xf3ff33,
    "Set2")->setDataSymbol(Chart::DiamondSymbol, 18);






/************************************ End **************************************************/
    // Output the chart
    c->makeChart("gantt.png");

    //free up resources
    delete c;
    return 0;
}
gantt.png

  Re: Blocks in gantt diagram
Posted by Babak on Sep-23-2016 21:25
Dear Peter

I try to use std::vector in BoxWhiskerLayer and other functions but it does not compile .


/************************************ MESSAGE TO MESSAGE relation   **************************************************/

vector <double> startDate2(4);

startDate2.at(0)=Chart::chartTime2(15) ;
startDate2.at(1)=Chart::chartTime2(18) ;
startDate2.at(2)=Chart::chartTime2(12) ;
startDate2.at(3)=Chart::chartTime2(28) ;

/************************************ VARIABLES  Define  **************************************************/


    int MSN=startDate2.size(); // Finding size of message array

vector <double> endDate2(MSN);

double HTT=Chart::chartTime2(HT);

for (int i=0; i<=MSN-1;i++)
{
endDate2[i]=startDate2[i]+HT;
}

BoxWhiskerLayer *MLayer =c->addBoxWhiskerLayer(DoubleArray(startDate2, MSN),
        DoubleArray(endDate2,MSN), DoubleArray(),
        DoubleArray(), DoubleArray(), 0x00cc00, Chart::SameAsMainColor, Chart::SameAsMainColor);


ERROR :


gantt.cpp:140:76: error: no matching function for call to ‘DoubleArray::DoubleArray(std::vector<double>&, int&)’
  BoxWhiskerLayer *MLayer =c->addBoxWhiskerLayer(DoubleArray(startDate2, MSN),
                                                                            ^
gantt.cpp:140:76: note: candidates are:
In file included from ../../include/chartdir.h:17:0,
                 from gantt.cpp:1:
../../include/memblock.h:41:2: note: DoubleArray::DoubleArray(const double*, int)
  DoubleArray(const double *_data, int _len) : len(_len), data(_data) {}
  ^
../../include/memblock.h:41:2: note:   no known conversion for argument 1 from ‘std::vector<double>’ to ‘const double*’
../../include/memblock.h:40:2: note: DoubleArray::DoubleArray()
  DoubleArray() : len(0), data(0) {}
  ^
../../include/memblock.h:40:2: note:   candidate expects 0 arguments, 2 provided
../../include/memblock.h:35:7: note: DoubleArray::DoubleArray(const DoubleArray&)
class DoubleArray
       ^
../../include/memblock.h:35:7: note:   candidate expects 1 argument, 2 provided
gantt.cpp:141:33: error: no matching function for call to ‘DoubleArray::DoubleArray(std::vector<double>&, int&)’
         DoubleArray(endDate2,MSN), DoubleArray(),
                                 ^
gantt.cpp:141:33: note: candidates are:
In file included from ../../include/chartdir.h:17:0,
                 from gantt.cpp:1:
../../include/memblock.h:41:2: note: DoubleArray::DoubleArray(const double*, int)
  DoubleArray(const double *_data, int _len) : len(_len), data(_data) {}
  ^
../../include/memblock.h:41:2: note:   no known conversion for argument 1 from ‘std::vector<double>’ to ‘const double*’
../../include/memblock.h:40:2: note: DoubleArray::DoubleArray()
  DoubleArray() : len(0), data(0) {}
  ^
../../include/memblock.h:40:2: note:   candidate expects 0 arguments, 2 provided
../../include/memblock.h:35:7: note: DoubleArray::DoubleArray(const DoubleArray&)
class DoubleArray
       ^
../../include/memblock.h:35:7: note:   candidate expects 1 argument, 2 provided
make: *** [gantt] Error 1

  Re: Blocks in gantt diagram
Posted by Peter Kwan on Sep-24-2016 01:28
Hi Babak,

The DoubleArray expects a pointer to const double numbers as the first argument. See:

http://www.advsofteng.com/doc/cdcpp.htm#DoubleArray.htm

You probably already know that C++ is a strongly typed language, and you must use parameters of the correct type. In your case, the error message is generated by your compiler. It means you are using a type that is not suitable for DoubleArray. Please use a pointer to const double instead.

In case you are not familiar with how to use std::vector, you can obtain a poitner to const double with &(startDate2[0]), like:

  .... DoubleArray(&(startDate2[0]), MSN) ....

For more information, you may refer to the C++ documentation on std::vector.

Regards
Peter Kwan

  Re: Blocks in gantt diagram
Posted by Peter Kwan on Sep-24-2016 02:42
Hi Babak,

You probably know that in C++, *Jlabels means the first label in the Jlabels array. So the following code sets the data label to be the first label in the Jlabels array:

JLayer->setDataLabelFormat(*Jlabels);

The {xLabel} refers to the x-axis labels. For your case, I assume you do not want to use the x-axis labels for the JLayer. In this case, please do not use {xLabel}. If you want to use other labels, please add an extra field:

JLayer->addExtraField(StringArray(Jlabels, (int)(sizeof(Jlabels)/ sizeof(Jlabels[0]))));
JLayer->setDataLabelFormat("{field0}");

Hope this can help.

Regards
Peter Kwan

  Re: Blocks in gantt diagram
Posted by Babak on Sep-26-2016 17:13
Dear Peter
Your solution for Labels in BOXes work and thank you ,but i found that if i going to use only 5 labels in axis not all of elements ,it does not work !.


   char const *ESlabels[] = {"ES0","ES1", "ES2", "ES3",
        "ES4", "ES5", "ES6", "ES7", "ES8",
        "ES12","ES11","ES10","ES9"};
    char const *SWlabels[] = {"SW0","SW1", "SW2", "SW3",
        "SW4", "SW5", "SW6", "SW7", "SW8",
        "SW9","SW10","SW11","SW12"};


c->xAxis()->setLabels(StringArray(ESlabels,(4)));
I only want 4 labels but it show all array entry !.
because i want use 2 different labels in XAxis , and some times first label with 5 element and after it next label .

  Re: Blocks in gantt diagram
Posted by Babak on Sep-26-2016 18:16
Attachments:
Dear Petter

I cant make connection between vector and double class your solution does not answer.

i insert all codes in here i disabled vector codes that you can find what its in normal way and what i want.

I have to use vector as input because this gantt program have to connect to my main program that make 1000 different gantt model then start,end and labels change in each run time with new variables.

for example in attached pic i have 8job,4msg ,8 ES and 4sw  and in next time it will change to 6job ,6msg,6es and 5 SW.

then i have to use vector and flexible parameters , not as constant.


#include "chartdir.h"
#include <iostream>
#include <vector>
#include <assert.h>
#include <stdio.h>
#include <algorithm>
#include <sstream>
#include <string>
#include <map>


using namespace std;
int main(int argc, char *argv[])
{

/************************************ Label Define  **************************************************/
/************************************ Y Axis Lables Define  **************************************************/
    char const *ESlabels[] = {"ES0","ES1", "ES2", "ES3",
        "ES4", "ES5", "ES6", "ES7", "ES8",
        "ES12","ES11","ES10","ES9"};
    char const *SWlabels[] = {"SW0","SW1", "SW2", "SW3",
        "SW4", "SW5", "SW6", "SW7", "SW8",
        "SW9","SW10","SW11","SW12"};
/************************************ Task Lables Define  **************************************************/
    char const *Jlabels[] = {"JOB0","JOB1", "JOB2", "JOB3",
        "JOB4", "JOB5", "JOB6", "JOB7", "JOB8",
        "JOB9","JOB10","JOB11","JOB12"};

    char const *Mlabels[] = {"MSG0","MSG1", "MSG2", "MSG3",
        "MSG4", "MSG5", "MSG6", "MSG7", "MSG8",
        "MSG9","MSG10","MSG11","MSG12"};

/************************************ Task relation Define  **************************************************/
/************************************ JOB TO JOB relation   **************************************************/

double startDate1[] = {Chart::chartTime2(2), Chart::chartTime2(7),
        Chart::chartTime2(13), Chart::chartTime2(20), Chart::chartTime2(27),
        Chart::chartTime2(4), Chart::chartTime2(25), Chart::chartTime2(1
        )};
double endDate1[] ={Chart::chartTime2(8), Chart::chartTime2(13),
        Chart::chartTime2(23), Chart::chartTime2(25), Chart::chartTime2(32),
        Chart::chartTime2(9), Chart::chartTime2(33), Chart::chartTime2(6
        ), Chart::chartTime2(22)};

/************************************ MESSAGE TO MESSAGE relation   **************************************************/
double startDate2[] = {Chart::chartTime2(15), Chart::chartTime2(18), Chart::chartTime2(12), Chart::chartTime2(28)};
double endDate2[] ={Chart::chartTime2(22), Chart::chartTime2(23), Chart::chartTime2(16), Chart::chartTime2(34)};
/*
vector <double> *startDate2=new vector<double>(4); //= {Chart::chartTime2(15), Chart::chartTime2(18), Chart::chartTime2(12), Chart::chartTime2(28)};
startDate2->at(0)=Chart::chartTime2(15) ;
startDate2->at(1)=Chart::chartTime2(18) ;
startDate2->at(2)=Chart::chartTime2(12) ;
startDate2->at(3)=Chart::chartTime2(28) ;

*/
double startDate3[] = {Chart::chartTime2(2), Chart::chartTime2(13), Chart::chartTime2(25), Chart::chartTime2(15)};

/************************************ VARIABLES  Define  **************************************************/
    double HT =2 ;//hope to hope static time
    double MCoor[] = {8,9,10,11};//Message cordination
int MSN=4;
/*
    int MSN=startDate2->size(); // Finding size of message array

vector <double> endDate2(MSN);



std::cout << "msn " << MSN << "n";

/************************************   Define finishing time of Messages **************************************************/
double HTT=Chart::chartTime2(HT);
for (int i=0; i<=MSN-1;i++)
{
//endDate2.at(i)=startDate2->at(i)+HT;
endDate2[i]=startDate2[i]+HT;
//endDate2[2]=startDate2[2]+HT;
//endDate2[3]=startDate2[3]+HT;
}
//std::cout << "coord " << endDate2.size() << "n";
/************************************ Chart Define  **************************************************/

// Create a XYChart object of size 620 x 280 pixels. Set background color to light blue
    // (ccccff), with 1 pixel 3D border effect.
    XYChart *c = new XYChart(1100, 800, 0xccccff, 0x000000, 1);

    c->setRoundedFrame();


    // Add a title to the chart using 15 points Times Bold Itatic font, with white (ffffff) text on
    // a deep blue (000080) background
    c->addTitle("MetaScheduling Time System", "timesbi.ttf", 15, 0xffffff)->setBackground(0x000080);

    // Set the plotarea at (140, 55) and of size 460 x 200 pixels. Use alternative white/grey
    // background. Enable both horizontal and vertical grids by setting their colors to grey
    // (c0c0c0). Set vertical major grid (represents month boundaries) 2 pixels in width
    c->setPlotArea(40, 55, 1000, 600, 0xffffff, 0xeeeeee, Chart::Transparent, 0xc0c0c0, 0xc0c0c0
        )->setGridWidth(2, 1, 1, 1);


    // swap the x and y axes to create a horziontal box-whisker chart
    c->swapXY();

    // Set the y-axis scale to be date scale from minimum to maxmim
    // days (1 week)
    c->yAxis()->setDateScale(Chart::chartTime2(1), Chart::chartTime2(40),0);

    // Set multi-style axis label formatting. Month labels are in Arial Bold font in "mmm d" format.
    // Weekly labels just show the day of month and use minor tick (by using '-' as first character
    // of format string).
    c->yAxis()->setMultiFormat(Chart::StartOfSecondFilter(), "<*font=arialbd.ttf*>{value|s}",
        Chart::StartOfSecondFilter(),"{value|s}");

    // Set the y-axis to shown on the top (right + swapXY = top)
    c->setYAxisOnRight();

    // Set the labels on the x axis
c->xAxis()->setLabels(StringArray(ESlabels, (int)(sizeof(ESlabels) / sizeof(ESlabels[0]))));
// c->xAxis()->setLabels(StringArray(labels, (int)(sizeof(labels) / sizeof(labels[0]))));

    // Reverse the x-axis scale so that it points downwards.
    c->xAxis()->setReverse();

    // Set the horizontal ticks and grid lines to be between the bars
    c->xAxis()->setTickOffset(0.5);

/*************************************** Job **************************************************/
/************************************Draw  BOX Job **************************************************/

    // Add a green (33ff33) box-whisker layer showing the box only.
BoxWhiskerLayer *JLayer =c->addBoxWhiskerLayer(DoubleArray(startDate1, (int)(sizeof(startDate1) / sizeof(startDate1[0]))),
        DoubleArray(endDate1, (int)(sizeof(endDate1) / sizeof(endDate1[0]))), DoubleArray(),
        DoubleArray(), DoubleArray(), 0x00cc00, Chart::SameAsMainColor, Chart::SameAsMainColor);

/************************************ BOX labels Job  **************************************************/
//c->xAxis()->setLabels(StringArray(ESlabels, (int)(sizeof(ESlabels-10)/ sizeof(ESlabels[0]))));
c->xAxis()->setLabels(StringArray(ESlabels,(4)));
JLayer->setDataLabelFormat(*Jlabels);
JLayer->addExtraField(StringArray(Jlabels, (int)(sizeof(Jlabels)/ sizeof(Jlabels[0]))));
    JLayer->setDataLabelFormat("{field0}");
JLayer->setDataLabelStyle("arialbd.ttf", 10)->setAlignment(Chart::Center);

/*************************************** Message **************************************************/
/************************************Draw  BOX Message **************************************************/
BoxWhiskerLayer *MLayer =c->addBoxWhiskerLayer(DoubleArray(startDate2, (int)(sizeof(startDate2) / sizeof(startDate2[0]))),
        DoubleArray(endDate2, (int)(sizeof(endDate2) / sizeof(endDate2[0]))), DoubleArray(),
        DoubleArray(), DoubleArray(), 0x44ccFE, Chart::SameAsMainColor, Chart::SameAsMainColor);

MLayer->setDataLabelFormat(*Mlabels);
MLayer->addExtraField(StringArray(Mlabels, (int)(sizeof(Mlabels)/ sizeof(Mlabels[0]))));
    MLayer->setDataLabelFormat("{field0}");
MLayer->setDataLabelStyle("arialbd.ttf", 10)->setAlignment(Chart::Center);

MLayer->setXData(DoubleArray(MCoor, 4));//BOX cordination

    // Add a green (33ff33) box-whisker layer showing the box only.
/*


  *
  * BoxWhiskerLayer *MLayer =c->addBoxWhiskerLayer(DoubleArray(startDate2,MSN),
        DoubleArray(endDate2, MSN), DoubleArray(),
        DoubleArray(), DoubleArray(), 0x00cc00, Chart::SameAsMainColor, Chart::SameAsMainColor);
/*BoxWhiskerLayer *MLayer =c->addBoxWhiskerLayer(DoubleArray(MSN)),
        DoubleArray(endDate2,  endDate2.size(), DoubleArray(),
        DoubleArray(), DoubleArray(), 0xFFcc00, Chart::SameAsMainColor, Chart::SameAsMainColor);



/************************************ BOX labels Message  **************************************************/
/*
c->xAxis()->setLabels(StringArray(Mlabels, (int)(sizeof(Mlabels)/ sizeof(Mlabels[0]))));
MLayer->setDataLabelFormat("{xLabel}");
MLayer->setDataLabelStyle("arialbd.ttf", 10)->setAlignment(Chart::Center);






/************************************ Layer Define  **************************************************/
// Add a line layer to the chart
    LineLayer *layer0 = c->addLineLayer();
    LineLayer *layer1 = c->addLineLayer();
    LineLayer *layer2 = c->addLineLayer();

    // Set the line width to 3 pixels
    layer0->setLineWidth(3);
    layer1->setLineWidth(3);
    layer2->setLineWidth(3);



/************************************ Line connectio Start **************************************************/


//Add the 2 data sets to the line layer, using circles, diamands and X shapes as symbols
   layer0->addDataSet(DoubleArray( startDate1, (int)(sizeof( startDate1) / sizeof( startDate1[0]))), 0xff0000,
     "Set1")->setDataSymbol(Chart::CircleSymbol, 18);

layer1->setXData(DoubleArray(MCoor, 4));//Number of tasks fore new layer connection


//std::cout << "coorx " <<  c->getXCoor(startDate[0]) << "n";
//std::cout << "coory " << << "n";


layer1->addDataSet(DoubleArray(startDate2,  (int)(sizeof( startDate2) / sizeof( startDate2[0]))), 0x33ff33,
    "Set2")->setDataSymbol(Chart::DiamondSymbol, 18);

double xCoor2[] = {0,2,6,8};//related tasks
layer2->setXData(DoubleArray(xCoor2, 4));//Number of tasks fore new layer connection

layer2->addDataSet(DoubleArray(startDate3, (int)(sizeof( startDate3) / sizeof( startDate3[0]))), 0xf3ff33,
    "Set2")->setDataSymbol(Chart::DiamondSymbol, 18);






/************************************ End **************************************************/
    // Output the chart
    c->makeChart("gantt.png");

    //free up resources
    delete c;
    return 0;
}
gantt.png

  Re: Blocks in gantt diagram
Posted by Peter Kwan on Sep-27-2016 03:19
Hi Babak,

I have just tried your code using "vector", and it works normally. Would you mind to clarify what is the issue?

Note that the code I suggested in my last message is for your reference only. It is standard C++ code and is not related to ChartDirector. Like all sample code, you need to modify for your own needs. For example, in the original code, it assumes the variable is a vector. In your code, the startDate2 is a vector pointer, not a vector, and the endDate2 is a vector. You probably already know that if the code expects a vector, but the variable is a vector pointer, you need to dereference it to get the vector. (The compiler should produce an error message to inform you of the issue if this is not done.)

For the c->xAxis()->setLabels(StringArray(ESlabels, 4));, it works normally and only 4 labels are displayed. In your original, you use:

c->xAxis()->setLabels(StringArray(ESlabels, (int)(sizeof(ESlabels) / sizeof(ESlabels[0]))));

and also:

c->xAxis()->setLabels(StringArray(ESlabels, 4));

So both sets of labels are added to the x-axis, which means all the labels are added. If you only need 4 labels, please do not add all the labels.

Hope this can help.

Regards
Peter Kwan


#include "chartdir.h"
#include <iostream>
#include <vector>
#include <assert.h>
#include <stdio.h>
#include <algorithm>
#include <sstream>
#include <string>
#include <map>


using namespace std;
int main(int argc, char *argv[])
{

/************************************ Label Define  **************************************************/
/************************************ Y Axis Lables Define  **************************************************/
    char const *ESlabels[] = {"ES0","ES1", "ES2", "ES3",
        "ES4", "ES5", "ES6", "ES7", "ES8",
        "ES12","ES11","ES10","ES9"};
    char const *SWlabels[] = {"SW0","SW1", "SW2", "SW3",
        "SW4", "SW5", "SW6", "SW7", "SW8",
        "SW9","SW10","SW11","SW12"};
/************************************ Task Lables Define  **************************************************/
    char const *Jlabels[] = {"JOB0","JOB1", "JOB2", "JOB3",
        "JOB4", "JOB5", "JOB6", "JOB7", "JOB8",
        "JOB9","JOB10","JOB11","JOB12"};

    char const *Mlabels[] = {"MSG0","MSG1", "MSG2", "MSG3",
        "MSG4", "MSG5", "MSG6", "MSG7", "MSG8",
        "MSG9","MSG10","MSG11","MSG12"};

/************************************ Task relation Define  **************************************************/
/************************************ JOB TO JOB relation   **************************************************/

double startDate1[] = {Chart::chartTime2(2), Chart::chartTime2(7),
        Chart::chartTime2(13), Chart::chartTime2(20), Chart::chartTime2(27),
        Chart::chartTime2(4), Chart::chartTime2(25), Chart::chartTime2(1
        )};
double endDate1[] ={Chart::chartTime2(8), Chart::chartTime2(13),
        Chart::chartTime2(23), Chart::chartTime2(25), Chart::chartTime2(32),
        Chart::chartTime2(9), Chart::chartTime2(33), Chart::chartTime2(6
        ), Chart::chartTime2(22)};

/************************************ MESSAGE TO MESSAGE relation   **************************************************/
//double startDate2[] = {Chart::chartTime2(15), Chart::chartTime2(18), Chart::chartTime2(12), Chart::chartTime2(28)};
//double endDate2[] ={Chart::chartTime2(22), Chart::chartTime2(23), Chart::chartTime2(16), Chart::chartTime2(34)};

vector <double> *startDate2=new vector<double>(4); //= {Chart::chartTime2(15), Chart::chartTime2(18), Chart::chartTime2(12), Chart::chartTime2(28)};
startDate2->at(0)=Chart::chartTime2(15) ;
startDate2->at(1)=Chart::chartTime2(18) ;
startDate2->at(2)=Chart::chartTime2(12) ;
startDate2->at(3)=Chart::chartTime2(28) ;


double startDate3[] = {Chart::chartTime2(2), Chart::chartTime2(13), Chart::chartTime2(25), Chart::chartTime2(15)};

/************************************ VARIABLES  Define  **************************************************/
    double HT =2 ;//hope to hope static time
    double MCoor[] = {8,9,10,11};//Message cordination
//int MSN=4;

    int MSN=startDate2->size(); // Finding size of message array

vector <double> endDate2(MSN);



//std::cout << "msn " << MSN << "n";

/************************************   Define finishing time of Messages **************************************************/
double HTT=Chart::chartTime2(HT);
for (int i=0; i<=MSN-1;i++)
{
endDate2.at(i)=startDate2->at(i)+HT;
//endDate2[i]=startDate2[i]+HT;
//endDate2[2]=startDate2[2]+HT;
//endDate2[3]=startDate2[3]+HT;
}
//std::cout << "coord " << endDate2.size() << "n";
/************************************ Chart Define  **************************************************/

// Create a XYChart object of size 620 x 280 pixels. Set background color to light blue
    // (ccccff), with 1 pixel 3D border effect.
    XYChart *c = new XYChart(1100, 800, 0xccccff, 0x000000, 1);

    c->setRoundedFrame();


    // Add a title to the chart using 15 points Times Bold Itatic font, with white (ffffff) text on
    // a deep blue (000080) background
    c->addTitle("MetaScheduling Time System", "timesbi.ttf", 15, 0xffffff)->setBackground(0x000080);

    // Set the plotarea at (140, 55) and of size 460 x 200 pixels. Use alternative white/grey
    // background. Enable both horizontal and vertical grids by setting their colors to grey
    // (c0c0c0). Set vertical major grid (represents month boundaries) 2 pixels in width
    c->setPlotArea(40, 55, 1000, 600, 0xffffff, 0xeeeeee, Chart::Transparent, 0xc0c0c0, 0xc0c0c0
        )->setGridWidth(2, 1, 1, 1);


    // swap the x and y axes to create a horziontal box-whisker chart
    c->swapXY();

    // Set the y-axis scale to be date scale from minimum to maxmim
    // days (1 week)
    c->yAxis()->setDateScale(Chart::chartTime2(1), Chart::chartTime2(40),0);

    // Set multi-style axis label formatting. Month labels are in Arial Bold font in "mmm d" format.
    // Weekly labels just show the day of month and use minor tick (by using '-' as first character
    // of format string).
    c->yAxis()->setMultiFormat(Chart::StartOfSecondFilter(), "<*font=arialbd.ttf*>{value|s}",
        Chart::StartOfSecondFilter(),"{value|s}");

    // Set the y-axis to shown on the top (right + swapXY = top)
    c->setYAxisOnRight();

    // Set the labels on the x axis
c->xAxis()->setLabels(StringArray(ESlabels, 4));
// c->xAxis()->setLabels(StringArray(labels, (int)(sizeof(labels) / sizeof(labels[0]))));

    // Reverse the x-axis scale so that it points downwards.
    c->xAxis()->setReverse();

    // Set the horizontal ticks and grid lines to be between the bars
    c->xAxis()->setTickOffset(0.5);

/*************************************** Job **************************************************/
/************************************Draw  BOX Job **************************************************/

    // Add a green (33ff33) box-whisker layer showing the box only.
BoxWhiskerLayer *JLayer =c->addBoxWhiskerLayer(DoubleArray(startDate1, (int)(sizeof(startDate1) / sizeof(startDate1[0]))),
        DoubleArray(endDate1, (int)(sizeof(endDate1) / sizeof(endDate1[0]))), DoubleArray(),
        DoubleArray(), DoubleArray(), 0x00cc00, Chart::SameAsMainColor, Chart::SameAsMainColor);

/************************************ BOX labels Job  **************************************************/
//c->xAxis()->setLabels(StringArray(ESlabels, (int)(sizeof(ESlabels-10)/ sizeof(ESlabels[0]))));
c->xAxis()->setLabels(StringArray(ESlabels,(4)));
JLayer->setDataLabelFormat(*Jlabels);
JLayer->addExtraField(StringArray(Jlabels, (int)(sizeof(Jlabels)/ sizeof(Jlabels[0]))));
    JLayer->setDataLabelFormat("{field0}");
JLayer->setDataLabelStyle("arialbd.ttf", 10)->setAlignment(Chart::Center);

/*************************************** Message **************************************************/
/************************************Draw  BOX Message **************************************************/
//BoxWhiskerLayer *MLayer =c->addBoxWhiskerLayer(DoubleArray(startDate2, (int)(sizeof(startDate2) / sizeof(startDate2[0]))),
//        DoubleArray(endDate2, (int)(sizeof(endDate2) / sizeof(endDate2[0]))), DoubleArray(),
//        DoubleArray(), DoubleArray(), 0x44ccFE, Chart::SameAsMainColor, Chart::SameAsMainColor);

BoxWhiskerLayer *MLayer =c->addBoxWhiskerLayer(DoubleArray(&((*startDate2)[0]), MSN),
        DoubleArray(&(endDate2[0]), MSN), DoubleArray(),
        DoubleArray(), DoubleArray(), 0x44ccFE, Chart::SameAsMainColor, Chart::SameAsMainColor);

MLayer->setDataLabelFormat(*Mlabels);
MLayer->addExtraField(StringArray(Mlabels, (int)(sizeof(Mlabels)/ sizeof(Mlabels[0]))));
    MLayer->setDataLabelFormat("{field0}");
MLayer->setDataLabelStyle("arialbd.ttf", 10)->setAlignment(Chart::Center);

MLayer->setXData(DoubleArray(MCoor, 4));//BOX cordination

    // Add a green (33ff33) box-whisker layer showing the box only.
/*


  *
  * BoxWhiskerLayer *MLayer =c->addBoxWhiskerLayer(DoubleArray(startDate2,MSN),
        DoubleArray(endDate2, MSN), DoubleArray(),
        DoubleArray(), DoubleArray(), 0x00cc00, Chart::SameAsMainColor, Chart::SameAsMainColor);
/*BoxWhiskerLayer *MLayer =c->addBoxWhiskerLayer(DoubleArray(MSN)),
        DoubleArray(endDate2,  endDate2.size(), DoubleArray(),
        DoubleArray(), DoubleArray(), 0xFFcc00, Chart::SameAsMainColor, Chart::SameAsMainColor);



/************************************ BOX labels Message  **************************************************/
/*
c->xAxis()->setLabels(StringArray(Mlabels, (int)(sizeof(Mlabels)/ sizeof(Mlabels[0]))));
MLayer->setDataLabelFormat("{xLabel}");
MLayer->setDataLabelStyle("arialbd.ttf", 10)->setAlignment(Chart::Center);






/************************************ Layer Define  **************************************************/
// Add a line layer to the chart
    LineLayer *layer0 = c->addLineLayer();
    LineLayer *layer1 = c->addLineLayer();
    LineLayer *layer2 = c->addLineLayer();

    // Set the line width to 3 pixels
    layer0->setLineWidth(3);
    layer1->setLineWidth(3);
    layer2->setLineWidth(3);



/************************************ Line connectio Start **************************************************/


//Add the 2 data sets to the line layer, using circles, diamands and X shapes as symbols
   layer0->addDataSet(DoubleArray( startDate1, (int)(sizeof( startDate1) / sizeof( startDate1[0]))), 0xff0000,
     "Set1")->setDataSymbol(Chart::CircleSymbol, 18);

layer1->setXData(DoubleArray(MCoor, 4));//Number of tasks fore new layer connection


//std::cout << "coorx " <<  c->getXCoor(startDate[0]) << "n";
//std::cout << "coory " << << "n";

layer1->addDataSet(DoubleArray(&((*startDate2)[0]), MSN), 0x33ff33,
    "Set2")->setDataSymbol(Chart::DiamondSymbol, 18);

double xCoor2[] = {0,2,6,8};//related tasks
layer2->setXData(DoubleArray(xCoor2, 4));//Number of tasks fore new layer connection

layer2->addDataSet(DoubleArray(startDate3, (int)(sizeof( startDate3) / sizeof( startDate3[0]))), 0xf3ff33,
    "Set2")->setDataSymbol(Chart::DiamondSymbol, 18);



/************************************ End **************************************************/
    // Output the chart
    c->makeChart("gantt.png");

    //free up resources
    delete c;
    return 0;
}

  Re: Blocks in gantt diagram
Posted by Babak on Sep-27-2016 03:38
Dear Peter
When i use vector as pointer or normal compiler show error to for DoubleArray class that can not convert vector to double constant.
if you think need then i have to change DoubleArray class variables from const double to vector ... i hope so dont do it !

about axis i want use ESlabel and after it SWlabel  together.

  Re: Blocks in gantt diagram
Posted by Babak on Sep-27-2016 03:57
i think error was from make file it need c++ 11 some problems solved

  Re: Blocks in gantt diagram
Posted by Babak on Sep-27-2016 17:18
Dera Peter

How i have to solve problem when i have vector in StringArray


int LabelNo=MSN+JN;
vector <char> *YLabel=new vector<char>(LabelNo);//Message finishing time array

    for(int i=0;i<=JN;i++)
        YLabel->at(i)=*ESlabels[i];
    for(int i=JN+1;i<=LabelNo;i++)
        YLabel->at(i)=*SWlabels[i];

    c->xAxis()->setLabels(StringArray(&((*YLabel)[0]), LabelNo);


compiler error :

gantt.cpp:131:63: error: no matching function for call to ‘StringArray::StringArray(__gnu_cxx::__alloc_traits<std::allocator<char> >::value_type*, int&)’
     c->xAxis()->setLabels(StringArray(&((*YLabel)[0]), LabelNo);
                                                               ^
gantt.cpp:131:63: note: candidates are:
In file included from ../../include/chartdir.h:17:0,
                 from gantt.cpp:2:
../../include/memblock.h:31:2: note: StringArray::StringArray(const char* const*, int)
  StringArray(const char * const *_data, int _len) : len(_len), data(_data) {}
  ^
../../include/memblock.h:31:2: note:   no known conversion for argument 1 from ‘__gnu_cxx::__alloc_traits<std::allocator<char> >::value_type* {aka char*}’ to ‘const char* const*’
../../include/memblock.h:30:2: note: StringArray::StringArray()
  StringArray() : len(0), data(0) {}

  Re: Blocks in gantt diagram
Posted by Peter Kwan on Sep-27-2016 23:25
Hi Babak,

You can use vector if you like. This is standard C++ and is not related to ChartDirector.

The StringArray needs an array of strings as the first argument. The documentation already mentions what it accepts:

http://www.advsofteng.com/doc/cdcpp.htm#StringArray.StringArray.htm

In your code, your vector<char> does not contain an array of text strings. It is at most an array of "char". (I assume you already know that a "char" is a character in C/C++, and a character is not a text string in C/C++.) Please set up the vector to contain an array of text strings instead.

In case you are not familiar with C and C++, a text string in C/C++ is "char *". Also, all types in C/C++ can have the constant modifier "const". In your previous code, the ESlabels contains string literals, which means the text string are constants. If your vector is not declared to accept constant strings, you cannot assign a constant string to it. You can set up the vector to accept constant strings, or cast the constant modifier away in the assignment, or use text strings that are not constants.

(Note: None of the above is related to ChartDirector. You may need to refer to C/C++ documentation if you are not familiar with text strings, pointers and constant types.)

Regards
Peter Kwan

  Re: Blocks in gantt diagram
Posted by Babak on Oct-04-2016 17:32
Hi I cant  pass constant modifier please help me,how i can pass a string  vector to StringArray .
I need code.

  Re: Blocks in gantt diagram
Posted by Peter Kwan on Oct-05-2016 01:38
Hi Babak,

In C, a constant string is "const char *". You just need to create a vector of constant strings, like:

vector <const char *> *YLabel=new vector<const char *>(LabelNo);

for(int i=0;i<=JN;i++)
   YLabel->at(i)= ESlabels[i];
for(int i=JN+1;i<=LabelNo;i++)
   YLabel->at(i)= SWlabels[i];

Hope this can help.

Regards
Peter Kwan

  Re: Blocks in gantt diagram
Posted by Babak on Oct-05-2016 03:39
Thank you but when i use this code compiler can not conver
vector <const char *> *YLabel=new vector<const char *>(LabelNo);

       for(int i=0;i<=JN;i++)
           YLabel->at(i)=ESlabels[i];
       for(int j=JN;j<=LabelNo;j++)
           {
   YLabel->at(j)=SWlabels[j];
   k++;
   }

       c->xAxis()->setLabels(StringArray(&((*YLabel)[0])), LabelNo);//error in here

  Re: Blocks in gantt diagram
Posted by Babak on Oct-05-2016 18:00
I solve it problem was in place of lib .

all: xmlparser.o main.o models.o scheduler.o metascheduler.o outputs.o visualize.o
g++ $(CPLEX_LIBS) -L../xml/lib -Wl,-R../xml/lib $(CCFLAGS) models.o xmlparser.o main.o outputs.o scheduler.o metascheduler.o visualize.o  -lchartdir -o sched `pkg-config --cflags --libs libxml++-2.6` $(CCLNFLAGS)

But the new problem is after compile withh other files and run, labels does not show.
but that code in single cpp file show labels.!!!

  Re: Blocks in gantt diagram
Posted by Peter Kwan on Oct-06-2016 02:25
Hi Babak,

If all text disappear, including the chart title and the numeric labels in the horizontal axis, one possibility is because of the fonts.

From your Makefile, you may have moved the location of the libchartdir.so. Have you also moved the fonts subdirectory? If you are using operating system that does not have fonts as standard (such as Linux, FreeBSD or Solaris), you would need to have the font folder copied to the same folder as libchartdir.so. Without fonts, no text can be displayed.

If the chart title and the horizontal axis labels appear normally, but the labels in your vector array do not appear, is it possible the text string you use are actually empty of points to invalid memory? In C, your code would need to manage the memory, so it needs to make sure the text strings are in memory properly. For literal strings, such as the ESlabels and SWlabels in your earlier code, the memory is always valid. However, if your text strings are dynamically generated, please make sure the memory for those strings are not freed or become invalid before the vector is passed to ChartDirector.

Regards
Peter Kwan