diff --git a/CMakeLists.txt b/CMakeLists.txt
index 38d945ae..0eaee653 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -39,13 +39,13 @@ message( STATUS "Build type: ${CMAKE_BUILD_TYPE}" )
option( CPM_DISABLE "Don't use CPM to retrieve dependencies" "$ENV{CPM_DISABLE}" )
option( OEMSH_PORTABILITY_TWEAKS "Enable some portability tweaks" OFF )
+list( APPEND CMAKE_MODULE_PATH
+ "${CMAKE_SOURCE_DIR}/cmake"
+ )
+
if( NOT CPM_DISABLE )
message( STATUS "Downloading dependencies with CPM" )
- list( APPEND CMAKE_MODULE_PATH
- "${CMAKE_SOURCE_DIR}/cmake"
- )
-
include( CPM )
CPMAddPackage(
@@ -126,12 +126,20 @@ else()
message( STATUS "Not found D2: Some parts of doc disabled" )
endif()
+find_program( PDF2SVG NAMES pdf2svg )
+if( PDF2SVG )
+ message( STATUS "Found pdf2svg: ${PDF2SVG}" )
+else()
+ message( STATUS "Not found pdf2svg: Some parts of doc disabled" )
+endif()
+
if( CMakeUtils_FOUND )
set( CMAKE_UTILS * )
set( COVERAGE_GLOBAL_ONLY ON )
include( CMakeUtils )
endif()
+include( ConfigureFileBuildTime )
include( GNUInstallDirs )
set( CMAKE_INSTALL_DEFAULT_DIRECTORY_PERMISSIONS
diff --git a/cmake/ConfigureFileBuildTime.cmake b/cmake/ConfigureFileBuildTime.cmake
new file mode 100644
index 00000000..b9690639
--- /dev/null
+++ b/cmake/ConfigureFileBuildTime.cmake
@@ -0,0 +1,33 @@
+
+################################################################################
+function( configure_file_build_time INPUT OUTPUT )
+ set( OPTIONS )
+ set( ONEVALUEARGS )
+ set( MULTIVALUEARGS VARS )
+# set( MULTIVALUEARGS ARGS VARS )
+ cmake_parse_arguments( CFBT
+ "${OPTIONS}"
+ "${ONEVALUEARGS}"
+ "${MULTIVALUEARGS}"
+ ${ARGN}
+ )
+
+ while( CFBT_VARS )
+ list( POP_FRONT CFBT_VARS VAR VAL )
+ list( APPEND VARS "-D${VAR}=\"${VAL}\"" )
+ endwhile()
+
+ file( WRITE
+ "${OUTPUT}.cmake"
+ "configure_file(\"${INPUT}\" \"${OUTPUT}\" ${CFBT_UNPARSED_ARGUMENTS})"
+# "configure_file(\"${INPUT}\" \"${OUTPUT}\" ${CFBT_ARGS})"
+ )
+
+ add_custom_command(
+ OUTPUT ${OUTPUT}
+ DEPENDS ${INPUT}
+ COMMAND ${CMAKE_COMMAND}
+ ${VARS}
+ -P "${OUTPUT}.cmake"
+ )
+endfunction()
diff --git a/default.nix b/default.nix
index 0b47584e..98348f33 100644
--- a/default.nix
+++ b/default.nix
@@ -4,11 +4,14 @@
, cmake-utils
, git
, texlive
+, pdf2svg
, cli11
, indicators
, pugixml
, qtbase
, wrapQtAppsHook
+, fetchzip
+, runCommand
, withPortabilityTweaks ? false
}:
@@ -40,8 +43,45 @@ stdenv.mkDerivation {
cmake-utils
git
wrapQtAppsHook
+ pdf2svg
(texlive.combine {
- inherit (texlive) scheme-small standalone pgfplots;
+ inherit (texlive) scheme-small standalone pgfplots unicode-math;
+ # https://ctan.org/tex-archive/fonts/lete-sans-math
+ # TODO use buildTeXLivePackage
+# lete-sans-math = pkgs.texlivePackages.buildTeXLivePackage {
+## revision = 64540;
+# shortdesc = "Lato-based OpenType Math font for LuaTeX and XeTeX";
+## stripPrefix = 0;
+## fontMaps = [
+## "Map andika.map"
+## ];
+## sha512.run = "4da9904459345033aa87deeb0019c8c4a39fbafcd59d973717ed2c4a410ece528944c69669b6a5ecf6ef8bb790f60bba909468e001485c405e7cf8775b7533e5";
+## sha512.doc = "50684857dc25ad942aff18eedec04c9e27e4e408f748c208f8527c5096e600d26769ec6f82e2f02e72ab472dfb662f12bb009156293a12daa2dc0676d63ed446";
+# hasRunfiles = false;
+# license = [ "lppl13c" ];
+# version = "0.41";
+# };
+ lete-sans-math = {
+ pkgs = [
+ (runCommand "lete-sans-math" rec {
+ src = fetchzip {
+ url = "https://github.com/abccsss/LeteSansMath/archive/refs/tags/v${passthru.version}.zip";
+ hash = "sha256-q+WwdSUeHIffpgrJ6GKzyQz+iNxUTeHr4GQZsT0r1Kw=";
+ };
+ passthru = {
+ pname = "lete-sans-math";
+ version = "0.50";
+ tlType = "run";
+ };
+ } ''
+ mkdir -p \
+ $out/tex/latex/lete-sans-math/ \
+ $out/fonts/opentype/public/lete-sans-math/
+ cp $src/*.sty $src/*.ltx $out/tex/latex/lete-sans-math/
+ cp $src/*.otf $out/fonts/opentype/public/lete-sans-math/
+ '')
+ ];
+ };
})
];
diff --git a/doc/CMakeLists.txt b/doc/CMakeLists.txt
index 749062d8..07b47b42 100644
--- a/doc/CMakeLists.txt
+++ b/doc/CMakeLists.txt
@@ -1,5 +1,38 @@
add_custom_target( doc )
+if( CMakeUtils_Latex_FOUND AND PDF2SVG )
+ compile_latex_file( "interval"
+ OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/interval.svg"
+ SOURCE "${CMAKE_CURRENT_SOURCE_DIR}/latex"
+ TEXINPUTS "${CMAKE_CURRENT_SOURCE_DIR}/latex"
+ REGISTER_TO "INTERVAL_FILES"
+ SHELL_ESCAPE
+ )
+endif()
+
+configure_file_build_time(
+ "${CMAKE_CURRENT_SOURCE_DIR}/interval.md.in"
+ "${CMAKE_CURRENT_BINARY_DIR}/interval.md"
+ @ONLY
+ VARS
+ INTERVAL_SVG "./latex/interval.svg"
+ )
+
+add_custom_target( interval
+ DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/interval.md" ${INTERVAL_FILES}
+ )
+
+add_dependencies( doc interval )
+
+install(
+ FILES
+ "${CMAKE_CURRENT_BINARY_DIR}/interval.md"
+ ${INTERVAL_FILES}
+ DESTINATION "${CMAKE_INSTALL_DOCDIR}"
+ CONFIGURATIONS Release
+ OPTIONAL
+ )
+
configure_file(
"${CMAKE_CURRENT_SOURCE_DIR}/openemsh.1.in"
"${CMAKE_CURRENT_BINARY_DIR}/openemsh.1"
diff --git a/doc/interval.md.in b/doc/interval.md.in
new file mode 100644
index 00000000..ef59e577
--- /dev/null
+++ b/doc/interval.md.in
@@ -0,0 +1,42 @@
+# Meshing algorithm
+
+## Scope
+
+The meshing process consists of two parts:
+- The geometrical analysis that, given a structure, outputs some `MeshlinePolicies` ("Here is something of interest that must be meshed according those rules", typically an `Edge` must be meshed according Thirds rule) and some `Interval` in between.
+- The `Meshline` generation, that consist of filling each `Interval` while respecting enclosing `MeshlinePolicies`' specific rules.
+
+Despite being actually just the last step of the whole process, this explanatory document is about the generation of `Meshlines` at `Interval` level.
+
+## Reference
+
+
+
+- `x`: Position of `MeshlinePolicies`.
+- `m`: Position of the middle of the `Interval` between two `MeshlinePolicies`.
+- `h`: Half of the Interval between two `MeshlinePolicies`.
+- `f`: Smoothness factor `[1;2]`.
+- `d`: Distance between the two lines around a `MeshlinePolicy`.
+- `dinit`: Space between `x` and the first line (may not be the half of `d`).
+- `dmax`: Maximal authorized space between two lines.
+- `s`: Space to fill of lines.
+- `z`: Distance from the first line (belonging to `MeshlinePolicy`) to the last line before `m` (the middle of the `Interval`).
+- `lz`: Number of lines before the middle of the `Interval` (minus the line belonging to the `MeshlinePolicy`).
+
+Orange lines belong to `MeshlinePolicies`, green lines belong to `Interval`.
+
+## Algorithm
+
+### Rules
+
+- Axes are meshed `Interval` by `Interval`, smallest first.
+- `Intervals` are meshed **half by half**.
+- Spaces between lines, including `d` are always bounded to `dmax`.
+- Space between lines cannot exceed adjacent spaces multiplied by the smoothness factor.
+
+### Steps
+
+- Choose `dmax` among `Interval`'s `dmax` and projection from both sides' `d` of `f**(lz+1)`, so the sizes of the two cells around `m` (belonging to both sides) will respect the smoothness factor (`f`).
+- Reduce `d` until enough lines are in the half (`lz >= lmin`).
+- Reduce the smoothness factor (which augments the spaces between lines, except `d`) until `z` matches `s`, that is to say until the last line of the half overlaps with `m` (actually just passed `m`).
+- Trim out the last line, that overlaps `m` (a line at `m`, that will count for both halves, will be placed instead).
diff --git a/doc/latex/interval.tex b/doc/latex/interval.tex
new file mode 100644
index 00000000..9193da3b
--- /dev/null
+++ b/doc/latex/interval.tex
@@ -0,0 +1,239 @@
+\documentclass[
+ tikz,
+ multi=false,
+ convert=pdf2svg
+ ]{standalone}
+
+%\usepackage{etoolbox}
+\usepackage{fontspec}
+\setmainfont[Ligatures=TeX, Mapping=tex-text]{Lato}
+%\usepackage[default]{lato}
+\usepackage{unicode-math}
+%\setmathfont{Lete Sans Math}
+\setmathfont{LeteSansMath.otf}
+%\usepackage{lete-sans-math}
+\usepackage{tikz}
+\usetikzlibrary{math}
+\usepackage{xfp}
+
+\begin{document}
+\begin{tikzpicture}
+
+\def\width{10}
+\def\height{5}
+\def\ox{\fpeval{\width /2}}
+\def\oy{\fpeval{\height /2}}
+\coordinate (O) at (\ox,\oy);
+
+\tiny
+\path [use as bounding box] (0,0) rectangle (\width,\height);
+
+% SHAPE
+%\filldraw [line width=0.5pt, fill=orange] (\ox,\oy)
+% +(-0.5,-0.5) node[draw, fill=black, circle, inner sep=1pt] {} node[below left] {0} --
+% +(0.5,-0.5) node[draw, fill=black, circle, inner sep=1pt] {} node[below right] {1} --
+% +(0.5,0.5) node[draw, fill=black, circle, inner sep=1pt] {} node[above right] {2} --
+% +(-0.5,0.5) node[draw, fill=black, circle, inner sep=1pt] {} node[above left] {3} --
+% cycle;
+
+% PORTS
+%\draw [line width=2pt] (\ox,\oy) ++(-0.5,0) node[right] {1} +(0,-0.5) -- +(0,0.5);
+%\draw [line width=2pt] (\ox,\oy) ++(0,-0.5) node[above] {2} +(-0.5,0) -- +(0.5,0);
+
+
+
+% MID LINE
+\draw [line width=0.5pt, dotted] (O) +(0,-2) node[below] {$m$} -- +(0,1);
+
+% EDGE LINES
+\draw [line width=0.5pt, dotted] (\ox,\oy) +(-4,-2) node[below] {$x$} -- +(-4,1);
+\draw [line width=0.5pt, dotted] (\ox,\oy) +(4,-2) node[below] {$x$} -- +(4,1);
+
+% POLICY LINES
+%\draw [line width=0.5pt, orange] (\ox,\oy) ++(-4,0)
+% +(-0.2,-1) -- +(-0.2,1)
+% +(0.2,-1) -- +(0.2,1);
+%\draw [line width=0.5pt, orange] (\ox,\oy) ++(4,0)
+% +(-0.1,-1) -- +(-0.1,1)
+% +(0.2,-1) -- +(0.2,1);
+% Function: policy line
+% #1 : x
+% #2 : x1 (relative to x)
+% #3 : x2 (relative to x)
+\newcommand{\policylines}[3]{%
+ \draw [line width=0.5pt, orange] (\ox,\oy) ++(#1,0)
+ +(#2,-1) -- +(#2,1)
+ +(#3,-1) -- +(#3,1)%
+}
+\policylines{-4}{-0.3}{0.3}; % 1/2 - Halfs rule
+\policylines{4}{-0.1}{0.2}; % 1/3 - Thirds rule
+
+% LINES
+%\newcommand{\drawline}[2][violet]{%
+% \draw [line width=0.5pt, color={#1}] (\ox,\oy)
+% +(#2,-1) -- +(#2,1)%
+%}
+%\drawline[orange]{3};
+%\newcommand{\drawline}[2][violet]{%
+% \draw [line width=0.5pt, {#1}] (\ox,\oy)
+\newcommand{\drawline}[2][line width=0.5pt, color=black]{%
+ \draw [{#1}] (\ox,\oy)
+ +(#2,-1) -- +(#2,1)%
+}
+%\drawline[orange, dotted]{3};
+%\drawline{2.5};
+%
+%\draw [line width=0.5pt, violet] (\ox,\oy) ++(-3.7,-1)
+%% ++(0,0) +(0,2)
+% ++(1.2,0) -- +(0,2)
+% ++(2.4,0) -- +(0,2)
+%;
+
+
+% First, produce a list of lines coordinates
+% Then, use the list to draw the lines and draw annotations
+% https://tex.stackexchange.com/questions/662928/is-this-the-right-way-to-understand-let-def-edef-gdef-xdef-newcommand-ren
+% edef daclare a var, performing expansion
+% xdef declare a global edef var
+\xdef\lines{}
+% TODO define as func with args { x, d_init, d, direction }
+\foreach \n in {1,...,2} {
+ \edef\tmp{\lines,\n}
+ \xdef\lines{\tmp}
+}
+
+%%%% #1 : output var
+%%%% #2 : n
+%%%% #3 : x
+%%%% #4 : d
+%%%% #5 : d_init
+%%%% #6 : smoothness
+%%%% #7 : direction
+%%%\newcommand{\createlines}[6] {%
+%%% % ##1 : n
+%%% \newcommand{\calculate}[1] {%
+%%%% \fpeval{#3 + ##1}%
+%%% \fpeval{(#3 + #5) + (#4 * (#6 ^ ##1))}%
+%%% }
+%%% % ##1 : s
+%%% % ##2 : d
+%%% %% ##3 : n
+%%% \newcommand{\calculates}[2] {%
+%%%% \fpeval{#3 + ##1}%
+%%% \fpeval{##1 + (##2 * #6)}%
+%%% }
+%%% \edef\currents{\fpeval{#3 + #5}}
+%%% \edef\currentd{#4}
+%%% \expandafter\xdef\csname #1\endcsname{}
+%%%
+%%% \foreach \n in {1,...,#2} {%
+%%% \edef\currentd{\fpeval{\currentd * #6}}
+%%% \edef\currents{\fpeval{\currents + \currentd}}
+%%% \ifnum \n = 1%
+%%%% \edef\tooutput{\calculate{\n}}%
+%%% \edef\tooutput{\currents}%
+%%%% \edef\tooutput{\calculates{\currents}{\currentd}}%
+%%% \else%
+%%%% \edef\tooutput{\csname #1\endcsname,\calculate{\n}}%
+%%% \edef\tooutput{\csname #1\endcsname,\currents}%
+%%%% \edef\tooutput{\csname #1\endcsname,\calculate{\n}}%
+%%% \fi%
+%%% \expandafter\xdef\csname #1\endcsname{\tooutput}%
+%%% }%
+%%%}
+
+% #1 : output var
+% #2 : n
+% #3 : x
+% #4 : d
+% #5 : d_init
+% #6 : smoothness
+% #7 : direction (+ | -)
+\newcommand{\createlines}[7] {%
+ \tikzmath{
+ real \d, \s;
+ \d = #4;
+ \s = #3 #7 #5;
+ let \ret =;
+ for \i in {1,...,#2} {
+ \d = \d * #6;
+ \s = \s #7 \d;
+ if \i == 1
+ then { \ret = \s; }
+ else { \ret = "\ret,\s"; };
+ };
+ }
+ \expandafter\xdef\csname #1\endcsname{\ret}
+}
+
+%\createlines{linus}{3}{-4}
+%\createlines{linus}{3}{-4}{0.6}{0.3}{2}
+\createlines{lines}{7}{-4}{0.6}{0.3}{1.1}{+}
+
+\edef\orig{\fpeval{-4+0.3}}
+
+\foreach \n [expand list=true, count=\i] in {\lines} {
+ \drawline[green]{\n};
+% \draw [line width=0.5pt, red] (\ox,\oy)
+% ++(\n,-1) -- +(0,2) node[above] {\n};
+
+% \draw [line width=0.5pt] (\ox,\oy) ++(-4,0) ++(0.3,0)
+ \draw [line width=0.5pt] (\ox,\oy) ++(\orig,0)
+ ++(0,1) -- +(0,0.5);
+ \ifnum \i = 4
+ \draw [line width=0.5pt] (\ox,\oy)
+ ++(\n,1) -- +(0,0.5);
+ \draw [line width=0.5pt] (\ox,\oy) ++(0,1.5)
+ +(\orig,0)
+ .. controls +(0,0.3) and +(0,0.3) ..
+ +(\n,0)
+ +(\fpeval{(\orig+\n)/2},0.2) node[above] {$z$}
+ +(\fpeval{(\orig+\n)/2},0.4) node[above] {$lz=\i$};
+ \fi
+}
+
+\edef\dmax{1}
+
+\foreach \n [
+ expand list=true,
+ count=\i,
+ remember=\n as \lastn (initially \fpeval{-4+0.3})
+] in {\lines} {
+ \draw [line width=0.5pt] (\ox,\oy) ++(0,1)
+ +(\lastn,0) .. controls +(0,0.2) and +(0,0.2) .. +(\n,0)
+ +(\fpeval{(\lastn+\n)/2},0.2) node[above] {$d\cdot f$$^\i$};
+
+ \pgfmathparse{\dmax < \fpeval{abs(\lastn-\n)}}
+ \ifnum \pgfmathresult>0
+ \draw [line width=0.5pt] (\ox,\oy) ++(0,1)
+ ++(\lastn,0) .. controls +(0,-0.2) and +(0,-0.2) .. +(\dmax,0)
+ +(\fpeval{(\dmax)/2},-0.2) node[below] {$d_{max}$};
+ \fi
+}
+
+
+
+% ANNOTATIONS
+\draw [line width=0.5pt] (\ox,\oy) ++(-4,1)
+ +(-0.3,0) .. controls +(0,0.2) and +(0,0.2) .. +(0.3,0)
+ +(0,0.2) node[above] {$d$};
+
+\draw [line width=0.5pt] (\ox,\oy) ++(-4,-1)
+ +(0,0) .. controls +(0,-0.1) and +(0,-0.1) .. +(0.3,0)
+ +(0.25,-0.1) node[below] {$d_{init}$};
+
+\draw [line width=0.5pt] (\ox,\oy) ++(0,-1)
+ +(-3.7,0) .. controls +(0,-0.2) and +(0,-0.2) .. +(0,0)
+ +(-2,-0.2) node[below] {$s$};
+
+%\draw [line width=0.5pt, yellow] (\ox,\oy) ++(0,-1)
+% +(-3.7,0) to [bend right=30] +(0,0)
+% +(-2,-0.2) node[below] {s};
+
+\draw [line width=0.5pt] (\ox,\oy) ++(0,-1.5)
+ +(-4,0) .. controls +(0,-0.2) and +(0,-0.2) .. +(0,0)
+ +(-2,-0.2) node[below] {$h$};
+
+
+\end{tikzpicture}
+\end{document}