Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Doc] Update gui_system.md #7628

Merged
merged 5 commits into from
Mar 23, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions docs/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@
N = 16
M = 8

gui = ti.GUI('Title', res=(400, 400))
'''


Expand Down
1 change: 1 addition & 0 deletions docs/cover-in-ci.lst
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
docs/lang/articles/basic
docs/lang/articles/advanced
docs/lang/articles/kernels
docs/lang/articles/visualization/gui_system.md
161 changes: 145 additions & 16 deletions docs/lang/articles/visualization/gui_system.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ Each window is built on a coordinate system: the origin is located in the lower-
To display a Taichi field or a NumPy ndarray, call `gui.set_image()`. The method accepts both types as input.

```python
gui = ti.GUI('Set Image', (640, 480))
image = ti.Vector.field(3, ti.f32, shape=(640, 480))
while gui.running:
gui.set_image(image)
Expand All @@ -64,7 +65,7 @@ In each loop of the `gui.set_image()` method call, the GUI system converts the i
If you only need to call the `set_image()` method without using any drawing command, you can enable `fast_gui` mode for better performance. This mode allows Taichi GUI to write the image data directly to the frame buffer without additional copying, and significantly increases FPS.

```python
gui = ti.GUI(res, title, fast_gui=True)
gui = ti.GUI('Fast GUI', res=(400, 400), fast_gui=True)
```

For this mode to work, ensure that the data passed into `gui.set_image()` is in a display-compatible format. In other words, If it is a Taichi field, ensure that it is one of the following:
Expand All @@ -76,30 +77,120 @@ Note that `dtype` must be `ti.f32`, `ti.f64`, or `ti.u8`.

## Draw on a window

Taichi's GUI system supports drawing simple geometries, such as lines, triangles, rectangles, circles, and texts.
Taichi's GUI system supports drawing simple geometries, such as lines, circles, triangles, rectangles, arrows, and texts.

The `pos` parameter of every drawing method accepts Taichi fields or NumPy arrays, *not* Python primitive lists. Each element of the array is a pair of floats ranging from `0.0` to `1.0`, which represent the relative positions of the geometries. For example:
### Single geometry

- `(0.0, 0.0)`: the lower-left corner of the window.
- `(1.0, 1.0)`: the upper-right corner of the window.
In Taichi, drawing basic geometric shapes on the GUI is very intuitive. In most cases, all we need to do is specify information such as the position and size of the geometry and call the corresponding APIs.

The following code draws 50 circles with a radius of `5` and in three different colors randomly assigned by `indices`, an integer array of the same size as `pos`.
#### Line

You can draw a single line on a GUI canvas by specifying its begin and end points:

```python
import numpy as np
pos = np.random.random((50, 2))
# Create an array of 50 integer elements whose values are randomly 0, 1, 2
# 0 corresponds to 0x068587
# 1 corresponds to 0xED553B
# 2 corresponds to 0xEEEEF0
indices = np.random.randint(0, 2, size=(50,))
gui = ti.GUI("circles", res=(400, 400))
gui = ti.GUI('Single Line', res=(400, 400))
begin = [0.1, 0.1]
end = [0.9, 0.9]
while gui.running:
gui.circles(pos, radius=5, palette=[0x068587, 0xED553B, 0xEEEEF0], palette_indices=indices)
gui.line(begin, end, radius=1, color=0x068587)
gui.show()
```
![gui-line](https://user-images.githubusercontent.com/2747993/226812450-0037a798-c31f-457b-b15c-99362119b560.png)

![gui-circles](https://raw.githubusercontent.com/taichi-dev/public_files/master/taichi/doc/gui-circles.png)
:::note

Coordinates such as `begin` and `end` for single geometry can be Python lists, Numpy arrays or `ti.Vector`, as long as it's subscriptable and its dimension is (2, ).

:::

#### Circle

You can draw a single circle on a GUI canvas by specifying its center poistion and its radius:

```python
import numpy as np
gui = ti.GUI('Single Circle', res=(400, 400))
center = [0.5, 0.5]
while gui.running:
gui.circle(pos=center, radius=30, color=0xED553B)
gui.show()
```

![gui-circle](https://user-images.githubusercontent.com/2747993/226813425-94c6c2d9-56ed-444a-83b5-261e5ce935fe.png)


#### Triangle

You can draw a single triangle on a GUI canvas by specifying its three end points:

```python
import numpy as np
gui = ti.GUI('Single Triangle', res=(400, 400))
p1 = [0.5, 0.5]
p2 = [0.6, 0.5]
p3 = [0.5, 0.6]
while gui.running:
gui.triangle(a=p1, b=p2, c=p3, color=0xEEEEF0)
gui.show()
```

![gui-triangle](https://user-images.githubusercontent.com/2747993/226815118-bc80198b-f707-4747-b199-9971918d0f7c.png)

#### Rectangle

You can draw a single rectangle on a GUI canvas by specifying its topleft and bottomright points:

```python
import numpy as np
gui = ti.GUI('Single Rectangle', res=(400, 400))
p1 = [0.3, 0.4]
p2 = [0.7, 0.6]
while gui.running:
gui.rect(topleft=p1, bottomright=p2, color=0xFFFFFF)
gui.show()
```

![gui-rect](https://user-images.githubusercontent.com/2747993/226816661-96f21ee9-9367-4df4-aa31-0aa36596bba1.png)

#### Arrow

You can draw a single arrow on a GUI canvas by specifying its start point and direction:

```python
import numpy as np
gui = ti.GUI('Single Arrow', res=(400, 400))
begin = [0.3, 0.3]
increment = [0.5, 0.5]
while gui.running:
gui.arrow(orig=begin, direction=increment, color=0xFFFFFF)
gui.show()
```

![gui-arrow](https://user-images.githubusercontent.com/2747993/226817706-507d20ec-3b68-48cd-bbfc-ea3c0fde0ad0.png)

#### Text

You can draw a single line of text on a GUI canvas by specifying its position and contents:

```python
gui = ti.GUI('Text', res=(400, 400))
position = [0.3, 0.5]
while gui.running:
gui.text(content='Hello Taichi', pos=position, font_size=34, color=0xFFFFFF)
gui.show()
```

![gui-text](https://user-images.githubusercontent.com/2747993/226821728-7dec5958-6f80-441c-8432-c8f7f9d54f7d.png)

### Multiple geometries

It's also possible to draw multiple geometries at once by providing a collection of their positions to the GUI. The `pos` parameter of every drawing method accepts Taichi fields or NumPy arrays, *not* Python primitive lists. Each element of the array is a pair of floats ranging from `0.0` to `1.0`, which represent the relative positions of the geometries. For example:

- `(0.0, 0.0)`: the lower-left corner of the window.
- `(1.0, 1.0)`: the upper-right corner of the window.

#### Lines

The following code draws five blue line segments whose width is 2, with `X` and `Y` representing the five starting points and the five ending points.

Expand All @@ -115,6 +206,28 @@ while gui.running:

![gui-lines](https://raw.githubusercontent.com/taichi-dev/public_files/master/taichi/doc/gui-lines.png)

#### Circles

The following code draws 50 circles with a radius of `5` and in three different colors randomly assigned by `indices`, an integer array of the same size as `pos`.

```python
import numpy as np
pos = np.random.random((50, 2))
# Create an array of 50 integer elements whose values are randomly 0, 1, 2
# 0 corresponds to 0x068587
# 1 corresponds to 0xED553B
# 2 corresponds to 0xEEEEF0
indices = np.random.randint(0, 2, size=(50,))
gui = ti.GUI("circles", res=(400, 400))
while gui.running:
gui.circles(pos, radius=5, palette=[0x068587, 0xED553B, 0xEEEEF0], palette_indices=indices)
gui.show()
```

![gui-circles](https://raw.githubusercontent.com/taichi-dev/public_files/master/taichi/doc/gui-circles.png)

#### Triangles

The following code draws two orange triangles orange, with `X`, `Y`, and `Z` representing the three points of the triangles.

```python
Expand All @@ -130,6 +243,23 @@ while gui.running:

![gui-triangles](https://raw.githubusercontent.com/taichi-dev/public_files/master/taichi/doc/gui-triangles.png)

#### Arrows

The following code generates 100 random sized arrows, with `begins` and `direction` represents their begin points and incrementals:

```python
import numpy as np
begins = np.random.random((100, 2))
directions = np.random.uniform(low=-0.05, high=0.05, size=(100, 2))
gui = ti.GUI('arrows', res=(400, 400))
while gui.running:
gui.arrows(orig=begins, direction=directions, radius=1)
gui.show()
```

![gui-arrows](https://user-images.githubusercontent.com/2747993/226820031-7bfeff9a-6348-42d5-97e0-bb0e333fcdfd.png)

Notice that we used `low` and `high` in the call to `np.random.uniform()` to limit the range of generated random numbers.

## Event handling

Expand Down Expand Up @@ -186,7 +316,6 @@ The following code defines that the `while` loop goes on until **ESC** is presse
```python
gui = ti.GUI('Title', (640, 480))
while not gui.get_event(ti.GUI.ESCAPE):
gui.set_image(img)
gui.show()
```

Expand Down