# CG HW1 Report
## Line algorithm implementation
We first calculate the vector $(dx, dy)$ and the distance $D$ from $(x_1, y_1)$ to $(x2, y2)$.
\begin{cases}
dx = x_2-x_1 \\
dy = y_2-y_1
\end{cases}
$$
D = \sqrt{dx^2+dy^2}
$$
Then, with the vector and distance calculated, we can simply plot the graph by interpolation.
That is, for each each "step" $d$ we make, we calculate the "completion ratio" until $d=D$, plot the line with the following formula:
$$
(x, y) = (x_1 + \frac{d}{D}dx,\ y_1 + \frac{d}{D}dy) \quad where \quad d \in [0,D]
$$
> 
## Circle algorithm implementation
With the same idea as above, we can first evaluate the perimeter $P$ of a circle,
$$
P = 2 \pi r
$$
With the perimeter calculated, we need to transform "completion rate" to radian form, in order to apply trigonometric operations,
$$
c = 2\pi \frac{d}{P}
$$
We can then draw a circle with the classic circle formulae,
$$
(x, y) = (x + r \cos{c},\ y+r \sin{c} ) \quad where \quad c \in [0, 2\pi]
$$
> 
## Ellipse algorithm implementation
Again, same energy, we need to find the ellipse's perimeter.
However, currently there is no accurate formula for Ellipse Perimeter in math.
Luckily, there is still a proximated alternative version that can be easily evaluated, by using
$$
P = 2\pi\sqrt{\frac{{2r_1}^2 + {2r_2}^2}{2}}
$$
we get perimeter which gives the result at most 5% more than the real perimeter, which is acceptable as it may cause at most 5% curve segment be drawn twice.
Cool. Then we can retrieve the completion rate with the same operation
$$
c = 2\pi \frac{d}{P}
$$
Draw a ellipse with the classic ellipse formulae,
$$
(x, y) = (x + r_1 \cos{c},\ y+r_2 \sin{c} ) \quad where \quad c \in [0, 2\pi]
$$
> 
## Bezier curve algorithm implementation
Finally, here comes the boss attack.
Bezier curve has no easy way to evaluate its length $L$. My way to implement it is to abandon the accuate perimeter evaluation, using a value greater than the actual length $L_e \ge L$. I chose
$$
L_{e} = |\overrightarrow{p_1p_2}| + |\overrightarrow{p_2p_3}| + |\overrightarrow{p_3p_4}|
$$
Completion rate is the same as a simple line (which we omitted in the previous line example)
$$
c = \frac{d}{L_e}
$$
Draw the line with the bezier curve algorithm
$$
B(c) = p_1(1-c)^3 + 3 p_2 c(1-c)^2 + 3p_3 c^2(1-t) + p4 c^3
$$
> 
:::info
We may also set $L_e$ as a constant value, using linear interpolation to fill the gap
> 
> $L_e$ = 10
:::
## Eraser implementation
We draw the pixel with the same color as the background, within the range of $(x_1, y_1)$ and $(x_2, y_2)$.
I added a check to ensure $x_1, y_1$ are always less than $x_2, y_2$.
> 
## :rainbow: Extra feature :rainbow:
Click the rainbow button to enable <b><span style="color: #ff0000">R</span><span style="color: #ff7f00">A</span><span style="color: #eeee00">I</span><span style="color: #80ff00">N</span><span style="color: #00ff00">B</span><span style="color: #00ffff">O</span><span style="color: #0000ff">W</span></b> MODE!!!
<!--  -->
> 
**Implementation**
In `HW1.pde` where UI button is defined, we copied `shapeButton`'s code, modify it to fit our need, create a rainbow button.
```java=142
rainbowButton = new Button(width-90,10,30,30);
rainbowButton.setBoxAndClickColor(color(250), color(150));
rainbowButton.setImage(loadImage("rainbow.png"));
```
In `Renderer.pde`, we defined two variables `UseRainbow` and `ColorShiftSpeed`. The former tells the renderer uses the rainbow utility or not, the latter set the rainbow rotation speed. Also, there is a private field `ColorShift` records current rotation.
```java=1
public boolean UseRainbow = false;
public float ColorShiftSpeed = 148.763;
float ColorShift = 0;
```
foreach draw call, `ColorShift` value grows, until it reach 1, at that time, it will be reset to 0. We will draw rainbow color base on this value.
```java=17
public void run(){
//...
ColorShift += ColorShiftSpeed / 10000;
if(ColorShift > 1)
ColorShift %= 1;
}
```
We also create a function to implement rainbow toggle
```java=45
public void toggleRainbow() {
UseRainbow = !UseRainbow;
}
```
We can now reference in `HW1.pde`
```java=36
rainbowButton.run(()->{shapeRenderer.toggleRainbow();});
```
Here comes the most important part, how to draw in rainbow color?
Below is the RGB value of rainbow color

Observe that RGB value can be splitted into 5 phases,
- **Phase 1**: (255,**0**,0) → (255,**255**,0)
- **Phase 2**: (**255**,255,0) → (**0**,255,0)
- **Phase 3**: (0,**255**,0) → (0,**0**,255)
- **Phase 4**: (**0**,0,255) → (**255**,0,255)
- **Phase 5**: (255,0,**255**) → (255,0,**0**)
by using these relationships, we can write the below code in `util.pde`
```java=153
color evalColor(float t) {
// Use Rainbow?
if(!UseRainbow)
return _color;
// Apply animated color
t += ColorShift;
if(t > 1)
t -= 1;
// scalar [0-1] to rgb
int phase = (int)(t * 6); // 0~6
t = (t % (1/6.0)) * 6; // normalize t to 0~1 scalar within that phase
switch(phase) {
case 0: return color(255, 255*t, 0);
case 1: return color(255-255*t, 255, 0);
case 2: return color(0, 255, 255*t);
case 3: return color(0, 255-255*t, 255);
case 4: return color(255*t, 0, 255);
case 5: return color(255, 0, 255-255*t);
case 6: return color(255, 0, 0);
}
return -1;
}
```
Since all of our implementation has the parameter `complete_ratio` ($c$), we can easily change all color calls to this function to set rainbow color!
<!--
\begin{cases}
\text{open,} &\quad\text{if RMSD}_\text{s-open}\ge6, \text{RMSD}_\text{closed}\ge6\\
\text{closed,} &\quad\text{if RMSD}_\text{closed}\le2 \\
\text{semiopen,} &\quad\text{if RMSD}_\text{s-open}\le2\\
\text{transition,} &\quad\text{otherwise.} \\
\end{cases}
-->