Skip to content

Commit

Permalink
Fix for mindmap connection bar glitches
Browse files Browse the repository at this point in the history
When the distance between two concepts is at least the sum of the concepts' radii, the connection bar is constructed as expected with initial, bar, and final portions.  There is a visual glitch due to abutting filled path segments on certain anti-aliasing PDF rasterizers, including the one built into macOS, but that could be excused because the apparent gap is truly zero-width and a (sane) printer driver would not produce a white line.  However, there is a more serious visual glitch when the distance between two concepts is less than the sum of the concepts' radii (I will reply to this thread with images in a moment).  In that case, the connection bar path becomes self-intersecting, and the even-odd inclusion test results in unfilled wedges.

This patch unifies the three path segments (initial, bar, and final) into a single continuous filled path segment.  It alters the logic which computes the length of the initial and final flares, proportionally reducing them from their nominal values (of one-half the abutted circle radius) in the case where the distance between concept circles would be too small to fit this shape.
  • Loading branch information
piannucci authored Jul 1, 2020
1 parent a9818b1 commit d2eae0a
Showing 1 changed file with 53 additions and 38 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -17,72 +17,63 @@
%
% Parameters: start radius, end radius, amplitude, angle

\newdimen\pgf@lib@mm@flarelength
\pgfdeclaredecoration{circle connection bar}{initial}
{%
\state{initial}[width=0pt,next state=bar]
\state{initial}[width=0pt,next state=final]
{
{
\pgftransformxshift{-\pgfkeysvalueof{/pgf/decoration/start radius}}%
\pgfpathmoveto{\pgfpointpolar{\pgfdecorationsegmentangle}{\pgfkeysvalueof{/pgf/decoration/start radius}}}
\pgfpatharc{\pgfdecorationsegmentangle}{-\pgfdecorationsegmentangle}{\pgfkeysvalueof{/pgf/decoration/start radius}}
\pgfutil@tempcnta=-\pgfdecorationsegmentangle\relax
\advance\pgfutil@tempcnta by90\relax
\pgfmathsetlength\pgfutil@tempdima{\pgfkeysvalueof{/pgf/decoration/start radius}}
\pgfmathsetlength\pgfutil@tempdimb{\pgfdecorationsegmentamplitude}
\pgfpathcurveto
{\pgfpointadd
{\pgfpointpolar{-\pgfdecorationsegmentangle}{\pgfkeysvalueof{/pgf/decoration/start radius}}}
{\pgfpointpolar{\the\pgfutil@tempcnta}{.25\pgfutil@tempdima}}}
{\pgfqpoint{1.25\pgfutil@tempdima}{-.5\pgfutil@tempdimb}}
{\pgfqpoint{1.5\pgfutil@tempdima}{-.5\pgfutil@tempdimb}}
\pgfpathlineto{\pgfpoint{1.5\pgfutil@tempdima}{.5\pgfutil@tempdimb}}
\pgfmathsetlength\pgf@lib@mm@flarelength{\pgfkeysvalueof{/pgf/decoration/start flare length}}
\pgfpathmoveto{\pgfpoint{\pgfutil@tempdima+1.0\pgf@lib@mm@flarelength}{.5\pgfutil@tempdimb}}
\pgfutil@tempcnta=\pgfdecorationsegmentangle\relax
\advance\pgfutil@tempcnta by-90\relax
\pgfpathcurveto
{\pgfpoint{1.25\pgfutil@tempdima}{.5\pgfutil@tempdimb}}
{\pgfpoint{\pgfutil@tempdima+0.5\pgf@lib@mm@flarelength}{.5\pgfutil@tempdimb}}
{\pgfpointadd
{\pgfpointpolar{\pgfdecorationsegmentangle}{\pgfkeysvalueof{/pgf/decoration/start radius}}}
{\pgfpointpolar{\the\pgfutil@tempcnta}{.25\pgfutil@tempdima}}}
{\pgfpointpolar{\pgfdecorationsegmentangle}{\pgfkeysvalueof{/pgf/decoration/start radius}}}
\pgfpathclose
\pgfpathlineto{\pgfpointpolar{\pgfdecorationsegmentangle}{\pgfkeysvalueof{/pgf/decoration/start radius}}}
\pgfpatharc{\pgfdecorationsegmentangle}{-\pgfdecorationsegmentangle}{\pgfkeysvalueof{/pgf/decoration/start radius}}
\pgfutil@tempcnta=-\pgfdecorationsegmentangle\relax
\advance\pgfutil@tempcnta by90\relax
\pgfpathcurveto
{\pgfpointadd
{\pgfpointpolar{-\pgfdecorationsegmentangle}{\pgfkeysvalueof{/pgf/decoration/start radius}}}
{\pgfpointpolar{\the\pgfutil@tempcnta}{.25\pgfutil@tempdima}}}
{\pgfpoint{\pgfutil@tempdima+0.5\pgf@lib@mm@flarelength}{-.5\pgfutil@tempdimb}}
{\pgfpoint{\pgfutil@tempdima+1.0\pgf@lib@mm@flarelength}{-.5\pgfutil@tempdimb}}
}
}%
\state{bar}[width=0pt,next state=end]
{
\pgfmathsetlength\pgfutil@tempdima{\pgfkeysvalueof{/pgf/decoration/start radius}}%
\pgfmathsetlength\pgfutil@tempdimb{\pgfkeysvalueof{/pgf/decoration/end radius}}%
\pgfmathsetlength\pgf@xc{\pgfdecorationsegmentamplitude}%
\pgfpathrectangle
{\pgfqpoint{.5\pgfutil@tempdima}{-.5\pgf@xc}}
{\pgfpoint{\pgfdecoratedremainingdistance+-.5\pgfutil@tempdimb+-.5\pgfutil@tempdima}{\pgf@xc}}
}%
\state{end}[width=0pt,next state=final]
{
{
\pgftransformxshift{\pgfdecoratedremainingdistance}%
\pgftransformxscale{-1}%
\pgftransformyscale{-1}%
\pgftransformxshift{-\pgfkeysvalueof{/pgf/decoration/end radius}}%
\pgfpathmoveto{\pgfpointpolar{\pgfdecorationsegmentangle}{\pgfkeysvalueof{/pgf/decoration/end radius}}}
\pgfpatharc{\pgfdecorationsegmentangle}{-\pgfdecorationsegmentangle}{\pgfkeysvalueof{/pgf/decoration/end radius}}
\pgfutil@tempcnta=-\pgfdecorationsegmentangle\relax
\advance\pgfutil@tempcnta by90\relax
\pgfmathsetlength\pgfutil@tempdima{\pgfkeysvalueof{/pgf/decoration/end radius}}
\pgfmathsetlength\pgfutil@tempdimb{\pgfdecorationsegmentamplitude}%
\pgfpathcurveto
{\pgfpointadd
{\pgfpointpolar{-\pgfdecorationsegmentangle}{\pgfkeysvalueof{/pgf/decoration/end radius}}}
{\pgfpointpolar{\the\pgfutil@tempcnta}{.25\pgfutil@tempdima}}}
{\pgfqpoint{1.25\pgfutil@tempdima}{-.5\pgfutil@tempdimb}}
{\pgfqpoint{1.5\pgfutil@tempdima}{-.5\pgfutil@tempdimb}}
\pgfpathlineto{\pgfpoint{1.5\pgfutil@tempdima}{.5\pgfutil@tempdimb}}
\pgfmathsetlength\pgf@lib@mm@flarelength{\pgfkeysvalueof{/pgf/decoration/end flare length}}
\pgfpathlineto{\pgfpoint{\pgfutil@tempdima+1.0\pgf@lib@mm@flarelength}{.5\pgfutil@tempdimb}}
\pgfutil@tempcnta=\pgfdecorationsegmentangle\relax
\advance\pgfutil@tempcnta by-90\relax
\pgfpathcurveto
{\pgfpoint{1.25\pgfutil@tempdima}{.5\pgfutil@tempdimb}}
{\pgfpoint{\pgfutil@tempdima+0.5\pgf@lib@mm@flarelength}{.5\pgfutil@tempdimb}}
{\pgfpointadd
{\pgfpointpolar{\pgfdecorationsegmentangle}{\pgfkeysvalueof{/pgf/decoration/end radius}}}
{\pgfpointpolar{\the\pgfutil@tempcnta}{.25\pgfutil@tempdima}}}
{\pgfpointpolar{\pgfdecorationsegmentangle}{\pgfkeysvalueof{/pgf/decoration/end radius}}}
\pgfpathlineto{\pgfpointpolar{\pgfdecorationsegmentangle}{\pgfkeysvalueof{/pgf/decoration/end radius}}}
\pgfpatharc{\pgfdecorationsegmentangle}{-\pgfdecorationsegmentangle}{\pgfkeysvalueof{/pgf/decoration/end radius}}
\pgfutil@tempcnta=-\pgfdecorationsegmentangle\relax
\advance\pgfutil@tempcnta by90\relax
\pgfpathcurveto
{\pgfpointadd
{\pgfpointpolar{-\pgfdecorationsegmentangle}{\pgfkeysvalueof{/pgf/decoration/end radius}}}
{\pgfpointpolar{\the\pgfutil@tempcnta}{.25\pgfutil@tempdima}}}
{\pgfpoint{\pgfutil@tempdima+0.5\pgf@lib@mm@flarelength}{-.5\pgfutil@tempdimb}}
{\pgfpoint{\pgfutil@tempdima+1.0\pgf@lib@mm@flarelength}{-.5\pgfutil@tempdimb}}
\pgfpathclose
}
}%
Expand Down Expand Up @@ -110,17 +101,41 @@
}}%
\tikzset{every circle connection bar/.style={}}%

\pgfkeys{/pgf/decoration/start flare length/.initial=0pt}%
\pgfkeys{/pgf/decoration/end flare length/.initial=0pt}%

\def\tikz@compute@circle@radii{%
\pgf@process{\pgfpointtransformed{\pgfpointanchor{\tikztostart}{center}}}%
\pgf@xa=\pgf@x%
\pgf@process{\pgfpointtransformed{\pgfpointanchor{\tikztostart}{west}}}%
\advance\pgf@xa by-\pgf@x%
\pgfkeys{/pgf/decoration/start radius/.expanded=\the\pgf@xa}%
\pgfutil@tempdima=.5\pgf@xa\relax%
\pgf@process{\pgfpointtransformed{\pgfpointanchor{\tikztotarget}{center}}}%
\pgf@xa=\pgf@x%
\pgf@process{\pgfpointtransformed{\pgfpointanchor{\tikztotarget}{west}}}%
\advance\pgf@xa by-\pgf@x%
\pgfkeys{/pgf/decoration/end radius/.expanded=\the\pgf@xa}%
\advance\pgfutil@tempdima by.5\pgf@xa\relax%
% Now tempdima = .5 start radius + .5 end radius = nominal sum of flare lengths.
\pgfpointdiff{\pgfpointanchor{\tikztostart}{center}}%
{\pgfpointanchor{\tikztotarget}{center}}%
\pgfmathparse{veclen(\the\pgf@x,\the\pgf@y)}%
\pgfmathsetlength\pgfutil@tempdimb{\pgfmathresult}%
\advance\pgfutil@tempdimb by-2\pgfutil@tempdima%
% Now tempdimb = room available for flares.
\ifdim\pgfutil@tempdimb>\pgfutil@tempdima\relax%
\pgfutil@tempdimb=\pgfutil@tempdima\relax%
\fi%
% Now tempdimb = actual sum of flare lengths.
\pgf@xa=\pgfkeysvalueof{/pgf/decoration/start radius}\relax%
\pgf@xa=\dimexpr .5\pgf@xa * \pgfutil@tempdimb / \pgfutil@tempdima\relax%
% start flare length = sum of flare lengths * start radius / sum of radii
\pgfkeys{/pgf/decoration/start flare length/.expanded=\the\pgf@xa}%
\pgf@xa=\pgfkeysvalueof{/pgf/decoration/end radius}\relax%
\pgf@xa=\dimexpr .5\pgf@xa * \pgfutil@tempdimb / \pgfutil@tempdima\relax%
% end flare length = sum of flare lengths * end radius / sum of radii
\pgfkeys{/pgf/decoration/end flare length/.expanded=\the\pgf@xa}%
}%
\def\tikz@compute@segmentamplitude{%
\pgf@x=\pgfkeysvalueof{/pgf/decoration/start radius}\relax%
Expand Down

0 comments on commit d2eae0a

Please sign in to comment.