11

I am extremely new to Tikz, and know that it's easy to draw regular (Cartesian) grids, but haven't seen any examples using unstructured grids.

Is this possible to do in Tikz, and if so, is there a MWE available somewhere?

EDIT: From the comments below, to better clarify what I'm looking for:

To start, I would like a 2D case with a small mesh, say regularly spaced nodes (5x5) made into a Delaunay mesh. I would only need to display vertices and edges.

Eventually, I'd like to expand the example to 3D and overly semi-transparent block elements on this mesh, elements similar to the cone segment on the left of this example: texample.net/tikz/examples/3d-cone

My case would be a bit simpler since I'd just be using cubes. However, I just want to get the 2D mesh case figured out first, and expand from there.

EDIT2: Based on the answer below, I drew a grid with regular spacing using:

\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}

enter image description here

With the only issue that the way it connects the vertices is not always consistent.

  • 6
    What do you mean with "unstructured grids"? – Heiko Oberdiek Aug 10 '15 at 3:58
  • @HeikoOberdiek Sorry, that was a little domain specific. In my field, an "unstructured grid" is a way to tessellate a plane, most often using triangles, It is often done using Delaunay triangulation, but there are other ways of constructing the grid.. – chasely Aug 10 '15 at 12:48
21

Something like this?

\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}

enter image description here

And some triangles...

\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}

enter image description here

Although something like asymptote may be better for this kind of thing (see g.kov's answer), if you like python and use scipy and are happy compiling with --shell-escape the following (rather impractical) code may be a useful starting point.

\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}

enter image description here

  • This is close to what I'm looking for. Is there any way to force triangulation (like Delaunay)? That may be beyond the abilities of Tikz, but I'm not sure. – chasely Aug 10 '15 at 12:45
  • @chasely Proper Delauney triangulation is going to to be really hard in TikZ, but it is possible to get a sort of triangular irregular grid. – Mark Wibrow Aug 10 '15 at 13:03
  • Thanks, I don't need proper Delauney triangulation (though that would be nice). The example you provided is very good to get me started. – chasely Aug 10 '15 at 13:37
  • @chasely: I had some success using lualatex but it is slow (and I am not used to lua). Your best bet probably is to create the mesh with an external application and to import it into Tikz/LaTeX in a table like format. However, we probably need more detail. What do you want to display? Only edges and vertices? Color coded faces? 2D 3D? – Nobody Aug 10 '15 at 13:43
  • @Nobody To start, I would like a 2D case with a small mesh, say regularly spaced nodes (5x5) made into a Delaunay mesh. I would only need to display vertices and nodes. Eventually, I'd like to expand the example to 3D and overly semi-transparent block elements on this mesh, elements similar to the cone segment on the left of this example: texample.net/tikz/examples/3d-cone My case would be a bit simpler since I'd just be using cubes. However, I just want to get the 2D mesh case figured out first, and expand from there. – chasely Aug 10 '15 at 14:08
10

A interpretation of an "unstructured grid" with random lines:

\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}

Result

10

Since you've asked, "Asymptote uses a robust version of Paul Bourke’s Delaunay triangulation algorithm based on the public-domain exact arithmetic predicates written by Jonathan Shewchuk" (from the docs).

Here is an example with the circles added:

//  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
//

enter image description here

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.