commit 1e82af86cae38f256968840ac8f4c0625aefd684 Author: Tarik Moussa Date: Sat May 23 23:22:46 2026 +0200 Initial Codeberg Pages publish: Doxygen HTML for v0.9.x main diff --git a/README.txt b/README.txt new file mode 100644 index 0000000..4d39397 --- /dev/null +++ b/README.txt @@ -0,0 +1,3 @@ +conformallab++ — Doxygen HTML API documentation + +Generated from the v0.9.x main branch. Source: https://codeberg.org/TMoussa/ConformalLabpp diff --git a/clipboard.js b/clipboard.js new file mode 100644 index 0000000..6a0f42c --- /dev/null +++ b/clipboard.js @@ -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 = `` +let clipboard_successIcon = `` +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) + } + } +}) diff --git a/codefolding.js b/codefolding.js new file mode 100644 index 0000000..a7e977f --- /dev/null +++ b/codefolding.js @@ -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 = '…'; + line.appendChild(document.createTextNode(' '+start)); + line.appendChild(ellipsisLink); + line.appendChild(document.createTextNode(end)); + // insert constructed line into closed div + closedDiv.appendChild(line); + } + }); + }, +}; +/* @license-end */ diff --git a/cookie.js b/cookie.js new file mode 100644 index 0000000..53ad21d --- /dev/null +++ b/cookie.js @@ -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); + } + }, +} diff --git a/doxygen.css b/doxygen.css new file mode 100644 index 0000000..2c1bcfa --- /dev/null +++ b/doxygen.css @@ -0,0 +1,2170 @@ +/* The standard CSS for doxygen 1.17.0*/ + +body { + background-color: white; + color: black; +} + +body, table, div, p, dl { + font-weight: 400; + font-size: 14px; + font-family: system-ui,-apple-system,Segoe UI,Roboto,Ubuntu,Cantarell,Noto Sans,sans-serif,BlinkMacSystemFont,"Segoe UI",Helvetica,Arial,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol"; + line-height: 22px; +} + +body.resizing { + user-select: none; + -webkit-user-select: none; +} + +#doc-content { + scrollbar-width: thin; +} + +/* @group Heading Levels */ + +.title { + font-family: system-ui,-apple-system,Segoe UI,Roboto,Ubuntu,Cantarell,Noto Sans,sans-serif,BlinkMacSystemFont,"Segoe UI",Helvetica,Arial,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol"; + line-height: 28px; + font-size: 160%; + font-weight: 400; + margin: 10px 2px; +} + +h1.groupheader { + font-size: 150%; +} + +h2.groupheader { + box-shadow: 12px 0 white, + -12px 0 white, + 12px 1px #D9E0EE, + -12px 1px #D9E0EE; + color: #354C7B; + font-size: 150%; + font-weight: normal; + margin-top: 1.75em; + padding-top: 8px; + padding-bottom: 4px; + width: 100%; +} + +td h2.groupheader { + box-shadow: 13px 0 white, + -13px 0 white, + 13px 1px #D9E0EE, + -13px 1px #D9E0EE; +} + +h3.groupheader { + font-size: 100%; +} + +h1, h2, h3, h4, h5, h6 { + -webkit-transition: text-shadow 0.5s linear; + -moz-transition: text-shadow 0.5s linear; + -ms-transition: text-shadow 0.5s linear; + -o-transition: text-shadow 0.5s linear; + transition: text-shadow 0.5s linear; + margin-right: 15px; +} + +h1.glow, h2.glow, h3.glow, h4.glow, h5.glow, h6.glow { + text-shadow: 0 0 15px cyan; +} + +dt { + font-weight: bold; +} + +p.startli, p.startdd { + margin-top: 2px; + margin-bottom: 0px; +} + +th p.starttd, th p.intertd, th p.endtd { + font-size: 100%; + font-weight: 700; +} + +p.starttd { + margin-top: 0px; +} + +p.endli { + margin-bottom: 0px; +} + +p.enddd { + margin-bottom: 4px; +} + +p.endtd { + margin-bottom: 2px; +} + +p.interli { +} + +p.interdd { +} + +p.intertd { +} + +/* @end */ + +caption { + font-weight: bold; +} + +span.legend { + font-size: 70%; + text-align: center; +} + +h3.version { + font-size: 90%; + text-align: center; +} + +div.navtab { + margin-right: 6px; + padding-right: 6px; + text-align: right; + line-height: 110%; + background-color: #F9FAFC; +} + +div.navtab table { + border-spacing: 0; +} + +td.navtab { + padding-right: 6px; + padding-left: 6px; +} + +td.navtabHL { + padding-right: 6px; + padding-left: 6px; + border-radius: 0 6px 6px 0; + background-color: #DCE2EF; +} + +div.alphasepar:before{ + content: " | " ; + width: 14px; + display: inline-block; + text-align: center; + line-height: 140%; + font-size: 130%; +} + +div.alphasepar{ + display: inline-block; +} + +div.qindex{ + text-align: center; + width: 100%; + line-height: 140%; + font-size: 130%; + color: #A0A0A0; +} + +#main-menu a:focus { + outline: auto; + z-index: 10; + position: relative; +} + +dt.alphachar{ + font-size: 180%; + font-weight: bold; +} + +.alphachar a{ + color: black; +} + +.alphachar a:hover, .alphachar a:visited{ + text-decoration: none; +} + +.classindex dl { + padding: 25px; + column-count:1 +} + +.classindex dd { + display:inline-block; + margin-left: 50px; + width: 90%; + line-height: 1.15em; +} + +.classindex dl.even { + background-color: white; +} + +.classindex dl.odd { + background-color: #F8F9FC; +} + +@media(min-width: 1120px) { + .classindex dl { + column-count:2 + } +} + +@media(min-width: 1320px) { + .classindex dl { + column-count:3 + } +} + + +/* @group Link Styling */ + +a { + color: #3D578C; + font-weight: normal; + text-decoration: none; +} + +.contents a:visited { + color: #3D578C; +} + +span.label a:hover { + text-decoration: none; + background: linear-gradient(to bottom, transparent 0,transparent calc(100% - 1px), currentColor 100%); +} + +a.el { + font-weight: bold; +} + +a.elRef { +} + +a.el, a.el:visited, a.code, a.code:visited, a.line, a.line:visited { + color: #3D578C; +} + +a.codeRef, a.codeRef:visited, a.lineRef, a.lineRef:visited { + color: #334975; +} + +a.code.hl_class { /* style for links to class names in code snippets */ } +a.code.hl_struct { /* style for links to struct names in code snippets */ } +a.code.hl_union { /* style for links to union names in code snippets */ } +a.code.hl_interface { /* style for links to interface names in code snippets */ } +a.code.hl_protocol { /* style for links to protocol names in code snippets */ } +a.code.hl_category { /* style for links to category names in code snippets */ } +a.code.hl_exception { /* style for links to exception names in code snippets */ } +a.code.hl_service { /* style for links to service names in code snippets */ } +a.code.hl_singleton { /* style for links to singleton names in code snippets */ } +a.code.hl_concept { /* style for links to concept names in code snippets */ } +a.code.hl_namespace { /* style for links to namespace names in code snippets */ } +a.code.hl_package { /* style for links to package names in code snippets */ } +a.code.hl_define { /* style for links to macro names in code snippets */ } +a.code.hl_function { /* style for links to function names in code snippets */ } +a.code.hl_variable { /* style for links to variable names in code snippets */ } +a.code.hl_typedef { /* style for links to typedef names in code snippets */ } +a.code.hl_enumvalue { /* style for links to enum value names in code snippets */ } +a.code.hl_enumeration { /* style for links to enumeration names in code snippets */ } +a.code.hl_signal { /* style for links to Qt signal names in code snippets */ } +a.code.hl_slot { /* style for links to Qt slot names in code snippets */ } +a.code.hl_friend { /* style for links to friend names in code snippets */ } +a.code.hl_dcop { /* style for links to KDE3 DCOP names in code snippets */ } +a.code.hl_property { /* style for links to property names in code snippets */ } +a.code.hl_event { /* style for links to event names in code snippets */ } +a.code.hl_sequence { /* style for links to sequence names in code snippets */ } +a.code.hl_dictionary { /* style for links to dictionary names in code snippets */ } + +div.embeddoc { + font-family: 'JetBrains Mono',Consolas,Monaco,'Andale Mono','Ubuntu Mono',monospace,fixed; + padding-left: 10px; +} + +/* @end */ + +dl.el { + margin-left: -1cm; +} + +ul.check { + list-style: none; + padding-left: 40px; + margin: 0; +} + +ul.check li { + position: relative; +} + +li.unchecked::before, li.checked::before { + position: absolute; + left: -18px; + top: 0; +} + +li.unchecked::before { + content: "☐"; +} + +li.checked::before { + content: "☑"; +} + +ul.check li > p { + display: inline; +} + +ul.check li > p:not(:first-child) { + display: block; +} + +ol { + text-indent: 0px; +} + +ul { + text-indent: 0px; + overflow: visible; +} + +ul.multicol { + -moz-column-gap: 1em; + -webkit-column-gap: 1em; + column-gap: 1em; + -moz-column-count: 3; + -webkit-column-count: 3; + column-count: 3; + list-style-type: none; +} + +#side-nav ul { + overflow: visible; /* reset ul rule for scroll bar in GENERATE_TREEVIEW window */ +} + +#main-nav ul { + overflow: visible; /* reset ul rule for the navigation bar drop down lists */ +} + +.fragment { + text-align: left; + direction: ltr; + overflow-x: auto; + overflow-y: hidden; + position: relative; + min-height: 12px; + margin: 10px 0px; + padding: 10px 10px; + border: 1px solid #C4CFE5; + border-radius: 4px; + background-color: #FBFCFD; + color: black; +} + +pre.fragment { + word-wrap: break-word; + font-size: 10pt; + line-height: 125%; + font-family: 'JetBrains Mono',Consolas,Monaco,'Andale Mono','Ubuntu Mono',monospace,fixed; +} + +span.tt { + white-space: pre; + font-family: 'JetBrains Mono',Consolas,Monaco,'Andale Mono','Ubuntu Mono',monospace,fixed; + background-color: #FBFCFD; +} + +.clipboard { + width: 24px; + height: 24px; + right: 5px; + top: 5px; + opacity: 0; + position: absolute; + display: inline; + overflow: hidden; + justify-content: center; + align-items: center; + cursor: pointer; +} + +.clipboard.success { + border: 1px solid black; + border-radius: 4px; +} + +.fragment:hover .clipboard, .clipboard.success { + opacity: .4; +} + +.clipboard:hover, .clipboard.success { + opacity: 1 !important; +} + +.clipboard:active:not([class~=success]) svg { + transform: scale(.91); +} + +.clipboard.success svg { + fill: #2EC82E; +} + +.clipboard.success { + border-color: #2EC82E; +} + +div.line { + font-family: 'JetBrains Mono',Consolas,Monaco,'Andale Mono','Ubuntu Mono',monospace,fixed; + font-size: 13px; + min-height: 13px; + line-height: 1.2; + text-wrap: wrap; + word-break: break-all; + white-space: -moz-pre-wrap; /* Moz */ + white-space: -pre-wrap; /* Opera 4-6 */ + white-space: -o-pre-wrap; /* Opera 7 */ + white-space: pre-wrap; /* CSS3 */ + word-wrap: break-word; /* IE 5.5+ */ + text-indent: -62px; + padding-left: 62px; + padding-bottom: 0px; + margin: 0px; + -webkit-transition-property: background-color, box-shadow; + -webkit-transition-duration: 0.5s; + -moz-transition-property: background-color, box-shadow; + -moz-transition-duration: 0.5s; + -ms-transition-property: background-color, box-shadow; + -ms-transition-duration: 0.5s; + -o-transition-property: background-color, box-shadow; + -o-transition-duration: 0.5s; + transition-property: background-color, box-shadow; + transition-duration: 0.5s; +} + +div.line:after { + content:"\000A"; + white-space: pre; +} + +div.line.glow { + background-color: cyan; + box-shadow: 0 0 10px cyan; +} + +span.fold { + display: inline-block; + width: 12px; + height: 12px; + margin-left: 4px; + margin-right: 1px; +} + +span.foldnone { + display: inline-block; + position: relative; + cursor: pointer; + user-select: none; +} + +span.fold.plus, span.fold.minus { + width: 10px; + height: 10px; + background-color: #FBFCFD; + position: relative; + border: 1px solid #808080; + margin-right: 1px; +} + +span.fold.plus::before, span.fold.minus::before { + content: ''; + position: absolute; + background-color: #808080; +} + +span.fold.plus::before { + width: 2px; + height: 6px; + top: 2px; + left: 4px; +} + +span.fold.plus::after { + content: ''; + position: absolute; + width: 6px; + height: 2px; + top: 4px; + left: 2px; + background-color: #808080; +} + +span.fold.minus::before { + width: 6px; + height: 2px; + top: 4px; + left: 2px; +} + +span.lineno { + padding-right: 4px; + margin-right: 9px; + text-align: right; + border-right: 2px solid #00FF00; + color: black; + background-color: #E8E8E8; + white-space: pre; +} +span.lineno a, span.lineno a:visited { + color: #4665A2; + background-color: #D8D8D8; +} + +span.lineno a:hover { + color: #4665A2; + background-color: #C8C8C8; +} + +.lineno { + -webkit-touch-callout: none; + -webkit-user-select: none; + -khtml-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; +} + +div.classindex ul { + list-style: none; + padding-left: 0; +} + +div.classindex span.ai { + display: inline-block; +} + +div.groupHeader { + box-shadow: 13px 0 white, + -13px 0 white, + 13px 1px #D9E0EE, + -13px 1px #D9E0EE; + color: #354C7B; + font-size: 110%; + font-weight: 500; + margin-left: 0px; + margin-top: 0em; + margin-bottom: 6px; + padding-top: 8px; + padding-bottom: 4px; +} + +div.groupText { + margin-left: 16px; + font-style: italic; +} + +body { + color: black; + margin: 0; +} + +div.contents { + margin-top: 10px; + margin-left: 12px; + margin-right: 12px; +} + +p.formulaDsp { + text-align: center; +} + +img.dark-mode-visible { + display: none; +} +img.light-mode-visible { + display: none; +} + +img.formulaInl, img.inline { + vertical-align: middle; +} + +div.center { + text-align: center; + margin-top: 0px; + margin-bottom: 0px; + padding: 0px; +} + +div.center img { + border: 0px; +} + +address.footer { + text-align: right; + padding-right: 12px; +} + +img.footer { + border: 0px; + vertical-align: middle; + width: 75px; +} + +.compoundTemplParams { + color: #4665A2; + font-size: 80%; + line-height: 120%; +} + +/* @group Code Colorization */ + +span.keyword { + color: #008000; +} + +span.keywordtype { + color: #604020; +} + +span.keywordflow { + color: #E08000; +} + +span.comment { + color: #800000; +} + +span.preprocessor { + color: #806020; +} + +span.stringliteral { + color: #002080; +} + +span.charliteral { + color: #008080; +} + +span.xmlcdata { + color: black; +} + +span.vhdldigit { + color: #FF00FF; +} + +span.vhdlchar { + color: #000000; +} + +span.vhdlkeyword { + color: #700070; +} + +span.vhdllogic { + color: #FF0000; +} + +blockquote { + background-color: #F7F8FB; + border-left: 2px solid #9CAFD4; + margin: 0 24px 0 4px; + padding: 0 12px 0 16px; +} + +/* @end */ + +td.tiny { + font-size: 75%; +} + +.dirtab { + padding: 4px; + border-collapse: collapse; + border: 1px solid #2D4068; +} + +th.dirtab { + background-color: #374F7F; + color: #FFFFFF; + font-weight: bold; +} + +hr { + border: none; + margin-top: 16px; + margin-bottom: 16px; + height: 1px; + box-shadow: 13px 0 white, + -13px 0 white, + 13px 1px #D9E0EE, + -13px 1px #D9E0EE; +} + +hr.footer { + height: 1px; +} + +/* @group Member Descriptions */ + +table.memberdecls { + border-spacing: 0px; + padding: 0px; +} + +.memberdecls td, .fieldtable tr { + transition-property: background-color, box-shadow; + transition-duration: 0.5s; +} + +.memberdecls td.glow, .fieldtable tr.glow { + background-color: cyan; + box-shadow: 0 0 15px cyan; +} + +.memberdecls tr[class^='memitem'] { + font-family: 'JetBrains Mono',Consolas,Monaco,'Andale Mono','Ubuntu Mono',monospace,fixed; +} + +.mdescLeft, .mdescRight, +.memItemLeft, .memItemRight { + padding-top: 2px; + padding-bottom: 2px; +} + +.memTemplParams { + padding-left: 10px; + padding-top: 5px; +} + +.memItemLeft, .memItemRight, .memTemplParams { + background-color: #F9FAFC; +} + +.mdescLeft, .mdescRight { + padding: 0px 8px 4px 8px; + color: #555; +} + +tr[class^='memdesc'] { + box-shadow: inset 0px 1px 3px 0px rgba(0,0,0,.075); +} + +.mdescLeft { + border-left: 1px solid #D5DDEC; + border-bottom: 1px solid #D5DDEC; +} + +.mdescRight { + border-right: 1px solid #D5DDEC; + border-bottom: 1px solid #D5DDEC; +} + +.memTemplParams { + color: #4665A2; + white-space: nowrap; + font-size: 80%; + border-left: 1px solid #D5DDEC; + border-right: 1px solid #D5DDEC; +} + +td.ititle { + border: 1px solid #D5DDEC; + border-top-left-radius: 4px; + border-top-right-radius: 4px; + padding-left: 10px; +} + +tr:not(:first-child) > td.ititle { + border-top: 0; + border-radius: 0; +} + +.memItemLeft { + white-space: nowrap; + border-left: 1px solid #D5DDEC; + border-bottom: 1px solid #D5DDEC; + padding-left: 10px; + transition: none; + vertical-align: top; + text-align: right; +} + +.memItemRight { + width: 100%; + border-right: 1px solid #D5DDEC; + border-bottom: 1px solid #D5DDEC; + padding-right: 10px; + transition: none; + vertical-align: bottom; +} + +tr.heading + tr[class^='memitem'] td.memItemLeft, +tr.groupHeader + tr[class^='memitem'] td.memItemLeft, +tr.inherit_header + tr[class^='memitem'] td.memItemLeft { + border-top: 1px solid #D5DDEC; + border-top-left-radius: 4px; +} + +tr.heading + tr[class^='memitem'] td.memItemRight, +tr.groupHeader + tr[class^='memitem'] td.memItemRight, +tr.inherit_header + tr[class^='memitem'] td.memItemRight { + border-top: 1px solid #D5DDEC; + border-top-right-radius: 4px; +} + +tr.heading + tr[class^='memitem'] td.memTemplParams, +tr.heading + tr td.ititle, +tr.groupHeader + tr[class^='memitem'] td.memTemplParams, +tr.groupHeader + tr td.ititle, +tr.inherit_header + tr[class^='memitem'] td.memTemplParams { + border-top: 1px solid #D5DDEC; + border-top-left-radius: 4px; + border-top-right-radius: 4px; +} + +table.memberdecls tr:last-child td.memItemLeft, +table.memberdecls tr:last-child td.mdescLeft, +table.memberdecls tr[class^='memitem']:has(+ tr.groupHeader) td.memItemLeft, +table.memberdecls tr[class^='memitem']:has(+ tr.inherit_header) td.memItemLeft, +table.memberdecls tr[class^='memdesc']:has(+ tr.groupHeader) td.mdescLeft, +table.memberdecls tr[class^='memdesc']:has(+ tr.inherit_header) td.mdescLeft { + border-bottom-left-radius: 4px; +} + +table.memberdecls tr:last-child td.memItemRight, +table.memberdecls tr:last-child td.mdescRight, +table.memberdecls tr[class^='memitem']:has(+ tr.groupHeader) td.memItemRight, +table.memberdecls tr[class^='memitem']:has(+ tr.inherit_header) td.memItemRight, +table.memberdecls tr[class^='memdesc']:has(+ tr.groupHeader) td.mdescRight, +table.memberdecls tr[class^='memdesc']:has(+ tr.inherit_header) td.mdescRight { + border-bottom-right-radius: 4px; +} + +tr.template .memItemLeft, tr.template .memItemRight { + border-top: none; + padding-top: 0; +} + + +/* @end */ + +/* @group Member Details */ + +/* Styles for detailed member documentation */ + +.memtitle { + padding: 8px; + border-top: 1px solid #A8B8D9; + border-left: 1px solid #A8B8D9; + border-right: 1px solid #A8B8D9; + border-top-right-radius: 4px; + border-top-left-radius: 4px; + margin-bottom: -1px; + background-color: #EEF1F7; + line-height: 1.25; + font-family: 'JetBrains Mono',Consolas,Monaco,'Andale Mono','Ubuntu Mono',monospace,fixed; + font-weight: 500; + font-size: 16px; + float:left; + box-shadow: 0 10px 0 -1px #EEF1F7, + 0 2px 8px 0 rgba(0,0,0,.075); + position: relative; +} + +.memtitle:after { + content: ''; + display: block; + background: #EEF1F7; + height: 10px; + bottom: -10px; + left: 0px; + right: -14px; + position: absolute; + border-top-right-radius: 6px; +} + +.permalink +{ + font-family: 'JetBrains Mono',Consolas,Monaco,'Andale Mono','Ubuntu Mono',monospace,fixed; + font-weight: 500; + line-height: 1.25; + font-size: 16px; + display: inline-block; + vertical-align: middle; +} + +.memtemplate { + font-size: 80%; + color: #4665A2; + font-family: 'JetBrains Mono',Consolas,Monaco,'Andale Mono','Ubuntu Mono',monospace,fixed; + font-weight: normal; + margin-left: 9px; +} + +.mempage { + width: 100%; +} + +.memitem { + padding: 0; + margin-bottom: 10px; + margin-right: 5px; + display: table !important; + width: 100%; + box-shadow: 0 2px 8px 0 rgba(0,0,0,.075); + border-radius: 4px; +} + +.memitem.glow { + box-shadow: 0 0 15px cyan; +} + +.memname { + font-family: 'JetBrains Mono',Consolas,Monaco,'Andale Mono','Ubuntu Mono',monospace,fixed; + font-size: 13px; + font-weight: 400; + margin-left: 6px; +} + +.memname td { + vertical-align: bottom; +} + +.memproto, dl.reflist dt { + border-top: 1px solid #A8B8D9; + border-left: 1px solid #A8B8D9; + border-right: 1px solid #A8B8D9; + padding: 6px 0px 6px 0px; + color: #253555; + font-weight: bold; + background-color: #EEF1F7; + border-top-right-radius: 4px; + border-bottom: 1px solid #A8B8D9; +} + +.overload { + font-family: 'JetBrains Mono',Consolas,Monaco,'Andale Mono','Ubuntu Mono',monospace,fixed; + font-size: 65%; +} + +.memdoc, dl.reflist dd { + border-bottom: 1px solid #A8B8D9; + border-left: 1px solid #A8B8D9; + border-right: 1px solid #A8B8D9; + padding: 6px 10px 2px 10px; + border-top-width: 0; + border-bottom-left-radius: 4px; + border-bottom-right-radius: 4px; +} + +dl.reflist dt { + padding: 5px; +} + +dl.reflist dd { + margin: 0px 0px 10px 0px; + padding: 5px; +} + +.paramkey { + text-align: right; +} + +.paramtype { + white-space: nowrap; + padding: 0px; + padding-bottom: 1px; +} + +.paramname { + white-space: nowrap; + padding: 0px; + padding-bottom: 1px; + margin-left: 2px; +} + +.paramname em { + color: #602020; + font-style: normal; + margin-right: 1px; +} + +.paramname .paramdefval { + font-family: 'JetBrains Mono',Consolas,Monaco,'Andale Mono','Ubuntu Mono',monospace,fixed; +} + +.params, .retval, .exception, .tparams { + margin-left: 0px; + padding-left: 0px; +} + +.params .paramname, .retval .paramname, .tparams .paramname, .exception .paramname { + font-weight: bold; + vertical-align: top; +} + +.params .paramtype, .tparams .paramtype { + font-style: italic; + vertical-align: top; +} + +.params .paramdir, .tparams .paramdir { + font-family: 'JetBrains Mono',Consolas,Monaco,'Andale Mono','Ubuntu Mono',monospace,fixed; + vertical-align: top; +} + +table.mlabels { + border-spacing: 0px; +} + +td.mlabels-left { + width: 100%; + padding: 0px; +} + +td.mlabels-right { + vertical-align: bottom; + padding: 0px; + white-space: nowrap; +} + +span.mlabels { + margin-left: 8px; +} + +span.mlabel { + background-color: #728DC1; + border-top:1px solid #5373B4; + border-left:1px solid #5373B4; + border-right:1px solid #C4CFE5; + border-bottom:1px solid #C4CFE5; + text-shadow: none; + color: white; + margin-right: 4px; + padding: 2px 3px; + border-radius: 3px; + font-size: 7pt; + white-space: nowrap; + vertical-align: middle; +} + + + +/* @end */ + +/* these are for tree view inside a (index) page */ + +div.directory { + margin: 10px 0px; + width: 100%; +} + +.directory table { + border-collapse:collapse; +} + +.directory td { + margin: 0px; + padding: 0px; + vertical-align: top; +} + +.directory td.entry { + white-space: nowrap; + padding-right: 6px; + padding-top: 3px; +} + +.directory td.entry a { + outline:none; +} + +.directory td.entry a img { + border: none; +} + +.directory td.desc { + width: 100%; + padding-left: 6px; + padding-right: 6px; + padding-top: 3px; + border-left: 1px solid rgba(0,0,0,0.05); +} + +.directory tr.odd { + padding-left: 6px; + background-color: #F8F9FC; +} + +.directory tr.even { + padding-left: 6px; + background-color: white; +} + +.directory img { + vertical-align: -30%; +} + +.directory .levels { + white-space: nowrap; + width: 100%; + text-align: right; + font-size: 9pt; +} + +.directory .levels span { + cursor: pointer; + padding-left: 2px; + padding-right: 2px; + color: #3D578C; +} + +.arrow { + color: #F9FAFC; + -webkit-user-select: none; + -khtml-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; + cursor: pointer; + font-size: 80%; + display: inline-block; + width: 16px; + height: 14px; + transition: opacity 0.3s ease; +} + +span.arrowhead { + position: relative; + padding: 0; + margin: 0 0 0 2px; + display: inline-block; + width: 5px; + height: 5px; + border-right: 2px solid #B6C4DF; + border-bottom: 2px solid #B6C4DF; + transform: rotate(-45deg); + transition: transform 0.3s ease; +} + +span.arrowhead.opened { + transform: rotate(45deg); +} + +.selected span.arrowhead { + border-right: 2px solid #90A5CE; + border-bottom: 2px solid #90A5CE; +} + +.icon { + font-family: Arial,Helvetica; + line-height: normal; + font-weight: bold; + font-size: 12px; + height: 14px; + width: 16px; + display: inline-block; + background-color: #728DC1; + color: white; + text-align: center; + border-radius: 4px; + margin-left: 2px; + margin-right: 2px; +} + +.icona { + width: 24px; + height: 22px; + display: inline-block; +} + +.iconfolder { + width: 24px; + height: 18px; + margin-top: 6px; + vertical-align:top; + display: inline-block; + position: relative; +} + +.icondoc { + width: 24px; + height: 18px; + margin-top: 3px; + vertical-align:top; + display: inline-block; + position: relative; +} + +.folder-icon { + width: 16px; + height: 11px; + background-color: #D8DFEE; + border: 1px solid #4665A2; + border-radius: 0 2px 2px 2px; + position: relative; + box-sizing: content-box; +} + +.folder-icon::after { + content: ''; + position: absolute; + top: 2px; + left: -1px; + width: 16px; + height: 7px; + background-color: #C4CFE5; + border: 1px solid #4665A2; + border-radius: 7px 7px 2px 2px; + transform-origin: top left; + opacity: 0; + transition: all 0.3s linear; +} + +.folder-icon::before { + content: ''; + position: absolute; + top: -3px; + left: -1px; + width: 6px; + height: 2px; + background-color: #D8DFEE; + border-top: 1px solid #4665A2; + border-left: 1px solid #4665A2; + border-right: 1px solid #4665A2; + border-radius: 2px 2px 0 0; +} + +.folder-icon.open::after { + top: 3px; + opacity: 1; +} + +.doc-icon { + left: 6px; + width: 12px; + height: 16px; + background-color: #4665A2; + clip-path: polygon(0 0, 66% 0, 100% 25%, 100% 100%, 0 100%); + position: relative; + display: inline-block; +} +.doc-icon::before { + content: ""; + left: 1px; + top: 1px; + width: 10px; + height: 14px; + background-color: #D8DFEE; + clip-path: polygon(0 0, 66% 0, 100% 25%, 100% 100%, 0 100%); + position: absolute; + box-sizing: border-box; +} +.doc-icon::after { + content: ""; + left: 7px; + top: 0px; + width: 3px; + height: 3px; + background-color: transparent; + position: absolute; + border: 1px solid #4665A2; +} + + + + +/* @end */ + +div.dynheader { + margin-top: 8px; + -webkit-touch-callout: none; + -webkit-user-select: none; + -khtml-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; +} + +span.dynarrow { + position: relative; + display: inline-block; + width: 12px; + bottom: 1px; +} + +address { + font-style: normal; + color: #2A3D61; +} + +table.doxtable caption { + caption-side: top; +} + +table.doxtable { + border-collapse:collapse; + margin-top: 4px; + margin-bottom: 4px; +} + +table.doxtable td, table.doxtable th { + border: 1px solid #2D4068; + padding: 3px 7px 2px; +} + +table.doxtable th { + background-color: #374F7F; + color: #FFFFFF; + font-size: 110%; + padding-bottom: 4px; + padding-top: 5px; +} + +table.fieldtable { + margin-bottom: 10px; + border: 1px solid #A8B8D9; + border-spacing: 0px; + border-radius: 4px; + box-shadow: 2px 2px 2px rgba(0, 0, 0, 0.15); +} + +.fieldtable td, .fieldtable th { + padding: 3px 7px 2px; +} + +.fieldtable td.fieldtype, .fieldtable td.fieldname, .fieldtable td.fieldinit { + white-space: nowrap; + border-right: 1px solid #A8B8D9; + border-bottom: 1px solid #A8B8D9; + vertical-align: top; +} + +.fieldtable td.fieldname { + padding-top: 3px; +} + +.fieldtable td.fieldinit { + padding-top: 3px; + text-align: right; +} + +.fieldtable td.fielddoc { + border-bottom: 1px solid #A8B8D9; +} + +.fieldtable td.fielddoc p:first-child { + margin-top: 0px; +} + +.fieldtable td.fielddoc p:last-child { + margin-bottom: 2px; +} + +.fieldtable tr:last-child td { + border-bottom: none; +} + +.fieldtable th { + background-color: #E2E8F2; + font-size: 90%; + color: #253555; + padding-bottom: 4px; + padding-top: 5px; + text-align:left; + font-weight: 400; + border-top-left-radius: 4px; + border-top-right-radius: 4px; + border-bottom: 1px solid #A8B8D9; +} + +/* style requirements page */ + +div.req_title { + text-decoration-line: underline; + text-decoration-style: solid; + text-decoration-color: #2D4068; + text-decoration-thickness: 1px; + font-weight: bold; +} + +table.reqlist tr > td:first-child { + text-align: right; + font-weight: bold; +} + +div.missing_satisfies { + border-left: 8px solid #b61825; + border-radius: 4px; + background: #f8d1cc; + padding: 10px; + margin: 10px 0px; + overflow: hidden; + margin-left: 0; +} + +div.missing_verifies { + border-left: 8px solid #b61825; + border-radius: 4px; + background: #f8d1cc; + padding: 10px; + margin: 10px 0px; + overflow: hidden; + margin-left: 0; +} + +/* ----------- navigation breadcrumb styling ----------- */ + +#nav-path ul { + height: 30px; + line-height: 30px; + color: #283A5D; + overflow: hidden; + margin: 0px; + padding-left: 4px; + background-image: none; + background: white; + border-bottom: 1px solid #C4CFE5; + font-size: 13px; + font-family: 'Lucida Grande',Geneva,Helvetica,Arial,sans-serif; + position: relative; + z-index: 100; +} + +#main-nav { + border-bottom: 1px solid #C4CFE5; +} + +.navpath li { + list-style-type:none; + float:left; + color: #364D7C; +} + +.navpath li.footer { + list-style-type:none; + float:right; + padding-left:10px; + padding-right:15px; + background-image:none; + background-repeat:no-repeat; + background-position:right; + font-size: 8pt; + color: #2A3D61; +} + +#nav-path li.navelem { + background-image: none; + display: flex; + align-items: center; + padding-left: 15px; +} + +.navpath li.navelem a { + text-shadow: none; + display: inline-block; + color: #354C7B; + position: relative; + top: 0px; + height: 30px; + margin-right: -20px; +} + +#nav-path li.navelem:after { + content: ''; + display: inline-block; + position: relative; + top: 0; + right: -15px; + width: 30px; + height: 30px; + transform: scaleX(0.5) scale(0.707) rotate(45deg); + z-index: 10; + background: white; + box-shadow: 2px -2px 0 2px #C4CFE5; + border-radius: 0 5px 0 50px; +} + +#nav-path li.navelem:first-child { + margin-left: -6px; +} + +#nav-path li.navelem:hover, +#nav-path li.navelem:hover:after { + background-color: #EEF1F7; +} + +/* ---------------------- */ + +div.summary +{ + float: right; + font-size: 8pt; + padding-right: 5px; + width: 50%; + text-align: right; +} + +div.summary a +{ + white-space: nowrap; +} + +table.classindex +{ + margin: 10px; + white-space: nowrap; + margin-left: 3%; + margin-right: 3%; + width: 94%; + border: 0; + border-spacing: 0; + padding: 0; +} + +div.ingroups +{ + font-size: 8pt; + width: 50%; + text-align: left; +} + +div.ingroups a +{ + white-space: nowrap; +} + +div.header +{ + margin: 0px; + background-color: #F9FAFC; + border-bottom: 1px solid #C4CFE5; +} + +div.headertitle +{ + padding: 5px 5px 5px 10px; +} + +dl { + padding: 0 0 0 0; +} + +dl.bug dt a, dl.deprecated dt a, dl.todo dt a, dl.test a { + font-weight: bold !important; +} + +dl.warning, dl.attention, dl.important, dl.note, dl.deprecated, dl.bug, +dl.invariant, dl.pre, dl.post, dl.todo, dl.test, dl.remark { + padding: 10px; + margin: 10px 0px; + overflow: hidden; + margin-left: 0; + border-radius: 4px; +} + +dl.section dd { + margin-bottom: 2px; +} + +dl.warning, dl.attention, dl.important { + background: #f8d1cc; + border-left: 8px solid #b61825; + color: #75070f; +} + +dl.warning dt, dl.attention dt, dl.important dt { + color: #b61825; +} + +dl.warning .tt, dl.attention .tt, dl.important .tt { + background-color: hsl(from #f8d1cc h s calc(l + -3)); +} + +dl.note, dl.remark { + background: #faf3d8; + border-left: 8px solid #f3a600; + color: #5f4204; +} + +dl.note dt, dl.remark dt { + color: #f3a600; +} + +dl.note .tt, dl.remark .tt { + background-color: hsl(from #faf3d8 h s calc(l + -3)); +} + +dl.todo { + background: #e4f3ff; + border-left: 8px solid #1879C4; + color: #274a5c; +} + +dl.todo dt { + color: #1879C4; +} + +dl.todo .tt { + background-color: hsl(from #e4f3ff h s calc(l + -3)); +} + +dl.test { + background: #e8e8ff; + border-left: 8px solid #3939C4; + color: #1a1a5c; +} + +dl.test dt { + color: #3939C4; +} + +dl.test .tt { + background-color: hsl(from #e8e8ff h s calc(l + -3)); +} + +dl.bug dt a { + color: #5b2bdd !important; +} + +dl.bug { + background: #e4dafd; + border-left: 8px solid #5b2bdd; + color: #2a0d72; +} + +dl.bug dt a { + color: #5b2bdd !important; +} + +dl.bug .tt { + background-color: hsl(from #e4dafd h s calc(l + -3)); +} + +dl.deprecated { + background: #ecf0f3; + border-left: 8px solid #5b6269; + color: #43454a; +} + +dl.deprecated dt a { + color: #5b6269 !important; +} + +dl.deprecated .tt { + background-color: hsl(from #ecf0f3 h s calc(l + -3)); +} + + +dl.invariant, dl.pre, dl.post { + background: #d8f1e3; + border-left: 8px solid #44b86f; + color: #265532; +} + +dl.invariant dt, dl.pre dt, dl.post dt { + color: #44b86f; +} + +dl.invariant .tt, dl.pre .tt, dl.post .tt { + background-color: hsl(from #d8f1e3 h s calc(l + -3)); +} + +dl.note dd, dl.warning dd, dl.pre dd, dl.post dd, +dl.remark dd, dl.attention dd, dl.important dd, dl.invariant dd, +dl.bug dd, dl.deprecated dd, dl.todo dd, dl.test dd { + margin-inline-start: 0px; +} + + +#projectrow +{ + height: 56px; +} + +#projectlogo +{ + text-align: center; + vertical-align: bottom; + border-collapse: separate; +} + +#projectlogo img +{ + border: 0px none; +} + +#projectalign +{ + vertical-align: middle; + padding-left: 0.5em; +} + +#projectname +{ + font-size: 200%; + font-family: system-ui,-apple-system,Segoe UI,Roboto,Ubuntu,Cantarell,Noto Sans,sans-serif,BlinkMacSystemFont,"Segoe UI",Helvetica,Arial,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol"; + margin: 0; + padding: 0; +} + +#side-nav #projectname +{ + font-size: 130%; +} + +#projectbrief +{ + font-size: 90%; + font-family: system-ui,-apple-system,Segoe UI,Roboto,Ubuntu,Cantarell,Noto Sans,sans-serif,BlinkMacSystemFont,"Segoe UI",Helvetica,Arial,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol"; + margin: 0px; + padding: 0px; +} + +#projectnumber +{ + font-size: 50%; + font-family: system-ui,-apple-system,Segoe UI,Roboto,Ubuntu,Cantarell,Noto Sans,sans-serif,BlinkMacSystemFont,"Segoe UI",Helvetica,Arial,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol"; + margin: 0px; + padding: 0px; +} + +#titlearea +{ + padding: 0 0 0 5px; + margin: 0px; + border-bottom: 1px solid #C4CFE5; + background-color: white; +} + +.image +{ + text-align: center; +} + +.dotgraph +{ + text-align: center; +} + +.mscgraph +{ + text-align: center; +} + +.plantumlgraph +{ + text-align: center; +} + +.diagraph +{ + text-align: center; +} + +.caption +{ + font-weight: bold; +} + +dl.citelist { + margin-bottom:50px; +} + +dl.citelist dt { + color:#334975; + float:left; + font-weight:bold; + margin-right:10px; + padding:5px; + text-align:right; + width:52px; +} + +dl.citelist dd { + margin:2px 0 2px 72px; + padding:5px 0; +} + +div.toc { + padding: 14px 25px; + background-color: #F4F6FA; + border: 1px solid #D8DFEE; + border-radius: 7px 7px 7px 7px; + float: right; + height: auto; + margin: 0 8px 10px 10px; + width: 200px; +} + +div.toc li { + background: url("data:image/svg+xml;utf8,&%238595;") no-repeat scroll 0 5px transparent; + font: 10px/1.2 Verdana,'DejaVu Sans',Geneva,sans-serif; + margin-top: 5px; + padding-left: 10px; + padding-top: 2px; +} + +div.toc h3 { + font: bold 12px/1.2 Verdana,'DejaVu Sans',Geneva,sans-serif; + color: #4665A2; + border-bottom: 0 none; + margin: 0; +} + +div.toc ul { + list-style: none outside none; + border: medium none; + padding: 0px; +} + +div.toc li[class^='level'] { + margin-left: 15px; +} + +div.toc li.level1 { + margin-left: 0px; +} + +div.toc li.empty { + background-image: none; + margin-top: 0px; +} + +span.emoji { + /* font family used at the site: https://unicode.org/emoji/charts/full-emoji-list.html + * font-family: "Noto Color Emoji", "Apple Color Emoji", "Segoe UI Emoji", Times, Symbola, Aegyptus, Code2000, Code2001, Code2002, Musica, serif, LastResort; + */ +} + +span.obfuscator { + display: none; +} + +.inherit_header { + font-weight: 400; + cursor: pointer; + -webkit-touch-callout: none; + -webkit-user-select: none; + -khtml-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; +} + +.inherit_header td { + padding: 6px 0 2px 0; +} + +.inherit { + display: none; +} + +tr.heading h2 { + margin-top: 12px; + margin-bottom: 12px; +} + +/* tooltip related style info */ + +.ttc { + position: absolute; + display: none; +} + +#powerTip { + cursor: default; + color: black; + background-color: rgba(255,255,255,0.8); + backdrop-filter: blur(3px); + -webkit-backdrop-filter: blur(3px); + border: 1px solid rgba(150,150,150,0.7); + border-radius: 4px; + box-shadow: 0 4px 8px 0 rgba(0,0,0,.25); + display: none; + font-size: smaller; + max-width: 80%; + padding: 1ex 1em 1em; + position: absolute; + z-index: 2147483647; +} + +#powerTip div.ttdoc { + color: grey; + font-style: italic; +} + +#powerTip div.ttname a { + font-weight: bold; +} + +#powerTip a { + color: #4665A2; +} + +#powerTip div.ttname { + font-weight: bold; +} + +#powerTip div.ttdeci { + color: #006318; +} + +#powerTip div { + margin: 0px; + padding: 0px; + font-size: 12px; + font-family: Roboto,sans-serif; + line-height: 16px; +} + +#powerTip:before, #powerTip:after { + content: ""; + position: absolute; + margin: 0px; +} + +#powerTip.n:after, #powerTip.n:before, +#powerTip.s:after, #powerTip.s:before, +#powerTip.w:after, #powerTip.w:before, +#powerTip.e:after, #powerTip.e:before, +#powerTip.ne:after, #powerTip.ne:before, +#powerTip.se:after, #powerTip.se:before, +#powerTip.nw:after, #powerTip.nw:before, +#powerTip.sw:after, #powerTip.sw:before { + border: solid transparent; + content: " "; + height: 0; + width: 0; + position: absolute; +} + +#powerTip.n:after, #powerTip.s:after, +#powerTip.w:after, #powerTip.e:after, +#powerTip.nw:after, #powerTip.ne:after, +#powerTip.sw:after, #powerTip.se:after { + border-color: rgba(255, 255, 255, 0); +} + +#powerTip.n:before, #powerTip.s:before, +#powerTip.w:before, #powerTip.e:before, +#powerTip.nw:before, #powerTip.ne:before, +#powerTip.sw:before, #powerTip.se:before { + border-color: rgba(128, 128, 128, 0); +} + +#powerTip.n:after, #powerTip.n:before, +#powerTip.ne:after, #powerTip.ne:before, +#powerTip.nw:after, #powerTip.nw:before { + top: 100%; +} + +#powerTip.n:after, #powerTip.ne:after, #powerTip.nw:after { + border-top-color: white; + border-width: 10px; + margin: 0px -10px; +} +#powerTip.n:before, #powerTip.ne:before, #powerTip.nw:before { + border-top-color: rgba(150,150,150,0.7); + border-width: 11px; + margin: 0px -11px; +} +#powerTip.n:after, #powerTip.n:before { + left: 50%; +} + +#powerTip.nw:after, #powerTip.nw:before { + right: 14px; +} + +#powerTip.ne:after, #powerTip.ne:before { + left: 14px; +} + +#powerTip.s:after, #powerTip.s:before, +#powerTip.se:after, #powerTip.se:before, +#powerTip.sw:after, #powerTip.sw:before { + bottom: 100%; +} + +#powerTip.s:after, #powerTip.se:after, #powerTip.sw:after { + border-bottom-color: white; + border-width: 10px; + margin: 0px -10px; +} + +#powerTip.s:before, #powerTip.se:before, #powerTip.sw:before { + border-bottom-color: rgba(150,150,150,0.7); + border-width: 11px; + margin: 0px -11px; +} + +#powerTip.s:after, #powerTip.s:before { + left: 50%; +} + +#powerTip.sw:after, #powerTip.sw:before { + right: 14px; +} + +#powerTip.se:after, #powerTip.se:before { + left: 14px; +} + +#powerTip.e:after, #powerTip.e:before { + left: 100%; +} +#powerTip.e:after { + border-left-color: rgba(150,150,150,0.7); + border-width: 10px; + top: 50%; + margin-top: -10px; +} +#powerTip.e:before { + border-left-color: rgba(150,150,150,0.7); + border-width: 11px; + top: 50%; + margin-top: -11px; +} + +#powerTip.w:after, #powerTip.w:before { + right: 100%; +} +#powerTip.w:after { + border-right-color: rgba(150,150,150,0.7); + border-width: 10px; + top: 50%; + margin-top: -10px; +} +#powerTip.w:before { + border-right-color: rgba(150,150,150,0.7); + border-width: 11px; + top: 50%; + margin-top: -11px; +} + +@media print +{ + #top { display: none; } + #side-nav { display: none; } + #nav-path { display: none; } + body { overflow:visible; } + h1, h2, h3, h4, h5, h6 { page-break-after: avoid; } + .summary { display: none; } + .memitem { page-break-inside: avoid; } + #doc-content + { + margin-left:0 !important; + height:auto !important; + width:auto !important; + overflow:inherit; + display:inline; + } +} + +/* @group Markdown */ + +table.markdownTable { + border-collapse:collapse; + margin-top: 4px; + margin-bottom: 4px; +} + +table.markdownTable td, table.markdownTable th { + border: 1px solid #2D4068; + padding: 3px 7px 2px; +} + +table.markdownTable tr { +} + +th.markdownTableHeadLeft, th.markdownTableHeadRight, th.markdownTableHeadCenter, th.markdownTableHeadNone { + background-color: #374F7F; + color: #FFFFFF; + font-size: 110%; + padding-bottom: 4px; + padding-top: 5px; +} + +th.markdownTableHeadLeft, td.markdownTableBodyLeft { + text-align: left +} + +th.markdownTableHeadRight, td.markdownTableBodyRight { + text-align: right +} + +th.markdownTableHeadCenter, td.markdownTableBodyCenter { + text-align: center +} + +tt, code, kbd +{ + display: inline-block; +} +tt, code, kbd +{ + vertical-align: top; +} +/* @end */ + +u { + text-decoration: underline; +} + +details>summary { + list-style-type: none; +} + +details > summary::-webkit-details-marker { + display: none; +} + +details>summary::before { + content: "\25bc"; + padding-right:4px; + font-size: 80%; + display: inline-block; + transform: rotate(-90deg); +} + +details[open]>summary::before { + content: "\25bc"; + padding-right:4px; + font-size: 80%; + display: inline-block; + transform: rotate(0deg); +} +:root { + scrollbar-width: thin; + scrollbar-color: #C4CFE5 #F9FAFC; +} + +:root.dark-mode { + color-scheme: dark; +} + +::-webkit-scrollbar { + background-color: #F9FAFC; + height: 12px; + width: 12px; +} +::-webkit-scrollbar-thumb { + border-radius: 6px; + box-shadow: inset 0 0 12px 12px #C4CFE5; + border: solid 2px transparent; +} +::-webkit-scrollbar-corner { + background-color: #F9FAFC; +} + diff --git a/doxygen.svg b/doxygen.svg new file mode 100644 index 0000000..79a7635 --- /dev/null +++ b/doxygen.svg @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/doxygen_crawl.html b/doxygen_crawl.html new file mode 100644 index 0000000..6c7db7b --- /dev/null +++ b/doxygen_crawl.html @@ -0,0 +1,55 @@ + + + +Validator / crawler helper + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/dynsections.js b/dynsections.js new file mode 100644 index 0000000..4658ccb --- /dev/null +++ b/dynsections.js @@ -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 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 */ diff --git a/index.html b/index.html new file mode 100644 index 0000000..edf990b --- /dev/null +++ b/index.html @@ -0,0 +1,273 @@ + + + + + + + +conformallab++: conformallab++ + + + + + + + + + + + + + + + +
+
+ + + + + + +
+
conformallab++ 0.7.0 +
+
Discrete conformal maps on triangle meshes — C++17 reimplementation of ConformalLab (TU Berlin)
+
+
+ + + + + + + + +
+
+
+ +
+
+
+ +
+
+ +
+
+ + +
+
+
+
+
+
Loading...
+
Searching...
+
No Matches
+
+
+
+
+ +
+
conformallab++
+
+
+

+

CI [License: MIT](LICENSE) DOI

+

C++17 reimplementation of ConformalLab — Stefan Sechelmann's Java research library for discrete conformal geometry (TU Berlin). The long-term goal is a CGAL package for discrete conformal maps.

+

Algorithmic foundation:

+

Stefan Sechelmann — Variational Methods for Discrete Surface Parameterization: Applications and Implementation, TU Berlin 2016. DOI: 10.14279/depositonce-5415 · CC BY-SA 4.0 · Java original · sechel.de

+
+

Status: v0.9.0 — Phases 1–9a complete, Phase 8b-Lite CGAL API surface. Newton solvers for five DCE models (Euclidean / Spherical / HyperIdeal / CP-Euclidean / Inversive-Distance), priority-BFS layout in ℝ²/S²/Poincaré disk, Gauss–Bonnet, 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 doc/api/tests.md for the per-suite breakdown.

+
+

+Quick start

+
git clone https://codeberg.org/TMoussa/ConformalLabpp && cd ConformalLabpp
+
+
# Fast tests — no system dependencies
+
cmake -S code -B build && cmake --build build --target conformallab_tests -j$(nproc)
+
ctest --test-dir build --output-on-failure
+
+
# CGAL tests headless (apt install libboost-dev / brew install boost)
+
cmake -S code -B build -DWITH_CGAL_TESTS=ON
+
cmake --build build --target conformallab_cgal_tests -j$(nproc)
+
ctest --test-dir build -R "^cgal\." --output-on-failure
+
+
# Full build with CLI + viewer (requires Wayland/X11 dev headers)
+
cmake -S code -B build -DWITH_CGAL=ON && cmake --build build -j$(nproc)
+
./bin/conformallab_core -i input.off -g euclidean -o layout.off -j result.json
+
+
# API documentation (requires doxygen: brew/apt install doxygen)
+
cmake --build build --target doc
+
open doc/doxygen/html/index.html
+

+

+Minimal usage

+
#include "conformal_mesh.hpp"
+
#include "mesh_io.hpp"
+
#include "euclidean_functional.hpp"
+
#include "gauss_bonnet.hpp"
+
#include "newton_solver.hpp"
+
#include "layout.hpp"
+
+
using namespace conformallab;
+
+
ConformalMesh mesh = load_mesh("input.off");
+
EuclideanMaps maps = setup_euclidean_maps(mesh);
+
compute_euclidean_lambda0_from_mesh(mesh, maps);
+
+
// Assign DOFs — pin first vertex (gauge fix)
+
auto vit = mesh.vertices().begin();
+
maps.v_idx[*vit++] = -1;
+
int idx = 0;
+
for (; vit != mesh.vertices().end(); ++vit) maps.v_idx[*vit] = idx++;
+
+
// Natural equilibrium target: x* = 0 by construction
+
std::vector<double> x0(idx, 0.0);
+
auto G0 = euclidean_gradient(mesh, x0, maps);
+
for (auto v : mesh.vertices())
+
if (maps.v_idx[v] >= 0) maps.theta_v[v] -= G0[maps.v_idx[v]];
+
+
check_gauss_bonnet(mesh, maps);
+
NewtonResult res = newton_euclidean(mesh, x0, maps);
+
Layout2D layout = euclidean_layout(mesh, res.x, maps);
+

+

+Documentation

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Getting started — build modes, single-test invocation, CLI, Docker doc/getting-started.md
Pipeline API — all three geometries, holonomy, serialisation doc/api/pipeline.md
Public headers — all public headers with descriptions doc/api/headers.md
Test suites — per-suite breakdown and counts (single source of truth) doc/api/tests.md
Extending — new functionals, geometry modes, porting from Java doc/api/extending.md
Processing unit contracts — preconditions / provides table doc/api/contracts.md
CGAL package design — Phase 8 target, YAML pipeline doc/api/cgal-package.md
Architecture & pipeline diagram doc/architecture/overall_pipeline.md
geometry-central comparison — shared core, demarcation, adoption candidates, scientific added value doc/architecture/geometry-central-comparison.md
Design decisions — key architectural choices + rationale doc/architecture/design-decisions.md
Project structure — directory tree + build targets doc/architecture/project-structure.md
Discrete conformal theory — mathematical background for collaborators doc/math/discrete-conformal-theory.md
Validation — known analytic results + how to verify them doc/math/validation.md
Validation protocol — concrete commands with expected outputs doc/math/validation-protocol.md
Tutorial: add a new functional — step-by-step Inversive-Distance port doc/tutorials/add-inversive-distance.md
Declarative YAML pipeline — concept, token vocabulary, 5 examples doc/concepts/declarative-pipeline.md
Geometry modes — Euclidean / Spherical / HyperIdeal comparison doc/math/geometry-modes.md
References — all papers by module doc/math/references.md
Software landscape — how conformallab++ relates to libigl, CGAL, geometry-central doc/math/software-landscape.md
Novelty statement — unique features, target audience, what this is not doc/math/novelty-statement.md
Complexity & scalability — O() analysis, measured timings on real meshes, HyperIdeal bottleneck doc/math/complexity.md
Roadmap — Phases 1–10 doc/roadmap/phases.md
Java parity table — what is ported, what is planned doc/roadmap/java-parity.md
Contributing — language policy, test standards, release flow doc/contributing.md
Claude Code context CLAUDE.md
+
+

+Citing

+

If you use conformallab++ in your research, please cite it using the metadata in CITATION.cff. GitHub and Codeberg show a "Cite this repository" button that generates BibTeX and APA automatically.

+

The primary algorithmic source is:

+
+

Stefan Sechelmann — Variational Methods for Discrete Surface Parameterization: Applications and Implementation, TU Berlin 2016. DOI: 10.14279/depositonce-5415

+
+
+

+Bugs & questions

+ +
+

+License

+

conformallab++ is released under the MIT License (see [LICENSE](LICENSE)).
+ Copyright © 2024–2026 Tarik Moussa.
+ The dissertation (Sechelmann 2016) is CC BY-SA 4.0.

+
+ +
+
+
+ + + + diff --git a/md__c_l_a_u_d_e.html b/md__c_l_a_u_d_e.html new file mode 100644 index 0000000..68558f4 --- /dev/null +++ b/md__c_l_a_u_d_e.html @@ -0,0 +1,541 @@ + + + + + + + +conformallab++: CLAUDE.md + + + + + + + + + + + + + + + +
+
+ + + + + + +
+
conformallab++ 0.7.0 +
+
Discrete conformal maps on triangle meshes — C++17 reimplementation of ConformalLab (TU Berlin)
+
+
+ + + + + + + + + +
+
+ +
+
+
+ +
+
+ +
+
+ + +
+
+
+
+
+
Loading...
+
Searching...
+
No Matches
+
+
+
+
+ +
+
CLAUDE.md
+
+
+

+

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

+

+Project purpose and long-term goal

+

conformallab++ is a C++17 reimplementation of ConformalLab — Stefan Sechelmann's Java research library for discrete conformal geometry (TU Berlin, ~850 commits, v1.0.0 2018). The algorithmic foundation is his dissertation:

+
+

Stefan Sechelmann — Variational Methods for Discrete Surface Parameterization: Applications and Implementation, TU Berlin 2016. DOI: 10.14279/depositonce-5415 · CC BY-SA 4.0

+
+

The long-term goal is a CGAL package — a submission to the CGAL library that brings discrete conformal maps (hyper-ideal, spherical, Euclidean) to the CGAL ecosystem using CGAL::Surface_mesh as the underlying halfedge data structure, with a traits-class design compatible with arbitrary CGAL-conforming mesh types.

+

The project has four distinct phase blocks (updated 2026-05-22):

    +
  • Phase 1–7 (done, v0.7.0): Direct port of the Java library algorithms to C++.
  • +
  • Phase 8a MVP + 8b-Lite (done, v0.9.0): CGAL public-API surface for all five DCE models via <CGAL/Discrete_*.h>. Phase 8a.2 (generic FaceGraph), 8c (manuals), 8d (CGAL-test-format), 8e (YAML pipeline) deferred on-demand.
  • +
  • Phase 9a + 9b (done, v0.9.0): Two new functionals (CP-Euclidean port, Inversive-Distance research), two new Newton solvers, block-FD HyperIdeal Hessian.
  • +
  • Phase 9b-analytic + 9c (planned): Full analytic HyperIdeal Hessian via Schläfli identity (research, see doc/roadmap/research-track.md); 4g-polygon fundamental domain for genus g > 1 (mixed port + research).
  • +
  • Phase 10+ (research): Holomorphic differentials, Siegel period matrix Ω ∈ H_g, full uniformization for genus g ≥ 2.
  • +
+

+Language

+

All code, comments, documentation, commit messages, and test descriptions must be in English. 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.

+

+Build commands

+

All source lives under code/. Three build modes:

+
# Mode 1 — fast tests, no CGAL, no Boost, no display (CI default)
+
cmake -S code -B build
+
cmake --build build --target conformallab_tests -j$(nproc)
+
ctest --test-dir build --output-on-failure
+
+
# Mode 2 — CGAL tests, headless (CI full, requires Boost headers only)
+
# macOS: brew install boost Linux: apt install libboost-dev
+
cmake -S code -B build -DWITH_CGAL_TESTS=ON
+
cmake --build build --target conformallab_cgal_tests -j$(nproc)
+
ctest --test-dir build -R "^cgal\." --output-on-failure
+
+
# Mode 3 — full local build: CLI app + viewer + examples (requires Wayland/X11)
+
cmake -S code -B build -DWITH_CGAL=ON
+
cmake --build build -j$(nproc)
+

-DWITH_CGAL=ON automatically enables -DWITH_VIEWER=ON, which pulls in GLFW and requires wayland-scanner. Never use this in headless CI.

+

+Running a single test

+
# By GTest suite/test name
+
./build/conformallab_cgal_tests --gtest_filter="NewtonSolver*"
+
./build/conformallab_tests --gtest_filter="Clausen*"
+
+
# By CTest regex (prefix "cgal." for all CGAL tests)
+
ctest --test-dir build -R "cgal.NewtonSolver" --output-on-failure
+

+Rebuilding the CI Docker image

+
docker buildx build \
+
--platform linux/arm64 \
+
-f .gitea/docker/Dockerfile.ci-cpp \
+
-t git.eulernest.eu/conformallab/ci-cpp:latest \
+
--push \
+
.gitea/docker/
+

+Architecture

+

+Everything is header-only

+

All algorithms live in code/include/*.hpp. There is no compiled library. The three CMake targets (conformallab_tests, conformallab_cgal_tests, conformallab_core) compile headers directly from their .cpp entry points. To add a new algorithm: create a .hpp in code/include/, add a test in code/tests/cgal/, and register the test file in code/tests/cgal/CMakeLists.txt.

+

+Central type: ConformalMesh

+

conformal_mesh.hpp defines the core type:

using ConformalMesh = CGAL::Surface_mesh<Point3>; // CGAL::Simple_cartesian<double>
+

This replaces the Java CoHDS (half-edge data structure) and its intrusive CoVertex/CoEdge/CoFace types. Data is attached via named CGAL property maps instead of intrusive fields:

+ + + + + + + + + + + + + +
Property map name Type Meaning
"v:lambda" double per vertex log scale factor (conformal variable uᵢ)
"v:theta" double per vertex target cone angle Θᵥ
"v:idx" int per vertex solver DOF index; -1 = pinned/boundary
"e:alpha" double per edge intersection angle αᵢⱼ (hyperbolic only)
"f:type" int per face geometry type (0=Euclidean, 1=Hyperbolic, 2=Spherical)
+

CGAL_DISABLE_GMP and CGAL_DISABLE_MPFR are defined for all CGAL targets — the library deliberately uses Simple_cartesian<double> (floating-point, no exact arithmetic) because conformal geometry does not require exact predicates.

+

+The five DCE models

+

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:

+ + + + + + + + + + + + + +
Model Space DOFs Maps struct Key headers Newton function CGAL entry
Euclidean ℝ² vertex EuclideanMaps euclidean_functional.hpp, euclidean_hessian.hpp newton_euclidean() discrete_conformal_map_euclidean()
Spherical vertex SphericalMaps spherical_functional.hpp, spherical_hessian.hpp newton_spherical() discrete_conformal_map_spherical()
Hyper-ideal H² (Poincaré disk) vertex + edge HyperIdealMaps hyper_ideal_functional.hpp, hyper_ideal_hessian.hpp (block-FD, Phase 9b) newton_hyper_ideal() discrete_conformal_map_hyper_ideal()
CP-Euclidean (BPS 2010) face-based circle packing face CPEuclideanMaps cp_euclidean_functional.hpp newton_cp_euclidean() discrete_circle_packing_euclidean()
Inversive-Distance (Luo 2004) vertex-based circle packing vertex InversiveDistanceMaps inversive_distance_functional.hpp newton_inversive_distance() discrete_inversive_distance_map()
+

DOF-assignment patterns:

    +
  • Vertex-only models (Euclidean, Spherical, Inversive-Distance): pin one vertex manually (maps.v_idx[first_vertex] = -1) 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).
  • +
  • HyperIdeal: assign_all_dof_indices(mesh, maps) assigns vertex + edge DOFs automatically.
  • +
  • CP-Euclidean: face-based — assign_cp_euclidean_face_dof_indices(mesh, maps, pinned_face) pins one face and indexes the rest.
  • +
+

+The full pipeline

+
load_mesh() → ConformalMesh (OFF/OBJ/PLY)
+
setup_*_maps(mesh) → *Maps (property maps created, all zero)
+
compute_*_lambda0_from_mesh(mesh, m) → λ° initialised from 3-D edge lengths
+
DOF assignment → v_idx[v] set; -1 = pinned
+
check_gauss_bonnet(mesh, maps) → throws if Σ(2π−Θᵥ) ≠ 2π·χ(M)
+
enforce_gauss_bonnet(mesh, maps) → redistributes angle defect uniformly
+
newton_*(mesh, x0, maps) → NewtonResult{x*, iterations, converged}
+
compute_cut_graph(mesh) → CutGraph (2g seam edges, tree-cotree)
+
*_layout(mesh, x*, maps, &cg, &hol) → Layout2D/3D + HolonomyData
+
normalise_*(layout) → canonical position (PCA / Möbius / Rodrigues)
+
compute_period_matrix(hol) → PeriodData{τ∈ℍ} (genus 1 flat torus)
+
compute_fundamental_domain(hol) → FundamentalDomain{vertices, generators}
+
tiling_neighbourhood(layout, hol) → vector of translated layout copies
+
save_result_json/xml() → serialised result
+

After compute_*_lambda0_from_mesh() the original vertex positions are no longer used — all subsequent computation is in log-length/scale-factor space.

+

+Newton solver (newton_solver.hpp)

+

Gradient sign convention differs across the five models:

    +
  • Euclidean / Spherical / Inversive-Distance: G_v = Θ_v − actual_angle_sum (target minus actual).
  • +
  • HyperIdeal: G_v = actual_angle_sum − Θ_v (actual minus target).
  • +
  • CP-Euclidean: G_f = φ_f − Σ_{h:face(h)=f} (p(θ*,Δρ) + θ*) (face-based; see cp_euclidean_functional.hpp header for the full formula).
  • +
+

Hessian sign and solver per model:

    +
  • Euclidean: H is PSD (cotangent Laplacian) → SimplicialLDLT(H).
  • +
  • Spherical: H is NSD (concave energy) → SimplicialLDLT(−H) (sign flip inside newton_spherical).
  • +
  • HyperIdeal: H is PSD (strictly convex) → SimplicialLDLT(H). Phase 9b uses a block-FD Hessian (per-face 6×6 local block, ~96× speed-up vs full FD on V=200). Full analytic Hessian via the chain (bᵢ, aₑ) → lᵢⱼ → ζ₁₃/ζ₁₄/ζ₁₅ → αᵢⱼ/βᵢ is planned research — see doc/roadmap/research-track.md Phase 9b-analytic.
  • +
  • CP-Euclidean: analytic 2×2-per-edge h_jk = sin θ / (cosh Δρ − cos θ) (BPS 2010), strictly convex → SimplicialLDLT(H).
  • +
  • Inversive-Distance: FD Hessian (inline in newton_inversive_distance). Analytic via Glickenstein 2011 eq. (4.6) is planned research (Phase 9a.2-analytic).
  • +
+

When SimplicialLDLT fails (rank-deficient H — gauge mode on a closed mesh without pinned vertex/face), the solver automatically retries with Eigen::SparseQR to find the minimum-norm step orthogonal to the null space. Public API: solve_linear_system(H, rhs, &used_fallback).

+

+Layout and holonomy (layout.hpp)

+

BFS-trilateration with a priority min-heap on BFS depth (depth = max(depth[src], depth[tgt]) + 1). Root face = largest 3-D area face. This minimises trilateration error accumulation compared to simple BFS.

+

Key output fields:

    +
  • layout.uv[v.idx()] — primary UV (first/shallowest BFS visit per vertex)
  • +
  • layout.halfedge_uv[h.idx()] — UV of source(h) as seen from face(h); at seam halfedges the two opposite halfedges carry different UV values, enabling proper GPU texture atlasing without vertex duplication
  • +
  • hol.translations[i] — lattice generator ωᵢ ∈ ℂ (Euclidean/spherical)
  • +
  • hol.mobius_maps[i] — Möbius isometry Tᵢ ∈ SU(1,1) (hyperbolic, Poincaré disk)
  • +
+

MobiusMap is defined in layout.hpp: T(z) = (az+b)/(cz+d). Key methods: from_three() (fit to 3 point correspondences via 3×3 complex linear system), compose(), inverse(), apply(Vector2d).

+

+Key mathematical reference for each header

+ + + + + + + + + + + + + + + +
Header Java original Key reference
hyper_ideal_geometry.hpp HyperIdealGeometry.java Springborn (2020) — ζ₁₃/ζ₁₄/ζ₁₅ functions
euclidean_hessian.hpp EuclideanHessian.java Pinkall & Polthier (1993) — cotangent Laplacian
spherical_hessian.hpp SphericalHessian.java ∂α/∂u from spherical law of cosines
cut_graph.hpp CuttingUtility.java Erickson & Whittlesey (SODA 2005) — tree-cotree
period_matrix.hpp PeriodMatrixUtility.java Sechelmann (2016) §4 — SL(2,ℤ) reduction
gauss_bonnet.hpp (distributed across Java) Gauss–Bonnet: Σ(2π−Θᵥ) = 2π·χ(M)
+

+Java features not yet ported (Phase 9)

+

The Java library under de.varylab.discreteconformal contains these items not yet in C++:

+ + + + + + + + + + + + + + + +
Java class Planned C++ header Phase
InversiveDistanceFunctional inversive_distance_functional.hpp 9a
Analytic HyperIdeal Hessian hyper_ideal_hessian.hpp (replace FD) 9b
4g-polygon boundary walk in FundamentalDomainUtility fundamental_domain.hpp (extend) 9c
DiscreteHarmonicFormUtility Phase 10a prerequisite 10
DiscreteHolomorphicFormUtility Phase 10a 10
HomologyUtility, CanonicalBasisUtility Phase 10 10
+

When porting a Java class, locate the original in de.varylab.discreteconformal.* at github.com/varylab/conformallab and use it as the reference implementation.

+

+Test design patterns

+

+"Natural theta" — constructing a known equilibrium at x* = 0

+
// Evaluate gradient at x=0; set target angles = actual angle sums → x*=0 by definition
+
std::vector<double> x0(n_dofs, 0.0);
+
auto G0 = euclidean_gradient(mesh, x0, maps);
+
for (auto v : mesh.vertices())
+
if (maps.v_idx[v] >= 0)
+
maps.theta_v[v] -= G0[maps.v_idx[v]]; // shift so G(x=0) = 0
+

This is used in virtually every Newton convergence test — it avoids hardcoding specific angle values.

+

+Gradient check pattern

+
// Copy from any test_*_functional.cpp — GradientCheck_* test suite
+
double eps = 1e-5;
+
for (int i = 0; i < n; ++i) {
+
xp[i] += eps; auto Gp = euclidean_gradient(mesh, xp, maps);
+
xm[i] -= eps; auto Gm = euclidean_gradient(mesh, xm, maps);
+
double fd = (energy(xp) - energy(xm)) / (2*eps);
+
EXPECT_NEAR(G[i], fd, 1e-7);
+
xp[i] = xm[i] = x0[i];
+
}
+

All new functionals must have a gradient-check test before being considered complete.

+

+Halfedge traversal

+
for (auto f : mesh.faces()) {
+
auto h0 = mesh.halfedge(f); // canonical halfedge of face
+
auto h1 = mesh.next(h0);
+
auto h2 = mesh.next(h1);
+
+
Vertex_index v1 = mesh.source(h0); // = mesh.target(h2)
+
Vertex_index v2 = mesh.source(h1);
+
Vertex_index v3 = mesh.source(h2);
+
+
// Angle at v3 is opposite to h0 (edge v1–v2)
+
// h_alpha[h0] = α₃, h_alpha[h1] = α₁, h_alpha[h2] = α₂
+
+
bool is_boundary = mesh.is_border(mesh.opposite(h0));
+
}
+

+Attaching custom data to the mesh

+
auto [my_map, created] = mesh.add_property_map<Vertex_index, double>("v:my_data", 0.0);
+
my_map[v] = 3.14;
+

+CI pipeline

+

Two jobs in .gitea/workflows/cpp-tests.yml:

+ + + + + + + +
Job CMake flags Deps Triggers on
test-fast (none) Eigen + GTest only all branches
test-cgal -DWITH_CGAL_TESTS=ON + Boost pull requests only
+

Runner: eulernest — self-hosted Raspberry Pi, ARM64, Ubuntu 22.04. Docker image: git.eulernest.eu/conformallab/ci-cpp:latest. test-cgal needs test-fast to pass first (needs: test-fast).

+

Expected results: full test suite passing, 0 skipped, 0 failed. The canonical counts live in doc/api/tests.md — do not hardcode them anywhere else (see doc/release-policy.md).

+

+Release state

+

Current release: v0.9.0 (tag on main, released 2026-05-22). Phases 1–9a complete, Phase 8b-Lite CGAL API surface complete (all 5 DCE models reachable via <CGAL/Discrete_*.h>), Phase 9b block-FD HyperIdeal Hessian shipped (~96× speed-up). Next planned milestones: Phase 9c (4g-polygon, genus g > 1) and Phase 9b-analytic (Schläfli identity). See doc/release-policy.md for the version-tag policy and doc/roadmap/phases.md for the phase plan.

+

+Phase 8 strategic decisions (2026-05-19)

+

The CGAL-package architecture was frozen on 2026-05-19. Full design: doc/api/cgal-package.md. Key decisions:

+ + + + + + + + + + + + + + + + + + + +
Decision Choice
Submission to upstream CGAL Pre-submission-ready, not bound. 12+ months horizon.
License MIT preserved (no LGPL switch).
Mesh-type flexibility Generic FaceGraph + HalfedgeGraph in target design; MVP starts Surface_mesh-only.
Parameter style Named Parameters (CGAL::parameters::...).
Default kernel Simple_cartesian<double> (status quo).
Backward compatibility Dual-layer wrappercode/include/*.hpp stays as implementation, include/CGAL/*.h is thin wrapper. No algorithm duplication.
Implementation strategy Hybrid MVP — minimum Phase 8 (traits + one wrapper) first, then Phase 9 in full, then Phase 8 extensions only on concrete demand.
Phase-8 MVP acceptance test Phase 9a (Inversive-Distance) as the first new client of the new traits API.
+

+Implementation sequence (committed)

+
1. Phase 7.5 Doxygen + cleanup done ✅
+
2. Phase 8 MVP — traits + one euclidean wrapper 3–5 days
+
3. Phase 9a — Inversive-Distance against new traits 3–5 days
+
4. Phase 9b — analytic HyperIdeal Hessian 1 week
+
5. Phase 9c — 4g-polygon for genus g > 1 1 week
+
→ port really complete, v0.9.0 release
+

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.

+

Root-level files added at v0.7.0:

    +
  • CITATION.cff — machine-readable citation (Sechelmann 2016, Springborn 2020, Bobenko–Springborn 2004)
  • +
  • CONTRIBUTING.md — short root-level pointer to doc/contributing.md
  • +
  • scripts/try_it.sh — one-script quickstart: build → 209 tests → example run
  • +
  • CMake install target: cmake --install build --prefix /usr/local → headers land in include/conformallab/
  • +
+

+Port-vs-research maintenance rule (2026-05-21 audit)

+

Before claiming something "ports X from Java", verify empirically:

+
find /Users/tarikmoussa/Desktop/conformallab -iname "*X*"
+
grep -r "ClassName" /Users/tarikmoussa/Desktop/conformallab/src
+

If zero matches, the work is new research — add it to doc/roadmap/research-track.md with primary literature citations, not to doc/roadmap/java-parity.md.

+

The 2026-05-21 audit found four pre-existing mis-labels:

+ + + + + + + + + + + +
Item Wrong claim Reality
InversiveDistanceFunctional "Java port (Luo 2004)" No such Java class exists
HyperIdeal Hessian (FD) "Phase 4a" Research — Java has hasHessian()==false
HyperIdeal Hessian (analytic) "Phase 9b port" Research — derivation via Schläfli 1858
Tutorial framing "ports `InversiveDistanceFunctional.java`" Implementation from Luo 2004 + Glickenstein 2011
+

All four are corrected as of this commit. Future contributors must follow the empirical verification rule above before any new claim.

+

+Documentation map

+

24 documents across 6 categories. Read the relevant one before reasoning from scratch — do not hallucinate content that is already written down.

+

+Mathematics & theory

+ + + + + + + + + + + + + + + + + + + +
Question Document
What problem does this library solve mathematically? doc/math/discrete-conformal-theory.md
How do the three geometry modes differ (Euclidean/Spherical/HyperIdeal)? doc/math/geometry-modes.md
What analytic invariants can be used to validate correctness? doc/math/validation.md
What are the exact ctest commands with expected terminal output? doc/math/validation-protocol.md
What is the O() complexity and how does it scale with mesh size? doc/math/complexity.md
Which papers are referenced by which header? doc/math/references.md
How does conformallab++ compare to libigl, CGAL, geometry-central, pmp-library? doc/math/software-landscape.md
What is unique about conformallab++ (novelty, target audience)? doc/math/novelty-statement.md
+

+Architecture & design

+ + + + + + + + + + + + + +
Question Document
Full pipeline diagram and data-flow overview doc/architecture/overall_pipeline.md
Directory tree, build targets, file organisation doc/architecture/project-structure.md
Key architectural decisions and their rationale doc/architecture/design-decisions.md
Detailed comparison with geometry-central (CMU): overlap, adoption, scientific value doc/architecture/geometry-central-comparison.md
Phase 9a validation report (CP-Euclidean port + Luo-inversive-distance literature check) doc/architecture/phase-9a-validation.md
+

+API & extension

+ + + + + + + + + + + + + + + +
Question Document
All 24 public headers with descriptions doc/api/headers.md
Full pipeline API for all three geometries doc/api/pipeline.md
What does each processing unit require/provide (contracts)? doc/api/contracts.md
How to add a new functional / geometry mode / port from Java doc/api/extending.md
Per-suite breakdown and counts (single source of truth) doc/api/tests.md
Phase 8 CGAL package design + Declarative YAML pipeline spec doc/api/cgal-package.md
+

+Concepts & specs

+ + + + + +
Question Document
Declarative YAML pipeline: token vocabulary, 5 examples, validation algorithm doc/concepts/declarative-pipeline.md
+

+Roadmap & porting

+ + + + + + + + + +
Question Document
Phases 1–10 with status and sub-tasks doc/roadmap/phases.md
Which Java classes are ported, which are planned, which are skipped? doc/roadmap/java-parity.md
New research items (beyond Java) — citations, acceptance criteria doc/roadmap/research-track.md
+

+Tutorials & onboarding

+ + + + + + + + + + + +
Question Document
Build modes, single-test invocation, CLI, Docker image rebuild doc/getting-started.md
Step-by-step: port the Inversive Distance functional (Phase 9a template) doc/tutorials/add-inversive-distance.md
Language policy, test standards, release flow doc/contributing.md
Versioning rules + release process + single-source-of-truth list doc/release-policy.md
+

+geometry-central context

+

geometry-central (Keenan Crane, CMU) implements the same discrete conformal equivalence problem (Gillespie, Springborn & 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: doc/architecture/geometry-central-comparison.md. Optional adoption roadmap (GC-1/2/3): doc/roadmap/phases.md (Optional section).

+

+Known quirks

+
    +
  • No GTEST_SKIP stubs remain (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 conformallab_tests target now only contains active tests.
  • +
  • Boost is header-only: CGAL 6.x uses only Boost headers (Boost.Config, Boost.Graph). No compiled Boost libraries are needed. find_package(Boost REQUIRED) only locates the include path.
  • +
  • main branch is protected on origin (Gitea). Push to dev, then merge via pull request. Codeberg main can be pushed to directly.
  • +
  • Both remotes must stay in sync: origin = git.eulernest.eu (CI runs here), codeberg = codeberg.org/TMoussa/ConformalLabpp (public mirror). Push to both after every significant change.
  • +
+
+
+
+ +
+ + + + diff --git a/menu.js b/menu.js new file mode 100644 index 0000000..8172efe --- /dev/null +++ b/menu.js @@ -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+=''; + } + } + 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 = '';//''; + 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 = ''; + 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 */ diff --git a/menudata.js b/menudata.js new file mode 100644 index 0000000..752f4f4 --- /dev/null +++ b/menudata.js @@ -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"}]} diff --git a/navtree.css b/navtree.css new file mode 100644 index 0000000..972d1b4 --- /dev/null +++ b/navtree.css @@ -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; +} diff --git a/navtree.js b/navtree.js new file mode 100644 index 0000000..ccee918 --- /dev/null +++ b/navtree.js @@ -0,0 +1,1161 @@ +/* + @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 + */ + +let initResizableFunc; + +function initNavTree(toroot,relpath,allMembersFile) { + let navTreeSubIndices = []; + const ARROW_DOWN = ''; + const ARROW_RIGHT = ''; + const NAVPATH_COOKIE_NAME = ''+'navpath'; + const fullSidebar = typeof page_layout!=='undefined' && page_layout==1; + + // Helper functions to replace jQuery + const $ = (selector) => document.querySelector(selector); + const $$ = (selector) => Array.from(document.querySelectorAll(selector)); + const hasClass = (el, className) => el ? el.classList.contains(className) : false; + const offsetTop = (el) => el ? (el.getBoundingClientRect().top + window.pageYOffset) : 0; + + const slideUp = function(el, duration, callback) { + if (!el) return; + el.style.overflow = 'hidden'; + el.style.transition = `height ${duration}ms ease`; + el.style.height = el.scrollHeight + 'px'; + setTimeout(() => { + el.style.height = '0'; + setTimeout(() => { + el.style.display = 'none'; + el.style.transition = ''; + el.style.overflow = ''; + el.style.height = ''; + if (callback) callback(); + }, duration); + }, 10); + }; + + const slideDown = function(el, duration, callback) { + if (!el) return; + el.style.display = 'block'; + const height = el.scrollHeight; + el.style.overflow = 'hidden'; + el.style.height = '0'; + el.style.transition = `height ${duration}ms ease`; + setTimeout(() => { + el.style.height = height + 'px'; + setTimeout(() => { + el.style.transition = ''; + el.style.overflow = ''; + el.style.height = ''; + if (callback) callback(); + }, duration); + }, 10); + }; + + const animateScrolling = function(el, targetPos, duration, callback) { + if (!el) return; + const start = performance.now(); + const startVal = el.scrollTop; + const tick = (now) => { + const elapsed = now - start; + const progress = Math.min(elapsed / duration, 1); + const endVal = targetPos; + el.scrollTop = startVal + (endVal - startVal) * progress; + + if (progress < 1) { + requestAnimationFrame(tick); + } else if (callback) { + callback(); + } + }; + requestAnimationFrame(tick); + }; + + function getScrollBarWidth () { + const outer = document.createElement('div'); + outer.style.visibility='hidden'; + outer.style.width='100px'; + outer.style.overflow='scroll'; + outer.style.scrollbarWidth='thin'; + document.body.appendChild(outer); + + const inner = document.createElement('div'); + inner.style.width='100%'; + outer.appendChild(inner); + + const widthWithScroll = inner.offsetWidth; + document.body.removeChild(outer); + return 100 - widthWithScroll; + } + const scrollbarWidth = getScrollBarWidth(); + + function adjustSyncIconPosition() { + if (!fullSidebar) { + const nt = document.getElementById("nav-tree"); + const hasVerticalScrollbar = nt.scrollHeight > nt.clientHeight; + const navSync = $("#nav-sync"); + navSync.style.right = (hasVerticalScrollbar ? scrollbarWidth : 0) + 'px'; + } + } + + const getData = function(varName) { + const i = varName.lastIndexOf('/'); + const n = i>=0 ? varName.substring(i+1) : varName; + const e = n.replace(/-/g,'_'); + return window[e]; + } + + const stripPath = (uri) => uri.substring(uri.lastIndexOf('/')+1); + + const stripPath2 = function(uri) { + const i = uri.lastIndexOf('/'); + const s = uri.substring(i+1); + const m = uri.substring(0,i+1).match(/\/d\w\/d\w\w\/$/); + return m ? uri.substring(i-6) : s; + } + + const hashValue = () => location.hash.substring(1).replace(/[^\w-]/g,''); + const hashUrl = () => '#'+hashValue(); + const pathName = () => location.pathname.replace(/[^-A-Za-z0-9+&@#/%?=~_|!:,.;()]/g, ''); + + const storeLink = function(link) { + const navSync = $("#nav-sync"); + if (!hasClass(navSync, 'sync')) { + Cookie.writeSetting(NAVPATH_COOKIE_NAME,link,0); + } + } + + const deleteLink = function() { + Cookie.eraseSetting(NAVPATH_COOKIE_NAME); + } + + const cachedLink = () => Cookie.readSetting(NAVPATH_COOKIE_NAME,''); + + const getScript = function(scriptName,func) { + const head = document.getElementsByTagName("head")[0]; + const script = document.createElement('script'); + script.id = scriptName; + script.type = 'text/javascript'; + script.onload = function() { func(); adjustSyncIconPosition(); } + script.src = scriptName+'.js'; + head.appendChild(script); + } + + const createIndent = function(o,domNode,node) { + let level=-1; + let n = node; + while (n.parentNode) { level++; n=n.parentNode; } + if (node.childrenData) { + const imgNode = document.createElement("span"); + imgNode.className = 'arrow'; + imgNode.style.paddingLeft=(16*level).toString()+'px'; + imgNode.innerHTML=ARROW_RIGHT; + node.plus_img = imgNode; + node.expandToggle = document.createElement("a"); + node.expandToggle.href = "javascript:void(0)"; + node.expandToggle.onclick = function() { + if (node.expanded) { + slideUp(node.getChildrenUL(), 200, adjustSyncIconPosition); + const child0 = node.plus_img.childNodes[0] + if (child0) { + child0.classList.remove('opened'); + child0.classList.add('closed'); + } + node.expanded = false; + } else { + expandNode(o, node, false, true); + } + } + node.expandToggle.appendChild(imgNode); + domNode.appendChild(node.expandToggle); + } else { + let span = document.createElement("span"); + span.className = 'arrow'; + span.style.width = 16*(level+1)+'px'; + span.innerHTML = ' '; + domNode.appendChild(span); + } + } + + let animationInProgress = false; + + const gotoAnchor = function(anchor,aname) { + if (!anchor) return; + let pos, docContent = $('#doc-content'); + if (!docContent) return; + + const anchorParent = anchor.parentElement; + if (!anchorParent) return; + + const parentClass = anchorParent.className; + if (hasClass(anchorParent, 'memItemLeft') || hasClass(anchorParent, 'memtitle') || + hasClass(anchorParent, 'fieldname') || hasClass(anchorParent, 'fieldtype') || + anchorParent.tagName.match(/^H[1-6]$/)) { + pos = offsetTop(anchorParent); // goto anchor's parent + } else { + pos = offsetTop(anchor); // goto anchor + } + if (pos) { + const dcOffset = offsetTop(docContent); + const dcHeight = docContent.clientHeight; + const dcScrHeight = docContent.scrollHeight; + const dcScrTop = docContent.scrollTop; + let dist = Math.abs(Math.min(pos-dcOffset,dcScrHeight-dcHeight-dcScrTop)); + animationInProgress = true; + animateScrolling(docContent, pos+dcScrTop-dcOffset, Math.max(50,Math.min(500,dist)), function() { + animationInProgress=false; + if (parentClass=='memItemLeft') { + const rows = $$('.memberdecls tr[class$="'+hashValue()+'"]'); + rows.forEach(row => { + const children = Array.from(row.children); + children.forEach(child => glowEffect(child, 300)); + }); + } else if (parentClass=='fieldname') { + glowEffect(anchorParent.parentElement, 1000); // enum value + } else if (parentClass=='fieldtype') { + glowEffect(anchorParent.parentElement, 1000); // struct field + } else if (anchorParent.tagName.match(/^H[1-6]$/)) { + glowEffect(anchorParent, 1000); // section header + } else { + glowEffect(anchor.nextElementSibling, 1000); // normal member + } + }); + } + } + + function htmlToNode(html) { + const template = document.createElement('template'); + template.innerHTML = html; + const nNodes = template.content.childNodes.length; + if (nNodes !== 1) { + throw new Error(`html parameter must represent a single node; got ${nNodes}. `); + } + return template.content.firstChild; + } + + const newNode = function(o, po, text, link, childrenData, lastNode) { + const node = { + children : [], + childrenData : childrenData, + depth : po.depth + 1, + relpath : po.relpath, + isLast : lastNode, + li : document.createElement("li"), + parentNode : po, + itemDiv : document.createElement("div"), + labelSpan : document.createElement("span"), + expanded : false, + childrenUL : null, + getChildrenUL : function() { + if (!this.childrenUL) { + this.childrenUL = document.createElement("ul"); + this.childrenUL.className = "children_ul"; + this.childrenUL.style.display = "none"; + this.li.appendChild(node.childrenUL); + } + return node.childrenUL; + }, + }; + + node.itemDiv.className = "item"; + node.labelSpan.className = "label"; + createIndent(o,node.itemDiv,node); + node.itemDiv.appendChild(node.labelSpan); + node.li.appendChild(node.itemDiv); + + const a = document.createElement("a"); + node.labelSpan.appendChild(a); + po.getChildrenUL().appendChild(node.li); + a.appendChild(htmlToNode(''+text+'')); + if (link) { + let url; + if (link.substring(0,1)=='^') { + url = link.substring(1); + link = url; + } else { + url = node.relpath+link; + } + a.className = stripPath(link.replace('#',':')); + if (link.indexOf('#')!=-1) { + const aname = '#'+link.split('#')[1]; + const srcPage = stripPath(pathName()); + const targetPage = stripPath(link.split('#')[0]); + a.href = srcPage!=targetPage ? url : aname; + a.onclick = function() { + storeLink(link); + const aPPar = a.parentElement.parentElement; + if (!hasClass(aPPar, 'selected')) { + $$('.item').forEach(item => { + item.classList.remove('selected'); + item.removeAttribute('id'); + }); + aPPar.classList.add('selected'); + aPPar.setAttribute('id', 'selected'); + } + const anchor = document.querySelector(aname); + gotoAnchor(anchor,aname); + }; + } else { + a.href = url; + a.onclick = () => storeLink(link); + } + } else if (childrenData != null) { + a.className = "nolink"; + a.href = "javascript:void(0)"; + a.onclick = node.expandToggle.onclick; + } + return node; + } + + const showRoot = function() { + const top = $("#top"); + const navPath = $("#nav-path"); + const headerHeight = top ? top.clientHeight : 0; + const footerHeight = navPath ? navPath.clientHeight : 0; + const windowHeight = window.innerHeight - headerHeight - footerHeight; + (function retry() { // retry until we can scroll to the selected item + try { + const navtree = $('#nav-tree'); + if (navtree) { + const selected = navtree.querySelector('#selected'); + if (selected) { + const offset = -windowHeight/2; + const targetPos = selected.offsetTop + offset; + animateScrolling(navtree, Math.max(0, targetPos), 100); + } + } + } catch (err) { + setTimeout(retry, 0); + } + })(); + } + + const expandNode = function(o, node, imm, setFocus) { + if (node.childrenData && !node.expanded) { + if (typeof(node.childrenData)==='string') { + const varName = node.childrenData; + getScript(node.relpath+varName,function() { + node.childrenData = getData(varName); + expandNode(o, node, imm, setFocus); + }); + } else { + if (!node.childrenVisited) { + getNode(o, node); + } + slideDown(node.getChildrenUL(), 200, adjustSyncIconPosition); + const child0 = node.plus_img.childNodes[0] + if (child0) { + child0.classList.add('opened'); + child0.classList.remove('closed'); + } + node.expanded = true; + if (setFocus) { + node.expandToggle.focus(); + } + } + } + } + + const glowEffect = function(n, duration) { + if (!n) return; + n.classList.add('glow'); + setTimeout(() => { + n.classList.remove('glow'); + }, duration); + } + + const highlightAnchor = function() { + const aname = hashUrl(); + const anchor = document.querySelector(aname); + gotoAnchor(anchor,aname); + } + + const selectAndHighlight = function(hash,n) { + let a; + if (hash) { + const link=stripPath(pathName())+':'+hash.substring(1); + a=document.querySelector('.item a[class$="'+link+'"]'); + } + if (a) { + const parent = a.parentElement.parentElement; + if (parent) { + parent.classList.add('selected'); + parent.setAttribute('id', 'selected'); + } + highlightAnchor(); + } else if (n && n.itemDiv) { + n.itemDiv.classList.add('selected'); + n.itemDiv.setAttribute('id', 'selected'); + } + let topOffset=5; + const firstItem = document.querySelector('#nav-tree-contents .item:first-child'); + if (firstItem && hasClass(firstItem, 'selected')) { + topOffset+=25; + } + showRoot(); + } + + const showNode = function(o, node, index, hash) { + if (node && node.childrenData) { + if (typeof(node.childrenData)==='string') { + const varName = node.childrenData; + getScript(node.relpath+varName,function() { + node.childrenData = getData(varName); + showNode(o,node,index,hash); + }); + } else { + if (!node.childrenVisited) { + getNode(o, node); + } + const childUL = node.getChildrenUL(); + if (childUL) { + childUL.style.display='block'; + } + const child0 = node.plus_img.childNodes[0]; + if (child0) { + child0.classList.remove('closed'); + child0.classList.add('opened'); + } + node.expanded = true; + const n = node.children[o.breadcrumbs[index]]; + if (index+10) { // try root page without hash as fallback + gotoUrl(o,root,'',relpath); + } else { + o.breadcrumbs = nti ? JSON.parse(JSON.stringify(nti)) : null; + if (!o.breadcrumbs && root!=NAVTREE[0][1]) { // fallback: show index + navTo(o,NAVTREE[0][1],"",relpath); + $$('.item').forEach(item => { + item.classList.remove('selected'); + item.removeAttribute('id'); + }); + } + if (o.breadcrumbs) { + o.breadcrumbs.unshift(0); // add 0 for root node + showNode(o, o.node, 0, hash); + } + } + } + + const gotoUrl = function(o,root,hash,relpath) { + const url=root+hash; + let i=-1; + while (NAVTREEINDEX[i+1]<=url) i++; + if (i==-1) { i=0; root=NAVTREE[0][1]; } // fallback: show index + if (navTreeSubIndices[i]) { + gotoNode(o,i,root,hash,relpath) + } else { + getScript(relpath+'navtreeindex'+i,function() { + navTreeSubIndices[i] = window['NAVTREEINDEX'+i]; + if (navTreeSubIndices[i]) { + gotoNode(o,i,root,hash,relpath); + } + }); + } + } + + const navTo = function(o,root,hash,relpath) { + const link = cachedLink(); + if (link) { + const parts = link.split('#'); + root = parts[0]; + hash = parts.length>1 ? '#'+parts[1].replace(/[^\w-]/g,'') : ''; + } + if (hash.match(/^#l\d+$/)) { + const anchor = document.querySelector('a[name='+hash.substring(1)+']'); + if (anchor && anchor.parentElement) { + glowEffect(anchor.parentElement, 1000); // line number + } + hash=''; // strip line number anchors + } + gotoUrl(o,root,hash,relpath); + } + + const showSyncOff = function(n,relpath) { + if (n) n.innerHTML = ''; + } + + const showSyncOn = function(n,relpath) { + if (n) n.innerHTML = ''; + } + + const o = { + toroot : toroot, + node : { + childrenData : NAVTREE, + children : [], + childrenUL : document.createElement("ul"), + getChildrenUL : function() { return this.childrenUL }, + li : document.getElementById("nav-tree-contents"), + depth : 0, + relpath : relpath, + expanded : false, + isLast : true, + plus_img : document.createElement("span"), + }, + }; + o.node.li.appendChild(o.node.childrenUL); + o.node.plus_img.className = 'arrow'; + o.node.plus_img.innerHTML = ARROW_RIGHT; + + const navSync = $('#nav-sync'); + if (cachedLink()) { + showSyncOff(navSync,relpath); + navSync.classList.remove('sync'); + } else { + showSyncOn(navSync,relpath); + } + + if (navSync) { + navSync.addEventListener('click', () => { + const navSync = $('#nav-sync'); + if (hasClass(navSync, 'sync')) { + navSync.classList.remove('sync'); + showSyncOff(navSync,relpath); + storeLink(stripPath2(pathName())+hashUrl()); + } else { + navSync.classList.add('sync'); + showSyncOn(navSync,relpath); + deleteLink(); + } + }); + } + + navTo(o,toroot,hashUrl(),relpath); + showRoot(); + + window.addEventListener('hashchange', () => { + if (!animationInProgress) { + if (window.location.hash && window.location.hash.length>1) { + let a; + if (location.hash) { + const clslink=stripPath(pathName())+':'+hashValue(); + a=document.querySelector('.item a[class$="'+clslink.replace(/ { + item.classList.remove('selected'); + item.removeAttribute('id'); + }); + } + const link=stripPath2(pathName()); + navTo(o,link,hashUrl(),relpath); + } else { + const docContent = $('#doc-content'); + if (docContent) docContent.scrollTop = 0; + $$('.item').forEach(item => { + item.classList.remove('selected'); + item.removeAttribute('id'); + }); + navTo(o,toroot,hashUrl(),relpath); + } + } + }); + + window.addEventListener('resize', function() { adjustSyncIconPosition(); }); + + let navtree_trampoline = { + updateContentTop : function() {} + } + + function initResizable() { + let sidenav,mainnav,pagenav,container,navtree,content,header,footer,barWidth=6; + const RESIZE_COOKIE_NAME = ''+'width'; + const PAGENAV_COOKIE_NAME = ''+'pagenav'; + const fullSidebar = typeof page_layout!=='undefined' && page_layout==1; + + function showHideNavBar() { + const bar = document.querySelector('div.sm-dox'); + if (fullSidebar && mainnav && bar) { + if (mainnav.clientWidth < 768) { + bar.style.display = 'none'; + } else { + bar.style.display = ''; + } + } + } + + function constrainPanelWidths(leftPanelWidth,rightPanelWidth,dragLeft) { + const contentWidth = container.clientWidth - leftPanelWidth - rightPanelWidth; + const minContentWidth = 280; + const minPanelWidth = barWidth; + if (contentWidth try to keep right panel width + const shrinkLeft = Math.min(deficit, leftPanelWidth-minPanelWidth); + leftPanelWidth -= shrinkLeft; + const remainingDeficit = deficit - shrinkLeft; + const shrinkRight = Math.min(remainingDeficit, rightPanelWidth-minPanelWidth); + rightPanelWidth -= shrinkRight; + } else { // dragging right handle -> try to keep left panel width + const shrinkRight = Math.min(deficit, rightPanelWidth-minPanelWidth); + rightPanelWidth -= shrinkRight; + const remainingDeficit = deficit - shrinkRight; + const shrinkLeft = Math.min(remainingDeficit, leftPanelWidth-minPanelWidth); + leftPanelWidth -= shrinkLeft; + } + } else { + rightPanelWidth = pagenav ? Math.max(minPanelWidth,rightPanelWidth) : 0; + leftPanelWidth = Math.max(minPanelWidth,leftPanelWidth); + } + return { leftPanelWidth, rightPanelWidth } + } + + function updateWidths(sidenavWidth,pagenavWidth,dragLeft) + { + const widths = constrainPanelWidths(sidenavWidth,pagenavWidth,dragLeft); + const widthStr = parseFloat(widths.leftPanelWidth)+"px"; + content.style.marginLeft = widthStr; + if (fullSidebar) { + footer.style.marginLeft = widthStr; + if (mainnav) { + mainnav.style.marginLeft = widthStr; + } + } + sidenav.style.width = widthStr; + if (pagenav) { + container.style.gridTemplateColumns = 'auto '+parseFloat(widths.rightPanelWidth)+'px'; + if (!dragLeft) { + pagenav.style.width = parseFloat(widths.rightPanelWidth-1)+'px'; + } + } + return widths; + } + + function resizeWidth(dragLeft) { + const sidenavWidth = sidenav.offsetWidth - barWidth; + let pagenavWidth = pagenav ? pagenav.offsetWidth : 0; + const widths = updateWidths(sidenavWidth,pagenavWidth,dragLeft); + Cookie.writeSetting(RESIZE_COOKIE_NAME,widths.leftPanelWidth-barWidth); + if (pagenav) { + Cookie.writeSetting(PAGENAV_COOKIE_NAME,widths.rightPanelWidth); + } + } + + function restoreWidth(sidenavWidth,pagenavWidth) { + updateWidths(sidenavWidth,pagenavWidth,false); + showHideNavBar(); + } + + function resizeHeight() { + const headerHeight = header.offsetHeight; + const windowHeight = window.innerHeight; + let contentHeight; + const footerHeight = footer.offsetHeight; + let navtreeHeight,sideNavHeight; + if (!fullSidebar) { + contentHeight = windowHeight - headerHeight - footerHeight - 1; + navtreeHeight = contentHeight; + sideNavHeight = contentHeight; + } else if (fullSidebar) { + contentHeight = windowHeight - footerHeight - 1; + navtreeHeight = windowHeight - headerHeight - 1; + sideNavHeight = windowHeight - 1; + if (mainnav) { + contentHeight -= mainnav.offsetHeight; + } + } + navtree.style.height = navtreeHeight + "px"; + sidenav.style.height = sideNavHeight + "px"; + content.style.height = contentHeight + "px"; + resizeWidth(false); + showHideNavBar(); + if (location.hash.slice(1)) { + (document.getElementById(location.hash.slice(1))||document.body).scrollIntoView(); + } + } + + header = $("#top"); + content = $("#doc-content"); + footer = $("#nav-path"); + sidenav = $("#side-nav"); + if (document.getElementById('main-nav')) { + mainnav = $("#main-nav"); + } + navtree = $("#nav-tree"); + pagenav = $("#page-nav"); + container = $("#container"); + + // Native JavaScript implementation for resizable side navigation + const splitbar = $("#splitbar"); + if (splitbar) { + // Add the ui-resizable-e class to make the splitbar visible and styled correctly + splitbar.classList.add('ui-resizable-e'); + splitbar.style.zIndex = 90; + + let isResizing = false; + let startX = 0; + let startWidth = 0; + + const startResize = (e) => { + startX = e.clientX ?? e.touches?.[0]?.clientX; + startWidth = sidenav.offsetWidth - barWidth; + document.body.classList.add('resizing'); + document.body.style.cursor = 'col-resize'; + + const doResize = (e) => { + const clientX = e.clientX ?? e.touches?.[0]?.clientX; + if (clientX === undefined) return; + const delta = clientX - startX; + const newWidth = startWidth + delta; + sidenav.style.width = newWidth + 'px'; + resizeWidth(true); + }; + + const stopResize = () => { + document.body.classList.remove('resizing'); + document.body.style.cursor = 'auto'; + document.removeEventListener('mousemove', doResize); + document.removeEventListener('touchmove', doResize); + document.removeEventListener('mouseup', stopResize); + document.removeEventListener('touchend', stopResize); + }; + + document.addEventListener('mousemove', doResize); + document.addEventListener('touchmove', doResize); + document.addEventListener('mouseup', stopResize); + document.addEventListener('touchend', stopResize); + }; + + splitbar.addEventListener('mousedown', startResize); + splitbar.addEventListener('touchstart', startResize, { passive: false }); + } + + if (pagenav) { + const pagehandle = $("#page-nav-resize-handle"); + if (pagehandle) { + const startDrag = (e) => { + document.body.classList.add('resizing'); + pagehandle.classList.add('dragging'); + + const mouseMoveHandler = (e) => { + const clientX = e.clientX ?? e.touches?.[0]?.clientX; + if (clientX === undefined) return; + let pagenavWidth = container.offsetWidth - clientX + barWidth/2; + const sidenavWidth = sidenav.clientWidth; + const widths = constrainPanelWidths(sidenavWidth,pagenavWidth,false); + container.style.gridTemplateColumns = 'auto '+parseFloat(widths.rightPanelWidth)+'px'; + pagenav.style.width = parseFloat(widths.rightPanelWidth-1)+'px'; + content.style.marginLeft = parseFloat(widths.leftPanelWidth - barWidth)+'px'; + Cookie.writeSetting(PAGENAV_COOKIE_NAME,pagenavWidth); + }; + + const mouseUpHandler = (e) => { + document.body.classList.remove('resizing'); + pagehandle.classList.remove('dragging'); + document.removeEventListener('mousemove', mouseMoveHandler); + document.removeEventListener('mouseup', mouseUpHandler); + document.removeEventListener('touchmove', mouseMoveHandler); + document.removeEventListener('touchend', mouseUpHandler); + }; + + document.addEventListener('mousemove', mouseMoveHandler); + document.addEventListener('touchmove', mouseMoveHandler); + document.addEventListener('mouseup', mouseUpHandler); + document.addEventListener('touchend', mouseUpHandler); + }; + + pagehandle.addEventListener('mousedown', startDrag); + pagehandle.addEventListener('touchstart', startDrag, { passive: false }); + } + } else { + container.style.gridTemplateColumns = 'auto'; + } + const width = parseInt(Cookie.readSetting(RESIZE_COOKIE_NAME,280)); + const pagenavWidth = parseInt(Cookie.readSetting(PAGENAV_COOKIE_NAME,280)); + if (width) { restoreWidth(width+barWidth,pagenavWidth); } else { resizeWidth(); } + const url = location.href; + const i=url.indexOf("#"); + if (i>=0) window.location.hash=url.substr(i); + + + let lastWidth = -1; + let lastHeight = -1; + window.addEventListener('resize', function() { + const newWidth = window.innerWidth; + const newHeight = window.innerHeight; + if (newWidth!=lastWidth || newHeight!=lastHeight) { + resizeHeight(); + navtree_trampoline.updateContentTop(); + lastWidth = newWidth; + lastHeight = newHeight; + } + }); + resizeHeight(); + lastWidth = window.innerWidth; + lastHeight = window.innerHeight; + if (content) { + content.addEventListener('scroll', function() { + navtree_trampoline.updateContentTop(); + }); + } + } + + function initPageToc() { + const topMapping = []; + const toc_contents = $('#page-nav-contents'); + const content = document.createElement('ul'); + content.className = 'page-outline'; + + var entityMap = { + '&': '&', + '<': '<', + '>': '>', + '"': '"', + "'": ''', + '/': '/', + '`': '`', + '=': '=' + }; + function escapeHtml (string) { + return String(string).replace(/[&<>"'`=\/]/g, function (s) { + return entityMap[s]; + }); + } + + // for ClassDef/GroupDef/ModuleDef/ConceptDef/DirDef + const groupSections = []; + let currentGroup = null; + $$('h2.groupheader, h2.memtitle').forEach(function(element){ + if (hasClass(element, 'groupheader')) { + currentGroup = { groupHeader: element, memTitles: [] }; + groupSections.push(currentGroup); + } else if (hasClass(element, 'memtitle') && currentGroup) { + currentGroup.memTitles.push(element); + } + }); + groupSections.forEach(function(item){ + const title = item.groupHeader.textContent.trim(); + let id = item.groupHeader.getAttribute('id'); + let table = item.groupHeader.closest('table.memberdecls'); + let rows = []; + if (table) { + rows = Array.from(table.querySelectorAll("tr[class^='memitem:'] td.memItemRight, tr[class^='memitem:'] td.memItemLeft.anon, tr[class=groupHeader] td")); + } + function hasSubItems() { + return item.memTitles.length>0 || rows.some(function(el) { + return el.offsetParent !== null; // check if visible + }); + } + const li = document.createElement('li'); + li.setAttribute('id', 'nav-'+id); + const div = document.createElement('div'); + div.classList.add('item'); + const span = document.createElement('span'); + span.classList.add('arrow'); + span.style.paddingLeft='0px'; + if (hasSubItems()) { + const arrowSpan = document.createElement('span'); + arrowSpan.classList.add('arrowhead', 'opened'); + span.appendChild(arrowSpan); + } + const ahref = document.createElement('a'); + ahref.setAttribute('href', '#'+id); + ahref.textContent = title; + div.appendChild(span); + div.appendChild(ahref); + li.appendChild(div); + content.appendChild(li); + topMapping.push(id); + const ulStack = []; + ulStack.push(content); + if (hasSubItems()) { + let last_id = undefined; + let inMemberGroup = false; + // declaration sections have rows for items + rows.forEach(function(td) { + let tr = td.parentElement; + const firstChild = td.childNodes[0]; + const is_anon_enum = firstChild && firstChild.textContent.trim()=='{'; + if (hasClass(tr, 'template')) { + tr = tr.previousElementSibling; + } + id = tr.getAttribute('id'); + let text = is_anon_enum ? 'anonymous enum' : (td.querySelector(':first-child') ? td.querySelector(':first-child').textContent : ''); + let isMemberGroupHeader = hasClass(tr, 'groupHeader'); + if (tr.offsetParent !== null && last_id!=id && id!==undefined) { + if (isMemberGroupHeader && inMemberGroup) { + ulStack.pop(); + inMemberGroup=false; + } + const li2 = document.createElement('li'); + li2.setAttribute('id', 'nav-'+id); + const div2 = document.createElement('div'); + div2.classList.add('item'); + const span2 = document.createElement('span'); + span2.classList.add('arrow'); + span2.style.paddingLeft = parseInt(ulStack.length*16)+'px'; + const ahref = document.createElement('a'); + ahref.setAttribute('href', '#'+id); + ahref.textContent = escapeHtml(text); + div2.appendChild(span2); + div2.appendChild(ahref); + li2.appendChild(div2); + topMapping.push(id); + if (isMemberGroupHeader) { + const arrowSpan = document.createElement('span'); + arrowSpan.classList.add('arrowhead','opened'); + span2.appendChild(arrowSpan); + ulStack[ulStack.length-1].appendChild(li2); + const ul2 = document.createElement('ul'); + ulStack.push(ul2); + li2.appendChild(ul2); + inMemberGroup=true; + } else { + ulStack[ulStack.length-1].appendChild(li2); + } + last_id=id; + } + }); + // detailed documentation has h2.memtitle sections for items + item.memTitles.forEach(function(data) { + const childNodes = Array.from(data.childNodes); + const firstChild = data.children[0]; + let text = ''; + childNodes.forEach(node => { + if (node !== firstChild) { + text += node.textContent || ''; + } + }); + const name = text.replace(/\(\)(\s*\[\d+\/\d+\])?$/, '') // func() [2/8] -> func + const permalinkAnchor = data.querySelector('span.permalink a'); + id = permalinkAnchor ? permalinkAnchor.getAttribute('href') : undefined; + if (id!==undefined && name!==undefined) { + const li2 = document.createElement('li'); + li2.setAttribute('id', 'nav-'+id.substring(1)); + const div2 = document.createElement('div'); + div2.classList.add('item'); + const span2 = document.createElement('span'); + span2.classList.add('arrow'); + span2.style.paddingLeft = parseInt(ulStack.length*16)+'px'; + const ahref = document.createElement('a'); + ahref.setAttribute('href', id); + ahref.textContent = escapeHtml(name); + div2.appendChild(span2); + div2.appendChild(ahref); + li2.appendChild(div2); + ulStack[ulStack.length-1].appendChild(li2); + topMapping.push(id.substring(1)); + } + }); + } + }); + if (allMembersFile.length) { // add entry linking to all members page + const url = location.href; + let srcBaseUrl = ''; + let dstBaseUrl = ''; + if (relpath.length) { // CREATE_SUBDIRS=YES -> find target location + srcBaseUrl = url.substring(0, url.lastIndexOf('/')) + '/' + relpath; + dstBaseUrl = allMembersFile.substr(0, allMembersFile.lastIndexOf('/'))+'/'; + } + const pageName = url.split('/').pop().split('#')[0].replace(/(\.[^/.]+)$/, '-members$1'); + const li = document.createElement('li'); + const div = document.createElement('div'); + div.classList.add('item'); + const span = document.createElement('span'); + span.classList.add('arrow'); + span.style.paddingLeft='0px'; + const ahref = document.createElement('a'); + ahref.setAttribute('href', srcBaseUrl+dstBaseUrl+pageName); + ahref.classList.add('noscroll'); + ahref.textContent = LISTOFALLMEMBERS; + div.appendChild(span); + div.appendChild(ahref); + li.appendChild(div); + content.appendChild(li); + } + + if (groupSections.length==0) { + // for PageDef + const sectionTree = [], sectionStack = []; + $$('h1.doxsection, h2.doxsection, h3.doxsection, h4.doxsection, h5.doxsection, h6.doxsection').forEach(function(element){ + const level = parseInt(element.tagName[1]); + const anchorEl = element.querySelector('a.anchor'); + const anchor = anchorEl ? anchorEl.getAttribute('id') : null; + // Note: innerHTML is used here to preserve HTML formatting in section headings + // This content is generated by doxygen, not from user input + const node = { text: element.innerHTML, id: anchor, children: [] }; + while (sectionStack.length && sectionStack[sectionStack.length - 1].level >= level) sectionStack.pop(); + (sectionStack.length ? sectionStack[sectionStack.length - 1].children : sectionTree).push(node); + sectionStack.push({ ...node, level }); + }); + if (sectionTree.length>0) { + function render(nodes, level=0) { + nodes.map(n => { + const li = document.createElement('li'); + li.setAttribute('id', 'nav-'+n.id); + const div = document.createElement('div'); + div.classList.add('item'); + const span = document.createElement('span'); + span.classList.add('arrow'); + span.setAttribute('style', 'padding-left:'+parseInt(level*16)+'px;'); + if (n.children.length > 0) { + const arrowSpan = document.createElement('span'); + arrowSpan.classList.add('arrowhead','opened'); + span.appendChild(arrowSpan); + } + const url = document.createElement('a'); + url.setAttribute('href', '#'+n.id); + // innerHTML used to preserve HTML formatting from doxygen-generated content + url.innerHTML = n.text; + div.appendChild(span); + div.appendChild(url); + li.appendChild(div); + content.appendChild(li); + topMapping.push(n.id); + render(n.children,level+1); + }); + } + render(sectionTree); + } + } + + if (toc_contents) { + toc_contents.appendChild(content); + } + + $$(".page-outline a[href]:not(.noscroll)").forEach(function(anchor) { + anchor.addEventListener('click', function(e) { + e.preventDefault(); + const aname = this.getAttribute("href"); + gotoAnchor(document.querySelector(aname), aname); + }); + }); + + let lastScrollSourceOffset = -1; + let lastScrollTargetOffset = -1; + let lastScrollTargetId = ''; + + navtree_trampoline.updateContentTop = function() { + const pagenavcontents = $("#page-nav-contents"); + if (pagenavcontents) { + const content = $("#doc-content"); + const height = content ? content.clientHeight : 0; + const navy = pagenavcontents ? offsetTop(pagenavcontents) : 0; + const yc = content ? offsetTop(content) : 0; + let offsets = [] + for (let i=0;imargin || ye>margin) && (yslastScrollTargetOffset) || + (!scrollDown && targetOffset { + navtree_trampoline.updateContentTop(); + },200); + } + + if (document.readyState === 'loading') { + document.addEventListener('DOMContentLoaded', function() { + initPageToc(); + initResizable(); + }); + } else { + initPageToc(); + initResizable(); + } + + initResizableFunc = initResizable; + +} +/* @license-end */ diff --git a/navtreedata.js b/navtreedata.js new file mode 100644 index 0000000..6346cef --- /dev/null +++ b/navtreedata.js @@ -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 & 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: ConformalMesh", "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 (newton_solver.hpp)", "md__c_l_a_u_d_e.html#autotoc_md24", null ], + [ "Layout and holonomy (layout.hpp)", "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 & theory", "md__c_l_a_u_d_e.html#autotoc_md39", null ], + [ "Architecture & design", "md__c_l_a_u_d_e.html#autotoc_md40", null ], + [ "API & extension", "md__c_l_a_u_d_e.html#autotoc_md41", null ], + [ "Concepts & specs", "md__c_l_a_u_d_e.html#autotoc_md42", null ], + [ "Roadmap & porting", "md__c_l_a_u_d_e.html#autotoc_md43", null ], + [ "Tutorials & 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'; \ No newline at end of file diff --git a/navtreeindex0.js b/navtreeindex0.js new file mode 100644 index 0000000..95a5f5a --- /dev/null +++ b/navtreeindex0.js @@ -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":[] +}; diff --git a/pages.html b/pages.html new file mode 100644 index 0000000..4bbe536 --- /dev/null +++ b/pages.html @@ -0,0 +1,138 @@ + + + + + + + +conformallab++: Related Pages + + + + + + + + + + + + + + + +
+
+ + + + + + +
+
conformallab++ 0.7.0 +
+
Discrete conformal maps on triangle meshes — C++17 reimplementation of ConformalLab (TU Berlin)
+
+
+ + + + + + + + + +
+
+ +
+
+
+ +
+
+ +
+
+ + +
+
+
+
+
+
Loading...
+
Searching...
+
No Matches
+
+
+
+
+ +
+
Related Pages
+
+
+
Here is a list of all related documentation pages:
+ + +
 CLAUDE.md
+
+
+
+
+ + + + diff --git a/search/all_0.js b/search/all_0.js new file mode 100644 index 0000000..b270833 --- /dev/null +++ b/search/all_0.js @@ -0,0 +1,6 @@ +var searchData= +[ + ['0_0',['"Natural theta" — 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,'']]] +]; diff --git a/search/all_1.js b/search/all_1.js new file mode 100644 index 0000000..a4f0238 --- /dev/null +++ b/search/all_1.js @@ -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,'']]] +]; diff --git a/search/all_10.js b/search/all_10.js new file mode 100644 index 0000000..8eeeb2e --- /dev/null +++ b/search/all_10.js @@ -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 (<span class="tt">layout.hpp</span>)',['../md__c_l_a_u_d_e.html#autotoc_md25',1,'']]], + ['layout_20hpp_2',['Layout and holonomy (<span class="tt">layout.hpp</span>)',['../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,'']]] +]; diff --git a/search/all_11.js b/search/all_11.js new file mode 100644 index 0000000..85007cc --- /dev/null +++ b/search/all_11.js @@ -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; 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,'']]] +]; diff --git a/search/all_12.js b/search/all_12.js new file mode 100644 index 0000000..641ec81 --- /dev/null +++ b/search/all_12.js @@ -0,0 +1,7 @@ +var searchData= +[ + ['natural_20theta_20—_20constructing_20a_20known_20equilibrium_20at_20x_200_0',['"Natural theta" — 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 (<span class="tt">newton_solver.hpp</span>)',['../md__c_l_a_u_d_e.html#autotoc_md24',1,'']]], + ['newton_5fsolver_20hpp_2',['Newton solver (<span class="tt">newton_solver.hpp</span>)',['../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,'']]] +]; diff --git a/search/all_13.js b/search/all_13.js new file mode 100644 index 0000000..247c6c8 --- /dev/null +++ b/search/all_13.js @@ -0,0 +1,5 @@ +var searchData= +[ + ['onboarding_0',['Tutorials &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,'']]] +]; diff --git a/search/all_14.js b/search/all_14.js new file mode 100644 index 0000000..49b27af --- /dev/null +++ b/search/all_14.js @@ -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; 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,'']]] +]; diff --git a/search/all_15.js b/search/all_15.js new file mode 100644 index 0000000..15bcc5f --- /dev/null +++ b/search/all_15.js @@ -0,0 +1,6 @@ +var searchData= +[ + ['questions_0',['Bugs &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,'']]] +]; diff --git a/search/all_16.js b/search/all_16.js new file mode 100644 index 0000000..e4171e0 --- /dev/null +++ b/search/all_16.js @@ -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; 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,'']]] +]; diff --git a/search/all_17.js b/search/all_17.js new file mode 100644 index 0000000..a5cfb0a --- /dev/null +++ b/search/all_17.js @@ -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 (<span class="tt">newton_solver.hpp</span>)',['../md__c_l_a_u_d_e.html#autotoc_md24',1,'']]], + ['specs_3',['Concepts &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,'']]] +]; diff --git a/search/all_18.js b/search/all_18.js new file mode 100644 index 0000000..ca34208 --- /dev/null +++ b/search/all_18.js @@ -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; theory',['../md__c_l_a_u_d_e.html#autotoc_md39',1,'']]], + ['theta_20—_20constructing_20a_20known_20equilibrium_20at_20x_200_8',['"Natural theta" — 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; onboarding',['../md__c_l_a_u_d_e.html#autotoc_md44',1,'']]], + ['type_3a_20conformalmesh_12',['Central type: <span class="tt">ConformalMesh</span>',['../md__c_l_a_u_d_e.html#autotoc_md21',1,'']]] +]; diff --git a/search/all_19.js b/search/all_19.js new file mode 100644 index 0000000..f339e96 --- /dev/null +++ b/search/all_19.js @@ -0,0 +1,4 @@ +var searchData= +[ + ['usage_0',['Minimal usage',['../index.html#autotoc_md4',1,'']]] +]; diff --git a/search/all_1a.js b/search/all_1a.js new file mode 100644 index 0000000..b0cf2df --- /dev/null +++ b/search/all_1a.js @@ -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,'']]] +]; diff --git a/search/all_1b.js b/search/all_1b.js new file mode 100644 index 0000000..073ff3b --- /dev/null +++ b/search/all_1b.js @@ -0,0 +1,4 @@ +var searchData= +[ + ['x_200_0',['"Natural theta" — constructing a known equilibrium at x* = 0',['../md__c_l_a_u_d_e.html#autotoc_md29',1,'']]] +]; diff --git a/search/all_1c.js b/search/all_1c.js new file mode 100644 index 0000000..e51422e --- /dev/null +++ b/search/all_1c.js @@ -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,'']]] +]; diff --git a/search/all_1d.js b/search/all_1d.js new file mode 100644 index 0000000..3633db0 --- /dev/null +++ b/search/all_1d.js @@ -0,0 +1,4 @@ +var searchData= +[ + ['—_20constructing_20a_20known_20equilibrium_20at_20x_200_0',['"Natural theta" — constructing a known equilibrium at x* = 0',['../md__c_l_a_u_d_e.html#autotoc_md29',1,'']]] +]; diff --git a/search/all_2.js b/search/all_2.js new file mode 100644 index 0000000..c950ef0 --- /dev/null +++ b/search/all_2.js @@ -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,'']]] +]; diff --git a/search/all_3.js b/search/all_3.js new file mode 100644 index 0000000..27d3ab9 --- /dev/null +++ b/search/all_3.js @@ -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,'']]] +]; diff --git a/search/all_4.js b/search/all_4.js new file mode 100644 index 0000000..4f854ab --- /dev/null +++ b/search/all_4.js @@ -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,'']]] +]; diff --git a/search/all_5.js b/search/all_5.js new file mode 100644 index 0000000..6dfc841 --- /dev/null +++ b/search/all_5.js @@ -0,0 +1,13 @@ +var searchData= +[ + ['a_20known_20equilibrium_20at_20x_200_0',['"Natural theta" — 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 (<span class="tt">layout.hpp</span>)',['../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; 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; design',['../md__c_l_a_u_d_e.html#autotoc_md40',1,'']]], + ['at_20x_200_7',['"Natural theta" — 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,'']]] +]; diff --git a/search/all_6.js b/search/all_6.js new file mode 100644 index 0000000..4e92342 --- /dev/null +++ b/search/all_6.js @@ -0,0 +1,5 @@ +var searchData= +[ + ['bugs_20questions_0',['Bugs &amp; questions',['../index.html#autotoc_md10',1,'']]], + ['build_20commands_1',['Build commands',['../md__c_l_a_u_d_e.html#autotoc_md16',1,'']]] +]; diff --git a/search/all_7.js b/search/all_7.js new file mode 100644 index 0000000..5c815bd --- /dev/null +++ b/search/all_7.js @@ -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: <span class="tt">ConformalMesh</span>',['../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; specs',['../md__c_l_a_u_d_e.html#autotoc_md42',1,'']]], + ['conformallab_11',['conformallab++',['../index.html',1,'']]], + ['conformalmesh_12',['Central type: <span class="tt">ConformalMesh</span>',['../md__c_l_a_u_d_e.html#autotoc_md21',1,'']]], + ['constructing_20a_20known_20equilibrium_20at_20x_200_13',['"Natural theta" — 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,'']]] +]; diff --git a/search/all_8.js b/search/all_8.js new file mode 100644 index 0000000..9dbd06e --- /dev/null +++ b/search/all_8.js @@ -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; 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,'']]] +]; diff --git a/search/all_9.js b/search/all_9.js new file mode 100644 index 0000000..c67bcc8 --- /dev/null +++ b/search/all_9.js @@ -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',['"Natural theta" — 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; extension',['../md__c_l_a_u_d_e.html#autotoc_md41',1,'']]] +]; diff --git a/search/all_a.js b/search/all_a.js new file mode 100644 index 0000000..9651e0d --- /dev/null +++ b/search/all_a.js @@ -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,'']]] +]; diff --git a/search/all_b.js b/search/all_b.js new file mode 100644 index 0000000..aecf429 --- /dev/null +++ b/search/all_b.js @@ -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,'']]] +]; diff --git a/search/all_c.js b/search/all_c.js new file mode 100644 index 0000000..f64a944 --- /dev/null +++ b/search/all_c.js @@ -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 (<span class="tt">layout.hpp</span>)',['../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 (<span class="tt">layout.hpp</span>)'],['../md__c_l_a_u_d_e.html#autotoc_md24',1,'Newton solver (<span class="tt">newton_solver.hpp</span>)']]] +]; diff --git a/search/all_d.js b/search/all_d.js new file mode 100644 index 0000000..307ac3c --- /dev/null +++ b/search/all_d.js @@ -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,'']]] +]; diff --git a/search/all_e.js b/search/all_e.js new file mode 100644 index 0000000..478db41 --- /dev/null +++ b/search/all_e.js @@ -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,'']]] +]; diff --git a/search/all_f.js b/search/all_f.js new file mode 100644 index 0000000..11a80a9 --- /dev/null +++ b/search/all_f.js @@ -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',['"Natural theta" — 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,'']]] +]; diff --git a/search/files_0.js b/search/files_0.js new file mode 100644 index 0000000..45de0b1 --- /dev/null +++ b/search/files_0.js @@ -0,0 +1,4 @@ +var searchData= +[ + ['claude_2emd_0',['CLAUDE.md',['../_c_l_a_u_d_e_8md.html',1,'']]] +]; diff --git a/search/files_1.js b/search/files_1.js new file mode 100644 index 0000000..4accdc1 --- /dev/null +++ b/search/files_1.js @@ -0,0 +1,4 @@ +var searchData= +[ + ['readme_2emd_0',['README.md',['../_r_e_a_d_m_e_8md.html',1,'']]] +]; diff --git a/search/pages_0.js b/search/pages_0.js new file mode 100644 index 0000000..b270833 --- /dev/null +++ b/search/pages_0.js @@ -0,0 +1,6 @@ +var searchData= +[ + ['0_0',['"Natural theta" — 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,'']]] +]; diff --git a/search/pages_1.js b/search/pages_1.js new file mode 100644 index 0000000..a4f0238 --- /dev/null +++ b/search/pages_1.js @@ -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,'']]] +]; diff --git a/search/pages_10.js b/search/pages_10.js new file mode 100644 index 0000000..8eeeb2e --- /dev/null +++ b/search/pages_10.js @@ -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 (<span class="tt">layout.hpp</span>)',['../md__c_l_a_u_d_e.html#autotoc_md25',1,'']]], + ['layout_20hpp_2',['Layout and holonomy (<span class="tt">layout.hpp</span>)',['../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,'']]] +]; diff --git a/search/pages_11.js b/search/pages_11.js new file mode 100644 index 0000000..85007cc --- /dev/null +++ b/search/pages_11.js @@ -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; 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,'']]] +]; diff --git a/search/pages_12.js b/search/pages_12.js new file mode 100644 index 0000000..641ec81 --- /dev/null +++ b/search/pages_12.js @@ -0,0 +1,7 @@ +var searchData= +[ + ['natural_20theta_20—_20constructing_20a_20known_20equilibrium_20at_20x_200_0',['"Natural theta" — 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 (<span class="tt">newton_solver.hpp</span>)',['../md__c_l_a_u_d_e.html#autotoc_md24',1,'']]], + ['newton_5fsolver_20hpp_2',['Newton solver (<span class="tt">newton_solver.hpp</span>)',['../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,'']]] +]; diff --git a/search/pages_13.js b/search/pages_13.js new file mode 100644 index 0000000..247c6c8 --- /dev/null +++ b/search/pages_13.js @@ -0,0 +1,5 @@ +var searchData= +[ + ['onboarding_0',['Tutorials &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,'']]] +]; diff --git a/search/pages_14.js b/search/pages_14.js new file mode 100644 index 0000000..49b27af --- /dev/null +++ b/search/pages_14.js @@ -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; 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,'']]] +]; diff --git a/search/pages_15.js b/search/pages_15.js new file mode 100644 index 0000000..15bcc5f --- /dev/null +++ b/search/pages_15.js @@ -0,0 +1,6 @@ +var searchData= +[ + ['questions_0',['Bugs &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,'']]] +]; diff --git a/search/pages_16.js b/search/pages_16.js new file mode 100644 index 0000000..54c9a00 --- /dev/null +++ b/search/pages_16.js @@ -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; 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,'']]] +]; diff --git a/search/pages_17.js b/search/pages_17.js new file mode 100644 index 0000000..a5cfb0a --- /dev/null +++ b/search/pages_17.js @@ -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 (<span class="tt">newton_solver.hpp</span>)',['../md__c_l_a_u_d_e.html#autotoc_md24',1,'']]], + ['specs_3',['Concepts &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,'']]] +]; diff --git a/search/pages_18.js b/search/pages_18.js new file mode 100644 index 0000000..ca34208 --- /dev/null +++ b/search/pages_18.js @@ -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; theory',['../md__c_l_a_u_d_e.html#autotoc_md39',1,'']]], + ['theta_20—_20constructing_20a_20known_20equilibrium_20at_20x_200_8',['"Natural theta" — 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; onboarding',['../md__c_l_a_u_d_e.html#autotoc_md44',1,'']]], + ['type_3a_20conformalmesh_12',['Central type: <span class="tt">ConformalMesh</span>',['../md__c_l_a_u_d_e.html#autotoc_md21',1,'']]] +]; diff --git a/search/pages_19.js b/search/pages_19.js new file mode 100644 index 0000000..f339e96 --- /dev/null +++ b/search/pages_19.js @@ -0,0 +1,4 @@ +var searchData= +[ + ['usage_0',['Minimal usage',['../index.html#autotoc_md4',1,'']]] +]; diff --git a/search/pages_1a.js b/search/pages_1a.js new file mode 100644 index 0000000..b0cf2df --- /dev/null +++ b/search/pages_1a.js @@ -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,'']]] +]; diff --git a/search/pages_1b.js b/search/pages_1b.js new file mode 100644 index 0000000..073ff3b --- /dev/null +++ b/search/pages_1b.js @@ -0,0 +1,4 @@ +var searchData= +[ + ['x_200_0',['"Natural theta" — constructing a known equilibrium at x* = 0',['../md__c_l_a_u_d_e.html#autotoc_md29',1,'']]] +]; diff --git a/search/pages_1c.js b/search/pages_1c.js new file mode 100644 index 0000000..e51422e --- /dev/null +++ b/search/pages_1c.js @@ -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,'']]] +]; diff --git a/search/pages_1d.js b/search/pages_1d.js new file mode 100644 index 0000000..3633db0 --- /dev/null +++ b/search/pages_1d.js @@ -0,0 +1,4 @@ +var searchData= +[ + ['—_20constructing_20a_20known_20equilibrium_20at_20x_200_0',['"Natural theta" — constructing a known equilibrium at x* = 0',['../md__c_l_a_u_d_e.html#autotoc_md29',1,'']]] +]; diff --git a/search/pages_2.js b/search/pages_2.js new file mode 100644 index 0000000..c950ef0 --- /dev/null +++ b/search/pages_2.js @@ -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,'']]] +]; diff --git a/search/pages_3.js b/search/pages_3.js new file mode 100644 index 0000000..27d3ab9 --- /dev/null +++ b/search/pages_3.js @@ -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,'']]] +]; diff --git a/search/pages_4.js b/search/pages_4.js new file mode 100644 index 0000000..4f854ab --- /dev/null +++ b/search/pages_4.js @@ -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,'']]] +]; diff --git a/search/pages_5.js b/search/pages_5.js new file mode 100644 index 0000000..6dfc841 --- /dev/null +++ b/search/pages_5.js @@ -0,0 +1,13 @@ +var searchData= +[ + ['a_20known_20equilibrium_20at_20x_200_0',['"Natural theta" — 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 (<span class="tt">layout.hpp</span>)',['../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; 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; design',['../md__c_l_a_u_d_e.html#autotoc_md40',1,'']]], + ['at_20x_200_7',['"Natural theta" — 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,'']]] +]; diff --git a/search/pages_6.js b/search/pages_6.js new file mode 100644 index 0000000..4e92342 --- /dev/null +++ b/search/pages_6.js @@ -0,0 +1,5 @@ +var searchData= +[ + ['bugs_20questions_0',['Bugs &amp; questions',['../index.html#autotoc_md10',1,'']]], + ['build_20commands_1',['Build commands',['../md__c_l_a_u_d_e.html#autotoc_md16',1,'']]] +]; diff --git a/search/pages_7.js b/search/pages_7.js new file mode 100644 index 0000000..c73b127 --- /dev/null +++ b/search/pages_7.js @@ -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: <span class="tt">ConformalMesh</span>',['../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; specs',['../md__c_l_a_u_d_e.html#autotoc_md42',1,'']]], + ['conformallab_10',['conformallab++',['../index.html',1,'']]], + ['conformalmesh_11',['Central type: <span class="tt">ConformalMesh</span>',['../md__c_l_a_u_d_e.html#autotoc_md21',1,'']]], + ['constructing_20a_20known_20equilibrium_20at_20x_200_12',['"Natural theta" — 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,'']]] +]; diff --git a/search/pages_8.js b/search/pages_8.js new file mode 100644 index 0000000..9dbd06e --- /dev/null +++ b/search/pages_8.js @@ -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; 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,'']]] +]; diff --git a/search/pages_9.js b/search/pages_9.js new file mode 100644 index 0000000..c67bcc8 --- /dev/null +++ b/search/pages_9.js @@ -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',['"Natural theta" — 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; extension',['../md__c_l_a_u_d_e.html#autotoc_md41',1,'']]] +]; diff --git a/search/pages_a.js b/search/pages_a.js new file mode 100644 index 0000000..9651e0d --- /dev/null +++ b/search/pages_a.js @@ -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,'']]] +]; diff --git a/search/pages_b.js b/search/pages_b.js new file mode 100644 index 0000000..aecf429 --- /dev/null +++ b/search/pages_b.js @@ -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,'']]] +]; diff --git a/search/pages_c.js b/search/pages_c.js new file mode 100644 index 0000000..f64a944 --- /dev/null +++ b/search/pages_c.js @@ -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 (<span class="tt">layout.hpp</span>)',['../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 (<span class="tt">layout.hpp</span>)'],['../md__c_l_a_u_d_e.html#autotoc_md24',1,'Newton solver (<span class="tt">newton_solver.hpp</span>)']]] +]; diff --git a/search/pages_d.js b/search/pages_d.js new file mode 100644 index 0000000..307ac3c --- /dev/null +++ b/search/pages_d.js @@ -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,'']]] +]; diff --git a/search/pages_e.js b/search/pages_e.js new file mode 100644 index 0000000..478db41 --- /dev/null +++ b/search/pages_e.js @@ -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,'']]] +]; diff --git a/search/pages_f.js b/search/pages_f.js new file mode 100644 index 0000000..11a80a9 --- /dev/null +++ b/search/pages_f.js @@ -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',['"Natural theta" — 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,'']]] +]; diff --git a/search/search.css b/search/search.css new file mode 100644 index 0000000..e0ce0ee --- /dev/null +++ b/search/search.css @@ -0,0 +1,377 @@ +/*---------------- Search Box positioning */ + +#main-menu > li:last-child { + /* This
  • 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; +} + diff --git a/search/search.js b/search/search.js new file mode 100644 index 0000000..dc14410 --- /dev/null +++ b/search/search.js @@ -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 do a search + this.Search(); + } + } + + this.OnSearchSelectKey = function(evt) { + const e = (evt) ? evt : window.event; // for IE + if (e.keyCode==40 && this.searchIndex0) { // 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. + 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; cli>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 +} +} +