## Drawing Polygon on Canvas in OnAfterDraw

TeeChart for ActiveX, COM and ASP
LAL
Newbie
Posts: 40
Joined: Fri Jun 20, 2008 12:00 am

### Drawing Polygon on Canvas in OnAfterDraw

In C++ ActiveX v8, I want to draw a direction arrow on my line series that points along the line.

I've calculated the points of the arrow (below) - but I'm not sure how to put them into the VARIANT for the Polygon?
Is it supposed to be an array of CPoints? Or an integer list of coordinates?

Code: Select all

``````//------------------------------------------------------------------------------
void MyDialog::OnAfterDraw()
//------------------------------------------------------------------------------
{
int nValues = m_Chart.Series(1).GetXValues().GetCount();
int nHalf = nValues / 2;

CPoint to(m_Chart.Series(0).CalcXPos(nHalf ), m_Chart.Series(0).CalcYPos(nHalf));
CPoint from(m_Chart.Series(0).CalcXPos(nHalf - 1), m_Chart.Series(0).CalcYPos(nHalf - 1));

int x1 = to.x;
int y1 = to.y;

int x2 = from.x;
int y2 = from.y;

CPoint p1, p2, p3;

int xres = 8;		// Size of arrow
double theta;
double theta2 = atan(0.5);
double hypot = sqrt(double(xres * xres) * 5/4);
double l;

p1 = CPoint(0, 0);
p2 = CPoint(0, 0);
p3 = CPoint(0, 0);

// Calculate angle of line
if (y2 == y1)
{
theta = ((x2 > x1) ? 0.0 : PI);
}
else
{
theta = atan((double) (y2 - y1) / (double) (x2 - x1));

if ((y2 > y1) && (x2 < x1))
{
theta = PI + theta;
}

if ((y1 > y2) && (x1 > x2))
{
theta = PI + theta;
}
}

// If arrow is in the middle, adjust P1 to line centre
if (TRUE)
{
l = 0.6 * hypot * cos(theta2);

p1.x = long(x2 + l * cos(theta) + 0.5);
p1.y = long(y2 + l * sin(theta) + 0.5);
}
else
{
p1.x = x2;
p1.y = y2;
}

p2.x = long((p1.x - hypot * cos (theta + theta2)) + 0.5);
p2.y = long((p1.y - hypot * sin (theta + theta2)) + 0.5);

p3.x = long((p1.x - hypot * cos (theta - theta2)) + 0.5);
p3.y = long((p1.y - hypot * sin (theta - theta2)) + 0.5);

m_Chart.GetCanvas().GetPen().SetColor(RGB(0, 0, 0));
m_Chart.GetCanvas().GetPen().SetWidth(1);
m_Chart.GetCanvas().GetBrush().SetColor(RGB(0, 0, 255));
m_Chart.GetCanvas().GetBrush().SetBackColor(RGB(0, 0, 255));

VARIANT pts; // <<<<<<------- How to construct this?
m_Chart.GetCanvas().Polygon(3, pts);
}
``````

Kyudos
Newbie
Posts: 2
Joined: Wed Sep 09, 2020 12:00 am

### Re: Drawing Polygon on Canvas in OnAfterDraw

After some trial and error I found this seems to work...is it correct?

Code: Select all

``````	VARIANT pts;
VariantInit(&pts);
pts.vt = VT_ARRAY|VT_I4;

SAFEARRAY* psa = SafeArrayCreateVector(VT_I4, 0, 6);
if (psa != NULL)
{
LONG i;
i = 0; SafeArrayPutElement(psa, &i, &p1.x);
i = 1; SafeArrayPutElement(psa, &i, &p1.y);
i = 2; SafeArrayPutElement(psa, &i, &p2.x);
i = 3; SafeArrayPutElement(psa, &i, &p2.y);
i = 4; SafeArrayPutElement(psa, &i, &p3.x);
i = 5; SafeArrayPutElement(psa, &i, &p3.y);
}

pts.parray = psa;
m_Chart.GetCanvas().Polygon(3, pts);

SafeArrayDestroy(psa);
``````

Yeray
Posts: 8910
Joined: Tue Dec 05, 2006 12:00 am
Location: Girona, Catalonia
Contact:

### Re: Drawing Polygon on Canvas in OnAfterDraw

Hello,

In the AddArrays example here, we populate arrays in a similar way than what you are doing. So it looks good to me.

- .h:

Code: Select all

``````class CVCTeeChart5Dlg : public CDialog
{
public:
//...
COleSafeArray XValues;
COleSafeArray YValues;
//...``````
- .cpp:

Code: Select all

``````BOOL CVCTeeChart5Dlg::OnInitDialog()
{
//...
DWORD numElements[] = {200000};

// Create the safe-arrays...
XValues.Create(VT_R8, 1, numElements);
YValues.Create(VT_R8, 1, numElements);

// Initialize them with values...
long index;
for(index=0; index<200000; index++) {
double val = index+((rand()*5)/RAND_MAX);
XValues.PutElement(&index, &val);
};

srand(100);

for(index=0; index<200000; index++) {
double val = index+rand();
YValues.PutElement(&index, &val);
};
//...``````
Best Regards,
 Yeray Alonso Development & Support Steema Software Av. Montilivi 33, 17003 Girona, Catalonia (SP) Please read our Bug Fixing Policy