diff options
Diffstat (limited to 'experimental/tectonics/world.c')
-rw-r--r-- | experimental/tectonics/world.c | 68 |
1 files changed, 45 insertions, 23 deletions
diff --git a/experimental/tectonics/world.c b/experimental/tectonics/world.c index a1dd4de..5aead24 100644 --- a/experimental/tectonics/world.c +++ b/experimental/tectonics/world.c @@ -2,19 +2,17 @@ #include <math.h> #include "tectonics.h" - -struct centroid_t { - double x, y; - int updates; -}; +#include "geometry.h" +#include "util.h" static void rebuild_tree(struct world_t *world) { + // remove any existing tree if (world->tree.nw != NULL) { - free_tree(world->tree.nw); - free_tree(world->tree.ne); - free_tree(world->tree.sw); - free_tree(world->tree.se); + quadtree_free(world->tree.nw); + quadtree_free(world->tree.ne); + quadtree_free(world->tree.sw); + quadtree_free(world->tree.se); world->tree.nw = NULL; world->tree.ne = NULL; world->tree.sw = NULL; @@ -22,16 +20,28 @@ static void rebuild_tree(struct world_t *world) } world->tree.id = -1; + // build a new tree for (int i=0; i<world->n_points; i++) { - insert(&(world->tree), world->points, i); + quadtree_insert(&(world->tree), world->points, i); } } + +/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ + +struct centroid_t { + double x, y; + int updates; +}; + +// monte-carlo lloyd's algorithm static void relax_points(struct world_t *world, int iterations) { + // centroids to compute struct centroid_t *centroid = malloc(sizeof(struct centroid_t) * world->n_points); - + + // initialize centroids with current locations for (int i=0; i<world->n_points; i++) { struct point_t *pt = world->points + i; struct centroid_t *c = centroid + i; @@ -40,18 +50,22 @@ static void relax_points(struct world_t *world, int iterations) c->updates = 1; } + // approximate centroids for (int i=0; i<iterations; i++) { printf("%02f%%\n", 100*((double)i+1)/iterations); + // generate a random point and find the closest + // terrain point double x = rand01(); double y = rand01(); - int closest = get_closest(&(world->tree), - world->points, - (struct point_t){x, y}); + int closest = quadtree_get_closest(&(world->tree), + world->points, + (struct point_t){x, y}); if (closest == -1) { printf("WARN: bad closest point!\n"); } else { + // average the centroid towards that random point struct centroid_t *c = centroid + closest; int u = c->updates; c->x = (u*c->x + x)/(u+1); @@ -60,6 +74,7 @@ static void relax_points(struct world_t *world, int iterations) } } + // update positions from centroids for (int i=0; i<world->n_points; i++) { struct point_t *pt = world->points + i; struct centroid_t *c = centroid + i; @@ -72,6 +87,9 @@ static void relax_points(struct world_t *world, int iterations) free(centroid); } + +/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ + void create_world(struct world_t *world, int n_points) { world->n_points = n_points; @@ -84,35 +102,39 @@ void create_world(struct world_t *world, int n_points) } struct point_t center = { 0.5, 0.5 }; - world->tree = new_node(center, 0.5); + world->tree = quadtree_new_node(center, 0.5); for (int i=0; i<n_points; i++) { struct point_t *pt = world->points + i; pt->x = rand01(); pt->y = rand01(); - //insert(&(world->tree), world->points, i); + //quadtree_insert(&(world->tree), world->points, i); } rebuild_tree(world); - for (int i=0; i<10; i++) - relax_points(world, 100000); + for (int i=0; i<3; i++) + relax_points(world, 10*world->n_points); } +/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ + void free_world(struct world_t *world) { if (world->tree.nw != NULL) { - free_tree(world->tree.nw); - free_tree(world->tree.ne); - free_tree(world->tree.sw); - free_tree(world->tree.se); + quadtree_free(world->tree.nw); + quadtree_free(world->tree.ne); + quadtree_free(world->tree.sw); + quadtree_free(world->tree.se); } free(world->points); } +/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ + void render_world(cairo_t *cr, struct world_t *world) { int width, height; @@ -128,5 +150,5 @@ void render_world(cairo_t *cr, struct world_t *world) cairo_stroke(cr); } - draw_quadtree(cr, &(world->tree)); + //draw_quadtree(cr, &(world->tree)); } |