mirror of https://github.com/CGAL/cgal
Add benchmarking scripts
This commit is contained in:
parent
62bb2a58d0
commit
00f167a835
|
|
@ -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")
|
||||||
|
|
@ -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:])
|
||||||
|
|
@ -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:])
|
||||||
|
|
@ -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;
|
||||||
|
}
|
||||||
|
|
@ -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:])
|
||||||
|
|
@ -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_
|
||||||
|
|
@ -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:])
|
||||||
|
|
@ -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;
|
||||||
|
}
|
||||||
|
|
@ -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:])
|
||||||
|
|
@ -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:])
|
||||||
|
|
@ -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;
|
||||||
|
}
|
||||||
|
|
@ -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
|
||||||
|
|
@ -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>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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>
|
||||||
|
|
|
||||||
|
|
@ -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>
|
||||||
|
|
|
||||||
|
|
@ -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>
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue