Initial Codeberg Pages publish: Doxygen HTML for v0.9.x main

This commit is contained in:
Tarik Moussa
2026-05-23 23:22:46 +02:00
commit 1e82af86ca
83 changed files with 8040 additions and 0 deletions

3
README.txt Normal file
View File

@@ -0,0 +1,3 @@
conformallab++ — Doxygen HTML API documentation
Generated from the v0.9.x main branch. Source: https://codeberg.org/TMoussa/ConformalLabpp

61
clipboard.js Normal file
View File

@@ -0,0 +1,61 @@
/**
The code below is based on the Doxygen Awesome project, see
https://github.com/jothepro/doxygen-awesome-css
MIT License
Copyright (c) 2021 - 2022 jothepro
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
let clipboard_title = "Copy to clipboard"
let clipboard_icon = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24"><path fill="#888" d="M16 1H4c-1.1 0-2 .9-2 2v14h2V3h12V1zm3 4H8c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h11c1.1 0 2-.9 2-2V7c0-1.1-.9-2-2-2zm0 16H8V7h11v14z"/></svg>`
let clipboard_successIcon = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24"><path d="M9 16.17L4.83 12l-1.42 1.41L9 19 21 7l-1.41-1.41L9 16.17z"/></svg>`
let clipboard_successDuration = 1000
document.addEventListener('DOMContentLoaded', function() {
if(navigator.clipboard) {
const fragments = document.getElementsByClassName("fragment")
for(const fragment of fragments) {
const clipboard_div = document.createElement("div")
clipboard_div.classList.add("clipboard")
clipboard_div.innerHTML = clipboard_icon
clipboard_div.title = clipboard_title
clipboard_div.addEventListener('click', function() {
const content = this.parentNode.cloneNode(true)
// filter out line number and folded fragments from file listings
content.querySelectorAll(".lineno, .ttc, .foldclosed").forEach((node) => { node.remove() })
let text = content.textContent
// remove trailing newlines and trailing spaces from empty lines
text = text.replace(/^\s*\n/gm,'\n').replace(/\n*$/,'')
navigator.clipboard.writeText(text);
this.classList.add("success")
this.innerHTML = clipboard_successIcon
window.setTimeout(() => { // switch back to normal icon after timeout
this.classList.remove("success")
this.innerHTML = clipboard_icon
}, clipboard_successDuration);
})
fragment.insertBefore(clipboard_div, fragment.firstChild)
}
}
})

143
codefolding.js Normal file
View File

@@ -0,0 +1,143 @@
/*
@licstart The following is the entire license notice for the JavaScript code in this file.
The MIT License (MIT)
Copyright (C) 1997-2026 by Dimitri van Heesch
Permission is hereby granted, free of charge, to any person obtaining a copy of this software
and associated documentation files (the "Software"), to deal in the Software without restriction,
including without limitation the rights to use, copy, modify, merge, publish, distribute,
sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or
substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@licend The above is the entire license notice for the JavaScript code in this file
*/
let codefold = {
opened : true,
show_plus : function(el) {
if (el) {
el.classList.remove('minus');
el.classList.add('plus');
}
},
show_minus : function(el) {
if (el) {
el.classList.add('minus');
el.classList.remove('plus');
}
},
// toggle all folding blocks
toggle_all : function() {
if (this.opened) {
const foldAll = document.getElementById('fold_all');
this.show_plus(foldAll);
document.querySelectorAll('div[id^=foldopen]').forEach(el => el.style.display = 'none');
document.querySelectorAll('div[id^=foldclosed]').forEach(el => el.style.display = '');
document.querySelectorAll('div[id^=foldclosed] span.fold').forEach(el => this.show_plus(el));
} else {
const foldAll = document.getElementById('fold_all');
this.show_minus(foldAll);
document.querySelectorAll('div[id^=foldopen]').forEach(el => el.style.display = '');
document.querySelectorAll('div[id^=foldclosed]').forEach(el => el.style.display = 'none');
}
this.opened=!this.opened;
},
// toggle single folding block
toggle : function(id) {
const openEl = document.getElementById('foldopen'+id);
const closedEl = document.getElementById('foldclosed'+id);
if (openEl) {
openEl.style.display = openEl.style.display === 'none' ? '' : 'none';
const nextEl = openEl.nextElementSibling;
if (nextEl) {
nextEl.querySelectorAll('span.fold').forEach(el => this.show_plus(el));
}
}
if (closedEl) {
closedEl.style.display = closedEl.style.display === 'none' ? '' : 'none';
}
},
init : function() {
// add code folding line and global control
document.querySelectorAll('span.lineno').forEach((el, index) => {
el.style.paddingRight = '4px';
el.style.marginRight = '2px';
el.style.display = 'inline-block';
el.style.width = '54px';
el.style.background = 'linear-gradient(#808080,#808080) no-repeat 46px/2px 100%';
const span = document.createElement('span');
if (index === 0) { // add global toggle to first line
span.className = 'fold minus';
span.id = 'fold_all';
span.onclick = () => codefold.toggle_all();
} else { // add vertical lines to other rows
span.className = 'fold'
}
el.appendChild(span);
});
// add toggle controls to lines with fold divs
document.querySelectorAll('div.foldopen').forEach(el => {
// extract specific id to use
const id = el.getAttribute('id').replace('foldopen','');
// extract start and end foldable fragment attributes
const start = el.getAttribute('data-start');
const end = el.getAttribute('data-end');
// replace normal fold span with controls for the first line of a foldable fragment
const firstFold = el.querySelector('span.fold');
if (firstFold) {
const span = document.createElement('span');
span.className = 'fold minus';
span.onclick = () => codefold.toggle(id);
firstFold.replaceWith(span);
}
// append div for folded (closed) representation
const closedDiv = document.createElement('div');
closedDiv.id = 'foldclosed'+id;
closedDiv.className = 'foldclosed';
closedDiv.style.display = 'none';
el.after(closedDiv);
// extract the first line from the "open" section to represent closed content
const line = el.children[0] ? el.children[0].cloneNode(true) : null;
if (line) {
// remove any glow that might still be active on the original line
line.classList.remove('glow');
if (start) {
// if line already ends with a start marker (e.g. trailing {), remove it
line.innerHTML = line.innerHTML.replace(new RegExp('\\s*'+start+'\\s*$','g'),'');
}
// replace minus with plus symbol
line.querySelectorAll('span.fold').forEach(span => {
codefold.show_plus(span);
// re-apply click handler as it is not copied with cloneNode
span.onclick = () => codefold.toggle(id);
});
// append ellipsis
const ellipsisLink = document.createElement('a');
ellipsisLink.href = "javascript:codefold.toggle('"+id+"')";
ellipsisLink.innerHTML = '&#8230;';
line.appendChild(document.createTextNode(' '+start));
line.appendChild(ellipsisLink);
line.appendChild(document.createTextNode(end));
// insert constructed line into closed div
closedDiv.appendChild(line);
}
});
},
};
/* @license-end */

58
cookie.js Normal file
View File

@@ -0,0 +1,58 @@
/*!
Cookie helper functions
Copyright (c) 2023 Dimitri van Heesch
Released under MIT license.
*/
let Cookie = {
cookie_namespace: 'doxygen_',
readSetting(cookie,defVal) {
if (window.chrome) {
const val = localStorage.getItem(this.cookie_namespace+cookie) ||
sessionStorage.getItem(this.cookie_namespace+cookie);
if (val) return val;
} else {
let myCookie = this.cookie_namespace+cookie+"=";
if (document.cookie) {
const index = document.cookie.indexOf(myCookie);
if (index != -1) {
const valStart = index + myCookie.length;
let valEnd = document.cookie.indexOf(";", valStart);
if (valEnd == -1) {
valEnd = document.cookie.length;
}
return document.cookie.substring(valStart, valEnd);
}
}
}
return defVal;
},
writeSetting(cookie,val,days=10*365) { // default days='forever', 0=session cookie, -1=delete
if (window.chrome) {
if (days==0) {
sessionStorage.setItem(this.cookie_namespace+cookie,val);
} else {
localStorage.setItem(this.cookie_namespace+cookie,val);
}
} else {
let date = new Date();
date.setTime(date.getTime()+(days*24*60*60*1000));
const expiration = days!=0 ? "expires="+date.toGMTString()+";" : "";
document.cookie = this.cookie_namespace + cookie + "=" +
val + "; SameSite=Lax;" + expiration + "path=/";
}
},
eraseSetting(cookie) {
if (window.chrome) {
if (localStorage.getItem(this.cookie_namespace+cookie)) {
localStorage.removeItem(this.cookie_namespace+cookie);
} else if (sessionStorage.getItem(this.cookie_namespace+cookie)) {
sessionStorage.removeItem(this.cookie_namespace+cookie);
}
} else {
this.writeSetting(cookie,'',-1);
}
},
}

2170
doxygen.css Normal file

File diff suppressed because it is too large Load Diff

28
doxygen.svg Normal file

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 15 KiB

55
doxygen_crawl.html Normal file
View File

@@ -0,0 +1,55 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" lang="en-US">
<head>
<title>Validator / crawler helper</title>
<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
<meta http-equiv="X-UA-Compatible" content="IE=11"/>
<meta name="generator" content="Doxygen 1.17.0"/>
<meta name="viewport" content="width=device-width, initial-scale=1"/>
</head>
<body>
<a href="doxygen_crawl.html"/>
<a href="index.html"/>
<a href="index.html#autotoc_md10"/>
<a href="index.html#autotoc_md12"/>
<a href="index.html#autotoc_md2"/>
<a href="index.html#autotoc_md4"/>
<a href="index.html#autotoc_md6"/>
<a href="index.html#autotoc_md8"/>
<a href="md__c_l_a_u_d_e.html"/>
<a href="md__c_l_a_u_d_e.html#autotoc_md14"/>
<a href="md__c_l_a_u_d_e.html#autotoc_md15"/>
<a href="md__c_l_a_u_d_e.html#autotoc_md16"/>
<a href="md__c_l_a_u_d_e.html#autotoc_md17"/>
<a href="md__c_l_a_u_d_e.html#autotoc_md18"/>
<a href="md__c_l_a_u_d_e.html#autotoc_md19"/>
<a href="md__c_l_a_u_d_e.html#autotoc_md20"/>
<a href="md__c_l_a_u_d_e.html#autotoc_md21"/>
<a href="md__c_l_a_u_d_e.html#autotoc_md22"/>
<a href="md__c_l_a_u_d_e.html#autotoc_md23"/>
<a href="md__c_l_a_u_d_e.html#autotoc_md24"/>
<a href="md__c_l_a_u_d_e.html#autotoc_md25"/>
<a href="md__c_l_a_u_d_e.html#autotoc_md26"/>
<a href="md__c_l_a_u_d_e.html#autotoc_md27"/>
<a href="md__c_l_a_u_d_e.html#autotoc_md28"/>
<a href="md__c_l_a_u_d_e.html#autotoc_md29"/>
<a href="md__c_l_a_u_d_e.html#autotoc_md30"/>
<a href="md__c_l_a_u_d_e.html#autotoc_md31"/>
<a href="md__c_l_a_u_d_e.html#autotoc_md32"/>
<a href="md__c_l_a_u_d_e.html#autotoc_md33"/>
<a href="md__c_l_a_u_d_e.html#autotoc_md34"/>
<a href="md__c_l_a_u_d_e.html#autotoc_md35"/>
<a href="md__c_l_a_u_d_e.html#autotoc_md36"/>
<a href="md__c_l_a_u_d_e.html#autotoc_md37"/>
<a href="md__c_l_a_u_d_e.html#autotoc_md38"/>
<a href="md__c_l_a_u_d_e.html#autotoc_md39"/>
<a href="md__c_l_a_u_d_e.html#autotoc_md40"/>
<a href="md__c_l_a_u_d_e.html#autotoc_md41"/>
<a href="md__c_l_a_u_d_e.html#autotoc_md42"/>
<a href="md__c_l_a_u_d_e.html#autotoc_md43"/>
<a href="md__c_l_a_u_d_e.html#autotoc_md44"/>
<a href="md__c_l_a_u_d_e.html#autotoc_md45"/>
<a href="md__c_l_a_u_d_e.html#autotoc_md46"/>
<a href="pages.html"/>
</body>
</html>

317
dynsections.js Normal file
View File

@@ -0,0 +1,317 @@
/*
@licstart The following is the entire license notice for the JavaScript code in this file.
The MIT License (MIT)
Copyright (C) 1997-2026 by Dimitri van Heesch
Permission is hereby granted, free of charge, to any person obtaining a copy of this software
and associated documentation files (the "Software"), to deal in the Software without restriction,
including without limitation the rights to use, copy, modify, merge, publish, distribute,
sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or
substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@licend The above is the entire license notice for the JavaScript code in this file
*/
function toggleVisibility(linkObj) {
return dynsection.toggleVisibility(linkObj);
}
let dynsection = {
// helper function
updateStripes : function() {
const rows = document.querySelectorAll('table.directory tr');
rows.forEach(row => {
row.classList.remove('even', 'odd');
});
const visibleRows = Array.from(rows).filter(row => {
return row.offsetParent !== null; // checks if element is visible
});
visibleRows.forEach((row, index) => {
if (index % 2 === 0) {
row.classList.add('even');
} else {
row.classList.add('odd');
}
});
},
slide : function(element, fromHeight, toHeight, duration=200) {
element.style.overflow = 'hidden';
element.style.transition = `height ${duration}ms ease-out`;
element.style.height = fromHeight;
setTimeout(() => {
element.style.height = toHeight;
setTimeout(() => {
element.style.height = '';
element.style.transition = '';
element.style.overflow = '';
if (toHeight === '0px') {
element.style.display = 'none';
}
}, duration);
}, 0);
},
toggleVisibility : function(linkObj) {
const base = linkObj.getAttribute('id');
const summary = document.getElementById(base+'-summary');
const content = document.getElementById(base+'-content');
const trigger = document.getElementById(base+'-trigger');
const src = trigger ? trigger.getAttribute('src') : null;
if (content.offsetParent !== null) { // checks if element is visible
const height = content.offsetHeight;
this.slide(content, height + 'px', '0px');
if (summary) summary.style.display = '';
linkObj.querySelectorAll('.arrowhead').forEach(el => {
el.classList.add('closed');
el.classList.remove('opened');
});
} else {
// slideDown animation
const height = content.scrollHeight;
if (height==0) { // height unknown -> show immediately
content.style.display = 'block';
} else {
this.slide(content, '0px', height + 'px');
}
if (summary) summary.style.display = 'none';
linkObj.querySelectorAll('.arrowhead').forEach(el => {
el.classList.remove('closed');
el.classList.add('opened');
});
}
return false;
},
toggleLevel : function(level) {
document.querySelectorAll('table.directory tr').forEach(function(row) {
const l = row.id.split('_').length-1;
const i = document.getElementById('img'+row.id.substring(3));
const a = document.getElementById('arr'+row.id.substring(3));
if (l<level+1) {
if (i) i.querySelectorAll('.folder-icon').forEach(el => el.classList.add('open'));
if (a) {
a.querySelectorAll('.arrowhead').forEach(el => {
el.classList.remove('closed');
el.classList.add('opened');
});
}
row.style.display = '';
} else if (l==level+1) {
if (a) {
a.querySelectorAll('.arrowhead').forEach(el => {
el.classList.remove('opened');
el.classList.add('closed');
});
}
if (i) i.querySelectorAll('.folder-icon').forEach(el => el.classList.remove('open'));
row.style.display = '';
} else {
row.style.display = 'none';
}
});
this.updateStripes();
},
toggleFolder : function(id) {
// the clicked row
const currentRow = document.getElementById('row_'+id);
if (!currentRow) return;
// all rows after the clicked row
const rows = [];
let nextRow = currentRow.nextElementSibling;
while (nextRow && nextRow.tagName === 'TR') {
rows.push(nextRow);
nextRow = nextRow.nextElementSibling;
}
const re = new RegExp('^row_'+id+'\\d+_$', "i"); //only one sub
// only match elements AFTER this one (can't hide elements before)
const childRows = rows.filter(function(row) { return row.id.match(re); });
if (childRows.length === 0) return;
function replaceClass(el,fromClass,toClass) {
if (el.classList.contains(fromClass)) {
el.classList.remove(fromClass);
el.classList.add(toClass);
}
}
// first row is visible we are HIDING
if (childRows[0].offsetParent !== null) { // checks if element is visible
// replace down arrow by right arrow for current row
const currentRowSpans = currentRow.querySelectorAll("span");
currentRowSpans.forEach(span => {
if (span.classList.contains('iconfolder')) {
span.querySelectorAll('.folder-icon').forEach(el => el.classList.remove("open"));
}
replaceClass(span,'opened','closed');
});
rows.forEach(row => {
if (row.id.startsWith('row_'+id)) {
row.style.display = 'none'; // hide all children
}
});
} else { // we are SHOWING
// replace right arrow by down arrow for current row
const currentRowSpans = currentRow.querySelectorAll("span");
currentRowSpans.forEach(span => {
if (span.classList.contains('iconfolder')) {
span.querySelectorAll('.folder-icon').forEach(el => el.classList.add("open"));
}
replaceClass(span,'closed','opened');
});
// replace down arrows by right arrows for child rows
childRows.forEach(row => {
const childRowSpans = row.querySelectorAll("span");
childRowSpans.forEach(span => {
if (span.classList.contains('iconfolder')) {
span.querySelectorAll('.folder-icon').forEach(el => el.classList.remove("open"));
}
replaceClass(span,'opened','closed');
});
row.style.display = ''; //show all children
});
}
this.updateStripes();
},
toggleInherit : function(id) {
const rows = document.querySelectorAll('tr.inherit.'+id);
const header = document.querySelector('tr.inherit_header.'+id);
if (rows.length > 0 && rows[0].offsetParent !== null) { // checks if element is visible
rows.forEach(row => row.style.display = 'none');
if (header) {
header.querySelectorAll('.arrowhead').forEach(el => {
el.classList.add('closed');
el.classList.remove('opened');
});
}
} else {
rows.forEach(row => row.style.display = 'table-row');
if (header) {
header.querySelectorAll('.arrowhead').forEach(el => {
el.classList.remove('closed');
el.classList.add('opened');
});
}
}
},
};
/* @license-end */
/*
@licstart The following is the entire license notice for the JavaScript code in this file.
The MIT License (MIT)
Copyright (C) 1997-2026 by Dimitri van Heesch
Permission is hereby granted, free of charge, to any person obtaining a copy of this software
and associated documentation files (the "Software"), to deal in the Software without restriction,
including without limitation the rights to use, copy, modify, merge, publish, distribute,
sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or
substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@licend The above is the entire license notice for the JavaScript code in this file
*/
// Simple tooltip implementation
document.addEventListener('DOMContentLoaded', function() {
// Create hidden tooltip container
const tooltip = document.createElement('div');
tooltip.id = 'powerTip';
tooltip.style.position = 'absolute';
tooltip.style.display = 'none';
tooltip.style.zIndex = '9999';
document.body.appendChild(tooltip);
let currentElement = null;
let hideTimeout = null;
function showTooltip(element, content) {
clearTimeout(hideTimeout);
currentElement = element;
// Materialize tooltip so we can compute its size
tooltip.innerHTML = content;
tooltip.style.display = 'block';
// Compute the position of the tooltip with respect to the source
const sourceRect = element.getBoundingClientRect();
const tooltipRect = tooltip.getBoundingClientRect();
// Ideal position
let left = sourceRect.left + (sourceRect.width - tooltipRect.width) / 2;
let top = sourceRect.bottom;
// Check if tooltip goes off screen
const margin = 10;
if (left < margin) left = margin;
if (left + tooltipRect.width + margin > window.innerWidth) {
left = window.innerWidth - tooltipRect.width - margin;
}
// If tooltip would go below viewport, show above element instead
if (top + tooltipRect.height > window.innerHeight) {
top = sourceRect.top - tooltipRect.height;
}
// Set computed position
tooltip.style.left = left + window.scrollX + 'px';
tooltip.style.top = top + window.scrollY + 'px';
}
function hideTooltip() {
hideTimeout = setTimeout(() => {
tooltip.style.display = 'none';
currentElement = null;
}, 100);
}
// Add hover listeners to code elements
document.querySelectorAll('.code,.codeRef').forEach(sourceElement => {
const href = sourceElement.getAttribute('href');
if (!href) return;
// Get tooltip content from data attribute or related sourceElement
const targetId = 'a' + href.replace(/.*\//, '').replace(/[^a-z_A-Z0-9]/g, '_');
const targetElement = document.getElementById(targetId);
const targetContent = targetElement ? targetElement.innerHTML : null;
if (targetContent) {
sourceElement.addEventListener('mouseenter', () => showTooltip(sourceElement, targetContent));
sourceElement.addEventListener('mouseleave', () => hideTooltip());
sourceElement.addEventListener('focus', () => showTooltip(sourceElement, targetContent));
sourceElement.addEventListener('blur', () => hideTooltip());
}
});
// Allow mouse to enter tooltip without hiding it
tooltip.addEventListener('mouseenter', () => clearTimeout(hideTimeout));
tooltip.addEventListener('mouseleave', () => hideTooltip());
});
/* @license-end */

273
index.html Normal file
View File

@@ -0,0 +1,273 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" lang="en-US">
<head>
<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
<meta http-equiv="X-UA-Compatible" content="IE=11"/>
<meta name="generator" content="Doxygen 1.17.0"/>
<meta name="viewport" content="width=device-width, initial-scale=1"/>
<title>conformallab++: conformallab++</title>
<link href="tabs.css" rel="stylesheet" type="text/css"/>
<script type="text/javascript" src="dynsections.js"></script>
<script type="text/javascript" src="codefolding.js"></script>
<script type="text/javascript" src="clipboard.js"></script>
<link href="navtree.css" rel="stylesheet" type="text/css"/>
<script type="text/javascript" src="navtreedata.js"></script>
<script type="text/javascript" src="navtree.js"></script>
<script type="text/javascript" src="cookie.js"></script>
<link href="search/search.css" rel="stylesheet" type="text/css"/>
<script type="text/javascript" src="search/searchdata.js"></script>
<script type="text/javascript" src="search/search.js"></script>
<script type="module">
import mermaid from 'https://cdn.jsdelivr.net/npm/mermaid@11/dist/mermaid.esm.min.mjs';
const theme = 'default';
mermaid.initialize({ startOnLoad: true, theme: theme });
</script>
<link href="doxygen.css" rel="stylesheet" type="text/css" />
</head>
<body>
<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
<div id="titlearea">
<table cellspacing="0" cellpadding="0">
<tbody>
<tr id="projectrow">
<td id="projectalign">
<div id="projectname">conformallab++<span id="projectnumber">&#160;0.7.0</span>
</div>
<div id="projectbrief">Discrete conformal maps on triangle meshes — C++17 reimplementation of ConformalLab (TU Berlin)</div>
</td>
</tr>
</tbody>
</table>
</div>
<!-- end header part -->
<!-- Generated by Doxygen 1.17.0 -->
<script type="text/javascript">
let searchBox = new SearchBox("searchBox", "search/",'.html');
</script>
<script type="text/javascript">
document.addEventListener('DOMContentLoaded', codefold.init);
</script>
<script type="text/javascript" src="menudata.js"></script>
<script type="text/javascript" src="menu.js"></script>
<script type="text/javascript">
document.addEventListener('DOMContentLoaded', () => {
initMenu('',true);
init_search();
});
</script>
<div id="main-nav-mobile">
<div class="sm sm-dox"><input id="main-menu-state" type="checkbox"/>
<label class="main-menu-btn" for="main-menu-state">
<span class="main-menu-btn-icon"></span> Toggle main menu visibility</label>
<span id="searchBoxPos1" style="position:absolute;right:8px;top:8px;height:36px;"></span>
</div>
</div><!-- main-nav-mobile -->
<div id="main-nav">
<ul class="sm sm-dox" id="main-menu">
<li id="searchBoxPos2" style="float:right">
<div id="MSearchBox" class="MSearchBoxInactive">
<span class="left">
<span id="MSearchSelect" class="search-icon" onmouseover="return searchBox.OnSearchSelectShow()" onmouseout="return searchBox.OnSearchSelectHide()"><span class="search-icon-dropdown"></span></span>
<input type="text" id="MSearchField" value="" placeholder="Search" accesskey="S"
onfocus="searchBox.OnSearchFieldFocus(true)"
onblur="searchBox.OnSearchFieldFocus(false)"
onkeyup="searchBox.OnSearchFieldChange(event)"/>
</span><span class="right">
<a id="MSearchClose" href="javascript:searchBox.CloseResultsWindow()"><div id="MSearchCloseImg" class="close-icon"></div></a>
</span>
</div>
</li>
</ul>
</div><!-- main-nav -->
</div><!-- top -->
<div id="side-nav" class="ui-resizable side-nav-resizable">
<div id="nav-tree">
<div id="nav-tree-contents">
<div id="nav-sync" class="sync"></div>
</div>
</div>
<div id="splitbar" style="-moz-user-select:none;"
class="ui-resizable-handle">
</div>
</div>
<script type="text/javascript">
document.addEventListener('DOMContentLoaded',() => { initNavTree('index.html','',''); });
</script>
<div id="container">
<div id="doc-content">
<!-- window showing the filter options -->
<div id="MSearchSelectWindow"
onmouseover="return searchBox.OnSearchSelectShow()"
onmouseout="return searchBox.OnSearchSelectHide()"
onkeydown="return searchBox.OnSearchSelectKey(event)">
</div>
<!-- iframe showing the search results (closed by default) -->
<div id="MSearchResultsWindow">
<div id="MSearchResults">
<div class="SRPage">
<div id="SRIndex">
<div id="SRResults"></div>
<div class="SRStatus" id="Loading">Loading...</div>
<div class="SRStatus" id="Searching">Searching...</div>
<div class="SRStatus" id="NoMatches">No Matches</div>
</div>
</div>
</div>
</div>
<div><div class="header">
<div class="headertitle"><div class="title">conformallab++ </div></div>
</div><!--header-->
<div class="contents">
<div class="textblock"><p><a class="anchor" id="md__r_e_a_d_m_e"></a></p>
<p><a href="https://git.eulernest.eu/conformallab/ConformalLabpp/actions"><img src="https://git.eulernest.eu/conformallab/ConformalLabpp/actions/workflows/cpp-tests.yml/badge.svg" alt="CI" style="pointer-events: none;" class="inline"/></a> [<img src="https://img.shields.io/badge/License-MIT-yellow.svg" alt="License: MIT" style="pointer-events: none;" class="inline"/>](LICENSE) <a href="https://depositonce.tu-berlin.de/items/8e2988b2-d991-45b5-aad5-9fb7988f3b2f"><img src="https://img.shields.io/badge/doi-Sechelmann%202016-blue" alt="DOI" class="inline"/></a></p>
<p>C++17 reimplementation of <a href="https://github.com/varylab/conformallab">ConformalLab</a> — Stefan Sechelmann's Java research library for discrete conformal geometry (TU Berlin). The long-term goal is a <b>CGAL package</b> for discrete conformal maps.</p>
<p>Algorithmic foundation: </p><blockquote class="doxtable">
<p>Stefan Sechelmann — <em>Variational Methods for Discrete Surface Parameterization: Applications and Implementation</em>, TU Berlin 2016. DOI: <a href="https://depositonce.tu-berlin.de/items/8e2988b2-d991-45b5-aad5-9fb7988f3b2f">10.14279/depositonce-5415</a> · CC BY-SA 4.0 · <a href="https://github.com/varylab/conformallab">Java original</a> · <a href="https://sechel.de/">sechel.de</a> </p>
</blockquote>
<p><b>Status:</b> v0.9.0 — Phases 19a complete, Phase 8b-Lite CGAL API surface. Newton solvers for <b>five</b> DCE models (Euclidean / Spherical / HyperIdeal / CP-Euclidean / Inversive-Distance), priority-BFS layout in ℝ²/S²/Poincaré disk, GaussBonnet, tree-cotree cut graph, Möbius holonomy, period matrix (genus 1), fundamental domain, halfedge_uv texture atlas, JSON/XML serialisation, CLI app. Full test suite passing, 0 skipped — see <a href="doc/api/tests.md"><span class="tt">doc/api/tests.md</span></a> for the per-suite breakdown.</p>
<hr />
<h1 class="doxsection"><a class="anchor" id="autotoc_md2"></a>
Quick start</h1>
<div class="fragment"><div class="line">git clone https://codeberg.org/TMoussa/ConformalLabpp &amp;&amp; cd ConformalLabpp</div>
<div class="line"> </div>
<div class="line"># Fast tests — no system dependencies</div>
<div class="line">cmake -S code -B build &amp;&amp; cmake --build build --target conformallab_tests -j$(nproc)</div>
<div class="line">ctest --test-dir build --output-on-failure</div>
<div class="line"> </div>
<div class="line"># CGAL tests headless (apt install libboost-dev / brew install boost)</div>
<div class="line">cmake -S code -B build -DWITH_CGAL_TESTS=ON</div>
<div class="line">cmake --build build --target conformallab_cgal_tests -j$(nproc)</div>
<div class="line">ctest --test-dir build -R &quot;^cgal\.&quot; --output-on-failure</div>
<div class="line"> </div>
<div class="line"># Full build with CLI + viewer (requires Wayland/X11 dev headers)</div>
<div class="line">cmake -S code -B build -DWITH_CGAL=ON &amp;&amp; cmake --build build -j$(nproc)</div>
<div class="line">./bin/conformallab_core -i input.off -g euclidean -o layout.off -j result.json</div>
<div class="line"> </div>
<div class="line"># API documentation (requires doxygen: brew/apt install doxygen)</div>
<div class="line">cmake --build build --target doc</div>
<div class="line">open doc/doxygen/html/index.html</div>
</div><!-- fragment --><hr />
<h1 class="doxsection"><a class="anchor" id="autotoc_md4"></a>
Minimal usage</h1>
<div class="fragment"><div class="line"><span class="preprocessor">#include &quot;conformal_mesh.hpp&quot;</span></div>
<div class="line"><span class="preprocessor">#include &quot;mesh_io.hpp&quot;</span></div>
<div class="line"><span class="preprocessor">#include &quot;euclidean_functional.hpp&quot;</span></div>
<div class="line"><span class="preprocessor">#include &quot;gauss_bonnet.hpp&quot;</span></div>
<div class="line"><span class="preprocessor">#include &quot;newton_solver.hpp&quot;</span></div>
<div class="line"><span class="preprocessor">#include &quot;layout.hpp&quot;</span></div>
<div class="line"> </div>
<div class="line"><span class="keyword">using namespace </span>conformallab;</div>
<div class="line"> </div>
<div class="line">ConformalMesh mesh = load_mesh(<span class="stringliteral">&quot;input.off&quot;</span>);</div>
<div class="line">EuclideanMaps maps = setup_euclidean_maps(mesh);</div>
<div class="line">compute_euclidean_lambda0_from_mesh(mesh, maps);</div>
<div class="line"> </div>
<div class="line"><span class="comment">// Assign DOFs — pin first vertex (gauge fix)</span></div>
<div class="line"><span class="keyword">auto</span> vit = mesh.vertices().begin();</div>
<div class="line">maps.v_idx[*vit++] = -1;</div>
<div class="line"><span class="keywordtype">int</span> idx = 0;</div>
<div class="line"><span class="keywordflow">for</span> (; vit != mesh.vertices().end(); ++vit) maps.v_idx[*vit] = idx++;</div>
<div class="line"> </div>
<div class="line"><span class="comment">// Natural equilibrium target: x* = 0 by construction</span></div>
<div class="line">std::vector&lt;double&gt; x0(idx, 0.0);</div>
<div class="line"><span class="keyword">auto</span> G0 = euclidean_gradient(mesh, x0, maps);</div>
<div class="line"><span class="keywordflow">for</span> (<span class="keyword">auto</span> v : mesh.vertices())</div>
<div class="line"> <span class="keywordflow">if</span> (maps.v_idx[v] &gt;= 0) maps.theta_v[v] -= G0[maps.v_idx[v]];</div>
<div class="line"> </div>
<div class="line">check_gauss_bonnet(mesh, maps);</div>
<div class="line">NewtonResult res = newton_euclidean(mesh, x0, maps);</div>
<div class="line">Layout2D layout = euclidean_layout(mesh, res.x, maps);</div>
</div><!-- fragment --><hr />
<h1 class="doxsection"><a class="anchor" id="autotoc_md6"></a>
Documentation</h1>
<table class="markdownTable">
<tr class="markdownTableHead">
<th class="markdownTableHeadNone"></th><th class="markdownTableHeadNone"></th></tr>
<tr class="markdownTableRowOdd">
<td class="markdownTableBodyNone"><b>Getting started</b> — build modes, single-test invocation, CLI, Docker </td><td class="markdownTableBodyNone"><a href="doc/getting-started.md">doc/getting-started.md</a> </td></tr>
<tr class="markdownTableRowEven">
<td class="markdownTableBodyNone"><b>Pipeline API</b> — all three geometries, holonomy, serialisation </td><td class="markdownTableBodyNone"><a href="doc/api/pipeline.md">doc/api/pipeline.md</a> </td></tr>
<tr class="markdownTableRowOdd">
<td class="markdownTableBodyNone"><b>Public headers</b> — all public headers with descriptions </td><td class="markdownTableBodyNone"><a href="doc/api/headers.md">doc/api/headers.md</a> </td></tr>
<tr class="markdownTableRowEven">
<td class="markdownTableBodyNone"><b>Test suites</b> — per-suite breakdown and counts (single source of truth) </td><td class="markdownTableBodyNone"><a href="doc/api/tests.md">doc/api/tests.md</a> </td></tr>
<tr class="markdownTableRowOdd">
<td class="markdownTableBodyNone"><b>Extending</b> — new functionals, geometry modes, porting from Java </td><td class="markdownTableBodyNone"><a href="doc/api/extending.md">doc/api/extending.md</a> </td></tr>
<tr class="markdownTableRowEven">
<td class="markdownTableBodyNone"><b>Processing unit contracts</b> — preconditions / provides table </td><td class="markdownTableBodyNone"><a href="doc/api/contracts.md">doc/api/contracts.md</a> </td></tr>
<tr class="markdownTableRowOdd">
<td class="markdownTableBodyNone"><b>CGAL package design</b> — Phase 8 target, YAML pipeline </td><td class="markdownTableBodyNone"><a href="doc/api/cgal-package.md">doc/api/cgal-package.md</a> </td></tr>
<tr class="markdownTableRowEven">
<td class="markdownTableBodyNone"><b>Architecture &amp; pipeline diagram</b> </td><td class="markdownTableBodyNone"><a href="doc/architecture/overall_pipeline.md">doc/architecture/overall_pipeline.md</a> </td></tr>
<tr class="markdownTableRowOdd">
<td class="markdownTableBodyNone"><b>geometry-central comparison</b> — shared core, demarcation, adoption candidates, scientific added value </td><td class="markdownTableBodyNone"><a href="doc/architecture/geometry-central-comparison.md">doc/architecture/geometry-central-comparison.md</a> </td></tr>
<tr class="markdownTableRowEven">
<td class="markdownTableBodyNone"><b>Design decisions</b> — key architectural choices + rationale </td><td class="markdownTableBodyNone"><a href="doc/architecture/design-decisions.md">doc/architecture/design-decisions.md</a> </td></tr>
<tr class="markdownTableRowOdd">
<td class="markdownTableBodyNone"><b>Project structure</b> — directory tree + build targets </td><td class="markdownTableBodyNone"><a href="doc/architecture/project-structure.md">doc/architecture/project-structure.md</a> </td></tr>
<tr class="markdownTableRowEven">
<td class="markdownTableBodyNone"><b>Discrete conformal theory</b> — mathematical background for collaborators </td><td class="markdownTableBodyNone"><a href="doc/math/discrete-conformal-theory.md">doc/math/discrete-conformal-theory.md</a> </td></tr>
<tr class="markdownTableRowOdd">
<td class="markdownTableBodyNone"><b>Validation</b> — known analytic results + how to verify them </td><td class="markdownTableBodyNone"><a href="doc/math/validation.md">doc/math/validation.md</a> </td></tr>
<tr class="markdownTableRowEven">
<td class="markdownTableBodyNone"><b>Validation protocol</b> — concrete commands with expected outputs </td><td class="markdownTableBodyNone"><a href="doc/math/validation-protocol.md">doc/math/validation-protocol.md</a> </td></tr>
<tr class="markdownTableRowOdd">
<td class="markdownTableBodyNone"><b>Tutorial: add a new functional</b> — step-by-step Inversive-Distance port </td><td class="markdownTableBodyNone"><a href="doc/tutorials/add-inversive-distance.md">doc/tutorials/add-inversive-distance.md</a> </td></tr>
<tr class="markdownTableRowEven">
<td class="markdownTableBodyNone"><b>Declarative YAML pipeline</b> — concept, token vocabulary, 5 examples </td><td class="markdownTableBodyNone"><a href="doc/concepts/declarative-pipeline.md">doc/concepts/declarative-pipeline.md</a> </td></tr>
<tr class="markdownTableRowOdd">
<td class="markdownTableBodyNone"><b>Geometry modes</b> — Euclidean / Spherical / HyperIdeal comparison </td><td class="markdownTableBodyNone"><a href="doc/math/geometry-modes.md">doc/math/geometry-modes.md</a> </td></tr>
<tr class="markdownTableRowEven">
<td class="markdownTableBodyNone"><b>References</b> — all papers by module </td><td class="markdownTableBodyNone"><a href="doc/math/references.md">doc/math/references.md</a> </td></tr>
<tr class="markdownTableRowOdd">
<td class="markdownTableBodyNone"><b>Software landscape</b> — how conformallab++ relates to libigl, CGAL, geometry-central </td><td class="markdownTableBodyNone"><a href="doc/math/software-landscape.md">doc/math/software-landscape.md</a> </td></tr>
<tr class="markdownTableRowEven">
<td class="markdownTableBodyNone"><b>Novelty statement</b> — unique features, target audience, what this is not </td><td class="markdownTableBodyNone"><a href="doc/math/novelty-statement.md">doc/math/novelty-statement.md</a> </td></tr>
<tr class="markdownTableRowOdd">
<td class="markdownTableBodyNone"><b>Complexity &amp; scalability</b> — O() analysis, measured timings on real meshes, HyperIdeal bottleneck </td><td class="markdownTableBodyNone"><a href="doc/math/complexity.md">doc/math/complexity.md</a> </td></tr>
<tr class="markdownTableRowEven">
<td class="markdownTableBodyNone"><b>Roadmap</b> — Phases 110 </td><td class="markdownTableBodyNone"><a href="doc/roadmap/phases.md">doc/roadmap/phases.md</a> </td></tr>
<tr class="markdownTableRowOdd">
<td class="markdownTableBodyNone"><b>Java parity table</b> — what is ported, what is planned </td><td class="markdownTableBodyNone"><a href="doc/roadmap/java-parity.md">doc/roadmap/java-parity.md</a> </td></tr>
<tr class="markdownTableRowEven">
<td class="markdownTableBodyNone"><b>Contributing</b> — language policy, test standards, release flow </td><td class="markdownTableBodyNone"><a href="doc/contributing.md">doc/contributing.md</a> </td></tr>
<tr class="markdownTableRowOdd">
<td class="markdownTableBodyNone"><b>Claude Code context</b> </td><td class="markdownTableBodyNone"><a href="CLAUDE.md">CLAUDE.md</a> </td></tr>
</table>
<hr />
<h1 class="doxsection"><a class="anchor" id="autotoc_md8"></a>
Citing</h1>
<p>If you use conformallab++ in your research, please cite it using the metadata in <a href="CITATION.cff"><span class="tt">CITATION.cff</span></a>. GitHub and Codeberg show a "Cite this repository" button that generates BibTeX and APA automatically.</p>
<p>The primary algorithmic source is:</p>
<blockquote class="doxtable">
<p>Stefan Sechelmann — <em>Variational Methods for Discrete Surface Parameterization: Applications and Implementation</em>, TU Berlin 2016. DOI: <a href="https://depositonce.tu-berlin.de/items/8e2988b2-d991-45b5-aad5-9fb7988f3b2f">10.14279/depositonce-5415</a> </p>
</blockquote>
<hr />
<h1 class="doxsection"><a class="anchor" id="autotoc_md10"></a>
Bugs &amp; questions</h1>
<ul>
<li><b>Bug reports / feature requests:</b> <a href="https://git.eulernest.eu/conformallab/ConformalLabpp/issues">Gitea Issues</a></li>
<li><b>Code mirror (read-only):</b> <a href="https://codeberg.org/TMoussa/ConformalLabpp">Codeberg</a></li>
<li><b>Contact:</b> Tarik Moussa · <a href="#" onclick="location.href='mai'+'lto:'+'Tar'+'ik'+'.mo'+'us'+'sa9'+'5@'+'gma'+'il'+'.co'+'m'; return false;">Tarik<span class="obfuscator">.nosp@m.</span>.mou<span class="obfuscator">.nosp@m.</span>ssa95<span class="obfuscator">.nosp@m.</span>@gma<span class="obfuscator">.nosp@m.</span>il.co<span class="obfuscator">.nosp@m.</span>m</a></li>
</ul>
<hr />
<h1 class="doxsection"><a class="anchor" id="autotoc_md12"></a>
License</h1>
<p>conformallab++ is released under the MIT License (see [LICENSE](LICENSE)). <br />
Copyright © 20242026 Tarik Moussa. <br />
The dissertation (Sechelmann 2016) is CC BY-SA 4.0. </p>
</div></div><!-- PageDoc -->
<a href="doxygen_crawl.html"></a>
</div><!-- contents -->
</div><!-- doc-content -->
</div><!-- container -->
<!-- start footer part -->
<div id="nav-path" class="navpath"><!-- id is needed for treeview function! -->
<ul>
<li class="footer">Generated by <a href="https://www.doxygen.org/index.html"><img class="footer" src="doxygen.svg" width="104" height="31" alt="doxygen"/></a> 1.17.0 </li>
</ul>
</div>
</body>
</html>

541
md__c_l_a_u_d_e.html Normal file
View File

@@ -0,0 +1,541 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" lang="en-US">
<head>
<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
<meta http-equiv="X-UA-Compatible" content="IE=11"/>
<meta name="generator" content="Doxygen 1.17.0"/>
<meta name="viewport" content="width=device-width, initial-scale=1"/>
<title>conformallab++: CLAUDE.md</title>
<link href="tabs.css" rel="stylesheet" type="text/css"/>
<script type="text/javascript" src="dynsections.js"></script>
<script type="text/javascript" src="codefolding.js"></script>
<script type="text/javascript" src="clipboard.js"></script>
<link href="navtree.css" rel="stylesheet" type="text/css"/>
<script type="text/javascript" src="navtreedata.js"></script>
<script type="text/javascript" src="navtree.js"></script>
<script type="text/javascript" src="cookie.js"></script>
<link href="search/search.css" rel="stylesheet" type="text/css"/>
<script type="text/javascript" src="search/searchdata.js"></script>
<script type="text/javascript" src="search/search.js"></script>
<script type="module">
import mermaid from 'https://cdn.jsdelivr.net/npm/mermaid@11/dist/mermaid.esm.min.mjs';
const theme = 'default';
mermaid.initialize({ startOnLoad: true, theme: theme });
</script>
<link href="doxygen.css" rel="stylesheet" type="text/css" />
</head>
<body>
<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
<div id="titlearea">
<table cellspacing="0" cellpadding="0">
<tbody>
<tr id="projectrow">
<td id="projectalign">
<div id="projectname">conformallab++<span id="projectnumber">&#160;0.7.0</span>
</div>
<div id="projectbrief">Discrete conformal maps on triangle meshes — C++17 reimplementation of ConformalLab (TU Berlin)</div>
</td>
</tr>
</tbody>
</table>
</div>
<!-- end header part -->
<!-- Generated by Doxygen 1.17.0 -->
<script type="text/javascript">
let searchBox = new SearchBox("searchBox", "search/",'.html');
</script>
<script type="text/javascript">
document.addEventListener('DOMContentLoaded', codefold.init);
</script>
<script type="text/javascript" src="menudata.js"></script>
<script type="text/javascript" src="menu.js"></script>
<script type="text/javascript">
document.addEventListener('DOMContentLoaded', () => {
initMenu('',true);
init_search();
});
</script>
<div id="main-nav-mobile">
<div class="sm sm-dox"><input id="main-menu-state" type="checkbox"/>
<label class="main-menu-btn" for="main-menu-state">
<span class="main-menu-btn-icon"></span> Toggle main menu visibility</label>
<span id="searchBoxPos1" style="position:absolute;right:8px;top:8px;height:36px;"></span>
</div>
</div><!-- main-nav-mobile -->
<div id="main-nav">
<ul class="sm sm-dox" id="main-menu">
<li id="searchBoxPos2" style="float:right">
<div id="MSearchBox" class="MSearchBoxInactive">
<span class="left">
<span id="MSearchSelect" class="search-icon" onmouseover="return searchBox.OnSearchSelectShow()" onmouseout="return searchBox.OnSearchSelectHide()"><span class="search-icon-dropdown"></span></span>
<input type="text" id="MSearchField" value="" placeholder="Search" accesskey="S"
onfocus="searchBox.OnSearchFieldFocus(true)"
onblur="searchBox.OnSearchFieldFocus(false)"
onkeyup="searchBox.OnSearchFieldChange(event)"/>
</span><span class="right">
<a id="MSearchClose" href="javascript:searchBox.CloseResultsWindow()"><div id="MSearchCloseImg" class="close-icon"></div></a>
</span>
</div>
</li>
</ul>
</div><!-- main-nav -->
</div><!-- top -->
<div id="side-nav" class="ui-resizable side-nav-resizable">
<div id="nav-tree">
<div id="nav-tree-contents">
<div id="nav-sync" class="sync"></div>
</div>
</div>
<div id="splitbar" style="-moz-user-select:none;"
class="ui-resizable-handle">
</div>
</div>
<script type="text/javascript">
document.addEventListener('DOMContentLoaded',() => { initNavTree('md__c_l_a_u_d_e.html','',''); });
</script>
<div id="container">
<div id="doc-content">
<!-- window showing the filter options -->
<div id="MSearchSelectWindow"
onmouseover="return searchBox.OnSearchSelectShow()"
onmouseout="return searchBox.OnSearchSelectHide()"
onkeydown="return searchBox.OnSearchSelectKey(event)">
</div>
<!-- iframe showing the search results (closed by default) -->
<div id="MSearchResultsWindow">
<div id="MSearchResults">
<div class="SRPage">
<div id="SRIndex">
<div id="SRResults"></div>
<div class="SRStatus" id="Loading">Loading...</div>
<div class="SRStatus" id="Searching">Searching...</div>
<div class="SRStatus" id="NoMatches">No Matches</div>
</div>
</div>
</div>
</div>
<div><div class="header">
<div class="headertitle"><div class="title">CLAUDE.md </div></div>
</div><!--header-->
<div class="contents">
<div class="textblock"><p><a class="anchor" id="autotoc_md13"></a></p>
<p>This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.</p>
<h1 class="doxsection"><a class="anchor" id="autotoc_md14"></a>
Project purpose and long-term goal</h1>
<p>conformallab++ is a C++17 reimplementation of <a href="https://github.com/varylab/conformallab">ConformalLab</a> — Stefan Sechelmann's Java research library for discrete conformal geometry (TU Berlin, ~850 commits, v1.0.0 2018). The algorithmic foundation is his dissertation:</p>
<blockquote class="doxtable">
<p>Stefan Sechelmann — <em>Variational Methods for Discrete Surface Parameterization: Applications and Implementation</em>, TU Berlin 2016. DOI: <a href="https://depositonce.tu-berlin.de/items/8e2988b2-d991-45b5-aad5-9fb7988f3b2f">10.14279/depositonce-5415</a> · CC BY-SA 4.0 </p>
</blockquote>
<p><b>The long-term goal is a CGAL package</b> — a submission to the CGAL library that brings discrete conformal maps (hyper-ideal, spherical, Euclidean) to the CGAL ecosystem using <span class="tt">CGAL::Surface_mesh</span> as the underlying halfedge data structure, with a traits-class design compatible with arbitrary CGAL-conforming mesh types.</p>
<p>The project has four distinct phase blocks (updated 2026-05-22):</p><ul>
<li><b>Phase 17 (done, v0.7.0):</b> Direct port of the Java library algorithms to C++.</li>
<li><b>Phase 8a MVP + 8b-Lite (done, v0.9.0):</b> CGAL public-API surface for all five DCE models via <span class="tt">&lt;CGAL/Discrete_*.h&gt;</span>. Phase 8a.2 (generic FaceGraph), 8c (manuals), 8d (CGAL-test-format), 8e (YAML pipeline) deferred on-demand.</li>
<li><b>Phase 9a + 9b (done, v0.9.0):</b> Two new functionals (CP-Euclidean port, Inversive-Distance research), two new Newton solvers, block-FD HyperIdeal Hessian.</li>
<li><b>Phase 9b-analytic + 9c (planned):</b> Full analytic HyperIdeal Hessian via Schläfli identity (research, see <span class="tt">doc/roadmap/research-track.md</span>); 4g-polygon fundamental domain for genus g &gt; 1 (mixed port + research).</li>
<li><b>Phase 10+ (research):</b> Holomorphic differentials, Siegel period matrix Ω ∈ H_g, full uniformization for genus g ≥ 2.</li>
</ul>
<h1 class="doxsection"><a class="anchor" id="autotoc_md15"></a>
Language</h1>
<p><b>All code, comments, documentation, commit messages, and test descriptions must be in English.</b> The project is intended for international collaboration and CGAL submission. Existing German-language comments in older files should be replaced with English when editing those files.</p>
<h1 class="doxsection"><a class="anchor" id="autotoc_md16"></a>
Build commands</h1>
<p>All source lives under <span class="tt">code/</span>. Three build modes:</p>
<div class="fragment"><div class="line"># Mode 1 — fast tests, no CGAL, no Boost, no display (CI default)</div>
<div class="line">cmake -S code -B build</div>
<div class="line">cmake --build build --target conformallab_tests -j$(nproc)</div>
<div class="line">ctest --test-dir build --output-on-failure</div>
<div class="line"> </div>
<div class="line"># Mode 2 — CGAL tests, headless (CI full, requires Boost headers only)</div>
<div class="line"># macOS: brew install boost Linux: apt install libboost-dev</div>
<div class="line">cmake -S code -B build -DWITH_CGAL_TESTS=ON</div>
<div class="line">cmake --build build --target conformallab_cgal_tests -j$(nproc)</div>
<div class="line">ctest --test-dir build -R &quot;^cgal\.&quot; --output-on-failure</div>
<div class="line"> </div>
<div class="line"># Mode 3 — full local build: CLI app + viewer + examples (requires Wayland/X11)</div>
<div class="line">cmake -S code -B build -DWITH_CGAL=ON</div>
<div class="line">cmake --build build -j$(nproc)</div>
</div><!-- fragment --><p><span class="tt">-DWITH_CGAL=ON</span> automatically enables <span class="tt">-DWITH_VIEWER=ON</span>, which pulls in GLFW and requires <span class="tt">wayland-scanner</span>. Never use this in headless CI.</p>
<h2 class="doxsection"><a class="anchor" id="autotoc_md17"></a>
Running a single test</h2>
<div class="fragment"><div class="line"># By GTest suite/test name</div>
<div class="line">./build/conformallab_cgal_tests --gtest_filter=&quot;NewtonSolver*&quot;</div>
<div class="line">./build/conformallab_tests --gtest_filter=&quot;Clausen*&quot;</div>
<div class="line"> </div>
<div class="line"># By CTest regex (prefix &quot;cgal.&quot; for all CGAL tests)</div>
<div class="line">ctest --test-dir build -R &quot;cgal.NewtonSolver&quot; --output-on-failure</div>
</div><!-- fragment --><h2 class="doxsection"><a class="anchor" id="autotoc_md18"></a>
Rebuilding the CI Docker image</h2>
<div class="fragment"><div class="line">docker buildx build \</div>
<div class="line"> --platform linux/arm64 \</div>
<div class="line"> -f .gitea/docker/Dockerfile.ci-cpp \</div>
<div class="line"> -t git.eulernest.eu/conformallab/ci-cpp:latest \</div>
<div class="line"> --push \</div>
<div class="line"> .gitea/docker/</div>
</div><!-- fragment --><h1 class="doxsection"><a class="anchor" id="autotoc_md19"></a>
Architecture</h1>
<h2 class="doxsection"><a class="anchor" id="autotoc_md20"></a>
Everything is header-only</h2>
<p>All algorithms live in <span class="tt">code/include/*.hpp</span>. There is no compiled library. The three CMake targets (<span class="tt">conformallab_tests</span>, <span class="tt">conformallab_cgal_tests</span>, <span class="tt">conformallab_core</span>) compile headers directly from their <span class="tt">.cpp</span> entry points. To add a new algorithm: create a <span class="tt">.hpp</span> in <span class="tt">code/include/</span>, add a test in <span class="tt">code/tests/cgal/</span>, and register the test file in <span class="tt">code/tests/cgal/CMakeLists.txt</span>.</p>
<h2 class="doxsection"><a class="anchor" id="autotoc_md21"></a>
Central type: <span class="tt">ConformalMesh</span></h2>
<p><span class="tt">conformal_mesh.hpp</span> defines the core type: </p><div class="fragment"><div class="line"><span class="keyword">using </span>ConformalMesh = CGAL::Surface_mesh&lt;Point3&gt;; <span class="comment">// CGAL::Simple_cartesian&lt;double&gt;</span></div>
</div><!-- fragment --><p>This replaces the Java <span class="tt">CoHDS</span> (half-edge data structure) and its intrusive <span class="tt">CoVertex</span>/<span class="tt">CoEdge</span>/<span class="tt">CoFace</span> types. Data is attached via named CGAL property maps instead of intrusive fields:</p>
<table class="markdownTable">
<tr class="markdownTableHead">
<th class="markdownTableHeadNone">Property map name </th><th class="markdownTableHeadNone">Type </th><th class="markdownTableHeadNone">Meaning </th></tr>
<tr class="markdownTableRowOdd">
<td class="markdownTableBodyNone"><span class="tt">"v:lambda"</span> </td><td class="markdownTableBodyNone"><span class="tt">double</span> per vertex </td><td class="markdownTableBodyNone">log scale factor (conformal variable uᵢ) </td></tr>
<tr class="markdownTableRowEven">
<td class="markdownTableBodyNone"><span class="tt">"v:theta"</span> </td><td class="markdownTableBodyNone"><span class="tt">double</span> per vertex </td><td class="markdownTableBodyNone">target cone angle Θᵥ </td></tr>
<tr class="markdownTableRowOdd">
<td class="markdownTableBodyNone"><span class="tt">"v:idx"</span> </td><td class="markdownTableBodyNone"><span class="tt">int</span> per vertex </td><td class="markdownTableBodyNone">solver DOF index; <span class="tt">-1</span> = pinned/boundary </td></tr>
<tr class="markdownTableRowEven">
<td class="markdownTableBodyNone"><span class="tt">"e:alpha"</span> </td><td class="markdownTableBodyNone"><span class="tt">double</span> per edge </td><td class="markdownTableBodyNone">intersection angle αᵢⱼ (hyperbolic only) </td></tr>
<tr class="markdownTableRowOdd">
<td class="markdownTableBodyNone"><span class="tt">"f:type"</span> </td><td class="markdownTableBodyNone"><span class="tt">int</span> per face </td><td class="markdownTableBodyNone">geometry type (0=Euclidean, 1=Hyperbolic, 2=Spherical) </td></tr>
</table>
<p><span class="tt">CGAL_DISABLE_GMP</span> and <span class="tt">CGAL_DISABLE_MPFR</span> are defined for all CGAL targets — the library deliberately uses <span class="tt">Simple_cartesian&lt;double&gt;</span> (floating-point, no exact arithmetic) because conformal geometry does not require exact predicates.</p>
<h2 class="doxsection"><a class="anchor" id="autotoc_md22"></a>
The five DCE models</h2>
<p>Each model has its own Maps struct that bundles all property maps, plus a functional, optional Hessian, Newton solver, and (since v0.9.0) a CGAL public-API entry function:</p>
<table class="markdownTable">
<tr class="markdownTableHead">
<th class="markdownTableHeadNone">Model </th><th class="markdownTableHeadNone">Space </th><th class="markdownTableHeadNone">DOFs </th><th class="markdownTableHeadNone">Maps struct </th><th class="markdownTableHeadNone">Key headers </th><th class="markdownTableHeadNone">Newton function </th><th class="markdownTableHeadNone">CGAL entry </th></tr>
<tr class="markdownTableRowOdd">
<td class="markdownTableBodyNone">Euclidean </td><td class="markdownTableBodyNone">ℝ² </td><td class="markdownTableBodyNone">vertex </td><td class="markdownTableBodyNone"><span class="tt">EuclideanMaps</span> </td><td class="markdownTableBodyNone"><span class="tt">euclidean_functional.hpp</span>, <span class="tt">euclidean_hessian.hpp</span> </td><td class="markdownTableBodyNone"><span class="tt">newton_euclidean()</span> </td><td class="markdownTableBodyNone"><span class="tt">discrete_conformal_map_euclidean()</span> </td></tr>
<tr class="markdownTableRowEven">
<td class="markdownTableBodyNone">Spherical </td><td class="markdownTableBodyNone"></td><td class="markdownTableBodyNone">vertex </td><td class="markdownTableBodyNone"><span class="tt">SphericalMaps</span> </td><td class="markdownTableBodyNone"><span class="tt">spherical_functional.hpp</span>, <span class="tt">spherical_hessian.hpp</span> </td><td class="markdownTableBodyNone"><span class="tt">newton_spherical()</span> </td><td class="markdownTableBodyNone"><span class="tt">discrete_conformal_map_spherical()</span> </td></tr>
<tr class="markdownTableRowOdd">
<td class="markdownTableBodyNone">Hyper-ideal </td><td class="markdownTableBodyNone">H² (Poincaré disk) </td><td class="markdownTableBodyNone">vertex + edge </td><td class="markdownTableBodyNone"><span class="tt">HyperIdealMaps</span> </td><td class="markdownTableBodyNone"><span class="tt">hyper_ideal_functional.hpp</span>, <span class="tt">hyper_ideal_hessian.hpp</span> (block-FD, Phase 9b) </td><td class="markdownTableBodyNone"><span class="tt">newton_hyper_ideal()</span> </td><td class="markdownTableBodyNone"><span class="tt">discrete_conformal_map_hyper_ideal()</span> </td></tr>
<tr class="markdownTableRowEven">
<td class="markdownTableBodyNone">CP-Euclidean (BPS 2010) </td><td class="markdownTableBodyNone">face-based circle packing </td><td class="markdownTableBodyNone"><b>face</b> </td><td class="markdownTableBodyNone"><span class="tt">CPEuclideanMaps</span> </td><td class="markdownTableBodyNone"><span class="tt">cp_euclidean_functional.hpp</span> </td><td class="markdownTableBodyNone"><span class="tt">newton_cp_euclidean()</span> </td><td class="markdownTableBodyNone"><span class="tt">discrete_circle_packing_euclidean()</span> </td></tr>
<tr class="markdownTableRowOdd">
<td class="markdownTableBodyNone">Inversive-Distance (Luo 2004) </td><td class="markdownTableBodyNone">vertex-based circle packing </td><td class="markdownTableBodyNone">vertex </td><td class="markdownTableBodyNone"><span class="tt">InversiveDistanceMaps</span> </td><td class="markdownTableBodyNone"><span class="tt">inversive_distance_functional.hpp</span> </td><td class="markdownTableBodyNone"><span class="tt">newton_inversive_distance()</span> </td><td class="markdownTableBodyNone"><span class="tt">discrete_inversive_distance_map()</span> </td></tr>
</table>
<p>DOF-assignment patterns:</p><ul>
<li><b>Vertex-only models</b> (Euclidean, Spherical, Inversive-Distance): pin one vertex manually (<span class="tt">maps.v_idx[first_vertex] = -1</span>) then assign sequential indices. The CGAL public entries do this automatically with the "natural-theta" trick (so calling them with no arguments returns x = 0 as the equilibrium).</li>
<li><b>HyperIdeal</b>: <span class="tt">assign_all_dof_indices(mesh, maps)</span> assigns vertex + edge DOFs automatically.</li>
<li><b>CP-Euclidean</b>: face-based — <span class="tt">assign_cp_euclidean_face_dof_indices(mesh, maps, pinned_face)</span> pins one face and indexes the rest.</li>
</ul>
<h2 class="doxsection"><a class="anchor" id="autotoc_md23"></a>
The full pipeline</h2>
<div class="fragment"><div class="line">load_mesh() → ConformalMesh (OFF/OBJ/PLY)</div>
<div class="line">setup_*_maps(mesh) → *Maps (property maps created, all zero)</div>
<div class="line">compute_*_lambda0_from_mesh(mesh, m) → λ° initialised from 3-D edge lengths</div>
<div class="line">DOF assignment → v_idx[v] set; -1 = pinned</div>
<div class="line">check_gauss_bonnet(mesh, maps) → throws if Σ(2πΘᵥ) ≠ 2π·χ(M)</div>
<div class="line">enforce_gauss_bonnet(mesh, maps) → redistributes angle defect uniformly</div>
<div class="line">newton_*(mesh, x0, maps) → NewtonResult{x*, iterations, converged}</div>
<div class="line">compute_cut_graph(mesh) → CutGraph (2g seam edges, tree-cotree)</div>
<div class="line">*_layout(mesh, x*, maps, &amp;cg, &amp;hol) → Layout2D/3D + HolonomyData</div>
<div class="line">normalise_*(layout) → canonical position (PCA / Möbius / Rodrigues)</div>
<div class="line">compute_period_matrix(hol) → PeriodData{τ∈ℍ} (genus 1 flat torus)</div>
<div class="line">compute_fundamental_domain(hol) → FundamentalDomain{vertices, generators}</div>
<div class="line">tiling_neighbourhood(layout, hol) → vector of translated layout copies</div>
<div class="line">save_result_json/xml() → serialised result</div>
</div><!-- fragment --><p>After <span class="tt">compute_*_lambda0_from_mesh()</span> the original vertex positions are no longer used — all subsequent computation is in log-length/scale-factor space.</p>
<h2 class="doxsection"><a class="anchor" id="autotoc_md24"></a>
Newton solver (<span class="tt">newton_solver.hpp</span>)</h2>
<p>Gradient sign convention differs across the five models:</p><ul>
<li><b>Euclidean / Spherical / Inversive-Distance:</b> <span class="tt">G_v = Θ_v actual_angle_sum</span> (target minus actual).</li>
<li><b>HyperIdeal:</b> <span class="tt">G_v = actual_angle_sum Θ_v</span> (actual minus target).</li>
<li><b>CP-Euclidean:</b> <span class="tt">G_f = φ_f Σ_{h:face(h)=f} (p(θ*,Δρ) + θ*)</span> (face-based; see <span class="tt">cp_euclidean_functional.hpp</span> header for the full formula).</li>
</ul>
<p>Hessian sign and solver per model:</p><ul>
<li><b>Euclidean:</b> H is PSD (cotangent Laplacian) → <span class="tt">SimplicialLDLT(H)</span>.</li>
<li><b>Spherical:</b> H is NSD (concave energy) → <span class="tt">SimplicialLDLT(H)</span> (sign flip inside <span class="tt">newton_spherical</span>).</li>
<li><b>HyperIdeal:</b> H is PSD (strictly convex) → <span class="tt">SimplicialLDLT(H)</span>. Phase 9b uses a <b>block-FD Hessian</b> (per-face 6×6 local block, ~96× speed-up vs full FD on V=200). Full analytic Hessian via the chain <span class="tt">(bᵢ, aₑ) → lᵢⱼ → ζ₁₃/ζ₁₄/ζ₁₅ → αᵢⱼ/βᵢ</span> is planned research — see <span class="tt">doc/roadmap/research-track.md</span> Phase 9b-analytic.</li>
<li><b>CP-Euclidean:</b> analytic 2×2-per-edge <span class="tt">h_jk = sin θ / (cosh Δρ cos θ)</span> (BPS 2010), strictly convex → <span class="tt">SimplicialLDLT(H)</span>.</li>
<li><b>Inversive-Distance:</b> FD Hessian (inline in <span class="tt">newton_inversive_distance</span>). Analytic via Glickenstein 2011 eq. (4.6) is planned research (Phase 9a.2-analytic).</li>
</ul>
<p>When <span class="tt">SimplicialLDLT</span> fails (rank-deficient H — gauge mode on a closed mesh without pinned vertex/face), the solver automatically retries with <span class="tt">Eigen::SparseQR</span> to find the minimum-norm step orthogonal to the null space. Public API: <span class="tt">solve_linear_system(H, rhs, &amp;used_fallback)</span>.</p>
<h2 class="doxsection"><a class="anchor" id="autotoc_md25"></a>
Layout and holonomy (<span class="tt">layout.hpp</span>)</h2>
<p>BFS-trilateration with a <b>priority min-heap on BFS depth</b> (<span class="tt">depth = max(depth[src], depth[tgt]) + 1</span>). Root face = largest 3-D area face. This minimises trilateration error accumulation compared to simple BFS.</p>
<p>Key output fields:</p><ul>
<li><span class="tt">layout.uv[v.idx()]</span> — primary UV (first/shallowest BFS visit per vertex)</li>
<li><span class="tt">layout.halfedge_uv[h.idx()]</span> — UV of <span class="tt">source(h)</span> as seen from <span class="tt">face(h)</span>; at seam halfedges the two opposite halfedges carry <em>different</em> UV values, enabling proper GPU texture atlasing without vertex duplication</li>
<li><span class="tt">hol.translations[i]</span> — lattice generator ωᵢ ∈ (Euclidean/spherical)</li>
<li><span class="tt">hol.mobius_maps[i]</span> — Möbius isometry Tᵢ ∈ SU(1,1) (hyperbolic, Poincaré disk)</li>
</ul>
<p><span class="tt">MobiusMap</span> is defined in <span class="tt">layout.hpp</span>: T(z) = (az+b)/(cz+d). Key methods: <span class="tt">from_three()</span> (fit to 3 point correspondences via 3×3 complex linear system), <span class="tt">compose()</span>, <span class="tt">inverse()</span>, <span class="tt">apply(Vector2d)</span>.</p>
<h2 class="doxsection"><a class="anchor" id="autotoc_md26"></a>
Key mathematical reference for each header</h2>
<table class="markdownTable">
<tr class="markdownTableHead">
<th class="markdownTableHeadNone">Header </th><th class="markdownTableHeadNone">Java original </th><th class="markdownTableHeadNone">Key reference </th></tr>
<tr class="markdownTableRowOdd">
<td class="markdownTableBodyNone"><span class="tt">hyper_ideal_geometry.hpp</span> </td><td class="markdownTableBodyNone"><span class="tt">HyperIdealGeometry.java</span> </td><td class="markdownTableBodyNone">Springborn (2020) — ζ₁₃/ζ₁₄/ζ₁₅ functions </td></tr>
<tr class="markdownTableRowEven">
<td class="markdownTableBodyNone"><span class="tt">euclidean_hessian.hpp</span> </td><td class="markdownTableBodyNone"><span class="tt">EuclideanHessian.java</span> </td><td class="markdownTableBodyNone">Pinkall &amp; Polthier (1993) — cotangent Laplacian </td></tr>
<tr class="markdownTableRowOdd">
<td class="markdownTableBodyNone"><span class="tt">spherical_hessian.hpp</span> </td><td class="markdownTableBodyNone"><span class="tt">SphericalHessian.java</span> </td><td class="markdownTableBodyNone">∂α/∂u from spherical law of cosines </td></tr>
<tr class="markdownTableRowEven">
<td class="markdownTableBodyNone"><span class="tt">cut_graph.hpp</span> </td><td class="markdownTableBodyNone"><span class="tt">CuttingUtility.java</span> </td><td class="markdownTableBodyNone">Erickson &amp; Whittlesey (SODA 2005) — tree-cotree </td></tr>
<tr class="markdownTableRowOdd">
<td class="markdownTableBodyNone"><span class="tt">period_matrix.hpp</span> </td><td class="markdownTableBodyNone"><span class="tt">PeriodMatrixUtility.java</span> </td><td class="markdownTableBodyNone">Sechelmann (2016) §4 — SL(2,) reduction </td></tr>
<tr class="markdownTableRowEven">
<td class="markdownTableBodyNone"><span class="tt">gauss_bonnet.hpp</span> </td><td class="markdownTableBodyNone">(distributed across Java) </td><td class="markdownTableBodyNone">GaussBonnet: Σ(2πΘᵥ) = 2π·χ(M) </td></tr>
</table>
<h2 class="doxsection"><a class="anchor" id="autotoc_md27"></a>
Java features not yet ported (Phase 9)</h2>
<p>The Java library under <span class="tt">de.varylab.discreteconformal</span> contains these items not yet in C++:</p>
<table class="markdownTable">
<tr class="markdownTableHead">
<th class="markdownTableHeadNone">Java class </th><th class="markdownTableHeadNone">Planned C++ header </th><th class="markdownTableHeadNone">Phase </th></tr>
<tr class="markdownTableRowOdd">
<td class="markdownTableBodyNone"><span class="tt">InversiveDistanceFunctional</span> </td><td class="markdownTableBodyNone"><span class="tt">inversive_distance_functional.hpp</span> </td><td class="markdownTableBodyNone">9a </td></tr>
<tr class="markdownTableRowEven">
<td class="markdownTableBodyNone">Analytic HyperIdeal Hessian </td><td class="markdownTableBodyNone"><span class="tt">hyper_ideal_hessian.hpp</span> (replace FD) </td><td class="markdownTableBodyNone">9b </td></tr>
<tr class="markdownTableRowOdd">
<td class="markdownTableBodyNone">4g-polygon boundary walk in <span class="tt">FundamentalDomainUtility</span> </td><td class="markdownTableBodyNone"><span class="tt">fundamental_domain.hpp</span> (extend) </td><td class="markdownTableBodyNone">9c </td></tr>
<tr class="markdownTableRowEven">
<td class="markdownTableBodyNone"><span class="tt">DiscreteHarmonicFormUtility</span> </td><td class="markdownTableBodyNone">Phase 10a prerequisite </td><td class="markdownTableBodyNone">10 </td></tr>
<tr class="markdownTableRowOdd">
<td class="markdownTableBodyNone"><span class="tt">DiscreteHolomorphicFormUtility</span> </td><td class="markdownTableBodyNone">Phase 10a </td><td class="markdownTableBodyNone">10 </td></tr>
<tr class="markdownTableRowEven">
<td class="markdownTableBodyNone"><span class="tt">HomologyUtility</span>, <span class="tt">CanonicalBasisUtility</span> </td><td class="markdownTableBodyNone">Phase 10 </td><td class="markdownTableBodyNone">10 </td></tr>
</table>
<p>When porting a Java class, locate the original in <span class="tt">de.varylab.discreteconformal.*</span> at <a href="https://github.com/varylab/conformallab">github.com/varylab/conformallab</a> and use it as the reference implementation.</p>
<h1 class="doxsection"><a class="anchor" id="autotoc_md28"></a>
Test design patterns</h1>
<h2 class="doxsection"><a class="anchor" id="autotoc_md29"></a>
"Natural theta" — constructing a known equilibrium at x* = 0</h2>
<div class="fragment"><div class="line"><span class="comment">// Evaluate gradient at x=0; set target angles = actual angle sums → x*=0 by definition</span></div>
<div class="line">std::vector&lt;double&gt; x0(n_dofs, 0.0);</div>
<div class="line"><span class="keyword">auto</span> G0 = euclidean_gradient(mesh, x0, maps);</div>
<div class="line"><span class="keywordflow">for</span> (<span class="keyword">auto</span> v : mesh.vertices())</div>
<div class="line"> <span class="keywordflow">if</span> (maps.v_idx[v] &gt;= 0)</div>
<div class="line"> maps.theta_v[v] -= G0[maps.v_idx[v]]; <span class="comment">// shift so G(x=0) = 0</span></div>
</div><!-- fragment --><p>This is used in virtually every Newton convergence test — it avoids hardcoding specific angle values.</p>
<h2 class="doxsection"><a class="anchor" id="autotoc_md30"></a>
Gradient check pattern</h2>
<div class="fragment"><div class="line"><span class="comment">// Copy from any test_*_functional.cpp — GradientCheck_* test suite</span></div>
<div class="line"><span class="keywordtype">double</span> eps = 1e-5;</div>
<div class="line"><span class="keywordflow">for</span> (<span class="keywordtype">int</span> i = 0; i &lt; n; ++i) {</div>
<div class="line"> xp[i] += eps; <span class="keyword">auto</span> Gp = euclidean_gradient(mesh, xp, maps);</div>
<div class="line"> xm[i] -= eps; <span class="keyword">auto</span> Gm = euclidean_gradient(mesh, xm, maps);</div>
<div class="line"> <span class="keywordtype">double</span> fd = (energy(xp) - energy(xm)) / (2*eps);</div>
<div class="line"> EXPECT_NEAR(G[i], fd, 1e-7);</div>
<div class="line"> xp[i] = xm[i] = x0[i];</div>
<div class="line">}</div>
</div><!-- fragment --><p>All new functionals must have a gradient-check test before being considered complete.</p>
<h2 class="doxsection"><a class="anchor" id="autotoc_md31"></a>
Halfedge traversal</h2>
<div class="fragment"><div class="line"><span class="keywordflow">for</span> (<span class="keyword">auto</span> f : mesh.faces()) {</div>
<div class="line"> <span class="keyword">auto</span> h0 = mesh.halfedge(f); <span class="comment">// canonical halfedge of face</span></div>
<div class="line"> <span class="keyword">auto</span> h1 = mesh.next(h0);</div>
<div class="line"> <span class="keyword">auto</span> h2 = mesh.next(h1);</div>
<div class="line"> </div>
<div class="line"> Vertex_index v1 = mesh.source(h0); <span class="comment">// = mesh.target(h2)</span></div>
<div class="line"> Vertex_index v2 = mesh.source(h1);</div>
<div class="line"> Vertex_index v3 = mesh.source(h2);</div>
<div class="line"> </div>
<div class="line"> <span class="comment">// Angle at v3 is opposite to h0 (edge v1v2)</span></div>
<div class="line"> <span class="comment">// h_alpha[h0] = α₃, h_alpha[h1] = α₁, h_alpha[h2] = α₂</span></div>
<div class="line"> </div>
<div class="line"> <span class="keywordtype">bool</span> is_boundary = mesh.is_border(mesh.opposite(h0));</div>
<div class="line">}</div>
</div><!-- fragment --><h2 class="doxsection"><a class="anchor" id="autotoc_md32"></a>
Attaching custom data to the mesh</h2>
<div class="fragment"><div class="line"><span class="keyword">auto</span> [my_map, created] = mesh.add_property_map&lt;Vertex_index, <span class="keywordtype">double</span>&gt;(<span class="stringliteral">&quot;v:my_data&quot;</span>, 0.0);</div>
<div class="line">my_map[v] = 3.14;</div>
</div><!-- fragment --><h1 class="doxsection"><a class="anchor" id="autotoc_md33"></a>
CI pipeline</h1>
<p>Two jobs in <span class="tt">.gitea/workflows/cpp-tests.yml</span>:</p>
<table class="markdownTable">
<tr class="markdownTableHead">
<th class="markdownTableHeadNone">Job </th><th class="markdownTableHeadNone">CMake flags </th><th class="markdownTableHeadNone">Deps </th><th class="markdownTableHeadNone">Triggers on </th></tr>
<tr class="markdownTableRowOdd">
<td class="markdownTableBodyNone"><span class="tt">test-fast</span> </td><td class="markdownTableBodyNone"><em>(none)</em> </td><td class="markdownTableBodyNone">Eigen + GTest only </td><td class="markdownTableBodyNone">all branches </td></tr>
<tr class="markdownTableRowEven">
<td class="markdownTableBodyNone"><span class="tt">test-cgal</span> </td><td class="markdownTableBodyNone"><span class="tt">-DWITH_CGAL_TESTS=ON</span> </td><td class="markdownTableBodyNone">+ Boost </td><td class="markdownTableBodyNone">pull requests only </td></tr>
</table>
<p>Runner: <span class="tt">eulernest</span> — self-hosted Raspberry Pi, ARM64, Ubuntu 22.04. Docker image: <span class="tt">git.eulernest.eu/conformallab/ci-cpp:latest</span>. <span class="tt">test-cgal</span> needs <span class="tt">test-fast</span> to pass first (<span class="tt">needs: test-fast</span>).</p>
<p>Expected results: full test suite passing, 0 skipped, 0 failed. The canonical counts live in <span class="tt">doc/api/tests.md</span> — do not hardcode them anywhere else (see <a href="doc/release-policy.md"><span class="tt">doc/release-policy.md</span></a>).</p>
<h1 class="doxsection"><a class="anchor" id="autotoc_md34"></a>
Release state</h1>
<p>Current release: <b>v0.9.0</b> (tag on <span class="tt">main</span>, released 2026-05-22). Phases 19a complete, Phase 8b-Lite CGAL API surface complete (all 5 DCE models reachable via <span class="tt">&lt;CGAL/Discrete_*.h&gt;</span>), Phase 9b block-FD HyperIdeal Hessian shipped (~96× speed-up). Next planned milestones: Phase 9c (4g-polygon, genus g &gt; 1) and Phase 9b-analytic (Schläfli identity). See <span class="tt">doc/release-policy.md</span> for the version-tag policy and <span class="tt">doc/roadmap/phases.md</span> for the phase plan.</p>
<h1 class="doxsection"><a class="anchor" id="autotoc_md35"></a>
Phase 8 strategic decisions (2026-05-19)</h1>
<p>The CGAL-package architecture was frozen on 2026-05-19. Full design: <a href="doc/api/cgal-package.md"><span class="tt">doc/api/cgal-package.md</span></a>. Key decisions:</p>
<table class="markdownTable">
<tr class="markdownTableHead">
<th class="markdownTableHeadNone">Decision </th><th class="markdownTableHeadNone">Choice </th></tr>
<tr class="markdownTableRowOdd">
<td class="markdownTableBodyNone">Submission to upstream CGAL </td><td class="markdownTableBodyNone"><b>Pre-submission-ready, not bound.</b> 12+ months horizon. </td></tr>
<tr class="markdownTableRowEven">
<td class="markdownTableBodyNone">License </td><td class="markdownTableBodyNone"><b>MIT preserved</b> (no LGPL switch). </td></tr>
<tr class="markdownTableRowOdd">
<td class="markdownTableBodyNone">Mesh-type flexibility </td><td class="markdownTableBodyNone"><b>Generic <span class="tt">FaceGraph + HalfedgeGraph</span></b> in target design; MVP starts Surface_mesh-only. </td></tr>
<tr class="markdownTableRowEven">
<td class="markdownTableBodyNone">Parameter style </td><td class="markdownTableBodyNone"><b>Named Parameters</b> (<span class="tt">CGAL::parameters::...</span>). </td></tr>
<tr class="markdownTableRowOdd">
<td class="markdownTableBodyNone">Default kernel </td><td class="markdownTableBodyNone"><b><span class="tt">Simple_cartesian&lt;double&gt;</span></b> (status quo). </td></tr>
<tr class="markdownTableRowEven">
<td class="markdownTableBodyNone">Backward compatibility </td><td class="markdownTableBodyNone"><b>Dual-layer wrapper</b><span class="tt">code/include/*.hpp</span> stays as implementation, <span class="tt">include/CGAL/*.h</span> is thin wrapper. No algorithm duplication. </td></tr>
<tr class="markdownTableRowOdd">
<td class="markdownTableBodyNone">Implementation strategy </td><td class="markdownTableBodyNone"><b>Hybrid MVP</b> — minimum Phase 8 (traits + one wrapper) first, then Phase 9 in full, then Phase 8 extensions only on concrete demand. </td></tr>
<tr class="markdownTableRowEven">
<td class="markdownTableBodyNone">Phase-8 MVP acceptance test </td><td class="markdownTableBodyNone"><b>Phase 9a (Inversive-Distance)</b> as the first new client of the new traits API. </td></tr>
</table>
<h2 class="doxsection"><a class="anchor" id="autotoc_md36"></a>
Implementation sequence (committed)</h2>
<div class="fragment"><div class="line">1. Phase 7.5 Doxygen + cleanup done ✅</div>
<div class="line">2. Phase 8 MVP — traits + one euclidean wrapper 35 days</div>
<div class="line">3. Phase 9a — Inversive-Distance against new traits 35 days</div>
<div class="line">4. Phase 9b — analytic HyperIdeal Hessian 1 week</div>
<div class="line">5. Phase 9c — 4g-polygon for genus g &gt; 1 1 week</div>
<div class="line"> → port really complete, v0.9.0 release</div>
</div><!-- fragment --><p>Phase 8 extensions (8a.2 generic FaceGraph, 8c full Doxygen manuals, 8d CGAL-format tests, 8e YAML pipeline) are deferred to on-demand status — no speculative architecture for an uncertain submission.</p>
<p>Root-level files added at v0.7.0:</p><ul>
<li><span class="tt">CITATION.cff</span> — machine-readable citation (Sechelmann 2016, Springborn 2020, BobenkoSpringborn 2004)</li>
<li><span class="tt">CONTRIBUTING.md</span> — short root-level pointer to <span class="tt">doc/contributing.md</span></li>
<li><span class="tt">scripts/try_it.sh</span> — one-script quickstart: build → 209 tests → example run</li>
<li>CMake install target: <span class="tt">cmake --install build --prefix /usr/local</span> → headers land in <span class="tt">include/conformallab/</span></li>
</ul>
<h1 class="doxsection"><a class="anchor" id="autotoc_md37"></a>
Port-vs-research maintenance rule (2026-05-21 audit)</h1>
<p>Before claiming something "ports X from Java", <b>verify empirically</b>:</p>
<div class="fragment"><div class="line">find /Users/tarikmoussa/Desktop/conformallab -iname &quot;*X*&quot;</div>
<div class="line">grep -r &quot;ClassName&quot; /Users/tarikmoussa/Desktop/conformallab/src</div>
</div><!-- fragment --><p>If zero matches, the work is <b>new research</b> — add it to <span class="tt">doc/roadmap/research-track.md</span> with primary literature citations, <b>not</b> to <span class="tt">doc/roadmap/java-parity.md</span>.</p>
<p>The 2026-05-21 audit found four pre-existing mis-labels:</p>
<table class="markdownTable">
<tr class="markdownTableHead">
<th class="markdownTableHeadNone">Item </th><th class="markdownTableHeadNone">Wrong claim </th><th class="markdownTableHeadNone">Reality </th></tr>
<tr class="markdownTableRowOdd">
<td class="markdownTableBodyNone"><span class="tt">InversiveDistanceFunctional</span> </td><td class="markdownTableBodyNone">"Java port (Luo 2004)" </td><td class="markdownTableBodyNone">No such Java class exists </td></tr>
<tr class="markdownTableRowEven">
<td class="markdownTableBodyNone">HyperIdeal Hessian (FD) </td><td class="markdownTableBodyNone">"Phase 4a" </td><td class="markdownTableBodyNone">Research — Java has <span class="tt">hasHessian()==false</span> </td></tr>
<tr class="markdownTableRowOdd">
<td class="markdownTableBodyNone">HyperIdeal Hessian (analytic) </td><td class="markdownTableBodyNone">"Phase 9b port" </td><td class="markdownTableBodyNone">Research — derivation via Schläfli 1858 </td></tr>
<tr class="markdownTableRowEven">
<td class="markdownTableBodyNone">Tutorial framing </td><td class="markdownTableBodyNone">"ports `InversiveDistanceFunctional.java`" </td><td class="markdownTableBodyNone">Implementation from Luo 2004 + Glickenstein 2011 </td></tr>
</table>
<p>All four are corrected as of this commit. Future contributors must follow the empirical verification rule above before any new claim.</p>
<h1 class="doxsection"><a class="anchor" id="autotoc_md38"></a>
Documentation map</h1>
<p>24 documents across 6 categories. Read the relevant one before reasoning from scratch — do not hallucinate content that is already written down.</p>
<h2 class="doxsection"><a class="anchor" id="autotoc_md39"></a>
Mathematics &amp; theory</h2>
<table class="markdownTable">
<tr class="markdownTableHead">
<th class="markdownTableHeadNone">Question </th><th class="markdownTableHeadNone">Document </th></tr>
<tr class="markdownTableRowOdd">
<td class="markdownTableBodyNone">What problem does this library solve mathematically? </td><td class="markdownTableBodyNone"><span class="tt">doc/math/discrete-conformal-theory.md</span> </td></tr>
<tr class="markdownTableRowEven">
<td class="markdownTableBodyNone">How do the three geometry modes differ (Euclidean/Spherical/HyperIdeal)? </td><td class="markdownTableBodyNone"><span class="tt">doc/math/geometry-modes.md</span> </td></tr>
<tr class="markdownTableRowOdd">
<td class="markdownTableBodyNone">What analytic invariants can be used to validate correctness? </td><td class="markdownTableBodyNone"><span class="tt">doc/math/validation.md</span> </td></tr>
<tr class="markdownTableRowEven">
<td class="markdownTableBodyNone">What are the exact ctest commands with expected terminal output? </td><td class="markdownTableBodyNone"><span class="tt">doc/math/validation-protocol.md</span> </td></tr>
<tr class="markdownTableRowOdd">
<td class="markdownTableBodyNone">What is the O() complexity and how does it scale with mesh size? </td><td class="markdownTableBodyNone"><span class="tt">doc/math/complexity.md</span> </td></tr>
<tr class="markdownTableRowEven">
<td class="markdownTableBodyNone">Which papers are referenced by which header? </td><td class="markdownTableBodyNone"><span class="tt">doc/math/references.md</span> </td></tr>
<tr class="markdownTableRowOdd">
<td class="markdownTableBodyNone">How does conformallab++ compare to libigl, CGAL, geometry-central, pmp-library? </td><td class="markdownTableBodyNone"><span class="tt">doc/math/software-landscape.md</span> </td></tr>
<tr class="markdownTableRowEven">
<td class="markdownTableBodyNone">What is unique about conformallab++ (novelty, target audience)? </td><td class="markdownTableBodyNone"><span class="tt">doc/math/novelty-statement.md</span> </td></tr>
</table>
<h2 class="doxsection"><a class="anchor" id="autotoc_md40"></a>
Architecture &amp; design</h2>
<table class="markdownTable">
<tr class="markdownTableHead">
<th class="markdownTableHeadNone">Question </th><th class="markdownTableHeadNone">Document </th></tr>
<tr class="markdownTableRowOdd">
<td class="markdownTableBodyNone">Full pipeline diagram and data-flow overview </td><td class="markdownTableBodyNone"><span class="tt">doc/architecture/overall_pipeline.md</span> </td></tr>
<tr class="markdownTableRowEven">
<td class="markdownTableBodyNone">Directory tree, build targets, file organisation </td><td class="markdownTableBodyNone"><span class="tt">doc/architecture/project-structure.md</span> </td></tr>
<tr class="markdownTableRowOdd">
<td class="markdownTableBodyNone">Key architectural decisions and their rationale </td><td class="markdownTableBodyNone"><span class="tt">doc/architecture/design-decisions.md</span> </td></tr>
<tr class="markdownTableRowEven">
<td class="markdownTableBodyNone">Detailed comparison with geometry-central (CMU): overlap, adoption, scientific value </td><td class="markdownTableBodyNone"><span class="tt">doc/architecture/geometry-central-comparison.md</span> </td></tr>
<tr class="markdownTableRowOdd">
<td class="markdownTableBodyNone">Phase 9a validation report (CP-Euclidean port + Luo-inversive-distance literature check) </td><td class="markdownTableBodyNone"><span class="tt">doc/architecture/phase-9a-validation.md</span> </td></tr>
</table>
<h2 class="doxsection"><a class="anchor" id="autotoc_md41"></a>
API &amp; extension</h2>
<table class="markdownTable">
<tr class="markdownTableHead">
<th class="markdownTableHeadNone">Question </th><th class="markdownTableHeadNone">Document </th></tr>
<tr class="markdownTableRowOdd">
<td class="markdownTableBodyNone">All 24 public headers with descriptions </td><td class="markdownTableBodyNone"><span class="tt">doc/api/headers.md</span> </td></tr>
<tr class="markdownTableRowEven">
<td class="markdownTableBodyNone">Full pipeline API for all three geometries </td><td class="markdownTableBodyNone"><span class="tt">doc/api/pipeline.md</span> </td></tr>
<tr class="markdownTableRowOdd">
<td class="markdownTableBodyNone">What does each processing unit require/provide (contracts)? </td><td class="markdownTableBodyNone"><span class="tt">doc/api/contracts.md</span> </td></tr>
<tr class="markdownTableRowEven">
<td class="markdownTableBodyNone">How to add a new functional / geometry mode / port from Java </td><td class="markdownTableBodyNone"><span class="tt">doc/api/extending.md</span> </td></tr>
<tr class="markdownTableRowOdd">
<td class="markdownTableBodyNone">Per-suite breakdown and counts (single source of truth) </td><td class="markdownTableBodyNone"><span class="tt">doc/api/tests.md</span> </td></tr>
<tr class="markdownTableRowEven">
<td class="markdownTableBodyNone">Phase 8 CGAL package design + Declarative YAML pipeline spec </td><td class="markdownTableBodyNone"><span class="tt">doc/api/cgal-package.md</span> </td></tr>
</table>
<h2 class="doxsection"><a class="anchor" id="autotoc_md42"></a>
Concepts &amp; specs</h2>
<table class="markdownTable">
<tr class="markdownTableHead">
<th class="markdownTableHeadNone">Question </th><th class="markdownTableHeadNone">Document </th></tr>
<tr class="markdownTableRowOdd">
<td class="markdownTableBodyNone">Declarative YAML pipeline: token vocabulary, 5 examples, validation algorithm </td><td class="markdownTableBodyNone"><span class="tt">doc/concepts/declarative-pipeline.md</span> </td></tr>
</table>
<h2 class="doxsection"><a class="anchor" id="autotoc_md43"></a>
Roadmap &amp; porting</h2>
<table class="markdownTable">
<tr class="markdownTableHead">
<th class="markdownTableHeadNone">Question </th><th class="markdownTableHeadNone">Document </th></tr>
<tr class="markdownTableRowOdd">
<td class="markdownTableBodyNone">Phases 110 with status and sub-tasks </td><td class="markdownTableBodyNone"><span class="tt">doc/roadmap/phases.md</span> </td></tr>
<tr class="markdownTableRowEven">
<td class="markdownTableBodyNone">Which Java classes are ported, which are planned, which are skipped? </td><td class="markdownTableBodyNone"><span class="tt">doc/roadmap/java-parity.md</span> </td></tr>
<tr class="markdownTableRowOdd">
<td class="markdownTableBodyNone">New research items (beyond Java) — citations, acceptance criteria </td><td class="markdownTableBodyNone"><span class="tt">doc/roadmap/research-track.md</span> </td></tr>
</table>
<h2 class="doxsection"><a class="anchor" id="autotoc_md44"></a>
Tutorials &amp; onboarding</h2>
<table class="markdownTable">
<tr class="markdownTableHead">
<th class="markdownTableHeadNone">Question </th><th class="markdownTableHeadNone">Document </th></tr>
<tr class="markdownTableRowOdd">
<td class="markdownTableBodyNone">Build modes, single-test invocation, CLI, Docker image rebuild </td><td class="markdownTableBodyNone"><span class="tt">doc/getting-started.md</span> </td></tr>
<tr class="markdownTableRowEven">
<td class="markdownTableBodyNone">Step-by-step: port the Inversive Distance functional (Phase 9a template) </td><td class="markdownTableBodyNone"><span class="tt">doc/tutorials/add-inversive-distance.md</span> </td></tr>
<tr class="markdownTableRowOdd">
<td class="markdownTableBodyNone">Language policy, test standards, release flow </td><td class="markdownTableBodyNone"><span class="tt">doc/contributing.md</span> </td></tr>
<tr class="markdownTableRowEven">
<td class="markdownTableBodyNone">Versioning rules + release process + single-source-of-truth list </td><td class="markdownTableBodyNone"><span class="tt">doc/release-policy.md</span> </td></tr>
</table>
<h2 class="doxsection"><a class="anchor" id="autotoc_md45"></a>
geometry-central context</h2>
<p><b>geometry-central</b> (Keenan Crane, CMU) implements the same discrete conformal equivalence problem (Gillespie, Springborn &amp; Crane, SIGGRAPH 2021) but uses Ptolemaic flips on intrinsic triangulations instead of Newton on the original mesh. It has no period matrix, holonomy, or spherical geometry mode. The shared mathematical core (Springborn 2020) means cross-validation is meaningful. Full analysis: <span class="tt">doc/architecture/geometry-central-comparison.md</span>. Optional adoption roadmap (GC-1/2/3): <span class="tt">doc/roadmap/phases.md</span> (Optional section).</p>
<h1 class="doxsection"><a class="anchor" id="autotoc_md46"></a>
Known quirks</h1>
<ul>
<li><b>No GTEST_SKIP stubs remain</b> (since v0.9.0): the three stale HDS-port stub files were removed because the CGAL test suite covers the same functionality with real tests. The pure-math <span class="tt">conformallab_tests</span> target now only contains active tests.</li>
<li><b>Boost is header-only</b>: CGAL 6.x uses only Boost headers (<span class="tt">Boost.Config</span>, <span class="tt">Boost.Graph</span>). No compiled Boost libraries are needed. <span class="tt">find_package(Boost REQUIRED)</span> only locates the include path.</li>
<li><b><span class="tt">main</span> branch is protected</b> on <span class="tt">origin</span> (Gitea). Push to <span class="tt">dev</span>, then merge via pull request. Codeberg <span class="tt">main</span> can be pushed to directly.</li>
<li><b>Both remotes must stay in sync</b>: <span class="tt">origin</span> = <span class="tt">git.eulernest.eu</span> (CI runs here), <span class="tt">codeberg</span> = <span class="tt">codeberg.org/TMoussa/ConformalLabpp</span> (public mirror). Push to both after every significant change. </li>
</ul>
</div></div><!-- contents -->
</div><!-- PageDoc -->
</div><!-- doc-content -->
<div id="page-nav" class="page-nav-panel">
<div id="page-nav-resize-handle"></div>
<div id="page-nav-tree">
<div id="page-nav-contents">
</div><!-- page-nav-contents -->
</div><!-- page-nav-tree -->
</div><!-- page-nav -->
</div><!-- container -->
<!-- start footer part -->
<div id="nav-path" class="navpath"><!-- id is needed for treeview function! -->
<ul>
<li class="footer">Generated by <a href="https://www.doxygen.org/index.html"><img class="footer" src="doxygen.svg" width="104" height="31" alt="doxygen"/></a> 1.17.0 </li>
</ul>
</div>
</body>
</html>

569
menu.js Normal file
View File

@@ -0,0 +1,569 @@
/*
@licstart The following is the entire license notice for the JavaScript code in this file.
The MIT License (MIT)
Copyright (C) 1997-2020 by Dimitri van Heesch
Permission is hereby granted, free of charge, to any person obtaining a copy of this software
and associated documentation files (the "Software"), to deal in the Software without restriction,
including without limitation the rights to use, copy, modify, merge, publish, distribute,
sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or
substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@licend The above is the entire license notice for the JavaScript code in this file
*/
function initMenu(relPath,treeview) {
const SHOW_DELAY = 250; // 250ms delay before showing
const HIDE_DELAY = 500; // 500ms delay before hiding
const SLIDE_DELAY = 250; // 250ms slide up/down delay
const WHEEL_STEP = 30; // 30 pixel per mouse wheel tick
const ARROW_STEP = 5; // 5 pixel when hovering arrow up/down
const ARROW_POLL_INTERVAL = 20; // 20ms per arrow up/down check
const MOBILE_WIDTH = 768; // switch point for mobile/desktop mode
// Helper function for slideDown animation
function slideDown(element, duration, callback) {
if (element.dataset.animating) return;
element.dataset.animating = 'true';
element.style.removeProperty('display');
let display = window.getComputedStyle(element).display;
if (display === 'none') display = 'block';
element.style.display = display;
const height = element.offsetHeight;
element.style.overflow = 'hidden';
element.style.height = 0;
element.offsetHeight; // force reflow
element.style.transitionProperty = 'height';
element.style.transitionDuration = duration + 'ms';
element.style.height = height + 'px';
window.setTimeout(() => {
element.style.removeProperty('height');
element.style.removeProperty('overflow');
element.style.removeProperty('transition-duration');
element.style.removeProperty('transition-property');
delete element.dataset.animating;
if (callback) callback();
}, duration);
}
// Helper function for slideUp animation
function slideUp(element, duration, callback) {
if (element.dataset.animating) return;
element.dataset.animating = 'true';
element.style.transitionProperty = 'height';
element.style.transitionDuration = duration + 'ms';
element.style.height = element.offsetHeight + 'px';
element.offsetHeight; // force reflow
element.style.overflow = 'hidden';
element.style.height = 0;
window.setTimeout(() => {
element.style.display = 'none';
element.style.removeProperty('height');
element.style.removeProperty('overflow');
element.style.removeProperty('transition-duration');
element.style.removeProperty('transition-property');
delete element.dataset.animating;
if (callback) callback();
}, duration);
}
// Helper to create the menu tree structure
function makeTree(data,relPath,topLevel=false) {
let result='';
if ('children' in data) {
if (!topLevel) {
result+='<ul>';
}
for (let i in data.children) {
let url;
const link = data.children[i].url;
if (link.substring(0,1)=='^') {
url = link.substring(1);
} else {
url = relPath+link;
}
result+='<li><a href="'+url+'">'+
data.children[i].text+'</a>'+
makeTree(data.children[i],relPath)+'</li>';
}
if (!topLevel) {
result+='</ul>';
}
}
return result;
}
const mainNav = document.getElementById('main-nav');
if (mainNav && mainNav.children.length > 0) {
const firstChild = mainNav.children[0];
firstChild.insertAdjacentHTML('afterbegin', makeTree(menudata, relPath, true));
}
const searchBoxPos2 = document.getElementById('searchBoxPos2');
let searchBoxContents = searchBoxPos2 ? searchBoxPos2.innerHTML : '';
const mainMenuState = document.getElementById('main-menu-state');
let prevWidth = 0;
const initResizableIfExists = function() {
if (typeof initResizableFunc === 'function') initResizableFunc(treeview);
}
// Dropdown menu functionality to replace smartmenus
let closeAllDropdowns = null; // Will be set by initDropdownMenu
const isMobile = () => window.innerWidth < MOBILE_WIDTH;
if (mainMenuState) {
const mainMenu = document.getElementById('main-menu');
const searchBoxPos1 = document.getElementById('searchBoxPos1');
// animate mobile main menu
mainMenuState.addEventListener('change', function() {
if (this.checked) {
slideDown(mainMenu, SLIDE_DELAY, () => {
mainMenu.style.display = 'block';
initResizableIfExists();
});
} else {
slideUp(mainMenu, SLIDE_DELAY, () => {
mainMenu.style.display = 'none';
});
}
});
// set default menu visibility
const resetState = function() {
const newWidth = window.innerWidth;
if (newWidth !== prevWidth) {
// Close all open dropdown menus when switching between mobile/desktop modes
if (closeAllDropdowns) {
closeAllDropdowns();
}
if (newWidth < MOBILE_WIDTH) {
mainMenuState.checked = false;
mainMenu.style.display = 'none';
if (searchBoxPos2) {
searchBoxPos2.innerHTML = '';
searchBoxPos2.style.display = 'none';
}
if (searchBoxPos1) {
searchBoxPos1.innerHTML = searchBoxContents;
searchBoxPos1.style.display = '';
}
} else {
mainMenu.style.display = '';
if (searchBoxPos1) {
searchBoxPos1.innerHTML = '';
searchBoxPos1.style.display = 'none';
}
if (searchBoxPos2) {
searchBoxPos2.innerHTML = searchBoxContents;
searchBoxPos2.style.display = '';
}
}
if (typeof searchBox !== 'undefined') {
searchBox.CloseResultsWindow();
}
prevWidth = newWidth;
}
}
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', function() {
resetState();
initResizableIfExists();
});
} else {
resetState();
initResizableIfExists();
}
window.addEventListener('resize', resetState);
} else {
initResizableIfExists();
}
function initDropdownMenu() {
const mainMenu = document.getElementById('main-menu');
if (!mainMenu) return;
const menuItems = mainMenu.querySelectorAll('li');
// Helper function to position nested submenu with viewport checking
function positionNestedSubmenu(submenu, link) {
const viewport = {
height: window.innerHeight,
scrollY: window.scrollY
};
// Set initial position - top aligned with parent (next to arrow)
submenu.style.top = '0';
if (isMobile()) {
submenu.style.marginLeft = 0;
} else {
submenu.style.marginLeft = link.offsetWidth + 'px';
}
// Get submenu dimensions and position
const submenuRect = submenu.getBoundingClientRect();
const submenuHeight = submenuRect.height;
const submenuTop = submenuRect.top;
const submenuBottom = submenuRect.bottom+1; // add space for border
// Check if submenu fits in viewport
const fitsAbove = submenuTop >= 0;
const fitsBelow = submenuBottom <= viewport.height;
if (!fitsAbove || !fitsBelow) {
// Submenu doesn't fit - try to adjust position
// Overflows bottom, try to shift up
const overflow = submenuBottom - viewport.height;
const newTop = Math.max(0, submenuTop-overflow)-submenuTop;
submenu.style.top = newTop + 'px';
// Re-check after adjustment
const adjustedRect = submenu.getBoundingClientRect();
if (adjustedRect.height > viewport.height) {
// Still doesn't fit - enable scrolling
enableSubmenuScrolling(submenu, link);
}
}
}
// Helper function to enable scrolling for tall submenus
function enableSubmenuScrolling(submenu, link) {
// Check if scroll arrows already exist
if (submenu.dataset.scrollEnabled) return;
submenu.dataset.scrollEnabled = 'true';
const viewport = {
height: window.innerHeight,
scrollY: window.scrollY
};
// Position submenu to fill available viewport space
const parentRect = link.getBoundingClientRect();
const availableHeight = viewport.height - 2; // Leave some margin
submenu.style.maxHeight = availableHeight + 'px';
submenu.style.overflow = 'hidden';
submenu.style.position = 'absolute';
// Create scroll arrows
const scrollUpArrow = document.createElement('div');
scrollUpArrow.className = 'submenu-scroll-arrow submenu-scroll-up';
scrollUpArrow.innerHTML = '<span class="scroll-up-arrow"></span>';//'<span>▲</span>';
scrollUpArrow.style.cssText = 'position:absolute;top:0;left:0;right:0;height:30px;background:transparent;text-align:center;line-height:30px;color:#fff;cursor:pointer;z-index:1000;display:none;';
const scrollDownArrow = document.createElement('div');
scrollDownArrow.className = 'submenu-scroll-arrow submenu-scroll-down';
scrollDownArrow.innerHTML = '<span class="scroll-down-arrow"></span>';
scrollDownArrow.style.cssText = 'position:absolute;bottom:0;left:0;right:0;height:30px;background:transparent;text-align:center;line-height:30px;color:#fff;cursor:pointer;z-index:1000;';
// Create wrapper for submenu content
const scrollWrapper = document.createElement('div');
scrollWrapper.className = 'submenu-scroll-wrapper';
scrollWrapper.style.cssText = 'height:100vh;overflow:hidden;position:relative;';
// Move submenu children to wrapper
while (submenu.firstChild) {
scrollWrapper.appendChild(submenu.firstChild);
}
submenu.appendChild(scrollUpArrow);
submenu.appendChild(scrollWrapper);
submenu.appendChild(scrollDownArrow);
let scrollPosition = 0;
let scrollInterval = null;
function updateScrollArrows() {
const maxScroll = scrollWrapper.scrollHeight - availableHeight;
scrollUpArrow.style.display = scrollPosition > 0 ? 'block' : 'none';
scrollDownArrow.style.display = scrollPosition < maxScroll ? 'block' : 'none';
}
function startScrolling(direction) {
if (scrollInterval) return;
scrollInterval = setInterval(() => {
const maxScroll = scrollWrapper.scrollHeight - availableHeight;
if (direction === 'up') {
scrollPosition = Math.max(0, scrollPosition - ARROW_STEP);
} else {
scrollPosition = Math.min(maxScroll, scrollPosition + ARROW_STEP);
}
scrollWrapper.scrollTop = scrollPosition;
updateScrollArrows();
if ((direction === 'up' && scrollPosition === 0) ||
(direction === 'down' && scrollPosition === maxScroll)) {
stopScrolling();
}
}, ARROW_POLL_INTERVAL);
}
function stopScrolling() {
if (scrollInterval) {
clearInterval(scrollInterval);
scrollInterval = null;
}
}
scrollUpArrow.addEventListener('mouseenter', () => startScrolling('up'));
scrollUpArrow.addEventListener('mouseleave', stopScrolling);
scrollDownArrow.addEventListener('mouseenter', () => startScrolling('down'));
scrollDownArrow.addEventListener('mouseleave', stopScrolling);
function wheelEvent(e) {
e.preventDefault();
e.stopPropagation();
const maxScroll = scrollWrapper.scrollHeight - availableHeight;
const wheelDelta = e.deltaY;
const scrollAmount = wheelDelta > 0 ? WHEEL_STEP : -WHEEL_STEP; // Scroll 30px per wheel tick
scrollPosition = Math.max(0, Math.min(maxScroll, scrollPosition + scrollAmount));
scrollWrapper.scrollTop = scrollPosition;
updateScrollArrows();
}
// Add mouse wheel scrolling support
scrollWrapper.addEventListener('wheel', (e) => wheelEvent(e));
// Also add wheel event to submenu itself to catch events
submenu.addEventListener('wheel', function(e) {
// Only handle if scrolling is enabled
if (submenu.dataset.scrollEnabled) {
wheelEvent(e);
}
});
// Initial arrow state
updateScrollArrows();
}
// Helper function to clean up scroll arrows
function disableSubmenuScrolling(submenu) {
if (!submenu.dataset.scrollEnabled) return;
delete submenu.dataset.scrollEnabled;
// Find and remove scroll elements
const scrollArrows = submenu.querySelectorAll('.submenu-scroll-arrow');
const scrollWrapper = submenu.querySelector('.submenu-scroll-wrapper');
if (scrollWrapper) {
// Move children back to submenu
while (scrollWrapper.firstChild) {
submenu.appendChild(scrollWrapper.firstChild);
}
scrollWrapper.remove();
}
scrollArrows.forEach(arrow => arrow.remove());
// Reset styles
submenu.style.maxHeight = '';
submenu.style.overflow = '';
}
menuItems.forEach(item => {
const submenu = item.querySelector('ul');
if (submenu) {
const link = item.querySelector('a');
if (link) {
// Add class and ARIA attributes for accessibility
link.classList.add('has-submenu');
link.setAttribute('aria-haspopup', 'true');
link.setAttribute('aria-expanded', 'false');
// Add sub-arrow indicator
const span = document.createElement('span');
span.classList.add('sub-arrow');
link.append(span);
// Calculate nesting level for z-index
// Root menu (main-menu) is level 200 (above the search box at 102),
// first submenus are level 201, etc.
let nestingLevel = 200;
let currentElement = item.parentElement;
while (currentElement && currentElement.id !== 'main-menu') {
if (currentElement.tagName === 'UL') {
nestingLevel++;
}
currentElement = currentElement.parentElement;
}
// Apply z-index based on nesting level
// This ensures child menus with shadows appear above parent menus
submenu.style.zIndex = nestingLevel + 1;
// Check if this is a level 2+ submenu (nested within another dropdown)
const isNestedSubmenu = item.parentElement && item.parentElement.id !== 'main-menu';
// Timeout management for smooth menu navigation
let showTimeout = null;
let hideTimeout = null;
// Desktop: show on hover
item.addEventListener('mouseenter', function() {
if (!isMobile()) {
// Clear any pending hide timeout
if (hideTimeout) {
clearTimeout(hideTimeout);
hideTimeout = null;
}
// Set show timeout
showTimeout = setTimeout(() => {
// Hide all sibling menus at the same level before showing this one
const parentElement = item.parentElement;
if (parentElement) {
const siblings = parentElement.querySelectorAll(':scope > li');
siblings.forEach(sibling => {
if (sibling !== item) {
const siblingSubmenu = sibling.querySelector('ul');
const siblingLink = sibling.querySelector('a');
if (siblingSubmenu && siblingLink) {
siblingSubmenu.style.display = 'none';
siblingLink.setAttribute('aria-expanded', 'false');
disableSubmenuScrolling(siblingSubmenu);
}
}
});
}
submenu.style.display = 'block';
// Only apply positioning for nested submenus (level 2+)
if (isNestedSubmenu) {
positionNestedSubmenu(submenu, link);
}
link.setAttribute('aria-expanded', 'true');
showTimeout = null;
}, SHOW_DELAY);
}
});
item.addEventListener('mouseleave', function() {
if (!isMobile()) {
// Clear any pending show timeout
if (showTimeout) {
clearTimeout(showTimeout);
showTimeout = null;
}
// Set hide timeout
hideTimeout = setTimeout(() => {
submenu.style.display = 'none';
link.setAttribute('aria-expanded', 'false');
// Clean up scrolling if enabled
disableSubmenuScrolling(submenu);
hideTimeout = null;
}, HIDE_DELAY);
}
});
if (isMobile() && isNestedSubmenu) {
positionNestedSubmenu(submenu, link);
}
function toggleMenu() {
const isExpanded = link.getAttribute('aria-expanded') === 'true';
if (isExpanded) {
slideUp(submenu, SLIDE_DELAY, () => {
submenu.style.display = 'none';
link.setAttribute('aria-expanded', 'false');
link.classList.remove('highlighted')
disableSubmenuScrolling(submenu);
});
} else {
slideDown(submenu, SLIDE_DELAY, () => {
submenu.style.display = 'block';
link.classList.add('highlighted')
link.setAttribute('aria-expanded', 'true');
});
}
}
// Mobile/Touch: toggle on click
link.addEventListener('click', function(e) {
if (isMobile()) {
e.preventDefault();
toggleMenu();
}
});
// Keyboard navigation
link.addEventListener('keydown', function(e) {
if (e.key === 'Enter' || e.key === ' ') {
e.preventDefault();
toggleMenu();
} else if (e.key === 'Escape') {
submenu.style.display = 'none';
link.setAttribute('aria-expanded', 'false');
disableSubmenuScrolling(submenu);
link.focus();
}
});
}
}
});
// Helper function to close all open dropdown menus
closeAllDropdowns = function() {
menuItems.forEach(item => {
const submenu = item.querySelector('ul');
const link = item.querySelector('a.has-submenu');
if (submenu && link) {
disableSubmenuScrolling(submenu);
submenu.style.display = 'none';
submenu.style.marginLeft = 0;
link.setAttribute('aria-expanded', 'false');
link.classList.remove('highlighted');
}
});
};
// Close all dropdown menus when clicking a link (navigation to new page or anchor)
const allLinks = mainMenu.querySelectorAll('a');
allLinks.forEach(link => {
link.addEventListener('click', function() {
// Close dropdowns when navigating (unless it's a has-submenu link in mobile mode)
if (!link.classList.contains('has-submenu') || !isMobile()) {
if (closeAllDropdowns) {
closeAllDropdowns();
}
}
});
});
}
// Initialize dropdown menu behavior
initDropdownMenu();
// Close all open menus when browser back button is pressed
window.addEventListener('popstate', function() {
if (closeAllDropdowns) {
closeAllDropdowns();
}
});
}
/* @license-end */

27
menudata.js Normal file
View File

@@ -0,0 +1,27 @@
/*
@licstart The following is the entire license notice for the JavaScript code in this file.
The MIT License (MIT)
Copyright (C) 1997-2020 by Dimitri van Heesch
Permission is hereby granted, free of charge, to any person obtaining a copy of this software
and associated documentation files (the "Software"), to deal in the Software without restriction,
including without limitation the rights to use, copy, modify, merge, publish, distribute,
sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or
substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@licend The above is the entire license notice for the JavaScript code in this file
*/
var menudata={children:[
{text:"Main Page",url:"index.html"},
{text:"Related Pages",url:"pages.html"}]}

327
navtree.css Normal file
View File

@@ -0,0 +1,327 @@
#nav-tree .children_ul {
margin:0;
padding:4px;
}
#nav-tree ul {
list-style:none outside none;
margin:0px;
padding:0px;
}
#nav-tree li {
white-space:nowrap;
margin:0;
padding:0;
}
#nav-tree .plus {
margin:0px;
}
#nav-tree .selected {
position: relative;
background-color: #DCE2EF;
border-radius: 0 6px 6px 0;
/*margin-right: 5px;*/
}
#nav-tree img {
margin:0px;
padding:0px;
border:0px;
vertical-align: middle;
}
#nav-tree a {
text-decoration:none;
padding:0px;
margin:0px;
}
#nav-tree .label {
margin:0px;
padding:0px;
font: 12px 'Lucida Grande',Geneva,Helvetica,Arial,sans-serif;
line-height: 22px;
}
#nav-tree .label a {
padding:2px;
}
#nav-tree .selected a {
text-decoration:none;
color:#3D578C;
}
#nav-tree .children_ul {
margin:0px;
padding:0px;
}
#nav-tree .item {
margin: 0 6px 0 -5px;
padding: 0 0 0 5px;
height: 22px;
}
#nav-tree {
padding: 0px 0px;
font-size:14px;
overflow:auto;
}
#doc-content {
overflow:auto;
display:block;
padding:0px;
margin:0px;
-webkit-overflow-scrolling : touch; /* iOS 5+ */
}
#side-nav {
padding:0 6px 0 0;
margin: 0px;
display:block;
position: absolute;
left: 0px;
overflow : hidden;
}
.ui-resizable .ui-resizable-handle {
display:block;
}
.ui-resizable-e {
transition: opacity 0.5s ease;
background-color: #DCE2EF;
opacity:0;
cursor:col-resize;
height:100%;
right:0;
top:0;
width:6px;
position: relative;
}
.ui-resizable-e:after {
content: '';
display: block;
top: 50%;
left: 1px;
width: 2px;
height: 15px;
border-left: 1px solid #9CAFD4;
border-right: 1px solid #9CAFD4;
position: absolute;
}
.ui-resizable-e:hover {
opacity: 1;
}
.ui-resizable-handle {
display:none;
font-size:0.1px;
position:absolute;
z-index:1;
}
#nav-tree-contents {
margin: 6px 0px 0px 0px;
}
#nav-tree {
background-color: #F9FAFC;
-webkit-overflow-scrolling : touch; /* iOS 5+ */
scrollbar-width: thin;
border-right: 1px solid #C4CFE5;
padding-left: 5px;
}
#nav-sync {
position:absolute;
top:0px;
right:0px;
z-index:1;
}
#nav-sync img {
opacity:0.3;
}
div.nav-sync-icon {
position: relative;
width: 24px;
height: 17px;
left: -6px;
top: -1px;
opacity: 0.7;
display: inline-block;
background-color: #F9FAFC;
border: 1px solid #C4CFE5;
box-sizing: content-box;
}
div.nav-sync-icon:hover {
background-color: #EEF1F7;
opacity: 1.0;
}
div.nav-sync-icon.active:after {
content: '';
background-color: #F9FAFC;
border-top: 2px solid #C4CFE5;
position: absolute;
width: 16px;
height: 0px;
top: 7px;
left: 4px;
}
div.nav-sync-icon.active:hover:after {
border-top: 2px solid #6884BD;
}
span.sync-icon-left {
position: absolute;
padding: 0;
margin: 0;
top: 3px;
left: 4px;
display: inline-block;
width: 8px;
height: 8px;
border-left: 2px solid #C4CFE5;
border-top: 2px solid #C4CFE5;
transform: rotate(-45deg);
}
span.sync-icon-right {
position: absolute;
padding: 0;
margin: 0;
top: 3px;
left: 10px;
display: inline-block;
width: 8px;
height: 8px;
border-right: 2px solid #C4CFE5;
border-bottom: 2px solid #C4CFE5;
transform: rotate(-45deg);
}
div.nav-sync-icon:hover span.sync-icon-left {
border-left: 2px solid #6884BD;
border-top: 2px solid #6884BD;
}
div.nav-sync-icon:hover span.sync-icon-right {
border-right: 2px solid #6884BD;
border-bottom: 2px solid #6884BD;
}
#nav-path ul {
border-top: 1px solid #C4CFE5;
}
@media print
{
#nav-tree { display: none; }
div.ui-resizable-handle { display: none; position: relative; }
}
/*---------------------------*/
#container {
display: grid;
grid-template-columns: auto auto;
overflow: hidden;
}
#page-nav {
background: #F9FAFC;
display: block;
width: 250px;
box-sizing: content-box;
position: relative;
border-left: 1px solid #C4CFE5;
}
#page-nav-tree {
display: inline-block;
}
#page-nav-resize-handle {
transition: opacity 0.5s ease;
background-color: #DCE2EF;
opacity:0;
cursor:col-resize;
height:100%;
right:0;
top:0;
width:6px;
position: relative;
z-index: 1;
user-select: none;
}
#page-nav-resize-handle:after {
content: '';
display: block;
top: 50%;
left: 1px;
width: 2px;
height: 15px;
border-left: 1px solid #9CAFD4;
border-right: 1px solid #9CAFD4;
position: absolute;
}
#page-nav-resize-handle.dragging,
#page-nav-resize-handle:hover {
opacity: 1;
}
#page-nav-contents {
padding: 0;
margin: 0;
display: block;
top: 0;
left: 0;
height: 100%;
width: 100%;
position: absolute;
overflow: auto;
scrollbar-width: thin;
-webkit-overflow-scrolling : touch; /* iOS 5+ */
}
ul.page-outline,
ul.page-outline ul {
text-indent: 0;
list-style: none outside none;
padding: 0 0 0 4px;
}
ul.page-outline {
margin: 0 4px 4px 6px;
}
ul.page-outline div.item {
font: 12px 'Lucida Grande',Geneva,Helvetica,Arial,sans-serif;
line-height: 22px;
}
ul.page-outline li {
white-space: nowrap;
}
ul.page-outline li.vis {
background-color: #EEF1F7;
}
#container.resizing {
cursor: col-resize;
user-select: none;
}

1161
navtree.js Normal file

File diff suppressed because it is too large Load Diff

84
navtreedata.js Normal file
View File

@@ -0,0 +1,84 @@
/*
@licstart The following is the entire license notice for the JavaScript code in this file.
The MIT License (MIT)
Copyright (C) 1997-2020 by Dimitri van Heesch
Permission is hereby granted, free of charge, to any person obtaining a copy of this software
and associated documentation files (the "Software"), to deal in the Software without restriction,
including without limitation the rights to use, copy, modify, merge, publish, distribute,
sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or
substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@licend The above is the entire license notice for the JavaScript code in this file
*/
var NAVTREE =
[
[ "conformallab++", "index.html", [
[ "Quick start", "index.html#autotoc_md2", null ],
[ "Minimal usage", "index.html#autotoc_md4", null ],
[ "Documentation", "index.html#autotoc_md6", null ],
[ "Citing", "index.html#autotoc_md8", null ],
[ "Bugs &amp; questions", "index.html#autotoc_md10", null ],
[ "License", "index.html#autotoc_md12", null ],
[ "CLAUDE.md", "md__c_l_a_u_d_e.html", [
[ "Project purpose and long-term goal", "md__c_l_a_u_d_e.html#autotoc_md14", null ],
[ "Language", "md__c_l_a_u_d_e.html#autotoc_md15", null ],
[ "Build commands", "md__c_l_a_u_d_e.html#autotoc_md16", [
[ "Running a single test", "md__c_l_a_u_d_e.html#autotoc_md17", null ],
[ "Rebuilding the CI Docker image", "md__c_l_a_u_d_e.html#autotoc_md18", null ]
] ],
[ "Architecture", "md__c_l_a_u_d_e.html#autotoc_md19", [
[ "Everything is header-only", "md__c_l_a_u_d_e.html#autotoc_md20", null ],
[ "Central type: <span class=\"tt\">ConformalMesh</span>", "md__c_l_a_u_d_e.html#autotoc_md21", null ],
[ "The five DCE models", "md__c_l_a_u_d_e.html#autotoc_md22", null ],
[ "The full pipeline", "md__c_l_a_u_d_e.html#autotoc_md23", null ],
[ "Newton solver (<span class=\"tt\">newton_solver.hpp</span>)", "md__c_l_a_u_d_e.html#autotoc_md24", null ],
[ "Layout and holonomy (<span class=\"tt\">layout.hpp</span>)", "md__c_l_a_u_d_e.html#autotoc_md25", null ],
[ "Key mathematical reference for each header", "md__c_l_a_u_d_e.html#autotoc_md26", null ],
[ "Java features not yet ported (Phase 9)", "md__c_l_a_u_d_e.html#autotoc_md27", null ]
] ],
[ "Test design patterns", "md__c_l_a_u_d_e.html#autotoc_md28", [
[ "\"Natural theta\" — constructing a known equilibrium at x* = 0", "md__c_l_a_u_d_e.html#autotoc_md29", null ],
[ "Gradient check pattern", "md__c_l_a_u_d_e.html#autotoc_md30", null ],
[ "Halfedge traversal", "md__c_l_a_u_d_e.html#autotoc_md31", null ],
[ "Attaching custom data to the mesh", "md__c_l_a_u_d_e.html#autotoc_md32", null ]
] ],
[ "CI pipeline", "md__c_l_a_u_d_e.html#autotoc_md33", null ],
[ "Release state", "md__c_l_a_u_d_e.html#autotoc_md34", null ],
[ "Phase 8 strategic decisions (2026-05-19)", "md__c_l_a_u_d_e.html#autotoc_md35", [
[ "Implementation sequence (committed)", "md__c_l_a_u_d_e.html#autotoc_md36", null ]
] ],
[ "Port-vs-research maintenance rule (2026-05-21 audit)", "md__c_l_a_u_d_e.html#autotoc_md37", null ],
[ "Documentation map", "md__c_l_a_u_d_e.html#autotoc_md38", [
[ "Mathematics &amp; theory", "md__c_l_a_u_d_e.html#autotoc_md39", null ],
[ "Architecture &amp; design", "md__c_l_a_u_d_e.html#autotoc_md40", null ],
[ "API &amp; extension", "md__c_l_a_u_d_e.html#autotoc_md41", null ],
[ "Concepts &amp; specs", "md__c_l_a_u_d_e.html#autotoc_md42", null ],
[ "Roadmap &amp; porting", "md__c_l_a_u_d_e.html#autotoc_md43", null ],
[ "Tutorials &amp; onboarding", "md__c_l_a_u_d_e.html#autotoc_md44", null ],
[ "geometry-central context", "md__c_l_a_u_d_e.html#autotoc_md45", null ]
] ],
[ "Known quirks", "md__c_l_a_u_d_e.html#autotoc_md46", null ]
] ]
] ]
];
var NAVTREEINDEX =
[
"index.html"
];
const SYNCONMSG = 'click to disable panel synchronization';
const SYNCOFFMSG = 'click to enable panel synchronization';
const LISTOFALLMEMBERS = 'List of all members';

45
navtreeindex0.js Normal file
View File

@@ -0,0 +1,45 @@
var NAVTREEINDEX0 =
{
"index.html":[],
"index.html#autotoc_md10":[4],
"index.html#autotoc_md12":[5],
"index.html#autotoc_md2":[0],
"index.html#autotoc_md4":[1],
"index.html#autotoc_md6":[2],
"index.html#autotoc_md8":[3],
"md__c_l_a_u_d_e.html":[6],
"md__c_l_a_u_d_e.html#autotoc_md14":[6,0],
"md__c_l_a_u_d_e.html#autotoc_md15":[6,1],
"md__c_l_a_u_d_e.html#autotoc_md16":[6,2],
"md__c_l_a_u_d_e.html#autotoc_md17":[6,2,0],
"md__c_l_a_u_d_e.html#autotoc_md18":[6,2,1],
"md__c_l_a_u_d_e.html#autotoc_md19":[6,3],
"md__c_l_a_u_d_e.html#autotoc_md20":[6,3,0],
"md__c_l_a_u_d_e.html#autotoc_md21":[6,3,1],
"md__c_l_a_u_d_e.html#autotoc_md22":[6,3,2],
"md__c_l_a_u_d_e.html#autotoc_md23":[6,3,3],
"md__c_l_a_u_d_e.html#autotoc_md24":[6,3,4],
"md__c_l_a_u_d_e.html#autotoc_md25":[6,3,5],
"md__c_l_a_u_d_e.html#autotoc_md26":[6,3,6],
"md__c_l_a_u_d_e.html#autotoc_md27":[6,3,7],
"md__c_l_a_u_d_e.html#autotoc_md28":[6,4],
"md__c_l_a_u_d_e.html#autotoc_md29":[6,4,0],
"md__c_l_a_u_d_e.html#autotoc_md30":[6,4,1],
"md__c_l_a_u_d_e.html#autotoc_md31":[6,4,2],
"md__c_l_a_u_d_e.html#autotoc_md32":[6,4,3],
"md__c_l_a_u_d_e.html#autotoc_md33":[6,5],
"md__c_l_a_u_d_e.html#autotoc_md34":[6,6],
"md__c_l_a_u_d_e.html#autotoc_md35":[6,7],
"md__c_l_a_u_d_e.html#autotoc_md36":[6,7,0],
"md__c_l_a_u_d_e.html#autotoc_md37":[6,8],
"md__c_l_a_u_d_e.html#autotoc_md38":[6,9],
"md__c_l_a_u_d_e.html#autotoc_md39":[6,9,0],
"md__c_l_a_u_d_e.html#autotoc_md40":[6,9,1],
"md__c_l_a_u_d_e.html#autotoc_md41":[6,9,2],
"md__c_l_a_u_d_e.html#autotoc_md42":[6,9,3],
"md__c_l_a_u_d_e.html#autotoc_md43":[6,9,4],
"md__c_l_a_u_d_e.html#autotoc_md44":[6,9,5],
"md__c_l_a_u_d_e.html#autotoc_md45":[6,9,6],
"md__c_l_a_u_d_e.html#autotoc_md46":[6,10],
"pages.html":[]
};

138
pages.html Normal file
View File

@@ -0,0 +1,138 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" lang="en-US">
<head>
<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
<meta http-equiv="X-UA-Compatible" content="IE=11"/>
<meta name="generator" content="Doxygen 1.17.0"/>
<meta name="viewport" content="width=device-width, initial-scale=1"/>
<title>conformallab++: Related Pages</title>
<link href="tabs.css" rel="stylesheet" type="text/css"/>
<script type="text/javascript" src="dynsections.js"></script>
<script type="text/javascript" src="codefolding.js"></script>
<script type="text/javascript" src="clipboard.js"></script>
<link href="navtree.css" rel="stylesheet" type="text/css"/>
<script type="text/javascript" src="navtreedata.js"></script>
<script type="text/javascript" src="navtree.js"></script>
<script type="text/javascript" src="cookie.js"></script>
<link href="search/search.css" rel="stylesheet" type="text/css"/>
<script type="text/javascript" src="search/searchdata.js"></script>
<script type="text/javascript" src="search/search.js"></script>
<script type="module">
import mermaid from 'https://cdn.jsdelivr.net/npm/mermaid@11/dist/mermaid.esm.min.mjs';
const theme = 'default';
mermaid.initialize({ startOnLoad: true, theme: theme });
</script>
<link href="doxygen.css" rel="stylesheet" type="text/css" />
</head>
<body>
<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
<div id="titlearea">
<table cellspacing="0" cellpadding="0">
<tbody>
<tr id="projectrow">
<td id="projectalign">
<div id="projectname">conformallab++<span id="projectnumber">&#160;0.7.0</span>
</div>
<div id="projectbrief">Discrete conformal maps on triangle meshes — C++17 reimplementation of ConformalLab (TU Berlin)</div>
</td>
</tr>
</tbody>
</table>
</div>
<!-- end header part -->
<!-- Generated by Doxygen 1.17.0 -->
<script type="text/javascript">
let searchBox = new SearchBox("searchBox", "search/",'.html');
</script>
<script type="text/javascript">
document.addEventListener('DOMContentLoaded', codefold.init);
</script>
<script type="text/javascript" src="menudata.js"></script>
<script type="text/javascript" src="menu.js"></script>
<script type="text/javascript">
document.addEventListener('DOMContentLoaded', () => {
initMenu('',true);
init_search();
});
</script>
<div id="main-nav-mobile">
<div class="sm sm-dox"><input id="main-menu-state" type="checkbox"/>
<label class="main-menu-btn" for="main-menu-state">
<span class="main-menu-btn-icon"></span> Toggle main menu visibility</label>
<span id="searchBoxPos1" style="position:absolute;right:8px;top:8px;height:36px;"></span>
</div>
</div><!-- main-nav-mobile -->
<div id="main-nav">
<ul class="sm sm-dox" id="main-menu">
<li id="searchBoxPos2" style="float:right">
<div id="MSearchBox" class="MSearchBoxInactive">
<span class="left">
<span id="MSearchSelect" class="search-icon" onmouseover="return searchBox.OnSearchSelectShow()" onmouseout="return searchBox.OnSearchSelectHide()"><span class="search-icon-dropdown"></span></span>
<input type="text" id="MSearchField" value="" placeholder="Search" accesskey="S"
onfocus="searchBox.OnSearchFieldFocus(true)"
onblur="searchBox.OnSearchFieldFocus(false)"
onkeyup="searchBox.OnSearchFieldChange(event)"/>
</span><span class="right">
<a id="MSearchClose" href="javascript:searchBox.CloseResultsWindow()"><div id="MSearchCloseImg" class="close-icon"></div></a>
</span>
</div>
</li>
</ul>
</div><!-- main-nav -->
</div><!-- top -->
<div id="side-nav" class="ui-resizable side-nav-resizable">
<div id="nav-tree">
<div id="nav-tree-contents">
<div id="nav-sync" class="sync"></div>
</div>
</div>
<div id="splitbar" style="-moz-user-select:none;"
class="ui-resizable-handle">
</div>
</div>
<script type="text/javascript">
document.addEventListener('DOMContentLoaded',() => { initNavTree('pages.html','',''); });
</script>
<div id="container">
<div id="doc-content">
<!-- window showing the filter options -->
<div id="MSearchSelectWindow"
onmouseover="return searchBox.OnSearchSelectShow()"
onmouseout="return searchBox.OnSearchSelectHide()"
onkeydown="return searchBox.OnSearchSelectKey(event)">
</div>
<!-- iframe showing the search results (closed by default) -->
<div id="MSearchResultsWindow">
<div id="MSearchResults">
<div class="SRPage">
<div id="SRIndex">
<div id="SRResults"></div>
<div class="SRStatus" id="Loading">Loading...</div>
<div class="SRStatus" id="Searching">Searching...</div>
<div class="SRStatus" id="NoMatches">No Matches</div>
</div>
</div>
</div>
</div>
<div class="header">
<div class="headertitle"><div class="title">Related Pages</div></div>
</div><!--header-->
<div class="contents">
<div class="textblock">Here is a list of all related documentation pages:</div><div class="directory">
<table class="directory">
<tr id="row_0_" class="even"><td class="entry"><span style="width:16px;display:inline-block;">&#160;</span><a class="el" href="md__c_l_a_u_d_e.html" target="_self">CLAUDE.md</a></td><td class="desc"></td></tr>
</table>
</div><!-- directory -->
</div><!-- contents -->
</div><!-- doc-content -->
</div><!-- container -->
<!-- start footer part -->
<div id="nav-path" class="navpath"><!-- id is needed for treeview function! -->
<ul>
<li class="footer">Generated by <a href="https://www.doxygen.org/index.html"><img class="footer" src="doxygen.svg" width="104" height="31" alt="doxygen"/></a> 1.17.0 </li>
</ul>
</div>
</body>
</html>

6
search/all_0.js Normal file
View File

@@ -0,0 +1,6 @@
var searchData=
[
['0_0',['&quot;Natural theta&quot; — constructing a known equilibrium at x* = 0',['../md__c_l_a_u_d_e.html#autotoc_md29',1,'']]],
['05_2019_1',['Phase 8 strategic decisions (2026-05-19)',['../md__c_l_a_u_d_e.html#autotoc_md35',1,'']]],
['05_2021_20audit_2',['Port-vs-research maintenance rule (2026-05-21 audit)',['../md__c_l_a_u_d_e.html#autotoc_md37',1,'']]]
];

4
search/all_1.js Normal file
View File

@@ -0,0 +1,4 @@
var searchData=
[
['19_0',['Phase 8 strategic decisions (2026-05-19)',['../md__c_l_a_u_d_e.html#autotoc_md35',1,'']]]
];

8
search/all_10.js Normal file
View File

@@ -0,0 +1,8 @@
var searchData=
[
['language_0',['Language',['../md__c_l_a_u_d_e.html#autotoc_md15',1,'']]],
['layout_20and_20holonomy_20layout_20hpp_1',['Layout and holonomy (&lt;span class=&quot;tt&quot;&gt;layout.hpp&lt;/span&gt;)',['../md__c_l_a_u_d_e.html#autotoc_md25',1,'']]],
['layout_20hpp_2',['Layout and holonomy (&lt;span class=&quot;tt&quot;&gt;layout.hpp&lt;/span&gt;)',['../md__c_l_a_u_d_e.html#autotoc_md25',1,'']]],
['license_3',['License',['../index.html#autotoc_md12',1,'']]],
['long_20term_20goal_4',['Project purpose and long-term goal',['../md__c_l_a_u_d_e.html#autotoc_md14',1,'']]]
];

11
search/all_11.js Normal file
View File

@@ -0,0 +1,11 @@
var searchData=
[
['maintenance_20rule_202026_2005_2021_20audit_0',['Port-vs-research maintenance rule (2026-05-21 audit)',['../md__c_l_a_u_d_e.html#autotoc_md37',1,'']]],
['map_1',['Documentation map',['../md__c_l_a_u_d_e.html#autotoc_md38',1,'']]],
['mathematical_20reference_20for_20each_20header_2',['Key mathematical reference for each header',['../md__c_l_a_u_d_e.html#autotoc_md26',1,'']]],
['mathematics_20theory_3',['Mathematics &amp;amp; theory',['../md__c_l_a_u_d_e.html#autotoc_md39',1,'']]],
['md_4',['CLAUDE.md',['../md__c_l_a_u_d_e.html',1,'']]],
['mesh_5',['Attaching custom data to the mesh',['../md__c_l_a_u_d_e.html#autotoc_md32',1,'']]],
['minimal_20usage_6',['Minimal usage',['../index.html#autotoc_md4',1,'']]],
['models_7',['The five DCE models',['../md__c_l_a_u_d_e.html#autotoc_md22',1,'']]]
];

7
search/all_12.js Normal file
View File

@@ -0,0 +1,7 @@
var searchData=
[
['natural_20theta_20—_20constructing_20a_20known_20equilibrium_20at_20x_200_0',['&quot;Natural theta&quot; — constructing a known equilibrium at x* = 0',['../md__c_l_a_u_d_e.html#autotoc_md29',1,'']]],
['newton_20solver_20newton_5fsolver_20hpp_1',['Newton solver (&lt;span class=&quot;tt&quot;&gt;newton_solver.hpp&lt;/span&gt;)',['../md__c_l_a_u_d_e.html#autotoc_md24',1,'']]],
['newton_5fsolver_20hpp_2',['Newton solver (&lt;span class=&quot;tt&quot;&gt;newton_solver.hpp&lt;/span&gt;)',['../md__c_l_a_u_d_e.html#autotoc_md24',1,'']]],
['not_20yet_20ported_20phase_209_3',['Java features not yet ported (Phase 9)',['../md__c_l_a_u_d_e.html#autotoc_md27',1,'']]]
];

5
search/all_13.js Normal file
View File

@@ -0,0 +1,5 @@
var searchData=
[
['onboarding_0',['Tutorials &amp;amp; onboarding',['../md__c_l_a_u_d_e.html#autotoc_md44',1,'']]],
['only_1',['Everything is header-only',['../md__c_l_a_u_d_e.html#autotoc_md20',1,'']]]
];

13
search/all_14.js Normal file
View File

@@ -0,0 +1,13 @@
var searchData=
[
['pattern_0',['Gradient check pattern',['../md__c_l_a_u_d_e.html#autotoc_md30',1,'']]],
['patterns_1',['Test design patterns',['../md__c_l_a_u_d_e.html#autotoc_md28',1,'']]],
['phase_208_20strategic_20decisions_202026_2005_2019_2',['Phase 8 strategic decisions (2026-05-19)',['../md__c_l_a_u_d_e.html#autotoc_md35',1,'']]],
['phase_209_3',['Java features not yet ported (Phase 9)',['../md__c_l_a_u_d_e.html#autotoc_md27',1,'']]],
['pipeline_4',['pipeline',['../md__c_l_a_u_d_e.html#autotoc_md33',1,'CI pipeline'],['../md__c_l_a_u_d_e.html#autotoc_md23',1,'The full pipeline']]],
['port_20vs_20research_20maintenance_20rule_202026_2005_2021_20audit_5',['Port-vs-research maintenance rule (2026-05-21 audit)',['../md__c_l_a_u_d_e.html#autotoc_md37',1,'']]],
['ported_20phase_209_6',['Java features not yet ported (Phase 9)',['../md__c_l_a_u_d_e.html#autotoc_md27',1,'']]],
['porting_7',['Roadmap &amp;amp; porting',['../md__c_l_a_u_d_e.html#autotoc_md43',1,'']]],
['project_20purpose_20and_20long_20term_20goal_8',['Project purpose and long-term goal',['../md__c_l_a_u_d_e.html#autotoc_md14',1,'']]],
['purpose_20and_20long_20term_20goal_9',['Project purpose and long-term goal',['../md__c_l_a_u_d_e.html#autotoc_md14',1,'']]]
];

6
search/all_15.js Normal file
View File

@@ -0,0 +1,6 @@
var searchData=
[
['questions_0',['Bugs &amp;amp; questions',['../index.html#autotoc_md10',1,'']]],
['quick_20start_1',['Quick start',['../index.html#autotoc_md2',1,'']]],
['quirks_2',['Known quirks',['../md__c_l_a_u_d_e.html#autotoc_md46',1,'']]]
];

11
search/all_16.js Normal file
View File

@@ -0,0 +1,11 @@
var searchData=
[
['readme_2emd_0',['README.md',['../_r_e_a_d_m_e_8md.html',1,'']]],
['rebuilding_20the_20ci_20docker_20image_1',['Rebuilding the CI Docker image',['../md__c_l_a_u_d_e.html#autotoc_md18',1,'']]],
['reference_20for_20each_20header_2',['Key mathematical reference for each header',['../md__c_l_a_u_d_e.html#autotoc_md26',1,'']]],
['release_20state_3',['Release state',['../md__c_l_a_u_d_e.html#autotoc_md34',1,'']]],
['research_20maintenance_20rule_202026_2005_2021_20audit_4',['Port-vs-research maintenance rule (2026-05-21 audit)',['../md__c_l_a_u_d_e.html#autotoc_md37',1,'']]],
['roadmap_20porting_5',['Roadmap &amp;amp; porting',['../md__c_l_a_u_d_e.html#autotoc_md43',1,'']]],
['rule_202026_2005_2021_20audit_6',['Port-vs-research maintenance rule (2026-05-21 audit)',['../md__c_l_a_u_d_e.html#autotoc_md37',1,'']]],
['running_20a_20single_20test_7',['Running a single test',['../md__c_l_a_u_d_e.html#autotoc_md17',1,'']]]
];

10
search/all_17.js Normal file
View File

@@ -0,0 +1,10 @@
var searchData=
[
['sequence_20committed_0',['Implementation sequence (committed)',['../md__c_l_a_u_d_e.html#autotoc_md36',1,'']]],
['single_20test_1',['Running a single test',['../md__c_l_a_u_d_e.html#autotoc_md17',1,'']]],
['solver_20newton_5fsolver_20hpp_2',['Newton solver (&lt;span class=&quot;tt&quot;&gt;newton_solver.hpp&lt;/span&gt;)',['../md__c_l_a_u_d_e.html#autotoc_md24',1,'']]],
['specs_3',['Concepts &amp;amp; specs',['../md__c_l_a_u_d_e.html#autotoc_md42',1,'']]],
['start_4',['Quick start',['../index.html#autotoc_md2',1,'']]],
['state_5',['Release state',['../md__c_l_a_u_d_e.html#autotoc_md34',1,'']]],
['strategic_20decisions_202026_2005_2019_6',['Phase 8 strategic decisions (2026-05-19)',['../md__c_l_a_u_d_e.html#autotoc_md35',1,'']]]
];

16
search/all_18.js Normal file
View File

@@ -0,0 +1,16 @@
var searchData=
[
['term_20goal_0',['Project purpose and long-term goal',['../md__c_l_a_u_d_e.html#autotoc_md14',1,'']]],
['test_1',['Running a single test',['../md__c_l_a_u_d_e.html#autotoc_md17',1,'']]],
['test_20design_20patterns_2',['Test design patterns',['../md__c_l_a_u_d_e.html#autotoc_md28',1,'']]],
['the_20ci_20docker_20image_3',['Rebuilding the CI Docker image',['../md__c_l_a_u_d_e.html#autotoc_md18',1,'']]],
['the_20five_20dce_20models_4',['The five DCE models',['../md__c_l_a_u_d_e.html#autotoc_md22',1,'']]],
['the_20full_20pipeline_5',['The full pipeline',['../md__c_l_a_u_d_e.html#autotoc_md23',1,'']]],
['the_20mesh_6',['Attaching custom data to the mesh',['../md__c_l_a_u_d_e.html#autotoc_md32',1,'']]],
['theory_7',['Mathematics &amp;amp; theory',['../md__c_l_a_u_d_e.html#autotoc_md39',1,'']]],
['theta_20—_20constructing_20a_20known_20equilibrium_20at_20x_200_8',['&quot;Natural theta&quot; — constructing a known equilibrium at x* = 0',['../md__c_l_a_u_d_e.html#autotoc_md29',1,'']]],
['to_20the_20mesh_9',['Attaching custom data to the mesh',['../md__c_l_a_u_d_e.html#autotoc_md32',1,'']]],
['traversal_10',['Halfedge traversal',['../md__c_l_a_u_d_e.html#autotoc_md31',1,'']]],
['tutorials_20onboarding_11',['Tutorials &amp;amp; onboarding',['../md__c_l_a_u_d_e.html#autotoc_md44',1,'']]],
['type_3a_20conformalmesh_12',['Central type: &lt;span class=&quot;tt&quot;&gt;ConformalMesh&lt;/span&gt;',['../md__c_l_a_u_d_e.html#autotoc_md21',1,'']]]
];

4
search/all_19.js Normal file
View File

@@ -0,0 +1,4 @@
var searchData=
[
['usage_0',['Minimal usage',['../index.html#autotoc_md4',1,'']]]
];

4
search/all_1a.js Normal file
View File

@@ -0,0 +1,4 @@
var searchData=
[
['vs_20research_20maintenance_20rule_202026_2005_2021_20audit_0',['Port-vs-research maintenance rule (2026-05-21 audit)',['../md__c_l_a_u_d_e.html#autotoc_md37',1,'']]]
];

4
search/all_1b.js Normal file
View File

@@ -0,0 +1,4 @@
var searchData=
[
['x_200_0',['&quot;Natural theta&quot; — constructing a known equilibrium at x* = 0',['../md__c_l_a_u_d_e.html#autotoc_md29',1,'']]]
];

4
search/all_1c.js Normal file
View File

@@ -0,0 +1,4 @@
var searchData=
[
['yet_20ported_20phase_209_0',['Java features not yet ported (Phase 9)',['../md__c_l_a_u_d_e.html#autotoc_md27',1,'']]]
];

4
search/all_1d.js Normal file
View File

@@ -0,0 +1,4 @@
var searchData=
[
['—_20constructing_20a_20known_20equilibrium_20at_20x_200_0',['&quot;Natural theta&quot; — constructing a known equilibrium at x* = 0',['../md__c_l_a_u_d_e.html#autotoc_md29',1,'']]]
];

6
search/all_2.js Normal file
View File

@@ -0,0 +1,6 @@
var searchData=
[
['2026_2005_2019_0',['Phase 8 strategic decisions (2026-05-19)',['../md__c_l_a_u_d_e.html#autotoc_md35',1,'']]],
['2026_2005_2021_20audit_1',['Port-vs-research maintenance rule (2026-05-21 audit)',['../md__c_l_a_u_d_e.html#autotoc_md37',1,'']]],
['21_20audit_2',['Port-vs-research maintenance rule (2026-05-21 audit)',['../md__c_l_a_u_d_e.html#autotoc_md37',1,'']]]
];

4
search/all_3.js Normal file
View File

@@ -0,0 +1,4 @@
var searchData=
[
['8_20strategic_20decisions_202026_2005_2019_0',['Phase 8 strategic decisions (2026-05-19)',['../md__c_l_a_u_d_e.html#autotoc_md35',1,'']]]
];

4
search/all_4.js Normal file
View File

@@ -0,0 +1,4 @@
var searchData=
[
['9_0',['Java features not yet ported (Phase 9)',['../md__c_l_a_u_d_e.html#autotoc_md27',1,'']]]
];

13
search/all_5.js Normal file
View File

@@ -0,0 +1,13 @@
var searchData=
[
['a_20known_20equilibrium_20at_20x_200_0',['&quot;Natural theta&quot; — constructing a known equilibrium at x* = 0',['../md__c_l_a_u_d_e.html#autotoc_md29',1,'']]],
['a_20single_20test_1',['Running a single test',['../md__c_l_a_u_d_e.html#autotoc_md17',1,'']]],
['and_20holonomy_20layout_20hpp_2',['Layout and holonomy (&lt;span class=&quot;tt&quot;&gt;layout.hpp&lt;/span&gt;)',['../md__c_l_a_u_d_e.html#autotoc_md25',1,'']]],
['and_20long_20term_20goal_3',['Project purpose and long-term goal',['../md__c_l_a_u_d_e.html#autotoc_md14',1,'']]],
['api_20extension_4',['API &amp;amp; extension',['../md__c_l_a_u_d_e.html#autotoc_md41',1,'']]],
['architecture_5',['Architecture',['../md__c_l_a_u_d_e.html#autotoc_md19',1,'']]],
['architecture_20design_6',['Architecture &amp;amp; design',['../md__c_l_a_u_d_e.html#autotoc_md40',1,'']]],
['at_20x_200_7',['&quot;Natural theta&quot; — constructing a known equilibrium at x* = 0',['../md__c_l_a_u_d_e.html#autotoc_md29',1,'']]],
['attaching_20custom_20data_20to_20the_20mesh_8',['Attaching custom data to the mesh',['../md__c_l_a_u_d_e.html#autotoc_md32',1,'']]],
['audit_9',['Port-vs-research maintenance rule (2026-05-21 audit)',['../md__c_l_a_u_d_e.html#autotoc_md37',1,'']]]
];

5
search/all_6.js Normal file
View File

@@ -0,0 +1,5 @@
var searchData=
[
['bugs_20questions_0',['Bugs &amp;amp; questions',['../index.html#autotoc_md10',1,'']]],
['build_20commands_1',['Build commands',['../md__c_l_a_u_d_e.html#autotoc_md16',1,'']]]
];

19
search/all_7.js Normal file
View File

@@ -0,0 +1,19 @@
var searchData=
[
['central_20context_0',['geometry-central context',['../md__c_l_a_u_d_e.html#autotoc_md45',1,'']]],
['central_20type_3a_20conformalmesh_1',['Central type: &lt;span class=&quot;tt&quot;&gt;ConformalMesh&lt;/span&gt;',['../md__c_l_a_u_d_e.html#autotoc_md21',1,'']]],
['check_20pattern_2',['Gradient check pattern',['../md__c_l_a_u_d_e.html#autotoc_md30',1,'']]],
['ci_20docker_20image_3',['Rebuilding the CI Docker image',['../md__c_l_a_u_d_e.html#autotoc_md18',1,'']]],
['ci_20pipeline_4',['CI pipeline',['../md__c_l_a_u_d_e.html#autotoc_md33',1,'']]],
['citing_5',['Citing',['../index.html#autotoc_md8',1,'']]],
['claude_20md_6',['CLAUDE.md',['../md__c_l_a_u_d_e.html',1,'']]],
['claude_2emd_7',['CLAUDE.md',['../_c_l_a_u_d_e_8md.html',1,'']]],
['commands_8',['Build commands',['../md__c_l_a_u_d_e.html#autotoc_md16',1,'']]],
['committed_9',['Implementation sequence (committed)',['../md__c_l_a_u_d_e.html#autotoc_md36',1,'']]],
['concepts_20specs_10',['Concepts &amp;amp; specs',['../md__c_l_a_u_d_e.html#autotoc_md42',1,'']]],
['conformallab_11',['conformallab++',['../index.html',1,'']]],
['conformalmesh_12',['Central type: &lt;span class=&quot;tt&quot;&gt;ConformalMesh&lt;/span&gt;',['../md__c_l_a_u_d_e.html#autotoc_md21',1,'']]],
['constructing_20a_20known_20equilibrium_20at_20x_200_13',['&quot;Natural theta&quot; — constructing a known equilibrium at x* = 0',['../md__c_l_a_u_d_e.html#autotoc_md29',1,'']]],
['context_14',['geometry-central context',['../md__c_l_a_u_d_e.html#autotoc_md45',1,'']]],
['custom_20data_20to_20the_20mesh_15',['Attaching custom data to the mesh',['../md__c_l_a_u_d_e.html#autotoc_md32',1,'']]]
];

11
search/all_8.js Normal file
View File

@@ -0,0 +1,11 @@
var searchData=
[
['data_20to_20the_20mesh_0',['Attaching custom data to the mesh',['../md__c_l_a_u_d_e.html#autotoc_md32',1,'']]],
['dce_20models_1',['The five DCE models',['../md__c_l_a_u_d_e.html#autotoc_md22',1,'']]],
['decisions_202026_2005_2019_2',['Phase 8 strategic decisions (2026-05-19)',['../md__c_l_a_u_d_e.html#autotoc_md35',1,'']]],
['design_3',['Architecture &amp;amp; design',['../md__c_l_a_u_d_e.html#autotoc_md40',1,'']]],
['design_20patterns_4',['Test design patterns',['../md__c_l_a_u_d_e.html#autotoc_md28',1,'']]],
['docker_20image_5',['Rebuilding the CI Docker image',['../md__c_l_a_u_d_e.html#autotoc_md18',1,'']]],
['documentation_6',['Documentation',['../index.html#autotoc_md6',1,'']]],
['documentation_20map_7',['Documentation map',['../md__c_l_a_u_d_e.html#autotoc_md38',1,'']]]
];

7
search/all_9.js Normal file
View File

@@ -0,0 +1,7 @@
var searchData=
[
['each_20header_0',['Key mathematical reference for each header',['../md__c_l_a_u_d_e.html#autotoc_md26',1,'']]],
['equilibrium_20at_20x_200_1',['&quot;Natural theta&quot; — constructing a known equilibrium at x* = 0',['../md__c_l_a_u_d_e.html#autotoc_md29',1,'']]],
['everything_20is_20header_20only_2',['Everything is header-only',['../md__c_l_a_u_d_e.html#autotoc_md20',1,'']]],
['extension_3',['API &amp;amp; extension',['../md__c_l_a_u_d_e.html#autotoc_md41',1,'']]]
];

7
search/all_a.js Normal file
View File

@@ -0,0 +1,7 @@
var searchData=
[
['features_20not_20yet_20ported_20phase_209_0',['Java features not yet ported (Phase 9)',['../md__c_l_a_u_d_e.html#autotoc_md27',1,'']]],
['five_20dce_20models_1',['The five DCE models',['../md__c_l_a_u_d_e.html#autotoc_md22',1,'']]],
['for_20each_20header_2',['Key mathematical reference for each header',['../md__c_l_a_u_d_e.html#autotoc_md26',1,'']]],
['full_20pipeline_3',['The full pipeline',['../md__c_l_a_u_d_e.html#autotoc_md23',1,'']]]
];

6
search/all_b.js Normal file
View File

@@ -0,0 +1,6 @@
var searchData=
[
['geometry_20central_20context_0',['geometry-central context',['../md__c_l_a_u_d_e.html#autotoc_md45',1,'']]],
['goal_1',['Project purpose and long-term goal',['../md__c_l_a_u_d_e.html#autotoc_md14',1,'']]],
['gradient_20check_20pattern_2',['Gradient check pattern',['../md__c_l_a_u_d_e.html#autotoc_md30',1,'']]]
];

8
search/all_c.js Normal file
View File

@@ -0,0 +1,8 @@
var searchData=
[
['halfedge_20traversal_0',['Halfedge traversal',['../md__c_l_a_u_d_e.html#autotoc_md31',1,'']]],
['header_1',['Key mathematical reference for each header',['../md__c_l_a_u_d_e.html#autotoc_md26',1,'']]],
['header_20only_2',['Everything is header-only',['../md__c_l_a_u_d_e.html#autotoc_md20',1,'']]],
['holonomy_20layout_20hpp_3',['Layout and holonomy (&lt;span class=&quot;tt&quot;&gt;layout.hpp&lt;/span&gt;)',['../md__c_l_a_u_d_e.html#autotoc_md25',1,'']]],
['hpp_4',['hpp',['../md__c_l_a_u_d_e.html#autotoc_md25',1,'Layout and holonomy (&lt;span class=&quot;tt&quot;&gt;layout.hpp&lt;/span&gt;)'],['../md__c_l_a_u_d_e.html#autotoc_md24',1,'Newton solver (&lt;span class=&quot;tt&quot;&gt;newton_solver.hpp&lt;/span&gt;)']]]
];

6
search/all_d.js Normal file
View File

@@ -0,0 +1,6 @@
var searchData=
[
['image_0',['Rebuilding the CI Docker image',['../md__c_l_a_u_d_e.html#autotoc_md18',1,'']]],
['implementation_20sequence_20committed_1',['Implementation sequence (committed)',['../md__c_l_a_u_d_e.html#autotoc_md36',1,'']]],
['is_20header_20only_2',['Everything is header-only',['../md__c_l_a_u_d_e.html#autotoc_md20',1,'']]]
];

4
search/all_e.js Normal file
View File

@@ -0,0 +1,4 @@
var searchData=
[
['java_20features_20not_20yet_20ported_20phase_209_0',['Java features not yet ported (Phase 9)',['../md__c_l_a_u_d_e.html#autotoc_md27',1,'']]]
];

6
search/all_f.js Normal file
View File

@@ -0,0 +1,6 @@
var searchData=
[
['key_20mathematical_20reference_20for_20each_20header_0',['Key mathematical reference for each header',['../md__c_l_a_u_d_e.html#autotoc_md26',1,'']]],
['known_20equilibrium_20at_20x_200_1',['&quot;Natural theta&quot; — constructing a known equilibrium at x* = 0',['../md__c_l_a_u_d_e.html#autotoc_md29',1,'']]],
['known_20quirks_2',['Known quirks',['../md__c_l_a_u_d_e.html#autotoc_md46',1,'']]]
];

4
search/files_0.js Normal file
View File

@@ -0,0 +1,4 @@
var searchData=
[
['claude_2emd_0',['CLAUDE.md',['../_c_l_a_u_d_e_8md.html',1,'']]]
];

4
search/files_1.js Normal file
View File

@@ -0,0 +1,4 @@
var searchData=
[
['readme_2emd_0',['README.md',['../_r_e_a_d_m_e_8md.html',1,'']]]
];

6
search/pages_0.js Normal file
View File

@@ -0,0 +1,6 @@
var searchData=
[
['0_0',['&quot;Natural theta&quot; — constructing a known equilibrium at x* = 0',['../md__c_l_a_u_d_e.html#autotoc_md29',1,'']]],
['05_2019_1',['Phase 8 strategic decisions (2026-05-19)',['../md__c_l_a_u_d_e.html#autotoc_md35',1,'']]],
['05_2021_20audit_2',['Port-vs-research maintenance rule (2026-05-21 audit)',['../md__c_l_a_u_d_e.html#autotoc_md37',1,'']]]
];

4
search/pages_1.js Normal file
View File

@@ -0,0 +1,4 @@
var searchData=
[
['19_0',['Phase 8 strategic decisions (2026-05-19)',['../md__c_l_a_u_d_e.html#autotoc_md35',1,'']]]
];

8
search/pages_10.js Normal file
View File

@@ -0,0 +1,8 @@
var searchData=
[
['language_0',['Language',['../md__c_l_a_u_d_e.html#autotoc_md15',1,'']]],
['layout_20and_20holonomy_20layout_20hpp_1',['Layout and holonomy (&lt;span class=&quot;tt&quot;&gt;layout.hpp&lt;/span&gt;)',['../md__c_l_a_u_d_e.html#autotoc_md25',1,'']]],
['layout_20hpp_2',['Layout and holonomy (&lt;span class=&quot;tt&quot;&gt;layout.hpp&lt;/span&gt;)',['../md__c_l_a_u_d_e.html#autotoc_md25',1,'']]],
['license_3',['License',['../index.html#autotoc_md12',1,'']]],
['long_20term_20goal_4',['Project purpose and long-term goal',['../md__c_l_a_u_d_e.html#autotoc_md14',1,'']]]
];

11
search/pages_11.js Normal file
View File

@@ -0,0 +1,11 @@
var searchData=
[
['maintenance_20rule_202026_2005_2021_20audit_0',['Port-vs-research maintenance rule (2026-05-21 audit)',['../md__c_l_a_u_d_e.html#autotoc_md37',1,'']]],
['map_1',['Documentation map',['../md__c_l_a_u_d_e.html#autotoc_md38',1,'']]],
['mathematical_20reference_20for_20each_20header_2',['Key mathematical reference for each header',['../md__c_l_a_u_d_e.html#autotoc_md26',1,'']]],
['mathematics_20theory_3',['Mathematics &amp;amp; theory',['../md__c_l_a_u_d_e.html#autotoc_md39',1,'']]],
['md_4',['CLAUDE.md',['../md__c_l_a_u_d_e.html',1,'']]],
['mesh_5',['Attaching custom data to the mesh',['../md__c_l_a_u_d_e.html#autotoc_md32',1,'']]],
['minimal_20usage_6',['Minimal usage',['../index.html#autotoc_md4',1,'']]],
['models_7',['The five DCE models',['../md__c_l_a_u_d_e.html#autotoc_md22',1,'']]]
];

7
search/pages_12.js Normal file
View File

@@ -0,0 +1,7 @@
var searchData=
[
['natural_20theta_20—_20constructing_20a_20known_20equilibrium_20at_20x_200_0',['&quot;Natural theta&quot; — constructing a known equilibrium at x* = 0',['../md__c_l_a_u_d_e.html#autotoc_md29',1,'']]],
['newton_20solver_20newton_5fsolver_20hpp_1',['Newton solver (&lt;span class=&quot;tt&quot;&gt;newton_solver.hpp&lt;/span&gt;)',['../md__c_l_a_u_d_e.html#autotoc_md24',1,'']]],
['newton_5fsolver_20hpp_2',['Newton solver (&lt;span class=&quot;tt&quot;&gt;newton_solver.hpp&lt;/span&gt;)',['../md__c_l_a_u_d_e.html#autotoc_md24',1,'']]],
['not_20yet_20ported_20phase_209_3',['Java features not yet ported (Phase 9)',['../md__c_l_a_u_d_e.html#autotoc_md27',1,'']]]
];

5
search/pages_13.js Normal file
View File

@@ -0,0 +1,5 @@
var searchData=
[
['onboarding_0',['Tutorials &amp;amp; onboarding',['../md__c_l_a_u_d_e.html#autotoc_md44',1,'']]],
['only_1',['Everything is header-only',['../md__c_l_a_u_d_e.html#autotoc_md20',1,'']]]
];

13
search/pages_14.js Normal file
View File

@@ -0,0 +1,13 @@
var searchData=
[
['pattern_0',['Gradient check pattern',['../md__c_l_a_u_d_e.html#autotoc_md30',1,'']]],
['patterns_1',['Test design patterns',['../md__c_l_a_u_d_e.html#autotoc_md28',1,'']]],
['phase_208_20strategic_20decisions_202026_2005_2019_2',['Phase 8 strategic decisions (2026-05-19)',['../md__c_l_a_u_d_e.html#autotoc_md35',1,'']]],
['phase_209_3',['Java features not yet ported (Phase 9)',['../md__c_l_a_u_d_e.html#autotoc_md27',1,'']]],
['pipeline_4',['pipeline',['../md__c_l_a_u_d_e.html#autotoc_md33',1,'CI pipeline'],['../md__c_l_a_u_d_e.html#autotoc_md23',1,'The full pipeline']]],
['port_20vs_20research_20maintenance_20rule_202026_2005_2021_20audit_5',['Port-vs-research maintenance rule (2026-05-21 audit)',['../md__c_l_a_u_d_e.html#autotoc_md37',1,'']]],
['ported_20phase_209_6',['Java features not yet ported (Phase 9)',['../md__c_l_a_u_d_e.html#autotoc_md27',1,'']]],
['porting_7',['Roadmap &amp;amp; porting',['../md__c_l_a_u_d_e.html#autotoc_md43',1,'']]],
['project_20purpose_20and_20long_20term_20goal_8',['Project purpose and long-term goal',['../md__c_l_a_u_d_e.html#autotoc_md14',1,'']]],
['purpose_20and_20long_20term_20goal_9',['Project purpose and long-term goal',['../md__c_l_a_u_d_e.html#autotoc_md14',1,'']]]
];

6
search/pages_15.js Normal file
View File

@@ -0,0 +1,6 @@
var searchData=
[
['questions_0',['Bugs &amp;amp; questions',['../index.html#autotoc_md10',1,'']]],
['quick_20start_1',['Quick start',['../index.html#autotoc_md2',1,'']]],
['quirks_2',['Known quirks',['../md__c_l_a_u_d_e.html#autotoc_md46',1,'']]]
];

10
search/pages_16.js Normal file
View File

@@ -0,0 +1,10 @@
var searchData=
[
['rebuilding_20the_20ci_20docker_20image_0',['Rebuilding the CI Docker image',['../md__c_l_a_u_d_e.html#autotoc_md18',1,'']]],
['reference_20for_20each_20header_1',['Key mathematical reference for each header',['../md__c_l_a_u_d_e.html#autotoc_md26',1,'']]],
['release_20state_2',['Release state',['../md__c_l_a_u_d_e.html#autotoc_md34',1,'']]],
['research_20maintenance_20rule_202026_2005_2021_20audit_3',['Port-vs-research maintenance rule (2026-05-21 audit)',['../md__c_l_a_u_d_e.html#autotoc_md37',1,'']]],
['roadmap_20porting_4',['Roadmap &amp;amp; porting',['../md__c_l_a_u_d_e.html#autotoc_md43',1,'']]],
['rule_202026_2005_2021_20audit_5',['Port-vs-research maintenance rule (2026-05-21 audit)',['../md__c_l_a_u_d_e.html#autotoc_md37',1,'']]],
['running_20a_20single_20test_6',['Running a single test',['../md__c_l_a_u_d_e.html#autotoc_md17',1,'']]]
];

10
search/pages_17.js Normal file
View File

@@ -0,0 +1,10 @@
var searchData=
[
['sequence_20committed_0',['Implementation sequence (committed)',['../md__c_l_a_u_d_e.html#autotoc_md36',1,'']]],
['single_20test_1',['Running a single test',['../md__c_l_a_u_d_e.html#autotoc_md17',1,'']]],
['solver_20newton_5fsolver_20hpp_2',['Newton solver (&lt;span class=&quot;tt&quot;&gt;newton_solver.hpp&lt;/span&gt;)',['../md__c_l_a_u_d_e.html#autotoc_md24',1,'']]],
['specs_3',['Concepts &amp;amp; specs',['../md__c_l_a_u_d_e.html#autotoc_md42',1,'']]],
['start_4',['Quick start',['../index.html#autotoc_md2',1,'']]],
['state_5',['Release state',['../md__c_l_a_u_d_e.html#autotoc_md34',1,'']]],
['strategic_20decisions_202026_2005_2019_6',['Phase 8 strategic decisions (2026-05-19)',['../md__c_l_a_u_d_e.html#autotoc_md35',1,'']]]
];

16
search/pages_18.js Normal file
View File

@@ -0,0 +1,16 @@
var searchData=
[
['term_20goal_0',['Project purpose and long-term goal',['../md__c_l_a_u_d_e.html#autotoc_md14',1,'']]],
['test_1',['Running a single test',['../md__c_l_a_u_d_e.html#autotoc_md17',1,'']]],
['test_20design_20patterns_2',['Test design patterns',['../md__c_l_a_u_d_e.html#autotoc_md28',1,'']]],
['the_20ci_20docker_20image_3',['Rebuilding the CI Docker image',['../md__c_l_a_u_d_e.html#autotoc_md18',1,'']]],
['the_20five_20dce_20models_4',['The five DCE models',['../md__c_l_a_u_d_e.html#autotoc_md22',1,'']]],
['the_20full_20pipeline_5',['The full pipeline',['../md__c_l_a_u_d_e.html#autotoc_md23',1,'']]],
['the_20mesh_6',['Attaching custom data to the mesh',['../md__c_l_a_u_d_e.html#autotoc_md32',1,'']]],
['theory_7',['Mathematics &amp;amp; theory',['../md__c_l_a_u_d_e.html#autotoc_md39',1,'']]],
['theta_20—_20constructing_20a_20known_20equilibrium_20at_20x_200_8',['&quot;Natural theta&quot; — constructing a known equilibrium at x* = 0',['../md__c_l_a_u_d_e.html#autotoc_md29',1,'']]],
['to_20the_20mesh_9',['Attaching custom data to the mesh',['../md__c_l_a_u_d_e.html#autotoc_md32',1,'']]],
['traversal_10',['Halfedge traversal',['../md__c_l_a_u_d_e.html#autotoc_md31',1,'']]],
['tutorials_20onboarding_11',['Tutorials &amp;amp; onboarding',['../md__c_l_a_u_d_e.html#autotoc_md44',1,'']]],
['type_3a_20conformalmesh_12',['Central type: &lt;span class=&quot;tt&quot;&gt;ConformalMesh&lt;/span&gt;',['../md__c_l_a_u_d_e.html#autotoc_md21',1,'']]]
];

4
search/pages_19.js Normal file
View File

@@ -0,0 +1,4 @@
var searchData=
[
['usage_0',['Minimal usage',['../index.html#autotoc_md4',1,'']]]
];

4
search/pages_1a.js Normal file
View File

@@ -0,0 +1,4 @@
var searchData=
[
['vs_20research_20maintenance_20rule_202026_2005_2021_20audit_0',['Port-vs-research maintenance rule (2026-05-21 audit)',['../md__c_l_a_u_d_e.html#autotoc_md37',1,'']]]
];

4
search/pages_1b.js Normal file
View File

@@ -0,0 +1,4 @@
var searchData=
[
['x_200_0',['&quot;Natural theta&quot; — constructing a known equilibrium at x* = 0',['../md__c_l_a_u_d_e.html#autotoc_md29',1,'']]]
];

4
search/pages_1c.js Normal file
View File

@@ -0,0 +1,4 @@
var searchData=
[
['yet_20ported_20phase_209_0',['Java features not yet ported (Phase 9)',['../md__c_l_a_u_d_e.html#autotoc_md27',1,'']]]
];

4
search/pages_1d.js Normal file
View File

@@ -0,0 +1,4 @@
var searchData=
[
['—_20constructing_20a_20known_20equilibrium_20at_20x_200_0',['&quot;Natural theta&quot; — constructing a known equilibrium at x* = 0',['../md__c_l_a_u_d_e.html#autotoc_md29',1,'']]]
];

6
search/pages_2.js Normal file
View File

@@ -0,0 +1,6 @@
var searchData=
[
['2026_2005_2019_0',['Phase 8 strategic decisions (2026-05-19)',['../md__c_l_a_u_d_e.html#autotoc_md35',1,'']]],
['2026_2005_2021_20audit_1',['Port-vs-research maintenance rule (2026-05-21 audit)',['../md__c_l_a_u_d_e.html#autotoc_md37',1,'']]],
['21_20audit_2',['Port-vs-research maintenance rule (2026-05-21 audit)',['../md__c_l_a_u_d_e.html#autotoc_md37',1,'']]]
];

4
search/pages_3.js Normal file
View File

@@ -0,0 +1,4 @@
var searchData=
[
['8_20strategic_20decisions_202026_2005_2019_0',['Phase 8 strategic decisions (2026-05-19)',['../md__c_l_a_u_d_e.html#autotoc_md35',1,'']]]
];

4
search/pages_4.js Normal file
View File

@@ -0,0 +1,4 @@
var searchData=
[
['9_0',['Java features not yet ported (Phase 9)',['../md__c_l_a_u_d_e.html#autotoc_md27',1,'']]]
];

13
search/pages_5.js Normal file
View File

@@ -0,0 +1,13 @@
var searchData=
[
['a_20known_20equilibrium_20at_20x_200_0',['&quot;Natural theta&quot; — constructing a known equilibrium at x* = 0',['../md__c_l_a_u_d_e.html#autotoc_md29',1,'']]],
['a_20single_20test_1',['Running a single test',['../md__c_l_a_u_d_e.html#autotoc_md17',1,'']]],
['and_20holonomy_20layout_20hpp_2',['Layout and holonomy (&lt;span class=&quot;tt&quot;&gt;layout.hpp&lt;/span&gt;)',['../md__c_l_a_u_d_e.html#autotoc_md25',1,'']]],
['and_20long_20term_20goal_3',['Project purpose and long-term goal',['../md__c_l_a_u_d_e.html#autotoc_md14',1,'']]],
['api_20extension_4',['API &amp;amp; extension',['../md__c_l_a_u_d_e.html#autotoc_md41',1,'']]],
['architecture_5',['Architecture',['../md__c_l_a_u_d_e.html#autotoc_md19',1,'']]],
['architecture_20design_6',['Architecture &amp;amp; design',['../md__c_l_a_u_d_e.html#autotoc_md40',1,'']]],
['at_20x_200_7',['&quot;Natural theta&quot; — constructing a known equilibrium at x* = 0',['../md__c_l_a_u_d_e.html#autotoc_md29',1,'']]],
['attaching_20custom_20data_20to_20the_20mesh_8',['Attaching custom data to the mesh',['../md__c_l_a_u_d_e.html#autotoc_md32',1,'']]],
['audit_9',['Port-vs-research maintenance rule (2026-05-21 audit)',['../md__c_l_a_u_d_e.html#autotoc_md37',1,'']]]
];

5
search/pages_6.js Normal file
View File

@@ -0,0 +1,5 @@
var searchData=
[
['bugs_20questions_0',['Bugs &amp;amp; questions',['../index.html#autotoc_md10',1,'']]],
['build_20commands_1',['Build commands',['../md__c_l_a_u_d_e.html#autotoc_md16',1,'']]]
];

18
search/pages_7.js Normal file
View File

@@ -0,0 +1,18 @@
var searchData=
[
['central_20context_0',['geometry-central context',['../md__c_l_a_u_d_e.html#autotoc_md45',1,'']]],
['central_20type_3a_20conformalmesh_1',['Central type: &lt;span class=&quot;tt&quot;&gt;ConformalMesh&lt;/span&gt;',['../md__c_l_a_u_d_e.html#autotoc_md21',1,'']]],
['check_20pattern_2',['Gradient check pattern',['../md__c_l_a_u_d_e.html#autotoc_md30',1,'']]],
['ci_20docker_20image_3',['Rebuilding the CI Docker image',['../md__c_l_a_u_d_e.html#autotoc_md18',1,'']]],
['ci_20pipeline_4',['CI pipeline',['../md__c_l_a_u_d_e.html#autotoc_md33',1,'']]],
['citing_5',['Citing',['../index.html#autotoc_md8',1,'']]],
['claude_20md_6',['CLAUDE.md',['../md__c_l_a_u_d_e.html',1,'']]],
['commands_7',['Build commands',['../md__c_l_a_u_d_e.html#autotoc_md16',1,'']]],
['committed_8',['Implementation sequence (committed)',['../md__c_l_a_u_d_e.html#autotoc_md36',1,'']]],
['concepts_20specs_9',['Concepts &amp;amp; specs',['../md__c_l_a_u_d_e.html#autotoc_md42',1,'']]],
['conformallab_10',['conformallab++',['../index.html',1,'']]],
['conformalmesh_11',['Central type: &lt;span class=&quot;tt&quot;&gt;ConformalMesh&lt;/span&gt;',['../md__c_l_a_u_d_e.html#autotoc_md21',1,'']]],
['constructing_20a_20known_20equilibrium_20at_20x_200_12',['&quot;Natural theta&quot; — constructing a known equilibrium at x* = 0',['../md__c_l_a_u_d_e.html#autotoc_md29',1,'']]],
['context_13',['geometry-central context',['../md__c_l_a_u_d_e.html#autotoc_md45',1,'']]],
['custom_20data_20to_20the_20mesh_14',['Attaching custom data to the mesh',['../md__c_l_a_u_d_e.html#autotoc_md32',1,'']]]
];

11
search/pages_8.js Normal file
View File

@@ -0,0 +1,11 @@
var searchData=
[
['data_20to_20the_20mesh_0',['Attaching custom data to the mesh',['../md__c_l_a_u_d_e.html#autotoc_md32',1,'']]],
['dce_20models_1',['The five DCE models',['../md__c_l_a_u_d_e.html#autotoc_md22',1,'']]],
['decisions_202026_2005_2019_2',['Phase 8 strategic decisions (2026-05-19)',['../md__c_l_a_u_d_e.html#autotoc_md35',1,'']]],
['design_3',['Architecture &amp;amp; design',['../md__c_l_a_u_d_e.html#autotoc_md40',1,'']]],
['design_20patterns_4',['Test design patterns',['../md__c_l_a_u_d_e.html#autotoc_md28',1,'']]],
['docker_20image_5',['Rebuilding the CI Docker image',['../md__c_l_a_u_d_e.html#autotoc_md18',1,'']]],
['documentation_6',['Documentation',['../index.html#autotoc_md6',1,'']]],
['documentation_20map_7',['Documentation map',['../md__c_l_a_u_d_e.html#autotoc_md38',1,'']]]
];

7
search/pages_9.js Normal file
View File

@@ -0,0 +1,7 @@
var searchData=
[
['each_20header_0',['Key mathematical reference for each header',['../md__c_l_a_u_d_e.html#autotoc_md26',1,'']]],
['equilibrium_20at_20x_200_1',['&quot;Natural theta&quot; — constructing a known equilibrium at x* = 0',['../md__c_l_a_u_d_e.html#autotoc_md29',1,'']]],
['everything_20is_20header_20only_2',['Everything is header-only',['../md__c_l_a_u_d_e.html#autotoc_md20',1,'']]],
['extension_3',['API &amp;amp; extension',['../md__c_l_a_u_d_e.html#autotoc_md41',1,'']]]
];

7
search/pages_a.js Normal file
View File

@@ -0,0 +1,7 @@
var searchData=
[
['features_20not_20yet_20ported_20phase_209_0',['Java features not yet ported (Phase 9)',['../md__c_l_a_u_d_e.html#autotoc_md27',1,'']]],
['five_20dce_20models_1',['The five DCE models',['../md__c_l_a_u_d_e.html#autotoc_md22',1,'']]],
['for_20each_20header_2',['Key mathematical reference for each header',['../md__c_l_a_u_d_e.html#autotoc_md26',1,'']]],
['full_20pipeline_3',['The full pipeline',['../md__c_l_a_u_d_e.html#autotoc_md23',1,'']]]
];

6
search/pages_b.js Normal file
View File

@@ -0,0 +1,6 @@
var searchData=
[
['geometry_20central_20context_0',['geometry-central context',['../md__c_l_a_u_d_e.html#autotoc_md45',1,'']]],
['goal_1',['Project purpose and long-term goal',['../md__c_l_a_u_d_e.html#autotoc_md14',1,'']]],
['gradient_20check_20pattern_2',['Gradient check pattern',['../md__c_l_a_u_d_e.html#autotoc_md30',1,'']]]
];

8
search/pages_c.js Normal file
View File

@@ -0,0 +1,8 @@
var searchData=
[
['halfedge_20traversal_0',['Halfedge traversal',['../md__c_l_a_u_d_e.html#autotoc_md31',1,'']]],
['header_1',['Key mathematical reference for each header',['../md__c_l_a_u_d_e.html#autotoc_md26',1,'']]],
['header_20only_2',['Everything is header-only',['../md__c_l_a_u_d_e.html#autotoc_md20',1,'']]],
['holonomy_20layout_20hpp_3',['Layout and holonomy (&lt;span class=&quot;tt&quot;&gt;layout.hpp&lt;/span&gt;)',['../md__c_l_a_u_d_e.html#autotoc_md25',1,'']]],
['hpp_4',['hpp',['../md__c_l_a_u_d_e.html#autotoc_md25',1,'Layout and holonomy (&lt;span class=&quot;tt&quot;&gt;layout.hpp&lt;/span&gt;)'],['../md__c_l_a_u_d_e.html#autotoc_md24',1,'Newton solver (&lt;span class=&quot;tt&quot;&gt;newton_solver.hpp&lt;/span&gt;)']]]
];

6
search/pages_d.js Normal file
View File

@@ -0,0 +1,6 @@
var searchData=
[
['image_0',['Rebuilding the CI Docker image',['../md__c_l_a_u_d_e.html#autotoc_md18',1,'']]],
['implementation_20sequence_20committed_1',['Implementation sequence (committed)',['../md__c_l_a_u_d_e.html#autotoc_md36',1,'']]],
['is_20header_20only_2',['Everything is header-only',['../md__c_l_a_u_d_e.html#autotoc_md20',1,'']]]
];

4
search/pages_e.js Normal file
View File

@@ -0,0 +1,4 @@
var searchData=
[
['java_20features_20not_20yet_20ported_20phase_209_0',['Java features not yet ported (Phase 9)',['../md__c_l_a_u_d_e.html#autotoc_md27',1,'']]]
];

6
search/pages_f.js Normal file
View File

@@ -0,0 +1,6 @@
var searchData=
[
['key_20mathematical_20reference_20for_20each_20header_0',['Key mathematical reference for each header',['../md__c_l_a_u_d_e.html#autotoc_md26',1,'']]],
['known_20equilibrium_20at_20x_200_1',['&quot;Natural theta&quot; — constructing a known equilibrium at x* = 0',['../md__c_l_a_u_d_e.html#autotoc_md29',1,'']]],
['known_20quirks_2',['Known quirks',['../md__c_l_a_u_d_e.html#autotoc_md46',1,'']]]
];

377
search/search.css Normal file
View File

@@ -0,0 +1,377 @@
/*---------------- Search Box positioning */
#main-menu > li:last-child {
/* This <li> object is the parent of the search bar */
display: flex;
justify-content: center;
align-items: center;
height: 43px;
margin-right: 0;
}
/*---------------- Search box styling */
.SRPage * {
font-weight: normal;
line-height: normal;
}
dark-mode-toggle {
margin-left: 5px;
display: flex;
float: right;
}
#MSearchBox {
display: inline-block;
white-space : nowrap;
background: white;
border-radius: 0.65em;
border: 1px solid #B6C4DF;
z-index: 102;
margin-right: 4px;
}
#MSearchBox .left {
display: inline-block;
vertical-align: middle;
height: 1.6em;
}
#MSearchField {
display: inline-block;
vertical-align: top;
width: 7.5em;
height: 22px;
margin: 0 0 0 0.15em;
padding: 0;
line-height: 1em;
border:none;
color: #909090;
outline: none;
font-family: Arial,Verdana,sans-serif;
-webkit-border-radius: 0px;
border-radius: 0px;
background: none;
}
@media(hover: none) {
/* to avoid zooming on iOS */
#MSearchField {
font-size: 16px;
}
}
#MSearchBox .right {
display: inline-block;
vertical-align: middle;
width: 1.4em;
height: 1.6em;
}
#MSearchClose {
display: none;
font-size: inherit;
background : none;
border: none;
margin: 0;
padding: 0;
outline: none;
}
#MSearchCloseImg {
margin: 6px 0 0 4px;
}
.close-icon {
width: 11px;
height: 11px;
background-color: #A0A0A0;
border-radius: 50%;
position: relative;
display: flex;
justify-content: center;
align-items: center;
box-sizing: content-box;
}
.close-icon:before,
.close-icon:after {
content: '';
position: absolute;
width: 7px;
height: 1px;
background-color: white;
}
.close-icon:before {
transform: rotate(45deg);
}
.close-icon:after {
transform: rotate(-45deg);
}
.MSearchBoxActive #MSearchField {
color: black;
}
.search-icon {
width: 20px;
height: 20px;
display: inline-block;
position: relative;
margin-left: 3px;
}
#MSearchSelectExt.search-icon {
width: 10px;
}
#MSearchSelectExt + input {
margin-left: 5px;
}
.search-icon::before, .search-icon::after {
content: '';
position: absolute;
border: 1.5px solid #909090;
box-sizing: content-box;
}
.search-icon::before {
width: 6px;
height: 6px;
border-radius: 50%;
top: 7px;
left: 2px;
background: white;
}
.search-icon::after {
border: 1px solid #909090;
width: 0px;
height: 3px;
border-radius: 2px;
top: 15px;
left: 8px;
transform: rotate(-45deg);
transform-origin: top left;
}
.search-icon-dropdown {
content: '';
width: 0;
height: 0;
border-left: 3px solid transparent;
border-right: 3px solid transparent;
border-top: 3px solid #909090;
top: 8px;
left: 15px;
transform: translateX(-50%);
position: absolute;
}
/*---------------- Search filter selection */
#MSearchSelectWindow {
display: none;
position: absolute;
left: 0; top: 0;
border: 1px solid rgba(150,150,150,.4);
background-color: rgba(255,255,255,.7);
backdrop-filter: blur(4px);
-webkit-backdrop-filter: blur(4px);
z-index: 10001;
padding-top: 4px;
padding-bottom: 4px;
border-radius: 4px;
}
.SelectItem {
font: 8pt Arial,Verdana,sans-serif;
padding-left: 2px;
padding-right: 12px;
border: 0px;
}
span.SelectionMark {
margin-right: 4px;
font-family: 'JetBrains Mono',Consolas,Monaco,'Andale Mono','Ubuntu Mono',monospace,fixed;
outline-style: none;
text-decoration: none;
}
a.SelectItem {
display: block;
outline-style: none;
color: black;
text-decoration: none;
padding-left: 6px;
padding-right: 12px;
}
a.SelectItem:focus,
a.SelectItem:active {
color: black;
outline-style: none;
text-decoration: none;
}
a.SelectItem:hover {
color: white;
background-color: #3D578C;
outline-style: none;
text-decoration: none;
cursor: pointer;
display: block;
}
/*---------------- Search results window */
iframe#MSearchResults {
/*width: 60ex;*/
height: 15em;
}
@keyframes slideInSearchResults {
from {
opacity: 0;
transform: translate(0, 15px);
}
to {
opacity: 1;
transform: translate(0, 20px);
}
}
#MSearchResultsWindow {
display: none;
position: absolute;
left: auto;
right: 4px;
top: 0;
border: 1px solid rgba(150,150,150,.4);
background-color: rgba(255,255,255,.8);
backdrop-filter: blur(4px);
-webkit-backdrop-filter: blur(4px);
z-index:10000;
width: 300px;
height: 400px;
overflow: auto;
border-radius: 8px;
transform: translate(0, 20px);
animation: ease-out 280ms slideInSearchResults;
box-shadow: 0 2px 8px 0 rgba(0,0,0,.075);
}
/* ----------------------------------- */
#SRIndex {
clear:both;
}
.SREntry {
font-size: 10pt;
padding-left: 1ex;
}
.SRPage .SREntry {
font-size: 10pt;
padding: 2px 5px;
}
div.SRPage {
margin: 5px 2px;
}
.SRChildren {
padding-left: 3ex; padding-bottom: .5em
}
.SRPage .SRChildren {
display: none;
}
.SRSymbol {
font-weight: bold;
color: #425E97;
font-family: Arial,Verdana,sans-serif;
text-decoration: none;
outline: none;
}
a.SRScope {
display: block;
color: #425E97;
font-family: Arial,Verdana,sans-serif;
font-size: 8pt;
text-decoration: none;
outline: none;
}
a.SRSymbol:focus, a.SRSymbol:active,
a.SRScope:focus, a.SRScope:active {
text-decoration: underline;
}
span.SRScope {
padding-left: 4px;
font-family: Arial,Verdana,sans-serif;
}
.SRPage .SRStatus {
padding: 2px 5px;
font-size: 8pt;
font-style: italic;
font-family: Arial,Verdana,sans-serif;
}
.SRResult {
display: none;
}
div.searchresults {
margin-left: 10px;
margin-right: 10px;
}
#searchBoxPos1 dark-mode-toggle {
margin-top: 4px;
}
/*---------------- External search page results */
.pages b {
color: #364D7C;
padding: 5px 5px 3px 5px;
background-color: #DCE2EF;
border-radius: 4px;
}
.pages {
line-height: 17px;
margin-left: 4px;
text-decoration: none;
}
.hl {
font-weight: bold;
}
#searchresults {
margin-bottom: 20px;
}
.searchpages {
margin-top: 10px;
}

708
search/search.js Normal file
View File

@@ -0,0 +1,708 @@
/*
@licstart The following is the entire license notice for the JavaScript code in this file.
The MIT License (MIT)
Copyright (C) 1997-2020 by Dimitri van Heesch
Permission is hereby granted, free of charge, to any person obtaining a copy of this software
and associated documentation files (the "Software"), to deal in the Software without restriction,
including without limitation the rights to use, copy, modify, merge, publish, distribute,
sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or
substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@licend The above is the entire license notice for the JavaScript code in this file
*/
const SEARCH_COOKIE_NAME = ''+'search_grp';
const searchResults = new SearchResults();
/* A class handling everything associated with the search panel.
Parameters:
name - The name of the global variable that will be
storing this instance. Is needed to be able to set timeouts.
resultPath - path to use for external files
*/
function SearchBox(name, resultsPath, extension) {
if (!name || !resultsPath) { alert("Missing parameters to SearchBox."); }
if (!extension || extension == "") { extension = ".html"; }
function getXPos(item) {
let x = 0;
if (item.offsetWidth) {
while (item && item!=document.body) {
x += item.offsetLeft;
item = item.offsetParent;
}
}
return x;
}
function getYPos(item) {
let y = 0;
if (item.offsetWidth) {
while (item && item!=document.body) {
y += item.offsetTop;
item = item.offsetParent;
}
}
return y;
}
// ---------- Instance variables
this.name = name;
this.resultsPath = resultsPath;
this.keyTimeout = 0;
this.keyTimeoutLength = 500;
this.closeSelectionTimeout = 300;
this.lastSearchValue = "";
this.lastResultsPage = "";
this.hideTimeout = 0;
this.searchIndex = 0;
this.searchActive = false;
this.extension = extension;
// ----------- DOM Elements
this.DOMSearchField = () => document.getElementById("MSearchField");
this.DOMSearchSelect = () => document.getElementById("MSearchSelect");
this.DOMSearchSelectWindow = () => document.getElementById("MSearchSelectWindow");
this.DOMPopupSearchResults = () => document.getElementById("MSearchResults");
this.DOMPopupSearchResultsWindow = () => document.getElementById("MSearchResultsWindow");
this.DOMSearchClose = () => document.getElementById("MSearchClose");
this.DOMSearchBox = () => document.getElementById("MSearchBox");
// ------------ Event Handlers
// Called when focus is added or removed from the search field.
this.OnSearchFieldFocus = function(isActive) {
this.Activate(isActive);
}
this.OnSearchSelectShow = function() {
const searchSelectWindow = this.DOMSearchSelectWindow();
const searchField = this.DOMSearchSelect();
const left = getXPos(searchField);
const top = getYPos(searchField) + searchField.offsetHeight;
// show search selection popup
searchSelectWindow.style.display='block';
searchSelectWindow.style.left = left + 'px';
searchSelectWindow.style.top = top + 'px';
// stop selection hide timer
if (this.hideTimeout) {
clearTimeout(this.hideTimeout);
this.hideTimeout=0;
}
return false; // to avoid "image drag" default event
}
this.OnSearchSelectHide = function() {
this.hideTimeout = setTimeout(this.CloseSelectionWindow.bind(this),
this.closeSelectionTimeout);
}
// Called when the content of the search field is changed.
this.OnSearchFieldChange = function(evt) {
if (this.keyTimeout) { // kill running timer
clearTimeout(this.keyTimeout);
this.keyTimeout = 0;
}
const e = evt ? evt : window.event; // for IE
if (e.keyCode==40 || e.keyCode==13) {
if (e.shiftKey==1) {
this.OnSearchSelectShow();
const win=this.DOMSearchSelectWindow();
for (let i=0;i<win.childNodes.length;i++) {
const child = win.childNodes[i]; // get span within a
if (child.className=='SelectItem') {
child.focus();
return;
}
}
return;
} else {
const elem = searchResults.NavNext(0);
if (elem) elem.focus();
}
} else if (e.keyCode==27) { // Escape out of the search field
e.stopPropagation();
this.DOMSearchField().blur();
this.DOMPopupSearchResultsWindow().style.display = 'none';
this.DOMSearchClose().style.display = 'none';
this.lastSearchValue = '';
this.Activate(false);
return;
}
// strip whitespaces
const searchValue = this.DOMSearchField().value.replace(/ +/g, "");
if (searchValue != this.lastSearchValue) { // search value has changed
if (searchValue != "") { // non-empty search
// set timer for search update
this.keyTimeout = setTimeout(this.Search.bind(this), this.keyTimeoutLength);
} else { // empty search field
this.DOMPopupSearchResultsWindow().style.display = 'none';
this.DOMSearchClose().style.display = 'none';
this.lastSearchValue = '';
}
}
}
this.SelectItemCount = function() {
let count=0;
const win=this.DOMSearchSelectWindow();
for (let i=0;i<win.childNodes.length;i++) {
const child = win.childNodes[i]; // get span within a
if (child.className=='SelectItem') {
count++;
}
}
return count;
}
this.GetSelectionIdByName = function(name) {
let j=0;
const win=this.DOMSearchSelectWindow();
for (let i=0;i<win.childNodes.length;i++) {
const child = win.childNodes[i];
if (child.className=='SelectItem') {
if (child.childNodes[1].nodeValue==name) {
return j;
}
j++;
}
}
return 0;
}
this.SelectItemSet = function(id) {
let j=0;
const win=this.DOMSearchSelectWindow();
for (let i=0;i<win.childNodes.length;i++) {
const child = win.childNodes[i]; // get span within a
if (child.className=='SelectItem') {
const node = child.firstChild;
if (j==id) {
node.innerHTML='&#8226;';
Cookie.writeSetting(SEARCH_COOKIE_NAME, child.childNodes[1].nodeValue, 0)
} else {
node.innerHTML='&#160;';
}
j++;
}
}
}
// Called when an search filter selection is made.
// set item with index id as the active item
this.OnSelectItem = function(id) {
this.searchIndex = id;
this.SelectItemSet(id);
const searchValue = this.DOMSearchField().value.replace(/ +/g, "");
if (searchValue!="" && this.searchActive) { // something was found -> do a search
this.Search();
}
}
this.OnSearchSelectKey = function(evt) {
const e = (evt) ? evt : window.event; // for IE
if (e.keyCode==40 && this.searchIndex<this.SelectItemCount()) { // Down
this.searchIndex++;
this.OnSelectItem(this.searchIndex);
} else if (e.keyCode==38 && this.searchIndex>0) { // Up
this.searchIndex--;
this.OnSelectItem(this.searchIndex);
} else if (e.keyCode==13 || e.keyCode==27) {
e.stopPropagation();
this.OnSelectItem(this.searchIndex);
this.CloseSelectionWindow();
this.DOMSearchField().focus();
}
return false;
}
// --------- Actions
// Closes the results window.
this.CloseResultsWindow = function() {
this.DOMPopupSearchResultsWindow().style.display = 'none';
this.DOMSearchClose().style.display = 'none';
this.Activate(false);
}
this.CloseSelectionWindow = function() {
this.DOMSearchSelectWindow().style.display = 'none';
}
// Performs a search.
this.Search = function() {
this.keyTimeout = 0;
// strip leading whitespace
const searchValue = this.DOMSearchField().value.replace(/^ +/, "");
const code = searchValue.toLowerCase().charCodeAt(0);
let idxChar = searchValue.substr(0, 1).toLowerCase();
if ( 0xD800 <= code && code <= 0xDBFF && searchValue > 1) { // surrogate pair
idxChar = searchValue.substr(0, 2);
}
let jsFile;
let idx = indexSectionsWithContent[this.searchIndex].indexOf(idxChar);
if (idx!=-1) {
const hexCode=idx.toString(16);
jsFile = this.resultsPath + indexSectionNames[this.searchIndex] + '_' + hexCode + '.js';
}
const loadJS = function(url, impl, loc) {
const scriptTag = document.createElement('script');
scriptTag.src = url;
scriptTag.onload = impl;
scriptTag.onreadystatechange = impl;
loc.appendChild(scriptTag);
}
const domPopupSearchResultsWindow = this.DOMPopupSearchResultsWindow();
const domSearchBox = this.DOMSearchBox();
const domPopupSearchResults = this.DOMPopupSearchResults();
const domSearchClose = this.DOMSearchClose();
const resultsPath = this.resultsPath;
const handleResults = function() {
document.getElementById("Loading").style.display="none";
if (typeof searchData !== 'undefined') {
createResults(resultsPath);
document.getElementById("NoMatches").style.display="none";
}
if (idx!=-1) {
searchResults.Search(searchValue);
} else { // no file with search results => force empty search results
searchResults.Search('====');
}
if (domPopupSearchResultsWindow.style.display!='block') {
domSearchClose.style.display = 'inline-block';
let left = getXPos(domSearchBox) + 150;
let top = getYPos(domSearchBox) + 20;
domPopupSearchResultsWindow.style.display = 'block';
left -= domPopupSearchResults.offsetWidth;
const maxWidth = document.body.clientWidth;
const maxHeight = document.body.clientHeight;
let width = 300;
if (left<10) left=10;
if (width+left+8>maxWidth) width=maxWidth-left-8;
let height = 400;
if (height+top+8>maxHeight) height=maxHeight-top-8;
domPopupSearchResultsWindow.style.top = top + 'px';
domPopupSearchResultsWindow.style.left = left + 'px';
domPopupSearchResultsWindow.style.width = width + 'px';
domPopupSearchResultsWindow.style.height = height + 'px';
}
}
if (jsFile) {
loadJS(jsFile, handleResults, this.DOMPopupSearchResultsWindow());
} else {
handleResults();
}
this.lastSearchValue = searchValue;
}
// -------- Activation Functions
// Activates or deactivates the search panel, resetting things to
// their default values if necessary.
this.Activate = function(isActive) {
if (isActive || // open it
this.DOMPopupSearchResultsWindow().style.display == 'block'
) {
this.DOMSearchBox().className = 'MSearchBoxActive';
this.searchActive = true;
} else if (!isActive) { // directly remove the panel
this.DOMSearchBox().className = 'MSearchBoxInactive';
this.searchActive = false;
this.lastSearchValue = ''
this.lastResultsPage = '';
this.DOMSearchField().value = '';
}
}
}
// -----------------------------------------------------------------------
// The class that handles everything on the search results page.
function SearchResults() {
function convertToId(search) {
let result = '';
for (let i=0;i<search.length;i++) {
const c = search.charAt(i);
const cn = c.charCodeAt(0);
if (c.match(/[a-z0-9\u0080-\uFFFF]/)) {
result+=c;
} else if (cn<16) {
result+="_0"+cn.toString(16);
} else {
result+="_"+cn.toString(16);
}
}
return result;
}
// The number of matches from the last run of <Search()>.
this.lastMatchCount = 0;
this.lastKey = 0;
this.repeatOn = false;
// Toggles the visibility of the passed element ID.
this.FindChildElement = function(id) {
const parentElement = document.getElementById(id);
let element = parentElement.firstChild;
while (element && element!=parentElement) {
if (element.nodeName.toLowerCase() == 'div' && element.className == 'SRChildren') {
return element;
}
if (element.nodeName.toLowerCase() == 'div' && element.hasChildNodes()) {
element = element.firstChild;
} else if (element.nextSibling) {
element = element.nextSibling;
} else {
do {
element = element.parentNode;
}
while (element && element!=parentElement && !element.nextSibling);
if (element && element!=parentElement) {
element = element.nextSibling;
}
}
}
}
this.Toggle = function(id) {
const element = this.FindChildElement(id);
if (element) {
if (element.style.display == 'block') {
element.style.display = 'none';
} else {
element.style.display = 'block';
}
}
}
// Searches for the passed string. If there is no parameter,
// it takes it from the URL query.
//
// Always returns true, since other documents may try to call it
// and that may or may not be possible.
this.Search = function(search) {
if (!search) { // get search word from URL
search = window.location.search;
search = search.substring(1); // Remove the leading '?'
search = unescape(search);
}
search = search.replace(/^ +/, ""); // strip leading spaces
search = search.replace(/ +$/, ""); // strip trailing spaces
search = search.toLowerCase();
search = convertToId(search);
const resultRows = document.getElementsByTagName("div");
let matches = 0;
let i = 0;
while (i < resultRows.length) {
const row = resultRows.item(i);
if (row.className == "SRResult") {
let rowMatchName = row.id.toLowerCase();
rowMatchName = rowMatchName.replace(/^sr\d*_/, ''); // strip 'sr123_'
if (search.length<=rowMatchName.length &&
rowMatchName.substr(0, search.length)==search) {
row.style.display = 'block';
matches++;
} else {
row.style.display = 'none';
}
}
i++;
}
document.getElementById("Searching").style.display='none';
if (matches == 0) { // no results
document.getElementById("NoMatches").style.display='block';
} else { // at least one result
document.getElementById("NoMatches").style.display='none';
}
this.lastMatchCount = matches;
return true;
}
// return the first item with index index or higher that is visible
this.NavNext = function(index) {
let focusItem;
for (;;) {
const focusName = 'Item'+index;
focusItem = document.getElementById(focusName);
if (focusItem && focusItem.parentNode.parentNode.style.display=='block') {
break;
} else if (!focusItem) { // last element
break;
}
focusItem=null;
index++;
}
return focusItem;
}
this.NavPrev = function(index) {
let focusItem;
for (;;) {
const focusName = 'Item'+index;
focusItem = document.getElementById(focusName);
if (focusItem && focusItem.parentNode.parentNode.style.display=='block') {
break;
} else if (!focusItem) { // last element
break;
}
focusItem=null;
index--;
}
return focusItem;
}
this.ProcessKeys = function(e) {
if (e.type == "keydown") {
this.repeatOn = false;
this.lastKey = e.keyCode;
} else if (e.type == "keypress") {
if (!this.repeatOn) {
if (this.lastKey) this.repeatOn = true;
return false; // ignore first keypress after keydown
}
} else if (e.type == "keyup") {
this.lastKey = 0;
this.repeatOn = false;
}
return this.lastKey!=0;
}
this.Nav = function(evt,itemIndex) {
const e = (evt) ? evt : window.event; // for IE
if (e.keyCode==13) return true;
if (!this.ProcessKeys(e)) return false;
if (this.lastKey==38) { // Up
const newIndex = itemIndex-1;
let focusItem = this.NavPrev(newIndex);
if (focusItem) {
let child = this.FindChildElement(focusItem.parentNode.parentNode.id);
if (child && child.style.display == 'block') { // children visible
let n=0;
let tmpElem;
for (;;) { // search for last child
tmpElem = document.getElementById('Item'+newIndex+'_c'+n);
if (tmpElem) {
focusItem = tmpElem;
} else { // found it!
break;
}
n++;
}
}
}
if (focusItem) {
focusItem.focus();
} else { // return focus to search field
document.getElementById("MSearchField").focus();
}
} else if (this.lastKey==40) { // Down
const newIndex = itemIndex+1;
let focusItem;
const item = document.getElementById('Item'+itemIndex);
const elem = this.FindChildElement(item.parentNode.parentNode.id);
if (elem && elem.style.display == 'block') { // children visible
focusItem = document.getElementById('Item'+itemIndex+'_c0');
}
if (!focusItem) focusItem = this.NavNext(newIndex);
if (focusItem) focusItem.focus();
} else if (this.lastKey==39) { // Right
const item = document.getElementById('Item'+itemIndex);
const elem = this.FindChildElement(item.parentNode.parentNode.id);
if (elem) elem.style.display = 'block';
} else if (this.lastKey==37) { // Left
const item = document.getElementById('Item'+itemIndex);
const elem = this.FindChildElement(item.parentNode.parentNode.id);
if (elem) elem.style.display = 'none';
} else if (this.lastKey==27) { // Escape
e.stopPropagation();
searchBox.CloseResultsWindow();
document.getElementById("MSearchField").focus();
} else if (this.lastKey==13) { // Enter
return true;
}
return false;
}
this.NavChild = function(evt,itemIndex,childIndex) {
const e = (evt) ? evt : window.event; // for IE
if (e.keyCode==13) return true;
if (!this.ProcessKeys(e)) return false;
if (this.lastKey==38) { // Up
if (childIndex>0) {
const newIndex = childIndex-1;
document.getElementById('Item'+itemIndex+'_c'+newIndex).focus();
} else { // already at first child, jump to parent
document.getElementById('Item'+itemIndex).focus();
}
} else if (this.lastKey==40) { // Down
const newIndex = childIndex+1;
let elem = document.getElementById('Item'+itemIndex+'_c'+newIndex);
if (!elem) { // last child, jump to parent next parent
elem = this.NavNext(itemIndex+1);
}
if (elem) {
elem.focus();
}
} else if (this.lastKey==27) { // Escape
e.stopPropagation();
searchBox.CloseResultsWindow();
document.getElementById("MSearchField").focus();
} else if (this.lastKey==13) { // Enter
return true;
}
return false;
}
}
function createResults(resultsPath) {
function setKeyActions(elem,action) {
elem.setAttribute('onkeydown',action);
elem.setAttribute('onkeypress',action);
elem.setAttribute('onkeyup',action);
}
function setClassAttr(elem,attr) {
elem.setAttribute('class',attr);
elem.setAttribute('className',attr);
}
const decodeHtml = (html) => {
const txt = document.createElement("textarea");
txt.innerHTML = html;
return txt.value;
};
const results = document.getElementById("SRResults");
results.innerHTML = '';
searchData.forEach((elem,index) => {
const id = elem[0];
const srResult = document.createElement('div');
srResult.setAttribute('id','SR_'+id);
setClassAttr(srResult,'SRResult');
const srEntry = document.createElement('div');
setClassAttr(srEntry,'SREntry');
const srLink = document.createElement('a');
srLink.setAttribute('id','Item'+index);
setKeyActions(srLink,'return searchResults.Nav(event,'+index+')');
setClassAttr(srLink,'SRSymbol');
srLink.innerHTML = decodeHtml(elem[1][0]);
srEntry.appendChild(srLink);
if (elem[1].length==2) { // single result
if (elem[1][1][0].startsWith('http://') || elem[1][1][0].startsWith('https://')) { // absolute path
srLink.setAttribute('href',elem[1][1][0]);
} else { // relative path
srLink.setAttribute('href',resultsPath+elem[1][1][0]);
}
srLink.setAttribute('onclick','searchBox.CloseResultsWindow()');
if (elem[1][1][1]) {
srLink.setAttribute('target','_parent');
} else {
srLink.setAttribute('target','_blank');
}
const srScope = document.createElement('span');
setClassAttr(srScope,'SRScope');
srScope.innerHTML = decodeHtml(elem[1][1][2]);
srEntry.appendChild(srScope);
} else { // multiple results
srLink.setAttribute('href','javascript:searchResults.Toggle("SR_'+id+'")');
const srChildren = document.createElement('div');
setClassAttr(srChildren,'SRChildren');
for (let c=0; c<elem[1].length-1; c++) {
const srChild = document.createElement('a');
srChild.setAttribute('id','Item'+index+'_c'+c);
setKeyActions(srChild,'return searchResults.NavChild(event,'+index+','+c+')');
setClassAttr(srChild,'SRScope');
if (elem[1][c+1][0].startsWith('http://') || elem[1][c+1][0].startsWith('https://')) { // absolute path
srChild.setAttribute('href',elem[1][c+1][0]);
} else { // relative path
srChild.setAttribute('href',resultsPath+elem[1][c+1][0]);
}
srChild.setAttribute('onclick','searchBox.CloseResultsWindow()');
if (elem[1][c+1][1]) {
srChild.setAttribute('target','_parent');
} else {
srChild.setAttribute('target','_blank');
}
srChild.innerHTML = decodeHtml(elem[1][c+1][2]);
srChildren.appendChild(srChild);
}
srEntry.appendChild(srChildren);
}
srResult.appendChild(srEntry);
results.appendChild(srResult);
});
}
function init_search() {
const results = document.getElementById("MSearchSelectWindow");
results.tabIndex=0;
for (let key in indexSectionLabels) {
const link = document.createElement('a');
link.setAttribute('class','SelectItem');
link.setAttribute('onclick','searchBox.OnSelectItem('+key+')');
link.href='javascript:void(0)';
link.innerHTML='<span class="SelectionMark">&#160;</span>'+indexSectionLabels[key];
results.appendChild(link);
}
const input = document.getElementById("MSearchSelect");
const searchSelectWindow = document.getElementById("MSearchSelectWindow");
input.tabIndex=0;
input.addEventListener("keydown", function(event) {
if (event.keyCode==13 || event.keyCode==40) {
event.preventDefault();
if (searchSelectWindow.style.display == 'block') {
searchBox.CloseSelectionWindow();
} else {
searchBox.OnSearchSelectShow();
searchBox.DOMSearchSelectWindow().focus();
}
}
});
const name = Cookie.readSetting(SEARCH_COOKIE_NAME,0);
const id = searchBox.GetSelectionIdByName(name);
searchBox.OnSelectItem(id);
}
/* @license-end */

21
search/searchdata.js Normal file
View File

@@ -0,0 +1,21 @@
var indexSectionsWithContent =
{
0: "01289abcdefghijklmnopqrstuvxy—",
1: "cr",
2: "01289abcdefghijklmnopqrstuvxy—"
};
var indexSectionNames =
{
0: "all",
1: "files",
2: "pages"
};
var indexSectionLabels =
{
0: "All",
1: "Files",
2: "Pages"
};

482
tabs.css Normal file
View File

@@ -0,0 +1,482 @@
.sm {
position: relative;
z-index: 9999
}
.sm,.sm li,.sm ul {
list-style: none;
margin: 0;
padding: 0;
line-height: normal;
direction: ltr;
text-align: left;
-webkit-tap-highlight-color: transparent
}
.sm,.sm li {
display: block
}
.sm-rtl,.sm-rtl li,.sm-rtl ul {
direction: rtl;
text-align: right
}
.sm>li>h1,.sm>li>h2,.sm>li>h3,.sm>li>h4,.sm>li>h5,.sm>li>h6 {
margin: 0;
padding: 0
}
.sm ul {
display: none
}
.sm a,.sm li {
position: relative
}
.sm a,.sm:after {
display: block
}
.sm a.disabled {
cursor: not-allowed
}
.sm:after {
content: " ";
height: 0;
font: 0/0 serif;
clear: both;
visibility: hidden;
overflow: hidden
}
.sm,.sm *,.sm :after,.sm :before {
-moz-box-sizing: border-box;
-webkit-box-sizing: border-box;
box-sizing: border-box
}
.main-menu-btn {
position: relative;
display: inline-block;
width: 36px;
height: 36px;
text-indent: 36px;
margin-left: 8px;
white-space: nowrap;
overflow: hidden;
cursor: pointer;
-webkit-tap-highlight-color: transparent
}
.main-menu-btn-icon {
top: 50%;
left: 2px
}
.main-menu-btn-icon,.main-menu-btn-icon:after,.main-menu-btn-icon:before {
position: absolute;
height: 2px;
width: 24px;
background: #364D7C;
-webkit-transition: all .25s;
transition: all .25s
}
.main-menu-btn-icon:before {
content: "";
top: -7px;
left: 0
}
.main-menu-btn-icon:after {
content: "";
top: 7px;
left: 0
}
#main-menu-state:checked~.main-menu-btn .main-menu-btn-icon {
height: 0
}
#main-menu-state:checked~.main-menu-btn .main-menu-btn-icon:before {
top: 0;
-webkit-transform: rotate(-45deg);
transform: rotate(-45deg)
}
#main-menu-state:checked~.main-menu-btn .main-menu-btn-icon:after {
top: 0;
-webkit-transform: rotate(45deg);
transform: rotate(45deg)
}
#main-menu-state {
position: absolute;
width: 1px;
height: 1px;
margin: -1px;
border: 0;
padding: 0;
overflow: hidden;
clip: rect(1px,1px,1px,1px)
}
#main-menu-state:not(:checked)~#main-menu {
display: none
}
#main-menu-state:checked~#main-menu {
display: block
}
@media (min-width:768px) {
.main-menu-btn {
position: absolute;
top: -99999px
}
#main-menu-state:not(:checked)~#main-menu {
display: block
}
}
.sm-dox {
background-color: white
}
.sm-dox a,.sm-dox a:active,.sm-dox a:focus,.sm-dox a:hover {
padding: 0 43px 0 12px;
font-family: 'Lucida Grande',Geneva,Helvetica,Arial,sans-serif;
font-size: 13px;
line-height: 36px;
text-decoration: none;
color: #283A5D;
outline: 0
}
.sm-dox a:hover {
background-color: #DCE2EF;
border-radius: 5px
}
.sm-dox a.current {
color: #d23600
}
.sm-dox a.disabled {
color: #bbb
}
.sm-dox a span.sub-arrow {
position: absolute;
top: 50%;
margin-top: -14px;
left: auto;
right: 3px;
width: 28px;
height: 28px;
overflow: hidden;
font: 700 12px/28px monospace!important;
text-align: center;
text-shadow: none;
-moz-border-radius: 5px;
-webkit-border-radius: 5px;
border-radius: 5px
}
.sm-dox a span.sub-arrow:before {
display: block;
content: "+"
}
.sm-dox a.highlighted span.sub-arrow:before {
display: block;
content: "-"
}
.sm-dox>li:first-child>:not(ul) a,.sm-dox>li:first-child>a {
-moz-border-radius: 5px 5px 0 0;
-webkit-border-radius: 5px;
border-radius: 5px 5px 0 0
}
.sm-dox>li:last-child>:not(ul) a,.sm-dox>li:last-child>a,.sm-dox>li:last-child>ul,.sm-dox>li:last-child>ul>li:last-child>:not(ul) a,.sm-dox>li:last-child>ul>li:last-child>a,.sm-dox>li:last-child>ul>li:last-child>ul,.sm-dox>li:last-child>ul>li:last-child>ul>li:last-child>:not(ul) a,.sm-dox>li:last-child>ul>li:last-child>ul>li:last-child>a,.sm-dox>li:last-child>ul>li:last-child>ul>li:last-child>ul,.sm-dox>li:last-child>ul>li:last-child>ul>li:last-child>ul>li:last-child>:not(ul) a,.sm-dox>li:last-child>ul>li:last-child>ul>li:last-child>ul>li:last-child>a,.sm-dox>li:last-child>ul>li:last-child>ul>li:last-child>ul>li:last-child>ul,.sm-dox>li:last-child>ul>li:last-child>ul>li:last-child>ul>li:last-child>ul>li:last-child>:not(ul) a,.sm-dox>li:last-child>ul>li:last-child>ul>li:last-child>ul>li:last-child>ul>li:last-child>a,.sm-dox>li:last-child>ul>li:last-child>ul>li:last-child>ul>li:last-child>ul>li:last-child>ul {
-moz-border-radius: 0 0 5px 5px;
-webkit-border-radius: 0;
border-radius: 0 0 5px 5px
}
.sm-dox>li:last-child>:not(ul) a.highlighted,.sm-dox>li:last-child>a.highlighted,.sm-dox>li:last-child>ul>li:last-child>:not(ul) a.highlighted,.sm-dox>li:last-child>ul>li:last-child>a.highlighted,.sm-dox>li:last-child>ul>li:last-child>ul>li:last-child>:not(ul) a.highlighted,.sm-dox>li:last-child>ul>li:last-child>ul>li:last-child>a.highlighted,.sm-dox>li:last-child>ul>li:last-child>ul>li:last-child>ul>li:last-child>:not(ul) a.highlighted,.sm-dox>li:last-child>ul>li:last-child>ul>li:last-child>ul>li:last-child>a.highlighted,.sm-dox>li:last-child>ul>li:last-child>ul>li:last-child>ul>li:last-child>ul>li:last-child>:not(ul) a.highlighted,.sm-dox>li:last-child>ul>li:last-child>ul>li:last-child>ul>li:last-child>ul>li:last-child>a.highlighted {
-moz-border-radius: 0;
-webkit-border-radius: 0;
border-radius: 0
}
.sm-dox ul {
background: white
}
.sm-dox ul a,.sm-dox ul a:active,.sm-dox ul a:focus,.sm-dox ul a:hover {
font-size: 12px;
border-left: 8px solid transparent;
line-height: 36px;
text-shadow: none;
background-color: white;
background-image: none
}
.sm-dox ul a:hover {
background-color: #DCE2EF;
border-radius: 5px
}
.sm-dox ul ul a,.sm-dox ul ul a:active,.sm-dox ul ul a:focus,.sm-dox ul ul a:hover {
border-left: 16px solid transparent
}
.sm-dox ul ul ul a,.sm-dox ul ul ul a:active,.sm-dox ul ul ul a:focus,.sm-dox ul ul ul a:hover {
border-left: 24px solid transparent
}
.sm-dox ul ul ul ul a,.sm-dox ul ul ul ul a:active,.sm-dox ul ul ul ul a:focus,.sm-dox ul ul ul ul a:hover {
border-left: 32px solid transparent
}
.sm-dox ul ul ul ul ul a,.sm-dox ul ul ul ul ul a:active,.sm-dox ul ul ul ul ul a:focus,.sm-dox ul ul ul ul ul a:hover {
border-left: 40px solid transparent
}
@media (min-width:768px) {
.sm-dox ul {
position: absolute;
width: 12em;
border: 1px solid #bbb;
padding: 5px 0;
background: white;
-moz-border-radius: 5px!important;
-webkit-border-radius: 5px;
border-radius: 5px!important;
-moz-box-shadow: 0 5px 9px rgba(0,0,0,.2);
-webkit-box-shadow: 0 5px 9px rgba(0,0,0,.2);
box-shadow: 0 5px 9px rgba(0,0,0,.2)
}
.sm-dox li {
float: left;
border-top: 0;
padding: 3px
}
.sm-dox.sm-rtl li {
float: right
}
.sm-dox ul li,.sm-dox.sm-rtl ul li,.sm-dox.sm-vertical li {
float: none
}
.sm-dox a {
white-space: nowrap
}
.sm-dox ul a,.sm-dox.sm-vertical a {
white-space: normal
}
.sm-dox .sm-nowrap>li>:not(ul) a,.sm-dox .sm-nowrap>li>a {
white-space: nowrap
}
.sm-dox,.sm-dox a span.sub-arrow {
background-color: white
}
.sm-dox {
padding: 0 10px;
line-height: 36px
}
.sm-dox a span.sub-arrow {
top: 15px;
right: 10px;
box-sizing: content-box;
padding: 0;
margin: 0;
display: inline-block;
width: 5px;
height: 5px;
border-right: 2px solid #B6C4DF;
border-bottom: 2px solid #B6C4DF;
transform: rotate(45deg);
-moz-border-radius: 0;
-webkit-border-radius: 0;
border-radius: 0
}
.sm-dox a,.sm-dox a.highlighted,.sm-dox a:active,.sm-dox a:focus,.sm-dox a:hover {
padding: 0 6px
}
.sm-dox a:hover {
background-color: #DCE2EF;
border-radius: 5px!important
}
.sm-dox a:hover span.sub-arrow {
background-color: #DCE2EF;
border-right: 2px solid #90A5CE;
border-bottom: 2px solid #90A5CE
}
.sm-dox a.has-submenu {
padding-right: 24px
}
.sm-dox>li>ul:after,.sm-dox>li>ul:before {
content: "";
position: absolute;
top: -18px;
left: 30px;
width: 0;
height: 0;
overflow: hidden;
border-width: 9px;
border-style: dashed dashed solid;
border-color: transparent transparent #bbb
}
.sm-dox>li>ul:after {
top: -16px;
left: 31px;
border-width: 8px;
border-color: transparent transparent white transparent
}
.sm-dox ul a span.sub-arrow {
transform: rotate(-45deg);
top: 3px;
}
.sm-dox ul a,.sm-dox ul a.highlighted,.sm-dox ul a:active,.sm-dox ul a:focus,.sm-dox ul a:hover {
color: #555555;
background-image: none;
line-height: normal;
border: 0!important
}
.sm-dox ul a:hover {
background-color: #DCE2EF;
border-radius: 5px
}
.sm-dox span.scroll-down,.sm-dox span.scroll-up {
position: absolute;
display: none;
visibility: hidden;
overflow: hidden;
background: white;
height: 36px
}
.sm-dox span.scroll-down:hover,.sm-dox span.scroll-up:hover {
background: #eee
}
.sm-dox span.scroll-up:hover span.scroll-down-arrow,.sm-dox span.scroll-up:hover span.scroll-up-arrow {
border-color: transparent transparent #d23600
}
.sm-dox span.scroll-down:hover span.scroll-down-arrow {
border-color: #d23600 transparent transparent
}
.sm-dox span.scroll-down-arrow,.sm-dox span.scroll-up-arrow {
position: absolute;
top: 0;
left: 50%;
margin-left: -6px;
width: 0;
height: 0;
overflow: hidden;
border-width: 6px;
border-style: dashed dashed solid;
border-color: transparent transparent #555555 transparent
}
.sm-dox span.scroll-down-arrow {
top: 8px;
border-style: solid dashed dashed;
border-color: #555555 transparent transparent transparent
}
.sm-dox.sm-rtl a.has-submenu {
padding-right: 6px;
padding-left: 24px
}
.sm-dox.sm-rtl a span.sub-arrow {
right: auto;
left: 6px
}
.sm-dox.sm-rtl.sm-vertical a.has-submenu,.sm-dox.sm-vertical a,.sm-dox.sm-vertical ul a {
padding: 10px 20px
}
.sm-dox.sm-rtl ul a span.sub-arrow,.sm-dox.sm-rtl.sm-vertical a span.sub-arrow {
right: auto;
left: 8px;
border-style: dashed solid dashed dashed;
border-color: transparent #555 transparent transparent
}
.sm-dox.sm-rtl>li>ul:before {
left: auto;
right: 30px
}
.sm-dox.sm-rtl>li>ul:after {
left: auto;
right: 31px
}
.sm-dox.sm-rtl ul a.has-submenu {
padding: 10px 20px!important
}
.sm-dox.sm-vertical {
padding: 10px 0;
-moz-border-radius: 5px;
-webkit-border-radius: 5px;
border-radius: 5px
}
.sm-dox.sm-vertical a.highlighted,.sm-dox.sm-vertical a:active,.sm-dox.sm-vertical a:focus,.sm-dox.sm-vertical a:hover {
background: #fff
}
.sm-dox.sm-vertical a span.sub-arrow {
right: 8px;
top: 50%;
margin-top: -5px;
border-width: 5px;
border-style: dashed dashed dashed solid;
border-color: transparent transparent transparent #555
}
.sm-dox.sm-vertical>li>ul:after,.sm-dox.sm-vertical>li>ul:before {
display: none
}
.sm-dox.sm-vertical ul a.highlighted,.sm-dox.sm-vertical ul a:active,.sm-dox.sm-vertical ul a:focus,.sm-dox.sm-vertical ul a:hover {
background: #eee
}
.sm-dox.sm-vertical ul a.disabled {
background: white
}
}