我想知道如何绘制类似下图的东西:
我一直在研究该代码:
\documentclass[12pt]{article}
\usepackage{tikz}
\usetikzlibrary{matrix, calc, backgrounds, decorations.pathreplacing}
\begin{document}
\begin{tikzpicture}[thick]
\foreach[count=\i] \a in {0,2,4,6,8}
{
\foreach[count=\j] \a in {0,2,4,6,8}
{
\foreach[count=\k] \a in {0,2,4,6,8}
{
\node at (\i,\j,\k) [circle,fill=black] {};
}
}
}
\end{tikzpicture}
\end{document}
但目前结果并不好:
我必须绘制一个 5 x 5 x 5 的立方体,并且我想使用不同的颜色突出显示中心体素 (3, 3, 3) 及其尺寸邻域 (3 x 3 x 3)。
我正在努力适应这代码来生成“好看”的图像并绘制连接。但是,我不太理解。
先感谢您。
答案1
这里有两个\tikzset
版本。本质区别在于的内容 \pgfmathparse{}
,也就是公式距离。
我喜欢 L-1 规范
\tikzset{
blur/.style={preaction={draw,fill,white,opacity=.9,line width=2pt}},
showdepth/.style={color=#1,ball color=#1,opacity=1+(\k-2)/5},
edgemeta/.is choice,
edgemeta/1/.style={blur,showdepth=blue!66!green},
edgemeta/2/.style={blur,showdepth=green!66!blue},
edgemeta/3/.style={blur,showdepth=green},
edgemeta/4/.style={blur,showdepth=green!66!yellow},
edgemeta/5/.style={blur,showdepth=yellow!66!green},
edgemeta/6/.style={blur,showdepth=yellow},
nodemeta/.is choice,
nodemeta/0/.style={blur,showdepth=blue},
nodemeta/1/.style={blur,showdepth=blue!66!green},
nodemeta/2/.style={blur,showdepth=green!66!blue},
nodemeta/3/.style={blur,showdepth=green},
nodemeta/4/.style={blur,showdepth=green!66!yellow},
nodemeta/5/.style={blur,showdepth=yellow!66!green},
nodemeta/6/.style={blur,showdepth=yellow},
drawedge/.style={drawedgex,drawedgey,drawedgez},
drawedgex/.code={
\ifnum\i=2\else
\pgfmathparse{int(max(abs(\i),abs(\i+1))+abs(\j)+abs(\k))}
\draw[edgemeta=\pgfmathresult](\i,\j,\k)--+(1,0,0);
\fi
},
drawedgey/.code={
\ifnum\j=2\else
\pgfmathparse{int(abs(\i)+max(abs(\j),abs(\j+1))+abs(\k))}
\draw[edgemeta=\pgfmathresult](\i,\j,\k)--+(0,1,0);
\fi
},
drawedgez/.code={
\ifnum\k=2\else
\pgfmathparse{int(abs(\i)+abs(\j)+max(abs(\k),abs(\k+1)))}
\draw[edgemeta=\pgfmathresult](\i,\j,\k)--+(0,0,1);
\fi
},
drawnode/.code={
\pgfmathparse{int(abs(\i)+abs(\j)+abs(\k))}
\shade[nodemeta=\pgfmathresult](\i,\j,\k)circle(3pt);
}
}
\begin{tikzpicture}[z={(-.28,-.15)},draw=white]
\foreach\k in{-2,...,2}{
\foreach\j in{-2,...,2}{
\foreach\i in{-2,...,2}{
\path[drawedge,drawnode];
}
}
}
\end{tikzpicture}
我喜欢 L-∞ 范数
\documentclass[tikz,border=9]{standalone}
\begin{document}
\tikzset{
blur/.style={preaction={draw,fill,white,opacity=.9,line width=2pt}},
showdepth/.style={color=#1,ball color=#1,opacity=1+(\k-2)/5},
edgemeta/.is choice,
edgemeta/1/.style={blur,showdepth=green},
edgemeta/2/.style={blur,showdepth=yellow},
nodemeta/.is choice,
nodemeta/0/.style={blur,showdepth=blue},
nodemeta/1/.style={blur,showdepth=green},
nodemeta/2/.style={blur,showdepth=yellow},
drawedge/.style={drawedgex,drawedgey,drawedgez},
drawedgex/.code={
\ifnum\i=2\else
\pgfmathparse{int(max(abs(\i),abs(\i+1),abs(\j),abs(\k)))}
\draw[edgemeta=\pgfmathresult](\i,\j,\k)--+(1,0,0);
\fi
},
drawedgey/.code={
\ifnum\j=2\else
\pgfmathparse{int(max(abs(\i),abs(\j),abs(\j+1),abs(\k)))}
\draw[edgemeta=\pgfmathresult](\i,\j,\k)--+(0,1,0);
\fi
},
drawedgez/.code={
\ifnum\k=2\else
\pgfmathparse{int(max(abs(\i),abs(\j),abs(\k),abs(\k+1)))}
\draw[edgemeta=\pgfmathresult](\i,\j,\k)--+(0,0,1);
\fi
},
drawnode/.code={
\pgfmathparse{int(max(abs(\i),abs(\j),abs(\k)))}
\shade[nodemeta=\pgfmathresult](\i,\j,\k)circle(3pt);
}
}
\begin{tikzpicture}[z={(-.3,-.15)},draw=white]
\foreach\k in{-2,...,2}{
\foreach\j in{-2,...,2}{
\foreach\i in{-2,...,2}{
\path[drawedge,drawnode];
}
}
}
\end{tikzpicture}
\end{document}
我想要插入文字
\tikzset{
drawnode/.code={
\pgfmathparse{int(max(abs(\i),abs(\j),abs(\k)))}
\node at(\i,\j,\k)[circle,nodemeta=\pgfmathresult]{\color{black}\tikzset{textnode/\i/\j/\k/.try}};
}
}
\begin{tikzpicture}[scale=2,z={(-.28,-.15)},draw=white,textnode/1/0/-1/.code={(-2,0,-1)}]
\foreach\k in{-2,...,2}{
\foreach\j in{-2,...,2}{
\foreach\i in{-2,...,2}{
\path[drawedge,drawnode];
}
}
}
答案2
一个tikz-3dplot
办法。
代码
\documentclass{article}
\usepackage{tikz}
\usepackage{tikz-3dplot}
\usetikzlibrary{shapes,calc,positioning,intersections}
\tdplotsetmaincoords{80}{120}
\begin{document}
\begin{tikzpicture}[scale=3, tdplot_main_coords,axis/.style={->},thick]
\foreach \x in {0,1,2}
\foreach \y in {0,1,2}
\foreach \z in {0,1,2}
{
\draw[thick,opacity=1] (\x,0,\z) -- (\x,2,\z);
\draw[thick,opacity=1] (0,\y,\z) -- (2,\y,\z);
\draw[thick,opacity=1] (\x,\y,0) -- (\x,\y,2);
}
% --- labels for vertices
\foreach \x in {0,1,2}
\foreach \y in {0,1,2}
\foreach \z in {0,1,2}
{\draw[fill=gray!10] (\x,\y,\z) circle (0.3em);}
\foreach \x/\y in {1/0,2/1,1/2,0/1}
\foreach \z in {0,2}
{\draw[fill=gray!50] (\x,\y,\z) circle (0.3em);}
\foreach \x/\y in {2/0,2/2,0/2,0/0}
\foreach \z in {1}
{\draw[fill=gray!50] (\x,\y,\z) circle (0.3em);}
\foreach \x/\y in {1/0,2/1,1/2,0/1}
\foreach \z in {1}
{\draw[fill=gray!90] (\x,\y,\z) circle (0.3em);}
\foreach \x/\y in {1/1}
\foreach \z in {0,1,2}
{\draw[fill=gray] (\x,\y,\z) circle (0.3em);}
\end{tikzpicture}
\end{document}
答案3
如果简单的等距投影足够好,那么你可以得到相当不错的结果元帖子。
prologues := 3;
outputtemplate := "%j%c.eps";
vardef odraw expr p = undraw p withpen pencircle scaled 1.2; draw p enddef;
beginfig(1);
path p[];
transform t; t = identity shifted (27,12);
p0 = unitsquare scaled 90;
p1 = p0 transformed t;
p2 = p1 transformed t;
% draw the back first
odraw p2; odraw point 0.5 of p2 -- point 2.5 of p2; odraw point 1.5 of p2 -- point 3.5 of p2;
% draw LH sides
for t=0 step 1/2 until 7/2:
odraw point t of p0 -- point t of p2;
endfor
% now the rest
odraw p1; odraw point 0.5 of p1 -- point 2.5 of p1; odraw point 1.5 of p1 -- point 3.5 of p1;
odraw center p0 -- center p2;
odraw p0; odraw point 0.5 of p0 -- point 2.5 of p0; odraw point 1.5 of p0 -- point 3.5 of p0;
picture b[]; d=8;
b1 = image(fill fullcircle scaled d withcolor .8[red,white]; draw fullcircle scaled d;);
b2 = image(fill fullcircle scaled d withcolor .5[red,white]; draw fullcircle scaled d;);
b3 = image(fill fullcircle scaled d withcolor .1[red,blue]; draw fullcircle scaled d;);
forsuffixes $=0,2:
for t=0 upto 3:
draw b1 shifted point t of p$;
draw b2 shifted point t+1/2 of p$;
endfor
draw b3 shifted center p$;
endfor
for t=0 upto 3:
draw b2 shifted point t of p1;
draw b3 shifted point t+1/2 of p1;
endfor
draw b1 shifted center p1;
endfig;
end.
答案4
首先,我尝试了欧几里得范数,并将计算出的距离四舍五入为一系列 TikZ 样式,后来我尝试了符号 1 推荐的绝对值范数,以使用 Lua 中的递归算法验证我的尝试。我将其作为所给答案的有效替代方案附上。
-- texlua mal-recursive.lua, 2015-03-14
-- A snippet to find a level of nodes from a specific node.
-- I am testing recursive approach, however, the L-1 norm is more effective.
function searchit(malx,maly,malz, mallevel)
-- an initial point
print("Finding neighbours in volume...")
maxlevel = mallevel -- from local to global
-- local testing=fromx -- from global to local
malp = malx.." "..maly.." "..malz -- a small data trick if point was tested earlier
data = {
[malp] = {
x = malx,
y = maly,
z = malz,
level = 0
}
} -- initial value
neighbours(data[malp])
print("Saving nodes to a TikZ file...")
occupied(data)
end -- searchit
-- The core of the program...
function neighbours(point)
if point.level<maxlevel then
for _, newpoint in pairs{ {-1,0,0},{1,0,0},{0,-1,0},{0,1,0},{0,0,-1},{0,0,1} } do
--print(dlevel, point.x+dx.." "..point.y+dy.." "..point.z+dz)
newx = point.x+newpoint[1]
newy = point.y+newpoint[2]
newz = point.z+newpoint[3]
testing = newx.." "..newy.." "..newz
if not data[testing] or point.level <= data[testing].level then
-- test an untested point or retest higher level point recursively
data[testing] = {
x = newx,
y = newy,
z = newz,
level = point.level + 1}
neighbours(data[testing])
end -- test a point
end -- for cycle for all 6 directions
end -- if, test a level
end -- function neighbours
function occupied(maldata)
-- Drawing lines...
saveme=io.open("mal-result.tikz","w")
-- This is not effective as it uses many lines, but it is a short TeX code.
saveme:write([[\foreach \z in {]]..fromz..[[,...,]]..uptoz..[[} { % from back to front
\foreach \y in {]]..fromy..[[,...,]]..uptoy..[[} { % from bottom to up
\foreach \x in {]]..fromx..[[,...,]]..uptox..[[} { % from left to right
\ifnum\x<]]..uptox..[[ \draw[line] (\x,\y,\z)--(\x+1,\y,\z); \fi
\ifnum\y<]]..uptoy..[[ \draw[line] (\x,\y,\z)--(\x,\y+1,\z); \fi
\ifnum\z<]]..uptoz..[[ \draw[line] (\x,\y,\z)--(\x,\y,\z+1); \fi
}}} % \z, \y, \x
]]
) -- print or :write
-- Drawing nodes in styles...
for z=fromz, uptoz do
for y=fromy, uptoy do
for x=fromx, uptox do
test=x.." "..y.." "..z
--[[if not data[test] then
-- print("Not found: ("..test..")")
else --
-- print("("..test.."), level "..data[test].level)
end -- if]]
if data[test] then mallevel=data[test].level else mallevel="nil" end
saveme:write("\\node["..mallevel.."] at ("..x..","..y..","..z..") {};\n")
end
end
end -- for x, y, z
saveme:close()
end -- function occupied
-- For user manipulation, an initial setting of the volume...
--fromx=0; fromy=0; fromz=0 -- lower corner
--uptox=6; uptoy=6; uptoz=6 -- upper corner
--searchit(2,2,2, 5) -- (x,y,z), maxlevel
-- OP's request
fromx=1; fromy=1; fromz=1 -- lower corner
uptox=5; uptoy=5; uptoz=5 -- upper corner
--fromx=2; fromy=2; fromz=2 -- lower corner
--uptox=4; uptoy=4; uptoz=4 -- upper corner
searchit(3,3,3, 3)
--[[ Malipivo's testing example...
fromx=1; fromy=1; fromz=1 -- lower corner
uptox=10; uptoy=10; uptoz=10 -- upper corner
searchit(5,5,7, 6)]]
-- A tip for possible animation of growing levels...
--searchit(3,3,3, 0)
--searchit(3,3,3, 1)
--searchit(3,3,3, 2)
--searchit(3,3,3, 3)
我们运行texlua mal-recursive.lua
。我们收到有关进度的消息,并mal-result.tikz
生成一个 TikZ 文件,该文件随后由 LaTeX 加载。
% texlua mal-recursive.lua
% *latex mal-volume.tex
\documentclass[a4paper]{article}
\pagestyle{empty}
\usepackage{tikz}
% In case I don't want to use z= directly, use:
%\usepackage{tikz-3dplot}
%\tdplotsetmaincoords{25}{25}
\begin{document}
\tikzset{inner sep=0pt, outer sep=0pt,
every node/.append style={minimum width=1.8mm, circle, draw=gray},
% nodes without assigned level, nil is a Lua term for an undefined variable
nil/.style={ball color=white},
0/.style={ball color=red},
1/.style={ball color=blue},
2/.style={ball color=green},
3/.style={ball color=orange},
4/.style={ball color=yellow},
5/.style={ball color=brown},
6/.style={ball color=black},
line/.style={gray, line width=.2pt},
}
% My second attempt...
\begin{tikzpicture}[z={(-.3,-.15)}]%[tdplot_main_coords]
% a skeleton of volume and
% nodes with levels
\input mal-result.tikz
\end{tikzpicture}
\newpage
% My first attempt...
\begin{tikzpicture}[z={(-.3,-.15)}] %[tdplot_main_coords]
% This doesn't work well for all points as OP's requested...
\foreach \z in {1,...,5} { % from back to front
\foreach \y in {1,...,5} { % from bottom to up
\foreach \x in {1,...,5} { % from left to right
% a skeleton of volume
\ifnum\x<5 \draw[line] (\x,\y,\z)--(\x+1,\y,\z); \fi
\ifnum\y<5 \draw[line] (\x,\y,\z)--(\x,\y+1,\z); \fi
\ifnum\z<5 \draw[line] (\x,\y,\z)--(\x,\y,\z+1); \fi
% nodes with levels
%\pgfmathparse{int(ceil(sqrt((\x-3)^2+(\y-3)^2+(\z-3)^2)))} % an Euclidean distance from the center, (3,3,3)
\pgfmathparse{int(abs(\x-3)+abs(\y-3)+abs(\z-3))} % L-1 norm for comparison
\def\malstyle{\pgfmathresult}
\ifnum\pgfmathresult>3 \def\malstyle{nil} \fi % 3+
\node[\malstyle] at (\x,\y,\z) {};
}}} % \z, \y, \x
\end{tikzpicture}
\end{document}
我们运行任何主流的 LaTeX 引擎,例如lualatex mal-volume.tex
。我们得到两页相同的图片。第一张图片由 Lua 代码片段(递归算法)生成,第二张图片使用符号 1 的思想,并考虑到 L-1 范数。
我们可以重新定义级别的样式,因为它在 TikZ 中很常见。图片如下所示。