更新

更新

如何获得新的重新计算的随机模式?这个在任何地方翻译都是一样的。

编辑

我完全理解这种模式计算一次并绘制之后多次

我的问题是,如何改变这种情况:使用图案的机制来绘制一个区域,但是强制在每次绘图时重新计算图案。对于通常的模式来说,它是无用的,但在这种情况下可以提取代码并切换顺序,并在填充区域的循环内插入模式计算和绘制:一种可以用作正常模式语法的模式二。

如果可能的话,我对 TeX 编程的了解还不够。当然,这样的工作值得奖励!

enter image description here

\documentclass[tikz,margin=3pt]{standalone}
\usetikzlibrary{patterns}

\pgfdeclarepatternformonly{Rnd}
{\pgfpointorigin}{\pgfpoint{1cm}{1cm}}
{\pgfpoint{.5cm}{.5cm}}
{\foreach \i in {1,...,100} {%
    \pgfpathcircle{%
        %\pgfpoint{.25cm}{.25cm}}{.4pt}
        \pgfpoint{rnd*.5cm}{rnd*.5cm}}{.25pt}}
    \pgfusepath{fill}
}

\begin{document}
\begin{tikzpicture}

\draw[pattern=Rnd] (0,0) rectangle (5,5) ;
\end{tikzpicture}

\end{document}

答案1

正如评论中所解释的,模式的代码只被评估一次,因此每次重复模式时不能有新的随机点,但必须有在定义模式时计算的相同随机点。

我在评论中建议定义一个与页面大小相同的“巨大图案”。但是,经过一些测试后,我发现这个解决方案并不实用。为了用与您发布的图像中类似的点密度覆盖页面,应该生成数万个点,而时间是令人望而却步的。即使这应该在定义图案时评估一次,而不是在每次使用图案时都评估一次,时间也会过长。

这里还有另一个您可以尝试的想法。

首先,生成一个包含“稀疏”随机模式的pdf:

% This is random-pattern.tex
\documentclass{standalone}
\usepackage{tikz}
\begin{document}
\begin{tikzpicture}
\foreach \i in {1,...,500}
  \fill (rnd*5cm, rnd*5cm) circle (.25pt);
\end{tikzpicture}
\end{document}

编译只需不到 2 秒,并生成以下内容random-pattern.pdf

random

现在,您可以将此图像用作“基本印章”,您可以在图形中随机放置和旋转几次以创建更密集的图案:

\documentclass[tikz,margin=3pt]{standalone}
\begin{document}
\begin{tikzpicture}
\draw[clip] (0,0) rectangle (5,5);
\foreach \i in {1,...,100} {
  \node[rotate=360*rnd] at (-5+rnd*5cm, -5+rnd*5cm) {\includegraphics{random-pattern}};
}
\draw[thick] (0,0) rectangle (5,5);
\end{tikzpicture}
\end{document}

这是结果(也是在 2sec 下编译的):

random2

问题

当然,用这个想法来生成一个模式会很好。不幸的是,图案不能包含外部图像

图像不是“真实”图案的问题在于,结果中的点密度不均匀。图像中心的点比边界上的点多。即使“印章”在 5x5 正方形中随机且均匀地“盖印”,靠近边界的“印章”对最终结果的贡献也小于靠近中心的“印章”。如果我们删除剪辑,就可以理解这个问题:

Problem

如果图像可以在真实图案中使用,我们可以将图案的“边界框”定义为小于图像,然后画布将表现得像一个圆环面,其中图案的“脱落”到右侧的部分会从左侧再次“进入”,反之亦然。这将产生更均匀的点状。我无法想象这个问题的解决方案。

更新

在阅读了 OP 对问题的更新后,我必须详细说明我的答案。

正如@MarkWibrow在评论中所解释的那样,我在回答另一个问题,图案不是在 tikz/pgf 级别绘制的,而是转换为驱动程序使用的语言(PDF 或 PS),并作为参数传递给这些语言的图案绘制原语。这排除了每次需要图案时都评估该代码的可能性。

有人可能会认为解决方案是直接用后端语言编写代码(通过特殊函数)。这样,rnd人们可以使用一些 PDF/PS 原生随机函数,而不是使用 tikz 的函数,希望每次绘制图案时都会对其进行评估。然而,这种方法对 PDF 来说会失败,因为它缺乏适当的编程结构(它没有随机函数,也没有执行循环的能力)。

PostScript 是一种更完整的语言,使用纯 PostScript 代码编写一个执行循环以在随机坐标处绘制任意数量的点的函数是完全可能的。但是,我不知道 PostScript 中图案定义的细节,因此有可能(取决于图案在 PS 中的工作方式)您遇到与 tikz/pgf 级别相同的问题,即:图案的定义仅用于计算图像一次,然后在需要时重复该图像。

更新的更新

在上一段中,我担心尝试纯 PostScript 实现是徒劳的,这一点在阅读第 253 页(pdf 中的第 267 页)后得到了证实。PostScript 规范。图案通过几个参数定义,其中一个参数是规范所称的PaintProc,它是纯 PostScript 中的函数,用于“绘制”图案图块的内容。此代码可以包含任何 PostScript,因此可以使用循环和rand获取随机点图案,

它[ PaintProc]除了绘制模式单元之外,不应产生任何副作用。它不应该改变虚拟内存或其他地方的对象。由于缓存的影响, PaintProc过程在不可预知的时间和不可预知的环境中被调用。它应该只依赖于模式字典中的信息,并且每次调用时都应产生相同的效果。

因此,总而言之,每次绘制时不可能出现图案块以不同的方式呈现的情况。

答案2

enter image description here

感谢JLDias的想法,我制作了一个 metapost 文件来创建一些包含随机点且密度受控的图像,也感谢Qrrbrbirlbel图书馆人们可以使用这幅图像作为模式。

  1. 在 `~/texmf/tex/generic/pgf/libraries 中安装库
  2. 编译 metapost 文件。该命令的参数是点的密度(单位为平方厘米)。您可以选择图片的大小:a4、a5、a6,具体取决于您想要覆盖的区域的大小。a5 似乎是个折衷的选择。
  3. 使用以下脚本转换 metapost eps 图像.jpg。可以删除.mps文件并将脚本存储.jpg在与库相同的目录中。
  4. 用你的密度完成 tex 文件的序言并享受。

LaTeX 文件:

\documentclass[tikz,margin=3pt]{standalone}
\usetikzlibrary{patterns.images}

\pgfSetupImageAsPattern{Rnd-Patt-20}{Rnd-Patt-20.jpg}
\pgfSetupImageAsPattern{Rnd-Patt-40}{Rnd-Patt-40.jpg}
\pgfSetupImageAsPattern{Rnd-Patt-50}{Rnd-Patt-50.jpg}
\pgfSetupImageAsPattern{Rnd-Patt-60}{Rnd-Patt-60.jpg}
\pgfSetupImageAsPattern{Rnd-Patt-80}{Rnd-Patt-80.jpg}
\pgfSetupImageAsPattern{Rnd-Patt-100}{Rnd-Patt-100.jpg}
\pgfSetupImageAsPattern{Rnd-Patt-250}{Rnd-Patt-250.jpg}
\pgfSetupImageAsPattern{Rnd-Patt-500}{Rnd-Patt-500.jpg}
\pgfSetupImageAsPattern{Rnd-Patt-1000}{Rnd-Patt-1000.jpg}

\tikzset{rand pattern/.style args={#1}{%
    use image as pattern=Rnd-Patt-#1, image as pattern}}    

\begin{document}

\begin{tikzpicture}
\draw[rand pattern = 100] (-1.5,-1) rectangle (0.5,1) ;
\draw[rand pattern = 500] (2,0) circle (1) ;
\draw[rand pattern = 1000,shift={(3.2,-.86)}]
        (0,0)--(2,0)--(60:2)--cycle ;
\end{tikzpicture}
\end{document}

文件metapost

prologues:=3;
input TEX;

outputtemplate := "Rnd-Patt-%c.mps" ;

u := 1cm ;
format := 2 ; % 1 - A4, 2 - A5, 4 - A6
w := 24/format ;
h := 32/format ; % 24*32 to be by 4 divisible

vardef Rnd_Patt(expr i) =

%##############
\beginfig(i) %#
%##############

for x = 1 upto w :
    for y = 1 upto h :
        for n = 1 upto i :
        fill fullcircle scaled .25pt
            shifted ((uniformdeviate w)*u,(uniformdeviate h)*u) ;
        endfor ;
    endfor ;
endfor ;

%##############
endfig;      %#
%##############

enddef;

Rnd_Patt(20) ;
Rnd_Patt(50) ;
Rnd_Patt(100) ;
Rnd_Patt(250) ;
Rnd_Patt(500) ;
Rnd_Patt(1000) ;

end

转换的小脚本

#!/bin/bash

for i in $(ls *.mps) ;
    do
    FILE_EXT=$(echo "$i" | cut -f1 -d '.')
    convert -density 300 $FILE_EXT.mps $FILE_EXT.jpg
    done

答案3

编辑:更简单的解决方案是将其添加到您的序言中:

\pgfmathsetseed{\number\pdfrandomseed}
\pgfdeclarepatternformonly{Rnd}
{
...
}

如果使用 LuaLaTeX 的解决方案可以的话,您可以尝试一下。

\documentclass[tikz,margin=3pt]{standalone}
\usetikzlibrary{patterns}
\usepackage{luacode}

\begin{luacode}
tex.print('\\pgfdeclarepatternformonly{Rnd}')
tex.print('{\\pgfpointorigin}{\\pgfpoint{1cm}{1cm}}')
tex.print('{\\pgfpoint{.5cm}{.5cm}}')
tex.print('{')
 for i=1,100,1 do
  tex.print('\\pgfpathcircle{\\pgfpoint{' .. math.random() .. '*.5cm}{' .. math.random() .. '*.5cm}}{.25pt}')
 end
 tex.print('\\pgfusepath{fill}')
tex.print('}')
\end{luacode}

\begin{document}
\begin{tikzpicture}

\draw[pattern=Rnd] (0,0) rectangle (5,5) ;
\end{tikzpicture}

\end{document}

相关内容