Arduino Icon Library - c++

I'm working on an Arduino project and I want to display icons on a NeoMatrix 8x8 panel.
Initially, I went in direction that relied on inheritance, and requested some input on Arduino Stack Exchange where I was advised to go another route, and to ask my question elsewhere is it pertained more to C++ than to Arduino.
Instead of relying on inheritance, I was recommended to store my icons in PROGMEM and have the program build the icons from there.
I attempted the approach as much as I could, but I'm not at ease so I'd like some further insight!
The idea is to have a byte array that composes an 8x8 icon.
The values are 0-2, each representing a color set in an RGB struct array.
From what I believe I understand, my byte array stored in PROGMEM is read as a pointer, and needs to be accessed using ppm_read_byte.
I am unsure on how to handle the RGB struct. When I attempt to read it from PROGMEM, it causes my program to crash. So I removed it from PROGMEM, and the icon displays correctly. My byte array is in PROGMEM, but not the colors.
I am aware that I have a serious lack of knowledge about pointers which I need to work on...
Also, the idea is to have a collection of icons, so should I store all my icons (byte arrays and colors) in a header file? Will that not bloat it?
Thank you in advance for insight on this!
header.h
typedef struct {
byte r;
byte g;
byte b;
} RGB;
const byte PROGMEM WifiIcon[8][8] = {
{1, 1, 1, 1, 1, 1, 1, 1},
{1, 1, 2, 2, 2, 2, 1, 1},
{1, 2, 1, 1, 1, 1, 2, 1},
{2, 1, 2, 2, 2, 2, 1, 2},
{1, 2, 1, 1, 1, 1, 2, 1},
{1, 1, 1, 2, 2, 1, 1, 1},
{1, 1, 2, 1, 1, 2, 1, 1},
{0, 0, 0, 1, 1, 0, 0, 0}
};
const RGB WifiIconColors[3] = {
{0, 0, 0},
{0, 0, 0},
{0, 200, 61}
};
ESP8266Neomatrix.ino
#include "header.h"
void printIcon(int startPosition, const byte (&icon)[8][8], const RGB (&colors)[3]){
for (int i = 0; i < 8; i++) {
for (int j = 0; j < 8; j++) {
byte currentPixel = pgm_read_byte(&icon[i][j]);
const RGB currentColor = colors[currentPixel];
byte red = currentColor.r;
byte green = currentColor.g;
byte blue = currentColor.b;
matrix.setPixelColor(startPosition++, red, green, blue);
}
}
}
https://gist.github.com/Nate1661/0eea9200e9d1c86187c2acf205ba3602

If you want the RGB data to reside in PROGMEM, since it is not a native type handled by pgm_read_XXX functions, just read it with memcpy_P():
RGB currentColor;
memcpy_P(&currentColor, colors + currentPixel, sizeof(RGB));
If this crashes, then perhaps there is an issue with the value of currentPixel that you read.

Related

How to create a variable alias on a array of arrays in c++

Say I have the following array of arrays of floats and a selector index:
const float array[][3] = {
{0, 1, 2,},
{0, 1, 2,},
{0, 1, 2,},
{0, 1, 2,},
{0, 1, 2,},
};
/// The one that select one of the five arrays
int selector = 0;
To streamline my code, I'd like to declare an array that points to the current array selector to further use it as a simple array of float, as follows:
/// A shortcut to the current selection
const float currentArray[] = array[selector];
for (int i = 0; i<3: i++) {
process(currentArray[iI]);
}
As this does not compile (initialization expected with {}), how could I declare my current-array alias?
If I understand you right you need type alias for your currentArray.
In this case you can do the following:
const float array[][3] = {
{0, 1, 2,},
{0, 1, 2,},
{0, 1, 2,},
{0, 1, 2,},
{0, 1, 2,},
};
/// The one that select one of the five arrays
int selector = 0;
using InnerArrayT = const float (&)[3];
InnerArrayT currentArray = array[selector];
for (int i = 0; i<3: i++) {
process(currentArray[i]);
}
Or as #tadman has pointed out you can use auto & but be careful because if you use just auto(without &) then currentArray type will be const float * instead of const float (&)[3].

GEOS OverlayOp intersection operation

I am using GEOS 3.6.2 to compute an intersection between two polygons. I was able to construct my polygons, but when I try to compute the intersection it won't work.
Compiling my program in Debug mode, I get the error message:
The inferior stopped because it received a signal from the operating
system.
Signal name : SIGSEG
Signal meaning : Segmentation fault
Any idea where I'm wrong?
Here is my code:
#include <geos/geom/Polygon.h>
#include <geos/geom/LinearRing.h>
#include <geos/geom/CoordinateSequenceFactory.h>
#include <geos/geom/GeometryFactory.h>
#include <geos/geom/Geometry.h>
#include <geos/operation/overlay/OverlayOp.h>
#include <iostream>
#include <array>
////////////////////////////////////////////////////////////////////////////////
geos::geom::Polygon* MakePoly(std::vector<std::vector<int>> const& polyCoords)
{
geos::geom::GeometryFactory* factory = geos::geom::GeometryFactory::create().get();
geos::geom::CoordinateSequence* temp = factory->getCoordinateSequenceFactory()->create((std::size_t) 0, 0);
std::vector<std::vector<int>>::const_iterator it_x = polyCoords.begin();
int size = it_x->size();
for (int i=0; i<size; i++)
{
temp->add(geos::geom::Coordinate(polyCoords[0][i], polyCoords[1][i]));
}
geos::geom::LinearRing *shell=factory->createLinearRing(temp);
//NULL in this case could instead be a collection of one or more holes
//in the interior of the polygon
return factory->createPolygon(shell,NULL);
}
////////////////////////////////////////////////////////////////////////////////
int main()
{
// Create geometry.
std::vector<std::vector<int>> polyCoords1 = {
{1, 1, 2, 2, 1, 1, 4, 5, 4, 1},
{1, 2, 2, 4, 4, 5, 5, 3, 1, 1}
};
geos::geom::Polygon* poly1 = MakePoly(polyCoords1);
std::vector<std::vector<int>> polyCoords2 = {
{4, 4, 6, 6, 4},
{1, 5, 5, 1, 1}
};
geos::geom::Polygon* poly2 = MakePoly(polyCoords2);
// Actually perform the operation.
geos::operation::overlay::OverlayOp intersection(poly1, poly2);
// Extracting the geometry of the intersection (position of the error).
geos::geom::Geometry* intersectionGeo = intersection.getResultGeometry( geos::operation::overlay::OverlayOp::OpCode::opINTERSECTION );
std::cout<<intersectionGeo->getArea()<<std::endl;
}
The problem in your code is getting the GeometryFactory pointer.
geos::geom::GeometryFactory::create() returns a smart pointer (std::unique_ptr) so after this line:
geos::geom::GeometryFactory* factory = geos::geom::GeometryFactory::create().get();
The unique_ptr returned by create is disposed.
Change that line with:
geos::geom::GeometryFactory::Ptr factory = geos::geom::GeometryFactory::create();
And the code works.

Should each element of a 2d array create a new Sprite object?

I'm trying to create a tilemap with a 2d array and was struggling slightly with it. When I iterate through the array should I create a new Sprite object for each element in the array or is it possible to just create a sprite object for each of the different tiles then copy them to the relevant positions on screen. For example - note Rows and Columns are const ints already initialised to 5
int MazeMap[Rows][Columns] = { //Should the array type be int or Sprite*
{1, 1, 1, 1, 1},
{1, 0, 0, 0, 1},
{1, 0, 1, 1, 1},
{1, 0, 0, 0, 1},
{1, 1, 1, 1, 1}
};
for(int x = 0; x<Rows; x++)
{
for(int y = 0; y<Columns; y++)
{
if(MazeMap[x][y]==1)
{
//should I create a new Sprite object here or should I create
// a Tile1 sprite object above the array and then just pass it into
//this array to draw it to the screen?
}
}
}
To me it just seems really inefficient to have (in this case) 25 sprite objects when you can just have 2 sprite objects and copy them to a number of different locations on screen.

Member List implementation of different class not working

I can't seem to get the implementation of my member list correct. I want to DEFAULT initialize my Set members nyX and nyY, however I keep getting an error.
class Location
{
public:
vector<int> nyXv = { 0, 1, 2, 3, 4, 5};
vector<int> nyYv = { 0, 1, 2, 3, 4, 5 };
Set nyX(vector<int>);
Set nyY(vector<int>);
Location();
~Location();
};
Location::Location()
:nyX(nyXv), nyY(nyYv)
{
}
Look at this example
You can initialize you vectors like this:
class Location
{
public:
vector<int> nyXv;// = { 0, 1, 2, 3, 4, 5};
vector<int> nyYv;// = { 0, 1, 2, 3, 4, 5 };
///...
Location();
~Location();
};
static const int arrX[] = {0, 1, 2, 3, 4, 5};
static const int arrY[] = {0, 1, 2, 3, 4, 5};
Location::Location()
:nyXv(arrX, arrX + sizeof(arrX) / sizeof(arrX[0]) )
,nyYv(arrY, arrY + sizeof(arrY) / sizeof(arrY[0]))
{
}
P.S. Of course there are many ways to improve this code but it should give you an idea

Unit-testing code with a large number of interdependent conditions

I'm testing a set of output styler classes which style data before outputting it to an output interface. The behavior of each styler is dependent on up to 5 different conditions (at the moment, but a sixth is on the way) with regard to the object being outputted: isKey, isDefault, isEmpty, isReadOnly, isAccessible
So one styler might output nothing if it has readonly data, while another might show "access denied".
At the moment I am testing along these lines, but the tests are exploding as more conditions are added.
{
// isKey, isDefault, isEmpty, isReadOnly, isAccessible
ValueOutputTester::TestConditions conditions = {0, 0, 0, 0, 0};
EXPECT_EQ(valueOutputTester(conditions), accessDeniedOutput);
}
{
ValueOutputTester::TestConditions conditions = {0, 0, 0, 0, 1};
EXPECT_EQ(valueOutputTester(conditions), normalOutput);
}
{
ValueOutputTester::TestConditions conditions = {0, 0, 0, 1, 0};
EXPECT_EQ(valueOutputTester(conditions), accessDeniedOutput);
}
{
ValueOutputTester::TestConditions conditions = {0, 0, 0, 1, 1};
EXPECT_EQ(valueOutputTester(conditions), accessDeniedOutput);
}
{
ValueOutputTester::TestConditions conditions = {0, 0, 1, 0, 0};
EXPECT_EQ(valueOutputTester(conditions), emptyOutput);
}
...
Can you recommend a better way of doing this?
You might write a test helper method that lets you specify condition patterns and that generates all combinations that match the pattern, e.g. assuming -1 means 'either 0 or 1':
TestPattern pattern = {-1, -1, 1, -1, -1};
ExpectForPattern(pattern, emptyOutput);