0

Is there an elegant way to draw a dotted line with white solid line underneath? The reason I'm asking is that often I'm drawing lots polygons which share some dotted sides. However, I would like to have all lines having the same number of dots regardless of how many times each particular line was drawn. Here is a minimal example:

\documentclass{article}
\usepackage{tikz}

\begin{document}
    \begin{tikzpicture}
        \draw [dotted]
            (0,0) -- (1,0) -- (1,1) -- (0,1) -- cycle
            (1,0) -- (2,0) -- (2,1) -- (1,1) -- cycle
        ;
    \end{tikzpicture}
\end{document}

enter image description here

So here you can see two squares with a shared side. I would like to avoid the shared side having visibly larger number of dots. Obviously, I want a general solution, i.e. one which still involves drawing the same page twice but without the dots adding up.

3
  • 1
    Welcome to TeX.SX! If you draw the common edge of both paths first and in the same direction, the dots will exactly overlap: \draw [dotted] (1,0) -- (1,1) -- (0,1) -- (0,0) -- cycle (1,0) -- (1,1) -- (2,1) -- (2,0) -- cycle;. Dec 9, 2022 at 11:02
  • 1
    @JasperHabicht doesn't necessarily need to be at the start, just need to the same distance from the last move to, e.g. (0,0) -- (1,0) -- (1,1) -- (0,1) -- cycle (2,0) -- (1,0) -- (1,1) -- (2,1) -- cycle. But that won't help much in a more complex diagram, either. Dec 9, 2022 at 11:08
  • Can you show us what are you trying to achieve? A grid of dotted rectangle might be better to achieve with the grid operation. You will need a carefully crafted dash pattern otherwise. Dec 9, 2022 at 11:09

1 Answer 1

4

The common part between both segments need to be the same distance away from the start of a segment (i.e. the recent move to):

\draw [dotted] 
  (0,0) -- (1,0) -- (1,1) -- (0,1) -- cycle
  (2,0) -- (1,0) -- (1,1) -- (2,1) -- cycle;

Here, the part (1,0) -- (1,1) is at the same place and starts one unit after the recent move to (the (0,0) or the (2,0) at the start of the line).

But this can get messy real quick with a lot of rectangles but you can just draw every side separatly, every horizontal from left to right and every vertical from bottom to top:

\draw [dotted]
  foreach \x in {0, ..., 2} {
    foreach \y in {0, ..., 1} {
      [shift={(\x, \y)}]
        (0,0) --  (1,0) (0,0) --  (0,1)
        (0,1) -- +(1,0) (1,0) -- +(0,1)
    }
  };

It might be better to just define a dash pattern that has a phase which adds up nicely to the length of your edge.

Since you're using the length of 1, i.e. 1cm in the default xyz coordinate system, you could use

dash pattern = on \pgflinewidth off .66667mm-\pgflinewidth,
dash phase   = .5\pgflinewidth
% or:
dash         = on \pgflinewidth off .66667mm-\pgflinewidth phase .5\pgflinewidth

which means that the line has one square dot (on \pgflinewidth) and the next one starts after 0.66667 mm.

Since the \pgflinewidth is not a nice number that fits into the metric coordinate system we subtract the \pgflinewidth again which means just .66667mm needs to fit into 1 cm (which it does 150 times).
The dash phase is needed so that the dot starts with its center at the start of the path.

Now you can simply use the rectangle path operation again (or even your version of specifying the corners):

\draw[
  dash pattern=on \pgflinewidth off 1mm-\pgflinewidth,
  dash phase=.5\pgflinewidth
] foreach \x in {0, ..., 2} {
    foreach \y in {0, ..., 1} {
      (\x, \y) rectangle + (1,1)    
    }
  };

If you change your coordinate system, you need to adjust this value (or we need to write a special key that does that for you but that is a bit mathy).

This also doesn't scale nicely with the line width since .66667mm ignores the line width. So, if your line width approaches this value the space between the dots get smaller. (This is why I'm using 1mm in the example below because of thick is used.)


I've also added an example with the grid operation (which just draws non-overlapping straight lines) – which doesn't look that nice because the pattern doesn't fit the coordinate system but it doesn't draw multiple lines on top of each other. (You can of course use a similar dash setting as above to have it nicely line up again).

The fourth example places rectangles along the path of your grid which makes it very easy for weird xyz coordinate systems though it will be a bit work do rotate them so that it will look like a dash pattern.

I've placed all examples in a \matrix to make it easier to show them in one diagram.

Code

\documentclass[tikz]{standalone}
\begin{document}
\tikz[thick]\matrix[row sep=5mm, column sep=5mm]{
\draw [dotted] 
  (0,0) -- (1,0) -- (1,1) -- (0,1) -- cycle
  (2,0) -- (1,0) -- (1,1) -- (2,1) -- cycle;
&
\draw [dotted]
  foreach \x in {0, ..., 2} {
    foreach \y in {0, ..., 1} {
      [shift={(\x, \y)}]
        (0,0) --  (1,0) (0,0) --  (0,1)
        (0,1) -- +(1,0) (1,0) -- +(0,1)
    }
  };
\\
\draw[
  dash pattern=on \pgflinewidth off 1mm-\pgflinewidth,
  dash phase=.5\pgflinewidth
] foreach \x in {0, ..., 2} {
    foreach \y in {0, ..., 1} {
      (\x, \y) rectangle + (1,1)    
    }
  };
&
\draw [dotted] (0,0) grid (3,2);
\\
\fill[x=(30:.5cm), y=(70:.7777cm)]
  foreach \x in {0, ..., 2} {
    foreach \y in {0, ..., 1} {
      [shift={(\x, \y)}]
      foreach \X in {0, ..., 9} {
        foreach \xy/\yx/\v in {x/y/0, y/x/0, x/y/1, y/x/1} {
          ([shift={(-.5\pgflinewidth,-.5\pgflinewidth)}]xyz cs: \xy=\X/10,\yx=\v)
            rectangle + (\pgflinewidth, \pgflinewidth)
        }
      }
    }
  };
\\};
\end{document}

Output

enter image description here

0

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .