diff --git a/bib.bib b/bib.bib index 3647a8d..09f32a9 100644 --- a/bib.bib +++ b/bib.bib @@ -228,3 +228,24 @@ url={https://github.com/motiejus/wm}, urldate={2021-05-19}, } + +@online{openstreetmap, + author={OpenStreetMap contributors}, + title={Project that creates and distributes free world's geographic data}, + url={https://www.openstreetmap.org}, + urldate={2021-05-15}, + } + +@online{nzt, + author={Nacionalinė Žemės Tarnyba Prie Žemės Ūkio Ministerijos}, + title={Atviri Duomenys}, + url={http://nzt.lt/go.php/lit/Atviri-duomenys}, + urldate={2021-05-15}, + } + +@online{openmapwm, + author={Tomas Straupis}, + title={Test harness for Wang--M{\"u}ller algorithm}, + url={https://dev.openmap.lt/webgl/wm.html}, + urldate={2021-05-15}, +} diff --git a/mj-msc.tex b/mj-msc.tex index d6302b2..2f775ba 100644 --- a/mj-msc.tex +++ b/mj-msc.tex @@ -909,11 +909,20 @@ When debug mode is turned off (that is, \textsc{dbgname} is left unspecified), \subsection{Merging pieces of the river into one} -% TODO +Example river geometries were sourced from OpenStreetMap\cite{openstreetmap} +and NŽT\cite{nzt}. Rivers in both data sources are stored in shorter line +segments, and multiple segments (usually hundreds or thousands for significant +rivers) define one full river. While it is convenient to store and edit, these +segments are not explicitly related to each other. This poses a problem for +simplification algorithms, which manipulate on full linear features at a time: +full river geometries, but not their parts. -NOTE: explain how different river segments are merged into a single line. This -is not explained in the {\WM} paper, but is a necessary prerequisite. This is -implemented in \textsc{aggregate-rivers.sql}. +Since these rivers do not have an explicit relationship to connect them +together, they were connected using heuristics: if two line segments share a +name and are within 500 meters from each other, then they form a single river. +For all line simplification algorithms, all rivers need to be combined, and +this way proved to be reasonably effective. Source code for this operation can +be found in listings~\onpage{lst:aggregate-rivers.sql}. \subsection{Bend scaling and dimensions} \label{sec:bend-scaling-and-dimensions} @@ -1002,7 +1011,7 @@ but with bends colored as polygons: each color is a distinctive bend. \centering \includegraphics[width=\textwidth]{fig8-definition-of-a-bend} - \caption{similar to figure 8 in \cite{wang1998line}: detected bends are + \caption{Similar to figure 8 in \cite{wang1998line}: detected bends are highlighted.} \label{fig:fig8-definition-of-a-bend} @@ -1031,7 +1040,7 @@ when a single vertex is moved outwards the end of the bend. \includegraphics[width=\textwidth]{fig5-gentle-inflection-after} \caption{After applying the inflection rule.} \end{subfigure} - \caption{figure 5 in \cite{wang1998line}: gentle inflections at the ends of + \caption{Figure 5 in \cite{wang1998line}: gentle inflections at the ends of the bend.} \label{fig:fig5-gentle-inflection} \end{figure} @@ -1347,7 +1356,8 @@ isolated bends are exaggerated, and some small bends are removed. \label{fig:salvis-wm-220-250k} \end{figure} -% TODO: expand +% TODO: expand section and remove clear-page. +\clearpage \subsection{Generalization result comparison with national spatial data sets} @@ -1355,9 +1365,28 @@ isolated bends are exaggerated, and some small bends are removed. \subsection{Testing results online} -% TODO: [Siūlau įdėti nuorodą į web app, kur būtų galima interaktyviai -% pastestuoti rezultatus. Jeigu planuotum dėti, tuomet galima nedidelį poskyrį -% pridėti Testing Results] +An on-line tool\cite{openmapwm} has been developed to test incoming parameters +to {\WM} algorithm. A user should select a river of interest, enter the +\textsc{dhalfcircle} parameter and click "Submit". The simplified line feature +will be overlaid on top of the map. + +Figure~\ref{fig:openmap-wm-good} illustrates the end result that looks +reasonably well. Figure~\ref{fig:openmap-wm-bad} illustrates that the algorithm +produces poorly simplified results for some geometries. + +\begin{figure}[ht] + \centering + \includegraphics[width=\textwidth]{openmap-wm-good.png} + \caption{Example on-line test tool for {\WM} algorithm.} + \label{fig:openmap-wm-good} +\end{figure} + +\begin{figure}[ht] + \centering + \includegraphics[width=.5\textwidth]{openmap-wm-bad.png} + \caption{Another example from the on-line test tool.} + \label{fig:openmap-wm-bad} +\end{figure} \section{Conclusions} \label{sec:conclusions} diff --git a/openmap-wm-bad.png b/openmap-wm-bad.png new file mode 100644 index 0000000..9f73bf9 Binary files /dev/null and b/openmap-wm-bad.png differ diff --git a/openmap-wm-good.png b/openmap-wm-good.png new file mode 100644 index 0000000..287fd53 Binary files /dev/null and b/openmap-wm-good.png differ diff --git a/vars.awk b/vars.awk index 3dfd8dc..f979a82 100644 --- a/vars.awk +++ b/vars.awk @@ -10,7 +10,7 @@ BEGIN { FS="[(); ]" } x2 += 1; d2 = sprintf("\\newcommand{\\isolationThreshold}{%.1f}",$7); } -/scale constant float default / { +/scale2 constant float default / { x3 += 1; d3 = sprintf("\\newcommand{\\exaggerationEnthusiasm}{%.1f}",$7); } diff --git a/wm.sql b/wm.sql index 6c215e3..09da3ee 100644 --- a/wm.sql +++ b/wm.sql @@ -417,7 +417,9 @@ begin return st_split(st_snap(input, blade, 0.00000001), blade); end $$ language plpgsql; - +-- wm_exaggerate_bend2 is the second version of bend exaggeration. Uses +-- non-linear interpolation by point azimuth. Slower, but produces nicer +-- exaggerated geometries. drop function if exists wm_exaggerate_bend2; create function wm_exaggerate_bend2( INOUT bend geometry, @@ -425,7 +427,7 @@ create function wm_exaggerate_bend2( desired_size float ) as $$ declare - scale constant float default 1.2; -- exaggeration enthusiasm + scale2 constant float default 1.2; -- exaggeration enthusiasm midpoint geometry; -- midpoint of the baseline points geometry[]; startazimuth float; @@ -459,7 +461,7 @@ begin if diffazimuth > 90 then diffazimuth = 180 - diffazimuth; end if; - sss = ((scale-1) * (diffazimuth / 90)^0.5); + sss = ((scale2-1) * (diffazimuth / 90)^0.5); point = st_transform( st_project( st_transform(point, 4326)::geography, @@ -472,6 +474,60 @@ begin end loop; end $$ language plpgsql; +-- wm_exaggerate_bend exaggerates a given bend. Uses naive linear +-- interpolation. Faster than wm_exaggerate_bend2, but result visually looks +-- worse. +drop function if exists wm_exaggerate_bend; +create function wm_exaggerate_bend( + INOUT bend geometry, + size float, + desired_size float +) as $$ +declare + scale constant float default 1.2; -- exaggeration enthusiasm + midpoint geometry; -- midpoint of the baseline + splitbend geometry; -- bend split across its half + bendm geometry; -- bend with coefficients to prolong the lines + points geometry[]; +begin + if size = 0 then + raise 'invalid input: zero-area bend'; + end if; + midpoint = st_lineinterpolatepoint(st_makeline( + st_pointn(bend, 1), + st_pointn(bend, -1) + ), .5); + + while size < desired_size loop + splitbend = wm_st_split(bend, st_lineinterpolatepoint(bend, .5)); + -- Convert bend to LINESTRINGM, where M is the fraction by how + -- much the point will be prolonged: + -- 1. draw a line between midpoint and the point on the bend. + -- 2. multiply the line length by M. Midpoint stays intact. + -- 3. the new set of lines form a new bend. + -- Uses linear interpolation; can be updated to gaussian or similar; + -- then interpolate manually instead of relying on st_addmeasure. + bendm = st_collect( + st_addmeasure(st_geometryn(splitbend, 1), 1, scale), + st_addmeasure(st_geometryn(splitbend, 2), scale, 1) + ); + + points = array(( + select st_scale( + st_makepoint(st_x(geom), st_y(geom)), + st_makepoint(st_m(geom), st_m(geom)), + midpoint + ) + from st_dumppoints(bendm) + order by path[1], path[2] + )); + + bend = st_setsrid(st_makeline(points), st_srid(bend)); + size = wm_adjsize(bend); + end loop; +end $$ language plpgsql; + + -- wm_adjsize calculates adjusted size for a polygon. Can return 0. drop function if exists wm_adjsize; create function wm_adjsize(bend geometry, OUT adjsize float) as $$