echart 坐标数字间隔_用LaTeX优雅地绘制数字电路
本文主要介紹數字電路的實現方法。使用的包為
。(首次出現,標準拼寫以示尊敬)主要信息來自于官方文檔以及一些TikZ的使用經驗。注意:circuitikz在2020年4月19日發布了1.1.0版本,提供了IEEE標準的邏輯門。對于數字電路繪制幫助極大,但未包含在TeX Live 2020發行版中,請務必記得更新。具體更新方法因發行版和系統不同而有差異。
一、導入Circuitikz
導言區寫usepackage{circuitikz}即可。 同時還可以在導言區做一些全局設置,比如:
ctikzset{logic ports=ieee} %所有邏輯門使用IEEE標準 usetikzlibrary{calc} %使用TikZ中的計算功能在文檔中需要插入電路圖的地方,使用環境circuitikz:
begin{circuitikz}%繪制指令 end{circuitikz}也可以在開始環境時聲明一個縮放比例。因為CircuiTikZ提供的邏輯門普遍偏大(個人感覺),所以我會把整個圖縮小到0.7倍。
begin{circuitikz}[scale=0.7, transform shape] %必須添加transform shape選項才能正??s放CircuiTikZ%繪制指令 end{circuitikz}二、TikZ基礎
介紹CircuiTikZ之前,有必要介紹TikZ中的一些基礎功能。CircuiTikZ只不過是TikZ的一個包裝,所以所有下述的的TikZ指令都可以在CircuiTikZ中使用。
TikZ的圖形主要由三部分構成:坐標(coordinate),路徑(path),節點(node)。它們大致的關系如下:
- 節點是位于一個坐標的二維結構;
- 路徑是連接若干個坐標的一維結構。
每一條TikZ的指令大概都長這樣:
command[options] <other information>; %一定要有結尾的分號1、坐標
要聲明一個坐標很簡單,(x,y)就表示了這個坐標。但是,我們很少單獨使用坐標本身,所以它的聲明往往是包含在一個路徑或節點的聲明中的。我們可以先用坐標生成一個輔助的網格:
begin{circuitikz}[scale=0.7, transform shape]draw[step=1,gray,very thin] (0,0) grid (5,5); end{circuitikz}此處還用了draw指令,但暫時不必在意,只需知道我們生成了一個從(0,0)到(5,5),間隔為1的網格即可。注意到這個指令給三個選項賦了值:網格線的間距step,以及兩個繪制選項gray和very thin,表示顏色和線的粗細。
聲明坐標時,我們實際上做的是把TikZ中的”筆尖“移到了那個位置,從那里開始繪制圖形。在筆尖確定的情況下,我們也可以使用相對坐標,根據上一個坐標的偏移量來聲明下一個坐標。如果筆尖位于(x,y),那么下一個坐標可以用+(a,b)或者++(a,b)來表示,意為”將筆尖向右移動a,向上移動b“,即(x+a,y+b)。一個加號和兩個加號的區別在于兩個加號聲明的相對坐標會變成新的”筆尖位置“,而一個加號的坐標不會影響”筆尖位置“,筆尖仍然留在(x,y)上——但這只會在聲明第二個相對坐標時有區別。下面的代碼會生成一樣的網格圖案:
begin{circuitikz}[scale=0.7, transform shape]draw[step=1,gray,very thin] (0,0) grid +(5,5); %或者++(5,5) end{circuitikz}2、路徑
一個路徑是連接若干個點的線。最簡單的聲明路徑的方法(也是在CircuiTikZ中少數派得上用場的方法之一):
begin{circuitikz}[scale=0.7, transform shape]draw[step=1,gray,very thin] (0,0) grid (5,5);path (1,1) -- (4,5); end{circuitikz}在這個指令中,path表示一個路徑,--連接了兩個坐標(1,1)和(4,5)。這樣,就在這兩個點之間連接了一條線段。 但是,現在只是聲明了路徑,為了讓TikZ真的去畫它,還需要顯式地給一個draw:
begin{circuitikz}[scale=0.7, transform shape]draw[step=1,gray,very thin] (0,0) grid (5,5);path[draw] (1,1) -- (4,5); end{circuitikz}路徑一般的聲明方式是:
path[options] <cord 1> <connection> <cord 2>;
除了--,還有|-和-|兩種常用連接選項,前者會先垂直,再水平地從第一個點走到第二個點;后者則相反,先水平,再垂直。我們一直使用的grid,也是一種路徑連接方式。
begin{circuitikz}[scale=0.7, transform shape]draw[step=1,gray,very thin] (0,0) grid (5,5);path[draw] (1,1) -- (4,5);path[draw,red] (1,1) -| (4,5);path[draw,blue] (1,1) |- (4,5); end{circuitikz}一條路徑可以連續連接多個坐標,在最后使用-- cycle會使得路徑閉合。同時,一直用path[draw]顯得太過累贅。我們可以簡單地用draw替換。
begin{circuitikz}[scale=0.7, transform shape]draw[step=1,gray,very thin] (0,0) grid (5,5);draw (1,1) -- (4,5) -- (3,2) -- cycle; end{circuitikz}為什么要說(1,1) -- (4,5) -- (3,2) -- cycle而不說(1,1) -- (4,5) -- (3,2) -- (1,1)?可以放大一下兩者生成的圖片:
左邊是-- cycle,右邊是簡單的”起點=終點“的路徑??梢钥吹?#xff0c;前者閉合得更加優雅。
3、節點
一個節點是一個微型的TikZ圖形。一般我們用它添加文字,也可以用它畫一些小圖形。節點是一個二維圖形,它會按預先設置好的一個錨點來對齊設定的坐標。
begin{circuitikz}[scale=0.7, transform shape]draw[step=1,gray,very thin] (0,0) grid (5,5);node at (2,2) {A}; %錨點默認在節點中央 end{circuitikz}每個節點都自帶四個錨點:north,south,east,west。如果我們在設置節點時,用south錨點錨定坐標(2,2),那么節點的下端就會對齊(2,2),這個節點就會出現在(2,2)上方。
begin{circuitikz}[scale=0.7, transform shape]draw[step=1,gray,very thin] (0,0) grid (5,5);node[anchor=south] at (2,2) {A}; end{circuitikz}當然,south表示“上方”實在太反人類,所以有這樣的簡寫方式:
"above" == "anchor=south", "below" == "anchor=north",
"left" == "anchor=east", "right" == "anchor=west"
節點的一般聲明方式是:
node[options] (name) at <cord> {text};
除了用node顯式聲明節點,還可以在路徑定義中為涉及的坐標綁定一個節點:
begin{circuitikz}[scale=0.7, transform shape]draw[step=1,gray,very thin] (0,0) grid (5,5);draw (1,1) node[below] {A} -- (4,5); end{circuitikz}設置節點時,還可以為它指定名字,并把它作為一個坐標調用。
begin{circuitikz}[scale=0.7, transform shape]draw[step=1,gray,very thin] (0,0) grid (5,5);draw (1,1) node[below] (a) {A} -- (4,5);draw (a.north) -- ++(2,1); end{circuitikz}要注意的是,要用(a.north)而不只是(a),因為后者所代表的坐標是在"A"的中央,而前者才是之前聲明的(1,1)這個點。
利用節點,可以繪制一些我們并不清楚真實坐標的點。但是,如果用相對坐標,就需要我們同時知道橫縱坐標的偏移量。如果我們只知道一個偏移量,而知道另一個的絕對坐標,又如何處理?此時需要使用tikz librarycalc 中的let語法:
draw let p<數字> = (節點) in ...
并在其后用x<數字>和y<數字>調用這個節點的橫縱坐標。比如:
begin{circuitikz}[scale=0.7, transform shape]draw[step=1,gray,very thin] (0,0) grid (5,5);draw (1,1) node[below] (a) {A} -- (4,5);draw let p1=(a.north) in (x1,y1) -- (4,y1); end{circuitikz}三、CircuiTikZ中的元件
CircuiTikZ中有兩類元件:“路徑類”和“節點類”?;舅械臄底蛛娐吩紝儆诠濣c式,所以只舉一例路徑類的繪制方法。
begin{circuitikz}[scale=0.7, transform shape]draw[step=1,gray,very thin] (0,0) grid (5,5);draw (3,3) to[R] (1,3); %從(3,3)到(1,3)的路徑,內容是一個電阻 end{circuitikz}所有的路徑類元件都使用to[]連接。方括號中的參數除了指定元件(如電阻R和導線short),還可以指定末端的連接方式。下文中會出現一些例子。
對于節點,我們一般先聲明節點本身,再從節點的各個錨點向外繪制。
begin{circuitikz}[scale=0.7, transform shape]draw[step=1,gray,very thin] (0,0) grid (5,5);draw (3,3) node[and port] (and1) {}; %或者node[and port] (and1) at (3,3) {}; end{circuitikz}還要注意,每個節點都需要有一個大括號圍起的標簽,哪怕是空的。接下來,就可以從各個錨點出發,繪制其他導線了。一個邏輯門有out和若干in錨點;比如下面的例子:
begin{circuitikz}[scale=0.7, transform shape]draw[step=1,gray,very thin] (0,0) grid (5,5);draw (3,3) node[and port] (and1) {};draw (and1.out) -- ++(1,0);draw (and1.in 1) -| (1,5);draw (and1.in 2) -| (1,1); end{circuitikz}可以設置不止兩個接口的邏輯門,只需添加選項number inputs,同時也可以通過inner inputs指定有多少個位于邏輯門內部:
begin{circuitikz}[scale=0.7, transform shape]draw[step=1,gray,very thin] (0,0) grid (5,5);draw (3,3) node[and port, number inputs=10, inner inputs=2] (and1) {};draw (and1.out) -- ++(1,0);draw (and1.in 1) -| (1,5);draw (and1.in 10) -| (1,1); end{circuitikz}對于表示否定的“小圓圈”,如果是輸出端,那可以使用nand等表示否定的門;不然,就需要手動在接口處添加一個notcirc節點。注意,in,out等錨點在“針腳”的末端,如果要設置在起點,要在前面加b,變成bin,bout:
begin{circuitikz}[scale=0.7, transform shape]draw[step=1,gray,very thin] (0,0) grid (5,5);draw (3,3) node[and port, number inputs=10, inner inputs=2] (and1) {};draw (and1.out) -- ++(1,0);draw (and1.in 1) -| (1,5);draw (and1.in 10) -| (1,1);draw (and1.bin 3) node[notcirc,left] {}; end{circuitikz}以下是所有常用邏輯門的節點名:
- 與門:and port;
- 或門:or port;
- 非門:not port;
- 異或門:xor port;
- 同或門:xnor port;
- 與非門:nand port;
- 或非門:nor port;
- 施密特電路:schmitt port;
- 反施密特電路:inv schmitt port;
- 緩沖門:buffer port
更多的關于電路繪制的技術細節可以見CircuiTikZ官方文檔:
CircuiTikZ文檔?mirrors.sjtug.sjtu.edu.cn四、實例
以一位比較器為例:
首先,確定各個門電路的位置。
begin{circuitikz}[scale=0.7, transform shape]draw (3,5.5) node[and port, anchor=out] (and1) {};draw (3.5,4) node[xnor port, anchor=out] (xor1) {};draw (3,2.5) node[and port, anchor=out] (and2) {}; end{circuitikz}坐標是隨意設的,只要符合審美即可。使用anchor=out也只是因為這樣容易設置坐標。
接下來,要為兩個與門添加圓圈。
begin{circuitikz}[scale=0.7, transform shape]draw (3,5.5) node[and port, anchor=out] (and1) {};draw (3.5,4) node[xnor port, anchor=out] (xor1) {};draw (3,2.5) node[and port, anchor=out] (and2) {};draw (and1.bin 1) node[notcirc,left] {};draw (and2.bin 1) node[notcirc,left] {}; end{circuitikz}然后是最繁瑣的接線部分。可以先接連接兩個與門的線:
begin{circuitikz}[scale=0.7, transform shape]draw (3,5.5) node[and port, anchor=out] (and1) {};draw (3.5,4) node[xnor port, anchor=out] (xor1) {};draw (3,2.5) node[and port, anchor=out] (and2) {};draw (and1.bin 1) node[notcirc,left] {};draw (and2.bin 1) node[notcirc,left] {};draw (and2.in 1) |- (and1.in 2);draw (and1.in 1) -- ++(-0.5,0) |- (and2.in 2); end{circuitikz}對于同或門向后的兩根線,我們知道與它們橫縱坐標相同的幾個節點,但不知道它們的具體坐標,因此,我們將要使用let語法。
begin{circuitikz}[scale=0.7, transform shape]draw (3,5.5) node[and port, anchor=out] (and1) {};draw (3.5,4) node[xnor port, anchor=out] (xor1) {};draw (3,2.5) node[and port, anchor=out] (and2) {};draw (and1.bin 1) node[notcirc,left] {};draw (and2.bin 1) node[notcirc,left] {};draw (and2.in 1) |- (and1.in 2);draw (and1.in 1) -- ++(-0.5,0) |- (and2.in 2);draw let p1=(xor1.in 1),p2=(and1.in 1) in (x1,y1) to[short,-*] (x2,y1) node (a) {};draw let p1=(xor1.in 2),p2=(and2.in 1) in (x1,y1) to[short,-*] ({x2-0.5cm},y1) node (b) {}; end{circuitikz}其中還用了一個小語法:在大括號之間的內容會被TikZ的數學引擎計算。所以{x2-0.5cm}有類似(x2,y2)+(-0.5,0)的效果。to中包含的-*選項會在線路末端生成一個小黑圓表示連接點。這是CircuiTikZ提供的連接方式,而不是TikZ的,所以只有在用to時才能使用,如果用--則不行。
最后,延長導線,添加輸入輸出標簽。對于文字標簽,有一個注意:由于在最前面設置了scale=0.7,會導致文字偏小;所以我們要手動再把文字比例調回來。(這是CircuiTikZ中一個不合理的地方,TikZ的縮放不影響文字) 調整方法是再為文字節點添加scale={1/0.7}。
begin{circuitikz}[scale=0.7, transform shape]draw (3,5.5) node[and port, anchor=out] (and1) {};draw (3.5,4) node[xnor port, anchor=out] (xor1) {};draw (3,2.5) node[and port, anchor=out] (and2) {};draw (and1.bin 1) node[notcirc,left] {};draw (and2.bin 1) node[notcirc,left] {};draw (and2.in 1) |- (and1.in 2);draw (and1.in 1) -- ++(-0.5,0) |- (and2.in 2);draw let p1=(xor1.in 1),p2=(and1.in 1) in (x1,y1) to[short,-*] (x2,y1) node (a) {};draw let p1=(xor1.in 2),p2=(and2.in 1) in (x1,y1) to[short,-*] ({x2-0.5cm},y1) node (b) {};draw let p1=(a) in (x1,y1) -- (-1,y1) node[left,scale={1/0.7}] {$A$};draw let p1=(b) in (x1,y1) -- (-1,y1) node[left,scale={1/0.7}] {$B$};draw let p1=(and1.out) in (x1,y1) -- (4,y1) node[right,scale={1/0.7}] {$Y_{A>B}$};draw let p1=(xor1.out) in (x1,y1) -- (4,y1) node[right,scale={1/0.7}] {$Y_{A=B}$};draw let p1=(and2.out) in (x1,y1) -- (4,y1) node[right,scale={1/0.7}] {$Y_{A<B}$}; end{circuitikz}就這樣,我們完成了此圖的繪制。
總結
以上是生活随笔為你收集整理的echart 坐标数字间隔_用LaTeX优雅地绘制数字电路的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 告诉你怎么看摄像头分辨率如何查询电脑分辨
- 下一篇: python dataframe取一列_