Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
be66936
Basic_viewer: colour faces by value (distance to the clipping plane)
RajdeepKushwaha5 Aug 3, 2026
274459d
Basic_viewer: colour by value per cell (one flat colour per cell)
RajdeepKushwaha5 Aug 5, 2026
fc92e4c
Basic_viewer: add cell size as a colour-by-value source
RajdeepKushwaha5 Aug 6, 2026
4b57ba9
Basic_viewer: colour the kept volumes in whole-volume clipping
RajdeepKushwaha5 Aug 6, 2026
dc20ab2
Basic_viewer: add a colour legend for colour by value
RajdeepKushwaha5 Aug 11, 2026
5f1c27f
Basic_viewer: add a viridis palette for colour by value
RajdeepKushwaha5 Aug 14, 2026
433bb9f
Basic_viewer: colour by distance over the actual range, not the scene…
RajdeepKushwaha5 Aug 14, 2026
5d3beea
Basic_viewer: colour faces by a value provided by the drawer (surface…
RajdeepKushwaha5 Aug 15, 2026
163d647
Basic_viewer: colour the clip-plane cap by the palette, and clarify t…
RajdeepKushwaha5 Aug 17, 2026
5db58d4
Basic_viewer: document the colour-by-value drawer API (valued_face, f…
RajdeepKushwaha5 Aug 17, 2026
7820923
Basic_viewer: add a changelog entry for colour by value
RajdeepKushwaha5 Aug 17, 2026
3164f46
Basic_viewer: use the full 'distance to clipping plane' legend label,…
RajdeepKushwaha5 Aug 17, 2026
7862c7b
Basic_viewer: apply the drawer value in whole-volume mode for a surfa…
RajdeepKushwaha5 Aug 17, 2026
9349827
Basic_viewer: colour by distance over a plane-anchored range so movin…
RajdeepKushwaha5 Aug 18, 2026
f950dbd
Basic_viewer: rename valued_face to is_face_valued (review)
RajdeepKushwaha5 Aug 21, 2026
5b3fc9c
Update Basic_viewer/doc/Basic_viewer/Concepts/GraphicsSceneOptions.h
RajdeepKushwaha5 Aug 24, 2026
1dcdce8
Update Basic_viewer/doc/Basic_viewer/Concepts/GraphicsSceneOptions.h
RajdeepKushwaha5 Aug 24, 2026
978baa0
Update Basic_viewer/doc/Basic_viewer/Concepts/GraphicsSceneOptions.h
RajdeepKushwaha5 Aug 24, 2026
438e81b
Basic_viewer: use American spelling color instead of colour (review)
RajdeepKushwaha5 Aug 24, 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
6 changes: 6 additions & 0 deletions BGL/include/CGAL/draw_face_graph.h
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,9 @@ void compute_elements(const FG &fg,

if (gs_options.are_faces_enabled())
{
// Color by value: name the value once, for the legend.
if (!gs_options.face_value_name.empty())
{ graphics_scene.set_value_name(gs_options.face_value_name); }
for (auto fh : faces(fg))
{
if (fh != boost::graph_traits<FG>::null_face() && // face exists
Expand All @@ -78,6 +81,9 @@ void compute_elements(const FG &fg,
hd = next(hd, fg);
}
while (hd != first_hd);
// Color by value: attach the face's scalar value before committing it.
if (gs_options.is_face_valued(fg, fh))
{ graphics_scene.set_face_value(gs_options.face_value(fg, fh)); }
graphics_scene.face_end();
}
}
Expand Down
11 changes: 11 additions & 0 deletions Basic_viewer/doc/Basic_viewer/Concepts/GraphicsSceneOptions.h
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,17 @@ class GraphicsSceneOptions
/// `nullptr` by default.
std::function<CGAL::IO::Color(const DS &, face_descriptor)> face_color;

/// `std::function` that returns `true` when call for faces having an associated a scalar value, and `false` otherwise. `false` by default.
std::function<bool(const DS &, face_descriptor)> is_face_valued;

/// `std::function` that returns the associated scalar value of a face. Called only if
/// `is_face_valued()` returns `true`. The viewer normalizes the values over their range
/// and maps them to a color palette.
std::function<float(const DS &, face_descriptor)> face_value;

/// name of the value, shown in the viewer's color legend (for example "aspect ratio").
std::string face_value_name;

/// ignores all vertices when `b` is `true`; otherwise ignores only vertices for which `ignore_vertex()` returns `true`.
void ignore_all_vertices(bool b);

Expand Down
46 changes: 44 additions & 2 deletions Basic_viewer/include/CGAL/Basic_shaders.h
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,38 @@ uniform highp vec4 u_PointPlane;
uniform mediump float u_RenderingMode;
uniform mediump float u_RenderingTransparency;

// Color by value: 0 keeps the vertex color, otherwise a palette index. The
// value shown is the signed distance from the fragment to the clipping plane,
// normalised to [u_ValueMin, u_ValueMax].
uniform mediump float u_ColorMapMode;
uniform mediump float u_ValueMin;
uniform mediump float u_ValueMax;
// Per cell: the viewer gives one value for the whole cell (its centre distance or
// its size), so a whole cell takes one flat color and neighbouring cells do not melt.
uniform int u_ColorPerCell;
uniform highp float u_CellValue;

vec3 color_palette(float t, float mode)
{
if (mode < 1.5)
{ return clamp(vec3(t*3.0, t*3.0-1.0, t*3.0-2.0), 0.0, 1.0); } // heat
if (mode < 2.5)
{ return clamp(vec3(1.5-abs(4.0*t-3.0), 1.5-abs(4.0*t-2.0), 1.5-abs(4.0*t-1.0)),
0.0, 1.0); } // jet
if (mode < 3.5)
{ return vec3(t); } // grey ramp
// viridis, a perceptually uniform map (polynomial fit by Matt Zucker). The same
// coefficients are mirrored in the viewer's legend so the bar matches the faces.
const vec3 c0=vec3(0.2777273272234177, 0.005407344544966578, 0.3340998053353061);
const vec3 c1=vec3(0.1050930431085774, 1.404613529898575, 1.384590162594685);
const vec3 c2=vec3(-0.3308618287255563, 0.214847559468213, 0.09509516302823659);
const vec3 c3=vec3(-4.634230498983486, -5.799100973351585, -19.33244095627987);
const vec3 c4=vec3(6.228269936347081, 14.17993336680509, 56.69055260068105);
const vec3 c5=vec3(4.776384997670288, -13.74514537774601, -65.35303263337234);
const vec3 c6=vec3(-5.435455855934631, 4.645852612178535, 26.3124352495832);
return clamp(c0+t*(c1+t*(c2+t*(c3+t*(c4+t*(c5+t*c6))))), 0.0, 1.0);
}

void main(void)
{
highp vec3 L = u_LightPos.xyz - vs_fP.xyz;
Expand All @@ -84,9 +116,19 @@ void main(void)
L = normalize(L);
V = normalize(V);

// Base color is the vertex color, or a palette applied to the value.
vec3 base = fColor.rgb;
if (u_ColorMapMode > 0.5)
{
float value = (u_ColorPerCell != 0) ? u_CellValue
: dot(ls_fP.xyz-u_PointPlane.xyz, normalize(u_ClipPlane.xyz));
float t = clamp((value-u_ValueMin)/max(u_ValueMax-u_ValueMin, 1e-6), 0.0, 1.0);
base = color_palette(t, u_ColorMapMode);
}

highp vec3 R = reflect(-L, a_Normal);
highp vec4 diffuse = vec4(max(dot(a_Normal,L), 0.0) * u_LightDiff.rgb * fColor.rgb, 1.0);
highp vec4 ambient = vec4(u_LightAmb.rgb * fColor.rgb, 1.0);
highp vec4 diffuse = vec4(max(dot(a_Normal,L), 0.0) * u_LightDiff.rgb * base, 1.0);
highp vec4 ambient = vec4(u_LightAmb.rgb * base, 1.0);
highp vec4 specular = pow(max(dot(R,V), 0.0), u_SpecPower) * u_LightSpec;

// onPlane == 1: inside clipping plane, should be solid;
Expand Down
42 changes: 42 additions & 0 deletions Basic_viewer/include/CGAL/Graphics_scene.h
Original file line number Diff line number Diff line change
Expand Up @@ -252,6 +252,13 @@ class Graphics_scene
return m_buffer_for_faces.is_a_face_started();
}

/// sets the scalar value of the face currently being built. The viewer can color
/// the faces by these values, normalised over their range and mapped to a palette.
void set_face_value(float v) { m_current_face_value=v; m_has_face_values=true; }

/// sets the name of the value, shown in the viewer's color legend.
void set_value_name(const std::string &n) { m_value_name=n; }

void face_begin()
{
if (a_face_started())
Expand Down Expand Up @@ -314,6 +321,7 @@ class Graphics_scene
const unsigned int idx=static_cast<unsigned int>(m_faces.size());
m_faces.emplace_back(m_current_face_start,
number_of_elements(POS_FACES)-m_current_face_start);
record_current_face_value();
m_face_dedup.emplace(std::move(key), idx);
m_volume_faces.back().push_back(idx);
return;
Expand All @@ -324,6 +332,22 @@ class Graphics_scene
// Record this face's vertex range in POS_FACES, for the clip-plane cap.
m_faces.emplace_back(m_current_face_start,
number_of_elements(POS_FACES) - m_current_face_start);
record_current_face_value();
}

// Color by value: store the value of the face just committed, parallel to
// m_faces, and keep the min and max for the palette range.
void record_current_face_value()
{
if (m_has_face_values)
{
if (m_face_values.empty())
{ m_face_value_min=m_face_value_max=m_current_face_value; }
else
{ if (m_current_face_value<m_face_value_min) { m_face_value_min=m_current_face_value; }
if (m_current_face_value>m_face_value_max) { m_face_value_max=m_current_face_value; } }
}
m_face_values.push_back(m_current_face_value);
}

// Clip-plane cap: a volume groups the faces added until volume_end, de-duplicated
Expand Down Expand Up @@ -366,6 +390,14 @@ class Graphics_scene
const std::vector<CGAL::Bbox_3> &get_volume_bboxes() const
{ return m_volume_bboxes; }

// Color by value: the per-face values set by the drawer, whether any were set,
// the legend name, and the value range.
const std::vector<float> &get_face_values() const { return m_face_values; }
bool has_face_values() const { return m_has_face_values; }
const std::string &value_name() const { return m_value_name; }
float face_value_min() const { return m_face_value_min; }
float face_value_max() const { return m_face_value_max; }

template <typename KPoint>
void add_text(const KPoint &kp, const std::string &txt)
{
Expand Down Expand Up @@ -509,6 +541,16 @@ class Graphics_scene
std::vector<CGAL::Bbox_3> m_volume_bboxes;
unsigned int m_current_face_start = 0;

// Color by value: an optional scalar per face, set by the drawer, that the viewer
// maps to a palette (like the color, but any float). Each value is parallel to
// m_faces; m_value_name labels the legend.
std::vector<float> m_face_values;
float m_current_face_value = 0.f;
bool m_has_face_values = false;
std::string m_value_name;
float m_face_value_min = 0.f;
float m_face_value_max = 1.f;

// Clip-plane cap: geometric face de-duplication during volume building. The key
// is the sorted face vertex positions, so both sides of a shared wall match.
// Hashed so the build stays linear on meshes with many faces.
Expand Down
15 changes: 15 additions & 0 deletions Basic_viewer/include/CGAL/Graphics_scene_options.h
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,8 @@ struct Graphics_scene_options<DS, VertexDescriptor, EdgeDescriptor, FaceDescript
colored_face=[](const DS &, face_descriptor)->bool { return false; };

face_wireframe=[](const DS &, face_descriptor)->bool { return false; };

is_face_valued=[](const DS &, face_descriptor)->bool { return false; };
}

// The seven following functions should not be null
Expand All @@ -65,6 +67,19 @@ struct Graphics_scene_options<DS, VertexDescriptor, EdgeDescriptor, FaceDescript

std::function<bool(const DS &, face_descriptor)> face_wireframe;

/// `std::function` that returns `true` if the given face carries a scalar value to
/// color it by, `false` otherwise. `false` by default.
std::function<bool(const DS &, face_descriptor)> is_face_valued;

/// `std::function` that returns the scalar value of the given face. Called only
/// when `is_face_valued()` returns `true`. The viewer normalises the values over their
/// range and maps them to a color palette.
std::function<float(const DS &, face_descriptor)> face_value;

/// The name of the value, shown in the viewer's color legend (for example
/// "aspect ratio"). Empty by default.
std::string face_value_name;

// These functions must be non null if the corresponding colored_XXX function
// returns true.
std::function<CGAL::IO::Color(const DS &, vertex_descriptor)> vertex_color;
Expand Down
Loading
Loading