概述
希望模拟以下正弦波,其填充和轮廓厚度均有随机变化:
波形由两部分组成:厚度可变的填充和厚度可变的轮廓。MetaPostfunction
函数允许通过函数调用创建路径,例如sin
。可以使用以下方法创建初始曲线:
path wave;
wave := curved function( 1, "sin(x)", "x", 1, 10, 1 ) xyscaled( 1cm, 1cm );
这产生了一个相当接近的结果:
问题
我曾尝试制作一支粗细不一的笔:
pen variably_thick;
variably_thick := pencircle yscaled uniformdeviate( 1mm ) rotated 10;
然而,这设置了初始笔的粗细——在绘制路径时没有回调来增加或减少笔的粗细。
代码
一个工作示例:
\setupcolors[state=start]
\definecolor[BaseColour][h=66CEF1]
% Randomize the seed without having to delete the tuc file.
\ctxlua{math.randomseed( os.time() )}
% Draws three waves, somewhat evenly spaced, with two inflection points
% per line.
\startuseMPgraphic{page:ThemeElementWave}
color base_colour;
base_colour := \MPcolor{BaseColour};
% The wavy shape used for creating the wave and its border.
path wave;
% The wave "path"
path underwave;
% The wave "fill"
path overwave;
% Create the base path
wave := curved function( 1, "sin(x)", "x", 1, 10, 1 ) xyscaled( 1cm, 1cm );
% Draw the "path" for the wave (the outside edges)
underwave := wave rotated 90 xscaled 5 yscaled .45;
draw underwave withpen pencircle scaled 1.25cm withcolor (.7[base_colour,white]);
% "Fill" the wave.
overwave := wave rotated 90 xscaled 5 yscaled .5;
draw overwave withpen pencircle scaled 1cm withcolor base_colour;
\stopuseMPgraphic
\defineoverlay[page:ThemeElementWave][\uniqueMPgraphic{page:ThemeElementWave}]
\starttext
\setupbackgrounds[page][background={page:ThemeElementWave}]
\startchapter
\input knuth
\stopchapter
\stoptext
问题
如何在 MetaPost 中创建一条可产生粗细不一的线条的曲线?
想法
来自MetaPost 示例:
path p;
p =
(0,u)
for i=.1 step .1 until 10:
hide( pair A; A = (i*u, (sind (i*180/3.14))/i *u);
draw A withpen pencircle scaled 2pt )
.. A
endfor;
draw p;
应该可以使用上面的代码(即循环正弦波)来绘制曲线,同时在整个循环过程中改变笔的粗细,但我希望有更清晰的解决方案。
有关的
答案1
虽然这不能回答粗细曲线的问题,但模拟所需结果的另一种方法是将曲线视为两个偏移正弦波,两端连接:
\startuseMPgraphic{page:ThemeElementWave}
color base_colour;
base_colour := \MPcolor{BaseColour};
deviation_dark := uniformdeviate( .025 );
def dark_colour = deviation_dark [base_colour, black] enddef;
wave_height := 1.5mm;
path top_wave;
top_wave := (0, 0);
wave_resolution := 20;
for x = 0 step (1 / wave_resolution) until 2:
y := sin( x * pi );
top_wave := top_wave .. (x, y);
endfor;
% Duplicate the top wave, but move it up a random amount.
path bottom_wave;
bottom_wave := top_wave shifted( 0, wave_height );
% Offset the waves.
top_wave := top_wave xyscaled (5.5cm, 5mm);
bottom_wave := bottom_wave xyscaled (6.5cm, 4.5mm);
% Create a path for connecting the waves.
path wave_right_side;
wave_right_side :=
(point length(top_wave) of top_wave) --
(point length(bottom_wave) of bottom_wave);
% Connect the waves.
path wave;
wave := top_wave & wave_right_side & reverse bottom_wave -- cycle;
% Stretch the wave to extend beyond the page boundaries.
wave := wave xscaled( 2.5 );
draw wave withpen pencircle scaled 3mm withcolor .7[base_colour,white];
fill wave withcolor dark_colour;
\stopuseMPgraphic
这产生了一个合理的传真:
答案2
如果没有明显的简单方法,几乎总是可以实现缺失的功能。我想到的解决这个问题的方法基本上是:编写一个函数,生成到给定路径的偏移路径,该路径是给定路径上的时间函数;在给定路径的两侧生成两条这样的路径;连接它们;填充生成的形状。您可以找到代码(它是库的一部分,不幸的是,在这里引用它很长而且很乱)这里。一旦包含此库(输入 fiziko.mp),您就可以编写如下代码:
path p;
p := (0,0){dir(30)}..(5cm, 0)..{dir(30)}(10cm, 0);
draw brush (p)(1cm*sin(offsetPathLength*pi)) withcolor (0.75, 0.75, 1);
draw brush (p)(0.6cm*sin(offsetPathLength*pi)) withcolor (0.5, 0.5, 1);
其中函数“brush”实际上绘制可变宽度的线,它有两个参数:第一个是路径;第二个是一些任意函数,可以是“offsetPathLength”(路径上的弧长)或“offsetPathTime”(路径上的时间);并得到如下图片:
为了获得更多细节,您可能需要细分原始路径。它似乎可以与 ConTeXt 配合使用,但可能需要进行一些调整。