Pgfplot - Cross section of a 3D line plot (Poincare Sections)
I would use a split approach, really -- I am posting this here because I am sure that someone with Lua skills will integrate it in a standalone LaTeX source. It happens I know python... and I will learn from the other answer :-)
So I created this quick and dirty python
script to find the intercepts, by linear interpolation:
#! /usr/bin/env python3
#
# use as ./process.py filename x-coordinate-to-cut
#
import sys
xcut = float(sys.argv[2])
with open(sys.argv[1]) as f:
i=-1
for line in f:
i += 1
if i==0:
print ("p1t p2t")
continue # skip first line
data = [float(f) for f in line.split()]
if i==1:
old_data = data
continue
if (old_data[0] <= xcut and data[0] > xcut) or (old_data[0] >= xcut and data[0] < xcut):
# crossing the plane
y = old_data[1] + (data[1]-old_data[1])/(data[0]-old_data[0])*(xcut - old_data[0])
z = old_data[2] + (data[2]-old_data[2])/(data[0]-old_data[0])*(xcut - old_data[0])
print("%g %g" % (y,z))
old_data = data
And use it to create data points for the cut at p=0
:
./process.py dummy.txt 0.0 > cross0.txt
./process.py dummy.txt 100.0 > cross100.txt
./process.py dummy.txt 200.0 > cross200.txt
and now with the source:
\documentclass[border=10pt]{standalone}
\usepackage{pgfplots}\pgfplotsset{compat=1.13}
\usepackage{pgfplotstable}
\usepackage{graphicx}
\usepackage{tikz}
\usepackage{pgf}
\usepackage{mathtools}
\pgfplotsset{compat=newest}
\begin{document}
\begin{tikzpicture}
\begin{axis}[xlabel=p1, ylabel=p1t, zlabel=p2t, tick style={draw=none},
xmin=-300, xmax=300, ymin=-300, ymax=300, zmin=-300, zmax=300]
\addplot3[smooth, mark=none, color=black] table [x=p, y=p1t, z=p2t]{dummy.txt};
\draw [dashed, red] (0,-300,-300) -- (0,300,-300) -- (0,300,300) -- (0,-300,300) -- cycle;
\draw [dashed, blue] (100,-300,-300) -- (100,300,-300) -- (100,300,300) -- (100,-300,300) -- cycle;
\draw [dashed, green] (200,-300,-300) -- (200,300,-300) -- (200,300,300) -- (200,-300,300) -- cycle;
\end{axis}
\end{tikzpicture}
\begin{tikzpicture}
\begin{axis}[xlabel=p1t, ylabel=p2t, tick style={draw=none},
xmin=-300, xmax=300, ymin=-300, ymax=300]
\addplot [red, only marks] table [x=p1t, y=p2t]{cross0.txt};
\addplot [blue, only marks] table [x=p1t, y=p2t]{cross100.txt};
\addplot [green, only marks] table [x=p1t, y=p2t]{cross200.txt};
\legend{$p=0$, $p=100$, $p=200$}
\end{axis}
\end{tikzpicture}
\end{document}
I have the result:
which obviously needs a bit of love to massage a bit, but I think it's more or less what the OP wanted.
Here is the same answer as Rmano's one, but in Lualatex with everything in the same file:
\documentclass[border=10pt]{standalone}
\usepackage{pgfplots}
\usepackage{tikz}
\usepackage{pgf}
\usepackage{luacode}
\pgfplotsset{compat=newest}
\begin{document}
\begin{tikzpicture}
\begin{axis}[xlabel=p1, ylabel=p1t, zlabel=p2t, tick style={draw=none},
xmin=-300, xmax=300, ymin=-300, ymax=300, zmin=-300, zmax=300]
\addplot3[smooth, mark=none, color=black] table [x=p, y=p1t, z=p2t]{dummy.txt};
\draw [dashed, red] (0,-300,-300) -- (0,300,-300) -- (0,300,300) -- (0,-300,300) -- cycle;
\draw [dashed, blue] (100,-300,-300) -- (100,300,-300) -- (100,300,300) -- (100,-300,300) -- cycle;
\draw [dashed, green] (200,-300,-300) -- (200,300,-300) -- (200,300,300) -- (200,-300,300) -- cycle;
\end{axis}
\end{tikzpicture}
\begin{luacode*}
function split(str)
return {str:match("([^ ]*) +([^ ]*) +([^ ]*)")}
end
function plot_crosssection(filename,p1val)
local i=0
local data,olddata
for line in io.lines(filename) do
print (i,data)
i=i+1
if i==2 then data=split(line)
elseif i>2 then
olddata={data[1],data[2],data[3]}
data=split(line)
if (olddata[1]-p1val)*(data[1]-p1val)<=0 then
local y = olddata[2] + (data[2]-olddata[2])/(data[1]-olddata[1])*(p1val - olddata[1])
local z = olddata[3] + (data[3]-olddata[3])/(data[1]-olddata[1])*(p1val - olddata[1])
tex.sprint("("..y..","..z..")")
end
end
end
end
\end{luacode*}
\begin{tikzpicture}
\begin{axis}[xlabel=p1t, ylabel=p2t, tick style={draw=none},
xmin=-300, xmax=300, ymin=-300, ymax=300]
\addplot [red, only marks] coordinates {\directlua{plot_crosssection("dummy.txt",0);}};
\addplot [blue, only marks] coordinates {\directlua{plot_crosssection("dummy.txt",100);}};
\addplot [green, only marks] coordinates {\directlua{plot_crosssection("dummy.txt",200);}};
\legend{$p=0$, $p=100$, $p=200$}
\end{axis}
\end{tikzpicture}
\end{document}
Compile it with lualatex
. I have used a very simple way to read this .txt
file, but you can also use the csv.lua
library for this.