用于绘制几何图的语言或包

Bri*_*ell 20 language-agnostic math diagram geometry programming-languages

我正在寻找一种语言或现有语言的包,这对指定和绘制几何图表很有帮助.

例如,我想绘制一个六边形网格,其上叠加双三角形网格.现在,我可以坐下来,用一些肘部油脂来手工制作三角形,然后拿出一些会显示这样一个网格的Postscript或SVG.但我想知道是否有任何语言或软件包可以帮助我解决这个问题; 这样可以轻松指定六边形网格,找到中心,并在其上绘制三角形网格.

最简单的方法是什么?

代码示例,表明创建这种几何指定图表是多么容易,将是值得赞赏的.特别是,请说明绘制六边形网格是多么容易; 虽然我可以通过手工绘制所有线条来用任何语言做到这一点,但我对语言或包装很感兴趣,这使得几何图形变得简单明了.

赏金

既然这个问题已经回答了,但得到的答复是更复杂得多,我愿意,我将提供一个赏金谁可以产生最短和最简单的代码,在任何预先存在的语言的人,并使用预先存在的任何包,对绘制一个六边形网格,其双三角形网格叠加在其上面; 如果您将每个六边形的中心连接到每个相邻六边形的中心,则双三角网格是您获得的三角形网格.以Antal S-Z的答案为例; 他的例子完成了这项工作,但我一直在寻找一种能让这个问题更容易的语言.你可以或者产生一个网格,其是大致矩形,在他的实施例(奇数行对齐,并且偶数行对准),或一个在风格六角板(每行向右移动半个十六进制,形成一个菱形); 两者都可以接受.

程序可以采用输入无论是在其中需要的行数和列数,或采取输入指示行和列在命令行上传递的语言中的函数或子程序的形式.它应该以任何标准和通用图形格式产生输出,例如Postscript,PDF,SVG,PNG或PNM ; 输出应包含六角网格和三角形网格,以一些对比色,线宽或线条样式,以使图表清晰.

我正在寻找最简单和最简单的答案,作为一种找到最适合描述这些图表的语言或包的方法; 赏金将用于解决问题的最短程序.这不是代码高尔夫,所以我不会计算字符数或代码行数.如果没有明显的最短答案,那么我将根据令牌数来衡量; 用你的语言有多少令牌来表达这个问题?因此,使用库函数,注释,空格等的可读常量和变量名都可以,因为它们不会增加令牌数.它仍然不是一个完美的度量标准(Lisps会有更多的标记,因为你需要更多的括号来分隔你的算术表达式,而且我'

因此,对于赏金而言,挑战在于创建最短的程序,该程序使用叠加的三角形网格绘制十六进制网格.请发布您的代码,语言链接以及您使用过的所有软件包,如果可能,请提供粗略的令牌计数,以及示例输出图像.现有的答案是你必须击败才能获得资格的标准; 它做的工作,但我想要更短更简单的东西.

为了给我足够的时间来查看答案并奖励赏金,所有答案必须在赏金截止日期前至少24小时提交.我可能会或可能不会考虑在截止日期前24小时内提交的任何答案.

Ant*_*sky 11

我还想推荐PGF/TikZ,但需要注意它是在TeX中.如果您不熟悉TeX编程,可能会有点头疼,因为有一些...特性.(例如,处理杂散空间可能是一种冒险.)但是,如果您愿意进行TeX编程,我强烈推荐它; 即使我不在TeX工作,我经常使用它来绘制数字.此外,它的手册绝对令人惊叹,TeXample画廊有很多很好的例子.

绘制十六进制网格并对其进行三角测量的示例代码如下.我承认它很长,但我认为它真的不是那么糟糕.

\documentclass{article}

\usepackage{tikz}
\usepackage{ifthen}

\usetikzlibrary{calc}
\usetikzlibrary{shapes.geometric}

\tikzset{hexagon/.style={regular polygon, regular polygon sides = 6}}

\newif\ifHexgridTriangulate
\newif\ifHexgridStartShifted
\pgfqkeys{/hexgrid}
         { name/.store in       = \HexgridName
         , xpos/.store in       = \HexgridX
         , ypos/.store in       = \HexgridY
         , rows/.store in       = \HexgridRows
         , cols/.store in       = \HexgridCols
         , size/.code           = {\pgfmathsetmacro{\HexDiameter}{#1}}
         , triangulate/.is if   = HexgridTriangulate
         , start shifted/.is if = HexgridStartShifted }

\tikzset{ every hexgrid hex/.style 2 args   = {draw}
        , every hexgrid triangulator/.style = {}}

\newcommand{\hexgrid}[2][]{
  \pgfqkeys{/hexgrid}{ name  = hexgrid , size = 1cm
                     , xpos  = 0       , ypos = 0
                     , triangulate   = false
                     , start shifted = false
                     ,#2 }

  \ifHexgridStartShifted
    \def\HexShiftModCheck{0}
  \else
    \def\HexShiftModCheck{1}
  \fi

  \begin{scope}[xshift=\HexgridX, yshift=\HexgridY,#1]
    \pgfmathsetmacro{\HexRadius}{\HexDiameter/2}
    \pgfmathsetmacro{\HexSide}{sqrt(3)*\HexRadius/2}
    \pgfmathsetmacro{\HexWidth}{2*\HexSide}

    \tikzset{every node/.style={hexagon, minimum size=\HexDiameter}}

    \foreach \row in {1,...,\HexgridRows} {
      \foreach \col in {1,...,\HexgridCols} {
        \pgfmathsetmacro{\HexX}%
                        {\HexWidth*(  (\col-1)
                                    + (mod(\row,2) == \HexShiftModCheck
                                        ? 0 : .5))}
        \pgfmathsetmacro{\HexY}%
                        {-(\HexRadius + \HexSide/2 + 2*\pgflinewidth)*(\row-1)}
        \node [hexagon, rotate=90, every hexgrid hex = {\row}{\col}]
              (\HexgridName-\row-\col)
              at (\HexX pt ,\HexY pt)
              {} ;
      }
    }

    \ifHexgridTriangulate
      \begin{scope}[every path/.style={every hexgrid triangulator}]
        \foreach \row in {1,...,\HexgridRows} {
          \foreach \col in {1,...,\HexgridCols} {
            % Using \pgfmathsetmacro always includes a decimal point, which
            % breaks \ifnum.
            \pgfmathparse{int(\row-1)}\let\prow\pgfmathresult
            \pgfmathparse{int(\col-1)}\let\pcol\pgfmathresult

            \ifnum\prow>0
              \draw    (\HexgridName-\prow-\col.center)
                    -- (\HexgridName-\row-\col.center) ;
            \fi
            \ifnum\pcol>0
              \draw    (\HexgridName-\row-\pcol.center)
                    -- (\HexgridName-\row-\col.center) ;
            \fi
            \ifnum\prow>0\ifnum\pcol>0
              \pgfmathparse{mod(\prow,2) == \HexShiftModCheck}
              \ifnum\pgfmathresult=1
                \draw    (\HexgridName-\prow-\col.center)
                      -- (\HexgridName-\row-\pcol.center) ;
              \else
                \draw    (\HexgridName-\prow-\pcol.center)
                      -- (\HexgridName-\row-\col.center) ;
              \fi
            \fi\fi
          }
        }
      \end{scope}
    \fi
  \end{scope}
}

\begin{document}

\begin{center}\begin{tikzpicture}
  % Simplest case
  \hexgrid{rows = 5, cols = 5}

  % Every possible option at once
  \hexgrid[ every hexgrid hex/.style 2 args   = {ultra thick, draw=blue}
          , every hexgrid triangulator/.style = {color=black!75} ]
          { name = thg , size = 1.5cm
          , xpos = 0   , ypos = -5cm
          , rows = 5   , cols = 5
          , triangulate
          , start shifted}
  % Mark the center of that grid, just because we can.
  \filldraw [red] (thg-3-3) circle (2pt) ;
\end{tikzpicture}\end{center}

\end{document}
Run Code Online (Sandbox Code Playgroud)

之前的代码\newcommand{\hexgrid}只包含所需的包并设置关键字参数:name设置用于引用六边形的名称,size设置每个六边形的角到角大小,xposypos定位整个网格的左上角,rows以及cols确定六边形的数量,该triangulate选项允许您可选地对网格进行三角测量,并且该start shifted选项使第一行开始缩进而不是第二行.我们还允许用户在第一个可选参数中传递样式命令\hexgrid; every hexgrid hex/.style 2 args将允许他们设置单个六边形的样式(甚至可以查询该十六进制的位置,如果他们想要的话),和every hexgrid triangulator/.style 将允许他们设置三角测量线的样式.

跳过一点,我们来到了\pgfsetmacro线上; 指定六边形的直径,因此我们必须计算半径,边长,然后从一侧到另一侧计算宽度.以下两个\foreach循环是绘图代码的主要内容,应该非常清楚.请注意,在确定垂直放置时,我们必须考虑线条的粗细.在此之后出现更长的代码块,在\ifHexgridTriangulate和之间\fi; 如果需要这样的话,这负责对网格进行三角测量.

最后,我们看看它是什么样的:

示例六角网格.


A. *_*Rex 5

正如其他人所说,最适合您需求的可扩展性和文档化语言可能是 PGF/TikZ。不到一周前,我刚刚学习了非常基础的 TikZ,所以希望这能展示它的力量:

\documentclass{article}
\usepackage{tikz}
\begin{document}
\begin{tikzpicture}

\newcommand{\hexcoord}[2]
{[shift=(0:#1),shift=(60:#1),shift=(0:#2),shift=(-60:#2)]}
% Five-by-five hexagonal grid
\foreach \x in {0,...,4}
\foreach \y in {0,...,4}
\draw\hexcoord{\x}{\y}
(0:1)--(60:1)--(120:1)--(180:1)--(-120:1)--(-60:1)--cycle;

% Dual triangular grid
\foreach \x in {0,...,4}
\foreach \y in {0,...,4}
\foreach \z in {0,60,...,300}
\draw[help lines]\hexcoord{\x}{\y}
(0,0) [rotate=\z,shift=(0:.5),shift=(60:.5)] -- (0,0);

\end{tikzpicture}
\end{document}
Run Code Online (Sandbox Code Playgroud)

结果如下:

替代文本

与另一个答案一样,六行只是 LaTeX 的样板。请注意,除了认识到 60 度是 360 度的六分之一之外,我不需要进行任何计算。我通过使用变换和大量极坐标来避免三的平方根(六边形之间的距离)。如果您不喜欢双网格中的杂散线,可以使用第二条注释后插入的剪切区域来剪切它们:

\clip (0,0)
\hexcoord{ 4}{0}--(0,0)
\hexcoord{ 0}{4}--(0,0)
\hexcoord{-4}{0}--(0,0)
-- cycle;
Run Code Online (Sandbox Code Playgroud)

编辑。实际上,剪切区域看起来有点糟糕。这是一个更有趣的完整版本:

\documentclass{article}
\usepackage{tikz}
\begin{document}
\begin{tikzpicture}

\newcommand{\hexcoord}[2]
{[shift=(0:#1),shift=(60:#1),shift=(0:#2),shift=(-60:#2)]}
% Five-by-five hexagonal grid
\foreach \x in {0,...,4}
\foreach \y in {0,...,4}
\draw\hexcoord{\x}{\y}
(0:1)--(60:1)--(120:1)--(180:1)--(-120:1)--(-60:1)--cycle;

% Dual triangular grid
\foreach \x in {0,...,4}
\draw[help lines] \hexcoord{0}{\x}(0,0) \hexcoord{4}{0}--(0,0)
\hexcoord{-4}{4}\hexcoord{\x}{-\x}--(0,0)
\hexcoord{0}{-4}--(0,0) \hexcoord{-\x}{\x}--(0,0);

\end{tikzpicture}
\end{document}
Run Code Online (Sandbox Code Playgroud)

结果如下:

替代文本