1#ifndef IO_OUTPUT_DEBUG_TRACES_TO_HTML_H_
2#define IO_OUTPUT_DEBUG_TRACES_TO_HTML_H_
17namespace coxeter_triangulation {
20std::ostream&
operator<<(std::ostream& os,
const std::vector<T>& vector) {
26 auto v_it = vector.begin();
28 for (; v_it != vector.end(); ++v_it) os <<
", " << *v_it;
35 Straighten(
const Eigen::VectorXd& vector) : vector_(vector) {}
36 const Eigen::VectorXd& vector_;
39std::ostream&
operator<<(std::ostream& os,
const Straighten& str) {
40 std::size_t size = str.vector_.size();
41 os <<
"(" << str.vector_(0);
46 for (std::size_t i = 1; i < size; ++i) os <<
", " << str.vector_(i);
51std::string id_from_simplex(
const std::string& simplex) {
52 std::regex r(
"\\s+"), r2(
"\\(|\\)|\\{|\\}"), r3(
","), r4(
"\\["), r5(
"\\]");
53 std::string output = std::regex_replace(simplex, r,
"");
54 output = std::regex_replace(output, r2,
":");
55 output = std::regex_replace(output, r3,
".");
56 output = std::regex_replace(output, r4,
"_");
57 output = std::regex_replace(output, r5,
"");
62std::string to_string(
const T& t) {
63 std::ostringstream oss;
68struct MT_inserted_info {
69 std::string qr_face_, init_face_, qr_intersection_;
70 bool qr_success_, is_boundary_;
71 template <
class Query_result,
class Simplex_handle>
72 MT_inserted_info(
const Query_result& qr,
const Simplex_handle& face,
bool is_boundary)
73 : qr_face_(to_string(face)),
74 init_face_(to_string(face)),
75 qr_intersection_(to_string(qr.intersection)),
76 qr_success_(qr.success),
77 is_boundary_(is_boundary) {}
79std::list<MT_inserted_info> mt_seed_inserted_list, mt_inserted_list;
81struct CC_summary_info {
82 std::string face_, cell_;
83 template <
class SC_pair>
84 CC_summary_info(
const SC_pair& sc_pair) : face_(to_string(sc_pair.first)), cell_(to_string(sc_pair.second)) {}
86using CC_summary_list = std::list<CC_summary_info>;
87std::vector<CC_summary_list> cc_interior_summary_lists, cc_boundary_summary_lists;
89struct CC_detail_info {
90 enum class Result_type { self, face, coface, inserted, join_single, join_is_face };
91 std::string simplex_, trigger_, init_simplex_;
93 bool join_trigger_ =
false;
94 std::list<std::string> faces_, post_faces_, cofaces_;
95 template <
class Simplex_handle>
96 CC_detail_info(
const Simplex_handle& simplex) : simplex_(to_string(simplex)) {}
98using CC_detail_list = std::list<CC_detail_info>;
99std::vector<CC_detail_list> cc_interior_detail_lists, cc_boundary_detail_lists;
100std::vector<CC_detail_list> cc_interior_insert_detail_lists, cc_boundary_insert_detail_lists;
102struct CC_prejoin_info {
103 enum class Result_type { join_single, join_is_face, join_different, join_same };
104 std::string simplex_, join_;
105 std::vector<std::string> faces_;
106 std::size_t dimension_;
108 template <
class Simplex_handle>
109 CC_prejoin_info(
const Simplex_handle& simplex) : simplex_(to_string(simplex)), dimension_(simplex.dimension()) {}
111using CC_prejoin_list = std::list<CC_prejoin_info>;
112std::vector<CC_prejoin_list> cc_interior_prejoin_lists, cc_boundary_prejoin_lists;
115 enum class Result_type { self, face, coface, inserted, join_single, join_is_face };
116 std::string simplex_, join_, trigger_;
118 std::list<std::string> boundary_faces_;
119 std::list<std::string> faces_, post_faces_, cofaces_;
120 template <
class Simplex_handle>
121 CC_join_info(
const Simplex_handle& simplex) : simplex_(to_string(simplex)) {}
123bool join_switch =
false;
124std::vector<CC_detail_list> cc_interior_join_detail_lists, cc_boundary_join_detail_lists;
126std::map<std::string, std::string> cell_vlist_map;
127std::map<std::string, std::string> simplex_vlist_map;
129std::ostringstream mt_ostream, vis_ostream;
130std::vector<std::ostringstream> cc_summary_ostream, cc_traces_ostream;
132std::string simplex_format(
const std::string& simplex,
bool is_boundary) {
133 std::string b_simplex = (is_boundary ?
"B" :
"I") + simplex;
134 std::string tooltiptext;
135 auto it = simplex_vlist_map.find(b_simplex);
136 if (it == simplex_vlist_map.end())
137 tooltiptext =
"deleted";
139 tooltiptext = simplex_vlist_map.at(b_simplex);
140 return (std::string)
"<a class=\"" + (is_boundary ?
"boundary" :
"interior") +
"\" href=\"#" +
141 id_from_simplex(b_simplex) +
"\">" + b_simplex +
"<span class=\"tooltiptext\">" + tooltiptext +
"</span></a>";
144std::string simplex_format(
const std::string& b_simplex) {
145 bool is_boundary = b_simplex[0] ==
'B';
146 std::string tooltiptext;
147 auto it = simplex_vlist_map.find(b_simplex);
148 if (it == simplex_vlist_map.end())
149 tooltiptext =
"deleted";
151 tooltiptext = simplex_vlist_map.at(b_simplex);
152 return (std::string)
"<a class=\"" + (is_boundary ?
"boundary" :
"interior") +
"\" href=\"#" +
153 id_from_simplex(b_simplex) +
"\">" + b_simplex +
"<span class=\"tooltiptext\">" + tooltiptext +
"</span></a>";
156void write_head(std::ofstream& ofs) {
158 <<
" <title>Cell complex debug trace</title>\n"
161 <<
" position: relative;\n"
162 <<
" display: inline-block;\n"
163 <<
" color: darkred;\n"
164 <<
" background-color: lightgreen\n"
167 <<
" position: relative;\n"
168 <<
" display: inline-block;\n"
170 <<
" background-color: yellow\n"
172 <<
" .tooltiptext {\n"
173 <<
" visibility: hidden;\n"
174 <<
" width: 120px;\n"
175 <<
" background-color: #555;\n"
177 <<
" text-align: center;\n"
178 <<
" padding: 5px 0;\n"
179 <<
" border-radius: 6px;\n"
180 <<
" position: absolute;\n"
182 <<
" bottom: 125%;\n"
184 <<
" margin-left: -60px;\n"
186 <<
" transition: opacity 0.3s;\n"
188 <<
" .boundary .tooltiptext::after {\n"
189 <<
" content: \"\";\n"
190 <<
" position: absolute;\n"
193 <<
" margin-left: -5px;\n"
194 <<
" border-width: 5px;\n"
195 <<
" border-style: solid;\n"
196 <<
" border-color: #555 transparent transparent transparent;\n"
198 <<
" .interior .tooltiptext::after {\n"
199 <<
" content: \"\";\n"
200 <<
" position: absolute;\n"
203 <<
" margin-left: -5px;\n"
204 <<
" border-width: 5px;\n"
205 <<
" border-style: solid;\n"
206 <<
" border-color: #555 transparent transparent transparent;\n"
208 <<
" .boundary:hover .tooltiptext {\n"
209 <<
" visibility: visible;\n"
212 <<
" .interior:hover .tooltiptext {\n"
213 <<
" visibility: visible;\n"
217 <<
" list-style-type: none;\n"
220 <<
" overflow: auto;\n"
221 <<
" background-color: #333;\n"
222 <<
" position: fixed;\n"
223 <<
" height: 100%;\n"
226 <<
" ul.nav li a {\n"
227 <<
" display: block;\n"
228 <<
" color: white;\n"
229 <<
" text-align: left;\n"
230 <<
" padding: 14px 16px;\n"
231 <<
" text-decoration: none;\n"
234 <<
" background-color: #4CAF50;\n"
237 <<
" margin-left: 15%;\n"
238 <<
" padding: 1px 16px\n"
241 <<
" margin-left: 0%;\n"
242 <<
" padding: 0px 0px\n"
245 <<
" margin-left: 15%;\n"
246 <<
" padding: 1px 16px\n"
252void write_nav(std::ofstream& ofs) {
253 ofs <<
" <div class=\"navi\" style=\"margin-top:30px;background-color:#1abc9c;\">\n"
254 <<
" <ul class=\"nav\">\n"
255 <<
" <li><a href=\"#mant\">Manifold tracing</a></li>\n"
256 <<
" <li><a href=\"#cell\">Cell complex</a>\n"
258 for (std::size_t i = 0; i < cc_interior_summary_lists.size(); ++i) {
259 ofs <<
" <li><a href=\"#dim" << i <<
"\">Dimension " << i <<
"</a>\n";
261 ofs <<
" <li><a href=\"#dim" << i <<
"i\">Interior</a></li>\n";
262 if (i < cc_boundary_summary_lists.size()) {
263 ofs <<
" <li><a href=\"#dim" << i <<
"b\">Boundary</a></li>\n";
270 <<
" <li><a href=\"#visu\">Visualization details</a></li>\n"
275void write_mt(std::ofstream& ofs) {
276 ofs <<
" <div id=\"mant\">\n";
277 ofs <<
" <h2> Manifold debug trace </h2>\n";
278 ofs <<
" <h3> Simplices inserted during the seed phase </h3>\n";
280 for (
const MT_inserted_info& mt_info : mt_seed_inserted_list) {
281 if (mt_info.qr_success_) {
282 ofs <<
" <li>Inserted " << simplex_format(mt_info.qr_face_, mt_info.is_boundary_);
283 if (mt_info.qr_face_ != mt_info.init_face_)
284 ofs <<
" (initially " << simplex_format(mt_info.init_face_, mt_info.is_boundary_) <<
")";
285 ofs <<
" intersection point is " << mt_info.qr_intersection_ <<
"</li>\n";
287 ofs <<
" <li>Failed to insert " << mt_info.init_face_ <<
"</li>\n";
290 ofs <<
" <h3> Simplices inserted during the while loop phase </h3>\n";
292 for (
const MT_inserted_info& mt_info : mt_inserted_list) {
293 if (mt_info.qr_success_) {
294 ofs <<
" <li>Inserted " << simplex_format(mt_info.qr_face_, mt_info.is_boundary_);
295 if (mt_info.qr_face_ != mt_info.init_face_)
296 ofs <<
" (initially " << simplex_format(mt_info.init_face_, mt_info.is_boundary_) <<
")";
297 ofs <<
" intersection point is " << mt_info.qr_intersection_ <<
"</li>\n";
299 ofs <<
" <li>Failed to insert " << mt_info.init_face_ <<
")</li>\n";
305void write_cc(std::ofstream& ofs) {
306 ofs <<
" <div id=\"cell\">\n"
307 <<
" <h2> Cell complex debug trace </h2>\n"
308 <<
" <p>Go to:</p>\n"
310 for (std::size_t i = 0; i < cc_interior_summary_lists.size(); ++i) {
311 ofs <<
" <li><a href=\"#dim" << i <<
"\">Dimension " << i <<
"</a></li>\n";
314 for (std::size_t i = 0; i < cc_interior_summary_lists.size(); ++i) {
315 ofs <<
" <h3 id=\"dim" << i <<
"\"> Dimension " << i <<
"</h3>\n";
316 ofs <<
" <h4 id=\"dim" << i <<
"i\"> Summary for interior simplices</h4>\n";
317 if (i < cc_boundary_summary_lists.size()) ofs <<
" <p><a href=\"#dim" << i <<
"b\">Go to boundary</a></p>\n";
319 for (
const CC_summary_info& cc_info : cc_interior_summary_lists[i])
320 ofs <<
" <li id = \"" << id_from_simplex(
"I" + cc_info.face_) <<
"\">"
321 << simplex_format(cc_info.face_,
false) <<
" cell =" << cc_info.cell_ <<
"</li>\n";
323 ofs <<
" <h4> Prejoin state of the interior cells of dimension " << i <<
"</h4>\n";
324 auto prejoin_it = cc_interior_prejoin_lists[i].begin();
325 while (prejoin_it != cc_interior_prejoin_lists[i].end()) {
326 std::size_t j = prejoin_it->dimension_;
327 ofs <<
" <h5>" << j <<
"-dimensional ambient simplices</h5>\n";
329 for (; prejoin_it->dimension_ == j; ++prejoin_it) {
330 ofs <<
" <li>" << simplex_format(prejoin_it->simplex_,
false)
331 <<
" join = " << simplex_format(prejoin_it->join_,
false) <<
" boundary:\n"
333 for (
const auto& face : prejoin_it->faces_) ofs <<
" <li>" << simplex_format(face) <<
"</li>";
335 switch (prejoin_it->status_) {
336 case (CC_prejoin_info::Result_type::join_single):
337 ofs <<
" <p style=\"color: red\">Deleted " << simplex_format(prejoin_it->simplex_,
false)
338 <<
" as it has a single face.</p>";
340 case (CC_prejoin_info::Result_type::join_is_face):
341 ofs <<
" <p style=\"color: red\">Deleted " << simplex_format(prejoin_it->simplex_,
false)
342 <<
" as its join " << simplex_format(prejoin_it->join_,
false) <<
" is one of the faces.</p>";
344 case (CC_prejoin_info::Result_type::join_different):
345 ofs <<
" <p style=\"color: magenta\">Deleted " << simplex_format(prejoin_it->simplex_,
false)
346 <<
" and replaced by its join " << simplex_format(prejoin_it->join_,
false) <<
".</p>";
348 case (CC_prejoin_info::Result_type::join_same):
349 ofs <<
" <p style=\"color: green\">Kept " << simplex_format(prejoin_it->simplex_,
false)
356 ofs <<
" <h4> Details for interior simplices</h4>\n";
358 for (
const CC_detail_info& cc_info : cc_interior_detail_lists[i]) {
359 if (cc_info.status_ == CC_detail_info::Result_type::join_single) {
360 ofs <<
" <li style=\"color:magenta\" id = \"" << id_from_simplex(
"I" + cc_info.simplex_)
361 <<
"\"> Simplex " << simplex_format(cc_info.simplex_,
false) <<
" has only one face ("
362 << simplex_format(cc_info.trigger_,
false) <<
") and is deleted.";
365 if (cc_info.status_ == CC_detail_info::Result_type::join_single) {
366 ofs <<
" <li style=\"color:darkmagenta\" id = \"" << id_from_simplex(
"I" + cc_info.simplex_)
367 <<
"\"> The join of the simplex " << simplex_format(cc_info.simplex_,
false) <<
" is one of its faces ("
368 << simplex_format(cc_info.trigger_,
false) <<
"), hence it is is deleted.";
371 ofs <<
" <li> Insert_cell called for " << simplex_format(cc_info.simplex_,
false) <<
"\n";
378 if (cc_info.status_ == CC_detail_info::Result_type::self) {
379 ofs <<
" <p><span style=\"color:blue\">The simplex " << simplex_format(cc_info.simplex_,
false)
380 <<
" already exists in the cell complex!</span></p>\n";
382 if (cc_info.status_ == CC_detail_info::Result_type::face) {
383 ofs <<
" <p><span style=\"color:red\">The simplex " << simplex_format(cc_info.simplex_,
false)
384 <<
" is a face of the simplex " << simplex_format(cc_info.trigger_,
false) <<
"!</span><br>\n";
386 for (
const std::string post_face : cc_info.post_faces_)
387 ofs <<
" <li id = \"" << id_from_simplex(
"I" + post_face) <<
"\">"
388 <<
"Post deleting " << simplex_format(post_face,
false) <<
"</li>\n";
391 ofs <<
" <p id = \"" << id_from_simplex(
"I" + cc_info.trigger_) <<
"\">"
392 <<
"Deleting " << simplex_format(cc_info.trigger_,
false) <<
"</p>\n";
397 if (cc_info.status_ == CC_detail_info::Result_type::coface) {
398 ofs <<
" <p><span style=\"color:darkorange\">The simplex " << simplex_format(cc_info.simplex_,
false)
399 <<
" is a coface of the simplex " << simplex_format(cc_info.trigger_,
false) <<
"!</span><p>\n";
401 if (cc_info.status_ == CC_detail_info::Result_type::inserted) {
402 ofs <<
" <p><span style=\"color:green\">Successfully inserted "
403 << simplex_format(cc_info.simplex_,
false) <<
"!</span><p>\n";
410 if (i < cc_boundary_summary_lists.size()) {
411 ofs <<
" <h4 id=\"dim" << i <<
"b\"> Summary for boundary simplices</h4>\n";
412 ofs <<
" <p><a href=\"#dim" << i <<
"i\">Go to interior</a></p>\n";
414 for (
const CC_summary_info& cc_info : cc_boundary_summary_lists[i])
415 ofs <<
" <li id = \"" << id_from_simplex(
"B" + cc_info.face_) <<
"\">"
416 << simplex_format(cc_info.face_,
true) <<
" cell =" << cc_info.cell_ <<
"</li>\n";
418 ofs <<
" <h4> Prejoin state of the boundary cells of dimension " << i <<
"</h4>\n";
419 auto prejoin_it = cc_boundary_prejoin_lists[i].begin();
420 while (prejoin_it != cc_boundary_prejoin_lists[i].end()) {
421 std::size_t j = prejoin_it->dimension_;
422 ofs <<
" <h5>" << j <<
"-dimensional ambient simplices</h5>\n";
424 for (; prejoin_it->dimension_ == j; ++prejoin_it) {
425 ofs <<
" <li>" << simplex_format(prejoin_it->simplex_,
true)
426 <<
" join = " << simplex_format(prejoin_it->join_,
true) <<
" boundary:\n"
428 for (
const auto& face : prejoin_it->faces_) ofs <<
" <li>" << simplex_format(face) <<
"</li>";
430 switch (prejoin_it->status_) {
431 case (CC_prejoin_info::Result_type::join_single):
432 ofs <<
" <p style=\"color: red\">Deleted " << simplex_format(prejoin_it->simplex_,
true)
433 <<
" as it has a single face.</p>";
435 case (CC_prejoin_info::Result_type::join_is_face):
436 ofs <<
" <p style=\"color: red\">Deleted " << simplex_format(prejoin_it->simplex_,
true)
437 <<
" as its join " << simplex_format(prejoin_it->join_,
true) <<
" is one of the faces.</p>";
439 case (CC_prejoin_info::Result_type::join_different):
440 ofs <<
" <p style=\"color: magenta\">Deleted " << simplex_format(prejoin_it->simplex_,
true)
441 <<
" and replaced by its join " << simplex_format(prejoin_it->join_,
true) <<
".</p>";
443 case (CC_prejoin_info::Result_type::join_same):
444 ofs <<
" <p style=\"color: green\">Kept " << simplex_format(prejoin_it->simplex_,
true)
452 if (i < cc_boundary_detail_lists.size()) {
453 ofs <<
" <h4> Details for boundary simplices</h4>\n"
455 for (
const CC_detail_info& cc_info : cc_boundary_detail_lists[i]) {
456 if (cc_info.status_ == CC_detail_info::Result_type::join_single) {
457 ofs <<
" <li style=\"color:magenta\" id = \"" << id_from_simplex(
"B" + cc_info.simplex_)
458 <<
"\"> Simplex " << simplex_format(cc_info.simplex_,
true) <<
" has only one face ("
459 << simplex_format(cc_info.trigger_,
true) <<
") and is deleted.";
462 if (cc_info.status_ == CC_detail_info::Result_type::join_single) {
463 ofs <<
" <li style=\"color:darkmagenta\" id = \"" << id_from_simplex(
"B" + cc_info.simplex_)
464 <<
"\"> The join of the simplex " << simplex_format(cc_info.simplex_,
true) <<
" is one of its faces ("
465 << simplex_format(cc_info.trigger_,
true) <<
"), hence it is is deleted.";
468 ofs <<
" <li> Insert_simplex called on " << simplex_format(cc_info.simplex_,
true);
475 if (cc_info.status_ == CC_detail_info::Result_type::self) {
476 ofs <<
" <p><span style=\"color:blue\">The simplex " << simplex_format(cc_info.simplex_,
true)
477 <<
" already exists in the cell complex!</span></p>\n";
479 if (cc_info.status_ == CC_detail_info::Result_type::face) {
480 ofs <<
" <p><span style=\"color:red\">The simplex " << simplex_format(cc_info.simplex_,
true)
481 <<
" is a face of the simplex " << simplex_format(cc_info.trigger_,
true) <<
"!</span><br>\n";
483 for (
const std::string post_face : cc_info.post_faces_)
484 ofs <<
" <li id=\"" << id_from_simplex(
"B" + post_face) <<
"\">Post deleting "
485 << simplex_format(post_face,
true) <<
"</li>\n";
488 ofs <<
" <p id=\"" << id_from_simplex(cc_info.trigger_) <<
"\">Deleting "
489 << simplex_format(cc_info.trigger_,
true) <<
"</p>\n";
496 if (cc_info.status_ == CC_detail_info::Result_type::coface) {
497 ofs <<
" <p><span style=\"color:darkorange\">The simplex "
498 << simplex_format(cc_info.simplex_,
true) <<
" is a coface of the simplex "
499 << simplex_format(cc_info.trigger_,
true) <<
"!</span><p>\n";
501 if (cc_info.status_ == CC_detail_info::Result_type::inserted) {
502 ofs <<
" <p><span style=\"color:green\">Successfully inserted "
503 << simplex_format(cc_info.simplex_,
true) <<
"!</span><p>\n";
512void write_visu(std::ofstream& ofs) {
513 ofs <<
" <div id=\"visu\">\n"
514 <<
" <h2> Visualization details debug trace </h2>\n";
516 std::map<std::string, std::string> vs_map;
517 for (
const auto& sv_pair : simplex_vlist_map) vs_map.emplace(sv_pair.second, sv_pair.first);
519 for (
const auto& vs_pair : vs_map) {
520 std::string w_simplex = vs_pair.second.substr(1);
521 bool is_boundary = vs_pair.second[0] ==
'B';
522 ofs <<
" <li><b>" << vs_pair.first <<
"</b>: " << simplex_format(w_simplex, is_boundary) <<
"</li>\n";
528void write_to_html(std::string file_name) {
529 std::ofstream ofs(file_name +
".html", std::ofstream::out);
530 ofs <<
"<!DOCTYPE html>\n"
535 ofs <<
" <h1> Debug traces for " << file_name <<
" </h1>\n";
std::ostream & operator<<(std::ostream &os, const Permutahedral_representation< Vertex, OrderedSetPartition > &simplex)
Print a permutahedral representation to a stream.
Definition: Permutahedral_representation.h:173