更新

更新

一位朋友展示了他们正在制作的被子图案。啊,我说,我可以轻松地在 Ti 中做到这一点Z 带pics。嗯,是也不是:当然可以做到;但不是那么容易。我有 pic下面展示的图案,以及完全靠蛮力完成的成品图案。一定有一种方法可以更有效地做到这一点,并且可以推广到其他图案。

\documentclass{article}

\usepackage[papersize={5.5in,8.5in},margin=0.6in]{geometry}
\usepackage{tikz}

\usetikzlibrary{shapes.geometric}

\tikzset{%
    dartstyle/.style={kite,draw,kite vertex angles=60,inner sep=0.125in,outer sep=0pt,fill=#1},
    pics/quiltdart/.style={%
        code={%
          \node[dartstyle=red](base) {};
          \node[rotate=0,dartstyle=white,anchor=upper vertex] at (base.right vertex) {};
          \node[rotate=0,dartstyle=white,anchor=upper vertex] at (base.left vertex) {};
          \node[rotate=0,dartstyle=red,anchor=upper vertex] at (base.lower vertex) {};
        }%
    }%
}

\parindent0pt

\begin{document}

This was easy:

\tikz \pic {quiltdart};

\bigskip

This, not so much\dots

\tikz {\pic {quiltdart};
    \pic[yshift=-0.51in,xshift=0.89in,rotate=-60,transform shape]  {quiltdart};
    \pic[yshift=-1.54in,xshift=0.89in,rotate=-120,transform shape]  {quiltdart};
    \pic[yshift=-2.05in,xshift=-0in,rotate=-180,transform shape]  {quiltdart};
    \pic[yshift=-1.54in,xshift=-0.89in,rotate=-240,transform shape]  {quiltdart};
    \pic[yshift=-0.51in,xshift=-0.89in,rotate=-300,transform shape]  {quiltdart};
}

\end{document}

被子图像

更新

首先,我要感谢那些回复我帖子的人:我学到了很多东西。因此,我把这篇文章作为更新而不是回答因为如果没有发人深省的答复,这一切都不可能实现,而我绝不会因此而减损这些答复。

这是我的方法。虽然它可能不是最高效的代码,但效果很好。另一方面,它很简单,易于维护/修改。

\documentclass[]{article}

\usepackage[rgb]{xcolor}
\usepackage{tikz}
\usetikzlibrary{positioning}
\usepackage[margin=1.4in,top=0.5in,left=0.75in]{geometry}

\NewDocumentCommand{\makeshape}{m}{%
    \pgfmathsetmacro{\myhuei}{rnd}
    \pgfmathsetmacro{\myhueii}{rnd}
    \pgfmathsetmacro{\myhueiii}{rnd}
    \definecolor{mycolori}{hsb}{\myhuei,1,1}
    \definecolor{mycolorii}{hsb}{\myhueii,0.25,1}
    \definecolor{mycoloriii}{hsb}{\myhueiii,1,1}
    \pgfmathsetmacro{\lang}{180/#1}%
    \pgfmathsetmacro{\bang}{90-\lang}%
    \tikzset{%
        pics/dart/.style={code={%
            \draw[fill=mycolorii] (0,0) -- ++(90-\lang:2) --
                ++(180-\bang:2) -- ++(-90-\lang:2) -- cycle;
            \draw[fill=mycolori](0,0) -- ++(90-\lang:1) -- ++(180 - \bang:1)coordinate(T) --
                ++(-90-\lang:1) -- cycle;
            \draw[fill=mycoloriii](T) -- ++(90-\lang:1) -- ++(-180 - \bang:1) --
                ++(-90-\lang:1)-- cycle;
            }%
        },%
    }%
    \begin{tikzpicture}[rotate=\lang,scale=0.5]%% both rotate and scale can be altered to suit
        \foreach \i [count=\ii from 0] in {1,...,#1}
            \path pic[rotate around={360/#1*\ii:(0,0)},transform shape]{dart};
    \end{tikzpicture}
}

\parindent0pt

\begin{document}

\thispagestyle{empty}

\foreach \N in {4,5,...,18}{\makeshape{\N}}

\end{document}

样品 新 更新

答案1

\foreach通过使用语句并将rotate选项替换为,可以实现一定程度的改进rotate around

\documentclass{article}

\usepackage[papersize={5.5in,8.5in},margin=0.6in]{geometry}
\usepackage{tikz}

\usetikzlibrary{shapes.geometric}

\tikzset{%
    dartstyle/.style={kite,draw,kite vertex angles=60,inner sep=0.125in,outer sep=0pt,fill=#1},
    pics/quiltdart/.style={%
        code={%
          \node[dartstyle=red](base) {};
          \node[rotate=0,dartstyle=white,anchor=upper vertex] at (base.right vertex) {};
          \node[rotate=0,dartstyle=white,anchor=upper vertex] at (base.left vertex) {};
          \node[rotate=0,dartstyle=red,anchor=upper vertex] 
                at (base.lower vertex)(bottom dart){}; % <-----
        }%
    }%
}

\parindent0pt

\begin{document}

This was easy:

\tikz \pic {quiltdart};

\bigskip

What about this ???


\begin{tikzpicture}
 \foreach \i in {0,60,...,300}{
  \pic[rotate around={\i:(bottom dart.lower vertex)},
      transform shape] {quiltdart};
  }

\end{tikzpicture}

\end{document}

另一种解决方案通过修改图片代码,使得图片的原点对应于最低顶点:

\documentclass{article}

\usepackage[papersize={5.5in,8.5in},margin=0.6in]{geometry}
\usepackage{tikz}

\usetikzlibrary{shapes.geometric}

\tikzset{%
    dartstyle/.style={kite,draw,kite vertex angles=60,inner sep=0.125in,outer sep=0pt,fill=#1},
    pics/quiltdart/.style={%
        code={%
          \node[dartstyle=red,anchor=lower vertex](base) {};
          \node[dartstyle=white,anchor=left vertex] at (base.upper vertex) {};
          \node[dartstyle=white,anchor=right vertex] at (base.upper vertex) {};
          \node[dartstyle=red,anchor=lower vertex] at (base.upper vertex){};
        }%
    }%
}

\parindent0pt

\begin{document}

%This was easy:

%\tikz \pic {quiltdart};

%\bigskip

%This, not so much\dots


\begin{tikzpicture}

% first copy
\foreach \i in {0,60,...,300}{
\pic[rotate =\i,transform shape] {quiltdart};
}
% second copy
\foreach \i in {0,60,...,300}{
\pic[rotate =\i,transform shape] at(0,8){quiltdart};
}
\end{tikzpicture}
\end{document}

答案2

只用path,不用picsnodes

\documentclass{article}

\usepackage[papersize={5.5in,8.5in},margin=0.6in]{geometry}
\usepackage{tikz}

\newcommand{\mydart}[1][]{
    \filldraw[black, fill=red, even odd rule,#1] (0,0)--++(60:1)--++(120:1)--++(240:1)--cycle (60:.5)--++(60:.5)--++(120:.5)--++(240:1)--++(120:.5)--++(60:.5)--cycle
}

\begin{document}

This was easy:

\tikz \mydart;

\bigskip

What about this ???

\begin{tikzpicture}
 \foreach \i in {0,60,...,300}{
  \mydart[rotate around={\i:(0,0)}];
  }

\end{tikzpicture}


or this ???

\begin{tikzpicture}
 \foreach \i in {0,60,...,300}{
  \mydart[shift={(\i:1)}, rotate=\i];
  }

\end{tikzpicture}

\end{document}

在此处输入图片描述

答案3

这是另一种方法,改变pic。在我的画中pic,我画了四个正方形,但我改变了轴来“变形”它们。

像这样:

\documentclass[border=2mm,tikz]{standalone}

\definecolor{color0}{HTML}{FFFFFF} % white
\definecolor{color1}{HTML}{FF0000} % red

\tikzset
{%
  pics/quiltdart/.style={
    code={%
      \pgfmathsetmacro\y{sin(60)}
      \begin{scope}[x={(0.5 cm,\y cm)}, y={(-0.5 cm,\y cm)}]
        \foreach\i in {0,1} \foreach\j in {0,1}
        {
          \pgfmathtruncatemacro\c{Mod(\i+\j+1,2)}
          \draw[fill=color\c] (\i,\j) -- (\i,\j+1) -- (\i+1,\j+1) -- (\i+1,\j) -- cycle;
        } 
      \end{scope}
    }},
}

\begin{document}
\begin{tikzpicture}[line join=round]
\foreach\a in {0,60,...,300}
  \pic[rotate=\a] {quiltdart};
\end{tikzpicture}
\end{document}

在此处输入图片描述

答案4

新的解决方案

在此处输入图片描述

\documentclass[border=5mm]{standalone}
\usepackage[rgb]{xcolor}
\usepackage{tikz}
\begin{document}
\begin{tikzpicture}
\tikzset{quiltdart/.pic={%
\def\n{#1} % the number of quiltdart
% random colors from OP
\pgfmathsetmacro{\myhuei}{rnd}
\pgfmathsetmacro{\myhueii}{rnd}
\pgfmathsetmacro{\myhueiii}{rnd}
\definecolor{mycolori}{hsb}{\myhuei,1,1}
\definecolor{mycolorii}{hsb}{\myhueii,0.25,1}
\definecolor{mycoloriii}{hsb}{\myhueiii,1,1}
        
\def\basicdart{(0,0)--(90-360/\n:1)--+(0,1)--(0,1)--cycle}          
\foreach \i in {0,...,\n}{
\draw[fill=mycoloriii,rotate=\i*360/\n,shift={(90-360/\n:1)},shift={(0,1)}] \basicdart;
\draw[fill=mycolori,rotate=\i*360/\n] \basicdart;
\draw[fill=mycolorii,rotate=\i*360/\n,shift={(0,1)}] \basicdart;
\draw[fill=mycolorii,rotate=\i*360/\n,shift={(0,1)},xscale=-1] \basicdart;
}
}}

\newcounter{myquilt}
\setcounter{myquilt}{2} 
\foreach \j in {1,...,5}
\foreach \i in {1,...,8}
{\stepcounter{myquilt}
\path (6*\i,-6*\j) pic[scale=.6]{quiltdart=\themyquilt} 
% +(-90:2.6) node{$n=$ \themyquilt}   % show the number of quiltdart
;
}
\end{tikzpicture}
\end{document} 

旧解决方案 我猜关键问题是居中/不居中pic,既不居中pic of nodes也不居中rotate。这变成了非常有趣的情况:

  • pic是否以原点为中心 (名称dart)
  • picpics(名称quiltdart)。

我为 s 的参数添加了默认值pic。使用选项[rotate,shift]代替[rotate around]。我希望代码和图片是不言自明的。

在此处输入图片描述

\documentclass[border=5mm,tikz]{standalone}
% Multi-parameters pic with default
\tikzset{
pics/dart/.style args={#1 and #2}{code={%
\draw[fill=#1] (-120:1)--(60:1)--([turn]60:1)--(120:1)--(-60:1)--([turn]-60:1)--cycle;
\draw[fill=#2] (-120:1)--(60:1)--(0:1)--(-60:1)--(120:1)--(180:1)--cycle;
}},
pics/dart/.default={red and white}
}

% Multi-parameters pic of pics with default
\tikzset{pics/quiltdart/.style args={#1 and #2}{code={%
\foreach \i in {0,...,5}
\path (0,0) pic[rotate=60*\i,shift={(0,-sqrt(3))}]{dart={#1 and #2}};
}},
pics/quiltdart/.default={red and white}
}

\begin{document}
\begin{tikzpicture}
\path 
(0,0) pic{dart} node[above=2.5cm,scale=2]{\verb|\pic{dart}|}
(18,0) pic{dart={magenta and cyan}} node[above=2.5cm,scale=2]{\verb|\pic{dart={magenta and cyan}}|};

\foreach \i in {0,...,5}
\path (0,-10) pic[rotate=60*\i,shift={(0,-sqrt(3))}]{dart};
\path (0,-10) node[above=3.5cm,scale=2,align=center]{Good\\
    \verb|\foreach \i in {0,...,5}|\\
    \verb|\pic[rotate=60*\i,shift={(0,-sqrt(3))}]{dart}|};
\path 
(18,-10) pic{quiltdart={magenta and cyan}} node[above=3.5cm,scale=2,align=center]{Better\\
    \verb|\pic{quiltdart={magenta and cyan}}|};
\end{tikzpicture}
\end{document} 
 

被子装饰的一些示例

  1. 平面的平铺

在此处输入图片描述

\begin{tikzpicture}
\foreach \i in {0,...,5}
\foreach \j in {0,...,4}
\path (5*\i,-5*\j) pic{quiltdart};
\end{tikzpicture}
  1. 绿色被子

在此处输入图片描述

\begin{tikzpicture}
\foreach \i in {0,...,5}
\foreach \j in {0,...,4}
\path (8*\i,-8*\j) pic{quiltdart={green and white}};
\end{tikzpicture}

更新 Asymptote 版本 picspic可以从 TikZ 转换为 Asymptote。

在此处输入图片描述

unitsize(1cm);

// creating dart
picture dart;
unitsize(dart,1cm);
path p=dir(-120)--dir(60)--dir(0)--dir(-60)--dir(120)--dir(180)--cycle;
path q=dir(-120)--dir(60)--sqrt(3)*dir(90)--dir(120)--dir(-60)--sqrt(3)*dir(-90)--cycle;
filldraw(dart,p,pink,black);
filldraw(dart,q,purple,black);

// creating quiltdart from darts
picture quiltdart;
unitsize(quiltdart,1cm);
for(int i=0;i<6;++i)
add(quiltdart,rotate(i*60)*shift(0,-sqrt(3))*dart);

// Here is the quilt
for (int i=0;i<6;++i)
for (int j=0;j<3;++j)
add(shift(8*i,-8*j)*quiltdart);

shipout(bbox(1cm,invisible));

更新 2:一般情况n-point-star quiltdarts 的概括。有时,一般问题比特定问题更容易处理。这是我对 OP 新更新答案的情况的感受。

想法很简单,直接创建一个带参数的函数n。共有 3 个类;每个类都由基本飞镖的旋转组成;中间类需要注意一点。

n=20 quiltdart(20,yellow,magenta,purple);

在此处输入图片描述

// http://asymptote.ualberta.ca/
unitsize(1cm);
// the basic dart
path dart(int n){
pair A=(0,0),D=(0,1),B=dir(90-360/n),C=B+D-A;
return A--B--C--D--cycle;
}

// the quiltdart of three classes
void quiltdart(int n, pen innerpen, pen middlepen, pen outerpen){
for(int i=0;i<n;++i){
transform rot=rotate(i*360/n);  
path outerclass=rot*shift((0,1)+dir(90-360/n))*dart(n);
path middleclass1=rot*shift(0,1)*dart(n);
path middleclass2=rot*shift(0,1)*xscale(-1)*dart(n);
path innerclass=rot*dart(n);
filldraw(outerclass,outerpen,black);
filldraw(middleclass1,middlepen,black);
filldraw(middleclass2,middlepen,black);
filldraw(innerclass,innerpen,black);
}} 

quiltdart(20,yellow,magenta,purple);
shipout(bbox(1cm,invisible));

n=4 quiltdart(4,yellow,orange,green);

在此处输入图片描述

n=50 quiltdart(50,yellow,green,red);

在此处输入图片描述

更新 3:TikZ 的通用解决方案n=45是 TikZ/TeX 可以编译的最大数量,而不会引起烦恼并引发“尺寸太大”错误。

在此处输入图片描述

\documentclass[border=5mm,tikz]{standalone}
\begin{document}
\begin{tikzpicture}
\def\n{45}
\def\basicdart{(0,0)--(90-360/\n:1)--+(0,1)--(0,1)--cycle}          
\foreach \i in {0,...,\n}{
\draw[fill=magenta,rotate=\i*360/\n,shift={(90-360/\n:1)},shift={(0,1)}] \basicdart;
\draw[fill=yellow,rotate=\i*360/\n] \basicdart;
\draw[fill=orange,rotate=\i*360/\n,shift={(0,1)}] \basicdart;
\draw[fill=orange,rotate=\i*360/\n,shift={(0,1)},xscale=-1] \basicdart;
}
\end{tikzpicture}
\end{document} 

相关内容