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

Message ListMessage List     Post MessagePost Message

  DrawXY V6 MFC - Draw a filled color rectangle over chart + points over Chart
Posted by Sal on May-23-2015 04:57
Hi Peter,

I am planning to draw a colored semi-transparent slanted rectangle over the XY graph I produced (Please see my previous message, if needed more details)

I have been looking at 2 my Methods:

FYI:
     // Code common for both attempts:

      XYChart *c = new XYChart(...)

     // These are arrays of World Point coordinates (4 corners of rectangle area to draw)
     // The points are listed in CW direction starting from the Top/Left corner
     //  and are know to be valid since they were plotted as discrete points using:
     double ObstructionX[4];
     double ObstructionY[4];


     // Plot the 4 corners point to make sure they can be drawn and so they are valid
     pLineLayer* pLL = c->addLineLayer(DoubleArray(ObstructionY, 4), 0xFF0000);
     pLL->setXData(DoubleArray(ObstructionX, 4));

     [Points are SUCCESSFULLY DRAWN]

     ....

     DrawArea* pDrawArea = c->getDrawArea();

------------
Method #1:


int X_Point[4];
int Y_Point[4];

for (int i=0; i < 4; i++)
{
         // I assmume these are Pixels
                X_Point[i] = c->getXCoor(ObstructionX[i]);
        Y_Point[I] = c->getYCoor(ObstructionY[i]);
}

        // draw rectangle as semi-transparent grey
pDrawArea->polygon(IntArray(X_Point, 4),
                                        IntArray(Y_Point, 4),
                                        0x40dddddd,
                                        0x40dddddd);

------------
Method #2:

        // Since Method 1 failed, try to draw a standard rectangle to simplify the task...
        // The edges points are parallel to the Axis of the chart
   pDrawArea->surface( ObstructionX0], ObstructionY[0],
ObstructionX[1], ObstructionY[1],
(int)abs(ObstructionX[1]-ObstructionX[0]),
(int)abs(ObstructionY[2]-ObstructionY[1]),
0x40dddddd, 0x40dddddd);

------------

Neither above code fragments draws anything.

The above attempts were done at the end of the code that produces the graph, just before the line that has:

         m_GraphsArea.setChart(c); // Output the chart


I must have miss-understood what is a "DrawArea" for when obtained from a XyChart() as I did.

As I read from the V6 documentation, this is the way to draw primitive drawing element in a Plot of our creation.

Q1: One basic question is: in which order my drawing elements are drawn ?

Q2: What I am missing that is not clear by reading the documentation if using Method# 1 ?
Q3: What I am missing that is not clear by reading the documentation if using Method# 2 ?

Looking back at your DrawXY w/Scroll (V6 Sample), I see that you added a semitransparent Legend w/some items in the Upper corner of CD sample code as:

-------------

    // Add a legend box at (450, 40) (top right corner of the chart) with vertical layout
    // and 8 pts Arial Bold font. Set the background color to semi-transparent grey.
    LegendBox *legendBox = c->addLegend(450, 40, true, "arialbd.ttf", 8);
    legendBox->setAlignment(Chart::TopRight);
    legendBox->setBackground(0x40dddddd);

------------

Q4: assuming my attempts are deadly wrong for a major reason, what if I use the above concept to produce a (empty) legend area what will contain no items (I know it cannot be slanted, just to understand what can be done and not)

Q5: Then, what if I want to plot 2 of this empty Rectangular Legends that have 2 different semi-transparent color. What happen to any overlapping area if it exists in between them? Would that area remain semi-transparent or What I can I about it?
What about making that area hollow ?

-------------

Thanks for any clarification and help you can supply:
Sal

  Re: DrawXY V6 MFC - Draw a filled color rectangle over chart + points over Chart
Posted by Peter Kwan on May-26-2015 00:59
Hi Sal,

If suspect the issue is related to the getXCoor/getYCoor, or that the rectangle you
drawn is hidden behind some other objects (such as a non-transparent plot area).

When you call addLineLayer, the line is not immediately drawn. It is because
ChartDirector does not know the axis scale yet. Your code can always add more layers
and more data later, and ChartDirector can only determine the axis scale after all the
data are added. ChartDirector will assume all the data have already been added and
determine the axis scale when:

(a) The chart is to be displayed or output (eg. calling makeChart, or setting the chart to
the CChartViewer).

or

(b) The XYChart.layoutAxes or XYChart.layout is called, which automatically means that
all the data have been added and the axis scale can be determined.


If the axis scale has not been determined, the getXCoor and getYCoor may not work.
Since you only provide some fragments of your code, I am not sure if your code have
already called XYChart.layoutAxes or XYChart.layout or XYChart.makeChart, etc.. If
these methods are not called, most of the things are not drawn (including the plot area),
so anything you draw with the DrawArea may become hidden by other objects.

To draw in front of the chart, the makeChart should be used instead, like:

DrawArea *d = c->makeChart();

This method causes the axis scale to be determined, and all chart objects to be drawn,
so anything you draw will be on top of the chart. The "getDrawArea" method is mostly
useful for drawing at the background of the chart (such as to draw a company logo at a
corner, etc).

Regards
Peter Kwan

  Re: DrawXY V6 MFC - Draw a filled color rectangle over chart + points over Chart
Posted by Sal on May-26-2015 22:30
Thanks Peter for your replay

This is the code fragment that sets up any scaling prior either of my code attempts (now showing only one):

-----------

// Create a XYChart object
XYChart *c = new XYChart(iDrawingWidth, iDrawingHeight, Chart::brushedSilverColor(), 0x888888);

// Shift graph away from the margins of the windows (all 4)
// Make room at the top to put a Colored Header that will contain what I am observing
// This values where produced via experimentation
int iLeftMargin = 45;
int iRightMargin = 70;
int iTopmargin = 55;
int iBottomMargin = 80;

int iXAxisSizeInPixels = iDrawingWidth - iRightMargin - iLeftMargin;

// Fill the whole Plot area with Laminated Silver looking Brush
// Turn on both horizontal and vertical grid lines with light grey color (0xc0c0c0)
    PlotArea* pPlotArea = c->setPlotArea(iLeftMargin, iTopmargin,
iDrawingWidth - iRightMargin,
iDrawingHeight - iBottomMargin,
-1, -1, 0xc0c0c0, 0xc0c0c0, -1);

// Set Grid Background Area only to "wheat1" (solid color, a sort of light yellow)
pPlotArea->setBackground(0xFFE7BA);

c->setClipping();

    // Add a legend box area at top of the chart with horizontal layout. Use 12
    // pts Times Bold Italic font. Set the background and border color to Transparent.
    c->addLegend(iLeftMargin - 13, iTopmargin - 33, false, "timesbi.ttf", 12)->setBackground(Chart::Transparent);

Axis* pAxisX = c->xAxis();
Axis* pAxisY = c->yAxis();

// Add a title to the y axis using 12 pts Arial Bold Italic font
    pAxisY->setTitle("X", "arialbi.ttf", 12);

    // Add a title to the x axis using 12 pts Arial Bold Italic font
    pAxisX->setTitle("Y", "arialbi.ttf", 12);

// Set the axes line width in pixels
    pAxisX->setWidth(2);
    pAxisY->setWidth(2);

// Flip interpretation of axis since needed
pAxisX->setLinearScale(dLimits.dMinY, dLimits.dMaxY, (dLimits.dMaxY-dLimits.dMinY)/2, 1000);
pAxisY->setLinearScale(dLimits.dMinX, dLimits.dMaxX, 5000, 2500);

        // This Draws a 4 sides Polygon (it could be other than rectangle, if needed)
// by connecting a series of vertices by discrete lines
for (int n=0; n < iNumObstructions; n++)
{
LineLayer* pLL = c->addLineLayer(DoubleArray(ObstructionY[n], MAX_NUM_POINTS_TO_PLOT_AREA), ObstructionColor[n]);
pLL->setXData(DoubleArray(ObstructionX[n], MAX_NUM_POINTS_TO_PLOT_AREA));
pLL->setLineWidth(2);

// Show the Obstruction Label in the Legend table
sz.Format("OE %d", n);
c->addScatterLayer(DoubleArray(DataX, 1), DoubleArray(DataY, 1),
sz, Chart::CircleSymbol, 5, ObstructionColor[n], ObstructionColor[n]);
}


// This code attempt to draw a filled Polygon over the rectangle drawn above
DrawArea* pDrawArea = c->getDrawArea();        // Polygon is hidden
//DrawArea* pDrawArea = c->makeChart(); // This draws over Graph + Grid (obscuring Grid and any data been displayed underneath)

for (int n=0; n < iNumObstructions; n++)
{
// Overlay a polygon (slanted or not) over the above the hollow rectangle
int X_Vertices[4];
int Y_Vertices[4];

for (int i=0; i < 4; i++)
{
X_Vertices[i] = c->getXCoor(ObstructionX[n][i]);
Y_Vertices[i] = c->getYCoor(ObstructionY[n][i]);

}

pDrawArea->polygon(IntArray(X_Vertices, 4), IntArray(Y_Vertices, 4), ObstructionColor[n], ObstructionColor[n]);
         }

// Show all the Data Points as Red Dots if data has arrived
if (nPoints)
c->addScatterLayer(DoubleArray(DataX, nPoints), DoubleArray(DataY, nPoints),
s, Chart::CircleSymbol, iSize, 0xff0000, 0xff0000);

// Required to have the View to show the selected part into the Zoomed Control View:
// Compute the visible data scale based on the viewport coordinates using linear interpolation,
// and then sets the axis to that linear scale

pViewer->syncLinearAxisWithViewPort("x", pAxisX);
pViewer->syncLinearAxisWithViewPort("y", pAxisY);

// Flip orientation if needed
if (bFlipBothAxis)
{
pAxisY->setReverse();
pAxisX->setReverse();
}

// Set the chart image to the WinChartViewer
delete pViewer->getChart();
pViewer->setChart(c); // Output the chart

------------

I see that the "makeChart" draws what I had in mind, but it is over the Grid and the data points that are displayed, not behind the way I would like

As you see, I used the layer concept to draw a series of N Points, that when connected creating a rectangle. (may be there was a better way..., I though "DrawArea" could have helped me)

Is it possible to "DrawArea" my drawing elements into a added Layer ?
In other word put my "Drawing elements" into their own layer and change the order of appearance to achieve my expected result (behind grid)?

Lastly, Is there a good sample code that uses the "DrawArea" class as example, to study further ?

Thanks for any additional response you can supply
Sal

  Re: DrawXY V6 MFC - Draw a filled color rectangle over chart + points over Chart
Posted by Sal on May-26-2015 23:53
Solved, thanks a hint I did not notice till now...

I basically replaced the LineLayer Line that my code had with the Following fragment:

-----------

for (int n=0; n < iNumObstructions; n++)
{
//LineLayer* pLL = c->addLineLayer(DoubleArray(ObstructionY[n], MAX_NUM_POINTS_TO_PLOT_AREA), ObstructionColor[n]);
AreaLayer* pLL = c->addAreaLayer(DoubleArray(ObstructionY[n], MAX_NUM_POINTS_TO_PLOT_AREA), 0x80000000 | ObstructionColor[n]);

pLL->setXData(DoubleArray(ObstructionX[n], MAX_NUM_POINTS_TO_PLOT_AREA));
pLL->setLineWidth(2);

// Show the Obstruction Label in the Legend table
sz.Format("OE %d", n);
c->addScatterLayer(DoubleArray(DataX, 1), DoubleArray(DataY, 1),
sz, Chart::CircleSymbol, 5, ObstructionColor[n], ObstructionColor[n]);
}

Now the areas are appearing behind the Grid, as I wanted

The Or Operation w/0x80000000 make that color semi-transparent, so the grid and my data points are visible over these areas

------------

So, basically I did not use the DrawArea Class concept all together
Only clarification I need, then, is when I would Use such class (drawArea)

In your Real Time examples it is used to overlay a Track Cursor over the graph.

Any sample of anything that uses DrawArea to display something, other than graph, since it looks to me you can you it to draw anything ?

Thanks
Sal

  Re: DrawXY V6 MFC - Draw a filled color rectangle over chart + points over Chart
Posted by Peter Kwan on May-27-2015 03:40
Hi Sal,

The DrawArea is only suggested to draw track cursors, or custom things not built-into
ChartDirector. In the past, I have seen people using it to draw small triangles at the end
points of the axis so act as arrows. Occasionally, people will use ChartDirector to draw on
maps, for example, to change the color of a country or state based on certain statistics
(using the flood filling method DrawArea.fill). Sometimes the DrawArea is used for simple but
rarely used visual representations, such as the "wafer chart".

Regards
Peter Kwan

  Re: DrawXY V6 MFC - Draw a filled color rectangle over chart + points over Chart
Posted by Sal on May-27-2015 03:54
Peter,

Thanks for the clarification
Sal