4

I would like to draw a relatively thick Bézier curve that goes all the way to the edge of a rectangle. In the MWE below, the eventual clipping boundary is represented by the drawn rectangle.

I like the shape of the curve from (0,10) to (20,30), but I want that small remaining triangle to be filled in as well. I found the ([turn]...) syntax which works well for the end of the curve, but can't work for the start of the curve.

My kludgy solution is to draw the curve twice, once starting from the top and once starting from the bottom, but seems like there must be a better way.

In actual use, these curves aren't simply from points like in the MWE but are parameterized relative to other dimensions of the image, which is why I don't want to manually calculate the tangent line and hardcode the numbers in.

EDIT: I realize I may be asking for a particular solution to the problem instead of just the easiest. If there is a way to "straight" extend a path that doesn't involve ([turn]...) or tangents, I'm open to that solution as well. (Although the original question is interesting to me even so.)

\documentclass[tikz, margin=1cm]{standalone}
\usetikzlibrary{calc}

\begin{document}
\begin{tikzpicture}
    \draw (0, 0) rectangle (30, 30);

    \draw[line width=1.333cm, line cap=rect] (0, 10) .. controls ($(0, 10)!0.333!(20, 30) + (-1, 1)$) and ($(0, 10)!0.666!(20, 30) + (-1, 1)$) .. (20, 30);
    \draw[green, opacity=0.25, line width=1.333cm, line cap=rect] (0, 10) .. controls ($(0, 10)!0.333!(20, 30) + (-1, 1)$) and ($(0, 10)!0.666!(20, 30) + (-1, 1)$) .. (20, 30) -- ([turn]0:2);
    \draw[blue, opacity=0.25, line width=1.333cm, line cap=rect] (20, 30) .. controls ($(0, 10)!0.666!(20, 30) + (-1, 1)$) and ($(0, 10)!0.333!(20, 30) + (-1, 1)$) .. (0, 10) -- ([turn]0:2);

    \draw[red] (0, 10) -- ($(0, 10)!0.333!(20, 30) +(-1, 1)$) -- ($(0, 10)!0.666!(20, 30) + (-1, 1)$) -- (20, 30);
\end{tikzpicture}
\end{document}

output of the MWE

EDIT 2: added arrows for clarity (sorry, I used Preview.app to add them, not TeX :P )

I would like the black line to extend far enough so it gets clipped "flat" by the rectangle and doesn't leave that small internal triangle.

MWE annotated with arrows to show the problem area

  • A solution is possible using the approach in this post: tex.stackexchange.com/q/25928/19170. However, the bug found in this question appears to happen with [tangent=0, tangent=1], necessitating [tangent=0, tangent=0.99999]. As mentioned in the second link, adding one more "9" brings back the bug. – Scott Colby Nov 29 '18 at 0:41
2

Assuming I understand the requirements, the shorten > and shorten < trick with negative values may produce the desired result:

\documentclass[tikz,border=1cm]{standalone}
\usetikzlibrary{calc}
\begin{document}
\begin{tikzpicture}
 \draw (0, 0) rectangle (30, 30);
 \draw [line width=1.333cm, line cap=rect, shorten >=-0.5cm, shorten <=-0.5cm] 
  (0, 10) .. controls 
  ($(0, 10)!0.333!(20, 30) + (-1, 1)$) and 
  ($(0, 10)!0.666!(20, 30) + (-1, 1)$) .. 
  (20, 30);
\end{tikzpicture}
\end{document}

enter image description here

1

I see. Better now? This adds some smooth cotinuation at both ends.

\documentclass[tikz, margin=1cm]{standalone}
\usetikzlibrary{calc}

\begin{document}
\begin{tikzpicture}
    \draw (0, 0) rectangle (30, 30);
    \draw[line width=1.333cm, line cap=rect] (0, 10) .. controls ($(0, 10)!0.333!(20, 30) + (-1, 1)$) and ($(0,
    10)!0.666!(20, 30) + (-1, 1)$) .. (20, 30) coordinate[pos=-0.1] (aux1) coordinate[pos=0] (aux2)
    coordinate[pos=1.1] (aux3) coordinate[pos=1] (aux4)
    (aux1) -- (aux2) (aux3) -- (aux4);
\end{tikzpicture}
\end{document}

enter image description here

You could make this a style, of course.

\documentclass[tikz, margin=1cm]{standalone}
\usetikzlibrary{calc}

\begin{document}
\begin{tikzpicture}[continuation/.style={insert path={coordinate[pos=-#1] (aux1) coordinate[pos=0] (aux2)
    coordinate[pos=1+#1] (aux3) coordinate[pos=1] (aux4)
    (aux1) -- (aux2) (aux3) -- (aux4)}}]
    \draw (0, 0) rectangle (30, 30);
    \draw[line width=1.333cm, line cap=rect] (0, 10) .. controls ($(0, 10)!0.333!(20, 30) + (-1, 1)$) and ($(0,
    10)!0.666!(20, 30) + (-1, 1)$) .. (20, 30) [continuation=0.1];
\end{tikzpicture}
\end{document}

and also produce the mandatory animation

\documentclass[tikz, margin=1cm]{standalone}
\usetikzlibrary{calc}

\begin{document}
\tikzset{continuation/.style={insert path={coordinate[pos=-#1] (aux1) coordinate[pos=0] (aux2)
    coordinate[pos=1+#1] (aux3) coordinate[pos=1] (aux4)
    (aux1) -- (aux2) (aux3) -- (aux4)}}}
\foreach \X in {0.01,0.02,...,0.25}
{\begin{tikzpicture}
    \draw (0, 0) rectangle (30, 30);
    \draw[line width=1.333cm, line cap=rect] (0, 10) .. controls ($(0, 10)!0.333!(20, 30) + (-1, 1)$) and ($(0,
    10)!0.666!(20, 30) + (-1, 1)$) .. (20, 30) [continuation=\X];
\end{tikzpicture}}
\end{document}

enter image description here

  • The problem isn't with the the extra green and blue, but the tiny triangle of white that would be left over inside the rectangle if the green and blue paths weren't there. – Scott Colby Nov 29 '18 at 0:29
  • @ScottColby Still not sure if I understand the question but does that come closer to what you want? – marmot Nov 29 '18 at 0:32
  • Yes, it's so close, but if you draw the auxiliary lines with reduced opacity and a different color, you'll see that they're not quite tangent to the Bézier. Not that anyone would probably notice/care at any reasonable print size, so this is acceptable if we can't find another way, but it would be nice to get things lined up perfectly. – Scott Colby Nov 29 '18 at 0:40
  • @ScottColby I am aware of the tangent solution but I am also aware of this issue, so I am afraid that the tangent solution may be more shaky than what I have. (The true question is which of these methods yield the "true" tangent. I believe that the above is sufficiently close to the true solution in the sense that it is almost indistinguishable from it.) – marmot Nov 29 '18 at 0:47
  • That's a much better investigation of the problem than the question I linked in my comment above! I'll do some reading and come back here. – Scott Colby Nov 29 '18 at 1:13
0

I have decided on the following solution utilizing the decorations.markings TikZ library.

\documentclass[tikz, margin=1cm]{standalone}
\usetikzlibrary{calc}
\usetikzlibrary{decorations.markings}

\begin{document}
\begin{tikzpicture}[
    continuation/.style={
        decoration={
            markings,
            mark=
                at position 0
                with {\draw[red, thin] (0.1, 0) -- (-1, 0);},
            mark=
                at position 0.99999
                with {\draw[blue, thin] (-0.1, 0) -- (1, 0);}
        },
        postaction=decorate,
    }]
    \draw (0, 0) rectangle (30, 30);

    \draw[line width=1.333cm, continuation] (0, 10) .. controls ($(0, 10)!0.333!(20, 30) + (-1, 1)$) and ($(0, 10)!0.666!(20, 30) + (-1, 1)$) .. (20, 30);

    \draw[red] (0, 10) -- ($(0, 10)!0.333!(20, 30) + (-1, 1)$) -- ($(0, 10)!0.666!(20, 30) + (-1, 1)$) -- (20, 30);

    \draw[green, shorten >=-0.5cm] ($(0, 10)!0.333!(20, 30) +(-1, 1)$) -- (0, 10);
    \draw[green, shorten >=-0.5cm] ($(0, 10)!0.666!(20, 30) +(-1, 1)$) -- (20, 30);
\end{tikzpicture}
\end{document}

output of the mwe

There are two considerations here. The first is does this create the actual tangent? The red and blue extensions on the end of the Bézier curve are produced by the continuation style utilizing markings. I have confirmed this here by drawing the tangent line through the Bézier curve in green and extending it with shorten >=-0.5cm. Zooming in on the two ends confirms that these are the same lines. (I suppose I could attempt to extract the actual paths from the PDF and check mathematically but...that's not a project for today.)

The second consideration is the bug in the markings library. The furthest the end position can be set in this case is 0.99999; one more 9 causes an error. By inspection of this image and because I know the Bézier curve I will be using will not be too curved at the end, I think this is fine.

I thought about literally "doing the math" on the Bézier curve and inserting the "perfect" extension line manually, but this didn't seem like a good use of my time, especially since I wanted to parameterize my final image.

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.