From 86d0b9df206d36a3574b6696d1a704e770ec3da2 Mon Sep 17 00:00:00 2001 From: jpchip Date: Sun, 9 Oct 2016 21:53:52 -0500 Subject: [PATCH 1/7] start work on overview-bounds rendermode --- overviewer_core/rendermodes.py | 10 +- .../src/primitives/overlay-bounds.c | 244 ++++++++++++++++++ 2 files changed, 253 insertions(+), 1 deletion(-) create mode 100644 overviewer_core/src/primitives/overlay-bounds.c diff --git a/overviewer_core/rendermodes.py b/overviewer_core/rendermodes.py index 00cac4a9c..2efd28e33 100644 --- a/overviewer_core/rendermodes.py +++ b/overviewer_core/rendermodes.py @@ -216,7 +216,15 @@ class StructureOverlay(Overlay): (((0, 0, 0, 157), (0, -1, 0, 4)), (255, 100, 0, 255)), ]), } - + +class BoundsOverlay(Overlay): + name = "overlay-bounds" + options = { + 'bounds': ('a list of ((((minx, minx, maxx, maxz)), ...), (r, g, b, a)) tuples for coloring boundaries', + [(((0, 0, 16, -16)), (255,160,122, 255)), + (((32, 32, 48, 48)), (255, 255, 0, 255)) + ]), + } class MineralOverlay(Overlay): name = "overlay-mineral" diff --git a/overviewer_core/src/primitives/overlay-bounds.c b/overviewer_core/src/primitives/overlay-bounds.c new file mode 100644 index 000000000..fb2e14720 --- /dev/null +++ b/overviewer_core/src/primitives/overlay-bounds.c @@ -0,0 +1,244 @@ +/* + * This file is part of the Minecraft Overviewer. + * + * Minecraft Overviewer is free software: you can redistribute it and/or + * modify it under the terms of the GNU General Public License as published + * by the Free Software Foundation, either version 3 of the License, or (at + * your option) any later version. + * + * Minecraft Overviewer is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General + * Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with the Overviewer. If not, see . + */ + +#include "overlay.h" + +typedef enum { false, true } bool; + +typedef struct { + /* inherits from overlay */ + RenderPrimitiveOverlay parent; + void *bounds; + int numcolors; +} RenderPrimitiveStructure; + +struct Condition{ + int minx, minz, maxx, maxz; +}; + + +struct Color { + int numconds; + struct Condition *conditions; + unsigned char r, g, b, a; +}; + +static int is_inside(int x, int z, int minx, int minz, int maxx, int maxz) { + +} + +static void get_color(void *data, + RenderState *state, + unsigned char *r, + unsigned char *g, + unsigned char *b, + unsigned char *a) { + /** + * Calculate the color at the current position and store the values to r,g,b,a. + **/ + RenderPrimitiveStructure *self = (RenderPrimitiveStructure *)data; + int x = state->x, z = state->z, y_max, y, col, cond; + struct Color *bounds = (struct Color *)(self->bounds); + struct Condition * c = NULL; + bool any = true; + y_max = state->y + 1; + + /** + * Check for every color in the current point is in the given bounds, + * and color appropriately + **/ + // iterate over all the colors + for ( col = 0; col < self->numcolors; col++) { + any = false; + // iterate over all conditions + for (cond = 0; cond < bounds[col].numconds; cond++) { + c = (struct Condition *)&bounds[col].conditions[cond]; + // check current point is in the condition + if(is_inside(x, z, c)) { + any = true; + } + } + + //if current point is in any of the conditions, draw it this color + if (any) { + // set the color + *r = bounds[col].r; + *g = bounds[col].g; + *b = bounds[col].b; + *a = bounds[col].a; + return; + } + } + return; +} + +static int overlay_bounds_start(void *data, RenderState *state, PyObject *support) { + /** + * Initializing the search for bounds by parsing the arguments and storing them into + * appropriate bounds. If no arguments are passed create and use default values. + **/ + PyObject *opt; + RenderPrimitiveStructure* self; + + /* first, chain up */ + int ret = primitive_overlay.start(data, state, support); + if (ret != 0) + return ret; + + /* now do custom initializations */ + self = (RenderPrimitiveStructure *)data; + + // opt is a borrowed reference. do not deref + // store the bounds python object into opt. + if (!render_mode_parse_option(support, "bounds", "O", &(opt))) + return 1; + + /** + * Check if a sane option was passed. + **/ + if (opt && opt != Py_None) { + struct Color *bounds = NULL; + struct Condition *cond = NULL; + Py_ssize_t bounds_size = 0, i, cond_size = 0, n = 0; + bool cont = true; + + opt = PySequence_Fast(opt, "expected a sequence"); + if (!opt) { + PyErr_SetString(PyExc_TypeError, "'bounds' must be a a sequence"); + return 1; + } + + bounds_size = PySequence_Fast_GET_SIZE(opt); + // Getting space on the heap and do not forget to set self->numcolors. + bounds = self->bounds = calloc(bounds_size, sizeof(struct Color)); + self->numcolors = bounds_size; + if (bounds == NULL) { + PyErr_SetString(PyExc_MemoryError, "failed to allocate memory"); + return 1; + } + + /** + * Try to parse the definitions of conditions and colors. + **/ + if (cont) { + for (i = 0; i < bounds_size; i++) { + PyObject *structure = PyList_GET_ITEM(opt, i); + // condspy holding the conditions tuple of variable length (python object) + PyObject *condspy; + // colorpy holding the 4 tuple with r g b a values of the color + PyObject *colorpy; + + // getting the condspy and colorpy out of the bounds. + if (!PyArg_ParseTuple(structure, "OO", &condspy, &colorpy)) { + // Exception set automatically + free(bounds); + self->bounds = NULL; + return 1; + } + + // Parse colorpy into a c-struct. + if (!PyArg_ParseTuple( colorpy, "bbbb", + &bounds[i].r, + &bounds[i].g, + &bounds[i].b, + &bounds[i].a)) { + free(bounds); + self->bounds = NULL; + return 1; + } + + // Convert condspy to a fast sequence + condspy = PySequence_Fast(condspy, "Failed to parse conditions"); + if(condspy == NULL) { + free(bounds); + self->bounds = NULL; + return 1; + } + + // get the number of conditions. + bounds[i].numconds = PySequence_Fast_GET_SIZE(condspy); + // reserve enough memory for the conditions. + cond = calloc(bounds[i].numconds, sizeof(struct Condition)); + bounds[i].conditions = cond; + + if (bounds[i].conditions == NULL) { + PyErr_SetString(PyExc_MemoryError, "failed to allocate memory"); + free(bounds); + self->bounds = NULL; + return 1; + } + + // iterate over all the conditions and read them. + for (n = 0; n < bounds[i].numconds; n++) { + PyObject *ccond = PySequence_Fast_GET_ITEM(condspy, n); + if(!PyArg_ParseTuple( ccond, "iiii", + &cond[n].minx, + &cond[n].minz, + &cond[n].maxx, + &cond[n].maxz)){ + int x = 0; + for(x = 0; x < bounds_size; x++){ + free(bounds[x].conditions); + } + free(bounds); + self->bounds = NULL; + return 1; + } + } + } + } + } + + /* setup custom color */ + self->parent.get_color = get_color; + + return 0; +} + +static void overlay_bounds_finish(void *data, RenderState *state) { + /* first free all *our* stuff */ + RenderPrimitiveStructure* self = (RenderPrimitiveStructure *)data; + int i = 0; + + if(self->bounds) { + // freeing the nested structure + struct Color * m = self->bounds; + for(i = 0; i < self->numcolors; i++){ + if(m[i].conditions) + free(m[i].conditions); + } + } + + if (self->bounds) { + free(self->bounds); + self->bounds = NULL; + } + + /* now, chain up */ + primitive_overlay.finish(data, state); +} + +RenderPrimitiveInterface primitive_overlay_bounds = { + "overlay-bounds", + sizeof(RenderPrimitiveStructure), + overlay_bounds_start, + overlay_bounds_finish, + NULL, + NULL, + overlay_draw, +}; + From c7dd67d4f6ae0bacb8559b2af8773196129fb94a Mon Sep 17 00:00:00 2001 From: jpchip Date: Mon, 10 Oct 2016 19:48:55 -0500 Subject: [PATCH 2/7] fix example, add is_inside function --- overviewer_core/rendermodes.py | 4 ++-- overviewer_core/src/primitives/overlay-bounds.c | 7 +++++-- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/overviewer_core/rendermodes.py b/overviewer_core/rendermodes.py index 2efd28e33..32954923c 100644 --- a/overviewer_core/rendermodes.py +++ b/overviewer_core/rendermodes.py @@ -220,8 +220,8 @@ class StructureOverlay(Overlay): class BoundsOverlay(Overlay): name = "overlay-bounds" options = { - 'bounds': ('a list of ((((minx, minx, maxx, maxz)), ...), (r, g, b, a)) tuples for coloring boundaries', - [(((0, 0, 16, -16)), (255,160,122, 255)), + 'bounds': ('a list of ((((minx, minz, maxx, maxz)), ...), (r, g, b, a)) tuples for coloring boundaries', + [(((0, -16, 16, 0)), (255, 160, 122, 255)), (((32, 32, 48, 48)), (255, 255, 0, 255)) ]), } diff --git a/overviewer_core/src/primitives/overlay-bounds.c b/overviewer_core/src/primitives/overlay-bounds.c index fb2e14720..0f778eaee 100644 --- a/overviewer_core/src/primitives/overlay-bounds.c +++ b/overviewer_core/src/primitives/overlay-bounds.c @@ -37,8 +37,11 @@ struct Color { unsigned char r, g, b, a; }; +/* +* Determines if point x,z is inside bounds minx, minz, maxx, maxz +*/ static int is_inside(int x, int z, int minx, int minz, int maxx, int maxz) { - + return (x >= minx && x <= maxx && z >= minz && z <= maxz); } static void get_color(void *data, @@ -68,7 +71,7 @@ static void get_color(void *data, for (cond = 0; cond < bounds[col].numconds; cond++) { c = (struct Condition *)&bounds[col].conditions[cond]; // check current point is in the condition - if(is_inside(x, z, c)) { + if(is_inside(x, z, c->minx, c->minz, c->maxx, c->maxz)) { any = true; } } From b4f59279d8402a208d0ede10bceb21d265880a60 Mon Sep 17 00:00:00 2001 From: jpchip Date: Mon, 10 Oct 2016 21:24:46 -0500 Subject: [PATCH 3/7] cleanup code --- overviewer_core/rendermodes.py | 5 +---- .../src/primitives/overlay-bounds.c | 21 +++++++++---------- 2 files changed, 11 insertions(+), 15 deletions(-) diff --git a/overviewer_core/rendermodes.py b/overviewer_core/rendermodes.py index 32954923c..a5656d0e6 100644 --- a/overviewer_core/rendermodes.py +++ b/overviewer_core/rendermodes.py @@ -220,10 +220,7 @@ class StructureOverlay(Overlay): class BoundsOverlay(Overlay): name = "overlay-bounds" options = { - 'bounds': ('a list of ((((minx, minz, maxx, maxz)), ...), (r, g, b, a)) tuples for coloring boundaries', - [(((0, -16, 16, 0)), (255, 160, 122, 255)), - (((32, 32, 48, 48)), (255, 255, 0, 255)) - ]), + 'bounds': ('a list of (((minx, minz, maxx, maxz), ...), (r, g, b, a)) tuples for coloring boundaries', None), } class MineralOverlay(Overlay): diff --git a/overviewer_core/src/primitives/overlay-bounds.c b/overviewer_core/src/primitives/overlay-bounds.c index 0f778eaee..9f3869ab0 100644 --- a/overviewer_core/src/primitives/overlay-bounds.c +++ b/overviewer_core/src/primitives/overlay-bounds.c @@ -24,7 +24,7 @@ typedef struct { RenderPrimitiveOverlay parent; void *bounds; int numcolors; -} RenderPrimitiveStructure; +} RenderPrimitiveBounds; struct Condition{ int minx, minz, maxx, maxz; @@ -53,12 +53,11 @@ static void get_color(void *data, /** * Calculate the color at the current position and store the values to r,g,b,a. **/ - RenderPrimitiveStructure *self = (RenderPrimitiveStructure *)data; - int x = state->x, z = state->z, y_max, y, col, cond; + RenderPrimitiveBounds *self = (RenderPrimitiveBounds *)data; + int x = state->x, z = state->z, col, cond; struct Color *bounds = (struct Color *)(self->bounds); struct Condition * c = NULL; bool any = true; - y_max = state->y + 1; /** * Check for every color in the current point is in the given bounds, @@ -95,7 +94,7 @@ static int overlay_bounds_start(void *data, RenderState *state, PyObject *suppor * appropriate bounds. If no arguments are passed create and use default values. **/ PyObject *opt; - RenderPrimitiveStructure* self; + RenderPrimitiveBounds* self; /* first, chain up */ int ret = primitive_overlay.start(data, state, support); @@ -103,7 +102,7 @@ static int overlay_bounds_start(void *data, RenderState *state, PyObject *suppor return ret; /* now do custom initializations */ - self = (RenderPrimitiveStructure *)data; + self = (RenderPrimitiveBounds *)data; // opt is a borrowed reference. do not deref // store the bounds python object into opt. @@ -139,14 +138,14 @@ static int overlay_bounds_start(void *data, RenderState *state, PyObject *suppor **/ if (cont) { for (i = 0; i < bounds_size; i++) { - PyObject *structure = PyList_GET_ITEM(opt, i); + PyObject *bound = PyList_GET_ITEM(opt, i); // condspy holding the conditions tuple of variable length (python object) PyObject *condspy; // colorpy holding the 4 tuple with r g b a values of the color PyObject *colorpy; // getting the condspy and colorpy out of the bounds. - if (!PyArg_ParseTuple(structure, "OO", &condspy, &colorpy)) { + if (!PyArg_ParseTuple(bound, "OO", &condspy, &colorpy)) { // Exception set automatically free(bounds); self->bounds = NULL; @@ -214,11 +213,11 @@ static int overlay_bounds_start(void *data, RenderState *state, PyObject *suppor static void overlay_bounds_finish(void *data, RenderState *state) { /* first free all *our* stuff */ - RenderPrimitiveStructure* self = (RenderPrimitiveStructure *)data; + RenderPrimitiveBounds* self = (RenderPrimitiveBounds *)data; int i = 0; if(self->bounds) { - // freeing the nested structure + // freeing the nested bounds struct Color * m = self->bounds; for(i = 0; i < self->numcolors; i++){ if(m[i].conditions) @@ -237,7 +236,7 @@ static void overlay_bounds_finish(void *data, RenderState *state) { RenderPrimitiveInterface primitive_overlay_bounds = { "overlay-bounds", - sizeof(RenderPrimitiveStructure), + sizeof(RenderPrimitiveBounds), overlay_bounds_start, overlay_bounds_finish, NULL, From 74668607f0bde663cb26fad689b24f736e85559f Mon Sep 17 00:00:00 2001 From: jpchip Date: Tue, 18 Oct 2016 17:14:15 -0500 Subject: [PATCH 4/7] fixed calculating absolute x and z positions --- overviewer_core/src/primitives/overlay-bounds.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/overviewer_core/src/primitives/overlay-bounds.c b/overviewer_core/src/primitives/overlay-bounds.c index 9f3869ab0..171bfaaaa 100644 --- a/overviewer_core/src/primitives/overlay-bounds.c +++ b/overviewer_core/src/primitives/overlay-bounds.c @@ -54,11 +54,11 @@ static void get_color(void *data, * Calculate the color at the current position and store the values to r,g,b,a. **/ RenderPrimitiveBounds *self = (RenderPrimitiveBounds *)data; - int x = state->x, z = state->z, col, cond; + int x = (state->chunkx * 16) + state->x, z = (state->chunkz * 16) + state->z, col, cond; struct Color *bounds = (struct Color *)(self->bounds); struct Condition * c = NULL; bool any = true; - + /** * Check for every color in the current point is in the given bounds, * and color appropriately From 1c5546d1eee4cebb7cf96af9b4be206911e7acda Mon Sep 17 00:00:00 2001 From: jpchip Date: Tue, 18 Oct 2016 20:20:09 -0500 Subject: [PATCH 5/7] update docs to include BoundsOverlay --- docs/config.rst | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/docs/config.rst b/docs/config.rst index 14904a45a..19abbdf9f 100644 --- a/docs/config.rst +++ b/docs/config.rst @@ -1195,6 +1195,28 @@ BiomeOverlay BiomeOverlay(biomes=[("Forest", (0, 255, 0)), ("Desert", (255, 0, 0))]) +BoundsOverlay + Color the map according to a set of bounding boxes. With this boundaries of + clans, land ownership, towns, etc. can be realized. + + This Overlay colors according to a patterns that are specified as + multiple tuples of the form ``(minx, minz, maxx, maxz)``. So + by specifying ``(0, 0, 16, 16)`` all the blocks (inclusive) within the boundary + created by these coordinates will be colored. The color is then specified as ``(r, g, b, a)``. + + Example:: + + BoundsOverlay(bounds=[ + (((0, 0, 16, 16),), (255, 160, 122, 255)), + (((17, 17, 23, 23),(24, 24, 40, 40)), (75, 0, 130, 255)), + ]) + + In this example the blocks within (0, 0, 16, 16) will be red and + all blocks within both (17, 17, 23, 23) and (24, 24, 40, 40) will be blue. + + Note the trailing comma behind the tuple, this is required if only one bounding + box is given. + Defining Custom Rendermodes --------------------------- From 09985a5c5c5fb2d015ab1226df9d2aaa9cd2079c Mon Sep 17 00:00:00 2001 From: jpchip Date: Tue, 18 Oct 2016 20:22:59 -0500 Subject: [PATCH 6/7] fix doc formatting --- docs/config.rst | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/docs/config.rst b/docs/config.rst index 19abbdf9f..0ad6f3c07 100644 --- a/docs/config.rst +++ b/docs/config.rst @@ -1197,12 +1197,12 @@ BiomeOverlay BoundsOverlay Color the map according to a set of bounding boxes. With this boundaries of - clans, land ownership, towns, etc. can be realized. + clans, land ownership, towns, etc. can be realized. This Overlay colors according to a patterns that are specified as multiple tuples of the form ``(minx, minz, maxx, maxz)``. So by specifying ``(0, 0, 16, 16)`` all the blocks (inclusive) within the boundary - created by these coordinates will be colored. The color is then specified as ``(r, g, b, a)``. + created by these coordinates will be colored. The color is then specified as ``(r, g, b, a)``. Example:: @@ -1212,11 +1212,11 @@ BoundsOverlay ]) In this example the blocks within (0, 0, 16, 16) will be red and - all blocks within both (17, 17, 23, 23) and (24, 24, 40, 40) will be blue. + all blocks within both (17, 17, 23, 23) and (24, 24, 40, 40) will be blue. + + Note the trailing comma behind the tuple, this is required if only one bounding + box is given. - Note the trailing comma behind the tuple, this is required if only one bounding - box is given. - Defining Custom Rendermodes --------------------------- From 42572ec47fcd8fc97216a33529413cb8f0de2148 Mon Sep 17 00:00:00 2001 From: jpchip Date: Thu, 20 Oct 2016 21:13:15 -0500 Subject: [PATCH 7/7] add curly braces to if statements --- overviewer_core/src/primitives/overlay-bounds.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/overviewer_core/src/primitives/overlay-bounds.c b/overviewer_core/src/primitives/overlay-bounds.c index 171bfaaaa..d543346b5 100644 --- a/overviewer_core/src/primitives/overlay-bounds.c +++ b/overviewer_core/src/primitives/overlay-bounds.c @@ -98,16 +98,18 @@ static int overlay_bounds_start(void *data, RenderState *state, PyObject *suppor /* first, chain up */ int ret = primitive_overlay.start(data, state, support); - if (ret != 0) - return ret; + if (ret != 0) { + return ret; + } /* now do custom initializations */ self = (RenderPrimitiveBounds *)data; // opt is a borrowed reference. do not deref // store the bounds python object into opt. - if (!render_mode_parse_option(support, "bounds", "O", &(opt))) - return 1; + if (!render_mode_parse_option(support, "bounds", "O", &(opt))) { + return 1; + } /** * Check if a sane option was passed. @@ -220,8 +222,9 @@ static void overlay_bounds_finish(void *data, RenderState *state) { // freeing the nested bounds struct Color * m = self->bounds; for(i = 0; i < self->numcolors; i++){ - if(m[i].conditions) - free(m[i].conditions); + if(m[i].conditions) { + free(m[i].conditions); + } } }