The version of the server that passes parameters by value instead of reference (mentioned in the last post) is ready but not yet uploaded to Buffet. The Buffet server isn't loading pages, so there must be maintenance, development, or a server issue preventing its use. The repos will be updated as soon as possible.
Also, minor testing of the concave hull groups has been set up, and I'll post the results later this week. The algorithm is as follows.
Given a set of adjacent points (a Group as defined in earlier posts), for each point in the group:
- Check all adjacent points, including diagonal points. Record the coordinates of all 0-datapoints adjacent.
- If there are only one or two adjacent 0-datapoints, or more than three, add the point being evaluated to the list of hull points.
- Else, if there are three 0-datapoints, check to see if the set of adjacent 0-datapoints is linear. If it is not linear, add the point being evaluated to the list of hull points. Otherwise, it is part of the hull but is unnecessary to determine the shape of the hull, so do not add it to the point list.
- Else, if there are no adjacent 0-datapoints, do not add it to the point list.
The implementation has not been tested yet, and improvements are probably necessary, but having worked this out by hand on several data sets, it seems to be a sufficient starting point. In addition, it can readily be extended to higher dimensions with a concrete definition of adjacency in that dimension.
For two dimensions, the current C++ implementation is as follows.
void NumViews::addHullGroup(TactonicFrame *frame, uint8_t * checkedArray, int x, int y) {
Group * g = new Group();
Point * p = NULL;
int zeropoints[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
std::queue<Point *> * q = new std::queue<Point *>();
int cols = device.cols, rows = device.rows, data, zerocount;
q->push(new Point(x, y, frame->forces[y * cols + x]));
while (q->size() > 0) {
p = q->front();
q->pop();
x = p->getX();
y = p->getY();
if (!checkedArray[y * cols + x]) {
data = p->getData();
zerocount = 0;
checkedArray[y * cols + x] = 1;
if (x - 1 >= 0 && frame->forces[y * cols + (x - 1)] > 0 && !checkedArray[y * cols + (x - 1)]) {
q->push(new Point(x - 1, y, frame->forces[y * cols + (x - 1)]));
}
else {
zeropoints[zerocount] = x - 1;
zeropoints[8 + zerocount++] = y;
}
if (x - 1 >= 0 && y - 1 >= 0 && frame->forces[(y - 1) * cols + (x - 1)] > 0 && !checkedArray[(y - 1) * cols + (x - 1)]) {
q->push(new Point(x - 1, y - 1, frame->forces[(y - 1) * cols + (x - 1)]));
}
else {
zeropoints[zerocount] = x - 1;
zeropoints[8 + zerocount++] = y - 1;
}
if (y - 1 >= 0 && frame->forces[(y - 1) * cols + x] > 0 && !checkedArray[(y - 1) * cols + x]) {
q->push(new Point(x, y - 1, frame->forces[(y - 1) * cols + x]));
}
else {
zeropoints[zerocount] = x;
zeropoints[8 + zerocount++] = y - 1;
}
if (x + 1 < cols && y - 1 >= 0 && frame->forces[(y - 1) * cols + (x + 1)] > 0 && !checkedArray[(y - 1) * cols + (x + 1)]) {
q->push(new Point(x + 1, y - 1, frame->forces[(y - 1) * cols + (x + 1)]));
}
else {
zeropoints[zerocount] = x + 1;
zeropoints[8 + zerocount++] = y - 1;
}
if (x + 1 < cols && frame->forces[y * cols + (x + 1)] > 0 && !checkedArray[y * cols + (x + 1)]) {
q->push(new Point(x + 1, y, frame->forces[y * cols + (x + 1)]));
}
else {
zeropoints[zerocount] = x + 1;
zeropoints[8 + zerocount++] = y;
}
if (x + 1 < cols && y + 1 < rows && frame->forces[(y + 1) * cols + (x + 1)] > 0 && !checkedArray[(y + 1) * cols + (x + 1)]) {
q->push(new Point(x + 1, y + 1, frame->forces[(y + 1) * cols + (x + 1)]));
}
else {
zeropoints[zerocount] = x + 1;
zeropoints[8 + zerocount++] = y + 1;
}
if (y + 1 < rows && frame->forces[(y + 1) * cols + x] > 0 && !checkedArray[(y + 1) * cols + x]) {
q->push(new Point(x, y + 1, frame->forces[(y + 1) * cols + x]));
}
else {
zeropoints[zerocount] = x;
zeropoints[8 + zerocount++] = y + 1;
}
if (x - 1 >= 0 && y + 1 < rows &&frame->forces[(y + 1) * cols + (x - 1)] > 0 && !checkedArray[(y + 1) * cols + (x - 1)]) {
q->push(new Point(x - 1, y + 1, frame->forces[(y + 1) * cols + (x - 1)]));
}
else {
zeropoints[zerocount] = x - 1;
zeropoints[8 + zerocount++] = y + 1;
}
if (zerocount == 3) {
for (int i = 0; i < zerocount - 1; i++) {
if (zeropoints[i] != zeropoints[i + 1] || zeropoints[i + 8] != zeropoints[i + 9]) {
g->addPoint(p, 'x');
}
}
}
else if (zerocount != 0) {
g->addPoint(p, 'x');
}
}
else {
std::cerr << "Deleting a point in NumViews::addHullGroup" << std::endl;
delete p;
}
p = NULL;
}
std::cerr << "Deleting q in NumViews::addHullGroup" << std::endl;
delete q;
if (g->size() > 0) {
g->calculateCenter();
pressure_groups.push_back(g);
}
else {
delete g;
}
}