Skip to content

Commit

Permalink
Merge branch 'dev'
Browse files Browse the repository at this point in the history
  • Loading branch information
JCash committed Nov 2, 2019
2 parents fc94abf + ac7758c commit e347cd7
Show file tree
Hide file tree
Showing 13 changed files with 1,104 additions and 1,117 deletions.
6 changes: 3 additions & 3 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ script:
- (cd test && ./compile_clang.sh)
- (cd src/examples && ./compile_clang.sh)
- cd ./build
- ./test
- ./test_double
- ./simple
- ASAN_OPTIONS=detect_stack_use_after_return=1 ./test
- ASAN_OPTIONS=detect_stack_use_after_return=1 ./test_double
- ASAN_OPTIONS=detect_stack_use_after_return=1 ./simple
- sleep 1 # wait for output
116 changes: 89 additions & 27 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,7 @@ A fast C/C++ header only implementation for creating 2D Voronoi diagrams from a

Uses [Fortune's sweep algorithm.](https://en.wikipedia.org/wiki/Fortune%27s_algorithm)

![50 points](images/example1.png)

<img src="images/example1.png" alt="vanilla" width="350"> <img src="images/example2.png" alt="custom clipping" width="350">

# Brief

Expand Down Expand Up @@ -43,12 +42,13 @@ This software is supplied "AS IS" without any warranties and support

# License

[The MIT license](http://choosealicense.com/licenses/mit/)
[LICENSE](./LICENSE) ([The MIT license](http://choosealicense.com/licenses/mit/))

# Feature comparisons

| Feature vs Impl | voronoi++ | boost | fastjet | jcv |
|-----------------------:|-----------|-------|---------|-----|
| Language | C++ | C++ | C | C |
| Edge clip | * | | * | * |
| Generate Edges | * | * | * | * |
| Generate Cells | * | * | | * |
Expand All @@ -57,27 +57,13 @@ This software is supplied "AS IS" without any warranties and support
| Easy Relaxation | | | | * |
| Custom Allocator | | | | * |


# Some Numbers

*Tests run on a Intel(R) Core(TM) i7-7567U CPU @ 3.50GHz MBP with 16 GB 2133 MHz LPDDR3 ram. Each test ran 20 times, and the minimum time is presented below*

*I removed the voronoi++ from the results, since it was consistently 10x-15x slower than the rest and consumed way more memory*
_
<br/>
<img src="test/images/timings_voronoi.png" alt="timings" width="350">
<img src="test/images/memory_voronoi.png" alt="memory" width="350">
<img src="test/images/num_allocations_voronoi.png" alt="num_allocations" width="350">

[Same stats, as tables](./test/report.md)

# Usage

The api contains these functions

```C
void jcv_diagram_generate( int num_points, const jcv_point* points, const jcv_rect* rect, jcv_diagram* diagram );
void jcv_diagram_generate_useralloc( int num_points, const jcv_point* points, const jcv_rect* rect, void* userallocctx, FJCVAllocFn allocfn, FJCVFreeFn freefn, jcv_diagram* diagram );
void jcv_diagram_generate( int num_points, const jcv_point* points, const jcv_rect* rect, const jcv_clipper* clipper, jcv_diagram* diagram );
void jcv_diagram_generate_useralloc( int num_points, const jcv_point* points, const jcv_rect* rect, const jcv_clipper* clipper, void* userallocctx, FJCVAllocFn allocfn, FJCVFreeFn freefn, jcv_diagram* diagram );
void jcv_diagram_free( jcv_diagram* diagram );

const jcv_site* jcv_diagram_get_sites( const jcv_diagram* diagram );
Expand All @@ -89,17 +75,17 @@ The input points are pruned if
* There are duplicates points
* The input points are outside of the bounding box
* The input points are rejected by the clipper's test function
The input bounding box is optional
The input clipper is optional, a default box clipper is used by default
## Example
Example implementation (see main.c for actual code)
Example implementation (see [main.c](./src/main.c) for actual code)
```C
#define JC_VORONOI_IMPLEMENTATION
// If you wish to use doubles
//#define JCV_REAL_TYPE double
//#define JCV_ATAN2 atan2
#include "jc_voronoi.h"
void draw_edges(const jcv_diagram* diagram);
Expand All @@ -109,7 +95,7 @@ void generate_and_draw(int numpoints, const jcv_point* points, int imagewidth, i
{
jcv_diagram diagram;
memset(&diagram, 0, sizeof(jcv_diagram));
jcv_diagram_generate(count, points, 0, &diagram );
jcv_diagram_generate(count, points, 0, 0, &diagram );
draw_edges(diagram);
draw_cells(diagram);
Expand Down Expand Up @@ -145,8 +131,13 @@ void draw_cells(const jcv_diagram* diagram)
}
}
}
```

## Relaxing the points

Here is an example of how to do the relaxations of the cells.

// Here is a simple example of how to do the relaxations of the cells
```C
void relax_points(const jcv_diagram* diagram, jcv_point* points)
{
const jcv_site* sites = jcv_diagram_get_sites(diagram);
Expand All @@ -170,17 +161,79 @@ void relax_points(const jcv_diagram* diagram, jcv_point* points)
points[site->index].y = sum.y / count;
}
}
```
## Double floating point precision
If you wish to use doubles, you can override these defines:
```C
#define JC_VORONOI_IMPLEMENTATION
#define JCV_REAL_TYPE double
#define JCV_ATAN2 atan2
#define JCV_SQRT sqrt
#define JCV_FLT_MAX DBL_MAX
#define JCV_PI 3.141592653589793115997963468544185161590576171875
//define JCV_EDGE_INTERSECT_THRESHOLD 1.0e-10F
#include "jc_voronoi.h"
```

## Custom clipping

The library also comes with a second header, that contains code for custom clipping of edges against a convex polygon.

The polygon is defined by a set of

Again, see [main.c](./src/main.c) for a practical example

```C

#define JC_VORONOI_CLIP_IMPLEMENTATION
#include "jc_voronoi_clip.h"

jcv_clipping_polygon polygon;
// Triangle
polygon.num_points = 3;
polygon.points = (jcv_point*)malloc(sizeof(jcv_point)*(size_t)polygon.num_points);

polygon.points[0].x = width/2;
polygon.points[1].x = width - width/5;
polygon.points[2].x = width/5;
polygon.points[0].y = height/5;
polygon.points[1].y = height - height/5;
polygon.points[2].y = height - height/5;

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;

jcv_diagram diagram;
memset(&diagram, 0, sizeof(jcv_diagram));
jcv_diagram_generate(count, (const jcv_point*)points, 0, clipper, &diagram);
```
# Some Numbers
*Tests run on a Intel(R) Core(TM) i7-7567U CPU @ 3.50GHz MBP with 16 GB 2133 MHz LPDDR3 ram. Each test ran 20 times, and the minimum time is presented below*
*I removed the voronoi++ from the results, since it was consistently 10x-15x slower than the rest and consumed way more memory*
_
<br/>
<img src="test/images/timings_voronoi.png" alt="timings" width="350">
<img src="test/images/memory_voronoi.png" alt="memory" width="350">
<img src="test/images/num_allocations_voronoi.png" alt="num_allocations" width="350">
[Same stats, as tables](./test/report.md)
# General thoughts
## Fastjet
The Fastjet version is built upon Steven Fortune's original C version, which Shane O'Sullivan improved upon.
The Fastjet version is built upon Steven Fortune's original C version, which Shane O'Sullivan improved upon.
Given the robustness and speed improvements of the implementation done by Fastjet,
that should be the base line to compare other implementations with.
Expand All @@ -205,7 +258,7 @@ For simply generating a 2D voronoi diagram using points as input, it is clearly
## Voronoi++
The performance of it is very slow (~20x slower than fastjet) and
The performance of it is very slow (~20x slower than fastjet) and
And it uses ~2.5x-3x more memory than the fastest algorithms.
Using the same data sets as the other algorithms, it breaks under some conditions.
Expand All @@ -216,3 +269,12 @@ Using the same data sets as the other algorithms, it breaks under some condition
A C++ version of the original C version from Steven Fortune.
Although fast, it's not completely robust and will produce errors.
# Gallery
I'd love to see what you're using this software for!
If possible, please send me images and some brief explanation of your usage of this library!
11 changes: 9 additions & 2 deletions compile_clang.sh
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
#!/usr/bin/env bash
mkdir -p build

clang -c src/stb_wrapper.c -o build/stb_wrapper.o
clang -o build/main -g -O2 -m64 -std=c99 -Wall -Weverything -Wno-float-equal -pedantic -lm build/stb_wrapper.o src/main.c
if [ "$USE_ASAN" != "" ]; then
ASAN="-fsanitize=address -fno-omit-frame-pointer -fsanitize-address-use-after-scope -fsanitize=undefined"
ASAN_LDFLAGS="-fsanitize=address "

echo Using ASAN
fi

clang $ASAN -c src/stb_wrapper.c -o build/stb_wrapper.o
clang $ASAN -o build/main -g -O0 -m64 -std=c99 -Wall -Weverything -Wno-float-equal -pedantic -lm -Isrc build/stb_wrapper.o src/main.c
4 changes: 3 additions & 1 deletion src/examples/compile_clang.sh
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,6 @@
BUILD_DIR=../../build
mkdir -p $BUILD_DIR

clang -Wall -Weverything -pedantic -Wno-float-equal simple.c -I.. -lm -o $BUILD_DIR/simple
ASAN_FLAGS="-O1 -fsanitize=address -fno-omit-frame-pointer -fsanitize-address-use-after-scope"
CFLAGS="$CFLAGS -Wall -Weverything -pedantic -Wno-float-equal"
clang $CFLAGS $ASAN_FLAGS simple.c -I.. -lm -o $BUILD_DIR/simple
4 changes: 2 additions & 2 deletions src/examples/simple.c
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
// gcc -Wall -Weverything -Wno-float-equal src/examples/simple.c -Isrc -o simple
//
// About:
//
//
// This example outputs 10 random 2D coordinates, and all the generated edges, to standard output.
// Note that the edges have duplicates, but you can easily filter them out.
//
Expand Down Expand Up @@ -48,7 +48,7 @@ int main(int argc, char** argv) {
printf("%f %f\n", (double)points[i].x, (double)points[i].y);
}

jcv_diagram_generate(NPOINT, (const jcv_point *)points, &bounding_box, &diagram);
jcv_diagram_generate(NPOINT, (const jcv_point *)points, &bounding_box, 0, &diagram);

printf("# Edges\n");
sites = jcv_diagram_get_sites(&diagram);
Expand Down
Loading

0 comments on commit e347cd7

Please sign in to comment.