summaryrefslogtreecommitdiff
path: root/experimental/tectonics/world.c
diff options
context:
space:
mode:
Diffstat (limited to 'experimental/tectonics/world.c')
-rw-r--r--experimental/tectonics/world.c105
1 files changed, 105 insertions, 0 deletions
diff --git a/experimental/tectonics/world.c b/experimental/tectonics/world.c
new file mode 100644
index 0000000..cfc5d14
--- /dev/null
+++ b/experimental/tectonics/world.c
@@ -0,0 +1,105 @@
+#include <stdio.h>
+#include <math.h>
+
+#include "tectonics.h"
+
+struct centroid_t {
+ double x, y;
+ int updates;
+};
+
+static int closest_point(struct world_t *world, double x, double y)
+{
+ double dist = 1e9;
+ int closest = -1;
+ for (int i=0; i<world->n_points; i++) {
+ struct point_t *pt = world->points + i;
+ double d = distance(x, y, pt->x, pt->y);
+ if (d <= dist) {
+ dist = d;
+ closest = i;
+ }
+ }
+ return closest;
+}
+
+static void relax_points(struct world_t *world, int iterations)
+{
+ struct centroid_t *centroid =
+ malloc(sizeof(struct centroid_t) * world->n_points);
+
+ for (int i=0; i<world->n_points; i++) {
+ struct point_t *pt = world->points + i;
+ struct centroid_t *c = centroid + i;
+ c->x = pt->x;
+ c->y = pt->y;
+ c->updates = 1;
+ }
+
+ for (int i=0; i<iterations; i++) {
+ printf("%02f%%\n", 100*((double)i+1)/iterations);
+ double x = rand01();
+ double y = rand01();
+ int closest = closest_point(world, x, y);
+
+ int t = centroid[closest].updates;
+ centroid[closest].x = (t*centroid[closest].x + x)/(t+1);
+ centroid[closest].y = (t*centroid[closest].y + y)/(t+1);
+ centroid[closest].updates += 1;
+ }
+
+ for (int i=0; i<world->n_points; i++) {
+ struct point_t *pt = world->points + i;
+ struct centroid_t *c = centroid + i;
+ pt->x = c->x;
+ pt->y = c->y;
+ }
+}
+
+void create_world(struct world_t *world, int n_points)
+{
+ world->n_points = n_points;
+ world->points = malloc(sizeof(struct point_t) * n_points);
+ if (world->points == NULL) {
+ fprintf(stderr,
+ "ERROR: failed to allocate %d points\n",
+ n_points);
+ return;
+ }
+
+ struct point_t center = { 0.5, 0.5 };
+ world->tree = 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);
+ }
+}
+
+
+void free_world(struct world_t *world)
+{
+ free(world->points);
+}
+
+
+void render_world(cairo_t *cr, struct world_t *world)
+{
+ int width, height;
+ get_cairo_size(cr, &width, &height);
+ double r = ((double)width) / (100*sqrt(world->n_points));
+ cairo_set_source_rgba(cr, 1, 0, 0, 1);
+
+ for (int i=0; i<world->n_points; i++) {
+ struct point_t *pt = world->points + i;
+ double xc = pt->x * width;
+ double yc = pt->y * height;
+ cairo_arc(cr, xc, yc, r, 0, 2*M_PI);
+ cairo_stroke(cr);
+ }
+
+ draw_quadtree(cr, &(world->tree));
+}