<commit_before>#include <iostream>
#include <fstream>
#include <string>
#include <zlib.h>
#include "vector_tile.pb.h"

#define XMAX 4096
#define YMAX 4096

extern "C" {
	#include "graphics.h"
	#include "clip.h"
}

struct line {
	int x0;
	int y0;
	int x1;
	int y1;
};

struct point {
	int x;
	int y;
};

#define MAX_POINTS 10000
struct pointlayer {
	struct point *points;
	int npoints;
	int npalloc;

	struct pointlayer *next;
};

struct linelayer {
	struct line *lines;
	int nlines;
	int nlalloc;
	unsigned char *used;

	struct linelayer *next;
};

class env {
public:
	mapnik::vector::tile tile;
	mapnik::vector::tile_layer *layer;
	mapnik::vector::tile_feature *feature;

	int x;
	int y;

	int cmd_idx;
	int cmd;
	int length;

	struct linelayer *linelayers;

	struct pointlayer *pointlayers;
	struct pointlayer **used;
};

#define MOVE_TO 1
#define LINE_TO 2
#define CLOSE_PATH 7
#define CMD_BITS 3

struct graphics {
	int width;
	int height;
	env *e;
};

struct pointlayer *new_pointlayer() {
	struct pointlayer *p = (struct pointlayer *) malloc(sizeof(struct pointlayer));
	p->npalloc = 1024;
	p->npoints = 0;
	p->points = (struct point *) malloc(p->npalloc * sizeof(struct point));
	p->next = NULL;

	return p;
}

struct linelayer *new_linelayer() {
	struct linelayer *l = (struct linelayer *) malloc(sizeof(struct linelayer));
	l->nlalloc = 1024;
	l->nlines = 0;
	l->lines = (struct line *) malloc(l->nlalloc * sizeof(struct line));
	l->next = NULL;
	l->used = (unsigned char *) malloc(256 * 256 * sizeof(unsigned char));

	return l;
}

struct graphics *graphics_init(int width, int height) {
	GOOGLE_PROTOBUF_VERIFY_VERSION;

	env *e = new env;

	e->linelayers = new_linelayer();
	e->pointlayers = new_pointlayer();
	e->used = (struct pointlayer **) malloc(256 * 256 * sizeof(struct pointlayer *));
	int i;
	for (i = 0; i < 256 * 256; i++) {
		e->used[i] = e->pointlayers;
	}

	struct graphics *g = (struct graphics *) malloc(sizeof(struct graphics));
	g->e = e;
	g->width = width;
	g->height = height;

	return g;
}

// from mapnik-vector-tile/src/vector_tile_compression.hpp
static inline int compress(std::string const& input, std::string & output)
{
	z_stream deflate_s;
	deflate_s.zalloc = Z_NULL;
	deflate_s.zfree = Z_NULL;
	deflate_s.opaque = Z_NULL;
	deflate_s.avail_in = 0;
	deflate_s.next_in = Z_NULL;
	deflateInit(&deflate_s, Z_DEFAULT_COMPRESSION);
	deflate_s.next_in = (Bytef *)input.data();
	deflate_s.avail_in = input.size();
	size_t length = 0;
	do {
		size_t increase = input.size() / 2 + 1024;
		output.resize(length + increase);
		deflate_s.avail_out = increase;
		deflate_s.next_out = (Bytef *)(output.data() + length);
		int ret = deflate(&deflate_s, Z_FINISH);
		if (ret != Z_STREAM_END && ret != Z_OK && ret != Z_BUF_ERROR) {
			return -1;
		}
		length += (increase - deflate_s.avail_out);
	} while (deflate_s.avail_out == 0);
	deflateEnd(&deflate_s);
	output.resize(length);
	return 0;
}

static void op(env *e, int cmd, int x, int y);

void out(struct graphics *gc, int transparency, double gamma, int invert, int color, int color2, int saturate, int mask) {
	env *e = gc->e;
	int i;

	e->layer = e->tile.add_layers();
	e->layer->set_name("lines");
	e->layer->set_version(1);
	e->layer->set_extent(XMAX);

	struct linelayer *l;
	for (l = e->linelayers; l != NULL; l = l->next){
		e->feature = e->layer->add_features();
		e->feature->set_type(mapnik::vector::tile::LineString);

		e->x = 0;
		e->y = 0;

		e->cmd_idx = -1;
		e->cmd = -1;
		e->length = 0;

		for (i = 0; i < l->nlines; i++) {
			// printf("draw %d %d to %d %d\n", e->lines[i].x0, e->lines[i].y0, e->lines[i].x1, e->lines[i].y1);

			if (l->lines[i].x0 != e->x || l->lines[i].y0 != e->y || e->length == 0) {
				op(e, MOVE_TO, l->lines[i].x0, l->lines[i].y0);
			}

			op(e, LINE_TO, l->lines[i].x1, l->lines[i].y1);
		}

		if (e->cmd_idx >= 0) {
			//printf("old command: %d %d\n", e->cmd, e->length);
			e->feature->set_geometry(e->cmd_idx,
				(e->length << CMD_BITS) |
				(e->cmd & ((1 << CMD_BITS) - 1)));
		}
	}

	//////////////////////////////////

	e->layer = e->tile.add_layers();
	e->layer->set_name("points");
	e->layer->set_version(1);
	e->layer->set_extent(XMAX);

	struct pointlayer *p;
	for (p = e->pointlayers; p != NULL; p = p->next) {
		if (p->npoints != 0) {
			e->feature = e->layer->add_features();
			e->feature->set_type(mapnik::vector::tile::LineString);

			e->x = 0;
			e->y = 0;

			e->cmd_idx = -1;
			e->cmd = -1;
			e->length = 0;

			for (i = 0; i < p->npoints; i++) {
				op(e, MOVE_TO, p->points[i].x, p->points[i].y);
				op(e, LINE_TO, p->points[i].x + 1, p->points[i].y);
			}

			if (e->cmd_idx >= 0) {
				e->feature->set_geometry(e->cmd_idx,
					(e->length << CMD_BITS) |
					(e->cmd & ((1 << CMD_BITS) - 1)));
			}
		}
	}

	//////////////////////////////////

	std::string s;
	e->tile.SerializeToString(&s);

	std::string compressed;
	compress(s, compressed);

	std::cout << compressed;
}

static void op(env *e, int cmd, int x, int y) {
	// printf("%d %d,%d\n", cmd, x, y);
	// printf("from cmd %d to %d\n", e->cmd, cmd);

	if (cmd != e->cmd) {
		if (e->cmd_idx >= 0) {
			// printf("old command: %d %d\n", e->cmd, e->length);
			e->feature->set_geometry(e->cmd_idx,
				(e->length << CMD_BITS) |
				(e->cmd & ((1 << CMD_BITS) - 1)));
		}

		e->cmd = cmd;
		e->length = 0;
		e->cmd_idx = e->feature->geometry_size();

		e->feature->add_geometry(0); // placeholder
	}

	if (cmd == MOVE_TO || cmd == LINE_TO) {
		int dx = x - e->x;
		int dy = y - e->y;
		// printf("new geom: %d %d\n", x, y);

		e->feature->add_geometry((dx << 1) ^ (dx >> 31));
		e->feature->add_geometry((dy << 1) ^ (dy >> 31));

		e->x = x;
		e->y = y;
		e->length++;
	} else if (cmd == CLOSE_PATH) {
		e->length++;
	}
}

// http://rosettacode.org/wiki/Bitmap/Bresenham's_line_algorithm#C
int lineused(struct linelayer *l, int x0, int y0, int x1, int y1) {
	int dx = abs(x1 - x0), sx = (x0 < x1) ? 1 : -1;
	int dy = abs(y1 - y0), sy = (y0 < y1) ? 1 : -1;
	int err = ((dx > dy) ? dx : -dy) / 2, e2;

	while (1) {
		if (x0 == x1 && y0 == y1) {
			break;
		}

		if (x0 >= 0 && y0 >=0 && x0 < 256 && y0 < 256) {
			if (l->used[y0 * 256 + x0]) {
				return 1;
			}
		}

		e2 = err;
		if (e2 > -dx) {
			err -= dy;
			x0 += sx;
		}
		if (e2 <  dy) {
			err += dx;
			y0 += sy;
		}
	}

	return 0;
}

// http://rosettacode.org/wiki/Bitmap/Bresenham's_line_algorithm#C
void useline(struct linelayer *l, int x0, int y0, int x1, int y1) {
	int dx = abs(x1 - x0), sx = (x0 < x1) ? 1 : -1;
	int dy = abs(y1 - y0), sy = (y0 < y1) ? 1 : -1;
	int err = ((dx > dy) ? dx : -dy) / 2, e2;

	while (1) {
		if (x0 == x1 && y0 == y1) {
			break;
		}

		if (x0 >= 0 && y0 >=0 && x0 < 256 && y0 < 256) {
			l->used[y0 * 256 + x0] = 1;
		}

		e2 = err;
		if (e2 > -dx) {
			err -= dy;
			x0 += sx;
		}
		if (e2 <  dy) {
			err += dx;
			y0 += sy;
		}
	}
}

int drawClip(double x0, double y0, double x1, double y1, struct graphics *gc, double bright, double hue, int antialias, double thick, struct tilecontext *tc) {
	double mult = XMAX / gc->width;
	int accept = clip(&x0, &y0, &x1, &y1, 0, 0, XMAX / mult, YMAX / mult);

	if (accept) {
		int xx0 = x0 * mult;
		int yy0 = y0 * mult;
		int xx1 = x1 * mult;
		int yy1 = y1 * mult;

		// Guarding against rounding error

		if (xx0 < 0) {
			xx0 = 0;
		}
		if (xx0 > XMAX - 1) {
			xx0 = XMAX - 1;
		}
		if (yy0 < 0) {
			yy0 = 0;
		}
		if (yy0 > YMAX - 1) {
			yy0 = YMAX - 1;
		}

		if (xx1 < 0) {
			xx1 = 0;
		}
		if (xx1 > XMAX - 1) {
			xx1 = XMAX - 1;
		}
		if (yy1 < 0) {
			yy1 = 0;
		}
		if (yy1 > YMAX - 1) {
			yy1 = YMAX - 1;
		}

		env *e = gc->e;
		struct linelayer *l = e->linelayers;

		if (xx0 != xx1 || yy0 != yy1) {
			while (l->nlines > MAX_POINTS || lineused(l, x0, y0, x1, y1)) {
				if (l->next == NULL) {
					l->next = new_linelayer();
				}
				l = l->next;
			}

			if (l->nlines + 1 >= l->nlalloc) {
				l->nlalloc *= 2;
				l->lines = (struct line *) realloc((void *) l->lines, l->nlalloc * sizeof(struct line));
			}

			useline(l, x0, y0, x1, y1);

			l->lines[l->nlines].x0 = xx0;
			l->lines[l->nlines].y0 = yy0;
			l->lines[l->nlines].x1 = xx1;
			l->lines[l->nlines].y1 = yy1;

			l->nlines++;
		}
	}

	return 0;
}

void drawPixel(double x, double y, struct graphics *gc, double bright, double hue, struct tilecontext *tc) {
	x += .5;
	y += .5;

	double mult = XMAX / gc->width;
	int xx = x * mult;
	int yy = y * mult;

	// Guarding against rounding error

	if (xx < 0) {
		xx = 0;
	}
	if (xx > XMAX - 1) {
		xx = XMAX - 1;
	}
	if (yy < 0) {
		yy = 0;
	}
	if (yy > YMAX - 1) {
		yy = YMAX - 1;
	}

	env *e = gc->e;

	int xu = x * 256 / gc->width;
	int yu = y * 256 / gc->height;
	if (xu < 0) {
		xu = 0;
	}
	if (xu > 255) {
		xu = 255;
	}
	if (yu < 0) {
		yu = 0;
	}
	if (yu > 255) {
		yu = 255;
	}

	struct pointlayer *p = e->used[256 * yu + xu];
	while (p->npoints >= MAX_POINTS) {
		if (p->next == NULL) {
			p->next = new_pointlayer();
		}
		p = p->next;
	}
	if (p->next == NULL) {
		p->next = new_pointlayer();
	}
	e->used[256 * yu + xu] = p->next;

	if (p->npoints + 1 >= p->npalloc) {
		p->npalloc *= 2;
		p->points = (struct point *) realloc((void *) p->points, p->npalloc * sizeof(struct point));
	}

	p->points[p->npoints].x = xx;
	p->points[p->npoints].y = yy;

	p->npoints++;
}

void drawBrush(double x, double y, struct graphics *gc, double bright, double brush, double hue, int gaussian, struct tilecontext *tc) {
	drawPixel(x - .5, y - .5, gc, bright, hue, tc);
}
<commit_msg>Clip a little beyond tile boundaries to keep joins out of sight.<commit_after>#include <iostream>
#include <fstream>
#include <string>
#include <zlib.h>
#include "vector_tile.pb.h"

#define XMAX 4096
#define YMAX 4096

extern "C" {
	#include "graphics.h"
	#include "clip.h"
}

struct line {
	int x0;
	int y0;
	int x1;
	int y1;
};

struct point {
	int x;
	int y;
};

#define MAX_POINTS 10000
struct pointlayer {
	struct point *points;
	int npoints;
	int npalloc;

	struct pointlayer *next;
};

struct linelayer {
	struct line *lines;
	int nlines;
	int nlalloc;
	unsigned char *used;

	struct linelayer *next;
};

class env {
public:
	mapnik::vector::tile tile;
	mapnik::vector::tile_layer *layer;
	mapnik::vector::tile_feature *feature;

	int x;
	int y;

	int cmd_idx;
	int cmd;
	int length;

	struct linelayer *linelayers;

	struct pointlayer *pointlayers;
	struct pointlayer **used;
};

#define MOVE_TO 1
#define LINE_TO 2
#define CLOSE_PATH 7
#define CMD_BITS 3

struct graphics {
	int width;
	int height;
	env *e;
};

struct pointlayer *new_pointlayer() {
	struct pointlayer *p = (struct pointlayer *) malloc(sizeof(struct pointlayer));
	p->npalloc = 1024;
	p->npoints = 0;
	p->points = (struct point *) malloc(p->npalloc * sizeof(struct point));
	p->next = NULL;

	return p;
}

struct linelayer *new_linelayer() {
	struct linelayer *l = (struct linelayer *) malloc(sizeof(struct linelayer));
	l->nlalloc = 1024;
	l->nlines = 0;
	l->lines = (struct line *) malloc(l->nlalloc * sizeof(struct line));
	l->next = NULL;
	l->used = (unsigned char *) malloc(256 * 256 * sizeof(unsigned char));

	return l;
}

struct graphics *graphics_init(int width, int height) {
	GOOGLE_PROTOBUF_VERIFY_VERSION;

	env *e = new env;

	e->linelayers = new_linelayer();
	e->pointlayers = new_pointlayer();
	e->used = (struct pointlayer **) malloc(256 * 256 * sizeof(struct pointlayer *));
	int i;
	for (i = 0; i < 256 * 256; i++) {
		e->used[i] = e->pointlayers;
	}

	struct graphics *g = (struct graphics *) malloc(sizeof(struct graphics));
	g->e = e;
	g->width = width;
	g->height = height;

	return g;
}

// from mapnik-vector-tile/src/vector_tile_compression.hpp
static inline int compress(std::string const& input, std::string & output)
{
	z_stream deflate_s;
	deflate_s.zalloc = Z_NULL;
	deflate_s.zfree = Z_NULL;
	deflate_s.opaque = Z_NULL;
	deflate_s.avail_in = 0;
	deflate_s.next_in = Z_NULL;
	deflateInit(&deflate_s, Z_DEFAULT_COMPRESSION);
	deflate_s.next_in = (Bytef *)input.data();
	deflate_s.avail_in = input.size();
	size_t length = 0;
	do {
		size_t increase = input.size() / 2 + 1024;
		output.resize(length + increase);
		deflate_s.avail_out = increase;
		deflate_s.next_out = (Bytef *)(output.data() + length);
		int ret = deflate(&deflate_s, Z_FINISH);
		if (ret != Z_STREAM_END && ret != Z_OK && ret != Z_BUF_ERROR) {
			return -1;
		}
		length += (increase - deflate_s.avail_out);
	} while (deflate_s.avail_out == 0);
	deflateEnd(&deflate_s);
	output.resize(length);
	return 0;
}

static void op(env *e, int cmd, int x, int y);

void out(struct graphics *gc, int transparency, double gamma, int invert, int color, int color2, int saturate, int mask) {
	env *e = gc->e;
	int i;

	e->layer = e->tile.add_layers();
	e->layer->set_name("lines");
	e->layer->set_version(1);
	e->layer->set_extent(XMAX);

	struct linelayer *l;
	for (l = e->linelayers; l != NULL; l = l->next){
		e->feature = e->layer->add_features();
		e->feature->set_type(mapnik::vector::tile::LineString);

		e->x = 0;
		e->y = 0;

		e->cmd_idx = -1;
		e->cmd = -1;
		e->length = 0;

		for (i = 0; i < l->nlines; i++) {
			// printf("draw %d %d to %d %d\n", e->lines[i].x0, e->lines[i].y0, e->lines[i].x1, e->lines[i].y1);

			if (l->lines[i].x0 != e->x || l->lines[i].y0 != e->y || e->length == 0) {
				op(e, MOVE_TO, l->lines[i].x0, l->lines[i].y0);
			}

			op(e, LINE_TO, l->lines[i].x1, l->lines[i].y1);
		}

		if (e->cmd_idx >= 0) {
			//printf("old command: %d %d\n", e->cmd, e->length);
			e->feature->set_geometry(e->cmd_idx,
				(e->length << CMD_BITS) |
				(e->cmd & ((1 << CMD_BITS) - 1)));
		}
	}

	//////////////////////////////////

	e->layer = e->tile.add_layers();
	e->layer->set_name("points");
	e->layer->set_version(1);
	e->layer->set_extent(XMAX);

	struct pointlayer *p;
	for (p = e->pointlayers; p != NULL; p = p->next) {
		if (p->npoints != 0) {
			e->feature = e->layer->add_features();
			e->feature->set_type(mapnik::vector::tile::LineString);

			e->x = 0;
			e->y = 0;

			e->cmd_idx = -1;
			e->cmd = -1;
			e->length = 0;

			for (i = 0; i < p->npoints; i++) {
				op(e, MOVE_TO, p->points[i].x, p->points[i].y);
				op(e, LINE_TO, p->points[i].x + 1, p->points[i].y);
			}

			if (e->cmd_idx >= 0) {
				e->feature->set_geometry(e->cmd_idx,
					(e->length << CMD_BITS) |
					(e->cmd & ((1 << CMD_BITS) - 1)));
			}
		}
	}

	//////////////////////////////////

	std::string s;
	e->tile.SerializeToString(&s);

	std::string compressed;
	compress(s, compressed);

	std::cout << compressed;
}

static void op(env *e, int cmd, int x, int y) {
	// printf("%d %d,%d\n", cmd, x, y);
	// printf("from cmd %d to %d\n", e->cmd, cmd);

	if (cmd != e->cmd) {
		if (e->cmd_idx >= 0) {
			// printf("old command: %d %d\n", e->cmd, e->length);
			e->feature->set_geometry(e->cmd_idx,
				(e->length << CMD_BITS) |
				(e->cmd & ((1 << CMD_BITS) - 1)));
		}

		e->cmd = cmd;
		e->length = 0;
		e->cmd_idx = e->feature->geometry_size();

		e->feature->add_geometry(0); // placeholder
	}

	if (cmd == MOVE_TO || cmd == LINE_TO) {
		int dx = x - e->x;
		int dy = y - e->y;
		// printf("new geom: %d %d\n", x, y);

		e->feature->add_geometry((dx << 1) ^ (dx >> 31));
		e->feature->add_geometry((dy << 1) ^ (dy >> 31));

		e->x = x;
		e->y = y;
		e->length++;
	} else if (cmd == CLOSE_PATH) {
		e->length++;
	}
}

// http://rosettacode.org/wiki/Bitmap/Bresenham's_line_algorithm#C
int lineused(struct linelayer *l, int x0, int y0, int x1, int y1) {
	int dx = abs(x1 - x0), sx = (x0 < x1) ? 1 : -1;
	int dy = abs(y1 - y0), sy = (y0 < y1) ? 1 : -1;
	int err = ((dx > dy) ? dx : -dy) / 2, e2;

	while (1) {
		if (x0 == x1 && y0 == y1) {
			break;
		}

		if (x0 >= 0 && y0 >=0 && x0 < 256 && y0 < 256) {
			if (l->used[y0 * 256 + x0]) {
				return 1;
			}
		}

		e2 = err;
		if (e2 > -dx) {
			err -= dy;
			x0 += sx;
		}
		if (e2 <  dy) {
			err += dx;
			y0 += sy;
		}
	}

	return 0;
}

// http://rosettacode.org/wiki/Bitmap/Bresenham's_line_algorithm#C
void useline(struct linelayer *l, int x0, int y0, int x1, int y1) {
	int dx = abs(x1 - x0), sx = (x0 < x1) ? 1 : -1;
	int dy = abs(y1 - y0), sy = (y0 < y1) ? 1 : -1;
	int err = ((dx > dy) ? dx : -dy) / 2, e2;

	while (1) {
		if (x0 == x1 && y0 == y1) {
			break;
		}

		if (x0 >= 0 && y0 >=0 && x0 < 256 && y0 < 256) {
			l->used[y0 * 256 + x0] = 1;
		}

		e2 = err;
		if (e2 > -dx) {
			err -= dy;
			x0 += sx;
		}
		if (e2 <  dy) {
			err += dx;
			y0 += sy;
		}
	}
}

int drawClip(double x0, double y0, double x1, double y1, struct graphics *gc, double bright, double hue, int antialias, double thick, struct tilecontext *tc) {
	double mult = XMAX / gc->width;
	int accept = clip(&x0, &y0, &x1, &y1, -1, -1, XMAX / mult + 1, YMAX / mult + 1);

	if (accept) {
		int xx0 = x0 * mult;
		int yy0 = y0 * mult;
		int xx1 = x1 * mult;
		int yy1 = y1 * mult;

		env *e = gc->e;
		struct linelayer *l = e->linelayers;

		if (xx0 != xx1 || yy0 != yy1) {
			while (l->nlines > MAX_POINTS || lineused(l, x0, y0, x1, y1)) {
				if (l->next == NULL) {
					l->next = new_linelayer();
				}
				l = l->next;
			}

			if (l->nlines + 1 >= l->nlalloc) {
				l->nlalloc *= 2;
				l->lines = (struct line *) realloc((void *) l->lines, l->nlalloc * sizeof(struct line));
			}

			useline(l, x0, y0, x1, y1);

			l->lines[l->nlines].x0 = xx0;
			l->lines[l->nlines].y0 = yy0;
			l->lines[l->nlines].x1 = xx1;
			l->lines[l->nlines].y1 = yy1;

			l->nlines++;
		}
	}

	return 0;
}

void drawPixel(double x, double y, struct graphics *gc, double bright, double hue, struct tilecontext *tc) {
	x += .5;
	y += .5;

	double mult = XMAX / gc->width;
	int xx = x * mult;
	int yy = y * mult;

	env *e = gc->e;

	int xu = x * 256 / gc->width;
	int yu = y * 256 / gc->height;
	if (xu < 0) {
		xu = 0;
	}
	if (xu > 255) {
		xu = 255;
	}
	if (yu < 0) {
		yu = 0;
	}
	if (yu > 255) {
		yu = 255;
	}

	struct pointlayer *p = e->used[256 * yu + xu];
	while (p->npoints >= MAX_POINTS) {
		if (p->next == NULL) {
			p->next = new_pointlayer();
		}
		p = p->next;
	}
	if (p->next == NULL) {
		p->next = new_pointlayer();
	}
	e->used[256 * yu + xu] = p->next;

	if (p->npoints + 1 >= p->npalloc) {
		p->npalloc *= 2;
		p->points = (struct point *) realloc((void *) p->points, p->npalloc * sizeof(struct point));
	}

	p->points[p->npoints].x = xx;
	p->points[p->npoints].y = yy;

	p->npoints++;
}

void drawBrush(double x, double y, struct graphics *gc, double bright, double brush, double hue, int gaussian, struct tilecontext *tc) {
	drawPixel(x - .5, y - .5, gc, bright, hue, tc);
}
<|endoftext|>


<commit_before>#include <iostream>
#include <fstream>
#include <string>
#include <zlib.h>
#include "vector_tile.pb.h"

#define XMAX 4096
#define YMAX 4096

extern "C" {
	#include "graphics.h"
	#include "clip.h"
}

struct line {
	int x0;
	int y0;
	int x1;
	int y1;
};

int linecmp(const void *v1, const void *v2) {
	const struct line *l1 = (const struct line *) v1;
	const struct line *l2 = (const struct line *) v2;

	if (l1->x0 != l2->x0) {
		return l1->x0 - l2->x0;
	}
	if (l1->y0 != l2->y0) {
		return l1->y0 - l2->y0;
	}

	if (l1->x1 != l2->x1) {
		return l1->x1 - l2->x1;
	}

	return l1->y1 - l2->y1;
}

int startcmp(const void *v1, const void *v2) {
	const struct line *l1 = (const struct line *) v1;
	const struct line *l2 = (const struct line *) v2;

	if (l1->x0 != l2->x0) {
		return l1->x0 - l2->x0;
	}

	return l1->y0 - l2->y0;
}

class env {
public:
	mapnik::vector::tile tile;
	mapnik::vector::tile_layer *layer;
	mapnik::vector::tile_feature *feature;

	int x;
	int y;

	int cmd_idx;
	int cmd;
	int length;

	struct line *lines;
	int nlines;
	int nlalloc;
};

#define MOVE_TO 1
#define LINE_TO 2
#define CLOSE_PATH 7
#define CMD_BITS 3

double *graphics_init() {
	GOOGLE_PROTOBUF_VERIFY_VERSION;

	env *e = new env;

	e->nlalloc = 1024;
	e->nlines = 0;
	e->lines = (struct line *) malloc(e->nlalloc * sizeof(struct line));

	return (double *) e;
}

// from mapnik-vector-tile/src/vector_tile_compression.hpp
static inline int compress(std::string const& input, std::string & output)
{
	z_stream deflate_s;
	deflate_s.zalloc = Z_NULL;
	deflate_s.zfree = Z_NULL;
	deflate_s.opaque = Z_NULL;
	deflate_s.avail_in = 0;
	deflate_s.next_in = Z_NULL;
	deflateInit(&deflate_s, Z_DEFAULT_COMPRESSION);
	deflate_s.next_in = (Bytef *)input.data();
	deflate_s.avail_in = input.size();
	size_t length = 0;
	do {
		size_t increase = input.size() / 2 + 1024;
		output.resize(length + increase);
		deflate_s.avail_out = increase;
		deflate_s.next_out = (Bytef *)(output.data() + length);
		int ret = deflate(&deflate_s, Z_FINISH);
		if (ret != Z_STREAM_END && ret != Z_OK && ret != Z_BUF_ERROR) {
			return -1;
		}
		length += (increase - deflate_s.avail_out);
	} while (deflate_s.avail_out == 0);
	deflateEnd(&deflate_s);
	output.resize(length);
	return 0;
}

static void op(env *e, int cmd, int x, int y);

void out(double *src, double *cx, double *cy, int width, int height, int transparency, double gamma, int invert, int color, int color2, int saturate, int mask) {
	env *e = (env *) src;

	qsort(e->lines, e->nlines, sizeof(struct line), linecmp);

	e->layer = e->tile.add_layers();
	e->layer->set_name("world");
	e->layer->set_version(1);
	e->layer->set_extent(4096);

	e->feature = e->layer->add_features();
	e->feature->set_type(mapnik::vector::tile::LineString);

	e->x = 0;
	e->y = 0;

	e->cmd_idx = -1;
	e->cmd = -1;
	e->length = 0;

	int i;
	for (i = 0; i < e->nlines; i++) {
		// printf("draw %d %d to %d %d\n", e->lines[i].x0, e->lines[i].y0, e->lines[i].x1, e->lines[i].y1);

		if (e->lines[i].x0 != e->x || e->lines[i].y0 != e->y || e->length == 0) {
			op(e, MOVE_TO, e->lines[i].x0, e->lines[i].y0);
		}

		op(e, LINE_TO, e->lines[i].x1, e->lines[i].y1);

		struct line l2;
		l2.x0 = e->lines[i].x1;
		l2.y0 = e->lines[i].y1;

		while (i < e->nlines) {
			// printf("looking for %d,%d\n", l2.x0, l2.y0);
			// printf("searching %d\n", e->nlines - i);

			struct line *next = (struct line *) bsearch(&l2, e->lines + i, e->nlines - i,
						sizeof(struct line), startcmp);

			if (next != NULL) {
				// printf("found %d,%d to %d,%d at %d\n", next->x0, next->y0, next->x1, next->y1, (int) (next - e->lines));

				op(e, LINE_TO, next->x1, next->y1);

				l2.x0 = next->x1;
				l2.y0 = next->y1;

				int n = next - e->lines;

				memmove(e->lines + n, e->lines + n + 1, (e->nlines - (n + 1)) * sizeof(struct line));
				e->nlines--;
			} else {
				break;
			}
		}
	}

	if (e->cmd_idx >= 0) {
		//printf("old command: %d %d\n", e->cmd, e->length);
		e->feature->set_geometry(e->cmd_idx,
			(e->length << CMD_BITS) |
			(e->cmd & ((1 << CMD_BITS) - 1)));
	}

	std::string s;
	e->tile.SerializeToString(&s);

	std::string compressed;
	compress(s, compressed);

	std::cout << compressed;
}

static void op(env *e, int cmd, int x, int y) {
	// printf("%d %d,%d\n", cmd, x, y);
	// printf("from cmd %d to %d\n", e->cmd, cmd);

	if (cmd != e->cmd) {
		if (e->cmd_idx >= 0) {
			// printf("old command: %d %d\n", e->cmd, e->length);
			e->feature->set_geometry(e->cmd_idx,
				(e->length << CMD_BITS) |
				(e->cmd & ((1 << CMD_BITS) - 1)));
		}

		e->cmd = cmd;
		e->length = 0;
		e->cmd_idx = e->feature->geometry_size();

		e->feature->add_geometry(0); // placeholder
	}

	if (cmd == MOVE_TO || cmd == LINE_TO) {
		int dx = x - e->x;
		int dy = y - e->y;
		// printf("new geom: %d %d\n", x, y);

		e->feature->add_geometry((dx << 1) ^ (dx >> 31));
		e->feature->add_geometry((dy << 1) ^ (dy >> 31));

		e->x = x;
		e->y = y;
		e->length++;
	} else if (cmd == CLOSE_PATH) {
		e->length++;
	}
}

int drawClip(double x0, double y0, double x1, double y1, double *image, double *cx, double *cy, double bright, double hue, int antialias, double thick) {
	int accept = clip(&x0, &y0, &x1, &y1, 0, 0, XMAX / 16.0, YMAX / 16.0);

	if (accept) {
		int xx0 = x0 * 16;
		int yy0 = y0 * 16;
		int xx1 = x1 * 16;
		int yy1 = y1 * 16;

		// Guarding against rounding error

		if (xx0 < 0) {
			xx0 = 0;
		}
		if (xx0 > 4095) {
			xx0 = 4095;
		}
		if (yy0 < 0) {
			yy0 = 0;
		}
		if (yy0 > 4095) {
			yy0 = 4095;
		}

		if (xx1 < 0) {
			xx1 = 0;
		}
		if (xx1 > 4095) {
			xx1 = 4095;
		}
		if (yy1 < 0) {
			yy1 = 0;
		}
		if (yy1 > 4095) {
			yy1 = 4095;
		}

		env *e = (env *) image;

		if (xx0 != xx1 || yy0 != yy1) {
			if (e->nlines + 1 >= e->nlalloc) {
				e->nlalloc *= 2;
				e->lines = (struct line *) realloc((void *) e->lines, e->nlalloc * sizeof(struct line));
			}

			e->lines[e->nlines].x0 = xx0;
			e->lines[e->nlines].y0 = yy0;
			e->lines[e->nlines].x1 = xx1;
			e->lines[e->nlines].y1 = yy1;

			e->nlines++;
		}
	}

	return 0;
}

void drawPixel(double x, double y, double *image, double *cx, double *cy, double bright, double hue) {

}

void drawBrush(double x, double y, double *image, double *cx, double *cy, double bright, double brush, double hue) {

}
<commit_msg>Turn off chaining.<commit_after>#include <iostream>
#include <fstream>
#include <string>
#include <zlib.h>
#include "vector_tile.pb.h"

#define XMAX 4096
#define YMAX 4096

extern "C" {
	#include "graphics.h"
	#include "clip.h"
}

struct line {
	int x0;
	int y0;
	int x1;
	int y1;
};

int linecmp(const void *v1, const void *v2) {
	const struct line *l1 = (const struct line *) v1;
	const struct line *l2 = (const struct line *) v2;

	if (l1->x0 != l2->x0) {
		return l1->x0 - l2->x0;
	}
	if (l1->y0 != l2->y0) {
		return l1->y0 - l2->y0;
	}

	if (l1->x1 != l2->x1) {
		return l1->x1 - l2->x1;
	}

	return l1->y1 - l2->y1;
}

int startcmp(const void *v1, const void *v2) {
	const struct line *l1 = (const struct line *) v1;
	const struct line *l2 = (const struct line *) v2;

	if (l1->x0 != l2->x0) {
		return l1->x0 - l2->x0;
	}

	return l1->y0 - l2->y0;
}

class env {
public:
	mapnik::vector::tile tile;
	mapnik::vector::tile_layer *layer;
	mapnik::vector::tile_feature *feature;

	int x;
	int y;

	int cmd_idx;
	int cmd;
	int length;

	struct line *lines;
	int nlines;
	int nlalloc;
};

#define MOVE_TO 1
#define LINE_TO 2
#define CLOSE_PATH 7
#define CMD_BITS 3

double *graphics_init() {
	GOOGLE_PROTOBUF_VERIFY_VERSION;

	env *e = new env;

	e->nlalloc = 1024;
	e->nlines = 0;
	e->lines = (struct line *) malloc(e->nlalloc * sizeof(struct line));

	return (double *) e;
}

// from mapnik-vector-tile/src/vector_tile_compression.hpp
static inline int compress(std::string const& input, std::string & output)
{
	z_stream deflate_s;
	deflate_s.zalloc = Z_NULL;
	deflate_s.zfree = Z_NULL;
	deflate_s.opaque = Z_NULL;
	deflate_s.avail_in = 0;
	deflate_s.next_in = Z_NULL;
	deflateInit(&deflate_s, Z_DEFAULT_COMPRESSION);
	deflate_s.next_in = (Bytef *)input.data();
	deflate_s.avail_in = input.size();
	size_t length = 0;
	do {
		size_t increase = input.size() / 2 + 1024;
		output.resize(length + increase);
		deflate_s.avail_out = increase;
		deflate_s.next_out = (Bytef *)(output.data() + length);
		int ret = deflate(&deflate_s, Z_FINISH);
		if (ret != Z_STREAM_END && ret != Z_OK && ret != Z_BUF_ERROR) {
			return -1;
		}
		length += (increase - deflate_s.avail_out);
	} while (deflate_s.avail_out == 0);
	deflateEnd(&deflate_s);
	output.resize(length);
	return 0;
}

static void op(env *e, int cmd, int x, int y);

void out(double *src, double *cx, double *cy, int width, int height, int transparency, double gamma, int invert, int color, int color2, int saturate, int mask) {
	env *e = (env *) src;

#ifdef CHAIN
	qsort(e->lines, e->nlines, sizeof(struct line), linecmp);
#endif

	e->layer = e->tile.add_layers();
	e->layer->set_name("world");
	e->layer->set_version(1);
	e->layer->set_extent(4096);

	e->feature = e->layer->add_features();
	e->feature->set_type(mapnik::vector::tile::LineString);

	e->x = 0;
	e->y = 0;

	e->cmd_idx = -1;
	e->cmd = -1;
	e->length = 0;

	int i;
	for (i = 0; i < e->nlines; i++) {
		// printf("draw %d %d to %d %d\n", e->lines[i].x0, e->lines[i].y0, e->lines[i].x1, e->lines[i].y1);

		if (e->lines[i].x0 != e->x || e->lines[i].y0 != e->y || e->length == 0) {
			op(e, MOVE_TO, e->lines[i].x0, e->lines[i].y0);
		}

		op(e, LINE_TO, e->lines[i].x1, e->lines[i].y1);

#ifdef CHAIN
		struct line l2;
		l2.x0 = e->lines[i].x1;
		l2.y0 = e->lines[i].y1;

		while (i < e->nlines) {
			// printf("looking for %d,%d\n", l2.x0, l2.y0);
			// printf("searching %d\n", e->nlines - i);

			struct line *next = (struct line *) bsearch(&l2, e->lines + i, e->nlines - i,
						sizeof(struct line), startcmp);

			if (next != NULL) {
				// printf("found %d,%d to %d,%d at %d\n", next->x0, next->y0, next->x1, next->y1, (int) (next - e->lines));

				op(e, LINE_TO, next->x1, next->y1);

				l2.x0 = next->x1;
				l2.y0 = next->y1;

				int n = next - e->lines;

				memmove(e->lines + n, e->lines + n + 1, (e->nlines - (n + 1)) * sizeof(struct line));
				e->nlines--;
			} else {
				break;
			}
		}
#endif
	}

	if (e->cmd_idx >= 0) {
		//printf("old command: %d %d\n", e->cmd, e->length);
		e->feature->set_geometry(e->cmd_idx,
			(e->length << CMD_BITS) |
			(e->cmd & ((1 << CMD_BITS) - 1)));
	}

	std::string s;
	e->tile.SerializeToString(&s);

	std::string compressed;
	compress(s, compressed);

	std::cout << compressed;
}

static void op(env *e, int cmd, int x, int y) {
	// printf("%d %d,%d\n", cmd, x, y);
	// printf("from cmd %d to %d\n", e->cmd, cmd);

	if (cmd != e->cmd) {
		if (e->cmd_idx >= 0) {
			// printf("old command: %d %d\n", e->cmd, e->length);
			e->feature->set_geometry(e->cmd_idx,
				(e->length << CMD_BITS) |
				(e->cmd & ((1 << CMD_BITS) - 1)));
		}

		e->cmd = cmd;
		e->length = 0;
		e->cmd_idx = e->feature->geometry_size();

		e->feature->add_geometry(0); // placeholder
	}

	if (cmd == MOVE_TO || cmd == LINE_TO) {
		int dx = x - e->x;
		int dy = y - e->y;
		// printf("new geom: %d %d\n", x, y);

		e->feature->add_geometry((dx << 1) ^ (dx >> 31));
		e->feature->add_geometry((dy << 1) ^ (dy >> 31));

		e->x = x;
		e->y = y;
		e->length++;
	} else if (cmd == CLOSE_PATH) {
		e->length++;
	}
}

int drawClip(double x0, double y0, double x1, double y1, double *image, double *cx, double *cy, double bright, double hue, int antialias, double thick) {
	int accept = clip(&x0, &y0, &x1, &y1, 0, 0, XMAX / 16.0, YMAX / 16.0);

	if (accept) {
		int xx0 = x0 * 16;
		int yy0 = y0 * 16;
		int xx1 = x1 * 16;
		int yy1 = y1 * 16;

		// Guarding against rounding error

		if (xx0 < 0) {
			xx0 = 0;
		}
		if (xx0 > 4095) {
			xx0 = 4095;
		}
		if (yy0 < 0) {
			yy0 = 0;
		}
		if (yy0 > 4095) {
			yy0 = 4095;
		}

		if (xx1 < 0) {
			xx1 = 0;
		}
		if (xx1 > 4095) {
			xx1 = 4095;
		}
		if (yy1 < 0) {
			yy1 = 0;
		}
		if (yy1 > 4095) {
			yy1 = 4095;
		}

		env *e = (env *) image;

		if (xx0 != xx1 || yy0 != yy1) {
			if (e->nlines + 1 >= e->nlalloc) {
				e->nlalloc *= 2;
				e->lines = (struct line *) realloc((void *) e->lines, e->nlalloc * sizeof(struct line));
			}

			e->lines[e->nlines].x0 = xx0;
			e->lines[e->nlines].y0 = yy0;
			e->lines[e->nlines].x1 = xx1;
			e->lines[e->nlines].y1 = yy1;

			e->nlines++;
		}
	}

	return 0;
}

void drawPixel(double x, double y, double *image, double *cx, double *cy, double bright, double hue) {

}

void drawBrush(double x, double y, double *image, double *cx, double *cy, double bright, double brush, double hue) {

}
<|endoftext|>


<commit_before>// SciTE - Scintilla based Text Editor
/** @file StyleDefinition.cxx
 ** Implementation of style aggregate.
 **/
// Copyright 2013 by Neil Hodgson <neilh@scintilla.org>
// The License.txt file describes the conditions under which this software may be distributed.

#include <stdlib.h>
#include <string.h>

#include <string>
#include <vector>
#include <algorithm>

#include "Scintilla.h"

#include "GUI.h"
#include "SString.h"
#include "StringHelpers.h"
#include "StyleDefinition.h"

StyleDefinition::StyleDefinition(const char *definition) :
		sizeFractional(10.0), size(10), fore("#000000"), back("#FFFFFF"),
		weight(SC_WEIGHT_NORMAL), italics(false), eolfilled(false), underlined(false),
		caseForce(SC_CASE_MIXED),
		visible(true), changeable(true),
		specified(sdNone) {
	ParseStyleDefinition(definition);
}

bool StyleDefinition::ParseStyleDefinition(const char *definition) {
	if (definition == NULL || *definition == '\0') {
		return false;
	}
	char *val = StringDup(definition);
	char *opt = val;
	while (opt) {
		// Find attribute separator
		char *cpComma = strchr(opt, ',');
		if (cpComma) {
			// If found, we terminate the current attribute (opt) string
			*cpComma = '\0';
		}
		// Find attribute name/value separator
		char *colon = strchr(opt, ':');
		if (colon) {
			// If found, we terminate the current attribute name and point on the value
			*colon++ = '\0';
		}
		if (0 == strcmp(opt, "italics")) {
			specified = static_cast<flags>(specified | sdItalics);
			italics = true;
		}
		if (0 == strcmp(opt, "notitalics")) {
			specified = static_cast<flags>(specified | sdItalics);
			italics = false;
		}
		if (0 == strcmp(opt, "bold")) {
			specified = static_cast<flags>(specified | sdWeight);
			weight = SC_WEIGHT_BOLD;
		}
		if (0 == strcmp(opt, "notbold")) {
			specified = static_cast<flags>(specified | sdWeight);
			weight = SC_WEIGHT_NORMAL;
		}
		if ((0 == strcmp(opt, "weight")) && colon) {
			specified = static_cast<flags>(specified | sdWeight);
			weight = atoi(colon);
		}
		if ((0 == strcmp(opt, "font")) && colon) {
			specified = static_cast<flags>(specified | sdFont);
			font = colon;
			std::replace(font.begin(), font.end(), '|', ',');
		}
		if ((0 == strcmp(opt, "fore")) && colon) {
			specified = static_cast<flags>(specified | sdFore);
			fore = colon;
		}
		if ((0 == strcmp(opt, "back")) && colon) {
			specified = static_cast<flags>(specified | sdBack);
			back = colon;
		}
		if ((0 == strcmp(opt, "size")) && colon) {
			specified = static_cast<flags>(specified | sdSize);
			sizeFractional = static_cast<float>(atof(colon));
			size = static_cast<int>(sizeFractional);
		}
		if (0 == strcmp(opt, "eolfilled")) {
			specified = static_cast<flags>(specified | sdEOLFilled);
			eolfilled = true;
		}
		if (0 == strcmp(opt, "noteolfilled")) {
			specified = static_cast<flags>(specified | sdEOLFilled);
			eolfilled = false;
		}
		if (0 == strcmp(opt, "underlined")) {
			specified = static_cast<flags>(specified | sdUnderlined);
			underlined = true;
		}
		if (0 == strcmp(opt, "notunderlined")) {
			specified = static_cast<flags>(specified | sdUnderlined);
			underlined = false;
		}
		if (0 == strcmp(opt, "case")) {
			specified = static_cast<flags>(specified | sdCaseForce);
			caseForce = SC_CASE_MIXED;
			if (colon) {
				if (*colon == 'u')
					caseForce = SC_CASE_UPPER;
				else if (*colon == 'l')
					caseForce = SC_CASE_LOWER;
			}
		}
		if (0 == strcmp(opt, "visible")) {
			specified = static_cast<flags>(specified | sdVisible);
			visible = true;
		}
		if (0 == strcmp(opt, "notvisible")) {
			specified = static_cast<flags>(specified | sdVisible);
			visible = false;
		}
		if (0 == strcmp(opt, "changeable")) {
			specified = static_cast<flags>(specified | sdChangeable);
			changeable = true;
		}
		if (0 == strcmp(opt, "notchangeable")) {
			specified = static_cast<flags>(specified | sdChangeable);
			changeable = false;
		}
		if (cpComma)
			opt = cpComma + 1;
		else
			opt = 0;
	}
	delete []val;
	return true;
}

long StyleDefinition::ForeAsLong() const {
	return ColourFromString(fore);
}

long StyleDefinition::BackAsLong() const {
	return ColourFromString(back);
}

int StyleDefinition::FractionalSize() const {
	return static_cast<int>(sizeFractional * SC_FONT_SIZE_MULTIPLIER);
}

bool StyleDefinition::IsBold() const {
	return weight > SC_WEIGHT_NORMAL;
}

int IntFromHexDigit(int ch) {
	if ((ch >= '0') && (ch <= '9')) {
		return ch - '0';
	} else if (ch >= 'A' && ch <= 'F') {
		return ch - 'A' + 10;
	} else if (ch >= 'a' && ch <= 'f') {
		return ch - 'a' + 10;
	} else {
		return 0;
	}
}

int IntFromHexByte(const char *hexByte) {
	return IntFromHexDigit(hexByte[0]) * 16 + IntFromHexDigit(hexByte[1]);
}

Colour ColourFromString(const std::string &s) {
	if (s.length()) {
		int r = IntFromHexByte(s.c_str() + 1);
		int g = IntFromHexByte(s.c_str() + 3);
		int b = IntFromHexByte(s.c_str() + 5);
		return ColourRGB(r, g, b);
	} else {
		return 0;
	}
}

IndicatorDefinition::IndicatorDefinition(const char *definition) :
	style(INDIC_PLAIN), colour(0), fillAlpha(30), outlineAlpha(50), under(false) {
	ParseIndicatorDefinition(definition);
}

bool IndicatorDefinition::ParseIndicatorDefinition(const char *definition) {
	if (definition == NULL || *definition == '\0') {
		return false;
	}
	struct {
		const char *name;
		int value;
	} indicStyleNames[] = {
		{ "plain", INDIC_PLAIN },
		{ "squiggle", INDIC_SQUIGGLE },
		{ "tt", INDIC_TT },
		{ "diagonal", INDIC_DIAGONAL },
		{ "strike", INDIC_STRIKE },
		{ "hidden", INDIC_HIDDEN },
		{ "box", INDIC_BOX },
		{ "roundbox", INDIC_ROUNDBOX },
		{ "straightbox", INDIC_STRAIGHTBOX },
		{ "dash", INDIC_DASH },
		{ "dots", INDIC_DOTS },
		{ "squigglelow", INDIC_SQUIGGLELOW },
		{ "dotbox", INDIC_DOTBOX },
		{ "squigglepixmap", INDIC_SQUIGGLEPIXMAP },
		{ "compositionthick", INDIC_COMPOSITIONTHICK },
	};

	std::string val(definition);
	LowerCaseAZ(val);
	char *opt = &val[0];
	while (opt) {
		// Find attribute separator
		char *cpComma = strchr(opt, ',');
		if (cpComma) {
			// If found, we terminate the current attribute (opt) string
			*cpComma = '\0';
		}
		// Find attribute name/value separator
		char *colon = strchr(opt, ':');
		if (colon) {
			// If found, we terminate the current attribute name and point on the value
			*colon++ = '\0';
		}
		if (colon && (0 == strcmp(opt, "style"))) {
			bool found = false;
			for (size_t i=0;i<ELEMENTS(indicStyleNames);i++) {
				if ((indicStyleNames[i].name) && (0 == strcmp(colon, indicStyleNames[i].name))) {
					style = indicStyleNames[i].value;
					found = true;
				}
			}
			if (!found)
				style = atoi(colon);
		}
		if (colon && ((0 == strcmp(opt, "colour")) || (0 == strcmp(opt, "color")))) {
			colour = ColourFromString(std::string(colon));
		}
		if (colon && (0 == strcmp(opt, "fillalpha"))) {
			fillAlpha = atoi(colon);
		}
		if (colon && (0 == strcmp(opt, "outlinealpha"))) {
			outlineAlpha = atoi(colon);
		}
		if (0 == strcmp(opt, "under")) {
			under = true;
		}
		if (0 == strcmp(opt, "notunder")) {
			under = false;
		}
		if (cpComma)
			opt = cpComma + 1;
		else
			opt = 0;
	}
	return true;
}
<commit_msg>Use std::vector<char> to encapsulate definition and avoid possibility of leak.<commit_after>// SciTE - Scintilla based Text Editor
/** @file StyleDefinition.cxx
 ** Implementation of style aggregate.
 **/
// Copyright 2013 by Neil Hodgson <neilh@scintilla.org>
// The License.txt file describes the conditions under which this software may be distributed.

#include <stdlib.h>
#include <string.h>

#include <string>
#include <vector>
#include <algorithm>

#include "Scintilla.h"

#include "GUI.h"
#include "SString.h"
#include "StringHelpers.h"
#include "StyleDefinition.h"

StyleDefinition::StyleDefinition(const char *definition) :
		sizeFractional(10.0), size(10), fore("#000000"), back("#FFFFFF"),
		weight(SC_WEIGHT_NORMAL), italics(false), eolfilled(false), underlined(false),
		caseForce(SC_CASE_MIXED),
		visible(true), changeable(true),
		specified(sdNone) {
	ParseStyleDefinition(definition);
}

bool StyleDefinition::ParseStyleDefinition(const char *definition) {
	if (definition == NULL || *definition == '\0') {
		return false;
	}
	std::vector<char> valHolder(definition, definition + strlen(definition)+1);
	char *val = &valHolder[0];
	char *opt = val;
	while (opt) {
		// Find attribute separator
		char *cpComma = strchr(opt, ',');
		if (cpComma) {
			// If found, we terminate the current attribute (opt) string
			*cpComma = '\0';
		}
		// Find attribute name/value separator
		char *colon = strchr(opt, ':');
		if (colon) {
			// If found, we terminate the current attribute name and point on the value
			*colon++ = '\0';
		}
		if (0 == strcmp(opt, "italics")) {
			specified = static_cast<flags>(specified | sdItalics);
			italics = true;
		}
		if (0 == strcmp(opt, "notitalics")) {
			specified = static_cast<flags>(specified | sdItalics);
			italics = false;
		}
		if (0 == strcmp(opt, "bold")) {
			specified = static_cast<flags>(specified | sdWeight);
			weight = SC_WEIGHT_BOLD;
		}
		if (0 == strcmp(opt, "notbold")) {
			specified = static_cast<flags>(specified | sdWeight);
			weight = SC_WEIGHT_NORMAL;
		}
		if ((0 == strcmp(opt, "weight")) && colon) {
			specified = static_cast<flags>(specified | sdWeight);
			weight = atoi(colon);
		}
		if ((0 == strcmp(opt, "font")) && colon) {
			specified = static_cast<flags>(specified | sdFont);
			font = colon;
			std::replace(font.begin(), font.end(), '|', ',');
		}
		if ((0 == strcmp(opt, "fore")) && colon) {
			specified = static_cast<flags>(specified | sdFore);
			fore = colon;
		}
		if ((0 == strcmp(opt, "back")) && colon) {
			specified = static_cast<flags>(specified | sdBack);
			back = colon;
		}
		if ((0 == strcmp(opt, "size")) && colon) {
			specified = static_cast<flags>(specified | sdSize);
			sizeFractional = static_cast<float>(atof(colon));
			size = static_cast<int>(sizeFractional);
		}
		if (0 == strcmp(opt, "eolfilled")) {
			specified = static_cast<flags>(specified | sdEOLFilled);
			eolfilled = true;
		}
		if (0 == strcmp(opt, "noteolfilled")) {
			specified = static_cast<flags>(specified | sdEOLFilled);
			eolfilled = false;
		}
		if (0 == strcmp(opt, "underlined")) {
			specified = static_cast<flags>(specified | sdUnderlined);
			underlined = true;
		}
		if (0 == strcmp(opt, "notunderlined")) {
			specified = static_cast<flags>(specified | sdUnderlined);
			underlined = false;
		}
		if (0 == strcmp(opt, "case")) {
			specified = static_cast<flags>(specified | sdCaseForce);
			caseForce = SC_CASE_MIXED;
			if (colon) {
				if (*colon == 'u')
					caseForce = SC_CASE_UPPER;
				else if (*colon == 'l')
					caseForce = SC_CASE_LOWER;
			}
		}
		if (0 == strcmp(opt, "visible")) {
			specified = static_cast<flags>(specified | sdVisible);
			visible = true;
		}
		if (0 == strcmp(opt, "notvisible")) {
			specified = static_cast<flags>(specified | sdVisible);
			visible = false;
		}
		if (0 == strcmp(opt, "changeable")) {
			specified = static_cast<flags>(specified | sdChangeable);
			changeable = true;
		}
		if (0 == strcmp(opt, "notchangeable")) {
			specified = static_cast<flags>(specified | sdChangeable);
			changeable = false;
		}
		if (cpComma)
			opt = cpComma + 1;
		else
			opt = 0;
	}
	return true;
}

long StyleDefinition::ForeAsLong() const {
	return ColourFromString(fore);
}

long StyleDefinition::BackAsLong() const {
	return ColourFromString(back);
}

int StyleDefinition::FractionalSize() const {
	return static_cast<int>(sizeFractional * SC_FONT_SIZE_MULTIPLIER);
}

bool StyleDefinition::IsBold() const {
	return weight > SC_WEIGHT_NORMAL;
}

int IntFromHexDigit(int ch) {
	if ((ch >= '0') && (ch <= '9')) {
		return ch - '0';
	} else if (ch >= 'A' && ch <= 'F') {
		return ch - 'A' + 10;
	} else if (ch >= 'a' && ch <= 'f') {
		return ch - 'a' + 10;
	} else {
		return 0;
	}
}

int IntFromHexByte(const char *hexByte) {
	return IntFromHexDigit(hexByte[0]) * 16 + IntFromHexDigit(hexByte[1]);
}

Colour ColourFromString(const std::string &s) {
	if (s.length()) {
		int r = IntFromHexByte(s.c_str() + 1);
		int g = IntFromHexByte(s.c_str() + 3);
		int b = IntFromHexByte(s.c_str() + 5);
		return ColourRGB(r, g, b);
	} else {
		return 0;
	}
}

IndicatorDefinition::IndicatorDefinition(const char *definition) :
	style(INDIC_PLAIN), colour(0), fillAlpha(30), outlineAlpha(50), under(false) {
	ParseIndicatorDefinition(definition);
}

bool IndicatorDefinition::ParseIndicatorDefinition(const char *definition) {
	if (definition == NULL || *definition == '\0') {
		return false;
	}
	struct {
		const char *name;
		int value;
	} indicStyleNames[] = {
		{ "plain", INDIC_PLAIN },
		{ "squiggle", INDIC_SQUIGGLE },
		{ "tt", INDIC_TT },
		{ "diagonal", INDIC_DIAGONAL },
		{ "strike", INDIC_STRIKE },
		{ "hidden", INDIC_HIDDEN },
		{ "box", INDIC_BOX },
		{ "roundbox", INDIC_ROUNDBOX },
		{ "straightbox", INDIC_STRAIGHTBOX },
		{ "dash", INDIC_DASH },
		{ "dots", INDIC_DOTS },
		{ "squigglelow", INDIC_SQUIGGLELOW },
		{ "dotbox", INDIC_DOTBOX },
		{ "squigglepixmap", INDIC_SQUIGGLEPIXMAP },
		{ "compositionthick", INDIC_COMPOSITIONTHICK },
	};

	std::string val(definition);
	LowerCaseAZ(val);
	char *opt = &val[0];
	while (opt) {
		// Find attribute separator
		char *cpComma = strchr(opt, ',');
		if (cpComma) {
			// If found, we terminate the current attribute (opt) string
			*cpComma = '\0';
		}
		// Find attribute name/value separator
		char *colon = strchr(opt, ':');
		if (colon) {
			// If found, we terminate the current attribute name and point on the value
			*colon++ = '\0';
		}
		if (colon && (0 == strcmp(opt, "style"))) {
			bool found = false;
			for (size_t i=0;i<ELEMENTS(indicStyleNames);i++) {
				if ((indicStyleNames[i].name) && (0 == strcmp(colon, indicStyleNames[i].name))) {
					style = indicStyleNames[i].value;
					found = true;
				}
			}
			if (!found)
				style = atoi(colon);
		}
		if (colon && ((0 == strcmp(opt, "colour")) || (0 == strcmp(opt, "color")))) {
			colour = ColourFromString(std::string(colon));
		}
		if (colon && (0 == strcmp(opt, "fillalpha"))) {
			fillAlpha = atoi(colon);
		}
		if (colon && (0 == strcmp(opt, "outlinealpha"))) {
			outlineAlpha = atoi(colon);
		}
		if (0 == strcmp(opt, "under")) {
			under = true;
		}
		if (0 == strcmp(opt, "notunder")) {
			under = false;
		}
		if (cpComma)
			opt = cpComma + 1;
		else
			opt = 0;
	}
	return true;
}
<|endoftext|>


<commit_before>#pragma once

#include "../data/array.hpp"
#include <QObject>

namespace datavis {

class DataSource : public QObject
{
public:
    DataSource(const QString & filePath, QObject * parent = 0);

    QString path() const { return m_path; }
    array<double> * data() { return & m_data; }
    const array<double> * data() const { return & m_data; }

private:
    QString m_path;
    array<double> m_data;
};

}
<commit_msg>DataSource: add constructor that doesn't load from file<commit_after>#pragma once

#include "../data/array.hpp"
#include <QObject>

namespace datavis {

class DataSource : public QObject
{
public:
    DataSource(const QString & filePath, QObject * parent = 0);
    DataSource(const vector<int> & size): m_data(size) {}
    QString path() const { return m_path; }
    array<double> * data() { return & m_data; }
    const array<double> * data() const { return & m_data; }

private:
    QString m_path;
    array<double> m_data;
};

}
<|endoftext|>


<commit_before>/*
 * Copyright 2011 Intel Corporation.
 *
 * This program is licensed under the terms and conditions of the
 * Apache License, version 2.0.  The full text of the Apache License is at
 * http://www.apache.org/licenses/LICENSE-2.0
 */

#include "TextEditHandler.h"

#include <QtGui/QTextCharFormat>
#include <QtGui/QTextDocumentFragment>

/********************************************************************
 * CTextEditHandler class declaration
 *
 * This class implements textedit handler. It provides such functions like:
 * bold, italic and underline
 *
 *******************************************************************/

/********************************************************************
 * CTextEditHandler - constructor of the class
 *
 *
 *******************************************************************/
CTextEditHandler::CTextEditHandler(QObject* parent):
    QObject(parent), m_pEdit(NULL),
    m_bIsBold(false), m_bIsItalic(false), m_bIsUnderline(false)
{
    Init();
}

/********************************************************************
 * ~CTextEditHandler - destructor of the class
 *
 *
 *******************************************************************/
CTextEditHandler::~CTextEditHandler()
{
    if (NULL != m_pEdit)
    {
        delete m_pEdit;
        m_pEdit = NULL;
    }
}

/********************************************************************
 * Init function makes some default operations
 *
 *
 *******************************************************************/
void CTextEditHandler::Init()
{
    m_pEdit = new QTextEdit(NULL);
    m_pEdit->setText("");
}

/********************************************************************
 * bold function makes selected text bold
 *
 *
 *******************************************************************/
QString CTextEditHandler::bold(const QString& _text, int _nPos, int _nPosEnd)
{
    setTextAndCursor(CTextEditHandler::BoldRole, _text, _nPos, _nPosEnd);
    return m_pEdit->toHtml();
}

/********************************************************************
 * italic function makes selected text italic
 *
 *
 *******************************************************************/
QString CTextEditHandler::italic(const QString& _text, int _nPos, int _nPosEnd)
{
    setTextAndCursor(CTextEditHandler::ItalicRole, _text, _nPos, _nPosEnd);
    return m_pEdit->toHtml();
}

/********************************************************************
 * underline function makes selected text underline
 *
 *
 *******************************************************************/
QString CTextEditHandler::underline(const QString& _text, int _nPos, int _nPosEnd)
{
    setTextAndCursor(CTextEditHandler::UnderlineRole, _text, _nPos, _nPosEnd);
    return m_pEdit->toHtml();
}

/********************************************************************
 * setTextAndCursor function set new text and move cursor to the new
 * position
 *
 *******************************************************************/
void CTextEditHandler::setTextAndCursor(int role, const QString& _text, int _nPos, int _nPosEnd)
{
    m_pEdit->setText(_text);

    QTextCursor cursor = m_pEdit->textCursor();

    if (_nPos == _nPosEnd) //no selection
    {
        cursor.setPosition(_nPos);
        if (!cursor.hasSelection())
        {
            cursor.select(QTextCursor::WordUnderCursor);
        }
    }
    else
    {
        cursor.setPosition(_nPos);
        cursor.setPosition(_nPosEnd, QTextCursor::KeepAnchor);
    }

    QString strSelection = cursor.selection().toHtml();
    QTextCharFormat fmt;

    if (CTextEditHandler::BoldRole == role)
    {
        m_bIsBold = (-1 != strSelection.indexOf("font-weight:")) ? false : true;
        fmt.setFontWeight(m_bIsBold ? QFont::Bold : QFont::Normal);
    }
    else if (CTextEditHandler::ItalicRole == role)
    {
        m_bIsItalic = (-1 != strSelection.indexOf("font-style:italic")) ? false : true;
        fmt.setFontItalic(m_bIsItalic);
    }
    else if (CTextEditHandler::UnderlineRole == role)
    {
        m_bIsUnderline = (-1 != strSelection.indexOf("text-decoration: underline;")) ? false : true;
        fmt.setFontUnderline(m_bIsUnderline);
    }

    cursor.mergeCharFormat(fmt);
    m_pEdit->mergeCurrentCharFormat(fmt);
}

/********************************************************************
 * toPlainText function converts Rich to Plain text
 *
 *
 *******************************************************************/
QString CTextEditHandler::toPlainText(const QString& _text)
{
    m_pEdit->setText(_text);
    return m_pEdit->toPlainText();
}

/********************************************************************
 * setFontFamily function set new font family to the text
 *
 *
 *******************************************************************/
QString CTextEditHandler::setFontFamily(const QString& _text, int _nPos, int _nPosEnd, const QString& _fontFamily)
{
    m_pEdit->setText(_text);

    QTextCursor cursor = m_pEdit->textCursor();

    if (_nPos == _nPosEnd) //no selection
    {
        cursor.setPosition(_nPos);
        if (!cursor.hasSelection())
        {
            cursor.select(QTextCursor::WordUnderCursor);
        }
    }
    else
    {
        cursor.setPosition(_nPos);
        cursor.setPosition(_nPosEnd, QTextCursor::KeepAnchor);
    }

    QTextCharFormat fmt;
    fmt.setFontFamily(_fontFamily);
    cursor.mergeCharFormat(fmt);
    m_pEdit->mergeCurrentCharFormat(fmt);

    return m_pEdit->toHtml();
}

/********************************************************************
 * setFontSize function set new font size to the text
 *
 *
 *******************************************************************/
QString CTextEditHandler::setFontSize(const QString& _text, int _nPos, int _nPosEnd, int _nPointSize)
{
    m_pEdit->setText(_text);

    QTextCursor cursor = m_pEdit->textCursor();

    if (_nPos == _nPosEnd) //no selection
    {
        cursor.setPosition(_nPos);
        if (!cursor.hasSelection())
        {
            cursor.select(QTextCursor::WordUnderCursor);
        }
    }
    else
    {
        cursor.setPosition(_nPos);
        cursor.setPosition(_nPosEnd, QTextCursor::KeepAnchor);
    }

    QTextCharFormat fmt;
    fmt.setFontPointSize(_nPointSize);
    cursor.mergeCharFormat(fmt);
    m_pEdit->mergeCurrentCharFormat(fmt);

    return m_pEdit->toPlainText();
}

<commit_msg>test again<commit_after>/*
 * Copyright 2011 Intel Corporation.
 *
 * This program is licensed under the terms and conditions of the
 * Apache License, version 2.0.  The full text of the Apache License is at
 * http://www.apache.org/licenses/LICENSE-2.0
 */

#include "TextEditHandler.h"

#include <QtGui/QTextCharFormat>
#include <QtGui/QTextDocumentFragment>

/********************************************************************
 * CTextEditHandler class declaration
 *
 * This class implements textedit handler. It provides such functions like:
 * bold, italic and underline
 *
 *******************************************************************/

/********************************************************************
 * CTextEditHandler - constructor of the class
 *
 *
 *******************************************************************/
CTextEditHandler::CTextEditHandler(QObject* parent):
    QObject(parent), m_pEdit(NULL),
    m_bIsBold(false), m_bIsItalic(false), m_bIsUnderline(false)
{
    Init();
}

/********************************************************************
 * ~CTextEditHandler - destructor of the class
 *
 *
 *******************************************************************/
CTextEditHandler::~CTextEditHandler()
{
    if (NULL != m_pEdit)
    {
        delete m_pEdit;
        m_pEdit = NULL;
    }
}

/********************************************************************
 * Init function makes some default operations
 *
 *
 *******************************************************************/
void CTextEditHandler::Init()
{
    m_pEdit = new QTextEdit(NULL);
    m_pEdit->setText("");
}

/********************************************************************
 * bold function makes selected text bold
 *
 *
 *******************************************************************/
QString CTextEditHandler::bold(const QString& _text, int _nPos, int _nPosEnd)
{
    setTextAndCursor(CTextEditHandler::BoldRole, _text, _nPos, _nPosEnd);
    return m_pEdit->toHtml();
}

/********************************************************************
 * italic function makes selected text italic
 *
 *
 *******************************************************************/
QString CTextEditHandler::italic(const QString& _text, int _nPos, int _nPosEnd)
{
    setTextAndCursor(CTextEditHandler::ItalicRole, _text, _nPos, _nPosEnd);
    return m_pEdit->toHtml();
}

/********************************************************************
 * underline function makes selected text underline
 *
 *
 *******************************************************************/
QString CTextEditHandler::underline(const QString& _text, int _nPos, int _nPosEnd)
{
    setTextAndCursor(CTextEditHandler::UnderlineRole, _text, _nPos, _nPosEnd);
    return m_pEdit->toHtml();
}

/********************************************************************
 * setTextAndCursor function set new text and move cursor to the new
 * position
 *
 *******************************************************************/
void CTextEditHandler::setTextAndCursor(int role, const QString& _text, int _nPos, int _nPosEnd)
{
    m_pEdit->setText(_text);

    QTextCursor cursor = m_pEdit->textCursor();

    if (_nPos == _nPosEnd) //no selection
    {
        cursor.setPosition(_nPos);
        if (!cursor.hasSelection())
        {
            cursor.select(QTextCursor::WordUnderCursor);
        }
    }
    else
    {
        cursor.setPosition(_nPos);
        cursor.setPosition(_nPosEnd, QTextCursor::KeepAnchor);
    }

    QString strSelection = cursor.selection().toHtml();
    QTextCharFormat fmt;

    if (CTextEditHandler::BoldRole == role)
    {
        m_bIsBold = (-1 != strSelection.indexOf("font-weight:")) ? false : true;
        fmt.setFontWeight(m_bIsBold ? QFont::Bold : QFont::Normal);
    }
    else if (CTextEditHandler::ItalicRole == role)
    {
        m_bIsItalic = (-1 != strSelection.indexOf("font-style:italic")) ? false : true;
        fmt.setFontItalic(m_bIsItalic);
    }
    else if (CTextEditHandler::UnderlineRole == role)
    {
        m_bIsUnderline = (-1 != strSelection.indexOf("text-decoration: underline;")) ? false : true;
        fmt.setFontUnderline(m_bIsUnderline);
    }

    cursor.mergeCharFormat(fmt);
    m_pEdit->mergeCurrentCharFormat(fmt);
}

/********************************************************************
 * toPlainText function converts Rich to Plain text
 *
 *
 *******************************************************************/
QString CTextEditHandler::toPlainText(const QString& _text)
{
    m_pEdit->setText(_text);
    return m_pEdit->toPlainText();
}

/********************************************************************
 * setFontFamily function set new font family to the text
 *
 *
 *******************************************************************/
QString CTextEditHandler::setFontFamily(const QString& _text, int _nPos, int _nPosEnd, const QString& _fontFamily)
{
    m_pEdit->setText(_text);

    QTextCursor cursor = m_pEdit->textCursor();

    if (_nPos == _nPosEnd) //no selection
    {
        cursor.setPosition(_nPos);
        if (!cursor.hasSelection())
        {
            cursor.select(QTextCursor::WordUnderCursor);
        }
    }
    else
    {
        cursor.setPosition(_nPos);
        cursor.setPosition(_nPosEnd, QTextCursor::KeepAnchor);
    }

    QTextCharFormat fmt;
    fmt.setFontFamily(_fontFamily);
    cursor.mergeCharFormat(fmt);
    m_pEdit->mergeCurrentCharFormat(fmt);

    return m_pEdit->toHtml();
}

/********************************************************************
 * setFontSize function set new font size to the text
 *
 *
 *******************************************************************/
QString CTextEditHandler::setFontSize(const QString& _text, int _nPos, int _nPosEnd, int _nPointSize)
{
    m_pEdit->setText(_text);

    QTextCursor cursor = m_pEdit->textCursor();

    if (_nPos == _nPosEnd) //no selection
    {
        cursor.setPosition(_nPos);
        if (!cursor.hasSelection())
        {
            cursor.select(QTextCursor::WordUnderCursor);
        }
    }
    else
    {
        cursor.setPosition(_nPos);
        cursor.setPosition(_nPosEnd, QTextCursor::KeepAnchor);
    }

    QTextCharFormat fmt;
    fmt.setFontPointSize(_nPointSize);
    cursor.mergeCharFormat(fmt);
    m_pEdit->mergeCurrentCharFormat(fmt);

    return m_pEdit->toPlainText();
}
<|endoftext|>


<commit_before>/*
 * Software License Agreement (BSD License)
 *
 *  Copyright (c) 2009-present, Willow Garage, Inc.
 *  All rights reserved.
 *
 *  Redistribution and use in source and binary forms, with or without
 *  modification, are permitted provided that the following conditions
 *  are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *   * Redistributions in binary form must reproduce the above
 *     copyright notice, this list of conditions and the following
 *     disclaimer in the documentation and/or other materials provided
 *     with the distribution.
 *   * Neither the name of Willow Garage, Inc. nor the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 *  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 *  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 *  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 *  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 *  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 *  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 *  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 *  POSSIBILITY OF SUCH DAMAGE.
 *
 * $Id$
 *
 */

#ifndef PCL_COMMON_IMPL_CENTROID_H_
#define PCL_COMMON_IMPL_CENTROID_H_

#include "pcl/ros/conversions.h"

/////////////////////////////////////////////////////////////////////////////////////////////
template <typename PointT> inline void
pcl::compute3DCentroid (const pcl::PointCloud<PointT> &cloud, Eigen::Vector4f &centroid)
{
  // Initialize to 0
  centroid.setZero ();
  if (cloud.points.empty ())
    return;
  // For each point in the cloud
  int cp = 0;

  // If the data is dense, we don't need to check for NaN
  if (cloud.is_dense)
  {
    for (size_t i = 0; i < cloud.points.size (); ++i)
      centroid += cloud.points[i].getVector4fMap ();
    centroid[3] = 0;
    centroid /= cloud.points.size ();
  }
  // NaN or Inf values could exist => check for them
  else
  {
    for (size_t i = 0; i < cloud.points.size (); ++i)
    {
      // Check if the point is invalid
      if (!pcl_isfinite (cloud.points[i].x) ||
          !pcl_isfinite (cloud.points[i].y) ||
          !pcl_isfinite (cloud.points[i].z))
        continue;

      centroid += cloud.points[i].getVector4fMap ();
      cp++;
    }
    centroid[3] = 0;
    centroid /= cp;
  }
}

//////////////////////////////////////////////////////////////////////////////////////////////
template <typename PointT> inline void
pcl::compute3DCentroid (const pcl::PointCloud<PointT> &cloud, const std::vector<int> &indices,
                        Eigen::Vector4f &centroid)
{
  // Initialize to 0
  centroid.setZero ();
  if (indices.empty ())
    return;
  // For each point in the cloud
  int cp = 0;

  // If the data is dense, we don't need to check for NaN
  if (cloud.is_dense)
  {
    for (size_t i = 0; i < indices.size (); ++i)
      centroid += cloud.points[indices[i]].getVector4fMap ();
    centroid[3] = 0;
    centroid /= indices.size ();
  }
  // NaN or Inf values could exist => check for them
  else
  {
    for (size_t i = 0; i < indices.size (); ++i)
    {
      // Check if the point is invalid
      if (!pcl_isfinite (cloud.points[indices[i]].x) ||
          !pcl_isfinite (cloud.points[indices[i]].y) ||
          !pcl_isfinite (cloud.points[indices[i]].z))
        continue;

      centroid += cloud.points[indices[i]].getVector4fMap ();
      cp++;
    }
    centroid[3] = 0;
    centroid /= cp;
  }
}

/////////////////////////////////////////////////////////////////////////////////////////////
template <typename PointT> inline void
pcl::compute3DCentroid (const pcl::PointCloud<PointT> &cloud,
                        const pcl::PointIndices &indices, Eigen::Vector4f &centroid)
{
  return (pcl::compute3DCentroid<PointT> (cloud, indices.indices, centroid));
}

//////////////////////////////////////////////////////////////////////////////////////////////
template <typename PointT> inline void
pcl::computeCovarianceMatrix (const pcl::PointCloud<PointT> &cloud,
                              const Eigen::Vector4f &centroid,
                              Eigen::Matrix3f &covariance_matrix)
{
  // Initialize to 0
  covariance_matrix.setZero ();

  if (cloud.points.empty ())
    return;
  // If the data is dense, we don't need to check for NaN
  if (cloud.is_dense)
  {
    // For each point in the cloud
    for (size_t i = 0; i < cloud.points.size (); ++i)
    {
      Eigen::Vector4f pt = cloud.points[i].getVector4fMap () - centroid;

      covariance_matrix (1, 1) += pt.y () * pt.y ();
      covariance_matrix (1, 2) += pt.y () * pt.z ();

      covariance_matrix (2, 2) += pt.z () * pt.z ();

      pt *= pt.x ();
      covariance_matrix (0, 0) += pt.x ();
      covariance_matrix (0, 1) += pt.y ();
      covariance_matrix (0, 2) += pt.z ();
    }
  }
  // NaN or Inf values could exist => check for them
  else
  {
    // For each point in the cloud
    for (size_t i = 0; i < cloud.points.size (); ++i)
    {
      // Check if the point is invalid
      if (!pcl_isfinite (cloud.points[i].x) ||
          !pcl_isfinite (cloud.points[i].y) ||
          !pcl_isfinite (cloud.points[i].z))
        continue;

      Eigen::Vector4f pt = cloud.points[i].getVector4fMap () - centroid;

      covariance_matrix (1, 1) += pt.y () * pt.y ();
      covariance_matrix (1, 2) += pt.y () * pt.z ();

      covariance_matrix (2, 2) += pt.z () * pt.z ();

      pt *= pt.x ();
      covariance_matrix (0, 0) += pt.x ();
      covariance_matrix (0, 1) += pt.y ();
      covariance_matrix (0, 2) += pt.z ();
    }
  }
  covariance_matrix (1, 0) = covariance_matrix (0, 1);
  covariance_matrix (2, 0) = covariance_matrix (0, 2);
  covariance_matrix (2, 1) = covariance_matrix (1, 2);
}

//////////////////////////////////////////////////////////////////////////////////////////////
template <typename PointT> inline void
pcl::computeCovarianceMatrixNormalized (const pcl::PointCloud<PointT> &cloud,
                                        const Eigen::Vector4f &centroid,
                                        Eigen::Matrix3f &covariance_matrix)
{
  pcl::computeCovarianceMatrix (cloud, centroid, covariance_matrix);
  covariance_matrix /= cloud.points.size ();
}

//////////////////////////////////////////////////////////////////////////////////////////////
template <typename PointT> inline void
pcl::computeCovarianceMatrix (const pcl::PointCloud<PointT> &cloud,
                              const std::vector<int> &indices,
                              const Eigen::Vector4f &centroid,
                              Eigen::Matrix3f &covariance_matrix)
{
  // Initialize to 0
  covariance_matrix.setZero ();

  if (indices.empty ())
    return;
  // If the data is dense, we don't need to check for NaN
  if (cloud.is_dense)
  {
    // For each point in the cloud
    for (size_t i = 0; i < indices.size (); ++i)
    {
      Eigen::Vector4f pt = cloud.points[indices[i]].getVector4fMap () - centroid;

      covariance_matrix (1, 1) += pt.y () * pt.y ();
      covariance_matrix (1, 2) += pt.y () * pt.z ();

      covariance_matrix (2, 2) += pt.z () * pt.z ();

      pt *= pt.x ();
      covariance_matrix (0, 0) += pt.x ();
      covariance_matrix (0, 1) += pt.y ();
      covariance_matrix (0, 2) += pt.z ();
    }
  }
  // NaN or Inf values could exist => check for them
  else
  {
    // For each point in the cloud
    for (size_t i = 0; i < indices.size (); ++i)
    {
      // Check if the point is invalid
      if (!pcl_isfinite (cloud.points[indices[i]].x) ||
          !pcl_isfinite (cloud.points[indices[i]].y) ||
          !pcl_isfinite (cloud.points[indices[i]].z))
        continue;

      Eigen::Vector4f pt = cloud.points[indices[i]].getVector4fMap () - centroid;

      covariance_matrix (1, 1) += pt.y () * pt.y ();
      covariance_matrix (1, 2) += pt.y () * pt.z ();

      covariance_matrix (2, 2) += pt.z () * pt.z ();

      pt *= pt.x ();
      covariance_matrix (0, 0) += pt.x ();
      covariance_matrix (0, 1) += pt.y ();
      covariance_matrix (0, 2) += pt.z ();
    }
  }
  covariance_matrix (1, 0) = covariance_matrix (0, 1);
  covariance_matrix (2, 0) = covariance_matrix (0, 2);
  covariance_matrix (2, 1) = covariance_matrix (1, 2);
}

//////////////////////////////////////////////////////////////////////////////////////////////
template <typename PointT> inline void
pcl::computeCovarianceMatrix (const pcl::PointCloud<PointT> &cloud,
                              const pcl::PointIndices &indices,
                              const Eigen::Vector4f &centroid,
                              Eigen::Matrix3f &covariance_matrix)
{
  return (pcl::computeCovarianceMatrix<PointT> (cloud, indices.indices, centroid));
}

//////////////////////////////////////////////////////////////////////////////////////////////
template <typename PointT> inline void
pcl::computeCovarianceMatrixNormalized (const pcl::PointCloud<PointT> &cloud,
                                        const std::vector<int> &indices,
                                        const Eigen::Vector4f &centroid,
                                        Eigen::Matrix3f &covariance_matrix)
{
  pcl::computeCovarianceMatrix (cloud, indices, centroid, covariance_matrix);
  covariance_matrix /= indices.size ();
}

//////////////////////////////////////////////////////////////////////////////////////////////
template <typename PointT> inline void
pcl::computeCovarianceMatrixNormalized (const pcl::PointCloud<PointT> &cloud,
                                        const pcl::PointIndices &indices,
                                        const Eigen::Vector4f &centroid,
                                        Eigen::Matrix3f &covariance_matrix)
{
  return (pcl::computeCovarianceMatrix (cloud, indices.indices, centroid, covariance_matrix));
}

//////////////////////////////////////////////////////////////////////////////////////////////
template <typename PointT> void
pcl::demeanPointCloud (const pcl::PointCloud<PointT> &cloud_in,
                       const Eigen::Vector4f &centroid,
                       pcl::PointCloud<PointT> &cloud_out)
{
  cloud_out = cloud_in;

  // Subtract the centroid from cloud_in
  for (size_t i = 0; i < cloud_in.points.size (); ++i)
    cloud_out.points[i].getVector4fMap () -= centroid;
}

//////////////////////////////////////////////////////////////////////////////////////////////
template <typename PointT> void
pcl::demeanPointCloud (const pcl::PointCloud<PointT> &cloud_in,
                       const std::vector<int> &indices,
                       const Eigen::Vector4f &centroid,
                       pcl::PointCloud<PointT> &cloud_out)
{
  cloud_out.header = cloud_in.header;
  cloud_out.is_dense = cloud_in.is_dense;
  if (indices.size () == cloud_in.points.size ())
  {
    cloud_out.width    = cloud_in.width;
    cloud_out.height   = cloud_in.height;
  }
  else
  {
    cloud_out.width    = indices.size ();
    cloud_out.height   = 1;
  }
  cloud_out.points.resize (indices.size ());

  // Subtract the centroid from cloud_in
  for (size_t i = 0; i < indices.size (); ++i)
    cloud_out.points[i].getVector4fMap () = cloud_in.points[indices[i]].getVector4fMap () -
                                            centroid;
}

//////////////////////////////////////////////////////////////////////////////////////////////
template <typename PointT> void
pcl::demeanPointCloud (const pcl::PointCloud<PointT> &cloud_in,
                       const Eigen::Vector4f &centroid,
                       Eigen::MatrixXf &cloud_out)
{
  size_t npts = cloud_in.points.size ();

  cloud_out = Eigen::MatrixXf::Zero (4, npts);        // keep the data aligned

  for (size_t i = 0; i < npts; ++i)
    // One column at a time
    cloud_out.block<4, 1> (0, i) = cloud_in.points[i].getVector4fMap () - centroid;

  // Make sure we zero the 4th dimension out (1 row, N columns)
  cloud_out.block (3, 0, 1, npts).setZero ();
}

//////////////////////////////////////////////////////////////////////////////////////////////
template <typename PointT> void
pcl::demeanPointCloud (const pcl::PointCloud<PointT> &cloud_in,
                       const std::vector<int> &indices,
                       const Eigen::Vector4f &centroid,
                       Eigen::MatrixXf &cloud_out)
{
  size_t npts = indices.size ();

  cloud_out = Eigen::MatrixXf::Zero (4, npts);        // keep the data aligned

  for (size_t i = 0; i < npts; ++i)
    // One column at a time
    cloud_out.block<4, 1> (0, i) = cloud_in.points[indices[i]].getVector4fMap () - centroid;

  // Make sure we zero the 4th dimension out (1 row, N columns)
  cloud_out.block (3, 0, 1, npts).setZero ();
}

//////////////////////////////////////////////////////////////////////////////////////////////
template <typename PointT> inline void
pcl::computeNDCentroid (const pcl::PointCloud<PointT> &cloud, Eigen::VectorXf &centroid)
{
  typedef typename pcl::traits::fieldList<PointT>::type FieldList;

  // Get the size of the fields
  centroid.setZero (boost::mpl::size<FieldList>::value);

  if (cloud.points.empty ())
    return;
  // Iterate over each point
  int size = cloud.points.size ();
  for (int i = 0; i < size; ++i)
  {
    // Iterate over each dimension
    pcl::for_each_type <FieldList> (NdCentroidFunctor <PointT> (cloud.points[i], centroid));
  }
  centroid /= size;
}

//////////////////////////////////////////////////////////////////////////////////////////////
template <typename PointT> inline void
pcl::computeNDCentroid (const pcl::PointCloud<PointT> &cloud, const std::vector<int> &indices,
                        Eigen::VectorXf &centroid)
{
  typedef typename pcl::traits::fieldList<PointT>::type FieldList;

  // Get the size of the fields
  centroid.setZero (boost::mpl::size<FieldList>::value);

  if (indices.empty ())
    return;
  // Iterate over each point
  int nr_points = indices.size ();
  for (int i = 0; i < nr_points; ++i)
  {
    // Iterate over each dimension
    pcl::for_each_type <FieldList> (NdCentroidFunctor <PointT> (cloud.points[indices[i]], centroid));
  }
  centroid /= nr_points;
}

/////////////////////////////////////////////////////////////////////////////////////////////
template <typename PointT> inline void
pcl::computeNDCentroid (const pcl::PointCloud<PointT> &cloud,
                        const pcl::PointIndices &indices, Eigen::VectorXf &centroid)
{
  return (pcl::computeNDCentroid<PointT> (cloud, indices.indices, centroid));
}

#endif  //#ifndef PCL_COMMON_IMPL_CENTROID_H_

<commit_msg>Fix: add missing header boost/mpl/size<commit_after>/*
 * Software License Agreement (BSD License)
 *
 *  Copyright (c) 2009-present, Willow Garage, Inc.
 *  All rights reserved.
 *
 *  Redistribution and use in source and binary forms, with or without
 *  modification, are permitted provided that the following conditions
 *  are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *   * Redistributions in binary form must reproduce the above
 *     copyright notice, this list of conditions and the following
 *     disclaimer in the documentation and/or other materials provided
 *     with the distribution.
 *   * Neither the name of Willow Garage, Inc. nor the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 *  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 *  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 *  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 *  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 *  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 *  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 *  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 *  POSSIBILITY OF SUCH DAMAGE.
 *
 * $Id$
 *
 */

#ifndef PCL_COMMON_IMPL_CENTROID_H_
#define PCL_COMMON_IMPL_CENTROID_H_

#include "pcl/ros/conversions.h"
#include <boost/mpl/size.hpp>

/////////////////////////////////////////////////////////////////////////////////////////////
template <typename PointT> inline void
pcl::compute3DCentroid (const pcl::PointCloud<PointT> &cloud, Eigen::Vector4f &centroid)
{
  // Initialize to 0
  centroid.setZero ();
  if (cloud.points.empty ())
    return;
  // For each point in the cloud
  int cp = 0;

  // If the data is dense, we don't need to check for NaN
  if (cloud.is_dense)
  {
    for (size_t i = 0; i < cloud.points.size (); ++i)
      centroid += cloud.points[i].getVector4fMap ();
    centroid[3] = 0;
    centroid /= cloud.points.size ();
  }
  // NaN or Inf values could exist => check for them
  else
  {
    for (size_t i = 0; i < cloud.points.size (); ++i)
    {
      // Check if the point is invalid
      if (!pcl_isfinite (cloud.points[i].x) ||
          !pcl_isfinite (cloud.points[i].y) ||
          !pcl_isfinite (cloud.points[i].z))
        continue;

      centroid += cloud.points[i].getVector4fMap ();
      cp++;
    }
    centroid[3] = 0;
    centroid /= cp;
  }
}

//////////////////////////////////////////////////////////////////////////////////////////////
template <typename PointT> inline void
pcl::compute3DCentroid (const pcl::PointCloud<PointT> &cloud, const std::vector<int> &indices,
                        Eigen::Vector4f &centroid)
{
  // Initialize to 0
  centroid.setZero ();
  if (indices.empty ())
    return;
  // For each point in the cloud
  int cp = 0;

  // If the data is dense, we don't need to check for NaN
  if (cloud.is_dense)
  {
    for (size_t i = 0; i < indices.size (); ++i)
      centroid += cloud.points[indices[i]].getVector4fMap ();
    centroid[3] = 0;
    centroid /= indices.size ();
  }
  // NaN or Inf values could exist => check for them
  else
  {
    for (size_t i = 0; i < indices.size (); ++i)
    {
      // Check if the point is invalid
      if (!pcl_isfinite (cloud.points[indices[i]].x) ||
          !pcl_isfinite (cloud.points[indices[i]].y) ||
          !pcl_isfinite (cloud.points[indices[i]].z))
        continue;

      centroid += cloud.points[indices[i]].getVector4fMap ();
      cp++;
    }
    centroid[3] = 0;
    centroid /= cp;
  }
}

/////////////////////////////////////////////////////////////////////////////////////////////
template <typename PointT> inline void
pcl::compute3DCentroid (const pcl::PointCloud<PointT> &cloud,
                        const pcl::PointIndices &indices, Eigen::Vector4f &centroid)
{
  return (pcl::compute3DCentroid<PointT> (cloud, indices.indices, centroid));
}

//////////////////////////////////////////////////////////////////////////////////////////////
template <typename PointT> inline void
pcl::computeCovarianceMatrix (const pcl::PointCloud<PointT> &cloud,
                              const Eigen::Vector4f &centroid,
                              Eigen::Matrix3f &covariance_matrix)
{
  // Initialize to 0
  covariance_matrix.setZero ();

  if (cloud.points.empty ())
    return;
  // If the data is dense, we don't need to check for NaN
  if (cloud.is_dense)
  {
    // For each point in the cloud
    for (size_t i = 0; i < cloud.points.size (); ++i)
    {
      Eigen::Vector4f pt = cloud.points[i].getVector4fMap () - centroid;

      covariance_matrix (1, 1) += pt.y () * pt.y ();
      covariance_matrix (1, 2) += pt.y () * pt.z ();

      covariance_matrix (2, 2) += pt.z () * pt.z ();

      pt *= pt.x ();
      covariance_matrix (0, 0) += pt.x ();
      covariance_matrix (0, 1) += pt.y ();
      covariance_matrix (0, 2) += pt.z ();
    }
  }
  // NaN or Inf values could exist => check for them
  else
  {
    // For each point in the cloud
    for (size_t i = 0; i < cloud.points.size (); ++i)
    {
      // Check if the point is invalid
      if (!pcl_isfinite (cloud.points[i].x) ||
          !pcl_isfinite (cloud.points[i].y) ||
          !pcl_isfinite (cloud.points[i].z))
        continue;

      Eigen::Vector4f pt = cloud.points[i].getVector4fMap () - centroid;

      covariance_matrix (1, 1) += pt.y () * pt.y ();
      covariance_matrix (1, 2) += pt.y () * pt.z ();

      covariance_matrix (2, 2) += pt.z () * pt.z ();

      pt *= pt.x ();
      covariance_matrix (0, 0) += pt.x ();
      covariance_matrix (0, 1) += pt.y ();
      covariance_matrix (0, 2) += pt.z ();
    }
  }
  covariance_matrix (1, 0) = covariance_matrix (0, 1);
  covariance_matrix (2, 0) = covariance_matrix (0, 2);
  covariance_matrix (2, 1) = covariance_matrix (1, 2);
}

//////////////////////////////////////////////////////////////////////////////////////////////
template <typename PointT> inline void
pcl::computeCovarianceMatrixNormalized (const pcl::PointCloud<PointT> &cloud,
                                        const Eigen::Vector4f &centroid,
                                        Eigen::Matrix3f &covariance_matrix)
{
  pcl::computeCovarianceMatrix (cloud, centroid, covariance_matrix);
  covariance_matrix /= cloud.points.size ();
}

//////////////////////////////////////////////////////////////////////////////////////////////
template <typename PointT> inline void
pcl::computeCovarianceMatrix (const pcl::PointCloud<PointT> &cloud,
                              const std::vector<int> &indices,
                              const Eigen::Vector4f &centroid,
                              Eigen::Matrix3f &covariance_matrix)
{
  // Initialize to 0
  covariance_matrix.setZero ();

  if (indices.empty ())
    return;
  // If the data is dense, we don't need to check for NaN
  if (cloud.is_dense)
  {
    // For each point in the cloud
    for (size_t i = 0; i < indices.size (); ++i)
    {
      Eigen::Vector4f pt = cloud.points[indices[i]].getVector4fMap () - centroid;

      covariance_matrix (1, 1) += pt.y () * pt.y ();
      covariance_matrix (1, 2) += pt.y () * pt.z ();

      covariance_matrix (2, 2) += pt.z () * pt.z ();

      pt *= pt.x ();
      covariance_matrix (0, 0) += pt.x ();
      covariance_matrix (0, 1) += pt.y ();
      covariance_matrix (0, 2) += pt.z ();
    }
  }
  // NaN or Inf values could exist => check for them
  else
  {
    // For each point in the cloud
    for (size_t i = 0; i < indices.size (); ++i)
    {
      // Check if the point is invalid
      if (!pcl_isfinite (cloud.points[indices[i]].x) ||
          !pcl_isfinite (cloud.points[indices[i]].y) ||
          !pcl_isfinite (cloud.points[indices[i]].z))
        continue;

      Eigen::Vector4f pt = cloud.points[indices[i]].getVector4fMap () - centroid;

      covariance_matrix (1, 1) += pt.y () * pt.y ();
      covariance_matrix (1, 2) += pt.y () * pt.z ();

      covariance_matrix (2, 2) += pt.z () * pt.z ();

      pt *= pt.x ();
      covariance_matrix (0, 0) += pt.x ();
      covariance_matrix (0, 1) += pt.y ();
      covariance_matrix (0, 2) += pt.z ();
    }
  }
  covariance_matrix (1, 0) = covariance_matrix (0, 1);
  covariance_matrix (2, 0) = covariance_matrix (0, 2);
  covariance_matrix (2, 1) = covariance_matrix (1, 2);
}

//////////////////////////////////////////////////////////////////////////////////////////////
template <typename PointT> inline void
pcl::computeCovarianceMatrix (const pcl::PointCloud<PointT> &cloud,
                              const pcl::PointIndices &indices,
                              const Eigen::Vector4f &centroid,
                              Eigen::Matrix3f &covariance_matrix)
{
  return (pcl::computeCovarianceMatrix<PointT> (cloud, indices.indices, centroid));
}

//////////////////////////////////////////////////////////////////////////////////////////////
template <typename PointT> inline void
pcl::computeCovarianceMatrixNormalized (const pcl::PointCloud<PointT> &cloud,
                                        const std::vector<int> &indices,
                                        const Eigen::Vector4f &centroid,
                                        Eigen::Matrix3f &covariance_matrix)
{
  pcl::computeCovarianceMatrix (cloud, indices, centroid, covariance_matrix);
  covariance_matrix /= indices.size ();
}

//////////////////////////////////////////////////////////////////////////////////////////////
template <typename PointT> inline void
pcl::computeCovarianceMatrixNormalized (const pcl::PointCloud<PointT> &cloud,
                                        const pcl::PointIndices &indices,
                                        const Eigen::Vector4f &centroid,
                                        Eigen::Matrix3f &covariance_matrix)
{
  return (pcl::computeCovarianceMatrix (cloud, indices.indices, centroid, covariance_matrix));
}

//////////////////////////////////////////////////////////////////////////////////////////////
template <typename PointT> void
pcl::demeanPointCloud (const pcl::PointCloud<PointT> &cloud_in,
                       const Eigen::Vector4f &centroid,
                       pcl::PointCloud<PointT> &cloud_out)
{
  cloud_out = cloud_in;

  // Subtract the centroid from cloud_in
  for (size_t i = 0; i < cloud_in.points.size (); ++i)
    cloud_out.points[i].getVector4fMap () -= centroid;
}

//////////////////////////////////////////////////////////////////////////////////////////////
template <typename PointT> void
pcl::demeanPointCloud (const pcl::PointCloud<PointT> &cloud_in,
                       const std::vector<int> &indices,
                       const Eigen::Vector4f &centroid,
                       pcl::PointCloud<PointT> &cloud_out)
{
  cloud_out.header = cloud_in.header;
  cloud_out.is_dense = cloud_in.is_dense;
  if (indices.size () == cloud_in.points.size ())
  {
    cloud_out.width    = cloud_in.width;
    cloud_out.height   = cloud_in.height;
  }
  else
  {
    cloud_out.width    = indices.size ();
    cloud_out.height   = 1;
  }
  cloud_out.points.resize (indices.size ());

  // Subtract the centroid from cloud_in
  for (size_t i = 0; i < indices.size (); ++i)
    cloud_out.points[i].getVector4fMap () = cloud_in.points[indices[i]].getVector4fMap () -
                                            centroid;
}

//////////////////////////////////////////////////////////////////////////////////////////////
template <typename PointT> void
pcl::demeanPointCloud (const pcl::PointCloud<PointT> &cloud_in,
                       const Eigen::Vector4f &centroid,
                       Eigen::MatrixXf &cloud_out)
{
  size_t npts = cloud_in.points.size ();

  cloud_out = Eigen::MatrixXf::Zero (4, npts);        // keep the data aligned

  for (size_t i = 0; i < npts; ++i)
    // One column at a time
    cloud_out.block<4, 1> (0, i) = cloud_in.points[i].getVector4fMap () - centroid;

  // Make sure we zero the 4th dimension out (1 row, N columns)
  cloud_out.block (3, 0, 1, npts).setZero ();
}

//////////////////////////////////////////////////////////////////////////////////////////////
template <typename PointT> void
pcl::demeanPointCloud (const pcl::PointCloud<PointT> &cloud_in,
                       const std::vector<int> &indices,
                       const Eigen::Vector4f &centroid,
                       Eigen::MatrixXf &cloud_out)
{
  size_t npts = indices.size ();

  cloud_out = Eigen::MatrixXf::Zero (4, npts);        // keep the data aligned

  for (size_t i = 0; i < npts; ++i)
    // One column at a time
    cloud_out.block<4, 1> (0, i) = cloud_in.points[indices[i]].getVector4fMap () - centroid;

  // Make sure we zero the 4th dimension out (1 row, N columns)
  cloud_out.block (3, 0, 1, npts).setZero ();
}

//////////////////////////////////////////////////////////////////////////////////////////////
template <typename PointT> inline void
pcl::computeNDCentroid (const pcl::PointCloud<PointT> &cloud, Eigen::VectorXf &centroid)
{
  typedef typename pcl::traits::fieldList<PointT>::type FieldList;

  // Get the size of the fields
  centroid.setZero (boost::mpl::size<FieldList>::value);

  if (cloud.points.empty ())
    return;
  // Iterate over each point
  int size = cloud.points.size ();
  for (int i = 0; i < size; ++i)
  {
    // Iterate over each dimension
    pcl::for_each_type <FieldList> (NdCentroidFunctor <PointT> (cloud.points[i], centroid));
  }
  centroid /= size;
}

//////////////////////////////////////////////////////////////////////////////////////////////
template <typename PointT> inline void
pcl::computeNDCentroid (const pcl::PointCloud<PointT> &cloud, const std::vector<int> &indices,
                        Eigen::VectorXf &centroid)
{
  typedef typename pcl::traits::fieldList<PointT>::type FieldList;

  // Get the size of the fields
  centroid.setZero (boost::mpl::size<FieldList>::value);

  if (indices.empty ())
    return;
  // Iterate over each point
  int nr_points = indices.size ();
  for (int i = 0; i < nr_points; ++i)
  {
    // Iterate over each dimension
    pcl::for_each_type <FieldList> (NdCentroidFunctor <PointT> (cloud.points[indices[i]], centroid));
  }
  centroid /= nr_points;
}

/////////////////////////////////////////////////////////////////////////////////////////////
template <typename PointT> inline void
pcl::computeNDCentroid (const pcl::PointCloud<PointT> &cloud,
                        const pcl::PointIndices &indices, Eigen::VectorXf &centroid)
{
  return (pcl::computeNDCentroid<PointT> (cloud, indices.indices, centroid));
}

#endif  //#ifndef PCL_COMMON_IMPL_CENTROID_H_

<|endoftext|>