Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
53 commits
Select commit Hold shift + click to select a range
6b55aa2
Incorporates jc_voronoi_clip.h into jcv::manager
sebsjames Jan 9, 2026
19b1034
Adds a skeleton app to be the test case for boundaried voronois
sebsjames Jan 9, 2026
79987c7
Changes to make the boundary setting compile (doesn't work yet)
sebsjames Jan 9, 2026
e1abd04
About to make the polygon boundary nicer
sebsjames Jan 9, 2026
2c9d24b
Progress, but have an odd behaviour here
sebsjames Jan 9, 2026
0376492
Refactors some function names
sebsjames Jan 9, 2026
d9bfdea
Found the location of the issue, just need to handle it nicely now
sebsjames Jan 9, 2026
d999fa5
Tiny changes
sebsjames Jan 10, 2026
571b0df
Get a nice looking boundary at this commit
sebsjames Jan 10, 2026
d19af8f
With just this change, I get the min_edge >= 0 assertion fail
sebsjames Jan 10, 2026
ef9f623
additional debugging/hacking
sebsjames Jan 10, 2026
5a37549
Work in progress
sebsjames Jan 12, 2026
bdb348e
More work in progress. Going round in circles?
sebsjames Jan 12, 2026
ed0d6b8
Debug reduction
sebsjames Jan 12, 2026
831d169
Avoids crashing in fillgaps
sebsjames Jan 12, 2026
19a1a82
Last bit of WIP before a change of scene
sebsjames Jan 12, 2026
aa1cbb4
Debugging progress
sebsjames Jan 12, 2026
da7d3a6
WIP
sebsjames Jan 12, 2026
5fd1542
Sorted
sebsjames Jan 13, 2026
f8d85d1
Small changes
sebsjames Jan 13, 2026
8218355
Removes some visual debug code
sebsjames Jan 13, 2026
90916d7
Tidy up...
sebsjames Jan 13, 2026
8b6c728
More tidyup
sebsjames Jan 13, 2026
fce6b99
Use latest maths on main
sebsjames Jan 13, 2026
cbf496a
Tidy up, restore default of rectangular domain in VoronoiVisual for now
sebsjames Jan 13, 2026
7dbee4c
Tidying, set up a scheme for different domain shapes on Voronoi diagram
sebsjames Jan 13, 2026
0fca139
Preparing for ellipsoid boundary
sebsjames Jan 13, 2026
46470df
Adds elliptic boundary finding
sebsjames Jan 14, 2026
ca548a6
Remove cruft from an idea/attempt
sebsjames Jan 14, 2026
64c0b7d
Attempting to trace round the points
sebsjames Jan 14, 2026
c8a0c0e
Use Graham's scan!
sebsjames Jan 15, 2026
d460c61
Adds traced boundary code. Seems good. Just need to resolve bugs in t…
sebsjames Jan 15, 2026
d9a18e9
Makes boundary shape settable with cmd arg (0, 1, 2 or 3)
sebsjames Jan 15, 2026
4db542a
More runtime options
sebsjames Jan 15, 2026
2f3d843
cray is dep. on armadillo
sebsjames Jan 15, 2026
7a81d86
Debugging more problems with clipping and traversing the boundary
sebsjames Jan 15, 2026
27c3d08
Brings in updated winder code and adds debugging to jc_voronoi
sebsjames Jan 16, 2026
f947dfd
Updates maths, bringing in polysolve and winder-fix-in-main
sebsjames Jan 16, 2026
ed07121
Current WIP on PCA
sebsjames Jan 17, 2026
0194cba
Update maths lib
sebsjames Jan 19, 2026
c073d6a
Update maths, and we won't be using sm::pca until it's ready
sebsjames Jan 19, 2026
73badf7
Remove ellipse domain option from VoronoiVisual, removing the arma re…
sebsjames Jan 20, 2026
3f71d3c
Minimise differences in jc_voronoi
sebsjames Jan 20, 2026
982b110
polygon clipping is now in jc_voronoi.h
sebsjames Jan 20, 2026
1784446
There's no file to add
sebsjames Jan 20, 2026
4a46452
These functions are unused
sebsjames Jan 20, 2026
22350e5
Minimise diffs
sebsjames Jan 20, 2026
f4a6178
No need for mat22
sebsjames Jan 20, 2026
4ad2c64
Updates to trace boundary
sebsjames Jan 20, 2026
6b722b6
Updates to ellipse_pca
sebsjames Jan 20, 2026
7720168
A voronoi boundary screenshot
sebsjames Jan 20, 2026
260160d
Moves an png and adds a missing png
sebsjames Jan 20, 2026
8e58544
Adds new screenshots for added examples
sebsjames Jan 20, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
84 changes: 43 additions & 41 deletions docs/index.md

Large diffs are not rendered by default.

12 changes: 12 additions & 0 deletions examples/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -411,6 +411,9 @@ target_link_libraries(triangle_intersect OpenGL::GL glfw Freetype::Freetype)
add_executable(voronoi_random voronoi_random.cpp)
target_link_libraries(voronoi_random OpenGL::GL glfw Freetype::Freetype)

add_executable(voronoi_boundary voronoi_boundary.cpp)
target_link_libraries(voronoi_boundary OpenGL::GL glfw Freetype::Freetype)

add_executable(voronoi_rectangular voronoi_rectangular.cpp)
target_link_libraries(voronoi_rectangular OpenGL::GL glfw Freetype::Freetype)

Expand Down Expand Up @@ -558,3 +561,12 @@ target_link_libraries(show_boundingboxes OpenGL::GL glfw Freetype::Freetype)
# if have compound-ray header
add_executable(cray_eye cray_eye.cpp)
target_link_libraries(cray_eye OpenGL::GL glfw Freetype::Freetype)

if(ARMADILLO_FOUND)
# Make use of principle component analysis from arma in this example
add_executable(ellipse_pca ellipse_pca.cpp)
target_link_libraries(ellipse_pca ${ARMADILLO_LIBRARY} ${ARMADILLO_LIBRARIES} OpenGL::GL glfw Freetype::Freetype)
endif()

add_executable(trace_boundary trace_boundary.cpp)
target_link_libraries(trace_boundary OpenGL::GL glfw Freetype::Freetype)
81 changes: 81 additions & 0 deletions examples/ellipse_pca.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
/*
* Applying principle component analysis (using arma) to some random data
*/
#include <iostream>

#include <sm/mathconst>
#include <sm/random>
#include <sm/mat22>

#include <armadillo>

#include <mplot/Visual.h>
#include <mplot/GraphVisual.h>

int main()
{
constexpr unsigned int n_samp = 100;

// Create data: Draw some samples from 2D Gaussian and rotate
sm::rand_normal<float> rn1 (0.0f, 2.0f);
sm::rand_normal<float> rn2 (0.0f, 0.5f);
sm::vvec<sm::vec<float, 2>> _x (n_samp, {0});
sm::mat22<float> rotn;
rotn.rotate (sm::mathconst<float>::pi_over_8);
for (unsigned int i = 0; i < n_samp; ++i) {
_x[i] = rotn * sm::vec<float, 2>{ rn1.get(), rn2.get() };
}

// Graph the data
mplot::Visual v(1024, 768, "Principle component analysis with armadillo");
// Create a GraphVisual object (obtaining a unique_ptr to the object) with a spatial offset within the scene of 0,0,0
auto gv = std::make_unique<mplot::GraphVisual<float>> (sm::vec<float>{-0.5f,-0.5f,0.0f});
mplot::DatasetStyle ds (mplot::stylepolicy::markers);
ds.datalabel = std::string("data");
v.bindmodel (gv);
gv->setlimits (-8, 8, -8, 8);
gv->setdata (_x, ds);

std::cout << "\narma gives:\n";
// Place data in arma::Mat
arma::Mat<float> x(_x.size(), 2);
for (unsigned int i = 0; i < _x.size(); ++i) {
x(i, 0) = _x[i][0];
x(i, 1) = _x[i][1];
}

// Apply arma::princomp
arma::Mat<float> co, sc;
arma::Col<float> lat, tsq;
arma::princomp (co, sc, lat, tsq, x);

std::cout << "coeff: " << co << std::endl;
//std::cout << "scores: " << sc << std::endl;
std::cout << "latent: " << lat << std::endl;

// Mat access is (r, c)
sm::vec<float, 2> pc1vec = { co(0, 0), co(1, 0) };
float angle1 = pc1vec.angle();
std::cout << "Angle of first component " << pc1vec << " is " << angle1 * sm::mathconst<float>::rad2deg
<< " and length is " << lat(0) << std::endl;
sm::vec<float, 2> pc2vec = { co(0, 1), co(1, 1) };
float angle2 = pc2vec.angle();
std::cout << "Angle of 2nd component " << pc2vec << " is " << angle2 * sm::mathconst<float>::rad2deg
<< " and length is " << lat(1) << std::endl;

mplot::DatasetStyle ds2 (mplot::stylepolicy::lines);
// Show 3 sigma axes
ds2.setcolour (mplot::colour::crimson);
ds2.datalabel = std::string("PC1 3") + mplot::unicode::toUtf8 (mplot::unicode::sigma);
sm::vvec<sm::vec<float, 2>> pc1vv = { {0,0}, pc1vec * 3.0f * std::sqrt(lat(0))};
gv->setdata (pc1vv, ds2);

ds2.setcolour (mplot::colour::orange);
ds2.datalabel = std::string("PC2 3") + mplot::unicode::toUtf8 (mplot::unicode::sigma);
sm::vvec<sm::vec<float, 2>> pc2vv = { {0,0}, pc2vec * 3.0f * std::sqrt(lat(1)) };
gv->setdata (pc2vv, ds2);

gv->finalize();
v.addVisualModel (gv);
v.keepOpen();
}
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 examples/screenshots/ellipse_pca.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 examples/screenshots/trace_boundary.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 examples/screenshots/voronoi_boundary.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
47 changes: 47 additions & 0 deletions examples/trace_boundary.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
/*
* Trace around a boundary of points in 2D. This code uses Graham's scan to compute the convex hull
* of a set of randomly generated points.
*/
#include <iostream>

#include <sm/mathconst>
#include <sm/random>
#include <sm/vvec>
#include <sm/vec>
#include <sm/algo>

#include <mplot/Visual.h>
#include <mplot/GraphVisual.h>

int main()
{
// Get ready to graph the data
mplot::Visual v(1024, 768, "Graham's scan computes the convex hull");
mplot::DatasetStyle ds (mplot::stylepolicy::markers);
auto gv = std::make_unique<mplot::GraphVisual<float>> (sm::vec<float>{-0.5f,-0.5f,0.0f});
v.bindmodel (gv);

constexpr unsigned int n_points = 200;

// Create data
sm::rand_uniform<float> rngxy(-0.8f, 0.8f);
sm::vvec<sm::vec<float, 2>> points(n_points);
for (unsigned int i = 0; i < n_points; ++i) { points[i] = { rngxy.get(), rngxy.get() }; }

// Trace algorithm
sm::vvec<sm::vec<float, 2>> boundary = sm::geometry::graham_scan (points);
// Close the boundary
boundary.push_back (boundary.front());

gv->setlimits (-1, 1, -1, 1);

gv->setdata (points, ds);

mplot::DatasetStyle ds2 (mplot::stylepolicy::lines);
ds2.linecolour = mplot::colour::crimson;
gv->setdata (boundary, ds2);

gv->finalize();
v.addVisualModel (gv);
v.keepOpen();
}
75 changes: 75 additions & 0 deletions examples/voronoi_boundary.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
/*
* This example generates a number (n_points) of random (but bounded) coordinates and
* uses the VoronoiVisual to display the coordinates as a map, with the order of
* random-choice being used to colourize the Voronoi cells.
*
* Test harness for drawing an arbitrary boundary around the Voronoi region
*
* Author Seb James
* Date 2026
*/
#include <iostream>
#include <sm/vec>
#include <sm/random>
#include <mplot/Visual.h>
#include <mplot/VoronoiVisual.h>

int main (int argc, char** argv)
{
int rtn = -1;

float border_width = 0.2f;
unsigned int n_points = 80;
int domshape = 0; // 0 for rectangular, 1 for circ, 2 for ellipse, 3 for traced

if (argc > 1) { domshape = std::stoi (argv[1]); }
if (argc > 2) { border_width = std::stof (argv[2]); }
if (argc > 3) { n_points = std::stoi (argv[3]); }

mplot::Visual v(1024, 768, "VoronoiVisual");

sm::rand_uniform<float> rngxy(-0.8f, 0.8f, n_points);
sm::rand_uniform<float> rngz(0.8f, 1.0f, n_points);

// make n_points random coordinates
std::vector<sm::vec<float>> points(n_points);
std::vector<float> data(n_points);

for (unsigned int i = 0; i < n_points; ++i) {
points[i] = { rngxy.get(), rngxy.get(), rngz.get() };
data[i] = static_cast<float>(i) / n_points;
}

mplot::ColourMapType cmap_t = mplot::ColourMapType::Plasma;

sm::vec<float, 3> offset = { 0.0f };
auto vorv = std::make_unique<mplot::VoronoiVisual<float>> (offset);
v.bindmodel (vorv);
vorv->show_voronoi2d = true; // true to show the 2D voronoi edges
vorv->debug_dataCoords = true; // true to show coordinate spheres

// traced, circular, ellipsoid, rectangular:
if (domshape == 1) {
vorv->dom_shape = mplot::VoronoiVisual<float>::domain_shape::circular;
} else if (domshape == 2) {
vorv->dom_shape = mplot::VoronoiVisual<float>::domain_shape::ellipsoid;
} else if (domshape == 3) {
vorv->dom_shape = mplot::VoronoiVisual<float>::domain_shape::traced;
} else {
vorv->dom_shape = mplot::VoronoiVisual<float>::domain_shape::rectangular;
}
// A border to add to our domain boundary
vorv->border_width = border_width;
// Some domain shapes need to know a number of points:
vorv->num_boundary_points = 12;

vorv->cm.setType (cmap_t);
vorv->setDataCoords (&points);
vorv->setScalarData (&data);
vorv->finalize();
v.addVisualModel (vorv);

v.keepOpen();

return rtn;
}
5 changes: 4 additions & 1 deletion examples/voronoi_function.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,10 @@ int main()
vorv->show_voronoi2d = false; // true to show the 2D voronoi edges
vorv->debug_dataCoords = false; // true to show coordinate spheres
float length_scale = 4.0f / std::sqrt (n_points);
vorv->border_width = length_scale;
vorv->border_width = length_scale;
//vorv->dom_shape = mplot::VoronoiVisual<float>::domain_shape::traced;
//vorv->dom_shape = mplot::VoronoiVisual<float>::domain_shape::circular;
//vorv->dom_shape = mplot::VoronoiVisual<float>::domain_shape::rectangular; // default
vorv->cm.setType (cmap_t);
vorv->setDataCoords (&points);
vorv->setScalarData (&data);
Expand Down
7 changes: 5 additions & 2 deletions examples/voronoi_function_flat.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,10 @@ int main()
vorv->show_voronoi2d = true; // true to show the 2D voronoi edges
vorv->debug_dataCoords = false; // true to show coordinate spheres
float length_scale = 4.0f / std::sqrt (n_points);
vorv->border_width = length_scale;
vorv->border_width = length_scale;
//vorv->dom_shape = mplot::VoronoiVisual<float>::domain_shape::traced;
//vorv->dom_shape = mplot::VoronoiVisual<float>::domain_shape::circular;
//vorv->dom_shape = mplot::VoronoiVisual<float>::domain_shape::rectangular; // default
vorv->cm.setType (cmap_t);
vorv->setDataCoords (&points);
vorv->setScalarData (&data);
Expand All @@ -61,7 +64,7 @@ int main()
if (fcount++% 600 == 0) {
vorvp->cm.setType (++cmap_t);
}
vorvp->reinitColours(); // Not quite working when I change the colourmap
vorvp->reinitColours();
v.waitevents(0.018);
v.render();
k += 0.01f;
Expand Down
2 changes: 1 addition & 1 deletion maths
3 changes: 3 additions & 0 deletions mplot/VisualDataModel.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
#include <sm/vec>
#include <sm/vvec>
#include <sm/scale>
#include <sm/centroid>
#include <mplot/VisualModel.h>
#include <mplot/ColourMap.h>

Expand Down Expand Up @@ -141,6 +142,8 @@ namespace mplot
this->reinit();
}

sm::vec<float> coordsCentroid() const { return sm::algo::centroid (*this->dataCoords); }

//! An overridable function to set the colour of rect ri
std::array<float, 3> setColour (uint64_t ri)
{
Expand Down
Loading