-
Notifications
You must be signed in to change notification settings - Fork 7
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
41d8ce7
commit b50236d
Showing
5 changed files
with
295 additions
and
4 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
cmake_minimum_required(VERSION 3.10) # specify the version of cmake | ||
|
||
############################# | ||
# set C++ detail | ||
enable_language(CXX) # we are using C++ | ||
set(CMAKE_CXX_STANDARD 17) # we are using C++ 17 | ||
set(CMAKE_CXX_STANDARD_REQUIRED TRUE) # we are using STL library | ||
|
||
############################# | ||
# set project name | ||
|
||
project(task02) | ||
|
||
############################# | ||
# define macro | ||
add_definitions(-DPROJECT_SOURCE_DIR="${PROJECT_SOURCE_DIR}") | ||
|
||
############################# | ||
# specifying libraries to use | ||
|
||
######################## | ||
# include, build, and link | ||
|
||
include_directories( | ||
${PROJECT_SOURCE_DIR}/../external | ||
${PROJECT_SOURCE_DIR}/../external/eigen | ||
${PROJECT_SOURCE_DIR}/../src | ||
) | ||
|
||
add_executable(${PROJECT_NAME} | ||
main.cpp | ||
) | ||
|
||
target_link_libraries(${PROJECT_NAME} | ||
# stdc++fs # uncomment here if <filesystem> cannot be included | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,148 @@ | ||
# Task01: Rasterization of parametric curves | ||
|
||
**Deadline: April 25st (Thu) at 15:00pm** | ||
|
||
|
||
This is the blurred preview of the expected result: | ||
|
||
 | ||
|
||
When you execute the program, it will output an PNG image file (`output.png`) replacing the image below. Try making the image below and the image above look similar after doing the assignment. | ||
|
||
 | ||
|
||
---- | ||
|
||
## Instruction | ||
|
||
Please follow this instruction to prepare the environment to do the assignment | ||
|
||
If you did not do the [task01](../task01) assignment, you need to prepare **git**, **cmake**, and **C++ compiler** in your computer to complete this assignment. | ||
Read the following document to install these. | ||
|
||
[How to Set Up C++ Programming Environment](../doc/setup_env.md) | ||
|
||
If you had some trouble with `git` in the local repository in the previous assignment, `clone` your remote repository again to avoid trouble. | ||
|
||
```bash | ||
$ git clone https://github.com/ACG-2024S/acg-<username>.git | ||
``` | ||
|
||
|
||
Go to the top of the local repository | ||
|
||
```bash | ||
$ cd acg-<username> # go to the local repository | ||
``` | ||
|
||
### Update Local Repository | ||
|
||
Update the local repository on your computer | ||
|
||
```bash | ||
$ git checkout main # set main branch as the current branch | ||
$ git fetch origin main # download the main branch from remote repository | ||
$ git reset --hard origin/main # reset the local main branch same as remote repository | ||
``` | ||
|
||
After this command, you will see the local repository is synced with the remote repository at `https://github.com/ACG-2024S/acg-<username>` | ||
|
||
### Create a Branch | ||
|
||
To do this assignment, you need to be in the branch `task02`. | ||
You can always check your the current branch by | ||
|
||
```bash | ||
$ git branch -a # list all branches, showing the current branch | ||
``` | ||
|
||
You are probably in the `main` branch. Let's create the `task02` branch and set it as the current branch. | ||
|
||
```bash | ||
$ git branch task02 # create task0 branch | ||
$ git checkout task02 # switch into the task02 branch | ||
$ git branch -a # make sure you are in the task02 branch | ||
``` | ||
|
||
The environment is ready. | ||
|
||
## Problem1 | ||
|
||
Install eigen under `acg-<username>/external` by the following command | ||
|
||
```bash | ||
$ pwd # make sure you are in acg-<username> directory | ||
$ git submodule update --init external/eigen # clone the "eigen" repository (this may take one or two minutes) | ||
``` | ||
|
||
Make sure you have a header file `Dense` at | ||
``` | ||
acg-<username>/external/eigen/Eigen/Dense | ||
``` | ||
|
||
Eigen can be used as a header-only library. You do not need to compile it to do this task. | ||
|
||
Next, compile the code with **out-of-source** build by making a new directory for build `task02/build` and compile inside that directory | ||
```bash | ||
$ cd task02 # you are in "acg-<username>/task02" directory | ||
$ mkdir build | ||
$ cd build | ||
$ cmake -DCMAKE_BUILD_TYPE=Release .. # configure Release mode for fast execution | ||
$ cmake --build . | ||
``` | ||
|
||
Now you will see the `output.png` is updated. The `output.png` will show an angular shape of the letter **R**. Now let's write a program to make the font shape smooth as the original one. | ||
|
||
|
||
## Problem2 | ||
|
||
The code you compiled above uses the ***Jordan's curve theorem** to find whether the center of a pixel is inside or outside the character.The code counts the number of intersections of a ray against the boundary. | ||
The boundary of the letter is represented by sequences of line segments and quadratic Bézier curves. The Problem1's output was angular because the Bézier curve was approximated as a line segment. | ||
|
||
Modify the code `main.cpp` around line #65 to compute the number of intersections of a ray against the Bézier curve. The output will be the letter ***R*** with smooth boundary. | ||
|
||
|
||
### Submit | ||
|
||
Finally, you submit the document by pushing to the `task02` branch of the remote repository. | ||
|
||
```bash | ||
cd acg-<username> # go to the top of the repository | ||
git status # check the changes | ||
git add . # stage the changes | ||
git status # check the staged changes | ||
git commit -m "task02 finished" # the comment can be anything | ||
git push --set-upstream origin task02 # update the task02 branch of the remote repository | ||
``` | ||
|
||
got to the GitHub webpage `https://github.com/ACG-2024S/acg-<username>`. | ||
If everything looks good on this page, make a pull request. | ||
|
||
 | ||
|
||
|
||
---- | ||
|
||
## Trouble Shooting | ||
|
||
If you have trouble with `#include <filesystem>`, your C++ compilar is very old. Try update one. Following command may work tos specify which compilar to use on linux & Mac | ||
|
||
``` | ||
export CC=/usr/local/bin/gcc-8 | ||
export CXX=/usr/local/bin/g++-8 | ||
cmake .. | ||
``` | ||
|
||
|
||
|
||
|
||
---- | ||
|
||
## Reference | ||
|
||
- Coding Adventure: Rendering Text | ||
: https://www.youtube.com/watch?v=SO83KQuuZvg | ||
|
||
- SIGGRAPH 2022 Talk - A Fast & Robust Solution for Cubic & Higher-Order Polynomials by Cem Yuksel: https://www.youtube.com/watch?v=ok0EZ0fBCMA | ||
|
||
- True Type: https://en.wikipedia.org/wiki/TrueType |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,105 @@ | ||
#include <filesystem> | ||
// #include <experimental/filesystem> // uncomment here if the <filesystem> cannot be included above | ||
// | ||
#define STB_IMAGE_WRITE_IMPLEMENTATION | ||
#include "stb_image_write.h" | ||
#include "Eigen/Core" | ||
// | ||
#include "parse_svg.h" | ||
|
||
/*** | ||
* signed area of a triangle connecting points (p0, p1, p2) in counter-clockwise order. | ||
* @param p0 1st point xy-coordinate | ||
* @param p1 2nd point xy-coordinate | ||
* @param p2 3rd point xy-coordinate | ||
* @return signed area (float) | ||
*/ | ||
float area( | ||
const Eigen::Vector2f &p0, | ||
const Eigen::Vector2f &p1, | ||
const Eigen::Vector2f &p2) { | ||
const auto v01 = p1 - p0; | ||
const auto v02 = p2 - p0; | ||
// return 0.5f * (v01[0] * v02[1] - v01[1] * v02[0]); // right handed coordinate | ||
return 0.5f * (v01[1] * v02[0] - v01[0] * v02[1]); // left-handed coordinate (because pixel y-coordinate is going down) | ||
} | ||
|
||
|
||
/*** | ||
* compute number of intersection of a ray against a line segment | ||
* @param org ray origin | ||
* @param dir ray direction (unit normal) | ||
* @param ps one of the two end points | ||
* @param pe the other end point | ||
* @return number of intersection | ||
*/ | ||
int number_of_intersection_ray_against_edge( | ||
const Eigen::Vector2f &org, | ||
const Eigen::Vector2f &dir, | ||
const Eigen::Vector2f &ps, | ||
const Eigen::Vector2f &pe) { | ||
auto a = area(org, org + dir, ps); | ||
auto b = area(org, pe, org + dir); | ||
auto c = area(org, ps, pe); | ||
auto d = area(org + dir, ps, pe); | ||
if (a * b > 0.f && d * c > 0.f && fabs(d) > fabs(c)) { return 1; } | ||
return 0; | ||
} | ||
|
||
/*** | ||
* | ||
* @param org ray origin | ||
* @param dir ray direction (unit vector) | ||
* @param ps one of the two end points | ||
* @param pc control point | ||
* @param pe the other end point | ||
* @return the number of intersections | ||
*/ | ||
int number_of_intersection_ray_against_quadratic_bezier( | ||
const Eigen::Vector2f &org, | ||
const Eigen::Vector2f &dir, | ||
const Eigen::Vector2f &ps, | ||
const Eigen::Vector2f &pc, | ||
const Eigen::Vector2f &pe) { | ||
// comment out below to do the assignment | ||
return number_of_intersection_ray_against_edge(org, dir, ps, pe); | ||
// write some code below to find the intersection between ray and the quadratic | ||
} | ||
|
||
int main() { | ||
const auto input_file_path = std::filesystem::path(PROJECT_SOURCE_DIR) / ".." / "asset" / "r.svg"; | ||
const auto [width, height, shape] = acg::svg_get_image_size_and_shape(input_file_path); | ||
if (width == 0) { // something went wrong in loading the function | ||
std::cout << "file open failure" << std::endl; | ||
abort(); | ||
} | ||
const std::vector<std::string> outline_path = acg::svg_outline_path_from_shape(shape); | ||
const std::vector<std::vector<acg::Edge>> loops = acg::svg_loops_from_outline_path(outline_path); | ||
// | ||
std::vector<unsigned char> img_data(width * height, 255); // grayscale image initialized white | ||
for (unsigned int ih = 0; ih < height; ++ih) { | ||
for (unsigned int iw = 0; iw < width; ++iw) { | ||
const auto org = Eigen::Vector2f(iw + 0.5, ih + 0.5); // pixel center | ||
const auto dir = Eigen::Vector2f(60., 20.); // search direction | ||
int count_cross = 0; | ||
for (const auto &loop: loops) { // loop over loop (letter R have internal/external loops) | ||
for (const auto &edge: loop) { // loop over edge in the loop | ||
if (edge.is_bezier) { // in case the edge is a quadratic Bézier | ||
count_cross += number_of_intersection_ray_against_quadratic_bezier( | ||
org, dir, | ||
edge.ps, edge.pc, edge.pe); | ||
} else { // in case the edge is a line segment | ||
count_cross += number_of_intersection_ray_against_edge( | ||
org, dir, | ||
edge.ps, edge.pe); | ||
} | ||
} | ||
} | ||
if (count_cross % 2 == 1) { // Jordan's curve theory | ||
img_data[ih * width + iw] = 0; // paint black if it is inside | ||
} | ||
} | ||
} | ||
const auto output_file_path = std::filesystem::path(PROJECT_SOURCE_DIR) / "output.png"; | ||
stbi_write_png(output_file_path.string().c_str(), width, height, 1, img_data.data(), width); | ||
} |
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.