Add benchmarking scripts

This commit is contained in:
Mael Rouxel-Labbé 2023-09-29 11:02:47 +02:00
parent 62bb2a58d0
commit 00f167a835
17 changed files with 1401 additions and 4 deletions

View File

@ -0,0 +1,15 @@
# Created by the script cgal_create_cmake_script
# This is the CMake script for compiling a CGAL application.
cmake_minimum_required(VERSION 3.1...3.20)
project(Alpha_wrap_3_Benchmark)
find_package(CGAL REQUIRED)
include_directories (BEFORE ../../include ./Quality ./Robustness) # AW3 includes
include_directories (BEFORE ../../../CGAL-Patches/include)
# create a target per cppfile
create_single_source_cgal_program("Performance/performance_benchmark.cpp")
create_single_source_cgal_program("Quality/quality_benchmark.cpp")
create_single_source_cgal_program("Robustness/robustness_benchmark.cpp")

View File

@ -0,0 +1,61 @@
# Copyright (c) 2019-2023 Google LLC (USA).
# All rights reserved.
#
# This file is part of CGAL (www.cgal.org).
#
# $URL$
# $Id$
# SPDX-License-Identifier: GPL-3.0-or-later
#
#
# Author(s) : Pierre Alliez
# Michael Hemmer
# Cedric Portaneri
#
#!/usr/bin/python
import os, sys, subprocess, datetime, time, getopt
def compute_performance_benchmark_data(execname, filename, alpha):
output = ""
cmd = ("/usr/bin/time", "-v",
execname, "-i",
filename, "-a", alpha)
proc = subprocess.Popen(
cmd,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
start_new_session=True)
outs, errs = proc.communicate()
output = outs.decode("utf-8") + errs.decode("utf-8")
for output_line in output.split("\n"):
if "User time (seconds): " in output_line:
print(output_line[len("User time (seconds): "):])
continue
if "Maximum resident set size (kbytes): " in output_line:
print(output_line[len("Maximum resident set size (kbytes): "):])
continue
def main(argv):
execname=""
filename=""
alpha=""
try:
opts, args = getopt.getopt(sys.argv[1:], 'e:i:a:')
except getopt.GetoptError:
sys.exit(2)
for opt, arg in opts:
if opt == "-e":
execname = arg
elif opt == "-i":
filename = arg
elif opt == "-a":
alpha = arg
compute_performance_benchmark_data(execname, filename, alpha)
if __name__ == "__main__":
main(sys.argv[1:])

View File

@ -0,0 +1,156 @@
# Copyright (c) 2019-2023 Google LLC (USA).
# All rights reserved.
#
# This file is part of CGAL (www.cgal.org).
#
# $URL$
# $Id$
# SPDX-License-Identifier: GPL-3.0-or-later
#
#
# Author(s) : Pierre Alliez
# Michael Hemmer
# Cedric Portaneri
#
#!/usr/bin/python
import os, sys, subprocess, datetime, time, signal, getopt
import numpy as np
import matplotlib.pyplot as plt
def main(argv):
inputdir=""
outputdir=""
commit_hash=""
alpha=""
do_diff=False
diffdir=""
diff_hash=""
try:
opts, args = getopt.getopt(sys.argv[1:], 'i:a:o:c:d:p:')
except getopt.GetoptError:
sys.exit(2)
for opt, arg in opts:
if opt == "-i":
inputdir = arg
elif opt == "-a":
alpha = arg
elif opt == "-o":
outputdir = arg
elif opt == "-c":
commit_hash = arg
elif opt == "-d":
diff_hash = arg
do_diff = True
elif opt == "-p":
diffdir = arg
all_metric = {
"Time_(second)" : {},
"Memory_Peak_(kbytes)" : {}}
num_input = 0
for filename in os.listdir(inputdir) :
new_path = os.path.join(inputdir,filename)
new_file = open(new_path)
is_empty_new = os.path.getsize(new_path) <= 1
if do_diff :
old_path = os.path.join(diffdir,filename)
old_file = open(old_path)
is_empty_old = os.path.getsize(old_path) <= 1
for key in all_metric:
if is_empty_new or is_empty_old :
new_val = 0.
old_val = 0.
else :
new_val = float(new_file.readline().rstrip('\n'))
old_val = float(old_file.readline().rstrip('\n'))
mesh_id = str(filename.split('.')[0])
all_metric[key][mesh_id] = [new_val, old_val]
else :
for key in all_metric:
if is_empty_new :
new_val = 0.
else :
new_val = float(new_file.readline().rstrip('\n'))
mesh_id = str(filename.split('.')[0])
all_metric[key][mesh_id] = [new_val, new_val]
num_input = num_input+1
# update .pdf chart
date_now = datetime.datetime.now()
date_for_filename = str(date_now.year) +"_"+ str(date_now.month) +"_"+ str(date_now.day) +"_"+ str(date_now.hour) +"h"+ str(date_now.minute) +"mn"
for key in all_metric:
goal = 0
num_el = range(len(all_metric[key]))
avg_diff_to_goal = 0.
avg = 0.
x1 = []
x2 = []
for value in all_metric[key].values() :
avg += value[0]
diff_to_goal = abs(value[1]-goal) - abs(value[0]-goal)
avg_diff_to_goal += diff_to_goal
x1.append(value[0])
x2.append(value[1])
avg_diff_to_goal /= float(len(all_metric[key]))
avg /= float(len(all_metric[key]))
plt.figure(figsize=(8,8))
if do_diff :
plt.hist(x2, bins=100, color='tab:green', alpha=0.5)
plt.hist(x1, bins=100, color='tab:blue', alpha=0.5)
plt.vlines(x = goal, ymin=plt.ylim()[0], ymax=plt.ylim()[1], linestyles='dashed')
title = ""
if do_diff :
title += "Diff between " + commit_hash + " and " + diff_hash + " on " + str(num_input) + " meshes from Thingi10K\nAlpha = Bbox diag length / " + alpha
else :
title += "Benchmarking on " + str(num_input) + " meshes from Thingi10K\nAlpha = Bbox diag length / " + alpha
avg_str = str(format(abs(avg), '.2f'))
if key == "Time_(second)" :
title += "\nIn average we spend " + avg_str + " seconds"
else :
title += "\nIn average we use up to " + avg_str + " kbytes"
if do_diff and avg_diff_to_goal == 0. :
title += "\nNo change between the two commits"
elif do_diff :
avg_diff_str = str(format(abs(avg_diff_to_goal), '.2f'))
if key == "Time_(second)" :
if avg_diff_to_goal < 0 :
title += "\nIn average we get slower by "
else :
title += "\nIn average we get faster "
title += avg_diff_str + " seconds"
else :
if avg_diff_to_goal < 0 :
title += "\nIn average we use " + avg_diff_str + " more"
else :
title += "\nIn average we use " + avg_diff_str + " less"
title += " kbytes"
plt.title(title, fontsize=15)
plt.xlabel(key.replace("_"," "), fontsize=14)
plt.ylabel("# of meshes", fontsize=14)
plt.tick_params(axis="x", labelsize=9)
plt.tick_params(axis="y", labelsize=9)
chart_filename = ""
if do_diff :
chart_filename += "diff_"+commit_hash+"_"+diff_hash+"_"+key+"_"+date_for_filename+".pdf"
else :
chart_filename += "results_"+commit_hash+"_"+key+"_"+date_for_filename+".pdf"
chart_path = os.path.join(outputdir+"/charts",chart_filename)
if os.path.isfile(chart_path) :
os.remove(chart_path)
plt.savefig(chart_path, bbox_inches="tight")
plt.close()
print("pdf updated")
sys.exit()
if __name__ == "__main__":
main(sys.argv[1:])

View File

@ -0,0 +1,65 @@
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
#include <CGAL/Surface_mesh.h>
#include <CGAL/alpha_wrap_3.h>
#include <CGAL/IO/polygon_soup_io.h>
#include <array>
#include <iostream>
#include <string>
#include <vector>
using K = CGAL::Exact_predicates_inexact_constructions_kernel;
using Point_3 = K::Point_3;
using Vector_3 = K::Vector_3;
using Mesh = CGAL::Surface_mesh<Point_3>;
namespace PMP = CGAL::Polygon_mesh_processing;
int main(int argc, char** argv)
{
const int argc_check = argc - 1;
const char* entry_name_ptr = nullptr;
double relative_alpha_ratio = 20., relative_offset_ratio = 600.;
for(int i=1; i<argc; ++i)
{
if(!strcmp("-i", argv[i]) && i < argc_check)
entry_name_ptr = argv[++i];
else if(!strcmp("-a", argv[i]) && i < argc_check)
relative_alpha_ratio = std::stod(argv[++i]);
else if(!strcmp("-d", argv[i]) && i < argc_check)
relative_offset_ratio = std::stod(argv[++i]);
}
if(argc < 3 || relative_alpha_ratio <= 0.)
{
std::cerr << "Error: bad input parameters." << std::endl;
return EXIT_FAILURE;
}
std::vector<Point_3> points;
std::vector<std::array<std::size_t, 3> > faces;
if(!CGAL::IO::read_polygon_soup(entry_name_ptr, points, faces) || faces.empty())
{
std::cerr << "Error: Invalid input data." << std::endl;
return EXIT_FAILURE;
}
CGAL::Bbox_3 bbox;
for(const Point_3& p : points)
bbox += p.bbox();
const double diag_length = std::sqrt(CGAL::square(bbox.xmax() - bbox.xmin()) +
CGAL::square(bbox.ymax() - bbox.ymin()) +
CGAL::square(bbox.zmax() - bbox.zmin()));
const double alpha = diag_length / relative_alpha_ratio;
const double offset = diag_length / relative_offset_ratio;
Mesh wrap;
CGAL::alpha_wrap_3(points, faces, alpha, offset, wrap);
return EXIT_SUCCESS;
}

View File

@ -0,0 +1,54 @@
# Copyright (c) 2019-2023 Google LLC (USA).
# All rights reserved.
#
# This file is part of CGAL (www.cgal.org).
#
# $URL$
# $Id$
# SPDX-License-Identifier: GPL-3.0-or-later
#
#
# Author(s) : Pierre Alliez
# Michael Hemmer
# Cedric Portaneri
#
#!/usr/bin/python
import os, sys, subprocess, datetime, time, getopt
def compute_quality_benchmark_data(execname, filename, alpha):
output = ""
cmd = (execname, "-i",
filename, "-a", alpha)
proc = subprocess.Popen(
cmd,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
start_new_session=True)
outs, errs = proc.communicate()
output = outs.decode("utf-8") + errs.decode("utf-8")
print(output)
def main(argv):
execname=""
filename=""
alpha=""
try:
opts, args = getopt.getopt(sys.argv[1:], 'e:i:a:')
except getopt.GetoptError:
sys.exit(2)
for opt, arg in opts:
if opt == "-e":
execname = arg
elif opt == "-i":
filename = arg
elif opt == "-a":
alpha = arg
compute_quality_benchmark_data(execname, filename, alpha)
if __name__ == "__main__":
main(sys.argv[1:])

View File

@ -0,0 +1,151 @@
// Copyright (c) 2019-2022 Google LLC (USA).
// All rights reserved.
//
// This file is part of CGAL (www.cgal.org).
//
// $URL$
// $Id$
// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial
//
// Author(s) : Pierre Alliez
// Michael Hemmer
// Cedric Portaneri
#ifndef CGAL_ALPHA_WRAP_3_BENCHMARK_ALPHA_WRAP_3_QUALITY_DISTANCE_H_
#define CGAL_ALPHA_WRAP_3_BENCHMARK_ALPHA_WRAP_3_QUALITY_DISTANCE_H_
#include <CGAL/AABB_face_graph_triangle_primitive.h>
#include <CGAL/AABB_traits.h>
#include <CGAL/AABB_tree.h>
#include <CGAL/bounding_box.h>
#include <CGAL/Polygon_mesh_processing/bbox.h>
#include <CGAL/Polygon_mesh_processing/distance.h>
#include <CGAL/point_generators_3.h>
#include <CGAL/Search_traits_3.h>
namespace Aw3i {
enum Distance_metric { HAUSDORFF = 0, MEAN = 1, RMS = 2 };
template <typename Point, typename AABBTree>
inline double approximate_hausdorff_distance(const std::vector<Point>& sample_points,
const AABBTree& tree,
Point& hint)
{
double hdist = 0;
for(const Point& pt : sample_points)
{
hint = tree.closest_point(pt, hint);
auto dist = CGAL::squared_distance(hint, pt);
double d = CGAL::to_double(CGAL::approximate_sqrt(dist));
if(d > hdist)
hdist = d;
}
return hdist;
}
template <typename Point, typename AABBTree>
inline double approximate_mean_distance(const std::vector<Point>& sample_points,
const AABBTree& tree,
Point& hint)
{
double mdist = 0;
for(const Point& pt : sample_points)
{
hint = tree.closest_point(pt, hint);
auto dist = CGAL::squared_distance(hint, pt);
double d = CGAL::to_double(CGAL::approximate_sqrt(dist));
mdist += d;
}
return mdist / sample_points.size();
}
template <typename Point, typename AABBTree>
inline double approximate_rms_distance(const std::vector<Point>& sample_points,
const AABBTree& tree,
Point& hint)
{
double rmsdist = 0;
for(const Point& pt : sample_points)
{
hint = tree.closest_point(pt, hint);
auto dist = CGAL::squared_distance(hint, pt);
rmsdist += CGAL::to_double(dist);
}
return CGAL::to_double(CGAL::approximate_sqrt(rmsdist / sample_points.size()));
}
template <typename TriangleMesh>
inline double approximate_distance(const TriangleMesh& tm1,
const TriangleMesh& tm2,
const Distance_metric& metric)
{
using GT = typename CGAL::GetGeomTraits<TriangleMesh>::type;
using Point_3 = typename GT::Point_3;
using Primitive = CGAL::AABB_face_graph_triangle_primitive<TriangleMesh>;
using AABB_traits = CGAL::AABB_traits<GT, Primitive>;
using AABB_tree = CGAL::AABB_tree<AABB_traits>;
using CGAL::parameters::choose_parameter;
using CGAL::parameters::get_parameter;
std::vector<Point_3> original_sample_points;
CGAL::Polygon_mesh_processing::sample_triangle_mesh(tm1, std::back_inserter(original_sample_points),
CGAL::parameters::all_default());
std::vector<Point_3> sample_points(std::begin(original_sample_points),
std::end(original_sample_points));
CGAL::spatial_sort(sample_points.begin(), sample_points.end());
AABB_tree tree(faces(tm2).first, faces(tm2).second, tm2);
tree.build();
auto vpm_2 = get(CGAL::vertex_point, tm2);
Point_3 hint = get(vpm_2, *vertices(tm2).first);
if(metric == HAUSDORFF)
return approximate_hausdorff_distance(sample_points, tree, hint);
else if(metric == MEAN)
return approximate_mean_distance(sample_points, tree, hint);
else if(metric == RMS)
return approximate_rms_distance(sample_points, tree, hint);
else
std::cerr << "Metric unknown\n" << std::endl;
return -1.0;
}
template <typename TriangleMesh>
double get_longest_diag_bbox(const TriangleMesh& tm)
{
CGAL::Bbox_3 bbox = CGAL::Polygon_mesh_processing::bbox(tm);
return std::sqrt(CGAL::square(bbox.xmax() - bbox.xmin()) +
CGAL::square(bbox.ymax() - bbox.ymin()) +
CGAL::square(bbox.zmax() - bbox.zmin()));
}
template <typename TriangleMesh>
inline double approximate_distance_relative_to_bbox(const TriangleMesh& tm1,
const TriangleMesh& tm2,
const Distance_metric& metric)
{
double longest_diag_length = get_longest_diag_bbox(tm1);
return approximate_distance(tm1, tm2, metric) / longest_diag_length;
}
template <typename TriangleMesh, typename FT>
inline double approximate_distance_relative_to_bbox(const TriangleMesh& tm1,
const TriangleMesh& tm2,
const Distance_metric& metric,
const FT& longest_diag_length)
{
return approximate_distance(tm1, tm2, metric) / CGAL::to_double(longest_diag_length);
}
} // namespace Aw3i
#endif // CGAL_CGAL_ALPHA_WRAP_3_BENCHMARK_ALPHA_WRAP_3_QUALITY_DISTANCE_H_

View File

@ -0,0 +1,182 @@
# Copyright (c) 2019-2023 Google LLC (USA).
# All rights reserved.
#
# This file is part of CGAL (www.cgal.org).
#
# $URL$
# $Id$
# SPDX-License-Identifier: GPL-3.0-or-later
#
#
# Author(s) : Pierre Alliez
# Michael Hemmer
# Cedric Portaneri
#
#!/usr/bin/python
import os, sys, subprocess, datetime, time, signal, getopt
import numpy as np
import matplotlib.pyplot as plt
def main(argv):
inputdir=""
outputdir=""
commit_hash=""
alpha=""
do_diff=False
diffdir=""
diff_hash=""
try:
opts, args = getopt.getopt(sys.argv[1:], 'i:a:o:c:d:p:')
except getopt.GetoptError:
sys.exit(2)
for opt, arg in opts:
if opt == "-i":
inputdir = arg
elif opt == "-a":
alpha = arg
elif opt == "-o":
outputdir = arg
elif opt == "-c":
commit_hash = arg
elif opt == "-d":
diff_hash = arg
do_diff = True
elif opt == "-p":
diffdir = arg
all_metric = {
"Mean_Min_Angle_(degree)" : {},
"Mean_Max_Angle_(degree)" : {},
"Mean_Radius_Ratio" : {},
"Mean_Edge_Ratio" : {},
"Mean_Aspect_Ratio" : {},
"Complexity_(#_of_triangle)" : {},
"#_of_almost_degenerate_triangle" : {},
"Hausdorff_distance_output_to_input_(%_of_bbox_diag)" : {}}
num_input = 0
print("inputdir = ", inputdir)
for filename in os.listdir(inputdir) :
new_path = os.path.join(inputdir,filename)
new_file = open(new_path)
if do_diff :
old_path = os.path.join(diffdir,filename)
old_file = open(old_path)
is_empty_old = os.path.getsize(old_path) <= 1
for key in all_metric :
try :
new_val = float(new_file.readline().rstrip('\n'))
old_val = float(old_file.readline().rstrip('\n'))
mesh_id = str(filename.split('.')[0])
all_metric[key][mesh_id] = [new_val, old_val]
except ValueError:
pass
else :
for key in all_metric :
try :
new_val = float(new_file.readline().rstrip('\n'))
mesh_id = str(filename.split('.')[0])
all_metric[key][mesh_id] = [new_val, new_val]
except ValueError:
pass
num_input = num_input+1
# update .pdf chart
date_now = datetime.datetime.now()
date_for_filename = str(date_now.year) +"_"+ str(date_now.month) +"_"+ str(date_now.day) +"_"+ str(date_now.hour) +"h"+ str(date_now.minute) +"mn"
for key in all_metric:
goal = 0
if key == "Mean_Min_Angle_(degree)" or key == "Mean_Max_Angle_(degree)":
goal = 60
elif key == "Mean_Radius_Ratio" or key == "Mean_Edge_Ratio" or key == "Mean_Aspect_Ratio" :
goal = 1
num_el = range(len(all_metric[key]))
avg_diff_to_goal = 0.
avg = 0.
x1 = []
x2 = []
for value in all_metric[key].values() :
avg += value[0]
diff_to_goal = abs(value[1]-goal) - abs(value[0]-goal)
avg_diff_to_goal += diff_to_goal
x1.append(value[0])
x2.append(value[1])
avg_diff_to_goal /= float(len(all_metric[key]))
avg /= float(len(all_metric[key]))
plt.figure(figsize=(8,8))
if do_diff :
plt.hist(x2, bins=100, color='tab:green', alpha=0.5)
plt.hist(x1, bins=100, color='tab:blue', alpha=0.5)
plt.vlines(x = goal, ymin=plt.ylim()[0], ymax=plt.ylim()[1], linestyles='dashed')
title = ""
if do_diff :
title += "Diff between " + commit_hash + " and " + diff_hash + " on " + str(num_input) + " meshes from Thingi10K\nAlpha = Bbox diag length / " + alpha
else :
title += "Benchmarking on " + str(num_input) + " meshes from Thingi10K\nAlpha = Bbox diag length / " + alpha
avg_str = str(format(abs(avg), '.2f'))
if key == "Mean_Min_Angle_(degree)" or key == "Mean_Max_Angle_(degree)":
title += "\nIn average we have " + avg_str + "°"
elif key == "Mean_Radius_Ratio" or key == "Mean_Edge_Ratio" or key == "Mean_Aspect_Ratio" :
title += "\nIn average we have a ratio of " + avg_str
elif key == "Hausdorff_distance_output_to_input_(%_of_bbox_diag)" :
title += "\nIn average we have a distance of " + avg_str + "% of bbox diag"
elif key == "Complexity_(#_of_triangle)" or key == "#_of_almost_degenerate_triangle" :
title += "\nIn average we have " + avg_str + " triangles"
if do_diff and avg_diff_to_goal == 0. :
title += "\nNo change between the two commits"
elif do_diff :
avg_diff_str = str(format(abs(avg_diff_to_goal), '.2f'))
if key == "Mean_Min_Angle_(degree)" or key == "Mean_Max_Angle_(degree)":
if avg_diff_to_goal < 0 :
title += "\nIn average we loose "
else :
title += "\nIn average we gain "
title += avg_diff_str + "° toward 60°"
elif key == "Mean_Radius_Ratio" or key == "Mean_Edge_Ratio" or key == "Mean_Aspect_Ratio" :
if avg_diff_to_goal < 0 :
title += "\nIn average we loose "
else :
title += "\nIn average we gain "
title += avg_diff_str + " of ratio toward 1"
elif key == "Hausdorff_distance_output_to_input_(%_of_bbox_diag)" :
if avg_diff_to_goal < 0 :
title += "\nIn average we increase by "
else :
title += "\nIn average we reduce by "
title += avg_diff_str + " the bbox ratio"
elif key == "Complexity_(#_of_triangle)" or key == "#_of_almost_degenerate_triangle" :
if avg_diff_to_goal < 0 :
title += "\nIn average we get " + avg_diff_str + " more"
else :
title += "\nIn average we get " + avg_diff_str + " less"
title += " triangles"
plt.title(title, fontsize=15)
plt.xlabel(key.replace("_"," "), fontsize=14)
plt.ylabel("# of meshes", fontsize=14)
plt.tick_params(axis="x", labelsize=9)
plt.tick_params(axis="y", labelsize=9)
chart_filename = ""
if do_diff :
chart_filename += "diff_"+commit_hash+"_"+diff_hash+"_"+key+"_"+date_for_filename+".pdf"
else :
chart_filename += "results_"+commit_hash+"_"+key+"_"+date_for_filename+".pdf"
chart_path = os.path.join(outputdir+"/charts",chart_filename)
if os.path.isfile(chart_path) :
os.remove(chart_path)
plt.savefig(chart_path, bbox_inches="tight")
plt.close()
print("pdf updated")
sys.exit()
if __name__ == "__main__":
main(sys.argv[1:])

View File

@ -0,0 +1,271 @@
#include <distance_utils.h>
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
#include <CGAL/Surface_mesh.h>
#include <CGAL/alpha_wrap_3.h>
#include <CGAL/Polygon_mesh_processing/IO/polygon_mesh_io.h>
#include <array>
#include <cmath>
#include <iostream>
using Kernel = CGAL::Exact_predicates_inexact_constructions_kernel;
using Point_3 = Kernel::Point_3;
using Vector_3 = Kernel::Vector_3;
using Triangle_3 = Kernel::Triangle_3;
using FT = Kernel::FT;
using Mesh = CGAL::Surface_mesh<Point_3>;
using face_descriptor = boost::graph_traits<Mesh>::face_descriptor;
using Oracle = CGAL::Alpha_wraps_3::internal::Triangle_mesh_oracle<Kernel>;
using Dt = CGAL::Alpha_wraps_3::internal::Alpha_wrap_3<Oracle>::Triangulation;
namespace PMP = CGAL::Polygon_mesh_processing;
std::array<FT, 3> triangle_angles(const Triangle_3& tr)
{
FT sq_a = CGAL::squared_distance(tr[0], tr[1]);
FT sq_b = CGAL::squared_distance(tr[1], tr[2]);
FT sq_c = CGAL::squared_distance(tr[2], tr[0]);
FT two_ab = 2. * CGAL::sqrt(sq_a) * CGAL::sqrt(sq_b);
FT two_bc = 2. * CGAL::sqrt(sq_b) * CGAL::sqrt(sq_c);
FT two_ca = 2. * CGAL::sqrt(sq_c) * CGAL::sqrt(sq_a);
FT angle_a = (sq_b + sq_c - sq_a) / two_bc;
FT angle_b = (sq_c + sq_a - sq_b) / two_ca;
FT angle_c = (sq_a + sq_b - sq_c) / two_ab;
if(angle_a < -1.) angle_a = -1.;
if(angle_b < -1.) angle_b = -1.;
if(angle_c < -1.) angle_c = -1.;
if(angle_a > 1.) angle_a = 1.;
if(angle_b > 1.) angle_b = 1.;
if(angle_c > 1.) angle_c = 1.;
angle_a = std::acos(angle_a);
angle_b = std::acos(angle_b);
angle_c = std::acos(angle_c);
return {angle_a, angle_b, angle_c};
}
bool is_almost_degenerate(const Triangle_3& tr,
double threshold)
{
FT sq_area = tr.squared_area();
return (CGAL::sqrt(CGAL::to_double(sq_area)) < threshold);
}
auto surface_mesh_face_to_triangle(const face_descriptor fd,
const Mesh& sm)
{
typename boost::graph_traits<Mesh>::halfedge_descriptor hd = halfedge(fd,sm);
return Triangle_3(sm.point(target(hd,sm)),
sm.point(target(next(hd,sm),sm)),
sm.point(target(next(next(hd,sm),sm),sm)));
}
double mean_min_angle(const Mesh& mesh)
{
double mean_min_angle = 0.;
for(const face_descriptor f : faces(mesh))
{
const Triangle_3 tr = surface_mesh_face_to_triangle(f, mesh);
std::array<FT, 3> angles = triangle_angles(tr);
FT min_angle = std::min({angles[0], angles[1], angles[2]});
min_angle = min_angle * (180.0 / CGAL_PI);
mean_min_angle += min_angle;
}
mean_min_angle /= static_cast<double>(mesh.number_of_faces());
return mean_min_angle;
}
double mean_max_angle(const Mesh& mesh)
{
double mean_max_angle = 0.;
for(const face_descriptor f : faces(mesh))
{
const Triangle_3 tr = surface_mesh_face_to_triangle(f, mesh);
std::array<FT, 3> angles = triangle_angles(tr);
FT max_angle = std::max({angles[0], angles[1], angles[2]});
max_angle = max_angle * (180.0 / CGAL_PI);
mean_max_angle += max_angle;
}
mean_max_angle /= static_cast<double>(mesh.number_of_faces());
return mean_max_angle;
}
double mean_radius_ratio(const Mesh& mesh,
double degenerate_threshold)
{
double mean_radius_ratio = 0.;
size_t num_almost_degenerate_tri = 0;
for(const face_descriptor f : faces(mesh))
{
const Triangle_3 tr = surface_mesh_face_to_triangle(f, mesh);
if(is_almost_degenerate(tr, degenerate_threshold))
{
++num_almost_degenerate_tri;
continue;
}
FT circumsphere_radius = std::sqrt(CGAL::squared_radius(tr[0], tr[1], tr[2]));
FT a = std::sqrt(CGAL::squared_distance(tr[0], tr[1]));
FT b = std::sqrt(CGAL::squared_distance(tr[1], tr[2]));
FT c = std::sqrt(CGAL::squared_distance(tr[2], tr[0]));
FT s = 0.5 * (a + b + c);
FT inscribed_radius = std::sqrt((s * (s - a) * (s - b) * (s - c)) / s);
FT radius_ratio = circumsphere_radius / inscribed_radius;
radius_ratio /= 2.; // normalized
mean_radius_ratio += radius_ratio;
}
mean_radius_ratio /= static_cast<double>(mesh.number_of_faces() - num_almost_degenerate_tri);
return mean_radius_ratio;
}
double mean_edge_ratio(const Mesh& mesh,
double degenerate_threshold)
{
double mean_edge_ratio = 0.;
size_t num_almost_degenerate_tri = 0;
for(const face_descriptor f : faces(mesh))
{
const Triangle_3 tr = surface_mesh_face_to_triangle(f, mesh);
if(is_almost_degenerate(tr, degenerate_threshold))
{
++num_almost_degenerate_tri;
continue;
}
FT a = std::sqrt(CGAL::squared_distance(tr[0], tr[1]));
FT b = std::sqrt(CGAL::squared_distance(tr[1], tr[2]));
FT c = std::sqrt(CGAL::squared_distance(tr[2], tr[0]));
FT min_edge = std::min({a, b, c});
FT max_edge = std::max({a, b, c});
FT edge_ratio = max_edge / min_edge;
mean_edge_ratio += edge_ratio;
}
mean_edge_ratio /= static_cast<double>(mesh.number_of_faces() - num_almost_degenerate_tri);
return mean_edge_ratio;
}
double mean_aspect_ratio(const Mesh& mesh,
double degenerate_threshold)
{
double mean_aspect_ratio = 0.;
size_t num_almost_degenerate_tri = 0;
for(const face_descriptor f : faces(mesh))
{
const Triangle_3 tr = surface_mesh_face_to_triangle(f, mesh);
if(is_almost_degenerate(tr, degenerate_threshold))
{
++num_almost_degenerate_tri;
continue;
}
FT a = std::sqrt(CGAL::squared_distance(tr[0], tr[1]));
FT b = std::sqrt(CGAL::squared_distance(tr[1], tr[2]));
FT c = std::sqrt(CGAL::squared_distance(tr[2], tr[0]));
FT s = 0.5 * (a + b + c);
FT inscribed_radius = std::sqrt((s * (s - a) * (s - b) * (s - c)) / s);
FT max_edge = std::max({a, b, c});
FT aspect_ratio = max_edge / inscribed_radius;
aspect_ratio /= (2. * std::sqrt(3.)); // normalized
mean_aspect_ratio += aspect_ratio;
}
mean_aspect_ratio /= static_cast<double>(mesh.number_of_faces() - num_almost_degenerate_tri);
return mean_aspect_ratio;
}
size_t num_almost_degenerate_tri(const Mesh& mesh,
double degenerate_threshold)
{
size_t num_almost_degenerate_tri = 0;
for(const face_descriptor f : faces(mesh))
{
const Triangle_3 tr = surface_mesh_face_to_triangle(f, mesh);
if(is_almost_degenerate(tr, degenerate_threshold))
{
++num_almost_degenerate_tri;
}
}
return num_almost_degenerate_tri;
}
int main(int argc, char** argv)
{
const int argc_check = argc - 1;
char *entry_name_ptr = nullptr;
double relative_alpha_ratio = 20.;
double relative_offset_ratio = 600.;
for(int i=1; i<argc; ++i)
{
if(!strcmp("-i", argv[i]) && i < argc_check) {
entry_name_ptr = argv[++i];
} else if(!strcmp("-a", argv[i]) && i < argc_check) {
relative_alpha_ratio = std::stod(argv[++i]);
} else if(!strcmp("-d", argv[i]) && i < argc_check) {
relative_offset_ratio = std::stod(argv[++i]);
}
}
if(argc < 3 || relative_alpha_ratio <= 0.)
{
std::cerr << "Error: bad input parameters." << std::endl;
return EXIT_FAILURE;
}
Mesh input_mesh;
if(!PMP::IO::read_polygon_mesh(entry_name_ptr, input_mesh) ||
is_empty(input_mesh) ||
!is_triangle_mesh(input_mesh))
{
return EXIT_FAILURE;
}
CGAL::Bbox_3 bbox = PMP::bbox(input_mesh);
const double diag_length = std::sqrt(CGAL::square(bbox.xmax() - bbox.xmin()) +
CGAL::square(bbox.ymax() - bbox.ymin()) +
CGAL::square(bbox.zmax() - bbox.zmin()));
const double alpha = diag_length / relative_alpha_ratio;
const double offset = diag_length / relative_offset_ratio;
Mesh wrap;
CGAL::alpha_wrap_3(input_mesh, alpha, offset, wrap);
double degenerate_threshold = 0.;
for(const face_descriptor f : faces(wrap))
{
const Triangle_3 tr = surface_mesh_face_to_triangle(f, wrap);
degenerate_threshold += CGAL::sqrt(CGAL::to_double(tr.squared_area()));
}
degenerate_threshold /= wrap.number_of_faces();
degenerate_threshold /= 1000;
std::cout << mean_min_angle(wrap) << "\n";
std::cout << mean_max_angle(wrap) << "\n";
std::cout << mean_radius_ratio(wrap, degenerate_threshold) << "\n";
std::cout << mean_edge_ratio(wrap, degenerate_threshold) << "\n";
std::cout << mean_aspect_ratio(wrap, degenerate_threshold) << "\n";
std::cout << wrap.number_of_faces() << "\n";
std::cout << num_almost_degenerate_tri(wrap, degenerate_threshold) << "\n";
std::cout << 100. * approximate_distance_relative_to_bbox(wrap, input_mesh, Aw3i::HAUSDORFF) << "\n";
return 0;
}

View File

@ -0,0 +1,96 @@
# Copyright (c) 2019-2023 Google LLC (USA).
# All rights reserved.
#
# This file is part of CGAL (www.cgal.org).
#
# $URL$
# $Id$
# SPDX-License-Identifier: GPL-3.0-or-later
#
#
# Author(s) : Pierre Alliez
# Michael Hemmer
# Cedric Portaneri
#
#!/usr/bin/python
import os, sys, subprocess, datetime, time, signal, getopt
def signal_handler(signum, frame):
raise Exception("Timed out!")
def compute_robustness_benchmark_data(execname, filename, alpha, max_time):
exit_codes = {
0 : "VALID_SOLID_OUTPUT",
1 : "OUTPUT_IS_NOT_TRIANGLE_MESH",
2 : "OUTPUT_IS_COMBINATORIAL_NON_MANIFOLD",
3 : "OUTPUT_HAS_BORDERS",
4 : "OUTPUT_HAS_DEGENERATED_FACES",
5 : "OUTPUT_HAS_GEOMETRIC_SELF_INTERSECTIONS",
6 : "OUTPUT_DOES_NOT_BOUND_VOLUME",
7 : "OUTPUT_DOES_NOT_CONTAIN_INPUT",
8 : "OUTPUT_DISTANCE_IS_TOO_LARGE",
9 : "SIGSEGV",
10 : "SIGABRT",
11 : "SIGFPE",
12 : "TIMEOUT"
}
exit_code = 0
output = ""
cmd = ("/usr/bin/time", "-v",
execname, "-i",
filename, "-a", alpha)
proc = subprocess.Popen(
cmd,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
start_new_session=True)
try:
outs, errs = proc.communicate(timeout=int(max_time))
exit_code = proc.returncode
output = outs.decode("utf-8") + errs.decode("utf-8")
for output_line in output.split("\n"):
if output_line == "Command terminated by signal 11":
exit_code = 9
continue
elif output_line == "Command terminated by signal 6":
exit_code = 10
continue
elif output_line == "Command terminated by signal 8":
exit_code = 11
continue
except subprocess.TimeoutExpired:
os.killpg(os.getpgid(proc.pid), signal.SIGTERM)
exit_code = 12
output = "process ran too long"
print(exit_codes[exit_code])
def main(argv):
execname=""
filename=""
alpha=""
max_time=""
try:
opts, args = getopt.getopt(sys.argv[1:], 'e:i:a:t:')
except getopt.GetoptError:
sys.exit(2)
for opt, arg in opts:
if opt == "-e":
execname = arg
elif opt == "-i":
filename = arg
elif opt == "-a":
alpha = arg
elif opt == "-t":
max_time = arg
compute_robustness_benchmark_data(execname, filename, alpha, max_time)
if __name__ == "__main__":
main(sys.argv[1:])

View File

@ -0,0 +1,154 @@
# Copyright (c) 2019-2023 Google LLC (USA).
# All rights reserved.
#
# This file is part of CGAL (www.cgal.org).
#
# $URL$
# $Id$
# SPDX-License-Identifier: GPL-3.0-or-later
#
#
# Author(s) : Pierre Alliez
# Michael Hemmer
# Cedric Portaneri
#
#!/usr/bin/python
import os, sys, subprocess, datetime, time, signal, getopt
import numpy as np
import matplotlib.pyplot as plt
def main(argv):
inputdir=""
outputdir=""
commit_hash=""
alpha=""
try:
opts, args = getopt.getopt(sys.argv[1:], 'i:a:o:c:')
except getopt.GetoptError:
sys.exit(2)
for opt, arg in opts:
if opt == "-i":
inputdir = arg
elif opt == "-a":
alpha = arg
elif opt == "-o":
outputdir = arg
elif opt == "-c":
commit_hash = arg
exit_codes = {
0 : "VALID_SOLID_OUTPUT",
1 : "OUTPUT_IS_NOT_TRIANGLE_MESH",
2 : "OUTPUT_IS_COMBINATORIAL_NON_MANIFOLD",
3 : "OUTPUT_HAS_BORDERS",
4 : "OUTPUT_HAS_DEGENERATED_FACES",
5 : "OUTPUT_HAS_GEOMETRIC_SELF_INTERSECTIONS",
6 : "OUTPUT_DOES_NOT_BOUND_VOLUME",
7 : "OUTPUT_DOES_NOT_CONTAIN_INPUT",
8 : "OUTPUT_DISTANCE_IS_TOO_LARGE",
9 : "SIGSEGV",
10 : "SIGABRT",
11 : "SIGFPE",
12 : "TIMEOUT"
}
current_run_data = {
"VALID_SOLID_OUTPUT" : 0,
"OUTPUT_IS_NOT_TRIANGLE_MESH" : 0,
"OUTPUT_IS_COMBINATORIAL_NON_MANIFOLD" : 0,
"OUTPUT_HAS_BORDERS" : 0,
"OUTPUT_HAS_DEGENERATED_FACES" : 0,
"OUTPUT_HAS_GEOMETRIC_SELF_INTERSECTIONS" : 0,
"OUTPUT_DOES_NOT_BOUND_VOLUME" : 0,
"OUTPUT_DOES_NOT_CONTAIN_INPUT" : 0,
"OUTPUT_DISTANCE_IS_TOO_LARGE" : 0,
"SIGSEGV" : 0,
"SIGABRT" : 0,
"SIGFPE" : 0,
"TIMEOUT" : 0
}
filenames_per_codes = {}
for key in current_run_data :
filenames_per_codes[key] = []
print("inputdir = ", inputdir)
num_input = 0
for filename in os.listdir(inputdir) :
print("filename = ", filename)
f = open(os.path.join(inputdir,filename))
status = f.readline().rstrip('\n');
current_run_data[status] += 1
filenames_per_codes[status].append(filename.rstrip('.log'))
num_input = num_input+1
# sort current_run_data by value
current_run_data = {k: v for k, v in sorted(current_run_data.items(), key=lambda item: item[1], reverse=True)}
# update chart data files
date_now = datetime.datetime.now()
date = str(date_now.year) +"-"+ str(date_now.month) +"-"+ str(date_now.day) +" "+ str(date_now.hour) +"h"+ str(date_now.minute) +"mn"
for key_filename in current_run_data:
f = open(os.path.join(outputdir+"/charts_data", key_filename+".txt"), "a+")
f.write(str(current_run_data[key_filename]) + " " + commit_hash + " " + date + "\n")
print("chart data updated")
# update .pdf chart
chart = plt.figure(figsize=(10, 7))
colormap = ["tab:blue","tab:orange","tab:green","tab:red","tab:purple","tab:brown","tab:pink","tab:gray","tab:olive","tab:cyan","b","palegreen", "peachpuff"]
plt.gca().set_prop_cycle('color', colormap)
plt.style.use('tableau-colorblind10')
for key_filename in current_run_data:
f = open(os.path.join(outputdir+"/charts_data", key_filename+".txt"), "r")
lines = f.readlines()
x_number_values = []
y_number_values = []
i = 0
for line in lines :
if i < (len(lines) - 10) :
i=i+1
continue
i=i+1
words = line.strip().split()
x_number_values.append(words[1]+"\n"+words[2]+"\n"+words[3])
y_number_values.append(int(words[0]))
plt.plot(x_number_values, y_number_values, marker='o', label=key_filename+": "+str(current_run_data[key_filename]))
plt.xlabel("Version", fontsize=14)
plt.ylabel("# of mesh", fontsize=14)
plt.tick_params(axis="both", labelsize=9)
plt.title("Benchmarking on " + str(num_input) + " meshes from Thingi10K\nAlpha = Bbox diag length / " + alpha, fontsize=15)
plt.legend(loc='lower left', bbox_to_anchor= (1.01, 0.58), ncol=1,
borderaxespad=0, frameon=False)
date_for_filename = str(date_now.year) +"-"+ str(date_now.month) +"-"+ str(date_now.day) +"-"+ str(date_now.hour) +"h"+ str(date_now.minute) +"mn"
chart_filename = os.path.join(outputdir+"/charts","benchmarking_version_"+commit_hash+"-"+date_for_filename+".pdf")
if os.path.isfile(chart_filename) :
os.remove(chart_filename)
chart.savefig(chart_filename, bbox_inches="tight")
plt.close(chart)
print("pdf updated")
# dump filenames per codes
log_dirname = os.path.join(outputdir, "log/"+commit_hash+"-"+date_for_filename)
if not os.path.exists(log_dirname):
os.mkdir(log_dirname)
for key in filenames_per_codes :
file = open(os.path.join(log_dirname, key+".txt"), "w+")
for filename in filenames_per_codes[key] :
file.write(filename + "\n")
file.close()
sys.exit()
if __name__ == "__main__":
main(sys.argv[1:])

View File

@ -0,0 +1,106 @@
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
#include <CGAL/Surface_mesh.h>
#include <CGAL/alpha_wrap_3.h>
#include <CGAL/Alpha_wrap_3/internal/validation.h>
#include <CGAL/Polygon_mesh_processing/IO/polygon_mesh_io.h>
using Kernel = CGAL::Exact_predicates_inexact_constructions_kernel;
using Point_3 = Kernel::Point_3;
using Mesh = CGAL::Surface_mesh<Point_3>;
namespace CGAL {
namespace Alpha_wraps_3 {
namespace internal {
namespace {
enum Robustness_benchmark_exit_code
{
// Success
VALID_SOLID_OUTPUT = 0,
// Failure
OUTPUT_IS_NOT_TRIANGLE_MESH = 1,
OUTPUT_IS_COMBINATORIAL_NON_MANIFOLD = 2,
OUTPUT_HAS_BORDERS = 3,
OUTPUT_HAS_DEGENERATED_FACES = 4,
OUTPUT_HAS_GEOMETRIC_SELF_INTERSECTIONS = 5,
OUTPUT_DOES_NOT_BOUND_VOLUME = 6,
OUTPUT_DOES_NOT_CONTAIN_INPUT = 7,
OUTPUT_DISTANCE_IS_TOO_LARGE = 8,
};
} // namespace
} // namespace internal
} // namespace Alpha_wraps_3
} // namespace CGAL
namespace PMP = CGAL::Polygon_mesh_processing;
namespace AW3i = CGAL::Alpha_wraps_3::internal;
int main(int argc, char** argv)
{
const int argc_check = argc - 1;
char* entry_name_ptr = nullptr;
double relative_alpha_ratio = 20.;
double relative_offset_ratio = 600.;
for(int i=1; i<argc; ++i)
{
if(!strcmp("-i", argv[i]) && i < argc_check) {
entry_name_ptr = argv[++i];
} else if(!strcmp("-a", argv[i]) && i < argc_check) {
relative_alpha_ratio = std::stod(argv[++i]);
} else if(!strcmp("-d", argv[i]) && i < argc_check) {
relative_offset_ratio = std::stod(argv[++i]);
}
}
if(argc < 3 || relative_alpha_ratio <= 0.)
return AW3i::VALID_SOLID_OUTPUT;
Mesh input_mesh;
if(!PMP::IO::read_polygon_mesh(entry_name_ptr, input_mesh) ||
is_empty(input_mesh) ||
!is_triangle_mesh(input_mesh))
{
return AW3i::VALID_SOLID_OUTPUT;
}
const CGAL::Bbox_3 bbox = PMP::bbox(input_mesh);
const double diag_length = std::sqrt(CGAL::square(bbox.xmax() - bbox.xmin()) +
CGAL::square(bbox.ymax() - bbox.ymin()) +
CGAL::square(bbox.zmax() - bbox.zmin()));
const double alpha = diag_length / relative_alpha_ratio;
const double offset = diag_length / relative_offset_ratio;
Mesh wrap;
alpha_wrap_3(input_mesh, alpha, offset, wrap);
if(!is_triangle_mesh(wrap))
return AW3i::OUTPUT_IS_NOT_TRIANGLE_MESH;
if(!is_closed(wrap))
return AW3i::OUTPUT_HAS_BORDERS;
if(AW3i::has_degenerated_faces(wrap))
return AW3i::OUTPUT_HAS_DEGENERATED_FACES;
if(AW3i::is_combinatorially_non_manifold(wrap))
return AW3i::OUTPUT_IS_COMBINATORIAL_NON_MANIFOLD;
if(PMP::does_self_intersect(wrap))
return AW3i::OUTPUT_HAS_GEOMETRIC_SELF_INTERSECTIONS;
if(!PMP::does_bound_a_volume(wrap))
return AW3i::OUTPUT_DOES_NOT_BOUND_VOLUME;
if(!AW3i::is_outer_wrap_of_triangle_mesh(wrap, input_mesh))
return AW3i::OUTPUT_DOES_NOT_CONTAIN_INPUT;
if(!AW3i::has_expected_Hausdorff_distance(wrap, input_mesh, alpha, offset))
return AW3i::OUTPUT_DISTANCE_IS_TOO_LARGE;
return AW3i::VALID_SOLID_OUTPUT;
}

View File

@ -0,0 +1,86 @@
# Copyright (c) 2019-2023 Google LLC (USA).
# All rights reserved.
#
# This file is part of the 3D Alpha Wrapping package, which is being prepared for
# submission to CGAL (www.cgal.org).
#
# $URL$
# $Id$
# SPDX-License-Identifier: GPL-3.0-or-later
#
#
# Author(s) : Pierre Alliez
# Michael Hemmer
# Cedric Portaneri
# Mael Rouxel-Labbé
#
#!/bin/bash
# $1: directory containing the alpha wrap project
# $2: directory containing the output results
# $3: alpha value
# $4: timeout value in seconds
# $5: hash of the latest commit
# $6: the input file path
function compute_benchmark_data() {
filename=$(basename -- "$6")
filename="${filename%.*}"
python3 $1/Alpha_wrap_3/benchmark/Alpha_wrap_3/Robustness/compute_robustness_benchmark_data.py \
-e $1/Alpha_wrap_3/benchmark/Alpha_wrap_3/build-release/robustness_benchmark -i $6 -a $3 -t $4 \
> $2/Robustness/results/$5/$filename.log
python3 $1/Alpha_wrap_3/benchmark/Alpha_wrap_3/Performance/compute_performance_benchmark_data.py \
-e $1/Alpha_wrap_3/benchmark/Alpha_wrap_3/build-release/performance_benchmark -i $6 -a $3 \
> $2/Performance/results/$5/$filename.log
python3 $1/Alpha_wrap_3/benchmark/Alpha_wrap_3/Quality/compute_quality_benchmark_data.py \
-e $1/Alpha_wrap_3/benchmark/Alpha_wrap_3/build-release/quality_benchmark -i $6 -a $3 \
> $2/Quality/results/$5/$filename.log
}
export -f compute_benchmark_data
# $1: directory containing the alpha wrap project
# $2: directory containing the input data folder
# $3: directory containing the output results
# $4: alpha value
# $5: timeout value for robustness benchmark in seconds
# $6: number of virtual thread used
# $7: hash of the latest commit
# $8: hash of a commit to perform the diff with latest
cd $1
mkdir -p $3/Robustness/results/$7
mkdir -p $3/Performance/results/$7
mkdir -p $3/Quality/results/$7
mkdir -p $3/Robustness/charts_data
mkdir -p $3/Performance/charts_data
mkdir -p $3/Quality/charts_data
mkdir -p $3/Robustness/charts
mkdir -p $3/Performance/charts
mkdir -p $3/Quality/charts
mkdir -p $3/Robustness/log
mkdir -p $3/Performance/log
mkdir -p $3/Quality/log
mkdir -p $3/charts
find $2 -mindepth 1 | parallel -j$6 compute_benchmark_data $1 $3 $4 $5 $7 :::
python3 $1/Alpha_wrap_3/benchmark/Alpha_wrap_3/Robustness/generate_robustness_benchmark_charts.py -i $3/Robustness/results/$7 -o $3/Robustness -a $4 -c $7
if [ -z "$8" ]; then
python3 $1/Alpha_wrap_3/benchmark/Alpha_wrap_3/Performance/generate_performance_benchmark_charts.py -i $3/Performance/results/$7 -o $3/Performance -a $4 -c $7;
else
python3 $1/Alpha_wrap_3/benchmark/Alpha_wrap_3/Performance/generate_performance_benchmark_charts.py -i $3/Performance/results/$7 -o $3/Performance -a $4 -c $7 -p $3/Performance/results/$8 -d $8;
fi
if [ -z "$8" ]; then
python3 $1/Alpha_wrap_3/benchmark/Alpha_wrap_3/Quality/generate_quality_benchmark_charts.py -i $3/Quality/results/$7 -o $3/Quality -a $4 -c $7;
else
python3 $1/Alpha_wrap_3/benchmark/Alpha_wrap_3/Quality/generate_quality_benchmark_charts.py -i $3/Quality/results/$7 -o $3/Quality -a $4 -c $7 -p $3/Quality/results/$8 -d $8;
fi
charts_path="$(ls "$3/Robustness/charts"/* -dArt | tail -n 1) $(ls "$3/Performance/charts"/* -dArt | tail -n 2) $(ls "$3/Quality/charts"/* -dArt | tail -n 9)"
pdfjam --nup 2x6 $charts_path --outfile $3/charts/results_$7_$8_alpha_$4_$(date '+%Y-%m-%d_%H:%M:%S').pdf

View File

@ -6,7 +6,7 @@
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h> #include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
#include <CGAL/alpha_wrap_3.h> #include <CGAL/alpha_wrap_3.h>
#include "alpha_wrap_validation.h" #include <CGAL/Alpha_wrap_3/internal/validation.h>
#include <CGAL/Polygon_mesh_processing/IO/polygon_mesh_io.h> #include <CGAL/Polygon_mesh_processing/IO/polygon_mesh_io.h>

View File

@ -5,7 +5,7 @@
//#define CGAL_AW3_DEBUG_QUEUE //#define CGAL_AW3_DEBUG_QUEUE
#include <CGAL/alpha_wrap_3.h> #include <CGAL/alpha_wrap_3.h>
#include "alpha_wrap_validation.h" #include <CGAL/Alpha_wrap_3/internal/validation.h>
#include <CGAL/Surface_mesh.h> #include <CGAL/Surface_mesh.h>
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h> #include <CGAL/Exact_predicates_inexact_constructions_kernel.h>

View File

@ -4,7 +4,7 @@
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h> #include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
#include <CGAL/alpha_wrap_3.h> #include <CGAL/alpha_wrap_3.h>
#include "alpha_wrap_validation.h" #include <CGAL/Alpha_wrap_3/internal/validation.h>
#include <CGAL/Surface_mesh.h> #include <CGAL/Surface_mesh.h>
#include <CGAL/IO/polygon_soup_io.h> #include <CGAL/IO/polygon_soup_io.h>

View File

@ -6,7 +6,7 @@
//#define CGAL_AW3_DEBUG_QUEUE //#define CGAL_AW3_DEBUG_QUEUE
#include <CGAL/alpha_wrap_3.h> #include <CGAL/alpha_wrap_3.h>
#include "alpha_wrap_validation.h" #include <CGAL/Alpha_wrap_3/internal/validation.h>
#include <CGAL/Surface_mesh.h> #include <CGAL/Surface_mesh.h>
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h> #include <CGAL/Exact_predicates_inexact_constructions_kernel.h>