首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >用于绘制几何图形的语言或软件包

用于绘制几何图形的语言或软件包
EN

Stack Overflow用户
提问于 2010-10-24 00:48:05
回答 12查看 6.3K关注 0票数 21

我正在寻找一种语言,或在现有的语言包,这是很好的规定和绘制几何图。

例如,我想画一个六边形网格,它的双重三角形网格叠加在上面。现在,我可以坐下来,手动计算出三角网格,然后想出一些Postscript或SVG来显示这样的网格。但我想知道是否有任何语言或软件包可以帮助我解决这个问题;这使得指定一个六边形网格,找到中心,并在它上面画一个三角形网格变得很容易。

做这件事最简单的方法是什么?

代码示例,展示创建这样的几何指定图是多么容易,将不胜感激。特别是,请演示绘制六边形网格是多么容易;虽然我可以用任何语言手工绘制所有的线条,但我对使这种几何图变得简单和清晰的语言或软件包感兴趣。

赏金

既然这个问题已经得到了回答,但答案比我希望的要复杂得多,我将奖励那些能够用任何预先存在的语言和使用任何预先存在的软件包生成最短和最简单的代码的人,来绘制一个六边形网格,其双重三角形网格叠加在它的顶部;双重三角形网格是您将每个六边形的中心连接到每个相邻六边形的中心时得到的三角形网格。例如,请参阅Antal S-Z's answer;他的示例可以解决这个问题,但我正在寻找一种可以简化此问题的语言。您可以生成一个大致为矩形的网格,如他的示例所示(奇数行对齐,偶数行对齐),也可以生成Hex电路板样式的网格(每行右移半个十六进制,形成菱形);两者都是可接受的。

程序可以在语言中以函数或子例程的形式接受输入,或者接受在命令行上传递的指示行和列的输入。它应该生成任何标准和常见图形格式的输出,例如Postscript、PDF、SVG、PNG或PNM;输出应该包含十六进制网格和三角形网格,采用一些对比颜色、线宽或线条样式,以使图表清晰。

我正在寻找最短和最简单的答案,作为一种找到最适合描述这类图的语言或包的方法;赏金将花在解决问题的最短程序上。这不是code golf,所以我不会按字符数或代码行计数。如果没有明显的最短答案,那么我将根据令牌计数进行测量;在您的语言中,需要多少个令牌来表达这个问题?因此,可读的常量和变量名、使用库函数、注释、空格等都很好,因为它们不会增加令牌计数。它仍然不是一个完美的指标(Lisp会有更多的标记,因为你需要更多的括号来分隔你的算术表达式,我确信如果你过度优化这个指标,你仍然会产生一些难以阅读的代码),但它是一个粗略的指南,告诉你你的代码有多复杂。

因此,对于赏金来说,挑战是创建一个最短的程序,用它的叠加三角形网格绘制一个十六进制网格。请张贴你的代码,链接到语言和你使用过的任何包,如果可能的话,粗略的令牌计数,以及一个示例输出图像。现有的答案是你必须通过的标准;它的工作,但我想要更短,更简单。

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

EN

回答 12

Stack Overflow用户

回答已采纳

发布于 2010-10-24 07:26:27

我还想推荐PGF/TikZ,但需要注意的是,它是在TeX中。如果您不习惯进行TeX编程,可能会有点头疼,因为有一些…不同的特质。(例如,处理零散空间可能是一种冒险。)但是,如果您愿意进行TeX编程,我强烈推荐它;即使我不是在TeX中工作,我也经常使用它来绘制图形。此外,its manual绝对是令人惊叹的,并且TeXample gallery有很多很棒的例子。

绘制十六进制网格并对其进行三角剖分的示例代码如下所示。我承认它是相当长的,但我认为它真的没有那么糟糕。

代码语言:javascript
复制
\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}

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

跳过一点,我们来到\pgfsetmacro线;六边形的直径是指定的,所以我们必须计算半径,边长,然后计算从一边到另一边的宽度。以下两个\foreach循环是绘图代码的核心,希望它们非常清晰。请注意,在确定垂直位置时,我们必须考虑线条的粗细。在这之后是一个更长的代码块,在\ifHexgridTriangulate\fi之间;如果需要的话,它负责对网格进行三角剖分。

最后,我们来看看这是什么样子的:

票数 11
EN

Stack Overflow用户

发布于 2010-10-24 01:07:31

Xy-picMetaPost,如果您有TeX,它们可能已经安装在您的计算机上。

更新:在尝试记住如何使用MetaPost但失败之后...我用的是谷歌的SketchUp。对布局来说微不足道。也许一个不同的CAD程序可能适合您。但是使用绘图程序是目前为止最简单的。也许是OpenOffice Draw?看起来像是作弊,但它能最快地完成工作。

这是几分钟后在OpenOffice Draw中生成的快速图像。需要在纵横比上做一点工作,但它展示了基本的东西。

Groovy更新第二个时,我想到了使用像GraphicsBuilder这样的声明式风格的工具是最好的。不幸的是,GraphicsBuilder似乎需要后台Groovy1.6-beta-2。因此,转向其他东西,最相似的结果是... JavaFX。下面是(非常差劲,但展示了可以做的)代码:

代码语言:javascript
复制
package hexgrid;

import javafx.scene.shape.Polygon;
import javafx.scene.paint.Color;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.stage.Stage;
import javafx.scene.shape.Line;
import javafx.scene.shape.Circle;
import javafx.util.Math;

/**
 * @author arouse
 */
var scale = 60;
var width = 400;
var height = 400;

function hexagon(x: Number, y: Number): Polygon {
    var basicpoints = [1, 0, 0.5, -0.866, -0.5, -0.866, -1, 0, -0.5, 0.866, 0.5, 0.866];
    basicpoints = for (i in basicpoints) i * scale;
    return Polygon {
                points: basicpoints
                fill: Color.WHITE
                translateX: x
                translateY: y
                strokeWidth: 2
                stroke: Color.BLUE
                opacity: 0.3
            }
}
var hexes = Group {
            content: [
                for (x in [0..width step scale * 3]) {
                    for (y in [0..height step 0.866 * scale * 2]) {
                        hexagon(x, y);
                    }
                }
                for (x in [0..width step scale * 3]) {
                    for (y in [0..height step 0.866 * scale * 2]) {
                        hexagon(x + 1.5 * scale, y + 0.866 * scale);
                    }
                }
            ]
        }
var lines60 = Group {
            content: [
                for (y in [0..height step scale]) {
                    Line {
                        startX: 0, startY: 2 * y * 0.866
                        endX: 3 * y, endY: 0
                        strokeWidth: 1
                        stroke: Color.BLACK
                    }
                }
            ]
        }
var lines120 = Group {
            content: [
                    for (y in [(-Math.floor(height/10)*scale)..height step scale]) {
                    Line {
                        startX: 0, startY: 2*0.866*y
                        endX: width, endY: 2*0.866/3*width + 2*0.866*y
                        strokeWidth: 1
                        stroke: Color.BLACK
                    }
                }
            ]
        }
var linesdown = Group {
            content: [
                for (x in [0..width step scale*1.5]) {
                    Line {
                        startX:  x, startY: 0
                        endX:  x, endY: height
                        strokeWidth: 1
                        stroke: Color.BLACK
                    }}
            ]
        }
Stage {
    title: "Hex Grid with dual triangular grid"
    scene: Scene {
        width: width
        height: height
        fill: Color.WHITE
        content: [
            hexes,
            lines60,
            lines120,
            linesdown
        ]
    }
}

这导致了这一点(我承认它可能会更好):

优点优于其他答案:可用于合成任意图像、文本、动画等,完全编程语言,java互操作。还提供了很棒的教程和丰富的文档。Netbeans IDE有一个非常好的预览按钮,对于几乎即时查看结果非常有用。

是的,我可以在代码中做得更好,但在转换和填充中有一些古怪的东西。所以我用了丑陋的方式。

顺便说一下,这是我的第一个javafx程序。我会感谢修复和更改。

票数 4
EN

Stack Overflow用户

发布于 2010-10-26 14:28:25

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

代码语言:javascript
复制
\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}

结果如下:

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

代码语言:javascript
复制
\clip (0,0)
\hexcoord{ 4}{0}--(0,0)
\hexcoord{ 0}{4}--(0,0)
\hexcoord{-4}{0}--(0,0)
-- cycle;

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

代码语言:javascript
复制
\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}

结果如下:

票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/4005042

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档