TikZ personalizado "to path" com bordas curvas

TikZ personalizado "to path" com bordas curvas

Estou tentando definir um estilo que defina to pathtal que um “retângulo curvo” (representação múltipla) seja desenhado quando coloco \draw (0,0) to[manifold] (5,3).

Eu fiz a forma manualmente especificando inângulos outem um sistema de coordenadas absoluto e relativo e desenhando os quatro cantos usando to. (Primeiro e segundo exemplo em MWE.)

Posso desenhar o retângulo usando um to pathestilo, conforme definido no preâmbulo. Estou lutando com dois problemas, onde acho que posso resolver (1), mas não sei como fazer (2):

  1. Como mover automaticamente os cantos SE e NW em direção ao centro, ou (equivalentemente) 10% em direção aos cantos SW e NE, como no primeiro exemplo. (b é movido um pouco em direção a c e a). Provavelmente posso fazer isso com cálculo e um pouco de ($(\tikztostart -| \tikztotarget)!0.9!(\tikztostart |- \tikztotarget)$)magia.
  2. Aplique the out=x,in=y,relativeaos caminhos internamente na operação manifold/.styledo . path toEu não tenho nenhuma idéia de como fazer isso.

Para 2., tentei coisas que encontrei em tikzlibrarytopaths.code.tex, onde por exemplo outé definido como uma opção TikZ que define \def\tikz@to@out{#1}\tikz@to@switch@on. Colocar isso em vários lugares (atualmente em \pgfextrain to path) não funciona. Alguém pode ajudar com isso?

MWE

\documentclass[tikz]{standalone}

\makeatletter
\tikzset{manifold/.style={
  to path={
    \pgfextra{
    \def\tikz@to@out{20}\tikz@to@switch@on
    }
    (\tikztostart) -- (\tikztostart -| \tikztotarget)
    -- (\tikztotarget)
    -- (\tikztostart |- \tikztotarget)
    -- cycle
    (\tikztotarget)
    \tikztonodes
  }
}}
\makeatother

\begin{document}

\begin{tikzpicture}[every node/.style={opacity=0.5,color=cyan}]
  \draw[line width=0.5pt,dotted,red] (-1,-3) grid (5,7);

  % base manifold: absolute in/out angles
  \draw[thick] (0,0) node{a}
    to[out=-10,in=170] (4,0.5) node{b}
    to[out=70,in=-130] (5,3) node{c}
    to[out=170,in=-10] (1,2.5) node{d}
    to[out=-130,in=70] cycle;

  % base manifold: relative in/out angles: all the same
  \begin{scope}[shift={(0,-3)},out=-20,in=160,relative]
    \draw (0,0) to (4,0.5) to (5,3) to (1,2.5) to cycle;
  \end{scope}

  % base manifold: to path style
  \begin{scope}[shift={(0,3)}]
    \draw[red] (0,0) to[manifold] (5,3);
  \end{scope}
\end{tikzpicture}
\end{document}

Saída MWE. Meio e fundo estão bem. O topo deve ser igual ao fundo.

Responder1

Completamente reimplementado e usando caminhos de curva de Bézier explícitos usando uma coordenada (passada como argumento, que tem um valor padrão) para determinar a curvatura. Espero que os comentários expliquem tudo.

\documentclass[tikz,border=5]{standalone}
\usetikzlibrary{calc}
\tikzset{manifold/.style={to path={
  % Create new coordinates to save typing
  (\tikztostart) coordinate (@1)
  (\tikztostart |- \tikztotarget) coordinate (@2)
  (\tikztotarget) coordinate (@3)
  (\tikztostart -| \tikztotarget) coordinate (@4)
  % Get 'transformed' points
  (@1) coordinate (@@1)
  ($(@2)!0.1!(@4)$) coordinate (@@2)
  (@3) coordinate (@@3)
  ($(@4)!0.1!(@2)$) coordinate (@@4)
  % Calculate \manifoldsize for scaling
  let \p1=(@1),\p2=(@3),\n1={veclen(\x2-\x1,\y2-\y1)} in
  \pgfextra{\edef\manifoldsize{\n1}} 
  % Use coordinate passed in as #1
  let \p1=#1 in
  %
  (@@1) .. controls ++( \x1, \y1) and ++(-\x1,-\y1) .. 
  (@@2) .. controls ++( \x1,-\y1) and ++(-\x1, \y1) ..
  (@@3) .. controls ++(-\x1,-\y1) and ++( \x1, \y1) ..
  (@@4) .. controls ++(-\x1, \y1) and ++( \x1,-\y1) .. cycle (@@3)
}}, manifold/.default={(45:\manifoldsize/4)}}
\begin{document}
\begin{tikzpicture}[ultra thick, line join=round]
\draw [purple] (-2,-2) to [manifold] (5,4);
\draw [orange] (0,0) to [manifold] (3,2);
\end{tikzpicture}
\end{document}

insira a descrição da imagem aqui

Responder2

Não é uma resposta para minhas perguntas/problemas específicos, mas uma maneira diferente e menos TikZ de fazer isso, usando uma macro simples:

\newcommand\manifold[3][]{
  \draw[every to/.style={out=-20,in=160,relative},#1] (#2) 
  to ($(#2 -| #3)!0.2!(#2 |- #3)$)
  to (#3)
  to ($(#2 -| #3)!0.8!(#2 |- #3)$)
  to cycle;
}

e usá-lo como \manifold[green,thick]{0,0}{4,3} a resposta de @Mark Wilbrow usa to path, minha intenção original. :)

informação relacionada