使用 Tikz 绘制非结构化网格

使用 Tikz 绘制非结构化网格

我对 Tikz 非常陌生,并且知道绘制规则(笛卡尔)网格很容易,但还没有看到使用非结构化网格的任何示例。

这可以在 Tikz 中实现吗?如果可以,是否有地方提供 MWE?

编辑:从下面的评论中,为了更好地阐明我正在寻找的内容:

首先,我想要一个 2D 案例,其中有一个小网格,比如说间距规则的节点(5x5),制成 Delaunay 网格。我只需要显示顶点和边。

最后,我想将示例扩展为 3D 和此网格上过度半透明的块元素,这些元素类似于此示例左侧的圆锥体部分:texample.net/tikz/examples/3d-cone

我的情况会稍微简单一些,因为我只使用立方体。但是,我只想先弄清楚 2D 网格的情况,然后再从那里扩展。

EDIT2:根据以下答案,我使用以下方法绘制了一个具有规则间距的网格:

\documentclass[tikz,border=5]{standalone}
\begin{document}

\begin{tikzpicture}
\foreach \i [evaluate={\ii=int(\i-1);}] in {0,...,3}{
  \foreach \j [evaluate={\jj=int(\j-1);}] in {0,...,3}{
    \coordinate [shift={(\j,\i)}] (n-\i-\j) at (0:0);
\ifnum\i>0
  \draw [help lines] (n-\i-\j) -- (n-\ii-\j);
\fi
\ifnum\j>0
  \draw [help lines] (n-\i-\j) -- (n-\i-\jj);
  \ifnum\i>0
    \pgfmathparse{int(rnd>.5)}
    \ifnum\pgfmathresult=0
      \draw [help lines] (n-\i-\j) -- (n-\ii-\jj);
    \else%
      \draw [help lines] (n-\ii-\j) -- (n-\i-\jj);
    \fi%
  \fi
\fi
}}
\end{tikzpicture}

在此处输入图片描述

唯一的问题是,它连接顶点的方式并不总是一致的。

答案1

像这样吗?

\documentclass[tikz,border=5]{standalone}
\begin{document}
\begin{tikzpicture}
\foreach \i [evaluate={\ii=int(\i-1);}] in {0,...,11}{
  \foreach \j [evaluate={\jj=int(\j-1);}] in {0,...,11}{
    \coordinate [shift={(\j,\i)}] (n-\i-\j) at (rand*180:1/4+rnd/8);
\ifnum\i>0
  \draw [help lines] (n-\i-\j) -- (n-\ii-\j);
\fi
\ifnum\j>0
  \draw [help lines] (n-\i-\j) -- (n-\i-\jj);
\fi
}}
\end{tikzpicture}
\end{document}

在此处输入图片描述

还有一些三角形……

\documentclass[tikz,border=5]{standalone}
\begin{document}
\begin{tikzpicture}
\foreach \i [evaluate={\ii=int(\i-1);}] in {0,...,7}{
  \foreach \j [evaluate={\jj=int(\j-1);}] in {0,...,7}{
    \coordinate [shift={(\j,\i)}] (n-\i-\j) at (rand*180:1/4+rnd/8);
\ifnum\i>0
  \draw [help lines] (n-\i-\j) -- (n-\ii-\j);
\fi
\ifnum\j>0
  \draw [help lines] (n-\i-\j) -- (n-\i-\jj);
  \ifnum\i>0
    \pgfmathparse{int(rnd>.5)}
    \ifnum\pgfmathresult=0
      \draw [help lines] (n-\i-\j) -- (n-\ii-\jj);
    \else%
      \draw [help lines] (n-\ii-\j) -- (n-\i-\jj);
    \fi%
  \fi
\fi
}}
\end{tikzpicture}
\end{document}

在此处输入图片描述

虽然类似的东西asymptote可能对这种事情更好(见科夫的回答),如果你喜欢python并使用scipy并且乐意使用--shell-escape以下(相当不切实际的)代码进行编译,可能是一个有用的起点。

\documentclass[tikz,border=5]{standalone}
\usepackage{pgfplots}
\pgfplotsset{compat=1.11}
\usepgfplotslibrary{patchplots}
{\obeyspaces\obeylines%
\gdef\delauney#1#2{%
\immediate\write18{echo "x y" > #1_points.dat; echo "%
import numpy as np
points=np.array([#2])
for point in points:
    print point[0], point[1]
" | python >> #1_points.dat}%   
\immediate\write18{echo "p1 p2 p3" > #1_triangles.dat; echo "%
import scipy.spatial as sp
import os
import numpy as np
points=np.array([#2])
triangulation=sp.Delaunay(points)
for simplex in triangulation.simplices:
    print
    for vertex in simplex:
        print vertex,
" | python >> #1_triangles.dat}%   
}}

\begin{document}
\def\points{(0,0)}
\foreach \i in {1,...,50}{
  \pgfmathparse{rand*10cm}\let\x=\pgfmathresult
  \pgfmathparse{rand*10cm}\let\y=\pgfmathresult
  \xdef\points{\points,(\x,\y)}%
}
\delauney{d1}{\points} 

\begin{tikzpicture} 
\begin{axis}[width=10cm, height=10cm, axis lines=none]
\addplot [patch, patch refines=0, mesh, help lines,
  patch table={d1_triangles.dat}] table {d1_points.dat}; 
\end{axis} 
\end{tikzpicture}

\end{document}

在此处输入图片描述

答案2

对具有随机线条的“非结构化网格”的解释:

\documentclass{article}
\usepackage{tikz}

\begin{document}
  \begin{tikzpicture}
    \def\xmin{0}
    \def\xmax{5}
    \def\ymin{0}
    \def\ymax{5}
    \def\xnum{20}% number of horizontal lines
    \def\ynum{20}% number of vertical lines
    \pgfmathsetseed{1000}% initialize randomness for reproducable results
    \draw[help lines]
      \foreach \i in {1, ..., \ynum} {
        (\xmin, {\ymin + rnd*(\ymax - \ymin)})
        -- ++(\xmax - \xmin, 0)
      }
      \foreach \i in {1, ..., \xnum} {
        ({\xmin + rnd*(\xmax - \xmin)}, \ymin)
        -- ++(0, \ymax - \ymin)
      }
    ;
  \end{tikzpicture}
\end{document}

结果

答案3

既然你问过了,“Asymptote使用基于 Jonathan Shewchuk 编写的公共领域精确算术谓词的 Paul Bourke 的 Delaunay 三角剖分算法的强大版本”(来自文档)。

以下是添加了圆圈的示例:

//  d.asy :
//    
settings.outformat="pdf";
import graph;
size(8cm);
pen p=deepblue+0.4bp;
pen[] circPen={red,deepgreen,blue};
int np=12;
pair[] points;
real r() {return unitrand();}
pair circCenter(pair A,pair B,pair C,real eps=1e-8){
  pair O,P,Q;
  real d;
  P=A-B;
  Q=B-C;
  d=P.x*Q.y-P.y*Q.x;
  assert(abs(d)>eps,"Collinear points");
  O=( (B.y-C.y)*(A.x^2-B.x^2+A.y^2-B.y^2)+(B.y-A.y)*(B.x^2-C.x^2+B.y^2-C.y^2)
      ,
      (C.x-B.x)*(A.x^2-B.x^2+A.y^2-B.y^2)+(A.x-B.x)*(B.x^2-C.x^2+B.y^2-C.y^2)
    )/(2*d);
  return O;
}

srand(123);
for(int i=0; i < np; ++i) points.push((r(),r()));
int[][] trn=triangulate(points);
pair O, t[];
for(int i=0; i < trn.length; ++i) {
  t=points[trn[i]];
  O=circCenter(t[0],t[1],t[2]);
  draw(t[0]--t[1]--t[2]--cycle,p);
  draw(Circle(O,abs(O-t[0])),circPen[i%circPen.length]+0.5bp+ opacity(0.8));
}
for(int i=0; i < np; ++i) dot(points[i],p+0.6bp,UnFill);
clip(box((0,0),(1,1)));
//
// To get d.pdf, run as:
//    
// asy d.asy
//

在此处输入图片描述

相关内容