Saltar al contenido

Dibujo retrasado de flechas en tikz-cd

Te doy la bienvenida a nuestro sitio web, ahora vas a encontrar la resolución de lo que estabas buscando.

Solución:

¿Como esto?

Resultado

Aunque debo confesar que todavía no tengo la solución general, para este caso particular el efecto se logró dibujando la flecha de TN a TM en lugar de TM a TN. De esta manera se dibujó la flecha después el horizontal. Y por supuesto que usé leftarrow para obtener la punta de flecha correcta.

documentclassarticle
usepackagetikz-cd
begindocument
[
begintikzcd[ampersand replacement=&,column sep=small]
  GM arrow[pos=0.75]rrmodels_M
     arrow[two heads,swap]dre_M
     arrow[swap]ddGf
     &      & 
     R^FM
       arrowddR^Ff \
     & T M 
    arrow[tail,swap]rum_M
     & \
  GN arrow[pos=0.75,crossing over]rrmodels_N
     arrow[two heads,swap]dre_N
     &      & R^FN \
     & T N 
    arrow[leftarrow,pos=0.25,crossing over]uuT f  % <<----- HERE
    arrow[tail,swap]rum_N &    
endtikzcd
]
enddocument

Actualización: una solución más general

La solución anterior es ad hoc y funciona solo para este ejemplo en particular. La solución general permitiría dibujar cualquier flecha adicional entre dos nodos del diagrama conmutativo ya compuesto.

La idea es la siguiente. Ya que internamente tikzcd usa un matrix of nodes para componer cada nodo del diagrama, ¿por qué no sería posible usar esos nodos como parte de una ruta dibujada después del diagrama?

La idea es razonable, pero hay algunos problemas aquí:

  1. ¿Cuáles son los nombres de cada nodo en el diagrama? ¿Sería posible usar la sintaxis [(name)] normalmente permitido dentro de un tikz matrix of nodes? Respuesta: no, no es posible, eso rompería el código del arrow macro, que se basa en los nombres generados automáticamente para los nodos.
  2. Entonces, ¿hay nombres generados automáticamente? ¿Cuáles son esos nombres? Respuesta: Todos comienzan con tikzmatrixname y tener el sufijo -row-column. Entonces, por ejemplo, el primer nodo de este diagrama (con la etiqueta GM) sería tikzmatrixname-1-1, el nodo central (TM) es tikzmatrixname-2-2, etcétera.
  3. Entonces sería posible agregar draw (tikzmatrixname-1-1) to[bend left] (tikzmatrixname-2-2); por ejemplo, después de que se hace la matriz? es decir: esto por ejemplo:

    begintikzcd[ampersand replacement=&,column sep=small]
      GM arrow[pos=0.75]rrmodels_M
      [...]
      arrow[tail,swap]rum_N &
    % After all nodes are in the matris, draw some extra arrows
    draw[bend left] (tikzmatrixname-1-1) to[bend left] (tikzmatrixname-2-2);
    endtikzcd
    

    Respuesta: Lamentablemente, la respuesta es no, esto no es posible debido a la forma tikcd maneja el diagrama. Dentro de tikzcd medio ambiente, sorprendentemente suficiente, no tikz se pueden emitir comandos. De hecho, todos tikz Los comandos no están definidos, porque el tikzcd medio ambiente no es a tikzpicture medio ambiente. Esto explica por qué no puede usar node, draw ni ningún otro comando.

    Qué tikzcd lo que hace es, cada vez que usa el comando arrow u otro equivalente, para calcular el apropiado path comando, pero en lugar de "ejecutarlo", se almacena en una lista con todas las otras rutas resultantes de otras arrow comandos. Al final de tikzcd medio ambiente, un tikzpicture se crea, que contiene el matrix of nodes, y dentro de esa imagen, finalmente la lista de path se ejecutan los comandos, dibujando todas las flechas.

¿Entonces, qué podemos hacer?

Seria genial si tikzcd proporcionó una especie de drawAtTheEnd comando, que permite almacenar cualquier comando de dibujo tikz de la misma manera que la lista de rutas, y ejecutar los comandos almacenados al final de la tikzcd medio ambiente. De esta manera podríamos agregar otras flechas, decoraciones, definir coordenadas de nodo con overlay, remember picture para acceder desde otras partes de la página, etc.

Mientras tanto, codifiqué un truco que permite insertar una nueva ruta en la lista interna utilizada por tikzcd. La macro se llama latearrow y se necesitan cuatro argumentos:

  1. Las opciones tikz de la flecha (puedes pasar colores, to paths, pos, etc
  2. El nombre del nodo inicial, sin el tikzmatrixnode parte. Es decir: para referirse al nodo GM lo llamarás 1-1, el nodo TM será 2-2, etcétera.
  3. El nombre del nodo final (también sin el tikzmatrixnode parte)
  4. El texto de la etiqueta en la flecha.

Usando esa macro, primero puede dibujar su diagrama conmutativo completo, excepto la flecha de TM a TN, y luego agregar esa flecha al final con la sintaxis:

latearrowpos=0.75,crossing over2-24-2T f

Como se dijo, es un truco rápido y sucio, y no usa la misma sintaxis que otras flechas, no permite opciones de estilo para la etiqueta y no estoy seguro de si rompería algo, pero aparentemente funciona. Aquí está el código:

documentclassarticle
usepackagetikz-cd

makeatletter
deflatearrow#1#2#3#4%
  [email protected]
expandafter[email protected]path[/tikz/commutative diagrams/every arrow,#1]% globaledef[email protected]% the[email protected]% (tikzmatrixname-#2)% noexpand[email protected])% to% node[/tikz/commutative diagrams/every label] $#4$ (tikzmatrixname-#3)% noexpand[email protected]) ; makeatother begindocument [ begintikzcd[ampersand replacement=&,column sep=small] GM arrow[pos=0.75]rrmodels_M arrow[two heads,swap]dre_M arrow[swap]ddGf & & R^FM arrowddR^Ff \ & T M arrow[tail,swap]rum_M & \ GN arrow[pos=0.75]rrmodels_N arrow[two heads,swap]dre_N & & R^FN \ & T N arrow[tail,swap]rum_N & latearrowpos=0.75,crossing over2-24-2T f latearrowred, bend left1-12-2x endtikzcd ] enddocument

Tenga en cuenta que agregué un blue opción a esta flecha, para demostrar que funciona. Solo por diversión, agregué también una "flecha tardía" curva roja de GM a TM. Este es el resultado:

Resultado

La funcionalidad de la respuesta principal se puede obtener directamente usando tikzcd colocando el siguiente comando al final del diagrama:

arrow[from=2-2, to=4-2, pos=0.75, crossing over, "T f"']

Entonces el ejemplo completo sería:

documentclassarticle
usepackagetikz-cd
begindocument
[
begintikzcd[ampersand replacement=&,column sep=small]
  GM arrow[pos=0.75]rrmodels_M
     arrow[two heads,swap]dre_M
     arrow[swap]ddGf
     &      & 
     R^FM
       arrowddR^Ff \
     & T M 
    arrow[tail,swap]rum_M
     & \
  GN arrow[pos=0.75,crossing over]rrmodels_N
     arrow[two heads,swap]dre_N
     &      & R^FN \
     & T N 
    arrow[tail,swap]rum_N &    
    arrow[from=2-2, to=4-2, pos=0.75, crossing over, "T f"']
endtikzcd
]
enddocument 

Una solución al definir un comando latearrow

Similar a la solución dada por JLDiaz, puede definir un comando latearrow. Mi versión de latearrow está configurado para que tikzcd imprima primero las flechas normales en el orden en que aparecen, luego las latearrows en el orden en que aparecen. La sintaxis de latearrow es exactamente idéntica a la sintaxis de arrow.

Tenga en cuenta que esto maneja tanto la sintaxis nueva como la antigua correctamente, por lo que puede usar la sintaxis antigua:

latearrow[pos=0.75, crossing over,swap]ddT f

o la nueva sintaxis:

latearrow[dd,pos=0.75, crossing over,"T f"']

y ambos funcionan (hacer que esto funcione para la sintaxis anterior agregó 8 llamadas a patchcmd y tres let's).

documentclassarticle
usepackageetoolbox
usepackagetikz-cd
makeatletter

patchcmd[email protected]
    globallet[email protected][email protected]
    globallet[email protected][email protected]
    globallet[email protected][email protected]

% For some reason this patchcmd call fails =(
%patchcmdendtikzcd[email protected][email protected][email protected]

% So we have to copy the whole original version of endtikzcd
defendtikzcd%
  pgfmatrixendrowegroup%
  pgfextragloballettikzcdmatrixnametikzlastnode;%
  tikzcdsetthepgfmatrixcurrentrow-row diagram/.try%
  begingroup%
    pgfkeys% `quotes' library support
      /handlers/first char syntax/the character "/.initial=[email protected]@quotes,%
      /tikz/edge quotes mean=%
        edge node=node [execute at begin node=[email protected]$fi,%$
                         execute at end node=[email protected]$fi,%$
                         /tikz/commutative diagrams/.cd,every label,##2]##1%
    let[email protected]errmessage% improve error messages
    deferrmessage##1[email protected]##1^^J...^^Jl.[email protected]space%
        I think the culprit is a tikzcd arrow in cell 
        [email protected][email protected]%
    [email protected]@[email protected]%
    [email protected][email protected] % I just added [email protected]
  endgroup%
  endtikzpicture%
  ifnum0=`fi

letlatearrow[email protected] % patchcmd comes through for us here.
let[email protected]@arrow[email protected]@arrow
let[email protected]@new[email protected]@new
let[email protected]@old[email protected]@old
let[email protected]@getlabel[email protected]@getlabel
patchcmdlatearrow[email protected][email protected]
patchcmdlatearrow[email protected]@arrow[email protected]@arrow
patchcmdlatearrow[email protected]@old[email protected]@old
patchcmd[email protected]@arrow[email protected]@old[email protected]@old
patchcmd[email protected]@arrow[email protected]@new[email protected]@new
patchcmd[email protected]@old[email protected]@getlabel[email protected]@getlabel
patchcmd[email protected]@old[email protected]@getlabel[email protected]@getlabel
patchcmd[email protected]@old[email protected]@new[email protected]@new
patchcmd[email protected]@getlabel[email protected]@getlabel[email protected]@getlabel
patchcmd[email protected]@getlabel[email protected]@getlabel[email protected]@getlabel
patchcmd[email protected]@getlabel[email protected]@new[email protected]@new
patchcmd[email protected]@new[email protected][email protected]
def[email protected]

makeatother
begindocument
[
begintikzcd[ampersand replacement=&,column sep=small]
  GM arrow[pos=0.75]rrmodels_M
     arrow[two heads,swap]dre_M
     arrow[swap]ddGf
     &      &
     R^FM
       arrowddR^Ff \
     & T Mlatearrow[pos=0.75, crossing over,swap]ddT f 
            % Here's the latearrow call. This arrow will go on top.
    arrow[tail,swap]rum_M
     & \
  GN arrow[pos=0.75,crossing over]rrmodels_N
     arrow[two heads,swap]dre_N
     &      & R^FN \
     & T N
    arrow[tail,swap]rum_N &
endtikzcd
]
enddocument

El código funciona 1) cambiando endtikzcd para que ponga los dos [email protected] y [email protected] en el diagrama y 2) copiando el arrow código pero modificándolo para almacenar las rutas en [email protected] en lugar de [email protected]. Porque al final se usan en el orden
[email protected][email protected], todos los caminos creados usando el normal arrow El comando se imprime primero, y luego las rutas usando latearrow, cada uno en el orden en que aparecen.

Por alguna razón el patchcmd la llamada que debería hacer el paso 1 falla, así que simplemente copié la definición completa de endtikzcd y agregué el comando adicional que necesitaba.

Hago el paso 2 copiando todos los comandos internos utilizados en arrow y luego usar un montón de llamadas para patchcmd para vincularlos entre sí y para reemplazar la macro de rutas guardadas. Porque arrow tiene una sintaxis excepcionalmente complicada, hay cuatro comandos internos, cada uno de los cuales necesita hasta tres sustituciones.

Obviamente, las actualizaciones de tikzcd pueden romper este código, pero es muy simple, por lo que no debería ser difícil de arreglar.

Editar: La versión que publiqué ayer estaba rota, gracias Aaron Mazel por notarlo. Pensé erróneamente que las rutas guardadas eran locales y se vaciarían automáticamente cuando el alcance se cerrara al final del entorno. En cambio, es global y se vacía al comienzo del próximo entorno tikzcd. La solución fue agregar la línea:

patchcmd[email protected]
    globallet[email protected][email protected]
    globallet[email protected][email protected]
    globallet[email protected][email protected]

Un enfoque aquí sería romper la flecha que pasa por debajo en dos pedazos. Aquí hay algunas ideas sobre cómo hacer esto:

Una posibilidad es utilizar el hecho de que hay una celda de matriz exactamente en el punto donde desea que se rompa una de las flechas:

documentclassarticle
usepackagetikz-cd
begindocument
begintikzcd[]
   & A arrowdd   &   \
     B arrow[-]r &  arrowrphi & C \
   & D           & 
endtikzcd
enddocument

Alternativamente, puede utilizar el sistema de coordenadas perpendiculares de TikZ (consulte el manual pgf, sección 13.3.1). En el siguiente ejemplo, la flecha que comienza en B aterrizaría en D, pero modificamos la ruta real dibujada diciendo to path= tikztotarget) (los to path se explica en la sección 14.14 del manual pgf). Esto cambia el punto final de la flecha para que sea la intersección de una línea horizontal a través de tikztostart (en este caso, el nodo que contiene B) y una línea vertical a través de tikztotarget (en este caso, el nodo que contiene D). Para la segunda parte de esta flecha, procedemos de manera similar.

documentclassarticle
usepackagetikz-cd
begintikzcd[]
  &
    A arrowdd
      & \
  B arrow[-,
           shorten >=0.7ex,
           to path= tikztotarget)]
          rd
    &
      &
        C \
   &
     D arrow[shorten <=0.7ex,
              to path=(tikztostart ]
             ru
             phi
       &
endtikzcd
enddocument

Finalmente, se puede lograr una generalización de lo anterior para líneas posiblemente inclinadas o curvas utilizando el intersections biblioteca (sección 13.3.2 del manual pgf). Espero que el siguiente ejemplo se explique por sí mismo.

documentclassarticle
usepackagetikz-cd
usetikzlibraryintersections
begintikzcd
  A arrow[name path=above]rd
    & B arrow[name path=below, draw=none]ld
        arrow[name intersections=of=above and below,
               -,
               shorten >=0.7ex,
               to path=-- (intersection-1)]
        arrow[shorten <=0.7ex,
               to path=(intersection-1) -- (tikztotarget) tikztonodes]
              ldphi
    \
  C
    & D
endtikzcd
enddocument

Si sostienes alguna incertidumbre y capacidad de modernizar nuestro crónica puedes escribir una explicación y con mucho gusto lo ojearemos.

¡Haz clic para puntuar esta entrada!
(Votos: 2 Promedio: 4)



Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *