类似谷歌地图的全国热图

类似谷歌地图的全国热图

有没有办法制作类似Google 地图热图/标记集群

我知道我可以放入图片,但我只是想确认一下 LaTeX 中是否有其他选择。

在此处输入图片描述

答案1

这里有一个名为 的命令\heatmark,用于在 中生成tikzpicture类似于您链接到的地图上的标记;代码可能需要改进(编辑:我稍微修改了一下原始代码)。

\heatmark命令接受 4 个参数:

  1. 位置,形式为x,y
  2. 内盘的半径,
  3. 内盘的颜色,
  4. 要写入磁盘中心的文本。

有关如何在 TikZ 中在外部图片(例如地图)上绘图的更多详细信息,请参阅使用 TikZ 在图像上绘图

裸地图,仅标记

地图+标记

\documentclass{article}

\usepackage[usenames,dvipsnames]{xcolor}
\usepackage{tikz}

\newcommand\heatmark[4]{
    \def\r{#2}                                  % radius of disk
    \def\d{.1*\r}                               % radius gap between arc segments
    \def\angleoffset{10}                        % half angular gap between arc segments
    \def\e{.3*\r}                               % radial width of arc segments
    \def\mycolor{#3}                            % color of disk
    \pgfmathtruncatemacro\n{3}                  % number of arc segments outside disk

    \begin{scope}[shift={(#1)}]                 % shift to desired position
    \fill[\mycolor] circle (\r);                % draw inner disk
    \foreach \onethirdangle in {0,120,240}{%    % rotational symmetry
      \begin{scope}[rotate=\onethirdangle]
        \foreach \i in {1,...,\n}{%    

          \pgfmathsetmacro\opac{1.1-\i/\n}
          \def\Aone{30+\angleoffset}
          \def\Atwo{150-\angleoffset}
          \def\Rone{\r+\i*\d+(\i-1)*\e}
          \def\Rtwo{\Rone+\e}

          \fill[\mycolor,opacity=\opac]                     % draw one arc segment
            ({(\Rone)*cos(\Aone)},{(\Rone)*sin(\Atwo)})
                arc ({\Aone}:{\Atwo}:{\Rone})               % arc 1 
             -- ++({\e*cos(\Atwo)},{\e*sin(\Atwo)})         % straight line 1
             -- ({(\Rtwo)*cos(\Atwo)},{(\Rtwo)*sin(\Aone)})
                arc ({\Atwo}:{\Aone}:{\Rtwo} )              % arc 2
             -- cycle;                                      % straight line 2
        }
      \end{scope}
    }
    \node[white] {\small #4};
    \end{scope}
}

\begin{document}

Original map:\\
\includegraphics[width=0.9\textwidth]{western_europe.png}

Some markers on their own:\\
\begin{tikzpicture}
    \heatmark{0,0}{.5}{RubineRed}{300}
    \heatmark{2,0}{.3}{YellowOrange!80}{50}
    \heatmark{4,0}{.3}{Cerulean}{50}
\end{tikzpicture}

\newpage
Original map with some markers on it:\\
\begin{tikzpicture}
    \node[anchor=south west,inner sep=0] (image) at (0,0)
        {\includegraphics[width=0.9\textwidth]{western_europe.png}};
    \begin{scope}[x={(image.south east)},y={(image.north west)}]
        \def\Paris{.45,.5}
        \def\Madrid{.25,.2}
        \def\Rome{.8,.25}
        \heatmark{\Rome}{.5cm}{RubineRed}{300}
        \heatmark{\Madrid}{.25cm}{YellowOrange!80}{35}
        \heatmark{\Paris}{.3cm}{Cerulean}{50}
    \end{scope}
\end{tikzpicture}

\end{document}

答案2

代码

\documentclass[tikz,convert=false]{standalone}
\makeatletter
\tikzset{
    heat arc width/.initial=+4pt,
    heat arc sep/.initial=+1pt,
    heat arc rings/.initial=3,
    heat arcs/.initial=3,
    heat arc sep angle/.initial=20,
    heat opacity high/.initial=.8,
    heat opacity low/.initial=.2,
    heat rotate/.initial=90,
}
\pgfdeclareshape{heat}
%
% Draws a circle around the text
%
{
  \savedanchor\centerpoint{%
    \pgf@x=.5\wd\pgfnodeparttextbox%
    \pgf@y=.5\ht\pgfnodeparttextbox%
    \advance\pgf@y by-.5\dp\pgfnodeparttextbox%
  }

  \saveddimen\innerradius{%
    % 
    % Caculate ``height radius''
    % 
    \pgf@ya=.5\ht\pgfnodeparttextbox%
    \advance\pgf@ya by.5\dp\pgfnodeparttextbox%
    \pgfmathsetlength\pgf@yb{\pgfkeysvalueof{/pgf/inner ysep}}%
    \advance\pgf@ya by\pgf@yb%
    % 
    % Caculate ``width radius''
    % 
    \pgf@xa=.5\wd\pgfnodeparttextbox%
    \pgfmathsetlength\pgf@xb{\pgfkeysvalueof{/pgf/inner xsep}}%
    \advance\pgf@xa by\pgf@xb%
    % 
    % Calculate length of radius vector:
    % 
    \pgf@process{\pgfpointnormalised{\pgfqpoint{\pgf@xa}{\pgf@ya}}}%
    \ifdim\pgf@x>\pgf@y%
        \c@pgf@counta=\pgf@x%
        \ifnum\c@pgf@counta=0\relax%
        \else%
          \divide\c@pgf@counta by 255\relax%
          \pgf@xa=16\pgf@xa\relax%
          \divide\pgf@xa by\c@pgf@counta%
          \pgf@xa=16\pgf@xa\relax%
        \fi%
      \else%
        \c@pgf@counta=\pgf@y%
        \ifnum\c@pgf@counta=0\relax%
        \else%
          \divide\c@pgf@counta by 255\relax%
          \pgf@ya=16\pgf@ya\relax%
          \divide\pgf@ya by\c@pgf@counta%
          \pgf@xa=16\pgf@ya\relax%
        \fi%
    \fi%
    \pgf@x=\pgf@xa%
    % 
    % If necessary, adjust radius so that the size requirements are
    % met: 
    % 
    \pgfmathsetlength{\pgf@xb}{\pgfkeysvalueof{/pgf/minimum width}}%  
    \pgfmathsetlength{\pgf@yb}{\pgfkeysvalueof{/pgf/minimum height}}%  
    \ifdim\pgf@x<.5\pgf@xb%
        \pgf@x=.5\pgf@xb%
    \fi%
    \ifdim\pgf@x<.5\pgf@yb%
        \pgf@x=.5\pgf@yb%
    \fi%
  }%

  \saveddimen\radius{%
    \pgfmathsetlength{\pgf@xb}{\pgfkeysvalueof{/pgf/outer xsep}}%  
    \pgfmathsetlength{\pgf@yb}{\pgfkeysvalueof{/pgf/outer ysep}}%  
    \ifdim\pgf@xb<\pgf@yb%
      \advance\pgf@x by\pgf@yb%
    \else%
      \advance\pgf@x by\pgf@xb%
    \fi%
    \pgfmathsetcount\c@pgf@counta{\pgfkeysvalueof{/tikz/heat arc rings}}%
    \pgfmathsetlength\pgf@xa{\pgfkeysvalueof{/tikz/heat arc width}+\pgfkeysvalueof{/tikz/heat arc sep}}%
    \multiply\pgf@xa\c@pgf@counta
    \advance\pgf@x\pgf@xa
  }%
  %
  % Anchors
  % 
  \inheritanchor[from=circle]{north}
  \inheritanchor[from=circle]{north west}
  \inheritanchor[from=circle]{north east}
  \inheritanchor[from=circle]{center}
  \inheritanchor[from=circle]{west}
  \inheritanchor[from=circle]{east}
  \inheritanchor[from=circle]{mid}
  \inheritanchor[from=circle]{mid west}
  \inheritanchor[from=circle]{mid east}
  \inheritanchor[from=circle]{base}
  \inheritanchor[from=circle]{base west}
  \inheritanchor[from=circle]{base east}
  \inheritanchor[from=circle]{south}
  \inheritanchor[from=circle]{south west}
  \inheritanchor[from=circle]{south east}
  \inheritanchorborder[from=circle]
  %
  % Background path
  %
  \backgroundpath{
    \pgfutil@tempdima=\innerradius%
    \pgfpathcircle{\centerpoint}{\pgfutil@tempdima}%
  }%
  %
  %
  %
  \behindbackgroundpath{%
    \pgfmathsetcount\c@pgf@counta{\pgfkeysvalueof{/tikz/heat arc rings}}%     heat arc rings
    \pgfmathsetcount\c@pgf@countb{\pgfkeysvalueof{/tikz/heat arcs}}%          heat arcs
    \pgfmathsetlength\pgf@xa{\pgfkeysvalueof{/tikz/heat arc width}}%          heat arc width
    \pgfmathsetlength\pgf@xb{\pgfkeysvalueof{/tikz/heat arc sep}}%            heat arc sep
    \pgfmathsetmacro\pgf@tempa{\pgfkeysvalueof{/tikz/heat arc sep angle}}%    heat arc sep angle
    \pgfmathsetmacro\pgf@tempb{(360-\c@pgf@countb*\pgf@tempa)/\c@pgf@countb}% heat arc
    \pgfmathsetmacro\pgf@tempc{\pgfkeysvalueof{/tikz/heat rotate}}%           heat rotate
    %
    \pgfmathsetmacro\pgf@tempd{\pgfkeysvalueof{/tikz/heat opacity high}}%     heat opacity high
    \ifnum\c@pgf@counta=1
      \def\qrr@heat@opacity@seps{0}%
    \else
      \pgfmathsetmacro\qrr@heat@opacity@seps
      {(\pgf@tempd-\pgfkeysvalueof{/tikz/heat opacity low})%
         /(\c@pgf@counta-1)}%
    \fi
    \pgfutil@tempcnta\z@
    \pgfutil@tempcntb\z@
    \pgf@ya\innerradius\relax
    \pgftransformshift{\centerpoint}
    \pgfutil@loop % ring loop
      \advance\pgf@ya\pgf@xb % current radius + heat arc sep
      \pgf@yb\pgf@ya         
      \advance\pgf@yb\pgf@xa % current radius + heat arc sep + heat arc width
      \pgfsetfillopacity{\pgf@tempd}%
      \begingroup
        \edef\pgf@marshal{\noexpand\tikzset{heat ring \number\numexpr\pgfutil@tempcnta+1\relax/.try}}%
        \pgf@marshal
        \tikz@options
        {%
        \pgfutil@loop
          \pgfmathsetmacro\qrr@start@angle{\[email protected]*\pgf@tempb+\pgfutil@tempcntb*(360/\c@pgf@countb)}%
          % path
          \begingroup
            \edef\pgf@marshal{\noexpand\tikzset{heat arc \number\numexpr\pgfutil@tempcntb+1\relax/.try}%
                              \noexpand\tikzset{heat arc \number\numexpr\pgfutil@tempcnta+1\relax-\number\numexpr\pgfutil@tempcntb+1\relax/.try}}%
            \pgf@marshal
            \tikz@options
            \pgfpathmoveto{\pgfpointpolar{\qrr@start@angle}{\pgf@ya}}%
            \pgfpatharc{\qrr@start@angle}{\qrr@start@angle+\pgf@tempb}{\pgf@ya}%
            \pgfpathlineto{\pgfpointpolar{\qrr@start@angle+\pgf@tempb}{\pgf@yb}}%
            \pgfpatharc{\qrr@start@angle+\pgf@tempb}{\qrr@start@angle}{\pgf@yb}%
            \pgfpathclose
            \pgfusepathqfill
          \endgroup
          \advance\pgfutil@tempcntb\@ne
          \ifnum\pgfutil@tempcntb<\c@pgf@countb
        \pgfutil@repeat
        }%
      \endgroup
      \advance\pgfutil@tempcnta\@ne
      \ifnum\pgfutil@tempcnta<\c@pgf@counta
        \pgf@ya\pgf@yb
        \pgfmathsetmacro\pgf@tempd{\pgf@tempd-\qrr@heat@opacity@seps}%
    \pgfutil@repeat
  }
}
\tikzset{every heat node/.append style={
  outer sep={+\z@},
  draw=none
  }}
\makeatother
\tikzset{radius=.5pt}
\begin{document}
    \tikz[
      heat ring 1/.append style={green},
      heat arc 1/.append style={blue},
      heat arc 2-2/.append style={yellow!70!black}
    ] {
        \node[heat, fill=red] (n) {100};
        \fill (n.west) circle[]
              (n.east) circle[]
              (n.north) circle[]
              (n.south) circle[];
            \useasboundingbox ([yshift=-2mm]n.south) ([xshift=-2mm]n.west) ([yshift=2mm]n.north) ([xshift=2mm]n.east);
    }

    \foreach \sep in {0,10,...,120}{%
        \tikz{
            \node[heat arc sep angle=\sep, heat, fill=red, text=white, minimum size=1cm] (n) {\sep};
            \fill (n.west) circle[] 
                  (n.east) circle[] 
                  (n.north) circle[]
                  (n.south) circle[];
            \useasboundingbox ([yshift=-2mm]n.south) ([xshift=-2mm]n.west) ([yshift=2mm]n.north) ([xshift=2mm]n.east);
        }%
    }%

    \foreach \rot in {0,10,...,359}{%
        \tikz{
            \node[heat rotate=\rot, heat, fill=green, minimum size=1cm] (n) {\rot};
            \fill (n.west) circle[] 
                  (n.east) circle[] 
                  (n.north) circle[]
                  (n.south) circle[];
            \useasboundingbox ([yshift=-2mm]n.south) ([xshift=-2mm]n.west) ([yshift=2mm]n.north) ([xshift=2mm]n.east);
        }%
    }%

    \foreach \arcs in {1,...,10}{%
        \tikz{
            \node[heat arcs=\arcs, heat, fill=blue, text=white, minimum size=1cm] (n) {\arcs};
            \fill (n.west) circle[] 
                  (n.east) circle[] 
                  (n.north) circle[]
                  (n.south) circle[];
            \useasboundingbox ([yshift=-2mm]n.south) ([xshift=-2mm]n.west) ([yshift=2mm]n.north) ([xshift=2mm]n.east);
        }%
    }%

    \foreach \arcs in {1,...,10,9,8,...,2}{%
        \tikz{
            \node[heat arc rings=\arcs, heat, fill=yellow!50!black, minimum size=1cm] (n) {\arcs};
            \fill (n.west) circle[] 
                  (n.east) circle[] 
                  (n.north) circle[]
                  (n.south) circle[];
            \useasboundingbox ([yshift=-2mm]n.south) ([xshift=-2mm]n.west) ([yshift=2mm]n.north) ([xshift=2mm]n.east);
        }%
    }%
\end{document}

输出

(最后一个确实改变了它的整体尺寸。)

在此处输入图片描述

在此处输入图片描述 在此处输入图片描述

在此处输入图片描述 在此处输入图片描述

相关内容