JCash / voronoi

A C implementation for creating 2D voronoi diagrams
MIT License
621 stars 92 forks source link

Clipping against 2D Bounding box #79

Closed AndreAhmed closed 1 year ago

AndreAhmed commented 1 year ago

Is it possible to clip the voroni generated diagram against 2D BBOX ? Can you show an example please ? Many thanks!

AndreAhmed commented 1 year ago

What I want is to generate voroni like the following diagram image

AndreAhmed commented 1 year ago

@JCash

JCash commented 1 year ago

Hi @AndreAhmed ! You have two options.

  1. Pass in the rectargument to jcv_diagram_generate(). This gives you an axis aligned box. or 2. use the clipperargument to clip against a convex shape. Example is shown in the readme. EDIT: And the result is also shown in the readme: https://github.com/JCash/voronoi/blob/dev/images/example2.png
AndreAhmed commented 1 year ago

@JCash Would the second option gives similar shapes look as above picture ?

JCash commented 1 year ago

Yes

AndreAhmed commented 1 year ago

@JCash so the polygon that is convex, will be inbetween those cells ? Can you show a quick example of how it would work ? :) Many thanks for your fast response

AndreAhmed commented 1 year ago

@JCash I tried to clip against a convex shape, but it clips the boundary, I really want to have shapes like the above picture Here is my trial;


jcv_clipping_polygon polygon;
    jcv_clipper* clipper = 0;
    if (1)
    {

        printf("Clip polygon '%s' used\n", clipfile);
        // Triangle
        polygon.num_points = 5;
        polygon.points = (jcv_point*)malloc(sizeof(jcv_point) * (size_t)polygon.num_points);

        polygon.points[0].x = 500;
        polygon.points[1].x = 670;
        polygon.points[2].x = 239;
        polygon.points[3].x = 270;
        polygon.points[4].x = 329;
       // polygon.points[5].x = 321;

        polygon.points[0].y = 117;
        polygon.points[1].y = 626;
        polygon.points[2].y = 400;
        polygon.points[3].y = 211;
        polygon.points[4].y = 150;
       // polygon.points[5].y = 106;

        jcv_clipper polygonclipper;
        polygonclipper.test_fn = jcv_clip_polygon_test_point;
        polygonclipper.clip_fn = jcv_clip_polygon_clip_edge;
        polygonclipper.fill_fn = jcv_clip_polygon_fill_gaps;
        polygonclipper.ctx = &polygon;;

        clipper = &polygonclipper;

    }

example

JCash commented 1 year ago

The clipping is for the outer bounds of the diagram.

Each cell has its boundaries set from the diagram generation. move each vertex of the cell edges towards the center of the cell.

v = edge_vtx - cell_cente
new_edge_vtx = cell_center + v * 0.8f
AndreAhmed commented 1 year ago

@JCash Thanks so much for your response. Can you tell me as I'm beginner also, where to put those two lines of code ? In your header library right ?

JCash commented 1 year ago

No, not in the header.

You need to iterate over the result of the diagram generator, and for each cell, calculate new vertices for that cell.

AndreAhmed commented 1 year ago

@JCash How can I calculate the cell center ? Sorry about that beginner question can you show me a pseudo code for iterating for each cell ?

JCash commented 1 year ago

I really suggest you read through the examples here, in particular the "draw_cells": https://github.com/JCash/voronoi#example

The cell center is the site you passed into the diagram.

AndreAhmed commented 1 year ago

@JCash I'm trying to apply your pseudocode, hope that's fine ?


`       const jcv_site* sites_ = jcv_diagram_get_sites(&diagram);
        for (int i = 0; i < diagram.numsites; ++i)
        {
            const jcv_site* site = &sites_[i];

            jcv_graphedge* e = site->edges;
            while (e)
            {
                jcv_point v;
                v.x = e->edge->pos->x - site->p.x;
                v.y = e->edge->pos->y - site->p.y;
                e->pos->x = site->p.x + v.x * 0.8f;
                e->pos->y = site->p.y + v.y * 0.8f;

                e = e->next;
            }
        }`
AndreAhmed commented 1 year ago

@JCash and that's the result: example

AndreAhmed commented 1 year ago

@JCash I managed to do it, Many thanks!

The question is now, If I want to have several bounding boxes as restricted areas for voroni, is that possible ?

example

AndreAhmed commented 1 year ago

image

JCash commented 1 year ago

If I want to have several bounding boxes as restricted areas for voroni, is that possible ?

I don't know what you are after?

AndreAhmed commented 1 year ago

@JCash suppose I have defined several bounding boxes, and I generated 500points random, I want to generate voroni diagrams on all the grid, except those areas of bounding boxes.

JCash commented 1 year ago

Then I guess you shold remove those points from the point set? Simply don't pass them to the diagram generator?

AndreAhmed commented 1 year ago

@JCash IF I remove them, would your voroni generate diagrams outside the bbox, if I suppose to have one ? image

JCash commented 1 year ago

The generator generates voronoi diagram for the points you pass into it, nothing more. I suggest you try it out?