Loading files
This file is pinned to the selected release. Download the original to open it in your design tool.
63c4d67e3This file is pinned to the selected release. Download the original to open it in your design tool.
#include "TimeSeriesCanvas.h"
#include "../CommonInterfaces/Common2dCanvasInterface.h"
#include "LinearMath/btAlignedObjectArray.h"
#include "TimeSeriesFontData.h"
#include "LinearMath/btVector3.h"
#include <stdio.h>
struct DataSource
{
unsigned char m_red;
unsigned char m_green;
unsigned char m_blue;
float m_lastValue;
bool m_hasLastValue;
DataSource()
: m_hasLastValue(false)
{
}
};
struct TimeSeriesInternalData
{
btAlignedObjectArray<DataSource> m_dataSources;
struct Common2dCanvasInterface* m_canvasInterface;
int m_canvasIndex;
int m_width;
int m_height;
float m_pixelsPerUnit;
float m_zero;
int m_timeTicks;
int m_ticksPerSecond;
float m_yScale;
int m_bar;
unsigned char m_backgroundRed;
unsigned char m_backgroundGreen;
unsigned char m_backgroundBlue;
unsigned char m_backgroundAlpha;
unsigned char m_textColorRed;
unsigned char m_textColorGreen;
unsigned char m_textColorBlue;
unsigned char m_textColorAlpha;
float getTime()
{
return m_timeTicks / (float)m_ticksPerSecond;
}
TimeSeriesInternalData(int width, int height)
: m_width(width),
m_height(height),
m_pixelsPerUnit(-100),
m_zero(height / 2.0),
m_timeTicks(0),
m_ticksPerSecond(100),
m_yScale(1),
m_bar(0),
m_backgroundRed(255),
m_backgroundGreen(255),
m_backgroundBlue(255),
m_backgroundAlpha(255),
m_textColorRed(0),
m_textColorGreen(0),
m_textColorBlue(255),
m_textColorAlpha(255)
{
}
};
TimeSeriesCanvas::TimeSeriesCanvas(struct Common2dCanvasInterface* canvasInterface, int width, int height, const char* windowTitle)
{
m_internalData = new TimeSeriesInternalData(width, height);
m_internalData->m_canvasInterface = canvasInterface;
if (canvasInterface)
{
m_internalData->m_canvasIndex = m_internalData->m_canvasInterface->createCanvas(windowTitle, m_internalData->m_width, m_internalData->m_height, 20, 50);
}
}
void TimeSeriesCanvas::addDataSource(const char* dataSourceLabel, unsigned char red, unsigned char green, unsigned char blue)
{
DataSource dataSource;
dataSource.m_red = red;
dataSource.m_green = green;
dataSource.m_blue = blue;
dataSource.m_lastValue = 0;
dataSource.m_hasLastValue = false;
if (dataSourceLabel)
{
int numSources = m_internalData->m_dataSources.size();
int row = numSources % 3;
int column = numSources / 3;
grapicalPrintf(dataSourceLabel, sTimeSeriesFontData, 50 + 200 * column, m_internalData->m_height - 48 + row * 16,
red, green, blue, 255);
}
m_internalData->m_dataSources.push_back(dataSource);
}
void TimeSeriesCanvas::setupTimeSeries(float yScale, int ticksPerSecond, int startTime, bool clearCanvas)
{
if (0 == m_internalData->m_canvasInterface)
return;
m_internalData->m_pixelsPerUnit = -(m_internalData->m_height / 3.f) / yScale;
m_internalData->m_ticksPerSecond = ticksPerSecond;
m_internalData->m_yScale = yScale;
m_internalData->m_dataSources.clear();
if (clearCanvas)
{
for (int i = 0; i < m_internalData->m_width; i++)
{
for (int j = 0; j < m_internalData->m_height; j++)
{
m_internalData->m_canvasInterface->setPixel(m_internalData->m_canvasIndex, i, j,
m_internalData->m_backgroundRed,
m_internalData->m_backgroundGreen,
m_internalData->m_backgroundBlue,
m_internalData->m_backgroundAlpha);
}
}
}
float zeroPixelCoord = m_internalData->m_zero;
float pixelsPerUnit = m_internalData->m_pixelsPerUnit;
float yPos = zeroPixelCoord + pixelsPerUnit * yScale;
float yNeg = zeroPixelCoord + pixelsPerUnit * -yScale;
grapicalPrintf("0", sTimeSeriesFontData, 2, zeroPixelCoord, m_internalData->m_textColorRed, m_internalData->m_textColorGreen, m_internalData->m_textColorBlue, m_internalData->m_textColorAlpha);
char label[1024];
sprintf(label, "%2.1f", yScale);
grapicalPrintf(label, sTimeSeriesFontData, 2, yPos, m_internalData->m_textColorRed, m_internalData->m_textColorGreen, m_internalData->m_textColorBlue, m_internalData->m_textColorAlpha);
sprintf(label, "%2.1f", -yScale);
grapicalPrintf(label, sTimeSeriesFontData, 2, yNeg, m_internalData->m_textColorRed, m_internalData->m_textColorGreen, m_internalData->m_textColorBlue, m_internalData->m_textColorAlpha);
m_internalData->m_canvasInterface->refreshImageData(m_internalData->m_canvasIndex);
}
TimeSeriesCanvas::~TimeSeriesCanvas()
{
if (m_internalData->m_canvasInterface && m_internalData->m_canvasIndex >= 0)
{
m_internalData->m_canvasInterface->destroyCanvas(m_internalData->m_canvasIndex);
}
delete m_internalData;
}
float TimeSeriesCanvas::getCurrentTime() const
{
return m_internalData->getTime();
}
void TimeSeriesCanvas::grapicalPrintf(const char* str, void* fontData, int rasterposx, int rasterposy, unsigned char red, unsigned char green, unsigned char blue, unsigned char alpha)
{
unsigned char c;
int x = 0;
int xx = 0;
while ((c = (unsigned char)*str++))
{
x = xx;
unsigned char* fontPtr = (unsigned char*)fontData;
char ch = c - 32;
int sx = ch % 16;
int sy = ch / 16;
for (int i = sx * 16; i < (sx * 16 + 16); i++)
{
int y = 0;
for (int j = sy * 16; j < (sy * 16 + 16); j++)
{
unsigned char packedColor = (fontPtr[i * 3 + 255 * 256 * 3 - (256 * j) * 3]);
//float colorf = packedColor ? 0.f : 1.f;
float colorf = packedColor / 255.f; // ? 0.f : 1.f;
btVector4 rgba(colorf, colorf, colorf, 1.f);
if (colorf)
{
if ((rasterposx + x >= 0) && (rasterposx + x < m_internalData->m_width) &&
(rasterposy + y >= 0) && (rasterposy + y < m_internalData->m_height))
{
m_internalData->m_canvasInterface->setPixel(m_internalData->m_canvasIndex, rasterposx + x, rasterposy + y,
red, green, blue, alpha);
}
}
y++;
}
x++;
}
xx += 10;
}
}
void TimeSeriesCanvas::shift1PixelToLeft()
{
int resetVal = 10;
int countdown = resetVal;
//shift pixture one pixel to the left
for (int j = 50; j < m_internalData->m_height - 48; j++)
{
for (int i = 40; i < this->m_internalData->m_width; i++)
{
unsigned char red, green, blue, alpha;
m_internalData->m_canvasInterface->getPixel(m_internalData->m_canvasIndex, i, j, red, green, blue, alpha);
m_internalData->m_canvasInterface->setPixel(m_internalData->m_canvasIndex, i - 1, j, red, green, blue, alpha);
}
if (!m_internalData->m_bar)
{
if (!countdown--)
{
countdown = resetVal;
m_internalData->m_canvasInterface->setPixel(m_internalData->m_canvasIndex, m_internalData->m_width - 1, j, 0, 0, 0, 255);
}
else
{
m_internalData->m_canvasInterface->setPixel(m_internalData->m_canvasIndex, m_internalData->m_width - 1, j, 255, 255, 255, 255);
}
}
else
{
m_internalData->m_canvasInterface->setPixel(m_internalData->m_canvasIndex, m_internalData->m_width - 1, j, 255, 255, 255, 255);
}
}
{
int resetVal = 2;
static int countdown = resetVal;
if (!countdown--)
{
countdown = resetVal;
m_internalData->m_canvasInterface->setPixel(m_internalData->m_canvasIndex, m_internalData->m_width - 1, m_internalData->m_zero, 0, 0, 0, 255);
}
}
{
int resetVal = 10;
static int countdown = resetVal;
if (!countdown--)
{
countdown = resetVal;
float zeroPixelCoord = m_internalData->m_zero;
float pixelsPerUnit = m_internalData->m_pixelsPerUnit;
float yPos = zeroPixelCoord + pixelsPerUnit * m_internalData->m_yScale;
float yNeg = zeroPixelCoord + pixelsPerUnit * -m_internalData->m_yScale;
m_internalData->m_canvasInterface->setPixel(m_internalData->m_canvasIndex, m_internalData->m_width - 1,
yPos, 0, 0, 0, 255);
m_internalData->m_canvasInterface->setPixel(m_internalData->m_canvasIndex, m_internalData->m_width - 1,
yNeg, 0, 0, 0, 255);
}
}
if (!m_internalData->m_bar)
{
char buf[1024];
float time = m_internalData->getTime();
sprintf(buf, "%2.0f", time);
grapicalPrintf(buf, sTimeSeriesFontData, m_internalData->m_width - 25, m_internalData->m_zero + 3, 0, 0, 0, 255);
m_internalData->m_bar = m_internalData->m_ticksPerSecond;
}
m_internalData->m_timeTicks++;
m_internalData->m_bar--;
}
void TimeSeriesCanvas::insertDataAtCurrentTime(float orgV, int dataSourceIndex, bool connectToPrevious)
{
if (0 == m_internalData->m_canvasInterface)
return;
btAssert(dataSourceIndex < m_internalData->m_dataSources.size());
float zero = m_internalData->m_zero;
float amp = m_internalData->m_pixelsPerUnit;
//insert some new value(s) in the right-most column
{
// float time = m_internalData->getTime();
float v = zero + amp * orgV;
m_internalData->m_canvasInterface->setPixel(m_internalData->m_canvasIndex, m_internalData->m_width - 1, v,
m_internalData->m_dataSources[dataSourceIndex].m_red,
m_internalData->m_dataSources[dataSourceIndex].m_green,
m_internalData->m_dataSources[dataSourceIndex].m_blue,
255);
if (connectToPrevious && m_internalData->m_dataSources[dataSourceIndex].m_hasLastValue)
{
for (int value = m_internalData->m_dataSources[dataSourceIndex].m_lastValue; value <= v; value++)
{
if (value >= 0 && value < float(m_internalData->m_height - 1))
{
m_internalData->m_canvasInterface->setPixel(m_internalData->m_canvasIndex, m_internalData->m_width - 1, value,
m_internalData->m_dataSources[dataSourceIndex].m_red,
m_internalData->m_dataSources[dataSourceIndex].m_green,
m_internalData->m_dataSources[dataSourceIndex].m_blue,
255);
}
}
for (int value = v; value <= m_internalData->m_dataSources[dataSourceIndex].m_lastValue; value++)
{
if (value >= 0 && value < float(m_internalData->m_height - 1))
{
m_internalData->m_canvasInterface->setPixel(m_internalData->m_canvasIndex, m_internalData->m_width - 1, value,
m_internalData->m_dataSources[dataSourceIndex].m_red,
m_internalData->m_dataSources[dataSourceIndex].m_green,
m_internalData->m_dataSources[dataSourceIndex].m_blue,
255);
}
}
}
m_internalData->m_dataSources[dataSourceIndex].m_lastValue = v;
m_internalData->m_dataSources[dataSourceIndex].m_hasLastValue = true;
}
}
void TimeSeriesCanvas::nextTick()
{
shift1PixelToLeft();
m_internalData->m_canvasInterface->refreshImageData(m_internalData->m_canvasIndex);
}