From 75b5a2510763722425226e2195d7d8625e26993d Mon Sep 17 00:00:00 2001 From: Seb James Date: Fri, 16 Oct 2026 16:42:34 +0100 Subject: [PATCH 1/3] First draft of boundary showing --- examples/CMakeLists.txt | 3 +++ examples/hexgrid_boundary.cpp | 50 +++++++++++++++++++++++++++++++++++ maths | 2 +- mplot/HexGridVisual.cppm | 25 ++++++++++++++++++ 4 files changed, 79 insertions(+), 1 deletion(-) create mode 100644 examples/hexgrid_boundary.cpp diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index 46fb1621..360f2059 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -103,6 +103,9 @@ target_link_libraries(hexgrid mathplot_examples) add_executable(hexgrid_transforms hexgrid_transforms.cpp) target_link_libraries(hexgrid_transforms mathplot_examples) +add_executable(hexgrid_boundary hexgrid_boundary.cpp) +target_link_libraries(hexgrid_boundary mathplot_examples) + add_executable(hexgrid_fft hexgrid_fft.cpp) target_link_libraries(hexgrid_fft mathplot_examples) diff --git a/examples/hexgrid_boundary.cpp b/examples/hexgrid_boundary.cpp new file mode 100644 index 00000000..e943edb0 --- /dev/null +++ b/examples/hexgrid_boundary.cpp @@ -0,0 +1,50 @@ +/* + * An example mplot::Visual scene, containing hexgrid with boundary shown + */ + +#include +#include +#include +#include + +import sm.vec; +import sm.hexgrid; + +import mplot.visual; +import mplot.visualdatamodel; +import mplot.hexgridvisual; + +int main() +{ + // Contructor args are width, height, title + mplot::Visual v(1600, 1000, "mplot::HexGridVisual"); + + sm::hexgrid hg1(0.01f, 0.205f, 0.0f); + //hg1.set_circular_boundary (0.1f); + hg1.set_boundary_on_outer_edge(); + + // Make some dummy data (a sine wave) to make an interesting surface + std::vector data1(hg1.num(), 0.0f); + for (unsigned int ri = 0; ri < hg1.num(); ++ri) { + data1[ri] = 0.05f + 0.05f * std::sin (20.0f * hg1.d_x[ri]) * std::sin (10.0f * hg1.d_y[ri]) ; // Range 0->1 + } + + // sm::HexVisMode::HexInterp to see the hexagons or sm::HexVisMode::Triangles for a smoother surface plot + const mplot::HexVisMode visMode = mplot::HexVisMode::HexInterp; + + sm::vec offset = { 0.0f, -0.05f, 0.0f }; + auto hgv1 = std::make_unique>(&hg1, offset); + hgv1->set_parent (v.get_id()); + hgv1->cm.setType (mplot::ColourMapType::Ice); + hgv1->showboundary = true; + hgv1->setScalarData (&data1); + hgv1->hexVisMode = visMode; + hgv1->zScale.null_scaling(); + hgv1->addLabel ("hexalign::point_up", sm::vec<>{ -hg1.width()/2.1f, -hg1.width()/1.6f }, mplot::TextFeatures(0.02f)); + hgv1->finalize(); + v.addVisualModel (hgv1); + + v.keepOpen(); + + return 0; +} diff --git a/maths b/maths index 7a523af5..54bba80f 160000 --- a/maths +++ b/maths @@ -1 +1 @@ -Subproject commit 7a523af556636b16033a2831fa8e4d51dbb246ac +Subproject commit 54bba80f0f04bd645182caba53932cf34e54e159 diff --git a/mplot/HexGridVisual.cppm b/mplot/HexGridVisual.cppm index 866b6126..fb425ebd 100644 --- a/mplot/HexGridVisual.cppm +++ b/mplot/HexGridVisual.cppm @@ -321,6 +321,10 @@ export namespace mplot if (this->showhexes == true) { this->computeHexes(); } + // Boundary + if (this->showboundary == true) { + this->computeHexgridBoundary(); + } // Optionally show a Flat surface for the zero plane if (this->zerogrid == true) { this->computeZerogridIndices(); @@ -328,6 +332,25 @@ export namespace mplot // End trial grid } + // Draw carefully around the boundary with tubes or lines or quads + void computeHexgridBoundary() + { + std::array blkclr = {}; + sm::mat lt (this->hg->tfm.template as()); + for (auto hptr : this->hg->bhexen) { + std::uint32_t hi = hptr->vi; + for (std::uint32_t i = 0; i < 6; ++i) { + if (this->hg->has_neighbour (hi, i) == false) { + // Draw in line from vtx 5 to 0, 0 to 1, 1 to 2, etc + std::uint32_t i0 = (i + 5u) % 6u; + sm::vec c0 = lt * hptr->get_vertex_coord (i0).template as().plus_one_dim (0.0f); + sm::vec c = lt * hptr->get_vertex_coord (i).template as().plus_one_dim (0.0f); + this->computeTube (c0, c, blkclr, blkclr, this->hg->d / 12.0f); + } + } + } + } + // Compute vertices for the patchwork quilt of hexes void computeHexes() { @@ -407,9 +430,11 @@ export namespace mplot // Use a single colour for each hex, even though hex z positions are // interpolated. Do the _colour_ scaling: std::array clr = this->setColour (hi); +#if 0 // Now going to draw carefully around the boundary if (this->showboundary && (this->hg->vhexen[hi])->boundary_hex() == true) { this->markHex (hi); } +#endif if (this->showcentre && _x == 0.0f && _y == 0.0f) { this->markHex (hi); } From 87d55e5e157f752757ee65a5dde02b8e70b6b144 Mon Sep 17 00:00:00 2001 From: Seb James Date: Fri, 16 Oct 2026 18:29:40 +0100 Subject: [PATCH 2/3] A lovely boundary --- examples/hexgrid_boundary.cpp | 6 ++++-- maths | 2 +- mplot/HexGridVisual.cppm | 40 ++++++++++++++++++++++++++++++++--- 3 files changed, 42 insertions(+), 6 deletions(-) diff --git a/examples/hexgrid_boundary.cpp b/examples/hexgrid_boundary.cpp index e943edb0..702c1057 100644 --- a/examples/hexgrid_boundary.cpp +++ b/examples/hexgrid_boundary.cpp @@ -18,10 +18,12 @@ int main() { // Contructor args are width, height, title mplot::Visual v(1600, 1000, "mplot::HexGridVisual"); + v.fov = 15; + //v.rotateAboutNearest (true); sm::hexgrid hg1(0.01f, 0.205f, 0.0f); - //hg1.set_circular_boundary (0.1f); - hg1.set_boundary_on_outer_edge(); + hg1.set_circular_boundary (0.1f); + //hg1.set_boundary_on_outer_edge(); // Make some dummy data (a sine wave) to make an interesting surface std::vector data1(hg1.num(), 0.0f); diff --git a/maths b/maths index 54bba80f..70b7718e 160000 --- a/maths +++ b/maths @@ -1 +1 @@ -Subproject commit 54bba80f0f04bd645182caba53932cf34e54e159 +Subproject commit 70b7718e14024b98e737be660c18b583f7f1c69a diff --git a/mplot/HexGridVisual.cppm b/mplot/HexGridVisual.cppm index fb425ebd..3efc8764 100644 --- a/mplot/HexGridVisual.cppm +++ b/mplot/HexGridVisual.cppm @@ -335,17 +335,51 @@ export namespace mplot // Draw carefully around the boundary with tubes or lines or quads void computeHexgridBoundary() { - std::array blkclr = {}; + constexpr std::array clr = {}; + constexpr std::array clr0 = {.1f,.1f,.1f}; sm::mat lt (this->hg->tfm.template as()); + //std::cout << "lt:\n" << lt << std::endl; + for (auto hptr : this->hg->bhexen) { std::uint32_t hi = hptr->vi; + // Look at each possible neighbour direction and see if we need a tube for (std::uint32_t i = 0; i < 6; ++i) { if (this->hg->has_neighbour (hi, i) == false) { - // Draw in line from vtx 5 to 0, 0 to 1, 1 to 2, etc + // There's no neighbour, so we need a tube. The logic is made complex by the + // need to angle the ends of the tubes correctly depending on the shape of + // the boundary std::uint32_t i0 = (i + 5u) % 6u; sm::vec c0 = lt * hptr->get_vertex_coord (i0).template as().plus_one_dim (0.0f); sm::vec c = lt * hptr->get_vertex_coord (i).template as().plus_one_dim (0.0f); - this->computeTube (c0, c, blkclr, blkclr, this->hg->d / 12.0f); + + sm::vec u0 = {}; // tube end normal for c0 + sm::vec u = {}; // tube end normal for c + sm::vec v = {}; + + std::uint32_t di = 0u; // direction to corner neighbour + std::uint32_t vi = 0u; // vector to cross with uz depends on if corner neighbour exists or not + + di = (i + 5u) % 6u; + if (this->hg->has_neighbour (hi, di) == false) { + vi = (i + 5u) % 6u; + } else { + vi = i; + } + v = hptr->get_vertex (vi).plus_one_dim(); + v.renormalize(); + u0 = lt * v.cross (sm::vec::uz()); + + di = (i + 1u) % 6u; + if (this->hg->has_neighbour (hi, di) == false) { + vi = i; + } else { + vi = (i + 5u) % 6u; + } + v = hptr->get_vertex (vi).plus_one_dim(); + v.renormalize(); + u = lt * v.cross (-sm::vec::uz()); + + this->computeOpenFlaredTube (c0, c, u0, u, clr0, clr, this->hg->d / 12.0f, this->hg->d / 12.0f); } } } From f3849a4ea77835721536113fb46a1f347cec64a2 Mon Sep 17 00:00:00 2001 From: Seb James Date: Sat, 17 Oct 2026 12:53:01 +0100 Subject: [PATCH 3/3] get_vertex() calls need to be converted to float --- mplot/HexGridVisual.cppm | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mplot/HexGridVisual.cppm b/mplot/HexGridVisual.cppm index 3efc8764..90702d26 100644 --- a/mplot/HexGridVisual.cppm +++ b/mplot/HexGridVisual.cppm @@ -365,7 +365,7 @@ export namespace mplot } else { vi = i; } - v = hptr->get_vertex (vi).plus_one_dim(); + v = hptr->get_vertex (vi).template as().plus_one_dim(); v.renormalize(); u0 = lt * v.cross (sm::vec::uz()); @@ -375,7 +375,7 @@ export namespace mplot } else { vi = (i + 5u) % 6u; } - v = hptr->get_vertex (vi).plus_one_dim(); + v = hptr->get_vertex (vi).template as().plus_one_dim(); v.renormalize(); u = lt * v.cross (-sm::vec::uz());