Skip to content

Commit

Permalink
Merge dev to master (#17)
Browse files Browse the repository at this point in the history
* CI tests

* Added bounding box to jcv_diagram_generate()
Input points are now culled against the bounding box
Added .csv support to test program

* Added missing file

* Windown compile fixes

* Added missing include for linux

* Added an examples folder

* Ensure to include stdlib.h for malloc/free (#14)

*  Updated max number of events that can be used at the same time (#16)

* Increased the maximum number of events the priority queue can have

* Added test for max num events
  • Loading branch information
JCash authored Jun 3, 2018
1 parent 87c0ab2 commit c1bc7e1
Show file tree
Hide file tree
Showing 16 changed files with 222 additions and 134 deletions.
9 changes: 6 additions & 3 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@ os:

script:
- ./compile_clang.sh
- cd test
- ./compile_clang.sh
- ../build/test
- (cd test && ./compile_clang.sh)
- (cd src/examples && ./compile_clang.sh)
- cd ./build
- ./test
- ./simple
- sleep 1 # wait for output
178 changes: 76 additions & 102 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,7 @@ Uses [Fortune's sweep algorithm.](https://en.wikipedia.org/wiki/Fortune%27s_algo
![50 points](images/example1.png)


Brief
=====
# Brief

I was realizing that the previous 2D voronoi generator I was using, was taking up too much time in my app,
and worse, sometimes it also produced errors.
Expand All @@ -38,21 +37,82 @@ So this project set out to achieve a combination of the good things the other li

But mostly, I did it for fun :)

Disclaimer
==========
# Disclaimer

This software is supplied "AS IS" without any warranties and support

License
=======
# License

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

# Feature comparisons

Usage
=====
| Feature vs Impl | voronoi++ | boost | fastjet | jcv |
|-----------------------:|-----------|-------|---------|-----|
| Edge clip | * | | * | * |
| Generate Edges | * | * | * | * |
| Generate Cells | * | * | | * |
| Cell Edges Not Flipped | | * | | * |
| Cell Edges CCW | | * | | * |
| 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 average time is presented below*

*I removed the voronoi++ from the results, since they were consistently 10x-15x slower than the rest and consumed way more memory*
_
<br/>
<img src="images/timings_small.png" alt="timings small" width="350">
<img src="images/memory_small.png" alt="memory small" width="350">
_
<br/>
<img src="images/timings_medium.png" alt="timings medium" width="350">
<img src="images/memory_medium.png" alt="memory medium" width="350">
_
<br/>
<img src="images/timings_large.png" alt="timings large" width="350">
<img src="images/memory_large.png" alt="memory large" width="350">

Same stats, as tables

## Timings medium

| counts | jc_voronoi | fastjet | boost |
|-------:|------------|-----------|------------|
| 1000 | 0.9119 ms | 0.8439 ms | 1.5290 ms |
| 2000 | 1.7700 ms | 1.7010 ms | 3.1100 ms |
| 3000 | 2.7680 ms | 2.5730 ms | 4.7400 ms |
| 4000 | 3.8420 ms | 3.4450 ms | 6.3510 ms |
| 5000 | 4.9620 ms | 4.3500 ms | 8.0390 ms |
| 6000 | 6.1100 ms | 5.2610 ms | 9.6720 ms |
| 7000 | 7.3090 ms | 6.2330 ms | 11.4420 ms |
| 8000 | 8.5580 ms | 7.1420 ms | 13.2150 ms |
| 9000 | 10.0490 ms | 8.0130 ms | 15.0490 ms |
| 10000 | 11.0250 ms | 8.9560 ms | 16.8780 ms |


## Memory medium

| counts | jc_voronoi | fastjet | boost |
|-------:|------------|---------|---------|
| 1000 | 447 kb | 137 kb | 888 kb |
| 2000 | 894 kb | 275 kb | 1779 kb |
| 3000 | 1325 kb | 412 kb | 2751 kb |
| 4000 | 1773 kb | 549 kb | 3567 kb |
| 5000 | 2220 kb | 687 kb | 4698 kb |
| 6000 | 2651 kb | 824 kb | 5508 kb |
| 7000 | 3098 kb | 961 kb | 6318 kb |
| 8000 | 3546 kb | 1098 kb | 7125 kb |
| 9000 | 3977 kb | 1235 kb | 8578 kb |
| 10000 | 4424 kb | 1372 kb | 9383 kb |

The api is very small

# 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 );
Expand All @@ -70,6 +130,7 @@ The input points are pruned if
The input bounding box is optional
## Example
Example implementation (see main.c for actual code)
```C
Expand Down Expand Up @@ -152,96 +213,11 @@ void relax_points(const jcv_diagram* diagram, jcv_point* points)
```


Comparisons
===========

| Feature vs Impl | voronoi++ | boost | fastjet | jcv |
|-----------------------:|-----------|-------|---------|-----|
| Edge clip | * | | * | * |
| Generate Edges | * | * | * | * |
| Generate Cells | * | * | | * |
| Cell Edges Not Flipped | | * | | * |
| Cell Edges CCW | | * | | * |
| Easy Relaxation | | | | * |
| Custom Allocator | | | | * |


Some Numbers
------------

*Tests run on a 2.9GHz Core i7 MBP with 8GB ram. Each test ran 20 times, and the average time is presented below*

Timings
-------

| counts | jc_voronoi | fastjet | boost | voronoi++ |
|-------:|------------|------------|------------|-------------|
| 3 | 0.0015 ms | 0.0275 ms | 0.0652 ms | 0.0296 ms |
| 10 | 0.0061 ms | 0.0113 ms | 0.0147 ms | 0.0497 ms |
| 50 | 0.0490 ms | 0.0449 ms | 0.1179 ms | 0.3452 ms |
| 100 | 0.0860 ms | 0.1019 ms | 0.2047 ms | 0.9219 ms |
| 200 | 0.1863 ms | 0.2037 ms | 0.4472 ms | 1.8210 ms |
| 1000 | 1.0830 ms | 1.1570 ms | 2.1010 ms | 12.1560 ms |
| 2000 | 2.5610 ms | 2.2350 ms | 4.1110 ms | 26.9570 ms |
| 5000 | 6.9380 ms | 5.7130 ms | 10.2390 ms | 85.1440 ms |
| 10000 | 16.1190 ms | 11.8410 ms | 22.4820 ms | 205.0000 ms |
| 20000 | 34.8410 ms | 23.7810 ms | 48.4620 ms | 524.0000 ms |

Memory
------

| counts | jc_voronoi | fastjet | boost | voronoi++ |
|-------:|------------|---------|----------|-----------|
| 3 | 16 kb | 1 kb | 1 kb | 1 kb |
| 10 | 16 kb | 4 kb | 7 kb | 8 kb |
| 50 | 33 kb | 21 kb | 44 kb | 53 kb |
| 100 | 50 kb | 40 kb | 89 kb | 110 kb |
| 200 | 99 kb | 78 kb | 180 kb | 226 kb |
| 1000 | 432 kb | 373 kb | 888 kb | 1130 kb |
| 2000 | 864 kb | 735 kb | 1779 kb | 2269 kb |
| 5000 | 2144 kb | 1818 kb | 4698 kb | 5676 kb |
| 10000 | 4271 kb | 3611 kb | 9383 kb | 11334 kb |
| 20000 | 8541 kb | 7179 kb | 18775 kb | 22652 kb |

# Allocations
-------------

| counts | jc_voronoi | fastjet | boost | voronoi++ |
|-------:|------------|---------|--------|-----------|
| 3 | 1 | 22 | 11 | 36 |
| 10 | 1 | 61 | 43 | 177 |
| 50 | 2 | 214 | 264 | 1015 |
| 100 | 3 | 383 | 536 | 2077 |
| 200 | 6 | 720 | 1073 | 4224 |
| 1000 | 26 | 3263 | 5524 | 21362 |
| 2000 | 52 | 6367 | 11073 | 42854 |
| 5000 | 129 | 15584 | 27872 | 107426 |
| 10000 | 257 | 30811 | 55797 | 214427 |
| 20000 | 514 | 61102 | 111734 | 428530 |

Same numbers, as images

Timings

<img src="images/timings_small.png" alt="timings small" width="350">
<img src="images/timings_large.png" alt="timings large" width="350">

Memory Usage

<img src="images/memory_small.png" alt="memory small" width="350">
<img src="images/memory_large.png" alt="memory large" width="350">

Number of Allocations

<img src="images/allocations_small.png" alt="allocations small" width="350">
<img src="images/allocations_large.png" alt="allocations large" width="350">


General thoughts
================
# General thoughts

Fastjet
-------
## Fastjet

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,
Expand All @@ -252,11 +228,11 @@ Unfortunately, the code is not very readable, and the license is unclear (GPL?)
Also, if you want access to the actual cells, you have to recreate that yourself using the edges.


Boost
-----
## Boost

Using boost might be convenient for some, but the sheer amount of code is too great in many cases.
I had to install 5 modules of boost to compile (config, core, mpl, preprocessor and polygon).
If you install full boost, that's 650mb of source.

It is ~2x as slow as the fastest algorithms, and takes ~2.5x as much memory.

Expand All @@ -266,17 +242,15 @@ The code consists of only templated headers, and it increases compile time a *lo
For simply generating a 2D voronoi diagram using points as input, it is clearly overkill.


Voronoi++
---------
## Voronoi++

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.


O'Sullivan
----------
## O'Sullivan

A C++ version of the original C version from Steven Fortune.

Expand Down
5 changes: 4 additions & 1 deletion appveyor.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,12 @@ build_script:
- compile_cl.bat
- cd test
- compile_cl.bat
- cd ..
- cd ..\src\examples
- compile_cl.bat
- cd ..\..\

test_script:
- build\main.exe -?
- build\main.exe -w 512 -h 512 -n 100 -o citest.png
- build\test.exe
- build\simple.exe
1 change: 1 addition & 0 deletions compile_clang.sh
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
#!/usr/bin/env bash
mkdir -p build

clang -c src/stb_wrapper.c -o build/stb_wrapper.o
Expand Down
Binary file modified images/memory_large.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added images/memory_medium.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified images/memory_small.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified images/timings_large.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added images/timings_medium.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified images/timings_small.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
40 changes: 40 additions & 0 deletions src/examples/compile_cl.bat
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
echo off

if NOT DEFINED VCINSTALLDIR (
if exist "C:\Program Files (x86)\Microsoft Visual Studio 15.0\VC\vcvarsall.bat" (
call "C:\Program Files (x86)\Microsoft Visual Studio 15.0\VC\vcvarsall.bat" amd64
echo "USING VISUAL STUDIO 15"
)
)

if NOT DEFINED VCINSTALLDIR (
if exist "C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat" (
call "C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat" amd64
echo "USING VISUAL STUDIO 14"
)
)

if NOT DEFINED VCINSTALLDIR (
if exist "C:\Program Files (x86)\Microsoft Visual Studio 13.0\VC\vcvarsall.bat" (
call "C:\Program Files (x86)\Microsoft Visual Studio 13.0\VC\vcvarsall.bat" amd64
echo "USING VISUAL STUDIO 13"
)
)

if NOT DEFINED VCINSTALLDIR (
if exist "C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\vcvarsall.bat" (
call "C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\vcvarsall.bat" amd64
echo "USING VISUAL STUDIO 12"
)
)

if NOT DEFINED VCINSTALLDIR (
echo "No compatible visual studio found! run vcvarsall.bat first!"
)

mkdir build

cl.exe /nologo /O2 /D_CRT_SECURE_NO_WARNINGS /W4 -I.. simple.c /link /out:../../build/simple.exe

del *.obj

5 changes: 5 additions & 0 deletions src/examples/compile_clang.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
#!/usr/bin/env bash
BUILD_DIR=../../build
mkdir -p $BUILD_DIR

clang -Wall -Weverything -pedantic -Wno-float-equal simple.c -I.. -lm -o $BUILD_DIR/simple
59 changes: 59 additions & 0 deletions src/examples/simple.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
// Contribution by: Abe Tusk https://github.com/abetusk
// To compile:
// gcc -Wall -Weverything -Wno-float-equal src/examples/simple.c -Isrc -o simple
//

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define JC_VORONOI_IMPLEMENTATION
// If you wish to use doubles
//#define JCV_REAL_TYPE double
//#define JCV_FABS fabs
//#define JCV_ATAN2 atan2
#include "jc_voronoi.h"

#define NPOINT 10

int main(int argc, char** argv) {
(void)argc;
(void)argv;

int i;
jcv_rect bounding_box = { { 0.0f, 0.0f }, { 1.0f, 1.0f } };
jcv_diagram diagram;
jcv_point points[NPOINT];
const jcv_site* sites;
jcv_graphedge* graph_edge;

memset(&diagram, 0, sizeof(jcv_diagram));

srand(0);
for (i=0; i<NPOINT; i++) {
points[i].x = (float)(rand()/(1.0f + RAND_MAX));
points[i].y = (float)(rand()/(1.0f + RAND_MAX));
}

printf("# Seed sites\n");
for (i=0; i<NPOINT; i++) {
printf("%f %f\n", (double)points[i].x, (double)points[i].y);
}

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

printf("# Edges\n");
sites = jcv_diagram_get_sites(&diagram);
for (i=0; i<diagram.numsites; i++) {

graph_edge = sites[i].edges;
while (graph_edge) {
// This approach will potentially print shared edges twice
printf("%f %f\n", (double)graph_edge->pos[0].x, (double)graph_edge->pos[0].y);
printf("%f %f\n", (double)graph_edge->pos[1].x, (double)graph_edge->pos[1].y);
graph_edge = graph_edge->next;
}
}

jcv_diagram_free(&diagram);
}
Loading

0 comments on commit c1bc7e1

Please sign in to comment.