Skip to content

Add do_snap parameter to PMP::autorefine_triangle_soup #8744

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 110 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
110 commits
Select commit Hold shift + click to select a range
3787d4b
Add snap polygon soup to PMP
LeoValque Feb 4, 2025
14ccffc
Doc, verbose and named parameter of snap_polygon_soup
LeoValque Feb 4, 2025
3a64fe3
add number_of_iterations as a named parameter for snap_polygon_soup
LeoValque Feb 4, 2025
3811271
add more verbose in snap_polygon_soup
LeoValque Feb 4, 2025
3dc12cd
New alternative version of snap_polygon_soup for testing
LeoValque Feb 4, 2025
4d4763f
Fig a bug when the scaling have a negative exponent
LeoValque Feb 7, 2025
aef30f0
Write a generic ceil function to use snap_polygon_soup with various n…
LeoValque Feb 11, 2025
64c4fd2
ceil for negative rational and comments
LeoValque Feb 12, 2025
8079f69
Add some parallellisation
LeoValque Feb 12, 2025
d4e6675
made snap polygon soup an option of autorefine_triangle_soup
LeoValque Feb 17, 2025
ac7bf3c
Doc modification of autorefine and Polygon mesh processing
LeoValque Feb 17, 2025
9b84d4c
rename do_snap to apply_iterative_snap_rounding, remove trailing whit…
LeoValque Feb 17, 2025
139e047
remove trailing whitespace
LeoValque Feb 17, 2025
09239da
rename snap_polygon_soup to triangle_soup_snap_rounding and fix bug i…
LeoValque Feb 19, 2025
0bbaa2a
replace #ifdef CGAL_LINED_WITH_TBB by constexpr
LeoValque Feb 19, 2025
20e54eb
reintroduced #ifdef CGAL_LINKED_WITH_TBB
LeoValque Feb 20, 2025
5d3ec39
Add more soup information in snap_polygon_soup.cpp
LeoValque Feb 24, 2025
3b29156
Bug solved: Shift before ceil was in the wrong direction
LeoValque Feb 25, 2025
04d5d74
Clean doc autorefine
LeoValque Feb 28, 2025
174d48f
Clean doc autorefine return description
LeoValque Feb 28, 2025
0a478a4
Clean doc autorefine snap_grid_size description
LeoValque Feb 28, 2025
6130b4a
solved conflict
LeoValque Mar 3, 2025
30ece15
missing word in the doc
LeoValque Mar 3, 2025
be1ada2
Reduce default number of iterations
LeoValque Mar 3, 2025
1467842
Modify soup_triangles_snap_rounding to support a visitor
LeoValque Mar 13, 2025
1f5d17a
correct typo in function name
LeoValque Mar 13, 2025
b891987
Add variant where cluster of points are round to the closest of them …
LeoValque Mar 14, 2025
b49c696
Update Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/a…
LeoValque Mar 18, 2025
a8c3c28
Merge branch 'CGAL:master' into PMP_triangle_soup_rounding-GF
LeoValque Mar 18, 2025
16da2a2
add delete_triangle function to the visitor of test_autorefinement
LeoValque Mar 18, 2025
dc6d7b1
Debug the visitor of triangle_soup_snap_rounding
LeoValque Mar 19, 2025
3e884c8
Move the mutex inside the class Indexes_range who using it
LeoValque Mar 19, 2025
8c59129
Change name of internal functions
LeoValque Mar 19, 2025
bfc9f5b
Solve bug with macro that skip repair_polygon_soup
LeoValque Apr 3, 2025
f81f5ab
factorize snap_polygon_soup
LeoValque Apr 3, 2025
290610f
add zhou and naive version
LeoValque Apr 3, 2025
7cb154f
add internal_new_subtriangle to Visistor of autorefinement
LeoValque Apr 3, 2025
4995634
use the new internal function of the visitor of autorefinement for th…
LeoValque Apr 3, 2025
da86f44
clone test_autorefinement.cmd to test_snap_rounding.cpp to test snap_…
LeoValque Apr 3, 2025
625299b
Update Polygon_mesh_processing/doc/Polygon_mesh_processing/Concepts/P…
LeoValque Apr 8, 2025
5126371
Update Polygon_mesh_processing/doc/Polygon_mesh_processing/Polygon_me…
LeoValque Apr 8, 2025
cc32efa
Update Polygon_mesh_processing/doc/Polygon_mesh_processing/Polygon_me…
LeoValque Apr 8, 2025
5b4e02b
use macro to define snap version
LeoValque Apr 8, 2025
06951ab
add missing reserve for the visitor
LeoValque Apr 8, 2025
f3abba4
Experiment with iterative rotated around x cubes
LeoValque Apr 25, 2025
e44ffbf
Experiment with iterative rotated along all axis cubes
LeoValque Apr 25, 2025
465183f
remove visitor of example snap_polygon_soup
LeoValque Apr 25, 2025
b8a0ab4
add data for snap rounding test
LeoValque Apr 25, 2025
2e24464
Test for snap rounding
LeoValque Apr 25, 2025
f4d46b8
update cmakelist to compile examples with rotated cubes
LeoValque Apr 25, 2025
3409446
Solve mistake in test_snap_rounding.cmd
LeoValque Apr 25, 2025
afa80c2
simplify the example code of snap_rounding
LeoValque Apr 28, 2025
d56fe48
less verbose test and add another test file
LeoValque Apr 28, 2025
a5f5e82
add specialization of repair_triangle_soup for indexes_range of array
LeoValque Apr 28, 2025
8301f15
some cleaning
LeoValque Apr 28, 2025
484ade6
move experiments with rotated cubes in benchmark
LeoValque Apr 28, 2025
b7fe173
modified example of cmd
LeoValque Apr 28, 2025
3bfe64e
reduce running time of test_snap_rounding, add a full test version
LeoValque Apr 28, 2025
87eb08e
Delete unused includes and solve a compilation error on some testing
LeoValque Apr 29, 2025
246d86b
Update Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/a…
LeoValque Apr 29, 2025
f72cfbd
Update Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/a…
LeoValque Apr 29, 2025
00d1f1e
Update Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/a…
LeoValque Apr 29, 2025
bbe48ca
Update Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/a…
LeoValque Apr 29, 2025
c1b8e6f
Update Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/i…
LeoValque Apr 29, 2025
c7b3e23
Update Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/a…
LeoValque Apr 29, 2025
dd9aca8
solved conflict on the documentation of autorefinement
LeoValque Apr 29, 2025
9e5c098
Update Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/i…
LeoValque Apr 29, 2025
da03f99
Update Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/i…
LeoValque Apr 29, 2025
0bb7709
Update Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/i…
LeoValque Apr 29, 2025
992c018
avoid copy of the input in double_ceil
LeoValque Apr 29, 2025
f2a7995
simplify constexpr test of NT is a fraction
LeoValque Apr 29, 2025
5d41cfd
avoid copy in indexes_range constructor
LeoValque Apr 29, 2025
b03ecb8
add internal in copy protection macro of triangle_soup_snap_rounding
LeoValque Apr 29, 2025
e7bf83f
correct Indexes_range constructor
LeoValque Apr 29, 2025
40c83a3
add std:: to size_t use in indexes_range
LeoValque Apr 29, 2025
1d66903
solved orthograph mystake in wrapp_id_visitor
LeoValque Apr 29, 2025
a7e54fb
Correct default value of number_of_iterations in the documentation
LeoValque Apr 29, 2025
a34a220
remove useless forward declaration
LeoValque Apr 29, 2025
f32a4a7
remove useless inline in Wrap_id_visitor
LeoValque Apr 29, 2025
d98154a
use a set in triangle_soup_snap_rounding instead of vector, sort and …
LeoValque Apr 29, 2025
b3fa751
Revert "use a set in triangle_soup_snap_rounding instead of vector, s…
LeoValque Apr 29, 2025
40326ab
Correct namepaspace of Polygon_types
LeoValque Apr 29, 2025
7e8a60b
Correct namespace of Polygon_types
LeoValque Apr 29, 2025
85326e5
Update Polygon_mesh_processing/doc/Polygon_mesh_processing/Concepts/P…
LeoValque May 7, 2025
0898e03
missing space in doc if AutorefinementVisitor
LeoValque May 7, 2025
389a19b
Update Polygon_mesh_processing/doc/Polygon_mesh_processing/Polygon_me…
LeoValque May 7, 2025
a73795d
Update Polygon_mesh_processing/doc/Polygon_mesh_processing/Polygon_me…
LeoValque May 7, 2025
405ff51
rename visitor of triangle_soup_snap_rounding and catch it specifical…
LeoValque May 7, 2025
8ad6e5e
Changes.md
LeoValque May 7, 2025
5f9273f
Change namespace from internal to autorefine_impl
LeoValque May 7, 2025
8b2ebce
rename internal function of snap visitor new_subtriangle to new_subdi…
LeoValque May 7, 2025
7afa87c
fix namespace
sloriot May 7, 2025
f4f37cc
solved bug when visitor is visited a triangle before its creation
LeoValque May 7, 2025
c051e58
Revert "solved bug when visitor is visited a triangle before its crea…
LeoValque May 7, 2025
b878217
Solve a bug when visitor is called before the creation of the associa…
LeoValque May 7, 2025
730d7cb
with the good index
LeoValque May 7, 2025
a63d72c
Update Polygon_mesh_processing/benchmark/Polygon_mesh_processing/rota…
LeoValque May 12, 2025
cdce5d8
Update Polygon_mesh_processing/benchmark/Polygon_mesh_processing/copl…
LeoValque May 12, 2025
a1d17f6
Update Installation/CHANGES.md
LeoValque May 12, 2025
1300346
Workaround for Visual 2017
afabri May 12, 2025
efe8500
Update Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/i…
LeoValque May 19, 2025
5abad8c
Update Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/i…
LeoValque May 19, 2025
ddb96ae
Update Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/i…
LeoValque May 19, 2025
a829de7
Apply suggestions from code review
LeoValque May 20, 2025
7b5b18f
Modification for review of Andres
LeoValque May 20, 2025
9cb2a25
put new named_parameter at the good place
LeoValque May 20, 2025
a088905
Update Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/i…
afabri May 20, 2025
296d799
Benchmark script for Nicolas
LeoValque May 20, 2025
96453a8
add new cpp in cmakelist of bench
LeoValque May 21, 2025
3864b46
undo namespace change
sloriot Jun 5, 2025
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
13 changes: 13 additions & 0 deletions Documentation/doc/biblio/geom.bib
Original file line number Diff line number Diff line change
Expand Up @@ -152085,3 +152085,16 @@ @article{ledoux2014triangulation
year={2014},
publisher={Elsevier}
}

@unpublished{lazard:hal-04907149,
TITLE = {{Removing self-intersections in 3D meshes while preserving floating-point coordinates}},
AUTHOR = {Lazard, Sylvain and Valque, Leo},
URL = {https://inria.hal.science/hal-04907149},
NOTE = {working paper or preprint},
YEAR = {2025},
MONTH = Jan,
KEYWORDS = {Snap rounding ; mesh intersection ; robustness},
PDF = {https://inria.hal.science/hal-04907149v1/file/Snap-HAL.pdf},
HAL_ID = {hal-04907149},
HAL_VERSION = {v1},
}
2 changes: 1 addition & 1 deletion Installation/CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
### [Polygon Mesh Processing](https://doc.cgal.org/6.1/Manual/packages.html#PkgPolygonMeshProcessing)
- Added the function `CGAL::Polygon_mesh_processing::discrete_mean_curvature` and `CGAL::Polygon_mesh_processing::discrete_Guassian_curvature` to evaluate the discrete curvature at a vertex of a mesh.
- Added the function `CGAL::Polygon_mesh_processing::angle_sum` to compute the sum of the angles around a vertex.

- Added the parameter `apply_iterative_snap_rounding` to the function `CGAL::Polygon_mesh_processing::autorefine_triangle_soup()`. When set to `true`, the coordinates are rounded to fit in double and may perform additional subdivisions to ensure the output remains free of self-intersections.

### [Algebraic Kernel](https://doc.cgal.org/6.1/Manual/packages.html#PkgAlgebraicKernelD)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,21 @@ else()
endif()

create_single_source_cgal_program("fast.cpp")
create_single_source_cgal_program("rotated_cubes_autorefinement.cpp")
create_single_source_cgal_program("coplanar_cubes_autorefinement.cpp")

create_single_source_cgal_program("Performance/performance_snap_polygon_soup.cpp")
create_single_source_cgal_program("Robustness/robustness_snap_polygon_soup.cpp")
create_single_source_cgal_program("Quality/quality_snap_polygon_soup.cpp")

create_single_source_cgal_program("polygon_mesh_slicer.cpp")
target_link_libraries(polygon_mesh_slicer PRIVATE CGAL::Eigen3_support)

find_package(TBB QUIET)
include(CGAL_TBB_support)
if(TARGET CGAL::TBB_support)
target_link_libraries(rotated_cubes_autorefinement PRIVATE CGAL::TBB_support)
target_link_libraries(coplanar_cubes_autorefinement PRIVATE CGAL::TBB_support)
else()
message(STATUS "NOTICE: Intel TBB was not found. Sequential code will be used.")
endif()
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
#include <CGAL/Polygon_mesh_processing/repair_polygon_soup.h>
#include <CGAL/Polygon_mesh_processing/autorefinement.h>
#include <CGAL/Polygon_mesh_processing/triangulate_faces.h>
#include <CGAL/IO/polygon_soup_io.h>

#include <boost/container/small_vector.hpp>

#include <iostream>

typedef CGAL::Exact_predicates_inexact_constructions_kernel Kernel;
typedef typename Kernel::Point_3 Point_3;
namespace PMP = CGAL::Polygon_mesh_processing;

enum EXIT_CODES { VALID_OUTPUT=0,
INVALID_INPUT=1,
ROUNDING_FAILED=2,
SIGSEGV=10,
SIGSABRT=11,
SIGFPE=12,
TIMEOUT=13
};

int main(int argc, char** argv)
{
if(argc<4){
std::cout << "Invalid argument" << std::endl;
return 1;
}

const std::string filename = std::string(argv[1]);
const int grid_size = std::stoi(std::string(argv[2]));
const bool erase_duplicate = std::stoi(argv[3])==1;

std::vector<Point_3> points;
std::vector<boost::container::small_vector<std::size_t, 3>> triangles;

if (!CGAL::IO::read_polygon_soup(filename, points, triangles))
{
std::cerr << "Cannot read " << filename << "\n";
return 1;
}

PMP::repair_polygon_soup(points, triangles);
PMP::triangulate_polygons(points, triangles);

PMP::autorefine_triangle_soup(points, triangles, CGAL::parameters::apply_iterative_snap_rounding(true).erase_all_duplicates(erase_duplicate).concurrency_tag(CGAL::Parallel_if_available_tag()).snap_grid_size(grid_size).number_of_iterations(15));

return 0;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
#!/bin/bash

set -e

if [ "$#" -lt 4 ]; then
echo "Usage: $0 <input_file> <timeout> [component_params...]"
exit 1
fi

INPUT_FILE=$1
TIMEOUT=$2
GRID_SIZE=$3
ERASE_ALL_DUPLICATE=$4

# Use /usr/bin/time for memory usage (maximum resident set size in KB)
TMP_LOG=$(mktemp)

# Run the benchmarked command
/usr/bin/time -f "TIME:%e\nMEM:%M" timeout "$TIMEOUT"s performance_snap_polygon_soup "$INPUT_FILE" "$GRID_SIZE" "$ERASE_ALL_DUPLICATE" 2> "$TMP_LOG"

# Parse time and memory
SECONDS=$(grep "TIME" "$TMP_LOG" | cut -d':' -f2)
MEMORY=$(grep "MEM" "$TMP_LOG" | cut -d':' -f2)

rm -f "$TMP_LOG"

# Output JSON
echo "{\"seconds\": \"$SECONDS\", \"memory_peaks\": \"$MEMORY\"}"
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
#include <CGAL/Polygon_mesh_processing/repair_polygon_soup.h>
#include <CGAL/Polygon_mesh_processing/autorefinement.h>
#include <CGAL/Polygon_mesh_processing/triangulate_faces.h>
#include <CGAL/Polygon_mesh_processing/distance.h>
#include <CGAL/IO/polygon_soup_io.h>

#include <CGAL/Bbox_3.h>
#include <CGAL/boost/graph/helpers.h>

#include <CGAL/Surface_mesh.h>

#include <boost/container/small_vector.hpp>
#include <CGAL/Polygon_mesh_processing/orientation.h>

using Kernel = CGAL::Exact_predicates_inexact_constructions_kernel;
typedef typename Kernel::Point_3 Point_3;
namespace PMP = CGAL::Polygon_mesh_processing;

int main(int argc, char** argv)
{
if(argc<4){
std::cout << "Invalid argument" << std::endl;
return 1;
}
const std::string filename = std::string(argv[1]);
const int grid_size = std::stoi(std::string(argv[2]));
const bool erase_duplicate = std::stoi(argv[3])==1;

std::vector<Point_3> points;
std::vector<boost::container::small_vector<std::size_t, 3>> triangles;

CGAL::Bbox_3 bb = CGAL::bbox_3(points.begin(), points.end());
double diag_length=std::sqrt((bb.xmax()-bb.xmin())*(bb.xmax()-bb.xmin()) + (bb.ymax()-bb.ymin())*(bb.ymax()-bb.ymin()) + (bb.zmax()-bb.zmin())*(bb.zmax()-bb.zmin()));
if (!CGAL::IO::read_polygon_soup(filename, points, triangles))
{
std::cerr << "Cannot read " << filename << "\n";
return 1;
}

std::vector<Point_3> input_points(points.begin(), points.end());

PMP::autorefine_triangle_soup(points, triangles, CGAL::parameters::apply_iterative_snap_rounding(true).erase_all_duplicates(erase_duplicate).concurrency_tag(CGAL::Parallel_if_available_tag()).snap_grid_size(grid_size).number_of_iterations(15));


std::cout << "{" <<
"\"Nb_output_points\": \"" << points.size() << "\",\n" <<
"\"Nb_output_triangles\": \"" << triangles.size() << "\",\n" <<
"\"Is_2_manifold\": \"" << (PMP::orient_polygon_soup(points, triangles)?"True":"False") << "\",\n";
CGAL::Surface_mesh<Point_3> sm;
PMP::polygon_soup_to_polygon_mesh(points, triangles, sm);

std::cout << std::setprecision(17) <<
"\"Hausdorff_distance_output_to_input_(divide_by_bbox_diag)\": \"" << PMP::max_distance_to_triangle_mesh<CGAL::Parallel_if_available_tag>(input_points, sm) / diag_length << "\",\n" <<
"\"Closed_output\": \"" << (CGAL::is_closed(sm)?"True":"False") << "\",\n" <<
"\"Ouput_bound_a_volume\": \"" << (PMP::does_bound_a_volume(sm)?"True":"False") << "\"\n}"
<< std::endl;

return 0;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
#!/bin/bash

set -e

if [ "$#" -lt 4 ]; then
echo "Usage: $0 <input_file> <timeout> [component_params...]"
exit 1
fi

INPUT_FILE=$1
TIMEOUT=$2
GRID_SIZE=$3
ERASE_ALL_DUPLICATE=$4

TMP_LOG=$(mktemp)
timeout "$TIMEOUT"s quality_snap_polygon_soup "$INPUT_FILE" "$GRID_SIZE" "$ERASE_ALL_DUPLICATE" > "$TMP_LOG"

cat $TMP_LOG
rm -f "$TMP_LOG"
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
#include <CGAL/Polygon_mesh_processing/repair_polygon_soup.h>
#include <CGAL/Polygon_mesh_processing/autorefinement.h>
#include <CGAL/Polygon_mesh_processing/triangulate_faces.h>
#include <CGAL/IO/polygon_soup_io.h>

#include <boost/container/small_vector.hpp>

typedef CGAL::Exact_predicates_inexact_constructions_kernel Kernel;
typedef typename Kernel::Point_3 Point_3;
namespace PMP = CGAL::Polygon_mesh_processing;

enum EXIT_CODES { VALID_OUTPUT=0,
INVALID_INPUT=1,
ROUNDING_FAILED=2,
SELF_INTERSECTING_OUTPUT=3,
SIGSEGV=10,
SIGSABRT=11,
SIGFPE=12,
TIMEOUT=13
};

int main(int argc, char** argv)
{
if(argc<4){
std::cout << "Invalid argument" << std::endl;
return 1;
}

const std::string filename = std::string(argv[1]);
const int grid_size = std::stoi(std::string(argv[2]));
const bool erase_duplicate = std::stoi(argv[3])==1;

std::vector<Point_3> points;
std::vector<boost::container::small_vector<std::size_t, 3>> triangles;

if (!CGAL::IO::read_polygon_soup(filename, points, triangles) || points.size()==0 || triangles.size()==0)
{
return INVALID_INPUT;
}

PMP::repair_polygon_soup(points, triangles);
PMP::triangulate_polygons(points, triangles);

bool success=PMP::autorefine_triangle_soup(points, triangles, CGAL::parameters::apply_iterative_snap_rounding(true).erase_all_duplicates(erase_duplicate).concurrency_tag(CGAL::Parallel_if_available_tag()).snap_grid_size(grid_size).number_of_iterations(15));

if(!success)
return ROUNDING_FAILED;
if( PMP::does_triangle_soup_self_intersect<CGAL::Parallel_if_available_tag>(points, triangles) )
return SELF_INTERSECTING_OUTPUT;

return VALID_OUTPUT;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
#!/bin/bash

if [ "$#" -lt 4 ]; then
echo "Usage: $0 <input_file> <timeout> [component_params...]"
exit 1
fi

timeout_bis() {
timeout 5 sleep 10
}

INPUT_FILE=$1
TIMEOUT=$2
GRID_SIZE=$3
ERASE_ALL_DUPLICATE=$4

# Run with timeout, capture exit code
timeout "--foreground" "$TIMEOUT"s robustness_snap_polygon_soup "$INPUT_FILE" "$GRID_SIZE" "$ERASE_ALL_DUPLICATE"
EXIT_CODE=$?

# Interpret exit codes
declare -A TAGS
TAGS[0]="VALID_OUTPUT"
TAGS[1]="INPUT_IS_INVALID"
TAGS[2]="ROUNDING_FAILED"
TAGS[3]="SELF_INTERSECTING_OUTPUT"
TAGS[139]="SIGSEGV"
TAGS[11]="SIGSEGV"
TAGS[6]="SIGABRT"
TAGS[8]="SIGFPE"
TAGS[132]="SIGILL"
TAGS[124]="TIMEOUT"

TAG_NAME=${TAGS[$EXIT_CODE]:-UNKNOWN}
TAG_DESC=$([[ "$EXIT_CODE" -eq 0 ]] && echo "OK" || echo "Error")

# Output JSON
echo "{\"TAG_NAME\": \"$TAG_NAME\", \"TAG\": \"$TAG_DESC\"}"
Loading