Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Issue with two matrices and positioning #1

Closed
Epithumia opened this issue Jul 17, 2014 · 12 comments
Closed

Issue with two matrices and positioning #1

Epithumia opened this issue Jul 17, 2014 · 12 comments

Comments

@Epithumia
Copy link

Epithumia commented Jul 17, 2014

There is a significant issue with the style contour and style grid functions: any repositioning of the matrix screws up placement of the border.

Consider the following example:

\documentclass[a4paper,10pt]{report}
\usepackage{tikz}

\usetikzlibrary{matrix,matrix.skeleton}
\usetikzlibrary{positioning}
\begin{document}

\begin{tikzpicture}
    % create matrix `A'
        \matrix [ampersand replacement=\&,
                 matrix of nodes, 
                 style grid = {draw, thin}, 
                 style contour={draw, thick},
        ] (A) {
            aa \& ba \& ca \& da \\
            ab \& bb \& cb \& db \\
        };
    % create matrix `B'
    % align both matrices at the top
        \matrix [ampersand replacement=\&,
            matrix of nodes,
            style grid = {draw, thin},
            style contour={draw, thick},
            matrix anchor=north west,
            right=0pt of A.north east,
        ] (B) {
            aa \& ba \\
            ab \& bb \\
            ac \& bc \\
            ad \& bd \\
        };
    % show that matrix `A' and `B' are aligned at the top
        \fill [green] (A.north east) circle (3pt);
        \fill [red]   (B.north west) circle (2pt);
    \end{tikzpicture} 
\end{document}

(image added by @dudebout on 2021/02/09)
2021-02-09-204816_236x114_scrot

You will see that the contents of the matrix is aligned/anchored as it should, but the outline of the second matrix is off.
In general, any absolute positioning of the matrix also sends the outline flying, for example

\documentclass[a4paper,10pt]{report}
\usepackage{tikz}

\usetikzlibrary{matrix,matrix.skeleton}
\usetikzlibrary{positioning}
\begin{document}

\begin{tikzpicture}[remember picture,overlay]
    % create matrix `A'
        \matrix [ampersand replacement=\&,
                 matrix of nodes,
                 style grid = {draw, thin},
                 style contour={draw, thick},
        ] at (current page.center) (A) {
            aa \& ba \& ca \& da \\
            ab \& bb \& cb \& db \\
        };
    % create matrix `B'
    % align both matrices at the top
        \matrix [ampersand replacement=\&,
            matrix of nodes,
            style grid = {draw, thin},
            style contour={draw, thick},
            matrix anchor=north west,
            right=0pt of A.north east,
        ] (B) {
            aa \& ba \\
            ab \& bb \\
            ac \& bc \\
            ad \& bd \\
        };
    % show that matrix `A' and `B' are aligned at the top
        \fill [green] (A.north east) circle (3pt);
        \fill [red]   (B.north west) circle (2pt);
    \end{tikzpicture} 
\end{document}

(image added by @dudebout on 2021/02/09)
2021-02-09-205033_409x449_scrot

I'm not sure what is happening, but somehow, the row and column coordinates aren't calculated correctly, while the cells are, see for example when you add

\path [draw, thick,red] (A-row-1.north west) -- (A-1-4.north east) -- (A-2-4.south east) -- (A-2-1.south west) -- cycle;

right before creating matrix B.
Most likely, moving ths matrix causes the row/col corrdinates to be computed twice: once with the right position, and then the shifting is applied again.

@dudebout
Copy link
Owner

I do not think I ever tried the code on multiple matrices. I will have a
look at it tonight or this weekend.
On Jul 17, 2014 12:43 PM, "Epithumia" notifications@github.com wrote:

There is a significant issue with the style contour and style grid
functions: any repositioning of the matrix screws up placement of the
border.

Consider the following example:

\documentclass[a4paper,10pt]{report}\usepackage{tikz}
\usetikzlibrary{matrix,matrix.skeleton}\usetikzlibrary{positioning}\begin{document}
\begin{tikzpicture}
% create matrix A' \matrix [ampersand replacement=\&, matrix of nodes, style grid = {draw, thin}, style contour={draw, thick}, ] (A) { aa \& ba \& ca \& da \\ ab \& bb \& cb \& db \\ }; % create matrixB'
% align both matrices at the top
\matrix ampersand replacement=&,
matrix of nodes,
style grid = {draw, thin},
style contour={draw, thick},
matrix anchor=north west,
right=0pt of A.north east,
{
aa & ba
ab & bb
ac & bc
ad & bd
};
% show that matrix A' andB' are aligned at the top
\fill [green](A.north east) circle (3pt);
\fill [red](B.north west) circle (2pt);
\end{tikzpicture} \end{document}

You will see that the contents of the matrix is aligned/anchored as it
should, but the outline of the second matrix is off.
In general, any absolute positioning of the matrix also sends the outline
flying, for example

\documentclass[a4paper,10pt]{report}\usepackage{tikz}
\usetikzlibrary{matrix,matrix.skeleton}\usetikzlibrary{positioning}\begin{document}
\begin{tikzpicture}[remember picture,overlay]
% create matrix A' \matrix [ampersand replacement=\&, matrix of nodes, style grid = {draw, thin}, style contour={draw, thick}, ] at (current page.center) (A) { aa \& ba \& ca \& da \\ ab \& bb \& cb \& db \\ }; % create matrixB'
% align both matrices at the top
\matrix ampersand replacement=&,
matrix of nodes,
style grid = {draw, thin},
style contour={draw, thick},
matrix anchor=north west,
right=0pt of A.north east,
{
aa & ba
ab & bb
ac & bc
ad & bd
};
% show that matrix A' andB' are aligned at the top
\fill [green](A.north east) circle (3pt);
\fill [red](B.north west) circle (2pt);
\end{tikzpicture} \end{document}

I'm not ure what is happening, but somehow, the row and column coordinates
aren't calculated correctly, while the cells are, see for example when you
add

\path [draw, thick,red](A-row-1.north west) -- (A-1-4.north east) -- (A-2-4.south east) -- (A-2-1.south west) -- cycle;

right before creating matrix B.
Most likely, moving th matrix causes the row/col corrdinates to be
computed twice: once with the right position, and then the shifting is
applied again.


Reply to this email directly or view it on GitHub
#1.

@Epithumia
Copy link
Author

Thanks for looking at it. I resorted to using subfigures to place them, but it really is unsatisfying compared to anchoring or absolute positioning.
I discovered it because I had to place multiple matrices, but really, it will happen with just one aswell, in my second example, you can try with just matrix A and see it in action.

@dudebout
Copy link
Owner

I have a good understanding of the bug but no real fix yet. This line is the root of the problem.

Once the skeleton elements are built, they need to be shifted in place to coincide with the actual matrix. To do so, they should be translated along a vector going from the anchor of the matrix to the lower left corner of the matrix.

The currently implemented shift is off by a vector from the most recently used (x, y) coordinate to to the anchor. In the case of a single matrix without a positioning in at, this vector is 0. This is why I never saw this bug.

In your your first example, the most recently used (x, y) coordinate is at the center of matrix A. To verify this claim, just use \fill [blue] circle (4pt);. You can verify that the grid is off by the vector blue-green.

I have tried to fix the faulty line, but have not found the right variables quite yet. Feel free to give it a try, or I should be able to solve it over the weekend.

@Epithumia
Copy link
Author

That doesn't look quite right, check in my first example with the following lines at the end (you need to add \usetikzlibrary{calc} in the preamble):

% show that matrix `A' and `B' are aligned at the top
\fill [blue] circle (1pt);
\fill [green] (A-row-1.north east) circle (1pt);
\fill [red]  (B.north west) circle (1pt);
\fill [cyan] (B-row-1.north west) circle (1pt);
\fill [yellow] (B-1-1.north west) circle (1pt);
% Cyan-Red vector
\draw [red] (B-1-1.north west) -- (B-row-1.north west);
% Transposed to star from yellow and green
\draw [red] ($(B-1-1.north west)-($(B-row-1.north west)-(B.north west)$)$) -- (B.north west);
\draw [red] ($(B-1-1.north west)-($(B-row-1.north west)-(A-row-1.north east)$)$) -- (A-row-1.north east);
% Cyan-Yellow vector
\draw [blue] (B-row-1.north west) -- (B.north west);
% Transposed to start from red and green
\draw [blue] ($(B.north west)-($(B-row-1.north west)-(B-1-1.north west)$)$) -- (B-1-1.north west);
\draw [blue] ($(B.north west)-($(B-row-1.north west)-(A-row-1.north east)$)$) -- (A-row-1.north east);

Neither vector matches vector Blue-Green.

@dudebout
Copy link
Owner

Indeed. This vector seems to be giving the general direction but needs a little adjustment that seems to be inner sep related. For proof, set inner sep=0pt on both matrices and the vectors do align. One more corrective term will be needed: see what happens when you do right=10pt of A.north east in matrix B, but it seems that this correction is just 10pt.

I forgot to mention last night that, in the meantime, you might want to use anchor = north east in matrix A as a work around. Having both matrices share the anchor solves the problem.

@Epithumia
Copy link
Author

For what it's worth, here is a semi-workaround I found inspired by one of the tikz examples on texamples.net, here's a sample of it in use:

\begin{tikzpicture}[remember picture]
\matrix (m2) [ampersand replacement=\&,
    matrix of nodes, label skeleton, inner sep=0pt, nodes={inner sep=0.2cm,scale=0.55},style contour = {draw, thick}, xshift=2cm,yshift=1cm
%style grid = {draw, thin},
        ]
  {
  \phantom{NumVoyage} \& \phantom{DureeTotale} \& \phantom{NbEtapes} \\
    \phantom{12345} \& \phantom{67890} \& ~ \\
    \phantom{12345} \& \phantom{67890} \& ~ \\
    \phantom{12345} \& \phantom{67890} \& ~ \\
    \phantom{12345} \& \phantom{67890} \& ~ \\
    \phantom{12345} \& \phantom{67890} \& ~ \\
    \phantom{12345} \& \phantom{67890} \& ~ \\
    \phantom{12345} \& \phantom{67890} \& ~ \\ 
    \phantom{12345} \& \phantom{67890} \& ~ \\
    \phantom{12345} \& \phantom{67890} \& ~ \\
    \phantom{12345} \& \phantom{67890} \& ~ \\
    \phantom{12345} \& \phantom{67890} \& ~ \\
    \phantom{12345} \& \phantom{67890} \& ~ \\
    \phantom{12345} \& \phantom{67890} \& ~ \\
    \phantom{12345} \& \phantom{67890} \& ~ \\
  };
%Headers    
\node [scale=0.55,inner sep=0cm] at (m2-cell-1-1.center) {NumVoyage};
\node [scale=0.55,inner sep=0cm] at (m2-cell-1-2.center) {DureeTotale};
\node [scale=0.55,inner sep=0cm] at (m2-cell-1-3.center) {NbEtapes};

%Data on line 3 (rowspan 2-4)
\node [fit = (m2-cell-3-1) (m2-cell-3-1),inner sep=0.2cm,scale=0.55] {\textcolor[rgb]{0,0,1}{4}};
\node [fit = (m2-cell-3-2) (m2-cell-3-2),inner sep=0.2cm,scale=0.55] {\textcolor[rgb]{0,0,1}{6}};
\node [fit = (m2-cell-3-3) (m2-cell-3-3),inner sep=0.2cm,scale=0.55] {\textcolor[rgb]{0,0,1}{3}};

%Center some data in the middle of the rowspan
\node [fit = (m2-cell-7-1) (m2-cell-8-1),inner sep=0.2cm,scale=0.55] {\textcolor[rgb]{0,1,0}{5}};
\node [fit = (m2-cell-7-2) (m2-cell-8-2),inner sep=0.2cm,scale=0.55] {\textcolor[rgb]{0,1,0}{16}};
\node [fit = (m2-cell-7-3) (m2-cell-8-3),inner sep=0.2cm,scale=0.55] {\textcolor[rgb]{0,1,0}{6}};

%Last bit of data
\node [fit = (m2-cell-13-1) (m2-cell-13-1),inner sep=0.2cm,scale=0.55] {\textcolor[rgb]{1,0,0}{8}};
\node [fit = (m2-cell-13-2) (m2-cell-13-2),inner sep=0.2cm,scale=0.55] {\textcolor[rgb]{1,0,0}{15}};
\node [fit = (m2-cell-13-3) (m2-cell-13-3),inner sep=0.2cm,scale=0.55] {\textcolor[rgb]{1,0,0}{5}};

%Vertical lines between columns
\draw (m2-cell-1-2.north west) -- (m2-cell-15-2.south west);
\draw (m2-cell-1-3.north west) -- (m2-cell-15-3.south west);
%Horizontal lines to make rowspans
\draw (m2-cell-1-1.south west) -- (m2-cell-1-3.south east);
\draw (m2-cell-4-1.south west) -- (m2-cell-4-3.south east);
\draw (m2-cell-10-1.south west) -- (m2-cell-10-3.south east);
\begin{pgfonlayer}{background}
\node [fit = (m2-cell-1-1) (m2-cell-1-3), fill=blue!7, inner sep=0pt] {};
\end{pgfonlayer}
\end{tikzpicture}

Basically the idea is to phantom the contents and later place the actual content in place. It will still misplace everything (if you anchor at (2,2) it will put the visible matrix somewhere that's not (2,2)), but you can now place it anywhere in the page, if only through trial and error to get the position right where you want.

@dudebout dudebout changed the title Matrix positioning and borders Issue with two matrices and positioning Feb 10, 2021
@onursehitoglu
Copy link
Contributor

I needed multiple positioned matrices and hit this issue.The following patch seems to solve it:

diff --git a/pgflibrarymatrix.skeleton.code.tex b/pgflibrarymatrix.skeleton.code.tex
index b031338..d2d876a 100644
--- a/pgflibrarymatrix.skeleton.code.tex
+++ b/pgflibrarymatrix.skeleton.code.tex
@@ -16,8 +16,13 @@
   \xdef\pgf@matrix@skel@innerxsep{\pgfkeysvalueof{/pgf/inner xsep}}%
   \xdef\pgf@matrix@skel@innerysep{\pgfkeysvalueof{/pgf/inner ysep}}%
   \pgfscope%
-    \pgfgetlastxy\ck@shift@x\ck@shift@y
-    \pgftransformshift{\pgfpoint{\ck@shift@x}{\ck@shift@y}}%
+    %\pgfgetlastxy\ck@shift@x\ck@shift@y
+    %\pgftransformshift{\pgfpoint{\ck@shift@x}{\ck@shift@y}}%
+       \pgf@yb=\csname pgf@matrix@maxy\the\pgfmatrixcurrentrow\endcsname%
+       \pgf@process{\pgfpointanchor{\tikz@fig@name}{south west}}%
+       \pgfmathsetlength\pgf@xa{\pgf@x+\pgf@matrix@skel@innerxsep}%
+       \pgfmathsetlength\pgf@ya{\pgf@y+\pgf@yb}%
+    \pgftransformshift{\pgfpoint{\pgf@xa}{\pgf@ya}}%
     \pgfset{inner sep=0pt}%
     \pgf@matrix@skeleton@create@cells%
     \pgf@matrix@skeleton@create@tiling@cells%

@dudebout
Copy link
Owner

Thanks Onur.

@onursehitoglu
Copy link
Contributor

I believe it breaks some regular cases in the manual. I will work on it.

@onursehitoglu
Copy link
Contributor

I believe I had a solution this time. It works for the examples in the manual and the issues here:

diff --git a/pgflibrarymatrix.skeleton.code.tex b/pgflibrarymatrix.skeleton.code.tex
index b031338..16d6010 100644
--- a/pgflibrarymatrix.skeleton.code.tex
+++ b/pgflibrarymatrix.skeleton.code.tex
@@ -16,8 +16,23 @@
   \xdef\pgf@matrix@skel@innerxsep{\pgfkeysvalueof{/pgf/inner xsep}}%
   \xdef\pgf@matrix@skel@innerysep{\pgfkeysvalueof{/pgf/inner ysep}}%
   \pgfscope%
-    \pgfgetlastxy\ck@shift@x\ck@shift@y
-    \pgftransformshift{\pgfpoint{\ck@shift@x}{\ck@shift@y}}%
+    \xdef\ck@shift@y{0pt}%  store extra  y shift from south west matrix anchor
+	\pgf@process{\pgfpointanchor{\tikz@fig@name}{south west}}%    Bottom left corner
+	\pgfmathsetlength\pgf@xa{\pgf@x+\pgf@matrix@skel@innerxsep}%
+	\pgfmathsetlength\pgf@ya{\pgf@y+\pgf@matrix@skel@innerysep}%
+	% find any node in the last row and set \ck@shift@y to difference between text and south anchors
+  	\foreach \pgf@matrix@skel@col in {1, ..., \pgf@matrix@numberofcolumns} {%
+		\pgfutil@ifundefined{pgf@sh@ns@\tikz@fig@name-\the\pgfmatrixcurrentrow-\pgf@matrix@skel@col}{}{%
+			\pgf@process{\pgfpointanchor{\tikz@fig@name-\the\pgfmatrixcurrentrow-\pgf@matrix@skel@col}{text}}%
+			\pgf@yb=\pgf@y%
+			\pgf@process{\pgfpointanchor{\tikz@fig@name-\the\pgfmatrixcurrentrow-\pgf@matrix@skel@col}{south}}%
+			\pgfmathsetlength\pgf@yb{\pgf@yb-\pgf@y}%
+			\xdef\ck@shift@y{\the\pgf@yb}%
+			\breakforeach%
+		}%
+	}%
+	\pgfmathaddtolength{\pgf@ya}{\ck@shift@y}%
+   	\pgftransformshift{\pgfpoint{\pgf@xa}{\pgf@ya}}%
     \pgfset{inner sep=0pt}%
     \pgf@matrix@skeleton@create@cells%
     \pgf@matrix@skeleton@create@tiling@cells%

I transform to south west anchor of matrix + inner seps . That keeps the positioning right. However y needs an extra shift in the distance of last rows text and the bottom. The ugly \foreach inside fixes that.

@dudebout
Copy link
Owner

That sounds great @onursehitoglu. Could you create a PR with that change? We can then start verifying it works against all the examples in this repo and all the reports of the issue.

@dudebout
Copy link
Owner

Thanks to @onursehitoglu, this issue has been resolved!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants